Swift Release Notes

Follow

63 release notes curated from 56 sources by the Releasebot Team. Last updated: Apr 23, 2026

Get this feed:

Swift Products

  • Oct 11, 2026
    • Date parsed from source:
      Oct 11, 2026
    • First seen by Releasebot:
      Apr 23, 2026
    • Modified by Releasebot:
      Oct 12, 2026
    Swift logo

    swift-format by Swift

    swift-DEVELOPMENT-SNAPSHOT-2026-10-10-a

    swift-format ships tag build swift-DEVELOPMENT-SNAPSHOT-2026-10-10-a.

    Tag build swift-DEVELOPMENT-SNAPSHOT-2026-10-10-a

    Original source
  • Oct 11, 2026
    • Date parsed from source:
      Oct 11, 2026
    • First seen by Releasebot:
      Apr 15, 2026
    • Modified by Releasebot:
      Oct 12, 2026
    Swift logo

    Swift

    swift-DEVELOPMENT-SNAPSHOT-2026-10-10-a

    Swift ships development snapshot swift-DEVELOPMENT-SNAPSHOT-2026-10-10-a.

    Tag build swift-DEVELOPMENT-SNAPSHOT-2026-10-10-a

    Original source
  • All of your release notes in one feed

    Join Releasebot and get updates from Swift and hundreds of other software products.

    Create account
  • Oct 10, 2026
    • Date parsed from source:
      Oct 10, 2026
    • First seen by Releasebot:
      Aug 13, 2026
    • Modified by Releasebot:
      Oct 10, 2026
    Swift logo

    swift-format by Swift

    swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-10-08-a

    swift-format ships a Swift 6.4.x development snapshot build.

    Tag build swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-10-08-a

    Original source
  • Oct 10, 2026
    • Date parsed from source:
      Oct 10, 2026
    • First seen by Releasebot:
      Jun 3, 2026
    • Modified by Releasebot:
      Oct 12, 2026
    Swift logo

    Swift

    swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-10-08-a

    Swift ships development snapshot swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-10-08-a.

    Tag build swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-10-08-a

    Original source
  • Oct 9, 2026
    • Date parsed from source:
      Oct 9, 2026
    • First seen by Releasebot:
      Oct 12, 2026
    Swift logo

    Swift

    swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-10-07-a

    Swift tags a development snapshot build for 6.4.x.

    Tag build swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-10-07-a

    Original source
  • Similar to Swift with recent updates:

  • Oct 9, 2026
    • Date parsed from source:
      Oct 9, 2026
    • First seen by Releasebot:
      Aug 13, 2026
    • Modified by Releasebot:
      Oct 10, 2026
    Swift logo

    swift-format by Swift

    swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-10-07-a

    swift-format ships a swift-6.4.x development snapshot tag build.

    Tag build swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-10-07-a

    Original source
  • Oct 8, 2026
    • Date parsed from source:
      Oct 8, 2026
    • First seen by Releasebot:
      Oct 10, 2026
    Swift logo

    Swift

    What's new in Swift: September 2026 Edition

    Swift highlights Swift 6.4, deeper interoperability and stronger platform support, plus Vapor 5 beta with structured concurrency and a full rewrite. The digest also covers new package releases, community updates, and accepted Swift Evolution proposals.

    Welcome to “What’s new in Swift,” a curated digest of releases, videos, and discussions in the Swift project and community.

    The Vapor web framework recently turned ten and celebrated with Vapor Week! We’ve invited one of the authors of Vapor as this month’s guest contributor:

    Hi, I’m Tim from the Vapor Core Team! 10 years ago, in September, Vapor 1.0 was released, and over the years Vapor has matured into a comprehensive framework for building backends and APIs in Swift.

    On the anniversary we released the first beta of Vapor 5, the next major version of Vapor, which is a complete rewrite, removing 6 years of tech debt, adding full structured concurrency support, and (finally!) saying goodbye to EventLoopFutures.

    From the very beginning, Vapor’s goals haven’t changed: an expressive, easy-to-use and powerful framework for building server applications in Swift. With Vapor 5 we can make use of the new Swift HTTP Server to handle the actual HTTP parts and concentrate on being a great web framework, using the latest Swift features where they make sense.

    It’s amazing to see the range of people using Vapor, from indie developers to large companies. You can find the full story, including our updated, localised and more accessible docs, in Vapor Week.

    If you’re curious about server-side Swift, give the Vapor 5 beta a try and let us know what you think!

    Now on to other news about Swift:

    Swift 6.4 release

    In September, the project’s headline story was the release of Swift 6.4, which brings deeper interoperability, stronger platform support, and easier everyday code. Highlights include Swift Build as the new default in Swift Package Manager, Subprocess reaching 1.0, and up to 40x faster WebAssembly bridging with JavaScriptKit.

    In the weeks leading up to the release we also shared two deep dives into some features it includes:

    • Module Tracking in Swift Debug Info explains how precise, path-based module imports make LLDB lookups more reliable and shrink dSYMs and binaries. Build-system maintainers (Bazel, Buck, CMake) will want to replace -modulewrap / -add_ast_path with -debug-module-path.
    • Embedded Swift Improvements Coming in Swift 6.4 rounds up what’s ahead for Swift on microcontrollers and other constrained environments.

    Community highlights

    • Google released a new SDK: the official Google Cloud client libraries for Swift. Built on SwiftNIO and Swift concurrency, it gives backend services and CLI tools async/await access to Cloud Storage, IAM, Secret Manager, Gemini, and 100+ other Google Cloud services, on both Linux and macOS.
    • Curious what it takes to run Swift with no OS at all? A minimal kernel in Swift running in QEMU uses Embedded Swift and the @c attribute to boot a kernel that prints a message and echoes typed input.
    • Solbach Leads shared their Swift adoption story, including how they migrated a production AI data pipeline from Kotlin and Spring Boot to Swift and Vapor. Six months in, their pipeline handles over 52 million tasks a month.
    • Stop Sleeping: Deterministic Tests for Concurrent Swift Code shows how to replace Task.sleep in tests with test spies, so tests can check timeouts, errors, and cancellation without waiting on the clock.
    • The monthly Swift for Wasm update is out. September 2026 updates highlights experimental threads support in the Wasm Swift SDK (currently in nightly snapshots), JavaScriptKit’s new uWASI option, and custom elements in ElementaryUI.

    New package releases

    • WasmKit is a WebAssembly runtime written in Swift. The 0.4 release doubles interpreter speed, and it can now run on ESP32-C6 microcontrollers and the Playdate.
    • Swift AWS Lambda Runtime 3.0 was released, adding SwiftPM plugins for init, build, and deploy. The build plugin can now package as a zip or OCI image, and you can choose how you compile: with Docker, Apple’s container, or cross-compiling using the Swift Static Linux SDK.

    Swift Evolution

    The Swift project adds new language features through the Swift Evolution process. These are some of the proposals currently under review or recently accepted for a future Swift release.

    Under active review:

    • SE-0554 Deployment target conditional compilation - Swift can test whether an API is available at runtime with if #available(...), but that cannot select between imports, type aliases, conformances, stored properties, or complete declarations; those choices have to be made while the module is being compiled. This proposal adds #if deploymentTargetAtLeast(...), so a library can compile different source for different minimum OS versions without maintaining a separate build-system flag.

    Recently accepted:

    • SE-0546 Same-file memberwise initializer extensions - When a struct’s memberwise initializer is meant to be public, it is only possible to define it in its base declaration; defining it in an extension is a redeclaration error, and for macro-generated structs there is no way to publicize their memberwise initializers. This proposal allows memberwise initializers, and default init(), to be defined in same-file extensions.
    • SE-0548 resignRemoteID for remote distributed actor references - Today, a DistributedActorSystem observes the lifecycle of local distributed actors through assignID(:) / resignID(:), and participates in creating remote references through resolve(id:as:), but there is no way to observe when a remote reference has been deinitialized. This proposal adds resignRemoteID(_:), invoked when a remote distributed actor proxy is deinitialized, so systems can keep connections alive only while at least one remote reference still uses them.
    • ST-0029 Include additional issue metadata in event stream - Tools such as Xcode and VS Code consume Swift Testing’s JSON event stream, but there isn’t enough structured information to distinguish between different kinds of issues, for example a thrown error versus a manual Issue.record call. This proposal adds new fields to the issue event type, including error, confirmation miscount, exceeded time limit, and expression, so tools can show richer failure context.

    Recently accepted with modifications:

    • SE-0540 Default Target Settings (reviewed as Default Package Settings) - It is very common for Swift packages to use the same settings flags across all their targets, which today means duplicating them per target or mutating package.targets after the package has been defined. This proposal lets default settings be defined as part of the Package initializer (defaultSwiftSettings, defaultCSettings, defaultCXXSettings, and defaultLinkerSettings), with a .defaults placeholder that controls how each target inherits them.
    Original source
  • Sep 29, 2026
    • Date parsed from source:
      Sep 29, 2026
    • First seen by Releasebot:
      Oct 12, 2026
    Swift logo

    swift-format by Swift

    swift-6.4.1-RELEASE

    swift-format bumps the Swift version to 6.4.1

    Bump the Swift version to 6.4.1

    Original source
  • Sep 28, 2026
    • Date parsed from source:
      Sep 28, 2026
    • First seen by Releasebot:
      Jul 14, 2026
    • Modified by Releasebot:
      Oct 12, 2026
    Swift logo

    Swift

    swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-09-26-a

    Swift tags the swift-6.4.x development snapshot build for 2026-09-26.

    Tag build swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-09-26-a

    Original source
  • Sep 26, 2026
    • Date parsed from source:
      Sep 26, 2026
    • First seen by Releasebot:
      Jun 3, 2026
    • Modified by Releasebot:
      Oct 12, 2026
    Swift logo

    swift-format by Swift

    swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-09-24-a

    swift-format ships a Swift 6.4 development snapshot tag build.

    Tag build swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-09-24-a

    Original source
  • Sep 22, 2026
    • Date parsed from source:
      Sep 22, 2026
    • First seen by Releasebot:
      Apr 23, 2026
    • Modified by Releasebot:
      Sep 28, 2026
    Swift logo

    swift-format by Swift

    swift-DEVELOPMENT-SNAPSHOT-2026-09-21-a

    swift-format ships development snapshot build swift-DEVELOPMENT-SNAPSHOT-2026-09-21-a.

    Tag build swift-DEVELOPMENT-SNAPSHOT-2026-09-21-a

    Original source
  • Sep 22, 2026
    • Date parsed from source:
      Sep 22, 2026
    • First seen by Releasebot:
      Apr 15, 2026
    • Modified by Releasebot:
      Sep 28, 2026
    Swift logo

    Swift

    swift-DEVELOPMENT-SNAPSHOT-2026-09-21-a

    Swift releases development snapshot swift-DEVELOPMENT-SNAPSHOT-2026-09-21-a.

    Tag build swift-DEVELOPMENT-SNAPSHOT-2026-09-21-a

    Original source
  • Sep 16, 2026
    • Date parsed from source:
      Sep 16, 2026
    • First seen by Releasebot:
      Sep 17, 2026
    Swift logo

    swift-format by Swift

    604.0.0

    swift-format ships a broad update with new formatting controls, better configuration handling, improved comment and import formatting, support for line-based formatting ranges, and fixes across platforms and workflows.

    What's Changed

    Move CODEOWNERS to .github/CODEOWNERS by @ahoppen in #1132

    Give all code owners the ability to edit .github/CODEOWNERS by @ahoppen in #1140

    Add OrderedImports configuration to disable grouping by import type by @amja in #1133

    [CI] Update the github-workflows tag to 0.0.6 to support macOS Tahoe by @shahmishal in #1148

    [UseShorthandTypeNames] Parenthesize (each T)? when converting from Optional. by @allevato in #1166

    Remove deprecated accessor modifier API in UseSingleLinePropertyGetter by @TTOzzi in #1173

    Add option to install without building. by @3405691582 in #1171

    Preserve required line breaks after standalone block comments when existing line breaks are not respected by @TTOzzi in #1169

    Fix rpath handling on OpenBSD. by @3405691582 in #1172

    Bump swiftlang/github-workflows/.github/workflows/soundness.yml from 0.0.6 to 0.0.8 by @dependabot[bot] in #1162

    Bump swiftlang/github-workflows/.github/workflows/create_automerge_pr.yml from 0.0.6 to 0.0.8 by @dependabot[bot] in #1163

    Bump swiftlang/github-workflows/.github/workflows/swift_package_test.yml from 0.0.6 to 0.0.8 by @dependabot[bot] in #1164

    Add --lines <start>:<end> to support formatting ranges based on line numbers instead of UTF-8 offsets. by @allevato in #1175

    [workflow] Use environment variables for user inputs by @rintaro in #1167

    Bump swiftlang/github-workflows/.github/workflows/swift_package_test.yml from 0.0.8 to 0.0.9 by @dependabot[bot] in #1179

    Bump swiftlang/github-workflows/.github/workflows/soundness.yml from 0.0.8 to 0.0.9 by @dependabot[bot] in #1180

    Bump swiftlang/github-workflows/.github/workflows/create_automerge_pr.yml from 0.0.8 to 0.0.9 by @dependabot[bot] in #1181

    Correctly format unsafe when preceding a for loop pattern. by @allevato in #1189

    Add group for swiftlang GitHub Actions by @shahmishal in #1185

    Add missing encoding for Configuration.multilineTrailingCommaBehavior by @li-bei in #1191

    Improve error messages on invalid configuration files by @Wilfred in #1184

    Bump the swiftlang-actions group across 1 directory with 3 updates by @dependabot[bot] in #1190

    Add support for .swift-format-ignore files by @bkhouri in #1156

    Revert "Add support for .swift-format-ignore files" by @bkhouri in #1195

    Revert "Revert "Add support for .swift-format-ignore files"" by @bkhouri in #1197

    [6.4] Change swift-syntax dependency to release/6.4.x by @rintaro in #1201

    [6.4] update ImportsXCTestVisitor class by @bkhouri in #1249

    [6.4.0] Match release branches with a patch component in publish_release by @rintaro in #1292

    [6.4.0][Workflow] Accept warnings in Publish Release by @rintaro in #1297

    New Contributors

    @amja made their first contribution in #1133

    @li-bei made their first contribution in #1191

    @Wilfred made their first contribution in #1184

    Full Changelog: 603.0.0...604.0.0

    Original source
  • Sep 15, 2026
    • Date parsed from source:
      Sep 15, 2026
    • First seen by Releasebot:
      Sep 15, 2026
    Swift logo

    Swift

    Swift 6.4 Released

    Swift releases 6.4 with broader support across apps, servers, systems, embedded devices, and the browser. It makes builds more unified, adds Subprocess 1.0, expands C++, Java, WebAssembly, and Android interoperability, and brings faster, safer code with clearer everyday syntax and tooling improvements.

    Swift 6.4 is now available. Swift aims to be a great choice across the stack, from apps and servers to systems code, embedded devices, and the browser. This release deepens that support, and makes everyday code easier to write. Highlights include:

    • Swift Build is now the default in Swift Package Manager, so your projects build the same way on Linux, macOS, and Windows.
    • Subprocess reaches 1.0, a stable, cross-platform way to run and interact with other programs from Swift, from command-line tools to streaming processes.
    • Interoperability reaches further, with Swift’s Span now bridging directly with C++20’s std::span, and Swift/Java interop extending its async and callback support.
    • Swift runs faster in the browser, with WebAssembly bridging through JavaScriptKit up to 40 times faster, and the Wasm SDK available directly from Swift.org.
    • Embedded Swift grows more capable, with support for existential types and richer error handling for microcontroller-class targets.
    • Performance improves while maintaining memory safety, with new array types that hold non-copyable elements without copy-on-write overhead, and the new Iterable protocol for iterating without copies.

    There’s so much more. Read on for a detailed guide to the new changes, or see the Swift Evolution dashboard for the full list of proposals in Swift 6.4.

    Simpler and clearer code

    Swift 6.4 streamlines your day-to-day programming to make your code simpler and clearer.

    • More natural optional some and any types. When writing an optional some or any type, you no longer have to wrap the type in parentheses. Instead of (some Rocket)?, you can simply write some Rocket? (SE-0521).
    • Source-level control over compiler warnings. When you need to control the behavior of warnings in your project, such as suppressing warnings or promoting them to errors, you can now define the warning behavior directly in your code using the new @diagnose attribute (SE-0522).
    • Clarify which API to use when multiple libraries conflict. When multiple modules define the same API name that you want to reference, you can specify which module you meant to use through module selectors. If your app imports two modules that both provide a type CommonThing, using the :: selector lets you clearly specify which of those you intend (SE-0491).
    • Call async functions in a defer block. Any asynchronous code you write in a defer block is awaited and runs to completion before it exits (SE-0493).
    • Ensure that necessary cleanup work isn’t cancelled. You can run a closure that’s shielded from the enclosing task’s cancellation through the withTaskCancellationShield API (SE-0504).

    You can combine asynchronous calls in defer blocks and cancellation shields to make sure that cleanup work always happens, no matter how the function returns:

    func processFile(at url: URL) async throws {
      let handle = try FileHandle(forReadingFrom: url)
      defer {
        // flushMetrics is a network call, so it can suspend after cancellation
        // is requested; the shield ensures it runs to completion and isn't
        // included in cancellation.
        await withTaskCancellationShield {
          await flushMetrics(for: url)
          try? handle.close()
        }
      }
      try await processContents(of: handle)
    }
    

    Richer core library APIs

    Improvements to Foundation and the standard library make it easier to use modern APIs with existing types.

    For example, ProgressManager added API to provide async/await support (SF-0023), and @Observable types now have fine-grained and continuous change notifications (SE-0506).

    The Subprocess library — originally introduced as SF-0007 and released as an initial 0.1 version in 2025 — has reached 1.0. It provides a cross-platform package to run and interact with subprocesses, built from the ground up using Swift concurrency. The following example, from Getting Started with Subprocess, illustrates running a process and capturing its output.

    let result = try await Subprocess.run(.name("ls"), arguments: ["-la"], output: .string(limit: 4096))
    print(result.standardOutput)
    

    Swift 6.4 makes it easier to migrate existing projects to use Swift Testing. You can now safely use XCTAssert in Swift Testing tests or #expect within XCTests (ST-0021), and customize the values shown in failed expectations using the CustomTestReflectable protocol (ST-0022).

    swift test lets you repeat test cases to focus and save time (ST-0024) and record attachments that conform to the Transferable protocol on Apple platforms (ST-0023).

    Swift now has a documentation site, and the documentation content for the standard library is now open source.

    Faster builds, clearer debugging, broader IDE support

    Swift 6.4 brings a range of tooling improvements that make everyday development smoother, from debugging and building to editor support:

    • More robust debugging. Swift 6.4 completes a multi-release overhaul of how the compiler tracks Swift modules in debug info — LLDB now imports modules through precise dependency tracking instead of ambiguous by-name lookups. Debug builds on Linux and Windows, and dSYM bundles on Darwin, shrink significantly since binary Swift modules are no longer embedded in them. Read the recent blog post Module Tracking in Swift Debug Info for a dive into the details.
    • Unified build system across IDEs. Swift Package Manager (SwiftPM) now uses Swift Build as its default build platform, and includes Software Bill of Materials (SBOM) Generation for Swift Package Manager (SE-0509), providing support for generating SBOM documents in either SPDX or CycloneDX format. Read more about SwiftPM’s updates in the SwiftPM 6.4 release notes, and learn how to generate an SBOM at Generating Software Bill of Materials (SBOM).
    • Broader IDE support for Swift. The VS Code extension for Swift is now available on the Open VSX Registry, so it works not only in VS Code, but also Cursor, Antigravity, Kiro, and other development tools. It also now includes integration with Swiftly, making it easier to select and use different versions of Swift toolchains with your project.

    Deeper interoperability and platform support

    Swift’s interoperability expands its reach across more of the stack: from systems-level C++ to Android’s Java runtime, and from WebAssembly (Wasm) in the browser to Embedded Swift on microcontrollers.

    Language interoperability goes deeper this release.

    • C: Pair @c with @implementation to use a Swift function to provide the implementation for a C header with no separate C declaration. Without @implementation, the compiler emits the declaration into the generated header. Either way, @c functions can get safe wrappers, such as a function that uses Span in place of a raw pointer-and-count pair.
    • C++: Swift 6.4 bridges C++20’s std::span with Swift’s Span, so you can pass a Span to a C++ API that expects a std::span, and receive a std::span back as a Span, without writing manual conversion code at the boundary.
    • Java: The Swift/Java interop project, which lets you call Swift from Java and Kotlin, extends its support for calling async and throwing functions to protocol and callback wrappers, adds automatic Runnable mapping for closures, variadic parameter import, and support for Java record types.

    Swift’s platform support deepens as well.

    WebAssembly

    JavaScriptKit has better performance when bridging to Wasm in Swift 6.4, with safe bridging up to 40 times faster than earlier dynamic bridging. The Wasm SDK is available from the Install Swift page of Swift.org, so compiling Swift for the browser requires no extra setup beyond adding the SDK.

    Foundation updates for Swift 6.4 improve FileManager support on WASI (the WebAssembly System Interface).

    Android

    Swift on Android continues to advance. This release of the Swift SDK for Android is built with the new LTS NDK 30, which provides Android availability attributes both in the Swift runtime libraries and for your Swift packages using the default NDK. Swift Build now supports Android in SwiftPM as well, removing the need for a post-install script.

    Embedded Swift

    The earlier post Embedded Swift Improvements Coming in Swift 6.4 covers Embedded Swift’s other improvements in this release in more depth, including generalized support for existential types (such as any Protocol), which lets you naturally express heterogeneous collections and throw and catch any Error.

    Embedded Swift also gains a new EmbeddedRestrictions warning that you can enable across a whole target:

    // Package.swift — enable EmbeddedRestrictions warnings for the target
    .target(
      name: "FirmwareCore",
      swiftSettings: [
        .treatWarning("EmbeddedRestrictions", as: .warning)
      ]
    )
    

    Faster code that stays safe

    Swift 6.4 makes it easier to avoid unnecessary copies of your data while staying memory-safe, extending earlier work on Span, non-copyable types, and InlineArray.

    • Work with values in memory without copying them. Borrow and mutate accessors let you read or update a Span or InlineArray through a property (SE-0507), non-copyable types can now conform to Equatable, Comparable, and Hashable, and new Ref and MutableRef types give you a first-class, storable container that lets you borrow or mutate one value at a time (SE-0519). Optionals of non-copyable types now work the same way, so you can inspect or update what’s inside an Optional without consuming it (SE-0532).
    • Build collections and heap-allocated values without unnecessary memory allocation. UniqueBox gives you a smart pointer that uniquely owns a heap value, including non-copyable values, without reference counting (SE-0517). UniqueArray stores non-copyable elements without the copy-on-write allocations you would see when using Array and provides a buffer that grows dynamically (SE-0527). You can loop over elements and borrow them with the Iterable protocol, instead of copying each value, which extends beyond what the Sequence protocol supports (SE-0516).
    • Access raw memory safely, without using unsafe-annotated APIs. withTemporaryAllocation provides a scratch buffer that is automatically initialized and cleaned up (SE-0524). A new safe loading API lets RawSpan and its variants load and store bytes safely, replacing the unsafe-flagged functions (SE-0525).

    Thank you

    Swift 6.4 reflects the contributions of many people across the Swift community, through code, proposals, forum discussions, and feedback. The community’s thoughts and real-world experience provide invaluable insights and motivation!

    If you’d like to get involved in what comes next, the Swift Forums are a great place to start.

    Get started with Swift 6.4

    Try out Swift 6.4 today by following the instructions on the Install Swift page, or download the new 6.4 toolchain with Swiftly.

    Original source
  • Sep 11, 2026
    • Date parsed from source:
      Sep 11, 2026
    • First seen by Releasebot:
      Sep 11, 2026
    Swift logo

    Swift

    Module Tracking in Swift Debug Info

    Swift introduces more precise debugger module tracking for Swift 6.4, making LLDB imports faster and more reliable while shrinking debug info and dSYM bundles. It also improves bridging header debugging and lets custom build systems replace older modulewrap and add_ast_path workflows.

    When your Swift program hits a breakpoint and stops so you can inspect it, the debugger’s expression evaluator has to find the exact Swift module your code was built from. Until now, that lookup wasn’t always precise. The upcoming Swift 6.4 release will include changes, begun in Swift 6.3, that address this by updating how the Swift compiler references explicitly-built Swift modules in debug info.

    The majority of developers will automatically benefit from faster, more reliable debugging and smaller build products, without any modifications to their SwiftPM or Xcode projects.

    For developers who maintain their own build systems using, for example, Bazel, Buck, or CMake, some adjustments may be necessary to take advantage of these changes.

    This article explains how the debugger uses Swift modules. Next, it describes how Swift 6.3 changes the way modules are tracked in debug info to solve several problems with the previous representation. Finally, it shows how to adjust build systems to take advantage of the new representation and eliminate some build steps that are no longer necessary.

    Swift modules and expression evaluation

    LLDB’s standout feature is its powerful expression evaluator. Because LLDB embeds the Clang and Swift compilers, it can JIT-compile any valid source code and run it in the context of your application while stopped at a breakpoint. This includes not just calling code in your application, but also defining new data types, functions, and closures. Debugging features that are usually reserved for interpreted or JIT-compiled languages like JavaScript become available to ahead-of-time-compiled languages like C++ and, of course, Swift!

    In order to JIT-compile user expressions that make use of data types defined in the debugged program, LLDB’s embedded Swift compiler needs to import the Swift modules defining those types. In a world before explicitly-built modules, LLDB would find the base name of the main module at the current breakpoint in the debug info and then kick off an implicit import of a module with that name. With a cold module cache this would launch an expensive compilation of that module and all its dependencies.

    To illustrate this, let’s walk through a simple example:

    (lldb)
    
    p
    myObj
    

    Here myObj is just a local variable: LLDB can find its location in the debug info and resolve its type via reflection metadata. No need to bother the Swift compiler. Let’s make it more complex:

    (lldb)
    
    p
    myObj.myComputedProperty
    

    In this case, myComputedProperty is really a function call; in order to evaluate this, LLDB needs the expression evaluator to run code in the target. In order to initialize a Swift compiler instance with the state of the current module, LLDB finds the name of the current function’s Swift module in debug info. We can visualize what LLDB does using the dwarfdump utility:

    $
    dwarfdump Foo.o
    ...
    DW_TAG_module
      DW_AT_name
    ("Foo")
    

    Conceptually, LLDB then wraps the expression in a function that can be compiled:

    (lldb)
    
    log enable lldb
    expr (
    lldb
    )
    p myObj.myComputedProperty
    ...
    import Foo
    func lldb_expr(_ $__lldb_arg : UnsafeMutablePointer<Any>) {
    let myObj : MyObject = /* some LLDB magic */
    // Expression begins here:
    myObj.myComputedProperty
    ...
    }
    

    One problem with this is that import Foo is quite imprecise: Even though the Swift language doesn’t allow multiple modules to have the same name, even the most stringently engineered application may have more than one copy of the same module. For example, there might be a private version of a module containing all of its private declarations (which would be great for LLDB) and also a Swift interface file that only contains the public interface for the module. Or there might be macOS and Mac Catalyst variants of the same module in the same process.

    Swift modules, debug info, and the build system

    Let’s look at where those modules are found next. In order to communicate the location of Foo.swiftmodule to LLDB, Swift build systems rely on some cooperation from the linker. On Darwin the system linker accepts an option called -add_ast_path and build systems are expected to specify this option to list every binary Swift module when linking.

    # Linker invocation on macOS
    ld -add_ast_path /path/to/Foo.swiftmodule Foo.o -o MyApplication
    

    The linker translates these options into symbol table entries. The debug info linker dsymutil then collects all Swift modules and stores them in a special __swift_ast section in the dSYM bundle, where LLDB can find them by name. Alternatively, when debugging without dSYM bundles, LLDB reads the symbol table entries in the binary to collect a list of all binary Swift modules. Such an approach would not work on platforms where the linker isn’t aware of Swift. For these platforms, which include Windows, Linux, and FreeBSD, the Swift compiler provides a -modulewrap action that takes a binary Swift module and outputs an object file with a .swift_ast section holding the contents of the module. This object file can then be passed to any linker to get added to the binary, where LLDB can find it.

    # Modulewrap and linker invocation on Linux
    swift-frontend -modulewrap Foo.swiftmodule -o Foo.swiftmodule.o
    lld Foo.o Foo.swiftmodule.o -o MyApplication
    

    This can create scalability issues, especially for large applications:

    • Module files can get large and for an entire application you can often end up with a large portion of the SDK in the resulting binary. That can be quite problematic for the binary size.
    • As mentioned above, the chances of LLDB finding the right module in a Swift AST section or symbol table just by its base name diminish as the application gets more complex.
    • Binary Swift modules are version-locked to the precise compiler that created them. This is at odds with the intent of dSYM bundles, which are meant for long-term archival serialization of debug info.
    • If a matching explicit module cannot be found, LLDB falls back to an implicit module import which may involve recompiling parts of the SDK from source. This can be very slow.

    Precise module tracking

    To evaluate expressions, the debugger needs to be able to find and import Swift modules. Until now, this relied either on special linker support or additional compilation steps, with a high cost for binary size. On top of that the debugger was imprecisely locating Swift modules by name.

    Starting in Swift 6.3 and continuing since, we have been making changes to the Swift compiler, the Swift driver, and LLDB that improve performance, reliability, and scalability. These changes are built on top of explicitly-built modules.

    What’s new

    • Explicitly-built modules track their explicit Swift dependencies: Explicitly-built binary Swift modules have always kept track of their explicitly-built Clang module dependencies. This is why LLDB can import explicit modules so much faster than implicit modules, which may need to recompile their dependencies from source. In Swift 6.3, explicitly-built binary Swift modules also keep track of their Swift module dependencies. This makes importing an explicitly-built module fast and unambiguous because no module needs to be looked up by name. This happens automatically. Users don’t need to make any changes. Users with distributed build systems will already be familiar with the Swift frontend’s path remapping options, which now also affect Swift module paths.
    • Debug info stores path of object file’s own Swift module: Once LLDB finds the top-level module it can precisely import it and all of its dependencies. But how can LLDB find precisely the module that belongs to the Swift file at the current breakpoint? In Swift 6.3, the Swift compiler can store the path to it in the debug info. Because a Swift file’s own Swift module is not an input to an object file compilation, there is a new -debug-module-path compiler option to communicate the path to each object file compilation action. This path is also subject to the standard path remapping options used by users with distributed build systems.
    • Swift driver passes module path to compile jobs: Users of swiftpm or Xcode do not need to think about this, because the Swift driver also knows about the new -debug-module-path option and automatically passes the path to the object file’s own Swift module to the compiler. However, users maintaining their own third-party build system to orchestrate Swift compilations with explicitly-built modules that are calling the Swift frontend directly and bypassing the Swift driver need to make sure to communicate the path to the top-level module to each object file compilation job.

    What’s deprecated

    Beginning in Swift 6.4, you can safely make the following changes.

    • swiftc -modulewrap and ld -add_ast_path: Because the module paths are now communicated via debug info and the module headers themselves, third-party build systems doing explicit module builds can now remove all -modulewrap actions on Linux and Windows; and remove the use of the -add_ast_path linker option on Darwin (macOS, iOS, etc…).
    • Binary Swift modules in dSYM bundles: As a consequence, dsymutil will no longer process binary Swift modules. This is a good thing, because binary Swift modules—which can only be parsed by the exact toolchain that produced them—were always at odds with dSYM bundles being a long-term archival format. Moreover, Swift modules often depend on Clang modules, and these Clang modules also were never included in dSYM bundles. By removing the binary Swift modules, dSYM bundles will get smaller.
      • But don’t we need them for debugging? Since Swift 1.0, binary Swift modules were included in dSYM bundles because they were needed to resolve the types of local variables. However, starting with Swift 5.6, LLDB could perform this operation by reading the reflection metadata in the binary. The absence of binary Swift modules in dSYM bundles does not affect LLDB’s ability to inspect the contents of variables or dump object descriptions with po. Binary Swift modules are still needed to evaluate complex expressions like function calls or computed getters. Expression evaluation continues to work as long as LLDB finds all binary modules in their original (or remapped) location. This is always the case when debugging a just-built binary on the same machine. If the absence of binary Swift modules in dSYM bundles creates an unforeseen problem with your workflow, please let us know, either on the Swift LLDB forum or by creating an issue on the bug tracker.

    When compiling with caching enabled, all paths pointing to Swift modules and module debug info are content-addressable storage references, identified by content rather than file location, so everything described here also works transparently with compilation caching.

    Coming in Swift 6.4: Faster bridging header import in LLDB

    Beyond more reliable path tracking, Swift 6.4 will also speed up importing bridging headers, a step common enough across Swift projects that most developers will feel the difference.

    Up to and including Swift 6.3, LLDB always compiles a bridging header from source, a step that can add noticeable time to debugging sessions that use one. In recent nightly development toolchains, LLDB can use the new precise explicit module information to import precompiled bridging headers and their explicit module dependencies directly. This makes debugging explicitly-built projects with bridging headers as fast and reliable as debugging fully modularized projects.

    Summary

    With these changes for explicitly-built modules:

    • Binaries built with debug info on Windows and Linux, and dSYM bundles on Darwin will get dramatically smaller, since they no longer contain any binary Swift modules (6.4+)
    • Contextual module imports in LLDB become more reliable due to precise tracking instead of by-name lookups
    • Certain performance cliffs around module importing in LLDB are eliminated (such as SDK module dependencies in dSYMs triggering implicit imports)
    • Developers maintaining their own build systems can remove support for -modulewrap actions and remove -add_ast_path from the linker flags, but may need to pass -debug-module-path to the compiler if they are not letting the Swift driver handle the frontend options
    • Finally, static archives were easy to overlook: projects that didn’t use -add_ast_path when linking them often had confusing debugging issues inside those archives as a result. This entire class of issues has been designed away.

    tl;dr: -modulewrap and -add_ast_path are replaced by -debug-module-path. Debug info gets smaller and more precise.

    Original source
Releasebot

Curated by the Releasebot team

Releasebot is an aggregator of official release notes from hundreds of software vendors and thousands of sources.

Our editorial process involves the manual review and audit of release notes procured with the help of automated systems.