Diretrizes de Empacotamento do Fedora

As diretrizes de empacotamento são uma coleção de questões comuns e a severidade que deve ser colocada sobre elas. Embora estas orientações não devam ser ignoradas, elas também não devem ser cegamente seguidas. Se você acha que seu pacote deve estar isento de parte das diretrizes, por favor traga o problema para o Fedora Packaging Committee.

Estes documentos cobrem os detalhes finos de empacotamento aceitável do Fedora e, embora possam incluir vários exemplos, eles não serão particularmente úteis como um tutorial. Eles também não cobrem os detalhes e políticas relacionadas a obter acesso aos repositórios do Fedora como um empacotador, ou a mecânica de criar e lançar pacotes como parte da distribuição. Para documentos que cubram essas questões, consulte o seguinte:

É responsabilidade do revisor do pacote apontar problemas específicos com um pacote e responsabilidade do empacotador lidar com esses problemas. O revisor e o empacotador trabalham juntos para determinar a gravidade dos problemas (se eles bloqueiam um pacote ou podem ser resolvidos depois que o pacote estiver no repositório). Lembre-se de que qualquer pacote que você enviar também deve estar em conformidade com as Diretrizes de Revisão.

O autor original desses documentos é Tom 'spot' Callaway, embora eles tenham sido originalmente baseados em muitos outros documentos. Eles foram modificados significativamente ao longo dos anos por muitos membros do Comitê de Embalagem.

As palavras-chave DEVE, NÃO DEVE, RECOMENDADO, NÃO RECOMENDADO e PODE nessas diretrizes devem ser interpretadas como descrito em https://www.rfc-editor.org/rfc/rfc2119 Ohrfc 2119].

Relate problemas com essas diretrizes, incluindo erros de digitação, aqui.

Aplicabilidade

Em geral, estas diretrizes se aplicam às versões atualmente lançadas e sem fim de vida útil do Fedora, bem como à versão de desenvolvimento do Fedora (Rawhide). Se uma parte específica destas diretrizes for relevante apenas para um subconjunto dessas versões, isso será especificamente observado. No entanto, observe que o Rawhide pode mudar rapidamente e haverá momentos em que as mudanças serão visíveis lá e ainda não foram refletidas aqui.

As diretrizes também cobrem, até certo ponto, pacotes para EPEL, mas apenas quando combinadas com as Diretrizes de empacotamento EPEL. O pacote Fedora muda muito mais rapidamente do que o pacote EPEL, portanto, com o tempo, essas diretrizes se afastarão ainda mais de qualquer versão EPEL específica e, para a versão EPEL mais antiga e suportada, as diferenças podem ser bastante significativas. As partes destas diretrizes que não se aplicam à EPEL geralmente não serão indicadas.

Política geral de exceção

Como estas diretrizes nunca poderão cobrir todas as contingências possíveis, existirão sempre pacotes que necessitam de exceções. É responsabilidade do empacotador seguir estas diretrizes tão fielmente quanto possível e documentar claramente, como comentários no arquivo spec do pacote, os casos em que elas não possam ser seguidas.

Se, em uma diretriz, for usada a expressão “é recomendado” ou “é sugerido” e não for viável que o pacote esteja em conformidade com essa diretriz, o empacotador pode desviar-se dela. A natureza do desvio e o raciocínio por trás dele DEVEM ser documentados no arquivo spec.

Quando a linguagem “deve”, “é necessário” ou “precisa” for usada, o empacotador pode desviar-se da diretriz somente com a aprovação do comitê de empacotamento. Por favor, siga o procedimento na página do Comitê de Empacotamento para fazer essas solicitações.

Pacotes permitidos

Por favor, revise O que pode ser empacotado para garantir que o que você pretende empacotar é permitido no Fedora.

Nomenclatura

Recomenda-se que você siga as Diretrizes de nomenclatura para garantir que seu pacote seja nomeado apropriadamente.

Versão e lançamento

A documentação que cobre a maneira correta de usar os campos Version e Release pode ser encontrada aqui.

Licenças

Recomenda-se que você revise as informações sobre licenças determinadas como permitidas no Fedora e Diretrizes de licenças para garantir que seu pacote tenha as licenças corretas e estas sejam indicadas corretamente.

Marcas registradas do Fedora

Os empacotadores NÃO DEVEM adicionar quaisquer ativos de marca registrada do Fedora, incluindo o logotipo do Fedora, ícones do logotipo do Fedora ou gráficos que incluam o logotipo do Fedora. Esses ativos DEVEM ser adicionados ao pacote fedora-logos. Seus pacotes instalam os logotipos por meio de dependência do pacote fedora-logos. Se o upstream contiver recursos da marca registrada do Fedora que você acredita terem sido usados de forma inadequada, envie um e-mail para legal@fedoraproject.org

Isso ocorre porque o logotipo do Fedora é uma marca registrada, que é tratada sob uma estrutura legal diferente do código. Ele deve ser distribuído sob termos que protejam a marca registrada. Manter as marcas registradas do Fedora separadas em seu próprio pacote, em vez de espalhadas por vários outros pacotes, também é uma prática essencial para permitir remixes que necessariamente não devem usar a marca registrada do Fedora, e em vez disso, crie seu próprio pacote *-logos ou use o pacote generic-logos.

Bibliotecas e aplicativos

Muitas diretrizes específicas de idioma ou domínio referem-se a "bibliotecas", "módulos", "plug-ins" ou outros termos específicos do idioma ou domínio. Isto é especificamente importante para a nomenclatura de pacotes. Alguns aplicativos podem incluir bibliotecas e algumas bibliotecas podem incluir aplicativos, portanto a distinção nem sempre é clara.

Biblioteca ou aplicativo?

  • Se o objetivo principal de um pacote é fornecer executáveis para serem executados pelos usuários, É RECOMENDADO que ele seja empacotado como um aplicativo. Se também incluir bibliotecas que podem ser importadas ou vinculadas por outro código, consulte Pacotes de uso misto abaixo.

  • Se o objetivo principal de um pacote é fornecer executáveis para serem executados pelos usuários, ele DEVE ser empacotado como um aplicativo. Se também incluir bibliotecas que podem ser importadas ou vinculadas por outro código, consulte Pacotes de uso misto abaixo.

Cabe ao empacotador determinar o propósito principal de um pacote. Muitas vezes o upstream já terá feito isso com sua escolha de nomenclatura e É RECOMENDADO que essa escolha seja seguida pelo empacotador do Fedora.

Pacotes de uso misto

Muitos pacotes, independentemente da sua finalidade principal, incluem aplicações e bibliotecas. Neste caso, É RECOMENDADO que um ou ambos sejam empacotados em subpacotes para permitir que outros aplicativos dependam apenas da biblioteca e não do(s) aplicativo(s) associado(s). No caso da instalação de um aplicativo que depende de uma biblioteca ou serviço, NÃO É RECOMENDADO incluir automaticamente outros aplicativos associados a essa biblioteca ou serviço.

Independência do pacote

É RECOMENDADO que os pacotes sejam instaláveis de forma independente sempre que isso for tecnicamente viável, mas eles DEVEM especificar dependências do tipo correto em outros pacotes, se necessário, veja Tipos de dependência abaixo.

Os aplicativos de desktop NÃO DEVEM depender de outros aplicativos de desktop, a menos que seja estritamente necessário. Em particular, pacotes que contêm um arquivo .desktop visível (um arquivo .desktop que não contém a linha NoDisplay=true) NÃO DEVEM ter um Requires, Recommends ou Supplements em qualquer outro pacote que contenha um arquivo de desktop visível, direta ou indiretamente.

Por exemplo, seria razoável que um editor de níveis de videogame exigisse o videogame associado para funcionar, ou que um plug-in de aplicativo exigisse o aplicativo associado. Mas não seria razoável que um aplicativo que usasse uma biblioteca de banco de dados dependesse de um conjunto de gerenciamento de banco de dados associado a essa biblioteca, ou que uma aplicação que usasse uma linguagem de programação específica dependesse de ferramentas de gerenciamento associadas a essa linguagem de programação.

Se um pacote fonte fornece múltiplas aplicações gráficas, essas aplicativos DEVEM ser empacotados em subpacotes separados quando possível.

Arquivos spec

O arquivo spec ("spec") é um elemento fundamental no fluxo de trabalho de empacotamento. Qualquer alteração feita no pacote incluirá uma alteração nas especificações. Como os pacotes no Fedora são mantidos por uma comunidade de empacotadores e também por ferramentas automatizadas, é importante que as especificações sigam certas convenções. A maior parte dessas diretrizes de empacotamento envolve o que consta nas especificações, mas aqui estão alguns itens gerais.

Nomenclatura do arquivo spec

O arquivo spec DEVE ser nomeado %{name}.spec. Ou seja, se o seu pacote for denominado exemplo, o arquivo spec deverá ser denominado exemplo.spec.

Legibilidade do spec

Todos os arquivos spec DEVEM ser legíveis e mantidos de tal forma que a comunidade de empacotadores seja capaz de entendê-los e trabalhar com eles.

Para ajudar a facilitar a legibilidade, apenas macros e condicionais para Fedora e EPEL podem ser usadas em Pacotes Fedora. O uso de macros e condicionais para outras distribuições, incluindo derivados do Fedora, não é permitido em arquivos de especificações de pacotes nos principais repositórios do Fedora, a menos que essas macros e condicionais também estejam presentes no Fedora.

Codificação de arquivos spec

A menos que você precise usar caracteres fora do repertório ASCII, você não precisará se preocupar com a codificação do arquivo spec. Se você precisar de caracteres não ASCII, salve seus arquivos de especificações como UTF-8. Se você tiver dúvidas sobre quais caracteres são ASCII, consulte este gráfico.

Nomes de arquivos não ASCII

Da mesma forma, nomes de arquivos que contenham caracteres não ASCII devem ser codificados como UTF-8. Como não há como saber em qual codificação o nome do arquivo está, usar a mesma codificação para todos os nomes de arquivos é a melhor maneira de garantir que os usuários possam ler os nomes dos arquivos corretamente. Se o upstream enviar nomes de arquivos que não estão codificados em UTF-8, você poderá usar um utilitário como convmv (do pacote convmv) para converter o nome do arquivo em sua seção %install.

Manutenção dos spec e canonicidade

O repositório git do Fedora é o local canônico para os arquivos de especificações do Fedora. Os mantenedores DEVEM esperar que outros mantenedores e ferramentas automatizadas façam alterações em seus pacotes, potencialmente sem se comunicarem antes de fazê-lo (embora a comunicação seja sempre incentivada). Se alguns mantenedores também estão tentando manter cópias de uma especificação em um repositório externo, eles DEVEM estar preparados para mesclar as alterações feitas na especificação no repositório do Fedora e NÃO DEVEM sobrescrever essas alterações com uma cópia de um repositório externo ou usando fedpkg import.

Verificação de arquivo-fonte

Nos casos em que o projeto upstream publica assinaturas OpenPGP de seus lançamentos, É RECOMENDADO que os pacotes Fedora verifiquem essa assinatura como parte do processo de construção do RPM.

Embora uma soma de verificação no arquivo-fonte certifique que um arquivo recuperado do cache lookaside é aquele que o empacotador carregou, ela não informa se o arquivo é o que o projeto upstream lançou. Uma assinatura dos desenvolvedores originais certifica que a fonte é idêntica à que eles lançaram. A verificação da assinatura como parte da construção garante que os empacotadores não se esqueçam de verificá-la.

Obtendo as chaves corretas

O método de verificação requer um arquivo de chaveiro OpenPGP com uma ou mais chaves públicas do projeto upstream. O chaveiro deverá conter todas as chaves confiáveis para certificar a autenticidade das fontes e NÃO DEVE conter quaisquer outras chaves.

Idealmente, o projeto upstream publica esse chaveiro como um arquivo para download. Você deve baixar esse arquivo e fazer tudo o que puder para verificar se ele é autêntico. Em seguida, você deve adicioná-lo sem modificações ao pacote SCM e fornecer sua URL no arquivo de especificações para que outros possam verificá-lo. A URL DEVE usar HTTPS ou um protocolo autenticado de forma semelhante, se possível.

Mesmo que você não consiga verificar a chave na primeira adição, ela ainda aumenta a segurança de uma forma confiável no primeiro uso. Isso garantirá que ataques futuros serão detectados se a chave for a correta, ou que um ataque atual será detectado posteriormente se versões futuras forem assinadas pela chave correta.

Verificando assinaturas

Quando a verificação do arquivo-fonte é feita, ela DEVE ser feita primeiro na seção %prep do arquivo de spec, antes que qualquer código potencialmente comprometido seja executado. A verificação DEVE ser feita com a macro %{gpgverify}, que se expande em um comando cujos parâmetros devem ser os caminhos do chaveiro, a assinatura e o arquivo assinado. BuildRequires: gnupg2 é necessário para que a verificação funcione.

Qualquer arquivo de assinatura desanexado (por exemplo, foo.tar.gz.asc ou foo.tar.gz.sig) deve ser carregado no cache lookaside do pacote junto com o código-fonte, enquanto o chaveiro deve ser enviado diretamente para o pacote SCM.

O seguinte formato deve ser usado:

Source0: ftp://ftp.example.com/pub/foo/%{name}-%{version}.tar.gz
Source1: ftp://ftp.example.com/pub/foo/%{name}-%{version}.tar.gz.asc
Source2: https://www.example.com/gpgkey-0123456789ABCDEF0123456789ABCDEF.gpg
…
BuildRequires: gnupg2
…
%prep
%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}'

A primeira fonte é o tarball real, a segunda é a assinatura do upstream e a terceira é o chaveiro.

Exceções

Se o tarball do upstream de um pacote precisar ser modificado, por exemplo, porque contém itens proibidos, então o tarball não poderá ser verificado como parte do processo de construção. Neste caso, o chaveiro OpenPGP do upstream ainda deve ser incluído no pacote SCM e as instruções/script usadas para construir o tarball simplificado precisam verificar a fonte do upstream.

Se o projeto upstream não publicar um arquivo de chaveiro (por exemplo, se publicar apenas uma impressão digital em seu site e consultar uma rede de servidores de chaves para baixar a chave), talvez seja necessário criar um chaveiro depois de verificar a chave. Nesse caso, não há URL upstream para o chaveiro; portanto, é recomendado que você documente como criou o chaveiro em um comentário no arquivo spec. Um chaveiro mínimo com a chave com a impressão digital 7D33D762FD6C35130481347FDB4B54CBA4826A18 pode ser criado com o seguinte comando:

gpg2 --export --export-options export-minimal 7D33D762FD6C35130481347FDB4B54CBA4826A18 > gpgkey-7D33D762FD6C35130481347FDB4B54CBA4826A18.gpg

Se o upstream assinou um tarball de forma diferente, por exemplo, assinando apenas o tarball descompactado, mas distribuindo uma versão compactada, então a etapa de verificação deverá ser ajustada de acordo, por exemplo:

Source0: ftp://ftp.example.com/pub/foo/%{name}-%{version}.tar.xz
Source1: ftp://ftp.example.com/pub/foo/%{name}-%{version}.tar.asc
Source2: https://www.example.com/gpgkey-0123456789ABCDEF0123456789ABCDEF.gpg
…
BuildRequires: gnupg2 xz
…
%prep
xzcat '%{SOURCE0}' | %{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data=-

Pacotes que são vitais durante a inicialização do Fedora podem usar um opção de bootstrap para pular a verificação antes do GnuPG ser compilado.

Ajuda

Se você precisar de ajuda para deixar seu pacote compatível com esta diretriz, ou se você não souber o que fazer se uma construção falhar na verificação de assinatura, então você deve procurar ajuda na lista de discussão de desenvolvimento do Fedora antes de contornar a verificação, para ter certeza de que você não está construindo software comprometido.

Suporte a arquitetura

Todos os pacotes do Fedora devem ser compilados e construídos com sucesso em rpms binários em pelo menos uma arquitetura primária suportada, exceto quando o pacote for útil apenas em uma arquitetura secundária (como um utilitário de inicialização específico da arquitetura, carregador de microcódigo ou ferramenta de configuração de hardware). É recomendado que os empacotadores do Fedora façam todos os esforços para suportar todas as arquiteturas primárias.

Conteúdo, código que não precisa ser compilado e construído, e código independente de arquitetura (noarch) são exceções notáveis.

Falhas de construção de arquitetura

Se um pacote Fedora não compilar, construir ou funcionar com sucesso em uma ou mais arquiteturas, então essas arquiteturas devem ser listadas na especificação em ExcludeArch. Cada arquitetura listada em ExcludeArch precisa ter um bug registrado no bugzilla que descreva a razão pela qual o pacote não compila/constrói/funciona naquela arquitetura. É recomendado que, em seguida, o número do bug seja colocado em um comentário, próximo à linha ExcludeArch correspondente. Novos pacotes não terão entradas do bugzilla durante o processo de revisão, então é recomendado que eles tenham esta descrição no comentário até que o pacote seja aprovado, registrar a entrada no bugzilla e substituir a explicação longa pelo número do bug. Por fim, é recomendado que o bug seja marcado como um bloqueio de um (ou mais) dos seguintes bugs para simplificar o rastreamento de tais problemas:

Noarch com dependências não portadas

Às vezes, você está trabalhando em um pacote noarch que só pode ser executado em locais nos quais um pacote arqueado diferente é construído. Isto é comum para pacotes escritos em uma linguagem de script que depende do pacote interpretador da linguagem, por exemplo. Se o pacote com arquitetura no qual seu pacote se baseia não estiver disponível em todas as arquiteturas alvo do Fedora (ou EPEL), você se deparará com uma situação em que poderá precisar excluir seu pacote dos repositórios de pacotes de certas arquiteturas ou impedir que ele seja compilado em certas arquiteturas em o sistema de construção.

Runtime específico da arquitetura e dependências de tempo de compilação

Você pode limitar as arquiteturas usadas para construir um pacote noarch e os repositórios aos quais o pacote noarch construído será adicionado, usando as tags ExcludeArch: ou ExclusiveArch::

BuildArch: noarch
# Liste abaixo as arquiteturas nas quais o pacote dependente é construído
ExclusiveArch: %{ix86} %{arm} x86_64 noarch

Às vezes, um runtime de linguagem que você está empacotando fornecerá uma macro para os arcos em que está disponível, por exemplo, %{nodejs_arches}. Se existir, você pode usar algo como ExclusiveArch: %{nodejs_arches} noarch em seu arquivo de especificações. Dê uma olhada nas diretrizes da linguagem para ver se tal macro existe.

Nenhuma fonte ou patch para arquitetura específica

Os pacotes NÃO DEVEM ter tags Source: ou Patch: que são condicionadas à arquitetura. Por exemplo, isso é proibido:

%ifarch ppc64
Patch0: build-fix-for-ppc64.patch
%endif

Condicionar tags Source: ou Patch: por arquitetura faz com que o conteúdo do pacote fonte seja diferente dependendo da arquitetura que foi usada para construí-lo.

Observe que isso infelizmente impede que %autosetup seja usado para aplicar patches quando alguns desses patches se aplicam apenas a determinadas arquiteturas. A melhor solução é escrever patches que simplesmente funcionem em todas as arquiteturas. Se isso não for possível, simplesmente use %setup e use a macro %patch para aplicar cada patch usando %ifarch ou %ifnarch conforme apropriado. Por exemplo:

%prep
%setup -q
%ifarch s390x
%patch0 -p1
%endif

Layout do sistema de arquivos

O Fedora segue o Filesystem Hierarchy Standard (em português, Padrão de Hierarquia do Sistema de Arquivos) no que diz respeito ao layout do sistema de arquivos, com exceções indicadas abaixo. O FHS define onde os arquivos devem ser colocados no sistema.

Exceções

  • O Fedora permite que compiladores cruzados coloquem arquivos em /usr/target.

  • O Fedora não permite novos diretórios diretamente em / ou /usr sem a aprovação do FPC.

Libexecdir

O Filesystem Hierarchy Standard não inclui nenhuma provisão para libexecdir, mas os pacotes do Fedora PODEM armazenar arquivos apropriados lá. Libexecdir (também conhecido como /usr/libexec em sistemas Fedora) só deve ser usado como diretório para programas executáveis que são projetados principalmente para serem executados por outros programas e não por usuários.

O rpm do Fedora inclui uma macro para libexecdir, %{_libexecdir}. Os empacotadores são altamente encorajados a armazenar arquivos libexecdir em um subdiretório específico do pacote de %{_libexecdir}, como %{_libexecdir}/%{name}.

Se os scripts de construção do upstream suportam o uso de %{_libexecdir} então esse é o local mais apropriado para configurá-lo (por exemplo, passando --libexecdir=%{_libexecdir}/%{name} para o configure do autotools). Se os scripts de construção do upstream não suportarem isso, %{_libdir}/%{name} é uma segunda opção válida. Se você precisar corrigir o suporte para usar um desses diretórios, então você deve corrigir em LIBEXECDIR, de preferência configurável em tempo de compilação (para que distribuições que não possuem /usr/libexec possam definir LIBEXECDIR para outro diretório mais apropriado para seus distribuição).

Locais isentos de multilib

Se um pacote estiver isento de multilib, ele pode usar %{_prefix}/lib em vez de %{_libdir}. Pacotes que contêm arquivos específicos de arquitetura que normalmente seriam instalados em %{_libexecdir} são sempre considerados inelegíveis para multilib. No entanto, você deve ter certeza de que o (sub)pacote em que eles estão não possui outro conteúdo que seria considerado elegível para multilib. Se este não for o caso dos arquivos que você deseja fazer em seu pacote ou se você simplesmente não tiver certeza, peça à FESCo uma isenção explícita de multilib.

/run

Os serviços do sistema devem armazenar pequenos dados voláteis de tempo de execução em /run. Este é um diretório suportado por tmpfs que é montado no início da inicialização, antes de qualquer serviço ser iniciado (e antes que /var esteja disponível). /var/run é um link simbólico legado para /run.

Nenhum arquivo ou diretório sob /srv, /usr/local ou /home/$USER

O FHS diz (traduzido):

"...recomenda-se que programas não contem com uma estrutura de subdiretórios
específica de /srv existente ou dados necessariamente armazenados em /srv.
No entanto, /srv deve sempre existir no FHS sistemas compatíveis e deve ser
usado como local padrão para tais dados.

As distribuições devem tomar cuidado para não remover arquivos colocados
localmente nesses diretórios sem permissão do administrador."

O FHS está entregando explicitamente o controle da estrutura de diretórios em /srv ao administrador do sistema, e não à distribuição. Portanto, nenhum pacote Fedora pode ter arquivos ou diretórios em /srv, vir pré-configurados para usar arquivos ou diretórios específicos em /srv, para remover arquivos ou modificar os arquivos de qualquer forma.

Além disso, nenhum pacote Fedora pode conter arquivos ou diretórios ou modificar arquivos em:

  • /usr/local, pois esses diretórios não podem ser usados pelas distribuições na FHS

  • /home/$USER, pois os usuários podem modificar arbitrariamente os arquivos em seus diretórios pessoais e os pacotes rpm que modificam esses arquivos correm o risco de destruir os dados do usuário. Além disso, os sites podem montar /home em nfs em muitos tipos diferentes de sistemas ou até mesmo montá-los automaticamente na rede sob demanda. Modificar arquivos em diretórios pessoais assim configurados terá efeitos negativos em ambas as situações.

É importante notar que o software em um pacote Fedora, uma vez instalado e configurado por um usuário, pode usar /srv como local para dados. O pacote simplesmente não deve fazer isso por padrão

Uso limitado de /opt, /etc/opt e /var/opt

/opt e seus diretórios relacionados (/etc/opt e /var/opt) são reservados para uso dos fornecedores na FHS. Reservamos o nome fedora com LANANA para nosso uso. Se um pacote instala arquivos em /opt ele só pode usar diretórios na hierarquia /opt/fedora. O Fedora tenta organizar este diretório alocando um subdiretório do nosso diretório /opt/fedora para subsistemas específicos. Se você acha que precisa usar /opt/fedora por favor registre um ticket no FPC para decidir se é um uso válido de /opt e qual subdiretório deve ser alocado para seu uso.

Atualmente, alocamos /opt/fedora/scls, /etc/opt/fedora/scls e /var/opt/fedora/scls para uso por Software Collections.

Como o pacote do Chrome fornecido pelo Google escolheu um local de arquivo específico para arquivos específicos de extensão que, se usados, entrariam em conflito com as diretrizes acima, o Comitê de Empacotamento aprovou a seguinte exceção: Um pacote PODE instalar arquivos no /etc/opt/chrome/native-messaging-hosts e pode criar essa hierarquia de diretórios, desde que o pacote como um todo também suporte o Chromium. (O suporte ao Chromium PODE estar em um subpacote diferente.) Se o Chrome no futuro permitir que um diretório mais padrão seja usado para essa finalidade, esta exceção será removida.

Efeito do recurso UsrMove do Fedora

O Fedora fundiu vários diretórios em / com seus equivalentes em /usr/:

Caminho Fundiu com Macro RPM

/bin

/usr/bin

{_bindir}

/sbin

/usr/sbin

%{_sbindir}

/lib64 ou /lib

/usr/lib64 ou /usr/lib

%{_libdir}

/lib

/usr/lib

%{_prefix}/lib

Por exemplo, os usuários finais descobrirão que /bin/sh é o mesmo arquivo que /usr/bin/sh.

No entanto, as dependências do arquivo rpm não funcionam de acordo com o que está no sistema de arquivos, elas funcionam de acordo com o caminho especificado na seção rpm %files. Então, um rpm que especificou:

%files
/bin/sh

seria capaz de satisfazer uma dependência de arquivo para /bin/sh, mas não para /usr/bin/sh. Como empacotador você pode precisar prestar atenção onde outros pacotes esperam encontrar seus arquivos. Coisas que o histórico colocou em /bin, /sbin, /lib ou /lib64 devem ser listadas na seção %files como estando nesses diretórios. Coisas que o histórico colocou em /usr/bin, /usr/sbin etc, devem ser listadas na seção %files como estando em %{_bindir}, %{ _sbindir}, etc. Se você acha que há alguma confusão histórica sobre em qual diretório um programa é colocado, você pode usar um Virtual Provides para listar o caminho alternativo. Por exemplo:

Provides: %{_sbindir}/ifconfig
[...]
%files
/sbin/ifconfig

Se você é um empacotador que usa dependências de arquivo para exigir as dependências adequadas, talvez seja necessário certificar-se de que as dependências de arquivo estão apontando para o local que o empacotador desse arquivo especificou para rpm. Aqui está um exemplo de como fazer isso:

$ rpm -ql $(rpm -qf /usr/sbin/ifconfig)|grep sbin/ifconfig
/sbin/ifconfig

Então você usaria Requires: /sbin/ifconfig em seu arquivo de especificações.

Use rpmlint

Execute o rpmlint em rpms binários e fonte para examiná-los em busca de erros comuns e corrigi-los (a menos que o rpmlint esteja errado, o que também pode acontecer). Se você achar a saída do rpmlint enigmática, a opção -e pode ser usada para obter descrições mais detalhadas da maioria dos erros e avisos. Observe que o rpmlint realizará verificações adicionais se receber o nome de um pacote instalado. Por exemplo, dnf install foo-1.0-1.f20.x86_64.rpm; rpmlint -i foo executará um conjunto de testes no pacote foo que rpmlint foo-1.0-1.f20.x86_64.rpm não pode. Uma página mantida pela comunidade sobre problemas de rpmlint pode ser encontrada aqui.

Tags e seções

  • As tags Copyright:, Packager:, Vendor: e PreReq: NÃO DEVEM ser usadas.

  • NÃO É RECOMENDADO que a tag BuildRoot:, a tag Group: e a seção %clean sejam usadas.

  • NÃO É RECOMENDADO que o conteúdo de buildroot seja removido na primeira linha de %install.

  • NÃO É RECOMENDADO que o valor da tag `Summary:`termine com um ponto.

  • As tags Source: documentam onde encontrar as fontes originais do pacote. Na maioria dos casos, É RECOMENDADO que seja uma URL completa para o tarball upstream. Para casos especiais, consulte Diretrizes de SourceURL.

Dependências de pacote

Todas as dependências de pacotes (tempo de construção ou tempo de execução, regulares, fracas ou outras) DEVEM SEMPRE ser satisfeitas nos repositórios oficiais do Fedora.

O RPM pode determinar automaticamente dependências para a maioria das bibliotecas compiladas e para algumas linguagens de script como Perl. Dependências determinadas automaticamente NÃO DEVEM ser duplicadas por dependências manuais.

As dependências de compilação, no entanto, DEVEM ser listadas explicitamente, a menos que você esteja usando um gerador automático de dependência de compilação (por exemplo, Rust ou Python). Consulte Build-Time Dependencies (BuildRequires).

Para dependências versionadas (tempo de construção ou tempo de execução), É RECOMENDADO que sejam usadas APENAS quando realmente necessárias para garantir que a versão adequada de um pacote esteja presente. Se uma dependência versionada for satisfeita por uma versão presente em três versões anteriores do Fedora então uma dependência versionada não é necessária e o uso de uma dependência regular não versionada É RECOMENDADA em seu lugar.

Uma dependência versionada em um pacote com uma época definida DEVE ser incluída nessa dependência. Caso contrário, a dependência não funcionará conforme o esperado.

Tipos de dependência

Requires DEVE ser usado se a dependência for necessária para o software funcionar corretamente.

Se o pacote funcionar corretamente, mas com capacidade reduzida, então É RECOMENDADO usar Recommends ou Suggests. Se a funcionalidade estiver disponível por padrão para os usuários, É RECOMENDADO usar Recommends, caso contrário usar Suggests. Alternativamente, as dependências reversas Supplements ou Enhances podem ser usadas em outro pacote. Consulte Packaging:WeakDependencies para obter diretrizes sobre como usar esses tipos de dependência.

Dependências específicas de arquitetura

Uma dependência torna-se específica do arco anexando a macro %{?_isa} ao nome do pacote. Por exemplo:

Requires: foo

se torna:

Requires: foo%{?_isa}

Se o pacote foo-devel tiver um script foo-config, você pode tentar fazer foo-config --libs e foo-config --cflags para obter dicas fortes de quais pacotes devem ser marcados como requisitos do foo. Por exemplo:

$ gtk-config --cflags
-I/usr/include/gtk-1.2 -I/usr/include/glib-1.2 -I/usr/lib/glib/include -I/usr/X11R6/include
$ gtk-config --libs
-L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmodule -lglib -ldl -lXi -lXext -lX11 -lm

Isso significa que gtk+-devel deve conter

Requires: glib-devel%{?_isa} libXi-devel%{?_isa} libXext-devel%{?_isa} libX11-devel%{?_isa}

Rich/Boolean Dependencies

Packages MAY make full use of the rich (or Boolean) dependency feature supported in RPM.

File and Directory Dependencies

RPM gives you the ability to depend on arbitrary files or directories instead of packages. Packages MAY include such dependencies for paths inside one of the following directories:

  • /usr/bin

  • /usr/sbin

  • /etc

They also MAY depend on paths listed in an explicit Provides:. They MUST NOT include dependencies on other paths, as that would require downloading of additional repository metadata to be enabled.

Please also note that it is not uncommon for multiple packages to provide the same directory. Directory dependencies SHOULD ONLY be used to express the dependency on that directory existing, not on any other functionality of any other package that might provide that directory.

When declaring file and directory dependencies, installation path macros like %{_bindir} MUST NOT be used. %{_bindir} of the package that provides sometool may be different from %{_bindir} of a package that requires sometool. In such case, BuildRequires: %{_bindir}/sometool does not work as expected.

Explicit Requires

Explicit Requires are Requires added manually by the packager in the spec file. Packages must not contain unnecessary explicit Requires on libraries. We generally rely on rpmbuild to automatically add dependencies on library SONAMEs. Modern package management tools are capable of resolving such dependencies to determine the required packages in many cases. However, present versions of rpmbuild only add deps on library SONAMES, not the library’s full version. This can be a problem if a library has added features over the course of time without backwards incompatibilities that would cause SONAMES to be changed. This can lead to a case where the user has an old version of a library installed, the new version of the library with new ABI is built in Fedora and an application using that ABI is built. If the user just attempts to install or update that one application without also updating the library, the application will install fine (because the SONAME dependency is satisfied) but will fail when run because the library installed on the system is missing features it needs.

Although you do need to add explicit library dependencies to keep this from occurring, there are drawbacks to manually specifying this in all your packages. History has shown that such dependencies add confusion when library/files are moved from one package to another, when packages get renamed, when one out of multiple alternative packages would suffice, and when versioned explicit dependencies become out-of-date and inaccurate. Additionally, in some cases, old explicit dependencies on package names require unnecessary updates/rebuilds. For example, Fedora packages are only required to retain historical provides for two full release cycles.

Because of this and because we hope to have this fixed in rpmbuild, this is something to be aware of but it’s not required that you explicitly specify the libraries you require with their version information.

When explicit library Requires are necessary, explicit library dependencies should typically be arch-specific (unless the packages involved are noarch) and there should be a spec file comment justifying it:

# The automatic dependency on libfubar.so.1 is insufficient,
# as we strictly need at least the release that fixes two segfaults.
Requires: libfubar%{?_isa} >= 0:1.2.3-7

Packagers should revisit an explicit dependency as appropriate to avoid it becoming inaccurate and superfluous. For instance in the example above, when no current Fedora release shipped with libfubar < 1.2.3-7, it is no longer necessary to list the explicit, versioned requirement.

Filtering Auto-Generated Requires

RPM attempts to auto-generate Requires (and Provides) at build time, but in some situations, the auto-generated Requires/Provides are not correct or not wanted. For more details on how to filter out auto-generated Requires or Provides, please see: Packaging:AutoProvidesAndRequiresFiltering.

Build-Time Dependencies (BuildRequires)

It is important that your package list all necessary build dependencies using the BuildRequires: tag. You MAY assume that enough of an environment exists for RPM to function, to build packages and execute basic shell scripts, but you SHOULD NOT assume any other packages are present as RPM dependencies and anything brought into the buildroot by the build system can change over time.

BuildRequires and %{_isa}

You MUST NOT use arched BuildRequires. The arch ends up in the built SRPM but SRPMs need to be architecture independent. For instance, if you did this:

# Example of what *not* to do
BuildRequires:  foo%{?_isa} >= 3.3

Then the SRPM that is built in Fedora would have one of these Requirements depending on what builder the SRPM was created on:

foo(x86-32) >= 3.3
# or
foo(x86-64) >= 3.3

Isso impediria que o yum-builddep ou ferramentas similares que usam os requisitos do SRPM funcionassem corretamente.

BuildRequires com base em pkg-config

Pacotes do Fedora que usam pkg-config para compilar em uma biblioteca (por exemplo, 'foo') da qual dependem, DEVEM expressar sua dependência de construção corretamente como pkgconfig(foo). Para obter mais informações, consulte Packaging:PkgConfigBuildRequires.

Dependências condicionais de tempo de construção

Se o arquivo spec contém dependências condicionais selecionadas com base na presença de argumentos opcionais --with(out) foo para rpmbuild, construa o RPM fonte a ser enviado com as opções padrão, ou seja, para que nenhum desses argumentos estão presentes na linha de comando rpmbuild. A razão é que esses requisitos são "serializados" no RPM fonte resultante, ou seja, as condicionais não se aplicam mais.

Summary and Description

The summary should be a short and concise description of the package. The description expands upon this. Do not include installation instructions in the description; it is not a manual. If the package requires some manual configuration or there are other important instructions to the user, refer the user to the documentation in the package. Add a README.Fedora, or similar, if you feel this is necessary. Also, please make sure that there are no lines in the description longer than 80 characters.

Please put personal preferences aside and use American English spelling in the summary and description. Packages can contain additional translated summary/description for supported Non-English languages, if available.

Trademarks in Summary or Description

Packagers should be careful how they use trademarks in Summary or Description. There are a few rules to follow:

  • Never use (TM) or (R) (or the Unicode equivalents, ™/®). It is incredibly complicated to use these properly, so it is actually safer for us to not use them at all.

  • Use trademarks in a way that is not ambiguous. Avoid phrasing like "similar to" or "like". Some examples:

  • BAD: It is similar to Adobe Photoshop.

  • GOOD: It supports Adobe Photoshop PSD files, …​

  • BAD: A Linux version of Microsoft Office

  • GOOD: A word-processor with support for Microsoft Office DOC files

If you’re not sure, ask yourself, is there any chance someone may get confused and think that this package is the trademarked item? When in doubt, try to leave the trademark out.

Documentation

Any relevant documentation included in the source distribution should be included in the package in the proper documentation directory. Irrelevant documentation includes build instructions, the omnipresent INSTALL file containing generic build instructions, or example, and documentation for non-Linux systems, e.g. README.MSDOS. Also pay attention about which subpackage you include documentation in. For example API documentation belongs in the -devel subpackage, not the main one. Or if there’s a lot of documentation, consider putting it into a subpackage. In this case, it is recommended to use *-doc as the subpackage name.

Marking a relative path with %doc in the %files section will cause RPM to copy the referenced file or directory from %_builddir to the proper location for documentation. Files can also be placed in %_pkgdocdir, and the build scripts of the software being packaged may do this automatically when called in %install. However, mixing these methods is problematic and may result in duplicated or conflicting files, so use of %doc with relative paths and installation of files directly into %_pkgdocdir in the same source package is forbidden.

Files marked as documentation must not cause the package to pull in more dependencies than it would without the documentation. One simple way to ensure this in most cases is to remove all executable permissions from files in %_pkgdocdir.

Files located in %_pkgdocdir must not affect the runtime of the packaged software. The software must function properly and with unchanged functionality if those files are modified, removed or not installed at all.

Although license files are documentation, they are treated specially (including using a different tag). Please see Licensing Guidelines for how to handle them.

Separate Documentation Packages

If building documentation requires many additional dependencies then you MAY elect to not build it in the main package and instead create a separate *-doc source package which builds only the documentation. This separately packaged documentation MUST correspond to the version of the packaged software. In other words, if a new release of the software includes changes to the documentation, then the documentation package MUST also be updated. But if the new version of the software does not include documentation changes, then you MAY choose not to update the documentation package.

A comment SHOULD be added near Version tag of the main package to remind maintainers to update the separate *-doc package when needed.

Changelogs

The changelog describes the changes to the package that are relevant to the users of the package. This includes new upstream versions, important changes to how the package is built, rebuilds, and other changes affecting the outcome. Changes which are only relevant to packagers should not be mentioned in the changelog. This includes spec file cleanups, build error fixes or workarounds, and other changes which don’t have an effect on content of the binary packages.

The changelog should be generated automatically from git commit logs using the %autochangelog macro:

%changelog
%autochangelog

The commit subject (the first line of the commit message) and optionally some additional lines are used to generate the changelog text. The commit author name and email address and the commit timestamp are also used in changelog entry.

The text in the the commit message which will become part of the changelog should should provide a brief summary of the changes relevant for the user. The commit message may contain additional information that is relevant to packagers.

If a particular change is related to a Bugzilla bug, include the bug ID in the changelog entry for easy reference, e.g.

Add README file (rhbz#1000042)

If a particular commit fixes a CVE, this information should be included too.

The intent is to give the user a hint as to what changed in a package update without overwhelming them with the technical details. They must never simply contain an entire copy of the source CHANGELOG entries. Links to upstream NEWS files or changelogs can be entered for those who want additional information.

See autochangelog documentation for the details of how the changelog is generated from git commit messages, and how to create multi-line entries or skip entries for certain commits.

Packagers may alternatively use a manual changelog instead of the %autochangelog macro. This is described in Manual Changelog.

Exemplo

The packager updates package to version 1.0 and creates a commit

$ git show
commit 0000000000001234567890ABCDEF000000000000
Author: Joe Packager <joe@example.com>
Date:   Wed Jun 14 2003

    Version 1.0

    ... (rhbz#1000024)
    - Also fixes the slowdown reported in rhbz#1000025
    - Upstream changelog: https://example.com/package/NEWS.html#v1.0

    Whitespace in the spec file has been cleaned up.

diff --git package.spec package.spec
index 5c77064c03..efcd53a61c 100644
--- package.spec
+++ package.spec
@@ -1,5 +1,5 @@
 Name:           package
-Version:        0.1
+Version:        0.2
 Release:        %autorelease
...

When the package is built, an appropriate changelog entry will be generated. It can be previewed with rpmautospec generate-chagengelog:

$ rpmautospec generate-changelog
* Wed Jun 14 2003 Joe Packager <joe@example.com> - 0.2-1
- Version 1.0 (rhbz#1000024)
- Also fixes the slowdown reported in rhbz#1000025
- Upstream changelog: https://example.com/package/NEWS.html#v1.0

Note that the sentence about whitespace is not included in the changelog.

Manpages

As man pages are the traditional method of getting help on a Unix system, packages SHOULD contain them for all executables. If some man pages are absent, packagers SHOULD work with upstream to add them. It is also occasionally possible to find pages created by other distributions, or to use the output of the help2man program; those are often useful as a starting point. When installing man pages, note that RPM will re-compress them into its preferred format. So the %files section MUST reference manpages with a pattern that takes this into account:

%files
%{_mandir}/man1/foo.1*

Note also that files installed in %{_mandir} are automatically marked by RPM as documentation. Thus it is not necessary to use %doc.

For localised manpages, use %find_lang --with-man as described in Handling Locale Files.

Compiler

Fedora packages should default to using gcc as the compiler (for all languages that gcc supports) or clang if upstream does not support building with gcc. However, if there is a good technical reason, packagers may choose not to use the default compiler. Examples of valid technical reasons to not use the default compiler, include but are not limited to:

  • The default compiler cannot build a package correctly.

  • The packager needs to disable a compiler feature (e.g. LTO) in order for the default compiler to correctly compile their package.

  • The default compiler takes significantly longer to build a package.

  • The default compiler is missing a feature that would benefit the package.

Packagers choosing to use a non-default compiler should document the reason for this decision in a comment in the spec file.

Compiler Macros

If clang is being used to build a package, packagers must set the %toolchain macro to clang:

%global toolchain clang

This ensures that Fedora’s clang-specific compiler flags are used when compiling.

If a packager wants to use conditional macros in a spec file to make it easier to switch between two different compilers, then the following macros names should be used:

%bcond_with toolchain_clang
%bcond_with toolchain_gcc

Packagers may also use the %build_cc, %build_cxx, or %build_cpp macros in the spec file in place of hard-coding the compiler name. The values of these variables are controled by setting the %toolchain macro to either clang or gcc.

Compiler Flags

Compilers used to build packages must honor the applicable compiler flags set in the system rpm configuration. Honoring means that the contents of that variable is used as the basis of the flags actually used by the compiler during the package build.

For C, C++, and Fortran code, the %{optflags} macro contains these flags. Overriding these flags for performance optimizations (for instance, -O3 instead of -O2) is generally discouraged. If you can present benchmarks that show a significant speedup for this particular code, this could be revisited on a case-by-case basis. Adding to and overriding or filtering parts of these flags is permitted if there’s a good reason to do so; the rationale for doing so must be documented in the specfile.

There are certain, security related flags that are commonly allowed. These flags may degrade performance slightly but the increased security can be worthwhile for some programs.

PIE

PIE adds security to executables by composing them entirely of position-independent code. Position-independent code (PIC) is machine instruction code that executes properly regardless of where in memory it resides. PIE allows Exec Shield to use address space layout randomization to prevent attackers from knowing where existing executable code is during a security attack using exploits that rely on knowing the offset of the executable code in the binary, such as return-to-libc attacks.

In Fedora, PIE is enabled by default. To disable it in your spec, add:

%undefine _hardened_build

If your package meets any of the following criteria you MUST NOT disable the PIE compiler flags:

  • Your package is long running. This means it’s likely to be started and keep running until the machine is rebooted, not start on demand and quit on idle.

  • Your package has suid binaries, or binaries with capabilities.

  • Your package runs as root.

Debuginfo Packages

Packages should produce useful -debuginfo packages, or explicitly disable them when it is not possible to generate a useful one but rpmbuild would do it anyway. Whenever a -debuginfo package is explicitly disabled, an explanation why it was done is required in the specfile. Debuginfo packages are discussed in more detail in a separate document, Packaging:Debuginfo.

Devel Packages

Fedora packages must be designed with a logical separation of files. Specifically, -devel packages must be used to contain files which are intended solely for development or needed only at build-time. This is done to minimize the install footprint for users. There are some types of files which almost always belong in a -devel package:

  • Header files (foo.h), usually found in /usr/include

  • Static library files when the package does not provide any matching shared library files. See Packaging Static Libraries for more information about this scenario.

  • Unversioned shared system library files, when a matching versioned shared system library file is also present. For example, if your package contains:

   /usr/lib/libfoo.so.3.0.0
   /usr/lib/libfoo.so.3
   /usr/lib/libfoo.so

The versioned shared library files (/usr/lib/libfoo.so.3.2.0 and /usr/lib/libfoo.so.3) are necessary for users to run programs linked against libfoo, so they belong in the base package. The other, unversioned, shared library file (/usr/lib/libfoo.so) is only used to actually link libfoo to code being compiled, and is not necessary to be installed on a users system. This means that it belongs in a -devel package. Please note that in most cases, only the fully versioned shared library file (/usr/lib/libfoo.so.3.2.0) is an actual file, all of the other files are symbolic links to it. When a shared library file is only provided in an unversioned format, the packager should ask upstream to consider providing a properly versioned library file. However, in such cases, if the shared library file is necessary for users to run programs linked against it, it must go into the base package. If upstream versions the shared library file at a future point, packagers must be careful to move to the versioned layout described above.

As an additional complication, some software generates unversioned shared objects which are not intended to be used as system libraries. These files are usually plugins or modular functionality specific to an application, and are not located in the ld library paths or cache. This means that they are not located directly in /usr/lib or /usr/lib64, or in a directory listed as a library path in /etc/ld.so.conf (or an /etc/ld.so.conf.d/config file). Usually, these unversioned shared objects can be found in a dedicated subdirectory under /usr/lib or /usr/lib64 (e.g. /usr/lib/purple-2/ is the plugin directory used for libpurple applications). In these cases, the unversioned shared objects do not need to be placed in a -devel package.

There are some notable exceptions to this packaging model, specifically:

  • compilers often include development files in the main package because compilers are themselves only used for software development, thus, a split package model does not make any sense.

When in doubt as to whether a file belongs in the base package or in -devel, packagers should consider whether the file is necessary to be present for a user to use or execute the functionality in the base package properly, or if it is only necessary for development. If it is only necessary for development, it must go into a -devel package.

As with all Fedora Packaging Guidelines, it is recognized that there are unique situations that fall outside of the boundaries of this model. Should you come across such a case, please open a ticket with the Fedora Packaging Committee and explain it to us so that we can extend the Guidelines to address it.

Pkgconfig Files (foo.pc)

The placement of pkgconfig(.pc) files depends on their usecase. Since they are almost always used for development purposes, they should be placed in a -devel package. A reasonable exception is when the main package itself is a development tool not installed in a user runtime, e.g. gcc or gdb.

Requiring Base Package

Subpackages are often extensions for their base package and in that case they should require their base package. When a subpackage requires the base package, it MUST do so using a fully versioned arch-specific (for non-noarch packages) dependency:

Requires: %{name}%{?_isa} = %{version}-%{release}

Devel packages are an example of a package that must require their base packages using a fully versioned dependency. -libs subpackages which only contain shared libraries do not normally need to explicitly depend on their base packages as they usually do not need the base package to be functional libraries.

If you end up in a situation where the main package depends on the subpackage and the subpackage on the main package you should think carefully about why you don’t have everything in the main package.

Shared Libraries

Whenever possible (and feasible), Fedora packages containing libraries SHOULD build them as shared libraries. It is not necessary to call ldconfig when installing shared libraries.

Listing Shared Library Files

Shared libraries installed directly into %{_libdir} SHOULD NOT be listed in the %files section of the spec by using a glob in a way that conceals important parts of the file name (e.g. libfoo.so*), since changes to the SONAME also result in a changed file name in most cases.

Otherwise, when the library bumps its SONAME as part of an update, this change might remain unnoticed and cause problems like broken dependencies (see the relevant Updates Policy section for further information).

However, if the use of globs is deemed useful by the packager - for example, if the Y and Z parts of a library named libfoo.so.X.Y.Z change frequently, using something like libfoo.so.X{,.*} is recommended instead, since dependent packages usually don’t have to be rebuilt for changes of this kind.

Downstream .so Name Versioning

In cases where upstream ships unversioned .so library (so this is not needed for plugins, drivers, etc.), the packager MUST try to convince upstream to start versioning it.

If that fails due to unwilling or unresponsive upstream, the packager may start versioning downstream but this must be done with caution and ideally only in rare cases. We don’t want to create a library that could conflict with upstream if they later start providing versioned shared libraries. Under no circumstances should the unversioned library be shipped in Fedora.

For downstream versioning, the name should be composed like this:

libfoobar.so.0.n

The n should initially be a small integer (for instance, "1"). we use two digits here ("0.n") because the common practice with upstreams is to use only a single digit here. Using multiple digits helps us avoid potential future conflicts. Do not forget to add the SONAME field (see below) to the library.

When new versions of the library are released, you should use an ABI comparison tool to check for ABI differences in the built shared libraries. If it detects any incompatibilities, bump the n number by one.

SONAME Handling

When running an executable linked to shared object with SONAME field, the dynamic linker checks for this field instead of filename to determine the object with which it should link. This allows developers to simply link against the unversioned library symlink and the dynamic linker will link against the correct object.

Keep in mind that although the filename is usually the library’s SONAME plus an incrementing minor version there’s nothing that intrinsically links these. ldconfig uses the SONAME as the value for a symlink to the actual filename. The dynamic linker then uses that symlink to find the library, disregarding the actual filename. The dynamic linker merely does a simple equality check on the field and does not check for ABI incompatibilities or similar problems. This is the main reason for using an ABI comparison tool and incrementing the SONAME.

The SONAME field is written to the shared object by linker, using (at least in case of ld) the -soname SONAME flags. This can be passed as an option to gcc like this:

$ gcc $CFLAGS -Wl,-soname,libfoo.so.0.n -o libfoo.so.0.n

If you want to check if the SONAME field is set and what value it has, use the objdump command (from binutils):

$ objdump -p /path/to/libfoo.so.0.n | grep 'SONAME'

Packaging Static Libraries

Packages including libraries SHOULD exclude static libs as far as possible (e.g., by configuring with --disable-static). Applications linking against libraries SHOULD link against shared libraries not static versions.

Libtool archives, foo.la files, SHOULD NOT be included. Packages using libtool will install these by default even if you configure with --disable-static, so they may need to be removed before packaging. Due to bugs in older versions of libtool or bugs in programs that use it, there are times when it is not always possible to remove *.la files without modifying the program. In most cases it is fairly easy to work with upstream to fix these issues. Note that if you are updating a library in a stable release (not devel) and the package already contains *.la files, removing the *.la files SHOULD be treated as an API/ABI change — i.e., removing them changes the interface that the library gives to the rest of the world thus MUST follow Fedora policies for potentially destabilizing updates.

Packaging Static Libraries

  • In general, packagers SHOULD NOT ship static libraries.

  • We want to be able to track which packages are using static libraries (so we can find which packages need to be rebuilt if a security flaw in a static library is fixed, for instance). There are two scenarios in which static libraries are packaged:

    1. Static libraries and shared libraries. In this case, the static libraries MUST be placed in a *-static subpackage. Separating the static libraries from the other development files in *-devel allow us to track this usage by checking which packages BuildRequire the *-static package. The intent is that whenever possible, packages will move away from using these static libraries, to the shared libraries. If the *-static subpackage requires headers or other files from *-devel in order to be useful it MUST require the *-devel subpackage.

    2. Static libraries only. When a package only provides static libraries you MAY place all the static library files in the *-devel subpackage. When doing this you also MUST have a virtual Provide for the *-static package:

      %package devel
      Provides: foo-static = %{version}-%{release}

Packages which explicitly need to link against the static version MUST BuildRequire: foo-static, so that the usage can be tracked.

  • If (and only if) a package has shared libraries which require static libraries to be functional, the static libraries can be included in the *-devel subpackage. The devel subpackage must have a virtual Provide for the *-static package, and packages dependent on it must BuildRequire the *-static package.

Packaging Header Only Libraries

Certain libraries, especially some C++ template libraries, are header only libraries. Since the code is generated during compile time, they act just like static libraries and need to be treated as such.

Place all of the header files in the *-devel subpackage and then you must have a virtual Provide for the *-static package:

%package devel
Provides: foo-static = %{version}-%{release}

Packages which use the header library must BuildRequire: foo-static, so that the usage can be tracked.

Use noarch only in subpackages

The base package for a header library MUST NOT be marked noarch. This ensures that any tests are run on all architectures, and makes it possible to detect whether the build or install process has modified the headers based on the build architecture.

When the contents of subpackages, including the -devel package, are actually architecture-independent, they may still be marked noarch. Since the base package for a header library typically has no %files list, this may result in an arched package that builds only noarch rpms.

Statically Linking Executables

Executables and libraries SHOULD NOT be linked statically against libraries which come from other packages. (It is of course acceptable for files generated during a package’s build process to be linked statically against .a files generated as part of that build process.)

If it is necessary to link against .a files from a different package, a build dependency on the -static package (not just the -devel package) which provides those files MUST be present so that the usage can be tracked.

Bundling and Duplication of System Libraries

Fedora packages SHOULD make every effort to avoid having multiple, separate, upstream projects bundled together in a single package.

All packages whose upstreams allow them to be built against system libraries MUST be built against system libraries. In this case, bundled libraries (and/or their source code) MUST be explicitly deleted during %prep. Build scripts may need to be patched to deal with this situation. Whenever possible, the patch should conditionalize the use of the bundled libraries, so that the patch can be sent upstream for consideration.

All packages whose upstreams have no mechanism to build against system libraries MAY opt to carry bundled libraries, but if they do, they MUST include an indication of what they bundle. This provides a mechanism for locating libraries with bundled code which can, for example, assist in locating packages which may have particular security vulnerabilities.

To indicate an instance of bundling, first determine the name and version of the bundled library:

  • If the bundled package also exists separately in the distribution, use the name of that package. Otherwise consult the Naming Guidelines to determine an appropriate name for the library as if it were entering the distribution as a separate package.

  • Use the Versioning Guidelines to determine an appropriate version for the library, if possible. If the library has been forked from an upstream, use the upstream version that was most recently merged in or rebased onto, or the version the original library carried at the time of the fork.

Then at an appropriate place in your spec, add Provides: bundled(<libname>) = <version> where <libname> and <version> are the name and version you determined above. If it was not possible to determine a version, use Provides: bundled(<libname>) instead.

In addition to indicating bundling in this manner, packages whose upstreams have no mechanism to build against system libraries must be contacted publicly about a path to supporting system libraries. If upstream refuses, this must be recorded in the spec file, either in comments placed adjacent to the Provides: above, or in an additional file checked into the SCM and referenced by a comment placed adjacent to the Provides: above.

Avoid Bundling of Fonts in Other Packages

Fonts in general-purpose formats such as Type1, OpenType TT (TTF) or OpenType CFF (OTF) are subject to specific packaging guidelines (Packaging/FontsPolicy), and should always be packaged in the system-wide font repositories instead of private application directories. For more information, see: Packaging/FontsPolicy.

Beware of rpath

Sometimes, code will hardcode specific library paths when linking binaries (using the -rpath or -R flag). This is commonly referred to as an rpath. Normally, the dynamic linker and loader (ld.so) resolve the executable’s dependencies on shared libraries and load what is required. However, when -rpath or -R is used, the location information is then hardcoded into the binary and is examined by ld.so in the beginning of the execution. Since the Linux dynamic linker is usually smarter than a hardcoded path, we usually do not permit the use of rpath in Fedora.

There is a tool called check-rpaths which is included in the rpmdevtools package. It is a good idea to add it to the %__arch_install_post macro in your ~/.rpmmacros config file:

%__arch_install_post          \
/usr/lib/rpm/check-rpaths     \
/usr/lib/rpm/check-buildroot

When check-rpaths is run, you might see output like this:

ERROR   0001: file '/usr/bin/xapian-tcpsrv' contains a standard rpath '/usr/lib64' in [/usr/lib64]

Any rpath flagged by check-rpaths MUST be removed.

rpath for Internal Libraries

When a program installs internal libraries they are often not installed in the system path. These internal libraries are only used for the programs that are present in the package (for example, to factor out code that’s common to the executables). These libraries are not intended for use outside of the package. When this occurs, it is acceptable for the programs within the package to use an rpath to find these libraries.

Example:

# Internal libraries for myapp are present in:
%{_libdir}/myapp/
%{_libdir}/myapp/libmyapp.so.0.3.4
%{_libdir}/myapp/libmyapp.so

# myapp has an rpath to %{_libdir}/myapp/
readelf -d /usr/bin/myapp | grep RPATH
 0x0000000f (RPATH)                      Library rpath: [/usr/lib/myapp]
Bibliotecas não internas: Quando programas fora do pacote devem se vincular à biblioteca, é melhor usar Alternativa ao Rpath ou simplesmente mover as bibliotecas para %{_libdir}. Dessa forma, o vinculador dinâmico pode encontrar as bibliotecas sem precisar vincular todos os programas a um rpath.

Alternatives to rpath

Often, rpath is used because a binary is looking for libraries in a non-standard location (standard locations are /lib, /usr/lib, /lib64, /usr/lib64). If you are storing a library in a non-standard location (e.g. /usr/lib/foo/), you should include a custom config file in /etc/ld.so.conf.d/. For example, if I was putting 32 bit libraries of libfoo in /usr/lib/foo, I would want to make a file called "foo32.conf" in /etc/ld.so.conf.d/, which contained the following:

/usr/lib/foo

Make sure that you also make a 64bit version of this file (e.g. foo64.conf) as well (unless the package is disabled for 64bit architectures, of course).

Removing rpath

There are several different ways to fix the rpath issue:

  • If the application uses configure, try passing the --disable-rpath flag to configure.

  • If the application uses a local copy of libtool, add the following lines to the spec after %configure:

%configure
sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool
sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
  • Sometimes, the code/Makefiles can be patched to remove the -rpath or -R flag from being called. This is not always easy or sane to do, however.

  • As a last resort, Fedora has a package called chrpath. When this package is installed, you can run chrpath --delete on the files which contain rpaths. So, in our earlier example, we’d run:

chrpath --delete $RPM_BUILD_ROOT%{_bindir}/xapian-tcpsrv

Make sure that you remember to add a BuildRequires: chrpath if you end up using this method.

Configuration Files

Configuration files must be marked as such in packages.

As a rule of thumb, use %config(noreplace) instead of plain %config unless your best, educated guess is that doing so will break things. In other words, think hard before overwriting local changes in configuration files n package upgrades. An example case when not to use noreplace is when a package’s configuration file changes so that the new package revision wouldn’t work with the config file from the previous package revision. Whenever plain %config is used, add a brief comment to the specfile explaining why.

Don’t use %config or %config(noreplace) under /usr. /usr is deemed to not contain configuration files in Fedora.

Configuration of Package Managers

Packages MUST NOT install repository configuration files which violate the Third Party Repository Policy, unless those files are installed under %{_docdir}.

Per-Product Configuration

In the Fedora.next world, we will have a set of curated Fedora Products as well as the availability of classic Fedora. Historically, we have maintained a single set of configuration defaults for all Fedora installs but different target use-cases have different needs. Please see the Per-Product Configuration Guidelines for instructions on how to create packages that need to behave differently between Fedora.next Products.

Initscripts

SystemV-style initscripts are forbidden in Fedora. Systemd units must be used instead.

Systemd Units

Detailed guidelines for packaging systemd units and systemd-managed services are here.

Desktop Files

If a package contains a GUI application, then it needs to also include a properly installed .desktop file. For the purposes of these guidelines, a GUI application is defined as any application which draws an X window and runs from within that window. Installed .desktop files MUST follow the desktop-entry-spec, paying particular attention to validating correct usage of Name, GenericName, Categories, StartupNotify entries.

Icon Tag in Desktop Files

The icon tag can be specified in two ways:

  • Full path to specific icon file:

Icon=/usr/share/pixmaps/comical.png

  • Short name without file extension:

Icon=comical

The short name without file extension is preferred, because it allows for icon theming (it assumes .png by default, then tries .svg and finally .xpm), but either method is acceptable.

.desktop File Creation

If the package doesn’t already include and install its own .desktop file, you need to make your own. You can do this by including a .desktop file you create as a Source: (e.g. Source3: %{name}.desktop) or generating it in the spec file. Here are the contents of a sample .desktop file (comical.desktop):

[Desktop Entry]
Name=Comical
GenericName=Comic Archive Reader
Comment=Open .cbr & .cbz files
Exec=comical
Icon=comical
Terminal=false
Type=Application
Categories=Graphics;

desktop-file-install Usage

It is not simply enough to just include the .desktop file in the package, one MUST run desktop-file-install (in %install) OR desktop-file-validate (in %check or %install) and have BuildRequires: desktop-file-utils, to help ensure .desktop file safety and spec-compliance. desktop-file-install MUST be used if the package does not install the file or there are changes desired to the .desktop file (such as add/removing categories, etc). desktop-file-validate MAY be used instead if the .desktop file’s content/location does not need modification. Here are some examples of usage:

desktop-file-install                                    \
--dir=%{buildroot}%{_datadir}/applications              \
%{SOURCE3}
desktop-file-install                                    \
--add-category="AudioVideo"                             \
--delete-original                                       \
--dir=%{buildroot}%{_datadir}/applications              \
%{buildroot}/%{_datadir}/applications/foo.desktop
desktop-file-validate %{buildroot}/%{_datadir}/applications/foo.desktop

Do not apply a vendor tag to .desktop files (using --vendor).

AppData Files

Packages containing graphical applications should include AppData files. See Packaging:AppData for the relevant guidelines.

Macros

Packagers are strongly encouraged to use macros instead of hard-coded directory names (see RPMMacros). However, in situations where the macro is longer than the path it represents, or situations where the packager feels it is cleaner to use the actual path, the packager is permitted to use the actual path instead of the macro. There are several caveats to this approach:

  • The package must be consistent. For any given path, within the same spec, use either a hard-coded path or a macro, not a combination of the two.

  • %{_libdir} must always be used for binary libraries due to multi-lib, you may not substitute a hard-coded path.

Macros with names beginning with underscores are generally considered to be implementation details internal to RPM and its associated macro packages and SHOULD NOT be referenced in specfiles except to set their values in order to influence RPM behavior. This implies that macro forms of system executables SHOULD NOT be used. For example, rm should be used in preference to %{__rm}. However, in some cases needed data are simply not provided under names which are not prefixed with underscores. If that is the case, the macro named with leading underscores MAY be used. Authors of macro packages are encouraged to avoid using leading underscores when naming macros which are intended to be used in specfiles (as opposed to being set).

Having macros in a Source: or Patch: line is a matter of style. Some people enjoy the ready readability of a source line without macros. Others prefer the ease of updating for new versions when macros are used. In all cases, remember to be consistent in your spec file and verify that the URLs you list are valid. spectool (from the rpmdevtools package) can aid you in checking that whether the URL contains macros or not.

If you need to determine the actual string when it contains macros, you can use rpm. For example, to determine the actual Source: value, you can run:

rpm -q --specfile foo.spec --qf "$(grep -i ^Source foo.spec)\n"

%autosetup

As an alternative to the usual %setup macro, the %autosetup can be used. In addition to the normal %setup tasks, it will apply all defined Patch# items in the spec automatically. It is also capable of handling VCS formatted patch files, but this will require additional BuildRequires, and assumes that all patch files in the spec are formatted for that single VCS type. For this reason, it is not recommended that you specify a VCS with %autosetup. For more details on proper use of %autosetup, refer to the RPM documentation.

Using %{buildroot} and %{optflags} vs $RPM_BUILD_ROOT and $RPM_OPT_FLAGS

There are two styles of defining the rpm Build Root and Optimization Flags in a spec file:

macro style

variable style

Build Root

%{buildroot}

$RPM_BUILD_ROOT

Opt. Flags

%{optflags}

$RPM_OPT_FLAGS

There is very little value in choosing one style over the other, since they will resolve to the same values in all scenarios. You should pick a style and use it consistently throughout your packaging.

Mixing the two styles, while valid, is bad from a QA and usability point of view, and should not be done in Fedora packages.

Why the %makeinstall Macro Should Not Be Used

Fedora’s RPM includes a %makeinstall macro but it must NOT be used when make install DESTDIR=%{buildroot} works. %makeinstall is a kludge that can work with Makefiles that don’t make use of the DESTDIR variable but it has the following potential issues:

  • %makeinstall overrides a set of Make variables during "make install" and prepends the %{buildroot} path, i.e. it performs make prefix="%{buildroot}%{_prefix}" libdir="%{buildroot}%{_libdir} …​".

  • It is error-prone and can have unexpected effects when run against less than perfect Makefiles, e.g., the buildroot path may be included in installed files where variables are substituted at install-time.

  • It can trigger unnecessary and wrong rebuilds when executing "make install", since the Make variables have different values compared with the %build section.

  • If a package contains libtool archives, it can cause broken *.la files to be installed.

Instead, Fedora packages should use: %make_install (Note the "_" !), make DESTDIR=%{buildroot} install or make DESTDIR=$RPM_BUILD_ROOT install. Those all do the same thing.

Source RPM Buildtime Macros

All macros in Summary: and %description need to be expandable at srpm buildtime. Because SRPMs are built without the package’s BuildRequires installed, depending on macros defined outside of the spec file can easily lead to the unexpanded macros showing up in the built SRPM. One way to check is to create a minimal chroot and build the srpm:

mock --init
mock --copyin [SRPM] /
mock --shell bash
rpm -ivh [SRPM]
cd /builddir/build/SPECS
rpmbuild -bs --nodeps [SRPM]
rpm -qpiv /builddir/build/SRPMS/[SRPM]

Check the rpm output for unexpanded macros (%{foo}) or missing information (when`%{?foo}` is expanded to the empty string). Even easier is to simply avoid macros in Summary: and %description unless they are defined in the current spec file.

Improper Use of %_sourcedir

Packages which use files itemized as Source# files, must refer to those files by their Source# macro name, and must not use $RPM_SOURCE_DIR or %{sourcedir} to refer to those files. See Packaging:RPM_Source_Dir for full details.

Software Collection Macros

Software Collections are to be kept to separate packages from mainstream packages similar to how MingW packages are managed.

In the past, SCL macros were allowed to be present inside of mainstream packages if they were not used. Since we’re now building SCLs, we are now enforcing a strict separation. Packages MUST be updated to restrict SCL macros to only those packages particularly approved as part of an SCL.

Packaging of Additional RPM Macros

Additional RPM macros must be stored in %{_rpmmacrodir}. They must be named using the syntax "macros.$PACKAGE" (e.g. macros.perl).

Normally, these files are packaged in the -devel subpackage, since they are usually only needed for building other packages. However, in some situations, this is not always ideal and packagers are encouraged to use their best judgment when determining the proper package for these files. RPM macro files MUST NOT be marked as %config.

Scripting Inside of Specfiles

Sometimes it is necessary to write a short script (perhaps a one-liner) that is executed in the %prep, %build, or %install sections of a spec file to get some information about the build environment. In order to simplify the dependency graph, spec files should only use the following languages for this purpose:

  • Python

  • Perl

  • Standard programs used in shell programing, for instance gawk or sed

  • Lua (as supported by the native lua interpreter in rpm)

Additionally, if your package cannot build without a specific scripting language (such as Ruby, or Tcl), and therefore already has a BuildRequires on that language, it may also be called from the spec file.

Note: If you call Perl or Python in your spec file (and it is not already a BuildRequires for the package), you need to explicitly add a BuildRequires for Perl or Python.

%global Preferred Over %define

Use %global instead of %define, unless you really need only locally defined submacros within other macro definitions (a very rare case).

Rationale: The two macro defining statements behave the same when they are at the top level of rpm’s nesting level.

But when they are used in nested macro expansions (like in %{!?foo: ... } constructs, %define theoretically only lasts until the end brace (local scope), while %global definitions have global scope.

Note that %define and %global differ in more ways than just scope: the body of a %define’d macro is lazily expanded (i.e., when used), but the body of %global is expanded at definition time. It’s possible to use %%-escaping to force lazy expansion of %global.

Handling Locale Files

Translation files may be handled by different programs for different frameworks. Make sure you add BuildRequires: for the correct package or else your package could fail to generate translation files in the buildroot.

If the package uses gettext for translations, add

BuildRequires: gettext

For Qt-based packages that use the Linguist tool chain, for the localization utilities add

BuildRequires: qt-devel

If you have few enough locale files that they can all go into one package, you can use the %find_lang macro. (If you need to split your package into separate language packs, please see the langpack guidelines.) This macro will locate all of the them belonging to your package (by name), and put this list in a file. You can then use that file to include all of the locales. %find_lang should be run in the %install section of your spec file, after all of the files have been installed into the buildroot. The correct syntax for %find_lang is usually:

%find_lang %{name}

In some cases, the application may use a different "name" for its locales. You may have to look at the locale files and see what they are named. If they are named myapp.mo, then you will need to pass myapp to %find_lang instead of %{name}. After %find_lang is run, it will generate a file in the active directory (by default, the top level of the source dir). This file will be named based on what you passed as the option to the %find_lang macro. Usually, it will be named %{name}.lang. You should then use this file in the %files list to include the locales detected by %find_lang. To do this, you should include it with the -f parameter to %files.

%files -f %{name}.lang
%{_bindir}/foobar
...

Note that %find_lang by default searches for gettext locales, but it can also handle Qt translations, localised manpages and help files.

To process GNOME help files put into /usr/share/gnome/help/ use

%find_lang %{name} --with-gnome

To process KDE help files put into /usr/share/doc/HTML/ use

%find_lang %{name} --with-kde

To process Qt’s .qm binary translation files use

%find_lang %{name} --with-qt

To process localised manpages (doesn’t include the default, non-localised one), use

%find_lang %{name} --with-man

To see all the options, run /usr/lib/rpm/find-lang.sh in the terminal.

Names different from %{name} (e.g. multiple manpages) must be handled via separate calls to %find_lang.

Here is an example of proper usage of %find_lang, in foo.spec with the "foo" application localised using gettext and man pages named "bar" instead of "foo":

Name: foo
...
%prep
%setup -q

%build
%configure --with-cheese
make %{?_smp_mflags}

%install
make DESTDIR=%{buildroot} install
%find_lang %{name}
%find_lang bar --with-man

%files -f %{name}.lang -f bar.lang
%license LICENSE
%doc README
%{_bindir}/%{name}
%{_mandir}/man1/bar.1*

%changelog
* Fri Jan 13 2012 Karel Volny <kvolny@redhat.com> 0.1-2
- add man pages example

* Thu May 4 2006 Tom "spot" Callaway <tcallawa@redhat.com> 0.1-1
- sample spec that uses %%find_lang

Why do we need to use %find_lang?

Using %find_lang helps keep the spec file simple, and helps avoid several other packaging mistakes.

  • Packages that use %{_datadir}/* to grab all the locale files in one line also grab ownership of the locale directories, which is not permitted.

  • Most packages that have locales have lots of locales. Using %find_lang is much easier in the spec file than having to do:

%{_datadir}/locale/ar/LC_MESSAGES/%{name}.mo
%{_datadir}/locale/be/LC_MESSAGES/%{name}.mo
%{_datadir}/locale/cs/LC_MESSAGES/%{name}.mo
%{_datadir}/locale/de/LC_MESSAGES/%{name}.mo
%{_datadir}/locale/es/LC_MESSAGES/%{name}.mo
...
  • As new locale files appear in later package revisions, %find_lang will automatically include them when it is run, preventing you from having to update the spec any more than is necessary.

Keep in mind that usage of %find_lang in packages containing locales is a MUST unless the locale files are broken out into langpacks. In which case, you should follow the langpack guidelines.

Log Files

Packages which generate log files should write out their logfiles in a package-specific (and package owned) directory under %{_localstatedir}/log. Unless the software being packaged rotates its own logs, it must also ship a logrotate config file to rotate its log file(s).

logrotate Config File

Logrotate config files should be named in a way that matches the daemon/software which is generating the logs, which is usually (though not always) the same name as the package. When unsure, use "%{name}.conf". These files must be placed in %{_sysconfdir}/logrotate.d, and should use standard file permissions (0644) and ownership (root:root).

Since these are config files, they must be marked as %config(noreplace) in the %files list.

Example Minimal logrotate Config File

/var/log/example/*log {
    missingok       # If the log file is missing, go on to the next one without issuing an error message
    notifempty      # Don't do any rotation if the logfile is empty
    compress        # Compress older files with gzip
    delaycompress       # Don't compress yesterdays files
}

Timestamps

When adding file copying commands in the spec file, consider using a command that preserves the files' timestamps, e.g., cp -p or install -p.

When downloading sources, patches etc., consider using a client that preserves the upstream timestamps. For example wget -N or curl -R. To make the change global for wget, add this to your ~/.wgetrc: timestamping = on, and for curl, add to your ~/.curlrc: -R.

Parallel Make

Whenever possible, invocations of make should be done as

%make_build

This generally speeds up builds and especially on SMP machines.

Do make sure, however, that the package builds cleanly this way as some make files do not support parallel building. Therefore you should consider adding

%_smp_mflags -j3

to your ~/.rpmmacros file — even on UP machines — as this will expose most of these errors.

Scriptlets

Great care should be taken when using scriptlets in Fedora packages. If scriptlets are used, those scriptlets must be sane. Some common scriptlets are documented here.

Scriplets are only allowed to write in certain directories

Build scripts of packages (%prep, %build, %install, %check and %clean) may only alter files (create, modify, delete) under %{buildroot}, %{_builddir} and valid temporary locations like /tmp, /var/tmp (or $TMPDIR or %{_tmppath} as set by the rpmbuild process) according to the following matrix

/tmp, /var/tmp, $TMPDIR, %{_tmppath}

%{_builddir}

%{buildroot}

%prep

yes

yes

no

%build

yes

yes

no

%install

yes

yes

yes

%check

yes

yes

no

%clean

yes

yes

yes

Further clarification: That should hold true irrespective of the builder’s uid.

Build Packages with Separate User Accounts

When building software, which you have not conducted a full security-audit on, protect sensitive data, such as your GPG private key, in a separate user account.

The same applies to reviewers/testers. Rebuild src.rpms in a separate account which does not have access to any sensitive data.

Relocatable Packages

The use of RPM’s facility for generating relocatable packages is strongly discouraged. It is difficult to make work properly, impossible to use from the installer or from yum, and not generally necessary if other packaging guidelines are followed. However, in the unlikely event that you have a good reason to make a package relocatable, you MUST state this intent and reasoning in the request for package review.

File and Directory Ownership

Your package should own all of the files that are installed as part of the %install process.

In most cases, it should not be necessary for multiple packages to contain identical copies of the same file. However, if it is necessary, multiple packages may contain identical copies of the same file, as long as the following requirements are met:

  • The packages sharing ownership of the identical files are built from a single SRPM.

OR

  • The packages sharing ownership of the identical files are not in a dependency chain (e.g. if package A requires package B, they should not both contain identical files, either A or B must own the common files, but not both.)

In addition, identical files are defined as files which are always identical in content, checksum, permissions, and location on the filesystem in each package.

One notable type of file that is often shared identically between subpackages is the license text. There are certain situations where it is required to duplicate the license text across multiple %files section within a package. For more details, please refer to Subpackage Licensing.

Directory ownership is a little more complex than file ownership. Packages must own all directories they put files in, except for:

  • any directories owned by the filesystem, man, or other explicitly created -filesystem packages

  • any directories owned by other packages in your package’s natural dependency chain

In this context, a package’s "natural dependency chain" is defined as the set of packages necessary for that package to function normally. To be specific, you do not need to require a package for the sole fact that it happens to own a directory that your package places files in. If your package already requires that package for other reasons, then your package should not also own that directory.

In all cases we are guarding against unowned directories being present on a system. Please see Packaging:UnownedDirectories for the details.

When co-owning directories, you must ensure that the ownership and permissions on the directory match in all packages that own it.

Here are examples that describe how to handle most cases of directory ownership.

The directory is wholly contained in your package, or involves core functionality of your package

An example:

gnucash places many files under the /usr/share/gnucash directory

Solution: the gnucash package should own the /usr/share/gnucash directory

The directory is also owned by a package implementing required functionality of your package

An example:

pam owns the /etc/pam.d directory
gdm places files into /etc/pam.d
gdm depends on pam to function normally, and would Require: pam (either implicitly or explicitly) separate from the directory ownership.

Solution: the pam package should own the /etc/pam.d directory, and gdm should Require: the pam package.

The directory is owned by a package which is not required for your package to function

Some packages create and own directories with the intention of permitting other packages to store appropriate files, but those other packages do not need that original package to be present to function properly.

An example:

gtk-doc owns the /usr/share/gtk-doc/ directory
evolution puts files into /usr/share/gtk-doc/
evolution does not need gtk-doc in order to function properly.
Nothing in evolution's dependency chain owns /usr/share/gtk-doc/

Solution: the evolution package should own the /usr/share/gtk-doc directory. There is no need to add an explicit Requires on gtk-doc solely for the directory ownership.

Sometimes, it may be preferable for such directories to be owned by an "artificial filesystem" package, such as mozilla-filesystem. These packages are designed to be explicitly required when other packages store files in their directories, thus, in such situations, these packages should explicitly Require the artificial filesystem package and not multiply own those directories. Packagers should consider the number of affected directories and packages when determining whether to create artificial filesystem packages, and use their own best judgement to determine if this is necessary or not.

Rule of Thumb: When determining whether this exception applies, packagers and reviewers should ask this question: Do the files in this common directory enhance or add functionality to another package, where that other package is not necessary to be present for the primary functionality of this package?

The package you depend on to provide a directory may choose to own a different directory in a later version and your package will run unmodified with that later version

An example involving Perl modules:

Assume perl-A-B depends on perl-A and installs files into /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/A/B. The base Perl package guarantees that it will own /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi for as long as it remains compatible with version 5.8.8, but a future upgrade of the perl-A package may install into (and thus own) /usr/lib/perl5/vendor_perl/5.9.0/i386-linux-thread-multi/A. So the perl-A-B package needs to own /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/A as well as /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/A/B in order to maintain proper ownership.

File Permissions

Permissions on files MUST be set properly. Inside of /usr, files should be owned by root:root unless a more specific user or group is needed for security. They MUST be universally readable (and executable if appropriate). Outside of /usr, non-config and non-state files SHOULD be owned by root:root, universally readable (and executable if appropriate) unless circumstances require otherwise.

The default file mode is 0644 or 0755. Directories should be mode 0755. Most well behaved build scripts and rpm will use these defaults. If the directory needs to be group writable, it SHOULD also have the setgid bit set so that files written there are owned by that group. These directories SHOULD have mode 2775.

The %defattr directive in the %files list SHOULD ONLY be used when setting a non-default value, or to reset to the default value after having set a non-default value.

Listas explícitas

Packagers SHOULD NOT simply glob everything under a shared directory.

In particular, the following SHOULD NOT be used in %files:

  • %{_bindir}/*

  • %{_datadir}/*

  • %{_includedir}/*

  • %{_mandir}/*

  • %{_docdir}/*

Esta regra serve como uma verificação contra erros comuns que, de outra forma, seriam difíceis de detectar. Isso limita algumas possibilidades de automação.

The most common mistake this rule prevents is upstream adding new commands in %{_bindir}/*. You should always check such changes for conflicts, and keep the list of such files explicit and auditable.

Users and Groups

Some packages require or benefit from dedicated runtime user and/or group accounts. Guidelines for handling these cases are in a separate document.

Note that system services packaged for Fedora MUST NOT run as the nobody user, but MUST instead allocate their own system user.

Web Applications

Web applications packaged in Fedora should put their content into /usr/share/%{name} and NOT into /var/www/. This is done because:

  • /var is supposed to contain variable data files and logs. /usr/share is much more appropriate for this.

  • Many users already have content in /var/www, and we do not want any Fedora package to step on top of that.

  • /var/www is no longer specified by the Filesystem Hierarchy Standard

Conflicts

Whenever possible, Fedora packages should avoid conflicting with each other. Unfortunately, this is not always possible. For full details on Fedora’s Conflicts policy, see: Conflicts.

Tools such as Alternatives and Environment Modules can also help prevent package conflicts.

Alternatives

The "alternatives" tool provides a means for parallel installation of packages which provide the same functionality by maintaining sets of symlinks. For full details on how to properly use alternatives, see Alternatives.

Environment Modules

When there are multiple variants that each serve the needs of some user and thus must be available simultaneously by users, the alternatives system simply isn’t enough since it is system-wide. In such situations, use of Environment Modules can avoid conflicts. For full details on how to properly use Environment Modules, see Environment Modules.

Patch Guidelines

All patches in Fedora spec files SHOULD have a comment above them about their upstream status. Any time you create a patch, it is best practice to file it in an upstream bug tracker, and include a link to that in the comment above the patch. For example:

# https://bugzilla.gnome.org/show_bug.cgi?id=12345
Patch: gnome-panel-fix-frobnicator.patch

The above is perfectly acceptable; but if you prefer, a brief comment about what the patch does above can be helpful:

# Don't crash with frobnicator applet
# https://bugzilla.gnome.org/show_bug.cgi?id=12345
Patch: gnome-panel-fix-frobnicator.patch

Sending patches upstream and adding this comment will help ensure that Fedora is acting as a good FLOSS citizen (Staying Close to Upstream Projects). It will help others (and even you) down the line in package maintenance by knowing what patches are likely to appear in a new upstream release.

If upstream doesn’t have a bug tracker

You can indicate that you have sent the patch upstream and any known status:

# Sent upstream via email 20080407
Patch: foobar-fix-the-bar.patch
# Upstream has applied this in SVN trunk
Patch: foobar-fix-the-baz.patch

Fedora-specific (or rejected upstream) patches

It may be that some patches truly are Fedora-specific; in that case, say so:

# This patch is temporary until we land the long term System.loadLibrary fix in OpenJDK
Patch: jna-jni-path.patch

Applying Patches

Normally, patches to a package SHOULD be listed in PatchN: tags in the RPM spec file and applied using the %patch or %autosetup macros. The files MUST then be checked into the Fedora Package revision control system (currently the git repos on pkgs.fedoraproject.org and commonly accessed via fedpkg). Storing the files in this way allows people to use standard tools to visualize the changes between revisions of the files and track additions and removals without a layer of indirection (as putting them into lookaside would do).

Applying patches directly from RPM_SOURCE_DIR IS NOT ALLOWED. Please see Packaging:RPM_Source_Dir for the complete rationale.

The maintainer MAY deviate from this rule when the upstream of the package provides an extremely large patch or a tarball of patches against a base release. In this case the tarball of patches MAY be listed as a SourceN: line and the patches would be applied by untarring the archive and then applying the distributed patch(es) using the regular /usr/bin/patch command. Additional patches to the package (for instance, generated by the Fedora maintainer to fix bugs) MUST still be listed in PatchN: lines and be applied by %patch macros after the patches from the tarball were applied. Maintainers and reviewers should be cautious when exercising this exception as shipping an update as a patchset may be a sign that the patchset is not from the actual upstream or that the patches should be reviewed for correctness rather than simply accepted as the upstream code base.

Use of Epochs

RPM supports a field called "Epoch:", which is a numeric field, that, if set, adds another qualifier for RPM to use in doing package comparisons. Specifically, if set, the Epoch of a package trumps all other comparisons (except for a larger Epoch). If Epoch is not set in a package, RPM treats it the same as if it was set to 0.

Example:

Version: 1.2
Release: 3%{?dist}
Epoch: 1

A package with those definitions would be considered greater than a package with a higher version or a higher release. Since Epoch is confusing to humans (and can never be removed from a package once used), it should only be used in Fedora as a last resort to resolve upgrade ordering of a package, and should be avoided wherever possible.

Also, Epoch complicates normal packaging guidelines. If a package uses an Epoch, it must be referred to in any place where %{version}-%{release} is used. For example, if a package being depended upon has an Epoch, this must be listed when adding a versioned dependency:

Requires: foo = %{epoch}:%{version}-%{release}

Epochs from Third Party Repositories

If a package to be imported is or previously was present in a publicly accessible repository, the packager can optionally include an Epoch tag equal to that of the most recent version of the third-party package.

There are two ways of making a symlink, either as a relative link or an absolute link. In Fedora, neither method is required. Packagers should use their best judgement when deciding which method of symlink creation is appropriate.

A relative symlink is a symlink which points to a file or directory relative to the position of the symlink. For example, this command would create a relative symlink:

ln -s ../..%{_bindir}/foo %{buildroot}%{_bindir}/bar

Pros:

  • Relative symlinks will point to the same file inside or outside of a chroot.

Cons:

  • Much more complicated to create than absolute symlinks

  • Relative symlinks may break or behave unexpectedly when a part of a filesystem is mounted to a custom location.

  • Relative symlinks may break when bind mounting or symlinking directories.

  • Relative symlinks may make it more difficult to use rpm system macros.

An absolute symlink is a symlink which points to an absolute file or directory path. For example, this command would create an absolute symlink:

ln -s %{_bindir}/foo %{buildroot}%{_bindir}/bar

Pros:

  • Much easier to create than relative symlinks.

  • Absolute symlinks work properly when bind mounting or symlinking directories.

  • Absolute symlinks work well with rpm system macros.

Cons:

  • Absolute symlinks may break when used with chroots.

In some cases replacing a symlink to a directory requires special handling. Replacing a directory with any type of file always requires special handling.

See Packaging:Directory_Replacement for information about doing this.

Test Suites

If the source code of the package provides a test suite, it should be executed in the %check section, whenever it is practical to do so.

binfmt.d, sysctl.d and tmpfiles.d

If you install a sysctl configuration snippet foobar.conf into %{_sysctldir} (/usr/lib/sysctl.d/) you must invoke %sysctl_apply in your %post section:

%sysctl_apply foobar.conf

If you install a binfmt configuration snippet waldo.conf into %{_binfmtdir} (/usr/lib/binfmt.d/) you must invoke %binfmt_apply in your %post section:

%binfmt_apply waldo.conf

These have the effect of making the appropriate changes immediately upon package installation instead of requiring a reboot or manual activation.

There are specific guidelines for handling tmpfiles.d configurations and directories (in /run and /run/lock): Tmpfiles.d.

Renaming/Replacing or Removing Existing Packages

Package Renaming Process should be followed when renaming an existing package.

In the event that it becomes necessary to rename or replace an existing package, the new package should make the change transparent to end users to the extent applicable.

If a package is being renamed without any functional changes, or is a compatible-enough replacement to an existing package (where "enough" means that it includes only changes of magnitude that are commonly found in version upgrade changes), provide clean upgrade paths and compatibility with:

Provides: oldpackagename = $provEVR
Obsoletes: oldpackagename < $obsEVR

$provEVR refers to an (Epoch-)Version-Release tuple the original unchanged package would have had if it had been version or release bumped. You usually use macros here because the provides EVR should continue to go up as the renamed package advances in version and release. $obsEVR is an (Epoch-)Version-Release tuple arranged so that there is a clean upgrade path but without gratuitously polluting the version space upwards. You usually do not use macros for this as you’re simply trying to advance beyond the last known release under the old name.

If a package supersedes/replaces an existing package without being a sufficiently compatible replacement as defined above, use only the Obsoletes: line from the above example.

Take %{?dist} into account: When deciding what $obsEVR should be, remember that it needs to be higher than the previous Release:, including the %{?dist} suffix. Example: if the package previously had the release tag of -4.fcNN, the release specified in $obsEVR should be at least 5.
If the replaced package uses rpmautospec, either look at the built package (e.g. in koji) to find the actual release tag of the latest build, or use rpmautospec calculate-release to calculate just the release number.

If retired packages need to be removed from end user machines because they cause dependency issues which interfere with upgrades or are otherwise harmful, a packager SHOULD request that Obsoletes: be added to fedora-obsolete-packages. Simply file a bugzilla ticket here. Please include information on which packages need to be obsoleted, the exact versions which need to be obsoleted, and the reasons why they cannot be allowed to remain installed.

If the obsoleted package had an Epoch set, it must be preserved in both the Provides: and Obsoletes:. For example, assume foo being renamed to bar, bar is compatible with foo, and the last foo package release being foo-1.0-3.fcNN with Epoch: 2. The following should be added to bar (and similarly for all subpackages as applicable):

Provides: foo = 2:%{version}-%{release}
# Important: We set the Obsoletes release to 4 to be higher than the last build of foo
Obsoletes: foo < 2:1.0-4

Explicit Provides: need to be aware of whether the package is supplying things that can be used in an arch-independent or arch-specific fashion. For packages that are not noarch, Provides: should be made arch-specific by applying the %{?_isa} macro to the end of the text string in Provides (e.g. Provides: foo%{?_isa} = 2:%{version}-%{release}). Packages that explicitly provide things that can be used in an arch-independent way (for example, those whose dependents don’t need to be of the same arch) need not apply this macro. In some cases, a package will supply multiple elements, some of which may be consumed only by dependents of an identical arch and some which may be consumed by dependents of any arch. In such cases, both arch-specific and arch-independent Provides: are warranted.

Examples of packages that should explicitly provide only arch-specific Provides: include native code libraries or plug-ins and their associated -devel packages. Packages that should explicitly provide only arch-independent Provides: include most stand-alone programs (in addition to all noarch packages). Even though these programs may themselves be arch-specific, clients that run them should not care about their arch in most cases. A package that explicitly provides, for example, both a native code library as well as an interpreted language interface to that library should have both arch-specific (for clients of the native code library) and arch-independent (for clients of the interpreted language interface) Provides:.

If there is no standard naming for a package or other long term naming compatibility requirements involved with the rename, the Provides should be assumed to be deprecated and short lived and removed in the distro release after the next one (i.e., if introduced in FC-X, keep in all subsequent package revisions for distros FC-X and FC-(X+1), drop in FC-(X+2)), and the distro version where it is planned to be dropped documented in a comment in the specfile. Maintainers of affected packages should be notified and encouraged to switch to use the new name. Forward compatibility Provides: in older distro branches can be considered in order to make it possible for package maintainers to keep same simple specfiles between branches but still switch to the newer name.

For packages that are not usually pulled in by using the package name as the dependency such as library only packages (which are pulled in through library soname depenencies), there’s usually no need to add the Provides. Note however that the -devel subpackages of lib packages are pulled in as build dependencies using the package name, so adding the Provides is often appropriate there.

Descontinuando pacotes

A procedure exists for indicating that a package is deprecated and may leave the distribution in the future. See Deprecating Packages.

Networking Support

If an application contains native and stable support for both IPv4 and IPv6, and support for IPv6 does not negatively affect IPv4 then both MUST be enabled in the Fedora package.

Cron Files

For details on how to package cron files, refer to: CronFiles.

Security Updates to Resolve Known CVE Issues

If an update to your package resolves a known security concern (at the time of the update) with a Common Vulnerabilities and Exposures (CVE) number assigned to it, you should mention the CVE number in the RPM changelog entry.

Build Time Network Access

Packages in the Fedora buildsystem are built in a mock chroot with no access to the internet. Packages must not depend or or use any network resources that they don’t themselves create (i.e., for tests). In no cases should source code be downloaded from any external sources, only from the lookaside cache and/or the Fedora git repository.

Bootstrapping

If your package introduces build time circular dependencies, you should use this macro to bootstrap your package:

# When we are bootstrapping, we drop some dependencies, and/or build time tests.
%bcond_with bootstrap

[...]

%if %{without bootstrap}
# dependencies for %%check
BuildRequires: foo
%endif

[...]

%if %{without bootstrap}
%check
make check
%endif
Since Fedora 30, as a nice side-effect, when bootstrapping mode is enabled, the ~bootstrap suffix is appended to the dist tag. This avoids the need to bump release between bootstrap and final build. You can temporarily enable bootstrapping by commit, which changes %bcond_with bootstrap to %bcond_without bootstrap and later reverting the commit to do final build.
Since Fedora 31, you can disable the automatic suffix addition by specifying %global __bootstrap %{nil} in your spec file.

If your package explicitly Provides: some functionality that is missing when bootstrapped, then that Provides: should look like:

%if %{without bootstrap}
Provides: bar(some_functionality)
%endif

Please note that usage of pre-built binaries in bootstrap still needs an exception from the Packaging Committee as stated in [General Exception Policy].

System Cryptographic Policies

Applications which make use the SSL or TLS cryptographic protocols MUST follow Crypto Policies.

Shebang Lines

When packaging script files, where the interpreter to be used is specified in the first line of the script (the shebang line) following #!, the following rules apply:

  • env, /bin/env and /usr/bin/env MUST NOT be used. The interpreter used to run packaged applications cannot depend upon what the user has in their personal $PATH.

  • Files which are not installed as executables SHOULD NOT have shebang lines.

  • Language-specific guidelines may have additional restrictions.

Shebang lines for executable scripts are automatically modified to convert calls to env into direct use of the proper executable in /usr/bin. Various checks are also applied to verify that the shebang lines are valid, and the build process can fail as a result of these. Finally, other language-specific modifications may also be made. It is thus generally unnecessary to manually modify executable scripts to fix env usage as long as this functionality is enabled.

If the automatic checks and modifications break a package, there are two primary options:

  • The packager can elect to fix the shebang lines manually (using patches, scripting via sed, or other similar methods).

  • The packager can remove the executable permission from the script so that the checks and modifications are not made.

If (and only if) the script needs to remain executable and cannot be modified to pass the checks, then the maintainer MAY elect to disable the checks and modifications. It is also possible to disable the functionality for specific paths or for specific shebang lines by setting %__brp_mangle_shebangs_exclude_from and %__brp_mangle_shebangs_exclude, respectively, using the same syntax as the settings described in Packaging:AutoProvidesAndRequiresFiltering. It is also possible to disable the functionality entirely by adding %undefine __brp_mangle_shebangs near the beginning of the specfile.

BRP (BuildRoot Policy) Scripts

BRP scripts are injected at the end of %install (via the %__os_install_post macro) and perform some automatic sanity checks of, or adjustments to, files installed in the build root.

All packages SHOULD always be subject to all the BRP scripts, but sometimes it is necessary for a package to opt-out of certain ones. It is possible to disable any BRP script simply by defining the corresponding variable to %{nil}. For example, to disable the brp-python-bytecompile script:

# Turn off Python bytecode compilation because this is a Jython
# package and we will generate JVM bytecode instead
%global __brp_python_bytecompile %{nil}

Any package that disables a BRP script this way MUST also note the reason in an accompanying comment. For a list of the BRP scripts run by default, invoke:

fgrep '%__brp_' /usr/lib/rpm/redhat/macros

Packaging for EPEL

For the most part, these guidelines and the application-specific guidelines below cover packaging for both Fedora and EPEL. However, there are necessarily some differences. When packaging for EPEL, please also consult the EPEL packaging guidelines for additional information.

Domain Specific Guidelines