Skip to content

Commit 56a611f

Browse files
committed
Generate and install a multilib.yaml file.
The multilib system added to clang by the previous commit doesn't do anything unless a YAML configuration file is available at run time. This commit adds one. This makes the .cfg files optional, although they're still available to be used if a user prefers. For example, these two commands have the same effect of building a semihosting hello-world program for Armv7-M, with and without a config file: clang --config=armv7m_soft_nofp_semihost.cfg -T picolibc.ld hello.c clang --target=arm-none-eabi -march=armv7-m -T picolibc.ld -lcrt0-semihost -lsemihost hello.c The multilib.yaml is built by a CMake configure_file command, starting from a template containing a static FlagMap section, and filling in the Variants section to match the set of library variants actually being built. Each library must now provide a set of multilib selection flags along with the compile flags for the library itself. Documentation for the YAML format can be found in clang/docs/Multilib.rst, which is included in the previous commit's patch update, or alternatively in https://reviews.llvm.org/D143587.
1 parent c953903 commit 56a611f

File tree

3 files changed

+178
-23
lines changed

3 files changed

+178
-23
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1111
- Support for locales and input/output streams
1212
- Experimental support for Armv4T and Armv5TE architectures (#177)
1313
- Support for building locally on Windows & macOS (#188)
14+
- Experimental support for multilib, meaning that clang can now automatically select an appropriate set of libraries based on your compile flags, without needing either an explicit `--sysroot` option or a `--config` option. However, the config files are still present, and you can still use them instead.
1415

1516
### Fixed
1617

CMakeLists.txt

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ function(add_picolibc directory variant target_triple flags qemu_params variant_
422422
INSTALL_DIR "${LLVM_BINARY_DIR}/${directory}"
423423
PREFIX picolibc/${variant}
424424
DEPENDS clang lld llvm-ar llvm-config llvm-nm llvm-ranlib llvm-strip
425-
CONFIGURE_COMMAND ${MESON_EXECUTABLE} -Dincludedir=include -Dlibdir=lib -Dspecsdir=none --prefix <INSTALL_DIR> --cross-file <BINARY_DIR>/meson-cross-build.txt ${picolibc_SOURCE_DIR}
425+
CONFIGURE_COMMAND ${MESON_EXECUTABLE} -Dincludedir=include -Dlibdir=lib -Dspecsdir=none -Dmultilib=false --prefix <INSTALL_DIR> --cross-file <BINARY_DIR>/meson-cross-build.txt ${picolibc_SOURCE_DIR}
426426
BUILD_COMMAND ninja
427427
INSTALL_COMMAND ${MESON_EXECUTABLE} install ${MESON_INSTALL_QUIET}
428428
USES_TERMINAL_CONFIGURE TRUE
@@ -743,7 +743,7 @@ function(get_compiler_rt_target_triple target_arch)
743743
else()
744744
set(target_triple "arm-none-eabi")
745745
endif()
746-
if(flags MATCHES "-mfloat-abi=hard")
746+
if(compile_flags MATCHES "-mfloat-abi=hard")
747747
# Also, compiler-rt looks in the ABI component of the
748748
# triple to decide whether to use the hard float ABI.
749749
set(target_triple "${target_triple}hf")
@@ -755,7 +755,7 @@ endfunction()
755755
function(add_library_variants)
756756
set(variant_args "${ARGN}")
757757
while(variant_args)
758-
list(POP_FRONT variant_args target_arch variant_suffix flags qemu_params)
758+
list(POP_FRONT variant_args target_arch variant_suffix compile_flags multilib_flags qemu_params)
759759

760760
if(variant_suffix)
761761
set(variant "${target_arch}_${variant_suffix}")
@@ -781,45 +781,73 @@ function(add_library_variants)
781781
get_compiler_rt_target_triple(${target_arch})
782782

783783
set(directory "lib/clang-runtimes/${parent_dir_name}/${variant}")
784-
set(flags "--target=${target_triple} ${flags}")
785-
make_config_cfg("${directory}" "${variant}" "${flags}")
784+
set(compile_flags "--target=${target_triple} ${compile_flags}")
785+
make_config_cfg("${directory}" "${variant}" "${compile_flags}")
786786
set(variant_options)
787787
if(NOT PREBUILT_TARGET_LIBRARIES)
788-
add_picolibc("${directory}" "${variant}" "${target_triple}" "${flags}" "${qemu_params}" variant_options)
789-
add_compiler_rt("${directory}" "${variant}" "${target_triple}" "${flags}" "picolibc_${variant}")
788+
add_picolibc("${directory}" "${variant}" "${target_triple}" "${compile_flags}" "${qemu_params}" variant_options)
789+
add_compiler_rt("${directory}" "${variant}" "${target_triple}" "${compile_flags}" "picolibc_${variant}")
790790
list(APPEND variant_options ${picolibc_specific_runtimes_options})
791-
add_libcxx_libcxxabi_libunwind("${directory}" "${variant}" "${target_triple}" "${flags}" "picolibc_${variant}" "${variant_options}")
792-
if(flags MATCHES "-march=armv8")
791+
add_libcxx_libcxxabi_libunwind("${directory}" "${variant}" "${target_triple}" "${compile_flags}" "picolibc_${variant}" "${variant_options}")
792+
if(compile_flags MATCHES "-march=armv8")
793793
message("C++ runtime libraries tests disabled for ${variant}")
794794
else()
795795
add_libcxx_libcxxabi_libunwind_tests("${variant}")
796796
endif()
797797
endif()
798798

799+
string(APPEND multilib_variants "- Dir: ${parent_dir_name}/${variant}\n")
800+
801+
string(APPEND multilib_variants " Flags:\n")
802+
string(REPLACE " " ";" multilib_flags_list ${multilib_flags})
803+
foreach(flag ${multilib_flags_list})
804+
string(APPEND multilib_variants " - ${flag}\n")
805+
endforeach()
806+
807+
string(APPEND multilib_variants " PrintOptions:\n")
808+
string(REPLACE " " ";" multilib_printoptions_list ${compile_flags})
809+
foreach(option ${multilib_printoptions_list})
810+
string(APPEND multilib_variants " - ${option}\n")
811+
endforeach()
812+
799813
install(
800814
DIRECTORY "${LLVM_BINARY_DIR}/${directory}/"
801815
DESTINATION "${directory}"
802816
COMPONENT llvm-toolchain
803817
)
804818
endwhile()
819+
set(multilib_variants "${multilib_variants}" PARENT_SCOPE)
805820
endfunction()
806821

822+
set(multilib_variants "")
823+
807824
# Define which library variants to build and which flags to use.
808-
# The order is <parent dir> <arch> <name suffix> <flags> <qemu params>
825+
# The order is <arch> <name suffix> <compile flags> <multilib selection flags> <qemu params>
809826
add_library_variants(
810-
aarch64 "" "-march=armv8-a" "-M raspi3b"
811-
armv4t "" "-march=armv4t" "-M musicpal -cpu arm926"
812-
armv5te "" "-march=armv5te" "-M musicpal -cpu arm926"
813-
armv6m soft_nofp "-mfloat-abi=soft -march=armv6m" "-M microbit"
814-
armv7m soft_nofp "-mfloat-abi=soft -march=armv7m+nofp" "-M mps2-an385 -cpu cortex-m3"
815-
armv7em soft_nofp "-mfloat-abi=soft -march=armv7em -mfpu=none" "-M mps2-an386 -cpu cortex-m4"
816-
armv7em hard_fpv4_sp_d16 "-mfloat-abi=hard -march=armv7em -mfpu=fpv4-sp-d16" "-M mps2-an386 -cpu cortex-m4"
817-
armv7em hard_fpv5_d16 "-mfloat-abi=hard -march=armv7em -mfpu=fpv5-d16" "-M mps2-an500 -cpu cortex-m7"
818-
armv8m.main soft_nofp "-mfloat-abi=soft -march=armv8m.main+nofp" "-M mps2-an505 -cpu cortex-m33"
819-
armv8m.main hard_fp "-mfloat-abi=hard -march=armv8m.main+fp" "-M mps3-an524 -cpu cortex-m33"
820-
armv8.1m.main soft_nofp_nomve "-mfloat-abi=soft -march=armv8.1m.main+nofp+nomve" "-M mps3-an547 -cpu cortex-m55"
821-
armv8.1m.main hard_fp "-mfloat-abi=hard -march=armv8.1m.main+fp" "-M mps3-an547 -cpu cortex-m55"
822-
armv8.1m.main hard_nofp_mve "-mfloat-abi=hard -march=armv8.1m.main+nofp+mve" "-M mps3-an547 -cpu cortex-m55"
827+
aarch64 "" "" "target=aarch64-none-unknown-elf" "-M raspi3b"
828+
armv4t "" "-march=armv4t" "target=armv4t-none-unknown-eabi mfpu=none" "-M musicpal -cpu arm926"
829+
armv5te "" "-march=armv5te" "target=armv5e-none-unknown-eabi mfpu=none" "-M musicpal -cpu arm926"
830+
armv6m soft_nofp "-mfloat-abi=soft -march=armv6m" "target=thumbv6m-none-unknown-eabi mfpu=none" "-M microbit"
831+
armv7m soft_nofp "-mfloat-abi=soft -march=armv7m+nofp" "target=thumbv7m-none-unknown-eabi mfpu=none" "-M mps2-an385 -cpu cortex-m3"
832+
armv7em soft_nofp "-mfloat-abi=soft -march=armv7em -mfpu=none" "target=thumbv7em-none-unknown-eabi mfpu=none" "-M mps2-an386 -cpu cortex-m4"
833+
armv7em hard_fpv4_sp_d16 "-mfloat-abi=hard -march=armv7em -mfpu=fpv4-sp-d16" "target=thumbv7em-none-unknown-eabihf mfpu=fpv4-sp-d16" "-M mps2-an386 -cpu cortex-m4"
834+
armv7em hard_fpv5_d16 "-mfloat-abi=hard -march=armv7em -mfpu=fpv5-d16" "target=thumbv7em-none-unknown-eabihf mfpu=fpv5-d16" "-M mps2-an500 -cpu cortex-m7"
835+
armv8m.main soft_nofp "-mfloat-abi=soft -march=armv8m.main+nofp" "target=thumbv8m.main-none-unknown-eabi mfpu=none" "-M mps2-an505 -cpu cortex-m33"
836+
armv8m.main hard_fp "-mfloat-abi=hard -march=armv8m.main+fp" "target=thumbv8m.main-none-unknown-eabihf mfpu=fpv5-d16" "-M mps3-an524 -cpu cortex-m33"
837+
armv8.1m.main soft_nofp_nomve "-mfloat-abi=soft -march=armv8.1m.main+nofp+nomve" "target=thumbv8.1m.main-none-unknown-eabi mfpu=none" "-M mps3-an547 -cpu cortex-m55"
838+
armv8.1m.main hard_fp "-mfloat-abi=hard -march=armv8.1m.main+fp" "target=thumbv8.1m.main-none-unknown-eabihf march=+fp16 mfpu=fp-armv8-fullfp16-sp-d16" "-M mps3-an547 -cpu cortex-m55"
839+
armv8.1m.main hard_nofp_mve "-mfloat-abi=hard -march=armv8.1m.main+nofp+mve" "target=thumbv8.1m.main-none-unknown-eabihf march=+dsp march=+mve mfpu=none" "-M mps3-an547 -cpu cortex-m55"
840+
)
841+
842+
configure_file(
843+
${CMAKE_CURRENT_SOURCE_DIR}/cmake/multilib.yaml.in
844+
${CMAKE_CURRENT_BINARY_DIR}/llvm/lib/clang-runtimes/multilib.yaml
845+
@ONLY
846+
)
847+
install(
848+
FILES ${CMAKE_CURRENT_BINARY_DIR}/llvm/lib/clang-runtimes/multilib.yaml
849+
DESTINATION lib/clang-runtimes
850+
COMPONENT llvm-toolchain
823851
)
824852

825853
install(

cmake/multilib.yaml.in

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#
2+
# Copyright (c) 2022, Arm Limited and affiliates.
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
# If you're reading this file under the name 'multilib.yaml.in' in the
19+
# LLVM-embedded-toolchain-for-Arm source tree, then it's not valid
20+
# YAML in its own right: it's a template that CMakeLists.txt will
21+
# expand into a real 'multilib.yaml' containing a list of library
22+
# variants and the flags that will select them.
23+
#
24+
# If you're reading it under the name 'multilib.yaml' in the build or
25+
# install directory, then that substitution has been done.
26+
#
27+
# Comments in this file mostly make more sense from the
28+
# multilib.yaml.in point of view.
29+
30+
MultilibVersion: '0.1'
31+
32+
# The list of library variants is substituted in by CMakeLists.txt, so
33+
# that it can respect the LLVM_TOOLCHAIN_LIBRARY_VARIANTS setting and
34+
# only include the set of libraries actually included in this build.
35+
36+
Variants:
37+
@multilib_variants@
38+
39+
FlagMap:
40+
41+
# Map higher architecture versions to subsets of them, so that a
42+
# compatible library can be found even for architectures we don't have
43+
# specific variants for.
44+
45+
# v8-M Baseline is a superset of v6-M
46+
- Regex: target=thumbv8m\.base-none-unknown-eabi
47+
MatchFlags:
48+
- target=thumbv6m-none-unknown-eabi
49+
50+
# v8.2-M Mainline is a superset of v8.1-M Mainline, in both hard and
51+
# soft float variants.
52+
#
53+
# Also, v8.1-M Mainline is also a superset of v8-M Mainline, which in
54+
# turn is a superset of v7E-M, and then of plain v7-M. We have
55+
# libraries for all those architecture versions, but not for every
56+
# combination of them with FPUs, so in some cases it might be
57+
# necessary to fall back to a lower architecture in order to provide
58+
# the needed FPU support.
59+
- Regex: target=thumbv8\.[2-9]m\.main-none-unknown-eabi
60+
MatchFlags:
61+
- target=thumbv8.1m.main-none-unknown-eabi
62+
- target=thumbv8m.main-none-unknown-eabi
63+
- target=thumbv7em-none-unknown-eabi
64+
- target=thumbv7m-none-unknown-eabi
65+
- Regex: target=thumbv8\.[2-9]m\.main-none-unknown-eabihf
66+
MatchFlags:
67+
- target=thumbv8.1m.main-none-unknown-eabihf
68+
- target=thumbv8m.main-none-unknown-eabihf
69+
- target=thumbv7em-none-unknown-eabihf
70+
- target=thumbv7m-none-unknown-eabihf
71+
- Regex: target=thumbv8\.1m\.main-none-unknown-eabi
72+
MatchFlags:
73+
- target=thumbv8m.main-none-unknown-eabi
74+
- target=thumbv7em-none-unknown-eabi
75+
- target=thumbv7m-none-unknown-eabi
76+
- Regex: target=thumbv8\.1m\.main-none-unknown-eabihf
77+
MatchFlags:
78+
- target=thumbv8m.main-none-unknown-eabihf
79+
- target=thumbv7em-none-unknown-eabihf
80+
- target=thumbv7m-none-unknown-eabihf
81+
- Regex: target=thumbv8m\.main-none-unknown-eabi
82+
MatchFlags:
83+
- target=thumbv7em-none-unknown-eabi
84+
- target=thumbv7m-none-unknown-eabi
85+
- Regex: target=thumbv8m\.main-none-unknown-eabihf
86+
MatchFlags:
87+
- target=thumbv7em-none-unknown-eabihf
88+
- target=thumbv7m-none-unknown-eabihf
89+
- Regex: target=thumbv7em-none-unknown-eabi
90+
MatchFlags:
91+
- target=thumbv7m-none-unknown-eabi
92+
- Regex: target=thumbv7em-none-unknown-eabihf
93+
MatchFlags:
94+
- target=thumbv7m-none-unknown-eabihf
95+
96+
# Higher versions of v8-A, and v9-A, are all supersets of v8-A. (And
97+
# of each other, in the obvious way, but we don't have any libraries
98+
# for those at present, so there's no need to generate all their
99+
# flags.)
100+
- Regex: target=armv(8\.[1-9]|9|9\.[1-9])a-none-unknown-eabi
101+
MatchFlags:
102+
- target=armv8a-none-unknown-eabi
103+
104+
# Hierarchy among FPUs: fpvN-d16 is a superset of fpvN-sp-d16, and
105+
# fpvN-d16 is a superset of fpv[N-1]-d16, for all N.
106+
#
107+
# We don't consider any hardware FP configuration to be compatible
108+
# with mfpu=none. It would work in most cases to cross-call between
109+
# code compiled for an FPU or no FPU, if you were using the soft float
110+
# ABI. But it wouldn't work in all cases: setjmp needs to know whether
111+
# to save FP registers in the jmp_buf, so a non-FPU-aware setjmp would
112+
# not behave correctly if linked into an otherwise FPU-using
113+
# application. Similarly for exception unwinding. So we don't permit
114+
# selecting an mfpu=none library as a fallback for any hard-FP
115+
# library.
116+
- Regex: mfpu=fpv5-d16
117+
MatchFlags:
118+
- mfpu=fpv4-d16
119+
- mfpu=fpv5-sp-d16
120+
- mfpu=fpv4-sp-d16
121+
- Regex: mfpu=fpv5-sp-d16
122+
MatchFlags:
123+
- mfpu=fpv4-sp-d16
124+
- Regex: mfpu=fpv4-d16
125+
MatchFlags:
126+
- mfpu=fpv4-sp-d16

0 commit comments

Comments
 (0)