Table of Contents

В данной статье процесс компиляции и создания пакетов для OpenWRT. Он немного устарел (описан процесс для OpenWRT Backfire), но вцелом все должно быть актуально и для новых версий.

Получение исходников OpenWrt

Поскольку для сборки мы будем использовать OpenWrt Build System то первое что необходимо сделать это получить исходный код OpenWRT. Если он у вас уже есть можно переходить к следующему пункту. Я использую OpenWrt 10.03, codename Backfire.

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

Должен появится каталог openwrt. Перейдем в него:

cd openwrt

В этом каталоге есть 3 ключевые директории: - toolchain - target - package

Вкратце по этим директориям:

toolchain – В этой директории содержится компилятор, библиотеки а также основные утилиты необходимые для построения и сборки образа прошивки. После выполнения команды make toolchain/install появляется директория staging_dir которая и содержит скомпилированный и установленный toolchain.

target – имеет отношение к “встроенной” embedded платформе. Содержит файлы и патчи относящиеся к различным embedded платформам. Например каталог target/linux содержит патчи и конфиги ядра специфичные для каждой платформы, а в каталоге target/image описано как именно собирать образ прошивки для той или иной платформы.

package – каталог в котором содержатся исходники, патчи и конфиги всех пакетов которые можно собрать для OpenWRT. Собственно этот каталог и нужен нам для сборки собственных приложений.

Также стоит отметить что все необходимые исходники и дополнительные файлы в процессе сборки OpenWRT загружаемые из интернета и ложатся в каталог dl, а каталог build_dir это временный каталог для сборки.

Для дальнейших шагов необходимо выполнить:

Получим исходники всех необходимях для сборки пакетов

./scripts/feeds update -a && ./scripts/feeds install -a

Соберем tools и toolchain

make prereq && make tools/install && make toolchain/install

Кросскомпиляция

Кросскомпиляция позволяет получить из исходников исполняемый файл под нужную платформу.

Для того чтобы исходник компилировался под нужную нам платформу достаточно вставить в Makefile директивы с указанием правильно компилятора. Мануал Openwrt предписывает нам скомпилировать среду для разработки, затем в директории ./staging_dir/toolchain-…../bin/ найти компилятор под нужную платформу и указать на него в Makefile директивами CC и LD. Это можно сделать так:

PATH=$PATH:/home/mike/backfire/staging_dir/toolchain-mipsel_gcc-4.3.3+cs_uClibc-0.9.30.1/bin/
export PATH
STAGING_DIR=/home/mike/backfire/staging_dir
export STAGING_DIR

А в Makefile указать компилятор. Если export работает нормально, то указывать можно и без полных путей. У меня export тупил и я написал с полными путями:

CC = /home/mike/backfire/staging_dir/toolchain-mipsel_gcc-4.3.3+cs_uClibc-0.9.30.1/bin/mipsel-openwrt-linux-uclibc-gcc
LD = /home/mike/backfire/staging_dir/toolchain-mipsel_gcc-4.3.3+cs_uClibc-0.9.30.1/bin/mipsel-openwrt-linux-uclibc-ld
all: autosys

%.o: %.c
        $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -I. -Iinclude -o $@ $^
    
autosys: main.o
        $(CC) -o $@ $^ -L.

clean:
        rm -f *.o autosys

А дальше просто make и все…

Создание нового пакета

Итак нам нужен каталог package

cd package

Создадим в нем директорию simple и simple/src

mkdir simple
mkdir simple/src
cd simple/src

Добавление исходников

В каталог simple/src положим исходник нашего приложения. Создадим файл main.c в simple/src директории с текстом:

#include
int main(void)
{
	int i=0;
	while (i < 100) {
		printf(" Hello world %d \n",i);
		i++;
	}
	return 0;
}

Далее подготовим Makefile для компиляции main.c в каталоге simple/srс с таким содержимым (отступы делать табуляцией)

# build executable on typing make
all: simple

%.o: %.c
	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -I. -Iinclude -o $@ $^

simple: main.o
	$(CC) -o $@ $^ -L.

clean:
	rm -f *.o simple

Компилирование на локальной машине под host платформу

Все исходник готов. Можно проверить как он собирается и выполняется на локальной машине (обратите внимание это пока не кросс компиляция):

$ make
cc   -c -I. -Iinclude -o main.o main.c
cc -o simple main.o -L.
$ ./simple
Hello world 0
Hello world 1
...
Hello world 99

Исходник собрался под host платформу без проблем, перейдем к сборке под embedded платформу. Для этого вначале почистим исходники:

make clean

Подготовка к кросс компилированию средствами OpenWRT

Поднимемся в директорию package/simple:

cd ..

Создадим следующий Makefile:

#
# Top level makefile for simple application
#

include $(TOPDIR)/rules.mk

PKG_NAME:=simple
PKG_VERSION:=1.0.0
PKG_RELEASE:=1

include $(INCLUDE_DIR)/package.mk

define Package/simple
  SECTION:=utils
  CATEGORY:=Utilities
  TITLE:=simple -- prints simple 1 to 99
endef

define Build/Prepare
	mkdir -p $(PKG_BUILD_DIR)
	$(CP) ./src/* $(PKG_BUILD_DIR)
endef

define Build/Configure
endef

TARGET_CFLAGS += $(FPIC)

define Package/simple/install
	$(INSTALL_DIR) $(1)/bin
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/simple $(1)/bin/
endef

$(eval $(call BuildPackage,simple))

Как видно этот файл не очень сложный но необходимо знать значения следующих переменных:

PKG_NAME – Имя пакета, которое будет видно в menuconfig и ipkg/opkg PKG_VERSION – Версия пакета PKG_RELEASE – Версия Makefile этого пакета PKG_BUILD_DIR – Директория для компилирования пакета PKG_SOURCE – Имя файла оригинальных исходников

PKG_SOURCE_URLURL загрузки оригинальных исходников PKG_MD5SUM – MD5 – checksum для проверки загрузки PKG_CAT – Чем распаковывать исходники (zcat, bzcat, unzip)

Как видно не все из этих переменных обязательны. Наиболее важными секциями являются секции define Package/_name_ и define Package/_name_/install:

Package/_name_

Секция описывает пакет для menuconfig и ipkg/opkg.

SECTION – Тип пакета (на текущий момент не используется) CATEGORY – В каком меню должно находится приложение в menuconfig TITLE – Короткое описание пакета DESCRIPTION – Длинное описание пакета URLURL исходного приложения MAINTAINER – (не обязательно) Контактные данные дева DEPENDS – (не обязательно) Какие пакеты должны быть установлены до этого пакета.

Package/_name_/install

В этой секции должен быть описан список команд для копирования собранных исходников в пакет (пакет представлен в виде $(1) директории) Компилирование

Поднимемся в корневую директорию OpenWRT и запустим конфигуратор:

$ cd ..
$ make menuconfig

В конфигураторе ищем свое приложение и отмечаем его как <M> (не забывайте также в конфигураторе сделать базовые настройки, как например выбор платформы) :

Utilities  ---> <M> simple

Здесь следует отметить как происходит выбор компонент в конфигураторе:

<*> (по клавише y) этот пакет будет включен в образ прошивки
<M> (по клавише m) этот пакет будет собран в виде отдельного пакета но не включен в образ прошивки (для последующей установки пакета вручную)
< > (по клавише n) этот пакет не будет собран

Для кругового select также можно использовать пробел.

Собственно компилирование:

make V=99

После компилирования все прошивки и пакеты будут находится в каталоге bin. Т.к. я собирал OpenWRT под свой D-Link DIR-320 то пакеты у меня находятся в каталоге bin/brcm47xx/package. В этом каталоге содержится ваш собственный репозиторий. Установка пакета

Достаточно открыть этот каталог по http, и в конфигурационном файле ipkg/opkg вашей embedded системы прописать url к http серверу.

Обновляем список пакетов и устанавливаем пакет simple:

root@OpenWrt:~# opkg update
Downloading http://192.168.120.2/pkg/Packages.gz.
Inflating http://192.168.120.2/pkg/Packages.gz.
Updated list of available packages in /var/opkg-lists/packages.
root@OpenWrt:~# opkg install simple
Installing simple (1.0.0-1) to root...
Downloading http://192.168.120.2/pkg/simple_1.0.0-1_brcm47xx.ipk.
Configuring simple.

Проверим работу:

root@OpenWrt:~# simple
 Hello world 0
 Hello world 1
 Hello world 2
 Hello world 3
 Hello world 4
 ...
 Hello world 98
 Hello world 99

Собственно все, приложение скомпилировано и работает.