什么是简单明了的find_package CMake 的文件集



我是CMake的新手(意思是几年来我被迫使用它,即使它让我质疑我的职业道路)。

我有一个包含文件夹的文件夹,以及一个包含 .lib 文件及其相应的依赖项的 .dll 的 lib 文件夹,我称之为"mydep"。我需要提供基础设施文件,mydep-config.cmake,mydep-target.cmake等,这将包含文件夹和.lib文件添加到命令行进行编译和链接,然后将.dlls移动到特定位置。

谁能指出我在网上任何地方的简单例子来说明做到这一点的方法?CMake 文档完全没用。

谢谢!

基本上有 2 个文件需要放在文件系统上的正确位置。假设要导入的库是用版本1.2.3调用ExternLib并编译为 64 位。有了它,你已经把它存储在你的仓库中

external_dependencies/lib/ExternLib.lib
external_dependencies/bin/ExternLib.dll
external_dependencies/include/ExternLib/ExternHeader.hpp
external_dependencies/include/ExternLib/...
...

并且您希望项目中使用的包含路径为

#include "ExternLib/ExternHeader.hpp"

首先,我们将使用文件名externlib-config.cmakeexternlib-version-config.cmake,以允许用户在使用find_package时使用任意大小写。

externlib-version-config.cmake

此文件用于检查配置脚本的版本是否与尝试查找包的 cmake 配置兼容。通过添加此文件,您可以放置多个版本的库,以便为不同的目标体系结构(例如Windows x64,Win32,linux x86_64等)找到。 如果版本通过版本文件标记为不兼容,find_package不会读取同一目录中的externlib-config.cmake

set(PACKAGE_VERSION "1.2.3")
# basically ignore the version passed
set(PACKAGE_VERSION_COMPATIBLE TRUE) # consider every version compatible
#usually you'd add logic for ignoring any unspecified parts of the version here instead of treating unspecified version parts as 0
# we'll keep it simple though
if(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
set(PACKAGE_VERSION_EXACT TRUE) # make version as exact match
endif()
if(NOT WIN32)
set(PACKAGE_VERSION_COMPATIBLE FALSE) # disallow older version
else()
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") # note: we'll ignore the possibility of find_package before the first project() command
set(PACKAGE_VERSION_UNSUITABLE TRUE)
endif()
if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") # check for 64 bit
set(PACKAGE_VERSION_UNSUITABLE TRUE)
endif()

externlib-config.cmake

在这里,除了提供用户应该有权访问的任何函数/宏/变量之外,我们还将创建实际库。我们将使用ExternLib::ExternLib作为目标名称,但您可以简单地将其替换为您在项目中选择的唯一名称。

if(NOT TARGET ExternLib::ExternLib) # prevent recreation on multiple uses of find_package
add_library(ExternLib::ExternLib SHARED IMPORTED)
get_filename_component(EXTERNLIB_BASE_DIR ${CMAKE_CURRENT_LISTS_DIR}/../../.. ABSOLUTE)
set(EXTERNLIB_BINARY_DIR ${EXTERNLIB_BASE_DIR} CACHE INTERNAL "Directory containing the dlls for ExternLib")
# add info about locations of the dll/lib files
set_target_properties(ExternLib::ExternLib PROPERTIES
IMPORTED_LOCATION "$CACHE{EXTERNLIB_BINARY_DIR}/ExternLib.dll"
IMPORTED_IMPLIB "${EXTERNLIB_BASE_DIR}/lib/ExternLib.lib"
)
# add include directory information
target_include_directories(ExternLib::ExternLib INTERFACE "${EXTERNLIB_BASE_DIR}/include")
# add dependencies, if required; you may need to use find_package to locate those
# target_link_libraries(ExternLib::ExternLib INTERFACE ...)
endif()
# any helper function/macro definitions should go here, since they may need to get reintroduced

注意:我确实忽略了在此处指定包组件的可能性。对于上面的脚本,任何为find_package指定组件的组件都会被忽略。

文件的放置

您需要将文件放置在CMAKE_PREFIX_PATH中提到的目录之一或默认目录之一下方的一些可能路径之一中,请参阅find_package配置模式搜索过程。

注意:我们将使用一个未记录在Windows上的路径,因为此路径也适用于Linux。(Boost也在这样做。

lib/cmake/ExternLib-x64-1.2.3

(您可以选择不同的后缀来lib/cmake/ExternLib或只使用lib/cmake/ExternLib。搜索过程会选取任何以包名称开头的目录名称,如果它需要 lib 名称,则忽略大小写。

将两个文件都放在此目录中。externlib-config.cmake假设lib在这里external_dependencies/lib。否则,您可能需要相应地调整EXTERNLIB_BASE_DIR

用法

我们假设CMakeLists.txt文件与external_dependencies放在同一个目录中

project(...)
...
add_executable(my_exe ...)
...
# this allows the user to pass directories to be searched first via -D option during configuration
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies)
find_package(ExternLib REQUIRED)
target_link_libraries(my_exe PRIVATE ExternLib::ExternLib)
# allow vs debugger to find the dll without copying the dlls around
set_target_properties(my_exe PROPERTIES
VS_DEBUGGER_ENVIRONMENT "PATH=${EXTERNLIB_BINARY_DIR};$ENV{PATH}"
)

相关内容

  • 没有找到相关文章

最新更新