ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CMake 可重定位包与 INTERFACE_INCLUDE_DIRECTORIES 警告:不要在安装接口中硬编码依赖头文件路径

CMake 可重定位包与 INTERFACE_INCLUDE_DIRECTORIES 警告:不要在安装接口中硬编码依赖头文件路径 构建工具开发工具CLI【免费下载链接】CMakeMirror of CMake upstream repository项目地址https://gitcode.com/gh_mirrors/cm/CMake点击查看免费下载本文聚焦 CMake 文档片段 INTERFACE_INCLUDE_DIRECTORIES_WARNING.rst 所阐述的规则在使用INTERFACE_INCLUDE_DIRECTORIES目标属性及其配套命令target_include_directories编写可分发relocatable的 CMake 包时不得把依赖库的头文件绝对路径写入INSTALL_INTERFACE生成器表达式。读完本文你将掌握这一警告背后的成因、正确的属性编写方式以及如何借助 IMPORTED 目标与find_dependency宏构建真正可移植的安装包。一、警告原文核心结论与适用场景在 CMake 文档体系中Help/include/INTERFACE_INCLUDE_DIRECTORIES_WARNING.rst是一段被复用的共享片段它同时被包含在target_include_directories 命令文档 的 Creating Relocatable Packages 小节INTERFACE_INCLUDE_DIRECTORIES 目标属性文档 的对应小节。其核心结论可以概括为三点不建议用依赖库 include 目录的绝对路径去填充目标INTERFACE_INCLUDE_DIRECTORIES属性中的INSTALL_INTERFACE部分这样做会把制作包的那台机器build machine上查找到的依赖 include 目录路径硬编码进安装包INSTALL_INTERFACE只适合描述目标自身随包分发的头文件所需的 include 目录而不是传递依赖由INTERFACE_LINK_LIBRARIES目标属性声明的那些依赖所需的目录。换言之依赖的 include 目录信息应当由依赖自身作为目标在它自己的INTERFACE_INCLUDE_DIRECTORIES属性中声明再由依赖方通过链接关系传递获得而非由依赖方把从find_package得到的绝对路径直接拼进自己的安装接口。二、为什么这是问题打包机路径 ≠ 消费机路径警告中强调的关键词是as found on the machine the package was made on在制作包的那台机器上找到的路径。安装包一旦分发就会被拷贝到任意其他机器上使用打包机上的/home/alice/deps/boost/include、C:/deps/sdk/include等绝对路径在消费机上几乎必然不存在即便存在也指向完全不同的软件版本或目录结构硬编码路径会让整个安装包失去可重定位能力——即无法被安装到任意前缀prefix下正常工作的能力。可重定位包的定义在 cmake-packages(7) 手册 中给出A relocatable package must not reference absolute paths of files on the machine where the package is built that will not exist on the machines where the package may be installed.可重定位包不得引用打包机器上存在、但安装机器上不存在的文件绝对路径。三、正确姿势INSTALL_INTERFACE 只描述目标自己的头文件INSTALL_INTERFACE与BUILD_INTERFACE是 CMake 提供的一对按使用场景区分内容的生成器表达式定义见 cmake-generator-expressions(7) 手册$INSTALL_INTERFACE:...当属性通过install(EXPORT)导出时内容为...否则为空字符串$BUILD_INTERFACE:...当属性通过export导出或目标被同一构建系统中的其他目标使用时内容为...否则为空字符串$INSTALL_PREFIX当目标经install(EXPORT)导出时求值为安装前缀可用于在复杂表达式中作为安装前缀的占位符而不会破坏可重定位性。标准的正确写法如下取自 INTERFACE_INCLUDE_DIRECTORIES 属性文档target_include_directories(mylib INTERFACE $BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/mylib $INSTALL_INTERFACE:include/mylib # prefix/include/mylib )关键规则见 target_include_directories 命令文档INSTALL_INTERFACE中允许使用相对路径相对路径会被解释为相对于安装前缀CMAKE_INSTALL_PREFIXBUILD_INTERFACE中不应使用相对路径因为相对路径不会被转换为绝对路径位于$INSTALL_INTERFACE:include/mylib中的include/mylib最终解析为prefix/include/mylib无论安装到哪个前缀都是正确的。这样包移动到哪里头文件查找路径都会跟随安装前缀实现真正的可重定位。错误 vs 正确安装前缀的两种写法cmake-packages(7) 手册 给出了直接对比# 错误不可重定位 target_include_directories(tgt INTERFACE $INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include/TgtName ) # 正确可重定位 target_include_directories(tgt INTERFACE $INSTALL_INTERFACE:include/TgtName )把CMAKE_INSTALL_PREFIX求值结果直接嵌入INSTALL_INTERFACE等于在导出文件中固定死打包时的前缀改用相对路径后前缀在哪里都能工作。复杂表达式场景$INSTALL_PREFIX如果需要在INSTALL_INTERFACE中组合多个生成器表达式例如按构建类型区分相对路径就不够用了此时应使用$INSTALL_PREFIX占位符见 cmake-packages(7) 手册target_include_directories(tgt INTERFACE # 正确可重定位 $INSTALL_INTERFACE:$$CONFIG:Debug:$INSTALL_PREFIX/include/TgtName )$INSTALL_PREFIX只在导出时求值为安装前缀不会把打包机的绝对路径写死进导出文件。四、警告的完整含义INSTALL_INTERFACE 与依赖的正确分工回到警告原文INTERFACE_INCLUDE_DIRECTORIES_WARNING.rst的结构它在否定向INSTALL_INTERFACE写入依赖绝对路径之后紧接着给出了正面指引TheINSTALL_INTERFACEof theINTERFACE_INCLUDE_DIRECTORIESis only suitable for specifying the required include directories for headers provided with the target itself, not those provided by the transitive dependencies listed in itsINTERFACE_LINK_LIBRARIEStarget property. Those dependencies should themselves be targets that specify their own header locations inINTERFACE_INCLUDE_DIRECTORIES.翻译成工程实践即INSTALL_INTERFACE只放随目标自身分发的头文件的 include 目录传递依赖的头文件位置由依赖目标自己的INTERFACE_INCLUDE_DIRECTORIES负责目标通过INTERFACE_LINK_LIBRARIES建立依赖关系依赖的头文件目录信息沿着链接关系自动传递transitive到消费者。这与 INTERFACE_LINK_LIBRARIES 警告片段 的立场完全一致后者同样警告不要用依赖库文件的绝对路径填充INTERFACE_LINK_LIBRARIES否则会把打包机上找到的库文件路径硬编码进安装包。五、依赖应该怎么写IMPORTED 目标 find_dependency 宏cmake-packages(7) 手册 给出了一个典型的反例与正解。反例——直接把find_package返回的变量拼进接口# 这样可能无法构成可重定位包 target_link_libraries(ClimbingStats INTERFACE ${Foo_LIBRARIES} ${Bar_LIBRARIES} ) target_include_directories(ClimbingStats INTERFACE $INSTALL_INTERFACE:${Foo_INCLUDE_DIRS};${Bar_INCLUDE_DIRS} )${Foo_INCLUDE_DIRS}、${Foo_LIBRARIES}中很可能包含打包机上查找到的绝对路径导出后就被固化进安装包包随之失去可重定位性。正解是让依赖通过它们自己的 IMPORTED 目标被引用见 cmake-packages(7) 手册target_link_libraries(ClimbingStats INTERFACE Foo::Foo Bar::Bar)IMPORTED 目标自身携带IMPORTED_LOCATION以及INTERFACE_INCLUDE_DIRECTORIES等使用要求属性。当消费者使用安装包时包内的find_dependency宏由Modules/CMakeFindDependencyMacro.cmake提供会在消费者自己的机器上执行对应的find_package将依赖的 IMPORTED 目标填充为消费机上的正确路径。包对外只暴露Foo::Foo、Bar::Bar这样的目标名称完全不涉及任何绝对路径。老式 find-module 的兜底方案警告与手册都承认一个现实不少 CMake 附带的 find-module其历史早于 IMPORTED 目标方案尚未提供 IMPORTED 目标。此时可重定位包的两个兜底做法见 cmake-packages(7) 手册构建包时将Foo_LIBRARY缓存条目指定为纯库名而非路径例如-DFoo_LIBRARYfoo让对应的 find-module 只把foo写入Foo_LIBRARIES交由链接器自行搜索库而不是硬编码路径在安装内容之后、制作发行安装包之前手动把绝对路径替换为占位符由安装工具在安装时完成替换。这两种方案都是绕开硬编码的过渡手段IMPORTED 目标仍是首选。六、相关命令与属性速查名称类型作用文档位置target_include_directories命令为目标添加 include 目录INTERFACE/PUBLIC条目写入INTERFACE_INCLUDE_DIRECTORIESPRIVATE/PUBLIC条目写入INCLUDE_DIRECTORIESHelp/command/target_include_directories.rstINTERFACE_INCLUDE_DIRECTORIES目标属性描述目标的 include 目录使用要求支持BUILD_INTERFACE/INSTALL_INTERFACE生成器表达式Help/prop_tgt/INTERFACE_INCLUDE_DIRECTORIES.rstINTERFACE_LINK_LIBRARIES目标属性声明目标的链接依赖依赖的使用要求沿此属性传递Help/prop_tgt/INTERFACE_LINK_LIBRARIES.rst$BUILD_INTERFACE:.../$INSTALL_INTERFACE:.../$INSTALL_PREFIX生成器表达式按使用场景构建树/安装树区分接口内容Help/manual/cmake-generator-expressions.7.rst补充说明target_include_directories命令还支持SYSTEM关键字与PUBLIC/INTERFACE联用时会把目录写入INTERFACE_SYSTEM_INCLUDE_DIRECTORIES属性AFTER/BEFORE控制追加或前置。相对路径会被解释为相对于当前源码目录CMAKE_CURRENT_SOURCE_DIR并转为绝对路径存储若路径以生成器表达式开头则一律视为绝对路径原样使用见 target_include_directories 命令文档。七、写作INTERFACE_INCLUDE_DIRECTORIES时的自查清单结合本文所有内容为你的包导出代码做一次最终检查INSTALL_INTERFACE中是否只出现了目标自身头文件的相对路径相对安装前缀是否出现${Foo_INCLUDE_DIRS}、${CMAKE_INSTALL_PREFIX}/...这类会求值为打包机绝对路径的内容若有改为相对路径或$INSTALL_PREFIX。依赖的头文件目录是否由依赖自己的INTERFACE_INCLUDE_DIRECTORIES提供本目标只通过INTERFACE_LINK_LIBRARIES链接 IMPORTED 目标安装包消费侧是否通过find_dependency宏在消费机上重新定位依赖构建树BUILD_INTERFACE与安装树INSTALL_INTERFACE的内容是否分开书写、各司其职遵循 INTERFACE_INCLUDE_DIRECTORIES_WARNING.rst 的这条核心纪律再配合 cmake-packages(7) 手册 中 Creating Relocatable Packages 一节的完整讨论你产出的安装包才能在任意前缀、任意机器上开箱即用。赞分享构建工具开发工具CLI【免费下载链接】CMakeMirror of CMake upstream repository项目地址https://gitcode.com/gh_mirrors/cm/CMake点击查看免费下载相关推荐CMake 可重定位包陷阱为何不应将绝对路径写入 INTERFACE_LINK_LIBRARIESCMake 可重定位包陷阱为何不应将绝对路径写入 INTERFACE_LINK_LIBRARIES 本篇指南围绕 CMake 官方文档中的 INTERFACE构建工具开发工具CLI在 Linux 上编译 ImHex依赖安装、CMake/Ninja 构建与 XDG 路径配置全指南在 Linux 上编译 ImHex依赖安装、CMake/Ninja 构建与 XDG 路径配置全指南 导读 本文以 dist/compiling/linux.m桌面应用开发工具逆向工程Caffe 安装完全指南依赖准备、Make/CMake 编译与硬件选型Caffe 安装完全指南依赖准备、Make/CMake 编译与硬件选型 Caffe 是一个专注于深度学习的快速开源框架其安装链路涉及 CUDA、BLAS、B操作系统上一篇Maestro record 功能教程操作一遍自动生成测试脚本下一篇3步搞定Redis多实例管理RedisInsight连接方法创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表