Executables

Making a binary executable file from FreeBASIC source files.

Preamble:

   A binary file is simply one in a binary (i.e. non-text) format:
      - The binary format means that the file's contents should not be 
      transformed for platform-specific reasons (e.g. replacing newlines 
      from \n to \r\n).
      - Binary files are not necessarily executable, for example a library 
      compiled to '*.dll' or '*.a' form is a binary but not an executable.
      - Executable files are not necessarily binary, for example a script 
      in text form can be made executable on Operating Systems.

   An executable file is one which can be executed (it can be run on the 
   command-line by writing the name of the file itself as the command).
   On Windows, the file's extension must be one of a fixed set of 
   executable file extensions, including '*.exe'.
   On Unix systems, the file's "executable" flag must also be set.

   FreeBASIC consists of fbc (the command line compiler/linker), the 
   runtime libraries, and FreeBASIC header files for third-party libraries.
   In order to produce executables, fbc uses the GNU binutils (assembler, 
   linker). When compiling for architectures other than 32bit x86, fbc 
   depends on gcc to generate assembly.

   FreeBASIC provides the FreeBASIC compiler/linker program (fbc or 
   fbc.exe), as well as the tools and libraries it uses:
      - fbc is a command line program that takes FreeBASIC source/include 
      files ('*.bas'/'*.bi') and object/library files ('*.o'/'*.a'), then 
      compiles them into executables.
      - fbc is typically invoked by Integrated Development Environments 
      (IDEs) or text editors, from a terminal or command prompt, or through 
      build-systems such as makefiles.
      - fbc itself is not a graphical code editor or IDE!

   By default, FreeBASIC programs are linked against various system and/or 
   support libraries, depending on the platform.
   Those include the DJGPP libraries used by FreeBASIC for DOS and the 
   MinGW/GCC libraries used by FreeBASIC for Windows.

Compiling an executable, in general
   fbc is a compiler that takes fbc source code and transforms it in to a 
   file that can be loaded and executed (run) by the operating system.
   fbc doesn't do this all on it's own. It uses some intermediate files and 
   other tools to complete this transformation.

   The "main" entry point of an executable
      An executable needs a starting point.
      This starting point which we will call the "main" function or "main" 
      entry point needs to be recorded in the executable so that when the 
      executable file is loaded by the operating system, the operating 
      system knows where to begin execution of the program.

      By default, the "main" function or starting point will be the first 
      line of the first basic source file on the command line:
         $ fbc program.bas module1.bas module2.bas
            "program" becomes the main module because it is first, and fbc 
            will generate an implicit "main" function that will be executed 
            first when the executable is loaded.

      This default can be overridden with the '-m module' option to specify 
      a main module that is not the first source file given on the command 
      line:
         $ fbc -m program module1.bas module2.bas program.bas
            The "-m program" option tells fbc to use "program.bas" as the 
            main module, even though "program.bas" is not listed first.

      If no other option is given that will affect the compile process, 
      this "main" function is generated implicitly by fbc.
      There can be only one "main" function for an executable. It's not 
      possible to have more than one "main" function.

Compile process for an executable
   When fbc compiles basic source code, it translates the source in to 
   another format that can be used by other tools that eventually create an 
   executable.
   By default, fbc will use these other tools automatically:

   '     .-------------------------------------.
   '     |              COMPILER               |
   '     '------.----------------------.-------'
   '            | GAS backend          | GCC backend
   '            |                      |
   '     .------V-----.    gcc     .---V----.
   '     |  ASM CODE  |<-----------| C CODE |
   '     | .s or .asm |  compiler  |   .c   |
   '     '------.-----'            '--------'
   '            | (G)AS assembler
   '            |
   '     .------V------.
   '     | OBJECT CODE |
   '     | .o or .obj  |-------------.
   '     '------.------'             |
   '            | (G)AR archiver     |
   '            |                    |
   '    .-------V--------.           |
   '    | STATIC LIBRARY |           |
   '    |   .a or .lib   |---------->|
   '    '----------------'           | (G)LD linker
   '                                 |
   '                                 |----------------------------.
   '                                 |                            |
   '                      .----------V-----------.    .-----------V-----------.
   '                      |        BINARY        |    |    SHARED LIBRARY     |
   '                      | no extension or .exe |    | .so or .dll or .dylib |
   '                      '----------------------'    '-----------------------'
   '
   '
   '      Extensions are Unix convention vs Windows (ld does .lib too nowadays).
   '      In the case of shared libs, the name for Mac deviates (.dylib).
   		

   To see all the steps that fbc uses, specify '-v' on the command line to 
   see the steps.
   For example, on win32:

   $ fbc a.bas -v
   FreeBASIC Compiler - Version 1.08.0 (2021-01-24), built For win32 (32Bit)
   Copyright (C) 2004-2021 The FreeBASIC development team.
   standalone
   target:       win32, 486, 32Bit
   backend:      gas
   compiling:    a.bas -o a.asm (main module)
   assembling:   D:\fb.git\Bin\win32\as.exe --32 --strip-Local-absolute "a.asm" -o "a.o"
   linking:      D:\fb.git\Bin\win32\ld.exe -m i386pe -o "a.exe" -subsystem console
   "D:\fb.git\lib\win32\fbextra.x" --stack 1048576,1048576 -s -L "D:\fb.git\lib\win32"
   -L "." "D:\fb.git\lib\win32\crt2.o" "D:\fb.git\lib\win32\crtbegin.o" "D:\fb.git\lib\win32\fbrt0.o"
   "a.o" "-(" -lfb -lgcc -lmsvcrt -lkernel32 -luser32 -lmingw32 -lmingwex -lmoldname -lgcc_eh "-)"
   "D:\fb.git\lib\win32\crtend.o"
   		

   Tools:
      - [ fbc ] compiler translate *.bas in to *.asm or *.c files
      - [ gcc ] compiler translate *.c files in to *.asm files
      - [ as ] assembler translate *.asm files in to *.o object files
      - [ ld ] linker join *.o files (and other files) in to executable 
      files
      - emscripten backend has other tools
      - llvm backend has other tools

   - GNU assembler 32-bit backend (-gen gas):
         *.bas => [ fbc ] => *.asm compile (first stage) to assembly (-r or 
         -rr, -R or -RR)
         *.asm => [ as ] => *.o assemble to object file (-c, -C)
         *.o => [ ld ] => *[.exe] link to executable

   - GNU assembler 64-bit backend (-gen gas64):
         *.bas => [ fbc ] => *.asm compile (first stage) to assembly (-r or 
         -rr, -R or -RR)
         *.asm => [ as ] => *.o assemble to object file (-c, -C)
         *.o => [ ld ] => *[.exe] link to executable

   - GCC compiler backend (-gen gcc):
         *.bas => [ fbc ] => *.c compile (first stage) to C (-r, -R)
         *.c => [ gcc ] => *.asm compile (second stage) to assembly (-rr, 
         -RR)
         *.asm => [ as ] => *.o assemble to object file (-c, -C)
         *.o => [ ld ] => *[.exe] link to executable

   Options controlling compile / assemble / link stages
      There are a few options that can control what fbc does with the 
      intermediate files and at what point the process may be stopped 
      early.

      -r, -rr, -c : stop the compile / assemble process sometime before the 
      link stage
         Compiler Option -r : compile up to first stage, keep file 
         (*.asm/*.c), and stop
         Compiler Option -rr : compile up to second stage, keep file 
         (*.asm), and stop
         Compiler Option -c : compile up to assembly stage, keep file 
         (*.o), and stop

      -R, -RR, -C : keep intermediate files at compile / assemble stages 
      then continue to next stage
         Compiler Option -R : don't delete compile (first stage) 
         intermediate file (*.asm/*.c)
         Compiler Option -RR : don't delete compile (second stage) 
         intermediate file (*.asm)
         Compiler Option -C : don't delete assemble stage intermediate file 
         (*.o)

      -r : option overrides -rr, -RR, -c, -C
      -rr : overrides overrides -c, -C
      -r and -rr : behave the same if there is only one compile stage
      -R and -RR : behave the same if there is only one compile stage

      -r, -rr, -c : override the default behaviour of creating an implicit 
      "main" entry point, and no "main" function is created by default.
      To have a "main" entry point when using the -r, -rr, -c, options, 
      then '-m module' option needs to be used to indicate which module 
      should have an "main" function.

   Note:
      Before fbc version 1.09.0, -gen gas64 generated a .a64 file extension 
      for assembler (instead of .asm).

Execution order of the different modules
   An executable program needs a "main" point of entry (in the main module 
   user code).
   fbc may or may not create an implicit main function, depending on 
   options or method of building an executable.
   The module constructors of modules run before main, the module 
   destructors of modules run after main.

   The module-level codes of other modules (than the main module) are put 
   in implicit module constructors which are consequently executed before 
   the module-level code of the main module.
   But it would be good practice that module-level code only be in the main 
   module.
   More generally, all module constructors and module destructors should be 
   noted with a big WARNING on their use. Because the corresponding code is 
   run outside of user code, it's quite likely that fbc's error checking 
   and some runtime facilities won't work as expected.

   A high level description of the start-up framework:
      - At compile time make arrays of addresses for all the module 
      constructors and destructors.
      - At link time, store the arrays in the executable.
      - At run time, the start-up framework will:
            - call all the module constructors in the array,
            - call the main module user code,
            - on exit (or error), call all the module destructors (usually, 
            depends on how the program failed though).

See also
   * fbc command-line
   * Static Libraries
   * Shared Libraries (DLLs)
   * Profiling
   * Embed and Access binary Data in Executable

