Travis CI にて、C++11のソースをgccとclangの両方でビルドする


このエントリーをはてなブックマークに追加

githubレポジトリと簡単に連携できる継続的インテグレーションサービスであるTravis CIを使って、C++11で書かれたソースコードをテストできるようにしました。想像以上に大変だったのでメモしておきます。

ソースコードとテストコードの準備

Travis CIで提供される仮想マシンLinuxOS Xなので、Visual Studio向けのコードはビルドできません。MakefileやCMakeなどコンソールからビルドできる仕組みを用意する必要があります。

今回は以下のような簡単なMakefileを用意しました。

CXX = g++
CPPFLAGS = -I3rdparty/catch -IMyVector
CXXFLAGS = -std=c++11
TARGET = test

$(TARGET): MyVectorTest/main.cpp MyVectorTest/test_constructor.cpp
        $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@

clean:
        rm -r $(TARGET)

単に

$ make

とすればg++でビルドできますし、

$ make CXX=clang++

などと変数を引数で指定すればclangでもビルドできます。

今回は、このMakefileを使い、gccとclangの両方でC++11のコードをビルドすることを目標にします。

参考までに、テストフレームワークには、最近人気があるphilsquared/Catchを使っています。ただし本編には関係ありません。

.travis.ymlの作成

Travis CIで提供されるUbuntuマシンで使えるg++とclang++のバージョンは現時点でそれぞれg++ 4.6.3とclang++ 3.4と古く、C++11には対応してません。そこで、Travis CIの設定ファイル.travis.ymlに、新しいバージョンのg++とclang++が使えるよう設定を加える必要があります。

Web検索をしまくった結果できあがったのが以下の設定ファイルです。g++ 5とclang++ 3.7を使ってC++11のコードがビルドできるようになりました。

sudo: false
language: cpp
compiler:
  - clang++
  - g++

install:
  - if [ "$CXX" = "g++" ]; then export CXXFLAGS="-std=c++11"; fi
  - if [ "$CXX" = "g++" ]; then export CXX="g++-5" CC="gcc-5"; fi
  - if [ "$CXX" = "clang++" ]; then export CXXFLAGS="-std=c++11"; fi
  - if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.7" CC="clang-3.7"; fi

  - make CXXFLAGS="${CXXFLAGS}" CXX="${CXX}"

addons:
  apt:
    sources:
      - ubuntu-toolchain-r-test
      - llvm-toolchain-precise-3.7
      - llvm-toolchain-precise
    packages:
      - clang-3.7
      - g++-5
      - gcc-5

script:
  - ./test

addonsの項で何が起こっているのか正確に理解していませんが、とにかくこれがミソのようです。後は変数CXX, CXXFLAGSに適当な変数を代入して、makeの引数として渡せばOKです。

蛇足ですが、このコードにたどり着く前は、以下のようにapt-getや自力ビルドを駆使してg++とclang++を用意していました。複雑な上に時間もかかり不経済なので、このコードを使う必要はまったくありません。

language: cpp
compiler:
    - clang++
    - g++
before_install:
  # g++4.8.1
  - if [ "$CXX" == "g++" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi

  # clang 3.4
  - if [ "$CXX" == "clang++" ]; then sudo add-apt-repository -y ppa:h-rayflood/llvm; fi

  - sudo apt-get update -qq

install:
  # g++4.8.1
  - if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.8; fi
  - if [ "$CXX" = "g++" ]; then export CXXFLAGS="-std=c++11"; fi
  - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8"; fi

  # clang 3.4
  - if [ "$CXX" == "clang++" ]; then sudo apt-get install --allow-unauthenticated -qq clang-3.4; fi
  - if [ "$CXX" == "clang++" ]; then export CXXFLAGS="-std=c++0x -stdlib=libc++"; fi
  - if [ "$CXX" == "clang++" ]; then svn co --quiet http://llvm.org/svn/llvm-project/libcxx/trunk libcxx; fi

  - if [ "$CXX" == "clang++" ]; then cd libcxx/lib && bash buildit; fi
  - if [ "$CXX" == "clang++" ]; then sudo cp ./libc++.so.1.0 /usr/lib/; fi
  - if [ "$CXX" == "clang++" ]; then sudo mkdir /usr/include/c++/v1; fi
  - if [ "$CXX" == "clang++" ]; then cd .. && sudo cp -r include/* /usr/include/c++/v1/; fi
  - if [ "$CXX" == "clang++" ]; then cd /usr/lib && sudo ln -sf libc++.so.1.0 libc++.so; fi
  - if [ "$CXX" == "clang++" ]; then sudo ln -sf libc++.so.1.0 libc++.so.1 && cd $cwd; fi
  - if [ "$CXX" == "clang++" ]; then export CXX="clang++-3.4"; fi

  - cd ${TRAVIS_BUILD_DIR}
  - ls
  - make CXXFLAGS="${CXXFLAGS}" CXX="${CXX}"
  - ls

script:
  - chmod ugo+x test
  - ./test

ビルド例

githubminus9d/MyVectorTravis CIでテストできるようにしています。この記事執筆時点でのテスト成功例は Build #34 - minus9d/MyVector - Travis CI です。

参考リンク