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

답변:


125

질문 1 및 2의 경우 main.cpp (이 경우 src / sqr.cpp 및 src / sqr.h)를 제외한 테스트 파일이 아닌 파일에서 라이브러리를 만드는 것이 좋습니다. 그러면 목록을 피할 수 있습니다 (더 중요하게 모든 소스를 두 번 다시 컴파일하십시오.

질문 3의 경우,이 명령은 "MyTest"라는 테스트를 추가하여 인수없이 실행 가능한 "test"를 호출합니다. 그러나 최상위 CMakeLists.txt가 아닌 test / CMakeLists.txt에 이러한 명령을 추가 했으므로 빌드 트리의 "test"서브 디렉토리 내에서만 테스트를 호출 할 수 있습니다 (try cd test && ctest -N). 최상위 빌드 디렉토리에서 테스트를 실행 add_test하려면 최상위 CMakeLists.txt에서 호출해야합니다 . 또한 add_test테스트 exe가 동일한 CMakeLists.txt에 정의되어 있지 않기 때문에 더 자세한 형태를 사용해야 함을 의미합니다.

귀하의 경우 루트 폴더에서 cmake를 실행하기 때문에 빌드 트리와 소스 트리가 동일합니다. 이것은 소스 빌드로 알려져 있으며 이상적이지 않으므로 질문 4로 이어집니다.

빌드 트리를 생성하는 데 선호되는 방법은 소스 외부 빌드를 수행하는 것입니다. 즉, 소스 트리 외부에 디렉토리를 작성하고 cmake를 실행하는 것입니다. 프로젝트 루트에 "빌드"디렉토리를 만들고 실행하더라도 cmake ..소스 트리를 방해하지 않는 깔끔한 구조를 제공 할 수 있습니다.

마지막으로 실행 파일을 "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

3
@Grzenio 이것은 편리한 기능 일뿐입니다. IDE의 경우 MSVC와 같은 IDE에 대상의 일부로 나타나지만, 그렇지 않으면 효과가 없습니다.
Fraser

1
TEST_SOURCE_DIR은 어디에 설정되어 있습니까?
aggsol

6
호출이 때 자동으로 CMake에 의해 설정되어 project (TEST)볼 - cmake.org/cmake/help/v3.6/variable/PROJECT-NAME_SOURCE_DIR.html
프레이저

> 타겟의 일부로 MSVC와 같은 IDE에 나타납니다. --- MSVC는 헤더가있는 디렉토리를 "include directory"로 표시하는 것을 지원하지 않습니까?
isnullxbh

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 -Nsubdir을 추가하기 전에 테스트 활성화에 대한 팁이 나올 때까지 테스트를 보여주지 않았습니다 .
alaferg

@alaferg : 그렇지 않으면 빌드 디렉토리 내부의 테스트 하위 디렉토리로 끝납니다.
gauteh

4
CMake가 구조와 비슷한 것을 원했습니다.
ruipacheco
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.