Observações Acerca de Construir Software

Aquelas pessoas que tenham construído um sistema LFS possivelmente estejam cientes dos princípios gerais da transferência e do desempacotamento de software. Alguma daquela informação está repetida aqui para aquelas novatas em construir o próprio software delas.

Cada conjunto de instruções de instalação contém um URL a partir do qual você pode transferir o pacote. Os remendos, no entanto, estão armazenados nos servidores do LFS e estão disponíveis via HTTP. Esses estão referenciados conforme necessários nas instruções de instalação.

Enquanto você pode manter os arquivos do fonte em qualquer lugar que queira, nós assumimos que você desempacotou o pacote e mudou para o diretório criado pelo processo de desempacotamento (o diretório de 'construção'). Nós assumimos também que você descomprimiu quaisquer remendos exigidos e que eles estão no diretório imediatamente acima do diretório de 'construção'.

Nós não podemos enfatizar fortemente o suficiente que você deveria iniciar a partir de uma árvore limpa do fonte a cada vez. Isso significa que, se você tiver tido um erro durante a configuração ou a compilação, [então] geralmente é melhor deletar a árvore do fonte e desempacotá-la outra vez antes de tentar novamente. Isso, obviamente, não se aplica se você for um(a) usuário(a) avançado(a) habituado(a) a hackear Makefiles e código C; porém, se em dúvida, [então] inicie a partir de uma árvore limpa.

Construindo Software como um(a) Usuário(a) Não Privilegiado(a) (não root)

A regra de ouro da Administração do Sistema Unix é a de usar os seus super poderes somente quando necessário. Assim, o BLFS recomenda que você construa software como um(a) usuário(a) não privilegiado(a) e somente se torne o(a) usuário(a) root quando instalar o software. Essa filosofia é seguida em todos os pacotes neste livro. A menos que especificado de outra maneira, todas as instruções deveriam ser executadas como um(a) usuário(a) não privilegiado(a). O livro alertará você acerca de instruções que precisarem de privilégios do(a) root.

Desempacotando o Software

Se um arquivo estiver no formato .tar e comprimido, [então] ele é desempacotado executando-se um dos seguintes comandos:

tar -xvf nome_arquivo.tar.gz
tar -xvf nome_arquivo.tgz
tar -xvf nome_arquivo.tar.Z
tar -xvf nome_arquivo.tar.bz2
[Nota]

Nota

Você possivelmente omita o uso do parâmetro v nos comandos mostrados acima e abaixo se você desejar suprimir a listagem verbosa de todos os arquivos no arquivamento conforme eles forem extraídos. Isso pode ajudar a acelerar a extração, bem como torna quaisquer erros produzidos durante a extração mais óbvios para você.

Você também pode usar um método ligeiramente diferente:

bzcat nome_arquivo.tar.bz2 | tar -xv

Finalmente, ocasionalmente, você precisa estar apto(a) a desempacotar remendos que geralmente não estão no formato .tar. A melhor maneira de fazer isso é a de copiar o arquivo do remendo para o ancestral do diretório da 'construção' e, então, executar um dos seguintes comandos, dependendo se o arquivo for um arquivo .gz ou um .bz2:

gunzip -v nome_remendo.gz
bunzip2 -v nome_remendo.bz2

Averiguando a Integridade do Arquivo

Geralmente, para se averiguar se o arquivo transferido está completo, muitos(as) mantenedores(as) de pacote também distribuem somas de verificação md5 dos arquivos. Para averiguar a soma de verificação md5 dos arquivos transferidos, transfira ambos, o arquivo e o arquivo correspondente de soma de verificação md5, para o mesmo diretório (preferencialmente a partir de locais diferentes online) e (assumindo que arquivo.md5sum seja o arquivo de soma de verificação md5 transferido) execute o seguinte comando:

md5sum -c arquivo.md5sum

Se existirem quaisquer erros, [então] eles serão informados. Observe que o livro BLFS inclui somas de verificação md5 para todos os arquivos de fonte também. Para usar as somas de verificação md5 fornecidas pelo BLFS, você pode criar um arquivo.md5sum (coloque os dados da soma de verificação md5 e o nome exato do arquivo transferido na mesma linha de um arquivo, separados por espaço em branco) e executar o comando mostrado acima. Alternativamente, simplesmente execute o comando mostrado abaixo e compare a saída gerada para os dados da soma de verificação md5 mostrada no livro BLFS.

md5sum <nome_do_arquivo_transferido>

MD5 não é seguro criptograficamente, de forma que as somas de verificação md5 são fornecidas somente para se detectar mudanças não maliciosas para o conteúdo do arquivo. Por exemplo, um erro ou truncamento introduzido durante a transferência de rede de comunicação; ou uma atualização furtiva para o pacote oriunda do(a) desenvolvedor(a) (atualizando o conteúdo de um tarball liberado em vez de fazer um lançamento novo adequadamente).

Não existe maneira 100% segura de garantir a genuinidade dos arquivos do fonte. Assumindo que o(a) desenvolvedor(a) esteja gerenciando corretamente o sítio da web dele(a) (a chave privada não vazou e o domínio não esteja sequestrado); e que as âncoras de confiança tenham sido configuradas corretamente usando make-ca-1.12 no sistema BLFS; nós podemos razoavelmente confiar nos URLs de transferência para o sítio oficial da web do(a) desenvolvedor(a) com protocolo https. Observe que o próprio livro BLFS está publicado em um sítio da web com https, de forma que você já deveria ter alguma confiança no protocolo https ou você não confiaria no conteúdo do livro.

Se o pacote for transferido a partir de um local não oficial (por exemplo, um espelho local), [então] as somas de verificação geradas por algoritmos de resumo criptograficamente seguros (por exemplo, SHA256) podem ser usadas para averiguar a genuinidade do pacote. Transfira o arquivo da soma de verificação a partir do sítio da web oficial do(a) desenvolvedor(a) (ou algum lugar que você possa confiar) e compare a soma de verificação do pacote oriunda do local não oficial com ele. Por exemplo, a soma de verificação SHA256 pode ser verificada com o comando:

[Nota]

Nota

Se a soma de verificação e o pacote forem transferidos a partir do mesmo local não confiável, [então] você não ganharia melhoramento de segurança averiguando o pacote com a soma de verificação. O(A) atacante pode falsear a soma de verificação assim como comprometer o próprio pacote.

sha256sum -c arquivo.sha256sum

Se o GnuPG-2.4.0 estiver instalado, [então] você também pode averiguar a genuinidade do pacote com uma assinatura GPG. Importe a chave pública GPG do(a) desenvolvedor(a) com:

gpg --recv-key ID_da_chave

ID_da_chave deveria ser substituído pelo ID da chave oriundo de algum lugar que você possa confiar (por exemplo, copie-o a partir do sítio da web oficial do(a) desenvolvedor(a) usando https). Agora, você consegue averiguar a assinatura com:

gpg --recv-key arquivo.sig arquivo

A vantagem da assinatura GnuPG é, tão logo você importou uma chave pública que possa ser confiada, você pode transferir ambos, o pacote e a assinatura dele, a partir do mesmo local não oficial e averiguá-los com a chave pública. Assim, você não precisaria conectar com o sítio da web oficial do(a) desenvolvedor(a) para ir buscar uma soma de verificação para cada lançamento novo. Você somente precisa atualizar a chave pública se ela estiver expirada ou revogada.

Criando Arquivos de Registro Durante a Instalação

Para pacotes mais largos, é conveniente se criar arquivos de registro em vez de olhar fixamente para a tela esperando pegar um erro ou aviso em particular. Os arquivos de registro também são úteis para depuração e para manter registros. O seguinte comando permite a você criar um registro da instalação. Substitua <comando> pelo comando que você pretende executar.

( <comando> 2>&1 | tee compile.log && exit $PIPESTATUS )

2>&1 redireciona as mensagens de erro para o mesmo local que a saída gerada padrão. O comando tee permite visualizar a saída gerada enquanto se registra os resultados em um arquivo. Os parênteses em volta do comando executam o comando inteiro em um sub shell; e, finalmente, o comando exit $PIPESTATUS garante que o resultado do <comando> seja retornado como o resultado e não o resultado do comando tee.

Usando Múltiplos Processadores

Para muitos sistemas modernos com múltiplos processadores (ou núcleos) o tempo de compilação para um pacote pode ser reduzido realizando-se um "make paralelo", ou configurando-se uma variável de ambiente, ou dizendo-se ao aplicativo make quantos processadores estão disponíveis. Por exemplo, um Core2Duo pode suportar dois processos simultâneos com:

export MAKEFLAGS='-j2'

ou apenas construir com:

make -j2

Se você tiver aplicado o sed opcional quando da construção do ninja no LFS, [então] você pode usar:

export NINJAJOBS=2

quando um pacote usar o ninja; ou apenas:

ninja -j2

porém, para o ninja, o número padrão de trabalhos é <N>+2, onde <N> é o número de processadores disponíveis, de forma que usar os comandos acima é preferencialmente para limitar o número de trabalhos (veja-se abaixo para o porque isso poderia ser necessário).

Geralmente o número de processos não deveria exceder o número de núcleos suportados pela CPU. Para listar os processadores em seu sistema, emita: grep processor /proc/cpuinfo.

Em alguns casos, usar múltiplos processos possivelmente resulte em uma condição de 'corrida' onde o sucesso da construção depende da ordem dos comandos executados pelo aplicativo make. Por exemplo, se um executável precisar do Arquivo A e do Arquivo B, [então] tentar-se vincular o aplicativo antes que um dos componentes dependentes esteja disponível resultará em uma falha. Essa condição geralmente surge, pois o(a) desenvolvedor(a) do aplicativo não designou adequadamente todos os pré requisitos necessários para realizar uma etapa no Makefile.

Se isso ocorrer, [então] a melhor maneira de se proceder é a de se voltar para uma construção de processador único. Adicionar '-j1' a um comando make substituirá a configuração semelhante na variável de ambiente MAKEFLAGS.

[Nota]

Nota

Quando se executar os testes de pacote ou a porção instalar do processo de construção do pacote, nós não recomendamos usar uma opção maior que '-j1', a menos que especificado de outra maneira. Os procedimentos ou verificações da instalação não foram validados usando-se procedimentos paralelos e possivelmente falhem com problemas que são difíceis de se depurar.

[Importante]

Importante

Outro problema possivelmente ocorra com CPUs modernas, as quais tem um monte de núcleos. Cada trabalho iniciado consome memória e, se a soma da memória necessária para cada trabalho exceder da memória disponível, [então] você possivelmente encontre, ou uma interrupção de kernel Out of Memory (OOM), ou troca intensa, que retardará a construção além de limites razoáveis.

Algumas compilações com o g++ possivelmente consumam até 2,5 GB de memória, de forma que, para estar seguro(a), você deveria restringir o número de trabalhos a (Memória Total em GB)/2,5, ao menos para pacotes grandes, tais como o LLVM; o WebKitGtk; o QtWebEngine; ou o Libreoffice.

Procedimentos Automatizados de Construção

Existem ocasiões onde automatizar a construção de um pacote pode vir a calhar. Todo mundo tem razões próprias para querer automatizar a construção e todo mundo faz isso de maneira própria. Criar Makefiles; scripts do Bash; scripts do Perl; ou, simplesmente, uma lista de comandos usados para recortar e colar, são apenas alguns dos métodos que você pode usar para automatizar a construção de pacotes do BLFS. Detalhar como e fornecer exemplos das muitas maneiras que você pode automatizar a construção de pacotes está além do escopo desta seção. Esta seção exporá você ao uso do redirecionamento de arquivo e do comando yes para ajudar a fornecer ideias acerca do como automatizar suas construções.

Redirecionamento de Arquivo para Automatizar a Entrada Gerada

Você achará ocasiões ao longo da sua jornada BLFS quando você se deparará com um pacote que tenha um comando solicitando informação. Essa informação poderia ser detalhes de configuração; um caminho de diretório; ou uma resposta a um acordo de licença. Isso pode apresentar um desafio para automatizar a construção desse pacote. Ocasionalmente, você será consultado(a) para diferentes informações em uma série de perguntas. Um método para automatizar esse tipo de cenário exige colocar as respostas desejadas em um arquivo e usar redirecionamento, de forma que o aplicativo use os dados no arquivo como as respostas para as perguntas.

Construir o pacote CUPS é um bom exemplo de como redirecionar um arquivo como entrada gerada para solicitações pode te ajudar a automatizar a construção. Se você executar a suíte de teste, [então] você é solicitado(a) a responder a uma série de perguntas relacionadas ao tipo do teste a executar e se você tem quaisquer aplicativos auxiliares que o teste possa usar. Você pode criar um arquivo com as suas respostas, uma resposta por linha, e usar um comando similar ao mostrado abaixo para automatizar a execução da suíte de teste:

make check < ../cups-1.1.23-testsuite_parms

Isso, efetivamente, faz com que a suíte de teste use as respostas no arquivo como a entrada gerada para as perguntas. Ocasionalmente você possivelmente termine fazendo um bocado de tentativa e erro para determinar o formato exato do seu arquivo de entrada gerada para algumas coisas, porém, tão logo determinado e documentado, você consegue usar isso para automatizar a construção do pacote.

Usando o yes para Automatizar a Entrada Gerada

Ocasionalmente você somente precisará fornecer uma resposta ou fornecer a mesma resposta para muitas solicitações. Para tais instâncias, o comando yes funciona realmente bem. O comando yes pode ser usado para fornecer uma resposta (a mesma) para uma ou mais instâncias de perguntas. Ele pode ser usado para simular o pressionamento apenas da tecla Enter; informar a tecla Y; ou informar uma sequência de caracteres de texto. Talvez a maneira mais fácil de mostrar o uso dele é em um exemplo.

Primeiro, crie um script curto do Bash informando os seguintes comandos:

cat > blfs-yes-test1 << "EOF"
#!/bin/bash

echo -n -e "\n\nPor favor, digite algo (ou nada) e pressione Enter ---> "

read A_STRING

if test "$A_STRING" = ""; then A_STRING="Apenas a tecla Enter foi pressionada"
else A_STRING="Você informou '$A_STRING'"
fi

echo -e "\n\n$A_STRING\n\n"
EOF
chmod 755 blfs-yes-test1

Agora execute o script emitindo ./blfs-yes-test1 a partir da linha de comando. Ele aguardará por uma resposta, que pode ser algo (ou nada) seguida pela tecla Enter. Depois de informar alguma coisa, o resultado será ecoado para a tela. Agora use o comando yes para automatizar a entrada de uma resposta:

yes | ./blfs-yes-test1

Perceba que canalizar o próprio yes para o script resulta em y sendo passada para o script. Agora tente com uma sequência de caracteres de texto:

yes 'Este é algum texto' | ./blfs-yes-test1

A sequência exata de caracteres foi usada como a resposta para o script. Finalmente, tente usando uma sequência de caracteres vazia (nula):

yes '' | ./blfs-yes-test1

Perceba que isso resulta na passagem apenas do pressionamento da tecla Enter para o script. Isso é útil para ocasiões quando a resposta padrão para a solicitação for suficiente. Essa sintaxe é usada nas instruções do Net-tools para aceitar todos os padrões para as muitas solicitações durante a etapa de configuração. Você possivelmente agora remova o script de teste, se desejado.

Redirecionamento de Arquivo para Automatizar a Saída Gerada

Para a finalidade de automatizar a construção de alguns pacotes, especialmente aqueles que exigem que você leia um acordo de licença em uma página por vez, exige-se usar um método que evite ter que pressionar uma tecla para exibir cada página. Redirecionar a saída gerada para um arquivo pode ser usado nessas instâncias para auxiliar com a automação. A seção anterior nesta página tocou na criação de arquivos de registro da saída gerada da construção. O método de redirecionamento mostrado lá usou o comando tee para redirecionar a saída gerada para um arquivo enquanto também exibia a saída gerada na tela. Aqui, a saída gerada somente será enviada para um arquivo.

Novamente, a maneira mais fácil para demonstrar a técnica é de mostrar um exemplo. Primeiro, emita o comando:

ls -l /usr/bin | more

Certamente, você será exigido(a) a visualizar a saída gerada uma página por vez, pois o filtro more foi usado. Agora tente o mesmo comando, porém, dessa vez, redirecione a saída gerada para um arquivo. O arquivo especial /dev/null pode ser usado em vez do nome de arquivo mostrado, porém você não terá arquivo de registro para examinar:

ls -l /usr/bin | more > redirect_test.log 2>&1

Perceba que, dessa vez, o comando imediatamente retornou ao prompt do shell sem ter que paginar ao longo da saída gerada. Você agora possivelmente remova o arquivo de registro.

O último exemplo usará o comando yes em combinação com o redirecionamento da saída gerada para desviar-se de ter que paginar ao longo da saída gerada e, então, fornecerá um y para uma solicitação. Essa técnica poderia ser usada em instâncias quando, de outra maneira, você teria que paginar ao longo da saída gerada de um arquivo (como um acordo de licença) e, então, responder à pergunta de você aceita o acima?. Para esse exemplo, outro script curto do Bash é exigido:

cat > blfs-yes-test2 << "EOF"
#!/bin/bash

ls -l /usr/bin | more

echo -n -e "\n\nVocê curtiu ler isso? (y,n) "

read A_STRING

if test "$A_STRING" = "y"; then A_STRING="Você informou a tecla 'y'"
else A_STRING="Você NÃO informou a tecla 'y'"
fi

echo -e "\n\n$A_STRING\n\n"
EOF
chmod 755 blfs-yes-test2

Esse script pode ser usado para simular um aplicativo que exige que você leia um acordo de licença, então responda apropriadamente que aceita o acordo antes do aplicativo instalar qualquer coisa. Primeiro, execute o script sem quaisquer técnicas de automação emitindo ./blfs-yes-test2.

Agora emita o seguinte comando que usa duas técnicas de automação, tornando-o adequado para uso em um script automatizado de construção:

yes | ./blfs-yes-test2 > blfs-yes-test2.log 2>&1

Se desejado, emita tail blfs-yes-test2.log para ver o final da saída gerada paginada e a confirmação de que y foi passada ao longo para o script. Tão logo satisfeito que ele funciona como deveria, você possivelmente remova o script e o arquivo de registro.

Finalmente, tenha em mente que existem muitas maneiras de automatizar e (ou) roteirizar os comandos de construção. Não existe maneira única correta para fazê-lo. Sua imaginação é o único limite.

Dependências

Para cada pacote descrito, o BLFS lista as dependências conhecidas. Essas são listadas sob vários títulos, cujo significado é como segue:

  • Exigida significa que o pacote alvo não consegue ser corretamente construído sem a dependência tendo primeiro sido instalada.

  • Recomendada significa que o BLFS enfaticamente sugere que esse pacote seja instalado primeiro para uma construção limpa e livre de problemas; que não teria problemas seja durante o processo de construção, seja em tempo de execução. As instruções no livro assumem que esses pacotes estejam instalados. Algumas mudanças ou gambiarras possivelmente sejam exigidas se esses pacotes não estiverem instalados.

  • Opcional significa que esse pacote poderia estar instalado para funcionalidade adicionada. Frequentemente o BLFS descreverá a dependência para explicar a funcionalidade adicionada que resultará.

Usando os Fontes Mais Atuais de Pacote

Ocasionalmente você possivelmente se encontre em uma situação no livro onde um pacote não construirá ou não funcionará adequadamente. Apesar dos(as) Editores(as) tentarem garantir que cada pacote no livro construa e funcione adequadamente, ocasionalmente um pacote tenha sido negligenciado ou não foi testado com esta versão particular do BLFS.

Se você descobrir que um pacote não construirá ou não funcionará adequadamente, [então] você deveria ver se existe uma versão mais recente do pacote. Tipicamente isso significa você ir ao sítio da web do(a) mantenedor(a) e transferir o tarball mais recente e tentar construir o pacote. Se você não conseguir determinar o sítio da web do(a) mantenedor(a) olhando para os URLs de transferência, [então] use o Google e consulte o nome do pacote. Por exemplo, na barra de pesquisa do Google, digite: 'nome_do_pacote download' (omita as aspas) ou algo semelhante. Ocasionalmente, digitar: 'nome_do_pacote home page' resultará em você encontrar o sítio da web do(a) mantenedor(a).

Despojando Mais Uma Vez

No LFS, a remoção de símbolos de depuração e entradas desnecessárias na tabela de símbolos foi discutida algumas vezes. Ao construir pacotes BLFS, geralmente não existem instruções especiais que discutam a remoção novamente. A remoção pode ser feita durante a instalação de um pacote ou posteriormente.

Despojando enquanto se Instala um Pacote

Existem várias maneiras de se despojar executáveis instalados por um pacote. Elas dependem do sistema de construção usado (veja-se abaixo a seção acerca de sistemas de construção), de modo que somente algumas generalidades podem ser listadas aqui:

[Nota]

Nota

Os métodos a seguir que usam o recurso de um sistema de construção ("autotools", "meson" ou "cmake") não despojarão bibliotecas estáticas, se alguma estiver instalada. Felizmente não existem muitas bibliotecas estáticas no BLFS, e uma biblioteca estática sempre pode ser despojada com segurança executando strip --strip-unneeded nela manualmente.

  • Os pacotes que usam "Autotools" geralmente tem um alvo install-strip nos arquivos Makefile gerados deles. Portanto, instalar executáveis despojados é apenas uma questão de usar make install-strip em vez de make install.

  • Os pacotes que usam o sistema de construção "Meson" conseguem aceitar -Dstrip=true ao executar meson. Se esqueceu de adicionar essa opção executando o meson, [então] você também consegue executar meson install --strip em vez de ninja install.

  • cmake gera alvos install/strip para ambos os geradores Unix Makefiles e Ninja (o padrão é Unix Makefiles no Linux). Portanto, basta executar make install/strip ou ninja install/strip em vez das contrapartes install.

  • A remoção (ou não geração) de símbolos de depuração também consegue ser obtida removendo-se as opções -g<alguma_coisa> em chamadas "C/C++". Como fazer isso é muito específico para cada pacote. E não remove entradas desnecessárias da tabela de símbolos. Portanto, não será explicado em detalhes aqui. Veja-se também abaixo os parágrafos acerca de otimização.

Despojando Executáveis Instalados

O utilitário strip muda arquivos no lugar, o que possivelmente quebre alguma coisa que os usem se estiverem carregados na memória. Observe que se um arquivo estiver em uso, mas recém removido, do disco (ou seja, não sobrescrito nem modificado), isso não será um problema, pois o núcleo consegue usar arquivos deletados. Veja-se /proc/*/maps e é provável que você veja algumas entradas (deleted). O mv apenas remove o arquivo de destino a partir do diretório, mas não toca no conteúdo dele, de modo que satisfaça a condição para o núcleo usar o arquivo antigo (deletado). O script abaixo é apenas um exemplo. Ele deveria ser executado como o(a) usuário(a) root:

cat > /usr/sbin/strip-all.sh << "EOF"
#!/usr/bin/bash

if [ $EUID -ne 0 ]; then
  echo "Precisa ser root"
  exit 1
fi

{ find /usr/lib -type f -name '*.so*' ! -name '*dbg'
  find /usr/lib -type f -name '*.a'
  find /usr/{bin,sbin,libexec} -type f
} |  while read file; do
       if ! readelf -h $file >/dev/null 2>&1; then continue; fi
       if file $file | grep --quiet --invert-match 'not stripped'; then continue; fi

       cp --preserve $file    ${file}.tmp
       strip --strip-unneeded ${file}.tmp
       mv ${file}.tmp $file
     done
EOF
chmod 744 /usr/sbin/strip-all.sh

Se você instalar aplicativos em outros diretórios, como /opt ou /usr/local, você possivelmente queira despojar os arquivos lá também . Basta adicionar outros diretórios a escanear na lista composta de comandos find entre chaves.

Para mais informações acerca de despojamento, veja-se https://www.technovelty.org/linux/stripping-shared-libraries.html.

Trabalhando com diferentes sistemas de construção

Existem, agora, três sistemas de construção em uso comum para converter código fonte C ou C++ em aplicativos ou bibliotecas compilados(as) e os detalhes deles (particularmente, descobrir acerca de opções disponíveis e os valores padrão delas) diferem. Possivelmente seja mais fácil entender os problemas causados por algumas escolhas (tipicamente, execução lenta; ou uso inesperado de, ou omissão de, otimizações) iniciando-se com as variáveis de ambiente CFLAGS e CXXFLAGS. Também existem alguns aplicativos que usam rust.

A maioria dos(as) construtores(as) do LFS e do BLFS provavelmente está ciente dos básicos de CFLAGS e CXXFLAGS para alterar como um aplicativo é compilado. Tipicamente, alguma forma de otimização é usada pelos(as) desenvolvedores(as) de aplicativos (-O2 ou -O3), ocasionalmente com a criação de símbolos de depuração (-g), como padrões.

Se existirem sinalizadores contraditórios (por exemplo, múltiplos valores -O), [então] o último valor será usado. Ocasionalmente, isso significa que os sinalizadores especificados em variáveis de ambiente serão escolhidos antes dos valores codificados rigidamente no Makefile, e, portanto, ignorados. Por exemplo, onde um(a) usuário(a) especificar '-O2' e isso for seguido por '-O3', a construção usará '-O3'.

Existem várias outras coisas que podem ser passadas em CFLAGS ou em CXXFLAGS, tais como forçar-se a compilação para uma microarquitetura específica (por exemplo, -march=amdfam10; -march=native) ou especificar-se um padrão específico para C ou C++ (-std=c++17, por exemplo). Porém, uma coisa que agora veio à tona é que os(as) programadores(as) poderiam incluir asserções de depuração no código deles(as), esperando que sejam desabilitados em lançamentos usando-se -DNDEBUG. Especificamente, se o Mesa-22.3.5 for construído com essas asserções habilitadas, [então] algumas atividades, tais como o carregamento de níveis dos jogos, podem tomar tempos extremamente longos, mesmo em placas de vídeo de alta qualidade.

Autotools com Make

Essa combinação frequentemente é descrita como 'CMMI' (configure; make; make install) e é usada aqui também para cobrir os poucos pacotes que tem um script de configuração que não é gerado por autotools.

Ocasionalmente, executar-se ./configure --help produzirá opções úteis acerca de chaves que poderiam ser usadas. Em outras ocasiões, depois de olhar para a saída gerada a partir do configure, você possivelmente precise olhar para os detalhes do script para descobrir pelo que ele estava procurando atualmente.

Muitos scripts de configuração escolherão quaisquer CFLAGS ou CXXFLAGS a partir do ambiente, porém os pacotes CMMI variam acerca do como esses serão misturados com quaisquer sinalizadores que, de outra maneira, seriam usados (variadamente: ignorados; usados para substituir a sugestão do(a) programador(a); usados antes da sugestão do(a) programador(a); ou usados depois da sugestão do(a) programador(a)).

Na maioria dos pacotes CMMI, executar-se 'make' listará cada comando e o executará, intercalado com quaisquer avisos. Porém, alguns pacotes tentam ser 'silenciosos' e mostram somente qual arquivo eles estão compilando ou vinculando em vez de mostrar a linha de comando. Se você precisar inspecionar o comando, seja por causa de um erro, seja apenas para ver quais opções e sinalizadores estão sendo usados, [então] adicionar 'V=1' à invocação do make possivelmente ajude.

CMake

O CMake funciona de uma maneira muito diferente e ele tem duas estruturas de retaguarda que conseguem ser usadas no BLFS: 'make' e 'ninja'. A estrutura de retaguarda padrão é o make, porém o ninja pode ser mais rápido sobre pacotes largos com múltiplos processadores. Para usar o ninja, especifique '-G Ninja' no comando cmake. Entretanto, existem alguns pacotes que criam erros fatais nos arquivos ninja deles, porém constroem com sucesso usando o padrão dos Makefiles do Unix.

A parte mais difícil do usar-se o CMake é saber quais opções você poderia desejar especificar. A única maneira de se obter uma lista do que o pacote conhece é a de executar cmake -LAH e olhar para a saída gerada para esta configuração padrão.

Talvez a coisa mais importante acerca do CMake é que ele tem uma variedade de valores CMAKE_BUILD_TYPE e esses afetam os sinalizadores. O padrão é o de que isso não é configurado e nenhum sinalizador é gerado. Quaisquer CFLAGS ou CXXFLAGS no ambiente serão usados. Se o(a) programador(a) tiver codificado quaisquer asserções de depuração, [então] essas serão habilitadas, a menos que - DNDEBUG seja usado. Os seguintes valores CMAKE_BUILD_TYPE gerarão os sinalizadores mostrados e esses virão depois de quaisquer sinalizadores no ambiente e, portanto, terão precedência.

Valor Sinalizadores
Debug -g
Release -O3 -DNDEBUG
RelWithDebInfo -O2 -g -DNDEBUG
MinSizeRel -Os -DNDEBUG

O "CMake" tenta produzir construções silenciosas. Para ver os detalhes dos comandos que estão sendo executados, use make VERBOSE=1 ou ninja -v.

Por padrão, o "CMake" trata a instalação de arquivos diferentemente dos outros sistemas de construção: se um arquivo já existir e não for mais recente que um arquivo que o sobrescreveria, então o arquivo não será instalado. Isso possivelmente seja um problema se um(a) usuário(a) quiser registrar qual arquivo pertence a um pacote, seja usando LD_PRELOAD, ou listando arquivos mais recentes que um carimbo de tempo. O padrão pode ser mudado definindo-se a variável CMAKE_INSTALL_ALWAYS como um ("1") no ambiente, por exemplo, via export.

Meson

O Meson tem algumas semelhanças com o CMake, porém muitas diferenças. Para obter os detalhes das definições que você possivelmente queira mudar, você pode olhar para o meson_options.txt que normalmente está no diretório de nível de topo.

Se você já configurou o pacote executando o meson e, agora, deseja mudar uma ou mais configurações, [então] você ou pode remover o diretório de construção, recriá-lo e usar as opções alteradas; ou, dentro do diretório de construção, executar meson configure, por exemplo, para configurar uma opção:

meson configure -D<alguma_opção>=true

Se você fizer isso, [então] o arquivo meson-private/cmd_line.txt mostrará os últimos comandos que foram usados.

O Meson fornece os seguintes valores de tipo de construção e os sinalizadores que eles habilitam vem depois de quaisquer sinalizadores fornecidos no ambiente e, portanto, tem precedência.

  • plano : nenhum sinalizador adicionado. Isso é para os(as) distribuidores(as) fornecerem os próprios CFLAGS, CXXFLAGS e LDFLAGS deles(as). Não existe razão óbvia para usar isso no BLFS.

  • depuração : '-g' - isso é o padrão, se nada for especificado, seja no meson.build, seja na linha de comando. Entretanto, resulta em binários largos e lentos, de forma que nós deveríamos substitui-lo no BLFS.

  • depuração otimizada : '-O2 -g' : isso é o padrão, especificado no meson.build, de alguns pacotes.

  • lançamento : '-O3 -DNDEBUG' (porém, ocasionalmente, um pacote forçará -O2 aqui)

Apesar do tipo de construção 'lançamento' estar descrito como habilitante do -DNDEBUG e todas as construções CMake Release passarem isso, tem, até agora, somente sido observado (em construções verbosas) para o Mesa-22.3.5. Isso sugere que somente poderia ser usado quando existirem asserções de depuração presentes.

O sinalizador -DNDEBUG também pode ser fornecido passando-se -Db_ndebug=true.

Para ver os detalhes dos comandos que estão sendo executados em um pacote usando o meson, use 'ninja -v'.

Rustc e Cargo

A maioria dos aplicativos rustc lançados é fornecida como engradado (tarballs de fonte), que consultarão um servidor para verificar as versões atuais de dependências e, então, as transferirão conforme necessário. Esses pacotes são construídos usando-se cargo --release. Na teoria, você consegue manipular o RUSTFLAGS para mudar o nível de otimização (padrão é 3, semelhante a -03; por exemplo, -Copt-level=3) ou para forçá-lo a construir para a máquina na qual está sendo compilado, usando -Ctarget-cpu=native; porém, na prática, isso parece não fazer uma diferença significante.

Se você encontrar um aplicativo rustc interessante que seja fornecido apenas como fonte desempacotado, [então] você deveria, pelo menos, especificar RUSTFLAGS=-Copt-level=2; do contrário, fará uma compilação não otimizada, com informação de depuração e executará muito mais lento.

Os(As) desenvolvedores(as) do rust parecem presumir que todos compilarão em uma máquina dedicada a produzir construções, de forma que, por padrão, todas as CPUs serão usadas. Isso, frequentemente, pode ser contornado, seja exportando-se CARGO_BUILD_JOBS=<N>, seja passando-se --jobs <N> para o cargo. Para compilar o próprio rustc, especificar-se --jobs <N> em invocações de x.py (junto com a variável de ambiente CARGO_BUILD_JOBS, que se parece com uma abordagem "cinto e suspensórios", porém parece ser necessária) na maioria das vezes funciona. A exceção é a de executar-se os testes quando construir-se o rustc; alguns deles, ainda assim, usarão todas as CPUs online, pelo menos desde o rustc-1.42.0.

Otimizando a construção

Muitas pessoas preferirão otimizar compilações como acharem melhor, fornecendo CFLAGS ou CXXFLAGS. Para uma introdução às opções disponíveis com o gcc e com o g++, veja-se https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html; e https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html; e info gcc.

Alguns pacotes padronizam para '-O2 -g'; outros para '-O3 -g'; e, se CFLAGS ou CXXFLAGS forem fornecidos, [então] eles poderiam ser adicionados aos padrões do pacote; substituir os padrões do pacote; ou até serem ignorados. Existem detalhes acerca de alguns pacotes de área de trabalho que eram na maioria das vezes atuais em abril de 2019 em https://www.linuxfromscratch.org/~ken/tuning/ - em particular, README.txt, tuning-1-packages-and-notes.txt e tuning-notes-2B.txt. A coisa particular a se lembrar é a de que, se você quiser tentar algum dos mais interessantes sinalizadores, [então] você possivelmente precise forçar construções verbosas para confirmar o que está sendo usado.

Claramente, se você estiver otimizando seu próprio aplicativo, [então] você pode gastar tempo para perfilá-lo e, talvez, re-codificar algo dele, se ele estiver lento demais. Porém, para construir um sistema inteiro, essa abordagem é impraticável. No geral, -O3 geralmente produz aplicativos mais rápidos que -O2. Especificar-se -march=native também é benéfico, porém significa que você não pode mover os binários para uma máquina incompatível - isso também pode se aplicar a máquinas mais novas, não apenas às máquinas mais antigas. Por exemplo, os aplicativos compilados para 'amdfam10' executam em Phenoms antigos; Kaveris; e Ryzens; porém, os aplicativos compilados para um Kaveri não executarão em um Ryzen, pois certos códigos de operação não estão presentes. Similarmente, se você construir para um Haswell, [então] nem tudo executará em um SandyBridge.

Existem também várias outras opções que algumas pessoas alegam que são benéficas. Na pior das hipóteses, você consegue recompilar e testar e, então, descobrir que, em seu uso, as opções não fornecem um benefício.

Se construir módulos do Perl ou do Python; ou pacotes do Qt que usam o qmake, [então], no geral, os CFLAGS e CXXFLAGS usados são aqueles que foram usados por aqueles pacotes 'ancestrais'.

Opções para fortalecer a construção

Mesmo em sistemas de área de trabalho, existe ainda um monte de vulnerabilidades exploráveis. Para muitas dessas, o ataque vem via javascript em um navegador. Frequentemente, uma série de vulnerabilidades é usada para ganhar acesso a dados (ou, às vezes, para pwn, isto é, dominar, a máquina e instalar rootkits). A maioria das distribuições comerciais aplicará várias medidas de fortalecimento.

No passado, existia o "LFS Reforçado", onde o "GCC" (uma versão muito mais antiga) era forçado a usar reforçamento (com opções para desativar parte dele por pacote). Os livros atuais LFS e BLFS estão levando adiante uma parte do espírito dele, habilitando "PIE" (-fPIE -pie) e "SSP" (-fstack-protector-strong) como padrões para o "GCC" e o "clang". O que está sendo abordado aqui é diferente - primeiro, você precisa ter certeza de que o pacote está realmente usando os teus sinalizadores adicionados e não os substituindo.

Para opções de reforço que são razoavelmente baratas, existe alguma discussão no link "ajuste" acima (ocasionalmente, uma ou mais dessas opções podem ser inadequadas para um pacote). Essas opções são -D_FORTIFY_SOURCE=2 e (para "C++") -D_GLIBCXX_ASSERTIONS. Nas máquinas modernas, isso deveria ter somente um pequeno impacto na rapidez com que as coisas funcionam e, muitas vezes, não serão perceptíveis.

As principais distribuições usam muito mais, como "RELRO" ("Relocation Read Only") e talvez -fstack-clash-protection. Você também possivelmente encontre a chamada retpoline do espaço de usuário(a) (-mindirect-branch=thunk etc.), que é o equivalente às mitigações de espectro aplicadas ao núcleo Linux no final de 2018. As mitigações do núcleo causaram muitas reclamações acerca de perda de desempenho; se você tiver um servidor de produção, você pode desejar considerar testá-las, juntamente com outras opções disponíveis, para ver se o desempenho ainda é suficiente.

Embora o gcc tenha muitas opções de fortalecimento, os pontos fortes do clang/LLVM estão em outro lugar. Algumas opções que o gcc fornece são ditas serem menos efetivas no clang/LLVM.