You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Work in review feedback
* Update resolution behaviour
* Small edits to the proposal
- removed note about "Multiple references to same artifact" because that case already shouldn't be possible in practice
- updated "name" note for artifacts to talk about module name
- removed leftover mention of opt-out for binaries
- replaced `--artifact-url` with `--original-url` option which is supposed to work for both package as well as artifact URLs
Secondly we propose to add a new configuration point to the package description that allows packages to opt-out of binary dependencies. This will enforce that nothing in its transitive dependencies brings a binary dependency with it.
Packages are allowed to contain a mix of binary and source targets. This is
125
110
useful when, for example, providing a pre-built or closed source C library
126
111
alongside an open source set of Swift bindings for the library.
127
112
128
-
When a package is built that depends upon any product with a binary target, the
129
-
package manager will search the `artifacts` declaration list to find an artifact
130
-
which matches the current build conditions. This list
131
-
will be searched in order, and the first matching artifact will be used. It is
132
-
the job of the package author/publisher to provide an appropriate set of
133
-
artifacts for the use cases the package wishes to support. This use case will be limited to Apple platforms in the beginning. In the future, we can add support for other platforms. A potential approach is outlined in the future directions section.
113
+
The use case will be limited to Apple platforms in the beginning. In the future, we can add support for other platforms. A potential approach is outlined in the future directions section.
134
114
135
115
## Detailed design
136
116
137
117
The design consists of the following key points:
138
118
* New `PackageDescription` API for defining a binary target.
139
-
* New parameter on a package declaration level to opt-out of binary dependencies.
140
119
* New requirements for the `Package.resolved` file when using binary packages.
120
+
* A new command to compute a checksum for a file.
141
121
* A new mechanism for downloading binary target artifacts.
122
+
* Support for artifact mirroring.
142
123
143
124
Terminology:
144
125
@@ -166,60 +147,86 @@ while keeping the following as non-goals:
166
147
## New `PackageDescription` API
167
148
168
149
### BinaryTarget
169
-
Since a binary target is different compared to a source only target, we propose to introduce a new struct `Artifact`. This struct defines a target's associated artifacts.
170
-
171
-
We propose to support local and remote artifacts from the beginning. In the alternatives considered section is larger collection of potential artifact stores. However we opted to simplify the initial implementation by just supporting a url and a path based definition. Later, we can implement different types of providers with different authentication methods.
150
+
Since a binary target is different compared to a source only target, we propose to introduce two new static method on `Target` to declare a binary target. We propose to support local and remote artifacts from the beginning. In the alternatives considered section is a larger collection of potential artifact stores. However we opted to simplify the initial implementation by just supporting a url and a path based definition. Later, we can implement different types of providers with different authentication methods.
172
151
173
152
```swift
174
-
publicstructArtifact {
175
-
publicenumSource {
176
-
caseurl(String, checksum: String)
177
-
casepath
178
-
}
179
-
180
-
publiclet source: Source
153
+
extensionTarget {
154
+
/// Declare a binary target with the given url.
155
+
publicstaticfuncbinaryTarget(
156
+
name: String,
157
+
url: String,
158
+
checksum: String
159
+
) -> Target
160
+
161
+
/// Declare a binary target with the given path on disk.
162
+
publicstaticfuncbinaryTarget(
163
+
name: String,
164
+
path: String
165
+
) -> Target
181
166
}
182
167
```
183
168
184
-
Furthermore, we propose to add a new `artifacts: [Artifacts]?` property to the `Target`, as well as extend the initializer with this parameter and create a new static method called `.binaryTarget()`. Lastly, we propose to extend the `TargetType` enum with a new case called `binary`.
185
-
186
-
### PackageDescription
187
-
To opt out of binary packages we propose a new configuration point inside the package description.
188
-
189
-
```swift
190
-
publicfinalclassPackage {
191
-
...
192
-
/// This disallows any binary dependency or any transitive binary dependency.
193
-
publicvar disallowsBinaryDependencies: Bool
194
-
...
195
-
}
196
-
```
169
+
## Checksum computation
170
+
We propose to add a new command to SwiftPM `swift package compute-checksum <file>` which is going to be used to compute the checksum of individual files. This implementation can then evolve in the future and is tied to the tools version of the package to avoid breaking compatibility with older tools.
197
171
198
172
## New `Package.resolved` Behavior
199
173
200
-
For binary targets we store the checksum of the artifact in the `Package.resolved`. This lets us check for errors during resolution where a package's version did not change but the checksum did. In this case we will throw an error alerting the user about this.
174
+
For binary targets we will validate the commit hashes from the resolved file for any dependencies from now on to ensure the checksums of binaries cannot be changed for a specific version. This lets us check for errors during resolution where a package's version did not change but the checksum did. In this case we will throw an error alerting the user about this.
201
175
202
176
### Resolution
203
177
204
178
Package resolution and dependency expression will not be impacted by this change (except where explicitly noted).
205
179
206
-
#### Multiple references to same artifact
207
-
During resolution SwiftPM will check that all references to an artifact in a dependency graph have the same checksum.
180
+
#### Exported product with binary dependency that specifies a type
181
+
SwiftPM will emit an error during resolution when a product that directly exports a binary dependency declares a type, e.g.: `.product(name: "MyBinaryLib", type: .static, targets: ["MyBinaryLib"])`.
182
+
183
+
#### Resolution on non-Apple platforms
184
+
When resolving a package that contains a binary dependency on non-Apple platforms, SwiftPM will throw an error and explicitly state that this dependency is not valid for the current platform. During the review it was brought up that we could ignore these dependencies but that would make the behavior of SwiftPM very unexpected. In the future, when properly supporting other platforms this can be solved easily with a proper condition mechanism.
208
185
209
186
## Binary Target Artifact Format
210
187
211
188
SwiftPM currently supports multiple platforms; however, this proposal only adds support for binary targets on Apple platforms. The reason for this is that Apple platforms provide ABI guarantees and an already existing format we can leverage to simplify the initial implementation. For Apple platforms we propose to use the `XCFramework` format for artifacts. This format already supports dynamic and static linking. Furthermore, it can contain products for every individual Apple platform at once.
212
189
190
+
SwiftPM expects url-based artifacts to be packaged inside a `.zip` file where the artifact is lying at the root of the archive. Furthermore, the artifact needs to have the same module name as the target name provided inside the manifest file.
191
+
192
+
For path-based artifact SwiftPM supports artifacts as a `.zip` and as a raw `XCFramework`.
193
+
194
+
During resolution SwiftPM won't do any verification of the format of the artifact. This is up to the vendor to provide correct and valid artifact. In the future, this can be extended and further validation, such as checking that the module name matches, can be implemented.
195
+
213
196
## Security
214
197
215
198
When adding new external dependencies, it is always important to consider the security implication that it will bring with it. Comparing the trust level of a source-based to a binary-based dependency the first thought is that the trust level of the source-based dependency is higher since on can inspect its source code. However, there is no difference between a binary and source dependency since source-based dependencies can have security issues as well. One should have better reasons to trust a dependency than source being inspectable.
216
199
217
-
There is still a significant difference between having a dependency with zero vs. any binary dependency. For example, the portability of a library with binary dependencies is far worse than the one with only source-based dependencies. For this reason, we propose to add an additional configuration point in the manifest that allows package authors to opt-out of binary dependencies.
200
+
There is still a significant difference between having a dependency with zero vs. any binary dependency. For example, the portability of a library with binary dependencies is far worse than the one with only source-based dependencies.
218
201
219
202
However, there are still some security related aspects when it comes to binary artifacts that we should mitigate. For example, when declaring a `binaryTarget` the hash of the artifact is required similar to Homebrew. By doing this an attacker needs to compromise both the server which provides the artifact as well as the git repository which provides the package manifest. A secondary reason is that the server providing the binary might be out of the package author's control and this way we can ensure that the expected binary is used.
220
203
221
204
Lastly, the hash of the binary is stored in the package resolved to avoid that the vendor changes the artifact behind a version without anyone noticing.
222
205
206
+
## Mirroring support
207
+
Binary artifacts can also be mirrored. We propose to deprecate the existing `--package-url` option and to replace it with a `--original-url` option which will work for both package URLs as well as artifact URLs:
The other unset command options `--mirror-url` and `--all` will be working the same for artifacts as they do for packages.
229
+
223
230
## Impact on existing packages
224
231
225
232
No current package should be affected by this change since this is only an additive change in enabling SwiftPM to use binary dependencies.
@@ -229,9 +236,18 @@ No current package should be affected by this change since this is only an addit
229
236
### Support for non-Apple platforms
230
237
Non-Apple platforms provide non-trivial challenges since they are not always giving guarantees of the ABI of the platform. Additionally, further conditions such as the corelibs-foundation ABI or if the hardware supports floating points need to be taken into consideration when declaring a package for non-Apple platforms. Various other communities tried to solve this, e.g. Python's [manylinux](https://www.python.org/dev/peps/pep-0600/).
231
238
232
-
In the future, we could add an `ArtifactCondition ` to SwiftPM which provides the possibility to declare under which conditions a certain artifact can be used. Below is a potential `ArtifactCondition` struct which does **not** include a complete set of conditions that need to be taken into consideration.
239
+
In the future, we could add an `Artifact` struct and `ArtifactCondition`s to SwiftPM which provides the possibility to declare under which conditions a certain artifact can be used. Below is a potential`Artifact` and`ArtifactCondition` struct which does **not** include a complete set of conditions that need to be taken into consideration.
233
240
234
241
```swift
242
+
publicstructArtifact {
243
+
publicenumSource {
244
+
caseurl(String, checksum: String)
245
+
casepath
246
+
}
247
+
248
+
publiclet source: Source
249
+
}
250
+
235
251
publicstructArtifactCondition: Encodable {
236
252
publicstructLLVMTriplet: Encodable {
237
253
// Should be only the subset that Swift supports
@@ -414,6 +430,31 @@ During the discussion of this proposal another solution to the `allowsBinary` fl
414
430
### Opt-out configuration in separate file
415
431
During the discussion of this proposal it was decided that an opt-out mechanism was good to give package users and vendors an escape hatch. However, it was discussed whether this configuration should live inside the manifest or a separate configuration file. In this proposal, we opted to keep the configuration inside the manifest file.
416
432
433
+
### Opt-out in package manifest
434
+
In the first round, we proposed to add a configuration flag in the manifest to opt-out of binary dependencies; however, during the review it became apparent that this flag doesn't provide as much value and can make some dependencies actually more restricted when they add this flag. Therefor, we opted to not include such a configuration flag and let workflow tooling provide this functionality if needed.
435
+
436
+
```swift
437
+
publicfinalclassPackage {
438
+
...
439
+
/// This disallows any binary dependency or any transitive binary dependency.
Initially, we considered the various artifact stores on the market and how we can integrate with them. We decided to support a URL based artifact definition for the first implementation since the various providers require each their own method of authentication. However, we wanted to keep the possibility for future additions of providers open; therefore, we made the source of an artifact an enum which can be extended.
0 commit comments