How do I point out OS includes? -- Or how to Build My Own SDK using Newlib
Wed Apr 18 17:24:00 GMT 2007
I've followed this conversation with great interest. Some of the
issues I recognize from my own experiance, some of them I don't (the
latter might however very well be due to that I haven't stumbled
across them yet).
Here's my 10 cent worth of contribution:
There's a lot of cross how-to's circulating the Net and I like many
others have learned the hard way by trial-and-error over the years.
I've assembled a how-to of my own from bits and pieces from a little
bit of everywhere:
IMO there is however an "issue" worth special attention, which is the
actual OS intricacies. In my experience building a Newlib based cross
tool-chain without having Newlib support a specific OS (or kernel) is
a bad idea. Even if one succeeds, one might end up with two different
sets of header files (one belonging to "_my_OS" and the other
belonging to Newlib – the native ones I don't mention since it's
already accurately explained by previous posts). These two are almost
certainly incompatible with each other and there is inherently a great
risk of the final application using the wrong one. One might be able
to compile applications with it this tool-chain, but sooner or later
the miss-matches will show up and the application will misbehave badly
*should* be enough. If it isn't then the OS in question is not
supported by Newlib.
So then what? Bummer! (...or not?)
IMHO there's only one *proper* way to deal with this and that is to
get "_my_OS_" integrated into the Newlib sources. This however is not
at all as smooth as it might seem. One of the reasons are that we
don't want every single OS or system (invented neither by me nor by my
grand-mother) to be part of the Newlib repository. It would pollute
the Newlib sources and only make it more difficult to maintain. The
only choice then, is for each vendor to maintain each integration
outside of Newlib (which is a lot of tedious work).
Alternatively there is another approach that could work. Since a while
ago I've been experimenting with a minimal Newlib patch called HIXS (
Basically it's a very simple stubbed framework for syscalls (inspired
by the RTEMS folks btw) with the added ability to modify the syscalls
dynamically *after* the whole tool-chain is built.
It has some benefits, but also some drawbacks:
+ HIXS is generic and need not to be specially adapted to any
architecture. It should work for all.
+ It will permit a compete build of a cross tool-chain all the way
from binutils to GDB for most architectures (I've tried it on PowerPC,
Blackfin, ARM, x86 and MIPS so far).
+ It will fool most configure scripts using the produced tool-chain
and it will thereby permit a finalized GCC and GDB build (i.e. some of
the GCC_NO_EXECUTABLES nitwits will automagically go away).
- It will not produce runnable code (read below)
- It has a slight run-time penalty
HIXS contains simple stubs for all the syscalls. For applications to
work, HIXS however requires an additional code block as part of each
applications (or kernels) boot sequence that binds the real syscalls
to specific function pointers used in each corresponding stub. The
function pointers are global and follow a simple naming convention
which makes the binding process quite pain-less.
I'm not trying to sell HIXS and I'd be happy to learn from others
that's come up with other solutions. All I'm saying is that I believe
we've stumbled across an area that is a real nightmare in all it's
aspects and an area that could be improved.
On 4/18/07, Anders Lindgren <email@example.com> wrote:
> Thanks for your detailed answer. I can sense the frustration you've gone
> through learning all this -- I've certainly felt quit a bit of it over the
> years, learning this stuff mostly by trial and error. :-)
> I agree on most of your points, it's quite similar to what I typically
> Yes, I am working with custom OSes, for embedded systems. The situation
> is typically this:
> - A complete toolchain is packaged somewhere (by me), and people just
> install it and add it to their $PATH. The command line challenged crowd
> gets a "build_prompt.bat" file to click on, in the Wintendo case. ;-)
> Moving it around is no problem because gcc etc finds its own includes,
> libs and binaries relative to itself.
> - The OS and the rest of the firmware source code is checked out of some
> version control system, and can be located just about anywhere on a user's
> hard disk. The firmware's build system uses an environment variable
> ($ROOT, say) and *everything* is referenced relative (under) this top
> directory -- except the toolchain, which just needs to be in $PATH
> somehwere. In practice, the toolchain is in a standard place, too.
> Up until now, building these cross-toolchains have been simple enough
> that I never felt a need to try things like crosstool. I've traditionally
> - Added my target to binutils, gcc and newlib configurations. Normally
> this only requires some trivial changes to config.sub, config.gcc and
> configure.host in newlib, plus a libc/sys/foo dir for my target for the
> syscalls, if any.
> - Built and installed binutils configured as --target=foo-bar-baz
> --prefix=/my/tool/dir --program-prefix=foo- # Shorter to type.
> - Soft-linked foo-bar-baz-$file to all of binutils' foo-$file (because gcc
> is too stupid to guess that if I'm building it with program-prefix=foo,
> binutils might just have been, too).
> - Soft-linked newlib-v.w.0/newlib into gcc-x.y.z/, and built the lot.
> The configure/build/install part of this I typically put in a script and
> just go.
> This has worked fine for a couple of years, because at first no syscalls
> were used in my newlib and, when I first started integrating stdio
> support, I got away without overriding any newlib headers. So the new
> thing here is really just that my target has ended up needing to provide
> it's own version of sys/lock.h -- which now depends on OS headers. These
> are of course located not in a fix location, but somewhere under $ROOT,
> wherever that is.
> Maybe --with-sysroot + some symlinks would've accomplished what I ended
> up doing: I built using --with-headers=$ROOT/foo/include, installed
> everything, and then rm -rf'd $prefix/foo-bar-baz/sys-include/*. Since the
> toolchain is only used within (or in combination with) the firmware build
> system, there'll always be a -I pointing out the OS includes. While
> changes to those OS includes (admittedly rare) may very well mean I need
> to rebuild newlib, I _don't_ want to keep non-versioned copies of them
> inside the gcc tree.
> I had to disable libssp (its configure appeared to try to execute a
> _target_ binary after a GCC_NO_EXECUTABLES token, or somesuch) and
> libstdc++ (which had complaints about no native atomic operations being
> available), but I didn't look further into either since I don't actually
> use them.
> Hrrm, I've written a rather detailed HOWTO of this whole procedure (for
> my own memory), and with these include issues more or less figured out,
> I'd say it's quite complete. I think I'll update it with notes on target
> includes and put it on the web -- it should be a good tutorial for
> beginners. I'd appreciate all feedback if any of you care to read it when
> it's up.
More information about the Newlib