cmake - 运行“make all”时忽略 CMake EXCLUDE_FROM_ALL 参数
问题描述
介绍
使用 CMake,我正在尝试使用特殊make
目标构建库。为此,我使用EXCLUDE_FROM_ALL
参数来确保库不是通过运行构建的make
(默认为make all
)。不幸的是,该EXCLUDE_FROM_ALL
选项似乎被cmake
.
考虑以下文件树:
.
├── CMakeLists.txt
├── foo
│ ├── CMakeLists.txt
│ ├── headers
│ │ └── foo.h
│ └── src
│ └── foo.cpp
└── src
└── main.cpp
4 directories, 5 files
在这个文件树中,你可以看到我基本上有两个部分:
- foo 库,所有文件都位于
./foo/
. - 主要可执行文件,其源代码位于
./src/main.cpp
.
下面,我将进一步解释这两个部分以及我观察到的行为。
foo 库
首先,位于的头文件代码./foo/headers/foo.h
是:
#ifndef _FOO_H_
#define _FOO_H_
#include <iostream>
void foo(void);
#endif // _FOO_H_
对应的源代码,位于./foo/src/foo.cpp
,是:
#include "foo.h"
void foo(void) {
std::printf("Hello foo!\n");
}
如您所见, foo 库仅包含 function foo()
。这个函数只是打印Hello, foo!
到终端。为了构建 foo 库,我CMakeLists.txt
定义了以下文件(在 中./foo/CMakeLists.txt
):
cmake_minimum_required(VERSION 3.10)
project(foo
LANGUAGES CXX
)
# Create a foo library target
add_library(foo EXCLUDE_FROM_ALL
"src/foo.cpp"
)
target_include_directories(foo
PUBLIC "headers"
)
请注意,我在函数中使用了EXCLUDE_FROM_ALL
参数add_library()
。
为了测试EXCLUDE_FROM_ALL
参数的行为,我现在将 foo 库构建为独立的(使用前面显示的CMakeLists.txt
)。从顶级目录 ( .
) 开始,我使用以下工作流程:
$ cd foo
$ mkdir build
$ cd build
$ cmake ..
完成后,我运行make
命令:
$ make
(nothing happens)
正如预期的那样,什么都没有发生(因为 foo 库被排除在all
目标之外)。现在,当我使用 时make foo
,我得到以下输出:
$ make foo
Scanning dependencies of target foo
[ 50%] Building CXX object CMakeFiles/foo.dir/src/foo.cpp.o
[100%] Linking CXX static library libfoo.a
[100%] Built target foo
到目前为止,一切都很好。在继续构建主可执行文件之前,我完全删除了该./foo/build
目录并返回到顶级目录:
$ cd ..
$ rm -rf build
$ cd ..
主要可执行文件
主要可执行文件的源代码位于./src/main.cpp
:
#include "foo.h"
int main() {
foo();
return 0;
}
顶层CMakeLists.txt
包含:
cmake_minimum_required(VERSION 3.10)
project(TestProject
LANGUAGES CXX
)
# Include the foo library
add_subdirectory("foo" EXCLUDE_FROM_ALL)
# Create the main executable
add_executable(TestProject
"src/main.cpp"
)
target_link_libraries(TestProject
PRIVATE foo
)
请注意,我再次使用EXCLUDE_FROM_ALL
参数,但现在用于add_subdirectory()
函数。
要为主可执行文件生成 makefile,我使用以下工作流程:
$ mkdir build
$ cd build
$ cmake ..
当我现在运行时make
,我得到以下输出:
$ make
Scanning dependencies of target foo
[ 25%] Building CXX object foo/CMakeFiles/foo.dir/src/foo.cpp.o
[ 50%] Linking CXX static library libfoo.a
[ 50%] Built target foo
Scanning dependencies of target TestProject
[ 75%] Building CXX object CMakeFiles/TestProject.dir/src/main.cpp.o
[100%] Linking CXX executable TestProject
[100%] Built target TestProject
如您所见,它首先构建了 foo 库。然而,这不是我所期望的!我明确声明要从all
目标中排除 foo 库。因此,我希望在运行make foo
之前需要先运行make
。
这让我想到了我的主要问题:有人知道为什么它会忽略顶层函数中的EXCLUDE_FROM_ALL
选项吗?当我将 foo 库构建为独立的时,它确实有效。这是一个错误吗?如果没有,我如何实现我的预期行为(即需要在运行之前运行)?add_subdirectory()
CMakeLists.txt
cmake
make foo
make
解决方案
这不是错误。CMake 不foo
直接将 lib 包含在 all 目标中。但是,它确实将foo
目标作为依赖项添加到目标中,TestProject
并且由于TestProject
包含在all
目标中,因此foo
也会构建,如果您构建all
.
这需要以这种方式完成。您还能如何将该foo
功能链接到TestProject
?
如果您想使用不是作为 .lib 的一部分构建的库,则all
需要使用导入的库。这样做并在项目中包含 lib 似乎有点荒谬,但是你去吧。
add_library(foo STATIC EXCLUDE_FROM_ALL
"src/foo.cpp"
)
cmake_minimum_required(VERSION 3.10)
project(TestProject
LANGUAGES CXX
)
# Include the foo library
add_subdirectory("foo" EXCLUDE_FROM_ALL)
# Create the main executable
add_executable(TestProject
"src/main.cpp"
)
# add copy of foo as imported lib
add_library(foo_imported STATIC IMPORTED)
target_include_directories(foo_imported INTERFACE $<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES>)
set_target_properties(foo_imported PROPERTIES IMPORTED_LOCATION $<TARGET_FILE:foo>)
target_link_libraries(TestProject
PRIVATE foo_imported
)
推荐阅读
- woocommerce - WooCommerce 最近的产品分页限制总体和每页
- spring-boot - 在 Spring Boot 中运行测试时,Liquibase 没有从 test/resources 目录中获取变更集
- android - 如何在 Flutter WebView 或 InAppWebView 中添加 JavaScriptInterface?
- snowflake-cloud-data-platform - 时间戳减少 1000 倍
- menu - LocalStorage - 单独选择
- javascript - Javascript 表格单元 mouseover()
- sqlite - 如何从 UIPath 多次插入 SQLite DB
- azure - Get-AutomationPSCredential 在 Azure Function App 中不可用
- ip-address - Azure 存储 Blob 容器 - 限制匿名视频的 IP 地址
- phpstorm - 调试会话已完成而没有暂停这可能是由路径映射配置错误引起的