diff --git a/Fixtures/PIFBuilder/CCPackage/Package.swift b/Fixtures/PIFBuilder/CCPackage/Package.swift new file mode 100644 index 00000000000..0237d0bd0f4 --- /dev/null +++ b/Fixtures/PIFBuilder/CCPackage/Package.swift @@ -0,0 +1,14 @@ +// swift-tools-version: 6.2 + +import PackageDescription + +let package = Package( + name: "CCPackage", + products: [ + .library(name: "CCTarget", type: .static, targets: ["CCTarget"]), + ], + targets: [ + .target(name: "CCTarget", ), + .executableTarget(name: "executable", dependencies: ["CCTarget"]), + ] +) diff --git a/Fixtures/PIFBuilder/CCPackage/Sources/CCTarget/test.cc b/Fixtures/PIFBuilder/CCPackage/Sources/CCTarget/test.cc new file mode 100644 index 00000000000..3b4ca51c9b9 --- /dev/null +++ b/Fixtures/PIFBuilder/CCPackage/Sources/CCTarget/test.cc @@ -0,0 +1,2 @@ + +#include diff --git a/Fixtures/PIFBuilder/CCPackage/Sources/executable/executable.swift b/Fixtures/PIFBuilder/CCPackage/Sources/executable/executable.swift new file mode 100644 index 00000000000..4190ba6a221 --- /dev/null +++ b/Fixtures/PIFBuilder/CCPackage/Sources/executable/executable.swift @@ -0,0 +1,9 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book + +@main +struct Executable { + static func main() { + print("Hello, world!") + } +} diff --git a/Fixtures/PIFBuilder/UnknownPlatforms/Package.swift b/Fixtures/PIFBuilder/UnknownPlatforms/Package.swift index 3aedee44976..6f791248e21 100644 --- a/Fixtures/PIFBuilder/UnknownPlatforms/Package.swift +++ b/Fixtures/PIFBuilder/UnknownPlatforms/Package.swift @@ -9,7 +9,7 @@ let package = Package( name: "UnknownPlatforms", swiftSettings: [ .define("FOO", .when(platforms: [.custom("DoesNotExist")])), - .define("BAR", .when(platforms: [.linux])), + .define("BAR", .when(platforms: [.linux])), .define("BAZ", .when(platforms: [.macOS])), ], ), diff --git a/Sources/SwiftBuildSupport/PackagePIFBuilder.swift b/Sources/SwiftBuildSupport/PackagePIFBuilder.swift index 3a82eda038b..5227a775a5a 100644 --- a/Sources/SwiftBuildSupport/PackagePIFBuilder.swift +++ b/Sources/SwiftBuildSupport/PackagePIFBuilder.swift @@ -552,7 +552,6 @@ public final class PackagePIFBuilder { // We currently deliberately do not support Swift ObjC interface headers. settings[.SWIFT_INSTALL_OBJC_HEADER] = "NO" settings[.SWIFT_OBJC_INTERFACE_HEADER_NAME] = "" - settings[.OTHER_LDRFLAGS] = [] // Packages use the SwiftPM workspace's cache directory as a compiler working directory to maximize module // sharing. diff --git a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift index 95dc7920a2c..aaf57fde37c 100644 --- a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift +++ b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift @@ -488,14 +488,16 @@ extension PackagePIFProjectBuilder { if enableDuplicateLinkageCulling { impartedSettings[.LD_WARN_DUPLICATE_LIBRARIES] = "NO" } - impartedSettings[.OTHER_LDFLAGS] = (sourceModule.isCxx ? ["-lc++"] : []) + ["$(inherited)"] - impartedSettings[.OTHER_LDRFLAGS] = [] - log( - .debug, - indent: 1, - "Added '\(impartedSettings[.OTHER_LDFLAGS]!)' to imparted OTHER_LDFLAGS" - ) - + if sourceModule.isCxx { + for platform in ProjectModel.BuildSettings.Platform.allCases { + // darwin & freebsd + if [.macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .xrOS, .driverKit, .freebsd].contains(platform) { + settings[.OTHER_LDFLAGS, platform] = ["-lc++", "$(inherited)"] + } else if [.android, .linux, .wasi, .openbsd].contains(platform) { + settings[.OTHER_LDFLAGS, platform] = ["-lstdc++", "$(inherited)"] + } + } + } // This should be only for dynamic targets, but that isn't possible today. // Improvement is tracked by rdar://77403529 (Only impart `PackageFrameworks` search paths to clients of dynamic // package targets and products). @@ -820,7 +822,6 @@ extension PackagePIFProjectBuilder { impartedSettings[.OTHER_CFLAGS] = ["-fmodule-map-file=\(systemLibrary.modulemapFileAbsolutePath)"] + pkgConfig.cFlags.prepending("$(inherited)") impartedSettings[.OTHER_LDFLAGS] = pkgConfig.libs.prepending("$(inherited)") - impartedSettings[.OTHER_LDRFLAGS] = [] impartedSettings[.OTHER_SWIFT_FLAGS] = ["-Xcc"] + impartedSettings[.OTHER_CFLAGS]! log(.debug, indent: 1, "Added '\(systemLibrary.path.pathString)' to imparted HEADER_SEARCH_PATHS") diff --git a/Tests/SwiftBuildSupportTests/PIFBuilderTests.swift b/Tests/SwiftBuildSupportTests/PIFBuilderTests.swift index 1b7e8d0fd4b..23bbd411c6b 100644 --- a/Tests/SwiftBuildSupportTests/PIFBuilderTests.swift +++ b/Tests/SwiftBuildSupportTests/PIFBuilderTests.swift @@ -85,6 +85,19 @@ extension SwiftBuildSupport.PIF.Workspace { } extension SwiftBuildSupport.PIF.Project { + fileprivate func target(id: String) throws -> ProjectModel.BaseTarget { + let matchingTargets: [ProjectModel.BaseTarget] = underlying.targets.filter { + return $0.common.id.value == String(id) + } + if matchingTargets.isEmpty { + throw StringError("No target named \(id) in PIF project") + } else if matchingTargets.count > 1 { + throw StringError("Multiple target named \(id) in PIF project") + } else { + return matchingTargets[0] + } + } + fileprivate func target(named name: String) throws -> ProjectModel.BaseTarget { let matchingTargets = underlying.targets.filter { $0.common.name == name @@ -135,6 +148,28 @@ struct PIFBuilderTests { } } + @Test func platformCCLibrary() async throws { + try await withGeneratedPIF(fromFixture: "PIFBuilder/CCPackage") { pif, observabilitySystem in + let releaseConfig = try pif.workspace + .project(named: "CCPackage") + .target(id: "PACKAGE-TARGET:CCTarget") + .buildConfig(named: "Release") + + for platform in ProjectModel.BuildSettings.Platform.allCases { + let ld_flags = releaseConfig.settings[.OTHER_LDFLAGS, platform] + if [.macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .xrOS, .driverKit, .freebsd].contains(platform) { + #expect(ld_flags == ["-lc++", "$(inherited)"], "for platform \(platform)") + } else if [.android, .linux, .wasi, .openbsd].contains(platform) { + #expect(ld_flags == ["-lstdc++", "$(inherited)"], "for platform \(platform)") + } else if [.windows, ._iOSDevice].contains(platform) { + #expect(ld_flags == nil, "for platform \(platform)") + } else { + Issue.record("Unexpected platform \(platform)") + } + } + } + } + @Test func pluginWithBinaryTargetDependency() async throws { try await withGeneratedPIF(fromFixture: "Miscellaneous/Plugins/BinaryTargetExePlugin") { pif, observabilitySystem in // Verify that PIF generation succeeds for a package with a plugin that depends on a binary target