29

So I'm working on an iOS project in Swift, and I wanted to create a Static library with some useful stuff in it.

My problem is when I try to build my lib in Xcode (version 6.3) I have a "Build Failed" followed by : /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: unknown option character 'X' in: -Xlinker

I've never saw this and it's not my first static lib. So I was thinking I may be linked to the fact that I'm using exclusively Swift class.

What do you guys think ? Thank you in advance.

Que20
  • 1,016
  • 1
  • 9
  • 22
  • The accepted answer is no longer accurate. As of Xcode 9 beta 4 Swift can be used in static libraries, though some scenarios required extra configuration. See my answer below. – Dean Kelly Dec 15 '17 at 15:32

4 Answers4

20

As mentioned, Apple does allow Swift in static libraries as of Xcode 9 Beta 4.

We attempted to do this on an existing project with an Objective-C-based target and "child" static library projects and kept running into a linking error

ld: library not found for -lswiftSwiftOnoneSupport for architecture x86_64

also

ld: library not found for -lswiftDispatch for architecture x86_64

This is because the main target (app) is trying to build solely against Objective-C and isn't told by the static library that it needs to include Swift libraries. This was because there weren't any Swift files in the Compile Sources section of our Build Phases for the app target.

So basically all you have to do is add at least one .swift file to that compile list and it will include the Swift libraries for you. It doesn't even need to have any code or values in it, it can be an empty file.

Then you can start adding Swift files to your "child" static library project. I would let it generate the bridging header for you at first then you can move it around and change what gets imported (make sure the project points to the right file in the build settings if you move it).

You should still keep in mind that using Swift and Objective-C within the same static library may have issues of its own. I suggest reading the Apple developer doc "Swift and Objective-C in the Same Project" on how to address importing Objective-C into Swift (using a bridging header) and how to use the Swift files in your Objective-C code (importing the generated -Swift.h for your library).

André Herculano
  • 1,111
  • 20
  • 28
Dean Kelly
  • 588
  • 7
  • 13
  • In my case, I was seeing `ld: library not found for -lswiftCoreImage for architecture x86_64`. This answer solved my linking issues. – Aaron Nov 22 '17 at 16:47
  • @afarnham I think it will do so for pretty much every library in the Swift "core" since it's attempting to link with them when linking in the stuff from the static library that's using Swift. I previously attempted to manually include *every* Swift library with the target dependencies and other build phases; needless to say it was a nightmare...and didn't work. I would hope Apple would make this a project setting so you don't have to have a dummy file in place to "trick" the primary target but this works for now I guess. – Dean Kelly Nov 24 '17 at 00:55
  • Dean Kelly - I am able to create static lib contains swift classes. But how could I access swift class from static library to main app ? – V V Dec 14 '17 at 04:26
  • @Vijay - That is a good candidate for separate question on SO. It depends on what type of file you are importing it into. Say for example your main app "FooApp" has a sub static library called "LibBar" and LibBar has a mix of Swift and ObjC. If you want to import a swift class from LibBar into an ObjC file in FooApp you have to import "LibBar/LibBar-Swift.h". If you want to use a LibBar Swift class in a Swift class in FooApp there are several ways: make LibBar publish a module with a modulemap and import that directly or import "LibBar/LibBar-Swift.h" in your FooApp bridging header. – Dean Kelly Dec 15 '17 at 15:31
  • @thibautnoah It's not a perfect integration by any means. You will have a tough time going from Swift to ObjC between two static libraries (that neither are the main app). It gets to the point it makes sense to create an adjacent static library for your Swift code that inherits from your ObjC one and then import both of those into the third library but that's to solve specific issues. – Dean Kelly Jan 17 '18 at 15:20
  • 1
    I just have a static library with a mix of objective-c and swift and i couldn't get the project (react-native) to compile :) – thibaut noah Jan 17 '18 at 15:30
  • 2
    Amazing, just add a empty Swift file and all those errors go away. Thanks for the help! – Max Apr 10 '18 at 18:10
  • 1
    I envy @thibautnoah. I have had this issue for several weeks now! Thanks a million! – Tiago A. Jun 04 '18 at 10:03
16

Swift doesn't support static library

Although the correct way should be create a framework, there is a workaround here.

Community
  • 1
  • 1
Giordano Scalzo
  • 6,224
  • 2
  • 29
  • 31
  • 3
    That is pretty annoying. Thank you for your answer. – Que20 Apr 16 '15 at 14:44
  • 3
    Hi, since swift doesn't support static library, how can I prevent my colleagues from reading my code ? (It's about encrypting data, so the fewer people know about it, the better). My app also support ios 7, so I guess I cannot use framework, right ? – Pham Hoan Jun 22 '15 at 14:46
  • 1
    might need update until now ? swift support both framework and static lib now ? – Forrest Sep 20 '15 at 02:26
  • From objective c project we can create static library but is it possible to create static library from Swift project as of xcode 8 – Durai Amuthan.H Mar 11 '17 at 15:26
  • Is there any solution using static library in swift 3, I have a encryption library which has only two .a files on vendors sample (written in objective-c ) is working file, When i tried to use those library with using bridging header, (obviously bridging header configuration is fine as other objective-c libs are working fine on ) , it cannot is throwing error. Any one got solution regarding this issue then kindly post some clue. – dip Jun 11 '17 at 03:55
  • Swift support static library now. This answer is very old. – pebble8888 Apr 20 '20 at 05:16
11

As of Xcode 9 beta 4, Xcode natively supports static libraries with Swift sources.

Alessandro
  • 626
  • 11
  • 18
  • 5
    What do I have to do to enable it? When using a static lib which contains swift, how do you access the headers from an objective-c project? – Hari Honor Sep 02 '17 at 03:09
  • @HariKaramSingh I answered the OP question and yours in a separate answer. – Dean Kelly Nov 16 '17 at 20:41
  • For me, this problem started appearing again on Xcode 9.2 (9C40b), after a `pod update`. Probably a swift pod I'm using changed a setting. – emrahgunduz Mar 02 '18 at 15:19
10

Swift consumer -> Swift static library

Xcode version 10.2.1

Create Swift static library

Create a library project or create a library target

File -> New -> Project... -> Cocoa Touch Static Library
//or
Project editor -> Add a Target -> Cocoa Touch Static Library 

Add files .swift

Select `.swift` file -> Select File Inspectors Tab -> Target Membership -> Select the target
//or
Project editor -> select a target -> Build Phases -> Compile Sources -> add files

Build library - ⌘ Command + B or Product -> Build

Note 1: Be sure that you build library for the same process architecture as the client code.
Note 2: expose your API that should be visible for consumer using public or open access modifiers[About]

Find generated output[Build location]

Products group -> lib<product_name>.a -> Show in Finder

The directory includes

  • lib<product_name>.a – a built static library
  • <product_name>.swiftmodule. swiftmodule describe an interface of a library and a compiler version. This folder includes:
  • .swiftdoc - docs
  • .swiftmodule - public interface/definitions

Swift consumer with Swift static library

Drag and drop the binary into the Xcode project[About]

Link Binary[Undefined symbols] [Link vs Embed]

Project editor -> select a target -> General -> Linked Frameworks and Libraries -> add -> Add Others... -> point to `lib<target_name>.a` file
//or
Project editor -> select a target -> Build Phases -> Link Binary With Libraries -> add -> Add Others... -> point to `lib<target_name>.a` file

Add Library Search paths(LIBRARY_SEARCH_PATHS)[Library not found for] [Recursive path]

Project editor -> select a target -> Build Settings -> Search Paths -> Library Search paths -> add path to the parent of `lib<target_name>.a` file

Add Import Paths[No such module] [Recursive path]

Project editor -> select a target -> Build Settings -> Swift Compiler - Search Paths -> Import Paths -> add path to a folder with `.swiftmodule`

Import module to the Swift client code [module_name]

import module_name

[More examples]

yoAlex5
  • 13,571
  • 5
  • 105
  • 98
  • 1
    I've built the static framework in its own self-contained project. I see the `.a` file and the `.swiftmodule` folder. I should drag both of them into my host app and then try to find the paths. Right? – Honey Aug 14 '19 at 20:32
  • Sorry to ask, but any notes on this? – Honey Aug 15 '19 at 22:04
  • Hello @Honey, I will check it again and provide you an information – yoAlex5 Aug 15 '19 at 22:08
  • @Honey, answering for your question, after building a library you should do 3 steps: 1. Drag `.a` file into your host app under `Linked Frameworks and Libraries` section. 2. Specify a path to `.a` fine under the `Library Search paths` section 3. Specify a path to `.swiftmodule` fine under the `Import Paths` section. I have just checked the tutorial and updated a post. If you have some issue pleas feel free to ask – yoAlex5 Aug 15 '19 at 23:52
  • 3
    @yoAlex5, Thanks a lot for your detailed and comprehensive explanation. The only thing I'd like to add it's that you have not to forget to mark your classes and methods `public` to make them available in other targets. Without that, you will be able to import the library but you can't use its code. Also, pay your attention that `init`s must be made public **explicitly**. – Rostyslav Druzhchenko Oct 08 '19 at 12:16