4

我正在尝试使用 CMake 函数 FIXUP_BUNDLE 来修复应用程序包,但我收到了安装时警告,并且由于缺乏更好的术语,而不是修复包。

安装的包具有正确的结构,但它使用的框架没有正确复制。只有每个框架的目录结构被复制,而不是实际的共享库二进制文件。例如,我的包使用 SFML 2.0 的系统框架。请注意,我使用的所有 SFML 框架都存储在/Library/Frameworks. 以下是我MyApp.app/Contents/Frameworks/对这个 SFML 组件的了解:

sfml-system.framework/
    Versions/
        2.0.0/

这就是我所得到的,只是目录。实际的 SFML System 框架具有如下结构:

sfml-system.framework/
    Resources  (this is a symlink)
    sfml-system  (this is a symlink)
    Versions/
        2.0.0/
            Resources/
                Info.plist
            sfml-system  (this is the actual library binary)
        Current  (this is a symlink)

在我的项目中,可执行文件都具有相同的格式,因此我有一个小功能可以使用这种通用格式添加它们。该函数只是添加可执行文件,设置要链接的库,并在安装时安装应用程序包并在其上调用 FIXUP_BUNDLE。这是该功能:

FUNCTION(ADD_CUSTOM_EXECUTABLE TARGET HEADERS SOURCES DEPENDENCIES)
    ADD_EXECUTABLE(${TARGET} MACOSX_BUNDLE ${HEADERS} ${SOURCES} ${ARGN})
    TARGET_LINK_LIBRARIES(${TARGET} ${DEPENDENCIES})

    INSTALL(TARGETS ${TARGET} BUNDLE DESTINATION .)

    INSTALL(CODE "
        INCLUDE(BundleUtilities)
        FIXUP_BUNDLE(${CMAKE_INSTALL_PREFIX}/${TARGET}.app \"\" \"\") 
    ")
ENDFUNCTION(ADD_CUSTOM_EXECUTABLE)

我没有为 FIXUP_BUNDLE 的 LIBS 或 DIRS 参数传递任何内容,因为我目前没有使用任何插件。ALL_BUILD 项目在 Xcode 中构建良好,安装项目运行没有失败,但是对于通过otool -L. 这是一个示例,显示了 SFML 系统框架的警告开始,几乎在 FIXUP_BUNDLE 被调用之后:

fixup_bundle
    app='/Users/user/Desktop/SFML_Testing_BUILD/dist/MyApp.app'
    libs=''
    dirs=''
fixup_bundle: preparing...
warning: embedded item does not exist 'Users/user/Desktop/SFML_Testing_BUILD/
dist/MyApp.app/Contents/Frameworks/sfml-system.framework/Versions/2.0.0/
sfml-system'
warning: cannot resolve item '@executable_path/../Frameworks/
sfml-system.framework/Versions/2.0.0/sfml-system'

possible problems:
    need more directories?
    need to use InstallRequiredSystemLibraries?
    run in install tree instead of build tree?

不久之后,像这样的东西:

warning: target '@executable_path/../Frameworks/sfml-system.framework/Versions/
2.0.0/sfml-system' is not absolute...
warning: target '@executable_path/../Frameworks/sfml-system.framework/Versions/
2.0.0/sfml-system' does not exist...
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/otool: can't open file: @executable_path/../Frameworks/
sfml-system.framework/Versions/2.0.0/sfml-system (No such file or directory)
otool: can't open file: @executable_path/../Frameworks/
sfml-system.framework/Versions/2.0.0/sfml-system
(No such file or directory)

有谁知道如何解决这个问题?我在互联网上搜寻解决方案,但没有运气。

4

1 回答 1

2

如果您尝试拉入的框架位于“/Library/Frameworks”中,则假定它是一个“系统库”,实际上不需要拉入...假设是,如果您依赖于已安装的系统库(而不是您自己在某个地方构建的系统库),那么您的最终用户也将拥有相同的已安装系统库。(在安装您的应用程序之前,您必须要求他们安装 SFML。)

我们这样做是为了阻止人们意外地在他们的捆绑软件中包含他们在法律上不应该包含的系统框架。捆绑 SFML 框架是否合法对您来说是一个严格的负担。

如果这种假设在您的情况下是错误的,并且您希望将 SFML 内容视为“非系统”,您可能必须自定义 BundleUtilities 来处理它。

不过,首先尝试这个会更容易:首先编写一个脚本,将它们复制到您的构建树包中,然后安装该包,并在尝试以下自定义覆盖之前查看 fixup_bundle 是否可以正常工作。

如有必要,您可以尝试如下自定义:

首先,将带有内联代码的 install(CODE 片段更改为 install(SCRIPT 调用,该调用调用配置/生成的脚本文件。否则,将有太多代码放入该块中,并且所有转义都会变得讨厌。

接下来,在脚本中包含 BundleUtilities 之前,为 GetPrerequisites gp_resolved_file_type 函数添加一个覆盖函数。这就是 BundleUtilities 用来声明库是否是“系统”库的方法。BundleUtilities 需要的每个文件类型解析都会调用名为 gp_resolved_file_type_override 的覆盖函数。您可以编写它以简单地将库名称与字符串“sfml”匹配,如果匹配,则将类型声明为“其他”,您的声明将获胜。

之后,上述一些警告应该会消失,但您可能会遇到其他需要进一步定制的问题。

这有点讨厌和复杂,但应该可以使用现有的 CMake ......

然而:

BundleUtilities 为系统库引入任何东西的事实是一个错误,应该在 CMake 错误跟踪器中报告为错误:http ://www.cmake.org/Bug

于 2012-11-08T15:35:40.260 回答