Skip to content

Add Wasm and its features to SupportedPlatforms #373

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

Closed
wants to merge 2 commits into from

Conversation

MaxDesiatov
Copy link

@MaxDesiatov MaxDesiatov commented Oct 28, 2020

Here's a proposal for how specifying requirements for atomics/SIMD and other features could look in Package.swift:

// swift-tools-version:5.4
import PackageDescription

let package = Package(
    name: "SwiftWasmApp",
    platforms: [.wasm(.atomics)]
    // all other package settings omitted here as irrelevant
)

Not all Wasm features are specified in this PR, as some of them are too low-level. I've only picked a few that could be useful in the near future, but the list can be easily expanded (as long as we don't have more than 64 features).

I want to start this discussion now, so that we propose this upstream as soon as possible in time for the Swift 5.4 merge window. The preliminary schedule is that Swift 5.4 will be released in spring 2021, so I guess it'll be tagged with no possibility to merge changes as big as this one after this December-January? Either way, if we miss the window, we'll have to wait some indefinite amount of time for it to land in the Swift version after that. If we make it in time, we'll be able to start specifying these features in Package.swift manifests that can be depended on other libraries for other platforms.

I want to get your feedback before submitting this upstream. One alternative could be to use browser versions instead of Wasm features, i.e.:

// swift-tools-version:5.4
import PackageDescription

let package = Package(
    name: "SwiftWasmApp",
    platforms: [.chrome(68), .safari(15), .firefox(79)]
    // all other package settings omitted here as irrelevant
)

In the latter case I guess some part of the toolchain (or just carton itself short-term) would have to maintain a database of what features are available in what browser versions. But in the end that would require more infrastructure changes to work. Additionally, these options are not mutually exclusive, I hope. .wasm(.atomics) could be useful for non-browser WebAssembly hosts, while .firefox(79) would imply a JavaScript environment and DOM availability, which is also useful to encode in platform requirements.

WDYT?

@MaxDesiatov MaxDesiatov requested a review from a team October 28, 2020 14:37
@kateinoigakukun
Copy link
Member

kateinoigakukun commented Oct 28, 2020

IMO compile-time feature detection should be more generic feature than only for wasm. Did you check rust's target-feature? and also clang supports similar feature in __attribute__((target())).

At least, we should allow users to depend on not browser-specific implementation details but stable feature interface or standard interface.

@MaxDesiatov
Copy link
Author

Would that be more similar to the @available attribute? There are different levels for feature detection in Swift, i.e. package level as proposed here, and source level with if #available, although the latter is a runtime check. I think we need to enable all of them eventually, as Apple platforms do. But SwiftPM support is the easiest to start with, and potentially the easiest to upstream.

@MaxDesiatov
Copy link
Author

I've posted it on Swift Forums for a wider discussion https://forums.swift.org/t/pitch-support-specifying-wasm-features-in-package-manifests/41532

@kateinoigakukun
Copy link
Member

I would like to know how you will implement the branching at compile time. Are you planning to pass -D option and branch using #if?

@MaxDesiatov
Copy link
Author

MaxDesiatov commented Oct 28, 2020

We'd probably have to ship both "threadless" and "threadful" libc, runtime and stdlib. Then I guess we'd patch the driver to take a -enable-experimental-wasm-atomics flag, similarly to other -enable-experimental flags that the driver already has. SwiftPM would pass the flag automatically if the platforms array contains .wasm(.atomics) in it. Does that make sense?

static let mvp = WasmFeatures([])

/// WebAssembly System Interface is available.
static let wasi = WasmFeatures(rawValue: 1 << 0)
Copy link
Member

Choose a reason for hiding this comment

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

I think wasi should be treated as OS in target triple instead of feature flag

Copy link
Author

Choose a reason for hiding this comment

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

How do we then distinguish between WASI with atomics and without them? Is WASI expected to be versioned?

Copy link
Author

Choose a reason for hiding this comment

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

Or, how do we indicate that these overlap? Say there's a package A with .wasm(.simd) requirement, but has no assumptions about WASI presence. Then there's another package B that assumes presence of WASI, but doesn't require SIMD. A package C depends on A and B. How do we express platform requirements for C in its Package.swift?

Copy link
Member

Choose a reason for hiding this comment

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

WASI is a versioned interface. (see also https://github.com/webassembly/wasi/blob/master/phases/README.md)

How do we then distinguish between WASI with atomics and without them?

They can be distinguished like below.

let package = Package(
    name: "SwiftWasmApp",
    platforms: [.wasi(.snapshot, features: [.atomics])]
)

let package = Package(
    name: "SwiftWasmApp",
    platforms: [.wasi(.snapshot)]
)

Copy link
Author

Choose a reason for hiding this comment

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

Right, and what about packages that don't require WASI, but still need specific Wasm features?

Copy link
Member

@kateinoigakukun kateinoigakukun Oct 29, 2020

Choose a reason for hiding this comment

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

Users can know that a feature is enabled at source code level not package dependency graph level.

Especially if the top-level package doesn't need it, but some dependency deep down in the dependency tree does?

I see, hmm let me think more.

Copy link
Member

Choose a reason for hiding this comment

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

Also abusing the version string is not horrible, but I cast my vote for adding build invocation parameters.

Copy link
Author

Choose a reason for hiding this comment

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

Ok, I think that SwiftPM dependency tree checks and source level checks are separate and not mutually exclusive. Other platforms support both. How's about we consider adding source-level checks with the @available attribute? swiftlang/swift#34439 is one example of that. We still need to decide how we pass a list of features to it, or if we version Wasm in some way.

For versioning we could consider is year versions. As in, Wasm 2018 is MVP, Wasm 2019 is MVP + whatever was available in all browsers at the end of 2019 etc. This would be similar to how Babel versions ECMAScript.

WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

Combining the two suggestions, the manifest could indicate:

let package = Package(
    name: "SwiftWasmApp",
    platforms: [.wasm("atomics,simd")]

and SPM translates that into --experimental-wasm-features

Copy link
Author

Choose a reason for hiding this comment

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

Nice, I like it!

@MaxDesiatov
Copy link
Author

BTW, here's a PR enabling Windows support for source-level checks. I wonder if we could adapt it to our needs. swiftlang/swift#34439

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants