[clang] 3a9380f - [Multilib] Custom flags processing for library selection (#110659)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 16 01:35:59 PST 2025
Author: Victor Campos
Date: 2025-01-16T09:35:56Z
New Revision: 3a9380f21d05eb8ced03349c8c503dc911f22621
URL: https://github.com/llvm/llvm-project/commit/3a9380f21d05eb8ced03349c8c503dc911f22621
DIFF: https://github.com/llvm/llvm-project/commit/3a9380f21d05eb8ced03349c8c503dc911f22621.diff
LOG: [Multilib] Custom flags processing for library selection (#110659)
This patch is the third step to extend the current multilib system to
support the selection of library variants which do not correspond to
existing command-line options.
Proposal can be found in
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
The multilib mechanism supports libraries that target code generation or
language options such as --target, -mcpu, -mfpu, -mbranch-protection.
However, some library variants are particular to features that do not
correspond to any command-line options. Examples include variants for
multithreading and semihosting.
This work introduces a way to instruct the multilib system to consider
these features in library selection. This particular patch is comprised
of the core processing of these flags.
- Custom flags in the command-line are read and forwarded to the
multilib system. If multiple flag values are present for the same flag
declaration, the last one wins. Default flag values are inserted for
flag declarations for which no value was given.
- Feed `MacroDefines` back into the driver. Each item `<string>` in the
`MacroDefines` list is formatted as `-D<string>`.
Library variants should list their requirement on one or more custom
flags like they do for any other flag. The new command-line option is
passed as-is to the multilib system, therefore it should be listed in
the format `-fmultilib-flag=<str>`.
Moreover, a variant that does not specify a requirement on any
particular flag can be matched against any value of that flag.
If the user specifies `-fmultilib-flag=<name>` with a name that is
invalid, but close enough to any valid flag value name in terms of edit
distance, a suggesting error is shown:
```
error: unsupported option '-fmultilib-flag=invalidname'; did you mean '-fmultilib-flag=validname'?
```
The candidate with the smallest edit distance is chosen for the
suggestion, up to a certain maximum value (implementation detail), after
which a non-suggesting error is shown instead:
```
error: unsupported option '-fmultilib-flag=invalidname'
```
Added:
clang/test/Driver/baremetal-multilib-custom-flags.yaml
Modified:
clang/include/clang/Driver/Driver.h
clang/include/clang/Driver/Multilib.h
clang/include/clang/Driver/ToolChain.h
clang/lib/Driver/Driver.cpp
clang/lib/Driver/Multilib.cpp
clang/lib/Driver/ToolChains/BareMetal.cpp
clang/lib/Driver/ToolChains/BareMetal.h
Removed:
################################################################################
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index e2eec58ba99d36..f4a52cc529b79c 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -491,7 +491,7 @@ class Driver {
/// ArgList.
llvm::opt::InputArgList ParseArgStrings(ArrayRef<const char *> Args,
bool UseDriverMode,
- bool &ContainsError);
+ bool &ContainsError) const;
/// BuildInputs - Construct the list of inputs and their types from
/// the given arguments.
diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h
index 0a533ed2804e25..fc071ef48ca0f9 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -168,9 +168,18 @@ class MultilibSet {
const_iterator begin() const { return Multilibs.begin(); }
const_iterator end() const { return Multilibs.end(); }
+ /// Process custom flags from \p Flags and returns an expanded flags list and
+ /// a list of macro defines.
+ /// Returns a pair where:
+ /// - first: the new flags list including custom flags after processing.
+ /// - second: the extra macro defines to be fed to the driver.
+ std::pair<Multilib::flags_list, SmallVector<StringRef>>
+ processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
/// Select compatible variants, \returns false if none are compatible
bool select(const Driver &D, const Multilib::flags_list &Flags,
- llvm::SmallVectorImpl<Multilib> &) const;
+ llvm::SmallVectorImpl<Multilib> &,
+ llvm::SmallVector<StringRef> * = nullptr) const;
unsigned size() const { return Multilibs.size(); }
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 701a1d25ca4c8d..7d1d8feebf35e3 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -686,6 +686,13 @@ class ToolChain {
/// Add warning options that need to be passed to cc1 for this target.
virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
+ // Get the list of extra macro defines requested by the multilib
+ // configuration.
+ virtual SmallVector<std::string>
+ getMultilibMacroDefinesStr(llvm::opt::ArgList &Args) const {
+ return {};
+ };
+
// GetRuntimeLibType - Determine the runtime library type to use with the
// given compilation arguments.
virtual RuntimeLibType
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 7767c81d654dc3..87855fdb799710 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -308,7 +308,8 @@ void Driver::setDriverMode(StringRef Value) {
}
InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
- bool UseDriverMode, bool &ContainsError) {
+ bool UseDriverMode,
+ bool &ContainsError) const {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
ContainsError = false;
@@ -1674,13 +1675,31 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
std::unique_ptr<llvm::opt::InputArgList> UArgs =
std::make_unique<InputArgList>(std::move(Args));
+ // Owned by the host.
+ const ToolChain &TC =
+ getToolChain(*UArgs, computeTargetTriple(*this, TargetTriple, *UArgs));
+
+ {
+ SmallVector<std::string> MultilibMacroDefinesStr =
+ TC.getMultilibMacroDefinesStr(*UArgs);
+ SmallVector<const char *> MLMacroDefinesChar(
+ llvm::map_range(MultilibMacroDefinesStr, [&UArgs](const auto &S) {
+ return UArgs->MakeArgString(Twine("-D") + Twine(S));
+ }));
+ bool MLContainsError;
+ auto MultilibMacroDefineList =
+ std::make_unique<InputArgList>(ParseArgStrings(
+ MLMacroDefinesChar, /*UseDriverMode=*/false, MLContainsError));
+ if (!MLContainsError) {
+ for (auto *Opt : *MultilibMacroDefineList) {
+ appendOneArg(*UArgs, Opt);
+ }
+ }
+ }
+
// Perform the default argument translations.
DerivedArgList *TranslatedArgs = TranslateInputArgs(*UArgs);
- // Owned by the host.
- const ToolChain &TC = getToolChain(
- *UArgs, computeTargetTriple(*this, TargetTriple, *UArgs));
-
// Check if the environment version is valid except wasm case.
llvm::Triple Triple = TC.getTriple();
if (!Triple.isWasm()) {
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index ccf747e90cb2ca..efb99d3ffc752c 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -92,12 +92,145 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
-bool MultilibSet::select(const Driver &D, const Multilib::flags_list &Flags,
- llvm::SmallVectorImpl<Multilib> &Selected) const {
- llvm::StringSet<> FlagSet(expandFlags(Flags));
+static void DiagnoseUnclaimedMultilibCustomFlags(
+ const Driver &D, const SmallVector<StringRef> &UnclaimedCustomFlagValues,
+ const SmallVector<custom_flag::Declaration> &CustomFlagDecls) {
+ struct EditDistanceInfo {
+ StringRef FlagValue;
+ unsigned EditDistance;
+ };
+ const unsigned MaxEditDistance = 5;
+
+ for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+ std::optional<EditDistanceInfo> BestCandidate;
+ for (const auto &Decl : CustomFlagDecls) {
+ for (const auto &Value : Decl.ValueList) {
+ const std::string &FlagValueName = Value.Name;
+ unsigned EditDistance =
+ Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
+ /*MaxEditDistance=*/MaxEditDistance);
+ if (!BestCandidate || (EditDistance <= MaxEditDistance &&
+ EditDistance < BestCandidate->EditDistance)) {
+ BestCandidate = {FlagValueName, EditDistance};
+ }
+ }
+ }
+ if (!BestCandidate)
+ D.Diag(clang::diag::err_drv_unsupported_opt)
+ << (custom_flag::Prefix + Unclaimed).str();
+ else
+ D.Diag(clang::diag::err_drv_unsupported_opt_with_suggestion)
+ << (custom_flag::Prefix + Unclaimed).str()
+ << (custom_flag::Prefix + BestCandidate->FlagValue).str();
+ }
+}
+
+namespace clang::driver::custom_flag {
+// Map implemented using linear searches as the expected size is too small for
+// the overhead of a search tree or a hash table.
+class ValueNameToDetailMap {
+ SmallVector<std::pair<StringRef, const ValueDetail *>> Mapping;
+
+public:
+ template <typename It>
+ ValueNameToDetailMap(It FlagDeclsBegin, It FlagDeclsEnd) {
+ for (auto DeclIt = FlagDeclsBegin; DeclIt != FlagDeclsEnd; ++DeclIt) {
+ const Declaration &Decl = *DeclIt;
+ for (const auto &Value : Decl.ValueList)
+ Mapping.emplace_back(Value.Name, &Value);
+ }
+ }
+
+ const ValueDetail *get(StringRef Key) const {
+ auto Iter = llvm::find_if(
+ Mapping, [&](const auto &Pair) { return Pair.first == Key; });
+ return Iter != Mapping.end() ? Iter->second : nullptr;
+ }
+};
+} // namespace clang::driver::custom_flag
+
+std::pair<Multilib::flags_list, SmallVector<StringRef>>
+MultilibSet::processCustomFlags(const Driver &D,
+ const Multilib::flags_list &Flags) const {
+ Multilib::flags_list Result;
+ SmallVector<StringRef> MacroDefines;
+
+ // Custom flag values detected in the flags list
+ SmallVector<const custom_flag::ValueDetail *> ClaimedCustomFlagValues;
+
+ // Arguments to -fmultilib-flag=<arg> that don't correspond to any valid
+ // custom flag value. An error will be printed out for each of these.
+ SmallVector<StringRef> UnclaimedCustomFlagValueStrs;
+
+ const auto ValueNameToValueDetail = custom_flag::ValueNameToDetailMap(
+ CustomFlagDecls.begin(), CustomFlagDecls.end());
+
+ for (StringRef Flag : Flags) {
+ if (!Flag.starts_with(custom_flag::Prefix)) {
+ Result.push_back(Flag.str());
+ continue;
+ }
+
+ StringRef CustomFlagValueStr = Flag.substr(custom_flag::Prefix.size());
+ const custom_flag::ValueDetail *Detail =
+ ValueNameToValueDetail.get(CustomFlagValueStr);
+ if (Detail)
+ ClaimedCustomFlagValues.push_back(Detail);
+ else
+ UnclaimedCustomFlagValueStrs.push_back(CustomFlagValueStr);
+ }
+
+ // Set of custom flag declarations for which a value was passed in the flags
+ // list. This is used to, firstly, detect multiple values for the same flag
+ // declaration (in this case, the last one wins), and secondly, to detect
+ // which declarations had no value passed in (in this case, the default value
+ // is selected).
+ llvm::SmallPtrSet<custom_flag::Declaration *, 32> TriggeredCustomFlagDecls;
+
+ // Detect multiple values for the same flag declaration. Last one wins.
+ for (auto *CustomFlagValue : llvm::reverse(ClaimedCustomFlagValues)) {
+ if (!TriggeredCustomFlagDecls.insert(CustomFlagValue->Decl).second)
+ continue;
+ Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue->Name);
+ if (CustomFlagValue->MacroDefines)
+ MacroDefines.append(CustomFlagValue->MacroDefines->begin(),
+ CustomFlagValue->MacroDefines->end());
+ }
+
+ // Detect flag declarations with no value passed in. Select default value.
+ for (const auto &Decl : CustomFlagDecls) {
+ if (TriggeredCustomFlagDecls.contains(&Decl))
+ continue;
+ const custom_flag::ValueDetail &CustomFlagValue =
+ Decl.ValueList[*Decl.DefaultValueIdx];
+ Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue.Name);
+ if (CustomFlagValue.MacroDefines)
+ MacroDefines.append(CustomFlagValue.MacroDefines->begin(),
+ CustomFlagValue.MacroDefines->end());
+ }
+
+ DiagnoseUnclaimedMultilibCustomFlags(D, UnclaimedCustomFlagValueStrs,
+ CustomFlagDecls);
+
+ return {Result, MacroDefines};
+}
+
+bool MultilibSet::select(
+ const Driver &D, const Multilib::flags_list &Flags,
+ llvm::SmallVectorImpl<Multilib> &Selected,
+ llvm::SmallVector<StringRef> *CustomFlagMacroDefines) const {
+ auto [FlagsWithCustom, CFMacroDefines] = processCustomFlags(D, Flags);
+ llvm::StringSet<> FlagSet(expandFlags(FlagsWithCustom));
Selected.clear();
bool AnyErrors = false;
+ // Determining the list of macro defines depends only on the custom flags
+ // passed in. The library variants actually selected are not relevant in
+ // this. Therefore this assignment can take place before the selection
+ // happens.
+ if (CustomFlagMacroDefines)
+ *CustomFlagMacroDefines = std::move(CFMacroDefines);
+
// Decide which multilibs we're going to select at all.
llvm::DenseSet<StringRef> ExclusiveGroupsSelected;
for (const Multilib &M : llvm::reverse(Multilibs)) {
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index eecaaa9a42930d..ffb1c6e34d6039 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -162,9 +162,11 @@ static bool isPPCBareMetal(const llvm::Triple &Triple) {
Triple.getEnvironment() == llvm::Triple::EABI;
}
-static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
- StringRef MultilibPath, const ArgList &Args,
- DetectedMultilibs &Result) {
+static void
+findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
+ StringRef MultilibPath, const ArgList &Args,
+ DetectedMultilibs &Result,
+ SmallVector<StringRef> &CustomFlagsMacroDefines) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB =
D.getVFS().getBufferForFile(MultilibPath);
if (!MB)
@@ -175,7 +177,8 @@ static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
if (ErrorOrMultilibSet.getError())
return;
Result.Multilibs = ErrorOrMultilibSet.get();
- if (Result.Multilibs.select(D, Flags, Result.SelectedMultilibs))
+ if (Result.Multilibs.select(D, Flags, Result.SelectedMultilibs,
+ &CustomFlagsMacroDefines))
return;
D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
std::stringstream ss;
@@ -234,9 +237,13 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
// If multilib.yaml is found, update sysroot so it doesn't use a target
// specific suffix
SysRoot = computeBaseSysRoot(D, /*IncludeTriple=*/false);
- findMultilibsFromYAML(*this, D, *MultilibPath, Args, Result);
+ SmallVector<StringRef> CustomFlagMacroDefines;
+ findMultilibsFromYAML(*this, D, *MultilibPath, Args, Result,
+ CustomFlagMacroDefines);
SelectedMultilibs = Result.SelectedMultilibs;
Multilibs = Result.Multilibs;
+ MultilibMacroDefines.append(CustomFlagMacroDefines.begin(),
+ CustomFlagMacroDefines.end());
} else if (isRISCVBareMetal(Triple)) {
if (findRISCVMultilibs(D, Triple, Args, Result)) {
SelectedMultilibs = Result.SelectedMultilibs;
@@ -551,3 +558,8 @@ SanitizerMask BareMetal::getSupportedSanitizers() const {
}
return Res;
}
+
+SmallVector<std::string>
+BareMetal::getMultilibMacroDefinesStr(llvm::opt::ArgList &Args) const {
+ return MultilibMacroDefines;
+}
diff --git a/clang/lib/Driver/ToolChains/BareMetal.h b/clang/lib/Driver/ToolChains/BareMetal.h
index 483b5efab5e6e2..f6295bda0a6a2e 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/clang/lib/Driver/ToolChains/BareMetal.h
@@ -70,12 +70,17 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
std::string computeSysRoot() const override;
SanitizerMask getSupportedSanitizers() const override;
+ SmallVector<std::string>
+ getMultilibMacroDefinesStr(llvm::opt::ArgList &Args) const override;
+
private:
using OrderedMultilibs =
llvm::iterator_range<llvm::SmallVector<Multilib>::const_reverse_iterator>;
OrderedMultilibs getOrderedMultilibs() const;
std::string SysRoot;
+
+ SmallVector<std::string> MultilibMacroDefines;
};
} // namespace toolchains
diff --git a/clang/test/Driver/baremetal-multilib-custom-flags.yaml b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
new file mode 100644
index 00000000000000..9c0320ea16117a
--- /dev/null
+++ b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
@@ -0,0 +1,81 @@
+# UNSUPPORTED: system-windows
+
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabi -mfpu=none --sysroot= \
+# RUN: | FileCheck --check-prefix=CHECK-DEFAULT %s
+
+# CHECK-DEFAULT: "-cc1" "-triple" "thumbv8m.main-unknown-none-eabi"
+# CHECK-DEFAULT-SAME: "-internal-isystem" "[[SYSROOT:[^"]*]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/nofp/include"
+# CHECK-DEFAULT-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/nofp/lib"
+
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=no-multithreaded --sysroot= \
+# RUN: | FileCheck --check-prefix=CHECK-NOMULTI %s
+
+# CHECK-NOMULTI: "-cc1" "-triple" "thumbv8m.main-unknown-none-eabi"
+# CHECK-NOMULTI-SAME: "-internal-isystem" "[[SYSROOT:[^"]*]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/nofp/include"
+# CHECK-NOMULTI-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/nofp/lib"
+
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=multithreaded --sysroot= \
+# RUN: | FileCheck --check-prefix=CHECK-MULTI %s
+
+# CHECK-MULTI: "-cc1" "-triple" "thumbv8m.main-unknown-none-eabi"
+# CHECK-MULTI-SAME: "-internal-isystem" "[[SYSROOT:[^"]*]]/bin/../lib/clang-runtimes/arm-none-eabi/multithreaded/thumb/v8-m.main/nofp/include"
+# CHECK-MULTI-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/multithreaded/thumb/v8-m.main/nofp/lib"
+
+# RUN: not %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=singlethreaded -fmultilib-flag=no-io --sysroot= \
+# RUN: | FileCheck --check-prefix=CHECK-ERROR %s
+# CHECK-ERROR-DAG: error: unsupported option '-fmultilib-flag=singlethreaded'
+# CHECK-ERROR-DAG: error: unsupported option '-fmultilib-flag=no-io'; did you mean '-fmultilib-flag=io-none'?
+
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabi -mfpu=none -print-multi-lib --sysroot= \
+# RUN: | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/nofp;@-target=thumbv8m.main-unknown-none-eabi at mfpu=none at fmultilib-flag=no-multithreaded
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/multithreaded/thumb/v8-m.main/nofp;@-target=thumbv8m.main-unknown-none-eabi at mfpu=none at fmultilib-flag=multithreaded
+
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%s -x c %s -fmultilib-flag=no-multithreaded -### -o /dev/null 2>&1 \
+# RUN: | FileCheck --check-prefix=CHECK-MACRODEFINES-NOMULTI %s
+# CHECK-MACRODEFINES-NOMULTI: "-D" "__SINGLE_THREAD__"
+
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%s -x c %s -fmultilib-flag=io-semihosting -### -o /dev/null 2>&1 \
+# RUN: | FileCheck --check-prefix=CHECK-MACRODEFINES-IO-SEMIHOSTING %s
+# CHECK-MACRODEFINES-IO-SEMIHOSTING: "-D" "SEMIHOSTING"
+
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%s -x c %s -fmultilib-flag=io-linux-syscalls -### -o /dev/null 2>&1 \
+# RUN: | FileCheck --check-prefix=CHECK-MACRODEFINES-IO-LINUX %s
+# CHECK-MACRODEFINES-IO-LINUX: "-D" "LINUX_SYSCALLS"
+# CHECK-MACRODEFINES-IO-LINUX-SAME: "-D" "HOSTED"
+
+---
+MultilibVersion: 1.0
+
+Groups:
+- Name: stdlib
+ Type: Exclusive
+
+Variants:
+- Dir: arm-none-eabi/thumb/v8-m.main/nofp
+ Flags: [--target=thumbv8m.main-unknown-none-eabi, -mfpu=none, -fmultilib-flag=no-multithreaded]
+ Group: stdlib
+- Dir: arm-none-eabi/multithreaded/thumb/v8-m.main/nofp
+ Flags: [--target=thumbv8m.main-unknown-none-eabi, -mfpu=none, -fmultilib-flag=multithreaded]
+ Group: stdlib
+
+Flags:
+ - Name: multithreading
+ Values:
+ - Name: no-multithreaded
+ MacroDefines: [__SINGLE_THREAD__]
+ - Name: multithreaded
+ Default: no-multithreaded
+ - Name: io
+ Values:
+ - Name: io-none
+ - Name: io-semihosting
+ MacroDefines: [SEMIHOSTING]
+ - Name: io-linux-syscalls
+ MacroDefines: [LINUX_SYSCALLS, HOSTED]
+ Default: io-none
\ No newline at end of file
More information about the cfe-commits
mailing list