Skip to content

[clang][darwin] Add support for the -mtargetos= option to the driver #3133

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -3193,6 +3193,8 @@ def meabi : Separate<["-"], "meabi">, Group<m_Group>, Flags<[CC1Option]>,
MarshallingInfoEnum<TargetOpts<"EABIVersion">, "Default">,
NormalizedValuesScope<"llvm::EABI">,
NormalizedValues<["Default", "EABI4", "EABI5", "GNU"]>;
def mtargetos_EQ : Joined<["-"], "mtargetos=">, Group<m_Group>,
HelpText<"Set the deployment target to be the specified OS and OS version">;

def mno_constant_cfstrings : Flag<["-"], "mno-constant-cfstrings">, Group<m_Group>;
def mno_global_merge : Flag<["-"], "mno-global-merge">, Group<m_Group>, Flags<[CC1Option]>,
Expand Down
108 changes: 89 additions & 19 deletions clang/lib/Driver/ToolChains/Darwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1418,6 +1418,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<os>-version-min argument.
OSVersionArg,
/// The OS was specified using the OS_DEPLOYMENT_TARGET environment.
Expand Down Expand Up @@ -1469,7 +1471,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:
Expand All @@ -1494,6 +1497,7 @@ struct DarwinPlatform {
std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {
switch (Kind) {
case TargetArg:
case MTargetOSArg:
case OSVersionArg:
case InferredFromSDK:
case InferredFromArch:
Expand All @@ -1505,40 +1509,54 @@ struct DarwinPlatform {
llvm_unreachable("Unsupported Darwin Source Kind");
}

static DarwinPlatform
createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
const Optional<DarwinSDKInfo> &SDKInfo) {
DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
A);
unsigned Major, Minor, Micro;
TT.getOSVersion(Major, Minor, Micro);
if (Major == 0)
Result.HasOSVersion = false;

switch (TT.getEnvironment()) {
void setEnvironment(llvm::Triple::EnvironmentType EnvType,
const VersionTuple &OSVersion,
const Optional<DarwinSDKInfo> &SDKInfo) {
switch (EnvType) {
case llvm::Triple::Simulator:
Result.Environment = DarwinEnvironmentKind::Simulator;
Environment = DarwinEnvironmentKind::Simulator;
break;
case llvm::Triple::MacABI: {
Environment = DarwinEnvironmentKind::MacCatalyst;
// The minimum native macOS target for MacCatalyst is macOS 10.15.
auto NativeTargetVersion = VersionTuple(10, 15);
if (Result.HasOSVersion && SDKInfo) {
NativeTargetVersion = VersionTuple(10, 15);
if (HasOSVersion && SDKInfo) {
if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping(
DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {
if (auto MacOSVersion = MacCatalystToMacOSMapping->map(
VersionTuple(Major, Minor, Micro), NativeTargetVersion,
None)) {
OSVersion, NativeTargetVersion, None)) {
NativeTargetVersion = *MacOSVersion;
}
}
}
Result.Environment = DarwinEnvironmentKind::MacCatalyst;
Result.NativeTargetVersion = NativeTargetVersion;
break;
}
default:
break;
}
}

static DarwinPlatform
createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
const Optional<DarwinSDKInfo> &SDKInfo) {
DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
A);
unsigned Major, Minor, Micro;
TT.getOSVersion(Major, Minor, Micro);
if (Major == 0)
Result.HasOSVersion = false;
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<DarwinSDKInfo> &SDKInfo) {
DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS),
OSVersion.getAsString(), A);
Result.InferSimulatorFromArch = false;
Result.setEnvironment(Environment, OSVersion, SDKInfo);
return Result;
}
static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform,
Expand Down Expand Up @@ -1852,6 +1870,39 @@ Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
Triple, OSVersion, Args.getLastArg(options::OPT_target), SDKInfo);
}

/// Returns the deployment target that's specified using the -mtargetos option.
Optional<DarwinPlatform>
getDeploymentTargetFromMTargetOSArg(DerivedArgList &Args,
const Driver &TheDriver,
const Optional<DarwinSDKInfo> &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<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
const ArgList &Args,
const Driver &TheDriver) {
Expand Down Expand Up @@ -1900,6 +1951,13 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
Optional<DarwinPlatform> 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<DarwinPlatform> OSVersionArgTarget =
getDeploymentTargetFromOSVersionArg(Args, getDriver());
if (OSVersionArgTarget) {
Expand Down Expand Up @@ -1931,6 +1989,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 -m<os>version-min=.
Optional<DarwinPlatform> 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 -m<os>version-min argument.
OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());
Expand Down
26 changes: 26 additions & 0 deletions clang/test/Driver/mtargetos-darwin.c
Original file line number Diff line number Diff line change
@@ -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'