gpt4 book ai didi

c++ - cmake install(FILES ...) 似乎不起作用

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:18:43 25 4
gpt4 key购买 nike

我有一个用 C++ 编写的项目,我正在使用 cmake 来构建它。该项目有许多子项目,其中一个是其他子项目所需的库。我可以编译 .so 并将其移动到构建目录添加_库,和安装(目标...)

但是我还需要将 lib 的头文件安装在构建目录的 include 目录下。我使用 install(FILES ...) 来完成它,但它似乎根本没有做任何事情。

为了演示它,我通过 qtcreator 创建了一个测试项目,

& ls test
CMakeLists.txt empty.hh main.cpp

$ cat test/CMakeLists.txt
project(test)
cmake_minimum_required(VERSION 2.8)
install(FILES empty.hh DESTINATION include)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})

$ cat test/main.cpp
#include

using namespace std;

int main()
{
cout << "Hello World!" << endl;
return 0;
}

$ cat test/empty.hh
#ifndef EMPTY_HH
#define EMPTY_HH

#endif // EMPTY_HH

If the files under "test" qtcreator will compile (by default) the files to test-build.
$ ls test-build/
CMakeCache.txt CMakeFiles Makefile cmake_install.cmake test test.cbp
$ ./test-build/test
Hello World!

如您所见,没有包含目录或空的.hh 文件。也试过用

install(FILES empty.hh DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

但是还是看不到头文件。

$ cmake --help
cmake version 2.8.12

如果你有任何想法,请告诉我。

最佳答案

在构建时使用install 命令来移动文件通常是一种糟糕的方法。该命令旨在用于设置文件和目标,这些文件和目标将在用户执行 make install 或等效操作时安装。由于您没有运行 make install,我想这就是 install(FILES ...) 命令似乎不起作用的原因。

这里有一些略有不同的方法来完成这项工作。

如果没有必要,我建议不要移动标题。假设您的库名为 MyLib,那么您可以通过 target_include_directories 将这些 header 作为 MyLib 目标的一部分提供。 :

target_include_directories(MyLib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")

这意味着如果有一个依赖目标,例如 MyExe:

target_link_libraries(MyExe MyLib)

然后它会自动访问 MyLib 的源目录。


如果库的目录结构不适合将 API header 与其余源和 header 分开,这可能不太理想。 Say MyLib 由以下文件组成:my_lib.cpp、my_lib_api.hh(API header - 供其他项目包含)和 my_lib_detail.hh(不供其他项目包含)。理想的结构是将 API header 与其余部分分开,例如

/my_lib
- CMakeLists.txt
- src/
- my_lib.cpp
- my_lib_detail.hh
- include/
- my_lib/
- my_lib_api.hh

有了这个结构你就可以指定

target_include_directories(MyLib PUBLIC  "${CMAKE_CURRENT_SOURCE_DIR}/include"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src")

MyLib 源将能够包含#include "my_lib_detail.hh"#include "my_lib/my_lib_api.hh",但依赖目标的源代码只能包含#include "my_lib/my_lib_api.hh"


因此,如果 MyLib 只有一个平面结构或没有将内部 header 与 API header 分开,您可能需要将 API header 复制到构建树中的某个位置并添加 target_include_directories 调用的路径。在这种情况下,如果 MyLib 本身不需要访问复制的文件(只是源代码树中的原始文件),您可以使用 INTERFACE 而不是 PUBLIC target_include_directories 调用中。

然而,这个问题的关键(我想是在回答你的实际问题)是将这些文件复制为配置过程(当 CMake 运行时)或构建过程(当 make 运行时)的一部分 - 而不是作为安装过程。

因此,我们假设 MyLib 没有上面显示的有用目录结构,而是扁平的(即 CMakeLists.txt 和三个源文件都在同一个目录中)目录)。我们可以使用构建后命令将 API header 复制到构建树中:

project(my_lib)
cmake_minimum_required(VERSION 2.8.12.2) # for 'target_include_directories'
add_library(MyLib SHARED my_lib.cpp my_lib_api.hh my_lib_detail.hh)
target_include_directories(MyLib INTERFACE "${CMAKE_BINARY_DIR}/include"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")

file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/my_lib")
add_custom_command(TARGET MyLib POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/my_lib_api.hh"
"${CMAKE_BINARY_DIR}/include/my_lib"
COMMENT "Copying MyLib public headers to ${CMAKE_BINARY_DIR}/include/my_lib"
VERBATIM)

然后对于 MyExe 的 CMakeLists.txt,你可以这样做:

project(my_exe)
cmake_minimum_required(VERSION 2.8.12.2)
add_executable(MyExe main.cpp)
target_link_libraries(MyExe MyLib)

# Copy MyLib.so to this build dir to allow MyExe to find it at runtime
add_custom_command(TARGET MyExe POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:MyLib>"
"$<TARGET_FILE_DIR:MyExe>"
VERBATIM)


这对于 MSVC 不会按原样工作 - 您需要处理 Windows 导出库(有关更多详细信息,请参阅 CMake wikiGenerateExportHeader 的文档),但它只涉及添加诸如以下是 MyLib 的 CMakeLists.txt:

include(GenerateExportHeader)
generate_export_header(MyLib
BASE_NAME MyLib
EXPORT_MACRO_NAME MyLib_EXPORT
EXPORT_FILE_NAME "${CMAKE_BINARY_DIR}/include/my_lib/my_lib_export.hh"
STATIC_DEFINE MyLib_BUILT_AS_STATIC)

如果你确实需要这个,你必须在 target_include_directories(MyLib ...) 中将 INTERFACE 更改为 PUBLIC,因为 MyLib 本身将需要访问生成的文件 "${CMAKE_BINARY_DIR}/include/my_lib/my_lib_export.hh"

关于c++ - cmake install(FILES ...) 似乎不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27665939/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com