#navi_header|技術| uClibcをPC環境で試すのに自分が使っている方法を紹介します。 環境: CentOS 5.5 (x86, 32bit) gcc-4.1.2-48.el5 libgcc-4.1.2-48.el5 binutils-2.17.50.0.6-14.el5 uClibc-0.9.31 ''Buildrootは使いません。'' 紹介するサンプルでは以下のディレクトリ構成を使っています。"/home/msakamoto/reduced.linux"の部分は適宜読み替えてください。 /home/msakamoto/reduced.linux/uclibc_test2/ uClibc-0.9.31.tar.bz2 uClibc-0.9.31/ uclibc_test/ Makefile ret1.c helloworld.c その他細かいディレクトリは続いて紹介するMakefile中の変数を適宜調整して対応してください。 #more|| #outline|| ---- * Makefile, ret1.c, helloworld.c Makefile: #pre||> # オリジナルのソースツリー UCLIBC_SRC_DIR=/home/msakamoto/reduced.linux/uClibc-0.9.31 # 実験環境のルートディレクトリ TEST_DIR=/home/msakamoto/reduced.linux/uclibc_test # "make O=..." で指定するビルドディレクトリ UCLIBC_BUILD_DIR=$(TEST_DIR)/build # 開発用のヘッダーとライブラリのインストール先 UCLIBC_DEV_DIR=$(TEST_DIR)/dev # 実行時に使うライブラリとローダ(ld-uClibc)のインストール先 UCLIBC_RUNTIME_DIR=$(TEST_DIR)/runtime # アプリケーションをリンクするときに指定するローダのフルパス UCLIBC_RUNTIME_INTERP=$(UCLIBC_RUNTIME_DIR)/lib/ld-uClibc.so.0 # 必要に応じてprefixを設定 #PREFIX_INSTALL_DEV=PREFIX=$(UCLIBC_DEV_DIR) #PREFIX_INSTALL_RUNTIME=PREFIX=$(UCLIBC_RUNTIME_DIR) # Linuxのヘッダーファイルのディレクトリ(ホストPCの環境をそのまま流用) LINUX_KERNEL_HEADER=/usr/include # 以下、ret1.c, helloworld.c のコンパイルとリンク用オプション設定 CFLAGS=-nostdinc \ -I$(UCLIBC_DEV_DIR)/usr/include \ -I$(LINUX_KERNEL_HEADER) \ -Wall \ -D_GNU_SOURCE \ -isystem /usr/lib/gcc/i386-redhat-linux/4.1.2/include-fixed \ -isystem /usr/lib/gcc/i386-redhat-linux/4.1.2/include \ -fno-builtin LFLAGS_COMMON=-nostdlib \ -L $(UCLIBC_RUNTIME_DIR)/lib \ -L $(UCLIBC_DEV_DIR)/usr/lib \ -Wl,--dynamic-linker=$(UCLIBC_RUNTIME_INTERP) \ CRT_START=$(UCLIBC_DEV_DIR)/usr/lib/crt1.o \ $(UCLIBC_DEV_DIR)/usr/lib/crti.o CRT_STATIC=$(UCLIBC_DEV_DIR)/usr/lib/libc.a \ $(UCLIBC_DEV_DIR)/usr/lib/uclibc_nonshared.a CRT_END=$(UCLIBC_DEV_DIR)/usr/lib/crtn.o TARGETS=ret1_static ret1_dyn helloworld_static helloworld_dyn help: @echo "targets:" @echo " uclibc-menuconfig" @echo " uclibc-build" @echo " uclibc-clean" @echo " testbuild ($(TARGETS))" @echo " clean (remove *.o and $(TARGETS))" # 以下、uClibcのmenuconfig, all, install_dev, install_runtime, cleanターゲットのラッパ uclibc-menuconfig: $(MAKE) -C $(UCLIBC_SRC_DIR) O=$(UCLIBC_BUILD_DIR) menuconfig uclibc-build: $(MAKE) -C $(UCLIBC_SRC_DIR) O=$(UCLIBC_BUILD_DIR) all $(MAKE) -C $(UCLIBC_SRC_DIR) O=$(UCLIBC_BUILD_DIR) $(PREFIX_INSTALL_DEV) install_dev $(MAKE) -C $(UCLIBC_SRC_DIR) O=$(UCLIBC_BUILD_DIR) $(PREFIX_INSTALL_RUNTIME) install_runtime uclibc-clean: $(MAKE) -C $(UCLIBC_SRC_DIR) O=$(UCLIBC_BUILD_DIR) realclean rm -rf $(UCLIBC_DEV_DIR) rm -rf $(UCLIBC_RUNTIME_DIR) # 以下、ret1.c, helloworld.c 関連のターゲット設定 .SUFFIXES: .c .o .c.o: $(CC) $(CFLAGS) -c -o $@ $< testbuild: $(TARGETS) ret1_static: ret1.o $(CC) -static -o $@ $(LFLAGS_COMMON) $(CRT_START) $< $(CRT_STATIC) $(CRT_END) ret1_dyn: ret1.o $(CC) -lc -o $@ $(LFLAGS_COMMON) $(CRT_START) $< $(CRT_END) helloworld_static: helloworld.o $(CC) -static -o $@ $(LFLAGS_COMMON) $(CRT_START) $< $(CRT_STATIC) $(CRT_END) helloworld_dyn: helloworld.o $(CC) -lc -o $@ $(LFLAGS_COMMON) $(CRT_START) $< $(CRT_END) clean: rm -f *.o rm -f $(TARGETS) ||< ret1.c : シンプルな、とりあえずリンクできて実行出来るか確認するだけのプログラム。 #code|c|> int main(void) { return 1; } ||< helloworld.c : 想定通りのLinuxカーネルヘッダをinclude出来ているか確認できるようちょっと調整。 #code|c|> #include #include int main(int argc, char *argv[]) { int i; printf("Hello, World! LINUX_VERSION_CODE=%ld\n", LINUX_VERSION_CODE); for (i = 0; i < argc; i++) { printf("args[%d]=[%s]\n", i, argv[i]); } return 0; } ||< * uClibcのビルド 1.uClibcのアーカイブを展開する。 2.以下の記事を参照し、 "libc/misc/time/time.c" を修正する。 - uClibc-0.9.31 symbol table oddities -- http://permalink.gmane.org/gmane.comp.lib.uclibc.general/19300 - Discussion and development of uClibc (the embedded C library) -- http://comments.gmane.org/gmane.comp.lib.uclibc.general/19298 - 解决uClibc-0.9.31 can’t resolve symbol ll_tzname_UNKNOWN ? 三人行 -- http://blog.microsuncn.com/?p=1467 3.以下の記事を参照し、"extra/scripts/install_headers.sh" を修正する。 - 技術/Linux/uClibc/01, "make install_headers" 関連PATCH(uClibc-0.9.31) - Glamenv-Septzen.net -- http://www.glamenv-septzen.net/view/945 4."make defconfig"でビルドディレクトリを初期化する。 $ cd uClibc-0.9.31 $ make O=`pwd`/reduced.linux/uclibc_test/build defconfig '' "O=" オプションはフルパスで指定する。 '' 5."make uclibc-menuconfig" で微調整する。 $ cd uclibc_test $ make uclibc-menuconfig + LDSO_GNU_HASH_SUPPORT を有効化する。 [[948]] 参照。 + RUNTIME_PREFIX, DEVEL_PREFIX を適宜調整する。 + HARDWIRED_ABSPATH を無効化する。 サンプル差分diff: #pre||> 91c91 < # LDSO_GNU_HASH_SUPPORT is not set --- > LDSO_GNU_HASH_SUPPORT=y 214,215c214,215 < RUNTIME_PREFIX="/usr/$(TARGET_ARCH)-linux-uclibc/" < DEVEL_PREFIX="/usr/$(TARGET_ARCH)-linux-uclibc/usr/" --- > RUNTIME_PREFIX="/home/msakamoto/reduced.linux/uclibc_test/runtime" > DEVEL_PREFIX="/home/msakamoto/reduced.linux/uclibc_test/dev/usr" 217c217 < HARDWIRED_ABSPATH=y --- > # HARDWIRED_ABSPATH is not set 235,236c235 < # DODEBUG is not set < DOSTRIP=y --- > DODEBUG=y ||< ''静的リンクしたバイナリが Segmentation Fault してしまう場合は、 DODEBUG オプションを有効化してuClibcおよび対象アプリケーションをリビルドしてみてください。'' 6."make uclibc-build" でビルドする。 $ make uclibc-build 開発用ヘッダー・ライブラリファイルおよび実行時ライブラリがインストールで来たか確認: /home/msakamoto/reduced.linux/uclibc_test/ dev/ usr/ lib/ : *.a, *.so, symbolic-links include/ : *.h # "bits/", "sys/" ディレクトリ以下もコピーされていること。 runtime/ lib/ : *.so, symbolic-links * ret1, helloworld のビルド 7.ret1, helloworldをビルドする。 $ make testbuild 静的リンク版:ret1_static, helloworld_static 動的リンク版:ret1_dyn, helloworld_dyn 動的リンク版の場合は ".interp" セクションが想定通りのローダを指しているか確認: $ readelf -x .interp ret1_dyn Hex dump of section '.interp': 0x080480f4 2f6f746f 6d616b61 736d2f65 6d6f682f /home/msakamoto/ 0x08048104 63752f78 756e696c 2e646563 75646572 reduced.linux/uc 0x08048114 6d69746e 75722f74 7365745f 6362696c libc_test/runtim 0x08048124 2e636269 6c43752d 646c2f62 696c2f65 e/lib/ld-uClibc. 0x08048134 00 302e6f73 so.0. 実行してみます。 $ ./ret1_dyn $ echo $? 1 $ ./helloworld_dyn abc def Hello, World! LINUX_VERSION_CODE=132626 args[0]=[./helloworld_dyn] args[1]=[abc] args[2]=[def] $ ./ret1_static $ echo $? 1 $ ./helloworld_static abc def Hello, World! LINUX_VERSION_CODE=132626 args[0]=[./helloworld_static] args[1]=[abc] args[2]=[def] 8.後片付け ret1, helloworld のバイナリを削除: $ make clean uClibcのバイナリ(*.o含む), "dev/", "runtime/" 以下を削除: $ make uclibc-clean #navi_footer|技術|