HOME | CERN
Building a GNU GCC cross compiler (RX,M32C,M16C)
- build on Linux
- compile on Linux
- execute on Renesas MCU
As I spent a lot of time to understand and make this working so I decided to write a little guide to save time and effort for other newbies like me.
This guide is to build the GNU GCC cross compiler on a Linux machine, later you will use this same machine to compile and generate code for your favorite Renesas MCU.
other guides 2 - build on Linux, compile on Windows, execute on Renesas MCU
3 - build on Windows (Cygwin), compile on Windows (Cygwin), execute on Renesas MCU
4 - build on Windows (Cygwin), compile on Windows, execute on Renesas MCU
5 - build on Windows (MSYS, Mingw), compile on Windows, execute on Renesas MCU
sources The source code of the GNU GCC cross compiler we will build can be downloaded from several places.
The official websites are:
  • GNU binutils (assembler, linker and other tools)
  • GNU GCC (the language compiler, in this case C and/or C++)
  • Redhat newlib (a C library intended for use on embedded systems)
  • GNU GMP (The GNU Multiple Precision Arithmetic Library)
  • MPFR ( C library for multiple-precision floating-point computations with correct rounding)
  • MPC ( C library for the arithmetic of complex numbers with arbitrarily high precision and correct rounding of the result)
Personally I prefer using git.
The corresponding git Mirrors sites are:
I suggest you to download the sources in a directory structure like this (please replace johndoe with you username)

/home/johndoe/gitMirror/binutils
/home/johndoe/gitMirror/gcc
/home/johndoe/gitMirror/newlib
/home/johndoe/src/gmp-v.v.v
/home/johndoe/src/mpfr-v.v.v
/home/johndoe/src/mpc-v.v
What we'll do Using the (native) compiler installed in your linux machine (that is also gcc!!!) we will compile the source code to generated the cross-compiler (linux-renesas) and libraries.

This produced cross-compiler is what you will run to generate the executable code for Renesas MCU.

To deal with the different machine codes that can be involved during the process of producing the cross-compiler the gcc people have defined three arguments
  • --build, The machine you are building on (the actual machine you are using to produce the cross-compiler)
  • --host, The machine you are building for (the machine where you will execute the cross-compiler)
  • --target, The machine that cross-compiler will produce code for
examples of --build and --host are

i386-pc-linux-gnu
pentium4-pc-linux-gnu
i686-pc-linux-gnu
i386-pc-mingw32msvc
i386-pc-mingw32
i586-pc-mingw32
i686-pc-mingw32
i686-w64-mingw32
i686-pc-cygwin

examples of --target are

m32c-elf
rx-elf
Prerequisites On your linux machine you need to have installed and running
GCC compiler
Binutils
gperf
Coreutils
Make
Perl
Bison
Flex
libiconv
libtool
I'm not quite sure of the exact list, these are the tools used during the compilation of the gcc cross-compiler.
Hands on! You can go by hand or use some scripts. The variables I'll explain are the ones used by the scripts.
Note:my skills on linux are very limited and the main goal is to be very explicit so for sure the scripts can be improved a lot.
The very first thing is the correct setup of the variables used by the scripts (in the build_vars.sh)
for the --build (the building ON machine) we'll use the variable THIS_PLATFORM for this guide we can use any of the linux values i.e.:
THIS_PLATFORM=i686-pc-linux-gnu
for the --host (the building FOR machine) we'll use the variable WANTED_COMPILER_PLATFORM for this guide must be the same or compatible as THIS_PLATFORM, i.e.:
WANTED_COMPILER_PLATFORM=THIS_PLATFORM
for --target (the machine that the cross-compiler will produce code for) we can choose:
WANTED_COMPILER_CODE=m32c-elf
or
WANTED_COMPILER_CODE=rx-elf
if you choose m32c-elf it supports only C language
COMPI_LANGUAGES=c
MAKE_LANGUAGES="c"
for the rx-elf it supports both C and C++ languages
COMPI_LANGUAGES=c,c++
MAKE_LANGUAGES="c c++"
now the place where you decided to put the source files
SRC_DIR_NEWLIB=/home/johndoe/gitMirror/newlib
SRC_DIR_BINUTILS=/home/johndoe/gitMirror/binutils
SRC_DIR_GCC=/home/johndoe/gitMirror/gcc
SRC_DIR_GMP=/home/johndoe/src/gmp-5.0.2
SRC_DIR_MPFR=/home/johndoe/src/mpfr-3.1.0
SRC_DIR_MPC=/home/johndoe/src/mpc-0.9
these are the destination directories, where the final produced cross-compiler will be stored
THIS_PLATFORM_PREFIX=/home/johndoe/rx/pre/linux
THIS_PLATFORM_PREFIX_BINUTILS=/home/johndoe/rx/pre/linux
THIS_PLATFORM_PREFIX_GCC=/home/johndoe/rx/pre/linux
THIS_PLATFORM_PREFIX_NEWLIB=/home/johndoe/rx/pre/linux
THIS_PLATFORM_PREFIX_GMP=/home/johndoe/rx/pre/linux/gmp
THIS_PLATFORM_PREFIX_MPFR=/home/johndoe/rx/pre/linux/mpfr
THIS_PLATFORM_PREFIX_MPC=/home/johndoe/rx/pre/linux/mpc
if you try to build in the same directory as the sources you will run into troubles, you need a place to store the intermediate files while producing the cross-compiler
THIS_PLATFORM_BUILD_DIR=/home/johndoe/rx/bld/linux
THIS_PLATFORM_BUILD_BINUTILS=binutils
THIS_PLATFORM_BUILD_GCC=gcc
THIS_PLATFORM_BUILD_NEWLIB=newlib
THIS_PLATFORM_BUILD_GMP=gmp
THIS_PLATFORM_BUILD_MPFR=mpfr
THIS_PLATFORM_BUILD_MPC=mpc
now you are ready to run ./build_all.sh
Step 1 - building binutils The standard procedure with GNU products is configure, make and make install.
cd $THIS_PLATFORM_BUILD_DIR/$THIS_PLATFORM_BUILD_BINUTILS
$SRC_DIR_BINUTILS/configure --target=$WANTED_COMPILER_CODE --prefix=$THIS_PLATFORM_PREFIX_BINUTILS --disable-werror
make
make install
configure prepares all the scripts needed by make and make install and then make and make install do the job.
The --disable-werror changes the default behavior where warnings are treated as errors and stops the compilation.
Step 2 - building GMP cd $THIS_PLATFORM_BUILD_DIR/$THIS_PLATFORM_BUILD_GMP
$SRC_DIR_GMP/configure --disable-shared --prefix=$THIS_PLATFORM_PREFIX_GMP
make
make check
make install
make check compiles and runs the testsuits verifying that GMP works ok.
Normally in embedded system we don't use shared libraries (--disable-shared).
Step 3 - building MPFR cd $THIS_PLATFORM_BUILD_DIR/$THIS_PLATFORM_BUILD_MPFR
$SRC_DIR_MPFR/configure --disable-shared --with-gmp=$THIS_PLATFORM_PREFIX_GMP --prefix=$THIS_PLATFORM_PREFIX_MPFR
make
make check
make install
Build of MPFR needs GMP this is why this is done afterwards.
Step 4 - building MPC cd $THIS_PLATFORM_BUILD_DIR/$THIS_PLATFORM_BUILD_MPC
$SRC_DIR_MPC/configure --disable-shared --with-gmp=$THIS_PLATFORM_PREFIX_GMP --with-mpfr=$THIS_PLATFORM_PREFIX_MPFR --prefix=$THIS_PLATFORM_PREFIX_MPC
make
make check
make install
Build of MPC needs GMP and MPFR this is why this is done afterwards.
Step 5 - building gcc (start) cd $THIS_PLATFORM_BUILD_DIR/$THIS_PLATFORM_BUILD_GCC
$SRC_DIR_GCC/configure --disable-shared --with-newlib=yes --enable-lto --enable-gold --disable-libstdcxx-pch --enable-languages=$COMPI_LANGUAGES --target=$WANTED_COMPILER_CODE --with-gmp=$THIS_PLATFORM_PREFIX_GMP --with-mpfr=$THIS_PLATFORM_PREFIX_MPFR --with-mpc=$THIS_PLATFORM_PREFIX_MPC --prefix=$THIS_PLATFORM_PREFIX_GCC
make configure-build-libiberty
make all-build-libiberty
make all-gcc
make install-gcc
You see, gcc needs GMP, MPFR and MPC this is why we were forced to compile them.
--with-newlib tells the compiler to use newlib headers wherever possible (also for other libraries than libgcc).
--without-headers tells the compiler to build libgcc (only it) without any headers at all.
(Note that --without-headers is the default for a cross-compiler.)
So if we use --without-headers --with-newlib, libgcc will be built without requiring the presence of any header, and other libraries will be built with newlib headers.
If we use --without-headers alone, libgcc will be built without requiring the presence of any headers, and other libraries will be built with libc headers.
(When building a cross-compiler, in practice what will happen is that libgcc will build and the other libraries will fail to build.)
If I use --with-newlib alone, libgcc and other libraries will be built with newlib headers.
(When building a cross-compiler, you do need to provide some headers for the libraries other than libgcc. In other words, at build time, the compiler needs to be able to find the libc headers. This is typically done using one of --with-newlib, --with-sysroot, or --with-build-sysroot.)
If we use nothing, libgcc and other libraries will be built with libc headers.
You can disable unwanted parts with
--disable-threads
--disable-libmudflap
--disable-libssp
--disable-libgomp
--disable-libquadmath
--disable-target-libiberty
--disable-target-zlib
You can run configure --help to get the complete list of available options.
Step 6 - building newlib cd $THIS_PLATFORM_BUILD_DIR/$THIS_PLATFORM_BUILD_NEWLIB
$SRC_DIR_NEWLIB/configure --disable-libquadmath --disable-libada --disable-libssp --target=$WANTED_COMPILER_CODE --prefix=$THIS_PLATFORM_PREFIX_NEWLIB
make
make install
Step 7 - building gcc final (libraries) cd $THIS_PLATFORM_BUILD_DIR/$THIS_PLATFORM_BUILD_GCC
make
make install
Ta.. daaa!!!!
You can go to $THIS_PLATFORM_PREFIX/bin and run your cross-compiler to generated code for the Renesas MCU
Notes For newlib I want the specific defines REENTRANT_SYSCALLS_PROVIDED, INTERNAL_NEWLIB DEFINE_MALLOC, DEFINE_FREE, DEFINE_REALLOC, DEFINE_CALLOC. Because my targets are rx-elf and m32c-elf when I try via CFLAGS is not a complete sucess.
I finish patching source/newlib/newlib/configure.host
adding in the last case "${host}" in
the case
rx-*-*)
default_newlib_io_long_long="yes"
newlib_cflags="${newlib_cflags} -Os -DREENTRANT_SYSCALLS_PROVIDED -DINTERNAL_NEWLIB -DDEFINE_MALLOC -DDEFINE_FREE -DDEFINE_REALLOC -DDEFINE_CALLOC"
syscall_dir=
;;
(and similar for m32c-*-* )
because the case rx-*-* was not defined and was passing at default adding always -DMISSING_SYSCALL_NAMES what is not good for me.