Anterior: O Bootstrap de código fonte completo, Acima: Inicializando [Conteúdo][Índice]
A figura acima mostra o início do grafo de dependência da distribuição,
correspondendo às definições de pacote do módulo (gnu packages
bootstrap)
. Uma figura similar pode ser gerada com guix graph
(veja Invocando guix graph
), ao longo das linhas de:
guix graph -t derivation \ -e '(@@ (gnu packages bootstrap) %bootstrap-gcc)' \ | dot -Tps > gcc.ps
ou, para o bootstrap de semente binária reduzida
guix graph -t derivation \ -e '(@@ (pacotes gnu bootstrap) %bootstrap-mes)' \ | ponto -Tps > mes.ps
Neste nível de detalhe, as coisas são um pouco complexas. Primeiro, o
próprio Guile consiste em um executável ELF, junto com muitas fontes e
arquivos de Scheme compilados que são carregados dinamicamente quando ele é
executado. Isso é armazenado no tarball guile-2.0.7.tar.xz mostrado
neste grafo. Este tarball é parte da distribuição de “fontes” do Guix e é
inserido no armazém com add-to-store
(veja O armazém).
Mas como escrevemos uma derivação que descompacta esse tarball e o adiciona
ao armazém? Para resolver esse problema, a derivação
guile-bootstrap-2.0.drv
— a primeira que é construída — usa
bash
como seu construtor, que executa
build-bootstrap-guile.sh
, que por sua vez chama tar
para
descompactar o tarball. Assim, bash, tar, xz e
mkdir são binários estaticamente vinculados, também parte da
distribuição de fontes do Guix, cujo único propósito é permitir que o
tarball do Guile seja descompactado.
Uma vez que guile-bootstrap-2.0.drv
é construído, temos um Guile
funcional que pode ser usado para executar programas de construção
subsequentes. Sua primeira tarefa é baixar tarballs contendo os outros
binários pré-construídos — é isso que as derivações .tar.xz.drv
fazem. Módulos Guix como ftp-client.scm
são usados para esse
propósito. As derivações module-import.drv
importam esses módulos em
um diretório no armazém, usando o layout original. As derivações
module-import-compiled.drv
compilam esses módulos e os escrevem em um
diretório de saída com o layout correto. Isso corresponde ao argumento
#:modules
de build-expression->derivation
(veja Derivações).
Por fim, os vários tarballs são descompactados pelas derivações
gcc-bootstrap-0.drv
, glibc-bootstrap-0.drv
ou
bootstrap-mes-0.drv
e bootstrap-mescc-tools-0.drv
, ponto em
que temos uma cadeia de ferramentas C funcional.
O bootstrapping está completo quando temos uma cadeia de ferramentas
completa que não depende das ferramentas bootstrap pré-construídas
discutidas acima. Esse requisito de não dependência é verificado verificando
se os arquivos da cadeia de ferramentas final contêm referências aos
diretórios /gnu/store das entradas bootstrap. O processo que leva a
essa cadeia de ferramentas “final” é descrito pelas definições de pacote
encontradas no módulo (gnu packages commencement)
.
O comando guix graph
nos permite “diminuir o zoom” em comparação
ao grafo acima, observando o nível de objetos do pacote em vez de derivações
individuais — lembre-se de que um pacote pode ser traduzido para várias
derivações, normalmente uma derivação para baixar sua fonte, uma para
construir os módulos Guile de que ele precisa e uma para realmente construir
o pacote a partir da fonte. O comando:
guix graph -t bag \ -e '(@@ (gnu packages commencement) glibc-final-with-bootstrap-bash)' | xdot -
exibe o grafo de dependência que leva à biblioteca C “final”42, descrita abaixo.
A primeira ferramenta que é construída com os binários bootstrap é o
GNU Make—observado make-boot0
acima—que é um pré-requisito
para todos os pacotes seguintes. A partir daí, Findutils e Diffutils são
construídos.
Então vêm os Binutils e GCC de primeiro estágio, construídos como pseudo cross tools—i.e., com --target igual a --host. Eles são usados para construir a libc. Graças a esse truque de cross-build, essa libc tem a garantia de não manter nenhuma referência à cadeia de ferramentas inicial.
A partir daí, os Binutils finais e o GCC (não mostrados acima) são
construídos. O GCC usa ld
dos Binutils finais e vincula programas
à libc recém-construída. Essa cadeia de ferramentas é usada para construir
os outros pacotes usados pelo Guix e pelo GNU Build System: Guile, Bash,
Coreutils, etc.
E voilà! Neste ponto, temos o conjunto completo de ferramentas de construção
que o GNU Build System espera. Elas estão na variável %final-inputs
do módulo (gnu packages commencement)
e são implicitamente usadas por
qualquer pacote que use gnu-build-system
(veja gnu-build-system
).
Because the final tool chain does not depend on the bootstrap binaries,
those rarely need to be updated. Nevertheless, it is useful to have an
automated way to produce them, should an update occur, and this is what the
(gnu packages make-bootstrap)
module provides.
The following command builds the tarballs containing the bootstrap binaries (Binutils, GCC, glibc, for the traditional bootstrap and linux-libre-headers, bootstrap-mescc-tools, bootstrap-mes for the Reduced Binary Seed bootstrap, and Guile, and a tarball containing a mixture of Coreutils and other basic command-line tools):
guix build bootstrap-tarballs
The generated tarballs are those that should be referred to in the
(gnu packages bootstrap)
module mentioned at the beginning of this
section.
Still here? Then perhaps by now you’ve started to wonder: when do we reach a fixed point? That is an interesting question! The answer is unknown, but if you would like to investigate further (and have significant computational and storage resources to do so), then let us know.
Our traditional bootstrap includes GCC, GNU Libc, Guile, etc. That’s a lot of binary code! Why is that a problem? It’s a problem because these big chunks of binary code are practically non-auditable, which makes it hard to establish what source code produced them. Every unauditable binary also leaves us vulnerable to compiler backdoors as described by Ken Thompson in the 1984 paper Reflections on Trusting Trust.
This is mitigated by the fact that our bootstrap binaries were generated from an earlier Guix revision. Nevertheless it lacks the level of transparency that we get in the rest of the package dependency graph, where Guix always gives us a source-to-binary mapping. Thus, our goal is to reduce the set of bootstrap binaries to the bare minimum.
The Bootstrappable.org web site lists on-going projects to do that. One of these is about replacing the bootstrap GCC with a sequence of assemblers, interpreters, and compilers of increasing complexity, which could be built from source starting from a simple and auditable assembler.
Our first major achievement is the replacement of GCC, the GNU C Library and Binutils by MesCC-Tools (a simple hex linker and macro assembler) and Mes (veja GNU Mes Reference Manual em GNU Mes, a Scheme interpreter and C compiler in Scheme). Neither MesCC-Tools nor Mes can be fully bootstrapped yet and thus we inject them as binary seeds. We call this the Reduced Binary Seed bootstrap, as it has halved the size of our bootstrap binaries! Also, it has eliminated the C compiler binary; i686-linux and x86_64-linux Guix packages are now bootstrapped without any binary C compiler.
Work is ongoing to make MesCC-Tools and Mes fully bootstrappable and we are also looking at any other bootstrap binaries. Your help is welcome!
Você
pode notar o rótulo glibc-intermediate
, sugerindo que ela não é
completamente final, mas como uma boa aproximação, a consideraremos
final.
Anterior: O Bootstrap de código fonte completo, Acima: Inicializando [Conteúdo][Índice]