この章では、ターゲットボードで動作する新しくアプリケーションを作成する方法と、作成したアプリケーションをatmark-dist内に追加する方法を説明します。
Out of Treeコンパイルは、atmark-distに変更を加えることなく手軽に開発を行うことができる方法です。atmark-distのビルドシステムを使うため、複雑なMakefileを書く必要もありません。atmark-distのディレクトリ構造を木に見たて、そのディレクトリ外でコンパイルするためにこう呼ばれています。
ここでは実際にターゲットボード用の"Hello World"を作成します。
Out of Treeコンパイルではatmark-distに入っているビルドシステムやライブラリ群を使うために、一度ビルドされている atmark-distが必要です。まず、atmark-distがターゲットボード用にコンフィグかつビルドされていることを確認してください。
次に、開発するアプリケーション用のディレクトリをatmark-distのディレクトリ構造の外に作ってください。この中にはMakefile
と必要なCのソースコードやヘッダファイルが入ります。
[PC ~]$
ls
atmark-dist-[version]
[PC ~]$
mkdir hello
[PC ~]$
ls
hello atmark-dist-[version]
:
:
[PC ~]$
ls hello
Makefile hello.c
hello.c
は、図のようにどのCの教科書にでもでてくるような簡単なものです。
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello World\n");
return 0;
}
Makefile
は図のようなものを使用します。
# ROOTDIR=/usr/src/atmark-dist-[version]
ifndef ROOTDIR
ROOTDIR ?= ../atmark-dist-[version]
endif
ROMFSDIR = $(ROOTDIR)/romfs
ROMFSINST = romfs-inst.sh
PATH := $(PATH):$(ROOTDIR)/tools
UCLINUX_BUILD_USER = 1
include $(ROOTDIR)/.config
LIBCDIR = $(CONFIG_LIBCDIR)
include $(ROOTDIR)/config.arch
EXEC = hello
OBJS = hello.o
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
clean:
-rm -f $(EXEC) *.elf *.gdb *.o *~
romfs:
$(ROMFSINST) /bin/$(EXEC)
%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
このMakefile
は"Hello World"以外のアプリケーションを開発するときにもテンプレートとして使用することができます。環境に合わせて変更する点は以下の3つです。
|
ROOTDIRが指定されていない場合、現在のディレクトリと並列に atmark-dist ディレクトリがあると仮定します。他の場所にatmark-dist がある場合は、この行のコメントを外して適切なディレクトリ名に変更してください。
|
|
生成される実行ファイル名を指定します。ここでは、helloとします。
|
|
生成される実行ファイルが依存するオブジェクトファイルを指定します。ここでは hello.oを指定します。
|
Makefile
と hello.c
が用意できたら、hello
をビルドします。ビルドには makeコマンドを使用します。ビルドが完了すると実行ファイル hello
がディレクトリ内に生成されています。(uClinuxとLinuxでは、生成されるファイルが異なります。)
[PC ~/hello]$
make
:
:
[PC ~/hello]$
ls hello*
Makefile hello hello.c hello.o
[PC ~/hello]$
file hello*
hello: ELF 32-bit LSB executable, ARM, version 1 (ARM), for GNU/Linux 2.4.1, dynamically linked (uses shared libs), for GNU/Linux 2.4.1, not stripped
hello.c: ASCII C program text
hello.o: ELF 32-bit LSB relocatable, ARM, version 1 (ARM), not stripped
helloはELFフォーマットのARM用実行ファイルです。
実行ファイルを atmark-distの romfs
ディレクトリにインストールするために、make
コマンドで romfs
ターゲットを指定します。
[PC ~/hello]$
make romfs
romfs-inst.sh /bin/hello
[PC ~/hello]$
ls ../atmark-dist-[version]/romfs/bin/hello
hello
make romfs
の後 atmark-dist
のディレクトリに移動して、make image
を実行することで、hello
を含んだ ターゲットボード用のイメージファイルが image
ディレクトリに生成されます。
[PC ~/hello]$
cd ../atmark-dist-[version]
[PC ~/atmark-dist]$
make image
:
:
[PC ~/atmark-dist]$
ls images
image.bin linux.bin.gz romfs.image romfs.image.gz
image
ターゲットについては、「image」を参照してください。
実行ファイルが複数のソースコードに分割されている場合は、Makefile
を変更することで対応できます。ここでは、hello.c
とprint.c
から実行ファイルhello
を生成する場合を例に説明します。
[PC ~/hello]$
ls
Makefile hello.c print.c
hello.c
#include <stdio.h>
extern void print_hello(char *string);
int main(int argc, char *argv[])
{
print_hello("World");
return 0;
}
print.c
void print_hello(char *string)
{
printf("Hello %s\n", string);
}
Makefile
のOBJSにprint.o
を追加します。
# ROOTDIR=/usr/src/atmark-dist-[version]
ifndef ROOTDIR
ROOTDIR=../atmark-dist-[version]
endif
ROMFSDIR = $(ROOTDIR)/romfs
ROMFSINST = romfs-inst.sh
PATH := $(PATH):$(ROOTDIR)/tools
UCLINUX_BUILD_USER = 1
include $(ROOTDIR)/.config
LIBCDIR = $(CONFIG_LIBCDIR)
include $(ROOTDIR)/config.arch
EXEC = hello
OBJS = hello.o print.o <------------------
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
clean:
-rm -f $(EXEC) *.elf *.gdb *.o
romfs:
$(ROMFSINST) /bin/$(EXEC)
%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
[PC ~/hello]$
make
:
:
[PC ~/hello]$
ls
Makefile hello hello.c hello.o print.c print.o
スレッドを使うアプリケーションの場合は、スレッド用のライブラリをリンクする必要があります。Makefile
の一部を以下のように変更します。
# ROOTDIR=/usr/src/atmark-dist-[version]
ifndef ROOTDIR
ROOTDIR=../atmark-dist-[version]
endif
ROMFSDIR = $(ROOTDIR)/romfs
ROMFSINST = romfs-inst.sh
PATH := $(PATH):$(ROOTDIR)/tools
UCLINUX_BUILD_USER = 1
include $(ROOTDIR)/.config
LIBCDIR = $(CONFIG_LIBCDIR)
include $(ROOTDIR)/config.arch
EXEC = hello
OBJS = hello.o
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPTHREAD) $(LDLIBS)
clean:
-rm -f $(EXEC) *.elf *.gdb *.o
romfs:
$(ROMFSINST) /bin/$(EXEC)
%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
|
$(LIBPTHREAD)を追加する
|
組み込み機器の場合、プロダクト固有のアプリケーションは、必ずと言っていいほど存在すると思います。ここでは、プロダクト固有のアプリケーションをatmark-distに統合する方法を紹介します。
atmark-dist/vendors/$(CONFIG_VENDOR)/$(CONFIG_PRODUCT)
以下に、アプリケーション用のディレクトリを作成します。$(CONFIG_VENDOR)と$(CONFIG_PRODUCT)は、お使いのボードにあわせて変更してください。ここでは、ベンダーをAtmarkTechno、プロダクトをArmadillo-220.Base、そしてアプリケーションをhello
とします。
[PC ~]$
mkdir atmark-dist-[version]/vendors/AtmarkTechno/Armadillo-220.Base/hello
[PC ~]$
ls -d atmark-dist-[version]/vendors/AtmarkTechno/Armadillo-220.Base/hello
hello
Cのソースコードは前項で使った hello.c
を使用します。Makefile
は Out of Tree Compileで使用したものよりもシンプルになります。
EXEC = hello
OBJS = hello.o
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
clean:
-rm -f $(EXEC) *.elf *.gdb *.o
romfs:
$(ROMFSINST) /bin/$(EXEC)
%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
追加したアプリケーションをプロダクトMakefile
に追加します。プロダクトMakefile
には、SUBDIR_yと呼ばれる変数が用意されています。ここに、アプリケーションのディレクトリ名を追加します。
:
:
SUBDIR_y += hello
:
:
ビルド方法は「ビルド」と同じです。all、clean、romfsターゲットは、以下のように定義されているので、SUBDIR_yで指定したディレクトリすべてに対して、適切なコマンドを実行するようになっています。
all:
for i in $(SUBDIR_y) ; do $(MAKE) -C $$i || exit $? ; done
clean:
-for i in $(SUBDIR_y) ; do [ ! -d $$i ] || $(MAKE) -C $$i clean; done
romfs:
:
:
for i in $(SUBDIR_y) ; do $(MAKE) -C $$i romfs || exit $? ; done
最初はプロダクト固有のアプリケーションとして開発されたものでも、多くのプロダクトで使われるようになることがあります。そんな時は、アプリケーションをuser
ディレクトリに移動し、プロダクト間で共有することができます。
atmark-dist/user
以下に、アプリケーション用のディレクトリを作成します。ここでは、hello
とします。
[PC ~]$
mkdir atmark-dist-[version]/user/hello
[PC ~]$
ls -d atmark-dist-[version]/user/hello
hello
変更個所は、atmark-dist/config/config.in
と atmark-dist/user/Makefile
です。この例では、追加するアプリケーションをMiscellaneous Applicationに追加します。他にならってアルファベット順に並べます。
例10.1 atmark-dist/config/config.in
の変更点
--- config.in.orig 2007-09-14 22:10:20.000000000 +0900
+++ config.in 2007-09-26 16:24:21.000000000 +0900
@@ -719,6 +719,7 @@
fi
bool 'grep' CONFIG_USER_GREP_GREP
bool 'hd' CONFIG_USER_HD_HD
+bool 'hello' CONFIG_USER_HELLO_HELLO
bool 'lcd' CONFIG_USER_LCD_LCD
bool 'ledcon' CONFIG_USER_LEDCON_LEDCON
bool 'lilo' CONFIG_USER_LILO_LILO
例10.2 atmark-dist/user/Makefile
の変更点
--- Makefile.orig 2007-09-14 22:10:20.000000000 +0900
+++ Makefile 2007-09-26 16:21:04.000000000 +0900
@@ -131,6 +131,7 @@
dir_$(CONFIG_USER_GETTYD_GETTYD) += gettyd
dir_$(CONFIG_USER_GREP_GREP) += grep
dir_$(CONFIG_USER_HD_HD) += hd
+dir_$(CONFIG_USER_HELLO_HELLO) += hello
dir_$(CONFIG_USER_HOSTAP_HOSTAP) += hostap
dir_$(CONFIG_USER_HOSTAP_HOSTAP) += hostap/utils
dir_$(CONFIG_USER_HOSTAP_HOSTAPD) += hostap/hostapd
make menuconfigなどで追加したアプリケーションがMiscellaneous Applicationセクションに表示されるか確認してください。表示されたhelloを選択し、設定を保存します。
In Treeコンパイルのビルド方法は「ビルド」と同じです。生成されたイメージファイルをターゲットボードに転送し、helloが動作するか確認してください。
今回使用したコンフィグ名はCONFIG_USER_HELLO_HELLO です。
atmark-distではユーザーランドアプリケーションの選択にはディレクトリ名とアプリケーション名を使う決まりになっています。
すべてのコンフィグオプションは、CONFIG_からはじめる
atmark-dist/user以下のものは、CONFIG_USER_からはじめる
ディレクトリ名がhelloなので、CONFIG_USER_HELLO_からはじめる
最後にアプリケーション名をつけて CONFIG_USER_HELLO_HELLOとなる
ひとつのディレクトリで複数のアプリケーションを開発する方法を紹介します。In Treeコンパイルに限った話ではないので、Out of Treeコンパイルでも可能です。
atmark-dist/user/hello
のディレクトリに hello2
という名前のアプリケーションを追加します。コンフィグの文字列は、CONFIG_USER_HELLO_HELLO2とします。
まずは、atmark-dist/config/config.in
と、atmark-dist/user/Makefile
の変更点です。
例10.3 atmark-dist/config/config.in
の変更点(複数アプリケーション)
--- config.in.orig 2007-09-14 22:10:20.000000000 +0900
+++ config.in 2007-09-26 16:30:48.000000000 +0900
@@ -719,6 +719,8 @@
fi
bool 'grep' CONFIG_USER_GREP_GREP
bool 'hd' CONFIG_USER_HD_HD
+bool 'hello' CONFIG_USER_HELLO_HELLO
+bool 'hello2' CONFIG_USER_HELLO_HELLO2
bool 'lcd' CONFIG_USER_LCD_LCD
bool 'ledcon' CONFIG_USER_LEDCON_LEDCON
bool 'lilo' CONFIG_USER_LILO_LILO
例10.4 atmark-dist/user/Makefile
の変更点(複数アプリケーション)
--- Makefile.orig 2007-09-14 22:10:20.000000000 +0900
+++ Makefile 2007-09-26 16:32:59.000000000 +0900
@@ -131,6 +131,8 @@
dir_$(CONFIG_USER_GETTYD_GETTYD) += gettyd
dir_$(CONFIG_USER_GREP_GREP) += grep
dir_$(CONFIG_USER_HD_HD) += hd
+dir_$(CONFIG_USER_HELLO_HELLO) += hello
+dir_$(CONFIG_USER_HELLO_HELLO2) += hello
dir_$(CONFIG_USER_HOSTAP_HOSTAP) += hostap
dir_$(CONFIG_USER_HOSTAP_HOSTAP) += hostap/utils
dir_$(CONFIG_USER_HOSTAP_HOSTAPD) += hostap/hostapd
Makefile
では、左側にコンフィグオプションを、+=の右側にはディレクトリ名を書きます。このため、hello
もhello2
も指定するディレクトリ名は同じhello
になります。
続いて、atmark-dist/user/hello/Makefile
です。今回はアプリケーション名を変数に入れずに直接扱ってみます。
例10.5 Makefile
(複数アプリケーション)
EXEC_HELLO = hello
EXEC_HELLO2 = hello2
OBJS_HELLO = hello.o
OBJS_HELLO2 = hello2.o
all: $(EXEC_HELLO) $(EXEC_HELLO2)
hello: $(OBJS_HELLO)
$(CC) $(LDFLAGS) -o $@ $(OBJS_HELLO) $(LDLIBS)
hello2: $(OBJS_HELLO2)
$(CC) $(LDFLAGS) -o $@ $(OBJS_HELLO2) $(LDLIBS)
clean:
-rm -f $(EXEC_HELLO) $(EXEC_HELLO2) *.elf *.gdb *.o
romfs:
$(ROMFSINST) -e CONFIG_USER_HELLO_HELLO /bin/hello
$(ROMFSINST) -e CONFIG_USER_HELLO_HELLO2 /bin/hello2
%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
romfs
ターゲットで、"-e CONFIG_USER_HELLO"を使っている点に注目してください。
atmark-dist
のビルドシステムは、hello
ディレクトリにあるアプリケーションがひとつでも選択されると、ディレクトリ内すべてのアプリケーションをビルドするように指定します。このため、romfsターゲットで条件によってインストールするアプリケーションを選択しなければなりません。上記のように、コンフィグオプションによる条件分岐を行い、インストールするアプリケーションを決定します。
romfsinst.sh
の詳しい説明は、9章romfsインストールツールの使い方を参照してください。