Skip to content

Commit 7f60fd9

Browse files
stevew817pratlucas
authored andcommitted
Add newlib-nano as multilib overlay package (#60)
See ARM-software/LLVM-embedded-toolchain-for-Arm#628 for context. This enables newlib-nano as a multilib. I didn't find any release scripts, so I don't know how to add it to the CI such that it also generates an overlay package for newlib-nano on release. Note: this also fixes an issue with the current newlib builds where they don't get built correctly for anything above ARMv6 as the `-march`, `-mfloat-abi` and `-mfpu` arguments weren't being passed on to the newlib compilation configuration. A little unsure why this hasn't popped up before...
1 parent 2e03bda commit 7f60fd9

File tree

9 files changed

+115
-40
lines changed

9 files changed

+115
-40
lines changed

arm-software/embedded/CMakeLists.txt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ set(LLVM_TOOLCHAIN_C_LIBRARY
170170
"Which C library to use."
171171
)
172172
set_property(CACHE LLVM_TOOLCHAIN_C_LIBRARY
173-
PROPERTY STRINGS picolibc newlib llvmlibc)
173+
PROPERTY STRINGS picolibc newlib newlib-nano llvmlibc)
174174

175175
option(
176176
SHORT_BUILD_PATHS
@@ -288,7 +288,7 @@ include(ProcessorCount)
288288
if(LLVM_TOOLCHAIN_C_LIBRARY STREQUAL picolibc)
289289
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/fetch_picolibc.cmake)
290290
endif()
291-
if(LLVM_TOOLCHAIN_C_LIBRARY STREQUAL newlib)
291+
if(LLVM_TOOLCHAIN_C_LIBRARY MATCHES "^newlib")
292292
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/fetch_newlib.cmake)
293293
endif()
294294

@@ -311,18 +311,18 @@ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
311311
endif()
312312
##################################################################################################
313313

314-
if(LLVM_TOOLCHAIN_C_LIBRARY STREQUAL newlib)
314+
if(LLVM_TOOLCHAIN_C_LIBRARY MATCHES "^newlib")
315315
install(
316316
FILES
317-
${CMAKE_CURRENT_SOURCE_DIR}/newlib.cfg
317+
${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TOOLCHAIN_C_LIBRARY}.cfg
318318
DESTINATION bin
319-
COMPONENT llvm-toolchain-newlib-configs
319+
COMPONENT llvm-toolchain-${LLVM_TOOLCHAIN_C_LIBRARY}-configs
320320
)
321321
install(
322322
DIRECTORY
323323
${CMAKE_CURRENT_SOURCE_DIR}/newlib-samples/
324324
DESTINATION samples
325-
COMPONENT llvm-toolchain-newlib-configs
325+
COMPONENT llvm-toolchain-${LLVM_TOOLCHAIN_C_LIBRARY}-configs
326326
)
327327
endif()
328328

@@ -733,7 +733,7 @@ if(LLVM_TOOLCHAIN_C_LIBRARY STREQUAL picolibc)
733733
${picolibc_SOURCE_DIR}/COPYING.picolibc COPYING.picolibc
734734
)
735735
endif()
736-
if(LLVM_TOOLCHAIN_C_LIBRARY STREQUAL newlib)
736+
if(LLVM_TOOLCHAIN_C_LIBRARY MATCHES "^newlib")
737737
list(APPEND third_party_license_files
738738
${newlib_SOURCE_DIR}/COPYING.NEWLIB COPYING.NEWLIB
739739
${newlib_SOURCE_DIR}/COPYING.LIBGLOSS COPYING.LIBGLOSS

arm-software/embedded/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ bare-metal LLVM based toolchain targeting Arm based on:
77
* libc++abi
88
* libc++
99
* compiler-rt
10-
* picolibc, or optionally newlib or LLVM's libc
10+
* picolibc, or optionally newlib(-nano) or LLVM's libc
1111

1212
## Goal
1313

@@ -191,7 +191,7 @@ relying on the Arm GNU Toolchain.
191191
> *Note:* `picolibc` provides excellent
192192
> [support for Arm GNU Toolchain](https://github.com/picolibc/picolibc/blob/main/doc/using.md),
193193
> so projects that require using both Arm GNU Toolchain and Arm Toolchain for Embedded
194-
> can choose either `picolibc` or `newlib`.
194+
> can choose either `picolibc` or `newlib`/`newlib-nano`.
195195
196196
## Building from source
197197

arm-software/embedded/arm-multilib/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ set(llvmproject_src_dir ${TOOLCHAIN_SOURCE_DIR}/../..)
2323
set(MULTILIB_JSON "" CACHE STRING "JSON file to load library definitions from.")
2424
set(ENABLE_VARIANTS "all" CACHE STRING "Semicolon separated list of variants to build, or \"all\". Must match entries in the json.")
2525
set(C_LIBRARY "picolibc" CACHE STRING "Which C library to use.")
26-
set_property(CACHE C_LIBRARY PROPERTY STRINGS picolibc newlib llvmlibc)
26+
set_property(CACHE C_LIBRARY PROPERTY STRINGS picolibc newlib newlib-nano llvmlibc)
2727
set(PROJECT_PREFIX "${CMAKE_BINARY_DIR}/lib-builds" CACHE STRING "Directory to build subprojects in.")
2828
option(
2929
NUMERICAL_BUILD_NAMES
@@ -95,7 +95,7 @@ include(ExternalProject)
9595
if(C_LIBRARY STREQUAL picolibc)
9696
include(${TOOLCHAIN_SOURCE_DIR}/cmake/fetch_picolibc.cmake)
9797
list(APPEND passthrough_dirs "-DFETCHCONTENT_SOURCE_DIR_PICOLIBC=${FETCHCONTENT_SOURCE_DIR_PICOLIBC}")
98-
elseif(C_LIBRARY STREQUAL newlib)
98+
elseif(C_LIBRARY MATCHES "^newlib")
9999
include(${TOOLCHAIN_SOURCE_DIR}/cmake/fetch_newlib.cmake)
100100
list(APPEND passthrough_dirs "-DFETCHCONTENT_SOURCE_DIR_NEWLIB=${FETCHCONTENT_SOURCE_DIR_NEWLIB}")
101101
endif()

arm-software/embedded/arm-multilib/json/multilib.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,25 @@
3434
"variant": "aarch64a_soft_nofp_exn_rtti",
3535
"json": "aarch64a_soft_nofp_exn_rtti.json",
3636
"flags": "--target=aarch64-unknown-none-elf -march=armvX+nofp -march=armvX+nosimd -mabi=aapcs-soft",
37-
"libraries_supported": "picolibc,newlib"
37+
"libraries_supported": "picolibc"
3838
},
3939
{
4040
"variant": "aarch64a_soft_nofp",
4141
"json": "aarch64a_soft_nofp.json",
4242
"flags": "--target=aarch64-unknown-none-elf -march=armvX+nofp -march=armvX+nosimd -mabi=aapcs-soft -fno-exceptions -fno-rtti",
43-
"libraries_supported": "picolibc,newlib"
43+
"libraries_supported": "picolibc"
4444
},
4545
{
4646
"variant": "aarch64a_be_soft_nofp_exn_rtti",
4747
"json": "aarch64a_be_soft_nofp_exn_rtti.json",
4848
"flags": "--target=aarch64_be-unknown-none-elf -march=armvX+nofp -march=armvX+nosimd -mabi=aapcs-soft",
49-
"libraries_supported": "picolibc,newlib"
49+
"libraries_supported": "picolibc"
5050
},
5151
{
5252
"variant": "aarch64a_be_soft_nofp",
5353
"json": "aarch64a_be_soft_nofp.json",
5454
"flags": "--target=aarch64_be-unknown-none-elf -march=armvX+nofp -march=armvX+nosimd -mabi=aapcs-soft -fno-exceptions -fno-rtti",
55-
"libraries_supported": "picolibc,newlib"
55+
"libraries_supported": "picolibc"
5656
},
5757
{
5858
"variant": "aarch64r_exn_rtti_unaligned",

arm-software/embedded/arm-runtimes/CMakeLists.txt

Lines changed: 83 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ set(llvmproject_src_dir ${TOOLCHAIN_SOURCE_DIR}/../..)
2121
# CMake arguments are loaded from the JSON file depending on which C
2222
# library is used, so this must be set before the JSON is processed.
2323
set(C_LIBRARY "picolibc" CACHE STRING "Which C library to use.")
24-
set_property(CACHE C_LIBRARY PROPERTY STRINGS picolibc newlib llvmlibc)
24+
set_property(CACHE C_LIBRARY PROPERTY STRINGS picolibc newlib newlib-nano llvmlibc)
2525

2626
set(VARIANT_JSON "" CACHE STRING "JSON file to load args from.")
2727
if(VARIANT_JSON)
@@ -37,7 +37,12 @@ if(VARIANT_JSON)
3737
set(${json_param}_def ${json_val})
3838
endforeach()
3939
# Load arguments specific to the chosen library, overwriting any existing values.
40-
string(JSON json_args GET ${variant_json_read} "args" ${C_LIBRARY})
40+
if(C_LIBRARY MATCHES "^newlib")
41+
# Treat newlib variants as newlib for library compatibility
42+
string(JSON json_args GET ${variant_json_read} "args" "newlib")
43+
else()
44+
string(JSON json_args GET ${variant_json_read} "args" ${C_LIBRARY})
45+
endif()
4146
string(JSON json_args_len LENGTH ${json_args})
4247
math(EXPR json_args_len_dec "${json_args_len} - 1")
4348
foreach(json_idx RANGE ${json_args_len_dec})
@@ -85,7 +90,7 @@ set(PICOLIBC_BUILD_TYPE ${PICOLIBC_BUILD_TYPE_def} CACHE STRING "Picolibc config
8590
set_property(CACHE PICOLIBC_BUILD_TYPE PROPERTY STRINGS minsize release)
8691

8792
set(ENABLE_CXX_LIBS ${ENABLE_CXX_LIBS_def} CACHE BOOL "Build CXX libs")
88-
set(ENABLE_LIBC_TESTS ${ENABLE_LIBC_TESTS_def} CACHE BOOL "Enable libc tests (picolibc, newlib or llvm-libc).")
93+
set(ENABLE_LIBC_TESTS ${ENABLE_LIBC_TESTS_def} CACHE BOOL "Enable libc tests (picolibc, newlib, newlib-nano or llvm-libc).")
8994
set(ENABLE_COMPILER_RT_TESTS ${ENABLE_COMPILER_RT_TESTS_def} CACHE BOOL "Enable compiler-rt tests.")
9095
set(ENABLE_LIBCXX_TESTS ${ENABLE_LIBCXX_TESTS_def} CACHE BOOL "Enable libcxx tests.")
9196
set(LLVM_BINARY_DIR "" CACHE PATH "Path to LLVM toolchain root to build libraries with")
@@ -459,11 +464,60 @@ endif()
459464
# newlib
460465
###############################################################################
461466

462-
if(C_LIBRARY STREQUAL newlib)
467+
if(C_LIBRARY MATCHES "^newlib")
463468
if(ENABLE_LIBC_TESTS)
464469
message(FATAL_ERROR "Tests cannot yet be enabled using newlib libc.")
465470
endif()
466471

472+
if(C_LIBRARY STREQUAL newlib-nano)
473+
set(newlib_optim_flags
474+
"-g -Oz")
475+
if(TARGET_ARCH MATCHES "^aarch64")
476+
# When trying to build newlib-nano on AArch64, fall back to regular newlib
477+
# See https://gitlab.arm.com/tooling/gnu-devtools-for-arm/-/blob/9e3db8c042400c9c59686dec8eda2e8c44e5fb5d/build-baremetal-toolchain.sh#L625
478+
# ARMGCC just skips building the nano libs for AArch64, but in order to not break integration and testing of multilib, we are building
479+
# regular newlib for AArch64 with extreme size optimisation and calling it newlib-nano.
480+
set(newlib_flags
481+
--enable-newlib-io-long-long
482+
--enable-newlib-register-fini
483+
--disable-newlib-supplied-syscalls
484+
--enable-newlib-io-c99-formats
485+
--disable-nls
486+
--enable-lite-exit
487+
--disable-multilib
488+
--enable-newlib-retargetable-locking)
489+
else()
490+
# Taken from https://gitlab.arm.com/tooling/gnu-devtools-for-arm/-/blob/9e3db8c042400c9c59686dec8eda2e8c44e5fb5d/build-baremetal-toolchain.sh#L582
491+
set(newlib_flags
492+
--disable-newlib-supplied-syscalls
493+
--disable-nls
494+
--enable-lite-exit
495+
--disable-multilib
496+
--enable-newlib-retargetable-locking
497+
--enable-newlib-nano-malloc
498+
--disable-newlib-unbuf-stream-opt
499+
--enable-newlib-reent-small
500+
--disable-newlib-fseek-optimization
501+
--enable-newlib-nano-formatted-io
502+
--disable-newlib-fvwrite-in-streamio
503+
--disable-newlib-wide-orient
504+
--enable-lite-exit
505+
--enable-newlib-global-atexit)
506+
endif()
507+
else()
508+
set(newlib_flags
509+
--enable-newlib-io-long-long
510+
--enable-newlib-register-fini
511+
--disable-newlib-supplied-syscalls
512+
--enable-newlib-io-c99-formats
513+
--disable-nls
514+
--enable-lite-exit
515+
--disable-multilib
516+
--enable-newlib-retargetable-locking)
517+
set(newlib_optim_flags
518+
"-g -O2")
519+
endif()
520+
467521
include(${TOOLCHAIN_SOURCE_DIR}/cmake/fetch_newlib.cmake)
468522
set(build_env
469523
"CC_FOR_TARGET=${LLVM_BINARY_DIR}/bin/clang -target ${target_triple} -ffreestanding"
@@ -474,8 +528,8 @@ if(C_LIBRARY STREQUAL newlib)
474528
"RANLIB_FOR_TARGET=${LLVM_BINARY_DIR}/bin/llvm-ranlib"
475529
"READELF_FOR_TARGET=${LLVM_BINARY_DIR}/bin/llvm-readelf"
476530
"STRIP_FOR_TARGET=${LLVM_BINARY_DIR}/bin/llvm-strip"
477-
"CFLAGS_FOR_TARGET=${flags} -Wno-error=implicit-function-declaration -D__USES_INITFINI__ -U_HAVE_INIT_FINI --sysroot ${TEMP_LIB_DIR}"
478-
"CCASFLAGS=${flags} -Wno-error=implicit-function-declaration -D__USES_INITFINI__ -U_HAVE_INIT_FINI --sysroot ${TEMP_LIB_DIR}"
531+
"CFLAGS_FOR_TARGET=${flags} ${newlib_optim_flags} ${lib_compile_flags} -Wno-error=implicit-function-declaration -D__USES_INITFINI__ -U_HAVE_INIT_FINI"
532+
"CCASFLAGS=${flags} ${newlib_optim_flags} ${lib_compile_flags} -Wno-error=implicit-function-declaration -D__USES_INITFINI__ -U_HAVE_INIT_FINI"
479533
)
480534

481535
include(ProcessorCount)
@@ -486,11 +540,11 @@ if(C_LIBRARY STREQUAL newlib)
486540
endif()
487541

488542
ExternalProject_Add(
489-
newlib
490-
STAMP_DIR ${PROJECT_PREFIX}/newlib/${VARIANT_BUILD_ID}/stamp
491-
BINARY_DIR ${PROJECT_PREFIX}/newlib/${VARIANT_BUILD_ID}/build
492-
DOWNLOAD_DIR ${PROJECT_PREFIX}/newlib/${VARIANT_BUILD_ID}/dl
493-
TMP_DIR ${PROJECT_PREFIX}/newlib/${VARIANT_BUILD_ID}/tmp
543+
${C_LIBRARY}
544+
STAMP_DIR ${PROJECT_PREFIX}/${C_LIBRARY}/${VARIANT_BUILD_ID}/stamp
545+
BINARY_DIR ${PROJECT_PREFIX}/${C_LIBRARY}/${VARIANT_BUILD_ID}/build
546+
DOWNLOAD_DIR ${PROJECT_PREFIX}/${C_LIBRARY}/${VARIANT_BUILD_ID}/dl
547+
TMP_DIR ${PROJECT_PREFIX}/${C_LIBRARY}/${VARIANT_BUILD_ID}/tmp
494548
SOURCE_DIR ${newlib_SOURCE_DIR}
495549
INSTALL_DIR ${TEMP_LIB_DIR}
496550
CONFIGURE_COMMAND
@@ -499,14 +553,7 @@ if(C_LIBRARY STREQUAL newlib)
499553
--target=${target_triple}
500554
--prefix "${TEMP_LIB_DIR}"
501555
--exec_prefix <BINARY_DIR>/tmpinstall
502-
--enable-newlib-io-long-long
503-
--enable-newlib-register-fini
504-
--disable-newlib-supplied-syscalls
505-
--enable-newlib-io-c99-formats
506-
--disable-nls
507-
--enable-lite-exit
508-
--disable-multilib
509-
--enable-newlib-retargetable-locking
556+
${newlib_flags}
510557
BUILD_COMMAND
511558
${CMAKE_COMMAND} -E env ${build_env}
512559
make ${make_flags}
@@ -690,19 +737,34 @@ if(ENABLE_CXX_LIBS)
690737
-DLLVM_LIT_ARGS=${cxxlibs_lit_args}
691738
)
692739
endif()
693-
elseif(C_LIBRARY STREQUAL newlib)
740+
elseif(C_LIBRARY MATCHES "^newlib")
694741
set(cxxlibs_extra_cmake_options
695742
-DLIBCXXABI_ENABLE_THREADS=OFF
696743
-DLIBCXX_ENABLE_MONOTONIC_CLOCK=OFF
697744
-DLIBCXX_ENABLE_RANDOM_DEVICE=OFF
698745
-DLIBCXX_ENABLE_THREADS=OFF
699-
-DLIBCXX_ENABLE_WIDE_CHARACTERS=ON
700746
-DLIBUNWIND_ENABLE_THREADS=OFF
701747
-DLIBCXXABI_ENABLE_EXCEPTIONS=${ENABLE_EXCEPTIONS}
702748
-DLIBCXXABI_ENABLE_STATIC_UNWINDER=${ENABLE_EXCEPTIONS}
703749
-DLIBCXX_ENABLE_EXCEPTIONS=${ENABLE_EXCEPTIONS}
704750
-DLIBCXX_ENABLE_RTTI=${ENABLE_RTTI}
705751
)
752+
753+
if(C_LIBRARY STREQUAL newlib-nano)
754+
set(lib_compile_flags "${lib_compile_flags} -g -Oz")
755+
endif()
756+
757+
if(C_LIBRARY STREQUAL newlib-nano AND NOT TARGET_ARCH MATCHES "^aarch64")
758+
set(cxxlibs_extra_cmake_options
759+
${cxxlibs_extra_cmake_options}
760+
-DLIBCXX_ENABLE_WIDE_CHARACTERS=OFF
761+
)
762+
else()
763+
set(cxxlibs_extra_cmake_options
764+
${cxxlibs_extra_cmake_options}
765+
-DLIBCXX_ENABLE_WIDE_CHARACTERS=ON
766+
)
767+
endif()
706768
endif()
707769

708770
ExternalProject_Add(

arm-software/embedded/cmake/generate_version_txt.cmake

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@ if(NOT ${armtoolchain_COMMIT} MATCHES "^[a-f0-9]+$")
1818
endif()
1919

2020
if(NOT (LLVM_TOOLCHAIN_C_LIBRARY STREQUAL llvmlibc)) # libc in a separate repo?
21+
if(LLVM_TOOLCHAIN_C_LIBRARY MATCHES "^newlib")
22+
set(base_library newlib)
23+
else()
24+
set(base_library $(LLVM_TOOLCHAIN_C_LIBRARY))
25+
endif()
26+
2127
execute_process(
22-
COMMAND git -C ${${LLVM_TOOLCHAIN_C_LIBRARY}_SOURCE_DIR} rev-parse HEAD
28+
COMMAND git -C ${${base_library}_SOURCE_DIR} rev-parse HEAD
2329
OUTPUT_VARIABLE ${LLVM_TOOLCHAIN_C_LIBRARY}_COMMIT
2430
OUTPUT_STRIP_TRAILING_WHITESPACE
2531
COMMAND_ERROR_IS_FATAL ANY

arm-software/embedded/docs/migrating.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Armv8-M or later architecture, including the
3737
|Binutils​|`objdump`, `readelf`, ...|`llvm-objdump`, `llvm-readelf`, ...|
3838
|Compiler runtime library​|`libgcc​`|`compiler-rt`|
3939
|Unwinder​|`libgcc`|`libunwind`|
40-
|C standard library​|`newlib`, `newlib-nano`|`picolibc`|​
40+
|C standard library​|`newlib`, `newlib-nano`|`picolibc` (or `newlib`/`newlib-nano` as overlay)|​
4141
|C++ ABI library​|`libsupc++.a`|`libc++abi`​|​
4242
|C++ standard library​|`libstdc++​`|`libc++`|
4343

@@ -90,7 +90,7 @@ however uses different command line options to control selection of semihosting.
9090
|--------|-----------|------------|
9191
|No semihosting|`--specs=nosys.specs`|
9292
|Semihosting|`--specs=rdimon.specs`|`-nostartfiles -lcrt0-semihost -lsemihost`|
93-
|Newlib-nano|`--specs=nano.specs`|Not available: `picolibc` is an equivalent of `newlib-nano`.
93+
|Newlib-nano|`--specs=nano.specs`|`--config=newlib-nano.cfg` (with [`newlib-nano` overlay](./newlib.md) installed)|
9494

9595
## Linker
9696

arm-software/embedded/docs/newlib.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,10 @@ overlay package.
4646

4747
Note that the `-DLLVM_TOOLCHAIN_LIBRARY_OVERLAY_INSTALL=on` option
4848
only generates the `newlib` package, but does not install it as part
49-
of the `install` CMake target.
49+
of the `install` CMake target.
50+
51+
## About `newlib-nano`
52+
`newlib-nano` is provided as a separate package, and is meant to be equal
53+
to using GCC with `--specs=nano.specs`. In order to use the nano version
54+
of newlib, where the documentation in this file refers to `newlib`, replace
55+
it with `newlib-nano`.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--sysroot <CFGDIR>/../lib/clang-runtimes/newlib-nano

0 commit comments

Comments
 (0)