Thursday, August 27, 2026
HomeiOS DevelopmentThe Swift compiler for novices

The Swift compiler for novices

[ad_1]

Compiling Swift supply recordsdata

Essentially the most fundamental state of affairs is whenever you wish to construct and run a single Swift file. Let’s create a foremost.swift file someplace in your disk and print out a easy “Hey world!” textual content.


print("Hey world!")


We do not even have to import the Basis framework, Swift has rather a lot built-in language features and the print operate is a part of the Swift customary library.

The customary library offers a “base layer” of performance for writing Swift purposes, however the Basis framework provides you OS unbiased additional features, core utilities (file administration, localization, and many others.) and extra.

So, how will we flip our print operate into an executable file that we are able to run? The Swift compiler (swiftc command) can compile (translate human readable code into machine code) Swift supply recordsdata into binary executable recordsdata that you could run. 🔨



swiftc foremost.swift 


./foremost


That is probably the most fundamental instance, you can even specify the identify of the output file by utilizing the -o parameter. After all that is an elective parameter, by default the compiler will use the basename of the Swift supply that you’re making an attempt to construct, that is why we had been in a position to run the executable with the ./foremost command within the earlier instance.


swiftc foremost.swift -o hiya
./hiya

There are many different flags and arguments that you need to use to regulate the compilation course of, you’ll be able to examine the obtainable choices with the -h or --help flag.

swiftc -h


Don’t fret you do not have to grasp any of these, we’ll cowl a number of the compiler flags on this tutorial, others in a extra superior article. 😉



Swift compiler flags

Generally you would possibly wish to create customized flags and compile components of your code if that flag is current. The commonest one is the DEBUG flag. You possibly can outline every kind of compiler flags by way of the -D argument, this is a fast foremost.swift instance file.

#if(DEBUG)
    print("debug mode")
#endif
print("Hey world!")


Now when you run the swiftc command it can solely print “Hey world!” once more, but when we add a brand new particular parameter.

swiftc foremost.swift -D DEBUG
./foremost


swiftc foremost.swift -D DEBUG && ./foremost


This time the “debug mode” textual content might be additionally printed out. Swift compiler flags can solely be current or absent, however you can even use different flags to vary supply compilation habits. 🐞




Mutliple Swift sources

What occurs in case you have a number of Swift supply recordsdata and also you wish to compile them to a single binary? Let me present you an instance actual fast. Think about the next level.swift file:


struct Level {
    let x: Int
    let y: Int
}


Now within the foremost.swift file, you’ll be able to truly use this newly outlined Level struct. Please notice that these recordsdata are each situated beneath the identical namespace, so you do not have to make use of the import key phrase, you need to use the struct straight away, it is an inside object.


#if(DEBUG)
    print("debug mode")
#endif
let p = Level(x: 4, y: 20)

print("Hey world!", p.x, p.y)


We will compile a number of sources by merely itemizing them one after different when utilizing the swiftc command, the order of the recordsdata would not matter, the compiler is sensible sufficient, so it may possibly work out the article dependencies between the listed sources.


swiftc level.swift foremost.swift -o point-app

./point-app


You may also use the discover command to checklist all of the Swift sources in a given listing (even with a most search depth), and go the output to the swiftc command. 🔍


swiftc `discover . -name "*.swift" -maxdepth 1` -o app-name


discover . -name "*.swift" -maxdepth 1 | xargs swiftc -o app-name


The xargs command can be helpful, when you don’t love to judge shell instructions by way of the backtick syntax (`) you need to use it to go one command output to a different as an argument.



Beneath the hood of swiftc

I simply talked about that the compiler is sensible sufficient to determine object dependencies, however how does swiftc truly works? Effectively, we are able to see the executed low-level directions if we compile our supply recordsdata utilizing the verbose -v flag. Let’s achieve this and study the output.

swiftc -D DEBUG level.swift foremost.swift -o point-app













































You would possibly assume, this can be a mess, I reformatted the output a bit, so we are able to stroll by way of the steps of the Swift supply compilation course of.

If you compile a program code with a number of sources, each supply must be transformed to machine code (compiler), then these transformed recordsdata must be put collectively (linker), this manner we are able to get our closing executable file. This whole course of known as construct pipeline and it’s best to positively learn the linked article if you wish to know extra about it. 👍

The swiftc command calls the “actual Swift compiler” (swift -frontend) to show each single swift file into an object file (.o). Each command, operate, (class, object and many others.) that you simply write whenever you create a Swift file must be resolved. It is because your machine must lookup the precise implementation of the elements in your codebase. For instance whenever you name the print(“Hey world!”) line, the print operate must be resolved to an precise system name, the operate itself is situated someplace inside an SDK that’s often shipped together with your working system.

The place precisely? For the compiler, it would not matter. The Software program Improvement Package (SDK) often comprises interfaces (header recordsdata or module maps) for particular functionalities. The compiler solely wants the interface to construct byte code from supply recordsdata, the compiler would not cares in regards to the implementation particulars. The compiler trusts the interface and builds intermediate object recordsdata for a given platform utilizing the flags and different parameters that we do not care about for now. 🙃

That is what occurs within the first two part. The swift command turns the level.swift file into a brief level.o file, then it does the very same factor with the foremost.swift file. If you happen to take a more in-depth look, aside from the lengthy paths, it is a fairly easy command with only a few arguments:

swift 
   -frontend 
   -c level.swift 
   -primary-file foremost.swift 
   -target arm64-apple-darwin20.3.0 
   -Xllvm -aarch64-use-tbi 
   -enable-objc-interop 
   -sdk MacOSX11.1.sdk 
   -color-diagnostics 
   -D DEBUG 
   -target-sdk-version 11.1 
   -module-name foremost 
   -o foremost.o

As you’ll be able to see we simply inform Swift to show our major enter file into an intermediate output file. After all the entire story is far more sophisticated involving the LLVM compiler infrastructure, there’s a nice article about a quick overview of the Swift compiler, that it’s best to learn if you need extra particulars in regards to the phases and instruments, such because the parser, analyzer and many others. 🤔

Compilers are sophisticated, for now it is greater than sufficient when you take away this one easy factor in regards to the Swift compiler: it turns your supply recordsdata into intermediate object recordsdata.

Earlier than we might run our closing program code, these short-term object recordsdata must be mixed collectively right into a single executable. That is what linkers can do, they confirm object recordsdata and resolve underlying dependencies by linking collectively numerous dependencies.

Dependencies will be linked collectively in a static or dynamic manner. For now lets simply keep that static linking implies that we actually copy & paste code into the ultimate binary file, however dynamic linking implies that libraries might be resolved at runtime. I’ve a fairly detailed article about Swift frameworks and associated command line instruments that you need to use to look at them.


In our case the linker command is ld and we feed it with our object recordsdata.

ld 
	level.o 
	foremost.o 
	libclang_rt.osx.a 
   -syslibroot MacOSX11.1.sdk 
   -lobjc 
   -lSystem 
   -arch arm64 
   -L /usr/lib/swift/macosx 
   -L /MacOSX11.1.sdk/usr/lib/swift 
   -platform_version macos 11.0.0 11.1.0 
   -no_objc_category_merging 
   -o point-app


I do know, there are many unknown flags concerned right here as nicely, however in 99% of the circumstances you do not have to immediately work together with this stuff. This entire article is all about making an attempt to grasp the “darkish magic” that produces video games, apps and all type of enjoyable issues for our computer systems, telephones and different sort of devices. These core elements makes potential to construct superb software program. ❤️

Simply bear in mind this in regards to the linker (ld command): it can use the article recordsdata (ready by the compiler) and it will create the ultimate product (library or executable) by combining each useful resource (object recordsdata and associated libraries) collectively.


It may be actual arduous to grasp this stuff at first sight, and you’ll stay with out them, construct nice packages with out ever touching the compiler or the linker. Why hassle? Effectively, I am not saying that you will change into a greater developer when you begin with the fundamentals, however you’ll be able to prolong your information with one thing that you simply use each day as a pc programmer. 💡


[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments