From f575f371822f6a07483b21701165492224a846bb Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 2 Aug 2021 12:43:54 -0700 Subject: [PATCH] [clang][darwin] Add support for the -mtargetos= option to the driver The new -mtargetos= option is a replacement for the existing, OS-specific options like -miphoneos-version-min=. This allows us to introduce support for new darwin OSes easier as they won't require the use of a new option. The older options will be deprecated and the use of the new option will be encouraged instead. Differential Revision: https://reviews.llvm.org/D106316 --- .../clang/Basic/DiagnosticDriverKinds.td | 1 + clang/include/clang/Driver/Options.td | 2 + clang/lib/Driver/ToolChains/Darwin.cpp | 122 ++++++++++++++---- clang/test/Driver/mtargetos-darwin.c | 26 ++++ 4 files changed, 125 insertions(+), 26 deletions(-) create mode 100644 clang/test/Driver/mtargetos-darwin.c diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 3b4daa59f66b..d27b83ecbe77 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -235,6 +235,7 @@ def warn_invalid_ios_deployment_target : Warning< DefaultError; def err_invalid_macos_32bit_deployment_target : Error< "32-bit targets are not supported when building for Mac Catalyst">; +def err_drv_invalid_os_in_arg : Error<"invalid OS value '%0' in '%1'">; def err_drv_conflicting_deployment_targets : Error< "conflicting deployment targets, both '%0' and '%1' are present in environment">; def err_arc_unsupported_on_runtime : Error< diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 34442060e277..8c562a6c0612 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3144,6 +3144,8 @@ def meabi : Separate<["-"], "meabi">, Group, Flags<[CC1Option]>, MarshallingInfoEnum, "Default">, NormalizedValuesScope<"llvm::EABI">, NormalizedValues<["Default", "EABI4", "EABI5", "GNU"]>; +def mtargetos_EQ : Joined<["-"], "mtargetos=">, Group, + HelpText<"Set the deployment target to be the specified OS and OS version">; def mno_constant_cfstrings : Flag<["-"], "mno-constant-cfstrings">, Group; def mno_global_merge : Flag<["-"], "mno-global-merge">, Group, Flags<[CC1Option]>, diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 261f522f6c49..f610bc2a781a 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1379,6 +1379,8 @@ struct DarwinPlatform { enum SourceKind { /// The OS was specified using the -target argument. TargetArg, + /// The OS was specified using the -mtargetos= argument. + MTargetOSArg, /// The OS was specified using the -m-version-min argument. OSVersionArg, /// The OS was specified using the OS_DEPLOYMENT_TARGET environment. @@ -1430,7 +1432,8 @@ struct DarwinPlatform { void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) { if (Argument) return; - assert(Kind != TargetArg && Kind != OSVersionArg && "Invalid kind"); + assert(Kind != TargetArg && Kind != MTargetOSArg && Kind != OSVersionArg && + "Invalid kind"); options::ID Opt; switch (Platform) { case DarwinPlatformKind::MacOS: @@ -1455,6 +1458,7 @@ struct DarwinPlatform { std::string getAsString(DerivedArgList &Args, const OptTable &Opts) { switch (Kind) { case TargetArg: + case MTargetOSArg: case OSVersionArg: case InferredFromSDK: case InferredFromArch: @@ -1466,6 +1470,33 @@ struct DarwinPlatform { llvm_unreachable("Unsupported Darwin Source Kind"); } + void setEnvironment(llvm::Triple::EnvironmentType EnvType, + const VersionTuple &OSVersion, + const Optional &SDKInfo) { + switch (EnvType) { + case llvm::Triple::Simulator: + Environment = DarwinEnvironmentKind::Simulator; + break; + case llvm::Triple::MacABI: { + Environment = DarwinEnvironmentKind::MacCatalyst; + // The minimum native macOS target for MacCatalyst is macOS 10.15. + NativeTargetVersion = VersionTuple(10, 15); + if (HasOSVersion && SDKInfo) { + if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping( + DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) { + if (auto MacOSVersion = MacCatalystToMacOSMapping->map( + OSVersion, NativeTargetVersion, None)) { + NativeTargetVersion = *MacOSVersion; + } + } + } + break; + } + default: + break; + } + } + static DarwinPlatform createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A, const Optional &SDKInfo) { @@ -1475,31 +1506,18 @@ struct DarwinPlatform { TT.getOSVersion(Major, Minor, Micro); if (Major == 0) Result.HasOSVersion = false; - - switch (TT.getEnvironment()) { - case llvm::Triple::Simulator: - Result.Environment = DarwinEnvironmentKind::Simulator; - break; - case llvm::Triple::MacABI: { - // The minimum native macOS target for MacCatalyst is macOS 10.15. - auto NativeTargetVersion = VersionTuple(10, 15); - if (Result.HasOSVersion && SDKInfo) { - if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping( - DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) { - if (auto MacOSVersion = MacCatalystToMacOSMapping->map( - VersionTuple(Major, Minor, Micro), NativeTargetVersion, - None)) { - NativeTargetVersion = *MacOSVersion; - } - } - } - Result.Environment = DarwinEnvironmentKind::MacCatalyst; - Result.NativeTargetVersion = NativeTargetVersion; - break; - } - default: - break; - } + Result.setEnvironment(TT.getEnvironment(), + VersionTuple(Major, Minor, Micro), SDKInfo); + return Result; + } + static DarwinPlatform + createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion, + llvm::Triple::EnvironmentType Environment, Arg *A, + const Optional &SDKInfo) { + DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS), + OSVersion.getAsString(), A); + Result.InferSimulatorFromArch = false; + Result.setEnvironment(Environment, OSVersion, SDKInfo); return Result; } static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform, @@ -1813,6 +1831,39 @@ Optional getDeploymentTargetFromTargetArg( Triple, OSVersion, Args.getLastArg(options::OPT_target), SDKInfo); } +/// Returns the deployment target that's specified using the -mtargetos option. +Optional +getDeploymentTargetFromMTargetOSArg(DerivedArgList &Args, + const Driver &TheDriver, + const Optional &SDKInfo) { + auto *A = Args.getLastArg(options::OPT_mtargetos_EQ); + if (!A) + return None; + llvm::Triple TT(llvm::Twine("unknown-apple-") + A->getValue()); + switch (TT.getOS()) { + case llvm::Triple::MacOSX: + case llvm::Triple::IOS: + case llvm::Triple::TvOS: + case llvm::Triple::WatchOS: + break; + default: + TheDriver.Diag(diag::err_drv_invalid_os_in_arg) + << TT.getOSName() << A->getAsString(Args); + return None; + } + + unsigned Major, Minor, Micro; + TT.getOSVersion(Major, Minor, Micro); + if (!Major) { + TheDriver.Diag(diag::err_drv_invalid_version_number) + << A->getAsString(Args); + return None; + } + return DarwinPlatform::createFromMTargetOS(TT.getOS(), + VersionTuple(Major, Minor, Micro), + TT.getEnvironment(), A, SDKInfo); +} + Optional parseSDKSettings(llvm::vfs::FileSystem &VFS, const ArgList &Args, const Driver &TheDriver) { @@ -1861,6 +1912,13 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { Optional OSTarget = getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo); if (OSTarget) { + // Disallow mixing -target and -mtargetos=. + if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) { + std::string TargetArgStr = OSTarget->getAsString(Args, Opts); + std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args); + getDriver().Diag(diag::err_drv_cannot_mix_options) + << TargetArgStr << MTargetOSArgStr; + } Optional OSVersionArgTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver()); if (OSVersionArgTarget) { @@ -1892,6 +1950,18 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { } } } + } else if ((OSTarget = getDeploymentTargetFromMTargetOSArg(Args, getDriver(), + SDKInfo))) { + // The OS target can be specified using the -mtargetos= argument. + // Disallow mixing -mtargetos= and -mversion-min=. + Optional OSVersionArgTarget = + getDeploymentTargetFromOSVersionArg(Args, getDriver()); + if (OSVersionArgTarget) { + std::string MTargetOSArgStr = OSTarget->getAsString(Args, Opts); + std::string OSVersionArgStr = OSVersionArgTarget->getAsString(Args, Opts); + getDriver().Diag(diag::err_drv_cannot_mix_options) + << MTargetOSArgStr << OSVersionArgStr; + } } else { // The OS target can be specified using the -mversion-min argument. OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver()); diff --git a/clang/test/Driver/mtargetos-darwin.c b/clang/test/Driver/mtargetos-darwin.c new file mode 100644 index 000000000000..5acce1a2c1cf --- /dev/null +++ b/clang/test/Driver/mtargetos-darwin.c @@ -0,0 +1,26 @@ +// RUN: %clang -mtargetos=macos11 -arch arm64 -arch x86_64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=MACOS %s +// RUN: %clang -mtargetos=ios14 -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=IOS %s +// RUN: %clang -mtargetos=ios14-simulator -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=IOS_SIM %s +// RUN: %clang -mtargetos=ios14-macabi -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=MACCATALYST %s +// RUN: %clang -mtargetos=tvos14 -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=TVOS %s +// RUN: %clang -mtargetos=watchos7.1 -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=WATCHOS %s + +// RUN: %clang -target arm64-apple-ios14 -mtargetos=ios14 -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=NOMIX1 %s +// RUN: %clang -mtargetos=ios14 -arch arm64 -miphoneos-version-min=14 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=NOMIX2 %s +// RUN: %clang -mtargetos=darwin20 -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=INVALIDOS %s +// RUN: %clang -mtargetos=ios -arch arm64 -c %s -o %t.o -### 2>&1 | FileCheck --check-prefix=NOVERSION %s + +// REQUIRES: darwin + +// MACOS: "-cc1" "-triple" "arm64-apple-macosx11.0.0" +// MACOS-NEXT: "-cc1" "-triple" "x86_64-apple-macosx11.0.0" +// IOS: "-cc1" "-triple" "arm64-apple-ios14.0.0" +// IOS_SIM: "-cc1" "-triple" "arm64-apple-ios14.0.0-simulator" +// MACCATALYST: "-cc1" "-triple" "arm64-apple-ios14.0.0-macabi" +// TVOS: "-cc1" "-triple" "arm64-apple-tvos14.0.0" +// WATCHOS: "-cc1" "-triple" "arm64-apple-watchos7.1.0" + +// NOMIX1: error: cannot specify '-mtargetos=ios14' along with '-target arm64-apple-ios14' +// NOMIX2: error: cannot specify '-miphoneos-version-min=14' along with '-mtargetos=ios14' +// INVALIDOS: error: invalid OS value 'darwin20' in '-mtargetos=darwin20' +// NOVERSION: error: invalid version number in '-mtargetos=ios'