cmake install(文件...)似乎不起作用
cmake install(FILES ...) doesn't seem to be working
我有一个用C++编写的项目,我正在使用cmake来构建它。该项目有许多子项目,其中一个是其他子项目所需的库。我可以使用 编译 .so 并将其移动到构建目录add_library,以及安装(目标...
但是,我还需要将库的头文件安装在构建目录的包含目录下。我使用安装(文件...)来做到这一点,但似乎它根本不起作用。
为了演示它,我通过 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
将这些标头作为MyLib
目标的一部分提供:
target_include_directories(MyLib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
这意味着如果有一个依赖目标,例如MyExe
:
target_link_libraries(MyExe MyLib)
然后它会自动访问MyLib
的源目录。
如果库的目录结构不适合将 API 标头与其他源和标头分开,则可能不太理想。 假设MyLib
由以下文件组成:my_lib.cpp、my_lib_api.hh(API 标头 - 供其他项目包含)和 my_lib_detail.hh(不用于其他项目包含)。 理想的结构将使 API 标头与其他标头分开,例如
/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
只有一个平面结构,或者没有将内部标头与 API 标头分开,则可能需要将 API 标头复制到构建树中的某个位置,并将该路径添加到target_include_directories
调用中。 在这种情况下,如果MyLib
本身不需要访问复制的文件(只需要源代码树中的原始文件),则可以在target_include_directories
调用中使用INTERFACE
而不是PUBLIC
。
但是,关键是(我想要回答您的实际问题)是将这些文件作为配置过程(当 CMake 运行时)或构建过程(当 make 运行时)的一部分复制 - 而不是作为安装过程的一部分。
因此,让我们假设MyLib
没有上面显示的有用的目录结构,而是平面的(即 CMakeLists.txt并且三个源文件都在同一个目录中)。 我们可以使用构建后命令将 API 标头复制到构建树中:
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 wiki 和文档以获取GenerateExportHeader
),但它只涉及将以下内容添加到 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++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 在其他文件中创建类时在 c++ 项目中不起作用
- g++ -I 和 -L 命令来查找不起作用的 .hpp 文件
- 该程序将.csv文件中的一系列单词放入数组中,然后随机生成句子.但它不起作用
- 无法打开包含文件'Graphics.hpp'没有这样的文件或目录,Visual Studio的其他包含不起作用
- 从类中的另一个文件请求函数不起作用
- 即使我正在.cpp文件中实例化一个伪对象,.cpp文件内模板函数的定义也不起作用
- 简单的二分搜索对我不起作用。我正在尝试从文本文件中搜索单词
- SFML 加载从文件不起作用,奇怪的错误
- C++密钥和文件的映射不起作用
- 从 TXT 文件中删除行不起作用
- QT QML:使用.qrc文件将SQLite数据库部署到Android不起作用
- bcdedit 文件输出不起作用,但其他命令可以
- 文件写入在PHP扩展c / c ++(linux)中不起作用
- Makefile在Linux中工作,但在Windows下不起作用,在子目录中找不到文件
- 使用 libcurl C++将文件下载到 Ubuntu,简单示例不起作用
- 尝试读取数据文件,存储在数组中并打印所有元素,但它不起作用
- 为什么写入文件不起作用
- 包括不起作用C 的文件
- 在 C++ 中,.h 文件包含文件但不起作用