RG350 Docker Buildroot
La distribución del sistema operativo OpenDingux de la RG350 está basado en Buildroot. Para compilarlo se recomienda utilizar una instalación Debian Stretch o Buster (según la versión de Buildroot en que esté basado). Si no es el sistema que tenemos en nuestra máquina (bien por usar Windows o Mac o por tener otra distribución Linux), y no queremos o podemos instalar una pesada máquina virtual para disponer del entorno adecuado, existe la posibilidad de encapsularlo en un contenedor Docker.
El procedimiento que se muestra a continuación está hecho sobre un Linux Ubuntu 20.04, pero no debería ser complicado de adaptar para poder realizarse sobre Windows o Mac.
Elección de distribución Buildroot¶
Existen varias distribuciones Buildroot para RG350. A continuación se listan algunas:
Distribución | Versión Buildroot | Entorno de compilación | Observaciones |
---|---|---|---|
GCW0 | Éste realmente no es para la RG350 sino para la GCWZero, pero se incluye por ser el origen del resto | ||
OpenDingux | Tampoco tiene una configuración específica para la RG350 | ||
Tonyjih | 2014.08 | Debian Stretch; Docker eduardofilo/rg350_buildroot | Buildroot en el que se basan muchos |
Ninoh-FOX | Debian Stretch | ROGUE CFW | |
gokr | |||
soarquin | CentOS 7; Docker soarqin/rg350_toolchain | ||
od-contrib | 2020.05 | Debian Buster; Docker eduardofilo/rg350_buster_buildroot | Basado en un Buildroot moderno |
glebm |
Vamos a empezar bajando una de estas distribuciones Buildroot de RG350 a un directorio de nuestra máquina (la que actuará de host para Docker). Es habitual utilizar un directorio git
en el home del usuario donde descargar los repositorios y nosotros seguiremos esta costumbre. Más adelante, al arrancar el contenedor, indicaremos ese directorio como volumen para conectar el sistema de archivos de nuestra máquina (host) con el contenedor. Así conseguimos que nuestra máquina (host) sólo sirva de almacén de las fuentes y los binarios resultantes, utilizando Docker para encapsular las dependencias que tiene la versión de Buildroot que vamos a utilizar que son muy numerosas y con frecuencia no coinciden con lo que nuestro sistema tiene instalado.
Por ejemplo vamos a utilizar la distribución de Tonyjih. Bajamos pues el repositorio en nuestra máquina. Con los siguientes comandos quedará en ~/git/RG350_buildroot
:
$ cd ~/git
$ git clone https://github.com/tonyjih/RG350_buildroot.git
Procedimiento para crear el contenedor¶
Veíamos en la tabla anterior que podemos compilar la distribución que hemos elegido para ilustrar el artículo (la de Tonyjih) con la imagen Docker eduardofilo/rg350_buildroot. A continuación vamos a ver los pasos para descargar y ejecutar esta imagen. Los primeros pasos son una receta rápida para instalar Docker en nuestro sistema si no contáramos ya con él, pero es mejor seguir una de las muchas guías que se pueden encontrar (por ejemplo para Ubuntu).
-
Instalar Docker en máquina host:
$ sudo apt install docker.io $ sudo groupadd docker $ sudo usermod -aG docker $USER $ sudo systemctl enable docker $ sudo systemctl start docker
-
Arrancar contenedor pasando el directorio
~/git
como volumen:$ docker run -it -v ~/git:/root/git --name RG350_buildroot eduardofilo/rg350_buildroot
Si en lugar de utilizar la versión compilada de la imagen subida al Docker Hub queremos construirla en local (por si quisiéramos hacer alguna modificación en el Dockerfile), intercalaríamos los siguientes comandos entre los pasos 1 y 2 anteriores:
$ cd ~/git
$ git clone https://github.com/eduardofilo/RG350_buildroot_docker.git
$ cd ~/git/RG350_buildroot_docker
$ docker build -t eduardofilo/rg350_buildroot .
Tras ejecutar el paso 2 debería quedar un prompt ejecutándose desde el entorno Debian dentro del contenedor. Como hemos conectado el directorio /root/git
del contenedor con el directorio ~/git
de nuestra máquina, cualquier cosa que queramos modificar o recoger al final de la compilación, la podremos localizar desde un explorador de archivos de nuestra máquina. Si en algún momento perdiéramos de vista la terminal ejecutándose en el entorno del contenedor, podremos recuperarla ejecutando:
$ docker exec -it RG350_buildroot /bin/bash
Si el comando anterior devuelve un error indicando que el contenedor está parado, podemos arrancarlo antes ejecutando la orden:
$ docker start RG350_buildroot
Operación general de Buildroot¶
Una vez que tenemos en marcha y el contenedor y nos hemos conectado con él, ya podemos empezar a trabajar con Buildroot. Esta distribución tiene su propia estructura y formas de operación. Vamos a empezar describiendo por encima el entorno y algunas operaciones habituales o interesantes.
Buildroot se puede describir de forma resumida como un toolchain de compilación cruzada unido a un gran número de paquetes (siendo uno de ellos el kernel Linux) que en conjunto pueden constituir un sistema Linux completo, habitualmente para un sistema embebido. La lista de paquetes que contiene Buildroot podemos encontrarla en el directorio package.
Luego, existen una serie de configuraciones predefinidas para placas conocidas. Las podemos encontrar en el directorio configs. Una de las primeras cosas que haremos más adelante es cargar la configuración para RG350 (fichero rg350_defconfig). Esta configuración se basa en la estructura oficial de Buildroot que es genérica para sistemas embebidos Linux. Si en nuestro sistema deseamos alguna característica especial o parche sobre los paquetes estándar que Buildroot ofrece, tenemos otro mecanismo, los ficheros que encontraremos en el directorio board/<fabricante>/<placa>
. En el caso de RG350 el nombre del fabricante elegido es opendingux
y el nombre de la placa gcw0
. Así pues en el directorio board/opendingux/gcw0
podemos encontrar por ejemplo los scripts para generar una imagen válida para la consola.
Nota
A partir de este punto veremos que las líneas de terminal están precedidas por #
y no por $
como antes porque se refieren al terminal dentro del contenedor Docker, que se ejecuta con el usuario root del mismo.
Antes de empezar cargamos la configuración para RG350 de las múltiples que trae Buildroot de serie:
# cd ~/git/RG350_buildroot
# make rg350_defconfig BR2_EXTERNAL=board/opendingux
Si ahora queremos repasar o cambiar algo de esta configuración lo haremos por medio de una herramienta similar a la que se utiliza para configurar un kernel Linux antes de compilarlo. Para ello utilizaremos uno de los dos comandos make
siguientes (sólo uno):
# cd ~/git/RG350_buildroot
# make menuconfig
# make nconfig
Antes de empezar a compilar cosas vamos a definir la siguiente variable de entorno que permitirá la compilación en paralelo:
# export BR2_JLEVEL=0
A continuación describimos algunas operaciones que podemos realizar:
Comando | Efecto |
---|---|
make clean |
Borra todos los ficheros generados en la compilación |
make toolchain |
Genera el toolchain de compilación cruzada. El resultado queda en el directorio ~/git/RG350_buildroot/output/host/usr/bin ; tarda 1h50m en un Intel i3-4005U y genera unos 3GBs de archivos |
make <paquete> |
Compila el paquete (de la lista de paquetes de la distribución) |
make <paquete>-rebuild |
Fuerza la recompilación del paquete |
make <paquete>-reconfigure |
Fuerza la reconfiguración del paquete |
make <paquete>-graph-depends |
Genera un gráfico del árbol de dependencias del paquete |
make all |
Compila la distribución completa |
Operación particular de la distribución Buildroot para RG350¶
Una vez que tenemos preparado el entorno podremos realizar las tareas y compilaciones previstas en el mismo. Por ejemplo en el entorno preparado por Tonyjih vemos que podemos realizar las siguientes operaciones:
-
Si se quiere que la imagen incluya emuladores y aplicaciones, ejecutar antes lo siguiente (sólo es necesario hacerlo una vez):
# cd ~/git/RG350_buildroot # board/opendingux/gcw0/download_local_pack.sh
-
Compilación de imagen para flashear en SD (el fichero con la imagen resultante queda en
~/git/RG350_buildroot/output/images/od-imager/images/sd_image.bin
; tarda 6h en un Intel i3-4005U y genera unos 9GBs de archivos):# cd ~/git/RG350_buildroot # board/opendingux/gcw0/make_initial_image.sh
-
Generación de un OPK update para ejecutarse directamente sobre el sistema anterior (el fichero con el OPK resultante queda en
~/git/RG350_buildroot/output/images/rg350-update-<fecha>.opk
):# cd ~/git/RG350_buildroot # board/opendingux/gcw0/make_upgrade.sh
Hay un problema con el script make_initial_image.sh
y es que internamente ejecuta make rg350_defconfig BR2_EXTERNAL=board/opendingux
lo que hace que si hemos hecho make menuconfig
se pierdan los cambios realizados ya que se vuelve a cargar el rg350_defconfig
que hay en config
. Tenemos varias opciones para evitar este problema:
- Editar manualmente el fichero rg350_defconfig.
- Retirar la llamada a
make rg350_defconfig BR2_EXTERNAL=board/opendingux
dentro del scriptmake_initial_image.sh
. - Ejecutar
make BR2_DEFCONFIG=configs/rg350_defconfig savedefconfig
tras elmake menuconfig
para regenerar el ficheroconfigs/rg350_defconfig
con la nueva configuración.
Compilación de distribución od-contrib¶
Existe una distribución Buildroot bastante moderna (basada en la versión 2020.05), que por tanto ofrece una versión mucho más actual de los paquetes que constituyen la distribución (no así el Kernel Linux que se mantiene en la versión 3.12). El procedimiento de compilación es muy similar al de la distribución de Tonyjih ilustrada antes. Vamos a mostrar el paso a paso sin dar explicaciones (sirven las mismas que antes) para compilar esta versión:
-
En máquina host:
$ cd ~/git $ git clone https://github.com/od-contrib/buildroot-rg350-old-kernel.git $ docker run -it -v ~/git:/root/git --name RG350_buster_buildroot eduardofilo/rg350_buster_buildroot
-
En contenedor:
# cd ~/git/buildroot-rg350-old-kernel # make rg350_defconfig BR2_EXTERNAL=board/opendingux # make menuconfig # export BR2_JLEVEL=0 # make toolchain # board/opendingux/gcw0/make_initial_image.sh rg350
El script make_initial_image.sh
tiene el mismo problema que comentábamos al final del apartado anterior con la distribución Tonyjih. Además falla por tener un patrón de target doble:
# cd ~/git/buildroot-rg350-old-kernel
# make rg350_defconfig BR2_EXTERNAL=board/opendingux:opks
Makefile:184: *** multiple target patterns. Stop.
La solución consiste en retirar el :opks
del final de la llamada anterior que hay en la linea 18 del script make_initial_image.sh
.
Tras solucionar esos problemas y ejecutar todo lo anterior, encontraremos la imagen completa compilada en ~/git/buildroot-rg350-old-kernel/output/images/od-imager/images/sd_image.bin
.
Nota
A la hora de compilar esta distribución Buildroot, no estaba disponible el paquete libpng14
. La URL principal de descarga producía timeout en la conexión y las secundarias no existían. La solución fue bajar el paquete por nuestra cuenta, colocarlo en el directorio ~/git/buildroot-rg350-old-kernel/dl/libpng14
y volver a compilar. El paquete se puede encontrar por ejemplo aquí.
Comandos para gestionar contenedores¶
Por último se comentan a continuación a modo de cheatsheet unos pocos comandos útiles para gestionar el contenedor que acabamos de crear:
Comando | Efecto |
---|---|
docker container ls -a |
Listar contenedores. Para averiguar hash por ejemplo. |
docker container start <hash> |
Arrancar contenedor. |
docker exec -it <hash> /bin/bash |
Obtener prompt bash en contenedor. |
docker container stop <hash> |
Detener contenedor. |
docker container rm <hash> |
Borrar contenedor. |