Edited at

c++14 with openmp + gtest-1.8のcmake環境を整備する

More than 1 year has passed since last update.


目標


  • c++14の並列計算(openmp)プログラムを書く

  • g++-5で動けばよい(他のコンパイラだと手直しが必要)

  • openmpが含まれているテストをgtestで書く

  • とりあえず手元のPC(Ubuntu)で動くまで検証する(Macなど環境が違うとうまくいかないかもしれません)

  • 参考




利用するソフト


  • gtest-1.8


  • gmock(gtest-1.8に統合されたので不要)

  • cmake

  • g++-5 (c++14 and openmp)


環境


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