CMake package guidelines (Português) - ArchWiki

# CMake package guidelines (Português)

From ArchWiki
Jump to navigation Jump to search
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.

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)

Category:

- Arch package guidelines (Português)