8.29.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 \
--enable-host-pie \
--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 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-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/12.4/
e https://gcc.gnu.org/ml/gcc-testresults/.
Os testes relacionados a pr90579.c
são conhecidos por falharem.
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