cmake 简单配置文件示例
Posted
技术标签:
【中文标题】cmake 简单配置文件示例【英文标题】:cmake simple config file example 【发布时间】:2018-04-16 12:39:11 【问题描述】:现在我有一个我自己制作的库,我想在另一个 CMake c++ 项目中使用它。它像这样存在于我的计算机中。
$MY_LIB_PATH\include
$MY_LIB_PATH\lib\x86\debug\lib-files
$MY_LIB_PATH\lib\x86\release\lib-files
$MY_LIB_PATH\lib\x64\debug\lib-files
$MY_LIB_PATH\lib\x64\release\lib-files
让 CMake find_package
知道这些的基本配置文件是什么样的?我希望它会非常简单,因为它没有太多信息可以提供。 But this page just make my head hurt.
对不起,我决定复制源代码,所以我真的不知道应该接受哪个答案。
【问题讨论】:
你看过this吗? 【参考方案1】:不要自己写配置;使用 CMake 的 export
命令。它过于宽泛,无法在此处完整介绍,但这里有一个来自我的一个项目的修改示例:
install(TARGETS
your_target
EXPORT YourPackageConfig
ARCHIVE DESTINATION $CMAKE_INSTALL_LIBDIR
LIBRARY DESTINATION $CMAKE_INSTALL_LIBDIR
RUNTIME DESTINATION $CMAKE_INSTALL_BINDIR
)
export(TARGETS
your_target
NAMESPACE YourPackage::
FILE "$CMAKE_CURRENT_BINARY_DIR/YourPackageConfig.cmake"
)
install(EXPORT
YourPackageConfig
DESTINATION "$CMAKE_INSTALL_DATADIR/YourPackage/cmake"
NAMESPACE YourPackage::
)
这将为您创建配置文件,因此其他项目可以通过find_package
使用它。
find_package(YourPackage REQUIRED)
target_link_libraries(foo YouprPackage::your_target)
这会自动处理IMPORTED
目标,还允许您嵌入编译器标志、包含路径、库依赖项,甚至哪些文件是您界面的一部分(基本上,任何属于INTERFACE
属性的文件)。
【讨论】:
你确定这有效吗?导出命令的手册说“此命令创建的文件特定于构建树,永远不应安装”。事实上,如果我尝试这样做,我会收到一条错误消息,说“文件...是由 export() 命令生成的。它可能不是用 install() 命令安装的”。 @GeorgP。 - 哪个命令给你这个问题?export
($CMAKE_CURRENT_BINARY_DIR/YourPackageConfig.cmake
) 创建的文件与正在安装的文件 ($CMAKE_INSTALL_DATADIR/YourPackage/cmake
) 不同。
啊,是的,我的错。但是 YourPackageConfig.cmake 到底是用来做什么的呢?
这个 sn-p 将创建两个文件,都名为 YourPackageConfig.cmake
,只是在不同的位置。 export
创建的包让其他包无需先安装即可使用您的工件,尽管我从未在简短的测试之外使用过它;我发现make && make install
更简洁,它与我正在处理的任何包的更常见用法相匹配。
导出路径不应该是$CMAKE_INSTALL_DATADIR/cmake/YourPackage
吗?因为对于系统范围安装的标准情况,这会将它放在 /usr/share/cmake/YourPackage
中,它由 cmake 找到。这是例如pybind11 做了什么。【参考方案2】:
在库的根目录下放一个“$libname-config.cmake”。
然后在该文件中添加一个 IMPORTED 目标。
有一个 libprotobuf 的例子。
add_library(libprotobuf STATIC IMPORTED GLOBAL)
set_target_properties(libprotobuf PROPERTIES
IMPORTED_LOCATION "$CMAKE_CURRENT_SOURCE_DIR/prebuilt/android/$ANDROID_ABI/libprotobuf.a"
IMPORTED_LINK_INTERFACE_LIBRARIES "$ZLIB_LIBRARIES;$CMAKE_THREAD_LIBS_INIT"
INTERFACE_INCLUDE_DIRECTORIES "$CMAKE_CURRENT_SOURCE_DIR/src")
将 Env 或 CMake 变量“$libname_DIR”设置为“$MY_LIB_PATH”
使用它。
find_package($libname)
#.......
target_link_libraries(main $libname)
【讨论】:
为什么这些建议不在官方文档中?为什么他们必须如此糟糕(文档)? Thx btw - 简单且有效。另外我建议使用 CMAKE_CURRENT_LIST_DIR 而不是 CMAKE_CURRENT_SOURCE_DIR 来使这个子项目可重定位。【参考方案3】:也许这个older doc 可能更轻量级。还有这个tutorial 或this other one。最后一个可能是最简单的。
希望不会增加更多的痛苦:-)
按照文档应该给出大致如下的内容(假设您的库是mylib
):
MyLib/MyLibConfig.cmake.in
# - Config file for the MyLib package
# It defines the following variables
# MYLIB_INCLUDE_DIRS - include directories for MyLib
# MYLIB_LIBRARIES - libraries to link against
# MYLIB_EXECUTABLE - the bar executable
# Compute paths
get_filename_component(MYLIB_CMAKE_DIR "$CMAKE_CURRENT_LIST_FILE" PATH)
set(MYLIB_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@")
# Our library dependencies (contains definitions for IMPORTED targets)
if(NOT TARGET mylib AND NOT MyLib_BINARY_DIR)
include("$MYLIB_CMAKE_DIR/MyLibTargets.cmake")
endif()
# These are IMPORTED targets created by MyLibTargets.cmake
set(MYLIB_LIBRARIES mylib)
MyLib/MyLibConfigVersion.cmake.in
set(PACKAGE_VERSION "@MYLIB_VERSION@")
# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("$PACKAGE_VERSION" VERSION_LESS "$PACKAGE_FIND_VERSION")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if ("$PACKAGE_VERSION" VERSION_EQUAL "$PACKAGE_FIND_VERSION")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()
主 MyLib/CMakeLists.txt
...
set(MYLIB_MAJOR_VERSION 0)
set(MYLIB_MINOR_VERSION 1)
set(MYLIB_PATCH_VERSION 0)
set(MYLIB_VERSION
$MYLIB_MAJOR_VERSION.$MYLIB_MINOR_VERSION.$MYLIB_PATCH_VERSION)
...
add_library(mylib SHARED mylib.c ...)
...
install(TARGETS mylib
# IMPORTANT: Add the mylib library to the "export-set"
EXPORT MyLibTargets
RUNTIME DESTINATION "$INSTALL_BIN_DIR" COMPONENT bin
LIBRARY DESTINATION "$INSTALL_LIB_DIR" COMPONENT shlib
PUBLIC_HEADER DESTINATION "$INSTALL_INCLUDE_DIR/mylib"
COMPONENT dev)
...
# The interesting stuff goes here
# ===============================
# Add all targets to the build-tree export set
export(TARGETS mylib
FILE "$PROJECT_BINARY_DIR/MyLibTargets.cmake")
# Export the package for use from the build-tree
# (this registers the build-tree with a global CMake-registry)
export(PACKAGE MyLib)
# Create the MyLibConfig.cmake and MyLibConfigVersion files
file(RELATIVE_PATH REL_INCLUDE_DIR "$INSTALL_CMAKE_DIR"
"$INSTALL_INCLUDE_DIR")
# ... for the build tree
set(CONF_INCLUDE_DIRS "$PROJECT_SOURCE_DIR" "$PROJECT_BINARY_DIR")
configure_file(MyLibConfig.cmake.in
"$PROJECT_BINARY_DIR/MyLibConfig.cmake" @ONLY)
# ... for the install tree
set(CONF_INCLUDE_DIRS "\$MYLIB_CMAKE_DIR/$REL_INCLUDE_DIR")
configure_file(MyLibConfig.cmake.in
"$PROJECT_BINARY_DIR$CMAKE_FILES_DIRECTORY/MyLibConfig.cmake" @ONLY)
# ... for both
configure_file(MyLibConfigVersion.cmake.in
"$PROJECT_BINARY_DIR/MyLibConfigVersion.cmake" @ONLY)
# Install the MyLibConfig.cmake and MyLibConfigVersion.cmake
install(FILES
"$PROJECT_BINARY_DIR$CMAKE_FILES_DIRECTORY/MyLibConfig.cmake"
"$PROJECT_BINARY_DIR/MyLibConfigVersion.cmake"
DESTINATION "$INSTALL_CMAKE_DIR" COMPONENT dev)
# Install the export set for use with the install-tree
install(EXPORT MyLibTargets DESTINATION
"$INSTALL_CMAKE_DIR" COMPONENT dev)
【讨论】:
以上是关于cmake 简单配置文件示例的主要内容,如果未能解决你的问题,请参考以下文章