Как использовать CMake с Catch2?
Из примера Catch2 я попытался запустить этот пример с cmake
где структура моего проекта такая:
/factorial
+-- CMakeLists.txt
+-- /bin
+-- /include
| +-- catch.hpp
| +-- fact.hpp
+-- /src
| +-- CMakeLists.txt
| +-- fact.cpp
+-- /test
+-- CMakeLists.txt
+-- test_fact.cpp
fact.cpp
:
unsigned int factorial( unsigned int number ) {
return number <= 1 ? number : factorial(number-1)*number;
}
fact.hpp
:
#ifndef FACT_H
#define FACT_H
unsigned int factorial(unsigned int);
#endif
test_fact.cpp
:
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "fact.hpp"
TEST_CASE( "factorials are computed", "[factorial]" ) {
REQUIRE( factorial(1) == 1 );
REQUIRE( factorial(2) == 2 );
REQUIRE( factorial(3) == 6 );
REQUIRE( factorial(10) == 3628800 );
}
Я уже пробовал несколько способов построить этот проект с cmake
но это не удалось. Иногда я получаю ошибку:
cpp:X:XX: fatal error: 'fact.hpp' file not found
...
и иногда я получаю:
Undefined symbols for architecture x86_64:
"_main", referenced from:
...
когда я бегу make
,
Что я должен иметь в factorial/CMakeLists.txt
,factorial/src/CMakeLists.txt
а также factorial/test/CMakeLists.txt
, если я хочу, чтобы мои файлы выполнения в factorial/bin
?
Дополнительно: это мой CMakeLists.txts (я думаю, что они совершенно не правы).
factorial/CMakeLists.txt
:
project(factorial)
cmake_minimum_required(VERSION 2.8.12)
add_definitions("-std=c++11")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
add_subdirectory(src)
add_subdirectory(test)
factorial/src/CMakeLists.txt
:
project(factorial)
cmake_minimum_required(VERSION 2.8.12)
add_executable(fact fact.cpp)
factorial/test/CMakeLists.txt
:
project(factorial)
cmake_minimum_required(VERSION 2.8.12)
add_executable(test_fact test_fact.cpp)
target_include_directories(test_fact PRIVATE ${CMAKE_SOURCE_DIR}/include)
2 ответа
Здесь много проблем:
add_executable(fact fact.cpp)
Вызов должен использовать add_library
(Вы также можете указать STATIC
или же SHARED
), поскольку вы определяете только факториальную функцию, а не исполняемый файл с main
функция
add_executable(fact fact.cpp)
Файл должен быть test_fact.cpp
, Кроме того, ваш fact.cpp
не включает fact.hpp
, Не в последнюю очередь, вместо того, чтобы делать target_include_directories
, просто напишите следующее на вашем верхнем уровне CMakeLists.txt
:
include_directories(include)
Теперь все подкаталоги должны иметь доступ к заголовочным файлам. Помните, что это удаляет контроль над областью заголовочных файлов (PRIVATE
против PUBLIC
против INTERFACE
) и позволяет всем подкаталогам получать доступ к файлам заголовков. Если вы хотите ограничить это поведение, используйте target_include_direcories
для всех целей (Ваша библиотека и исполняемый файл теста). В этом примере, так как все должно иметь доступ к файлам заголовка, с заявлением выше проблем нет.
Больше проблем:
project(factorial)
cmake_minimum_required(VERSION 2.8.12)
Либо поменяйте порядок этих утверждений, либо удалите оба. (Они нужны только в вашем файле CMake верхнего уровня)
Если вы посмотрите на документацию CMake, то PROJECT_SOURCE_DIR
переменная определяется так:
Исходный каталог верхнего уровня для текущего проекта.
Это исходный каталог самой последней команды project().
Так как ты звонил project
много раз, эта переменная будет постоянно меняться. Я бы предложил вам удалить директиву проекта или использовать CMAKE_SOURCE_DIR
, которые всегда указывают на исходный каталог всего проекта.
В качестве примечания, я предлагаю использовать set(CMAKE_CXX_STANDARD 11)
вместо add_definition