• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

CMake 使用 install 和 export 导出库

武飞扬头像
周上行Ryer
帮助1

关键词:CMake CMake install CMake export

废话不多说,先上成品!

给 VSCode 用的 Snippet 👇

{
    "CMake install configure": {
        "prefix": "cmake-install",
        "body": [
            "# --- BEGIN CMAKE INSTALL/EXPORT ---",
            "include(GNUInstallDirs)",
            "set(PROJECT_EXPORT_TARGETS ${1:\\${PROJECT_NAME\\}})",
            "set(PROJECT_EXPORT_NAME ${2:\\${PROJECT_NAME\\}})",
            "set(PROJECT_INSTALL_CMAKEDIR ${3:\\${CMAKE_INSTALL_LIBDIR\\}/cmake/\\${PROJECT_EXPORT_NAME\\}})",
            "",
            "# create aliases for targets",
            "foreach(target \\${PROJECT_EXPORT_TARGETS\\})",
            "\tadd_library(\\${PROJECT_EXPORT_NAME\\}::\\${target\\} ALIAS \\${target\\})",
            "endforeach()",
            "# install targets",
            "install(",
            "\tTARGETS \\${PROJECT_EXPORT_TARGETS\\}",
            "\tEXPORT \\${PROJECT_EXPORT_NAME\\}Targets",
            "\tARCHIVE DESTINATION \\${CMAKE_INSTALL_LIBDIR\\}",
            "\tLIBRARY DESTINATION \\${CMAKE_INSTALL_LIBDIR\\}",
            "\tRUNTIME DESTINATION \\${CMAKE_INSTALL_BINDIR\\}",
            "\tPUBLIC_HEADER DESTINATION \\${CMAKE_INSTALL_INCLUDEDIR\\}",
            "\tINCLUDES DESTINATION \\${CMAKE_INSTALL_INCLUDEDIR\\}",
            ")",
            "",
            "# install project headers",
            "install(",
            "\tDIRECTORY \\${CMAKE_CURRENT_SOURCE_DIR\\}/include/",
            "\tDESTINATION \\${CMAKE_INSTALL_INCLUDEDIR\\}",
            ")",
            "",
            "# install CMake xxxTargets.cmake",
            "export(",
            "\tEXPORT \\${PROJECT_EXPORT_NAME\\}Targets",
            "\tNAMESPACE \\${PROJECT_EXPORT_NAME\\}::",
            "\tFILE \\${PROJECT_EXPORT_NAME\\}Targets.cmake",
            ")",
            "install(",
            "\tFILES \\${CMAKE_CURRENT_BINARY_DIR\\}/\\${PROJECT_EXPORT_NAME\\}Targets.cmake",
            "\tDESTINATION \\${PROJECT_INSTALL_CMAKEDIR\\}",
            ")",
            "",
            "# install xxxConfigVersion.cmake",
            "include(CMakePackageConfigHelpers)",
            "write_basic_package_version_file(",
            "\t\\${PROJECT_EXPORT_NAME\\}ConfigVersion.cmake",
            "\tVERSION \\${PROJECT_VERSION\\}",
            "\tCOMPATIBILITY AnyNewerVersion",
            ")",
            "install(",
            "\tFILES \\${CMAKE_CURRENT_BINARY_DIR\\}/\\${PROJECT_EXPORT_NAME\\}ConfigVersion.cmake",
            "\tDESTINATION \\${PROJECT_INSTALL_CMAKEDIR\\}",
            ")",
            "",
            "# install CMake xxxConfig.cmake",
            "install(",
            "\tEXPORT \\${PROJECT_EXPORT_NAME\\}Targets",
            "\tFILE \\${PROJECT_EXPORT_NAME\\}Config.cmake",
            "\tNAMESPACE \\${PROJECT_EXPORT_NAME\\}::",
            "\tDESTINATION \\${PROJECT_INSTALL_CMAKEDIR\\}",
            ")",
            "# --- END CMAKE INSTALL/EXPORT ---"
        ],
        "description": "CMake 导出目标"
    }
}
学新通

简单讲讲

第一部分

#! 常用的模块了,设置 GNU 风格的 install 目录,变量命名为 CMAKE_INSTALL_xxxDIR
include(GNUInstallDirs)

#! 设置需要导出的目标(列表)
set(PROJECT_EXPORT_TARGETS ${PROJECT_NAME})

#! 设置导出的命名,在这份 snippet 中应用于 xxxConfig.cmake/xxxTargets.cmake/
#! xxxConfigVersion.cmake 和导出的目标的命名空间
set(PROJECT_EXPORT_NAME ${PROJECT_NAME})

#! 设置生成的 cmake 文件的 install 目录,通常会放在顶层目录为 share 或 lib/lib64 的
#! 目录下,在这里选择放在 lib/lib64 目录下
set(PROJECT_INSTALL_CMAKEDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_EXPORT_NAME})

第二部分

#! 在同一个 CMake build tree 中,每个项目的 targets 对外都是可见的,比如 A 项目中有一个
#! foobar 的静态库目标,那么在 B 项目中就可以直接链接 foobar 目标。
#! 但是一般情况在 CMake 使用第三方库引入库都会有命名空间(命名冲突问题),这时链接的目标可
#! 能就是 foobar::foobar !(如果不是的话假设就是!!!)
#! 出于统一性考虑,应尽可能使得同一 build tree 内外链接同名目标。
#! 然而 build tree 内即使进行了 install/export 操作,依旧不能直接使用带有命名空间的目标
#! (可能以某种参数进行的 install/export 可以做到,但是我写的时候实在是在这上面找不到办法)
#! 故而曲线救国,在这里额外对导出的目标定义带命名空间的别名,完美!
#! NOTE: 不会吧不会吧?不会有人连这种别名都能造成命名冲突吧?
#! NOTE: 我自认为因为别名没在这里被导出,所以不会影响外部 CMake 项目的引入,或许只不过是我
#> 多虑了,其实根本就不存在这种问题呢?不过说到底我对此机理并未深究,故留个疑问在这。
foreach(target ${PROJECT_EXPORT_TARGETS})
    add_library(${PROJECT_EXPORT_NAME}::${target} ALIAS ${target})
endforeach()

第三部分

#! 重头之一:配置待导出目标们的 install 选项,主要包括相关文件的 install 目录,
#! 其中 EXPORT 参数指示了被导出目标集合的导出名,该项将在 export 中被使用以代替显
#! 式地列出目标。另
install(
    TARGETS ${PROJECT_EXPORT_TARGETS}
    EXPORT ${PROJECT_EXPORT_NAME}Targets
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
    INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

第四部分

#! 导出头文件
#! 实际上该命令单纯地用于 install 目录(当路径后跟着 "/" 时表示仅导入目录下的文件与子目录)
#! 但是由于我个人的习惯,即项目结构一般服从如下:
#! Project
#! |   CMakeLists.txt
#!  ---include
#! |   \---ProjectInc
#! |           [Public Headers]
#! \---src
#!         *.cpp
#!         [Private Headers]
#!         CMakeLists.txt
#! 所以就方便如下这样直接导出公共头文件了!另外在这份 snippet 中还有几个地方也需要前置要求
#! 如上的目录结构,如果要直接挪用的话可能需要注意一下!
install(
    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
学新通

第五部分

#! 重头之二:生成用于导入被导出目标的 xxxTargets.cmake 文件
#! export 支持 export(TARGETS) 命令和 export(EXPORT) 命令,在第三部分中提过,install
#! 中指定了待导入目标们的导出名,在此处则直接使用导出名指代被导出的目标。这与代换后的
#! export(TARGETS) 命令是等价的。
export(
    EXPORT ${PROJECT_EXPORT_NAME}Targets
    NAMESPACE ${PROJECT_EXPORT_NAME}::
    FILE ${PROJECT_EXPORT_NAME}Targets.cmake
)

#! export 执行生成的 xxxTargets.cmake 存在于 ${CMAKE_CURRENT_BINARY_DIR} 目录下(也就
#! 是 CMake 构造目录下的与源代码同名子目录),故而需要额外导入该文件。
install(
    FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_EXPORT_NAME}Targets.cmake
    DESTINATION ${PROJECT_INSTALL_CMAKEDIR}
)
学新通

第六部分

#! 生成 xxxConfig.cmake 的版本配置脚本 xxxConfigVersion.cmake
#! NOTE: 不是特别重要,可以跳过~
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
    ${PROJECT_EXPORT_NAME}ConfigVersion.cmake
    VERSION ${PROJECT_VERSION}
    COMPATIBILITY AnyNewerVersion
)

#! 原因同第五部分,需要手动导入!
install(
    FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_EXPORT_NAME}ConfigVersion.cmake
    DESTINATION ${PROJECT_INSTALL_CMAKEDIR}
)

第七部分

#! 重头之三:生成库的配置文件 xxxConfig.cmake xxxConfig-<config>.cmake
#! 其中 EXPORT 是一个已经被指派的导出名,剩下的部分敢敢当当,一目了然!
install(
    EXPORT ${PROJECT_EXPORT_NAME}Targets
    FILE ${PROJECT_EXPORT_NAME}Config.cmake
    NAMESPACE ${PROJECT_EXPORT_NAME}::
    DESTINATION ${PROJECT_INSTALL_CMAKEDIR}
)

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggfkej
系列文章
更多 icon
同类精品
更多 icon
继续加载