Skip to content

add artifacts archive file format #3295

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 22, 2021
Merged

Conversation

tomerd
Copy link
Contributor

@tomerd tomerd commented Feb 20, 2021

motivation: to support the package extensions feature, we need to support binary dependencies with tools that can be distributed across different platforms

changes:

  • introduce new binary dependency type "artifactsArchive" with the extension "arar"
  • the structure of the archive is inspired by XCFramework, and it can contain multiple tools/executables targeting multiple platforms and architectures using target triples to indicate such support
  • update BuildPlan code to parse "arar" files and extract the tools available to the target in a [String: AbsolutePath] which * can be later hooks to be used by extensions
  • refactor XCFramework code
  • update call-sites and tests and add new tests

the new archive file name, extension and structure are all up to debate and would take final shape in an evolution proposal, but we can start discussing them now in preparation to such proposal.

the file structure proposed

<file>.arar
|- info.json
|- <artifact identifier> <-- an archive may have several artifacts
|   |   
|   <group identifer> <-- psoudo target triplet
|   |   |- executable
|   |   |- executable supporting files
|   |
|   <group identifer> 
|       |- executable
|       |- executable supporting files
|
|— <artifact identifier>
|   | ...

having the metadata file look like

{
    "schemaVersion": 1.0,
    "availableArtifacts": {
        "<artifact identifier>": {
            "version": "<version number>",
            "type": "<artifact type (e.g. executble, library)>",
            "variants": [ 
                    {
                        "exectuablePath": "<path to exectuable>",
                        "supportedTriples": ["<triplet identifier>"]
                    }
            ]
        }
    }
}

concrete example:

protocol-bufffer-compiler.exar
|- info.json
|— protocol-bufffer-compiler
|     |
|     x86_64-osx
|     |   |- protoc executable for macOS
|     | 
|     x86_64-linux
|     |   |- protoc executable for Linux
{
    "schemaVersion": 1.0,
    "availableArtifacts": {
        "protocol-bufffer-compiler": {
            "version": "3.5.1",
            "type": "executable",
            "variants": [
                {
                    "path": "x86_64-osx/protoc-3.5.1",
                    "supportedTriples": ["x86_64-apple-macosx"]
                },
                {
                    "path": "x86_64-linux/protoc-3.5.1",
                    "supportedTriples": ["x86_64-unknown-linux-gnu"]
                }
            ]
    }
}

open questions:

  • how do we deal with system dependencies these tools may have? we could require that the archive metadata includes information on such dependencies and do basic validation for the user, but this could get very messy.

    • imo we should lean on SwiftPM systemLibrary to express such dependencies and not invent something new
  • what about versioning? do we need to add metadata about the tool version?

    • I suggest we add a metadata field to indicate the version. I can't see how we practically use this field but at least we can make it available to the extension that can do some validation?
  • We are likely to extend the ArtifactsArchive file format to carry other types of artifacts beyond executables. Additional fields are likely to be required to support such artifact types, e.g. headers path for libraries.

@tomerd
Copy link
Contributor Author

tomerd commented Feb 20, 2021

@swift-ci please smoke test

1 similar comment
@tomerd
Copy link
Contributor Author

tomerd commented Feb 20, 2021

@swift-ci please smoke test

@tomerd tomerd added the ready Author believes the PR is ready to be merged & any feedback has been addressed label Feb 20, 2021
@tomerd tomerd changed the title RFC: add support for tools archive [RFC] add support for tools archive Feb 20, 2021
motivation: to support the package extensions feature, we need to support binary dependencies with tools that can be distributed across different platforms

changes:
* introuce new binary dependency type "toolsArchive" with the extension "toar"
* the structure of the archive is inspired by XCFramework, and it can contain multiple tools/executables targeting multiple platforms and architectures using target triplets to indicate such support
* update BuildPlan code to parse "toar" files and extract the tools available to the target in a [String: AbsolutePath] which can be later hooks to be used by extensions
* refactory XCFramework code
* update call-sites and tests and add new tests
@tomerd
Copy link
Contributor Author

tomerd commented Feb 22, 2021

@swift-ci please smoke test

@tomerd tomerd requested a review from abertelrud February 22, 2021 00:45
@tomerd tomerd changed the title [RFC] add support for tools archive add artifacts archive file format Feb 22, 2021
@tomerd
Copy link
Contributor Author

tomerd commented Feb 22, 2021

@swift-ci please smoke test


public struct Variant: Equatable {
let path: String
let supportedTriplets: [Triple]
Copy link
Contributor

@abertelrud abertelrud Feb 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest supportedTriples for consistency.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:D typo

extension ArtifactsArchiveMetadata: Decodable {
enum CodingKeys: String, CodingKey {
case schemaVersion
case artifacts = "availableArtifacts"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: should this just be "artifacts"? Are there any artifacts in the archive that aren't available?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just saw the example of the existing XCFrameworks format in the unit test, which uses AvailableLibraries, so now I understand where this comes from. I could go either way on this: if we expect to move to arar as the future format that can handle all types of artifacts than maybe it's more important to pick names we think are clear than to be consistent with XCFrameworks. Could go either way for me.

case type
case version
case variants
case supportedTriplets
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest supportedTriples to be consistent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also: since an Artifact has Variants, and both have supportedTriples, is this one a union of all the ones for all the variants?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm no, this is a typo

switch binaryTarget.kind {
case .xcframework:
let libraries = try self.parseXCFramework(for: binaryTarget)
libraries.forEach { library in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: what is our stance on for _ in vs forEach in the SwiftPM codebase? Historically I think we've been using for _ in, which I personally find much easier to read, but we should probably choose one and use the same in the codebase.

}

let libraryDirectory = target.artifactPath.appending(component: library.libraryIdentifier)
let binaryPath = libraryDirectory.appending(component: library.libraryPath)
let libraryPath = libraryDirectory.appending(component: library.libraryPath)
let headersPath = library.headersPath.map({ libraryDirectory.appending(component: $0) })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize this is existing code but this one should probably be .appending(RelativePath($0)) as well, if the path can be a relative path.

Copy link
Contributor

@abertelrud abertelrud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few comments, which are mostly suggestions but saw a couple of places of appending(component: )) in existing code that should probably be appending(RelativePath()) now if we support subpaths in those keys.

}

let libraryDirectory = target.artifactPath.appending(component: library.libraryIdentifier)
let binaryPath = libraryDirectory.appending(component: library.libraryPath)
let libraryPath = libraryDirectory.appending(component: library.libraryPath)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize this is existing code but this one should probably be .appending(RelativePath($0)) as well, if the path can be a relative path.

extension ArtifactsArchiveMetadata: Decodable {
enum CodingKeys: String, CodingKey {
case schemaVersion
case artifacts = "availableArtifacts"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just saw the example of the existing XCFrameworks format in the unit test, which uses AvailableLibraries, so now I understand where this comes from. I could go either way on this: if we expect to move to arar as the future format that can handle all types of artifacts than maybe it's more important to pick names we think are clear than to be consistent with XCFrameworks. Could go either way for me.

@tomerd
Copy link
Contributor Author

tomerd commented Feb 22, 2021

@swift-ci please smoke test

@abertelrud abertelrud self-requested a review February 22, 2021 02:50
Copy link
Contributor

@abertelrud abertelrud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me! Thanks for taking this on!

@tomerd tomerd merged commit 32c49a3 into swiftlang:main Feb 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready Author believes the PR is ready to be merged & any feedback has been addressed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants