Skip to content

Commit 655d89b

Browse files
committed
[Driver/Frontend] Add Driver support for macCatalyst and library search paths
Add support in the driver and frontend for macCatalyst target targets and library search paths. The compiler now adds two library search paths for overlays when compiling for macCatalyst: one for macCatalyst libraries and one for zippered macOS libraries. The macCatalyst path must take priority over the normal macOS path so that in the case of 'unzippered twins' the macCatalyst library is found instead of the macOS library. To support 'zippered' builds, also add support for a new -target-variant flag. For zippered libraries, the driver invocation takes both a -target and a -target-variant flag passes them along to the frontend. We support builds both when the target is a macOS triple and the target variant is macCatalyst and also the 'reverse zippered' configuration where the target is macCatalyst and the target-variant is macOS.
1 parent 89e381c commit 655d89b

File tree

13 files changed

+290
-12
lines changed

13 files changed

+290
-12
lines changed

include/swift/AST/DiagnosticsDriver.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ ERROR(error_sdk_too_old,none,
117117
ERROR(error_ios_maximum_deployment_32,none,
118118
"iOS %0 does not support 32-bit programs", (unsigned))
119119

120+
ERROR(error_unsupported_target_variant,none,
121+
"unsupported '%select{-target|-target-variant}1' value '%0'; use 'ios-macabi' instead",
122+
(StringRef, bool))
123+
120124
WARNING(warn_arclite_not_found_when_link_objc_runtime,none,
121125
"unable to find Objective-C runtime support library 'arclite'; "
122126
"pass '-no-link-objc-runtime' to silence this warning", ())

include/swift/Basic/LangOptions.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@ namespace swift {
6464
/// This represents the minimum deployment target.
6565
llvm::Triple Target;
6666

67+
/// \brief The second target for a zippered build
68+
///
69+
/// This represents the target and minimum deployment version for the
70+
/// second ('variant') target when performing a zippered build.
71+
/// For example, if the target is x86_64-apple-macosx10.14 then
72+
/// a target-variant of x86_64-apple-ios12.0-macabi will produce
73+
/// a zippered binary that can be loaded into both macCatalyst and
74+
/// macOS processes. A value of 'None' means no zippering will be
75+
/// performed.
76+
llvm::Optional<llvm::Triple> TargetVariant;
77+
6778
///
6879
/// Language features
6980
///

include/swift/Basic/Platform.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ namespace swift {
4646
/// Return true if the given triple represents any simulator.
4747
bool tripleIsAnySimulator(const llvm::Triple &triple);
4848

49+
/// Returns true if the given triple represents a macCatalyst environment.
50+
bool tripleIsMacCatalystEnvironment(const llvm::Triple &triple);
51+
52+
/// Returns true if the given -target triple and -target-variant triple
53+
/// can be zippered.
54+
bool triplesAreValidForZippering(const llvm::Triple &target,
55+
const llvm::Triple &targetVariant);
56+
4957
/// Returns true if the given triple represents an OS that ships with
5058
/// ABI-stable swift libraries (eg. in /usr/lib/swift).
5159
bool tripleRequiresRPathForSwiftInOS(const llvm::Triple &triple);

include/swift/Driver/ToolChain.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ class ToolChain {
201201
void getResourceDirPath(SmallVectorImpl<char> &runtimeLibPath,
202202
const llvm::opt::ArgList &args, bool shared) const;
203203

204+
/// Get the secondary runtime library link path given the primary path.
205+
void getSecondaryResourceDirPath(
206+
SmallVectorImpl<char> &secondaryResourceDirPath,
207+
StringRef primaryPath) const;
208+
204209
/// Get the runtime library link paths, which typically include the resource
205210
/// dir path and the SDK.
206211
void getRuntimeLibraryPaths(SmallVectorImpl<std::string> &runtimeLibPaths,
@@ -310,7 +315,8 @@ class ToolChain {
310315
/// An override point for platform-specific subclasses to customize the
311316
/// validations that should be performed.
312317
virtual void validateArguments(DiagnosticEngine &diags,
313-
const llvm::opt::ArgList &args) const {}
318+
const llvm::opt::ArgList &args,
319+
StringRef defaultTarget) const {}
314320
};
315321
} // end namespace driver
316322
} // end namespace swift

include/swift/Option/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,11 @@ def print_target_info : Flag<["-"], "print-target-info">,
919919
def target_cpu : Separate<["-"], "target-cpu">, Flags<[FrontendOption, ModuleInterfaceOption]>,
920920
HelpText<"Generate code for a particular CPU variant">;
921921

922+
def target_variant : Separate<["-"], "target-variant">,
923+
Flags<[FrontendOption]>,
924+
HelpText<"Generate 'zippered' code for macCatalyst that can run on the specified"
925+
" variant target triple in addition to the main -target triple">;
926+
922927
def profile_generate : Flag<["-"], "profile-generate">,
923928
Flags<[FrontendOption, NoInteractiveOption]>,
924929
HelpText<"Generate instrumented code to collect execution counts">;

lib/Basic/Platform.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ using namespace swift;
2121
bool swift::tripleIsiOSSimulator(const llvm::Triple &triple) {
2222
llvm::Triple::ArchType arch = triple.getArch();
2323
return (triple.isiOS() &&
24+
!tripleIsMacCatalystEnvironment(triple) &&
2425
// FIXME: transitional, this should eventually stop testing arch, and
2526
// switch to only checking the -environment field.
2627
(triple.isSimulatorEnvironment() ||
@@ -54,6 +55,38 @@ bool swift::tripleIsAnySimulator(const llvm::Triple &triple) {
5455
tripleIsAppleTVSimulator(triple);
5556
}
5657

58+
bool swift::tripleIsMacCatalystEnvironment(const llvm::Triple &triple) {
59+
return triple.isiOS() && !triple.isTvOS() &&
60+
triple.getEnvironment() == llvm::Triple::MacABI;
61+
}
62+
63+
bool swift::triplesAreValidForZippering(const llvm::Triple &target,
64+
const llvm::Triple &targetVariant) {
65+
// The arch and vendor must match.
66+
if (target.getArchName() != targetVariant.getArchName() ||
67+
target.getArch() != targetVariant.getArch() ||
68+
target.getSubArch() != targetVariant.getSubArch() ||
69+
target.getVendor() != targetVariant.getVendor()) {
70+
return false;
71+
}
72+
73+
// Allow a macOS target and an iOS-macabi target variant
74+
// This is typically the case when zippering a library originally
75+
// developed for macOS.
76+
if (target.isMacOSX() && tripleIsMacCatalystEnvironment(targetVariant)) {
77+
return true;
78+
}
79+
80+
// Allow an iOS-macabi target and a macOS target variant. This would
81+
// be the case when zippering a library originally developed for
82+
// iOS.
83+
if (targetVariant.isMacOSX() && tripleIsMacCatalystEnvironment(target)) {
84+
return true;
85+
}
86+
87+
return false;
88+
}
89+
5790
bool swift::tripleRequiresRPathForSwiftInOS(const llvm::Triple &triple) {
5891
if (triple.isMacOSX()) {
5992
// macOS 10.14.4 contains a copy of Swift, but the linker will still use an
@@ -304,6 +337,7 @@ getEnvironmentForAppleTargetSpecificModuleTriple(const llvm::Triple &triple) {
304337
.Cases("unknown", "", None)
305338
// These values are also supported, but are handled by the default case below:
306339
// .Case ("simulator", StringRef("simulator"))
340+
// .Case ("macabi", StringRef("macabi"))
307341
.Default(tripleEnvironment);
308342
}
309343

lib/Driver/DarwinToolChains.cpp

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ getDarwinLibraryNameSuffixForTriple(const llvm::Triple &triple,
9696
case DarwinPlatformKind::MacOS:
9797
return "osx";
9898
case DarwinPlatformKind::IPhoneOS:
99+
// Here we return "osx" under the assumption that all the
100+
// darwin runtime libraries are zippered and so the "osx" variants
101+
// should be used for macCatalyst targets.
102+
if (tripleIsMacCatalystEnvironment(triple))
103+
return "osx";
99104
return "ios";
100105
case DarwinPlatformKind::IPhoneOSSimulator:
101106
return "iossim";
@@ -431,6 +436,9 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments,
431436
// package isn't installed.
432437
Arguments.push_back("-rpath");
433438
Arguments.push_back(context.Args.MakeArgString("/usr/lib/swift"));
439+
// We don't need an rpath for /System/iOSSupport/usr/lib/swift because...
440+
assert(!tripleIsMacCatalystEnvironment(getTriple())
441+
&& "macCatalyst not supported without Swift-in-the-OS");
434442
}
435443
}
436444

@@ -489,12 +497,23 @@ toolchains::Darwin::addDeploymentTargetArgs(ArgStringList &Arguments,
489497
} else {
490498
if (isiOSSimulator)
491499
Arguments.push_back("-ios_simulator_version_min");
500+
else if (tripleIsMacCatalystEnvironment(Triple))
501+
Arguments.push_back("-maccatalyst_version_min");
492502
else
493503
Arguments.push_back("-iphoneos_version_min");
494504
}
495505
unsigned major, minor, micro;
496506
Triple.getiOSVersion(major, minor, micro);
497507
addVersionString(context.Args, Arguments, major, minor, micro);
508+
509+
if (TargetVariant) {
510+
assert(triplesAreValidForZippering(Triple, *TargetVariant));
511+
assert(TargetVariant->isMacOSX());
512+
Arguments.push_back("-macosx_version_min");
513+
unsigned major, minor, micro;
514+
TargetVariant->getMacOSXVersion(major, minor, micro);
515+
addVersionString(context.Args, Arguments, major, minor, micro);
516+
}
498517
} else if (Triple.isWatchOS()) {
499518
if (tripleIsWatchSimulator(Triple))
500519
Arguments.push_back("-watchos_simulator_version_min");
@@ -508,6 +527,15 @@ toolchains::Darwin::addDeploymentTargetArgs(ArgStringList &Arguments,
508527
unsigned major, minor, micro;
509528
Triple.getMacOSXVersion(major, minor, micro);
510529
addVersionString(context.Args, Arguments, major, minor, micro);
530+
531+
if (TargetVariant) {
532+
assert(triplesAreValidForZippering(Triple, *TargetVariant));
533+
assert(tripleIsMacCatalystEnvironment(*TargetVariant));
534+
Arguments.push_back("-maccatalyst_version_min");
535+
unsigned major, minor, micro;
536+
TargetVariant->getiOSVersion(major, minor, micro);
537+
addVersionString(context.Args, Arguments, major, minor, micro);
538+
}
511539
}
512540
}
513541

@@ -718,15 +746,33 @@ static void validateDeploymentTarget(const toolchains::Darwin &TC,
718746
}
719747
}
720748

749+
static void validateTargetVariant(const toolchains::Darwin &TC,
750+
DiagnosticEngine &diags,
751+
const llvm::opt::ArgList &args,
752+
StringRef defaultTarget) {
753+
if (TC.getTargetVariant().hasValue()) {
754+
auto target = TC.getTriple();
755+
auto variant = *TC.getTargetVariant();
756+
757+
if (!triplesAreValidForZippering(target, variant)) {
758+
diags.diagnose(SourceLoc(), diag::error_unsupported_target_variant,
759+
variant.str(),
760+
variant.isiOS());
761+
}
762+
}
763+
}
764+
721765
void
722766
toolchains::Darwin::validateArguments(DiagnosticEngine &diags,
723-
const llvm::opt::ArgList &args) const {
767+
const llvm::opt::ArgList &args,
768+
StringRef defaultTarget) const {
724769
// Validating arclite library path when link-objc-runtime.
725770
validateLinkObjcRuntimeARCLiteLib(*this, diags, args);
726771

727772
// Validating apple platforms deployment targets.
728773
validateDeploymentTarget(*this, diags, args);
729-
774+
validateTargetVariant(*this, diags, args, defaultTarget);
775+
730776
// Validating darwin unsupported -static-stdlib argument.
731777
if (args.hasArg(options::OPT_static_stdlib)) {
732778
diags.diagnose(SourceLoc(), diag::error_darwin_static_stdlib_not_supported);

lib/Driver/Driver.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/AST/DiagnosticsFrontend.h"
2323
#include "swift/Basic/LLVM.h"
2424
#include "swift/Basic/OutputFileMap.h"
25+
#include "swift/Basic/Platform.h"
2526
#include "swift/Basic/Range.h"
2627
#include "swift/Basic/Statistic.h"
2728
#include "swift/Basic/TaskQueue.h"
@@ -252,8 +253,13 @@ Driver::buildToolChain(const llvm::opt::InputArgList &ArgList) {
252253
case llvm::Triple::MacOSX:
253254
case llvm::Triple::IOS:
254255
case llvm::Triple::TvOS:
255-
case llvm::Triple::WatchOS:
256-
return llvm::make_unique<toolchains::Darwin>(*this, target);
256+
case llvm::Triple::WatchOS: {
257+
Optional<llvm::Triple> targetVariant;
258+
if (const Arg *A = ArgList.getLastArg(options::OPT_target_variant))
259+
targetVariant = llvm::Triple(llvm::Triple::normalize(A->getValue()));
260+
261+
return llvm::make_unique<toolchains::Darwin>(*this, target, targetVariant);
262+
}
257263
case llvm::Triple::Linux:
258264
if (target.isAndroid())
259265
return llvm::make_unique<toolchains::Android>(*this, target);
@@ -824,7 +830,7 @@ Driver::buildCompilation(const ToolChain &TC,
824830
validateArgs(Diags, *TranslatedArgList, TC.getTriple());
825831

826832
// Perform toolchain specific args validation.
827-
TC.validateArguments(Diags, *TranslatedArgList);
833+
TC.validateArguments(Diags, *TranslatedArgList, DefaultTargetTriple);
828834

829835
if (Diags.hadAnyError())
830836
return nullptr;

lib/Driver/ToolChains.cpp

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@ static void addCommonFrontendArgs(const ToolChain &TC, const OutputInfo &OI,
151151
break;
152152
}
153153

154+
if (const Arg *variant = inputArgs.getLastArg(options::OPT_target_variant)) {
155+
arguments.push_back("-target-variant");
156+
std::string normalized = llvm::Triple::normalize(variant->getValue());
157+
arguments.push_back(inputArgs.MakeArgString(normalized));
158+
}
159+
154160
// Enable address top-byte ignored in the ARM64 backend.
155161
if (Triple.getArch() == llvm::Triple::aarch64) {
156162
arguments.push_back("-Xllvm");
@@ -1223,8 +1229,28 @@ void ToolChain::getResourceDirPath(SmallVectorImpl<char> &resourceDirPath,
12231229
llvm::sys::path::append(resourceDirPath, "lib",
12241230
shared ? "swift" : "swift_static");
12251231
}
1226-
llvm::sys::path::append(resourceDirPath,
1227-
getPlatformNameForTriple(getTriple()));
1232+
1233+
StringRef libSubDir = getPlatformNameForTriple(getTriple());
1234+
if (tripleIsMacCatalystEnvironment(getTriple()))
1235+
libSubDir = "maccatalyst";
1236+
llvm::sys::path::append(resourceDirPath, libSubDir);
1237+
}
1238+
1239+
// Get the secondary runtime library link path given the primary path.
1240+
// The compiler will look for runtime libraries in the secondary path if they
1241+
// can't be found in the primary path.
1242+
void ToolChain::getSecondaryResourceDirPath(
1243+
SmallVectorImpl<char> &secondaryResourceDirPath,
1244+
StringRef primaryPath) const {
1245+
if (!tripleIsMacCatalystEnvironment(getTriple()))
1246+
return;
1247+
1248+
// For macCatalyst, the secondary runtime library path is the macOS library
1249+
// path. The compiler will find zippered libraries here.
1250+
secondaryResourceDirPath.append(primaryPath.begin(), primaryPath.end());
1251+
// Remove '/maccatalyst' and replace with 'macosx'.
1252+
llvm::sys::path::remove_filename(secondaryResourceDirPath);
1253+
llvm::sys::path::append(secondaryResourceDirPath, "macosx");
12281254
}
12291255

12301256
void ToolChain::getRuntimeLibraryPaths(SmallVectorImpl<std::string> &runtimeLibPaths,
@@ -1234,7 +1260,22 @@ void ToolChain::getRuntimeLibraryPaths(SmallVectorImpl<std::string> &runtimeLibP
12341260
getResourceDirPath(scratchPath, args, shared);
12351261
runtimeLibPaths.push_back(scratchPath.str());
12361262

1263+
// If there's a secondary resource dir, add it too.
1264+
scratchPath.clear();
1265+
getSecondaryResourceDirPath(scratchPath, runtimeLibPaths[0]);
1266+
if (!scratchPath.empty())
1267+
runtimeLibPaths.push_back(scratchPath.str());
1268+
12371269
if (!SDKPath.empty()) {
1270+
if (!scratchPath.empty()) {
1271+
// If we added the secondary resource dir, we also need the iOSSupport
1272+
// directory.
1273+
scratchPath = SDKPath;
1274+
llvm::sys::path::append(scratchPath, "System", "iOSSupport");
1275+
llvm::sys::path::append(scratchPath, "usr", "lib", "swift");
1276+
runtimeLibPaths.push_back(scratchPath.str());
1277+
}
1278+
12381279
scratchPath = SDKPath;
12391280
llvm::sys::path::append(scratchPath, "usr", "lib", "swift");
12401281
runtimeLibPaths.push_back(scratchPath.str());

lib/Driver/ToolChains.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,27 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain {
5555
const JobContext &context) const override;
5656

5757
void validateArguments(DiagnosticEngine &diags,
58-
const llvm::opt::ArgList &args) const override;
58+
const llvm::opt::ArgList &args,
59+
StringRef defaultTarget) const override;
5960

6061
std::string findProgramRelativeToSwiftImpl(StringRef name) const override;
6162

6263
bool shouldStoreInvocationInDebugInfo() const override;
6364

65+
const Optional<llvm::Triple> TargetVariant;
66+
6467
public:
65-
Darwin(const Driver &D, const llvm::Triple &Triple) : ToolChain(D, Triple) {}
68+
Darwin(const Driver &D, const llvm::Triple &Triple,
69+
const Optional<llvm::Triple> &TargetVariant) :
70+
ToolChain(D, Triple), TargetVariant(TargetVariant) {}
71+
6672
~Darwin() = default;
6773
std::string sanitizerRuntimeLibName(StringRef Sanitizer,
6874
bool shared = true) const override;
75+
76+
Optional<llvm::Triple> getTargetVariant() const {
77+
return TargetVariant;
78+
}
6979
};
7080

7181
class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain {

0 commit comments

Comments
 (0)