【发布时间】:2022-01-27 23:03:24
【问题描述】:
我是 CMake 新手,所以如果我的问题被证明是菜鸟问题,我深表歉意。
我正在尝试在 C++ 中建立一个项目,其目录结构类似于我在 Java 中编码时 Maven 将创建的目录结构(src 目录和 build 目录):
root
├── build (where to build)
├── CMakeLists.txt (main one)
├── compile_commands.json -> ./build/compile_commands.json
├── doc
├── Doxyfile
└── src
├── CMakeLists.txt
├── common
│ └── Terminal.hpp
├── fsa
│ ├── CMakeLists.txt
│ ├── Machine.cpp
│ ├── Machine.hpp
│ └── MachineState.hpp
└── main.cpp
我不知道如何正确设置 CMake 以识别、编译和链接所有文件。特别是,我认为我应该使用(混合使用)add_subdirectory()、add_executable()、link_directories()、target_link_libraries()、add_library() 和 target_include_directories(),但我不确定我知道如何。
我稍后提供我的CMakeLists.txt 文件,但是当我配置和编译时,我得到:
/usr/bin/ld: fsa/libfsalib.a(Machine.cpp.o): in function `Machine::addState(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, bool)':
Machine.cpp:(.text+0xd1): undefined reference to `MachineState::MachineState(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool)'
collect2: error: ld returned 1 exit status
make[2]: *** [src/CMakeFiles/elr1.dir/build.make:98: src/elr1] Error 1
make[1]: *** [CMakeFiles/Makefile2:115: src/CMakeFiles/elr1.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
我做错了什么? 编辑: 原来这是我的一个非常愚蠢的错误,我忘了添加一个实现。但是,仍然存在一些问题:
- 如果这个项目/cmake 结构是最佳实践,您能告诉我吗?
- 我不知道应该在哪里使用
link_directories()和target_include_directories()。 - 更一般地说,如何保持代码库整洁并编译我的项目? 提前致谢
我的命令是
to configure: "cmake -S /path_to_root_project -B /path_to_root_project/build -D CMAKE_EXPORT_COMPILE_COMMANDS=ON"
to compile: "cmake --build /path_to_root_project/build"
root_project/CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
# set the project name
project(elr1 VERSION 0.1)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_subdirectory(src)
root_project/src/CMakeLists.txt:
add_subdirectory(fsa)
# add the executable
add_executable(elr1 main.cpp)
link_directories(fsa)
target_link_libraries(elr1 #target in which link
fsalib #library name
)
root_project/src/fsa/CMakeLists.txt:
add_library(fsalib #name
Machine.cpp #files
MachineState.hpp
)
target_include_directories(fsalib PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
【问题讨论】:
-
那么
MachineState::MachineState(std::string, bool)定义在哪里呢?没有MachineState.cpp吗? -
你是对的,没有,我的错。现在错误消失了。我的错!我非常专注于构建项目,以至于我忘记了它可能是真正的链接器错误。我将编辑我的问题,但关于 CMake 命令和最佳实践的问题仍然存在。
-
“关于 CMake 命令和最佳实践的问题仍然存在。” - 组织项目没有“最佳实践”。在 CMake 中,您几乎可以使用任何项目文件布局。
-
可能不是最好的,但也有好的,例如除非绝对必须,否则不要创建文件夹,同时让
CMakeLists.txt只处理一个文件夹,并且只在更深层次上使用add_subdirectory而不是从不同的地方引用一堆文件。示例:project/tests/CMakeLists.txt、project/CMakeLists.txt现在可以向可选的add_subdirectory(tests)添加一个选项,这会导致测试构建生成器运行或完全忽略,甚至不被 CMake 解析。 -
(target_)link_directories()只能在极少数情况下使用。它为链接器添加目录以搜索库文件。对于同一个项目构建的链接目标,这是不必要的;对于提供 cmake 导入脚本的外部项目,这也不是必需的。对于不提供 cmake 配置文件的外部库,这可能是一个选项,但通常我更喜欢创建一个导入的目标...
标签: c++ cmake build linker configuration-files