Skip to content

Support swift build --experimental-xcframeworks-on-linux#1310

Merged
owenv merged 5 commits into
swiftlang:mainfrom
ordo-one:experimental-xcframeworks-on-linux
Apr 28, 2026
Merged

Support swift build --experimental-xcframeworks-on-linux#1310
owenv merged 5 commits into
swiftlang:mainfrom
ordo-one:experimental-xcframeworks-on-linux

Conversation

@vsarunas

Copy link
Copy Markdown
Contributor

Allow use of --experimental-xcframeworks-on-linux flag as per #1250

These changes allows us to compile our code base on Linux using --build-system swiftbuild.

@owenv owenv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As I said in the linked issue, I don't think it makes sense to take this change - we shouldn't attempt to process malformed XCFrameworks that don't contain MachO binaries, and we should ensure the compiler is prepared to enforce the appropriate stability guarantees before allowing packages to vend binary shared libraries via artifact bundle on non-Apple platforms.

Comment thread Sources/SWBCore/XCFramework.swift Outdated
/// Given a platform and the variant, attempt to find an library within the XCFramework that can be used.
public func findLibrary(platform: String, platformVariant: String = "") -> XCFramework.Library? {
public func findLibrary(platform: String, platformVariant: String = "", architectures: [String] = []) -> XCFramework.Library? {
#if canImport(Darwin)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You can't use ifdefs here because this will not work for cross-compilation.

I think the actual condition here is whether the platform uses per-arch slices? You can extract the logic in the usesPerArchSlices property you added to LibraryKey and re-use that here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

OK! ifdef removed, originally I was trying to minimise the changes required and not thread through this argument.

Comment thread Sources/SWBCore/XCFramework.swift Outdated
// that platform default archs to the host and allow a no-variant fallback.
let platformMatches = libraries.filter { $0.supportedPlatform == platform }
var effectiveArchs = architectures
if platform == "linux", effectiveArchs.isEmpty, let hostArch = Architecture.hostStringValue {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You can't use Architecture.hostStringValue here because this will not work for cross-compilation. architectures should never be an empty list - for the Linux case you can check that it contains exactly one value, and look up that value.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Adjusted.

@vsarunas vsarunas requested a review from jakepetroules April 22, 2026 11:30

@jakepetroules jakepetroules left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking better! Commented on a few more small things...

Comment thread Sources/SWBCore/XCFramework.swift Outdated
@_spi(Testing) public static let mergeableMetadataVersion = Version(1, 1)

static func hasPerArchSlices(_ platform: String) -> Bool {
return platform == "linux"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please change this to:

Suggested change
return platform == "linux"
return !["macosx", "iphoneos", "iphonesimulator", "appletvos", "appletvsimulator", "watchos", "watchsimulator", "xros", "xrsimulator", "driverkit"].contains(platform)

It's a bit verbose, but this is more correct and protects against edge cases if we end up splitting linux into multiple platforms, which @owenv and I have talked about doing to solve some cross compilation issues.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Adjusted, even more verbose as an existing test was failing.

Comment thread Sources/SWBCore/XCFramework.swift Outdated
lib.supportedPlatform == platform && (lib.platformVariant ?? "") == platformVariant
}.first
}
// Linux ships per-arch XCFramework slices and typically omits SupportedPlatformVariant, so for

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
// Linux ships per-arch XCFramework slices and typically omits SupportedPlatformVariant, so for
// Non-Apple platforms ship per-arch XCFramework slices and typically omit SupportedPlatformVariant, so for

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Adjusted.

Comment thread Sources/SWBCore/XCFramework.swift Outdated
}.first
}
// Linux ships per-arch XCFramework slices and typically omits SupportedPlatformVariant, so for
// that platform require exactly one target arch and allow a no-variant fallback.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
// that platform require exactly one target arch and allow a no-variant fallback.
// those platforms, require exactly one target arch and allow a no-variant fallback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Adjusted.

Comment thread Sources/SWBCore/XCFramework.swift Outdated
// identifier is only used for tracking the offending library
hasher.combine(platform)
hasher.combine(platformVariant)
if usesPerArchSlices {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This needs to be unconditionally added to the hash; Hashable and Equatable conformances are not the right place for this sort of business logic.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Business logic moved to validate().

Comment thread Sources/SWBCore/XCFramework.swift Outdated
guard lhs.platform == rhs.platform, lhs.platformVariant == rhs.platformVariant else {
return false
}
return lhs.usesPerArchSlices ? (lhs.architectures == rhs.architectures) : true

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This needs to be unconditionally compared; Hashable and Equatable conformances are not the right place for this sort of business logic.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed.

Comment thread Sources/SWBCore/XCFramework.swift Outdated
// Linux ships per-arch XCFramework slices and typically omits SupportedPlatformVariant, so for
// that platform require exactly one target arch and allow a no-variant fallback.
guard architectures.count == 1 else { return nil }
let targetArch = architectures[0]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You can combine the .count==1 check with this:

Suggested change
let targetArch = architectures[0]
guard let targetArch = architectures.only else { return nil }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed.

@vsarunas vsarunas requested a review from jakepetroules April 24, 2026 13:39
@vsarunas vsarunas force-pushed the experimental-xcframeworks-on-linux branch from 3c2fee8 to 18dff13 Compare April 24, 2026 13:45
Comment thread Sources/SWBCore/XCFramework.swift Outdated
return false
}
// SDK names from Info.plist.
let sdkCanonicalNames = [

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry, I forgot these platform names are in terms of the triples, not the Xcode platform names. You shouldn't check both -- just the BuildVersion.Platform code path is sufficient.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Simplified.

@vsarunas vsarunas requested a review from jakepetroules April 25, 2026 07:05
@jakepetroules

Copy link
Copy Markdown
Collaborator

@swift-ci test

@vsarunas

Copy link
Copy Markdown
Contributor Author

Ubuntu failure https://github.com/swiftlang/swift-build/actions/runs/24925300005/job/73036104365?pr=1310#step:14:43080 doesn't seem to be related to the changes:

◇ Test case passing 1 argument buildSystem → .swiftbuild to enableDisableCache(buildSystem:) started.
**** FAILURE EXECUTING SUBPROCESS ****
output: 
stderr: 
*** Signal 11: Backtracing from 0x7f19595ce9aa... failed ***

*** Backtracer crashed during backtracing; attempting to backtrace backtracer: ***

*** Signal 4: Backtracing from 0x7f2082b4983c... done ***

*** Program crashed: Illegal instruction at 0x00007f2082b4983c ***

Platform: x86_64 Linux (Ubuntu 22.04.5 LTS)

Thread 0 "swift-backtrace" crashed:

 0                0x00007f2082b4983c specialized ImageSource.fetchSLEB128(from:) + 220 in libswiftRuntime.so
 1 [ra]           0x00007f2082afcce7 DwarfReader.read(form:at:addressSize:isDwarf64:unit:shouldFetchIndirect:constantValue:) + 1654 in libswiftRuntime.so
 2 [ra]           0x00007f2082afea5e DwarfReader.readDieAttributes(at:unit:abbrevInfo:shouldFetchIndirect:) + 365 in libswiftRuntime.so
 3 [ra]           0x00007f2082b04907 DwarfReader._scanUnits() + 646 in libswiftRuntime.so
 4 [ra]           0x00007f2082b0068f DwarfReader._lazyInfo.getter + 46 in libswiftRuntime.so
 5 [ra]           0x00007f2082b00b11 DwarfReader.lookupInlineCallSites(at:) + 32 in libswiftRuntime.so
 6 [ra]           0x00007f2082b0f501 ElfImage.inlineCallSites(at:) + 48 in libswiftRuntime.so

@vsarunas vsarunas requested a review from owenv April 27, 2026 16:54

@owenv owenv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I guess this isn't doing too much harm

@owenv owenv merged commit 683439b into swiftlang:main Apr 28, 2026
121 of 126 checks passed
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