[clang] ab2c80b - [Driver] BareMetal ToolChain multilib layering
Michael Platings via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 13 22:47:26 PDT 2023
Author: Michael Platings
Date: 2023-06-14T06:46:41+01:00
New Revision: ab2c80bb125634816e39a1e4787a5a103cd03a74
URL: https://github.com/llvm/llvm-project/commit/ab2c80bb125634816e39a1e4787a5a103cd03a74
DIFF: https://github.com/llvm/llvm-project/commit/ab2c80bb125634816e39a1e4787a5a103cd03a74.diff
LOG: [Driver] BareMetal ToolChain multilib layering
This enables layering baremetal multilibs on top of each other.
For example a multilib containing only a no-exceptions libc++ could be
layered on top of a multilib containing C libs. This avoids the need
to duplicate the C library for every libc++ variant.
Differential Revision: https://reviews.llvm.org/D143075
Added:
clang/test/Driver/baremetal-multilib-layered.yaml
Modified:
clang/lib/Driver/ToolChains/BareMetal.cpp
clang/lib/Driver/ToolChains/BareMetal.h
Removed:
################################################################################
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index 748f24e151aa5..17fd1f88975b9 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -103,9 +103,12 @@ BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
findMultilibs(D, Triple, Args);
SmallString<128> SysRoot(computeSysRoot());
if (!SysRoot.empty()) {
- llvm::sys::path::append(SysRoot, "lib");
- getFilePaths().push_back(std::string(SysRoot));
- getLibraryPaths().push_back(std::string(SysRoot));
+ for (const Multilib &M : getOrderedMultilibs()) {
+ SmallString<128> Dir(SysRoot);
+ llvm::sys::path::append(Dir, M.osSuffix(), "lib");
+ getFilePaths().push_back(std::string(Dir));
+ getLibraryPaths().push_back(std::string(Dir));
+ }
}
}
@@ -222,10 +225,17 @@ Tool *BareMetal::buildLinker() const {
}
std::string BareMetal::computeSysRoot() const {
- std::string Result = computeBaseSysRoot(getDriver(), getTriple());
+ return computeBaseSysRoot(getDriver(), getTriple());
+}
+
+BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
+ // Get multilibs in reverse order because they're ordered most-specific last.
if (!SelectedMultilibs.empty())
- Result += SelectedMultilibs.back().osSuffix();
- return Result;
+ return llvm::reverse(SelectedMultilibs);
+
+ // No multilibs selected so return a single default multilib.
+ static const llvm::SmallVector<Multilib> Default = {Multilib()};
+ return llvm::reverse(Default);
}
void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -240,10 +250,14 @@ void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
}
if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
- SmallString<128> Dir(computeSysRoot());
- if (!Dir.empty()) {
- llvm::sys::path::append(Dir, "include");
- addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ const SmallString<128> SysRoot(computeSysRoot());
+ if (!SysRoot.empty()) {
+ for (const Multilib &M : getOrderedMultilibs()) {
+ SmallString<128> Dir(SysRoot);
+ llvm::sys::path::append(Dir, M.includeSuffix());
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
}
}
}
@@ -266,44 +280,47 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
if (SysRoot.empty())
return;
- switch (GetCXXStdlibType(DriverArgs)) {
- case ToolChain::CST_Libcxx: {
- // First check sysroot/usr/include/c++/v1 if it exists.
- SmallString<128> TargetDir(SysRoot);
- llvm::sys::path::append(TargetDir, "usr", "include", "c++", "v1");
- if (D.getVFS().exists(TargetDir)) {
- addSystemInclude(DriverArgs, CC1Args, TargetDir.str());
+ for (const Multilib &M : getOrderedMultilibs()) {
+ SmallString<128> Dir(SysRoot);
+ llvm::sys::path::append(Dir, M.gccSuffix());
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx: {
+ // First check sysroot/usr/include/c++/v1 if it exists.
+ SmallString<128> TargetDir(Dir);
+ llvm::sys::path::append(TargetDir, "usr", "include", "c++", "v1");
+ if (D.getVFS().exists(TargetDir)) {
+ addSystemInclude(DriverArgs, CC1Args, TargetDir.str());
+ break;
+ }
+ // Add generic path if nothing else succeeded so far.
+ llvm::sys::path::append(Dir, "include", "c++", "v1");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ break;
+ }
+ case ToolChain::CST_Libstdcxx: {
+ llvm::sys::path::append(Dir, "include", "c++");
+ std::error_code EC;
+ Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""};
+ // Walk the subdirs, and find the one with the newest gcc version:
+ for (llvm::vfs::directory_iterator
+ LI = D.getVFS().dir_begin(Dir.str(), EC),
+ LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
+ auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText);
+ if (CandidateVersion.Major == -1)
+ continue;
+ if (CandidateVersion <= Version)
+ continue;
+ Version = CandidateVersion;
+ }
+ if (Version.Major != -1) {
+ llvm::sys::path::append(Dir, Version.Text);
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
break;
}
- // Add generic path if nothing else succeeded so far.
- SmallString<128> Dir(SysRoot);
- llvm::sys::path::append(Dir, "include", "c++", "v1");
- addSystemInclude(DriverArgs, CC1Args, Dir.str());
- break;
- }
- case ToolChain::CST_Libstdcxx: {
- SmallString<128> Dir(SysRoot);
- llvm::sys::path::append(Dir, "include", "c++");
- std::error_code EC;
- Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""};
- // Walk the subdirs, and find the one with the newest gcc version:
- for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Dir.str(), EC),
- LE;
- !EC && LI != LE; LI = LI.increment(EC)) {
- StringRef VersionText = llvm::sys::path::filename(LI->path());
- auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText);
- if (CandidateVersion.Major == -1)
- continue;
- if (CandidateVersion <= Version)
- continue;
- Version = CandidateVersion;
}
- if (Version.Major == -1)
- return;
- llvm::sys::path::append(Dir, Version.Text);
- addSystemInclude(DriverArgs, CC1Args, Dir.str());
- break;
- }
}
}
diff --git a/clang/lib/Driver/ToolChains/BareMetal.h b/clang/lib/Driver/ToolChains/BareMetal.h
index 54de97c734c19..e594b12a7c924 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/clang/lib/Driver/ToolChains/BareMetal.h
@@ -71,6 +71,11 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
std::string computeSysRoot() const override;
+
+private:
+ using OrderedMultilibs =
+ llvm::iterator_range<llvm::SmallVector<Multilib>::const_reverse_iterator>;
+ OrderedMultilibs getOrderedMultilibs() const;
};
} // namespace toolchains
diff --git a/clang/test/Driver/baremetal-multilib-layered.yaml b/clang/test/Driver/baremetal-multilib-layered.yaml
new file mode 100644
index 0000000000000..2f86f8e3ea4f5
--- /dev/null
+++ b/clang/test/Driver/baremetal-multilib-layered.yaml
@@ -0,0 +1,45 @@
+# REQUIRES: shell
+# UNSUPPORTED: system-windows
+
+# This test demonstrates "layered" multilib in which more than one
+# multilib is matched.
+# For example a multilib containing only a no-exceptions libc++ could
+# be layered on top of a multilib containing C libs. This avoids the
+# need to duplicate the C library for every libc++ variant.
+# However -fno-exceptions is not yet supported for multilib selection
+# so we use a more contrived -mfloat-abi example instead.
+
+# RUN: rm -rf %T/baremetal_multilib_layered
+# RUN: mkdir -p %T/baremetal_multilib_layered/bin
+# RUN: mkdir -p %T/baremetal_multilib_layered/lib/clang-runtimes
+# RUN: ln -s %clang %T/baremetal_multilib_layered/bin/clang
+# RUN: ln -s %s %T/baremetal_multilib_layered/lib/clang-runtimes/multilib.yaml
+
+# RUN: %T/baremetal_multilib_layered/bin/clang -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \
+# RUN: --target=thumbv7m-none-eabi -mfloat-abi=softfp --sysroot= \
+# RUN: | FileCheck -DSYSROOT=%T/baremetal_multilib_layered %s
+# CHECK: "-cc1" "-triple" "thumbv7m-none-unknown-eabi"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/softfp/include/c++/v1"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/soft/include/c++/v1"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/softfp/include"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/soft/include"
+# CHECK-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/softfp/lib"
+# CHECK-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/soft/lib"
+
+# RUN: %T/baremetal_multilib_layered/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: --target=arm-none-eabi -mfloat-abi=softfp --sysroot= \
+# RUN: | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
+# CHECK-PRINT-MULTI-DIRECTORY: soft
+# CHECK-PRINT-MULTI-DIRECTORY-NEXT: softfp
+
+---
+MultilibVersion: 1.0
+Variants:
+- Dir: soft
+ Flags: [-mfloat-abi=soft]
+- Dir: softfp
+ Flags: [-mfloat-abi=softfp]
+Mappings:
+- Match: -mfloat-abi=softfp
+ Flags: [-mfloat-abi=soft]
+...
More information about the cfe-commits
mailing list