Próximo: API de imagem do sistema Guix, Anterior: Login automático em um TTY específico, Acima: Configuração do sistema [Conteúdo][Índice]
Guix é, em sua essência, uma distribuição baseada em código-fonte com substitutos (veja Substitutos em Manual de Referência do GNU Guix) e, como tal, construir pacotes a partir de seu código-fonte é uma parte esperada das instalações e atualizações regulares de pacotes. Dado este ponto de partida, faz sentido que sejam feitos esforços para reduzir a quantidade de tempo gasto na compilação de pacotes, e as recentes mudanças e atualizações na construção e distribuição de substitutos continuam a ser um tópico de discussão dentro do Guix.
O kernel, embora não exija uma superabundância de RAM para ser construído, leva muito tempo em uma máquina média. A configuração oficial do kernel, como é o caso de muitas distribuições GNU/Linux, erra pelo lado da inclusão, e é isso que realmente faz com que a construção demore tanto tempo quando o kernel é compilado a partir do código-fonte.
O kernel do Linux, entretanto, também pode ser descrito apenas como um pacote antigo normal e, como tal, pode ser personalizado como qualquer outro pacote. O procedimento é um pouco diferente, embora isso se deva principalmente à natureza de como a definição do pacote é escrita.
A definição do pacote do kernel linux-libre
é na verdade um
procedimento que cria um pacote.
(define* (make-linux-libre* versão gnu-revision fonte sistemas-suportados
#:key
(extra-version #f)
;; Uma função que pega um arch e uma variante.
;; Veja kernel-config para um exemplo.
(configuration-file #f)
(defconfig "defconfig")
(extra-options %default-extra-linux-options))
...)
O pacote linux-libre
atual é para a série 5.15.x e é declarado assim:
(define-public linux-libre-5.15
(make-linux-libre* linux-libre-5.15-version
linux-libre-5.15-gnu-revision
linux-libre-5.15-source
'("x86_64-linux" "i686-linux" "armhf-linux"
"aarch64-linux" "riscv64-linux")
#:configuration-file kernel-config))
Quaisquer chaves às quais não sejam atribuídos valores herdam seu valor
padrão da definição make-linux-libre
. Ao comparar os dois trechos
acima, observe o comentário do código que se refere a
#:configuration-file
. Por causa disso, não é realmente fácil incluir
uma configuração de kernel personalizada na definição, mas não se preocupe,
existem outras maneiras de trabalhar com o que temos.
Existem duas maneiras de criar um kernel com uma configuração de kernel
personalizada. A primeira é fornecer um arquivo .config padrão
durante o processo de construção, incluindo um arquivo .config real
como uma entrada nativa para nosso kernel personalizado. A seguir está um
trecho da fase 'configure
personalizada da definição do pacote
make-linux-libre
:
(let ((build (assoc-ref %standard-phases 'build))
(config (assoc-ref (or native-inputs inputs) "kconfig")))
;; Use um arquivo de configuração de kernel personalizado ou um padrão
;; configuration file.
(if config
(begin
(copy-file config ".config")
(chmod ".config" #o666))
(invoke "make" ,defconfig)))
Abaixo está um exemplo de pacote de kernel. O pacote linux-libre
não
é nada especial e pode ser herdado e ter seus campos substituídos como
qualquer outro pacote:
(define-public linux-libre/E2140
(package
(inherit linux-libre)
(native-inputs
`(("kconfig" ,(local-file "E2140.config"))
,@(alist-delete "kconfig"
(package-native-inputs linux-libre))))))
No mesmo diretório do arquivo que define linux-libre-E2140
está um
arquivo chamado E2140.config, que é um arquivo de configuração real
do kernel. A palavra-chave defconfig
de make-linux-libre
é
deixada em branco aqui, então a única configuração do kernel no pacote é
aquela que foi incluída no campo native-inputs
.
A segunda maneira de criar um kernel customizado é passar um novo valor para
a palavra-chave extra-options
do procedimento
make-linux-libre
. A palavra-chave extra-options
funciona com
outra função definida logo abaixo dela:
(define %default-extra-linux-options `(;; https://lists.gnu.org/archive/html/guix-devel/2014-04/msg00039.html ("CONFIG_DEVPTS_MULTIPLE_INSTANCES" . #true) ;; Modules required for initrd: ("CONFIG_NET_9P" . m) ("CONFIG_NET_9P_VIRTIO" . m) ("CONFIG_VIRTIO_BLK" . m) ("CONFIG_VIRTIO_NET" . m) ("CONFIG_VIRTIO_PCI" . m) ("CONFIG_VIRTIO_BALLOON" . m) ("CONFIG_VIRTIO_MMIO" . m) ("CONFIG_FUSE_FS" . m) ("CONFIG_CIFS" . m) ("CONFIG_9P_FS" . m))) (define (config->string options) (string-join (map (match-lambda ((option . 'm) (string-append option "=m")) ((option . #true) (string-append option "=y")) ((option . #false) (string-append option "=n"))) options) "\n"))
E no script de configuração personalizado do pacote ‘make-linux-libre‘:
;; A anexação funciona mesmo quando a opção não estava no arquivo. ;; A última prevalece se duplicada. (let ((port (open-file ".config" "a")) (extra-configuration ,(config->string extra-options))) (display extra-configuration port) (close-port port)) (invoke "make" "oldconfig")
Portanto, ao não fornecer um arquivo de configuração, o .config começa em branco e então escrevemos nele a coleção de flags que desejamos. Aqui está outro kernel personalizado:
(define %macbook41-full-config (append %macbook41-config-options %file-systems %efi-support %emulation (@@ (gnu packages linux) %default-extra-linux-options))) (define-public linux-libre-macbook41 ;; XXX: Access the internal 'make-linux-libre*' procedure, which is ;; private and unexported, and is liable to change in the future. ((@@ (gnu packages linux) make-linux-libre*) (@@ (gnu packages linux) linux-libre-version) (@@ (gnu packages linux) linux-libre-gnu-revision) (@@ (gnu packages linux) linux-libre-source) '("x86_64-linux") #:extra-version "macbook41" #:extra-options %macbook41-config-options))
No exemplo acima, %file-systems
é uma coleção de sinalizadores que
habilitam suporte a diferentes sistemas de arquivos, %efi-support
habilita suporte a EFI e %emulation
habilita uma máquina x86_64-linux
para atuar no modo de 32 bits também. O procedimento
default-extra-linux-options
é o definido acima, que teve que ser
usado para evitar a perda das opções de configuração padrão da palavra-chave
extra-options
.
Tudo isso parece viável, mas como saber quais módulos são necessários para
um sistema específico? Dois lugares que podem ser úteis para tentar
responder a esta pergunta são o
Gentoo Handbook e o documentação do próprio kernel. Pela documentação do kernel, parece que
make localmodconfig
é o comando que queremos.
Para realmente executar make localmodconfig
primeiro precisamos obter
e descompactar o código-fonte do kernel:
tar xf $(guix build linux-libre --source)
Uma vez dentro do diretório que contém o código-fonte, execute touch
.config
para criar um .config inicial e vazio para
começar. make localmodconfig
funciona vendo o que você já tem em
.config e informando o que está faltando. Se o arquivo estiver em
branco, você está perdendo tudo. O próximo passo é executar:
guix shell -D linux-libre -- make localmodconfig
e observe a saída. Observe que o arquivo .config ainda está vazio. A saída geralmente contém dois tipos de avisos. O primeiro começa com "WARNING" e pode ser ignorado no nosso caso. A segunda leitura:
module pcspkr did not have configs CONFIG_INPUT_PCSPKR
Para cada uma dessas linhas, copie a parte CONFIG_XXXX_XXXX
para
.config no diretório e anexe =m
, para que no final fique
assim:
CONFIG_INPUT_PCSPKR=m CONFIG_VIRTIO=m
Após copiar todas as opções de configuração, execute make
localmodconfig
novamente para ter certeza de que você não tem nenhuma saída
começando com “module”. Depois de todos esses módulos específicos da
máquina, restam mais alguns que também são
necessários. CONFIG_MODULES
é necessário para que você possa
construir e carregar módulos separadamente e não ter tudo embutido no
kernel. CONFIG_BLK_DEV_SD
é necessário para leitura de discos
rígidos. É possível que existam outros módulos dos quais você precisará.
Este post não pretende ser um guia para configurar seu próprio kernel, portanto, se você decidir construir um kernel personalizado, você terá que procurar outros guias para criar um kernel adequado às suas necessidades.
A segunda maneira de definir a configuração do kernel faz mais uso dos recursos do Guix e permite compartilhar segmentos de configuração entre diferentes kernels. Por exemplo, todas as máquinas que usam EFI para inicializar possuem vários sinalizadores de configuração EFI necessários. É provável que todos os kernels compartilhem uma lista de sistemas de arquivos para suporte. Ao usar variáveis, é mais fácil ver rapidamente quais recursos estão habilitados e garantir que você não tenha recursos em um kernel, mas ausentes em outro.
No entanto, não foi discutido o initrd do Guix e sua personalização. É provável que você precise modificar o initrd em uma máquina usando um kernel customizado, já que certos módulos que devem ser compilados podem não estar disponíveis para inclusão no initrd.
Próximo: API de imagem do sistema Guix, Anterior: Login automático em um TTY específico, Acima: Configuração do sistema [Conteúdo][Índice]