HOWTO

Development tools

Porting gcc 3.3.6 to MiNT, C++ language support, v 0.2

This text tries to explain the steps to port gcc 3.3.6 from original sources to a working MiNT port. Current gcc version for MiNT is 2.95.3, albeit working, a more recent version can be needed to compile recent software.

Step 1: Get the necessary archives

You need original gcc 3.3.6 archive. The archive decompress to a 185 MB of source directory. You will also need autoconf and automake to rebuild needed Makefile.in and configure scripts.

$ tar xvjf gcc-3.3.6.tar.bz2
$ mkdir gcc-3.3.6-mint

You also need a standard C library for the target, like mintlib for example (both standard and debugging versions), because gcc will need to build some stuff for the target (like libiberty and libgcc libraries). You can retrieve current mintlib development files from Sparemint website. They are in RPM format but you can convert them to tar.gz by using alien program.You need to unpack mintlib at the final place ($TARGETPATH/m68k-atari-mint). You should have headers in include subdir, and lib in another subdir.

You also need binutils to create MiNT binaries/libraries. We will start from our previous patch for C language support, so apply it before going further.

Step 2: First try

Note: TARGETPATH is a directory where gcc-mint will be installed. We modify the PATH variable so the build process will find the binutils needed to build MiNT binaries. We will configure gcc with C language support atm. Change the '/path/to/mintlib' to the absolute path to where you unpacked mintlib development files. This time we add c++ to the list of languages to be built.

$ mkdir gcc-3.3.6-mint
$ cd gcc-3.3.6-mint
$ export PATH=${TARGETPATH}/bin:PATH
$ ../gcc-3.3.6/configure --prefix=${TARGETPATH} --target=m68k-atari-mint
  --enable-languages="c,c++"
  --with-sysroot=${TARGETPATH}/m68k-atari-mint
$ make

This time, there are many errors, which are all related to libstdc++. This is the base C++ library, and MiNT support needs to be added to it.

We have these errors, related to missing ctype (character type) definitions:

In file included from libstdc++-v3/include/bits/locale_facets.h:166,
                 from libstdc++-v3/include/bits/basic_ios.h:44,
                 from libstdc++-v3/include/ios:51,
                 from libstdc++-v3/include/ostream:45,
                 from libstdc++-v3/include/bitset:58,
                 from ../../../../../gcc-3.3.6-new/libstdc++-v3/src/bitset.cc:43:
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:46: error: `_U' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:47: error: `_L' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:48: error: `_U' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:48: error: `_L' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:49: error: `_N' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:50: error: `_X' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:50: error: `_N' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:51: error: `_S' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:52: error: `_P' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:52: error: `_U' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:52: error: `_L' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:52: error: `_N' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:52: error: `_B' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:53: error: `_P' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:53: error: `_U' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:53: error: `_L' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:53: error: `_N' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:54: error: `_C' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:55: error: `_P' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:56: error: `_U' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:56: error: `_L' was not declared in this scope
libstdc++-v3/include/m68k-atari-mint/bits/ctype_base.h:56: error: `_N' was not declared in this scope

And we have these errors, related to missing math functions:

In file included from libstdc++-v3/include/bits/locale_facets.tcc:41,
                 from libstdc++-v3/include/locale:47,
                 from libstdc++-v3/include/bits/ostream.tcc:37,
                 from libstdc++-v3/include/ostream:535,
                 from libstdc++-v3/include/bitset:58,
                 from ../../../../../gcc-3.3.6-new/libstdc++-v3/src/bitset.cc:43:
libstdc++-v3/include/cmath:107: error: `acosf' not declared
libstdc++-v3/include/cmath:110: error: `asinf' not declared
libstdc++-v3/include/cmath:113: error: `atanf' not declared
libstdc++-v3/include/cmath:116: error: `atan2f' not declared
libstdc++-v3/include/cmath:119: error: `ceilf' not declared
libstdc++-v3/include/cmath:122: error: `coshf' not declared
libstdc++-v3/include/cmath:125: error: `expf' not declared
libstdc++-v3/include/cmath:128: error: `floorf' not declared
libstdc++-v3/include/cmath:131: error: `fmodf' not declared
libstdc++-v3/include/cmath:134: error: `frexpf' not declared
libstdc++-v3/include/cmath:137: error: `ldexpf' not declared
libstdc++-v3/include/cmath:140: error: `logf' not declared
libstdc++-v3/include/cmath:143: error: `log10f' not declared
libstdc++-v3/include/cmath:146: error: `modff' not declared
libstdc++-v3/include/cmath:149: error: `powf' not declared
libstdc++-v3/include/cmath:152: error: `sinhf' not declared
libstdc++-v3/include/cmath:155: error: `tanf' not declared
libstdc++-v3/include/cmath:158: error: `tanhf' not declared
libstdc++-v3/include/cmath: In function `float std::acos(float)':
libstdc++-v3/include/cmath:184: error: `acosf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::asin(float)':
libstdc++-v3/include/cmath:204: error: `asinf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::atan(float)':
libstdc++-v3/include/cmath:222: error: `atanf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::atan2(float, float)':
libstdc++-v3/include/cmath:240: error: `atan2f' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::ceil(float)':
libstdc++-v3/include/cmath:260: error: `ceilf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::cosh(float)':
libstdc++-v3/include/cmath:288: error: `coshf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::exp(float)':
libstdc++-v3/include/cmath:306: error: `expf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::floor(float)':
libstdc++-v3/include/cmath:334: error: `floorf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::fmod(float, float)':
libstdc++-v3/include/cmath:352: error: `fmodf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::frexp(float, int*)':
libstdc++-v3/include/cmath:372: error: `frexpf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::ldexp(float, int)':
libstdc++-v3/include/cmath:391: error: `ldexpf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::log(float)':
libstdc++-v3/include/cmath:411: error: `logf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::log10(float)':
libstdc++-v3/include/cmath:429: error: `log10f' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::modf(float, float*)':
libstdc++-v3/include/cmath:447: error: `modff' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::pow(float, float)':
libstdc++-v3/include/cmath:486: error: `powf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::sinh(float)':
libstdc++-v3/include/cmath:528: error: `sinhf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::tan(float)':
libstdc++-v3/include/cmath:556: error: `tanf' undeclared in namespace `__gnu_cxx::__c99_binding'
libstdc++-v3/include/cmath: In function `float std::tanh(float)':
libstdc++-v3/include/cmath:574: error: `tanhf' undeclared in namespace `__gnu_cxx::__c99_binding'
make[6]: *** [bitset.lo] Erreur 1
make[6]: Leaving directory `gcc-3.3.6-mint/m68k-atari-mint/m68020/libstdc++-v3/src'
make[5]: *** [all-recursive] Erreur 1
make[5]: Leaving directory `gcc-3.3.6-mint/m68k-atari-mint/m68020/libstdc++-v3'
make[4]: *** [all-recursive-am] Erreur 2
make[4]: Leaving directory `gcc-3.3.6-mint/m68k-atari-mint/m68020/libstdc++-v3'
make[3]: *** [multi-do] Erreur 1
make[3]: Leaving directory `gcc-3.3.6-mint/m68k-atari-mint/libstdc++-v3'
make[2]: *** [all-multi] Erreur 2
make[2]: Leaving directory `gcc-3.3.6-mint/m68k-atari-mint/libstdc++-v3'
make[1]: *** [all-recursive-am] Erreur 2
make[1]: Leaving directory `gcc-3.3.6-mint/m68k-atari-mint/libstdc++-v3'
make: *** [all-target-libstdc++-v3] Erreur 2

Step 3: Patch libstdc++ to accept m68k-atari-mint target

The biggest part of the work will be done in libstdc++-v3 sub directory. There is a docs sub dir if you want to know more about this library. You should read libstdc++-v3/docs/html/17_intro/porting.html as a starting point.

Step 3.1: Add MiNT target to configure.target and configure.in

the config/os/generic subdir used as default does not suit us, so we need to create a new config/os/mint, and make configure use it. This is done in configure.target, case "${target_os}" stuff:

  mint*)
    os_include_dir="os/mint"
    ;;

As we are building a cross-compiler, configure.in will have to be modified. Search for case "${target}", it will default to newlib usage for libc, and we need/want mintlib. This is the first step, it will be filled later.

    *-mint*)
      os_include_dir="os/mint"
      ;;

Beware: there is a second case "${target}" switch around line 290!

    *-mint*)
      ;;

So we can create mint subdir in config/os. Don't forget to also run autoconf in libstdc++-v3 subdir when you modify configure.in (Note: autoconf 2.13 required for it).

Step 3.2: Add MiNT character types

$ make
make[6]: *** No rule to make target « libstdc++-v3/config/os/mint/ctype_base.h », needed for « stamp-target ». Stop.

We need to have a look at mintlib's include/ctype.h to know what to define.

Step 3.2.1: config/os/mint/ctype_base.h

This one is easy, we just take types from mintlib/include/ctype.h, and inspired from config/os/generic/ctype_base.h, used as a template.

// Mint C types, taken from mintlib-0.56/include/ctype.h
  
  struct ctype_base
  {
    // Non-standard typedefs.
    typedef const int* 		__to_type;

    // NB: Offsets into ctype::_M_table force a particular size
    // on the mask type. Because of this, we don't use an enum.
    typedef unsigned int 	mask;   
    static const mask upper     = _CTu;
    static const mask lower 	= _CTl;
    static const mask alpha 	= _CTu | _CTl;
    static const mask digit 	= _CTd;
    static const mask xdigit 	= _CTx;
    static const mask space 	= _CTs;
    static const mask print 	= _CTP;
    static const mask graph 	= _CTg;
    static const mask cntrl 	= _CTc;
    static const mask punct 	= _CTp;
    static const mask alnum 	= _CTd | _CTu | _CTl ;
  };
Step 3.2.2: config/os/mint/ctype_inline.h

Will try to explain this file later.

  bool
  ctype::
  is(mask __m, char __c) const
  { return _ctype[(unsigned char)((__c) + 1)] & __m; }
   
  const char*
  ctype::
  is(const char* __low, const char* __high, mask* __vec) const
  {
    while (__low < __high)
      *__vec++ = _ctype[(*__low++) + 1] ;
    return __high;
  }

  const char*
  ctype::
  scan_is(mask __m, const char* __low, const char* __high) const
  {
    while (__low < __high && !this->is(__m, *__low))
      ++__low;
    return __low;
  }

  const char*
  ctype::
  scan_not(mask __m, const char* __low, const char* __high) const
  {
    while (__low < __high && this->is(__m, *__low) != 0)
      ++__low;
    return __low;
  }
Step 3.2.3: config/os/mint/ctype_noninline.h

Will try to explain this file later.

// Information as gleaned from /usr/include/ctype.h

  const ctype_base::mask*
  ctype::classic_table() throw()
  { return 0; }

  ctype::ctype(__c_locale, const mask* __table, bool __del, 
		     size_t __refs) 
  : __ctype_abstract_base(__refs), _M_del(__table != 0 && __del), 
  _M_toupper(NULL), _M_tolower(NULL), 
  _M_table(__table ? __table : classic_table()) 
  { }

  ctype::ctype(const mask* __table, bool __del, size_t __refs) 
  : __ctype_abstract_base(__refs), _M_del(__table != 0 && __del), 
  _M_toupper(NULL), _M_tolower(NULL), 
  _M_table(__table ? __table : classic_table())
  { }

  char
  ctype::do_toupper(char __c) const
  { return ::toupper((int) __c); }

  const char*
  ctype::do_toupper(char* __low, const char* __high) const
  {
    while (__low < __high)
      {
	*__low = ::toupper((int) *__low);
	++__low;
      }
    return __high;
  }

  char
  ctype::do_tolower(char __c) const
  { return ::tolower((int) __c); }

  const char* 
  ctype::do_tolower(char* __low, const char* __high) const
  {
    while (__low < __high)
      {
	*__low = ::tolower((int) *__low);
	++__low;
      }
    return __high;
  }
Step 3.2.4: config/os/mint/os_defines.h

Some OS-dependent definitions.

// These taken from mintlib-0.56/include/unistd.h

#define __off_t off_t
#define __off64_t off64_t
#define __ssize_t ssize_t
Step 3.2.5: Rebuild stuff.

As generic files where copied to build directory, we need to delete the current libstdc++-v3 build dir. And just tell make to only rebuild it.

$ rm -rf `find m68k-atari-mint -name libstdc++-v3`
$ make all-target-libstdc++-v3

OK, character types are defined, build stops at math functions.

Step 3.3: Add missing math functions

This is done in configure.in (the section we started to create, remember). I just shamelessly copied the section of a different OS. We add this in the first case "$target" switch:

    *-mint*)
      AC_CHECK_HEADERS([sys/types.h locale.h])
      GLIBCPP_CHECK_LINKER_FEATURES
      GLIBCPP_CHECK_COMPLEX_MATH_SUPPORT
      GLIBCPP_CHECK_WCHAR_T_SUPPORT
      os_include_dir="os/mint"
      ;;

Step 4: Make

Note: you can build the 'bootstrap' target (if you are not cross-compiling), which is a 3 pass compilation: (1)build gcc with current compiler (2) build gcc with gcc compiled at stage 1 (3) build gcc with gcc compiled at stage 2, and compare the two binaries. If they are not the same, gcc produced an incorrect program.

But as we are building a cross-compiler, we can't do that, so we just run make.

$ make

You will notice many warning messages, specially when building the floating point stuff.

Step 5: Install

$ make install

Step 6: Time to test and debug!

Apparently the build is ok, but we must be sure the code generated/linked by all these tools is right. That's the hard part. Most of these tools have testsuite, but maybe it requires writing MiNT tests as well.

Here is the final patch:
gcc-cpp-3.3.6-mint-1.diff.gz

News
Personnal productions
Patches
Ports
Projects
HOW-TOs
Development tools
Create a patch for binutils (binutils 2.16.1)
Create a patch for gcc (gcc 3.3.6, C language only)
Create a patch for gcc (gcc 3.3.6, C++ language)
Misc stuff

HTML 4.0 valide ! La montée de Pikes Peak Non aux brevets logiciels Nectarine demoscene radio
Write me to pmandin(at)caramail(point)com
(Address modified for spam protection)