x86_64 ubuntu上でcatapultをarm64用にビルドする(dragon)

catapult

[注意]この記事で書かれている不具合は、これを書いている時点でarm64向けにクロスコンパイルした時に起こるものです。通常の(x64上でx64向けにビルドする)時には起きません。

前回の記事

https://mijinc0.github.io/blog/post/20190602_building_catapult_for_arm/

前回、catapultのarm向けクロスコンパイルを行こないました。最初はversion dragonでビルドをし、catapult.serverの起動は確認しましたが、、catapult.tools.nemgenがどうもビルド出来ず、中途半端な状態になったためにバージョンを一旦cowに下げた記事に変更しました。

その後、version dragonのarm向けのクロスコンパイルが出来たので、それに関して書きます。

さいしょに

基本的には前回の記事と同じ。ただ、catapult.tools.nemgenをビルドする時にエラーが出るので、その対処のみを抜き出して書きます。

まずは、前回の記事に沿ってcatapult.tools.nemgenをビルドすると、どういったエラーが出るのかについて書いておきます。

catapult-server.d/_build$  cmake -DBOOST_ROOT=~/boost-build-1.69.0 -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=~/toolchain.arm.cmake ..
catapult-server.d/_build$ make catapult.tools.nemgen -j3

Scanning dependencies of target external
Scanning dependencies of target catapult.state
Scanning dependencies of target catapult.utils
[  0%] Building C object external/CMakeFiles/external.dir/ref10/crypto_verify_32.c.o
[  0%] Building C object external/CMakeFiles/external.dir/ref10/fe_0.c.o
[  0%] Building C object external/CMakeFiles/external.dir/ref10/fe_1.c.o
[  0%] Building C object external/CMakeFiles/external.dir/ref10/fe_add.c.o
[  0%] Building C object external/CMakeFiles/external.dir/ref10/fe_cmov.c.o

...

[100%] Linking CXX static library ../../lib/libcatapult.tools.a
[100%] Built target catapult.tools
Scanning dependencies of target catapult.tools.nemgen
[100%] Building CXX object tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/BlockGenerator.cpp.o
[100%] Building CXX object tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/BlockSaver.cpp.o
[100%] Building CXX object tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/NemesisConfiguration.cpp.o
In file included from /home/mij/catapult-server.d/_build/inc/catapult/state/RootNamespace.h:22:0,
                 from /home/mij/catapult-server.d/tools/nemgen/NemesisConfiguration.h:24,
                 from /home/mij/catapult-server.d/tools/nemgen/BlockSaver.cpp:22:
/home/mij/catapult-server.d/_build/inc/catapult/state/Namespace.h:32:36: error: 'NamespaceId' was not declared in this scope
   using Path = utils::CheckedArray<NamespaceId, Namespace_Max_Depth>;
                                    ^~~~~~~~~~~
/home/mij/catapult-server.d/_build/inc/catapult/state/Namespace.h:32:36: note: suggested alternative: 'Namespace'
   using Path = utils::CheckedArray<NamespaceId, Namespace_Max_Depth>;
                                    ^~~~~~~~~~~
                                    Namespace
/home/mij/catapult-server.d/_build/inc/catapult/state/Namespace.h:32:49: error: 'Namespace_Max_Depth' was not declared in this scope
   using Path = utils::CheckedArray<NamespaceId, Namespace_Max_Depth>;
                                                 ^~~~~~~~~~~~~~~~~~~
/home/mij/catapult-server.d/_build/inc/catapult/state/Namespace.h:32:68: error: template argument 1 is invalid
   using Path = utils::CheckedArray<NamespaceId, Namespace_Max_Depth>;
                                                                    ^
/home/mij/catapult-server.d/_build/inc/catapult/state/Namespace.h:32:68: error: template argument 2 is invalid
/home/mij/catapult-server.d/_build/inc/catapult/state/Namespace.h:36:28: error: 'Path' does not name a type

(省略 : 果てしなく続くエラー文)

/home/mij/catapult-server.d/tools/nemgen/BlockGenerator.cpp:209:53: error: 'nonce' was not declared in this scope
    auto mosaicId = transactions.addMosaicDefinition(nonce, mosaicEntry.definition().properties());
                                                     ^~~~~
/home/mij/catapult-server.d/tools/nemgen/BlockGenerator.cpp:209:53: note: suggested alternative: 'nice'
    auto mosaicId = transactions.addMosaicDefinition(nonce, mosaicEntry.definition().properties());
                                                     ^~~~~
                                                     nice
/home/mij/catapult-server.d/tools/nemgen/NemesisConfiguration.cpp: At global scope:
/home/mij/catapult-server.d/tools/nemgen/NemesisConfiguration.cpp:81:8: error: 'auto catapult::tools::nemgen::{anonymous}::CreateMosaicEntry(const catapult::utils::ConfigurationBag&, const Key&, const string&, int)' defined but not used [-Werror=unused-function]
   auto CreateMosaicEntry(
        ^~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/build.make:110: recipe for target 'tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/NemesisConfiguration.cpp.o' failed
make[3]: *** [tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/NemesisConfiguration.cpp.o] Error 1
/home/mij/catapult-server.d/tools/nemgen/BlockGenerator.cpp: At global scope:
/home/mij/catapult-server.d/tools/nemgen/BlockGenerator.cpp:54:15: error: 'std::__cxx11::string catapult::tools::nemgen::{anonymous}::GetChildName(const string&)' defined but not used [-Werror=unused-function]
   std::string GetChildName(const std::string& namespaceName) {
               ^~~~~~~~~~~~
cc1plus: all warnings being treated as errors
tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/build.make:62: recipe for target 'tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/BlockGenerator.cpp.o' failed
make[3]: *** [tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/BlockGenerator.cpp.o] Error 1
CMakeFiles/Makefile2:14165: recipe for target 'tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/all' failed
make[2]: *** [tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/all] Error 2
CMakeFiles/Makefile2:14177: recipe for target 'tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/rule' failed
make[1]: *** [tools/nemgen/CMakeFiles/catapult.tools.nemgen.dir/rule] Error 2
Makefile:2417: recipe for target 'catapult.tools.nemgen' failed
make: *** [catapult.tools.nemgen] Error 2

最下部付近を読んでいくと、どうやらBlockGenerator.cpp.oの生成に失敗している様子。
そして、例えば最上部付近を読んでみると、'NamespaceId' was not declared in this scopeとエラー文にあるとおり、定義されているはずの宣言を見つけることが出来ていない。つまり、インクルード廻りのエラーだと考えられます。

そして、結論から言うと、これに対処することで、ビルドが通るようになります。

環境

catapult

Dragon

コンパイルするOS

x86_64 GNU/Linux NAME=“Ubuntu” VERSION=“18.04.2 LTS (Bionic Beaver)”

対処

理由は後回しにして、“何をすべきか"を書きます。

対処自体は簡単で、catapult-server.d/tools/CMakeLists.txtの上部、include_directories(. ${CMAKE_BINARY_DIR}/inc)BEFOREオプションを追加します。

# catapult-server.d/tools/CMakeLists.txt

cmake_minimum_required(VERSION 3.2)

# BEFOREを追加
include_directories(BEFORE . ${CMAKE_BINARY_DIR}/inc)

add_subdirectory(address)
add_subdirectory(benchmark)
add_subdirectory(health)
add_subdirectory(nemgen)
add_subdirectory(network)
add_subdirectory(statusgen)
add_subdirectory(tools)

これでビルドすれば通ります。

何をしているのか

BEFOREを追記することで、その場所でインクルードされるディレクトリの優先順位を上げています。

何故そんなことをする必要があるのか

先に、少しビルド時の挙動について触れておきます。

https://github.com/nemtech/catapult-server/blob/master/BUILDING.md

上記のCATAPULTの部分を見ると、ninja -j4を実行する前にninja publishを実行しています。この操作は、pythonスクリプトを動かしているのですが、この操作によって、_buildディレクトリ内にincディレクトリが生成されます。

このincディレクトリには、ビルドに必要なヘッダファイルが収められています。
そして、対処のパートでBEFOREを追記した部分を読むと、include_directories(. ${CMAKE_BINARY_DIR}/inc)とあるとおり、ninja publishによって生成したincディレクトリを参照するように指示していることがわかります。

$ ninja publish
$ ninja -j4

何故src内のヘッダファイルを直接参照しないのかと言うと、恐らくpluginsextensionsなどはsrc内のヘッダファイルをインクルードするが、それらが収まるディレクトリツリーの外に完全に出てしまっているので、直接ディレクトリをインクルードすると煩雑になる。そのため、一旦incディレクトリを生成してその中にsrcplubins等で使うヘッダファイルを集約して、そこを参照するようにしているのだと考えられます。

とにかく、ビルドするときにはincディレクトリ内のヘッダファイルをインクルードしたいのです。

そして今回、それが失敗しています。詳しい話は書くと長くなるので書きませんが、本来インクルードすべきではない別の場所を参照してしまっています。(下記図参照)

draw1

下記、Makefileにwarningを追記してインクルードされているディレクトリを出力させてみた結果。

x86_64

/usr/bin/x86_64-linux-gnu-g++-7  $(CXX_DEFINES)
                                 $(CXX_INCLUDES) -isystem boost-build-1.69.0/include
                                                 -Icatapult-server/tools/.
                                                 -Iatapult-server/_build/inc
                                 $(CXX_FLAGS)
                                 -o CMakeFiles/catapult.tools.nemgen.dir/BlockGenerator.cpp.o
                                 -c catapult-server/tools/nemgen/BlockGenerator.cpp

x86_64で普通にビルドしたときは、BlockGenerator.cpp.oをコンパイルするときにはboost-build-1.69.0/includecatapult-server/tools/.catapult-server/_build/incがインクルードディレクトリとして指定されている。

arm64

/usr/bin/aarch64-linux-gnu-g++-7  $(CXX_DEFINES)
                                  $(CXX_INCLUDES) -isystem /home/mij/boost-build-1.69.0/include
                                                  -Icatapult-server
                                                  -Icatapult-server/src
                                                  -Icatapult-server/plugins/txes/mosaic/src
                                                  -Icatapult-server/tools/.
                                                  -Icatapult-server/_build/inc
                                  $(CXX_FLAGS)
                                  -o CMakeFiles/catapult.tools.nemgen.dir/BlockGenerator.cpp.o
                                  -c catapult-server.d/tools/nemgen/BlockGenerator.cpp

arm64向けにクロスコンパイルしたときは、catapult-servercatapult-server/srccatapult-server/plugins/txes/mosaic/srccatapult-server/_build/incよりも優先される位置でインクルードの指定を受けている。この為に本意でない場所のファイルをインクルードしてしまっていた。

なぜそれらがarm64向けにビルドするときのみ残ってしまうのかが分からないが、理由が分かればもう少し良い修正方法がありそう。