Question

I've been experimenting with porting an Obj-C library to Swift, and I've run into a problem where the linker fails to build a static library when Swift code is in the project.

As a minimal reproducer, go into XCode6 and create a new iOS Static Library. It'll give you a project with a blank .h and .m file. This will compile fine. Then, add a new .swift file to the project (with or without creating a header bridge). This too should compile fine, but instead it fails during linking:

Libtool /Users/alexkarantza/Library/Developer/Xcode/DerivedData/Test-alenfoymgkewlghfjjvizjjuvign/Build/Products/Debug-iphonesimulator/libTest.a normal i386
    cd /Users/alexkarantza/Workspace/Test
    export IPHONEOS_DEPLOYMENT_TARGET=8.0
    export PATH="/Applications/Xcode6-Beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode6-Beta.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static -arch_only i386 -syslibroot /Applications/Xcode6-Beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.0.sdk -L/Users/alexkarantza/Library/Developer/Xcode/DerivedData/Test-alenfoymgkewlghfjjvizjjuvign/Build/Products/Debug-iphonesimulator -filelist /Users/alexkarantza/Library/Developer/Xcode/DerivedData/Test-alenfoymgkewlghfjjvizjjuvign/Build/Intermediates/Test.build/Debug-iphonesimulator/Test.build/Objects-normal/i386/Test.LinkFileList -ObjC -L/Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator -Xlinker -rpath -Xlinker /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator -Xlinker -force_load -Xlinker /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.a -Xlinker -sectalign -Xlinker __SWIFT -Xlinker __ast -Xlinker 4 -Xlinker -sectcreate -Xlinker __SWIFT -Xlinker __ast -Xlinker /Users/alexkarantza/Library/Developer/Xcode/DerivedData/Test-alenfoymgkewlghfjjvizjjuvign/Build/Intermediates/Test.build/Debug-iphonesimulator/Test.build/Objects-normal/i386/Test.swiftmodule -o /Users/alexkarantza/Library/Developer/Xcode/DerivedData/Test-alenfoymgkewlghfjjvizjjuvign/Build/Products/Debug-iphonesimulator/libTest.a

error: /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: unknown option character `X' in: -Xlinker
Usage: /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static [-] file [...] [-filelist listfile[,dirname]] [-arch_only arch] [-sacLT] [-no_warning_for_no_symbols]
Usage: /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -dynamic [-] file [...] [-filelist listfile[,dirname]] [-arch_only arch] [-o output] [-install_name name] [-compatibility_version #] [-current_version #] [-seg1addr 0x#] [-segs_read_only_addr 0x#] [-segs_read_write_addr 0x#] [-seg_addr_table <filename>] [-seg_addr_table_filename <file_system_path>] [-all_load] [-noall_load]

This happens if I'm targeting the simulator or the device. It looks like perhaps having the Swift file in the project is causing it to use linker options normally reserved for executables, even though the target is a static library? I don't know enough about the build options to know if this is a bug in the beta, or some option I should be configuring. It seems questionable that the build would legitimately fail on such a trivial example. Any thoughts?

Was it helpful?

Solution

To answer my own question after some discussion in the comments, it is simply not possible to build static libraries that include Swift code yet. I'm writing this as of Beta 4, and the release notes still say, under "Known issues in Xcode 6 beta 4":

Xcode does not support building static libraries that include Swift code. (17181019)

OTHER TIPS

I have been looking at this issue too for a while, here is what I found:

First, in Xcode 6 Beta, there is no language selection when you create Cocoa Touch Static Library, the language is set to Objective-C by default, though you can add Swift file to the project, it gives error like in your question as a result. My interpretation is that it is Apple's intention to steer away from creating Swift static library.

So If you intent to build a library that leverages power of Swift, use Cocoa Touch Framework instead of Static Library. I have written steps on creating framework project and app project, you can find it here. Note in that example, I created an Objective-C framework project. Choose Language Swift if want pure Swift framework project.

enter image description here

Also note If you look to import Swift framework into Objective-C project, or mix the languages, there is a good reading here Swift and Objective-C in the Same Project.

Hope this will give you a good direction.

Look at this threat XCode5 simulator: unknown option character `X' in: -Xlinker

In order to understand the error, you have to understand what the command is attempting to do.

In this case it's using Libtool, which is a slightly altered version of libtool. There are some options that are specified in the command line, but what we're looking for is the destination file, and this is passed in as the -o option, who's argument is /Users/jr/ios/app/iCozi/build/DevOnly-iphonesimulator/libCozi\ Common\ Code.a, and the type of library we're generating, and in this case it's -static. Both options together explicitly state that you're making a static library archive.

Because you're making a static library archive, the only thing you're actually doing is taking .o files and possibly .a files and turning them into another .a file. This can be roughly equated to the creating of a .zip file from a set of files (.o), and the contents of other .zip files (.a). There are very few things you can do while making this archive, for example you can't specify libraries that need to be implicitly linked while building a static archive, you can't specify that you're going to require entitlements.

libtool is complaining because it doesn't understand the options that are being used for a static library that are being passed in. In this case the options are:

-Xlinker -sectcreate -Xlinker __TEXT -Xlinker __entitlements -Xlinker /Users/jr/ios/app/iCozi/build/iCozi.build/DevOnly-iphonesimulator/Cozi\ Common\ Code.build/Cozi\ Common\ Code.xcent

These are options that are present when you're trying to link in an entitlements file, which means that some options is specifying the use of an entitlements file. In this case, you found the correct solution yourself, which was to remove the entitlements file specified in the project settings -> Code Signing -> Code Signing Entitlements -> DevOnly.

I came across same problem and I did found a solution for it. 'libtool' is failing because of -Xlinker attribute, which tries to specify Swift module - that seems not to be supported for static libraries. (I also think that is mistake/deficiency by Apple, but maybe that's a discussion for another thread)

What I did is I copy/pasted the whole libtool command to terminal, remove all '-XLinker ...' parameters and surprisingly build succeeded from command line.

My static library project included both Objective-C and Swift sources and they were both 'packed' into produced static library!

The only downside was that Swift module was not produced but in my case that didn't matter because Swift was used only internally - I had only Objective C external interfaces.

I think it would be possible also to expose Swift 'interfaces' by copying produced static lib bridging header along the produced static lib.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top