【CMake】CMake打包Dll

本文详细阐述了CMake中的target属性设置、安装文件与头文件策略,以及CMakePackageConfigHelpers用于包配置和版本管理的部分,还涉及find_package和自定义命令的使用。
摘要由CSDN通过智能技术生成

设置lib的属性

1. target_include_directories

target_include_directories 是CMake的一个命令,用于特定的目标添加包含目录,包含目录是编译器在查找头文件会搜索的目标。

set(_INCLUDE_DIR 
    ${CMAKE_SOURCE_DIR}/src
    ${CMAKE_SOURCE_DIR}/3rdparty/plog
    ${CMAKE_SOURCE_DIR}/3rdParty/OpenCV460/include
)

set(_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src)
target_include_directories(${output_name_dynamic} PUBLIC
    $<BUILD_INTERFACE:${_INCLUDE_DIR}>
    $<INSTALL_INTERFACE:include>
)

1.1 BUILD_INTERFACE 和 <INSTALL_INTERFACE:include> 生成表达式

BUILD_INTERFACE 是CMake生成表达式的一部分,,通常用在target_include_directoriestarget_link_libraries等命令中,用于区分构建阶段和安装阶段。生成表达式是CMake的一种特性,它们在生成阶段被求值。
在构建阶段会被求值为一个路径,但是在安装阶段会被求值为空。
例如,下面的命令为目标添加一个包含目录:

target_include_directories(my_target PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include
)

在这个例子中,${CMAKE_SOURCE_DIR}/include目录在构建阶段会被添加到包含目录中,但是在安装阶段不会。这意味着构建阶段,编译器会在${CMAKE_SOURCE_DIR}/include目录中查找文件,但是在安装阶段不会。
这种使用生成表达式的方式可以在构建和安装阶段使用不同的包含目录,这在创建可安装的库时非常有用。

同理: $<INSTALL_INTERFACE:dir>生成表达式在构建阶段被求值为空,在安装阶段被求值为dir。
这个命令使得在安装阶段添加包含目录。

2. set_target_properties

set_target_properties(${output_name_dynamic}
    PROPERTIES
    DEBUG_POSTFIX "d"
    CXX_STANDARD 17
)

CMake代码使用set_target_properties命令为${output_name_dynamic}目标设置了一些属性。

  • FOLDER Lib设置了目标在IDE中的文件夹。在这个例子中,目标会被放在名为"Lib"的文件夹中。
  • CXX_STANDARD 17设置了目标的C++标准。在这个例子中,目标会使用C++17标准进行编译。

3. install FILES 安装头文件及PDB

使用 install (FILES) 安装头文件

install(FILES  ${mfmeidabase_HEADERS} DESTINATION include/aibase)
install(FILES  ${media_HEADERS} DESTINATION include/media)
install(FILES  ${simple_HEADERS} DESTINATION include/mediawrapper)

安装PDB

install(FILES $<TARGET_PDB_FILE:${output_name_dynamic}> DESTINATION bin OPTIONAL)

4. install TARGETS 安装 库

这段CMake代码使用install命令为${output_name_dynamic}目标设置了安装规则。

EXPORT ${output_name_dynamic}Targets表示在安装目标时,也会导出一个名为${output_name_dynamic}Targets的导出文件。这个导出文件可以被其他CMake项目使用,以便在其他项目中使用这个目标。

  • LIBRARY DESTINATION lib表示库目标(如果存在)会被安装到lib目录。

  • ARCHIVE DESTINATION lib表示静态库目标(如果存在)会被安装到lib目录。

  • RUNTIME DESTINATION bin表示运行时目标(例如可执行文件和模块)会被安装到bin目录。

  • INCLUDES DESTINATION include表示目标的公共头文件会被安装到include目录。

这些目录是相对于安装前缀的,安装前缀可以在调用CMake时通过CMAKE_INSTALL_PREFIX变量设置。例如,如果安装前缀是/usr/local,那么库目标会被安装到/usr/local/lib目录,运行时目标会被安装到/usr/local/bin目录,公共头文件会被安装到/usr/local/include目录。

5. include(CMakePackageConfigHelpers)

include(CMakePackageConfigHelpers)是CMake的一个命令,它包含了CMakePackageConfigHelpers模块。

CMakePackageConfigHelpers模块提供了一些函数和宏,用于创建和安装CMake包配置文件。这些配置文件可以让其他CMake项目更容易地使用你的项目。

例如,CMakePackageConfigHelpers模块提供了configure_package_config_file函数,你可以使用这个函数来创建一个包配置文件。这个函数会将一个输入文件复制到一个输出文件,并替换输入文件中的一些变量。

这个模块还提供了write_basic_package_version_file函数,你可以使用这个函数来创建一个包版本文件。这个函数会生成一个文件,这个文件定义了一个CMake变量,这个变量包含了包的版本信息。

5.1 write_basic_package_version_file

write_basic_package_version_file(
    ${output_name_dynamic}Version.cmake
    COMPATIBILITY AnyNewerVersion)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${output_name_dynamic}Version.cmake"
    DESTINATION share/MFMeidaCapture)

这段CMake代码使用write_basic_package_version_file函数创建了一个包版本文件。

${output_name_dynamic}Version.cmake是输出文件的名字,${output_name_dynamic}是一个变量,它应该在之前被设置为一个字符串。

COMPATIBILITY AnyNewerVersion表示这个包与任何新版本兼容。这意味着如果其他项目要求一个更高的版本,CMake会认为这个包满足要求。

write_basic_package_version_file函数会生成一个文件,这个文件定义了一个CMake变量,这个变量包含了包的版本信息。这个文件可以被其他CMake项目使用,以便在其他项目中使用这个包。
此外还需要用install 来安装到目标地址,不然不会生成。

5.2 安装 xxxTarget.cmake

install(EXPORT ${output_name_dynamic}Targets
    FILE ${output_name_dynamic}Targets.cmake
    NAMESPACE mfcap::
    DESTINATION share/MFMeidaCapture)
  • FILE ${output_name_dynamic}Targets.cmake表示导出文件的名字是${output_name_dynamic}Targets.cmake
  • NAMESPACE mfcap::表示在导出文件中,所有的目标都会被添加一个mfcap::的命名空间前缀

这个install命令会在安装阶段生成一个导出文件,这个导出文件包含了目标的信息,例如目标的类型、源文件、编译选项、依赖关系等。这个导出文件可以被其他CMake项目使用,以便在其他项目中使用这个目标。

例如,如果${output_name_dynamic}被设置为mylib,那么这个命令会创建一个名为mylibTargets.cmake的导出文件。这个文件可以被其他项目使用,以便在其他项目中使用mfcap::mylib目标。

NAMESPACE
在这个例子中,如果MyTargets导出文件中有一个名为mylib的目标,那么在导出文件中,这个目标的名字会变成mfcap::mylib。
其他CMake项目中使用这个命名空间前缀来引用这个目标。例如,你可以使用find_package(mfcap)和target_link_libraries(my_target mfcap::mylib)来在你的项目中使用mfcap::mylib目标。

这个命名空间前缀有两个作用:

  1. 避免命名冲突。如果两个不同的包都导出了一个名为mylib的目标,那么使用命名空间可以避免冲突。
  2. 明确指出目标来自哪个包。如果你看到一个名为mfcap::mylib的目标,你就知道这个目标来自mfcap包。

6. config_file

configure_file(MFMeidaCaptureConfig.cmake.in MFMeidaCaptureConfig.cmake @ONLY)

这段CMake代码使用configure_file函数来生成一个配置文件。

  • MFMeidaCaptureConfig.cmake.in是输入文件的名字。这个文件包含一些CMake变量
  • MFMeidaCaptureConfig.cmake是输出文件的名字。
  • @ONLY表示只有@VAR@形式的变量会被替换。如果没有@ONLY,那么${VAR}形式的变量也会被替换。
    一个典型的xxxConfig.cmake.in
include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
check_required_components("@PROJECT_NAME@")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/MFMeidaCaptureConfig.cmake"
                DESTINATION share/MFMeidaCapture)
  • @PACKAGE_INIT@是一个变量,它会被替换为一些初始化代码。

  • @targets_export_name@是一个变量,它会被替换为导出文件的名字。

  • @PROJECT_NAME@是一个变量,它会被替换为项目的名字。

check_required_components(“@PROJECT_NAME@”)
check_required_components(“@PROJECT_NAME@”)是一个CMake命令,它用于检查是否找到了所有需要的组件。
这个命令通常在find_package命令之后使用。例如:

find_package(MyPackage REQUIRED COMPONENTS comp1 comp2)
check_required_components(MyPackage)

在这个例子中,find_package命令会尝试找到MyPackage包,并且需要comp1和comp2这两个组件。然后,check_required_components命令会检查是否真的找到了这两个组件。

如果没有找到所有需要的组件,check_required_components命令会生成一个错误消息,并停止CMake的处理过程

7. find_package

cmake_minimum_required(VERSION 3.10)
project(MFInstallDemo)

set(CMAKE_CXX_STANDARD 17)

set(MFMeidaCapture_DIR "${CMAKE_CURRENT_SOURCE_DIR}/MFMeidaCapture/share/MFMeidaCapture")
find_package(OpenCV HINTS ../3rdparty/OpenCV460)

find_package(MFMeidaCapture REQUIRED)
add_executable(MFInstallDemo main.cpp)
get_target_property(MFCapDll mfcap::MFMeidaCapture IMPORTED_LOCATION_RELWITHDEBINFO)
get_target_property(MFCapDllDebug mfcap::MFMeidaCapture IMPORTED_LOCATION_DEBUG)
target_link_libraries(
        MFInstallDemo 
        ${OpenCV_LIBS}
        mfcap::MFMeidaCapture
)

target_include_directories(
        MFInstallDemo 
        PRIVATE
        ${CMAKE_SOURCE_DIR}/../3rdparty/plog/
        ${MFMeidaCapture_INCLUDE_DIRS}
        ${OpenCV_INCLUDE_DIRS}
        # "${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/OpenCV460/include"
)

add_custom_command(TARGET MFInstallDemo POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "$<IF:$<CONFIG:DEBUG>,${MFCapDllDebug},${MFCapDll}>"
        $<TARGET_FILE_DIR:MFInstallDemo>
)

add_custom_command(TARGET MFInstallDemo POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "$<IF:$<CONFIG:DEBUG>,${OpenCV_DIR}/x64/vc16/bin/opencv_world460d.dll,${OpenCV_DIR}/x64/vc16/bin/opencv_world460.dll>"
        $<TARGET_FILE_DIR:MFInstallDemo>)
  • 12
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值