Page 1 of 1

GCC cross compiler tutorial: full freestanding C++ toolchain

Posted: Wed Aug 03, 2011 10:35 am
by xenos
This post is based on a discussion in this thread. The basic problem is the following:

In order to use C effectively and in a compiler independent fashion for OS development / writing a kernel, one does not only need a cross compiler for the desired target architecture, but a complete freestanding environment - that is, a C cross compiler plus a few header files, such as stdint.h, as defined by the C standard (C90, C99 - whatever you prefer). These header files contain things like typedefs for types such as uint32_t, which are hard to define in a compiler independent fashion without these headers (recall that sizeof(int) is implementation defined and not guaranteed to be 32 bits). Fortunately, you get all these C header files for free when you compile and install your GCC cross compiler.

The same problem applies to C++. Standards such as C++0x define a number of freestanding headers such as cstdint, which basically cover the same typedefs as the C headers, plus / minus some changes. However, unfortunately these header are not installed if one follows the instructions in the wiki. They are not part of the GCC C++ cross compiler, but instead part of the C++ standard library. GCC comes with its version of the C++ library (called libstdc++-v3), which is not covered by the cross compiler tutorial in the wiki.

Digging through the wiki, I found 3 pages that contain relevant information:
  • GCC Cross-Compiler deals with compiling a bare metal cross compiler for both C and C++. While this is sufficient to build a freestanding C compiler environment, it does not suffice for a freestanding C++ compiler environment because it lacks the C++ header files.
  • C++ briefly mentions that one needs to port an STL implementation in order to use STL functions in native applications - in other words, it discusses the need for a hosted STL implementation once the kernel is done - but it does not contain any information on the freestanding part of the C++ runtime (i.e., the freestanding headers).
  • OS Specific Toolchain also discusses compilation of a hosted version of libstdc++-v3, which requires porting something like glibc or newlib first. Again this is not of much use if one is still in the first stages of kernel development.
So I came to the conclusion that the wiki does not contain a tutorial how to build a full freestanding C++ compiler environment, and I decided to write one on my own. This seemed to be rather simple, because the only thing that's missing in the wiki is how to install the freestanding C++ headers along with a newly built cross compiler. I tried to install these headers with my cross compiler toolchain - and I failed. Maybe someone has already encountered the same problem and can help me figure out how to do it. So here's what I've done:

In the libstdc++-v3 docs I found that the configure switch "--disable-hosted-libstdcxx" should disable installation of a hosted libstdc++, and enable installation of the freestanding headers only. That's perfectly fine, as this is exactly what I want to do. So I used the following configure command:

Code: Select all

../gcc-x.x.x/configure --target=$TARGET --prefix=$PREFIX --disable-nls --enable-languages=c,c++ --without-headers --disable-hosted-libstdcxx
(with appropriate target (i686-pc-elf), prefix and gcc version (4.5.3), of course) and it worked fine. However, it turned out that even though this switch disables installing a hosted libstdc++, it still insists on building a hosted libstdc++ - which of course fails without porting glibc or newlib first. So the following failed:

Code: Select all

make all-target-libstdc++-v3 install-target-libstdc++-v3
The error occurs when make invokes configure in the libstdc++-v3 subdirectory:

Code: Select all

checking for shl_load... configure: error: Link tests are not allowed after GCC_NO_EXECUTABLES.
make[1]: *** [configure-target-libstdc++-v3] Error 1
I found this interesting comment in libstdc++-v3/acinclude.m4:

Code: Select all

dnl
dnl Check if the user only wants a freestanding library implementation.
dnl
dnl --disable-hosted-libstdcxx will turn off most of the library build,
dnl installing only the headers required by [17.4.1.3] and the language
dnl support library.  More than that will be built (to keep the Makefiles
dnl conveniently clean), but not installed.
dnl
So does that mean that GCC will try to build the full hosted libstdc++ anyway, just to keeps the Makefiles simpler? By the way, the situation is still the same with the most recent GCC version. Any ideas?

Re: GCC cross compiler tutorial: full freestanding C++ toolc

Posted: Wed Aug 03, 2011 11:34 am
by Love4Boobies
XenOS wrote:In order to use C effectively and in a compiler independent fashion for OS development / writing a kernel, one does not only need a cross compiler for the desired target architecture, but a complete freestanding environment
Actually, one does not need a GCC cross-compiler at all, unless what the plan to do is to cross-compile (i.e., use a different target, be that a different object file format or CPU architecture), as the -ffreestanding switch is there for all GCC distributions. Not using a cross-compiler will save you from the building problems you are experiencing.

I expect to get contradicted on religious grounds again---sorry about that, I just haven't seen any meaningful arguments against this. I must mention that I give this advice on my behalf, not on anyone else's.
XenOS wrote:such as stdint.h
Just a bit of pedantism (again): It's actually incorrect to refer to it as stdint.h (as opposed to <stdint.h>) unless you specifically refer to the file provided by a specific library implementation (i.e., not the header). Indeed, C compilers needn't even implement headers as files. The same observation applies to C++ headers as well.

Re: GCC cross compiler tutorial: full freestanding C++ toolc

Posted: Wed Aug 03, 2011 11:50 am
by xenos
Love4Boobies wrote:Actually, one does not need a GCC cross-compiler at all, unless what the plan to do is to cross-compile (i.e., use a different target, be that a different object file format or CPU architecture), as the -ffreestanding switch is there for all GCC distributions. Not using a cross-compiler will save you from the building problems you are experiencing.
I agree with you. However, my personal experience showed me that using a cross compiler can avoid quite a lot of trouble, and it seems that this applies to quite a number of users of this forum. Besides that, building a cross compiler should not be too difficult for someone who has enough programming experience for OS development, and it's a good way to practice for someone who needs to practice.
Just a bit of pedantism (again): It's actually incorrect to refer to it as stdint.h (as opposed to <stdint.h>) unless you specifically refer to the file provided by a specific library implementation (i.e., not the header). Indeed, C compilers needn't even implement headers as files. The same observation applies to C++ headers as well.
Again, you're right.

Re: GCC cross compiler tutorial: full freestanding C++ toolc

Posted: Thu Aug 04, 2011 1:59 am
by Solar
You might be surprised, but I do agree too - to a certain extend. You don't need a cross-compiler to build your ELF files, you could just use -ffreestanding.

On Linux.

It's not about "religion", it's about any of the following points:
  • Avoiding PE / WinMain32 / alloca / leading underscore confusion on Cygwin.
  • Enabling Cygwin / Mac / Linux users to run with identical build instructions (i.e., the ones in the Wiki).
  • Allowing reproducability of build environment (I can build a gcc-3.4.2 or a gcc-4.2.2 in minutes on any host, but reproducing an gcc-ubuntu-4:4.0.3-1 on Cygwin is a bit difficult).
  • Avoiding accidential dragging in of user-space dependencies (i.e., make #include <stdio.h> fail at compile time).
  • Avoiding having your OS toolchain change (and possibly break) because of a system update.
  • Avoiding breaking your system compiler because of some OS-related tinkering with your toolchain (like, adding YourOS-headers to its include paths).
Again, it is not necessary, but it does avoid problems.

I do remember the time when there was no recommendation for a cross-compiler. Half the forum postings were about getting the compiler, the assembler and the linker to cooperate on object file formats, leading underscores and stuff like that. Every compiler-related question had a first reply of "what's your environment, Cygwin or Linux?". That more or less completely went away once we started pointing to the cross-compiler as solution. The only problem we still have today is people who are fuzzy about stuff like the PATH variable or thinking that binutils-2.9 must be the latest package because it's at the bottom of the alphabetical listing at ftp.gnu.org - i.e., people who cannot read a tutorial properly. It's a good thing to give them a slap on the head right away.

But we digress...

@XenOS:

Good thinking; I'd be very happy if we could provide a full freestanding C++ environment too.

Using C++ in a freestanding environment, however, is not exactly commonplace, so that's probably why the maintainers of the standard lib don't cater for it. They also don't care much about people who don't have either newlib or glibc available... so unless you care for some serious Makefile tinkering, I'm afraid we're out of luck there.

Re: GCC cross compiler tutorial: full freestanding C++ toolc

Posted: Wed Aug 10, 2011 7:57 pm
by TylerH
I build with C enabled. With that, I build newlib. Then, with newlib, I build with C++ enabled and lidstdc++v3 works.

I know this doesn't answer your actual question. Although, it does give you a relatively easy way to solve your problem.

Re: GCC cross compiler tutorial: full freestanding C++ toolc

Posted: Thu Aug 11, 2011 2:33 pm
by xenos
Relatively easy, indeed - provided you have everything that is required to build newlib...

Re: GCC cross compiler tutorial: full freestanding C++ toolc

Posted: Thu Aug 11, 2011 2:48 pm
by TylerH
XenOS wrote:Relatively easy, indeed - provided you have everything that is required to build newlib...
Which is?

Re: GCC cross compiler tutorial: full freestanding C++ toolc

Posted: Sun Aug 21, 2011 9:24 am
by xenos
According to this document, one needs to implement a few syscalls in order to compile newlib... I have not implemented most of them in my kernel yet.

I sent a mail to the libstdc++ mailing list, so let's see whether there will be any replies.

Re: GCC cross compiler tutorial: full freestanding C++ toolc

Posted: Sun Aug 21, 2011 10:06 am
by Owen
Build newlib with the "libnosys" libgloss. This is an implementation of the newlib system calls that is entirely stubbed out.

libnosys is the default for bare metal targets (e.g. x86_64-pc-elf)

Re: GCC cross compiler tutorial: full freestanding C++ toolc

Posted: Tue Aug 23, 2011 1:53 am
by xenos
Thanks a lot, that did the trick! (Even though it took me nearly 3 hours to compile, since newlib insisted running the build process for each supported CPU when I compiled it for the m68k-elf target...) At least it installed some of the freestanding headers... Maybe this conforms to some older standard.

Code: Select all

./cstdarg
./cstddef
./cstdlib
./cxxabi-forced.h
./cxxabi.h
./exception
./exception_defines.h
./exception_ptr.h
./i686-elf
./i686-elf/bits
./i686-elf/bits/c++config.h
./i686-elf/bits/os_defines.h
./initializer_list
./limits
./nested_exception.h
./new
./typeinfo
I'll try to figure out how I can get the remaining C++0x headers as well... Maybe I just install a hosted libstdc++.

Re: GCC cross compiler tutorial: full freestanding C++ toolc

Posted: Tue Aug 23, 2011 3:25 pm
by xenos
Well, in the end I just installed the full hosted libstdc++, based on the libnosys newlib, and it works fine. I'll put than on the wiki as soon as I have some time.