Overall Code Structure Of Swift Project

I was a long time C# programmer, and recently started learning Rust. Now that I recently purchased my first Mac, I ran into several issues trying to run binaries on the Mac, due to various restrictions. On another forum post here, it was mentioned that I should take a look at Swift, as a development tool.

This comment brings up an entirely new topic for me, as I discovered that the Swift project file structure seems daunting. But first let's backtrack to when I used C#.

C#

The first graphic show the default file structure that I used to start a new C# project. I would copy this entire folder structure to the clipboard and paste it where my new project folder was located, and start coding.

Using this same principle, I wrote my own music player, and again the file structure for the entire project was as below. For those that may not know, the "bin" folder contains both debug and release folders and appropriate contents.

Swift

I created a Windows UI called "Test" using Swift, and then started poking around the file system, trying to determine the file structure that was created. Unbeknownst to me at the time, part of the project files ended up on the Desktop in a folder called Test. I did not expect Swift to place the files there.

When I click on the Test folder and look inside, I see a file with a "xcodeproj" extension, which makes sense to me, as this is similar to C#. What I don't see however, is any file labeled Test.App. I also don't see either debug or release folders for this project.

Obviously there are additional files for this project that are "somewhere", just not in a location I am aware of.

Answered by Etresoft in 817526022

When you create a project, you'll be prompted for a location to save it. I don't recommend the Desktop or any other folder that may be controlled by any kind of file sync system.

Any build products like app files or debug/release objects will be located in your "DerivedData" folder at ~/Library/Developer/Xcode/DerivedData. You normally should never need to dig into this folder.

When you run your project in Xcode, it will run from an app wrapper in a folder deep within DerivedData. When you're ready to distribute, you'll perform an archive build and you'll have to specify what you want to do with the build product. You can choose to submit it to the App Store, distribute it using a different method, or just save it to disk.

When you create a project, you'll be prompted for a location to save it. I don't recommend the Desktop or any other folder that may be controlled by any kind of file sync system.

Any build products like app files or debug/release objects will be located in your "DerivedData" folder at ~/Library/Developer/Xcode/DerivedData. You normally should never need to dig into this folder.

When you run your project in Xcode, it will run from an app wrapper in a folder deep within DerivedData. When you're ready to distribute, you'll perform an archive build and you'll have to specify what you want to do with the build product. You can choose to submit it to the App Store, distribute it using a different method, or just save it to disk.

Yup, this is the design of the "modern" Xcode, which began at Xcode 4. In Xcode 3, the file structure of a project was a lot closer to your C# example.

There are a number of benefits, and not much in way of downsides. I'm not going to try to go into details, since benefits are a matter of opinion, but think of it as a "source of truth" issue. The project only contains files that are source of definitive information, such as your source code or your build settings. Anything that's derived from that source of truth can be discarded and recreated at any time. Hence DerivedData.

One other historical tidbit that's related: @Etresoft mentioned an "archive" operation, which is the same as a build operation but different!

When you're in your code-build-run-test cycle, Xcode will to some degree re-use build products in DerivedData that don't need to change since the last build iteration. When you use the archive operation, however, Xcode builds your project "clean" without using any existing build products that might be lying around.

It takes a bit longer, but it means that an archive is always fully built with the current set of build tools, with no artifacts or stale data that hasn't been rebuilt in a while. That gives you an added level of confidence that builds that you distribute from the archive represent the project's current source of truth

I’m going to mention the Swift Package Manager:

https://www.swift.org/documentation/package-manager/ https://www.swift.org/getting-started/cli-swiftpm/

If you’re looking for something that’s closer to cargo run or make; make install than the full Xcode experience, this may be worth looking at.

Question for the experts: to what extent is the Swift Package Manager “compatible” with Xcode? I.e. can I have a single source tree that’s usable by both?

P.S. I’d be interested to hear your thoughts about C# vs. Rust vs. Swift generally.

If you’re looking for something that’s closer to [cargo, SwiftPM] may be worth looking at.

Agreed.

to what extent is the Swift Package Manager “compatible” with Xcode?

It depends on what you’re building and what platform your targeting. Swift Package Manager has really good support for libraries on all supported platforms. The sticking point is executables. It’s able to build macOS standalone executables and that’s about it. So if you’re building a Mac app you need to add your own ‘smarts’ to wrap that executable in an .app bundle [1]. And building an app for iOS or one of its child problems is not supported [2].

Keep in mind that Xcode can use Swift packages in its native build system. If you’re building an app then a common practice is to use Swift packages for the bulk of the app’s code and then have Xcode put it all together.

This isn’t perfect. Every now and again I see cases where Xcode build a package in a way that doesn’t exactly align with Swift Package Manager. However, in general it seems to work well for a lot of folks.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] This isn’t something I’ve ever done, but I’ve seen folks do it in a way that’s not too ugly.

[2] The Swift Playgrounds app can do that but it uses undocumented extensions.

etresoft wrote:

When you're ready to distribute, you'll perform an archive build and you'll have to specify what you want to do with the build product. You can choose to submit it to the App Store, distribute it using a different method, or just save it to disk.

When you save the file to disk, does Xcode add a certain extension to the binary? In Windows it's EXE and running Linux, Rust has no binary extension at all.

DTS Engineer wrote:

The project only contains files that are source of definitive information, such as your source code or your build settings. Anything that's derived from that source of truth can be discarded and recreated at any time. Hence DerivedData.

Below is a Rust folder screenshot that shows a file structure very similar to C#. This example is from Github. When Rust compiles, it creates up to 1 gig of "extra stuff" during the build, and Rust leaves it alone until you send "cargo" a clean command.

Note that FLTK is the GUI part of Rust code.

Does Xcode clean up manually or automatically?

endecotp wrote:

I’m going to mention the Swift Package Manager:

Yes, this something that sounds very interesting. I would definitely like to look into this.

DTS Engineer wrote:

It’s able to build macOS standalone executables and that’s about it.

This sounds really good for my code usage. Does anyone have any other resources on this topic?

Accepted Answer
does Xcode add a certain extension to the binary?

macOS is a Unix-y system, where executables don’t need a file extension.

macOS does use file extensions for bundled code, but it applies those to the bundle rather than the app. For example:

% find /Applications/Pages.app 
/Applications/Pages.app
…
/Applications/Pages.app/Contents/MacOS
/Applications/Pages.app/Contents/MacOS/Pages
…

Here the app bundle has a .app extension but the main executable, Contents/MacOS/Pages, does not.

Does Xcode clean up manually or automatically?

No. By default Xcode places its build state into ~/Library/Developer/Xcode/DerivedData. There are options to configure that.

To clean this for a given project, open the project and choose Product > Clean Build Folder.

Does anyone have any other resources on this topic?

On Swift Package Manager? Sure, there’s lot of info on that, including:

But getting started is really easy:

% mkdir Test770564
% cd Test770564 
% swift package init --type executable
…
% cat Sources/main.swift 
…
print("Hello, world!")
% swift build
…
% swift run
…
Hello, world!
% swift package clean

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Quinn wrote:

But getting started is really easy:

So I tried what you had written, and it worked great for me. However, for some reason I was expecting that the binary would be a GUI background with Hello World printed on top. This is my main interest in learning Swift.

Thanks for the push to learn Swift, as I just purchased...

Hacking With MacOS

And will start learning with that text. Thanks again.

Overall Code Structure Of Swift Project
 
 
Q