Skip to content

Commit 974dfb7

Browse files
[stable/20240723][Darwin][Driver][clang] apple-none-macho orders the resource directory after internal-externc-isystem when nostdlibinc is used (llvm#122035)
Embedded development often needs to use a different C standard library, replacing the existing one normally passed as -internal-externc-isystem. This works fine for an apple-macos target, but apple-none-macho doesn't work because the MachO driver doesn't implement AddClangSystemIncludeArgs to add the resource directory as -internal-isystem like most other drivers do. Move most of the search path logic from Darwin and DarwinClang down into an AppleMachO toolchain between the MachO and Darwin toolchains. Also define __MACH__ for apple-none-macho, as Swift expects all MachO targets to have that defined. rdar://141248577
1 parent 99b818a commit 974dfb7

File tree

14 files changed

+217
-84
lines changed

14 files changed

+217
-84
lines changed

clang/lib/Basic/Targets/OSTargets.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,6 @@ void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
122122
assert(OsVersion.getMinor().value_or(0) < 100 &&
123123
OsVersion.getSubminor().value_or(0) < 100 && "Invalid version!");
124124
Builder.defineMacro("__ENVIRONMENT_OS_VERSION_MIN_REQUIRED__", Str);
125-
126-
// Tell users about the kernel if there is one.
127-
Builder.defineMacro("__MACH__");
128125
}
129126

130127
PlatformMinVersion = OsVersion;

clang/lib/Driver/Driver.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -6551,6 +6551,8 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
65516551
TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args);
65526552
else if (Target.isOSBinFormatELF())
65536553
TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args);
6554+
else if (Target.isAppleMachO())
6555+
TC = std::make_unique<toolchains::AppleMachO>(*this, Target, Args);
65546556
else if (Target.isOSBinFormatMachO())
65556557
TC = std::make_unique<toolchains::MachO>(*this, Target, Args);
65566558
else

clang/lib/Driver/ToolChains/Darwin.cpp

+64-52
Original file line numberDiff line numberDiff line change
@@ -1049,10 +1049,14 @@ MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
10491049
getProgramPaths().push_back(getDriver().Dir);
10501050
}
10511051

1052+
AppleMachO::AppleMachO(const Driver &D, const llvm::Triple &Triple,
1053+
const ArgList &Args)
1054+
: MachO(D, Triple, Args), CudaInstallation(D, Triple, Args),
1055+
RocmInstallation(D, Triple, Args) {}
1056+
10521057
/// Darwin - Darwin tool chain for i386 and x86_64.
10531058
Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
1054-
: MachO(D, Triple, Args), TargetInitialized(false),
1055-
CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {}
1059+
: AppleMachO(D, Triple, Args), TargetInitialized(false) {}
10561060

10571061
types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
10581062
types::ID Ty = ToolChain::LookupTypeForExtension(Ext);
@@ -1101,13 +1105,13 @@ bool Darwin::hasBlocksRuntime() const {
11011105
}
11021106
}
11031107

1104-
void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,
1105-
ArgStringList &CC1Args) const {
1108+
void AppleMachO::AddCudaIncludeArgs(const ArgList &DriverArgs,
1109+
ArgStringList &CC1Args) const {
11061110
CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);
11071111
}
11081112

1109-
void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,
1110-
ArgStringList &CC1Args) const {
1113+
void AppleMachO::AddHIPIncludeArgs(const ArgList &DriverArgs,
1114+
ArgStringList &CC1Args) const {
11111115
RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
11121116
}
11131117

@@ -1202,6 +1206,8 @@ VersionTuple MachO::getLinkerVersion(const llvm::opt::ArgList &Args) const {
12021206

12031207
Darwin::~Darwin() {}
12041208

1209+
AppleMachO::~AppleMachO() {}
1210+
12051211
MachO::~MachO() {}
12061212

12071213
std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
@@ -2619,7 +2625,7 @@ static void AppendPlatformPrefix(SmallString<128> &Path,
26192625
// Returns the effective sysroot from either -isysroot or --sysroot, plus the
26202626
// platform prefix (if any).
26212627
llvm::SmallString<128>
2622-
DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
2628+
AppleMachO::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
26232629
llvm::SmallString<128> Path("/");
26242630
if (DriverArgs.hasArg(options::OPT_isysroot))
26252631
Path = DriverArgs.getLastArgValue(options::OPT_isysroot);
@@ -2632,8 +2638,9 @@ DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
26322638
return Path;
26332639
}
26342640

2635-
void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
2636-
llvm::opt::ArgStringList &CC1Args) const {
2641+
void AppleMachO::AddClangSystemIncludeArgs(
2642+
const llvm::opt::ArgList &DriverArgs,
2643+
llvm::opt::ArgStringList &CC1Args) const {
26372644
const Driver &D = getDriver();
26382645

26392646
llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
@@ -2711,7 +2718,7 @@ bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverAr
27112718
return getVFS().exists(Base);
27122719
}
27132720

2714-
void DarwinClang::AddClangCXXStdlibIncludeArgs(
2721+
void AppleMachO::AddClangCXXStdlibIncludeArgs(
27152722
const llvm::opt::ArgList &DriverArgs,
27162723
llvm::opt::ArgStringList &CC1Args) const {
27172724
// The implementation from a base class will pass through the -stdlib to
@@ -2768,55 +2775,60 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
27682775
}
27692776

27702777
case ToolChain::CST_Libstdcxx:
2771-
llvm::SmallString<128> UsrIncludeCxx = Sysroot;
2772-
llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");
2773-
2774-
llvm::Triple::ArchType arch = getTriple().getArch();
2775-
bool IsBaseFound = true;
2776-
switch (arch) {
2777-
default: break;
2778-
2779-
case llvm::Triple::x86:
2780-
case llvm::Triple::x86_64:
2781-
IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2782-
"4.2.1",
2783-
"i686-apple-darwin10",
2784-
arch == llvm::Triple::x86_64 ? "x86_64" : "");
2785-
IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2786-
"4.0.0", "i686-apple-darwin8",
2787-
"");
2788-
break;
2778+
AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args);
2779+
break;
2780+
}
2781+
}
27892782

2790-
case llvm::Triple::arm:
2791-
case llvm::Triple::thumb:
2792-
IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2793-
"4.2.1",
2794-
"arm-apple-darwin10",
2795-
"v7");
2796-
IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2797-
"4.2.1",
2798-
"arm-apple-darwin10",
2799-
"v6");
2800-
break;
2783+
void AppleMachO::AddGnuCPlusPlusIncludePaths(
2784+
const llvm::opt::ArgList &DriverArgs,
2785+
llvm::opt::ArgStringList &CC1Args) const {}
28012786

2802-
case llvm::Triple::aarch64:
2803-
IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2804-
"4.2.1",
2805-
"arm64-apple-darwin10",
2806-
"");
2807-
break;
2808-
}
2787+
void DarwinClang::AddGnuCPlusPlusIncludePaths(
2788+
const llvm::opt::ArgList &DriverArgs,
2789+
llvm::opt::ArgStringList &CC1Args) const {
2790+
llvm::SmallString<128> UsrIncludeCxx = GetEffectiveSysroot(DriverArgs);
2791+
llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");
28092792

2810-
if (!IsBaseFound) {
2811-
getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
2812-
}
2793+
llvm::Triple::ArchType arch = getTriple().getArch();
2794+
bool IsBaseFound = true;
2795+
switch (arch) {
2796+
default:
2797+
break;
28132798

2799+
case llvm::Triple::x86:
2800+
case llvm::Triple::x86_64:
2801+
IsBaseFound = AddGnuCPlusPlusIncludePaths(
2802+
DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1", "i686-apple-darwin10",
2803+
arch == llvm::Triple::x86_64 ? "x86_64" : "");
2804+
IsBaseFound |= AddGnuCPlusPlusIncludePaths(
2805+
DriverArgs, CC1Args, UsrIncludeCxx, "4.0.0", "i686-apple-darwin8", "");
2806+
break;
2807+
2808+
case llvm::Triple::arm:
2809+
case llvm::Triple::thumb:
2810+
IsBaseFound =
2811+
AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1",
2812+
"arm-apple-darwin10", "v7");
2813+
IsBaseFound |=
2814+
AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1",
2815+
"arm-apple-darwin10", "v6");
2816+
break;
2817+
2818+
case llvm::Triple::aarch64:
2819+
IsBaseFound =
2820+
AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1",
2821+
"arm64-apple-darwin10", "");
28142822
break;
28152823
}
2824+
2825+
if (!IsBaseFound) {
2826+
getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
2827+
}
28162828
}
28172829

2818-
void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
2819-
ArgStringList &CmdArgs) const {
2830+
void AppleMachO::AddCXXStdlibLibArgs(const ArgList &Args,
2831+
ArgStringList &CmdArgs) const {
28202832
CXXStdlibType Type = GetCXXStdlibType(Args);
28212833

28222834
switch (Type) {
@@ -3717,7 +3729,7 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
37173729
return Res;
37183730
}
37193731

3720-
void Darwin::printVerboseInfo(raw_ostream &OS) const {
3732+
void AppleMachO::printVerboseInfo(raw_ostream &OS) const {
37213733
CudaInstallation->print(OS);
37223734
RocmInstallation->print(OS);
37233735
}

clang/lib/Driver/ToolChains/Darwin.h

+47-25
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,49 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
290290
/// }
291291
};
292292

293+
/// Apple specific MachO extensions
294+
class LLVM_LIBRARY_VISIBILITY AppleMachO : public MachO {
295+
public:
296+
AppleMachO(const Driver &D, const llvm::Triple &Triple,
297+
const llvm::opt::ArgList &Args);
298+
~AppleMachO() override;
299+
300+
/// }
301+
/// @name Apple Specific ToolChain Implementation
302+
/// {
303+
void
304+
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
305+
llvm::opt::ArgStringList &CC1Args) const override;
306+
307+
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
308+
llvm::opt::ArgStringList &CC1Args) const override;
309+
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
310+
llvm::opt::ArgStringList &CC1Args) const override;
311+
312+
void AddClangCXXStdlibIncludeArgs(
313+
const llvm::opt::ArgList &DriverArgs,
314+
llvm::opt::ArgStringList &CC1Args) const override;
315+
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
316+
llvm::opt::ArgStringList &CmdArgs) const override;
317+
318+
void printVerboseInfo(raw_ostream &OS) const override;
319+
/// }
320+
321+
LazyDetector<CudaInstallationDetector> CudaInstallation;
322+
LazyDetector<RocmInstallationDetector> RocmInstallation;
323+
324+
protected:
325+
llvm::SmallString<128>
326+
GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const;
327+
328+
private:
329+
virtual void
330+
AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
331+
llvm::opt::ArgStringList &CC1Args) const;
332+
};
333+
293334
/// Darwin - The base Darwin tool chain.
294-
class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
335+
class LLVM_LIBRARY_VISIBILITY Darwin : public AppleMachO {
295336
public:
296337
/// Whether the information on the target has been initialized.
297338
//
@@ -329,9 +370,6 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
329370
/// The target variant triple that was specified (if any).
330371
mutable std::optional<llvm::Triple> TargetVariantTriple;
331372

332-
LazyDetector<CudaInstallationDetector> CudaInstallation;
333-
LazyDetector<RocmInstallationDetector> RocmInstallation;
334-
335373
private:
336374
void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
337375

@@ -343,7 +381,7 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
343381
std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
344382
types::ID InputType) const override;
345383

346-
/// @name Apple Specific Toolchain Implementation
384+
/// @name Darwin Specific Toolchain Implementation
347385
/// {
348386

349387
void addMinVersionArgs(const llvm::opt::ArgList &Args,
@@ -559,11 +597,6 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
559597
ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override;
560598
bool hasBlocksRuntime() const override;
561599

562-
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
563-
llvm::opt::ArgStringList &CC1Args) const override;
564-
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
565-
llvm::opt::ArgStringList &CC1Args) const override;
566-
567600
bool UseObjCMixedDispatch() const override {
568601
// This is only used with the non-fragile ABI and non-legacy dispatch.
569602

@@ -594,8 +627,6 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
594627
bool SupportsEmbeddedBitcode() const override;
595628

596629
SanitizerMask getSupportedSanitizers() const override;
597-
598-
void printVerboseInfo(raw_ostream &OS) const override;
599630
};
600631

601632
/// DarwinClang - The Darwin toolchain used by Clang.
@@ -613,16 +644,6 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
613644
llvm::opt::ArgStringList &CmdArgs,
614645
bool ForceLinkBuiltinRT = false) const override;
615646

616-
void AddClangCXXStdlibIncludeArgs(
617-
const llvm::opt::ArgList &DriverArgs,
618-
llvm::opt::ArgStringList &CC1Args) const override;
619-
620-
void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
621-
llvm::opt::ArgStringList &CC1Args) const override;
622-
623-
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
624-
llvm::opt::ArgStringList &CmdArgs) const override;
625-
626647
void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
627648
llvm::opt::ArgStringList &CmdArgs) const override;
628649

@@ -651,15 +672,16 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
651672
StringRef Sanitizer,
652673
bool shared = true) const;
653674

675+
void
676+
AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
677+
llvm::opt::ArgStringList &CC1Args) const override;
678+
654679
bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
655680
llvm::opt::ArgStringList &CC1Args,
656681
llvm::SmallString<128> Base,
657682
llvm::StringRef Version,
658683
llvm::StringRef ArchDir,
659684
llvm::StringRef BitDir) const;
660-
661-
llvm::SmallString<128>
662-
GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const;
663685
};
664686

665687
} // end namespace toolchains

clang/lib/Frontend/InitPreprocessor.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,11 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
14981498
// ELF targets define __ELF__
14991499
if (TI.getTriple().isOSBinFormatELF())
15001500
Builder.defineMacro("__ELF__");
1501+
else if (TI.getTriple().isAppleMachO())
1502+
// Apple MachO targets define __MACH__ even when not using DarwinTargetInfo.
1503+
// Hurd will also define this in some circumstances, but that's done in
1504+
// HurdTargetInfo. Windows targets don't define this.
1505+
Builder.defineMacro("__MACH__");
15011506

15021507
// Target OS macro definitions.
15031508
if (PPOpts.DefineTargetOSMacros) {

clang/lib/Lex/InitHeaderSearch.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ bool InitHeaderSearch::ShouldAddDefaultIncludePaths(
315315
break;
316316

317317
case llvm::Triple::UnknownOS:
318-
if (triple.isWasm())
318+
if (triple.isWasm() || triple.isAppleMachO())
319319
return false;
320320
break;
321321

clang/test/Driver/Inputs/MacOSX15.1.sdk/embedded/usr/include/.keep

Whitespace-only changes.

clang/test/Driver/Inputs/MacOSX15.1.sdk/embedded/usr/local/include/.keep

Whitespace-only changes.

clang/test/Driver/Inputs/MacOSX15.1.sdk/usr/include/c++/v1/.keep

Whitespace-only changes.

clang/test/Driver/Inputs/MacOSX15.1.sdk/usr/local/include/.keep

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// REQUIRES: default-cxx-stdlib=libc++
2+
// UNSUPPORTED: system-windows
3+
// Windows is unsupported because we use the Unix path separator `/` in the test.
4+
5+
// Unlike the Darwin driver, the MachO driver doesn't add any framework search paths,
6+
// only the normal header ones.
7+
// RUN: %clang -x c -target arm64-apple-none-macho -isysroot %S/Inputs/MacOSX15.1.sdk -### -c %s 2>&1 \
8+
// RUN: | FileCheck --check-prefixes=CC1,NO-CXX,ULI,CI,UI,NO-FW -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
9+
10+
// Unlike the Darwin driver, the MachO driver doesn't default to libc++, but when
11+
// CLANG_DEFAULT_CXX_STDLIB is libc++ then the MachO driver should find the search path.
12+
// RUN: %clang -x c++ -target arm64-apple-none-macho -isysroot %S/Inputs/MacOSX15.1.sdk -### -c %s 2>&1 \
13+
// RUN: | FileCheck --check-prefixes=CC1,CXX,ULI,CI,UI,NO-FW -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
14+
15+
// If the user requests libc++, the MachO driver should still find the search path.
16+
// RUN: %clang -x c++ -stdlib=libc++ -target arm64-apple-none-macho -isysroot %S/Inputs/MacOSX15.1.sdk -### -c %s 2>&1 \
17+
// RUN: | FileCheck --check-prefixes=CC1,CXX,ULI,CI,UI,NO-FW -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
18+
19+
// Verify that embedded uses can swap in alternate usr/include and usr/local/include directories.
20+
// usr/local/include is specified in the driver as -internal-isystem, however, the driver generated
21+
// paths come before the paths in the driver arguments. In order to keep usr/local/include in the
22+
// same position, -isystem has to be used instead of -Xclang -internal-isystem. There isn't an
23+
// -externc-isystem, but it's ok to use -Xclang -internal-externc-isystem since the driver doesn't
24+
// use that if -nostdlibinc or -nostdinc is passed.
25+
// RUN: %clang -x c++ -stdlib=libc++ -target arm64-apple-none-macho -isysroot %S/Inputs/MacOSX15.1.sdk \
26+
// RUN: -nostdlibinc -isystem %S/Inputs/MacOSX15.1.sdk/embedded/usr/local/include \
27+
// RUN: -Xclang -internal-externc-isystem -Xclang %S/Inputs/MacOSX15.1.sdk/embedded/usr/include \
28+
// RUN: -### -c %s 2>&1 | FileCheck --check-prefixes=CC1,NO-CXX,EULI,CI,EUI,NO-FW -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
29+
30+
31+
// The ordering of these flags doesn't matter, and so this test is a little
32+
// fragile. i.e. all of the -internal-isystem paths will be searched before the
33+
// -internal-externc-isystem ones, and their order on the command line doesn't
34+
// matter. The line order here is just the current order that the driver writes
35+
// the cc1 arguments.
36+
37+
// CC1: "-cc1"
38+
// NO-CXX-NOT: "-internal-isystem" "{{.*}}/include/c++/v1"
39+
// CXX-SAME: "-internal-isystem" "{{.*}}/include/c++/v1"
40+
// ULI-SAME: "-internal-isystem" "[[SDKROOT]]/usr/local/include"
41+
// EULI-SAME: "-isystem" "[[SDKROOT]]/embedded/usr/local/include"
42+
// CI-SAME: "-internal-isystem" "{{.*}}/clang/{{[[:digit:].]*}}/include"
43+
// UI-SAME: "-internal-externc-isystem" "[[SDKROOT]]/usr/include"
44+
// EUI-SAME: "-internal-externc-isystem" "[[SDKROOT]]/embedded/usr/include"
45+
// NO-FW-NOT: "-internal-iframework"

0 commit comments

Comments
 (0)