CMake:単体テストを含むプロジェクト構造


139

プロダクションソース(srcサブフォルダー内)とテスト(サブフォルダー内)を含めるようにプロジェクトを構成しようとしていtestます。これを構築するためにCMakeを使用しています。最小限の例として、以下のファイルを用意しています。

CMakeLists.txt:

cmake_minimum_required (VERSION 2.8) 
project (TEST) 

add_subdirectory (src) 
add_subdirectory (test) 

src / CMakeLists.txt:

add_executable (demo main.cpp sqr.cpp) 

src / sqr.h

#ifndef SQR_H
#define SQR_H
double sqr(double);    
#endif // SQR_H

src / sqr.cpp

#include "sqr.h"
double sqr(double x) { return x*x; }

src / main.cpp-sqrを使用しますが、問題にはなりません

test / CMakeLists.txt:

find_package(Boost COMPONENTS system filesystem unit_test_framework REQUIRED)

include_directories (${TEST_SOURCE_DIR}/src) 

ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK) 

add_executable (test test.cpp ${TEST_SOURCE_DIR}/src/sqr.cpp) 

target_link_libraries(test
                      ${Boost_FILESYSTEM_LIBRARY}
                      ${Boost_SYSTEM_LIBRARY}
                      ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
                      )

enable_testing()
add_test(MyTest test)

test / test.cpp:

#define BOOST_TEST_MODULE SqrTests
#include <boost/test/unit_test.hpp>

#include "sqr.h"

BOOST_AUTO_TEST_CASE(FailTest)
{
    BOOST_CHECK_EQUAL(5, sqr(2));
}

BOOST_AUTO_TEST_CASE(PassTest)
{
    BOOST_CHECK_EQUAL(4, sqr(2));
}

いくつかの質問:

  1. この構造は意味がありますか?このコードを構築する際のベストプラクティスは何ですか?(私はC#とJavaから来ています、そしてそれはある意味で簡単です)
  2. ファイルsrc内のフォルダーからすべてのファイルを一覧表示する必要があるという事実が好きではありませんtest/CMakeLists.txt。これがライブラリプロジェクトである場合、ライブラリをリンクするだけです。他のプロジェクトのすべてのcppファイルを一覧表示しないようにする方法はありますか?
  3. ラインenable_testing()とは何add_test(MyTest test)ですか?影響は見られません。CMake(またはCTest)からテストを実行するにはどうすればよいですか?
  4. これまでのところcmake .、ルートフォルダーで実行しただけですが、これにより、一時ファイルがどこにでも散らかっています。コンパイル結果を合理的な構造で取得するにはどうすればよいですか?

私はCMakeの初心者なので、受け入れられているベストプラクティスが何なのかはわかりませんが、FWIWでは、メインとテストの両方に依存する「sqr」ライブラリ*を作成します。(*またはその道徳的同等物)
user786653 2013年

回答:


125

質問1と2については、main.cpp(この場合はsrc / sqr.cppとsrc / sqr.hだけ)を除いた非テストファイルからライブラリを作成することをお勧めします。すべてのソースを2回再コンパイルします。

質問3の場合、これらのコマンドは、引数なしで実行可能な「テスト」を呼び出す「MyTest」と呼ばれるテストを追加します。ただし、これらのコマンドは、最上位のCMakeLists.txtではなくtest / CMakeLists.txtに追加したため、ビルドツリーの「test」サブディレクトリ内からのみテストを呼び出すことができます(cd test && ctest -N)。トップレベルのビルドディレクトリからテストを実行できるようにする場合はadd_test、トップレベルのCMakeLists.txtから呼び出す必要があります。これadd_testは、テストのexeが同じCMakeLists.txtで定義されていないため、より冗長な形式を使用する必要があることも意味します。

あなたの場合、ルートフォルダーでcmakeを実行しているため、ビルドツリーとソースツリーはまったく同じです。これはインソースビルドと呼ばれ、理想的ではないため、質問4に進みます。

ビルドツリーを生成するための推奨される方法は、ソース外のビルドを実行することです。つまり、ソースツリーの外のどこかにディレクトリを作成し、そこからcmakeを実行します。プロジェクトのルートに「ビルド」ディレクトリを作成して実行するcmake ..だけでも、ソースツリーに干渉しないクリーンな構造が得られます。

最後のポイントの1つは、実行可能ファイルを "test"(大文字と小文字を区別)と呼ばないようにすることです。理由については、この回答をご覧ください。

これらの変更を実現するには、次のようにします。

CMakeLists.txt:

cmake_minimum_required (VERSION 2.8)
project (TEST)
add_subdirectory (src) 
add_subdirectory (test)
enable_testing ()
add_test (NAME MyTest COMMAND Test)


src / CMakeLists.txt:

add_library (Sqr sqr.cpp sqr.h)
add_executable (demo main.cpp)
target_link_libraries (demo Sqr)


test / CMakeLists.txt:

find_package (Boost COMPONENTS system filesystem unit_test_framework REQUIRED)
include_directories (${TEST_SOURCE_DIR}/src
                     ${Boost_INCLUDE_DIRS}
                     )
add_definitions (-DBOOST_TEST_DYN_LINK)
add_executable (Test test.cpp)
target_link_libraries (Test
                       Sqr
                       ${Boost_FILESYSTEM_LIBRARY}
                       ${Boost_SYSTEM_LIBRARY}
                       ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
                       )

2
あなたはそれに応じて.hファイルもCMakeLists.txtファイルに追加したことに気づきました。必要ですか?そして、それらを除外するとどうなりますか?
Grzenio 2013年

3
@Grzenioこれは便利な機能です-それらはターゲットの一部としてMSVCのようなIDEに表示されますが、それ以外の場合は効果がありません。
Fraser

1
TEST_SOURCE_DIRはどこに設定されていますか?
aggsol

6
これは、呼び出し時にCMakeによって自動的に設定されproject (TEST)ます-cmake.org/cmake/help/v3.6/variable/PROJECT-NAME_SOURCE_DIR.htmlを
Fraser

>それらはターゲットの一部としてMSVCのようなIDEに表示されます--- MSVCはヘッダーを含むディレクトリを「インクルードディレクトリ」としてマークすることをサポートしていませんか?
isnullxbh 2018年

46

@Fraserの例が好きですが、test / CMakeLists.txtでadd_testコマンドを使用し、add_subdirectory(test)の前にenable_testingを使用します。

このようにして、test / CMakeLists.txtでテストを指定しながら、最上位のビルドディレクトリからテストを実行できます。

結果は次のようになります(@Fraserの例を再利用しました)。

CMakeLists.txt

cmake_minimum_required (VERSION 2.8)
project (TEST)
add_subdirectory (src)

enable_testing ()
add_subdirectory (test)

src / CMakeLists.txt

add_library (Sqr sqr.cpp sqr.h)
add_executable (demo main.cpp)
target_link_libraries (demo Sqr)

test / CMakeLists.txt

find_package (Boost COMPONENTS system filesystem unit_test_framework REQUIRED)
include_directories (${TEST_SOURCE_DIR}/src
                     ${Boost_INCLUDE_DIRS}
                     )
add_definitions (-DBOOST_TEST_DYN_LINK)
add_executable (Test test.cpp)
target_link_libraries (Test
                       Sqr
                       ${Boost_FILESYSTEM_LIBRARY}
                       ${Boost_SYSTEM_LIBRARY}
                       ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
                       )
add_test (NAME MyTest COMMAND Test)

1
おかげでctest -N、サブディレクトリを追加する前にテストを有効にすることについてのヒントまで、テストは表示されませんでした。
alaferg 2016年

@alaferg:そうしないと、ビルドディレクトリ内のテストサブディレクトリになります。
gauteh 2017年

4
CMakeが構造に似たものを持っていればいいのに。
ruipacheco
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.