CMake:将头文件复制到输出目录

kknvjkwl  于 2023-01-13  发布在  其他
关注(0)|答案(4)|浏览(260)

我有一个包含C++源文件和头文件的目录。我想创建一个CMakeLists.txt来将其构建为一个库,以便在其他包含它作为子目录的CMake项目中使用。
结构:

example/
    foo.h
    foo.cpp
    CMakeLists.txt

我遇到的问题是CMake似乎没有把foo. h放在任何地方,所以让父CMake知道如何找到头文件是一件很有趣的事情。
下面是我目前的CMakeLists.txt:

cmake_minimum_required(VERSION 3.8.2)
project(example)
set (CMAKE_CXX_STANDARD 11)

# add library target foo
add_library(foo STATIC foo.cpp)

# tell cmake where to find headers for it
target_include_directories(foo PUBLIC .)

# sad attempt to get it to output the header
set_target_properties(foo PROPERTIES PUBLIC_HEADER foo.h)

我不想安装,这里的想法是库将被其他CMake项目使用,而不是整个系统。
理想情况下,foo. h应该显示在build目录中libfoo. a的旁边。
我试过称它为"框架",但没有成功;这只是一个宏观框架。
我相信我可以操纵陪审团,但我认为有一个最好的做法在那里。
也愿意接受"这里有更好的方法"的答案...
更新
这可能有助于澄清我想如何将这个项目拉到另一个项目中。我见过其他项目使用类似的东西:

add_subdirectory(<path_to_foo>/foo foo_build)

这使得foo编译发生在一个子目录中。这允许我使用'foo_build'引用库,这是很好的和干净的。但是,我仍然必须指向原始的include目录来获得. h文件,这让我觉得我错过了什么。
看起来cmake会有一个干净的解决方案。

2ul0zpep

2ul0zpep1#

我是相当新的CMake,但我认为你想要的是一个“add_custom_command”。

add_custom_command(TARGET foo.a POST_BUILD COMMAND copy foo.h ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})

那可能有用。

vpfxa7rd

vpfxa7rd2#

您需要的是以下结构:

example/
- CMakeLists.txt
- src/
  - main.c
- sub/
  - foo/
    - CMakeLists.txt
    - src/
      - foo/
        - foo.c
        - foo.h

您的CMakeList将如下所示

示例/CMakeLists.txt

# use modern target-based cmake features
cmake_minimum_required (VERSION 3.0)

# projectname
project (ff1_selfcheck)

add_subdirectory (sub/foo)

# executable to create
add_executable(${PROJECT_NAME}
    src/main.c
)

# link libraries
target_link_libraries(${PROJECT_NAME}
    PRIVATE
        foo # imported target
)

示例/子/foo/CMakeLists.txt

# use modern target-based cmake features
cmake_minimum_required (VERSION 3.0)

# projectname
project (foo)

# executable to create
add_library(${PROJECT_NAME}
    src/foo.c
)

# directories where to search for header files
target_include_directories(${PROJECT_NAME}
    PUBLIC
        source # the headerfiles in source are the includes
)

通过在target_link_libraries(...)中使用项目名称foo,可以引用foo库目标
此外,通过在foo库中使用PUBLIC关键字,您的头文件(include目录)会自动传播到每个通过add_subdirectory(...)添加此库的CMake项目。
因此你不需要复制你的头文件!CMake〉= 2.8.12很漂亮,不是吗?
如果您真的想通过CMake复制文件,可以使用以下方法:

file(COPY srcDir
    DESTINATION dstDir
    FILES_MATCHING
        PATTERN .h
)

看看这里:https://cmake.org/cmake/help/v3.2/command/file.html

6yt4nkrj

6yt4nkrj3#

作为CMake的一般规则,源代码保存在source目录中,二进制文件和其他生成的文件保存在build目录中,所以你希望它不是很像CMake。
CMake会根据你的意愿在你安装项目时放置头文件和库文件,然后你可以指定要复制的内容。
如果您不想安装此模块,最好的方法是通过为你的项目提供一个CMake配置文件来创建一个包。2这意味着你的项目 * Foo * 将生成一个包含包含路径和库路径的文件FooConfig.cmake。3另一个CMake项目将使用find_package(Foo)来查找该文件。通过在Foo_DIR中添加一个提示,您可以让CMake在非标准目录中查找您的项目。
进一步阅读:

注意,configure_file和你想要的是无关的,这个令人困惑的名字有历史原因。你可以使用这个命令,但是它本身是无关的。
更新:在更新之后,我认为你想使用一个外部项目。行为像一个内部库,但是非常独立。参见https://cmake.org/cmake/help/latest/module/ExternalProject.html

093gszye

093gszye4#

你应该为你的“foo”include目录使用生成器表达式:

target_include_directories(foo PUBLIC 
    $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR})

既然你不想安装规则,也不需要添加$<INSTALL_INTERFACE:include> ...
顺便说一句,你应该不关心复制构建目录中的包含文件(假设你是从源代码构建的)。
ps:如果你也生成头文件,只需add$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>

相关问题