Thursday, February 2, 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

All about the Swift Package Manager and the Swift toolchain

learningcode_x1mckf by learningcode_x1mckf
October 2, 2022
in Swift
0
All about the Swift Package Manager and the Swift toolchain
74
SHARES
1.2k
VIEWS
Share on FacebookShare on Twitter


2019/01/14

Study the whole lot in regards to the SPM structure. I will additionally educate you the right way to combine your binary executable into the Swift toolchain.

Swift

If you do not know an excessive amount of in regards to the Swift Bundle Supervisor, however you might be searching for the fundamentals please learn my tutorial about SPM that explains just about the whole lot. The intention of this text is to go deep into the SPM structure, additionally earlier than you begin studying this I might advocate to additionally learn my article about frameworks and tools. 📖

Prepared? Go! I imply Swift! 😂


Swift Bundle Supervisor

Have you ever ever questioned about how does SPM parse it’s manifest file to be able to install your packages? Properly, the Bundle.swift manifest is an odd beast. Let me present you an fast instance of an everyday package deal description file:


import PackageDescription

let package deal = Bundle(
    title: "HelloSwift",
    dependencies: [
        
    ],
    targets: [
        .target(
            name: "HelloSwift",
            dependencies: []),
        .testTarget(
            title: "HelloSwiftTests",
            dependencies: ["HelloSwift"]),
    ]
)

The primary line comprises the model data, subsequent we’ve got to import the PackageDescription module which comprises all of the required parts to correctly describe a Swift package deal. In case you run for instance swift package deal replace all of your dependencies on this manifest file shall be resolved & you should use them inside your personal code information. ✅

However how on earth are they doing this magic? 💫

That query was bugging me for some time, so I did a little analysis. First I used to be making an attempt to copy this behaviour with out wanting on the unique implementation of the Swift Bundle Supervisor at github. I knew I shoudn’t parse the Swift file, as a result of that’d be a horrible factor to do – Swift information are messy – so let’s attempt to import it one way or the other… 🙃

Dynamic library loading method

I looked for the “dynamic swift library” key phrases and located an fascinating forum topic on swift.org. Yeah, I am making some progress I believed. WRONG! I used to be method farther from the precise answer than I although, nevertheless it was enjoyable, so I used to be wanting into the implementation particulars of the right way to open a compiled .dylib file utilizing dlopen & dlsym from Swift. How does one create a .dylib file? Ah, I already know this! 👍

I all the time wished to grasp this subject higher, so I began to learn increasingly more each about static and dynamic libraries. Lengthy story quick, you’ll be able to create a dynamic (or static) library with the next product definition:


import PackageDescription

let package deal = Bundle(
    title: "instance",
    merchandise: [
        .library(name: "myStaticLib", type: .static, targets: ["myStaticLib"]),
        .library(title: "myDynamicLib", sort: .dynamic, targets: ["myDynamicLib"]),
    ],
    targets: [
        .target(
            name: "myStaticLib",
            dependencies: []),
        .goal(
            title: "myDynamicLib",
            dependencies: []),
    ]
)

The essential information are going to be positioned contained in the .construct/debug folder. The .swiftmodule is mainly the general public header file, this comprises all of the out there API on your library. The .swiftdoc file comprises the documentation for the compiled module, and relying on the kind you will additionally get a .dylib or a .a file. Guess which one is which.

So I might load the .dylib file through the use of dlopen & dlsym (some @_cdecl magic concerned to get fixed names as an alternative of the “fuzzy” ones), however I used to be continually receiving the identical warning time and again. The dynamic loading labored effectively, however I wished to do away with the warning, so I attempted to take away the embedded the lib dependency from my executable goal. (Trace: probably not doable… afaik. anybody? 🙄)

I used to be messing round with rpaths & the install_name_tool for like hours, however even after I succesfully eliminated my library from the executable, “libSwift*issues” have been nonetheless embedded into it. So that is the unhappy state of an unstable ABI, I believed… anyway at the very least I’ve discovered one thing essential throughout the best way right here:

Importing Swift code into Swift!

Sure, you heard that. It is doable to import compiled Swift libraries into Swift, however not lots of people heard about this (I assume). It is not a preferred subject amongs iOS / UIKit builders, however SPM does this on a regular basis behind the scenes. 😅

How on earth can we import the pre-built libraries? Properly, it is fairly easy.



swiftc dynamic_main.swift -I ./.construct/debug -lmyDynamicLib -L ./.construct/debug
swiftc static_main.swift -I ./.construct/debug -lmyStaticLib -L ./.construct/debug



swift construct -Xswiftc -I -Xswiftc ./.construct/debug -Xswiftc -L -Xswiftc ./.construct/debug -Xswiftc -lmyStaticLib
swift construct -Xswiftc -I -Xswiftc ./.construct/debug -Xswiftc -L -Xswiftc ./.construct/debug -Xswiftc -lmyDynamicLib

You simply need to append just a few compiler flags. The -I stands for the import search path, -L is the library search path, -l hyperlinks the given library. Verify swiftc -h for extra particulars and flags you will not remorse it! Voilá now you’ll be able to distribute closed supply Swift packages. At the least it was good to understand how SPM does the “trick”. 🤓

Please observe that till Swift 5 & ABI stability arrives you should use the precompiled libraries with the identical Swift model solely! So if you happen to compile a lib with Swift 4.2, your executable additionally must be compiled with 4.2., however this can change fairly quickly. 👏

The Swift Bundle Supervisor technique

After 2 days of analysis & studying I actually wished to resolve this, so I’ve began to examine the supply code of SPM. The very first thing I’ve tried was including the --verbose flag after the swift construct command. Right here is the essential factor:

/Functions/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc 
--driver-mode=swift 
-L /Functions/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/4_2 
-lPackageDescription 
-suppress-warnings 
-swift-version 4.2 
-I /Functions/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/4_2 
-target x86_64-apple-macosx10.10 
-sdk /Functions/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk 
/Customers/tib/instance/Bundle.swift 
-fileno 5

Whoa, this spits out a JSON primarily based on my Bundle.swift file!!! 🎉

How the hell are they doing this?

It seems, if you happen to change the -fileno parameter worth to 1 (that is the usual output) you’ll be able to see the outcomes of this command on the console. Now the trick right here is that SPM merely compiles the Bundle.swift and if there’s a -fileno flag current within the command line arguments, effectively it prints out the encoded JSON illustration of the Bundle object after the method exits. That is it, fuckn’ straightforward, nevertheless it took 1 extra day for me to determine this out… parenting 2 children & coding is a tough mixture. 🤷‍♂️

In case you open the /Functions/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/4_2 folder you will see 3 acquainted information there. Precisely. I additionally regarded on the supply of the Package.swift file from the SPM repository, and adopted the registerExitHandler technique. After a profitable Bundle initialization it merely registers an exit handler if a -fileno argument is current encodes itself & dumps the consequence through the use of the file handler quantity. Candy! 😎

Since I used to be just about within the end lap, I wished to determine yet one more factor: how did they handle to place the swift package deal command beneath the swift command?


Swift toolchain

I simply entered swift lol into my terminal. That is what occurred:

[email protected]~: swift lol
error: unable to invoke subcommand:
/Functions/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-lol
(No such file or listing)

Obtained ya! The toolchain is the important thing to the whole lot:

  1. Apple is compiling the PackageDescription library from the Swift Bundle Supervisor and places the .swiftmodule, .swiftdoc, .dylib information into the right locations beneath Xcode’s default toolchain library path.
  2. The swift build, run, take a look at subcommands are simply one other Swift binary executables positioned contained in the toolchain’s binary path. (Named like: swift-package, swift-build, swift-run, swift-test)
  3. The swift command tries to invoke the right subcommand if there’s any and it is a legitimate (Swift) binary. (Tried with a shell script, it failed miserably…)
  4. SPM makes use of the PackageDescription library from the toolchain to be able to compile & flip the manifest file into JSON output.
  5. The remaining is historical past. 🤐

Swift can resolve subcommands from wherever “inside” the PATH variable. You simply need to prefix your Swift script with swift- and also you’re good to go.


SwiftCI – a activity runner for Swift

I had this concept that it might be good to have a grunt / gulp like activity runner additionally a steady integration sercie on a long run through the use of this system I defined above. So I’ve made the same extension wired into the guts of the Swift toolchain: SwiftCI. ❤️

You may seize the proof-of-concept implementation of SwiftCI from github. After installing it you’ll be able to create your personal CI.swift information and run your workflows.

import CI

let buildWorkflow = Workflow(
    title: "default",
    duties: [
        Task(name: "HelloWorld",
             url: "[email protected]:BinaryBirds/HelloWorld.git",
             model: "1.0.0",
             inputs: [:]),

        Process(title: "OutputGenerator",
             url: "~/ci/Duties/OutputGenerator",
             model: "1.0.0",
             inputs: [:]),

        Process(title: "SampleTask",
             url: "[email protected]:BinaryBirds/SampleTask.git",
             model: "1.0.1",
             inputs: ["task-input-parameter": "Hello SampleTask!"]),
    ])

let testWorkflow = Workflow(
    title: "linux",
    duties: [
        Task(name: "SampleTask",
             url: "https://github.com/BinaryBirds/SampleTask.git",
             version: "1.0.0",
             inputs: ["task-input-parameter": "Hello SampleTask!"]),
        ])

let challenge = Mission(title: "Instance",
                      url: "[email protected]:BinaryBirds/Instance.git",
                      workflows: [buildWorkflow, testWorkflow])

The code above is a pattern from a CI.swift file, you’ll be able to merely run any workflow with the swift ci run workflow-name command. The whole lot is 100% written in Swift, even the CI workflow descriptor file. I am planning to increase my ci namespace with some useful subcommands afterward. PR’s are greater than welcomed!

I am very proud of the consequence, not simply due to the final product (that is solely a proof of idea implementation), however largely due to the issues I’ve discovered throughout the creation course of. If you wish to get extra suggestions and matters like this it is best to comply with me on Twitter and subscribe to my month-to-month e-newsletter.





Source link

You might also like

The abstract Vapor service factory design pattern

SwiftNIO tutorial – The echo server

Introducing – Vapor cheatsheet – The.Swift.Dev.

Share30Tweet19
learningcode_x1mckf

learningcode_x1mckf

Recommended For You

The abstract Vapor service factory design pattern

by learningcode_x1mckf
February 1, 2023
0
The abstract Vapor service factory design pattern

I've written a number of articles about manufacturing unit design patterns on my weblog and this time I might like to speak a couple of particular one, which...

Read more

SwiftNIO tutorial – The echo server

by learningcode_x1mckf
January 27, 2023
0
SwiftNIO tutorial – The echo server

Intoducing SwiftNIO In the event you used a excessive degree net framework, corresponding to Vapor, up to now, you would possibly had some interplay with occasion loops...

Read more

Introducing – Vapor cheatsheet – The.Swift.Dev.

by learningcode_x1mckf
January 23, 2023
0
Introducing – Vapor cheatsheet – The.Swift.Dev.

Out there on Gumroad Thanks for supporting my work by buying the cheatsheet. 🙏 Download now A whole Vapor framework reference for novices. greater than...

Read more

iCloud Programming Tutorial for iOS: An Introduction

by learningcode_x1mckf
January 18, 2023
0
iCloud Programming Tutorial for iOS: An Introduction

Editor’s observe: This week, we work with Ziad Tamim once more to provide you an introduction of iCloud programming. You’ll learn to save and retrieve knowledge from iCloud.On...

Read more

Easy multipart file upload for Swift

by learningcode_x1mckf
January 18, 2023
0
Easy multipart file upload for Swift

I imagine that you've got already heard in regards to the well-known multipart-data add method that everybody likes to add recordsdata and submit type knowledge, but when not,...

Read more
Next Post
5 principles for ‘stupidly brilliant’ JavaScript apps

5 principles for 'stupidly brilliant' JavaScript apps

Leave a Reply Cancel reply

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

Related News

LeetCode 1472. Design Browser History (Javascript Edition) | by Anisha Jain | Jan, 2023

LeetCode 1472. Design Browser History (Javascript Edition) | by Anisha Jain | Jan, 2023

January 29, 2023

Company-specific skills such as JavaScript, Java, and Python are most sought-after

January 16, 2023
Should C/C++ be deprecated in favor of Rust?

Should C/C++ be deprecated in favor of Rust?

September 29, 2022

Browse by Category

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

RECENT POSTS

  • Java :Full Stack Developer – Western Cape saon_careerjunctionza_state
  • Pay What You Want for this Learn to Code JavaScript Certification Bundle
  • UPB Java Jam brings coffeehouse vibes to Taylor Down Under | Culture

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?