CMakeで作るようにした既存のVisualStudioプロジェクトに、GoogleTestを追加する


概要

既存のCMakeで構築するVisualStudio Projectに対して、GoogleTestを追加してみます。
既存プロジェクトとしては
CMakeを使って、FreeRTOS最小構成のVisualStudioプロジェクト作る
を使います。

Google Test勉強録 (1) CMakeでのビルド が洗練されていると思いますが、
ここではGoogle Testでビルドしたlibを自分のプロジェクト内に置きます。

Google Testをプロジェクトに追加する

Google Testのダウンロード

https://github.com/google/googletest
からダウンロードする。
自身のプロジェクト内で管理するのでzipで落とす。

ビルド

unzipしたgoogletestフォルダ内にbuildフォルダを作ってcmakeします。
buildフォルダをShift押しながら右クリックするとpowershellが開けるので便利です。

でpowershellを開いて
> cmake ..
と入力する。

buildフォルダ内にできた googletest-distribution.sln を起動して、ビルドしましょう。Release, Debug両方しておきます。
ビルドが完了するとbuildフォルダ内にライブラリが生成されます。

|-- lib
|   |-- Debug
|   |   |-- gmock_maind.lib
|   |   |-- gmockd.lib
|   |   |-- gtest_maind.lib
|   |   `-- gtestd.lib
|   `-- Release
|       |-- gmock.lib
|       |-- gmock_main.lib
|       |-- gtest.lib
|       `-- gtest_main.lib

自身のプロジェクトに取り込む

プロジェクト直下にgtestフォルダを掘りました。
includeには、googletestのヘッダーファイルを置き、libフォルダにビルドしたlibを置きます。

Root
|-- CMakeLists.txt ※1
|-- ...
|-- gtest
|   |-- CMakeLists.txt ※2
|   |-- include
|   |   `-- gtest
|   |       |-- gtest.h
|   |       |-- gtest_pred_impl.h
|   |       |-- gtest_prod.h
|   |       |-- gtest-death-test.h
|   |       |-- gtest-matchers.h
|   |       |-- gtest-message.h
|   |       |-- gtest-param-test.h
|   |       |-- gtest-printers.h
|   |       |-- gtest-spi.h
|   |       |-- gtest-test-part.h
|   |       |-- gtest-typed-test.h
|   |       `-- internal
|   |           |-- custom
|   |           |   |-- gtest.h
|   |           |   |-- gtest-port.h
|   |           |   |-- gtest-printers.h
|   |           |   `-- README.md
|   |           |-- gtest-death-test-internal.h
|   |           |-- gtest-filepath.h
|   |           |-- gtest-internal.h
|   |           |-- gtest-param-util.h
|   |           |-- gtest-port.h
|   |           |-- gtest-port-arch.h
|   |           |-- gtest-string.h
|   |           `-- gtest-type-util.h
|   |-- lib
|   |   |-- gmock_maind.lib
|   |   |-- gmockd.lib
|   |   |-- gtest_maind.lib
|   |   `-- gtestd.lib

CMake対応

※1のCMakeLists.txtの修正

gtestの追加

`add_subdirectory(./gtest)`

unicode形式のWarning

自分のプロジェクトにあるFreeRTOSファイルで発生したのエラー。(Warningをコンパイルエラーとしている)

重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
警告 C4819 ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。
重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー C2220 次の警告はエラーとして処理されます gtest_main F:\git-work\cmake_freertos_visualstudio_gtest\FreeRTOS\Source\include\task.h 2065

UTF-8になのが問題
http://tech.hikware.com/article/20171020a.html
を参考にして、CMakeList.txtにadd_definitions(/source-charset:utf-8)を追加。

if (MSVC)
    add_definitions(/source-charset:utf-8)
endif()

で、ほぼ解消しましたが、なぜか1つだけWarningが残ってしまった。。
とりあえず、Warningにはするが、コンパイルエラーとはしない対応にした。

if (MSVC)
    # warning level 4 and all warnings as errors
    add_compile_options(/W4 /WX-)
else()
    # lots of warnings and all warnings as errors
    add_compile_options(-Wall -Wextra -pedantic -Werror)
endif()

↓の設定と同じ

「RuntimeLibrary' の不一致が検出されました」の対応

https://sgry.jp/blog/2017/05/27/4465/
で解決できた

# 
if(MSVC)
    string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_DEBUG            ${CMAKE_C_FLAGS_DEBUG})
    string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_MINSIZEREL       ${CMAKE_C_FLAGS_MINSIZEREL})
    string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE          ${CMAKE_C_FLAGS_RELEASE})
    string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELWITHDEBINFO   ${CMAKE_C_FLAGS_RELWITHDEBINFO})
    string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_DEBUG          ${CMAKE_CXX_FLAGS_DEBUG})
    string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_MINSIZEREL     ${CMAKE_CXX_FLAGS_MINSIZEREL})
    string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE        ${CMAKE_CXX_FLAGS_RELEASE})
    string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
endif(MSVC)

↓の設定と同じ

※2のCMakeLists.txtの修正

cmake_minimum_required(VERSION 3.1)

# lib方式.
include_directories(./include)  # #include "gtest/gtest.h"をするため
...  ※あとのincludeは自身のプロジェクトに合わせる

link_directories(./lib) # Google Testのライブラリをリンク
add_executable(TestSample1 test_sample1.cpp test_freertos.c)

target_link_libraries(TestSample1
 $<TARGET_OBJECTS:freertos>)
target_link_libraries(TestSample1 debug gtestd)      #Debugモード時のリンク
target_link_libraries(TestSample1 optimized gtest)   #Releaseモード時のリンク

※gtest.libをDebugモードですると

重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー LNK2038 '_ITERATOR_DEBUG_LEVEL' の不一致が検出されました。値 '0' が 2 の値 'test_sample1.obj' と一致しません。 TestSample1 F:\git-work\cmake_freertos_visualstudio_gtest\build\test\gtest.lib(gtest-all.obj) 1

となります。
https://ja.stackoverflow.com/questions/9699/debug%E7%89%88%E3%81%A8release%E7%89%88%E3%81%A7%E5%90%8C%E3%81%98lib%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95
にあるように別にする必要があります。(Debug時はgtestd.libを使う)