連絡先 最初に戻る 戻る 次へ進む
$Date: 2017-05-14 17:13:45 +0900 (2017/05/14 (日)) $
$Revision: 1130 $

cmake での googletest

概要

googletest を cmake で使う方法を説明します。

サンプルプロジェクト

https://github.com/m-tmatma/googletest-sample-cmake に格納されています。

取得方法

git clone --recursive https://github.com/m-tmatma/googletest-sample-cmake.git
or
git clone https://github.com/m-tmatma/googletest-sample-cmake.git
git submodule init
git submodule update

プロジェクトの生成方法

以下のように実行してプロジェクトを生成すれば Shared Library (DLL) になります。
mkdir build-on
cd    build-on
cmake -D BUILD_SHARED_LIBS=1 ..\googletest-sample-cmake\
以下のように実行してプロジェクトを生成すれば Static Library になります。
mkdir build-off
cd    build-off
cmake -D BUILD_SHARED_LIBS=0 ..\googletest-sample-cmake\

サンプルのプロジェクトの構成

│  CMakeLists.txt
│  runtime.cmake
│
├─googletest
│
├─src
│      CMakeLists.txt
│      calc.cpp
│      calc.h
│
└─tests
        CMakeLists.txt
        test.cpp
        test2.cpp

トップのruntime.cmakeの定義

########################################################################################################
# see https://cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
########################################################################################################
if (NOT BUILD_SHARED_LIBS)
    foreach(flag_var
            CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
            CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
       if(${flag_var} MATCHES "/MD")
          string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
       endif(${flag_var} MATCHES "/MD")
    endforeach(flag_var)
endif (NOT BUILD_SHARED_LIBS)

BUILD_SHARED_LIBS が OFF のとき (static ライブラリのとき) /MT オプションを指定することで C のランタイムを static バージョンを使うようにします。

トップのプロジェクトの定義

CMakeLists.txt
# set 3.6 to use VS_STARTUP_PROJECT
cmake_minimum_required(VERSION 3.6)

project (googletest-sample-cmake)

option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
if (APPLE)
  set(CMAKE_MACOSX_RPATH 1)
endif(APPLE)

# switch DLL or static libary by specifying by command line
set (LIB_TYPE STATIC)
if (BUILD_SHARED_LIBS)
  # User wants to build Dynamic Libraries, so change the LIB_TYPE variable to CMake keyword 'SHARED'
  set (LIB_TYPE SHARED)
endif (BUILD_SHARED_LIBS)

# set Target Directories
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

add_subdirectory(googletest)
add_subdirectory(src)
add_subdirectory(tests)

# set Startup Project
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT "tests" )

# turn on solution folder
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

# create solution folder
set_target_properties(gmock       PROPERTIES FOLDER GoogleTest)
set_target_properties(gmock_main  PROPERTIES FOLDER GoogleTest)
set_target_properties(gtest       PROPERTIES FOLDER GoogleTest)
set_target_properties(gtest_main  PROPERTIES FOLDER GoogleTest)
set_target_properties(calc        PROPERTIES FOLDER library)
set_target_properties(tests       PROPERTIES FOLDER executable)
Mac で警告ができるので以下を指定します。
if (APPLE)
  set(CMAKE_MACOSX_RPATH 1)
endif(APPLE)
以下定義で BUILD_SHARED_LIBS が ON(1) になっていたら ${LIB_TYPE} は SHARED (Shared Library) になります。
# switch DLL or static libary by specifying by command line
set (LIB_TYPE STATIC)
if (BUILD_SHARED_LIBS)
  # User wants to build Dynamic Libraries, so change the LIB_TYPE variable to CMake keyword 'SHARED'
  set (LIB_TYPE SHARED)
endif (BUILD_SHARED_LIBS)
BUILD_SHARED_LIBS が OFF(0) になっていたら ${LIB_TYPE} は STATIC (Static Library) になります。
そして BUILD_SHARED_LIBS はコマンドラインで cmake を実行するときに上書きすることができます。

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) でライブラリ出力先フォルダを指定します。
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) で実行ファイルの出力先フォルダを指定します。
CMAKE_BINARY_DIR の変数はビルドディレクトリのトップディレクトリを表します

CMake : out-of-sourceビルドで幸せになるを参考

add_subdirectory(googletest) 等でサブディレクトリをビルド対象にしています。

# turn on solution folder
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

# create solution folder
set_target_properties(gmock       PROPERTIES FOLDER GoogleTest)
set_target_properties(gmock_main  PROPERTIES FOLDER GoogleTest)
set_target_properties(gtest       PROPERTIES FOLDER GoogleTest)
set_target_properties(gtest_main  PROPERTIES FOLDER GoogleTest)
set_target_properties(calc        PROPERTIES FOLDER library)
set_target_properties(tests       PROPERTIES FOLDER executable)
set_property(GLOBAL PROPERTY USE_FOLDERS ON) でソリューションフォルダの機能を有効にします。
set_target_properties(tests PROPERTIES FOLDER executable) で tests というプロジェクトを executable というソリューションフォルダに入れています。
GoogleTest 関連のプロジェクトは GoogleTest というフォルダに入れます

src のプロジェクトの定義

Library/CMakeLists.txt
cmake_minimum_required(VERSION 2.6.4)

include (../runtime.cmake)

# define a variable of project name
set( project_name calc)

# define a variable of project name
project (${project_name})

# define a variable SRC with file GLOB
file(GLOB SRC *.cpp *.h)

# define as exports
if (BUILD_SHARED_LIBS)
  add_definitions(-D${project_name}_EXPORTS)
endif (BUILD_SHARED_LIBS)

# add include directory for ${project_name}_Export.h
include_directories(${PROJECT_BINARY_DIR})

# define sources files of an executable
ADD_LIBRARY(${project_name} ${LIB_TYPE} ${SRC} ${PROJECT_BINARY_DIR}/${project_name}_Export.h)

include (GenerateExportHeader)
GENERATE_EXPORT_HEADER( ${project_name}
	BASE_NAME ${project_name}
	EXPORT_MACRO_NAME ${project_name}_EXPORT
	EXPORT_FILE_NAME ${project_name}_Export.h
	STATIC_DEFINE ${project_name}_BUILT_AS_STATIC
)
親ディレクトリある runtime.cmake を読み込みます。

include (../runtime.cmake)

include_directories でインクルードディレクトリを指定します
${PROJECT_BINARY_DIR} はこのプロジェクトに対応するビルドディレクトリを意味します。

add_library でライブラリを定義します。${LIB_TYPE} のところで SHARED を指定すると shared Library(Windows ではDLL)になり,
STATIC を指定するとスタティックライブラリになります。

トップディレクトリにある CMakeLists.txt でこの変数を定義します。

以下の指定では calc_Export.h というDLL のインポート、エクスポート指定のためのヘッダファイルを作成するための命令です。
include (GenerateExportHeader)
GENERATE_EXPORT_HEADER( ${project_name}
	BASE_NAME ${project_name}
	EXPORT_MACRO_NAME ${project_name}_EXPORT
	EXPORT_FILE_NAME ${project_name}_Export.h
	STATIC_DEFINE ${project_name}_BUILT_AS_STATIC
)
以下のようなヘッダファイルが出力先に生成されます。これは Windows で実行したときの内容です。Mac や Linux では内容は異なります。
このファイルをインクルードするために include_directories(${PROJECT_BINARY_DIR}) の指定をしています。

#ifndef calc_EXPORT_H
#define calc_EXPORT_H

#ifdef calc_BUILT_AS_STATIC
#  define calc_EXPORT
#  define CALC_NO_EXPORT
#else
#  ifndef calc_EXPORT
#    ifdef calc_EXPORTS
        /* We are building this library */
#      define calc_EXPORT __declspec(dllexport)
#    else
        /* We are using this library */
#      define calc_EXPORT __declspec(dllimport)
#    endif
#  endif

#  ifndef CALC_NO_EXPORT
#    define CALC_NO_EXPORT 
#  endif
#endif

#ifndef CALC_DEPRECATED
#  define CALC_DEPRECATED __declspec(deprecated)
#endif

#ifndef CALC_DEPRECATED_EXPORT
#  define CALC_DEPRECATED_EXPORT calc_EXPORT CALC_DEPRECATED
#endif

#ifndef CALC_DEPRECATED_NO_EXPORT
#  define CALC_DEPRECATED_NO_EXPORT CALC_NO_EXPORT CALC_DEPRECATED
#endif

#if 0 /* DEFINE_NO_DEPRECATED */
#  ifndef CALC_NO_DEPRECATED
#    define CALC_NO_DEPRECATED
#  endif
#endif

#endif

exe のプロジェクトの定義

tests/CMakeLists.txt
cmake_minimum_required(VERSION 2.6.4)

include (../runtime.cmake)

# define a variable of project name
set( project_name tests)

# define a project name
project (${project_name})

# define a variable SRC with file GLOB
file(GLOB SRC *.cpp *.h)

# add include directories
include_directories(../googletest/googletest/include)
include_directories(../src)

# add include directory for ${project_name}_Export.h
include_directories(${PROJECT_BINARY_DIR}/../src)

# define sources files of an executable
add_executable(${project_name} ${SRC})

# link libraries
target_link_libraries(${project_name} gtest)
target_link_libraries(${project_name} gtest_main)
target_link_libraries(${project_name} calc)

include_directories でインクルードディレクトリの指定をしていますが、 ${PROJECT_BINARY_DIR} を参照する場合、Program のプロジェクトに対する生成ディレクトリなので calc のプロジェクトに対するフォルダを指定する必要があるので ../src を追加しています。

target_link_libraries でリンクするライブラリを指定しています。GoogleTest の gtest と gtest_main と calc をリンクしています。