CMake EXCLUDE_FROM_ALL参数在运行时被忽略';使所有'; 介绍

CMake EXCLUDE_FROM_ALL参数在运行时被忽略';使所有'; 介绍,cmake,Cmake,使用CMake,我试图使用一个特殊的make目标构建一个库。为此,我使用EXCLUDE\u FROM\u ALL参数来确保库不是通过运行make(默认为make ALL)构建的。不幸的是,cmake似乎忽略了EXCLUDE\u FROM\u ALL选项 考虑以下文件树: . ├── CMakeLists.txt ├── foo │   ├── CMakeLists.txt │   ├── headers │   │   └── foo.h │   └── src │   └── foo.

使用CMake,我试图使用一个特殊的
make
目标构建一个库。为此,我使用
EXCLUDE\u FROM\u ALL
参数来确保库不是通过运行
make
(默认为
make ALL
)构建的。不幸的是,
cmake
似乎忽略了
EXCLUDE\u FROM\u ALL
选项

考虑以下文件树:

.
├── CMakeLists.txt
├── foo
│   ├── CMakeLists.txt
│   ├── headers
│   │   └── foo.h
│   └── src
│       └── foo.cpp
└── src
    └── main.cpp

4 directories, 5 files
在这个文件树中,您可以看到我基本上有两个部分:

  • foo库,其所有文件都位于
    /foo/
  • 主可执行文件,其源代码位于
    /src/main.cpp
  • 下面,我将进一步解释这两个部分以及我观察到的行为

    富图书馆 首先,位于
    /foo/headers/foo.h
    中的头代码是:

    #ifndef _FOO_H_
    #define _FOO_H_
    
    #include <iostream>
    
    void foo(void);
    
    #endif // _FOO_H_
    
    如您所见,foo库只包含函数
    foo()
    。这个函数只打印
    Hello,foo到终端。为了构建foo库,我定义了以下
    CMakeLists.txt
    文件(在
    /foo/CMakeLists.txt
    中):

    请注意,我在
    add_library()
    函数中使用了
    EXCLUDE_FROM_ALL
    参数

    为了测试
    EXCLUDE\u FROM\u ALL
    参数的行为,我现在将构建一个独立的foo库(使用前面显示的
    CMakeLists.txt
    )。从顶部目录(
    )开始,我使用以下工作流:

    $ cd foo
    $ mkdir build
    $ cd build
    $ cmake ..
    
    $ mkdir build
    $ cd build
    $ cmake ..
    
    完成后,我运行
    make
    命令:

    $ make
    (nothing happens)
    
    正如预期的那样,什么也没有发生(因为foo库被排除在
    all
    目标之外)。现在,当我使用
    makefoo
    时,我得到以下输出:

    $ 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
    
    $ 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/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\u FROM\u ALL
    参数,但现在使用
    add\u subdirectory()
    函数

    要为主可执行文件生成makefile,我使用以下工作流:

    $ cd foo
    $ mkdir build
    $ cd build
    $ cmake ..
    
    $ mkdir build
    $ cd build
    $ cmake ..
    
    现在运行
    make
    时,我得到以下输出:

    $ 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
    
    $ 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库。然而,这不是我所期望的!我明确声明将foo库从
    all
    目标中排除。因此,我希望在运行
    make
    之前需要先运行
    make-foo


    这就引出了我的主要问题:有人知道为什么它会忽略顶级
    CMakeLists.txt
    中的
    add_subdirectory()
    函数中的
    EXCLUDE_FROM_ALL
    选项吗?当我把foo库作为一个独立库来构建时,它确实起了作用。这是
    cmake
    中的错误吗?如果没有,我如何实现我的预期行为(即在运行
    make
    之前需要运行
    make foo
    )?

    这不是一个bug。CMake不直接在all目标中包含
    foo
    lib。但是,它确实将
    foo
    目标作为依赖项添加到
    TestProject
    中,并且由于
    TestProject
    包含在
    all
    目标中,如果您构建
    all
    ,那么也会构建
    foo

    这需要这样做。您还可以如何将
    foo
    函数链接到
    TestProject

    如果要使用不是作为
    all
    的一部分构建的库,则需要使用。这样做是非常困难的,而且在项目中包含lib似乎有点荒谬,但现在开始吧

    add_library(foo STATIC EXCLUDE_FROM_ALL
        "src/foo.cpp"
    )
    
    cmake_最低要求(3.10版)
    项目(测试项目)
    语言CXX
    )
    #包括foo库
    添加子目录(“foo”从所有子目录中排除子目录)
    #创建主可执行文件
    添加可执行文件(TestProject
    “src/main.cpp”
    )
    #将foo的副本添加为导入的lib
    添加库(foo\u导入静态导入)
    目标目录(foo\u导入的接口$)
    设置\u目标\u属性(foo\u导入的属性导入的\u位置$)
    目标链接库(TestProject
    私人富屋
    )
    
    感谢您的快速回复!我尝试用您的版本替换我的顶级CMakeLists.txt,并将“静态”规范添加到add_library()函数中,但不幸的是,在配置过程中出现错误:CMakeLists.txt:17(target_include_目录):无法为导入的目标“foo_imported”指定包含目录。您知道是什么导致了这个问题吗?我通过将行
    target\u include\u directories(foo\u imported INTERFACE$)
    更改为
    set\u property(target foo\u imported APPEND property INTERFACE\u include\u directories“$”
    ,成功地解决了前面的问题。目前,cmake配置可以正常工作。但是,在运行生成的makefile时,它总是给我以下错误:
    CMakeFiles/TestProject.dir/build.make:93:**目标模式不包含“%”