diff options
author | Christoph Müllner <christoph.muellner@vrull.eu> | 2022-09-28 00:14:41 +0200 |
---|---|---|
committer | Kito Cheng <kito.cheng@sifive.com> | 2023-05-17 14:01:44 +0800 |
commit | ea26fd6cb82aaa8e7fc95adc704442dc466dac9e (patch) | |
tree | a9edf205efb85f89dbb0509a5ccfa9e3212adf65 | |
parent | ee1bb922707b53b479552b4aa8fb009b35ce8d22 (diff) | |
download | riscv-gnu-toolchain-ea26fd6cb82aaa8e7fc95adc704442dc466dac9e.zip riscv-gnu-toolchain-ea26fd6cb82aaa8e7fc95adc704442dc466dac9e.tar.gz riscv-gnu-toolchain-ea26fd6cb82aaa8e7fc95adc704442dc466dac9e.tar.bz2 |
Add support to build LLVM/clang with C and C++ support
We currently have a stale "llvm" branch, that does not build.
However, there is clear demand in the RISC-V toolchain community
for a working LLVM on top of a recent GNU toolchain.
In order to build such a toolchain, quite some LLVM and clang know-how is
required to avoid path issues at LLVM build time or later when using clang.
The main purpose of this commit is to demonstrate a way to combine
the RISC-V GNU toolchain repo with LLVM, with the intent to save
others hours of frustration, debugging time or support time.
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
-rw-r--r-- | Makefile.in | 54 | ||||
-rw-r--r-- | README.md | 42 | ||||
-rwxr-xr-x | configure | 53 | ||||
-rw-r--r-- | configure.ac | 12 |
4 files changed, 142 insertions, 19 deletions
diff --git a/Makefile.in b/Makefile.in index 71369ab..d4cc9a4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -12,6 +12,7 @@ GDB_SRCDIR := @with_gdb_src@ QEMU_SRCDIR := @with_qemu_src@ SPIKE_SRCDIR := @with_spike_src@ PK_SRCDIR := @with_pk_src@ +LLVM_SRCDIR := @with_llvm_src@ SIM ?= @WITH_SIM@ @@ -115,8 +116,16 @@ newlib: stamps/build-gdb-newlib linux: stamps/build-gdb-linux endif linux-native: stamps/build-gcc-linux-native +ifeq (@enable_llvm@,--enable-llvm) +all: stamps/build-llvm-@default_target@ +newlib: stamps/build-llvm-newlib +linux: stamps/build-llvm-linux +ifeq (@multilib_flags@,--enable-multilib) +$(error "Setting multilib flags for LLVM builds is not supported.") +endif +endif -.PHONY: build-binutils build-gdb build-gcc1 build-libc build-gcc2 build-qemu +.PHONY: build-binutils build-gdb build-gcc1 build-libc build-gcc2 build-qemu build-llvm build-binutils: stamps/build-binutils-@default_target@ build-gdb: stamps/build-gdb-@default_target@ build-gcc%: stamps/build-gcc-@default_target@-stage% @@ -127,6 +136,7 @@ build-libc: stamps/build-newlib stamps/build-newlib-nano \ stamps/merge-newlib-nano endif build-qemu: stamps/build-qemu +build-llvm: stamps/build-llvm-@default_target@ REGRESSION_TEST_LIST = gcc @@ -272,6 +282,12 @@ else SPIKE_SRC_GIT := endif +ifeq ($(findstring $(srcdir),$(LLVM_SRCDIR)),$(srcdir)) +LLVM_SRC_GIT := $(LLVM_SRCDIR)/.git +else +LLVM_SRC_GIT := +endif + ifneq ("$(wildcard $(GCC_SRCDIR)/.git)","") GCCPKGVER := g$(shell git -C $(GCC_SRCDIR) describe --always --dirty --exclude '*') else @@ -865,6 +881,42 @@ stamps/build-qemu: $(QEMU_SRCDIR) $(QEMU_SRC_GIT) mkdir -p $(dir $@) date > $@ +stamps/build-llvm-linux: $(LLVM_SRCDIR) $(LLVM_SRC_GIT) \ + stamps/build-gcc-linux-stage2 + # We have the following situation: + # - sysroot directory: $(INSTALL_DIR)/sysroot + # - GCC install directory: $(INSTALL_DIR) + # However, LLVM does not allow to set a GCC install prefix + # (-DGCC_INSTALL_PREFIX) if a sysroot (-DDEFAULT_SYSROOT) is set + # (the GCC install prefix will be ignored silently). + # Without a proper sysroot path feature.h won't be found by clang. + # Without a proper GCC install directory libgcc won't be found. + # As a workaround we have to merge both paths: + mkdir -p $(SYSROOT)/lib/ + ln -s $(INSTALL_DIR)/lib/gcc $(SYSROOT)/lib/gcc + rm -rf $@ $(notdir $@) + mkdir $(notdir $@) + cd $(notdir $@) && \ + cmake $(LLVM_SRCDIR)/llvm \ + -DCMAKE_INSTALL_PREFIX=$(INSTALL_DIR) \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_TARGETS_TO_BUILD="RISCV" \ + -DLLVM_ENABLE_PROJECTS="clang;lld" \ + -DLLVM_ENABLE_RUNTIMES="compiler-rt;libcxx;libcxxabi;libunwind" \ + -DLLVM_DEFAULT_TARGET_TRIPLE="$(LINUX_TUPLE)" \ + -DDEFAULT_SYSROOT="$(INSTALL_DIR)/sysroot" \ + -DLLVM_RUNTIME_TARGETS=$(call make_tuple,$(XLEN),linux-gnu) \ + -DLLVM_INSTALL_TOOLCHAIN_ONLY=On \ + -DLLVM_PARALLEL_LINK_JOBS=4 + $(MAKE) -C $(notdir $@) + $(MAKE) -C $(notdir $@) install + cd $(INSTALL_DIR)/bin && ln -s clang $(LINUX_TUPLE)-clang + mkdir -p $(dir $@) && touch $@ + +stamps/build-llvm-newlib: + echo "Building LLVM is only supported in combination with a Linux toolchain." + exit 1 + stamps/build-dejagnu: $(srcdir)/dejagnu $(srcdir)/dejagnu/.git rm -rf $@ $(notdir $@) mkdir $(notdir $@) @@ -245,6 +245,37 @@ The command below can be used to run the glibc tests: make check-glibc-linux +### LLVM / clang + +LLVM can be used in combination with the RISC-V GNU Compiler Toolchain +to build RISC-V applications. To build LLVM with C and C++ support the +configure flag `--enable-llvm` can be used. + +E.g. to build LLVM on top of a RV64 Linux toolchain the following commands +can be used: + + ./configure --prefix=$RISCV --enable-llvm --enable-linux + make + +Note, that a combination of `--enable-llvm` and multilib configuration flags +is not supported. +Also note, that building LLVM is only supported in combination with building +a Linux toolchain. + +Below is an example how to build a rv64gc Linux toolchain with LLVM support, +how to use it to build a C and a C++ application using clang, and how to +execute the generated binaries using QEMU: + + # Build rv64gc toolchain with LLVM + ./configure --prefix=$RISCV --enable-llvm --enable-linux --with-arch=rv64gc --with-abi=lp64d + make -j$(nproc) all build-sim SIM=qemu + # Build C application with clang + $RISCV/bin/clang -march=rv64imafdc -o hello_world hello_world.c + $RISCV/bin/qemu-riscv64 ./hello-world + # Build C++ application with clang + $RISCV/bin/clang++ -march=rv64imafdc -stdlib=libc++ -o hello_world_cpp hello_world_cpp.cxx + $RISCV/bin/qemu-riscv64 ./hello-world_cpp + ### Development This section is only for developer or advanced user, or you want to build @@ -295,13 +326,14 @@ For example you have a gcc in `$HOME/gcc`, use `--with-gcc-src` can specify that Here is the list of configure option for specify source tree: - --with-gcc-src --with-binutils-src - --with-newlib-src - --with-glibc-src - --with-musl-src + --with-gcc-src --with-gdb-src + --with-glibc-src --with-linux-headers-src + --with-llvm-src + --with-musl-src + --with-newlib-src + --with-pk-src --with-qemu-src --with-spike-src - --with-pk-src @@ -587,6 +587,7 @@ LIBOBJS qemu_targets enable_libsanitizer with_linux_headers_src +with_llvm_src with_pk_src with_spike_src with_qemu_src @@ -596,6 +597,7 @@ with_glibc_src with_newlib_src with_binutils_src with_gcc_src +enable_llvm enable_gdb with_guile with_system_zlib @@ -651,7 +653,6 @@ infodir docdir oldincludedir includedir -runstatedir localstatedir sharedstatedir sysconfdir @@ -690,6 +691,7 @@ with_host with_system_zlib with_guile enable_gdb +enable_llvm with_gcc_src with_binutils_src with_newlib_src @@ -699,6 +701,7 @@ with_gdb_src with_qemu_src with_spike_src with_pk_src +with_llvm_src with_linux_headers_src enable_libsanitizer enable_qemu_system @@ -749,7 +752,6 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1002,15 +1004,6 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1148,7 +1141,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir + libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1301,7 +1294,6 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1339,6 +1331,7 @@ Optional Features: slow, only enable it when developing gcc [--disable-gcc-checking] --disable-gdb Don't build GDB, as it's not upstream + --enable-llvm Build LLVM (clang) --enable-libsanitizer Build libsanitizer, which only supports rv64 --enable-qemu-system Build qemu with system-mode emulation @@ -1375,6 +1368,7 @@ Optional Packages: --with-qemu-src Set qemu source path, use builtin source by default --with-spike-src Set spike source path, use builtin source by default --with-pk-src Set pk source path, use builtin source by default + --with-llvm-src Set llvm source path, use builtin source by default --with-linux-headers-src Set linux-headers source path, use builtin source by default @@ -3556,6 +3550,20 @@ else fi +# Check whether --enable-llvm was given. +if test "${enable_llvm+set}" = set; then : + enableval=$enable_llvm; enable_llvm=yes +fi + + +if test "x$enable_llvm" != xyes; then : + enable_llvm=--disable-llvm + +else + enable_llvm=--enable-llvm + +fi + { @@ -3729,6 +3737,25 @@ else fi } +{ + +# Check whether --with-llvm-src was given. +if test "${with_llvm_src+set}" = set; then : + withval=$with_llvm_src; +else + with_llvm_src=default + +fi + + if test "x$with_llvm_src" != xdefault; then : + with_llvm_src=$with_llvm_src + +else + with_llvm_src="\$(srcdir)/llvm" + +fi + + } # Check whether --with-linux-headers-src was given. diff --git a/configure.ac b/configure.ac index 16178c7..a0cd3b6 100644 --- a/configure.ac +++ b/configure.ac @@ -221,6 +221,17 @@ AS_IF([test "x$enable_gdb" != xno], [AC_SUBST(enable_gdb, --enable-gdb)], [AC_SUBST(enable_gdb, --disable-gdb)]) +AC_ARG_ENABLE(llvm, + [AS_HELP_STRING([--enable-llvm], + [Build LLVM (clang)])], + [enable_llvm=yes], + [] + ) + +AS_IF([test "x$enable_llvm" != xyes], + [AC_SUBST(enable_llvm, --disable-llvm)], + [AC_SUBST(enable_llvm, --enable-llvm)]) + AC_DEFUN([AX_ARG_WITH_SRC], [{m4_pushdef([opt_name], with_$1_src) AC_ARG_WITH($1-src, @@ -244,6 +255,7 @@ AX_ARG_WITH_SRC(gdb, gdb) AX_ARG_WITH_SRC(qemu, qemu) AX_ARG_WITH_SRC(spike, spike) AX_ARG_WITH_SRC(pk, pk) +AX_ARG_WITH_SRC(llvm, llvm) AC_ARG_WITH(linux-headers-src, [AC_HELP_STRING([--with-linux-headers-src], |