https://github.com/ian-twilightcoder updated https://github.com/llvm/llvm-project/pull/120507
>From 1c5290e9f2ae2dfa7536097fabb0448ebd17da16 Mon Sep 17 00:00:00 2001 From: Ian Anderson <i...@apple.com> Date: Wed, 18 Dec 2024 16:31:19 -0800 Subject: [PATCH] [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. --- clang/lib/Driver/ToolChains/Darwin.cpp | 131 +++++++++++------- clang/lib/Driver/ToolChains/Darwin.h | 63 ++++++--- clang/lib/Lex/InitHeaderSearch.cpp | 3 +- .../Driver/darwin-embedded-search-paths.c | 55 ++++++++ 4 files changed, 175 insertions(+), 77 deletions(-) create mode 100644 clang/test/Driver/darwin-embedded-search-paths.c diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 4105d38d15d7d8..06d9f535160b4e 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -961,15 +961,15 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, } MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : ToolChain(D, Triple, Args) { + : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), + RocmInstallation(D, Triple, Args) { // We expect 'as', 'ld', etc. to be adjacent to our install dir. getProgramPaths().push_back(getDriver().Dir); } /// Darwin - Darwin tool chain for i386 and x86_64. Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : MachO(D, Triple, Args), TargetInitialized(false), - CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {} + : MachO(D, Triple, Args), TargetInitialized(false) {} types::ID MachO::LookupTypeForExtension(StringRef Ext) const { types::ID Ty = ToolChain::LookupTypeForExtension(Ext); @@ -1018,13 +1018,19 @@ bool Darwin::hasBlocksRuntime() const { } } -void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { +void MachO::AddCudaIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (!isTargetAppleBased()) + return ToolChain::AddCudaIncludeArgs(DriverArgs, CC1Args); + CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args); } -void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { +void MachO::AddHIPIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (!isTargetAppleBased()) + return ToolChain::AddHIPIncludeArgs(DriverArgs, CC1Args); + RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args); } @@ -2482,7 +2488,7 @@ static void AppendPlatformPrefix(SmallString<128> &Path, // Returns the effective sysroot from either -isysroot or --sysroot, plus the // platform prefix (if any). llvm::SmallString<128> -DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const { +MachO::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const { llvm::SmallString<128> Path("/"); if (DriverArgs.hasArg(options::OPT_isysroot)) Path = DriverArgs.getLastArgValue(options::OPT_isysroot); @@ -2495,8 +2501,11 @@ DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const { return Path; } -void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const { +void MachO::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + if (!isTargetAppleBased()) + return ToolChain::AddClangSystemIncludeArgs(DriverArgs, CC1Args); + const Driver &D = getDriver(); llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs); @@ -2574,9 +2583,12 @@ bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverAr return getVFS().exists(Base); } -void DarwinClang::AddClangCXXStdlibIncludeArgs( +void MachO::AddClangCXXStdlibIncludeArgs( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { + if (!isTargetAppleBased()) + return ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args); + // The implementation from a base class will pass through the -stdlib to // CC1Args. // FIXME: this should not be necessary, remove usages in the frontend @@ -2631,55 +2643,65 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs( } case ToolChain::CST_Libstdcxx: - llvm::SmallString<128> UsrIncludeCxx = Sysroot; - llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++"); - - llvm::Triple::ArchType arch = getTriple().getArch(); - bool IsBaseFound = true; - switch (arch) { - default: break; - - case llvm::Triple::x86: - case llvm::Triple::x86_64: - IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, - "4.2.1", - "i686-apple-darwin10", - arch == llvm::Triple::x86_64 ? "x86_64" : ""); - IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, - "4.0.0", "i686-apple-darwin8", - ""); - break; + AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args); + break; + } +} - case llvm::Triple::arm: - case llvm::Triple::thumb: - IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, - "4.2.1", - "arm-apple-darwin10", - "v7"); - IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, - "4.2.1", - "arm-apple-darwin10", - "v6"); - break; +void MachO::AddGnuCPlusPlusIncludePaths( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const {} - case llvm::Triple::aarch64: - IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, - "4.2.1", - "arm64-apple-darwin10", - ""); - break; - } +void DarwinClang::AddGnuCPlusPlusIncludePaths( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs); - if (!IsBaseFound) { - getDriver().Diag(diag::warn_drv_libstdcxx_not_found); - } + llvm::SmallString<128> UsrIncludeCxx = Sysroot; + llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++"); + + llvm::Triple::ArchType arch = getTriple().getArch(); + bool IsBaseFound = true; + switch (arch) { + default: + break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + IsBaseFound = AddGnuCPlusPlusIncludePaths( + DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1", "i686-apple-darwin10", + arch == llvm::Triple::x86_64 ? "x86_64" : ""); + IsBaseFound |= AddGnuCPlusPlusIncludePaths( + DriverArgs, CC1Args, UsrIncludeCxx, "4.0.0", "i686-apple-darwin8", ""); + break; + + case llvm::Triple::arm: + case llvm::Triple::thumb: + IsBaseFound = + AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1", + "arm-apple-darwin10", "v7"); + IsBaseFound |= + AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1", + "arm-apple-darwin10", "v6"); + break; + + case llvm::Triple::aarch64: + IsBaseFound = + AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1", + "arm64-apple-darwin10", ""); break; } + + if (!IsBaseFound) { + getDriver().Diag(diag::warn_drv_libstdcxx_not_found); + } } -void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { +void MachO::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + if (!isTargetAppleBased()) + return ToolChain::AddCXXStdlibLibArgs(Args, CmdArgs); + CXXStdlibType Type = GetCXXStdlibType(Args); switch (Type) { @@ -3615,7 +3637,10 @@ SanitizerMask Darwin::getSupportedSanitizers() const { return Res; } -void Darwin::printVerboseInfo(raw_ostream &OS) const { +void MachO::printVerboseInfo(raw_ostream &OS) const { + if (!isTargetAppleBased()) + return ToolChain::printVerboseInfo(OS); + CudaInstallation->print(OS); RocmInstallation->print(OS); } diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h index 2e55b49682a7e9..734b6416bbe0bf 100644 --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -180,6 +180,22 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain { llvm::opt::ArgStringList &CmdArgs, bool ForceLinkBuiltinRT = false) const; + void AddClangCXXStdlibIncludeArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + + void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + + void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + virtual void addStartObjectFileArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const { } @@ -195,6 +211,11 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain { /// this such a target? virtual bool isKernelStatic() const { return false; } + /// Is the target an Apple target? + bool isTargetAppleBased() const { + return getTriple().getVendor() == llvm::Triple::Apple; + } + /// Is the target either iOS or an iOS simulator? bool isTargetIOSBased() const { return false; } @@ -287,7 +308,20 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain { // Darwin toolchain uses legacy thin LTO API, which is not // capable of unit splitting. bool canSplitThinLTOUnit() const override { return false; } + + void printVerboseInfo(raw_ostream &OS) const override; /// } + + LazyDetector<CudaInstallationDetector> CudaInstallation; + LazyDetector<RocmInstallationDetector> RocmInstallation; + +protected: + llvm::SmallString<128> + GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const; + + virtual void + AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; }; /// Darwin - The base Darwin tool chain. @@ -329,9 +363,6 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO { /// The target variant triple that was specified (if any). mutable std::optional<llvm::Triple> TargetVariantTriple; - LazyDetector<CudaInstallationDetector> CudaInstallation; - LazyDetector<RocmInstallationDetector> RocmInstallation; - private: void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const; @@ -402,6 +433,8 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO { } public: + bool isTargetAppleBased() const { return true; } + bool isTargetIPhoneOS() const { assert(TargetInitialized && "Target not initialized!"); return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) && @@ -559,11 +592,6 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO { ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override; bool hasBlocksRuntime() const override; - void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const override; - void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const override; - bool UseObjCMixedDispatch() const override { // This is only used with the non-fragile ABI and non-legacy dispatch. @@ -594,8 +622,6 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO { bool SupportsEmbeddedBitcode() const override; SanitizerMask getSupportedSanitizers() const override; - - void printVerboseInfo(raw_ostream &OS) const override; }; /// DarwinClang - The Darwin toolchain used by Clang. @@ -613,16 +639,6 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin { llvm::opt::ArgStringList &CmdArgs, bool ForceLinkBuiltinRT = false) const override; - void AddClangCXXStdlibIncludeArgs( - const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const override; - - void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const override; - - void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const override; - void AddCCKextLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; @@ -647,15 +663,16 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin { StringRef Sanitizer, bool shared = true) const; + void + AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, llvm::SmallString<128> Base, llvm::StringRef Version, llvm::StringRef ArchDir, llvm::StringRef BitDir) const; - - llvm::SmallString<128> - GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const; }; } // end namespace toolchains diff --git a/clang/lib/Lex/InitHeaderSearch.cpp b/clang/lib/Lex/InitHeaderSearch.cpp index ea02f5dfb62644..e3d44d584a053a 100644 --- a/clang/lib/Lex/InitHeaderSearch.cpp +++ b/clang/lib/Lex/InitHeaderSearch.cpp @@ -312,7 +312,8 @@ bool InitHeaderSearch::ShouldAddDefaultIncludePaths( break; case llvm::Triple::UnknownOS: - if (triple.isWasm()) + if (triple.isWasm() || ((triple.getVendor() == llvm::Triple::Apple) && + triple.isOSBinFormatMachO())) return false; break; diff --git a/clang/test/Driver/darwin-embedded-search-paths.c b/clang/test/Driver/darwin-embedded-search-paths.c new file mode 100644 index 00000000000000..02db123dc91932 --- /dev/null +++ b/clang/test/Driver/darwin-embedded-search-paths.c @@ -0,0 +1,55 @@ +// UNSUPPORTED: system-windows +// Windows is unsupported because we use the Unix path separator `/` in the test. + +// Add default directories before running clang to check default +// search paths. +// RUN: rm -rf %t && mkdir -p %t +// RUN: cp -R %S/Inputs/MacOSX15.1.sdk %t/ +// RUN: mkdir -p %t/MacOSX15.1.sdk/usr/include +// RUN: mkdir -p %t/MacOSX15.1.sdk/usr/include/c++/v1 +// RUN: mkdir -p %t/MacOSX15.1.sdk/usr/local/include +// RUN: mkdir -p %t/MacOSX15.1.sdk/embedded/usr/include +// RUN: mkdir -p %t/MacOSX15.1.sdk/embedded/usr/local/include + +// Unlike the Darwin driver, the MachO driver doesn't add any framework search paths, +// only the normal header ones. +// RUN: %clang -xc %s -target arm64-apple-none-macho -isysroot %t/MacOSX15.1.sdk -E -v 2>&1 | FileCheck --check-prefix=CHECK-C %s +// +// CHECK-C: -isysroot [[SDKROOT:[^ ]*/MacOSX15.1.sdk]] +// CHECK-C: #include <...> search starts here: +// CHECK-C-NEXT: [[SDKROOT]]/usr/local/include +// CHECK-C-NEXT: /clang/{{.*}}/include +// CHECK-C-NEXT: [[SDKROOT]]/usr/include + +// Unlike the Darwin driver, the MachO driver doesn't default to libc++ +// RUN: %clang -xc++ %s -target arm64-apple-none-macho -isysroot %t/MacOSX15.1.sdk -E -v 2>&1 | FileCheck --check-prefix=CHECK-CXX %s +// +// CHECK-CXX: -isysroot [[SDKROOT:[^ ]*/MacOSX15.1.sdk]] +// CHECK-CXX: #include <...> search starts here: +// CHECK-CXX-NEXT: [[SDKROOT]]/usr/local/include +// CHECK-CXX-NEXT: /clang/{{.*}}/include +// CHECK-CXX-NEXT: [[SDKROOT]]/usr/include + +// However, if the user requests libc++, the MachO driver should find the search path. +// 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 +// +// CHECK-LIBCXX: -isysroot [[SDKROOT:[^ ]*/MacOSX15.1.sdk]] +// CHECK-LIBCXX: #include <...> search starts here: +// CHECK-LIBCXX-NEXT: [[SDKROOT]]/usr/include/c++/v1 +// CHECK-LIBCXX-NEXT: [[SDKROOT]]/usr/local/include +// CHECK-LIBCXX-NEXT: /clang/{{.*}}/include +// CHECK-LIBCXX-NEXT: [[SDKROOT]]/usr/include + +// Verify that embedded uses can swap in alternate usr/include and usr/local/include directories. +// usr/local/include is specified in the driver as -internal-isystem, however, the driver generated +// paths come before the paths in the driver arguments. In order to keep usr/local/include in the +// same position, -isystem has to be used instead of -Xclang -internal-isystem. There isn't an +// -externc-isystem, but it's ok to use -Xclang -internal-externc-isystem since the driver doesn't +// use that if -nostdlibinc or -nostdinc is passed. +// 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 +// +// CHECK-EMBEDDED: -isysroot [[SDKROOT:[^ ]*/MacOSX15.1.sdk]] +// CHECK-EMBEDDED: #include <...> search starts here: +// CHECK-EMBEDDED-NEXT: [[SDKROOT]]/embedded/usr/local/include +// CHECK-EMBEDDED-NEXT: /clang/{{.*}}/include +// CHECK-EMBEDDED-NEXT: [[SDKROOT]]/embedded/usr/include _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits