Building a command-line application using Swift and a Swift module

I have been teaching myself Apple’s new Swift programming language since it came out a while ago. I’ve mostly been interested in it to learn OS X programming more than iOS programming but it would apply to either.

I started with just a simple idea of a command-line tool as a toy project for it because it would be quick to get it running without having to design a complicated GUI to make it all work.

Also, in the interests of code-reuse, one component of it would be built as a Swift framework so that it could be used in other projects.

Being that Swift is a brand new language, it is still under heavy development by Apple. That means they have to make it so that elements of the language and run-time can be easily changed without breaking any of the current code that’s out there.

I wrote my framework (which would be analogous to a library or DLL in other operating systems) and got it to build. I brought the framework in to my Swift command-line tool and got everything to build there.

I go to run the command-line tool from Terminal and the loader says that it can’t find my framework, which it needs to run. In normal applications (that have a GUI), any needed frameworks are embedded in the application itself but that can’t be done with a command-line tool so I have to somehow tell the loader where to find my framework. I didn’t want to install my framework in the system-wide frameworks because this is just a toy project. So I made my own Frameworks directory and then used the DYLD_FRAMEWORK_PATH environment variable to point to that directory and then ran the executable again after copying my framework in there. Now the loader says that it can’t find the Swift run-time library in my framework.

This is where my previous mention of Swift being a new language comes in. Normally run-time libraries are included with the OS and they are found automatically by the loader when it tries to run an executable. Since Swift and its associated run-time library are so new and subject to change, when you build an executable the run-time library is embedded in the executable itself. I noticed that the size of my simple command-line application was in the megabytes and thought that was really high for how much code it contained but the fact that the run-time library is embedded in there makes that size a lot more reasonable. The problem is that a framework isn’t considered an executable so the compiler won’t embed the Swift run-time library in there. So when the main executable is run the loader wants the framework to have access to the Swift run-time library as well even though the main executable does have it already.

The way to fix this is to go in to the framework’s project settings and enable the option that says that the framework has embedded Swift code. This forces the compiler to embed the Swift run-time library in the framework. Rebuild the framework and then rebuild the main application. Now the problem is that both the framework and the main application both have the Swift run-time library embedded in them. So when the main application is run, a bunch of warnings will appear saying that multiple copies of methods in the Swift run-time library were found and which one is used is not defined. This isn’t a big deal for my toy project because both embedded Swift run-time libraries are the same and my application runs! The problem will be when something changes in the Swift run-time library and I’ll need to make sure to rebuild both my framework and the main application again or I’m likely to get some strange (and hard to debug behavior).

I hope that once Swift gets a little more mature that this issue will go away. Embedding the run-time library in every executable doesn’t seem like a good long-term solution (and is a waste of space).

Leave a comment

Your email address will not be published. Required fields are marked *