如何将 CMake 与 Catch2 一起使用?
How to use CMake with Catch2?
从 Catch2's example 开始,我尝试 运行 这个例子 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/bin
中包含我的执行文件,我应该在 factorial/CMakeLists.txt
、factorial/src/CMakeLists.txt
和 factorial/test/CMakeLists.txt
中包含什么?
补充:
这是我的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)
如果您查看 CMake 文档,PROJECT_SOURCE_DIR
变量定义如下:
Top level source directory for the current project.
This is the source directory of the most recent project() command.
由于您多次调用 project
,该变量将不断变化。我建议您删除项目指令,或使用 CMAKE_SOURCE_DIR
,它始终指向整个项目的源目录。
作为旁注,我建议使用 set(CMAKE_CXX_STANDARD 11)
而不是 add_definition
这里有很多问题:
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
,只需在 top-level CMakeLists.txt
中写下以下内容:
include_directories(include)
现在,所有子目录都应该可以访问头文件了。请注意,这会删除对头文件范围的控制(PRIVATE
vs PUBLIC
vs INTERFACE
)并允许 all 子目录访问头文件.如果您想限制此行为,请对所有目标(您的库和测试可执行文件)使用 target_include_direcories
。对于这个例子,由于一切都需要访问头文件,所以上面的语句没有问题。
更多问题:
project(factorial)
cmake_minimum_required(VERSION 2.8.12)
要么调换这些语句的顺序,要么将它们都删除。 (您只需要在顶级 CMake 文件中使用它们)
从 Catch2's example 开始,我尝试 运行 这个例子 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/bin
中包含我的执行文件,我应该在 factorial/CMakeLists.txt
、factorial/src/CMakeLists.txt
和 factorial/test/CMakeLists.txt
中包含什么?
补充: 这是我的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)
如果您查看 CMake 文档,PROJECT_SOURCE_DIR
变量定义如下:
Top level source directory for the current project.
This is the source directory of the most recent project() command.
由于您多次调用 project
,该变量将不断变化。我建议您删除项目指令,或使用 CMAKE_SOURCE_DIR
,它始终指向整个项目的源目录。
作为旁注,我建议使用 set(CMAKE_CXX_STANDARD 11)
而不是 add_definition
这里有很多问题:
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
,只需在 top-level CMakeLists.txt
中写下以下内容:
include_directories(include)
现在,所有子目录都应该可以访问头文件了。请注意,这会删除对头文件范围的控制(PRIVATE
vs PUBLIC
vs INTERFACE
)并允许 all 子目录访问头文件.如果您想限制此行为,请对所有目标(您的库和测试可执行文件)使用 target_include_direcories
。对于这个例子,由于一切都需要访问头文件,所以上面的语句没有问题。
更多问题:
project(factorial)
cmake_minimum_required(VERSION 2.8.12)
要么调换这些语句的顺序,要么将它们都删除。 (您只需要在顶级 CMake 文件中使用它们)