c++ - 在 CMakeLists.txt 中执行 cmake 与在终端中执行 cmake 有什么区别,我们如何使其行为相同?
问题描述
好的,我不确定如何准确解释问题,但基本上,在我的Project X的 CMakeLists.txt 中,我正在构建外部库依赖项,它们本身就是独立的项目(例如,项目 A、项目 B、项目 C,项目 D)-然后我使用catkin_make
.
ExternalProject_Add()
我为每个项目A、B、C、D使用 CMake ;然后声明add_dependencies()
使项目A, B, C, D在主项目 X之前先构建。
现在,我对Project D尤其有问题,需要设置多个路径CMAKE_PREFIX_PATH
(例如,CMAKE_PREFIX_PATH=/addrA;/addrB;addrC
)。
- 错误 #1:如果我使用
ExternalProject_Add()
,它会识别分号路径分隔符 ';' 作为“命令结束”,因此,它将 cmake 命令通过第一条路径(仅CMAKE_PREFIX_PATH=/addrA
被识别)。我已经尝试了很多东西-使用,在此之前LIST_SEPARATOR
设置使用,甚至使用-没有任何效果,同样的问题。CMAKE_PREFIX_PATH
set()
$<SEMICOLON>
- 错误 #2:我接下来所做的 - 不是
ExternalProject_Add()
用来下载和构建项目 D - 我ExternalProject_Add()
以前只是下载(例如,BUILD_COMMAND 将被设置为“”),然后通过add_custom_target()
. 现在那里的 cmake 命令也不起作用 - 因为由于某种原因/我不知道的限制,它没有正确映射CMAKE_INSTALL_*
标志,即使CMAKE_PREFIX_PATH
是正确的,它也没有真正识别 bin/ lib/include 目录应该在CMAKE_PREFIX_PATH
. 当我尝试在结果中替换这些标志的正确值CMakeCache.txt
并通过 重建时catkin_make
,它工作正常。但如果我不这样做,就像我只依赖最初的CMakeCache.txt
它生成了,它不会工作。
请注意,当我尝试在终端中运行 Project D 的 cmake 时,我根本没有遇到任何问题。
作为一种解决方法,我execute_process()
创建了一个包含项目 D的 cmake 和 make 命令的 bash 脚本,然后我只是在ExternalProject_Add()
'sBUILD_COMMAND
或add_custom_target()
's调用该 bash 脚本COMMAND
。这些工作中的任何一个 - 这只是表明,在其中一个中执行的COMMAND
cmakeExternalProject_Add()
或add_custom_target()
在某种程度上不同于在终端中或通过 bash 脚本执行 cmake。
我在这里搜索了所有内容,但找不到与我有相同问题的人,因此我现在的解决方法是。
这是有效的粗略代码(我的解决方法):
### Project A
include(ExternalProject)
ExternalProject_Add(ProjectA
PREFIX /tmp/ProjectA
GIT_REPOSITORY https://github.com/ProjectA
GIT_TAG v0.0.1
CONFIGURE_COMMAND ""
BUILD_COMMAND cmake -DWITH_GFLAGS=off -DCMAKE_INSTALL_PREFIX=/opt/ProjectA <SOURCE_DIR>
COMMAND sudo cmake --build . --target install
INSTALL_COMMAND ""
TEST_COMMAND ""
)
### Project B
include(ExternalProject)
ExternalProject_Add(ProjectB
PREFIX /tmp/ProjectB
GIT_REPOSITORY https://github.com/ProjectB
GIT_TAG v0.0.1
CONFIGURE_COMMAND ""
BUILD_COMMAND cmake -DLWS_STATIC_PIC=ON -DCMAKE_INSTALL_PREFIX=/opt/ProjectB <SOURCE_DIR>
COMMAND sudo cmake --build . --target install
INSTALL_COMMAND ""
TEST_COMMAND ""
)
### Project C
include(ExternalProject)
ExternalProject_Add(ProjectC
PREFIX /tmp/ProjectC
GIT_REPOSITORY https://github.com/ProjectC
GIT_TAG v0.0.1
CONFIGURE_COMMAND ""
BUILD_COMMAND cmake -Dprotobuf_BUILD_TESTS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=/opt/ProjectC <SOURCE_DIR>
COMMAND sudo cmake --build . --target install
INSTALL_COMMAND ""
TEST_COMMAND ""
)
### Project D
execute_process (
COMMAND bash -c "echo '#!/bin/bash\ncmake -DCMAKE_PREFIX_PATH=\"/opt/ProjectA;/opt/ProjectB;/opt/ProjectC\" /tmp/ProjectD/src/ProjectD\nmake' > /tmp/projectD_build.sh"
COMMAND bash -c "chmod 777 /tmp/projectD_build.sh"
)
include(ExternalProject)
ExternalProject_Add(ProjectD
PREFIX /tmp/ProjectD
GIT_REPOSITORY https://github.com/ProjectD
GIT_TAG master
CONFIGURE_COMMAND ""
BUILD_COMMAND /tmp/projectD_build.sh
INSTALL_COMMAND ""
TEST_COMMAND ""
)
### Set dependencies to force build Project A, B, C, D before Project X is build
add_library (ProjectX SHARED IMPORTED)
set_target_properties (ProjectX PROPERTIES IMPORTED_LOCATION ${ProjectX_LIBS})
add_dependencies(ProjectX ProjectA)
add_dependencies(ProjectX ProjectB)
add_dependencies(ProjectX ProjectC)
add_dependencies(ProjectX ProjectD)
### Project X build commands here (snipped)
这些是 /tmp/ProjecD_build.txt 中的 cmake + make 命令:
cmake -DCMAKE_PREFIX_PATH="/opt/ProjectA;/opt/ProjectB;/opt/ProjectC" /tmp/ProjectD/src/ProjectD
make
如果我用这个替换整个“### Project D”部分,我会遇到我上面讨论过的错误 #1(多路径 CMAKE_PREFIX_PATH 的问题):
### Project D
include(ExternalProject)
ExternalProject_Add(ProjectD
PREFIX /tmp/ProjectD
GIT_REPOSITORY https://github.com/ProjectD
GIT_TAG master
CONFIGURE_COMMAND ""
BUILD_COMMAND cmake -DCMAKE_PREFIX_PATH="/opt/ProjectA;/opt/ProjectB;/opt/ProjectC" /tmp/ProjectD/src/ProjectD
INSTALL_COMMAND make
TEST_COMMAND ""
)
...或像这样添加一个 post-ProjectD,它仍然不起作用并导致我上面讨论的错误 #2(CMAKE 标志未正确设置,如 CMakeCache.txt 中所示)。请注意,使用此解决方案,我将Project D ExternalProject_Add()
设置为" BUILD_COMMAND
" 因为构建将由添加完成add_custom_target()
:
ExternalProject_Get_Property(ProjectD install_dir)
ExternalProject_Get_Property(ProjectD source_dir)
ExternalProject_Get_Property(ProjectD binary_dir)
message(STATUS "install_dir is: " ${install_dir})
message(STATUS "source_dir is: " ${source_dir})
message(STATUS "binary_dir is: " ${binary_dir})
add_custom_target(ProjectD_part2 ALL
cmake -DCMAKE_PREFIX_PATH="/opt/ProjectA;/opt/ProjectB;/opt/ProjectC" ${source_dir}
COMMAND make
WORKING_DIRECTORY ${binary_dir}
)
add_dependencies(ProjectD_part2 ProjectA)
add_dependencies(ProjectD_part2 ProjectB)
add_dependencies(ProjectD_part2 ProjectC)
add_dependencies(ProjectD_part2 ProjectD)
解决方法有效。但是有没有更好的方法来做到这一点?谢谢你。
解决方案
看起来很复杂!你能试试https://github.com/floooh/fips吗 ,它让很多 cmake 的事情变得更容易。Fips 是一个 Python 命令行工具,它通过将现有构建工具连接在一起,为 C/C++ 项目提供“集成构建环境”。它支持类似于 Rust 的 Cargo 或 Javascript 的 NPM 的工作流,但适用于 C/C++ 项目。
推荐阅读
- floating-point - 您如何处理 GLSL 中增加浮点值的小数精度?
- apache-spark - 如何获得 Spark Streaming 的运行时间
- javascript - 如何使用 jquery 显示选择下拉列表?
- angular - TinyMCE 5 与 Angular 7 的集成
- android - 实现 com.android.utils.* 和 com.android.SdkConstants.* 的模块的依赖项
- siri - 如何让 Siri 读取 Pythonista 脚本的返回值?
- c# - AddAuthentication + RequireAuthenticatedUser = 多余?
- python - Python 的 range() 函数不循环
- python - 防止第 3 个库记录器创建记录文件
- node.js - 如果条件与反应量