building catapult-server from source

需要があるのかわかりませんが、catapult-serverのビルド手順です。

catapult-serverのビルドには、 パッケージマネージャのconanを利用する手順と利用しない手順があります。
今回はconanを利用しない手順について記述します。

~~手順については、本家の以下のドキュメントがあるのですが、
ドキュメントどおり実施してもうまくいかないので、本記事を残しておくことにしました。~~
手順については、以下を参照してください。(Jaguarさんに直してもらいました)
https://github.com/nemtech/catapult-server/blob/main/docs/BUILD-manual.md

なお、今回の手順は2020年12月8日時点でのものですので、ご注意ください。

所要時間は約150分です。

## 注意点
~~ドキュメント通りにやってもうまくビルドできない。以下注意点。~~

* <font color="Red">**clang**</font>はくせもの。いれないようにしよう。
* ビルド時には結構メモリを食う。メモリ1GBだと無理、16GBで試した。
* ディスクも食う。8GBだと無理。32GBで試した。

~~* bashでは動かない。<font color="Red">**zsh**</font>に変更したら動いた
* ドキュメントに書いてあるcmakeの<font color="Red">**CMAKE_PREFIX_PATH**</font>のデリミタが多分間違っている。<font color="Red">**:(コロン)**</font>ではなくて<font color="Red">**;(セミコロン)**</font>に変更したら動いた。
* あとboostのincludeディレクトリも<font color="Red">**-DBoost_INCLUDE_DIR**</font>で指定してあげる必要がある。
* googleのbenchmarkのライブラリがマニュアル通りだとデフォルト(-fPICなし)でコンパイルされる。そのため、catapult-serverのビルドのときのリンクに失敗してしまう。cmakeの引数に<font color="Red">**-DCMAKE_POSITION_INDEPENDENT_CODE=ON**</font>を追加する必要がある。
* 事前に<font color="Red">**pkg-config**</font>と<font color="Red">**build-essential**</font>のパッケージを入れておかないとビルドでこける。
* 最後に<font color="Red">**ninja**</font>を実行する必要がある。~~

2018年5月くらいに比べてビルドはずいぶん簡単になっている。

## 環境(Amazon EC2)
* Ubuntu Server 20.04 LTS (HVM), SSD Volume Type
    * t2.xlarge
    * vCPU 4
    * メモリ 16GB
    * ストレージ(SSD) 32GB

## 手順(インスタンス作成後)
以下手順です。

### Step0 準備
```
sudo apt update
sudo apt -y upgrade
sudo apt -y install gcc g++ cmake libssl-dev ninja-build zsh pkg-config

zsh

mkdir -p cat_deps_dir/boost
export CAT_DEPS_DIR=$HOME/cat_deps_dir
boost_output_dir=${CAT_DEPS_DIR}/boost
```

### Step1 download all dependencies from source
```
function download_boost {
	local boost_ver=1_${1}_0
	local boost_ver_dotted=1.${1}.0

	curl -o boost_${boost_ver}.tar.gz -SL https://dl.bintray.com/boostorg/release/${boost_ver_dotted}/source/boost_${boost_ver}.tar.gz
	tar -xzf boost_${boost_ver}.tar.gz
	mv boost_${boost_ver} boost
}

function download_git_dependency {
	git clone git://github.com/${1}/${2}.git
	cd ${2}
	git checkout ${3}
	cd ..
}

function download_all {
	download_boost 74

	download_git_dependency google googletest release-1.10.0
	download_git_dependency google benchmark v1.5.2

	download_git_dependency mongodb mongo-c-driver 1.17.2
	download_git_dependency mongodb mongo-cxx-driver r3.6.1

	download_git_dependency zeromq libzmq v4.3.3
	download_git_dependency zeromq cppzmq v4.7.1

	download_git_dependency facebook rocksdb v6.13.3
}
cd ${CAT_DEPS_DIR}
mkdir source
cd source
download_all
```

### Step 2 - Install all dependencies
~~マニュアルからの変更点は以下のとおり。
* install_google_benchmark()のオプションに"-DCMAKE_POSITION_INDEPENDENT_CODE=ON"を追加~~

```
function install_boost {
	cd boost
	./bootstrap.sh with-toolset=clang --prefix=${boost_output_dir}

	b2_options=()
	b2_options+=(--prefix=${boost_output_dir})
	./b2 ${b2_options[@]} -j 8 stage release
	./b2 install ${b2_options[@]}
}

function install_git_dependency {
	cd ${2}
	mkdir _build
	cd _build

	cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX="${CAT_DEPS_DIR}/${1}" ${cmake_options[@]} ..
	make -j 8 && make install
}

function install_google_test {
	cmake_options=()
	cmake_options+=(-DCMAKE_POSITION_INDEPENDENT_CODE=ON)
	install_git_dependency google googletest
}

function install_google_benchmark {
	cmake_options=()
	cmake_options+=(-DBENCHMARK_ENABLE_GTEST_TESTS=OFF)
	install_git_dependency google benchmark
}

function install_mongo_c_driver {
	cmake_options=()
	cmake_options+=(-DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF)
	cmake_options+=(-DENABLE_MONGODB_AWS_AUTH=OFF)
	cmake_options+=(-DENABLE_TESTS=OFF)
	cmake_options+=(-DENABLE_EXAMPLES=OFF)
	cmake_options+=(-DENABLE_SASL=OFF)
	install_git_dependency mongodb mongo-c-driver
}

function install_mongo_cxx_driver {
	cmake_options=()
	cmake_options+=(-DBOOST_ROOT=${boost_output_dir})
	cmake_options+=(-DCMAKE_CXX_STANDARD=17)
	install_git_dependency mongodb mongo-cxx-driver
}

function install_zmq_lib {
	cmake_options=()
	cmake_options+=(-DWITH_TLS=OFF)
	install_git_dependency zeromq libzmq
}

function install_zmq_cpp {
	cmake_options=()
	cmake_options+=(-DCPPZMQ_BUILD_TESTS=OFF)
	install_git_dependency zeromq cppzmq
}

function install_rocks {
	cmake_options=()
	cmake_options+=(-DPORTABLE=1)
	cmake_options+=(-DWITH_TESTS=OFF)
	cmake_options+=(-DWITH_TOOLS=OFF)
	cmake_options+=(-DWITH_BENCHMARK_TOOLS=OFF)
	cmake_options+=(-DWITH_CORE_TOOLS=OFF)
	cmake_options+=(-DWITH_GFLAGS=OFF)
	install_git_dependency facebook rocksdb
}

function install_all {
	declare -a installers=(
		install_boost
		install_google_test
		install_google_benchmark
		install_mongo_c_driver
		install_mongo_cxx_driver
		install_zmq_lib
		install_zmq_cpp
		install_rocks
	)
	for install in "${installers[@]}"
	do
		pushd source > /dev/null
		${install}
		popd > /dev/null
	done
}
cd ${CAT_DEPS_DIR}
install_all
```

### Step 3 - Finally, download and build catapult
~~マニュアルからの変更点は以下のとおり。
* -DCMAKE_PREFIX_PATHのデリミタを:から;に変更
* -DBoost_INCLUDE_DIRを追加
* 最後にninjaコマンドを実行しないとコンパイルされない~~

```
cd
git clone https://github.com/nemtech/catapult-server.git
cd catapult-server

mkdir _build && cd _build
BOOST_ROOT="${CAT_DEPS_DIR}/boost" cmake .. \
	-DCMAKE_BUILD_TYPE=RelWithDebInfo \
	-DCMAKE_PREFIX_PATH="${CAT_DEPS_DIR}/facebook;${CAT_DEPS_DIR}/google;${CAT_DEPS_DIR}/mongodb;${CAT_DEPS_DIR}/zeromq" \
	\
	-GNinja

ninja publish
ninja -j4
```

### Step 4 確認
```bash
ls ./bin
bench.catapult.crypto.hashers                        tests.catapult.local.recovery
bench.catapult.crypto.verify                         tests.catapult.local.server
catapult.broker                                      tests.catapult.model
catapult.recovery                                    tests.catapult.mongo
catapult.server                                      tests.catapult.mongo.plugins.accountlink
catapult.tools.address                               tests.catapult.mongo.plugins.aggregate
catapult.tools.benchmark                             tests.catapult.mongo.plugins.lockhash
catapult.tools.health                                tests.catapult.mongo.plugins.locksecret
catapult.tools.linker                                tests.catapult.mongo.plugins.metadata
catapult.tools.nemgen                                tests.catapult.mongo.plugins.mosaic
catapult.tools.network                               tests.catapult.mongo.plugins.multisig
catapult.tools.ssl                                   tests.catapult.mongo.plugins.namespace
catapult.tools.statusgen                             tests.catapult.mongo.plugins.restrictionaccount
catapult.tools.testvectors                           tests.catapult.mongo.plugins.restrictionmosaic
catapult.tools.votingkey                             tests.catapult.mongo.plugins.transfer
tests.catapult.addressextraction                     tests.catapult.net
tests.catapult.api                                   tests.catapult.networkheight
tests.catapult.cache                                 tests.catapult.nodediscovery
tests.catapult.cache_core                            tests.catapult.observers
tests.catapult.cache_db                              tests.catapult.packetserver
tests.catapult.cache_tx                              tests.catapult.partialtransaction
tests.catapult.chain                                 tests.catapult.pluginhandlers
tests.catapult.config                                tests.catapult.plugins
tests.catapult.consumers                             tests.catapult.plugins.accountlink
tests.catapult.crypto                                tests.catapult.plugins.aggregate
tests.catapult.crypto_voting                         tests.catapult.plugins.coresystem
tests.catapult.deltaset                              tests.catapult.plugins.hashcache
tests.catapult.diagnostics                           tests.catapult.plugins.lockhash
tests.catapult.disruptor                             tests.catapult.plugins.locksecret
tests.catapult.extensions                            tests.catapult.plugins.metadata
tests.catapult.filespooling                          tests.catapult.plugins.mosaic
tests.catapult.finalization                          tests.catapult.plugins.multisig
tests.catapult.handlers                              tests.catapult.plugins.namespace
tests.catapult.harvesting                            tests.catapult.plugins.restrictionaccount
tests.catapult.hashcache                             tests.catapult.plugins.restrictionmosaic
tests.catapult.int.mongo                             tests.catapult.plugins.signature
tests.catapult.int.mongo.plugins.lockhash            tests.catapult.plugins.transfer
tests.catapult.int.mongo.plugins.locksecret          tests.catapult.sdk
tests.catapult.int.mongo.plugins.metadata            tests.catapult.state
tests.catapult.int.mongo.plugins.mosaic              tests.catapult.subscribers
tests.catapult.int.mongo.plugins.multisig            tests.catapult.sync
tests.catapult.int.mongo.plugins.namespace           tests.catapult.syncsource
tests.catapult.int.mongo.plugins.restrictionaccount  tests.catapult.thread
tests.catapult.int.mongo.plugins.restrictionmosaic   tests.catapult.timesync
tests.catapult.int.node                              tests.catapult.transactionsink
tests.catapult.int.node.stress                       tests.catapult.tree
tests.catapult.int.stress                            tests.catapult.unbondedpruning
tests.catapult.io                                    tests.catapult.utils
tests.catapult.ionet                                 tests.catapult.validators
tests.catapult.keylink                               tests.catapult.zeromq
tests.catapult.local.broker
```

以上。