From 03dc31dbcb300787ef90bed1f1dbd953516ec2a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Aug 2022 22:33:23 -0700 Subject: [PATCH] Add support for picolibc This allows the creation of an embedded toolchain which uses picolibc as the C library instead of newlib. Signed-off-by: Keith Packard --- .gitignore | 1 + Makefile.in | 154 ++++++++++++++++++++++++++++++++++++++++++-- README.md | 11 ++++ configure | 58 ++++++++++++++++- configure.ac | 24 ++++++- make-picolibc-cross | 32 +++++++++ 6 files changed, 273 insertions(+), 7 deletions(-) create mode 100644 make-picolibc-cross diff --git a/.gitignore b/.gitignore index 5a1eeb513f5..c833cfa4c09 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ build config.log config.status Makefile +picolibc-cross.txt .DS_Store !/regression/Makefile /build-*/ diff --git a/Makefile.in b/Makefile.in index f6afeab494d..4ee6917ea88 100644 --- a/Makefile.in +++ b/Makefile.in @@ -5,6 +5,7 @@ INSTALL_DIR := @prefix@ GCC_SRCDIR := @with_gcc_src@ BINUTILS_SRCDIR := @with_binutils_src@ NEWLIB_SRCDIR := @with_newlib_src@ +PICOLIBC_SRCDIR := @with_picolibc_src@ GLIBC_SRCDIR := @with_glibc_src@ MUSL_SRCDIR := @with_musl_src@ LINUX_HEADERS_SRCDIR := @with_linux_headers_src@ @@ -59,9 +60,11 @@ MULTILIB_FLAGS := @multilib_flags@ MULTILIB_GEN := @multilib_gen@ ifeq ($(MULTILIB_GEN),) NEWLIB_MULTILIB_NAMES := @newlib_multilib_names@ +PICOLIBC_MULTILIB_NAMES := @picolibc_multilib_names@ GCC_MULTILIB_FLAGS := $(MULTILIB_FLAGS) else NEWLIB_MULTILIB_NAMES := $(shell echo "$(MULTILIB_GEN)" | $(SED) 's/;/\n/g'| $(AWK) '{split($$0,a,"-"); printf "%s-%s ", a[1],a[2]}') +PICOLIBC_MULTILIB_NAMES := $(shell echo "$(MULTILIB_GEN)" | $(SED) 's/;/\n/g'| $(AWK) '{split($$0,a,"-"); printf "%s-%s ", a[1],a[2]}') GCC_MULTILIB_FLAGS := $(MULTILIB_FLAGS) --with-multilib-generator="$(MULTILIB_GEN)" endif GLIBC_MULTILIB_NAMES := @glibc_multilib_names@ @@ -75,6 +78,7 @@ endif make_tuple = riscv$(1)-unknown-$(2) LINUX_TUPLE ?= $(call make_tuple,$(XLEN),linux-gnu) NEWLIB_TUPLE ?= $(call make_tuple,$(XLEN),elf) +PICOLIBC_TUPLE ?= $(call make_tuple,$(XLEN),elf) MUSL_TUPLE ?= $(call make_tuple,$(XLEN),linux-musl) CFLAGS_FOR_TARGET := $(CFLAGS_FOR_TARGET_EXTRA) @target_cflags@ @cmodel@ @@ -96,6 +100,10 @@ NEWLIB_CXX_FOR_TARGET ?= $(NEWLIB_TUPLE)-g++ NEWLIB_TARGET_BOARDS ?= $(shell echo "$(NEWLIB_MULTILIB_NAMES)" | sed 's!\([_a-z0-9]*\)-\([_a-z0-9]*\)!riscv-sim/-march=\1/-mabi=\2/@cmodel@!g') NEWLIB_NANO_TARGET_BOARDS ?= $(shell echo "$(NEWLIB_MULTILIB_NAMES)" | sed 's!\([_a-z0-9]*\)-\([_a-z0-9]*\)!riscv-sim-nano/-march=\1/-mabi=\2/@cmodel@!g') +PICOLIBC_CC_FOR_TARGET ?= $(PICOLIBC_TUPLE)-gcc +PICOLIBC_CXX_FOR_TARGET ?= $(PICOLIBC_TUPLE)-g++ +PICOLIBC_TARGET_BOARDS ?= $(shell echo "$(PICOLIBC_MULTILIB_NAMES)" | sed 's!\([_a-z0-9]*\)-\([_a-z0-9]*\)!riscv-sim/-march=\1/-mabi=\2/@cmodel@!g') + MUSL_TARGET_FLAGS := $(MUSL_TARGET_FLAGS_EXTRA) MUSL_CC_FOR_TARGET ?= $(MUSL_TUPLE)-gcc MUSL_CXX_FOR_TARGET ?= $(MUSL_TUPLE)-g++ @@ -104,6 +112,7 @@ CONFIGURE_HOST = @configure_host@ all: @default_target@ newlib: stamps/build-gcc-newlib-stage2 +picolibc: stamps/build-gcc-picolibc-stage2 linux: stamps/build-gcc-linux-stage2 ifneq (,$(findstring riscv32,$(MUSL_TUPLE))) .PHONY: musl @@ -114,6 +123,7 @@ musl: stamps/build-gcc-musl-stage2 endif ifeq (@enable_gdb@,--enable-gdb) newlib: stamps/build-gdb-newlib +picolibc: stamps/build-gdb-picolibc linux: stamps/build-gdb-linux endif linux-native: stamps/build-gcc-linux-native @@ -125,33 +135,40 @@ build-gcc%: stamps/build-gcc-@default_target@-stage% ifeq (@default_target@,linux) build-libc: $(addprefix stamps/build-glibc-linux-,$(GLIBC_MULTILIB_NAMES)) else +ifeq (@default_target@,picolibc) +build-libc: stamps/build-picolibc +else build-libc: stamps/build-newlib stamps/build-newlib-nano \ stamps/merge-newlib-nano endif +endif build-qemu: stamps/build-qemu REGRESSION_TEST_LIST = gcc .PHONY: check check: check-@default_target@ -.PHONY: check-linux check-newlib +.PHONY: check-linux check-newlib check-picolibc check-linux: $(patsubst %,check-%-linux,$(REGRESSION_TEST_LIST)) check-newlib: $(patsubst %,check-%-newlib,$(REGRESSION_TEST_LIST)) check-newlib-nano: $(patsubst %,check-%-newlib-nano,$(REGRESSION_TEST_LIST)) -.PHONY: check-gcc check-gcc-linux check-gcc-newlib check-gcc-newlib-nano +check-picolibc: $(patsubst %,check-%-picolibc,$(REGRESSION_TEST_LIST)) +.PHONY: check-gcc check-gcc-linux check-gcc-newlib check-gcc-newlib-nano check-gcc-picolibc check-gcc: check-gcc-@default_target@ check-gcc-linux: stamps/check-gcc-linux check-gcc-newlib: stamps/check-gcc-newlib check-gcc-newlib-nano: stamps/check-gcc-newlib-nano +check-gcc-picolibc: stamps/check-gcc-picolibc .PHONY: check-glibc-linux check-glibc-linux: $(addprefix stamps/check-glibc-linux-,$(GLIBC_MULTILIB_NAMES)) .PHONY: check-dhrystone check-dhrystone-linux check-dhrystone-newlib check-dhrystone: check-dhrystone-@default_target@ -.PHONY: check-binutils check-binutils-linux check-binutils-newlib +.PHONY: check-binutils check-binutils-linux check-binutils-newlib check-binutils-picolibc check-binutils: check-binutils-@default_target@ check-binutils-linux: stamps/check-binutils-linux check-binutils-newlib: stamps/check-binutils-newlib check-binutils-newlib-nano: stamps/check-binutils-newlib-nano +check-binutils-picolibc: stamps/check-binutils-picolibc .PHONY: check-gdb check-gdb-linux check-gdb-newlib check-gdb: check-gdb-@default_target@ check-gdb-linux: stamps/check-gdb-linux @@ -688,6 +705,119 @@ stamps/build-gcc-newlib-stage2: $(GCC_SRCDIR) $(GCC_SRC_GIT) stamps/build-newlib $(MAKE) -C $(notdir $@) install mkdir -p $(dir $@) && touch $@ +# +# PICOLIBC +# + +stamps/build-binutils-picolibc: $(BINUTILS_SRCDIR) $(BINUTILS_SRC_GIT) stamps/check-write-permission + rm -rf $@ $(notdir $@) + mkdir $(notdir $@) +# CC_FOR_TARGET is required for the ld testsuite. + cd $(notdir $@) && CC_FOR_TARGET=$(PICOLIBC_CC_FOR_TARGET) $ $@ + +stamps/build-gcc-picolibc-stage2: $(GCC_SRCDIR) $(GCC_SRC_GIT) stamps/build-picolibc + rm -rf $@ $(notdir $@) + mkdir $(notdir $@) + cd $(notdir $@) && $ $@ +stamps/check-gcc-picolibc: stamps/build-gcc-picolibc-stage2 stamps/build-qemu + cd build-picolibc && meson configure -Dtests=true + ninja -C build-picolibc test + mkdir -p $(dir $@) + date > $@ + stamps/check-gcc-linux: stamps/build-gcc-linux-stage2 $(SIM_STAMP) stamps/build-dejagnu $(SIM_PREPARE) $(MAKE) -C build-gcc-linux-stage2 check-gcc "RUNTESTFLAGS=$(RUNTESTFLAGS) --target_board='$(GLIBC_TARGET_BOARDS)'" mkdir -p $(dir $@) @@ -942,6 +1078,10 @@ stamps/check-binutils-newlib-nano: stamps/build-gcc-newlib-stage2 $(SIM_STAMP) s $(SIM_PREPARE) $(MAKE) -C build-binutils-newlib check-binutils check-gas check-ld -k "RUNTESTFLAGS=--target_board='$(NEWLIB_NANO_TARGET_BOARDS)'" || true date > $@ +stamps/check-binutils-picolibc: stamps/build-gcc-picolibc-stage2 $(SIM_STAMP) stamps/build-dejagnu + $(SIM_PREPARE) $(MAKE) -C build-binutils-picolibc check-binutils check-gas check-ld -k "RUNTESTFLAGS=--target_board='$(PICOLIBC_TARGET_BOARDS)'" || true + date > $@ + stamps/check-binutils-linux: stamps/build-gcc-linux-stage2 $(SIM_STAMP) stamps/build-dejagnu $(SIM_PREPARE) $(MAKE) -C build-binutils-linux check-binutils check-gas check-ld -k "RUNTESTFLAGS=--target_board='$(GLIBC_TARGET_BOARDS)'" || true date > $@ @@ -990,6 +1130,12 @@ report-binutils-newlib-nano: stamps/check-binutils-newlib-nano $(srcdir)/test/allowlist \ `find build-binutils-newlib/ -name *.sum |paste -sd "," -` +.PHONY: report-binutils-picolibc +report-binutils-picolibc: stamps/check-binutils-picolibc + $(srcdir)/scripts/testsuite-filter binutils picolibc \ + $(srcdir)/test/allowlist \ + `find build-binutils-picolibc/ -name *.sum |paste -sd "," -` + .PHONY: report-binutils-linux report-binutils-linux: stamps/check-binutils-linux $(srcdir)/scripts/testsuite-filter binutils glibc \ @@ -997,7 +1143,7 @@ report-binutils-linux: stamps/check-binutils-linux `find build-binutils-linux/ -name *.sum |paste -sd "," -` clean: - rm -rf build-* stamps install-newlib-nano + rm -rf build-* stamps install-newlib-nano picolibc-cross.txt .PHONY: report-gdb-newlib report-gdb-newlib-nano report-gdb-newlib: stamps/check-gdb-newlib diff --git a/README.md b/README.md index 4f383cc7ef1..37a8ffd5ed5 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,17 @@ run the following command: You should now be able to use riscv64-unknown-elf-gcc and its cousins. +### Installation (Picolibc multilib) + +To build the Picolibc cross-compiler, pick an install path. If you choose, +say, `/opt/riscv`, then add `/opt/riscv/bin` to your `PATH` now. Then, simply +run the following command: + + ./configure --prefix=/opt/riscv --enable-picolibc --enable-multilib + make + +You should now be able to use riscv64-unknown-elf-gcc and its cousins. + ### Installation (Linux) To build the Linux cross-compiler, pick an install path (that is writeable.) diff --git a/configure b/configure index 6b73555c7cc..00b21e48256 100755 --- a/configure +++ b/configure @@ -593,6 +593,7 @@ with_qemu_src with_gdb_src with_musl_src with_glibc_src +with_picolibc_src with_newlib_src with_binutils_src with_gcc_src @@ -605,6 +606,7 @@ target_cflags cmodel gcc_checking musl_multilib_names +picolibc_multilib_names newlib_multilib_names glibc_multilib_names multilib_flags @@ -675,6 +677,7 @@ ac_subst_files='' ac_user_opts=' enable_option_checking enable_linux +enable_picolibc with_arch with_abi with_tune @@ -693,6 +696,7 @@ enable_gdb with_gcc_src with_binutils_src with_newlib_src +with_picolibc_src with_glibc_src with_musl_src with_gdb_src @@ -1333,6 +1337,7 @@ Optional Features: --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-linux set linux as the default make target [--disable-linux] + --enable-picolibc set picolibc as the default make target --enable-multilib build both RV32 and RV64 runtime libraries (only RV64 for musl libc) [--disable-multilib] --enable-gcc-checking Enable gcc internal checking, it will make gcc very @@ -1369,6 +1374,8 @@ Optional Packages: default --with-newlib-src Set newlib source path, use builtin source by default + --with-picolibc-src Set picolibc source path, use builtin source by + default --with-glibc-src Set glibc source path, use builtin source by default --with-musl-src Set musl source path, use builtin source by default --with-gdb-src Set gdb source path, use builtin source by default @@ -3283,12 +3290,27 @@ else fi +# Check whether --enable-picolibc was given. +if test "${enable_picolibc+set}" = set; then : + enableval=$enable_picolibc; enable_picolibc=yes +else + enable_picolibc=no + +fi + + if test "x$enable_linux" != xno; then : default_target=linux +else + if test "x$enable_picolibc" != xno; then : + default_target=picolibc + else default_target=newlib + +fi fi @@ -3426,6 +3448,14 @@ else fi +if test "x$enable_multilib" != xno; then : + picolibc_multilib_names="rv32i-ilp32 rv32iac-ilp32 rv32im-ilp32 rv32imac-ilp32 rv32imafc-ilp32f rv64imac-lp64 rv64imafdc-lp64d" + +else + picolibc_multilib_names="$with_arch-$with_abi" + +fi + if test "x$enable_multilib" != xno; then : musl_multilib_names="rv64imac-lp64 rv64imafdc-lp64d" @@ -3617,6 +3647,25 @@ fi } { +# Check whether --with-picolibc-src was given. +if test "${with_picolibc_src+set}" = set; then : + withval=$with_picolibc_src; +else + with_picolibc_src=default + +fi + + if test "x$with_picolibc_src" != xdefault; then : + with_picolibc_src=$with_picolibc_src + +else + with_picolibc_src="\$(srcdir)/picolibc" + +fi + + } +{ + # Check whether --with-glibc-src was given. if test "${with_glibc_src+set}" = set; then : withval=$with_glibc_src; @@ -3765,11 +3814,18 @@ else fi +if test "x$enable_picolibc" != xno; then : + default_enable_qemu_system=yes +else + default_enable_qemu_system=no + +fi + # Check whether --enable-qemu_system was given. if test "${enable_qemu_system+set}" = set; then : enableval=$enable_qemu_system; else - enable_qemu_system=no + enable_qemu_system="$default_enable_qemu_system" fi diff --git a/configure.ac b/configure.ac index 16178c72eeb..cf9883bb32b 100644 --- a/configure.ac +++ b/configure.ac @@ -46,9 +46,19 @@ AC_ARG_ENABLE(linux, [enable_linux=no] ) +AC_ARG_ENABLE(picolibc, + [AS_HELP_STRING([--enable-picolibc], + [set picolibc as the default make target])], + [enable_picolibc=yes], + [enable_picolibc=no] + ) + AS_IF([test "x$enable_linux" != xno], [AC_SUBST(default_target, linux)], - [AC_SUBST(default_target, newlib)]) + [AS_IF([test "x$enable_picolibc" != xno], + [AC_SUBST(default_target, picolibc)], + [AC_SUBST(default_target, newlib)] + )]) AC_ARG_WITH(arch, [AS_HELP_STRING([--with-arch=rv64imafdc], @@ -134,6 +144,10 @@ AS_IF([test "x$enable_multilib" != xno], [AC_SUBST(newlib_multilib_names,"rv32i-ilp32 rv32iac-ilp32 rv32im-ilp32 rv32imac-ilp32 rv32imafc-ilp32f rv64imac-lp64 rv64imafdc-lp64d")], [AC_SUBST(newlib_multilib_names,"$with_arch-$with_abi")]) +AS_IF([test "x$enable_multilib" != xno], + [AC_SUBST(picolibc_multilib_names,"rv32i-ilp32 rv32iac-ilp32 rv32im-ilp32 rv32imac-ilp32 rv32imafc-ilp32f rv64imac-lp64 rv64imafdc-lp64d")], + [AC_SUBST(picolibc_multilib_names,"$with_arch-$with_abi")]) + AS_IF([test "x$enable_multilib" != xno], [AC_SUBST(musl_multilib_names,"rv64imac-lp64 rv64imafdc-lp64d")], [AC_SUBST(musl_multilib_names,"$with_arch-$with_abi")]) @@ -238,6 +252,7 @@ AC_DEFUN([AX_ARG_WITH_SRC], AX_ARG_WITH_SRC(gcc, gcc) AX_ARG_WITH_SRC(binutils, binutils) AX_ARG_WITH_SRC(newlib, newlib) +AX_ARG_WITH_SRC(picolibc, picolibc) AX_ARG_WITH_SRC(glibc, glibc) AX_ARG_WITH_SRC(musl, musl) AX_ARG_WITH_SRC(gdb, gdb) @@ -267,11 +282,16 @@ AS_IF([test "x$enable_libsanitizer" != xno], [AC_SUBST(enable_libsanitizer, --enable-libsanitizer)], [AC_SUBST(enable_libsanitizer, --disable-libsanitizer)]) +AS_IF([test "x$enable_picolibc" != xno], + [default_enable_qemu_system=yes], + [default_enable_qemu_system=no] + ) + AC_ARG_ENABLE(qemu_system, [AS_HELP_STRING([--enable-qemu-system], [Build qemu with system-mode emulation])], [], - [enable_qemu_system=no] + [enable_qemu_system="$default_enable_qemu_system"] ) AS_IF([test "x$enable_qemu_system" != xno], diff --git a/make-picolibc-cross b/make-picolibc-cross new file mode 100644 index 00000000000..f6ccfb52416 --- /dev/null +++ b/make-picolibc-cross @@ -0,0 +1,32 @@ +#!/bin/sh +tuple="$1" +shift +args="" +for cf in "$@"; do + args="$args '$cf'," +done +cat << EOF +[binaries] +c = '${tuple}-gcc' +ar = '${tuple}-ar' +as = '${tuple}-as' +strip = '${tuple}-strip' +nm = '${tuple}-nm' +exe_wrapper = ['sh', '-c', 'test -z "\$PICOLIBC_TEST" || run-riscv "\$@"', 'run-riscv'] + +[host_machine] +system = 'riscv' +cpu_family = 'riscv' +cpu = 'riscv' +endian = 'little' + +[properties] +c_args = [ ${args} '-nostdlib', '-fno-common', '-ftls-model=local-exec' ] +# default multilib is 64 bit, which requires medany +c_args_ = [ '-mcmodel=medany' ] +skip_sanity_check = true +default_flash_addr = '0x80000000' +default_flash_size = '0x00200000' +default_ram_addr = '0x80200000' +default_ram_size = '0x00200000' +EOF