Study every part about Swift modules, libraries, packages, closed supply frameworks, command line instruments and extra.
Fundamental definitions
To begin with you must have a transparent understanding in regards to the fundamental phrases. In the event you already know what’s the distinction between a module, package deal, library or framework you may skip this part. Nevertheless for those who nonetheless have some blended emotions about this stuff, please learn forward, you received’t remorse it. 😉
Bundle
A package deal consists of Swift supply recordsdata and a manifest file.
A package deal is a group of Swift supply recordsdata. In case you are utilizing Swift Bundle Supervisor you even have to offer a manifest file as a way to make an actual package deal. If you wish to be taught extra about this device, you must examine my Swift Bundle Supervisor tutorial.
Instance: that is your package deal:
Sources
my-source-file.swift
Bundle.swift
It’s also possible to try the open sourced swift-corelibs-foundation package deal by Apple, which is used to construct the Basis framework for Swift.
Library
Library is a packaged assortment of object recordsdata that program can hyperlink towards.
So a library is a bunch of compiled code. You may create two sorts of libraries:
From a extremely easy perspective the one distinction between them is the strategy of “integrating” aka. linking them into your venture. Earlier than I let you know extra about this course of, first we should always discuss object recordsdata.
Mach-O file format
To create packages, builders convert supply code to object recordsdata. The item recordsdata are then packaged into executable code or static libraries.
Once you’re compiling the supply recordsdata you might be mainly making object recordsdata, utilizing the Mach-O (MachObject) file format. These recordsdata are the core constructing blocks of your functions, frameworks, and libraries (each dynamic and static).
Linking libraries
Linking refers back to the creation of a single executable file from a number of object recordsdata.
In different phrases:
After the compiler has created all the thing recordsdata, one other program is known as to bundle them into an executable program file. That program is known as a linker and the method of bundling them into the executable is known as linking.
Linking is simply combining all of your object recordsdata into an executable and resolving all of the externals, so the system will be capable to name all of the capabilities contained in the binary.
Static linking
The supply code of the library is actually going to be copied into the appliance’s supply. It will end in a giant executable, it’ll take extra time to load, so the binary may have a slower startup time. Oh, did I point out that if you’re attempting to hyperlink the identical library greater than as soon as, the method will fail due to duplicated symbols?
This methodology has benefits as effectively, for instance the executable will at all times comprise the proper model of the library, and solely these components might be copied into the principle software which might be actually used, so that you don’t need to load the entire stuff, but it surely looks like dynamic linking goes to be higher in some circumstances.
Dynamic linking
Dynamic libraries are usually not embedded into the supply of the binary, they’re loaded at runtime. Because of this apps could be smaller and startup time can considerably be sooner due to the light-weight binary recordsdata. As a free of charge dynamic libraries could be shared with a number of executables to allow them to have decrease reminiscence footprints. That’s why typically they’re being referred as shared libraries.
After all if the dynamic library shouldn’t be out there – or it’s out there however their model is incompatible – your software received’t run or it’ll crash. However this may be a bonus, as a result of the creator of the dynamic library can ship fixes and your app can profit from these, with out recompilation.
Happily system libraries like UIKit are at all times out there, so that you don’t have to fret an excessive amount of about this concern…
Framework
A framework is a hierarchical listing that encapsulates shared sources, akin to a dynamic shared library, nib recordsdata, picture recordsdata, localized strings, header recordsdata, and reference documentation in a single package deal.
So let’s make this easy: frameworks are static or dynamic libraries packed right into a bundle with some additional property, meta description for versioning and extra. UIKit is a framework which wants picture property to show among the UI parts, additionally it has a model description, by the way in which the model of UIKit is similar because the model of iOS.
Module
Swift organizes code into modules. Every module specifies a namespace and enforces entry controls on which components of that code can be utilized outdoors of the module.
With the import key phrase you might be actually importing exterior modules into your sorce. In Swift you might be at all times utilizing frameworks as modules, however let’s return in time for some time to grasp why we would have liked modules in any respect.
import UIKit
import my-awesome-module
Earlier than modules you needed to import framework headers immediately into your code and also you additionally needed to hyperlink manually the framework’s binary inside Xcode. The #import macro actually copy-pasted the entire resolved dependency construction into your code, and the compiler did the work on that massive supply file.
It was a fragile system, issues might go mistaken with macro definitions, you possibly can simply break different frameworks. That was the rationale for outlining prefixed uppercased very lengthy macro names like: NS_MYSUPERLONGMACRONAME
… 😒
There was an different concern: the copy-pasting resulted in non-scalable compile occasions. In an effort to clear up this, precompiled header (PCH) recordsdata had been born, however that was solely a partial resolution, as a result of they polluted the namespace (you realize for those who import UIKit in a PCH file it will get out there in in every single place), and no-one actually maintained them.
Modules and module maps
The holy grail was already there, with the assistance of module maps (defining what sort of headers are a part of a module and what’s the binary that has the implementation) we’ve bought encapsulated modular frameworks. 🎉 They’re individually compiled as soon as, the header recordsdata are defining the interface (API), and the (mechanically) linked dylib
file comprises the implementation. Hurray, no have to parse framework headers throughout compilation time (scalability), so native macro definitions received’t break something. Modules can comprise submodules (inheritance), and also you don’t need to hyperlink them explicitly inside your (Xcode) venture, as a result of the .modulemap
file has all the knowledge that the construct system wants.
Finish of the story, now you realize what occurs beneath the hood, while you import Basis
or import UIKit
.
Now that you realize the logic behind the entire dynamic modular framework system, we should always begin analyzing the instruments that make this infrastructure doable.
All the time learn the person pages, aka. RTFM! In the event you don’t wish to learn that a lot, you may obtain the instance venture from GitLab and open the makefiles for the essence. There might be 3 major classes: C, Swift and Xcode venture examples.
clang
the Clang C, C++, and Goal-C compiler
Clang is a compiler frontend for C languages (C, C++, Goal-C). When you’ve got ever tried to compiled C code with gcc
throughout your college years, you may think about that clang is kind of the identical as gcc
, however these days it might probably do much more.
clang -c major.c -o major.o #compiles a C supply file
LLVM: compiler backend system, which might compile and optimize the intermediate illustration (IR) code generated by clang or the Swift compiler for instance. It’s language impartial, and it might probably achieve this many issues that would match right into a e book, however for now let’s say that LLVM is making the ultimate machine code in your executable.
swiftc
The Swift compiler, there is no such thing as a handbook entry for this factor, however don’t fear, simply hearth up swiftc -h
and see what can provide to you.
swiftc major.swift #compiles a Swift supply file
As you may see this device is what truly can compile the Swift supply recordsdata into Mach-O’s or ultimate executables. There’s a brief instance within the connected repository, you must examine on that for those who’d wish to be taught extra in regards to the Swift compiler.
ar
The ar
utility creates and maintains teams of recordsdata mixed into an archive. As soon as an archive has been created, new recordsdata could be added and current recordsdata could be extracted, deleted, or changed.
So, in a nutshell you may zip Mach-O recordsdata into one file.
ar -rcs myLibrary.a *.o
With the assistance of ar
you had been in a position to create static library recordsdata, however these days libtool
have the identical performance and much more.
ranlib
ranlib
generates an index to the contents of an archive and shops it within the archive. The index lists every image outlined by a member of an archive that could be a relocatable object file.
ranlib
can create an index file contained in the static lib, so issues are going to be sooner while you’re about to make use of your library.
ranlib myLibrary.a
So ranlib
& ar
are instruments for sustaining static libraries, often ar
takes care of the indexing, and also you don’t need to run ranlib
anymore. Nevertheless there’s a higher choice for managing static (and dynamic) libraries that you must be taught…
libtool
create libraries
With libtool
you may create dynamically linked libraries, or statically linked (archive) libraries. This device with the -static
choice is meant to exchange ar
& ranlib
.
libtool -static *.o -o myLibrary.a
These days libtool
is the principle choice for increase library recordsdata, you must undoubtedly be taught this device for those who’re into the subject. You may examine the instance venture’s Makefile
for more information, or as often you may learn the manuals (man libtool
). 😉
ld
The ld command combines a number of object recordsdata and libraries, resolves references, and produces an ouput file. ld can produce a ultimate linked picture (executable, dylib, or bundle).
Let’s make it easy: that is the linker device.
ld major.o -lSystem -LmyLibLocation -lmyLibrary -o MyApp
It will possibly hyperlink a number of recordsdata right into a single entity, so from the Mach-O’s you’ll be capable to make an executable binary. Linking is important, as a result of the system must resolve the addresses of every methodology from the linked libraries. In different phrases, the executable will be capable to run and your entire capabilities might be out there for calling. 📱
nm
show title checklist (image desk)
With nm
you may see what symbols are inside a file.
nm myLibrary.a
# 0000000000001000 A __mh_execute_header
# U _factorial
# 0000000000001f50 T _main
# U _printf
# U dyld_stub_binder
As you may see from the output, some form of reminiscence addresses are related for a few of symbols. People who have addresses are literally resolved, all of the others are coming from different libraries (they’re not resolved but). So which means that they’ll be resolved at runtime. The opposite choice is that it’s important to hyperlink them. 😅
otool
object file displaying device
With otool
you may look at the contents of Mach-O recordsdata or libraries.
otool -L myLibrary.a
otool -tV myLibrary.a
For instance you may checklist the linked libraries, or see the disassembled textual content contents of the file. It’s a extremely useful device for those who’re acquainted with the Mach-O file format, additionally good one to make use of for reverse-engineer an current software.
lipo
create or function on common recordsdata
With the assistance of the lipo
device you may create common (multi-architecture) recordsdata. Normally this device is used for creating common frameworks.
lipo -create -output myFramework.framework gadgets.framework simulator.framework
Think about the next state of affairs: you construct your sources each for arm7
and i386
. On an actual system you’d have to ship the arm7
model, however for the iOS simulator you’ll want the i386
one. With the assistance of lipo
you may mix these architectures into one, and ship that framework, so the top consumer don’t have to fret about this concern anymore.
Learn on the article to see the way it’s finished. 👇
These instruments could be invoked from the command line as effectively, however they’re rather more associated to Xcode than those earlier than. Let’s have a fast walk-through.
xcode-select
Manages the energetic developer listing for Xcode and BSD instruments. When you’ve got a number of variations of Xcode in your machine this device can simply change between the developer instruments offered by the induvidual variations.
xcode-select --switch path/to/Xcode.app
xcrun
Run or find improvement instruments and properties. With xcrun you may mainly run something you can handle from Xcode.
xcrun simctl checklist #checklist of simulators
codesign
Create and manipulate code signatures
It will possibly signal your software with the correct signature. Normally this factor failed while you had been attempting to signal your app earlier than automated signing was launched.
codesign -s "Your Firm, Inc." /path/to/MyApp.app
codesign -v /path/to/MyApp.app
xcodebuild
construct Xcode tasks and workspaces
That’s it. It’ll parse the Xcode venture or workspace file and executes the suitable buid instructions based mostly on it.
xcodebuild -project Instance.xcodeproj -target Instance
xcodebuild -list
xcodebuild -showsdks
FAT frameworks
Tips on how to make a closed supply common FATtened (multi-architecture) Swift framework for iOS?
So we’re right here, the entire article was made for studying the logic behind this tutorial.
To begin with, I don’t wish to reinvent the wheel, as a result of there’s a superbly written article that you must learn. Nevertheless, I’d like to present you some extra detailed clarification and just a little modification for the scripts.
Skinny vs. FAT frameworks
Skinny frameworks comprises compiled code for just one structure. FAT frameworks then again are containing “slices” for a number of architectures. Architectures are mainly referred as slices, so for instance the i386
or arm7
slice.
This implies, for those who compile a framework just for i386
and x86_64
architectures, it would work solely on the simulator and horribly fail on actual gadgets. So if you wish to construct a very common framework, it’s important to compile for ALL the prevailing architectures.
Constructing a FAT framework
I’ve a excellent news for you. You simply want one little construct part script and an combination goal as a way to construct a multi-architecture framework. Right here it’s, shamelessly ripped off from the supply article, with some additional modifications… 😁
set -e
BUILD_PATH="${SRCROOT}/construct"
DEPLOYMENT_PATH="${SRCROOT}"
TARGET_NAME="Console-iOS"
FRAMEWORK_NAME="Console"
FRAMEWORK="${FRAMEWORK_NAME}.framework"
FRAMEWORK_PATH="${DEPLOYMENT_PATH}/${FRAMEWORK}"
# clear the construct folder
if [ -d "${BUILD_PATH}" ]; then
rm -rf "${BUILD_PATH}"
fi
# construct the framework for each structure utilizing xcodebuild
xcodebuild -target "${TARGET_NAME}" -configuration Launch
-arch arm64 -arch armv7 -arch armv7s
only_active_arch=no defines_module=sure -sdk "iphoneos"
xcodebuild -target "${TARGET_NAME}" -configuration Launch
-arch x86_64 -arch i386
only_active_arch=no defines_module=sure -sdk "iphonesimulator"
# take away earlier model from the deployment path
if [ -d "${FRAMEWORK_PATH}" ]; then
rm -rf "${FRAMEWORK_PATH}"
fi
# copy freshly constructed model to the deployment path
cp -r "${BUILD_PATH}/Launch-iphoneos/${FRAMEWORK}" "${FRAMEWORK_PATH}"
# merge all of the slices and create the fats framework
lipo -create -output "${FRAMEWORK_PATH}/${FRAMEWORK_NAME}"
"${BUILD_PATH}/Launch-iphoneos/${FRAMEWORK}/${FRAMEWORK_NAME}"
"${BUILD_PATH}/Launch-iphonesimulator/${FRAMEWORK}/${FRAMEWORK_NAME}"
# copy Swift module mappings for the simulator
cp -r "${BUILD_PATH}/Launch-iphonesimulator/${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/"
"${FRAMEWORK_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule"
# clear up the construct folder once more
if [ -d "${BUILD_PATH}" ]; then
rm -rf "${BUILD_PATH}"
fi
You may at all times look at the created framework with the lipo
device.
lipo -info Console.framework/Console
#Architectures within the fats file: Console.framework/Console are: x86_64 i386 armv7 armv7s arm64
Utilization
You simply need to embed your model new framework into the venture that you just’d like to make use of and set some paths. That’s it. Virtually…
Transport to the App Retailer
There is just one concern with fats architectures. They comprise slices for the simulator as effectively. If you wish to submit your app to the app retailer, it’s important to lower off the simulator associated codebase from the framework. The rationale behind that is that no precise actual system requires this chunk of code, so why submit it, proper?
APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
# take away unused architectures from embedded frameworks
discover "$APP_PATH" -name '*.framework' -type d | whereas learn -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults learn "$FRAMEWORK/Data.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
finished
echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"
echo "Changing authentic executable with thinned model"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
finished
This little script will take away all of the pointless slices from the framework, so that you’ll be capable to submit your app by way of iTunesConnect, with none points. (ha-ha-ha. 😅)
NOTE: You need to add this final script to your software’s construct phases.
If you wish to get acquainted with the instruments behind the scenes, this text will provide help to with the fundamentals. I couldn’t discover one thing like this however I needed to dig deeper into the subject, so I made one. I hope you loved the article. 😉