web-dev-qa-db-ja.com

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

実動ソース(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. test/CMakeLists.txtファイル内のsrcフォルダーのすべてのファイルを一覧表示する必要があるという事実が気に入らない。これがライブラリプロジェクトの場合、ライブラリをリンクするだけです。他のプロジェクトのすべてのcppファイルを一覧表示しないようにする方法はありますか?
  3. enable_testing()およびadd_test(MyTest test)行は何をしていますか?何の効果も見ていません。 CMake(またはCTest)からテストを実行するにはどうすればよいですか?
  4. これまでのところ、ルートフォルダーでcmake .を実行しましたが、これにより、一時ファイルがいたるところに散らかりました。合理的な構造でコンパイル結果を取得するにはどうすればよいですか?
123
Grzenio

質問1と2については、main.cppを除くテスト以外のファイル(この場合はsrc/sqr.cppとsrc/sqr.hのみ)からライブラリを作成することをお勧めします。その後、リストを避けることができます(さらに重要なことです)すべてのソースを2回再コンパイルします。

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

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

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

最後の1つのポイントは、実行可能ファイルの「テスト」の呼び出しを避けることです(大文字と小文字が区別されます)。理由については、 this answer を参照してください。

これらの変更を実現するには、次のことを行います。

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}
                       )
116
Fraser

@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)
45
Mathias