Skip to content

fix(windows): align static Foundation autolinks - #5525

Open
mozharovsky wants to merge 4 commits into
swiftlang:mainfrom
mozharovsky:fix/windows-static-networking-autolinks
Open

fix(windows): align static Foundation autolinks#5525
mozharovsky wants to merge 4 commits into
swiftlang:mainfrom
mozharovsky:fix/windows-static-networking-autolinks

Conversation

@mozharovsky

@mozharovsky mozharovsky commented Aug 6, 2026

Copy link
Copy Markdown

Summary

  • Static CMake builds now autolink the packaged Windows archive names for FoundationNetworking and FoundationXML.
  • The Windows networking module propagates the zlib and Brotli archives required by its static curl build.
  • Other platforms retain their existing curl and xml2 autolinks.

Validation

  • CMake 4.3.2 emits the expected Windows autolink names for both patched targets.
  • The pinned x64 SDK reproduced the original curl.lib and xml2.lib link failures.
  • Rebuilt static modules produced libcurl.lib and libxml2s.lib directives and linked successfully.
  • A static FoundationXML executable parsed an XML document successfully.
  • Both x86_64 and ARM64 Windows SDK slices package libxml2s.lib and omit xml2.lib.
  • The Swift 6.3.3 release and 2026-07-11 development static Linux SDKs link unchanged on x86_64 and ARM64.

Related reports are thebrowsercompany/swift-build#351 and thebrowsercompany/swift-build#352.

Use the same static curl and compression archives in CMake builds that the package manifest already selects on Windows.
@mozharovsky
mozharovsky requested a review from a team as a code owner August 6, 2026 13:21
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend curl>")
if(WIN32)
target_compile_options(FoundationNetworking PRIVATE
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend libcurl>"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't understand why the name changes here. It worked as curl there? That said the rename is likely better as the name is supposed to be the actual name on disk.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The CMake path emitted an autolink for curl, which requests curl.lib, while the Windows static SDK packages the archive as libcurl.lib. A minimal FoundationNetworking executable therefore failed with LNK1104. The package manifest already names libcurl.lib, so this makes the CMake build match the working SwiftPM configuration.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Right, but I mean, how has this been working? I suppose that this fix is for outside the CMake build as the curl target in CMake already points to the static library.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yeah, exactly. This change is for consumers of the installed static SDK that are outside the CMake target graph. In the in-tree build _CFURLSessionInterface links CURL::libcurl so final CMake targets resolve the imported target to the static archive and its link interface.

An external swiftc consumer cannot see that CMake target. It only sees the -public-autolink-library metadata embedded in the installed Swift module. On Windows those entries become /DEFAULTLIB:<name>.lib, so the names must match the SDK’s packaged files and the static curl dependencies must be listed explicitly. These directives are emitted only under NOT BUILD_SHARED_LIBS which is why the installed static-SDK reproducer exposed the problem

@compnerd

compnerd commented Aug 6, 2026

Copy link
Copy Markdown
Member

This does need a cross repo test to build the full static SDK

@mozharovsky

Copy link
Copy Markdown
Author

@swift-ci please test Windows platform

"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend _CFURLSessionInterface>")
target_compile_options(FoundationNetworking PRIVATE
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend curl>")
if(WIN32)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Elsewhere we use if(CMAKE_SYSTEM_NAME STREQUAL "Windows") to conditionalize when building for Windows. How does if(WIN32) behave differently (if at all) / should we use the other format used elsewhere instead?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated in 0243902 to use CMAKE_SYSTEM_NAME STREQUAL "Windows", matching the condition style used elsewhere in this project.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To clarify - I'm not 100% certain whether that is the correct syntax but rather I was asking why you chose WIN32 and whether there is a difference with the CMAKE_SYSTEM_NAME check

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good question - I checked this directly with CMake 4.3.2. WIN32 was true for Windows, WindowsStore, WindowsPhone and WindowsCE while CMAKE_SYSTEM_NAME STREQUAL "Windows" selects only desktop Windows.

I originally used WIN32 as conventional shorthand, not because this change needed the broader Windows family. There is no benefit to that breadth here, so the narrower check matching the project's existing style is preferable. That is why I updated it.

"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend brotlicommon>"
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend brotlidec>")
else()
target_compile_options(FoundationNetworking PRIVATE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why doesn't Linux need the extra auto linked libraries as well? The dependencies should be the same between Linux/Windows so I wouldn't expect anything to be windows specific here (except for maybe the name of the library if windows uses a different prefix for example)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The Windows SDK builds and packages a static curl archive with zlib and Brotli enabled, but those archive dependencies are not encoded in its autolink metadata. Linux normally resolves the shared curl target and its dynamic dependencies; the existing BUILD_FULLY_STATIC path separately handles its static link additions. This Windows list also mirrors the existing Windows-only linker settings in Package.swift.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Linux normally resolves the shared curl target and its dynamic dependencies

I don't think this is true - the static Linux SDK includes a libcurl.a, a libz.a, etc. The static Linux SDK should not be dynamically linking curl.

This Windows list also mirrors the existing Windows-only linker settings in Package.swift.

I don't think the Package.swift file is relevant here because it does not build static libraries - it dynamically links in the dependencies

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I don't think this is true - the static Linux SDK includes a libcurl.a, a libz.a, etc. The static Linux SDK should not be dynamically linking curl.

You are right about the underlying mechanism and my earlier comment conflated archive naming with linkage mode. On Unix, curl is the correct -l name for either libcurl.so or libcurl.a. The selected linkage mode determines which file is used. The relevant question here is which transitive archives the static curl build actually needs.

I checked the published Swift 6.3.3 Static Linux SDK and the latest main snapshot from 2026-07-11 for both x86_64 and aarch64. In all four configurations:

  • libcurl.a references OpenSSL and zlib
  • libcurl.a has no unresolved Brotli* symbols
  • The SDK ships libcurl.a, libssl.a, libcrypto.a, and `libz.a
  • It does not ship libbrotlicommon.a or libbrotlidec.a
  • swift-sdk.json and toolset.json inject no dependency linker flags
  • A minimal FoundationNetworking executable links successfully

The generated autolink file contains -lcrypto, -lssl, -lcurl and -lz confirming that Linux's dependencies are supplied by the existing BUILD_FULLY_STATIC block. Brotli is absent because both published Linux curl archives were built without Brotli support.

Windows uses a different curl configuration: Schannel, zlib and Brotli. Its observed unresolved symbols are exactly the zlib and Brotli set. Therefore the platform-specific lists are intentional: Windows needs libcurl, zlibstatic, brotlicommon and brotlidec while Linux correctly retains curl plus the existing crypto, ssl and z autolinks.


I don't think the Package.swift file is relevant here because it does not build static libraries - it dynamically links in the dependencies

I agree that Package.swift does not establish the CMake or Linux behavior. Its narrower relevance is that its Windows _CFURLSessionInterface configuration defines CURL_STATICLIB and uses those same four Windows archive names.

The cross-repository full static SDK build @compnerd requested remains the final integration check. My @swift-ci request has not produced a visible run, so someone with CI access still needs to trigger it - I am happy to validate the result!

@mozharovsky

Copy link
Copy Markdown
Author

@swift-ci please test Windows platform

@jmschonfeld

Copy link
Copy Markdown
Contributor

Does the same problem exist with the libxml dependency for FoundationXML?

@mozharovsky mozharovsky changed the title fix(windows): autolink static networking dependencies fix(windows): align static Foundation autolinks Aug 6, 2026
@mozharovsky

Copy link
Copy Markdown
Author

Does the same problem exist with the libxml dependency for FoundationXML?

Yes - the archive-name half of the same problem exists for FoundationXML.


I reproduced it against the Swift 6.3.3 WindowsExperimental SDK. A static executable importing FoundationXML currently fails with LNK1104: cannot open file 'xml2.lib' while the SDK packages the archive as libxml2s.lib - I verified the archive name in both the x86_64 and ARM64 Windows SDKs.

Unlike curl the Windows libxml2 build has no companion static dependencies. Its build disables zlib, LZMA, iconv and ICU + the archive has no unresolved references to any of them. This agrees with Package.swift which links only libxml2s.lib on Windows.

Extended in fcd833c with the corresponding FoundationXML branch using libxml2s on Windows and retaining xml2 elsewhere. The build now passes -public-autolink-library libxml2s. The rebuilt module embeds /DEFAULTLIB:libxml2s.lib and a static executable successfully parses an XML document.


Linux remains unchanged. I verified the Swift 6.3.3 release SDK and the 2026-07-11 development snapshot for x86_64 and aarch64: all four static executables link successfully with the existing xml2 and z autolinks. Their libxml2 archives reference iconv which musl supplies directly so no separate iconv archive is required (the existing z entry there appears unneeded for the current libxml2 build but it is harmless - libz.a ships in the SDK so I've left it untouched to keep this change scoped)

I also checked every static public-autolink site in this repository: Foundation's existing archive names match the Windows SDK and FoundationNetworking plus FoundationXML are the two platform-specific dependency-name cases.

The FoundationXML change is a separate commit - if you'd rather keep this PR scoped to networking, I'm happy to peel it off into an immediate follow-up!

@mozharovsky

Copy link
Copy Markdown
Author

cc @compnerd - this extends the same archive-name fix to FoundationXML so the full static SDK build you requested will validate both in one run!

"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend xml2>")
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
target_compile_options(FoundationXML PRIVATE
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend libxml2s>")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think that this might be xml2s and not libxml2s

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I rechecked the installed SDK and the emitted directive. Both the x86_64 and ARM64 slices of the pinned WindowsExperimental SDK contain libxml2s.lib. Neither contains xml2s.lib or xml2.lib

The autolink argument is literal on Windows apart from the .lib suffix. The previous xml2 entry emitted /DEFAULTLIB:xml2.lib while libxml2s emits /DEFAULTLIB:libxml2s.lib. With that directive the static XMLParser reproducer links and prints true. Package.swift also names libxml2s.lib for Windows although the packaged SDK and functional link test are the decisive checks.

Are you seeing xml2s.lib in a different build-tree or SDK artifact? Could you please point me to it? Thanks!

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