GNU Libs with Debug Information: Rebuilding the GNU ARM Libraries

DZone 's Guide to

GNU Libs with Debug Information: Rebuilding the GNU ARM Libraries

· Java Zone ·
Free Resource

With my DIY tool chain (see “Constructing a Classroom IDE with Eclipse for ARM“) I get a complete tool chain. I do not need to build that tool chain from the sources for Windows, as all the binaries are nicely pre-compiled and made available. But there is one issue I face from time to time: as the libraries provided by ARM do not come with sources and debug information enabled, I end up with that “No source available for …” message in the debugger:

No Source Available

No Source Available

The solution is to grab the C/C++ library sources from the ARM launchpad site and get it built locally the way I need it.

Building the Libraries on Windows

I’m rebuilding the libraries on my Windows 7 64bit machine. Unfortunately, I have not found any good steps or tutorials how to do this anywhere (that’s why I’m documenting my findings here, otherwise I simply could point to an existing tutorial).While it would (or should?) be possible to re-build all the binaries ARM provided, I’m only interested in building the newlib and newlib-nano libraries, so I can have debug and source information enabled.

Actually it seems that doing things like this on a Windows machine is even more challenging that on Linux: the make files and scripts are all tuned for a Linux system, so to have it built on my machine, some extra steps and tools are needed. Oh well….

Setup of Tools and Environments

The first step is to setup the environment and to download and install the tools and files needed.

Setup of arm-none-eabi Tools

Because I want to build the libraries with the provided arm-none-eabi tools (compiler, linker, etc), I need to make sure they are found by the build process.

:idea: Usually I do *not* want the GNU binaries in my global system path. Setting global environment variables is a road to disaster in my view. With my Eclipse tool environment, I reference the tool chain locally from my IDE/tools folder. Oh well, it looks like at least for building the GNU libraries I have to break with my principles yet again :-(

MinGW and MSYS

The build process is assuming a Linux environment and utilities. To run it on a Windows host, the corresponding environment needs to be installed. This is MinGW (Minimalist GNU for Windows) and MSYS (a set of shell utilities). The build process needs to run from the MinGW shell, and cannot be run from a normal Windows DOS prompt.

Go to http://www.mingw.org/ and download the installer (links on the left hand side):

MinGW Installer

MinGW Installer

In the MinGW Installation Manager, make sure these tools are installed (marked with green box):

MinGW Installation Manager

MinGW Installation Manager

We need to use the MinGW/MSys shell later on, and it needs to be run from a shortcut. So from the msys.bat, create a short cut on the desktop or in the start menu:

Create a shortcut for msys.bat

Create a shortcut for msys.bat

Later I will run the shell from that shortcut:

Shortcut on Windows Desktop

Shortcut on Windows Desktop

The documentation about MSYS can be found at http://www.mingw.org/wiki/MSYS

System PATH

I have the path where I have the compiler (arm-none-eabi-gcc.exe) added to the end of my PATH system variable. For my DIY IDE this isc:\tools\IDE\gcc\bin



The next thing is a weird thing: somehow the library build process is looking for a arm-none-eabi-cc.exe. If not found, it will report an error later in the build process that arm-none-eabi.cc.exe has not been found.

Others have reported this problem too (see http://stackoverflow.com/questions/3660672/getting-error-on-compiling-newlib). To solve that problem, I have copied arm-none-eabi-gcc.exe and named it arm-none-eabi-cc.exe.

Installing the Library Sources

From https://launchpad.net/gcc-arm-embedded, download the source package (at this time it is gcc-arm-none-eabi-4_8-2014q2-20140609-src.tar.bz2), then unpack it.

In this tutorial, I have unpacked the files into a folder named ‘lib_build’ inside my tool chain:

Source Package

Source Package

There are multiple zip files in it, but I only need the newlib-nano-2.1.tar.bz2 and the newlib.tar.bz2 unpacked. I have them unpacked into the ‘src’ folder (see above screenshot).

Patching the Library Build

Unfortunately, the build does not work out of the box (at least under Windows). I have found two issues which need to be fixed to run the build successfully:

  1. Need to change line endings for MakeInfo in a .texi file
  2. Fix the make file rules in Makefile.in file

Fix for MakeInfo

On Windows 64bit system there seems to be a long-standing issue that MakeInfo fails with:

Unknown index 'fn' and/or 'cp' in ...

MakeInfo Failure

MakeInfo Failure

MakeInfo creates documentation, and seem failing to read library info (while it works on Linux). See https://sourceware.org/bugzilla/show_bug.cgi?id=14678 for details on this bug. The problem is very likely because makeinfo has a problem with Windows line endings. Open the file


in Eclipse and convert the file line delimiters to Unix style, then save the file:

Converting File Delimiters to Unix

Converting File Delimiters to Unix

Do the same thing for the newlib file


Patching the Library Makefile.in File

There is a problem with the make file rules in the libgloss part:

*** No rule to make target '../../../../../newlib-nano-2.1/libgloss/arm/../config/default.hm', needed by 'Makefile'. Stop.
No rule to make target for libgloss

No rule to make target for libgloss

The workaround (see this discussion) is to patch the ‘Makefile.in’ file:

The patch details:

From: Agustin Henze <tin@debian.org>
Date: Fri, 3 Jan 2014 11:29:55 -0300
Subject: [PATCH] Fix wrong path to libgloss/config/default.mh

 libgloss/arm/cpu-init/Makefile.in | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libgloss/arm/cpu-init/Makefile.in b/libgloss/arm/cpu-init/Makefile.in
index 547c58d..d63149f 100644
--- a/libgloss/arm/cpu-init/Makefile.in
+++ b/libgloss/arm/cpu-init/Makefile.in
@@ -18,6 +18,7 @@ libdir = @libdir@
 tooldir = $(exec_prefix)/$(target_alias)
 objtype = @objtype@
+host_makefile_frag = $(srcdir)/../../config/default.mh
@@ -80,7 +81,7 @@ info:
-Makefile: Makefile.in ../config.status @host_makefile_frag_path@
+Makefile: Makefile.in ../config.status ${host_makefile_frag_path}
     $(SHELL) ../config.status --file cpu-init/Makefile
 ../config.status: ../configure

Either apply the patch file, or open the Makefile.in in an editor and add:

host_makefile_frag = $(srcdir)/../../config/default.mh

Makefile.in Patch Part 1

Makefile.in Patch Part 1

Down further the file, change the Makefile line to:

Makefile: Makefile.in ../config.status ${host_makefile_frag_path}

Makefile.in Patch Part 2

Makefile.in Patch Part 2

Do the same for this make file in the newlib library sources:


With the two patches applied to both the newlib-nano and newlib, I’m able to build the libraries in the next step.

Building the Libraries

Building each of the libraries (newlib and newlib-nano) is a multi-step process:

  1. Configure the build
  2. Run the make file to build
  3. Run the make file to install/copy the files

The question is: what are the correct parameters to configure the build?

The answer is: have a look at the build-toolchain.sh provided in the source package, and locate the parameters for the newlib-nano and newlib packages:

Newlib-nano configuration options

Newlib-nano configuration options

newlib configuration options

newlib configuration options

I have created two shell scripts which will do the necessary calls for me, but you can execute the commands one-by-one on the shell too:

Build Scripts

Build Scripts

This is the build script for the newlib-nano:

# Script to build newlib and newlib-nano
# - make sure the cross-tool chain is present in the PATH
# - untar newlib-nano-2.1.tar.tar.bz2
# - untar newlib.tar.bz2
echo Creating build directory...
mkdir newlib-nano.build
echo Entering build directory...
cd newlib-nano.build
# run configure program to configure the build
echo Configuring newlib-nano build...
../gcc-arm-none-eabi-4_8-2014q2-20140609/src/newlib-nano-2.1/configure \
  --target=$TARGET \
  --prefix=$BUILDDIR_NATIVE/target-libs \
  --disable-newlib-supplied-syscalls \
  --enable-newlib-reent-small \
  --disable-newlib-fvwrite-in-streamio \
  --disable-newlib-fseek-optimization \
  --disable-newlib-wide-orient \
  --enable-newlib-nano-malloc \
  --disable-newlib-unbuf-stream-opt \
  --enable-lite-exit \
  --enable-newlib-global-atexit \
echo Building newlib-nano...
make -j
echo Installing...
make install

And the same for the newlib:

# Script to build newlib
# - make sure the cross-tool chain is present in the PATH
# - untar newlib.tar.bz2
echo Creating build directory...
mkdir newlib.build
echo Entering build directory...
cd newlib.build
# run configure program to configure the build
echo Configuring newlib build...
../gcc-arm-none-eabi-4_8-2014q2-20140609/src/newlib/configure \
  --target=$TARGET \
  --infodir=$INSTALLDIR_NATIVE_DOC/info \
  --mandir=$INSTALLDIR_NATIVE_DOC/man \
  --htmldir=$INSTALLDIR_NATIVE_DOC/html \
  --pdfdir=$INSTALLDIR_NATIVE_DOC/pdf \
  --enable-newlib-io-long-long \
  --enable-newlib-register-fini \
  --disable-newlib-supplied-syscalls \
#echo Building newlib-nano...
make -j
#echo Installing...
make install

To build the libraries, launch the msys.bat with the shortcut previously created, and cd (change directory) into the folder we have unpacked the source package and run the above shell scripts, or execute the commands on the command line.

If doing it directly on the command line, I show it here for the newlib-nano.

Create a folder ‘newlib-nano.build’

mkdir newlib-nano.build
Cd (change directory) into that folder.

cd newlib-nano.build

Run the configure command:

../newlib-nano-2.1/configure --target=arm-none-eabi --prefix=/C/tools/newlib-nano-arm-none-eabi --disable-newlib-supplied-syscalls --enable-newlib-reent-small --disable-newlib-fvwrite-in-streamio --disable-newlib-fseek-optimization --disable-newlib-wide-orient --enable-newlib-nano-malloc --disable-newlib-unbuf-stream-opt --enable-lite-exit --enable-newlib-global-atexit --disable-nls

Then do a make witih

make -j

and finally install it with

make install

The needed configuration options can be taken from the ‘build-toolchain.sh’ present in the root of the source zip file.

The build is then started with

make -j
Make command

Make command

The build process takes about 30 minutes.

If finished successfully, use

make install

To ‘install’ the libraries into the folder specifed with –prefix in the configuration settings.

Assembling the Libraries

Now I have the two libraries built:

  • newlib-nano in lib_build\install-native.newLibnano\target-libs\arm-none-eabi\lib
  • newlib in lib_build\install-native.newLib\arm-none-eabi\lib

The newlib-nano libs have a *_s.a extension, so I rename them with a shell script:


echo Creating directories
mkdir ./build.install
cd ./build.install

mkdir ./arm-none-eabi
cd ./arm-none-eabi

mkdir ./lib
cd ./lib

mkdir ./armv6-m
mkdir ./armv7-ar
mkdir ./armv7e-m
mkdir ./armv7-m
mkdir ./cpu-init
mkdir ./fpu
mkdir ./thumb

cd ../..

echo Rename newlib-nano files
mv $NEWLIB_NANO_LIB/libc.a $(NEWLIB_NANO_LIB)/libc_s.a
mv $NEWLIB_NANO_LIB/libg.a $NEWLIB_NANO_LIB/libg_s.a

mv $NEWLIB_NANO_LIB/armv6-m/libc.a $(NEWLIB_NANO_LIB)/armv6-m/libc_s.a
mv $NEWLIB_NANO_LIB/armv6-m/libg.a $NEWLIB_NANO_LIB/armv6-m/libg_s.a

mv $NEWLIB_NANO_LIB/armv7-ar/libc.a $NEWLIB_NANO_LIB/armv7-ar/libc_s.a
mv $NEWLIB_NANO_LIB/armv7-ar/libg.a $NEWLIB_NANO_LIB/armv7-ar/libg_s.a

mv $NEWLIB_NANO_LIB/armv7e-m/libc.a $NEWLIB_NANO_LIB/armv7e-m/libc_s.a
mv $NEWLIB_NANO_LIB/armv7e-m/libg.a $NEWLIB_NANO_LIB/armv7e-m/libg_s.a

mv $NEWLIB_NANO_LIB/armv7-m/libc.a $NEWLIB_NANO_LIB/armv7-m/libc_s.a
mv $NEWLIB_NANO_LIB/armv7-m/libg.a $NEWLIB_NANO_LIB/armv7-m/libg_s.a

mv $NEWLIB_NANO_LIB/fpu/libc.a $NEWLIB_NANO_LIB/fpu/libc_s.a
mv $NEWLIB_NANO_LIB/fpu/libg.a $NEWLIB_NANO_LIB/fpu/libg_s.a

mv $NEWLIB_NANO_LIB/thumb/libc.a $NEWLIB_NANO_LIB/thumb/libc_s.a
mv $NEWLIB_NANO_LIB/thumb/libg.a $NEWLIB_NANO_LIB/thumb/libg_s.a

And then move the newlib libraries over the newlib-nano libraries (merge):


With this, I have a new ‘lib’ folder I can use. I rename my original gcc/arm-none-eabi/lib one to lib.orig and copy my new library folder:

New Library Folder with Original as Backup

New Library Folder with Original as Backup

With this, I have my new library in place, and can go back to the original state if necessary.

Debugging the Library with Source Code

The the benifit of all the work: I can now debug and step through the library code with source files displayed:

Debugging Library with Source Code

Debugging Library with Source Code

:-) :-) :-)


It takes some time and knowledge to build the newlib and newlib-nano libraries from the sources. But doing so, I can build the libraries with debug information. What is missing now is a good way to provide my custom optimization options for the library build, and an automated way/script to build my set of library files.

Having the ability to re-build the library sources the way I want is a huge advantage of using open source libraries and tools. Yet another reason the swap out proprietary libraries as shown in this post :-).

Happy Libraring :-)


Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}