GCC cross compiler tutorial: full freestanding C++ toolchain

All about the OSDev Wiki. Discussions about the organization and general structure of articles and how to use the wiki. Request changes here if you don't know how to use the wiki.
Post Reply
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

GCC cross compiler tutorial: full freestanding C++ toolchain

Post 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?
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
Love4Boobies
Member
Member
Posts: 2111
Joined: Fri Mar 07, 2008 5:36 pm
Location: Bucharest, Romania

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

Post 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.
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

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

Post 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.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

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

Post 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.
Every good solution is obvious once you've found it.
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

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

Post 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.
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

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

Post by xenos »

Relatively easy, indeed - provided you have everything that is required to build newlib...
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

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

Post by TylerH »

XenOS wrote:Relatively easy, indeed - provided you have everything that is required to build newlib...
Which is?
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

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

Post 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.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

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

Post 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)
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

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

Post 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++.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

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

Post 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.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
Post Reply