Skip to content

Commit dbf7f49

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 DarwinClang down into MachO, as long as the target triple is an apple one, or the driver is one of the Darwin subclasses.
1 parent e34cc7c commit dbf7f49

File tree

4 files changed

+174
-77
lines changed

4 files changed

+174
-77
lines changed

clang/lib/Driver/ToolChains/Darwin.cpp

+78-53
Original file line numberDiff line numberDiff line change
@@ -961,15 +961,15 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
961961
}
962962

963963
MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
964-
: ToolChain(D, Triple, Args) {
964+
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
965+
RocmInstallation(D, Triple, Args) {
965966
// We expect 'as', 'ld', etc. to be adjacent to our install dir.
966967
getProgramPaths().push_back(getDriver().Dir);
967968
}
968969

969970
/// Darwin - Darwin tool chain for i386 and x86_64.
970971
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) {}
972+
: MachO(D, Triple, Args), TargetInitialized(false) {}
973973

974974
types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
975975
types::ID Ty = ToolChain::LookupTypeForExtension(Ext);
@@ -1018,13 +1018,19 @@ bool Darwin::hasBlocksRuntime() const {
10181018
}
10191019
}
10201020

1021-
void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,
1022-
ArgStringList &CC1Args) const {
1021+
void MachO::AddCudaIncludeArgs(const ArgList &DriverArgs,
1022+
ArgStringList &CC1Args) const {
1023+
if (!isTargetAppleBased())
1024+
return ToolChain::AddCudaIncludeArgs(DriverArgs, CC1Args);
1025+
10231026
CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);
10241027
}
10251028

1026-
void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,
1027-
ArgStringList &CC1Args) const {
1029+
void MachO::AddHIPIncludeArgs(const ArgList &DriverArgs,
1030+
ArgStringList &CC1Args) const {
1031+
if (!isTargetAppleBased())
1032+
return ToolChain::AddHIPIncludeArgs(DriverArgs, CC1Args);
1033+
10281034
RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
10291035
}
10301036

@@ -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+
MachO::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,11 @@ 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 MachO::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
2505+
llvm::opt::ArgStringList &CC1Args) const {
2506+
if (!isTargetAppleBased())
2507+
return ToolChain::AddClangSystemIncludeArgs(DriverArgs, CC1Args);
2508+
25002509
const Driver &D = getDriver();
25012510

25022511
llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
@@ -2574,9 +2583,12 @@ bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverAr
25742583
return getVFS().exists(Base);
25752584
}
25762585

2577-
void DarwinClang::AddClangCXXStdlibIncludeArgs(
2586+
void MachO::AddClangCXXStdlibIncludeArgs(
25782587
const llvm::opt::ArgList &DriverArgs,
25792588
llvm::opt::ArgStringList &CC1Args) const {
2589+
if (!isTargetAppleBased())
2590+
return ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);
2591+
25802592
// The implementation from a base class will pass through the -stdlib to
25812593
// CC1Args.
25822594
// FIXME: this should not be necessary, remove usages in the frontend
@@ -2631,55 +2643,65 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
26312643
}
26322644

26332645
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;
2646+
AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args);
2647+
break;
2648+
}
2649+
}
26522650

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;
2651+
void MachO::AddGnuCPlusPlusIncludePaths(
2652+
const llvm::opt::ArgList &DriverArgs,
2653+
llvm::opt::ArgStringList &CC1Args) const {}
26642654

2665-
case llvm::Triple::aarch64:
2666-
IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2667-
"4.2.1",
2668-
"arm64-apple-darwin10",
2669-
"");
2670-
break;
2671-
}
2655+
void DarwinClang::AddGnuCPlusPlusIncludePaths(
2656+
const llvm::opt::ArgList &DriverArgs,
2657+
llvm::opt::ArgStringList &CC1Args) const {
2658+
llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
26722659

2673-
if (!IsBaseFound) {
2674-
getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
2675-
}
2660+
llvm::SmallString<128> UsrIncludeCxx = Sysroot;
2661+
llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");
2662+
2663+
llvm::Triple::ArchType arch = getTriple().getArch();
2664+
bool IsBaseFound = true;
2665+
switch (arch) {
2666+
default:
2667+
break;
26762668

2669+
case llvm::Triple::x86:
2670+
case llvm::Triple::x86_64:
2671+
IsBaseFound = AddGnuCPlusPlusIncludePaths(
2672+
DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1", "i686-apple-darwin10",
2673+
arch == llvm::Triple::x86_64 ? "x86_64" : "");
2674+
IsBaseFound |= AddGnuCPlusPlusIncludePaths(
2675+
DriverArgs, CC1Args, UsrIncludeCxx, "4.0.0", "i686-apple-darwin8", "");
2676+
break;
2677+
2678+
case llvm::Triple::arm:
2679+
case llvm::Triple::thumb:
2680+
IsBaseFound =
2681+
AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1",
2682+
"arm-apple-darwin10", "v7");
2683+
IsBaseFound |=
2684+
AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1",
2685+
"arm-apple-darwin10", "v6");
2686+
break;
2687+
2688+
case llvm::Triple::aarch64:
2689+
IsBaseFound =
2690+
AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1",
2691+
"arm64-apple-darwin10", "");
26772692
break;
26782693
}
2694+
2695+
if (!IsBaseFound) {
2696+
getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
2697+
}
26792698
}
26802699

2681-
void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
2682-
ArgStringList &CmdArgs) const {
2700+
void MachO::AddCXXStdlibLibArgs(const ArgList &Args,
2701+
ArgStringList &CmdArgs) const {
2702+
if (!isTargetAppleBased())
2703+
return ToolChain::AddCXXStdlibLibArgs(Args, CmdArgs);
2704+
26832705
CXXStdlibType Type = GetCXXStdlibType(Args);
26842706

26852707
switch (Type) {
@@ -3615,7 +3637,10 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
36153637
return Res;
36163638
}
36173639

3618-
void Darwin::printVerboseInfo(raw_ostream &OS) const {
3640+
void MachO::printVerboseInfo(raw_ostream &OS) const {
3641+
if (!isTargetAppleBased())
3642+
return ToolChain::printVerboseInfo(OS);
3643+
36193644
CudaInstallation->print(OS);
36203645
RocmInstallation->print(OS);
36213646
}

clang/lib/Driver/ToolChains/Darwin.h

+40-23
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,22 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
180180
llvm::opt::ArgStringList &CmdArgs,
181181
bool ForceLinkBuiltinRT = false) const;
182182

183+
void AddClangCXXStdlibIncludeArgs(
184+
const llvm::opt::ArgList &DriverArgs,
185+
llvm::opt::ArgStringList &CC1Args) const override;
186+
187+
void
188+
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
189+
llvm::opt::ArgStringList &CC1Args) const override;
190+
191+
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
192+
llvm::opt::ArgStringList &CC1Args) const override;
193+
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
194+
llvm::opt::ArgStringList &CC1Args) const override;
195+
196+
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
197+
llvm::opt::ArgStringList &CmdArgs) const override;
198+
183199
virtual void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
184200
llvm::opt::ArgStringList &CmdArgs) const {
185201
}
@@ -195,6 +211,11 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
195211
/// this such a target?
196212
virtual bool isKernelStatic() const { return false; }
197213

214+
/// Is the target an Apple target?
215+
bool isTargetAppleBased() const {
216+
return getTriple().getVendor() == llvm::Triple::Apple;
217+
}
218+
198219
/// Is the target either iOS or an iOS simulator?
199220
bool isTargetIOSBased() const { return false; }
200221

@@ -287,7 +308,20 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
287308
// Darwin toolchain uses legacy thin LTO API, which is not
288309
// capable of unit splitting.
289310
bool canSplitThinLTOUnit() const override { return false; }
311+
312+
void printVerboseInfo(raw_ostream &OS) const override;
290313
/// }
314+
315+
LazyDetector<CudaInstallationDetector> CudaInstallation;
316+
LazyDetector<RocmInstallationDetector> RocmInstallation;
317+
318+
protected:
319+
llvm::SmallString<128>
320+
GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const;
321+
322+
virtual void
323+
AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
324+
llvm::opt::ArgStringList &CC1Args) const;
291325
};
292326

293327
/// Darwin - The base Darwin tool chain.
@@ -329,9 +363,6 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
329363
/// The target variant triple that was specified (if any).
330364
mutable std::optional<llvm::Triple> TargetVariantTriple;
331365

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

@@ -402,6 +433,8 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
402433
}
403434

404435
public:
436+
bool isTargetAppleBased() const { return true; }
437+
405438
bool isTargetIPhoneOS() const {
406439
assert(TargetInitialized && "Target not initialized!");
407440
return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
@@ -559,11 +592,6 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
559592
ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override;
560593
bool hasBlocksRuntime() const override;
561594

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-
567595
bool UseObjCMixedDispatch() const override {
568596
// This is only used with the non-fragile ABI and non-legacy dispatch.
569597

@@ -594,8 +622,6 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
594622
bool SupportsEmbeddedBitcode() const override;
595623

596624
SanitizerMask getSupportedSanitizers() const override;
597-
598-
void printVerboseInfo(raw_ostream &OS) const override;
599625
};
600626

601627
/// DarwinClang - The Darwin toolchain used by Clang.
@@ -613,16 +639,6 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
613639
llvm::opt::ArgStringList &CmdArgs,
614640
bool ForceLinkBuiltinRT = false) const override;
615641

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-
626642
void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
627643
llvm::opt::ArgStringList &CmdArgs) const override;
628644

@@ -647,15 +663,16 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
647663
StringRef Sanitizer,
648664
bool shared = true) const;
649665

666+
void
667+
AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
668+
llvm::opt::ArgStringList &CC1Args) const override;
669+
650670
bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
651671
llvm::opt::ArgStringList &CC1Args,
652672
llvm::SmallString<128> Base,
653673
llvm::StringRef Version,
654674
llvm::StringRef ArchDir,
655675
llvm::StringRef BitDir) const;
656-
657-
llvm::SmallString<128>
658-
GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const;
659676
};
660677

661678
} // 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.getVendor() == llvm::Triple::Apple) && triple.isOSBinFormatMachO()))
316316
return false;
317317
break;
318318

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// UNSUPPORTED: system-windows
2+
// Windows is unsupported because we use the Unix path separator `/` in the test.
3+
4+
// Add default directories before running clang to check default
5+
// search paths.
6+
// RUN: rm -rf %t && mkdir -p %t
7+
// RUN: cp -R %S/Inputs/MacOSX15.1.sdk %t/
8+
// RUN: mkdir -p %t/MacOSX15.1.sdk/usr/include
9+
// RUN: mkdir -p %t/MacOSX15.1.sdk/usr/include/c++/v1
10+
// RUN: mkdir -p %t/MacOSX15.1.sdk/usr/local/include
11+
// RUN: mkdir -p %t/MacOSX15.1.sdk/embedded/usr/include
12+
// RUN: mkdir -p %t/MacOSX15.1.sdk/embedded/usr/local/include
13+
14+
// Unlike the Darwin driver, the MachO driver doesn't add any framework search paths,
15+
// only the normal header ones.
16+
// RUN: %clang -xc %s -target arm64-apple-none-macho -isysroot %t/MacOSX15.1.sdk -E -v 2>&1 | FileCheck --check-prefix=CHECK-C %s
17+
//
18+
// CHECK-C: -isysroot [[SDKROOT:[^ ]*/MacOSX15.1.sdk]]
19+
// CHECK-C: #include <...> search starts here:
20+
// CHECK-C-NEXT: [[SDKROOT]]/usr/local/include
21+
// CHECK-C-NEXT: /clang/{{.*}}/include
22+
// CHECK-C-NEXT: [[SDKROOT]]/usr/include
23+
24+
// Unlike the Darwin driver, the MachO driver doesn't default to libc++
25+
// RUN: %clang -xc++ %s -target arm64-apple-none-macho -isysroot %t/MacOSX15.1.sdk -E -v 2>&1 | FileCheck --check-prefix=CHECK-CXX %s
26+
//
27+
// CHECK-CXX: -isysroot [[SDKROOT:[^ ]*/MacOSX15.1.sdk]]
28+
// CHECK-CXX: #include <...> search starts here:
29+
// CHECK-CXX-NEXT: [[SDKROOT]]/usr/local/include
30+
// CHECK-CXX-NEXT: /clang/{{.*}}/include
31+
// CHECK-CXX-NEXT: [[SDKROOT]]/usr/include
32+
33+
// However, if the user requests libc++, the MachO driver should find the search path.
34+
// RUN: %clang -xc++ -stdlib=libc++ %s -target arm64-apple-none-macho -isysroot %t/MacOSX15.1.sdk -E -v 2>&1 | FileCheck --check-prefix=CHECK-LIBCXX %s
35+
//
36+
// CHECK-LIBCXX: -isysroot [[SDKROOT:[^ ]*/MacOSX15.1.sdk]]
37+
// CHECK-LIBCXX: #include <...> search starts here:
38+
// CHECK-LIBCXX-NEXT: [[SDKROOT]]/usr/include/c++/v1
39+
// CHECK-LIBCXX-NEXT: [[SDKROOT]]/usr/local/include
40+
// CHECK-LIBCXX-NEXT: /clang/{{.*}}/include
41+
// CHECK-LIBCXX-NEXT: [[SDKROOT]]/usr/include
42+
43+
// Verify that embedded uses can swap in alternate usr/include and usr/local/include directories.
44+
// usr/local/include is specified in the driver as -internal-isystem, however, the driver generated
45+
// paths come before the paths in the driver arguments. In order to keep usr/local/include in the
46+
// same position, -isystem has to be used instead of -Xclang -internal-isystem. There isn't an
47+
// -externc-isystem, but it's ok to use -Xclang -internal-externc-isystem since the driver doesn't
48+
// use that if -nostdlibinc or -nostdinc is passed.
49+
// RUN: %clang -xc++ -stdlib=libc++ %s -target arm64-apple-none-macho -isysroot %t/MacOSX15.1.sdk -nostdlibinc -isystem %t/MacOSX15.1.sdk/embedded/usr/local/include -Xclang -internal-externc-isystem -Xclang %t/MacOSX15.1.sdk/embedded/usr/include -E -v 2>&1 | FileCheck --check-prefix=CHECK-EMBEDDED %s
50+
//
51+
// CHECK-EMBEDDED: -isysroot [[SDKROOT:[^ ]*/MacOSX15.1.sdk]]
52+
// CHECK-EMBEDDED: #include <...> search starts here:
53+
// CHECK-EMBEDDED-NEXT: [[SDKROOT]]/embedded/usr/local/include
54+
// CHECK-EMBEDDED-NEXT: /clang/{{.*}}/include
55+
// CHECK-EMBEDDED-NEXT: [[SDKROOT]]/embedded/usr/include

0 commit comments

Comments
 (0)