diff --git a/Package.swift b/Package.swift index 57b9d328950..1b67941a013 100644 --- a/Package.swift +++ b/Package.swift @@ -4,7 +4,7 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2014-2023 Apple Inc. and the Swift project authors +// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information @@ -349,7 +349,7 @@ let package = Package( .target( /** Support for building using Xcode's build system */ name: "XCBuildSupport", - dependencies: ["SPMBuildCore", "PackageGraph"], + dependencies: ["DriverSupport", "SPMBuildCore", "PackageGraph"], exclude: ["CMakeLists.txt", "CODEOWNERS"] ), .target( diff --git a/Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift b/Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift index 206bf6b163c..184ab64f59b 100644 --- a/Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift +++ b/Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift @@ -11,10 +11,13 @@ //===----------------------------------------------------------------------===// import Basics + import Foundation import PackageGraph import PackageLoading import PackageModel + +@_spi(SwiftPMInternal) import SPMBuildCore #if USE_IMPL_ONLY_IMPORTS @@ -419,18 +422,6 @@ public final class SwiftTargetBuildDescription { try self.fileSystem.writeIfChanged(path: path, string: content) } - private func packageNameArgumentIfSupported(with pkg: ResolvedPackage, packageAccess: Bool) -> [String] { - let flag = "-package-name" - if pkg.manifest.usePackageNameFlag, - DriverSupport.checkToolchainDriverFlags(flags: [flag], toolchain: self.buildParameters.toolchain, fileSystem: self.fileSystem) { - if packageAccess { - let pkgID = pkg.identity.description.spm_mangledToC99ExtendedIdentifier() - return [flag, pkgID] - } - } - return [] - } - private func macroArguments() throws -> [String] { var args = [String]() @@ -450,7 +441,14 @@ public final class SwiftTargetBuildDescription { #endif // If we're using an OSS toolchain, add the required arguments bringing in the plugin server from the default toolchain if available. - if self.buildParameters.toolchain.isSwiftDevelopmentToolchain, DriverSupport.checkSupportedFrontendFlags(flags: ["-external-plugin-path"], toolchain: self.buildParameters.toolchain, fileSystem: self.fileSystem), let pluginServer = try self.buildParameters.toolchain.swiftPluginServerPath { + if self.buildParameters.toolchain.isSwiftDevelopmentToolchain, + DriverSupport.checkSupportedFrontendFlags( + flags: ["-external-plugin-path"], + toolchain: self.buildParameters.toolchain, + fileSystem: self.fileSystem + ), + let pluginServer = try self.buildParameters.toolchain.swiftPluginServerPath + { let toolchainUsrPath = pluginServer.parentDirectory.parentDirectory let pluginPathComponents = ["lib", "swift", "host", "plugins"] @@ -631,7 +629,10 @@ public final class SwiftTargetBuildDescription { args += ["-user-module-version", version.description] } - args += self.packageNameArgumentIfSupported(with: self.package, packageAccess: self.target.packageAccess) + args += self.package.packageNameArgument( + target: self.target, + isPackageNameSupported: self.buildParameters.driverParameters.isPackageAccessModifierSupported + ) args += try self.macroArguments() // rdar://117578677 @@ -656,7 +657,12 @@ public final class SwiftTargetBuildDescription { result.append("-module-name") result.append(self.target.c99name) - result.append(contentsOf: packageNameArgumentIfSupported(with: self.package, packageAccess: self.target.packageAccess)) + result.append( + contentsOf: self.package.packageNameArgument( + target: self.target, + isPackageNameSupported: self.buildParameters.driverParameters.isPackageAccessModifierSupported + ) + ) if !scanInvocation { result.append("-emit-dependencies") diff --git a/Sources/CoreCommands/SwiftTool.swift b/Sources/CoreCommands/SwiftTool.swift index 478dbc253de..377eff2451c 100644 --- a/Sources/CoreCommands/SwiftTool.swift +++ b/Sources/CoreCommands/SwiftTool.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2014-2023 Apple Inc. and the Swift project authors +// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information @@ -23,8 +23,11 @@ import SPMBuildCore import Workspace #if USE_IMPL_ONLY_IMPORTS -@_implementationOnly import DriverSupport +@_implementationOnly +@_spi(SwiftPMInternal) +import DriverSupport #else +@_spi(SwiftPMInternal) import DriverSupport #endif @@ -757,7 +760,11 @@ public final class SwiftTool { enableParseableModuleInterfaces: options.build.shouldEnableParseableModuleInterfaces, explicitTargetDependencyImportCheckingMode: options.build.explicitTargetDependencyImportCheck.modeParameter, useIntegratedSwiftDriver: options.build.useIntegratedSwiftDriver, - useExplicitModuleBuild: options.build.useExplicitModuleBuild + useExplicitModuleBuild: options.build.useExplicitModuleBuild, + isPackageAccessModifierSupported: DriverSupport.isPackageNameSupported( + toolchain: toolchain, + fileSystem: self.fileSystem + ) ), linkingParameters: .init( linkerDeadStrip: options.linker.linkerDeadStrip, diff --git a/Sources/DriverSupport/DriverSupportUtils.swift b/Sources/DriverSupport/DriverSupportUtils.swift index 9e5bf00a739..7f8452ecc10 100644 --- a/Sources/DriverSupport/DriverSupportUtils.swift +++ b/Sources/DriverSupport/DriverSupportUtils.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2022 Apple Inc. and the Swift project authors +// Copyright (c) 2022-2024 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information @@ -20,7 +20,7 @@ import struct TSCBasic.ProcessResult public enum DriverSupport { private static var flagsMap = ThreadSafeBox<[String: Set]>() - // This checks _frontend_ supported flags, which are not necessarily supported in the driver. + /// This checks _frontend_ supported flags, which are not necessarily supported in the driver. public static func checkSupportedFrontendFlags( flags: Set, toolchain: PackageModel.Toolchain, @@ -54,7 +54,7 @@ public enum DriverSupport { // This checks if given flags are supported in the built-in toolchain driver. Currently // there's no good way to get the supported flags from it, so run `swiftc -h` directly // to get the flags and cache the result. - public static func checkToolchainDriverFlags( + static func checkToolchainDriverFlags( flags: Set, toolchain: PackageModel.Toolchain, fileSystem: FileSystem @@ -83,4 +83,9 @@ public enum DriverSupport { return false } } + + @_spi(SwiftPMInternal) + public static func isPackageNameSupported(toolchain: PackageModel.Toolchain, fileSystem: FileSystem) -> Bool { + DriverSupport.checkToolchainDriverFlags(flags: ["-package-name"], toolchain: toolchain, fileSystem: fileSystem) + } } diff --git a/Sources/PackageModel/Target/SwiftTarget.swift b/Sources/PackageModel/Target/SwiftTarget.swift index 13e16d5b30e..0dd16dbed91 100644 --- a/Sources/PackageModel/Target/SwiftTarget.swift +++ b/Sources/PackageModel/Target/SwiftTarget.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2014-2023 Apple Inc. and the Swift project authors +// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information diff --git a/Sources/SPMBuildCore/BuildParameters/BuildParameters+Driver.swift b/Sources/SPMBuildCore/BuildParameters/BuildParameters+Driver.swift index 6007d1d6046..0355f182cfb 100644 --- a/Sources/SPMBuildCore/BuildParameters/BuildParameters+Driver.swift +++ b/Sources/SPMBuildCore/BuildParameters/BuildParameters+Driver.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2020-2023 Apple Inc. and the Swift project authors +// Copyright (c) 2020-2024 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information @@ -25,13 +25,15 @@ extension BuildParameters { enableParseableModuleInterfaces: Bool = false, explicitTargetDependencyImportCheckingMode: TargetDependencyImportCheckingMode = .none, useIntegratedSwiftDriver: Bool = false, - useExplicitModuleBuild: Bool = false + useExplicitModuleBuild: Bool = false, + isPackageAccessModifierSupported: Bool = false ) { self.canRenameEntrypointFunctionName = canRenameEntrypointFunctionName self.enableParseableModuleInterfaces = enableParseableModuleInterfaces self.explicitTargetDependencyImportCheckingMode = explicitTargetDependencyImportCheckingMode self.useIntegratedSwiftDriver = useIntegratedSwiftDriver self.useExplicitModuleBuild = useExplicitModuleBuild + self.isPackageAccessModifierSupported = isPackageAccessModifierSupported } /// Whether to enable the entry-point-function-name feature. @@ -45,11 +47,16 @@ extension BuildParameters { /// `.swiftmodule`s. public var enableParseableModuleInterfaces: Bool - /// Whether to use the integrated Swift driver rather than shelling out + /// Whether to use the integrated Swift Driver rather than shelling out /// to a separate process. public var useIntegratedSwiftDriver: Bool /// Whether to use the explicit module build flow (with the integrated driver). public var useExplicitModuleBuild: Bool + + /// Whether the version of Swift Driver used in the currently selected toolchain + /// supports `-package-name` options. + @_spi(SwiftPMInternal) + public var isPackageAccessModifierSupported: Bool } } diff --git a/Sources/SPMBuildCore/CMakeLists.txt b/Sources/SPMBuildCore/CMakeLists.txt index d5c3ee43344..ed5d5d5d828 100644 --- a/Sources/SPMBuildCore/CMakeLists.txt +++ b/Sources/SPMBuildCore/CMakeLists.txt @@ -23,6 +23,7 @@ add_library(SPMBuildCore Plugins/PluginMessages.swift Plugins/PluginScriptRunner.swift PrebuildCommandResult.swift + ResolvedPackage+Extensions.swift Triple+Extensions.swift XCFrameworkMetadata.swift) # NOTE(compnerd) workaround for CMake not setting up include flags yet diff --git a/Sources/SPMBuildCore/ResolvedPackage+Extensions.swift b/Sources/SPMBuildCore/ResolvedPackage+Extensions.swift new file mode 100644 index 00000000000..f4e433b8631 --- /dev/null +++ b/Sources/SPMBuildCore/ResolvedPackage+Extensions.swift @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import struct PackageGraph.ResolvedPackage +import struct PackageGraph.ResolvedTarget + +extension ResolvedPackage { + @_spi(SwiftPMInternal) + public func packageNameArgument(target: ResolvedTarget, isPackageNameSupported: Bool) -> [String] { + if self.manifest.usePackageNameFlag, target.packageAccess { + ["-package-name", self.identity.description.spm_mangledToC99ExtendedIdentifier()] + } else { + [] + } + } +} diff --git a/Sources/SPMTestSupport/PIFTester.swift b/Sources/SPMTestSupport/PIFTester.swift index 4e4641fa016..85b64cbf6e5 100644 --- a/Sources/SPMTestSupport/PIFTester.swift +++ b/Sources/SPMTestSupport/PIFTester.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2014-2020 Apple Inc. and the Swift project authors +// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information @@ -32,7 +32,12 @@ public final class PIFWorkspaceTester { targetMap = Dictionary(uniqueKeysWithValues: targetsByGUID) } - public func checkProject(_ guid: PIF.GUID, file: StaticString = #file, line: UInt = #line, body: (PIFProjectTester) -> Void) throws { + public func checkProject( + _ guid: PIF.GUID, + file: StaticString = #file, + line: UInt = #line, + body: (PIFProjectTester) -> Void + ) throws { guard let project = projectMap[guid] else { return XCTFail("project \(guid) not found", file: file, line: line) } @@ -55,10 +60,20 @@ public final class PIFProjectTester { fileprivate init(project: PIF.Project, targetMap: [PIF.GUID: PIF.BaseTarget]) throws { self.project = project self.targetMap = targetMap - self.fileMap = try collectFiles(from: project.groupTree, parentPath: project.path, projectPath: project.path, builtProductsPath: project.path) + self.fileMap = try collectFiles( + from: project.groupTree, + parentPath: project.path, + projectPath: project.path, + builtProductsPath: project.path + ) } - public func checkTarget(_ guid: PIF.GUID, file: StaticString = #file, line: UInt = #line, body: ((PIFTargetTester) -> Void)? = nil) { + public func checkTarget( + _ guid: PIF.GUID, + file: StaticString = #file, + line: UInt = #line, + body: ((PIFTargetTester) -> Void)? = nil + ) { guard let baseTarget = baseTarget(withGUID: guid) else { let guids = project.targets.map { $0.guid }.joined(separator: ", ") return XCTFail("target \(guid) not found among \(guids)", file: file, line: line) @@ -71,13 +86,23 @@ public final class PIFProjectTester { body?(PIFTargetTester(target: target, targetMap: targetMap, fileMap: fileMap)) } - public func checkNoTarget(_ guid: PIF.GUID, file: StaticString = #file, line: UInt = #line, body: ((PIFTargetTester) -> Void)? = nil) { + public func checkNoTarget( + _ guid: PIF.GUID, + file: StaticString = #file, + line: UInt = #line, + body: ((PIFTargetTester) -> Void)? = nil + ) { if baseTarget(withGUID: guid) != nil { XCTFail("target \(guid) found", file: file, line: line) } } - public func checkAggregateTarget(_ guid: PIF.GUID, file: StaticString = #file, line: UInt = #line, body: ((PIFAggregateTargetTester) -> Void)? = nil) { + public func checkAggregateTarget( + _ guid: PIF.GUID, + file: StaticString = #file, + line: UInt = #line, + body: ((PIFAggregateTargetTester) -> Void)? = nil + ) { guard let baseTarget = baseTarget(withGUID: guid) else { let guids = project.targets.map { $0.guid }.joined(separator: ", ") return XCTFail("target \(guid) not found among \(guids)", file: file, line: line) @@ -90,7 +115,12 @@ public final class PIFProjectTester { body?(PIFAggregateTargetTester(target: target, targetMap: targetMap, fileMap: fileMap)) } - public func checkBuildConfiguration(_ name: String, file: StaticString = #file, line: UInt = #line, body: (PIFBuildConfigurationTester) -> Void) { + public func checkBuildConfiguration( + _ name: String, + file: StaticString = #file, + line: UInt = #line, + body: (PIFBuildConfigurationTester) -> Void + ) { guard let configuration = buildConfiguration(withName: name) else { let names = project.buildConfigurations.map { $0.name }.joined(separator: ", ") return XCTFail("build configuration \(name) not found among \(names)", file: file, line: line) @@ -151,7 +181,12 @@ public class PIFBaseTargetTester { }) } - public func checkBuildConfiguration(_ name: String, file: StaticString = #file, line: UInt = #line, body: (PIFBuildConfigurationTester) -> Void) { + public func checkBuildConfiguration( + _ name: String, + file: StaticString = #file, + line: UInt = #line, + body: (PIFBuildConfigurationTester) -> Void + ) { guard let configuration = buildConfiguration(withName: name) else { return XCTFail("build configuration \(name) not found", file: file, line: line) } @@ -163,19 +198,33 @@ public class PIFBaseTargetTester { return baseTarget.buildConfigurations.first { $0.name == name } } - public func checkImpartedBuildSettings(file: StaticString = #file, line: UInt = #line, _ body: (PIFBuildSettingsTester) -> Void) { - let buildSettingsTester = PIFBuildSettingsTester(buildSettings: baseTarget.buildConfigurations.first!.impartedBuildProperties.buildSettings) + public func checkImpartedBuildSettings( + file: StaticString = #file, + line: UInt = #line, + _ body: (PIFBuildSettingsTester) -> Void + ) { + let buildSettingsTester = PIFBuildSettingsTester( + buildSettings: baseTarget.buildConfigurations.first!.impartedBuildProperties.buildSettings + ) body(buildSettingsTester) } - public func checkAllImpartedBuildSettings(file: StaticString = #file, line: UInt = #line, _ body: (PIFBuildSettingsTester) -> Void) { - let buildSettingsTester = PIFBuildSettingsTester(buildSettings: baseTarget.buildConfigurations.first!.impartedBuildProperties.buildSettings) + public func checkAllImpartedBuildSettings( + file: StaticString = #file, + line: UInt = #line, + _ body: (PIFBuildSettingsTester) -> Void + ) { + let buildSettingsTester = PIFBuildSettingsTester( + buildSettings: baseTarget.buildConfigurations.first!.impartedBuildProperties.buildSettings + ) body(buildSettingsTester) buildSettingsTester.checkUncheckedSettings(file: file, line: line) } public func checkNoImpartedBuildSettings(file: StaticString = #file, line: UInt = #line) { - let buildSettingsTester = PIFBuildSettingsTester(buildSettings: baseTarget.buildConfigurations.first!.impartedBuildProperties.buildSettings) + let buildSettingsTester = PIFBuildSettingsTester( + buildSettings: baseTarget.buildConfigurations.first!.impartedBuildProperties.buildSettings + ) buildSettingsTester.checkUncheckedSettings(file: file, line: line) } } @@ -313,7 +362,12 @@ private func collectFiles( files[reference.guid] = referencePath.pathString } else if let group = reference as? PIF.Group { for child in group.children { - let childFiles = try collectFiles(from: child, parentPath: referencePath, projectPath: projectPath, builtProductsPath: builtProductsPath) + let childFiles = try collectFiles( + from: child, + parentPath: referencePath, + projectPath: projectPath, + builtProductsPath: builtProductsPath + ) files.merge(childFiles, uniquingKeysWith: { _, _ in fatalError("non-unique GUID") }) } } diff --git a/Sources/SPMTestSupport/SwiftPMProduct.swift b/Sources/SPMTestSupport/SwiftPMProduct.swift index b62a99b428c..1c10b1fda4e 100644 --- a/Sources/SPMTestSupport/SwiftPMProduct.swift +++ b/Sources/SPMTestSupport/SwiftPMProduct.swift @@ -128,7 +128,7 @@ extension SwiftPM { completeArgs += ["--package-path", packagePath.pathString] } completeArgs += args - + return try Process.popen(arguments: completeArgs, environment: environment) } } diff --git a/Sources/XCBuildSupport/PIFBuilder.swift b/Sources/XCBuildSupport/PIFBuilder.swift index 44117107238..3dda827da8e 100644 --- a/Sources/XCBuildSupport/PIFBuilder.swift +++ b/Sources/XCBuildSupport/PIFBuilder.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2014-2023 Apple Inc. and the Swift project authors +// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information @@ -15,6 +15,8 @@ import Basics import PackageModel import PackageLoading import PackageGraph + +@_spi(SwiftPMInternal) import SPMBuildCore import func TSCBasic.topologicalSort @@ -22,6 +24,8 @@ import func TSCBasic.memoize /// The parameters required by `PIFBuilder`. struct PIFBuilderParameters { + /// Whether the toolchain supports `-package-name` option. + let isPackageAccessModifierSupported: Bool /// Whether or not build for testability is enabled. let enableTestability: Bool @@ -264,12 +268,12 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { super.init() - guid = package.pifProjectGUID - name = package.manifest.displayName // TODO: use identity instead? - path = package.path - projectDirectory = package.path - developmentRegion = package.manifest.defaultLocalization ?? "en" - binaryGroup = groupTree.addGroup(path: "/", sourceTree: .absolute, name: "Binaries") + self.guid = package.pifProjectGUID + self.name = package.manifest.displayName // TODO: use identity instead? + self.path = package.path + self.projectDirectory = package.path + self.developmentRegion = package.manifest.defaultLocalization ?? "en" + self.binaryGroup = groupTree.addGroup(path: "/", sourceTree: .absolute, name: "Binaries") // Configure the project-wide build settings. First we set those that are in common between the "Debug" and // "Release" configurations, and then we set those that are different. @@ -471,6 +475,8 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { settings[.CLANG_CXX_LANGUAGE_STANDARD] = clangTarget.cxxLanguageStandard } else if let swiftTarget = mainTarget.underlying as? SwiftTarget { settings[.SWIFT_VERSION] = swiftTarget.swiftVersion.description + + settings.addCommonSwiftSettings(package: self.package, target: mainTarget, parameters: self.parameters) } if let resourceBundle = addResourceBundle(for: mainTarget, in: pifTarget) { @@ -501,7 +507,7 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { let executableName: String let productType: PIF.Target.ProductType if product.type == .library(.dynamic) { - if parameters.shouldCreateDylibForDynamicProducts { + if self.parameters.shouldCreateDylibForDynamicProducts { pifTargetProductName = "lib\(product.name).dylib" executableName = pifTargetProductName productType = .dynamicLibrary @@ -520,7 +526,7 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { // depend on. XCBuild will not produce a separate artifact for a package product, but will instead consider any // dependency on the package product to be a dependency on the whole set of targets on which the package product // depends. - let pifTarget = addTarget( + let pifTarget = self.addTarget( guid: product.pifTargetGUID, name: targetName(for: product), productType: productType, @@ -651,6 +657,8 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { settings[.SWIFT_OBJC_INTERFACE_HEADER_DIR] = "$(OBJROOT)/GeneratedModuleMaps/$(PLATFORM_NAME)" settings[.SWIFT_OBJC_INTERFACE_HEADER_NAME] = "\(target.name)-Swift.h" + settings.addCommonSwiftSettings(package: self.package, target: target, parameters: self.parameters) + moduleMapFileContents = """ module \(target.c99name) { header "\(target.name)-Swift.h" @@ -1663,6 +1671,22 @@ extension PIF.PlatformFilter { ] } +private extension PIF.BuildSettings { + mutating func addCommonSwiftSettings( + package: ResolvedPackage, + target: ResolvedTarget, + parameters: PIFBuilderParameters + ) { + let packageOptions = package.packageNameArgument( + target: target, + isPackageNameSupported: parameters.isPackageAccessModifierSupported + ) + if !packageOptions.isEmpty { + self[.OTHER_SWIFT_FLAGS] = packageOptions + } + } +} + private extension PIF.BuildSettings.Platform { static func from(platform: PackageModel.Platform) -> PIF.BuildSettings.Platform? { switch platform { diff --git a/Sources/XCBuildSupport/XcodeBuildSystem.swift b/Sources/XCBuildSupport/XcodeBuildSystem.swift index 8399a96e0c8..263027977f5 100644 --- a/Sources/XCBuildSupport/XcodeBuildSystem.swift +++ b/Sources/XCBuildSupport/XcodeBuildSystem.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2020 Apple Inc. and the Swift project authors +// Copyright (c) 2020-2024 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information @@ -16,6 +16,8 @@ import Dispatch import class Foundation.JSONEncoder import PackageGraph import PackageModel + +@_spi(SwiftPMInternal) import SPMBuildCore import protocol TSCBasic.OutputByteStream @@ -320,6 +322,7 @@ extension BuildConfiguration { extension PIFBuilderParameters { public init(_ buildParameters: BuildParameters) { self.init( + isPackageAccessModifierSupported: buildParameters.driverParameters.isPackageAccessModifierSupported, enableTestability: buildParameters.testingParameters.enableTestability, shouldCreateDylibForDynamicProducts: buildParameters.shouldCreateDylibForDynamicProducts, toolchainLibDir: (try? buildParameters.toolchain.toolchainLibDir) ?? .root, diff --git a/Sources/swift-bootstrap/CMakeLists.txt b/Sources/swift-bootstrap/CMakeLists.txt index 6371d1a01d4..e8cb9c4e879 100644 --- a/Sources/swift-bootstrap/CMakeLists.txt +++ b/Sources/swift-bootstrap/CMakeLists.txt @@ -15,6 +15,7 @@ target_link_libraries(swift-bootstrap PRIVATE PackageGraph PackageLoading PackageModel + SwiftDriver TSCBasic TSCUtility) diff --git a/Sources/swift-bootstrap/main.swift b/Sources/swift-bootstrap/main.swift index 6895b9c6b42..55f6b58e000 100644 --- a/Sources/swift-bootstrap/main.swift +++ b/Sources/swift-bootstrap/main.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2022 Apple Inc. and the Swift project authors +// Copyright (c) 2022-2024 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information @@ -14,6 +14,10 @@ import ArgumentParser import Basics import Build import Dispatch + +@_spi(SwiftPMInternal) +import DriverSupport + import Foundation import OrderedCollections import PackageGraph @@ -290,7 +294,11 @@ struct SwiftBootstrapBuildTool: ParsableCommand { isXcodeBuildSystemEnabled: buildSystem == .xcode, driverParameters: .init( explicitTargetDependencyImportCheckingMode: explicitTargetDependencyImportCheck == .error ? .error : .none, - useIntegratedSwiftDriver: useIntegratedSwiftDriver + useIntegratedSwiftDriver: useIntegratedSwiftDriver, + isPackageAccessModifierSupported: DriverSupport.isPackageNameSupported( + toolchain: targetToolchain, + fileSystem: self.fileSystem + ) ), linkingParameters: .init( shouldDisableLocalRpath: shouldDisableLocalRpath @@ -304,7 +312,6 @@ struct SwiftBootstrapBuildTool: ParsableCommand { let packageGraphLoader = { try self.loadPackageGraph(packagePath: packagePath, manifestLoader: manifestLoader) - } switch buildSystem { diff --git a/Tests/BuildTests/BuildPlanTests.swift b/Tests/BuildTests/BuildPlanTests.swift index 0ab7adc3bd6..e461ac1e93d 100644 --- a/Tests/BuildTests/BuildPlanTests.swift +++ b/Tests/BuildTests/BuildPlanTests.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2014-2021 Apple Inc. and the Swift project authors +// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information @@ -12,7 +12,11 @@ @testable import Basics @testable import Build + +@testable +@_spi(SwiftPMInternal) import DriverSupport + @testable import PackageGraph import PackageLoading @testable import PackageModel @@ -645,6 +649,37 @@ final class BuildPlanTests: XCTestCase { } } + #if os(macOS) + func testPackageNameFlagXCBuild() throws { + let isFlagSupportedInDriver = try DriverSupport.checkToolchainDriverFlags( + flags: ["package-name"], + toolchain: UserToolchain.default, + fileSystem: localFileSystem + ) + try fixture(name: "Miscellaneous/PackageNameFlag") { fixturePath in + let (stdout, _) = try executeSwiftBuild( + fixturePath.appending("appPkg"), + extraArgs: ["--build-system", "xcode", "-vv"] + ) + XCTAssertMatch(stdout, .contains("-module-name Foo")) + XCTAssertMatch(stdout, .contains("-module-name Zoo")) + XCTAssertMatch(stdout, .contains("-module-name Bar")) + XCTAssertMatch(stdout, .contains("-module-name Baz")) + XCTAssertMatch(stdout, .contains("-module-name App")) + XCTAssertMatch(stdout, .contains("-module-name exe")) + if isFlagSupportedInDriver { + XCTAssertMatch(stdout, .contains("-package-name apppkg")) + XCTAssertMatch(stdout, .contains("-package-name foopkg")) + // the flag is not supported if tools-version < 5.9 + XCTAssertNoMatch(stdout, .contains("-package-name barpkg")) + } else { + XCTAssertNoMatch(stdout, .contains("-package-name")) + } + XCTAssertMatch(stdout, .contains("Build succeeded")) + } + } + #endif + func testTargetsWithPackageAccess() throws { let isFlagSupportedInDriver = try DriverSupport.checkToolchainDriverFlags( flags: ["package-name"], diff --git a/Tests/CommandsTests/APIDiffTests.swift b/Tests/CommandsTests/APIDiffTests.swift index 7ab9a5fdd20..0f700957ac8 100644 --- a/Tests/CommandsTests/APIDiffTests.swift +++ b/Tests/CommandsTests/APIDiffTests.swift @@ -13,7 +13,10 @@ import Basics import Build import Commands + +@_spi(SwiftPMInternal) import DriverSupport + import Foundation import PackageModel import SourceControl diff --git a/Tests/XCBuildSupportTests/PIFBuilderTests.swift b/Tests/XCBuildSupportTests/PIFBuilderTests.swift index 79fc28be3b5..f1171d8c706 100644 --- a/Tests/XCBuildSupportTests/PIFBuilderTests.swift +++ b/Tests/XCBuildSupportTests/PIFBuilderTests.swift @@ -2218,7 +2218,7 @@ class PIFBuilderTests: XCTestCase { } } - func testBuildSettings() throws { + func buildSettingsTestCase(isPackageAccessModifierSupported: Bool) throws { #if !os(macOS) try XCTSkipIf(true, "test is only supported on macOS") #endif @@ -2228,6 +2228,8 @@ class PIFBuilderTests: XCTestCase { "/Foo/Sources/FooTests/FooTests.swift" ) + let toolsVersion: ToolsVersion = if isPackageAccessModifierSupported { .v5_9 } else { .v5 } + let mainTargetType: TargetDescription.TargetType = if toolsVersion >= .v5_9 { .executable } else { .regular } let observability = ObservabilitySystem.makeForTesting() let graph = try loadModulesGraph( fileSystem: fs, @@ -2235,28 +2237,32 @@ class PIFBuilderTests: XCTestCase { Manifest.createRootManifest( displayName: "Foo", path: "/Foo", - toolsVersion: .v5, + toolsVersion: toolsVersion, products: [ .init(name: "FooLib", type: .library(.automatic), targets: ["FooLib"]), ], targets: [ - .init(name: "foo", settings: [ - .init( - tool: .c, - kind: .define("ENABLE_BEST_MODE")), - .init( - tool: .cxx, - kind: .headerSearchPath("some/path"), - condition: .init(platformNames: ["macos"])), - .init( - tool: .linker, - kind: .linkedLibrary("z"), - condition: .init(config: "debug")), - .init( - tool: .swift, - kind: .unsafeFlags(["-secret", "value"]), - condition: .init(platformNames: ["macos", "linux"], config: "release")), - ]), + .init( + name: "foo", + type: mainTargetType, + settings: [ + .init( + tool: .c, + kind: .define("ENABLE_BEST_MODE")), + .init( + tool: .cxx, + kind: .headerSearchPath("some/path"), + condition: .init(platformNames: ["macos"])), + .init( + tool: .linker, + kind: .linkedLibrary("z"), + condition: .init(config: "debug")), + .init( + tool: .swift, + kind: .unsafeFlags(["-secret", "value"]), + condition: .init(platformNames: ["macos", "linux"], config: "release")), + ] + ), .init(name: "FooLib", settings: [ .init( tool: .c, @@ -2291,7 +2297,8 @@ class PIFBuilderTests: XCTestCase { kind: .unsafeFlags(["-secret", "value"]), condition: .init(platformNames: ["macos", "linux"], config: "release")), ]), - ]), + ] + ), ], shouldCreateMultipleTestProducts: true, observabilityScope: observability.topScope @@ -2299,7 +2306,7 @@ class PIFBuilderTests: XCTestCase { let builder = PIFBuilder( graph: graph, - parameters: .mock(), + parameters: .mock(isPackageAccessModifierSupported: isPackageAccessModifierSupported), fileSystem: fs, observabilityScope: observability.topScope ) @@ -2307,6 +2314,12 @@ class PIFBuilderTests: XCTestCase { XCTAssertNoDiagnostics(observability.diagnostics) + let packageNameOptions = if isPackageAccessModifierSupported { + ["-package-name", "foo"] + } else { + [String]?.none + } + try PIFTester(pif) { workspace in try workspace.checkProject("PACKAGE:/Foo") { project in project.checkTarget("PACKAGE-PRODUCT:foo") { target in @@ -2319,7 +2332,7 @@ class PIFBuilderTests: XCTestCase { "/Foo/Sources/foo/some/path" ]) XCTAssertEqual(settings[.OTHER_LDFLAGS], ["$(inherited)", "-lz"]) - XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], nil) + XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], packageNameOptions) } } @@ -2332,7 +2345,7 @@ class PIFBuilderTests: XCTestCase { "/Foo/Sources/foo/some/path" ]) XCTAssertEqual(settings[.OTHER_LDFLAGS], nil) - XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], nil) + XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], packageNameOptions) XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS, for: .macOS], ["$(inherited)", "-secret", "value"]) XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS, for: .linux], ["$(inherited)", "-secret", "value"]) } @@ -2371,7 +2384,7 @@ class PIFBuilderTests: XCTestCase { "/Foo/Sources/FooLib/some/path" ]) XCTAssertEqual(settings[.OTHER_LDFLAGS], ["$(inherited)", "-lz"]) - XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], nil) + XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], packageNameOptions) } } @@ -2384,7 +2397,7 @@ class PIFBuilderTests: XCTestCase { "/Foo/Sources/FooLib/some/path" ]) XCTAssertEqual(settings[.OTHER_LDFLAGS], nil) - XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], nil) + XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], packageNameOptions) XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS, for: .macOS], ["$(inherited)", "-secret", "value"]) XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS, for: .linux], ["$(inherited)", "-secret", "value"]) } @@ -2408,7 +2421,7 @@ class PIFBuilderTests: XCTestCase { "/Foo/Sources/FooTests/some/path" ]) XCTAssertEqual(settings[.OTHER_LDFLAGS], ["$(inherited)", "-lz"]) - XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], nil) + XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], packageNameOptions) } } @@ -2421,7 +2434,7 @@ class PIFBuilderTests: XCTestCase { "/Foo/Sources/FooTests/some/path" ]) XCTAssertEqual(settings[.OTHER_LDFLAGS], nil) - XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], nil) + XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS], packageNameOptions) XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS, for: .macOS], ["$(inherited)", "-secret", "value"]) XCTAssertEqual(settings[.OTHER_SWIFT_FLAGS, for: .linux], ["$(inherited)", "-secret", "value"]) } @@ -2431,6 +2444,14 @@ class PIFBuilderTests: XCTestCase { } } + func testBuildSettings() throws { + try buildSettingsTestCase(isPackageAccessModifierSupported: false) + } + + func testBuildSettingsPackageAccess() throws { + try buildSettingsTestCase(isPackageAccessModifierSupported: true) + } + func testConditionalDependencies() throws { #if !os(macOS) try XCTSkipIf(true, "test is only supported on macOS") @@ -2620,9 +2641,11 @@ class PIFBuilderTests: XCTestCase { extension PIFBuilderParameters { static func mock( + isPackageAccessModifierSupported: Bool = false, shouldCreateDylibForDynamicProducts: Bool = false ) -> Self { PIFBuilderParameters( + isPackageAccessModifierSupported: isPackageAccessModifierSupported, enableTestability: false, shouldCreateDylibForDynamicProducts: shouldCreateDylibForDynamicProducts, toolchainLibDir: "/toolchain/lib",