XtreemFSをFreeBSDでビルドする

まだまだ長い旅路の途中。
成果物はGitHubの2510/xtreemfs (freebsd branch)に。

# pkg install bash gmake openjdk8 apache-ant python27 cmake boost-all fusefs-libs
# mount -t fdescfs fdesc /dev/fd
# git clone https://github.com/2510/xtreemfs
# setenv JAVA_HOME /usr/local/openjdk8
# gmake ANT_BIN=/usr/local/bin/ant PYTHON=python2.7 CC=cc CXX=c++
(中略)
BUILD SUCCESSFUL
# gmake ANT_BIN=/usr/local/bin/ant PYTHON=python2.7 CC=cc CXX=c++ install
# sh /etc/xos/xtreemfs/postinstall_setup.sh

今日のところはビルドだけ。
またそのうち、ね。

# /etc/init.d/xtreemfs-osd start
/etc/init.d/xtreemfs-osd: line 19: /etc/init.d/functions: No such file or directory

失敗集

ここから先はビルドを通す過程の記録。

gmake: -c: Command not found

# gmake
gmake: -c: Command not found
gmake: -c: Command not found
gmake: -c: Command not found
Makefile:185: recipe for target 'check_server' failed
gmake: *** [check_server] Error 127

bashが入ってないとこんなこと言われる。
-cがないってことからsh -cを想像すれば辿り着けるんだろうけど、私には無理だった。

make: “/root/XtreemFS-1.5.1/Makefile” line 1: Need an operator

# make
make: "/root/XtreemFS-1.5.1/Makefile" line 1: Need an operator
make: "/root/XtreemFS-1.5.1/Makefile" line 3: Need an operator
(以下略)

gmakeじゃなくてmakeしている場合。
FreeBSDではよくあること。

javac not found! Make sure a JDK is installed and set JAVA_HOME.

javac not found! Make sure a JDK is installed and set JAVA_HOME.
Makefile:185: recipe for target 'check_server' failed
gmake: *** [check_server] Error 1

書いてある通り。ちゃんとsetenv(もしくはexport)してくださいな。

ant not found!

# gmake
java ok
ant not found! Make sure ant is installed and set ANT_HOME.
Makefile:185: recipe for target 'check_server' failed
gmake: *** [check_server] Error 1

antは/usr/bin/ant${ANT_HOME}/bin/antを探すけれど、FreeBSDはどっちにもない。
Makefileを修正する。

ifeq "$(ANT_HOME)" ""
        ANT_BIN = /usr/bin/ant                                                                                                                                                                                                   
else
        ANT_BIN = $(ANT_HOME)/bin/ant                                                                                                                                                                                            
endif

を、

ifeq "$(ANT_HOME)" ""
        ANT_BIN := /usr/bin/ant                                                                                                                                                                                                   
else
        ANT_BIN := $(ANT_HOME)/bin/ant                                                                                                                                                                                            
endif

に変更。
ビルド時はgmake ANT_BIN=/usr/local/bin/ant

C++ ok (/usr/local/bin/bash: line 0: [: !: binary operator expected)

java ok
ant ok
/usr/local/bin/bash: line 0: [: !: binary operator expected
C++ ok

C++ okなんだからokでいいと思った?(cmakeが入ってなくてもokって言われる)
pkg install cmakeすること。ちなみにcmakeが入っていても同じエラーを吐くので、Makefileのcheck_clientターゲットの、

@if [ ! $(WHICH_GPP) -a ! $(WHICH_CLANGPP) ];
@if [ ! $(CMAKE_BIN) ]; then echo "cmake not found";exit 1; fi;

を、以下のように直してやる。

@if [ ! -x "$(WHICH_GPP)" -a ! -x "$(WHICH_CLANGPP)" ];
@if [ -n "$(shell $(CMAKE_BIN) --version 2>/dev/null)" ]; then echo "cmake not found";exit 1; fi;

javacやantは-eでチェック、g++やclangはバージョンも見るためにwhichでパスを拾って$(shell ...)をチェックしてる。
cmakeはバージョンに興味はないけど、whichしてないので-eが使えない。まぁ、setenv CMAKE_BIN ...とすればいいだけなんだけどね。

python ok (python:: syntax error in expression)

root@xtreemfs-test-1:~/XtreemFS-1.5.1 # gmake
java ok
ant ok
C++ ok
/usr/local/bin/bash: [[: python:: syntax error in expression (error token is ":")
python ok

python okなんだからokでいいと(以下略
これもMakefileが悪い。(python入ってないのにokって言われる)
pkg install python27して、ln -s /usr/local/bin/python27 /usr/local/bin/pythonしましょう。
もちろんMakefileも直す。

PYTHON := python

check_testターゲット

@if [ -z "$(shell which $(PYTHON) 2>/dev/null)" ]; then echo "python >= 2.4 required! (not installed)"; exit 1; fi;
@if [ "$(shell $(PYTHON) -V 2>&1 | head -n1 | cut -d' ' -f2 | cut -d. -f2)" -lt 3 -a "$(shell $(PYTHON) -V 2>&1 | head -n1 | cut -d' ' -f2 | cut -d. -f1)" -lt 3 ]; then echo "python >= 2.4 required! (version error)"; \
exit 1; fi;

testターゲット

$(PYTHON) ./tests/xtestenv -c ./tests/test_config.py short
# gmake ANT_BIN=/usr/local/bin/ant PYTHON=python2.7

Configuring incomplete, errors occurred!

CMake Error at /usr/local/share/cmake/Modules/FindBoost.cmake:1657 (message):
  Unable to find the requested Boost libraries.

  Unable to find the Boost header files.  Please set BOOST_ROOT to the root
  directory containing Boost or BOOST_INCLUDEDIR to the directory containing
  Boost's headers.
Call Stack (most recent call first):
  CMakeLists.txt:151 (FIND_PACKAGE)


CMake Error at CMakeLists.txt:153 (message):
  The boost library was not found on your system.  If needed, you can also
  download and compile it on your own.  After compiling boost locally, set
  the the environment variable BOOST_ROOT to the boost base directory before
  executing 'make' e.g., 'export BOOST_ROOT=/Users/xyz/boost_1_47_0'.


-- Configuring incomplete, errors occurred!
See also "/root/XtreemFS-1.5.1/cpp/build/CMakeFiles/CMakeOutput.log".
See also "/root/XtreemFS-1.5.1/cpp/build/CMakeFiles/CMakeError.log".
Makefile:275: recipe for target 'client' failed
gmake: *** [client] Error 1

これは簡単。pkg install boost-all
似たようなエラーがvalgrind, fuseが見つからない場合に出る。
特にfuseはpkg install fuseではなくpkg install fusefs-libsなので注意が必要。

Could not find or load main class org.apache.tools.ant.launch.Launcher

/usr/local/bin/ant -D"file.encoding=UTF-8" -f java/foundation/build-1.6.5.xml jar
Error: Could not find or load main class org.apache.tools.ant.launch.Launcher
Makefile:318: recipe for target 'foundation' failed
gmake: *** [foundation] Error 1

/bin/bash: bad interpreter: No such file or directory

# gmake ANT_BIN=/usr/local/bin/ant PYTHON=python2.7 install
/usr/local/bin/bash: etc/init.d/generate_initd_scripts.sh: /bin/bash: bad interpreter: No such file or directory
Makefile:94: recipe for target 'install-server' failed
gmake: *** [install-server] Error 126

bashは/binにあるとは限らない。これもFreeBSDではよくあること。

ただ、etc/init.d/generate_initd_scripts.shの最初の行を直してやればいいように見えて、大量のスクリプトが同様の依存をしているので腹立たしい。
面倒なので一掃。(tcshじゃない人は!の前のエスケープを外してね)

# find . -print0 | xargs -0 -n 1 sed -i '' -e 's=^#\!/bin/bash$=#\!/usr/local/bin/bash='

groupadd: not found

# sh /etc/xos/xtreemfs/postinstall_setup.sh
Generated UUID for service: dir
Generated UUID for service: mrc
Generated UUID for service: osd
/etc/xos/xtreemfs/postinstall_setup.sh: groupadd: not found

packaging/postinstall_setup.sh中のLinuxに固有なユーザ・グループ作成コマンド群が原因なので、pwで置き換える。

groupadd $XTREEMFS_GROUP

pw groupadd $XTREEMFS_GROUP
useradd -r --home $XTREEMFS_HOME -g $XTREEMFS_GROUP $XTREEMFS_USER

は、

pw useradd $XTREEMFS_USER -L daemon -d $XTREEMFS_HOME -g $XTREEMFS_GROUP

としてみた。
ところでuseradd-rはCreate a system accountらしいので、こちらではlogin class指定に置き換えてやった。意味は違うけど。

/var/lib: No such file or directory

# sh /etc/xos/xtreemfs/postinstall_setup.sh
Generated UUID for service: dir
Generated UUID for service: mrc
Generated UUID for service: osd
mkdir: /var/lib: No such file or directory

FreeBSDでは/var/libは使いません。
欲しいらしいのでくれてやりましょう。
packaging/postinstall_setup.sh中のmkdirを、片っ端からmkdir -pで置き換え。

stat: illegal option — c

root@xtreemfs-test-1:~/XtreemFS-1.5.1 # sh /etc/xos/xtreemfs/postinstall_setup.sh
Generated UUID for service: dir
Generated UUID for service: mrc
Generated UUID for service: osd
stat: illegal option -- c
usage: stat [-FLnq] [-f format | -l | -r | -s | -x] [-t timefmt] [file ...]

stat(1)の仕様違い。
どうやらstat -c %U /var/lib/xtreemfsしたいらしいので、stat -f %Su /var/lib/xtreemfsに直してやる。
対応関係はこんなところか。

  • stat -c %U → stat -f %Su
  • stat -c %G → stat -f %Gu
  • stat -c %a → stat -f %p

ただ%a%pは完全に互換ではなく、例えば以下のようになってしまう。
この関係で余計なchmodが走るけど……誰も気にしないだろう。

# chmod 640 /etc/xos/xtreemfs/dirconfig.properties
# stat -f %p /etc/xos/xtreemfs/dirconfig.properties
100640

100000は、/usr/include/sys/stat.hによればregular fileを表す模様。

#define S_IFREG  0100000                /* regular */

gmake cleanしてgmakeしたらundefined reference

[ 81%] Linking CXX executable mount.xtreemfs
libxtreemfs.a(RPC.pb.cc.o): In function `xtreemfs::pbrpc::protobuf_AssignDesc_pbrpc_2fRPC_2eproto()':
/root/xtreemfs/cpp/generated/pbrpc/RPC.pb.cc:(.text+0x86): undefined reference to `google::protobuf::DescriptorPool::FindFileByName(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&) const'

うまくいったと思って整理したらこれだよ。
静的ライブラリとしてビルドしたprotobufとXtreemFS本体で、使っているC++コンパイラが違っているために起こっているみたい。
protobufはgccを優先し、XtreemFSはcmakeがclang++を優先している。(試行錯誤時、gccがない状態でprotobufがconfigureされたせいで、1回目は成功していたようだ。)
gmakeの引数にCC=cc CXX=c++というおまじないのような指定を追加して対応。