8.27. GCC-13.2.0

O pacote GCC contém a GNU Compiler Collection, a qual inclui os compiladores C e C++.

Tempo aproximado de construção: 42 UPC (com os testes)
Espaço em disco exigido: 5,5 GB

8.27.1. Instalação do GCC

Se construir em x86_64, [então] mude o nome padrão de diretório para bibliotecas de 64 bits para lib:

case $(uname -m) in
  x86_64)
    sed -e '/m64=/s/lib64/lib/' \
        -i.orig gcc/config/i386/t-linux64
  ;;
esac

A documentação do GCC recomenda construir o GCC em um diretório de construção dedicado:

mkdir -v build
cd      build

Prepare o GCC para compilação:

../configure --prefix=/usr            \
             LD=ld                    \
             --enable-languages=c,c++ \
             --enable-default-pie     \
             --enable-default-ssp     \
             --disable-multilib       \
             --disable-bootstrap      \
             --disable-fixincludes    \
             --with-system-zlib

O GCC suporta sete linguagens computacionais, porém os pré-requisitos para a maior parte delas ainda não foram instalados. Veja-se a página do GCC do Livro BLFS para instruções a respeito do como construir todas as linguagens suportadas do GCC.

O significado dos novos parâmetros do configure:

LD=ld

Esse parâmetro induz o script configure a usar o aplicativo ld instalado pelo pacote Binutils, construído anteriormente neste capítulo, em vez da versão construída cruzadamente, a qual de outra maneira seria usada.

--disable-fixincludes

Por padrão, durante a instalação do GCC alguns cabeçalhos de sistema seriam corrigidos para serem usados com o GCC. Isso não é necessário para um sistema moderno Linux e potencialmente danoso se um pacote for reinstalado depois de instalar o GCC. Essa chave evita que o GCC corrija os cabeçalhos.

--with-system-zlib

Essa chave diz ao GCC para vincular à cópia instalada do sistema da biblioteca Zlib, em vez da própria cópia interna dele.

[Nota]

Nota

PIE (position-independent executables) são aplicativos binários que conseguem ser carregados em qualquer lugar em memória. Sem PIE, o recurso de segurança chamado de ASLR (Address Space Layout Randomization) consegue ser aplicado para as bibliotecas compartilhadas, porém não para os próprios executáveis. Habilitar PIE permite ASLR para os executáveis em adição às bibliotecas compartilhadas e mitiga alguns ataques baseados em endereços fixos de código ou dados sensível(is) nos executáveis.

SSP (Stack Smashing Protection) é uma técnica para garantir que a pilha de parâmetros não está corrompida. A corrupção da pilha consegue, por exemplo, alterar o endereço de retorno de uma sub-rotina, dessa forma transferindo controle para algum código perigoso (existente no aplicativo ou nas bibliotecas compartilhadas; ou injetado pelo(a) atacante de alguma maneira).

Compile o pacote:

make
[Importante]

Importante

Nesta seção, a suíte de teste para o GCC é considerada importante, porém ela toma um tempo longo. Construtoras(es) de primeira vez são encorajadas(os) a executar a suíte de teste. O tempo para executar os testes pode ser reduzido significantemente adicionando-se -jx ao comando make -k check abaixo, onde x é o número de núcleos da CPU em seu sistema.

Um conjunto de testes na suíte de teste do GCC é conhecido por esgotar a pilha padrão, então aumente o tamanho de pilha para executar os testes:

ulimit -s 32768

Teste os resultados como um(a) usuário(a) não privilegiado(a), porém não pare em erros:

chown -Rv tester .
su tester -c "PATH=$PATH make -k check"

Para extrair um sumário dos resultados da suíte de teste, execute:

../contrib/test_summary

Para filtrar somente os sumários, entube a saída gerada por grep -A7 Summ.

Os resultados podem ser comparados com aqueles localizados em https://www.linuxfromscratch.org/lfs/build-logs/12.0/ e https://gcc.gnu.org/ml/gcc-testresults/.

Dois testes chamados copy.cc e pr56837.c são conhecidos por falharem. Adicionalmente, vários testes no diretório vect são conhecidos por falharem se o hardware não suportar "AVX".

Com "Glibc-2.38", os testes do analisador chamados data-model-4.c e conftest-1.c são conhecidos por falharem. Nos testes "asan", vários testes em asan_test.C são conhecidos por falharem. O teste chamado interception-malloc-test-1.C é conhecido por falhar.

Umas poucas falhas inesperadas não podem ser evitadas sempre. Os(As) desenvolvedores(as) do GCC geralmente estão cientes desses problemas, mas ainda não os resolveram. A menos que os resultados do teste sejam amplamente diferentes daqueles na URL acima, é seguro continuar.

Instale o pacote:

make install

O diretório de construção do GCC é de propriedade de tester agora e a propriedade do diretório do cabeçalho instalado (e o conteúdo dele) está incorreto. Mude a propriedade para o(a) usuário(a) e grupo root:

chown -v -R root:root \
    /usr/lib/gcc/$(gcc -dumpmachine)/13.2.0/include{,-fixed}

Crie um link simbólico exigido pelo FHS por razões "históricas".

ln -svr /usr/bin/cpp /usr/lib

Muitos pacotes usam o nome cc para chamar o compilador C. Já criamos cc como um link simbólico em gcc-passagem2; crie a página de manual dele como um link simbólico também:

ln -sv gcc.1 /usr/share/man/man1/cc.1

Adicione um link simbólico de compatibilidade para habilitar a construção de aplicativos com Link Time Optimization (LTO):

ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/13.2.0/liblto_plugin.so \
        /usr/lib/bfd-plugins/

Agora que nosso conjunto de ferramentas final está no lugar, é importante certificar-se novamente de que compilação e vinculação funcionarão como esperado. Nós fazemos isso realizando algumas verificações de sanidade:

echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'

Não deveriam existir erros e a saída gerada do último comando será (permitindo diferenças específicas de plataforma no nome do vinculador dinâmico):

[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

Agora tenha certeza de que nós estamos configurados para usar os arquivos de início corretos:

grep -E -o '/usr/lib.*/S?crt[1in].*succeeded' dummy.log

A saída gerada do último comando deveria ser:

/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.0/../../../../lib/Scrt1.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.0/../../../../lib/crti.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.0/../../../../lib/crtn.o succeeded

Dependendo da arquitetura da sua máquina, o acima possivelmente difira ligeiramente. A diferença será o nome do diretório depois de /usr/lib/gcc. A coisa importante a se olhar aqui é que o gcc tenha encontrado todos os três arquivos crt*.o sob o diretório /usr/lib.

Verifique se o compilador está procurando os arquivos de cabeçalho corretos:

grep -B4 '^ /usr/include' dummy.log

Esse comando deveria retornar a seguinte saída gerada:

#include <...> search starts here:
 /usr/lib/gcc/x86_64-pc-linux-gnu/13.2.0/include
 /usr/local/include
 /usr/lib/gcc/x86_64-pc-linux-gnu/13.2.0/include-fixed
 /usr/include

Novamente, o diretório nomeado depois do seu trio alvo possivelmente seja diferente do acima, dependendo da arquitetura do seu sistema.

Agora, verifique se o novo vinculador está sendo usado com os caminhos de procura corretos:

grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'

As referências a caminhos que tem componentes com '-linux-gnu' deveriam ser ignoradas, porém, do contrário, a saída gerada do último comando deveria ser:

SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64")
SEARCH_DIR("/usr/local/lib64")
SEARCH_DIR("/lib64")
SEARCH_DIR("/usr/lib64")
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");

Um sistema de 32 bits possivelmente use uns poucos outros diretórios. Por exemplo, aqui está a saída gerada originária de uma máquina i686:

SEARCH_DIR("/usr/i686-pc-linux-gnu/lib32")
SEARCH_DIR("/usr/local/lib32")
SEARCH_DIR("/lib32")
SEARCH_DIR("/usr/lib32")
SEARCH_DIR("/usr/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");

Em seguida, tenha certeza de que nós estamos usando a libc correta:

grep "/lib.*/libc.so.6 " dummy.log

A saída gerada do último comando deveria ser:

attempt to open /usr/lib/libc.so.6 succeeded

Tenha certeza de que o GCC está usando o vinculador dinâmico correto:

grep found dummy.log

A saída gerada do último comando deveria ser (permitindo diferenças específicas de plataforma no nome do vinculador dinâmico):

found ld-linux-x86-64.so.2 at /usr/lib/ld-linux-x86-64.so.2

Se a saída gerada não aparecer como mostrada acima ou não for recebida de jeito nenhum, então alguma coisa está seriamente errada. Investigue e refaça os passos para descobrir onde o problema está e corrigi-lo. Quaisquer problemas deveriam ser resolvidos antes de continuar com o processo.

Uma vez que tudo esteja funcionando corretamente, remova os arquivos de teste:

rm -v dummy.c a.out dummy.log

Finalmente, mova um arquivo mal colocado:

mkdir -pv /usr/share/gdb/auto-load/usr/lib
mv -v /usr/lib/*gdb.py /usr/share/gdb/auto-load/usr/lib

8.27.2. Conteúdo do GCC

Aplicativos instalados: c++, cc (link para gcc), cpp, g++, gcc, gcc-ar, gcc-nm, gcc-ranlib, gcov, gcov-dump, gcov-tool e lto-dump
Bibliotecas instaladas: libasan.{a,so}, libatomic.{a,so}, libcc1.so, libgcc.a, libgcc_eh.a, libgcc_s.so, libgcov.a, libgomp.{a,so}, libhwasan.{a,so}, libitm.{a,so}, liblsan.{a,so}, liblto_plugin.so, libquadmath.{a,so}, libssp.{a,so}, libssp_nonshared.a, libstdc++.{a,so}, libstdc++exp.a, libstdc++fs.a, libsupc++.a, libtsan.{a,so} e libubsan.{a,so}
Diretórios instalados: /usr/include/c++, /usr/lib/gcc, /usr/libexec/gcc e /usr/share/gcc-13.2.0

Descrições Curtas

c++

O compilador C++

cc

O compilador C

cpp

O preprocessador C; é usado pelo compilador para expandir as diretivas #include, #define e similares nos arquivos fonte

g++

O compilador C++

gcc

O compilador C

gcc-ar

Um encapsulador em torno de ar que adiciona um plugin à linha de comando. Esse aplicativo é usado somente para adicionar "link time optimization" e não é útil com as opções padrão de construção.

gcc-nm

Um encapsulador em torno de nm que adiciona um plugin à linha de comando. Esse aplicativo é usado somente para adicionar "link time optimization" e não é útil com as opções padrão de construção.

gcc-ranlib

Um encapsulador em torno de ranlib que adiciona um plugin à linha de comando. Esse aplicativo é usado somente para adicionar "link time optimization" e não é útil com as opções padrão de construção.

gcov

Uma ferramenta de testagem de cobertura; usada para analisar aplicativos para determinar onde as otimizações terão o maior efeito

gcov-dump

Ferramenta de despejo de perfil offline gcda e gcno

gcov-tool

Ferramenta de processamento de perfil offline gcda

lto-dump

Ferramenta para despejar arquivos objeto produzidos pelo GCC com LTO habilitado

libasan

A biblioteca de tempo de execução Address Sanitizer

libatomic

Biblioteca de tempo de execução integrada atômica do GCC

libcc1

A biblioteca de pré-processamento C

libgcc

Contém suporte de tempo de execução para o gcc

libgcov

Essa biblioteca é vinculada a um aplicativo quando o GCC for instruído a habilitar criação de perfil

libgomp

Implementação GNU da API OpenMP para programação paralela de memória compartilhada multiplataforma em C/C++ e Fortran

libhwasan

A biblioteca de tempo de execução do Address Sanitizer assistida por hardware

libitm

A biblioteca de memória transacional GNU

liblsan

A biblioteca de tempo de execução Leak Sanitizer

liblto_plugin

Plugin LTO do GCC permite ao Binutils processar arquivos objeto produzidos pelo GCC com LTO habilitado

libquadmath

API da Biblioteca GCC Quad Precision Math

libssp

Contém rotinas suportantes da funcionalidade de proteção contra esmagamento de pilha do GCC.

libstdc++

A biblioteca padrão C++

libstdc++exp

Biblioteca Experimental de Contratos C++

libstdc++fs

Biblioteca de Sistema de Arquivos ISO/IEC TS 18822:2015

libsupc++

Fornece rotinas suportantes para a linguagem de programação C++

libtsan

A biblioteca de tempo de execução Thread Sanitizer

libubsan

A biblioteca de tempo de execução Undefined Behavior Sanitizer