home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

技術/Linux/uClibc/03, x86(32bit) PC環境でuClibcを試す (v1)

技術/Linux/uClibc/03, x86(32bit) PC環境でuClibcを試す (v1)

技術 / Linux / uClibc / 03, x86(32bit) PC環境でuClibcを試す (v1)
id: 949 所有者: msakamoto-sf    作成日: 2011-04-11 18:12:30
カテゴリ: Linux 

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中の変数を適宜調整して対応してください。


Makefile, ret1.c, helloworld.c

Makefile:


# オリジナルのソースツリー
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 : シンプルな、とりあえずリンクできて実行出来るか確認するだけのプログラム。

int main(void)
{
    return 1;
}

helloworld.c : 想定通りのLinuxカーネルヘッダをinclude出来ているか確認できるようちょっと調整。

#include <stdio.h>
#include <linux/version.h>
 
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" を修正する。

3.以下の記事を参照し、"extra/scripts/install_headers.sh" を修正する。

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
  1. LDSO_GNU_HASH_SUPPORT を有効化する。 技術/Linux/uClibc/02, "symbol 'stdout': can't resolve symbol in lib" の対処 参照。
  2. RUNTIME_PREFIX, DEVEL_PREFIX を適宜調整する。
  3. HARDWIRED_ABSPATH を無効化する。

サンプル差分diff:

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


プレーンテキスト形式でダウンロード
表示中のバージョン : 1
現在のバージョン : 2
更新者: msakamoto-sf
更新日: 2011-04-12 12:27:56
md5:767388e6ab62caf1baa8285b7606d16d
sha1:f02fc1733686470d5d1360323665650e14149a68
コメント
コメントを投稿するにはログインして下さい。