Scripts to allow Swift static libraries to be compiled in Xcode
NOTE: As of Xcode 9 beta 4, Xcode natively supports static libraries
with Swift sources, meaning this hack workaround is no longer
needed!
This repo contains a replacement linker script for building iOS static frameworks that contain Swift sources from within Xcode
For each dynamic framework target in Xcode that you would like to be build statically:
LD
Xcode build setting to point to ld.py
Link Binary With Libraries
build phase.You can set this setting through a user defined build setting in Xcode,
or with a xcconfig
file like this:
LD = $(PROJECT_DIR)/path/to/ld.py
There are a few issues with using this script alongside CocoaPods:
[CP] Embed Pods Frameworks
build phase from all
targets that depend on CocoaPods. Otherwise your final .app
bundle
will contain frameworks that are not referenced and just bloating your
app sizeresources
directive
(which is not recommended), your must handle copying
the resources, and any conflicts caused by duplicate namingresource_bundles
directive, you still have to handle copying the resource bundle into
your targets, otherwise it is ignoredIf you feel comfortable working around these issues, you can add
something like this to your Podfile
:
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['LD'] = '$(PROJECT_DIR)/path/to/ld.py'
end
end
end
If you need a more elaborate configuration in CocoaPods, you can use the
xcodeproj
gem in order to
make decisions based on project configuration.
Xcode has never supported building static libraries (and definitely not static frameworks) containing Swift sources (although this has always been supported by Swift Package Manager)
Dynamic frameworks cause an impact on launch times. While this has improved since the original issues, there's still significant overhead when you have a large amount of modules
By using static libraries (or, in this case, static frameworks), you don't have to deal with all the overhead of dynamic framework loading. See this session from WWDC 2016 for more details around this.
By replacing the libtool
invocation from Xcode, this script hijacks
the passed arguments, and transforms them into the arguments necessary
for building static frameworks, instead of dynamic frameworks. Then
since the product ends up existing in the same place as the dynamic
framework that would have otherwise been included, Xcode happily links
the static framework instead.
Static frameworks are very similar to dynamic frameworks, except the
binary contained within the framework ends up being linked statically,
instead of dynamically (see this article for more
details). They differ from traditional static libraries in that they
have the .framework
directory structure identical to dynamic
frameworks. This makes it easier to integrate from within Xcode since
Xcode already expects the products from dynamic framework targets to
follow this structure.