Swift共享库是否为命令行应用程序静态链接?

时间:2015-05-16 14:58:50

标签: xcode swift static-linking dynamic-linking mac-frameworks

我试图在我的Swift应用程序中使用外部框架用于Mac OS X.外部框架也使用Swift,因此依赖于Swift共享库(例如,libswiftCore.dylib)。这由命令

验证
$ otool -L PromiseKit.framework/PromiseKit
PromiseKit.framework/PromiseKit:
    ...
    @rpath/libswiftCore.dylib (compatibility version 0.0.0, current version 0.0.0)

查看@rpath我看到了

$ otool -l PromiseKit.framework/PromiseKit
      ...
      cmd LC_RPATH
  cmdsize 40
     path @executable_path/Frameworks (offset 12)

因此,在运行时我希望@rpath解析为@executable_path/Frameworks

问题

我收到运行时错误

dyld: Library not loaded: @rpath/libswiftCore.dylib
  Referenced from: .../PromiseKit.framework/Versions/A/PromiseKit
  Reason: image not found

查看包含我构建的可执行文件的文件夹,我看不到Frameworks文件夹。

尝试修复

失败

我尝试为我的应用设置EMBEDDED_CONTENT_CONTAINS_SWIFTYES,但仍然创建Frameworks文件夹。

我尝试手动创建Frameworks文件夹并在Swift共享库中复制(来自/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx。这修复了原始错误,现在我看到重复的符号保暖像这一个:

objc[64445]: Class _TtC10Foundation15NSSimpleCString is implemented in both
   .../Frameworks/libswiftFoundation.dylib and
   .../myApp.
   One of the two will be used. Which one is undefined.

问题

是否有可能将Swift库静态链接到我的应用程序中?如果是这样,我如何关闭它并让XCode创建Frameworks文件夹版本?

  

我认为重要的是它是一个命令行应用程序。我尝试创建一个常规应用程序并添加框架,我在Frameworks包中获得了预期的.app文件夹,它包含Swift共享库

1 个答案:

答案 0 :(得分:4)

我可以使用或不使用外部框架的快速命令行工具,只要:

  1. 框架将swift库复制到其Frameworks目录(可选)
  2. 命令行工具在尝试复制swift库时不会生成构建失败
  3. 工具运行路径配置了包含swift库的路径
  4. 要获取框架以复制swift库,请设置:

    "Embedded Content Contains Swift Code" = Yes
    

    为避免在工具尝试将swift库复制到其不存在的Bundle Frameworks目录中时出现构建失败,请设置:

    "Embedded Content Contains Swift Code" = Yes
    

    要配置工具的运行路径,请将以下其中一项添加到LD_RUNPATH_SEARCH_PATHS:

    一个。外部框架中的swift库:

    @executable_path/PromiseKit.framework/Versions/A/Frameworks
    

    请注意,默认情况下,Xcode不会将版本/ A /框架符号链接到框架,就像资源,标题和模块一样。

    B中。 Xcode应用程序中的swift库:

    $(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx
    

    这仅适用于在可执行文件需要运行的每台机器上安装的足够类似的Xcode。但它不需要外部框架来使工具工作。

    ℃。 swift库在与可执行文件相同的目录中重新分发:

    @executable_path
    

    或者,如果可执行文件位于bin /目录中,并且库位于lib /目录中:

    @executable_path/../lib
    

    这可以重新分发,并且不需要外部框架来使工具正常工作。但它需要在Xcode中手动复制文件阶段才能以这种方式设置目录结构。

    请注意,如果工具配置为:

    "Embedded Content Contains Swift Code" = Yes
    

    Xcode会抛出以下构建错误:

    2015-06-04 00:56:28.816 swift-stdlib-tool[5208:2453424] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSFileManager copyItemAtPath:toPath:error:]: destination path is nil'
    *** First throw call stack:
    (
        0   CoreFoundation                      0x00007fff8ee4503c __exceptionPreprocess + 172
        1   libobjc.A.dylib                     0x00007fff89f1c76e objc_exception_throw + 43
        2   CoreFoundation                      0x00007fff8ee44eed +[NSException raise:format:] + 205
        3   Foundation                          0x00007fff926569b7 -[NSFileManager copyItemAtPath:toPath:error:] + 185
        4   swift-stdlib-tool                   0x000000010526b485 _Z13copyLibrariesP8NSStringS0_P19NSMutableDictionary + 853
        5   swift-stdlib-tool                   0x000000010526c60b main + 3915
        6   libdyld.dylib                       0x00007fff97d785c9 start + 1
    )
    libc++abi.dylib: terminating with uncaught exception of type NSException
    Copying libswiftCore.dylib from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx to (null)