[swift-build-dev] [swift-evolution] [Draft] Test-Only Package Dependencies and Targets

Rick Ballard rballard at apple.com
Tue Jan 31 11:05:04 CST 2017

+ swift-build-dev

To take a step back here, there are two problems I see in this space:

1) Building unnecessary test-only stuff.

Say you have a package A which depends on a package B. B might declare a library, a test module, and some auxiliary target that's only needed by the tests. Today, if you check out A and run `swift build`, it will build B's auxiliary target (among other things built). That's unnecessary, and it would be nice to avoid that.

The product definitions proposal will fix this. Once that's implemented, B would publish its library as its only product, and A would declare that it depends on that product. Then, when building A, we would know that we don't need the auxiliary target from B, and wouldn't build it. So I think the products proposal will solve this problem.

2) Cloning unnecessary test-only stuff.

Say you have a package A which depends on a package B, and B has a test module which depends on a package C. Once the products proposal has been implemented and you adopt it, running `swift build` on A will be smart enough not to build the test module from B or any of the targets from C; however, SwiftPM will still clone the C repository when doing dependency resolution, even though it never winds up building its products.

I don't personally see that as a major problem, but it is one that would be nice to address at some point. Ways we could address this include:

– We could add a "testDependencies" property on the package. These dependencies would only be resolved and cloned in situations where one or more test targets from that package need to be built. Some problems with this would be:

	* Since these dependencies would only conditionally resolve, but otherwise would affect dependency resolution as normal, this could lead to some really unexpected emergent behavior. For example, if a package that's only included in the graph via testDependencies happens to depend on another package that's otherwise already in the graph, but with a more restrictive version specification, then whether or not you're building tests would force that other package to re-resolve with a different version.

	* This is a non-generalized solution to a general problem. That is, once we have the products proposal implemented, you could wind up in this situation with no tests involved, but this mechanism wouldn't solve the problem in that case. To give a concrete example, if A depends on B, B vends two products, and only one of them depends on C, it's unnecessary to clone C unless the product that needs it is used by A. A properly general mechanism would let you make that dependency conditional on whether you need it for whatever reason, and not tie it to testing in particular. Another reason you might have this problem is if you have a dependency that only applies on one platform (e.g. linux but not macOS). (Conditional compilation blocks can be used for the platform case, but – once we have a better mechanism – I don't think that they should be used, for reasons that would be best discussed in its own thread).

	* Adding additional properties to the Package should be done carefully. Every new property is new API surface area, and makes our documentation, initializer, etc more complicated. In my opinion, this new property doesn't justify that cost if it's just saving you from initial cloning of the extra packages.

– We could add in-line dependencies for targets, as Ankit suggested. This is a more generalizable mechanism than "testDependencies". That said, it could potentially require you to duplicate your dependency declaration, which is bad. (E.g. if two test targets in your package depend on the same auxiliary package, that dependency would need to be stated twice). It also adds unfortunate complexity.

– We could add a general mechanism for declaring dependencies as conditional, supporting a variety of possible conditions. Some of the SwiftPM developers are in the early discussion stages for a proposal for how to to make various parts of a manifest conditional, as part of a larger conversation on build settings; we'll bring our thoughts to this list once we have something coherent to propose. But if we come up with a general syntax for making things like settings conditional, the same consistent syntax could potentially be applied to dependencies as well.

- - -

Personally, I think that the products proposal solves the first problem nicely, and that we should revisit the second problem as part of an upcoming conversation about conditionals in the manifest.

	- Rick

> On Jan 30, 2017, at 11:55 AM, Robert Widmann via swift-evolution <swift-evolution at swift.org> wrote:
>> On Jan 30, 2017, at 2:38 PM, Ankit Agarwal <ankit at ankit.im <mailto:ankit at ankit.im>> wrote:
>> Not in practice (with respect to package manifests). In fact, it seems that, given there are separate commands (swift build and swift test), separate directories (Sources and Tests), and separate products, that there's a hole to be filled here by separate handling for test suites in package manifests.
>> FWIW, overriding conventions will potentially allow you control the layout of the package (when we have that feature).
> In that case, as long as there are plans for this kind of feature, I can hold off on submitting this proposal until it materializes.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-build-dev/attachments/20170131/d415f999/attachment.html>

More information about the swift-build-dev mailing list