8.30.1. Instalação do GCC
Primeiro, faça uma correção exigida pela glibc-2.43 e posteriores:
sed -i 's/char [*]q/const &/' libgomp/affinity-fmt.c
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 \
--enable-host-pie \
--disable-multilib \
--disable-bootstrap \
--disable-fixincludes \
--with-system-zlib
Nós habilitamos somente C e C++ aqui para economizar o tempo de
construção, já que nenhum pacote no LFS e no BLFS exige o GCC para
compilar outras linguagens. Posponha cobol para Cobol (observe que isso fará com que o
GCC falhe para construir em um sistema LFS de 32 bits),
fortran para Fortran, go para Go, objc para
Objective C, obj-c++ para Objective
C++ e (ou) m2 para Modula 2 no valor
da opção --enable-languages
se você quiser compilar programas em uma ou mais dessas linguagens
com o GCC. O GCC também suporta Ada e D, mas o código para suportar
Ada ou D é escrito na própria Ada ou D, de forma que o suporte só
pode ser construído com uma instalação existente do compilador Ada
ou D e nós não conseguimos habilitar o suporte aqui.
O significado dos novos parâmetros de
configuração:
-
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-bootstrap
-
Por padrão, o sistema de construção do GCC autoaprimorará em
3 estágios, a menos que ele seja construído como um
compilador cruzado ou esteja sendo compilado cruzadamente. O
processo de autoaprimoramento é necessário para robusteza,
especialmente ao atualizar o GCC para uma nova versão. No
LFS, nós estamos usando um método diferente para
autoaprimorar o GCC (conforme nós apresentamos nas Observações
Técnicas do Conjunto de Ferramentas), de forma que aqui
nós não precisamos do processo de autoaprimoramento fornecido
pelo sistema de construção e nós o desabilitamos para reduzir
significativamente o tempo de construção. Remova essa opção
quando você atualizar o GCC em um sistema LFS completo (em
vez de construir o LFS).
-
--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
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
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.
O GCC pode precisar de mais espaço de pilha para compilar alguns
padrões de código extremamente complexos. Como precaução para as
distribuições anfitriãs com um limite de pilha apertado, configure
explicitamente o limite rígido do tamanho da pilha como infinito.
Na maioria das distribuições anfitriãs (e no sistema LFS final), o
limite rígido é infinito por padrão, mas não há mal algum em
configurá-lo explicitamente. Não é necessário mudar o limite
flexível do tamanho da pilha porque o GCC o configurará
automaticamente para um valor apropriado, desde que o valor não
exceda o limite rígido:
ulimit -s -H unlimited
Agora remova várias falhas conhecidas de teste:
sed -e '/cpython/d' -i ../gcc/testsuite/gcc.dg/plugin/plugin.exp
Teste os resultados como um(a) usuário(a) não privilegiado(a),
porém não pare em erros:
chown -R 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/13.0/
e https://gcc.gnu.org/ml/gcc-testresults/.
Quatro testes relacionados a pr90579.c são conhecidos por falharem.
Cinco testes relacionados a analyzer/strchr-1.c são conhecidos por falharem.
Quatro testes na libstdc++, 17_intro/badnames.cc, 17_intro/names.cc, 17_intro/names_fortify.cc e experimental/names.cc, são conhecidos por
falharem devido a mudanças com o glibc-2.43.
Umas poucas falhas inesperadas não podem ser evitadas sempre. 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)/15.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)/15.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(){}' | cc -x 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á
(levando em consideração diferenças específicas da plataforma no
nome do vinculador dinâmico):
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
Agora certifique-se de que nós estamos configurados para usar os
arquivos corretos de iniciação:
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/15.2.0/../../../../lib/Scrt1.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.0/../../../../lib/crti.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/15.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 corretos de
cabeçalho:
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/15.2.0/include
/usr/local/include
/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.0/include-fixed
/usr/include
Novamente, o diretório nomeado depois do teu tripleto alvo
possivelmente seja diferente do acima, dependendo da arquitetura do
teu sistema.
Agora, verifique se o novo vinculador está sendo usado com os
caminhos corretos de procura:
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
Referências para caminhos que tenham 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 GCC está usando o vinculador dinâmico correto:
grep found dummy.log
A saída gerada do último comando deveria ser (levando em
consideração diferenças específicas da 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 conforme mostrado acima ou não for
recebida, então alguma coisa está seriamente errada. Investigue e
refaça as etapas para descobrir onde está o problema e corrija-o.
Quaisquer problemas deveriam ser resolvidos antes de se continuar
com o processo.
Uma vez que tudo esteja funcionando corretamente, remova os
arquivos de teste:
rm -v 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