【问题标题】:How to use CMake with Catch2?如何将 CMake 与 Catch2 一起使用?
【发布时间】:2018-03-21 18:19:34
【问题描述】:

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.txtfactorial/src/CMakeLists.txtfactorial/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 文件的内容是什么?
  • 你查看过他们的最小示例here
  • 您的 CMake 文件是否在任何地方包含 include_directories(include)? (或者至少是target_include_directories()
  • @GuillaumeRacicot 我正在写,请稍候。卡尔还没谢谢。
  • 第二个问题,你可以这样做:set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)。但是,我建议您不要这样做,而是将可执行文件保存在创建它们的目录中。

标签: c++ cmake catch-unit-test


【解决方案1】:

这里有很多问题:

add_executable(fact fact.cpp)

调用应该使用add_library(您也可以指定STATICSHARED),因为您只是定义了一个阶乘函数,而不是一个带有main 函数的可执行文件 .

add_executable(fact fact.cpp)

该文件应该是test_fact.cpp,并且目标应该有一个不同的名称以避免与您之前创建的库冲突。此外,您的fact.cpp 不包括fact.hpp。最后但同样重要的是,不要使用target_include_directories,只需在您的顶级CMakeLists.txt 中写入以下内容:

include_directories(include)

现在,所有子目录都应该可以访问头文件了。请注意,这会删除对头文件范围的控制(PRIVATE vs PUBLIC vs INTERFACE)并允许 all 子目录访问头文件。如果您想限制此行为,请对所有目标(您的库和测试可执行文件)使用target_include_direcories。对于这个例子,由于一切都需要访问头文件,所以上面的语句没有问题。

更多问题:

project(factorial)
cmake_minimum_required(VERSION 2.8.12)

要么切换这些语句的顺序,要么同时删除它们。 (您只需要在顶级 CMake 文件中使用它们)

【讨论】:

  • 您如何建议某人使用include_directories 而不是target_include_directories 并在晚上睡觉?
  • @GuillaumeRacicot 对于此示例,实际上没有必要逐个目标地指定包含。但是,我会添加一条注释,说明target_include_directories 是更好的做法。
  • “调用应该使用add_library”和“文件应该是test_fact.cpp” - add_library(fact fact.cpp) 然后add_executable(fact test_fact.cpp) 引发CMake错误:“add_executable 无法创建目标“事实”,因为另一个同名目标已经存在。”。我误解了这个建议吗?
  • @swdon 你说得对,我没有意识到我指定了 2 个同名目标,它们应该是不同的。
【解决方案2】:

如果您查看 CMake 文档,PROJECT_SOURCE_DIR 变量的定义如下:

当前项目的顶级源目录。

这是最近的 project() 命令的源目录。

由于您多次调用project,该变量将不断变化。我建议你删除你的项目指令,或者使用CMAKE_SOURCE_DIR,它总是指向整个项目的源目录。


作为旁注,我建议使用set(CMAKE_CXX_STANDARD 11) 而不是add_definition

【讨论】:

    猜你喜欢
    • 2020-01-16
    • 1970-01-01
    • 2020-12-10
    • 2021-05-06
    • 2018-01-12
    • 1970-01-01
    • 2015-04-08
    • 2019-01-07
    相关资源
    最近更新 更多