首页 > 解决方案 > 运行“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

在这个文件树中,你可以看到我基本上有两个部分:

  1. foo 库,所有文件都位于./foo/.
  2. 主要可执行文件,其源代码位于./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.txtcmakemake foomake

标签: cmake

解决方案


这不是错误。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
)

推荐阅读