Ubuntuでc++17のために最新版のg++, boost, cmakeを自然に使う


2019年12月23日 追記
この記事の内容を汎化して、間違いなく継続的アップデートが可能なアップデート方法を記事にし直しました。この内容を修正したものとなっているので、そちらをご覧ください
https://qiita.com/forno/items/11c4a0f8169d987f232b

c++17を使いたい!

c++17もほとんど決まり、どんどん使い始めて良いかと思っている人は多いと思います。
しかし、最新のUbuntu LTSである16.04ではデフォルトでc++17に完全に対応した環境になりません。

自然とc++17が使える環境を目指して、最新版のソフトウェアを入手しましょう。

目標

  • CmakeLists.txtではCheckCXXCompilerFlag Moduleによる-std=c++1zの検出か、CXX_STANDARD による17の指定でc++17を有効にする。
  • CmakeLists.txtでfind_package(Boost)と指定することで導入した(最新の)Boostを探し当てる。
  • cmake コマンドを普通に実行して最新の機能を使う。
  • コンパイラは環境変数CXX,CCあるいはcmake実行時に渡してもらう前提で、g++を最新版に置き換えはしない。
  • 既存の環境を覆い隠すが、そのまま残すことでいつでも戻せる状態にしておく。(/usr/localを用いる)
  • 継続的にアップデートするために、メジャーアップデートを追いかけられるppaかGit repositoryのみを使用する。
  • システムインストールなのでソースコードのディレクトリ位置には依存しない。

gcc 最新版を入手

最新のgccは単一のppaで追いかけることができる。
本当はtest版では無い方を用いたほうがstableだと思うが、c++17を利用するにはgcc 7以降が欲しい。
よってtest用ppaを使用する。ちなみに依存関係で自動的にc++17用標準ライブラリも手に入る。

sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt update
sudo apt install -y g++-7

gcc 環境設定

環境変数CXXとCCを定義して、g++-7をデフォルトで使ってもらいやすくしておきます。

echo "export CXX='g++-7'" >> ~/.bashrc
echo "export CC='gcc-7'" >> ~/.bashrc

ここまでできたら一度端末をすべて閉じて開きなおすと良いです。

gcc インストール確認方法

g++-7 --version で何か表示される。失敗しているとコマンドが見つからないと言われます。

boost リリース最新をインストール

Boostを継続して追いかけられるppaどころか、最新のBoostを提供するppaも見つからなかった。
仕方がないのでGit repositoryからコンパイルして用いる。
先に言っておくとダウンロードにもコンパイルにも相当時間がかかる。

git clone --recursive [email protected]:boostorg/boost.git
cd boost
./bootstrap.sh
./b2 toolset=gcc-7 --prefix=/usr/local -j5
sudo ./b2 install toolset=gcc-7 --prefix=/usr/local -j5

コンパイル時にはtoolset=gcc-7を指定して、最新のコンパイラで処理しましょう。
途中warningが大量に出ますが、std::auto_ptrやunused valueが騒いでいるだけです。
Boostはc++17へ移行中のものもあるので、大目に見ておきましょう。

j オプションの引数5は並列処理数です。CPUの論理コア数+1にして全く他の仕事をしなければ全力でコンパイルしてくれます。速度が段違いなので論理コア数をきちんと調べて指定すると良いです。

なおBoostに特別な環境設定はいりません。

Note: reason of without develop branch

Boostをソースからコンパイルする手順を見ているとdevelopブランチをコンパイルさせて来ますが、Cmakeから見つけてもらうためにはmaster(default branch)をコンパイルする必要があります。

Boost インストール確認方法

Cmakeを入れた後で確かめます。

Cmake 最新版をインストール

Cmakeも追いかけるどころか最新のppaが見つかりませんでした。
さらにGit repositoryもgithubはミラーで、 https://gitlab.kitware.com/cmake/cmake が真の本体です。
せっかくなのでオリジナルを利用しましょう。

git clone https://gitlab.kitware.com/cmake/cmake.git
cd cmake
./bootstrap --prefix=/usr/local
make -j5
sudo make install

こちらではCXXとCCを判別するようなのでコンパイラの指定はいりません。
自動でc++17を用いてコンパイルが進むはずです。

Cmake 環境設定

echo "export CMAKE_ROOT='/usr/local/share/cmake-3.9'" >> ~/.bashrc

9月2日現在はCmakeのGit repositoryのmasterのヴァージョンは3.9なのでこの指定ですが、
実際のディレクトリを調べるためにls /usr/local/shareを実行してパスを調べてください。

Cmake インストールチェック

cmake --version

まずは上のコマンドが正しく動作することを確認してください。
CMAKE_ROOTに関してエラーが出た場合はパスの指定が間違っている可能性があります。.bashrcとパスの指定を確認してください。

次に適当なディレクトリを作って、コンパイルを試します。
まずはディレクトリにCMakeLists.txtとmain.cppを作成します。

- CMakeLists.txt
- main.cpp
CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(test)

find_package(Boost REQUIRED COMPONENTS system)
find_package(Threads REQUIRED)

include_directories(Boost::boost)

add_executable(main main.cpp)
target_link_libraries(main Boost::system Threads::Threads)

set(TARGETS main)

set_property(TARGET ${TARGETS} PROPERTY CXX_STANDARD 17)
set_property(TARGET ${TARGETS} PROPERTY CXX_STANDARD_REQUIRED ON)
set_property(TARGET ${TARGETS} PROPERTY CXX_EXTENSION OFF)
main.cpp
#include <iostream>
#include <string_view>

#include <boost/asio.hpp>

int main(int argc, char** argv)
{
  namespace asio = boost::asio;
  using asio::ip::tcp;

  asio::io_service io_service;
  tcp::socket socket(io_service);

  boost::system::error_code error;
  socket.connect(tcp::endpoint(asio::ip::address::from_string("127.0.0.1"), 31400), error);

  if (error)
    std::cout << "connect failed : " << error.message() << std::endl;
  else
    std::cout << "connected" << std::endl;
}

ファイルを準備したらcmakeでコンパイルします。

cmake .
make

無事コンパイルできれば全てのインストールと設定は終了です。

#include <string_view>がエラーを吐いた場合はg++-7の設定がおかしいです。

Cmakeがboostライブラリを見つけたが、warnを吐いている場合はCmakeのバージョンが(Boostに比べて)低いです。
Boostのバージョンを下げて再インストールすることで対応しましょう。

以上で全てのインストール作業は終わりです。

Uninstall method

アンインストールするには、次のようにrmで削除してしまいます。

cd /usr/local
sudo rm -f bin/cmake bin/cpack bin/ctest
sudo rm -rf share/cmake-3.9
sudo rm -f lib/libboost*
sudo rm -rf include/boost
sudo apt remove g++-7

また、 .bashrc に設定が3つあるので、テキストファイルで開いて最後の方を見て、

export CXX='g++-7'
export CC='gcc-7'
export CMAKE_ROOT='/usr/local/share/cmake-3.9'

この三行をまるまる削除すればアンインストール完了です。
元の環境に戻っています。