OpenWRT cross compilation

En esta receta se describe como instalar un firmware de OpenWRT a una placa ubiquity routerstation, y a compilar/instalar nuestros programas: cross-compilation (compilación cruzada).

1/ Instalamos el firmware.

Descargamos el firmware (backfire 10.03) de [2], el archivo es el siguiente:
openwrt-ar71xx-ubnt-rs-jffs2-factory.bin
Subiremos el firmware mediante atftp , en [1] hay una documentación detallada:

atftp
connect 192.168.1.1
mode octet
trace
timeout 1
put openwrt-xxx-x.x-xxx.bin

Una vez finalizado, creamos una clave de root (para acceder por ssh) y actualizamos el sistema:

telnet 192.168.1.1
passwd
exit
ssh root@192.168.1.1
opkg update && opkg upgrade

2/ Instalación del SDK:

hacemos un checkout del svn:

svn co svn://svn.openwrt.org/openwrt/branches/backfire

entramos en la carpeta que contiene la copia local, y ejecutamos:

make menuconfig

marcamos (M):

* target profile: ubiquity routerstation
* target system: atheros AR71xx
* build sdk
* build the openWRT based toolchain
* image configuration
* en libraries: libpcap (si marcamos ademas: ncurses, zlib, readline nos ahorrará trabajo, marcaremos todas las dependencias de paquetes que vamos a compilar despues..)
guardamos cambios.

ejecutamos make

tarda bastante rato..

al finalizar tendremos el SDK creado en:

./build_dir/target-mips_r2_uClibc-0.9.30.1/OpenWrt-SDK-ar71xx-for-Linux-i686-gcc-4.3.3+cs_uClibc-0.9.30.1

3/ Copia local del repositorio de paquetes:

svn co svn://svn.openwrt.org/openwrt/packages

Tendremos carpetas con los paquetes openwrt. Cada uno dispone de un Makefile y de una carpeta de parches (opcional).

4/ Cross compilation:

Supongamos que hemos hecho un programa llamado “gorosito”[3] que lee su configuración de un archivo xml ( usando libxml2) y realiza consultas sobre una base de datos mysql ( libmysqlclient)

instalamos ambas librerias en nuestro PC, apt-get install libxml2, urpmi libxml2 …

compilamos libxml2 (libs/libxml2) y libmysqlclient(libs/mysql) para openwrt. Para ello copiamos las 2 carpetas de la copia local de paquetes en la carpeta packages de dentro del sdk.

Ejecutamos make dentro del sdk. Al finalizar tendremos:

./bin/ar71xx/packages/ ————-> aqui tendremos los dos paquetes ipk listos para instalar en la placa.

./staging_dir/target-mips_r2_uClibc-0.9.30.1/usr/include/ ————-> cabeceras .h de las librerias que acabamos de compilar

./staging_dir/target-mips_r2_uClibc-0.9.30.1/usr/lib/ ———-> las librerias

Ahora compilaremos nuestro programa, dentro de la carpeta packages del sdk:

mkdir -p gorosito/patches
mkdir -p gorosito/src

En src copiamos los fuentes de nuestro programa en c (.c y .h) y creamos un Makefile:

CFLAGS_= $(CFLAGS) -c -I/usr/include/libxml2 -I/usr/include/mysql
LDFLAGS_= $(LDFLAGS)
SOURCES=airexml.c main.c basedatos.c
OBJECTS=$(SOURCES:.c=.o)
EXECUTABLE=gorosito

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS_) $(OBJECTS) -o $@

.c.o:
$(CC) $(CFLAGS_) $< -o $@

En este Makefile lo importante son las CFLAGS_ que apuntan a las cabeceras de las librerías en nuestro ordenador.

Dentro de ./gorosito/ creamos otro Makefile:

include $(TOPDIR)/rules.mk

# Name and release number of this package
PKG_NAME:=gorosito
PKG_RELEASE:=1

# This specifies the directory where we’re going to build the program.
# The root build directory, $(BUILD_DIR), is by default the build_mipsel
# directory in your OpenWrt SDK directory
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)

include $(INCLUDE_DIR)/package.mk

# Specify package information for this program.
# The variables defined here should be self explanatory.
define Package/gorosito
SECTION:=utils
CATEGORY:=Utilities
DEPENDS:=+libxml2 +libmysqlclient
TITLE:= Gorosito
endef
define Package/gorosito/description
gorosito rocks
endef

# Specify what needs to be done to prepare for building the package.
# In our case, we need to copy the source files to the build directory.
# This is NOT the default. The default uses the PKG_SOURCE_URL and the
# PKG_SOURCE which is not defined here to download the source from the web.
# In order to just build a simple program that we have just written, it is
# much easier to do it this way.
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
$(TARGET_CONFIGURE_OPTS) \
CFLAGS=”$(TARGET_CFLAGS) -I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/usr/include/libxml2 -I$(STAGING_DIR)/usr/include/mysql” \
LDFLAGS=”$(TARGET_LDFLAGS) -L$(STAGING_DIR)/usr/lib/libxml2 -lxml2 -lz -L$(STAGING_DIR)/usr/lib/mysql -L$(STAGING_DIR)/usr/lib -lmysqlclient”
endef
# Specify where and how to install the program. Since we only have one file,
# the gorosito executable, install it by copying it to the /bin directory on
# the router. The $(1) variable represents the root directory on the router running
# OpenWrt. The $(INSTALL_DIR) variable contains a command to prepare the install
# directory if it does not already exist. Likewise $(INSTALL_BIN) contains the
# command to copy the binary file from its current location (in our case the build
# directory) to the install directory.
define Package/gorosito/install
$(INSTALL_DIR) $(1)/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/gorosito $(1)/bin/
endef
# This line executes the necessary commands to compile our program.
# The above define directives specify all the information needed, but this
# line calls BuildPackage which in turn actually uses this information to
# build a package.
$(eval $(call BuildPackage,gorosito))

En este Makefile lo importante son las dependencias y los CFLAGS y LDFLAGS del bloque Compile.

Una vez hecho esto, dentro del sdk ejecutamos: make V=99.

Al finalizar tendremos el paquete listo: ./bin/ar71xx/packages/gorosito_1_ar71xx.ipk

Por último lo instalamos en la placa:

scp ./bin/ar71xx/packages/gorosito_1_ar71xx.ipk root@192.168.1.1:
ssh root@192.168.1.1
opkg install gorosito_1_ar71xx.ipk
gorosito

Una documentación más detallada sobre esto puede encontrarse en [4]. He preferido redactar una receta por los problemas que me fui encontrando al aplicar [4] con la version backfire.

[1] http://wiki.openwrt.org/doc/howto/tftp
[2] http://downloads.openwrt.org/backfire/10.03/ar71xx/
[3] http://www.google.es/images?hl=es&q=gorosito
[4] http://wiki.openwrt.org/doc/howto/creatingpackages

Leave a Reply