22 Fev, 2021

Um Diário da Minha Experiência no Linux From Scratch (LFS)

Esse post foi originalmente publicado no meu blog antigo entre 5 e 17 de Setembro de 2013.

Na época eu resolvi seguir o tutorial do Linux From Scratch (LFS), e conforme seguia os passos do tutorial, fui anotando algumas observações e problemas que encontrei. Talvez esse relato possa ser útil caso você também esteja interessado nesse tutorial.

Mas o que é o Linux From Scratch? O LFS é um livro/tutorial detalhando passo a passo como criar sua própria distribuição Linux do zero, desde a criação de uma partição no disco para a instalação, passando pela criação da toolchain usada para compilar os pacotes, até a compilação e instalação dos pacotes em si, tudo a partir do código-fonte. Esse tutorial não requere conhecimento de programação, mas é recomendado que o usuário já tenha alguma familiaridade com Linux.

O relato está incompleto, não sei porque, já que cheguei a completar a instalação, mas isso é o que encontrei. Talvez algumas coisas que eu digo abaixo também não façam muito sentido, já que na época meu entendimento sobre Linux era mais limitado do que é hoje.

LFS: Dia 1 - 7/3/13

Finalmente comecei o LFS, hoje, com o livro versão 7.2. Para dizer que realmente comecei apenas executei o script que checa as versões dos programas básicos que tenho que ter no meu computador hospedeiro. Estou usando um Debian 6. Tive que instalar o bison e o gawk. No caso do gawk, já tinha instalado o mawk, que dizem ser mais rápido, porém não é recomendado para o LFS. Ainda tive que criar um link simbólico em /bin/awk para /bin/gawk.

LFS: Dia 2 - 8/3/13

Comecei a fazer algo de fato. Instalei o GParted para redimensionar minhas partições, mas quando fui ver elas já estavam estruturadas de uma boa forma, e eu já tinha uma partição livre de 4,7GB formatada como ext3 (acho que já tinha deixado ela para o LFS desde a última vez que formatei o computador - algo que tenho feito com alguma frequência).

Após isso, tive que usar o programa mke2fs do pacote e2fsprogs para criar um sistema de arquivos ext3 na minha partição LFS (embora já estivesse criado, resolvi sobrescrever para passar pelo processo e para garantir que tudo ficaria igual ao livro). Bom, entendi errado uma nota do livro sobre usar o debugfs, e acabei achando que eu precisava compilar o e2fsprogs dos fontes (não precisava no meu caso). A compilação foi rápida e fácil, porém nunca havia compilado um pacote no Linux a partir dos fontes, demorou alguns segundos a compilação, mais do que eu estou acostumado quando compilo meus projetos com 20 arquivos fontes em C++.

Depois montei a partição.

Próximo passo, baixar os arquivos. São quase 1GB de arquivos, então acho que deixarei baixando por umas horas ou minutos. Usei o arquivo wget-list que eles disponibilizam no site do LFS para facilitar o processo de download usando o programa wget. O wget baixa uma lista de arquivos se receber como parâmetro um arquivo que contenha o nome desses arquivos (um em cada linha). Mais um comando útil aprendido.

Na verdade o download foi rápido, 307MB, 15min 24s. Então percebi que eu havia usado o wget-list do livro 7.3, porque as versões dos pacotes estavam maiores que as do livro 7.2. Então resolvi baixar o livro novo (7.3) e dar uma olhada para ver se precisava fazer algo diferente. Rodei o version-check.sh do livro novo para ver se meu sistema hospedeiro ainda é atualizado o bastante para essa versão do LFS. Felizmente tudo correu bem.

Agora preciso executar os MD5 sums para ver se os pacotes foram baixados corretamente. Novamente existe um arquivo no site deles com as MD5 sums, então com um comando tudo é checado. Na hora de fazer o checksum, o pacote lfs-bootscripts não passou. Procurei no Google pelo pacote na versão indicada no livro, encontrei, baixei, e ele passou no checksum. Bom, por hoje é só, no próximo dia vou para o início do capítulo 4.

LFS: Dia 3 - 9/3/13

Hoje tive que criar o diretório tools. É importante lembrar de verificar se a variável LFS está setada e se a partição está montada. Após criar o diretório, foram criados um usuário lfs e um grupo lfs. Um arquivo bash_profile foi criado para garantir que o ambiente será limpo quando logado no shell com esse usuário. Não entendi o que o comando source faz.

Tudo bem, vamos para o capítulo 5: Construindo um Sistema Temporário.

Antes de começar o processo de construir a toolchain, o livro reforça a necessidade de garantir que você está usando o bash como shell e a existência de alguns links simbólicos. Tive uma surpresa ao ver, usando o comando file, que o /usr/bin/awk não apontava para o gawk. Tinha certeza que eu já havia criado esse link. O yacc também não estava apontando para o bison. Removi o link e criei outro. O sh também estava apontando para o lugar errado: dash ao invés de bash. Para garantir que o shell usado era o bash tive que pesquisar, e descobri que podemos saber isso dando echo na variável $SHELL.

Agora, hora de compilar o binutils. Usei a recomendação do livro para medir o tempo usando o programa time, e colocando dentro dele tanto a chamada do configure quanto do make e do make install. Os resultados foram:

real	2m57.222s	(177s)
user	2m42.906s	(162s)
sys		0m32.010s	(32s)

Então, minha SBU vale 177s, o que significa que devo demorar 3115s (aproximadamente 52 minutos) para compilar o GCC, que é o maior pacote de todos. Esqueci de executar os comandos dentro do diretório binutils-build, o que fez meus arquivos não ficarem nessa pasta. Removi os arquivos que foram gerados na pasta sources manualmente e refiz da maneira correta.

real	2m53.382s	(173s)
user	2m41.438s	(161s)
sys		0m31.706s	(31s)

Vou considerar esse novo tempo como minha SBU, que agora passa a ter 173s, o que reduz o tempo de compilação da GCC para 3045s (51 minutos). A instalação do pacote gerou vários arquivos e diretórios na pasta tools. Próximo passo: compilar o GCC.

LFS: Dia 4 - 10/3/13

Hoje é o dia de compilar o GCC (pass 1). Antes de começar o trabalho, sempre tenho que montar a partição do LFS, então resolvi criar um script para isso. Até a extração do GCC é demorada. No entanto a configuração, compilação e instalação demoraram muito menos que o esperado:

real	15m36.000s
user	14m19.018s
sys		1m48.811s

Será que correu tudo bem? Não faço a menor ideia. Chequei o diretório tools e notei que existem alguns arquivos novos lá, espero que tudo tenha funcionado. A instalação dos Headers da API do Linux foi tranquila e rápida. Perdi algum tempo checando se havia alguma coisa nova no diretório da toolchain (tools). Depois, hora de completar o primeiro pass compilando a glibc. A compilação foi bem demorada (mais demorada que do GCC):

real	18m53.522s
user	17m1.896s
sys		2m50.755s

A próxima etapa é começar o pass 2.

LFS: Dia 5 - 23/3/13

Hoje começa o binutils pass 2. Relembrando: antes de começar, montar a partição do LFS e logar com o usuário lfs. Extrair o arquivo do binutils e entrar na pasta gerada. Para lembrar o comando tar necessário para extrair o binutils (que estava no formato .tar.bz2) usei o comando:

$ history | grep tar

que mostra os últimos comandos no histórico desse usuário contendo o termo tar. A compilação demorou menos de 7 minutos.

Tive dúvida se deveria ou não executar os testes do pacote, e como executar. Após uma busca no livro notei que anteriormente o autor fala que não é necessário testar as ferramentas compiladas no sistema temporário do capítulo 5.

LFS: Dia 6 - 28/4/13

Mais de um mês longe do LFS, resolvi voltar a fazê-lo. GCC pass 2. Bom, a compilação foi a mais demorada que eu já vi, demorou mais de uma hora. Infelizmente não usei o comando time para medir o tempo. Após a longa compilação, posso começar a compilação dos outros 23 pacotes da Toolchain.

O próximo pacote é o Tcl. Ele os 3 próximos pacotes são necessários para rodar os testes. Após a instalação do Tcl, novamente chequei o diretório /tools/lib e notei que já haviam muitas libs lá, a maioria do dia que compilei a GCC pass 1 e a glibc.

A esse ponto comecei a notar a importância de links simbólicos no Linux. Já tive que criar muitos até agora, e esse do Tcl me fez entender melhor o versionamento de shared objects (so) no Linux. Quando temos várias versões de libs instaladas, uma prática comum é a criação de um link simbólico para a versão padrão ou mais recente da lib.

Agora é hora de instalar o Expect. Esse pacote será o menor de todos até agora instalados, ocupando apenas uns 4,4MB. Realmente foi bem rápida a compilação. Rodei o comando make test e dos 26 testes 12 falharam, mas o livro diz para não se preocupar com isso agora.

A compilação e instalação do pacote DejaGNU e Check foram rápidas. O teste do pacote Check foi um pouco demorado (cerca de 5 minutos). Em seguida instalei o pacote ncurses sem maiores problemas.

Estranhamente, após a instalação do pacote bash, na tentativa de remover os arquivos que restaram da extração dos fontes, alguns arquivos não tinham permissão de escrita, com isso não era possível removê-los. Mudei a permissão manualmente e removi os arquivos.

Os testes do coreutils são um pouco demorados. Um assustador aviso vermelho dizendo 1 of 282 tests failed apareceu. Vou imaginar que nessa fase isso é normal. O mesmo problema de arquivos sem permissão de escrita ocorreu.

Após isso entrei num ritmo frenético de compilação e instalação de pacotes: diffutils, file, findutils, gawk, gettext, grep, gzip, m4, make, patch, perl, sed, tar, texinfo, xz. Tudo em sequência. Os mesmos passos: descompactar, entrar no diretório, configurar, compilar, testar, instalar, sair do diretório, remover fontes. As vezes era necessário mudar as permissões para remover os fontes.

Agora executei as instruções finais do capítulo para eliminar arquivos desnecessários e liberar espaço, e também mudar as permissões do diretório da toolchain. Daqui pra frente os comandos devem ser executados como usuário root (e não podemos nos esquecer de ter a variável $LFS setada para esse usuário). Caso eu pretenda usar essa toolchain para construir outros sistemas LFS futuramente, o livro recomenda fazer o backup agora. Não sei se farei isso. O que importa é que a próxima etapa é o início da construção do sistema LFS final :D

LFS: Dia 7 - 29/4/13

Hoje resolvi fazer o backup do diretório tools… Talvez eu queira usar a toolchain novamente no futuro…

Bom, backup criado, usando um comando:

$ su root
# tar -cf ~/lfs/tools.tar $LFS/tools

Agora começo a iniciar a verdadeira construção do Linux. From scratch…

Começou um pouco nebuloso… Montei uns sistemas de arquivos e executei alguns comandos que não sei se estarão lá quando eu reiniciar a máquina… Mas vamos ver no próximo dia.

LFS: Dia 8 - 30/4/13

Percebi que os comandos mknod que foram executados criaram um “arquivo”. Executando o comando mount para ver o que estava montado, vi que os sistemas de arquivos que montei da última vez não estavam mais montados. Executei novamente os comandos de montagem para dev, devpts, proc e sysfs, rodei mount e eles agora estavam lá. Executei também o comando com um if que monta o sistema de arquivos temporário shm.

A parte do livro que fala sobre atualização e gerenciamento de pacotes mostra que esse tema é muito mais complexo que eu imaginava. Vou ignorar isso, já que estou construindo o LFS para fins de aprendizado apenas.

O processo para copiar um LFS para outro computador (após finalizado) parece ser razoavelmente simples: uma cópia da raiz do LFS usando tar, extração do tar para a partição na nova máquina, alteração de alguns arquivos e tornar o sistema “bootável”.

Vou parar por aqui, o próximo passo é entrar no ambiente via chroot. O livro nos lembra que é preciso montar o sistema de arquivos do Kernel Virtual e fazer chroot sempre que o computador for reiniciado, para executar os comandos à frente. Para sair do ambiente chroot é simples:

$ logout

Resolvi continuar um pouco mais por hoje. Está ficando empolgante agora que o sistema está começando a tomar forma.

Para evitar digitar muitos comandos toda vez que eu reiniciar meu computador e vier trabalhar no LFS, criei um script que faz tudo que preciso: monta os sistemas de arquivos e faz chroot.

Acho que montei duas vezes os sistemas de arquivos do kernel virtual, eles já estavam montados e executei novamente o comando. O mount mostrou duas vezes cada um deles. Vou tentar desmontá-los. Criei também um script para quando eu sair do chroot (que já desmonta tudo).

Após a criação de alguns arquivos e links, o trabalho volta a ser parecido com o que estava sendo antes: extração, compilação e instalação. Instalei os headers da API do Linux e as man-pages. Nenhuma surpresa. O próximo passo é a glibc, que será um tanto demorada, por isso deixarei para depois…

Compilando e rodando os testes da glibc, os tempos foram:

real	57m26.194s
user	42m47.832s
sys		14m50.088s

E os seguintes erros foram encontrados:

make[2]: [/sources/glibc-build/posix/annexc.out] Error 1 (ignored)
make[2]: *** [/sources/glibc-build/rt/tst-cpuclock2.out] Error 1
make[1]: *** [rt/tests] Error 2
make[2]: [/sources/glibc-build/conform/run-conformtest.out] Error 1 (ignored)
make: *** [check] Error 2

Aparentemente esses erros estão dentro do esperado. Vou parar antes de 6.9.2. Configuring Glibc.

LFS: Dia 9 - 1/5/13

Completei os ajustes na Glibc. Zlib, file e binutils instalados… Agora só faltam… 49 pacotes ainda!! Achei que terminaria de instalar pacotes hoje mas me enganei. Instalei gmp, mpfr, mpc… Mas vou parar por aqui hoje, o próximo pacote é a GCC, que, de acordo com os SBUs vai me levar cerca de 150 minutos… Boa noite!

LFS: Dia 10 - 2/5/13

A configuração da GCC foi rápida. A compilação demorou:

real	21m19.677s
user	19m35.961s
sys		1m33.374s

A execução da test suite da GCC é realmente demorada…

real	153m1.177s
user	133m29.701s
sys		33m32.402s

Apesar da extrema demora dos testes e algumas falhas, os resultados, após comparados com os que estão nas URLs sugeridas pelo livro, foram dentro do esperado.

A instalação foi bem rápida. Após isso, fiz todas as verificações e ajustes necessários para garantir o funcionamento correto da GCC. Tudo ok. Próximos passos: sed e mais 44 pacotes.

A instalação dos pacotes sed, bzip2, pkg-config, ncurses foram rápidas e simples. O próximo pacote é o util-linux (e depois mais 40 pacotes).