I'd like to add support for
@main in Swift Packages, and would be interested in hearing thoughts about the following approach.
The Swift Package Manager doesn’t currently provide a way for a package manifest to declare that a target is the main module of an executable. Instead, SwiftPM infers this by looking for a source file named
main.cpp , etc) in the source directory of the target.
Knowing unambiguously whether or not a target is intended to be executable is important, because it affects the flags that are passed to the compiler at build time. It also affects the quality of diagnostics, such as detecting product declarations that mistakenly include multiple or no executable targets in an executable product.
Relying on specially named source files also doesn’t work when using
@main to specify the entry point of an executable. In addition, there are ergonomic problems with using specially named source files (e.g. SR-1379) that would be addressed by being able to explicitly declare a target as being executable in the manifest.
The most straightforward approach would be allow a target to be marked as executable in the manifest. This could take the form of either a parameter to the
target type or a new target type. There is already an established pattern of using the type itself to denote the kind of target being declared (e.g.
testTarget as a specialization of
target ), so the most natural approach seems to be to add a new
executableTarget type for this purpose.
Using a separate target type in the manifest would also support any future differences between the parameters for an executable target and a library target.
This proposal introduces a new target type as a peer of
systemTarget , and
binaryTarget . The new target type would have the same parameters as the
The Swift Package Manager is already passing
-parse-as-library to targets that are not marked as executable, and doesn’t pass that flag to targets that are. Since the Swift compiler still treats the source file name
main.swift as special, SwiftPM may need to pass additional flags if a target has both a
main.swift file that does not contain
@main but does contain a differently named source file that does contain it.
executableTarget type would only be available for package manifests that specify a tools version newer that 5.3. Package manifests specifying tools versions 5.3 or older would behave exactly as before.
Adding a parameter to the
Another approach would be to add another parameter to the existing
target type. That type already has many parameters, however, and it seems ill advised to add more. Using a separate target type in the manifest would also support any future differences between the parameters for an executable target and a library target.
Scanning source files for
Another approach would be to scan source files for occurrences of
@main , and to use that to infer whether a target is an executable target. This seems even more subtle than basing the detection of executable targets on a filename, however, making any mistakes in package authoring even harder to detect.