CMake package guidelines (Português)

From ArchWiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Status de tradução: Esse artigo é uma tradução de CMake package guidelines. Data da última tradução: 2020-04-27. Você pode ajudar a sincronizar a tradução, se houver alterações na versão em inglês.
Diretrizes de pacotes do Arch

32-bitCLRCMakeCrossDKMSEclipseElectronFonteFree PascalGNOMEGoHaskellJavaKDEKernelLispMesonMinGWNode.jsNonfreeOCamlPerlPHPPythonRRubyRustVCSWebWine

Este documento abrange padrões e diretrizes sobre como escrever PKGBUILDs para software que usa CMake.

Introdução

Do site do CMake:

O CMake é uma família de ferramentas de código aberto e de plataforma cruzada, projetada para criar, testar e empacotar software. O CMake é usado para controlar o processo de compilação de software usando arquivos simples de configuração independentes de plataforma e compilador e gerar makefiles e espaços de trabalho nativos que podem ser usados no ambiente do compilador de sua escolha.

Uso típico

O uso típico consiste em executar o comando cmake e depois executar o comando de construção. O comando cmake geralmente define alguns parâmetros, verifica as dependências necessárias e cria os arquivos de compilação, deixando o software pronto para ser compilado por outras ferramentas como make e ninja.

Comportamentos indesejados do CMake

Devido às suas próprias características internas para gerar os arquivos de compilação, às vezes o CMake pode se comportar de maneiras indesejadas. Sendo assim, algumas etapas devem ser observadas ao escrever PKGBUILDs para software baseado no CMake.

Carência de suporte à variável de ambiente CPPFLAGS

O CMake não possui suporte à variável de ambiente CPPFLAGS. Essa variável contém sinalizadores (opções) de preprocessador C/C++ que são passados para o compilador no momento da compilação e são definidos no arquivo de configuração do makepkg. Como o CMake não possui suporte a ela, todos os sinalizadores definidos nesta variável não serão passados para o compilador.

Atualmente, CPPFLAGS contém apenas o sinalizador -D_FORTIFY_SOURCE=2. Este é um sinalizador de proteção e é importante por motivos de segurança, pois pode evitar tipos específicos de ataques que podem ocorrer em estouros de buffer exploráveis. Para mais detalhes sobre este sinalizador, consulte feature_test_macros(7).

Os desenvolvedores do CMake estão cientes dessa situação, pois há um antigo relatório de erro[1][2] foi aberto (em 2012) no rastreador de erros do CMake e ainda não foi resolvido. Enquanto isso não for resolvido, os empacotadores devem manipular manualmente a passagem do CPPFLAGS para o CMake a nível de empacotamento.

Corrigindo o problema de CPPFLAGS

Isso pode ser corrigido anexando CPPFLAGS a CFLAGS e/ou CXXFLAGS, pois eles são analisados pelo CMake. Você pode usar export para anexar CPPFLAGS diretamente em CFLAGS/CXXFLAGS antes de executar o CMake. Por exemplo:

PKGBUILD
build() {
    export CFLAGS+=" ${CPPFLAGS}"
    export CXXFLAGS+=" ${CPPFLAGS}"
    cmake <opções>
    <outros comandos>
}

Isso afetará todos os comandos que usam CFLAGS/CXXFLAGS posteriormente. Existem outras possibilidades que preservam o CFLAGS/CXXFLAGS, como usar as opções do CMake -DCMAKE_C_FLAGS="${CFLAGS} ${CPPFLAGS}" e/ou -DCMAKE_CXX_FLAGS="${CXXFLAGS} ${CPPFLAGS}".

Alguns poucos projetos de software codificam -D_FORTIFY_SOURCE=2 em seus arquivos CMake. Se esse for o caso e se você tiver certeza de que -D_FORTIFY_SOURCE=2 está sendo usado, anexando CPPFLAGS a CFLAGS/CXXFLAGS não é necessário, mas geralmente não há problema em fazer isso como regra geral. Isso evitará que o pacote perca o suporte para -D_FORTIFY_SOURCE=2 se o upstream o remover do código-fonte em versões futuras e você não perceber, reduzindo o trabalho de atualização do pacote.

Nota:
  • Não é ideal misturar CPPFLAGS em CFLAGS/CXXFLAGS, mas é melhor do que permitir que o pacote seja compilado sem o importante sinalizador de proteção.
  • Ao usar o export, não esqueça o espaço após o operador do shell +=. Caso contrário, o comando do compilador falhará na execução porque produzirá uma opção inválida.
  • Nem todo software exigirá o acréscimo de CPPFLAGS a CFLAGS e CXXFLAGS. Programas diferentes exigirão apenas CFLAGS, apenas CXXFLAGS ou ambos, e isso dependerá do software upstream em questão. Em caso de dúvida, o uso de ambos geralmente não dói. Você pode usar apenas o necessário, se tiver certeza.

CMake pode substituir automaticamente o sinalizador padrão de otimização do compilador

É muito comum ver pessoas executando o CMake com a opção -DCMAKE_BUILD_TYPE=Release. Alguns projetos upstream, mesmo inadvertidamente, incluem essa opção em suas instruções de compilação, mas isso produz um comportamento indesejado.

Cada tipo de compilação faz com que o CMake anexe automaticamente um conjunto de sinalizadores a CFLAGS e CXXFLAGS. Ao usar o tipo de compilação comum Release, ele anexa automaticamente o sinalizador de otimização -O3[3] do compilador, e isso substitui o sinalizador padrão do Arch Linux que atualmente é -O2 (definido no arquivo de configuração do makepkg). Isso é indesejável, pois se desvia do nível de otimização direcionada do Arch Linux.

Notas sobre -O3

O uso de -O3 não garante que o software tenha um desempenho melhor e, às vezes, pode até atrasar o programa. Também pode quebrar o software em algumas situações. Há uma boa razão pela qual os desenvolvedores do Arch Linux escolhem -O2 como o nível de otimização de destino e devemos continuar com ele. A menos que você saiba exatamente o que está fazendo, ou se o upstream explicitamente disser ou implicar que -O3 é necessário, devemos evitar usá-lo em nossos pacotes.

Corrigindo a substituição automática do sinalizador de otimização

Corrigir isso de uma maneira 100% garantida não é uma questão simples devido à flexibilidade do CMake. Observe que não há solução padrão que possa ser aplicada a todos os casos. Nesta seção serão objeto de discussão as possíveis soluções e alguns pontos que devem ser observados.

O tipo de compilação padrão do CMake é None e não anexa nenhum sinalizador a CFLAGS e CXXFLAGS por padrão, então simplesmente omitir a opção CMAKE_BUILD_TYPE pode funcionar, pois será padronizada como None. Mas observe que a omissão desta opção não garante a correção do problema, pois muitos projetos de software configuram automaticamente o tipo de construção como Release (ou outro tipo) nos arquivos CMake, se CMAKE_BUILD_TYPE não estiver definido na linha de comando.

Como o tipo de compilação padrão None não anexa nenhum sinalizador a CFLAGS e CXXFLAGS por padrão, usando a opção -DCMAKE_BUILD_TYPE=None também pode funcionar. De um modo geral, usar a opção -DCMAKE_BUILD_TYPE=None é melhor do que omitir o uso de CMAKE_BUILD_TYPE. Ele abordará o caso quando o upstream definir automaticamente o tipo de compilação como Release quando CMAKE_BUILD_TYPE for omitido, ele não anexará nenhum sinalizador por padrão e é incomum ver o software configurando sinalizadores indesejados para o tipo de compilação None.

Mas, infelizmente, as coisas não são tão simples como usar apenas -DCMAKE_BUILD_TYPE=None para corrigir isso. Ao usar o tipo de compilação None para corrigir o problema de -O3, pode-se cair em outro problema. É uma prática comum para muitos projetos de software definir alguns sinalizadores de compilador necessários para o tipo de compilação Release nos arquivos CMake (por exemplo, como definir as variáveis do CMake CMAKE_C_FLAGS_RELEASE e CMAKE_CXX_FLAGS_RELEASE). Esse software pode quebrar ou se comportar mal quando compilado sem esses sinalizadores definidos pelo upstream, se você usar o tipo de compilação None. Para determinar se estão faltando alguns sinalizadores, é necessário examinar os arquivos do CMake ou comparar a saída de make VERBOSE=1 para os tipos de compilação None e Release. O que fazer se o tipo de compilação None fizer com que alguns sinalizadores definidos pelo upstream sejam perdidos? Nesse caso, você pode estar no meio de duas situações problemáticas, porque se você usar o tipo de compilação Release, poderá usar o sinalizador indesejado -O3 e se usar o tipo de compilação None, você perderá alguns sinalizadores definidos a montante necessários. Não existe uma maneira padrão de resolver essa situação e ela deve ser analisada caso a caso. Se o upstream definir -O2 para o tipo de compilação Release, você poderá usar -DCMAKE_BUILD_TYPE=Release (veja abaixo). Caso contrário, o patch dos arquivos do CMake pode ser uma solução.

Alguns poucos projetos de software codificam -O2 para o tipo de compilação Release em seus arquivos CMake e, portanto, -DCMAKE_BUILD_TYPE=Release pode ser configurado com segurança nesse caso se você tiver certeza de que -O2 é o nível de otimização que está sendo usado.

Atenção:
  • Alguns softwares podem falhar ao usar o tipo de compilação None. Teste o software ao usar o tipo de compilação None para verificar se ele irá quebrar ou perder funcionalidades.
  • Alguns softwares podem funcionar apenas com o tipo de compilação Release. Você precisará experimentar e testar o software.

Verificando as correções

Você pode verificar se as correções estão sendo usadas corretamente pelo CMake, ativando o modo detalhado da ferramenta de compilação. Por exemplo, ao usar make (que é o padrão do CMake), isso pode ser feito adicionando VERBOSE=1 a ele (como make VERBOSE=1). Isso permitirá que make produza os comandos do compilador que estão sendo executados. Você pode então executar makepkg e examinar a saída para ver se o compilador está usando os sinalizadores -D_FORTIFY_SOURCE=2 e -O2. Se vários sinalizadores de otimização estiverem sendo exibidos em cada linha de comando, o último sinalizador na linha será o usado pelo compilador (significa que -O2 precisa ser o último sinalizador de otimização para ser eficaz).

Diretórios de prefixo e instalação de biblioteca

O prefixo padrão do Arch Linux /usr pode ser especificado pela opção do CMake -DCMAKE_INSTALL_PREFIX=/usr. Isso geralmente é necessário porque muitos softwares padrão instalam arquivos no prefixo /usr/local.

Alguns projetos upstream configuram seus arquivos CMake para instalar bibliotecas no diretório /usr/lib64. Se esse for o caso, você poderá configurar corretamente o diretório de instalação da biblioteca como /usr/lib usando a opção CMake -DCMAKE_INSTALL_LIBDIR=lib.

Dicas e truques

Especificando diretórios

Desde a versão 3.13 do CMake, existe uma opção -B que cria automaticamente o diretório de compilação. Isso evita a criação do diretório de compilação por um comando mkdir (ou install) separado. A opção -S especifica o diretório fonte (onde procurar por um arquivo CMakeLists.txt) e evita a necessidade de usar cd na árvore de fontes antes executando cmake. Combinadas, essas duas opções são uma maneira conveniente de especificar os diretórios de compilação e de fontes. Por exemplo, para criar um programa chamado foo:

PKGBUILD
build() {
    <comando(s) de exportação>
    cmake -B build -S "foo-${pkgver}" [outras_opções_cmake]
    make -C build
}

Reduzindo possíveis saídas indesejadas

A opção -Wno-dev do CMake suprimirá a saída de alguns avisos destinados apenas aos desenvolvedores do projeto upstream que gravam os arquivos CMakeLists.txt. A remoção desses avisos torna a saída do CMake mais suave e reduz a carga de examiná-la. Como regra geral, esses avisos geralmente podem ser ignorados com segurança pelos empacotadores.

Removendo referências a RPATH inseguro de binários

Às vezes, os binários resultantes podem conter referências não seguras em RPATH. Isso pode ser verificado executando Namcap no pacote compilado e consiste em um problema de segurança que deve ser corrigido. Há uma boa chance de corrigir isso usando as opções do CMake CMAKE_SKIP_INSTALL_RPATH=YES ou CMAKE_SKIP_RPATH=YES. Você precisa experimentar os dois e ver o que funcionará no software em questão (não é necessário usar as duas opções).

Obtendo todas as opções disponíveis do CMake

Para obter todas as opções "visíveis" do CMake disponíveis para um projeto de software, execute cmake -LAH na árvore de origem (onde está localizado o arquivo principal CMakeLists.txt).

Se você deseja salvar a saída para referência posterior, você pode redirecioná-la para um arquivo:

$ cmake -LAH >options.txt 2>&1

Modelo

Aqui está um modelo geral para a função build() que serve como ponto de partida para pacotes baseados no CMake. Supondo que o pacote seja nomeado foo, ele é baseado em C e C++ e que não define nenhum sinalizador de compilador necessário para o tipo de compilação Release nos arquivos CMake:

PKGBUILD
build() {
    export CFLAGS+=" ${CPPFLAGS}"
    export CXXFLAGS+=" ${CPPFLAGS}"
    cmake -B build -S "foo-${pkgver}" \
        -DCMAKE_BUILD_TYPE='None' \
        -DCMAKE_INSTALL_PREFIX='/usr' \
        -Wno-dev
    make -C build
}

Não se esqueça de colocar o cmake em makedepends.

Pacotes exemplos

Veja também