第10章 新規アプリケーションの追加方法

この章では、ターゲットボードで動作する新しくアプリケーションを作成する方法と、作成したアプリケーションをatmark-dist内に追加する方法を説明します。

10.1. Out of Treeコンパイル

Out of Treeコンパイルは、atmark-distに変更を加えることなく手軽に開発を行うことができる方法です。atmark-distのビルドシステムを使うため、複雑なMakefileを書く必要もありません。atmark-distのディレクトリ構造を木に見たて、そのディレクトリ外でコンパイルするためにこう呼ばれています。

ここでは実際にターゲットボード用の"Hello World"を作成します。

10.1.1. 準備

Out of Treeコンパイルではatmark-distに入っているビルドシステムやライブラリ群を使うために、一度ビルドされている atmark-distが必要です。まず、atmark-distがターゲットボード用にコンフィグかつビルドされていることを確認してください。

10.1.2. ソースコードの用意

次に、開発するアプリケーション用のディレクトリを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]           1
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                                       2
OBJS = hello.o                                     3


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つです。

1

ROOTDIRが指定されていない場合、現在のディレクトリと並列に atmark-distディレクトリがあると仮定します。他の場所にatmark-distがある場合は、この行のコメントを外して適切なディレクトリ名に変更してください。

2

生成される実行ファイル名を指定します。ここでは、helloとします。

3

生成される実行ファイルが依存するオブジェクトファイルを指定します。ここでは hello.oを指定します。

10.1.3. ビルド

Makefilehello.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用実行ファイルです。

10.1.4. インストール

実行ファイルを atmark-distの romfsディレクトリにインストールするために、makeコマンドで romfsターゲットを指定します。

[PC ~/hello]$ make romfs
romfs-inst.sh /bin/hello
[PC ~/hello]$ ls ../atmark-dist-[version]/romfs/bin/hello
	  hello

10.1.5. imageファイルの作成

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ターゲットについては、項7.6.5. 「image」を参照してください。

10.1.6. 複数のソースコード

実行ファイルが複数のソースコードに分割されている場合は、Makefileを変更することで対応できます。ここでは、hello.cprint.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 <------------------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

10.1.7. pthread対応

スレッドを使うアプリケーションの場合は、スレッド用のライブラリをリンクする必要があります。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)  1

clean:
	-rm -f $(EXEC) *.elf *.gdb *.o

romfs:
	$(ROMFSINST) /bin/$(EXEC)

%.o: %.c
	$(CC) -c $(CFLAGS) -o $@ $<

1

$(LIBPTHREAD)を追加する

10.2. プロダクト別のアプリケーション

組み込み機器の場合、プロダクト固有のアプリケーションは、必ずと言っていいほど存在すると思います。ここでは、プロダクト固有のアプリケーションをatmark-distに統合する方法を紹介します。

10.2.1. ディレクトリの準備

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

10.2.2. ソースコードの用意

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 $@ $< 

10.2.3. 追加アプリケーションの設定

追加したアプリケーションをプロダクトMakefileに追加します。プロダクトMakefileには、SUBDIR_yと呼ばれる変数が用意されています。ここに、アプリケーションのディレクトリ名を追加します。

    :
    :
SUBDIR_y += hello
    :
    : 

10.2.4. ビルド

ビルド方法は項7.5. 「ビルド」と同じです。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

10.3. userディレクトリへのマージ

最初はプロダクト固有のアプリケーションとして開発されたものでも、多くのプロダクトで使われるようになることがあります。そんな時は、アプリケーションをuserディレクトリに移動し、プロダクト間で共有することができます。

10.3.1. ディレクトリの準備

atmark-dist/user以下に、アプリケーション用のディレクトリを作成します。ここでは、helloとします。

[PC ~]$ mkdir atmark-dist-[version]/user/hello
[PC ~]$ ls -d atmark-dist-[version]/user/hello
hello

10.3.2. ソースコードの用意

CのソースコードおよびMakefile項10.2. 「プロダクト別のアプリケーション」の章で使ったものと同じものを使用します。

10.3.3. 追加アプリケーションの設定

変更個所は、atmark-dist/config/config.inatmark-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

10.3.4. アプリケーションの選択

make menuconfigなどで追加したアプリケーションがMiscellaneous Applicationセクションに表示されるか確認してください。表示されたhelloを選択し、設定を保存します。

メニューに追加された hello

図 10.1. メニューに追加された hello


10.3.5. ビルド

In Treeコンパイルのビルド方法は項7.5. 「ビルド」と同じです。生成されたイメージファイルをターゲットボードに転送し、helloが動作するか確認してください。

10.3.6. コンフィグの命名規則

今回使用したコンフィグ名はCONFIG_USER_HELLO_HELLO です。

atmark-distではユーザーランドアプリケーションの選択にはディレクトリ名とアプリケーション名を使う決まりになっています。

  • すべてのコンフィグオプションは、CONFIG_からはじめる

  • atmark-dist/user以下のものは、CONFIG_USER_からはじめる

  • ディレクトリ名がhelloなので、CONFIG_USER_HELLO_からはじめる

  • 最後にアプリケーション名をつけて CONFIG_USER_HELLO_HELLOとなる

10.3.7. 複数のアプリケーション

ひとつのディレクトリで複数のアプリケーションを開発する方法を紹介します。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では、左側にコンフィグオプションを、+=の右側にはディレクトリ名を書きます。このため、hellohello2も指定するディレクトリ名は同じ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章の使い方を参照してください。