Wednesday, March 22, 2023
Learning Code
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
Learning Code
No Result
View All Result
Home Swift

Building static and dynamic Swift libraries using the Swift compiler

learningcode_x1mckf by learningcode_x1mckf
September 17, 2022
in Swift
0
Building static and dynamic Swift libraries using the Swift compiler
74
SHARES
1.2k
VIEWS
Share on FacebookShare on Twitter


2021/02/16

This tutorial is all about emitting varied Swift binaries with out the Swift package deal supervisor, however solely utilizing the Swift compiler.

Swift

What the heck is a library?


A library is a set of Swift elements that different functions can use.


Think about that you’re making a easy utility to pluralize a string. It really works nice, you end the app and also you begin working in your subsequent one. In your subsequent utility, you face the very same situation, it’s important to print countable gadgets (e.g 2 bananas). What would you do? 🤔


The very first thing that may cross your thoughts is to repeat all of the supply code from the primary utility into the second. Effectively, this might work in fact, however what occurs should you uncover a bug within the pluralization part? Now it’s important to repair the difficulty at two locations, since you have simply duplicated the complete stuff. There have to be a greater method… 🧠


Fortuitously laptop programmers confronted the very same situation, so that they invented shared libraries. A shared library is a particular sort of binary part that you should use in your primary utility. This fashion you may outsource Swift code right into a separate file (or bunch of recordsdata), throw in some entry management to permit different apps to make use of public strategies and name capabilities out of your library and right here we go, we simply shared our frequent code between our functions.


Oh wait, there’s a bug within the lib, how can I repair it? Effectively, that is the place issues get a bit sophisticated, however don’t fret an excessive amount of, I am going to attempt to clarify the way it works. So, final time, you understand, after we talked about the Swift compiler and linker, I discussed, that they will resolve dependencies in your program. While you use a library you may select between two approaches.

  • static linking
  • dynamic linking

Static linking signifies that the supply code contained in the library shall be actually copy-pasted into your utility binary. Dynamic linking then again signifies that your library dependencies shall be resolved at runtime. By the way in which, it’s important to determine this upfront, since it’s important to construct both a static or a dynamic library. Huhh? Okay, let me do that once more… 🙃


The static library strategy is extra easy. You may simply construct a static library utilizing the compiler (you will see find out how to make one in a while), then you may import this library inside your utility supply (import MyLibrary). Now once you compile the principle app, it’s important to inform the compiler the situation of your static (binary) library, and the publicly accessible objects (headers or module map) which can be obtainable to make use of. This fashion when your app consists the symbols from the lib (courses, strategies, and so forth) might be copied to the principle executable file). While you run the app, required objects shall be there already contained in the binary file, so you may run it as it’s.



The primary distinction between a static and a dynamic library is that you do not copy each required image to the executable utility binary once you use a dylib file, however among the “undefined” symbols shall be resolved at runtime. First it’s important to construct your library as a dynamic dependency utilizing the Swift compiler, it will produce a dynamic (binary) library file and a module map (header recordsdata). While you make the ultimate model of your app, the system will put references of the dynamic library to your executable as a substitute of copying the contents of the dylib file. If you wish to run your utility it’s important to ensure that the referenced dynamic library is out there to make use of. The working system will attempt to load the generated dylib file so the applying resolves the symbols primarily based on the reference pointers. 👈



Ought to I select dynamic or static linking?

Effectively, it depends upon the surroundings. For instance the Swift Package deal Supervisor prefers to make use of static linking, however Xcode will attempt to construct SPM packages as dynamic dependencies. You can even explicitly inform SPM to construct a static or dynamic library, however in many of the instances you need to follow the automated worth, so the system can construct the fitting module dependency for you.



import PackageDescription

let package deal = Package deal(
    identify: "MyLibrary",
    merchandise: [
        
        .library(name: "MyLibrary", targets: ["MyLibrary"]),
        
    ],
    targets: [
        .target(name: "MyLibrary", dependencies: []),
    ]
)


By the way in which in case you are confused sufficient, I’ve an article for beginners about Swift packages, modules, frameworks and the tools that makes this entire dependency administration potential. You must positively have a look, it is a some kind of a deep dive into FAT frameworks, however the first a part of the article is filled with helpful definitions and introductions to numerous instructions.


Again to the unique query: static vs dynamic? Do you keep in mind the bug within the library that we’ve got to repair? When you use a static library it’s important to rebuild all of the apps which can be relying on it (they have to be linked with the fastened library in fact) with a view to make the difficulty disappear. 🐛

Since a dynamic library is loaded at runtime and the symbols are usually not embedded into the applying binary, you may merely construct a brand new dylib file and substitute the previous one to repair the bug. This fashion all of the apps which can be referencing to this dependency could have the repair totally free. There is no such thing as a must recompile everyting, besides the defective code within the framework itself. 💪


Additionally it is price to say that the ultimate app measurement is smaller once you use a dylib.


Okay, however why ought to I ever use static linking if dylibz are so cool? The reality is that typically you wish to encapsulate all the pieces right into a single binary, as a substitute of putting in numerous different dylib recordsdata into the system. Additionally what occurs if one thing deletes a dylib that your app would require to work flawlessly? That’d suck for positive, particularly if it’s a mission-critical script on a server… 😳


Hopefully, I over-explained issues, so we will begin constructing our very first static library.



Compiling a static Swift library

Do you continue to have that little Level struct from the earlier tutorial? Let’s construct a static library from that file, however earlier than we achieve this, we’ve got to explicitly mark it as public, plus we want a public init technique so as to have the ability to create a Level struct from our utility. You understand, in Swift, access control permits us, programmers, to cover particular elements of a library from different builders.


public struct Level 
    public let x: Int
    public let y: Int

    public init(x: Int, y: Int) 
        self.x = x
        self.y = y
    


Now we’re able to construct our static library primarily based on this single level.swift supply file. As I discussed this earlier than, we want a binary file and a module map file that incorporates the publicly accessible interface for the lib. You should utilize the -emit-library flat to inform the Swift compiler that we want a binary library file plus utilizing the -emit-module parameter will produce a Swift module data file with all of the API and docs wanted for different modules. By default the compiler would emit a dylib (on macOS at the least), so we’ve got to make use of the -static flat to explicitly generate a static dependency. 🔨


swiftc level.swift -emit-module -emit-library -static


The command above ought to produce 4 new recordsdata:

  • libpoint.a – The binary static library itself
  • level.swiftdoc – Documentation for the module (binary format)
  • level.swiftmodule – Data in regards to the module, “Swift header file”
  • level.swiftsourceinfo – Source information file

Transfer these recordsdata inside a lib folder, so it’s going to be less difficult to work with them. That is actually it, we have simply created a working static library, however how can we use it to hyperlink them towards our primary utility? 🤔


To start with, we’ve got to import our newly created module contained in the primary.swift file if we wish to use the objects (in our case the Level struct) from it. By the way in which you may add a customized module identify to your library should you use the -module-name [name] argument with the earlier swiftc command.

import level

let p = Level(x: 4, y: 20)

print("Whats up library!", p.x, p.y)


So, all of our library recordsdata are situated in a lib folder, and our default module identify is level (primarily based on our single enter file). We are able to use the swiftc command once more, to compile the principle file, this time we use the -L flag so as to add a library search path, so the compiler can find our binary libpoint.a file. We additionally must set a search path for imports, the -I property will assist us, this fashion the general public API (headers) of the module shall be obtainable in our supply file. The very final thing that we’ve got to append to the top of the command is the -l[name] flag, this specifies the library identify we want to hyperlink towards. Watch out, there isn’t any house in between the -l and the identify worth! ⚠️


swiftc primary.swift -L ./lib/ -I ./lib/ -lpoint


./primary


Voilá, we have simply separated a file from the principle utility through the use of a static dependency. 👏




Compiling a dynamic Swift library

In principle, we will use the identical code and construct a dynamic library from the level.swift file and compile our primary.swift file utilizing that shared framework. We simply drop the -static flag first.


swiftc level.swift -emit-module -emit-library


This time the output is barely completely different. We have got a libpoint.dylib binary as a substitute of the libpoint.a, however all the opposite recordsdata look similar. Extension my fluctuate per working system:

  • macOS – static: .a, dynamic: .dylib
  • Linux – static: .so, dynamic: .dylib
  • Home windows – static: .lib, dynamic: .dll

So we’ve got our dylib file, however the actual query is: can we construct the principle.swift file with it?


swiftc primary.swift -L ./lib/ -I ./lib/ -lpoint


./primary


Now rename the libpoint.dylib file into libpoint.foo and run the principle app once more.


./primary





Whoops, looks as if we’ve got an issue. Don’t fret, that is the anticipated output, since we renamed the dynamic library and the applying cannot discover it. When the loader tries to get the referenced symbols from the file it seems up dynamic libraries at a couple of completely different locations.

  • The listing you specified by way of the -L flag (./lib/).
  • The listing the place your executable file is (./)
  • The /usr/lib/ or the /usr/native/lib/ directories

For the reason that /usr/lib/ listing is protected by the well-known SIP “guard”, you need to ship your dylib recordsdata subsequent to your executable binary, or alternatively you may set up them beneath the /usr/native/lib/ folder. Sadly, this lookup technique can result in all kind of points, I actually do not wish to get into the small print this time, however it will probably result in compatibility and safety points. 🤫


The excellent news is that now should you change one thing within the dylib, and also you merely rebuild & substitute the file then you definitely run the ./primary once more (with out recompiling), the altered dynamic library shall be used. Simply attempt to put a print assertion into the init technique of the Level struct…




Abstract

Actually, I would fairly go together with a static library in many of the instances as a result of utilizing a static library will assure that your utility has each essential dependency embedded into the binary file.


In fact dynamic libraries are nice in case you are the writer of a generally used framework, such the Swift customary library, Basis or UIKit. These modules are shipped as shared libraries, as a result of they’re large and nearly each single app imports them. Simply give it some thought, if we might hyperlink these three frameworks statically that’d add rather a lot to the dimensions of our apps, plus it might be method tougher to repair system-wide bugs. That is the explanation why these packages are shipped as shared libz, plus Apple can provides us a promise that these elements will all the time be obtainable as a part of the working system. 😅


In any case, there are some instruments that you should use to change library loader paths, I am going to let you know extra about this subsequent time. It will be a extra superior matter together with completely different languages. I will present you find out how to construct a library utilizing C and find out how to name it utilizing Swift, with out SPM. 🤓





Source link

You might also like

Hummingbird routing and requests – The.Swift.Dev.

Building a Scrollable Custom Tab Bar in SwiftUI

Beginner’s guide to server-side Swift using the Hummingbird framework

Share30Tweet19
learningcode_x1mckf

learningcode_x1mckf

Recommended For You

Hummingbird routing and requests – The.Swift.Dev.

by learningcode_x1mckf
March 17, 2023
0
Hummingbird routing and requests – The.Swift.Dev.

Routing on the server facet means the server goes to ship a response primarily based on the URL path that the consumer referred to as when firing up...

Read more

Building a Scrollable Custom Tab Bar in SwiftUI

by learningcode_x1mckf
March 10, 2023
0
Building a Scrollable Custom Tab Bar in SwiftUI

Whether or not you’re making a social media app or a productiveness device, the tab bar interface can improve the consumer expertise by making it extra intuitive and...

Read more

Beginner’s guide to server-side Swift using the Hummingbird framework

by learningcode_x1mckf
March 8, 2023
0
Beginner’s guide to server-side Swift using the Hummingbird framework

Swift on the Server in 2023 Three years in the past I began to focus on Vapor, the preferred web-framework written in Swift, which served me very...

Read more

What’s new in Swift 5.8 – Hacking with Swift

by learningcode_x1mckf
March 8, 2023
0
What’s new in Swift 5.8 – Hacking with Swift

Though many main Swift modifications are at present percolating by way of Swift Evolution, Swift 5.8 itself is extra of a clear up launch: there are additions, sure,...

Read more

Customizing SwiftUI Bottom Sheet’s Background and Scrolling

by learningcode_x1mckf
February 28, 2023
0
Customizing SwiftUI Bottom Sheet’s Background and Scrolling

For the reason that launch of iOS 16, it’s straightforward to create an interactive backside sheet utilizing SwiftUI. All it is advisable to do is to embed a...

Read more
Next Post
20 million JavaScript devs can now build applications on NEAR: KBW 2022

20 million JavaScript devs can now build applications on NEAR: KBW 2022

Leave a Reply Cancel reply

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

Related News

Introducing – Swift cheatsheet – The.Swift.Dev.

Introducing – Swift cheatsheet – The.Swift.Dev.

November 10, 2022
Inheriting From list vs UserList – Real Python

Inheriting From list vs UserList – Real Python

September 12, 2022
How to use the Command pattern in Java

How to use the Command pattern in Java

September 16, 2022

Browse by Category

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

RECENT POSTS

  • Introducing Carbon, Google's Experimental Successor for C++ – MUO – MakeUseOf
  • Oracle aims to sustain Java's 27-year franchise with version 20 rollout – SiliconANGLE News
  • How to learn JavaScript? – JavaScript – SitePoint

CATEGORIES

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

© 2022 Copyright Learning Code

No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#

© 2022 Copyright Learning Code

Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?