CMake package guidelines (Português)

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-bit
–
CLR
–
CMake
–
Cross
–
DKMS
–
Eclipse
–
Electron
–
Fonte
–
Free Pascal
–
GNOME
–
Go
–
Haskell
–
Java
–
KDE
–
Kernel
–
Lisp
–
Meson
–
MinGW
–
Node.js
–
Nonfree
–
OCaml
–
Perl
–
PHP
–
Python
–
R
–
Ruby
–
Rust
–
Shell
–
VCS
–
Web
–
Wine
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
i2pd
libmysofa
Veja também
Documentação do CMake
Documentação de referência para a versão mais recente
Artigo do Wikipédia
cmake(1)