如何使 cmakelists.txt 编译使用在其他地方声明和实现的函数和类的 cpp

Posted

技术标签:

【中文标题】如何使 cmakelists.txt 编译使用在其他地方声明和实现的函数和类的 cpp【英文标题】:how to make cmakelists.txt compile cpp that uses functions and classes declared and implemented in some other place 【发布时间】:2019-12-17 14:21:29 【问题描述】:

我在 2 个头文件中定义了一些函数类,并在某个文件夹的 cpp 文件中实现。我将它们用于位于同一目录中的一些 cpp 程序(我们称之为 cpp1.cpp)。我们称之为 dir1

现在我的问题是: 我在 dir1 的同一级别上有另一个 dir2 有它自己的 CMakeLists.txt 我正在尝试在其中编译另一个 cpp 文件(让我们称它为 cpp2.cpp) 位于 dir2。这个新的 cpp 使用或者应该使用在 dir1 头文件和 cpp 文件中声明和定义的一些函数和类。 在我的 cpp2.cpp 中,我正在做:

#include "header1_from_dir1.h"
#include "header2_from_dir1.h"

这给了我这个错误: 错误:“func_name”未在此范围内声明 func_name(param1) ^~~~~~~~~~~~~~~

当我尝试将它包含在相对路径中时,它可以编译并正常工作:

#include "../dir1/header1_from_dir1.h"
#include "../dir1/header2_from_dir1.h"

为什么会这样?如何修改 CMakelists.txt 以正确“查看”在 dir1 中定义的函数?

简而言之,在 CMakeLists 中:

include_directories(../dir1)
add_executable(cpp2 cpp2.cpp ../dir1/cpp_header1.cpp ../dir1/cpp_header2.cpp)
target_include_directories(cpp2 PUBLIC ./dir1)
target_link_libraries(some_library_from_another_place)
install(TARGETS cpp2 DESTINATION $CMAKE_SOURCE_DIR/bin/$TARGET_LOCATION)

目录结构:

.
|-- dir1
|   |-- bin
|   |-- build 
|   |-- header1_from_dir1.h
|   |-- header2_from_dir1.h
|   |-- cpp_header1.cpp
|   |-- cpp_header1.cpp
|   |-- cpp1.cpp       // this uses functions and clases from above files
|   `-- CMakeLists.txt // this is for above cpp1.cpp
|-- dir2
|   |-- bin
|   |-- build
|   |-- cpp2.cpp // this uses functions and clases from    
                 // dir1/cpp_header1.cpp
|   `-- CMakeLists.txt // this is for above cpp2.cpp and have briefly 
                       // described its contents

【问题讨论】:

target_include_directories(cpp2 PUBLIC ./dir1) - 你不是说要target_include_directories(cpp2 PUBLIC ../dir1) 还是更好的target_include_directories(cpp2 PUBLIC $CMAKE_CURRENT_SOURCE_DIR/../dir1) 我会说 ../dir1 是正确的,因为我有一个用于编译/构建的脚本,并且我尝试使用 $CMAKE_CURRENT_SOURCE_DIR/../dir1 并显示相同的错误消息 你的目录/文件结构是什么?你能展示/画出来吗? dir1 在哪里(或者有两个dir1?) Trytarget_include_directories(cpp2 PUBLIC $CMAKE_CURRENT_SOURCE_DIR/dir1) 这个 CMakeLists.txt 在哪里?是在 dir1 里面还是在 dir2 里面还是在 root 里面? 你为什么要给*include_directories()打两次电话?在本例中,这些调用是多余的。 @squareskittles 是的,您是对的,尽管删除并不能解决主要问题。我应该说我在 cmake 使用艺术方面并不像您可能已经看到的那样先进。 【参考方案1】:

来自target_include_directories 文档:

INSTALL_INTERFACE 表达式中允许使用相对路径,并且相对于安装前缀进行解释。

所以相对路径不是你想要的。您需要为其指定绝对路径才能正确解释以进行编译。使用CMAKE_CURRENT_SOURCE_DIR 指定当前源目录的相对路径。

【讨论】:

我已经切换到使用CMAKE_CURRENT_SOURCE_DIR,但结果是一样的。消息调用显示了任何一种使用方式的正确路径。另一方面,从 include_directories 中删除所需的文件确实会打印出我找不到包含的头文件,正如预期的那样。我看到的错误我只是将其解释为它找不到具有该功能的对象...这听起来对吗? it could not find the object that has the function - 你没有来源cpp1.cpp,检查目标文件。老实说,你为什么不从 dir1 链接库?我只想 target_link_libraries(cpp2 PUBLIC cpp1) 假设 dir1/CMakeLists.txt 以与 dir2 中类似的方式执行 add_library(cpp1) ..【参考方案2】:

如何修改 CMakelists.txt 以正确“查看”dir1 中定义的函数?

您可以通过以下方式修改项目:

项目结构:

 ┣ ?dir1
 ┃ ┣ ?test.cpp
 ┃ ┗ ?test.h
 ┣ ?dir2
 ┃ ┣ ?CMakeLists.txt
 ┃ ┗ ?cpp2.cpp
 ┗ ?CMakeLists.txt

CMakeLists.txt:

project(test)
add_subdirectory(dir2)

目录1

测试.h

#pragma once
void hello();

test.cpp

#include "test.h"
#include <iostream>

void hello()

    std::cout << "hello" << std::endl;

目录2

CMakeLists.txt:

add_executable(cpp2)

target_sources(cpp2 PRIVATE cpp2.cpp  $CMAKE_CURRENT_SOURCE_DIR/../dir1/test.cpp)
target_include_directories(cpp2 PRIVATE $CMAKE_CURRENT_SOURCE_DIR/../dir1)

cpp2.cpp:

#include <test.h>

int main()

    hello();

更好的方法是从dir1 创建一个库,将其导出,然后导入dir2/CMakeLists.txt

希望这会有所帮助。

【讨论】:

不幸的是,我不得不将 CmakeLists.txt 保留在 dir1 和 dir2 中,因为它们都在构建不同的应用程序。这是一个更大的项目的一部分。我也在想创建一个库会是更好的方法 您可以将文件保存在两个目录中。只是为了确保将dir2/CMakeLists.txt 中的新目标cpp2 添加到现有目标。 是的,我将新目标添加为: add_executable(cpp2 cpp2.cpp ../dir1/cpp_header1.cpp ../dir1/cpp_header2.cpp) 那个命令 target_sources 是什么?我似乎很难在 cmake doc 网站上找到它。 cmake.org/cmake/help/latest/command/target_sources.html

以上是关于如何使 cmakelists.txt 编译使用在其他地方声明和实现的函数和类的 cpp的主要内容,如果未能解决你的问题,请参考以下文章

如何将 NSIS 的 RequestExecutionLevel 选项添加到 CMakeLists.txt

CMakelists.txt 用于编译 HDF5?

将编译器命令行转换为 Casablanca Rest SDK 的 CMakeLists.txt

ROS中的CMakeLists.txt

直接传递编译选项(绕过 CMakeLists.txt)

在Android上部署深度学习模型之CMakeLists文件