
Buildroot è un tool che permette di costruirci una cross-compiler toolchain e un root filesystem per il nostro target in modo più efficiente e veloce. I suoi usi sono rivolti principalmente verso il settore embedded.
Buildroot è una collezione di makefiles e patches ed è largamente utilizzato per applicazioni che richiedono piccoli sistemi o sistemi dedicati. Le applicazioni dedicate, di solito, non utilizzano la famiglia x86, ma più spesso microprocessori come PowerPc, MIPS o ARM e incontrano maggiormente il gradimento dei tecnici. Se pensiamo di utilizzare Buildroot allora molto probabilmente quello che vogliamo è uno strumento che permette la creazione, in un modo abbastanza semplice, di un cross-compilatore con tutti le utilities a corredo. Questa proposta tecnica utilizza la mClibc, www.uclibc.org, una piccola libreria per lo standard C. Non solo, Buildroot è largamente utilizzato per costruire un root filesystem. Una cross toolchain è un insieme di tools utilizzati per la compilazione di codice sorgente, per esempio, un compilatore (gcc, nella distribuzione gnu), utilities per il trattamento dei files binari, assemblatori e linker (binutils). Senza dubbio, già utilizziamo un ambiente di questo tipo. Se il nostro compilatore non genera codice binario di un’altra macchina, allora diremo che il compilatore che stiamo utilizzando è di tipo nativo. Se, invece, produce codice binario non compatibile con la macchina host, allora l’ambiente è di tipo cross. Con host system indichiamo la macchina su cui viene compilata la nostra applicazione. Con la diffusione della tecnologia GNU, e grazie anche a Linux, sempre più sono utilizzate soluzioni cross non commerciali. Se utilizziamo una soluzione commerciale allora certamente possiamo fare a meno di Buildroot, questa tecnologia ha la sua importanza solo se utilizziamo una soluzione open, magari GNU: in questo caso si sfruttano tutti i vantaggi del tool in fatto di generazione dell’ambiente cross.
UTILIZZIAMO BUILDROOT
Buildroot è in sostanza un insieme di makefile per caricare il software, configurarlo e compilarlo con le opzioni corrette. La prima cosa da fare è di procurarsi una copia di Buildroot: lo possiamo trovare sul sito buildroot.ulibc.org/download, e se siamo sotto Linux non è necessario avere l’account di amministratore, ma basta essere un normale user. Dopo averlo prelevato dal sito e scompattato, occorre mettere in esecuzione l’utility di configurazione, infatti dalla shell:
$ make menuconfig
Per una rapida guida sulla procedura di configurazione è consigliabile leggere la documentazione associata, almeno così sarà possibile impostarlo con i valori opportuni. Al termine del comando viene generato un file con estensione .config. Al termine del processo di configurazione utilizziamo make per compilare e configurare tutto l’ambiente che abbiamo precedentemente selezionato e impostato. Quindi da shell:
$ make
Con make si produce la configurazione e la compilazione di tutti i tools selezionati, compreso un target filesystem. Questo target filesystem sarà identificato secondo questo nome:
root_fs_ARCH.EXT
dove ARCH è l’architettura che abbiamo selezionato e EXT dipende dal tipo del target filesystem selezionato precedentemente nel campo Target options nel tool di configurazione. Con Buildroot è necessario predisporre e configurare una serie di variabili d’ambiente, queste variabili saranno poi utilizzate dal comando make. Le variabili d’ambiente sono:
- HOSTCXX
- HOSTCC
- UCIBC_CONFIG_FILE=<path/to/.config>
- BUSYBOX_CONFIG_FILE=path/to/.config
Un esempio dell’uso del file di configurazione può essere trovato nella cartella nella vostra $HOME:
$ make UCLIBC_CONFIG_FILE=
=uClibc.configBUSYBOX_CONFIG_FILE=
=$HOME/bb.config
In Buildroot è possibile modificare, secondo le proprie esigenze, il target filesystem ottenuto o la uClibc. Se, infatti, volessimo modificare il target file system dovremmo procedere in questo modo:
- modificare direttamente il target filesystem e, successivamente, ricostruire la sua immagine in memoria. Questo target filesystem è disponibile in build_ARCH/root/, è possibile apportarvi i propri cambiamenti in questa cartella e poi fare di nuovo il make. Questo metodo ha una controindicazione, se apportiamo le modifiche e rifaciamo il builder di tutto, toolchain e tools, le modifiche andrebbero perse.
- apporre le modifiche sotto target/generic/target_skeleton/. In questo modo dobbiamo rinunciare al concetto di gerarchia di un file system poiché è stato creato durante il processo di compilazione. In questo metodo i cambiamenti permangono anche se decidiamo di fare il rebuild di tutto, cross-compiler toolchain e tools.
È possible inserire nella distribuzione di buildroot una propria applicazione. In questo caso occorre assolvere i seguenti passi:
- Occorre creare una cartella sotto package per la vostra applicazione.
- Creare un file chiamato config.in. Questo file deve contenere la vostra parte di configurazione, il listato 2 ci mostra un esempio minimo, “foo” identifica la nostra applicazione.
- A questo punto dobbiamo creare un file con estensione .mk: un makefile per l’appunto. Questo file deve contenere le regole per definire il caricamento dal sito, configurazione, compilazione e l’installazione del software. Sul sito di Buildroot è possibile vedere come costruirsi questo file.
In ogni caso, il listato 1 contiene il makefile d’esempio.
ESEMPIO_VERSION:=1.0 ESEMPIO_SOURCE:=ESEMPIO-$(ESEMPIO_VERSION).tar.gz ESEMPIO_SITE:=http://www.esempio.org/downloads ESEMPIO_DIR:=$(BUILD_DIR)/ESEMPIO-$(ESEMPIO_VERSION) ESEMPIO_BINARY:=ESEMPIO ESEMPIO_TARGET_BINARY:=usr/bin/ESEMPIO $(DL_DIR)/$(ESEMPIO_SOURCE): $(WGET) -P $(DL_DIR) $(ESEMPIO_SITE)/$(ESEMPIO_SOURCE) $(ESEMPIO_DIR)/.source: $(DL_DIR)/$(ESEMPIO_SOURCE) $(ZCAT) $(DL_DIR)/$(ESEMPIO_SOURCE) | tar -C $(BUILD_DIR) $(TAR_OPTIONS) - touch $@ $(ESEMPIO_DIR)/.configured: $(ESEMPIO_DIR)/.source (cd $(ESEMPIO_DIR); rm -rf config.cache ; \ $(TARGET_CONFIGURE_OPTS) \ CFLAGS=”$(TARGET_CFLAGS)“ \ ./configure \ —target=$(GNU_TARGET_NAME) \ —host=$(GNU_TARGET_NAME) \ —build=$(GNU_HOST_NAME) \ —prefix=/usr \ —sysconfdir=/etc \ ); touch $@ $(ESEMPIO_DIR)/$(ESEMPIO_BINARY): $(ESEMPIO_DIR)/.configured $(MAKE) CC=$(TARGET_CC) -C $(ESEMPIO_DIR) $(TARGET_DIR)/$(ESEMPIO_TARGET_BINARY): $(ESEMPIO_DIR)/$(ESEMPIO_BINARY) $(MAKE) prefix=$(TARGET_DIR)/usr -C $(ESEMPIO_DIR) install rm -Rf $(TARGET_DIR)/usr/man esempio: uclibc ncurses $(TARGET_DIR)/$(ESEMPIO_TARGET_BINARY) esempio-source: $(DL_DIR)/$(ESEMPIO_SOURCE) esempio-clean: $(MAKE) prefix=$(TARGET_DIR)/usr -C $(ESEMPIO_DIR) uninstall -$(MAKE) -C $(ESEMPIO_DIR) clean esempio-dirclean: rm -rf $(ESEMPIO_DIR) # Toplevel Makefile options # ifeq ($(strip $(BR2_PACKAGE_ESEMPIO)),y) TARGETS+=esempio endif
Listato 1 |
config BR2_PACKAGE_FOO bool “foo” default n help Possibile commento http://foosoftware.org/foo/
Listato 2 |
STRUTTURA DI BUILDROOT
Abbiamo scritto che buildroot è un insieme di makefiles, in buildroot questi script sono divisi in tre sezioni:
- Package - Questa cartella contiene i makefiles e tutti i file associati che buildroot utilizza per la sua procedura di buiding del target filesystem.
- Toolchain - Questa, invece, contiene i files per la parte della toolchain di compilazione
- Target - Contiene i makefiles e i file associati per la generazione dell’immagine del target filesystem. I filesystem supportati sono: ext2, jffs2, cramfs e squashfs. Per ognuno di questi ci sono delle sotto-cartelle che contengono i files necessari.
In ogni cartella ci sono almeno due files:
- something.mk, è il makefiles utilizzato per il downloads, configurazione, compilazione e per l’installazione del software.
- Config.in, questo descrive le opzioni del software corrente.

Articolo molto interessante. E’ previsto un seguito oppure l’argomento BuildRoot termina così?
Per adesso termina così. Ma se ci sono suggerimenti per approfondimenti particolari possiamo analizzare la cosa.
Grazie per la risposta, Maurizio. BuildRoot è sicuramente un approccio interessante alla creazione di un filesystem Linux partendo da scratch. Potrebbe magari essere interessante vederne l’aaplicazione su una board tipo il Raspberry Pi o similare.
In passato c’è stata una serie di articoli su come costruire un file system con Buildroot per Raspberry.
https://it.emcelettronica.com/embedded-gnulinux-partendo-da-zero-test-sulla-raspberry-pi
BuildRoot e’ ed e’ stato sicuramente una pietra miliare per costruire distro custom, o per basare alcune delle distro che poi si sono affermate. In passato ho lavorato customizzando una distro per una ditta, usando OpenEmbedded:
https://www.openembedded.org/wiki/Main_Page
Molto bello, complesso e ampiamente configurabile. Una delle piu’ utlizzate attualmente e’ Yocto:
https://www.yoctoproject.org/
Ma BuildRoot rimane sempre nel cuore 🙂