Jump to content

# CMake package guidelines (Português)

From ArchWiki
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)

CMake package guidelines (Português)
Add topic