GCC toolchain choice

FB is based on GCC toolchains and corresponding libraries. However, there 
is not a single GCC toolchain per platform, but often multiple slightly 
different ones. FB can generally work with all of them, but still there can 
be differences depending on the toolchain chosen to build and use FB. Here 
we document some of the issues to consider when building FB and/or making 
FB releases.

Windows (MinGW)

MinGW toolchains:

   * MinGW.org - also provides MSYS, besides a MinGW GCC toolchain. No 
     Win64 support (yet).
   * MinGW-w64 - 32bit and 64bit. Different runtime libraries than 
     MinGW.org.
   * TDM-GCC - 32bit based on MinGW.org, 64bit based on MinGW-w64, with 
     modifications.
   * MinGW cross-compilers on various GNU/Linux distributions - for 
     example MinGW-w64 on Debian/Ubuntu and Fedora (i686-w64-mingw32, 
     x86_64-w64-mingw32)

Notes:

   * GCC exception handling mechanism: SJLJ setjump/longjump (slow but 
     safe), DWARF-2 (fast but does not always work). The MinGW.org 
     toolchain uses DWARF2, while for MinGW-w64, both types are available.

      FB does not support exceptions anyways, so in theory the exception 
      handling mechanism used by the underlying GCC toolchain does not 
      matter.

      In practice though, DWARF-2 GCC generates static data for stack 
      unwinding which is put into .eh_frame sections. The problem is that 
      .eh_frame data is generated also for C code (not just C++ code) like 
      all the FB/GCC/MinGW runtime libraries, and it increases .exe size 
      noticably. This can be avoided in multiple ways:

         * Use gcc flags to disable the generation of the .eh_frame data. 
           FB is using this in its makefile and for -gen gcc, however 
           obviously it does not affect the prebuilt MinGW/GCC libraries 
           (unless the entire toolchain is rebuilt).
   -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables

         * Discard/strip the .eh_frame section when linking (by using a 
           custom ldscript)
         * Use an SJLJ toolchain (i.e. MinGW-w64 built for SJLJ, instead 
           of MinGW.org)

      Furthermore, the exception handling method may be an important detail 
      afterall (even if you do not care about .exe size) if you want to use 
      C++ libraries from FB, in case the C++ library uses exceptions.

      * GCC threading model: Win32 threads (native), POSIX threads (based 
        on winpthreads library). The MinGW.org toolchain uses Win32 
        threads, while for MinGW-w64, both types are available.

      GCC needs POSIX threads to implement certain new C++ features, which 
      is not possible with native Win32 threading functions. Thus, 
      MinGW-w64 uses the winpthreads library which provides POSIX threading 
      functions for Windows. However, winpthreads is not part of the main 
      MinGW-w64 runtime, and it has a different license, which may have to 
      be considered.

      Since FB does not care about these C++ features, we can just use 
      MinGW toolchains with Win32 threads, and avoid winpthreads.

   * Globbing (command line wildcard expansion etc.) behaviour is 
     different between MinGW.org and MinGW-w64 because they have different 
     runtime libraries/startup code impementations.

         * Globbing is enabled by default in the MinGW.org runtime, but 
           the MinGW-w64 runtime turns globbing off by default and has a 
           --enable-wildcard configure option. Thus, whether globbing is on 
           or off by default, depends on how MinGW-w64 was built.

            * The way to disable globbing is different:
         * MinGW.org:
   Extern _CRT_glob Alias "_CRT_glob" As Long
   Dim Shared _CRT_glob As Long = 0

         * MinGW-w64:
   Extern _dowildcard Alias "_dowildcard" As Long
   Dim Shared _dowildcard As Long = 0

      * MinGW-w64 includes DirectX headers needed to compile FB's graphics 
        library. MinGW.org does not contain them; they have to be added 
        manually.

      * MinGW.org provides a common installer for their MinGW toolchain 
        and the MSYS shell environment. This makes installing easier than 
        with other toolchains, if MSYS is needed too.

DOS (DJGPP)

FB needs the DJGPP 2.04 beta runtime (does DJGPP 2.03 not work?). Either 
way, this version of DJGPP is extremely old. On the other hand, there have 
not been any more recent DJGPP releases, and updates can only be found in 
DJGPP's CVS. The recommendation is to only use DJGPP CVS if really needed 
though.

Linux

GNU/Linux distros usually provide native gcc + glibc toolchains 
out-of-the-box, and FB is intended to work with them out-of-the-box.

Executables (such as fbc itself) produced on one GNU/Linux distro are not 
necessarily portable to other GNU/Linux distros, due to differences in 
system libraries and/or versions, such as glibc version differences, or 
ncurses/libtinfo differences. The most common problem with fbc is 
mismatching glibc versions, i.e. the fbc binary is run on a system with 
older glibc than the one it was built on, and some form of "glibc too old" 
error is encountered. The ncurses library is not always exactly the same 
either, as shown by the "`ospeed' has different size, consider re-linking" 
warnings when running fbc. Also, some distros have separated libncurses and 
libtinfo, some just have libncurses, which can cause errors due to the 
libtinfo shared library not being found.

In theory, it is possible to use static linking to avoid the problems with 
shared libraries:

   * The fbc -static command line option tells the linker to prefer static 
     libraries instead of shared ones. This can (in theory) also be used 
     when building fbc itself. It relies on the Linux distro to provide 
     static versions of the system libraries. Linking statically on 
     GNU/Linux is typically discouraged though, in particular with glibc 
     (some of its components are not designed for static linking), but also 
     in general (shared libraries are preferred to avoid redundancy.

      * FB can (in theory) also be used with a different libc (instead of 
        glibc), one that explicitly supports static linking, for example 
        musl-libc.

      In this context, you will typically use a custom gcc toolchain, which 
      also requires FB to be built specifically for that toolchain. This 
      approach in general works quite well, but it can be a lot of work.

      Besides that, other libc's may not be ABI-compatible with glibc, 
      which can cause problems for FB programs if they are written for 
      glibc. Most noticably, the FB Linux CRT headers are based on glibc. 
      An example of an ABI difference between musl-libc (0.9) and glibc was 
      the jmp_buf structure size (used with the setjmp()/longjmp() 
      functions). As the FB CRT headers defined the glibc jmp_buf, they 
      were incompatible to musl-libc which used a smaller jmp_buf 
      structure.

      Another headache when using a different libc than the Linux distro 
      default is that you also need to build a lot of libraries such as 
      ncurses, X11 and Mesa/OpenGL in order to satisfy FB's dependencies, 
      not to mention any other third-party libraries you want to use in 
      your program. Existing libraries precompiled for glibc can probably 
      not be used (at least not safely) due to the two libc's being 
      ABI-incompatible.

See also
   * Known problems when compiling FB

