newlibをビルドしてみた

2018-08-25

自作OSの上でなにかアプリケーションを動かそうと思ったときに、できれば既存のソースから引っぱってきて使いまわしたり他の環境でも動くようにしたいので、Cの標準ライブラリにのっとったライブラリ関数を用意したい。 今までは自前でシコシコと実装していたが、まあ面倒だしかなり手間がかかる。

最近newlibというものがあるということを知ったので、試してみた。

NewlibのソースはホームページからたどってgitまたはFTPから落とせる。 (-cygwinというのはCygnus Supportが作った名残り?)

./configure && makeしてみたが、なにもビルドされない。 手順通りでできないとMakefileの中見るのも辛いしだいたい諦めちゃうんだけど、ググったら方法が見つかった: Newlibビルドメモ - uchan note の「ネイティブビルド」部。 それによるとビルド用の別フォルダを作成して、リポジトリ直下じゃなくnewlib以下のconfigureを実行する:

$ tar xvf newlib-3.0.0.20180802.tar.gz
$ mkdir build-newlib && cd build-newlib
$ CC=gcc ../newlib-3.0.0.20180802/newlib/configure --disable-multilib
$ make

ビルドが始まる、しかし途中でエラーが出る:

make[3]: Entering directory '/vagrant/tmp/build-newlib/libc/stdio'
gcc -I/vagrant/tmp/build-newlib/targ-include -I/vagrant/tmp/newlib-3.0.0.20180802/newlib/libc/include -DPACKAGE_NAME=\"newlib\" -DPACKAGE_TARNAME=\"newlib\" -DPACKAGE_VERSION=\"3.0.0\" -DPACKAGE_STRING=\"newlib\ 3.0.0\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -I. -I../../../newlib-3.0.0.20180802/newlib/libc/stdio -DMISSING_SYSCALL_NAMES -DHAVE_INIT_FINI -fno-builtin -O2 -c -o lib_a-gets.o `test -f 'gets.c' || echo '../../../newlib-3.0.0.20180802/newlib/libc/stdio/'`gets.c
In file included from /vagrant/tmp/newlib-3.0.0.20180802/newlib/libc/include/ssp/stdio.h:34:0,
from /vagrant/tmp/newlib-3.0.0.20180802/newlib/libc/include/stdio.h:800,
from ../../../newlib-3.0.0.20180802/newlib/libc/stdio/gets.c:62:
/vagrant/tmp/newlib-3.0.0.20180802/newlib/libc/include/ssp/ssp.h:46:24: error: expected declaration specifiers or ‘...’ before ‘__builtin_object_size’
#define __ssp_bos(ptr) __builtin_object_size(ptr, __SSP_FORTIFY_LEVEL > 1)
^
/vagrant/tmp/newlib-3.0.0.20180802/newlib/libc/include/ssp/stdio.h:67:21: note: in expansion of macro ‘__ssp_bos’
__gets_chk(str, __ssp_bos(str))
^~~~~~~~~
../../../newlib-3.0.0.20180802/newlib/libc/stdio/gets.c:96:1: note: in expansion of macro ‘gets’
gets (char *buf)
^~~~
Makefile:1096: recipe for target 'lib_a-gets.o' failed

なぜエラーが出るのかよくわからないんだけど、getsの宣言なのにマクロ展開されてしまっていてるらしい。 直前で#undef getsで取り消すとエラーは回避できるので、すべて対応する(なにかラベル定義で回避する方法があるんじゃないかと思うけど、わからず…)。

で全部修正するとlibc.aとlibm.aができあがるので、これとヘッダを使えばよい。 どういうシステムコールを用意する必要があるのかは把握してない。

参考