From bb6fad8a3d1ed694d568409b6e2fb07aadfe0a77 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Thu, 27 Mar 2025 10:44:28 +0000 Subject: [PATCH 1/4] Rename Package.swift -> Package@swift-6.0.swift --- Package.swift => Package@swift-6.0.swift | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Package.swift => Package@swift-6.0.swift (100%) diff --git a/Package.swift b/Package@swift-6.0.swift similarity index 100% rename from Package.swift rename to Package@swift-6.0.swift From f9b3973044cb2cde6a335f09ddcb7c958c97a798 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Thu, 27 Mar 2025 10:45:06 +0000 Subject: [PATCH 2/4] Add package-trait based Package.swift --- Package.swift | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 Package.swift diff --git a/Package.swift b/Package.swift new file mode 100644 index 00000000..5a3a1ca5 --- /dev/null +++ b/Package.swift @@ -0,0 +1,94 @@ +// swift-tools-version:6.1 + +import PackageDescription + +// NOTE: needed for embedded customizations, ideally this will not be necessary at all in the future, or can be replaced with traits +let useLegacyResourceBundling = + Context.environment["JAVASCRIPTKIT_USE_LEGACY_RESOURCE_BUNDLING"].flatMap(Bool.init) ?? false + +let package = Package( + name: "JavaScriptKit", + products: [ + .library(name: "JavaScriptKit", targets: ["JavaScriptKit"]), + .library(name: "JavaScriptEventLoop", targets: ["JavaScriptEventLoop"]), + .library(name: "JavaScriptBigIntSupport", targets: ["JavaScriptBigIntSupport"]), + .library(name: "JavaScriptEventLoopTestSupport", targets: ["JavaScriptEventLoopTestSupport"]), + .plugin(name: "PackageToJS", targets: ["PackageToJS"]), + ], + traits: [ + "Embedded" + ], + targets: [ + .target( + name: "JavaScriptKit", + dependencies: ["_CJavaScriptKit"], + exclude: useLegacyResourceBundling ? [] : ["Runtime"], + resources: useLegacyResourceBundling ? [.copy("Runtime")] : [], + cSettings: [ + .unsafeFlags(["-fdeclspec"], .when(traits: ["Embedded"])) + ], + swiftSettings: [ + .enableExperimentalFeature("Embedded", .when(traits: ["Embedded"])), + .enableExperimentalFeature("Extern", .when(traits: ["Embedded"])), + .unsafeFlags(["-Xfrontend", "-emit-empty-object-file"], .when(traits: ["Embedded"])), + ] + ), + .target(name: "_CJavaScriptKit"), + .testTarget( + name: "JavaScriptKitTests", + dependencies: ["JavaScriptKit"], + swiftSettings: [ + .enableExperimentalFeature("Extern") + ] + ), + + .target( + name: "JavaScriptBigIntSupport", + dependencies: ["_CJavaScriptBigIntSupport", "JavaScriptKit"] + ), + .target(name: "_CJavaScriptBigIntSupport", dependencies: ["_CJavaScriptKit"]), + .testTarget( + name: "JavaScriptBigIntSupportTests", + dependencies: ["JavaScriptBigIntSupport", "JavaScriptKit"] + ), + + .target( + name: "JavaScriptEventLoop", + dependencies: ["JavaScriptKit", "_CJavaScriptEventLoop"] + ), + .target(name: "_CJavaScriptEventLoop"), + .testTarget( + name: "JavaScriptEventLoopTests", + dependencies: [ + "JavaScriptEventLoop", + "JavaScriptKit", + "JavaScriptEventLoopTestSupport", + ], + swiftSettings: [ + .enableExperimentalFeature("Extern") + ] + ), + .target( + name: "JavaScriptEventLoopTestSupport", + dependencies: [ + "_CJavaScriptEventLoopTestSupport", + "JavaScriptEventLoop", + ] + ), + .target(name: "_CJavaScriptEventLoopTestSupport"), + .testTarget( + name: "JavaScriptEventLoopTestSupportTests", + dependencies: [ + "JavaScriptKit", + "JavaScriptEventLoopTestSupport", + ] + ), + .plugin( + name: "PackageToJS", + capability: .command( + intent: .custom(verb: "js", description: "Convert a Swift package to a JavaScript package") + ), + sources: ["Sources"] + ), + ] +) From 64fb506b50c6ac1e35118eb01b8e471ed63a6208 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Thu, 27 Mar 2025 12:11:53 +0000 Subject: [PATCH 3/4] Update Examples/Embedded to use the new `Embedded` trait --- Examples/Embedded/Package.swift | 4 ++-- Examples/Embedded/build.sh | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Examples/Embedded/Package.swift b/Examples/Embedded/Package.swift index 5ae19adc..aae08002 100644 --- a/Examples/Embedded/Package.swift +++ b/Examples/Embedded/Package.swift @@ -1,11 +1,11 @@ -// swift-tools-version:6.0 +// swift-tools-version:6.1 import PackageDescription let package = Package( name: "Embedded", dependencies: [ - .package(name: "JavaScriptKit", path: "../../"), + .package(name: "JavaScriptKit", path: "../../", traits: ["Embedded"]), .package(url: "https://github.com/swiftwasm/swift-dlmalloc", branch: "0.1.0"), ], targets: [ diff --git a/Examples/Embedded/build.sh b/Examples/Embedded/build.sh index f807cdbf..81840e76 100755 --- a/Examples/Embedded/build.sh +++ b/Examples/Embedded/build.sh @@ -1,5 +1,4 @@ #!/bin/bash package_dir="$(cd "$(dirname "$0")" && pwd)" -JAVASCRIPTKIT_EXPERIMENTAL_EMBEDDED_WASM=true \ - swift package --package-path "$package_dir" \ +swift package --package-path "$package_dir" \ -c release --triple wasm32-unknown-none-wasm js From 047e5a631393f94d877a12ebcfc39aa9cd637223 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Thu, 27 Mar 2025 13:15:05 +0000 Subject: [PATCH 4/4] Detect Embedded build mode by compilation condition --- .../Sources/PackageToJSPlugin.swift | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift b/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift index 9d0b2c19..559022c2 100644 --- a/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift +++ b/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift @@ -161,9 +161,11 @@ struct PackageToJSPlugin: CommandPlugin { } // Build products + let selfPackage = try findSelfPackage(in: context.package) let productName = try buildOptions.product ?? deriveDefaultProduct(package: context.package) let build = try buildWasm( productName: productName, + selfPackage: selfPackage, context: context, options: buildOptions.packageOptions ) @@ -178,14 +180,6 @@ struct PackageToJSPlugin: CommandPlugin { } else { context.pluginWorkDirectoryURL.appending(path: "Package") } - guard - let selfPackage = findPackageInDependencies( - package: context.package, - id: Self.JAVASCRIPTKIT_PACKAGE_ID - ) - else { - throw PackageToJSError("Failed to find JavaScriptKit in dependencies!?") - } var make = MiniMake( explain: buildOptions.packageOptions.explain, printProgress: self.printProgress @@ -226,9 +220,11 @@ struct PackageToJSPlugin: CommandPlugin { exit(1) } + let selfPackage = try findSelfPackage(in: context.package) let productName = "\(context.package.displayName)PackageTests" let build = try buildWasm( productName: productName, + selfPackage: selfPackage, context: context, options: testOptions.packageOptions ) @@ -264,14 +260,6 @@ struct PackageToJSPlugin: CommandPlugin { } else { context.pluginWorkDirectoryURL.appending(path: "PackageTests") } - guard - let selfPackage = findPackageInDependencies( - package: context.package, - id: Self.JAVASCRIPTKIT_PACKAGE_ID - ) - else { - throw PackageToJSError("Failed to find JavaScriptKit in dependencies!?") - } var make = MiniMake( explain: testOptions.packageOptions.explain, printProgress: self.printProgress @@ -311,6 +299,7 @@ struct PackageToJSPlugin: CommandPlugin { private func buildWasm( productName: String, + selfPackage: Package, context: PluginContext, options: PackageToJS.PackageOptions ) throws @@ -331,11 +320,7 @@ struct PackageToJSPlugin: CommandPlugin { ) parameters.echoLogs = true parameters.otherSwiftcFlags = ["-color-diagnostics"] - let buildingForEmbedded = - ProcessInfo.processInfo.environment["JAVASCRIPTKIT_EXPERIMENTAL_EMBEDDED_WASM"].flatMap( - Bool.init - ) ?? false - if !buildingForEmbedded { + if !isBuildingForEmbedded(selfPackage: selfPackage) { // NOTE: We only support static linking for now, and the new SwiftDriver // does not infer `-static-stdlib` for WebAssembly targets intentionally // for future dynamic linking support. @@ -355,6 +340,31 @@ struct PackageToJSPlugin: CommandPlugin { return try self.packageManager.build(.product(productName), parameters: parameters) } + /// Check if the build is for embedded WebAssembly + private func isBuildingForEmbedded(selfPackage: Package) -> Bool { + let coreTarget = selfPackage.targets.first { $0.name == "JavaScriptKit" } + guard let swiftTarget = coreTarget as? SwiftSourceModuleTarget else { + return false + } + // SwiftPM defines "Embedded" compilation condition when `Embedded` experimental + // feature is enabled. + // TODO: This should be replaced with a proper trait-based solution in the future. + return swiftTarget.compilationConditions.contains("Embedded") + } + + /// Find JavaScriptKit package in the dependencies of the given package recursively + private func findSelfPackage(in package: Package) throws -> Package { + guard + let selfPackage = findPackageInDependencies( + package: package, + id: Self.JAVASCRIPTKIT_PACKAGE_ID + ) + else { + throw PackageToJSError("Failed to find JavaScriptKit in dependencies!?") + } + return selfPackage + } + /// Clean if the build graph of the packaging process has changed /// /// This is especially important to detect user changes debug/release