目標
- c++14の並列計算(openmp)プログラムを書く
- g++-5で動けばよい(他のコンパイラだと手直しが必要)
- openmpが含まれているテストをgtestで書く
- とりあえず手元のPC(Ubuntu)で動くまで検証する(Macなど環境が違うとうまくいかないかもしれません)
- 参考
利用するソフト
環境
- 環境1
- Ubuntu 16.04
- cmake 3.5
- g++5.4 (system default)
 
- 環境2
- Ubuntu 14.04
- cmake 2.8
- g++5.4 (sudo apt-get install g++-5)
 
使い方
コンパイル
git clone https://takeshi-uchitane@bitbucket.org/takeshi-uchitane/cmake_c-14_openmp_gtests.git
cd cmake_c-14_openmp_gtests
mkdir build
cd build
cmake .. # if you have another version of g++, you should set CXX=g++-5
make
実行
- OpenMPを利用するプログラムのテストができた
$ ./utest/tests/Foo/foo-test 
Running main() from gtest_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from Foo
[ RUN      ] Foo.constractor
thread 3
thread 1
thread thread 2
0
[       OK ] Foo.constractor (53 ms)
[----------] 1 test from Foo (53 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (53 ms total)
[  PASSED  ] 1 test.
ソースコード
Foo class
- OPM並列プログラムとそのテスト
src/Foo.cpp
# include "Foo.hpp"
# include <omp.h>
# include <iostream>
Foo::Foo() { for(unsigned int i=0u;i<4u;i++) { v.push_back(i); } }
std::vector<double> Foo::calc() {
  std::vector<double> array(v.size());
# pragma omp parallel for
  for(unsigned int i=0u;i<v.size();i++) {
    array[i]=double(v[i]);
    std::cout << "thread " << omp_get_thread_num() << std::endl;
  }
  sort(array.begin(), array.end());
  return std::move(array);
}
utest/tests/Foo/main.cpp
# include <gtest/gtest.h>
# include <gmock/gmock.h>
# include "Foo.hpp"
TEST(Foo, constractor) {
  Foo foo;
  EXPECT_THAT(foo.v, testing::ElementsAre(0,1,2,3));
  EXPECT_THAT(foo.calc(), testing::ElementsAre(0.0,1.0,2.0,3.0));
}
CmakeLists.txt
- CMakeLists.txtはプロジェクト用とテスト用の2つ
- OPENMPのフラグ(OpenMP_CXX_FLAGS)はテストを追加する前に見つけておく
CmakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# if you use special compiler, set the compiler
# SET(CMAKE_CXX_COMPILER  "g++-5")
# or
# set option -DCMAKE_CXX_COMPILER="g++-5"
PROJECT(hoge CXX)
include_directories(${PROJECT_SOURCE_DIR}/include)
aux_source_directory(${PROJECT_SOURCE_DIR}/src SOURCES)
ADD_EXECUTABLE(hoge.out main.cpp ${SOURCES})
if (NOT DEFINED ${CMAKE_CXX_FLAGS})
  SET (CMAKE_CXX_FLAGS "-Wall -O3 -std=c++14")
  find_package(OpenMP)
  if (OPENMP_FOUND)
    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
  endif()
endif ()
MESSAGE( STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS} )
# gtest
if(NOT without-test)
  enable_testing()
  include(${PROJECT_SOURCE_DIR}/utest/include/gtest.cmake)
  add_subdirectory(${PROJECT_SOURCE_DIR}/utest/tests)
endif()
utest/test/Foo/CmakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_executable(foo-test main.cpp ${SOURCES})
target_link_libraries(foo-test
  gtest
  gtest_main
  gmock
  gmock_main
  pthread
)
add_test(
  NAME foo
  COMMAND $<TARGET_FILE:foo-test>
  )
# run with: ctest -L lib
set_property(
  TEST foo
  PROPERTY LABELS lib foo
  )
gtest.cmake
- ダウンドーロ先のURLをgtest-1.8用に変更
- gmockはgtest1.8からgtestに統合された(gmockを別途インストールする必要は無い)
- 統合によりincludeファイルのパスが変更された
- ${source_dir}/googletest/include
- ${source_dir}/googlemock/include
 
- 静的ライブラリの作成されるパスが微妙(なんでこんなパスにしたんでしょう)
- ${binary_dir}/googlemock/gtest/libgtest.a
- ${binary_dir}/googlemock/gtest/libgtest_main.a
- ${binary_dir}/googlemock/libgmock.a
- ${binary_dir}/googlemock/libgmock_main.a
 
utest/include/gtest.cmake
cmake_minimum_required(VERSION 2.8)
# Google Test settings
include(ExternalProject)
ExternalProject_Add(
    GoogleTest
    URL https://github.com/google/googletest/archive/release-1.8.0.zip
    CMAKE_ARGS -DCMAKE_CXX_COMPILER=g++-5;-DCMAKE_C_COMPILER=gcc-5
    PREFIX ${CMAKE_CURRENT_BINARY_DIR}/lib
    INSTALL_COMMAND ""
    LOG_DOWNLOAD ON
    LOG_CONFIGURE ON
    LOG_BUILD ON
    )
ExternalProject_Get_Property(GoogleTest source_dir)
include_directories(${source_dir}/googletest/include)
include_directories(${source_dir}/googlemock/include)
ExternalProject_Get_Property(GoogleTest binary_dir)
add_library(gtest STATIC IMPORTED)
set_property(
    TARGET gtest
    PROPERTY IMPORTED_LOCATION ${binary_dir}/googlemock/gtest/libgtest.a
    )
add_library(gtest_main STATIC IMPORTED)
set_property(
    TARGET gtest_main
    PROPERTY IMPORTED_LOCATION ${binary_dir}/googlemock/gtest/libgtest_main.a
    )
add_library(gmock STATIC IMPORTED)
set_property(
    TARGET gmock
    PROPERTY IMPORTED_LOCATION ${binary_dir}/googlemock/libgmock.a
    )
add_library(gmock_main STATIC IMPORTED)
set_property(
    TARGET gmock_main
    PROPERTY IMPORTED_LOCATION ${binary_dir}/googlemock/libgmock_main.a
    )
所感
- 自分のメモ用に初投稿
- 以下のニーズを満たした開発環境が欲しかった
- c++-14で書きたい
- 並列計算プログラムが必要
- TDDしたい
- cmake使いたい
 
- 探したけど,上記が統合されている開発環境は落ちていなかった
- きっとニッチな要求なんだろう
- じゃあ,作ろう
 
- gtest1.7とgmock1.7用に作っていたがダウンロードURLが変更になったり,仕様が変わっていたりで手間取ったのでメモを共有