From 923ec97c0c8ad837eb59c23e1a4f84dd2a864b14 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Tue, 11 Mar 2025 13:05:41 -0700 Subject: [PATCH] [Explicit Module Builds] Add support for '-clang-target-variant' flag Adds equivalent functionality to that specified by '-clang-target' but for the zippered library variant on Darwin platforms. --- .../Toolchains/DarwinToolchain.swift | 17 ++++++++++++ Sources/SwiftOptions/Options.swift | 20 ++++++++++++-- Tests/SwiftDriverTests/SwiftDriverTests.swift | 26 +++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift b/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift index 79bce9cc2..697462037 100644 --- a/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift +++ b/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift @@ -453,6 +453,23 @@ public final class DarwinToolchain: Toolchain { commandLine.appendFlag(.clangTarget) commandLine.appendFlag(clangTargetTriple) + + // Repeat the above for the '-target-variant' flag + if driver.parsedOptions.contains(.targetVariant), + driver.isFrontendArgSupported(.clangTargetVariant), + let targetVariantTripleStr = frontendTargetInfo.targetVariant?.triple { + let clangTargetVariantTriple: String + if let explicitClangTargetVariantArg = driver.parsedOptions.getLastArgument(.clangTargetVariant)?.asSingle { + clangTargetVariantTriple = explicitClangTargetVariantArg + } else { + let currentVariantTriple = targetVariantTripleStr + let sdkVersionedOSSString = currentVariantTriple.osNameUnversioned + sdkInfo.sdkVersion(for: currentVariantTriple).sdkVersionString + clangTargetVariantTriple = currentVariantTriple.triple.replacingOccurrences(of: currentVariantTriple.osName, with: sdkVersionedOSSString) + } + + commandLine.appendFlag(.clangTargetVariant) + commandLine.appendFlag(clangTargetVariantTriple) + } } if driver.isFrontendArgSupported(.externalPluginPath) { diff --git a/Sources/SwiftOptions/Options.swift b/Sources/SwiftOptions/Options.swift index d2e0d17d0..4a9c393db 100644 --- a/Sources/SwiftOptions/Options.swift +++ b/Sources/SwiftOptions/Options.swift @@ -86,6 +86,7 @@ extension Option { public static let clangIncludeTreeFilelist: Option = Option("-clang-include-tree-filelist", .separate, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "", helpText: "Clang Include Tree FileList CASID") public static let clangIncludeTreeRoot: Option = Option("-clang-include-tree-root", .separate, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "", helpText: "Clang Include Tree CASID") public static let clangScannerModuleCachePath: Option = Option("-clang-scanner-module-cache-path", .separate, attributes: [.frontend, .doesNotAffectIncrementalBuild, .argumentIsPath], helpText: "Specifies the Clang dependency scanner module cache path") + public static let clangTargetVariant: Option = Option("-clang-target-variant", .separate, attributes: [.frontend, .synthesizeInterface], helpText: "Separately set the target we should use for internal Clang instance for the 'zippered' code for macCatalyst") public static let clangTarget: Option = Option("-clang-target", .separate, attributes: [.frontend, .synthesizeInterface], helpText: "Separately set the target we should use for internal Clang instance") public static let codeCompleteCallPatternHeuristics: Option = Option("-code-complete-call-pattern-heuristics", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Use heuristics to guess whether we want call pattern completions") public static let codeCompleteInitsInPostfixExpr: Option = Option("-code-complete-inits-in-postfix-expr", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Include initializers when completing a postfix expression") @@ -109,6 +110,7 @@ extension Option { public static let c: Option = Option("-c", .flag, alias: Option.emitObject, attributes: [.frontend, .noInteractive], group: .modes) public static let debugAssertAfterParse: Option = Option("-debug-assert-after-parse", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Force an assertion failure after parsing", group: .debugCrash) public static let debugAssertImmediately: Option = Option("-debug-assert-immediately", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Force an assertion failure immediately", group: .debugCrash) + public static let debugCallsiteInfo: Option = Option("-debug-callsite-info", .flag, attributes: [.frontend, .noDriver], helpText: "Generate callsite information in debug info") public static let debugConstraintsAttempt: Option = Option("-debug-constraints-attempt", .separate, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Debug the constraint solver at a given attempt") public static let debugConstraintsOnLineEQ: Option = Option("-debug-constraints-on-line=", .joined, alias: Option.debugConstraintsOnLine, attributes: [.helpHidden, .frontend, .noDriver]) public static let debugConstraintsOnLine: Option = Option("-debug-constraints-on-line", .separate, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "", helpText: "Debug the constraint solver for expressions on ") @@ -157,6 +159,7 @@ extension Option { public static let disableAliasModuleNamesInModuleInterface: Option = Option("-disable-alias-module-names-in-module-interface", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "When emitting a module interface, disable disambiguating modules using distinct alias names") public static let disableAllAutolinking: Option = Option("-disable-all-autolinking", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable all Swift autolink directives") public static let disableArcOpts: Option = Option("-disable-arc-opts", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Don't run SIL ARC optimization passes.") + public static let disableArm64Corocc: Option = Option("-disable-arm64-corocc", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Don't use swiftcorocc for yield_once_2 routines on arm64 variants.") public static let disableAstVerifier: Option = Option("-disable-ast-verifier", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Do not run the AST verifier during compilation. NOTE: This lets the user override the default behavior on whether or not the ASTVerifier is run. The default behavior is to run the verifier when asserts are enabled and not run it when asserts are disabled. NOTE: Can not be used if enable-ast-verifier is used as well") public static let disableAsyncFramePointerAll: Option = Option("-disable-async-frame-pointer-all", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable always emit async frame stack frames") public static let disableAsyncFramePushPopMetadata: Option = Option("-disable-async-frame-push-pop-metadata", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable async frame push pop metadata") @@ -272,6 +275,7 @@ extension Option { public static let disableTypoCorrection: Option = Option("-disable-typo-correction", .flag, attributes: [.frontend, .noDriver], helpText: "Disable typo correction") public static let disableUpcomingFeature: Option = Option("-disable-upcoming-feature", .separate, attributes: [.frontend, .moduleInterface], helpText: "Disable a feature that will be introduced in an upcoming language version") public static let disableVerifyExclusivity: Option = Option("-disable-verify-exclusivity", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable verification of access markers used to enforce exclusivity.") + public static let disableX8664Corocc: Option = Option("-disable-x86_64-corocc", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Don't use swiftcorocc for yield_once_2 routines on x86_64.") public static let disallowForwardingDriver: Option = Option("-disallow-use-new-driver", .flag, helpText: "Disable using new swift-driver") public static let downgradeTypecheckInterfaceError: Option = Option("-downgrade-typecheck-interface-error", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Downgrade error to warning when typechecking emitted module interfaces") public static let driverAlwaysRebuildDependents: Option = Option("-driver-always-rebuild-dependents", .flag, attributes: [.helpHidden, .doesNotAffectIncrementalBuild], helpText: "Always rebuild dependents of files that have been modified", group: .internalDebug) @@ -360,7 +364,7 @@ extension Option { public static let emitModuleSemanticInfoPath: Option = Option("-emit-module-semantic-info-path", .separate, attributes: [.frontend, .noDriver, .cacheInvariant], metaVar: "", helpText: "Output semantic info of current module to ") public static let emitModuleSeparatelyWMO: Option = Option("-emit-module-separately-wmo", .flag, attributes: [.helpHidden], helpText: "Emit module files as a distinct job in wmo builds") public static let emitModuleSerializeDiagnosticsPath: Option = Option("-emit-module-serialize-diagnostics-path", .separate, attributes: [.argumentIsPath, .supplementaryOutput], metaVar: "", helpText: "Emit a serialized diagnostics file for the emit-module task to ") - public static let emitModuleSourceInfoPath: Option = Option("-emit-module-source-info-path", .separate, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput], metaVar: "", helpText: "Output module source info file to ") + public static let emitModuleSourceInfoPath: Option = Option("-emit-module-source-info-path", .separate, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput, .cacheInvariant], metaVar: "", helpText: "Output module source info file to ") public static let emitModuleSourceInfo: Option = Option("-emit-module-source-info", .flag, attributes: [.frontend, .noDriver], helpText: "Output module source info file") public static let emitModuleSummaryPath: Option = Option("-emit-module-summary-path", .separate, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput, .cacheInvariant], metaVar: "", helpText: "Output module summary file to ") public static let emitModuleSummary: Option = Option("-emit-module-summary", .flag, attributes: [.noInteractive, .supplementaryOutput], helpText: "Output module summary file") @@ -382,6 +386,7 @@ extension Option { public static let emitSib: Option = Option("-emit-sib", .flag, attributes: [.frontend, .noInteractive, .doesNotAffectIncrementalBuild], helpText: "Emit serialized AST + canonical SIL file(s)", group: .modes) public static let emitSilgen: Option = Option("-emit-silgen", .flag, attributes: [.frontend, .noInteractive, .doesNotAffectIncrementalBuild], helpText: "Emit raw SIL file(s)", group: .modes) public static let emitSil: Option = Option("-emit-sil", .flag, attributes: [.frontend, .noInteractive, .doesNotAffectIncrementalBuild], helpText: "Emit canonical SIL file(s)", group: .modes) + public static let emitSingletonMetadataPointer: Option = Option("-emit-singleton-metadata-pointer", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Emit a pointer to the corresponding type metadata into non-public non-generic type descriptors.") public static let emitSortedSil: Option = Option("-emit-sorted-sil", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "When printing SIL, print out all sil entities sorted by name to ease diffing") public static let stackPromotionChecks: Option = Option("-emit-stack-promotion-checks", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Emit runtime checks for correct stack promotion of objects.") public static let emitSupportedFeatures: Option = Option("-emit-supported-features", .flag, attributes: [.frontend, .noInteractive, .doesNotAffectIncrementalBuild], helpText: "Emit a JSON file including all supported compiler features", group: .modes) @@ -395,7 +400,7 @@ extension Option { public static let emitVariantModuleDocPath: Option = Option("-emit-variant-module-doc-path", .separate, attributes: [.frontend, .noDriver, .cacheInvariant], metaVar: "", helpText: "Output module documentation file for the target variant to ") public static let emitVariantModuleInterfacePath: Option = Option("-emit-variant-module-interface-path", .separate, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput, .cacheInvariant], metaVar: "", helpText: "Output module interface file for the target variant to ") public static let emitVariantModulePath: Option = Option("-emit-variant-module-path", .separate, attributes: [.noInteractive, .argumentIsPath, .supplementaryOutput, .cacheInvariant], metaVar: "", helpText: "Emit an importable module for the target variant at the specified path") - public static let emitVariantModuleSourceInfoPath: Option = Option("-emit-variant-module-source-info-path", .separate, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput], metaVar: "", helpText: "Output module source info file for the target variant to ") + public static let emitVariantModuleSourceInfoPath: Option = Option("-emit-variant-module-source-info-path", .separate, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput, .cacheInvariant], metaVar: "", helpText: "Output module source info file for the target variant to ") public static let emitVariantPackageModuleInterfacePath: Option = Option("-emit-variant-package-module-interface-path", .separate, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput, .cacheInvariant], metaVar: "", helpText: "Output package module interface file for the target variant to ") public static let emitVariantPrivateModuleInterfacePath: Option = Option("-emit-variant-private-module-interface-path", .separate, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput, .cacheInvariant], metaVar: "", helpText: "Output private module interface file for the target variant to ") public static let emitVerboseSil: Option = Option("-emit-verbose-sil", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Emit locations during SIL emission") @@ -404,8 +409,10 @@ extension Option { public static let emptyBaseline_: Option = Option("--empty-baseline", .flag, alias: Option.emptyBaseline, attributes: [.noDriver], helpText: "Use empty baseline for diagnostics") public static let enableAccessControl: Option = Option("-enable-access-control", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Respect access control restrictions") public static let enableActorDataRaceChecks: Option = Option("-enable-actor-data-race-checks", .flag, attributes: [.frontend, .doesNotAffectIncrementalBuild], helpText: "Emit runtime checks for actor data races") + public static let enableAddressDependencies: Option = Option("-enable-address-dependencies", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable enforcement of lifetime dependencies on addressable values.") public static let enableAggressiveReg2mem: Option = Option("-enable-aggressive-reg2mem", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable a more aggressive reg2mem heuristic") public static let enableAnonymousContextMangledNames: Option = Option("-enable-anonymous-context-mangled-names", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable emission of mangled names in anonymous context descriptors") + public static let enableArm64Corocc: Option = Option("-enable-arm64-corocc", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Use swiftcorocc for yield_once_2 routines on arm64 variants.") public static let enableAstVerifier: Option = Option("-enable-ast-verifier", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Run the AST verifier during compilation. NOTE: This lets the user override the default behavior on whether or not the ASTVerifier is run. The default behavior is to run the verifier when asserts are enabled and not run it when asserts are disabled. NOTE: Can not be used if disable-ast-verifier is used as well") public static let enableAsyncFramePointerAll: Option = Option("-enable-async-frame-pointer-all", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Always emit async frame stack frames (frame-pointer=all)") public static let enableAsyncFramePushPopMetadata: Option = Option("-enable-async-frame-push-pop-metadata", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable async frame push pop metadata") @@ -504,6 +511,7 @@ extension Option { public static let enableUpcomingFeature: Option = Option("-enable-upcoming-feature", .separate, attributes: [.frontend, .moduleInterface], helpText: "Enable a feature that will be introduced in an upcoming language version") public static let enableVerifyExclusivity: Option = Option("-enable-verify-exclusivity", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable verification of access markers used to enforce exclusivity.") public static let enableVolatileModules: Option = Option("-enable-volatile-modules", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Load Swift modules in memory") + public static let enableX8664Corocc: Option = Option("-enable-x86_64-corocc", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Use swiftcorocc for yield_once_2 routines on x86_64.") public static let enforceExclusivityEQ: Option = Option("-enforce-exclusivity=", .joined, attributes: [.frontend, .moduleInterface], metaVar: "", helpText: "Enforce law of exclusivity") public static let entryPointFunctionName: Option = Option("-entry-point-function-name", .separate, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "", helpText: "Name of the entry point function") public static let errorOnAbiBreakage: Option = Option("-error-on-abi-breakage", .flag, attributes: [.noDriver], helpText: "Always treat ABI checker issues as errors") @@ -1021,6 +1029,7 @@ extension Option { Option.clangIncludeTreeFilelist, Option.clangIncludeTreeRoot, Option.clangScannerModuleCachePath, + Option.clangTargetVariant, Option.clangTarget, Option.codeCompleteCallPatternHeuristics, Option.codeCompleteInitsInPostfixExpr, @@ -1044,6 +1053,7 @@ extension Option { Option.c, Option.debugAssertAfterParse, Option.debugAssertImmediately, + Option.debugCallsiteInfo, Option.debugConstraintsAttempt, Option.debugConstraintsOnLineEQ, Option.debugConstraintsOnLine, @@ -1092,6 +1102,7 @@ extension Option { Option.disableAliasModuleNamesInModuleInterface, Option.disableAllAutolinking, Option.disableArcOpts, + Option.disableArm64Corocc, Option.disableAstVerifier, Option.disableAsyncFramePointerAll, Option.disableAsyncFramePushPopMetadata, @@ -1207,6 +1218,7 @@ extension Option { Option.disableTypoCorrection, Option.disableUpcomingFeature, Option.disableVerifyExclusivity, + Option.disableX8664Corocc, Option.disallowForwardingDriver, Option.downgradeTypecheckInterfaceError, Option.driverAlwaysRebuildDependents, @@ -1317,6 +1329,7 @@ extension Option { Option.emitSib, Option.emitSilgen, Option.emitSil, + Option.emitSingletonMetadataPointer, Option.emitSortedSil, Option.stackPromotionChecks, Option.emitSupportedFeatures, @@ -1339,8 +1352,10 @@ extension Option { Option.emptyBaseline_, Option.enableAccessControl, Option.enableActorDataRaceChecks, + Option.enableAddressDependencies, Option.enableAggressiveReg2mem, Option.enableAnonymousContextMangledNames, + Option.enableArm64Corocc, Option.enableAstVerifier, Option.enableAsyncFramePointerAll, Option.enableAsyncFramePushPopMetadata, @@ -1439,6 +1454,7 @@ extension Option { Option.enableUpcomingFeature, Option.enableVerifyExclusivity, Option.enableVolatileModules, + Option.enableX8664Corocc, Option.enforceExclusivityEQ, Option.entryPointFunctionName, Option.errorOnAbiBreakage, diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index 1ae33d985..f14bb7375 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -4346,6 +4346,32 @@ final class SwiftDriverTests: XCTestCase { job.commandLine.contains(.flag("-clang-target")) }) } + + // Check -clang-target-variant is handled correctly with the MacCatalyst remap. + try withTemporaryDirectory { path in + let main = path.appending(component: "Foo.swift") + try localFileSystem.writeFileContents(main, bytes: + """ + import Swift + """ + ) + var driver = try Driver(args: ["swiftc", "-explicit-module-build", + "-target", "arm64e-apple-ios13.0-macabi", + "-target-variant", "arm64e-apple-macos10.0", + "-sdk", sdkRoot.pathString, + main.pathString]) + guard driver.isFrontendArgSupported(.clangTarget) else { + throw XCTSkip("Skipping: compiler does not support '-clang-target'") + } + guard driver.isFrontendArgSupported(.clangTargetVariant) else { + throw XCTSkip("Skipping: compiler does not support '-clang-target-variant'") + } + let plannedJobs = try driver.planBuild() + XCTAssertTrue(plannedJobs.contains { job in + job.commandLine.contains(subsequence: [.flag("-clang-target"), .flag("arm64e-apple-ios13.3-macabi")]) && + job.commandLine.contains(subsequence: [.flag("-clang-target-variant"), .flag("arm64e-apple-macos10.15")]) + }) + } #endif }