Skip to content

Commit 7aecf68

Browse files
[Darwin][Driver][clang] apple-none-macho orders the resource directory after internal-externc-isystem when nostdlibinc is used
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.
1 parent 21a6dbd commit 7aecf68

File tree

10 files changed

+162
-78
lines changed

10 files changed

+162
-78
lines changed

clang/lib/Driver/Driver.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -6603,6 +6603,8 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
66036603
TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args);
66046604
else if (Target.isOSBinFormatELF())
66056605
TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args);
6606+
else if (Target.isAppleMachO())
6607+
TC = std::make_unique<toolchains::AppleMachO>(*this, Target, Args);
66066608
else if (Target.isOSBinFormatMachO())
66076609
TC = std::make_unique<toolchains::MachO>(*this, Target, Args);
66086610
else

clang/lib/Driver/ToolChains/Darwin.cpp

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

969+
AppleMachO::AppleMachO(const Driver &D, const llvm::Triple &Triple,
970+
const ArgList &Args)
971+
: MachO(D, Triple, Args), CudaInstallation(D, Triple, Args),
972+
RocmInstallation(D, Triple, Args) {}
973+
969974
/// Darwin - Darwin tool chain for i386 and x86_64.
970975
Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
971-
: MachO(D, Triple, Args), TargetInitialized(false),
972-
CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {}
976+
: AppleMachO(D, Triple, Args), TargetInitialized(false) {}
973977

974978
types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
975979
types::ID Ty = ToolChain::LookupTypeForExtension(Ext);
@@ -1018,13 +1022,13 @@ bool Darwin::hasBlocksRuntime() const {
10181022
}
10191023
}
10201024

1021-
void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,
1022-
ArgStringList &CC1Args) const {
1025+
void AppleMachO::AddCudaIncludeArgs(const ArgList &DriverArgs,
1026+
ArgStringList &CC1Args) const {
10231027
CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);
10241028
}
10251029

1026-
void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,
1027-
ArgStringList &CC1Args) const {
1030+
void AppleMachO::AddHIPIncludeArgs(const ArgList &DriverArgs,
1031+
ArgStringList &CC1Args) const {
10281032
RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
10291033
}
10301034

@@ -1119,6 +1123,8 @@ VersionTuple MachO::getLinkerVersion(const llvm::opt::ArgList &Args) const {
11191123

11201124
Darwin::~Darwin() {}
11211125

1126+
AppleMachO::~AppleMachO() {}
1127+
11221128
MachO::~MachO() {}
11231129

11241130
std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
@@ -2482,7 +2488,7 @@ static void AppendPlatformPrefix(SmallString<128> &Path,
24822488
// Returns the effective sysroot from either -isysroot or --sysroot, plus the
24832489
// platform prefix (if any).
24842490
llvm::SmallString<128>
2485-
DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
2491+
AppleMachO::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
24862492
llvm::SmallString<128> Path("/");
24872493
if (DriverArgs.hasArg(options::OPT_isysroot))
24882494
Path = DriverArgs.getLastArgValue(options::OPT_isysroot);
@@ -2495,8 +2501,9 @@ DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
24952501
return Path;
24962502
}
24972503

2498-
void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
2499-
llvm::opt::ArgStringList &CC1Args) const {
2504+
void AppleMachO::AddClangSystemIncludeArgs(
2505+
const llvm::opt::ArgList &DriverArgs,
2506+
llvm::opt::ArgStringList &CC1Args) const {
25002507
const Driver &D = getDriver();
25012508

25022509
llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
@@ -2574,7 +2581,7 @@ bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverAr
25742581
return getVFS().exists(Base);
25752582
}
25762583

2577-
void DarwinClang::AddClangCXXStdlibIncludeArgs(
2584+
void AppleMachO::AddClangCXXStdlibIncludeArgs(
25782585
const llvm::opt::ArgList &DriverArgs,
25792586
llvm::opt::ArgStringList &CC1Args) const {
25802587
// The implementation from a base class will pass through the -stdlib to
@@ -2631,55 +2638,60 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
26312638
}
26322639

26332640
case ToolChain::CST_Libstdcxx:
2634-
llvm::SmallString<128> UsrIncludeCxx = Sysroot;
2635-
llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");
2636-
2637-
llvm::Triple::ArchType arch = getTriple().getArch();
2638-
bool IsBaseFound = true;
2639-
switch (arch) {
2640-
default: break;
2641-
2642-
case llvm::Triple::x86:
2643-
case llvm::Triple::x86_64:
2644-
IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2645-
"4.2.1",
2646-
"i686-apple-darwin10",
2647-
arch == llvm::Triple::x86_64 ? "x86_64" : "");
2648-
IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2649-
"4.0.0", "i686-apple-darwin8",
2650-
"");
2651-
break;
2641+
AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args);
2642+
break;
2643+
}
2644+
}
26522645

2653-
case llvm::Triple::arm:
2654-
case llvm::Triple::thumb:
2655-
IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2656-
"4.2.1",
2657-
"arm-apple-darwin10",
2658-
"v7");
2659-
IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2660-
"4.2.1",
2661-
"arm-apple-darwin10",
2662-
"v6");
2663-
break;
2646+
void AppleMachO::AddGnuCPlusPlusIncludePaths(
2647+
const llvm::opt::ArgList &DriverArgs,
2648+
llvm::opt::ArgStringList &CC1Args) const {}
26642649

2665-
case llvm::Triple::aarch64:
2666-
IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2667-
"4.2.1",
2668-
"arm64-apple-darwin10",
2669-
"");
2670-
break;
2671-
}
2650+
void DarwinClang::AddGnuCPlusPlusIncludePaths(
2651+
const llvm::opt::ArgList &DriverArgs,
2652+
llvm::opt::ArgStringList &CC1Args) const {
2653+
llvm::SmallString<128> UsrIncludeCxx = GetEffectiveSysroot(DriverArgs);
2654+
llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");
26722655

2673-
if (!IsBaseFound) {
2674-
getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
2675-
}
2656+
llvm::Triple::ArchType arch = getTriple().getArch();
2657+
bool IsBaseFound = true;
2658+
switch (arch) {
2659+
default:
2660+
break;
26762661

2662+
case llvm::Triple::x86:
2663+
case llvm::Triple::x86_64:
2664+
IsBaseFound = AddGnuCPlusPlusIncludePaths(
2665+
DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1", "i686-apple-darwin10",
2666+
arch == llvm::Triple::x86_64 ? "x86_64" : "");
2667+
IsBaseFound |= AddGnuCPlusPlusIncludePaths(
2668+
DriverArgs, CC1Args, UsrIncludeCxx, "4.0.0", "i686-apple-darwin8", "");
2669+
break;
2670+
2671+
case llvm::Triple::arm:
2672+
case llvm::Triple::thumb:
2673+
IsBaseFound =
2674+
AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1",
2675+
"arm-apple-darwin10", "v7");
2676+
IsBaseFound |=
2677+
AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1",
2678+
"arm-apple-darwin10", "v6");
2679+
break;
2680+
2681+
case llvm::Triple::aarch64:
2682+
IsBaseFound =
2683+
AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1",
2684+
"arm64-apple-darwin10", "");
26772685
break;
26782686
}
2687+
2688+
if (!IsBaseFound) {
2689+
getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
2690+
}
26792691
}
26802692

2681-
void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
2682-
ArgStringList &CmdArgs) const {
2693+
void AppleMachO::AddCXXStdlibLibArgs(const ArgList &Args,
2694+
ArgStringList &CmdArgs) const {
26832695
CXXStdlibType Type = GetCXXStdlibType(Args);
26842696

26852697
switch (Type) {
@@ -3615,7 +3627,7 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
36153627
return Res;
36163628
}
36173629

3618-
void Darwin::printVerboseInfo(raw_ostream &OS) const {
3630+
void AppleMachO::printVerboseInfo(raw_ostream &OS) const {
36193631
CudaInstallation->print(OS);
36203632
RocmInstallation->print(OS);
36213633
}

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

@@ -647,15 +668,16 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
647668
StringRef Sanitizer,
648669
bool shared = true) const;
649670

671+
void
672+
AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
673+
llvm::opt::ArgStringList &CC1Args) const override;
674+
650675
bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
651676
llvm::opt::ArgStringList &CC1Args,
652677
llvm::SmallString<128> Base,
653678
llvm::StringRef Version,
654679
llvm::StringRef ArchDir,
655680
llvm::StringRef BitDir) const;
656-
657-
llvm::SmallString<128>
658-
GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const;
659681
};
660682

661683
} // end namespace toolchains

clang/lib/Lex/InitHeaderSearch.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ bool InitHeaderSearch::ShouldAddDefaultIncludePaths(
312312
break;
313313

314314
case llvm::Triple::UnknownOS:
315-
if (triple.isWasm())
315+
if (triple.isWasm() || triple.isAppleMachO())
316316
return false;
317317
break;
318318

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

llvm/include/llvm/TargetParser/Triple.h

+5
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,11 @@ class Triple {
564564

565565
bool isOSzOS() const { return getOS() == Triple::ZOS; }
566566

567+
/// Is this an Apple MachO triple.
568+
bool isAppleMachO() const {
569+
return (getVendor() == Triple::Apple) && isOSBinFormatMachO();
570+
}
571+
567572
/// Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, XROS, or DriverKit).
568573
bool isOSDarwin() const {
569574
return isMacOSX() || isiOS() || isWatchOS() || isDriverKit() || isXROS();

0 commit comments

Comments
 (0)