Why put the main file in a separate target

Hello, so I have this question:

When you generate a project with the vapor CLI it creates two targets: an App and a Run target. The only thing inside Run is the main.swift file. I thought it was just the way the team developing Vapor liked to do it, but then I read the Kitura documentation and saw this which does basically the same thing just with different folder names.

Is there a reason for putting the main file in a separate target? Is it a recommended practice, or is it just a preference of them? Either way, what are the benefits and downsides to separating it like that?

The projects you mention may have additional reasons of their own, but there is one significant reason for recommending that set‐up for any package:

Executables cannot be hooked up to XCTest. That means the more code lives in a library and the less code lives in the executable, the better the project can be tested.

The package manager executable template does have a test set‐up that can sort of work with a subset of executables (those which behave like shell commands by performing some work and then exiting), but even then, the executable is launched as an independent process, which means there is no way to monitor its execution flow to measure test coverage.

1 Like

I did not know that, but it makes sense now that I think about it. Now I have a followup question, mostly about XCTest rather than Swift itself. IIRC in the earlier days Swift Xcode projects used to expose the main file, and Objective-C still do. How are these (executable projects) hooked to XCTest.

I know probably the answer is: Xcode magic.

If an application—by that I mean a .app bundle, not just a binary file with the executable flag set—creates its run loop with @NSApplicationMain or something sufficiently similar, then XCTest can work with it thanks to the “Xcode magic” you mention. The Xcode‐provided run loop both ensures that the executable won’t (normally) exit before XCTest is done with it, and provides an entry point for XCTest to inject itself.