Skip to content

Commit d1ba77e

Browse files
feat: Add Swift WebAssembly compilation support to swift-distributed-tracing (#174)
# Summary This PR adds support for compiling swift-distributed-tracing to wasm using the [Swift SDK for WebAssembly](https://www.swift.org/documentation/articles/wasm-getting-started.html). This PR is [part of a larger effort](PassiveLogic/swift-web-examples#1) by a company called PassiveLogic to enable broad support for Swift WebAssembly compilation. # Details There are three changes required to enable wasm compilation for swift-distributed-tracing. - Removed unused `import Dispatch` imports. The Swift SDK for WebAssembly doesn't currently include GCD. Luckily, all usage of GCD was unused. - Added some missing wasi-libc and pthread imports - Add shim to allow wrapped access to CLOCK_REALTIME struct from WASILibc. This is a critical piece of distributed tracing to acquire timestamps that needed some manual shim code to map to the matching API in WASI. # Testing done - [x] Cleaned up swiftformat lint on modified lines of change. - [x] Verified unit tests still pass with these changes - [x] Verified `swift build` completes without errors - [x] Verified no new compiler warnings are added with these changes - [x] Verified `swift build --swift-sdk wasm32-unknown-wasi` completes without errors - [x] Verified `swift build --swift-sdk wasm32-unknown-wasip1-threads` completes without errors - [x] Verified a third-party executable can build this library as part of a larger wasm executable using the command `swift package --swift-sdk wasm32-unknown-wasip1-threads js --use-cdn` # Impact Risk Realistically, this change should not cause any impact or risk. Outside of wasm targets, the changes in this PR are additive.
1 parent 6146724 commit d1ba77e

File tree

9 files changed

+83
-5
lines changed

9 files changed

+83
-5
lines changed

.github/workflows/pull_request.yml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,24 @@ jobs:
1717
name: Unit tests
1818
uses: apple/swift-nio/.github/workflows/unit_tests.yml@main
1919
with:
20-
linux_5_9_arguments_override: "--explicit-target-dependency-import-check error"
21-
linux_5_10_arguments_override: "--explicit-target-dependency-import-check error"
20+
21+
# NOTE: Aug 5, 2025. We've determined SPM has bugs for `condition: .when(platforms: [.somePlatform])`
22+
# that incorrectly ignore the condition and import anyways for unintended platforms.
23+
#
24+
# See https://github.com/apple/swift-distributed-tracing/actions/runs/16578688393/job/46920025183?pr=174
25+
# for an example of the resulting build failure.
26+
#
27+
# This is documented as a bug in Swift 5.10, resolved in Swift 6.
28+
# See FB14859516.
29+
# See also https://forums.swift.org/t/do-swiftpm-conditional-target-dependencies-work/74047
30+
#
31+
# Given this, the explicit target dependency check is disabled for Swift versions before Swift 6.
32+
33+
# Intentionally disabled:
34+
#
35+
# linux_5_9_arguments_override: "--explicit-target-dependency-import-check error"
36+
# linux_5_10_arguments_override: "--explicit-target-dependency-import-check error"
37+
2238
linux_6_0_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
2339
linux_6_1_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
2440
linux_nightly_6_0_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"

Package.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ let package = Package(
3535
dependencies: [
3636
.product(name: "ServiceContextModule", package: "swift-service-context"),
3737
.target(name: "Instrumentation"),
38+
.target(name: "_CWASI", condition: .when(platforms: [.wasi])),
3839
]
3940
),
4041
.testTarget(
@@ -43,6 +44,15 @@ let package = Package(
4344
.target(name: "Tracing")
4445
]
4546
),
47+
48+
// ==== --------------------------------------------------------------------------------------------------------
49+
// MARK: Wasm Support
50+
51+
// Provides C shims for compiling to wasm
52+
.target(
53+
name: "_CWASI",
54+
dependencies: []
55+
),
4656
]
4757
)
4858

Sources/Instrumentation/Locks.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ import Glibc
3434
import Android
3535
#elseif canImport(Musl)
3636
import Musl
37+
#elseif canImport(WASILibc)
38+
import WASILibc
39+
#if canImport(wasi_pthread)
40+
import wasi_pthread
41+
#endif
3742
#else
3843
#error("Unsupported runtime")
3944
#endif

Sources/Tracing/NoOpTracer.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15-
import Dispatch
1615
@_exported import Instrumentation
1716
@_exported import ServiceContextModule
1817

Sources/Tracing/Tracer.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15-
import Dispatch
1615
@_exported import Instrumentation
1716
@_exported import ServiceContextModule
1817

Sources/Tracing/TracerProtocol+Legacy.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15-
import Dispatch
1615
@_exported import Instrumentation
1716
@_exported import ServiceContextModule
1817

Sources/Tracing/TracingTime.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,16 @@ import Glibc
2323
import Android
2424
#elseif canImport(Musl)
2525
import Musl
26+
#elseif canImport(WASILibc)
27+
import WASILibc
2628
#else
2729
#error("Unsupported runtime")
2830
#endif
2931

32+
#if os(WASI)
33+
import _CWASI
34+
#endif
35+
3036
public protocol TracerInstant: Comparable, Hashable, Sendable {
3137
/// Representation of this instant as the number of nanoseconds since UNIX Epoch (January 1st 1970)
3238
var nanosecondsSinceEpoch: UInt64 { get }
@@ -84,7 +90,11 @@ public struct DefaultTracerClock {
8490

8591
public var now: Self.Instant {
8692
var ts = timespec()
93+
#if os(WASI)
94+
CWASI_clock_gettime_realtime(&ts)
95+
#else
8796
clock_gettime(CLOCK_REALTIME, &ts)
97+
#endif
8898
/// We use unsafe arithmetic here because `UInt64.max` nanoseconds is more than 580 years,
8999
/// and the odds that this code will still be running 530 years from now is very, very low,
90100
/// so as a practical matter this will never overflow.

Sources/_CWASI/_CWASI.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Distributed Tracing open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift Distributed Tracing project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift Distributed Tracing project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//

Sources/_CWASI/include/_CWASI.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Distributed Tracing open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift Distributed Tracing project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift Distributed Tracing project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#pragma once
16+
17+
#if __wasi__
18+
19+
#include <fcntl.h>
20+
#include <time.h>
21+
22+
static inline void CWASI_clock_gettime_realtime(struct timespec *tv) {
23+
// ClangImporter doesn't support `CLOCK_REALTIME` declaration in WASILibc, thus we have to define a bridge manually
24+
clock_gettime(CLOCK_REALTIME, tv);
25+
}
26+
27+
#endif // __wasi__

0 commit comments

Comments
 (0)