Swift SDK for WebAssembly

  1. Are there tools similar to emconfigure and emmake available?
  2. Does having an autotools environment on macOS help with compiling C or C++ (like lcms2 project ) to a WASM static library?

% emconfigure ./configure
--prefix=/xxx/wasm/lcms2-2.19.1
--host=wasm32-unknown-wasip1
--enable-static
--disable-shared

% emmake make

% emmake make install

Can you elaborate what exactly you're trying to do? What's the nature of your C/C++ code? Is that a dependency that has been ported to WASI? If so, how do you build it outside of the Swift toolchain?

I have compiled the lcms2 to wasm static library using emconfigure and emmake make, but the Swift SDK for WebAssembly cannot use it. Therefore, I chose to compile it manually. I successfully compiled lcms2 into a static library and happily used it (liblcms2.a) in SwiftPM.

If the manual compilation part had tools like emconfigure and emmake or autotools (generate new configure file), it would be much more convenient, and it would also mean that more C or C++ open source libraries could be ported to Swift+WebAssembly much more easily.

In simple terms, I would like the Swift SDK for WebAssembly to provide tools similar to Emscripten's emconfigure and emmake, making it easier to cross-compile open-source C/C++ projects into WebAssembly static libraries.

% swift package --swift-sdk swift-6.3.3-RELEASE_wasm js -c release
  This .build/plugins/PackageToJS/outputs/Package package was also successfully used on the Web.

manual compilation

% SDK_ROOT=~/.swiftpm/swift-sdks/swift-6.3.3-RELEASE_wasm.artifactbundle/swift-6.3.3-RELEASE_wasm/wasm32-unknown-wasip1
% CLANG=~/.swiftly/bin/clang
% AR=~/.swiftly/bin/llvm-ar

% mkdir -p build-wasm
% cd build-wasm

% for f in ../src/*.c; do
    $CLANG \
    --target=wasm32-unknown-wasip1 \
    --sysroot="$SDK_ROOT/WASI.sdk" \
    -I../include \
    -O2 \
    -c "$f" -o "$(basename "$f" .c).o"
  done

% $AR rcs liblcms2.a *.o
% file cmsalpha.o
  cmsalpha.o: WebAssembly (wasm) binary module version 0x1 (MVP)

build-wasm
├── cmsalpha.o
├── cmscam02.o
├── cmscgats.o
├── cmscnvrt.o
├── cmserr.o
├── cmsgamma.o
├── cmsgmt.o
├── cmshalf.o
├── cmsintrp.o
├── cmsio0.o
├── cmsio1.o
├── cmslut.o
├── cmsmd5.o
├── cmsmtrx.o
├── cmsnamed.o
├── cmsopt.o
├── cmspack.o
├── cmspcs.o
├── cmsplugin.o
├── cmsps2.o
├── cmssamp.o
├── cmssm.o
├── cmstypes.o
├── cmsvirt.o
├── cmswtpnt.o
├── cmsxform.o
└── liblcms2.a

Package.swift

import PackageDescription

let package = Package(
    name: "color-foundation-wasm",
    platforms: [
        .macOS(.v15)
    ],
    products: [
        .executable(
            name: "ColorFoundation",
            targets: ["ColorFoundationWasm"]
        ),
    ],
    dependencies: [
        .package(url: "https://github.com/swiftwasm/JavaScriptKit", from: "0.57.1")
    ],
    targets: [
        // Targets are the basic building blocks of a package, defining a module or a test suite.
        // Targets can depend on other targets in this package and products from dependencies.
        .target(
            name: "CLibLCMS2",
            dependencies: [],
            cSettings: [.unsafeFlags(["-I/Volumes/Developer/usr/lib/wasm/lcms2-2.19.1/include"])],
            linkerSettings: [.unsafeFlags(["-L/Volumes/Developer/usr/lib/wasm/lcms2-2.19.1/lib"])]
        ),
        .executableTarget(
            name: "ColorFoundationWasm",
            dependencies: ["CLibLCMS2", "JavaScriptKit"],
            swiftSettings: [
                .enableExperimentalFeature("Extern")
            ],
            plugins: [
                .plugin(name: "BridgeJS", package: "JavaScriptKit")
            ]
        ),
        .testTarget(
            name: "ColorFoundationWasmTests",
            dependencies: ["ColorFoundationWasm"]
        ),
    ],
    swiftLanguageModes: [.v6]
)