Anterior: , Acima: Inicializando   [Conteúdo][Índice]


20.2 Preparando para usar os binários do Bootstrap

Grafo de dependência das primeiras
derivações do bootstrap

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.

Construindo as ferramentas de construção

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.

Grafo de dependência dos primeiros
pacotes

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).

Construindo os binários Bootstrap

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.

Reducing the Set of Bootstrap Binaries

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!


Notas de Rodapé

(42)

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]