You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CMake中使用file(GET_RUNTIME_DEPENDENCIES)处理框架依赖的方法

macOS下CMake打包时区分普通库与Framework依赖的解决方案

问题说明

当依赖为普通动态库时,以下CMake配置可正常完成打包并运行:

project(sample)
add_library(Foo SHARED foo.cpp foo.h)

add_executable(mytest main.cpp)
target_link_libraries(mytest Foo)
set_target_properties(mytest PROPERTIES INSTALL_RPATH "@loader_path/")
install(TARGETS mytest RUNTIME DESTINATION bin)
install(
  CODE "file(GET_RUNTIME_DEPENDENCIES EXECUTABLES \$<TARGET_FILE:mytest> RESOLVED_DEPENDENCIES_VAR DEPS)
        foreach(DEP \${DEPS})
          file(INSTALL \${DEP} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
        endforeach()"
)

执行cmake -DCMAKE_INSTALL_PREFIX=/tmp ..和make install后,/tmp/bin/mytest可正常运行。

但将依赖改为Framework后:

project(sample)
add_library(Foo SHARED foo.cpp foo.h)
set_target_properties(Foo PROPERTIES FRAMEWORK TRUE PUBLIC_HEADER "foo.h")

add_executable(mytest main.cpp)
target_link_libraries(mytest Foo)
set_target_properties(mytest PROPERTIES INSTALL_RPATH "@loader_path/")
install(TARGETS mytest RUNTIME DESTINATION bin)
install(
  CODE "file(GET_RUNTIME_DEPENDENCIES EXECUTABLES \$<TARGET_FILE:mytest> RESOLVED_DEPENDENCIES_VAR DEPS)
        foreach(DEP \${DEPS})
          file(INSTALL \${DEP} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
        endforeach()"
)

执行相同步骤后,/tmp/bin/mytest启动失败,报错dyld: Library not loaded: @rpath/Foo.framework/Versions/A/Foo。原因是仅复制了Framework中的二进制文件,未完整复制整个Framework目录结构。

修改方案

调整install CODE块,增加Framework判断与完整复制逻辑,并提前配置正确的RPATH:

完整配置代码

project(sample)
add_library(Foo SHARED foo.cpp foo.h)
set_target_properties(Foo PROPERTIES FRAMEWORK TRUE PUBLIC_HEADER "foo.h")

add_executable(mytest main.cpp)
target_link_libraries(mytest Foo)
# 配置RPATH,同时覆盖当前目录和上级Frameworks目录(符合macOS标准布局)
set_target_properties(mytest PROPERTIES INSTALL_RPATH "@loader_path/;@loader_path/../Frameworks")
install(TARGETS mytest RUNTIME DESTINATION bin)
install(
  CODE "file(GET_RUNTIME_DEPENDENCIES EXECUTABLES \$<TARGET_FILE:mytest> RESOLVED_DEPENDENCIES_VAR DEPS)
        foreach(DEP \${DEPS})
          # 检查当前依赖是否属于Framework
          string(FIND \${DEP} \".framework/\" FRAMEWORK_POS)
          if(FRAMEWORK_POS GREATER -1)
            # 提取Framework根目录路径
            string(SUBSTRING \${DEP} 0 \${FRAMEWORK_POS} FRAMEWORK_DIR)
            string(APPEND FRAMEWORK_DIR \".framework\")
            # 完整复制整个Framework到标准Frameworks目录
            file(INSTALL \${FRAMEWORK_DIR} DESTINATION ${CMAKE_INSTALL_PREFIX}/Frameworks)
          else()
            # 普通动态库直接复制到bin目录
            file(INSTALL \${DEP} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
          endif()
        endforeach()"
)

逻辑说明

  1. RPATH配置:提前给可执行文件添加@loader_path/../Frameworks路径,符合macOS应用的Framework标准存放位置,确保dyld能找到Framework。
  2. Framework判断:通过string(FIND)检查依赖路径中是否包含.framework/,识别Framework类型依赖。
  3. 完整复制Framework:提取Framework的根目录(而非仅二进制文件),将整个Framework目录复制到${CMAKE_INSTALL_PREFIX}/Frameworks,保留其完整目录结构。
  4. 普通库处理:保持原有逻辑,将普通动态库复制到bin目录。

执行cmake -DCMAKE_INSTALL_PREFIX=/tmp ..和make install后,/tmp/bin/mytest即可正常运行。

内容的提问来源于stack exchange,提问作者user3667089

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 11:21:04