-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[Multilib] Extend the Multilib system to support an IncludeDirs field. #146651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This patch extends the Multilib Yaml format to allow specifying an IncludePath for the header path/s per multilib variant. The goal is to enable fine-grained control over header search paths for each multilib variant. This feature is especially useful in setups where header paths deviate from the default bare-metal assumptions. For example, when headers are shared across target triples, it becomes necessary to organize them under target-triple-specific directories to ensure correct resolution. In the Clang driver, GCCSuffix, OSSuffix and IncludeSuffix are path suffixes that help the compiler locate the correct set of headers and libraries for the selected target. Clang’s multilib infrastructure uses the Multilib class to encapsulate these suffixes. Currently, in the bare-metal Clang driver, all of these suffixes — GCCSuffix, OSSuffix, and IncludeSuffix — are effectively mapped to the Dir field specified in the multilib.yaml configuration. This patch allows it to be configured independently of Dir, enabling finer-grained control over header search paths for each multilib variant. Key Changes: New Field: IncludePath in multilib.yaml (header path or list of header paths, strings, optional). When present, this path is passed to the Multilib constructor and appended to the sysroot during header path resolution. If omitted, behaviour defaults to preserving current behaviour. For example, - Dir: aarch64-none-elf/aarch64a_exn_rtti_unaligned Flags: - --target=aarch64-unknown-none-elf IncludePath: - include - include-libunwind - aarch64-none-elf/include - aarch64-none-elf/aarch64a_exn_rtti_unaligned/include Implementation Notes: 1. Extend the YAML parser to read the IncludePath key. 2. Update the Multilib constructor to store the content from this field. 3. Ensure the driver logic reads and applies IncludePath correctly.
|
@llvm/pr-subscribers-clang-driver @llvm/pr-subscribers-clang Author: Simi Pallipurath (simpal01) ChangesThis patch extends the Multilib Yaml format to allow specifying an IncludePath for the header path/s per multilib variant. The goal is to enable fine-grained control over header search paths for each multilib variant. This feature is especially useful in setups where header paths deviate from the default bare-metal assumptions. For example, when headers are shared across target triples, it becomes necessary to organize them under target-triple-specific directories to ensure correct resolution. In the Clang driver, GCCSuffix, OSSuffix and IncludeSuffix are path suffixes that help the compiler locate the correct set of headers and libraries for the selected target. Clang’s multilib infrastructure uses the Multilib class to encapsulate these suffixes. Currently, in the bare-metal Clang driver, all of these suffixes — GCCSuffix, OSSuffix, and IncludeSuffix — are effectively mapped to the Dir field specified in the multilib.yaml configuration. This patch allows it to be configured independently of Dir, enabling finer-grained control over header search paths for each multilib variant. Key Changes:
For example,
Implementation Notes:
Full diff: https://github.com/llvm/llvm-project/pull/146651.diff 3 Files Affected:
diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h
index fc071ef48ca0f..1f1372508c480 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -35,12 +35,14 @@ class Driver;
class Multilib {
public:
using flags_list = std::vector<std::string>;
+ using includepath_list = std::vector<std::string>;
private:
std::string GCCSuffix;
std::string OSSuffix;
std::string IncludeSuffix;
flags_list Flags;
+ includepath_list IncludePath;
// Optionally, a multilib can be assigned a string tag indicating that it's
// part of a group of mutually exclusive possibilities. If two or more
@@ -62,6 +64,7 @@ class Multilib {
/// This is enforced with an assert in the constructor.
Multilib(StringRef GCCSuffix = {}, StringRef OSSuffix = {},
StringRef IncludeSuffix = {}, const flags_list &Flags = flags_list(),
+ const includepath_list &IncludePath = includepath_list(),
StringRef ExclusiveGroup = {},
std::optional<StringRef> Error = std::nullopt);
@@ -81,6 +84,10 @@ class Multilib {
/// All elements begin with either '-' or '!'
const flags_list &flags() const { return Flags; }
+ /// Get the include paths specified in multilib.yaml under the 'IncludePath'
+ /// field
+ const includepath_list &includePath() const { return IncludePath; }
+
/// Get the exclusive group label.
const std::string &exclusiveGroup() const { return ExclusiveGroup; }
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 87fa1af54a8ea..2cbb47dd7acdb 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -29,9 +29,11 @@ using namespace llvm::sys;
Multilib::Multilib(StringRef GCCSuffix, StringRef OSSuffix,
StringRef IncludeSuffix, const flags_list &Flags,
+ const includepath_list &IncludePath,
StringRef ExclusiveGroup, std::optional<StringRef> Error)
: GCCSuffix(GCCSuffix), OSSuffix(OSSuffix), IncludeSuffix(IncludeSuffix),
- Flags(Flags), ExclusiveGroup(ExclusiveGroup), Error(Error) {
+ Flags(Flags), IncludePath(IncludePath), ExclusiveGroup(ExclusiveGroup),
+ Error(Error) {
assert(GCCSuffix.empty() ||
(StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1));
assert(OSSuffix.empty() ||
@@ -299,6 +301,7 @@ struct MultilibSerialization {
std::string Dir; // if this record successfully selects a library dir
std::string Error; // if this record reports a fatal error message
std::vector<std::string> Flags;
+ std::vector<std::string> IncludePath;
std::string Group;
};
@@ -350,6 +353,7 @@ template <> struct llvm::yaml::MappingTraits<MultilibSerialization> {
io.mapOptional("Dir", V.Dir);
io.mapOptional("Error", V.Error);
io.mapRequired("Flags", V.Flags);
+ io.mapOptional("IncludePath", V.IncludePath);
io.mapOptional("Group", V.Group);
}
static std::string validate(IO &io, MultilibSerialization &V) {
@@ -359,6 +363,10 @@ template <> struct llvm::yaml::MappingTraits<MultilibSerialization> {
return "the 'Dir' and 'Error' keys may not both be specified";
if (StringRef(V.Dir).starts_with("/"))
return "paths must be relative but \"" + V.Dir + "\" starts with \"/\"";
+ for (const auto &Path : V.IncludePath) {
+ if (StringRef(Path).starts_with("/"))
+ return "paths must be relative but \"" + Path + "\" starts with \"/\"";
+ }
return std::string{};
}
};
@@ -489,7 +497,8 @@ MultilibSet::parseYaml(llvm::MemoryBufferRef Input,
Multilibs.reserve(MS.Multilibs.size());
for (const auto &M : MS.Multilibs) {
if (!M.Error.empty()) {
- Multilibs.emplace_back("", "", "", M.Flags, M.Group, M.Error);
+ Multilibs.emplace_back("", "", "", M.Flags, M.IncludePath, M.Group,
+ M.Error);
} else {
std::string Dir;
if (M.Dir != ".")
@@ -498,7 +507,7 @@ MultilibSet::parseYaml(llvm::MemoryBufferRef Input,
// Multilib constructor. If we later support more than one type of group,
// we'll have to look up the group name in MS.Groups, check its type, and
// decide what to do here.
- Multilibs.emplace_back(Dir, Dir, Dir, M.Flags, M.Group);
+ Multilibs.emplace_back(Dir, Dir, Dir, M.Flags, M.IncludePath, M.Group);
}
}
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index 981395deb9dbc..dfa801ce887c7 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -417,10 +417,20 @@ void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
const SmallString<128> SysRootDir(computeSysRoot());
if (!SysRootDir.empty()) {
for (const Multilib &M : getOrderedMultilibs()) {
- SmallString<128> Dir(SysRootDir);
- llvm::sys::path::append(Dir, M.includeSuffix());
- llvm::sys::path::append(Dir, "include");
- addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ // Add include paths specified in multilib.yaml under the 'IncludePath'
+ // field
+ if (!M.includePath().empty()) {
+ for (const std::string &Path : M.includePath()) {
+ SmallString<128> Dir(SysRoot);
+ llvm::sys::path::append(Dir, Path);
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
+ } else {
+ SmallString<128> Dir(SysRootDir);
+ llvm::sys::path::append(Dir, M.includeSuffix());
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
}
}
}
@@ -501,10 +511,21 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
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;
+ if (!M.includePath().empty()) {
+ // Add include paths specified in multilib.yaml under the 'IncludePath'
+ // field
+ for (const std::string &Path : M.includePath()) {
+ Dir = SysRoot;
+ llvm::sys::path::append(Dir, Path, "c++", "v1");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
+ break;
+ } else {
+ // 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++");
|
|
This pull request implements the feature proposed in the corresponding RFC https://discourse.llvm.org/t/rfc-support-target-triple-specific-include-paths-derived-from-sysroot-via-multilib-yaml-or-driver-logic/86925 It is being now changed to an open implementation to help explore the design further and gather feedback. |
| # (/include) to IncludePath triggers the expected | ||
| # error. | ||
|
|
||
| # # RUN: %clang --target=aarch64-none-elf --multi-lib-config=%s %s -### -o /dev/null 2>&1 \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit surprised that this double # doesn't stop the run from happening!
Also slightly surprised that you didn't need a not on the command line. Does the clang driver not return a failure status when it finds an error in multilib.yaml?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. It did not give me any failure
-- Testing: 1 tests, 1 workers --
PASS: Clang :: Driver/baremetal-multilib-includepath-error.yaml (1 of 1)
Exit Code: 0
Command Output (stderr):
--
/data_nvme1n1/LLVM-PROJECT/build-driver/bin/clang --target=aarch64-none-elf --multi-lib-config=/data_nvme1n1/LLVM-PROJECT/llvm-project-fork/clang/test/Driver/baremetal-multilib-includepath-error.yaml /data_nvme1n1/LLVM-PROJECT/llvm-project-fork/clang/test/Driver/baremetal-multilib-includepath-error.yaml -### -o /dev/null 2>&1 | /data_nvme1n1/LLVM-PROJECT/build-driver/bin/FileCheck /data_nvme1n1/LLVM-PROJECT/llvm-project-fork/clang/test/Driver/baremetal-multilib-includepath-error.yaml --check-prefix=CHECK-ERROR # RUN: at line 15
+ /data_nvme1n1/LLVM-PROJECT/build-driver/bin/clang --target=aarch64-none-elf --multi-lib-config=/data_nvme1n1/LLVM-PROJECT/llvm-project-fork/clang/test/Driver/baremetal-multilib-includepath-error.yaml /data_nvme1n1/LLVM-PROJECT/llvm-project-fork/clang/test/Driver/baremetal-multilib-includepath-error.yaml -### -o /dev/null
+ /data_nvme1n1/LLVM-PROJECT/build-driver/bin/FileCheck /data_nvme1n1/LLVM-PROJECT/llvm-project-fork/clang/test/Driver/baremetal-multilib-includepath-error.yaml --check-prefix=CHECK-ERROR
--
********************
Testing Time: 0.07s
Total Discovered Tests: 1
Passed: 1 (100.00%)
When running the command manually:
$ /data_nvme1n1/LLVM-PROJECT/build-driver/bin/clang --target=aarch64-none-elf --multi-lib-config=/data_nvme1n1/LLVM-PROJECT/llvm-project-fork/clang/test/Driver/baremetal-multilib-includepath-error.yaml /data_nvme1n1/LLVM-PROJECT/llvm-project-fork/clang/test/Driver/baremetal-multilib-includepath-error.yaml -### -o /dev/null 2>&1
/data_nvme1n1/LLVM-PROJECT/llvm-project-fork/clang/test/Driver/baremetal-multilib-includepath-error.yaml:22:3: error: paths must be relative but "/include" starts with "/"
- Dir: aarch64-none-elf/aarch64a_exn_rtti_unaligned
^
clang version 21.0.0git ([email protected]:simpal01/llvm-project-fork.git fe8fcbffbfc7c8a16285d3100f089b6528fb1329)
Target: aarch64-unknown-none-elf
Thread model: posix
InstalledDir: /data_nvme1n1/LLVM-PROJECT/build-driver/bin
ah! This might be because I unintentionally included -###, which only prints the driver’s command sequence without actually performing compilation.
After removing -###, it became necessary to include not to ensure the llvm-lit test passed.
Good catch Simon!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i will update the test accordingly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see! Well found.
The `-###` flag was unintentionally included, causing the compiler to only print the driver command sequence without performing compilation. This masked the need for the `not` command in the llvm-lit test. After removing `-###`, the missing `not` was added to correctly expect a failing compile, ensuring the test behaves as intended.
The current ATFE package redundantly duplicates identical C and C++ headers across more than 100 ibrary variants, despite the fact that these headers do not vary within a given target triple aside from few. As a result, each variant currently maintains its own include/ and include/c++/v1/ directories, leading to unnecessary duplication. This patch is to refactor the multilib layout to use a single shared header directory per target triple, eliminating redundant copies of identical headers across library variants, while keeping variant-specific headers within each variant’s own include/ directory. Changing the layout of the package structure will require corresponding updates to the ATFE build system, as it currently assumes a variant specific directory hierarchy for headers and libraries during installation and packaging. A new Python script has been introduced that runs after the runtime subproject has been executed for each variant and the non-optimised multilib directories have been generated. This script identifies and extracts common headers from the non-optimised multilibs and creates an optimized multilib directory. In this optimised directory, only the common headers are centralised, while the remaining contents are preserved as-is from the non-optimised layout. A CMake flag has been added to disable this multilib optimisation phase. When this flag is set, the optimised multilib directory will not be generated. Additionally, the optimisation step is skipped automatically if there are fewer than two multilib variants to build. To support this new layout with a centralised include directory, a new field called IncludePath has been added to multilib.yaml.This field specifies a base path for locating header files wich gets added to the header search path sequence by clang. Corresponding changes in Clang: llvm/llvm-project#146651
The current ATFE package redundantly duplicates identical C and C++ headers across more than 100 ibrary variants, despite the fact that these headers do not vary within a given target triple aside from few. As a result, each variant currently maintains its own include/ and include/c++/v1/ directories, leading to unnecessary duplication. This patch is to refactor the multilib layout to use a single shared header directory per target triple, eliminating redundant copies of identical headers across library variants, while keeping variant-specific headers within each variant’s own include/ directory. Changing the layout of the package structure will require corresponding updates to the ATFE build system, as it currently assumes a variant specific directory hierarchy for headers and libraries during installation and packaging. A new Python script has been introduced that runs after the runtime subproject has been executed for each variant and the non-optimised multilib directories have been generated. This script identifies and extracts common headers from the non-optimised multilibs and creates an optimised multilib directory. In this optimised directory, only the common headers are centralised, while the remaining contents are preserved as-is from the non-optimised layout. A CMake flag has been added to disable this multilib optimisation phase. When this flag is set, the optimised multilib directory will not be generated. Additionally, the optimisation step is skipped automatically if there are fewer than two multilib variants to build. To support this new layout with a centralised include directory, a new field called IncludePath has been added to multilib.yaml.This field specifies a base path for locating header files wich gets added to the header search path sequence by clang. Corresponding changes in Clang: llvm/llvm-project#146651
The current ATFE package redundantly duplicates identical C and C++ headers across more than 100 ibrary variants, despite the fact that these headers do not vary within a given target triple aside from few. As a result, each variant currently maintains its own include/ and include/c++/v1/ directories, leading to unnecessary duplication. This patch is to refactor the multilib layout to use a single shared header directory per target triple, eliminating redundant copies of identical headers across library variants, while keeping variant-specific headers within each variant’s own include/ directory. Changing the layout of the package structure will require corresponding updates to the ATFE build system, as it currently assumes a variant specific directory hierarchy for headers and libraries during installation and packaging. A new Python script has been introduced that runs after the runtime subproject has been executed for each variant and the non-optimised multilib directories have been generated. This script identifies and extracts common headers from the non-optimised multilibs and creates an optimised multilib directory. In this optimised directory, only the common headers are centralised, while the remaining contents are preserved as-is from the non-optimised layout. A CMake flag has been added to disable this multilib optimisation phase. When this flag is set, the optimised multilib directory will not be generated. Additionally, the optimisation step is skipped automatically if there are fewer than two multilib variants to build. To support this new layout with a centralised include directory, a new field called IncludePath has been added to multilib.yaml.This field specifies a base path for locating header files wich gets added to the header search path sequence by clang. Corresponding changes in Clang: llvm/llvm-project#146651
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
… downstream patching. The corresponding llvm patch is currently under upstream review: llvm/llvm-project#146651
…n IncludeDirs field. (#447) Downstream issue:#446. This patch extends the Multilib yaml format to allow specifying an IncludeDirs for the header path/s per multilib variant. The goal is to enable fine-grained control over header search paths for each multilib variant. This feature is especially useful in setups where header paths deviate from the default bare-metal assumptions. For example, when headers are shared across target triples, it becomes necessary to organise them under target-triple-specific directories to ensure correct resolution. This is already in upstream review llvm/llvm-project#146651. Since the review is pending, a downstream patch is made to enable IncludeDirs support in multilib.yaml
…423) The current ATFE package redundantly duplicates identical C and C++ headers across more than 100 ibrary variants, despite the fact that these headers do not vary within a given target triple aside from few. As a result, each variant currently maintains its own include/ and include/c++/v1/ directories, leading to unnecessary duplication. This patch is to refactor the multilib layout to use a single shared header directory per target triple, eliminating redundant copies of identical headers across library variants, while keeping variant-specific headers within each variant’s own include/ directory. Changing the layout of the package structure will require corresponding updates to the ATFE build system, as it currently assumes a variant specific directory hierarchy for headers and libraries during installation and packaging. A new Python script has been introduced that runs after the runtime subproject has been executed for each variant and the non-optimised multilib directories have been generated. This script identifies and extracts common headers from the non-optimised multilibs and creates an optimized multilib directory. In this optimised directory, only the common headers are centralised, while the remaining contents are preserved as-is from the non-optimised layout. A CMake flag called ENABLE_MULTILIB_HEADER_OPTIMISATION has been added to disable this multilib optimisation phase. When this flag is not set, the optimised multilib directory will not be generated. Additionally, the optimisation step is skipped automatically if there are fewer than two multilib variants to build. To support this new layout with a centralised include directory, a new field called IncludeDirs has been added to multilib.yaml. This field specifies a base directory for locating header files which gets added to the header search path sequence by clang. Corresponding changes in Clang: llvm/llvm-project#146651
…n IncludeDirs field. (arm#447) Downstream issue:arm#446. This patch extends the Multilib yaml format to allow specifying an IncludeDirs for the header path/s per multilib variant. The goal is to enable fine-grained control over header search paths for each multilib variant. This feature is especially useful in setups where header paths deviate from the default bare-metal assumptions. For example, when headers are shared across target triples, it becomes necessary to organise them under target-triple-specific directories to ensure correct resolution. This is already in upstream review llvm/llvm-project#146651. Since the review is pending, a downstream patch is made to enable IncludeDirs support in multilib.yaml [ATFE] Package common multilib headers into target triple directory. (arm#423) The current ATFE package redundantly duplicates identical C and C++ headers across more than 100 ibrary variants, despite the fact that these headers do not vary within a given target triple aside from few. As a result, each variant currently maintains its own include/ and include/c++/v1/ directories, leading to unnecessary duplication. This patch is to refactor the multilib layout to use a single shared header directory per target triple, eliminating redundant copies of identical headers across library variants, while keeping variant-specific headers within each variant’s own include/ directory. Changing the layout of the package structure will require corresponding updates to the ATFE build system, as it currently assumes a variant specific directory hierarchy for headers and libraries during installation and packaging. A new Python script has been introduced that runs after the runtime subproject has been executed for each variant and the non-optimised multilib directories have been generated. This script identifies and extracts common headers from the non-optimised multilibs and creates an optimized multilib directory. In this optimised directory, only the common headers are centralised, while the remaining contents are preserved as-is from the non-optimised layout. A CMake flag called ENABLE_MULTILIB_HEADER_OPTIMISATION has been added to disable this multilib optimisation phase. When this flag is not set, the optimised multilib directory will not be generated. Additionally, the optimisation step is skipped automatically if there are fewer than two multilib variants to build. To support this new layout with a centralised include directory, a new field called IncludeDirs has been added to multilib.yaml. This field specifies a base directory for locating header files which gets added to the header search path sequence by clang. Corresponding changes in Clang: llvm/llvm-project#146651 [ATFE] Prioritize multilib-specific headers over target-level headers. (arm#451) Adjust the header search order so that variant-specific directories (e.g armv6m_soft_nofp_size/include/) are searched before the common target-level directories (e.g include/) in the -internal-isystem list. This ensures that headers tailored for a specific multilib variant take precedence over the generic headers, allowing correct header resolution in the presence of overrides. Previously, the common target-level directory could shadow multilib-specific headers if the same file existed in both paths.
…n IncludeDirs field. (arm#447) Downstream issue:arm#446. This patch extends the Multilib yaml format to allow specifying an IncludeDirs for the header path/s per multilib variant. The goal is to enable fine-grained control over header search paths for each multilib variant. This feature is especially useful in setups where header paths deviate from the default bare-metal assumptions. For example, when headers are shared across target triples, it becomes necessary to organise them under target-triple-specific directories to ensure correct resolution. This is already in upstream review llvm/llvm-project#146651. Since the review is pending, a downstream patch is made to enable IncludeDirs support in multilib.yaml
…rm#423) The current ATFE package redundantly duplicates identical C and C++ headers across more than 100 ibrary variants, despite the fact that these headers do not vary within a given target triple aside from few. As a result, each variant currently maintains its own include/ and include/c++/v1/ directories, leading to unnecessary duplication. This patch is to refactor the multilib layout to use a single shared header directory per target triple, eliminating redundant copies of identical headers across library variants, while keeping variant-specific headers within each variant’s own include/ directory. Changing the layout of the package structure will require corresponding updates to the ATFE build system, as it currently assumes a variant specific directory hierarchy for headers and libraries during installation and packaging. A new Python script has been introduced that runs after the runtime subproject has been executed for each variant and the non-optimised multilib directories have been generated. This script identifies and extracts common headers from the non-optimised multilibs and creates an optimized multilib directory. In this optimised directory, only the common headers are centralised, while the remaining contents are preserved as-is from the non-optimised layout. A CMake flag called ENABLE_MULTILIB_HEADER_OPTIMISATION has been added to disable this multilib optimisation phase. When this flag is not set, the optimised multilib directory will not be generated. Additionally, the optimisation step is skipped automatically if there are fewer than two multilib variants to build. To support this new layout with a centralised include directory, a new field called IncludeDirs has been added to multilib.yaml. This field specifies a base directory for locating header files which gets added to the header search path sequence by clang. Corresponding changes in Clang: llvm/llvm-project#146651
…n IncludeDirs field. (arm#447) Downstream issue:arm#446. This patch extends the Multilib yaml format to allow specifying an IncludeDirs for the header path/s per multilib variant. The goal is to enable fine-grained control over header search paths for each multilib variant. This feature is especially useful in setups where header paths deviate from the default bare-metal assumptions. For example, when headers are shared across target triples, it becomes necessary to organise them under target-triple-specific directories to ensure correct resolution. This is already in upstream review llvm/llvm-project#146651. Since the review is pending, a downstream patch is made to enable IncludeDirs support in multilib.yaml
…rm#423) The current ATFE package redundantly duplicates identical C and C++ headers across more than 100 ibrary variants, despite the fact that these headers do not vary within a given target triple aside from few. As a result, each variant currently maintains its own include/ and include/c++/v1/ directories, leading to unnecessary duplication. This patch is to refactor the multilib layout to use a single shared header directory per target triple, eliminating redundant copies of identical headers across library variants, while keeping variant-specific headers within each variant’s own include/ directory. Changing the layout of the package structure will require corresponding updates to the ATFE build system, as it currently assumes a variant specific directory hierarchy for headers and libraries during installation and packaging. A new Python script has been introduced that runs after the runtime subproject has been executed for each variant and the non-optimised multilib directories have been generated. This script identifies and extracts common headers from the non-optimised multilibs and creates an optimized multilib directory. In this optimised directory, only the common headers are centralised, while the remaining contents are preserved as-is from the non-optimised layout. A CMake flag called ENABLE_MULTILIB_HEADER_OPTIMISATION has been added to disable this multilib optimisation phase. When this flag is not set, the optimised multilib directory will not be generated. Additionally, the optimisation step is skipped automatically if there are fewer than two multilib variants to build. To support this new layout with a centralised include directory, a new field called IncludeDirs has been added to multilib.yaml. This field specifies a base directory for locating header files which gets added to the header search path sequence by clang. Corresponding changes in Clang: llvm/llvm-project#146651
…n IncludeDirs field. (#447) Downstream issue:#446. This patch extends the Multilib yaml format to allow specifying an IncludeDirs for the header path/s per multilib variant. The goal is to enable fine-grained control over header search paths for each multilib variant. This feature is especially useful in setups where header paths deviate from the default bare-metal assumptions. For example, when headers are shared across target triples, it becomes necessary to organise them under target-triple-specific directories to ensure correct resolution. This is already in upstream review llvm/llvm-project#146651. Since the review is pending, a downstream patch is made to enable IncludeDirs support in multilib.yaml
…423) The current ATFE package redundantly duplicates identical C and C++ headers across more than 100 ibrary variants, despite the fact that these headers do not vary within a given target triple aside from few. As a result, each variant currently maintains its own include/ and include/c++/v1/ directories, leading to unnecessary duplication. This patch is to refactor the multilib layout to use a single shared header directory per target triple, eliminating redundant copies of identical headers across library variants, while keeping variant-specific headers within each variant’s own include/ directory. Changing the layout of the package structure will require corresponding updates to the ATFE build system, as it currently assumes a variant specific directory hierarchy for headers and libraries during installation and packaging. A new Python script has been introduced that runs after the runtime subproject has been executed for each variant and the non-optimised multilib directories have been generated. This script identifies and extracts common headers from the non-optimised multilibs and creates an optimized multilib directory. In this optimised directory, only the common headers are centralised, while the remaining contents are preserved as-is from the non-optimised layout. A CMake flag called ENABLE_MULTILIB_HEADER_OPTIMISATION has been added to disable this multilib optimisation phase. When this flag is not set, the optimised multilib directory will not be generated. Additionally, the optimisation step is skipped automatically if there are fewer than two multilib variants to build. To support this new layout with a centralised include directory, a new field called IncludeDirs has been added to multilib.yaml. This field specifies a base directory for locating header files which gets added to the header search path sequence by clang. Corresponding changes in Clang: llvm/llvm-project#146651
This patch extends the Multilib Yaml format to allow specifying an IncludeDirs for the header path/s per multilib variant. The goal is to enable fine-grained control over header search paths for each multilib variant. This feature is especially useful in setups where header paths deviate from the default bare-metal assumptions. For example, when headers are shared across target triples, it becomes necessary to organize them under target-triple-specific directories to ensure correct resolution.
In the Clang driver, GCCSuffix, OSSuffix and IncludeSuffix are path suffixes that help the compiler locate the correct set of headers and libraries for the selected target. Clang’s multilib infrastructure uses the Multilib class to encapsulate these suffixes. Currently, in the bare-metal Clang driver, all of these suffixes — GCCSuffix, OSSuffix, and IncludeSuffix — are effectively mapped to the Dir field specified in the multilib.yaml configuration.
This patch allows it to be configured independently of Dir, enabling finer-grained control over header search directories for each multilib variant.
Key Changes:
New Field: IncludeDirs in multilib.yaml (header directory or list of header directories, strings, optional).
When present, this path is passed to the Multilib constructor and appended to the sysroot during header path resolution. If omitted, behaviour defaults to preserving current behaviour.
For example,
Implementation Notes: