SE-0294: Declaring executable targets in Package Manifests

The review of SE-0294, "Declaring executable targets in Package Manifests", begins now and runs through December 13, 2020.

Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager or direct message in the Swift forums).

What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thank you for helping improve the Swift programing language and ecosystem.

Tom Doron
Review Manager

13 Likes

What is your evaluation of the proposal?
I might have missed the reasoning behind this proposal, but I feel this functionality is already provided by the products section in package manifests.

Currently supported:

let package = Package(
    name: "Foo",
    platforms: [
        .macOS(.v10_13)
    ],
    products: [
        .executable(name: "foo", targets: ["Foo"])
    ],
    dependencies: [],
    targets: [
        .target(name: "Foo", dependencies: []),
    ]

Proposal:

let package = Package(
    name: "Foo",
    platforms: [
        .macOS(.v10_13)
    ],
    products: [
        .executable(name: "foo", targets: ["Foo"])
    ],
    dependencies: [],
    targets: [
        . executableTarget(name: "Foo", dependencies: []),
    ]

What would be the benefit of using executableTarget instead of target above?

Is the problem being addressed significant enough to warrant a change to Swift?
I'm not sure, I'm leaning towards no. The proposal itself indicates this is an interim/temporary solution, since the overall goal is to merge "products" and "targets" into one list. However, the proposal does not clarify if explicitly declaring "products" solves the issue.

Does this proposal fit well with the feel and direction of Swift?
Yes

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
I'm not familiar with other package manifests that allow defining executables.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
Quick reading

Thanks for your comments! That's a good point, and would work in the case of a declared executable product with a single target.

But inferring whether to treat a target as executable based on whether it is included in an executable product does have a couple of issues:

  • SwiftPM currently infers the declaration of an executable product for any executable target that doesn't already have a correspondingly named product. If membership in an executable product were used to determine whether the target is executable, then this proposal would also need to require executable products to be explicitly declared.

  • A product can be comprised of more than one target, and in that case there wouldn't be any way to know which of the targets should be treated as executable (only one of them can be, in any given executable product). This affects the flags that are passed to the compiler.

  • Knowing which target is intended by the author to be executable can help make diagnostics more clear when, for example, an executable product is declared as including anything other than a single executable target.

The proposal's reference to a goal of simplifying the manifest in the future was intended to acknowledge that this proposal is limited in scope, and could result in the word "executable" appearing in both the products and targets lists in the package. But the proposed executableTarget is not intended to be a temporary solution; rather, the hope is that the products list itself might become redundant via a future proposal if the targets contain all the necessary information.

6 Likes
  • What is your evaluation of the proposal?

Strong +1. As I mentioned in the pitch thread, I don't think the existing method of adding a main.swift to make a target executable is very discoverable, and this proposal would be a big improvement in that area. By enabling @main support, it also makes the behavior of SPM more consistent with other build systems.

I did want to make one suggestion regarding the backwards compatibility of the proposal:

On the implementation side, this proposal updates the logic in SwiftPM so that:

  • if the package tools version is 5.3 or earlier, a target is considered to be executable using the same rules as in SwiftPM 5.3
  • if the package tools version is newer than 5.3, only the target type determines whether the target is treated as an exeutable or a library target

I don't feel too strongly about it, but IMO it would be nice to continue treating a .target with a main.swift as an executable target in tools version 5.4, but emit a warning suggesting migrating to .executableTarget. I feel like this is a significant enough change to the API that it would be helpful to provide a smoother migration path for package authors who choose to upgrade their package's tools version.

  • Is the problem being addressed significant enough to warrant a change to Swift?

Yes, in my opinion the discoverability, diagnostics, and functional improvements make this change worthwhile.

  • Does this proposal fit well with the feel and direction of Swift?

Yes, it seems consistent with the approach used for test targets.

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

N/A

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

I followed the pitch thread and read through the final proposal.

3 Likes

Seems everyone is heads over heels in the concurrency discussions, and missing out on this great improvement proposal... :wink:

  • What is your evaluation of the proposal?

Strong +1, feels like the right way to do it and super excited to use @main in server apps soon :slight_smile:

  • Is the problem being addressed significant enough to warrant a change to Swift?

Yes, it’s very helpful and allows for more consistent use of @main around all platforms. I’m also most excited about better error messages here actually, I remember the current ones being a bit weird if there is a stray main file somewhere AFAIR?

  • Does this proposal fit well with the feel and direction of Swift?

Yes, the it feels right at home and is similar to testTarget.

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

Scala’s sbt has automagic detection of extends App things in targets; it does not need to declare a separate target type but relies on class scanning. I don’t think it matters much here though, declaring an executable explicitly is fine.

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Read through now and have been chatting about this feature for quite some time before :slight_smile:

+1. This is a good enhancement, and addresses an important SwiftPM shortcoming.

Yes. The scope of the change is minimal, it has limited backward-compatibility constraints, and it addresses a genuine point of ambiguity and uncertainty.

Yes, it fits in coherently with SwiftPM.

Participated in the previous pitch thread, read both the original and final proposal.

Strong +1.

Yes, absolutely. When trying to build executable targets with SwiftPM using @main, I found this limitation incredibly frustrating.

Yes, it resolves the long-standing lack of clarity in product and target declarations. The fact that one could declare implicitly executable targets without declaring a corresponding product was a source of confusion for me, and required additional heuristics to be added in developer tools that I work on. The solution seems explicit enough, but not too verbose. It also brings Swift forward on other platforms, as the possibility to use @main is sorely missed on non-Apple platforms.

N/A

In addition to reading the proposal, I was closely following the previous discussions and the pitch of this proposal.

That makes sense, especially since otherwise, increasing the tools version to 5.4 for other reasons would make the targets be treated as libraries for reasons that aren't immediately obvious. That seems like a much smoother upgrade path.

4 Likes

* What is your evaluation of the proposal?
+1 This seems like a straightforward way to address the issues described.

I also like @owenv's suggested approach of allowing package authors to more smoothly migrate to the new usage.

I would additionally suggest that the warning indicate that the old behavior will be removed in a future tool version. This would allow for a transition period but not commit to support the older implied behavior forever. At some point in the future, the warning would become an error and a package developer would need to update.

(I realize the support would still be necessary for packages with a tools version of 5.3 or earlier, but for new package authors the full set of rules of how things work would be simplified.)

* Is the problem being addressed significant enough to warrant a change to Swift?
Yes. The package manager needs to support use of @main and this addition makes that possible while also making it easier distinguish between types of targets in the manifest.

* Does this proposal fit well with the feel and direction of Swift?
Yes. The explicit naming promotes clarity at the call site and clarity above brevity.

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
    A quick reading of the proposal and the discussion to date.