目標
- 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が変更になったり,仕様が変わっていたりで手間取ったのでメモを共有