Bebbo’s amiga-gcc unter debian Linux installieren

Bebbo's amiga-gcc install

Bebbo’s amiga-gcc install

amiga-gcc ist eine C/C++ Cross-Compiler Suite, die Amiga-Programmierern die GNU Compiler Collection gcc und den C-Compiler VBCC, aber auch Werkzeuge wie vamos unter Linux, Windows und macOS zur Verfügung stellt. Die Suite kommt mit zwei vollständigen C-Entwicklungsumgebungen inklusive der Standard-Header und integrierten Erweiterungsbibliotheken, wie z.B. MUI und ReAction, für AmigaOS 1.3 bis AmigaOS 3.2 daher und kann als ein neuer Standard bei der Entwicklung von Programmen auf dem Commodore Amiga (68k) betrachtet werden.

Stefan ‚Bebbo‘ Franke, Autor der Cross-Compiler Suite, stellt amiga-gcc auf seiner Website kostenlos zur Verfügung. Um die Suite unter debian Linux zu installieren, genügen einige wenige Schritte – und ein bisschen Geduld. Auf einem durchschnittlichen PC dauert es mit einer schnellen Internet-Verbindung bummelig 40 Minuten, um Alles herunter zu laden, zu übersetzen und einzurichten.

Vorbereitungen

Zunächst muss das System auf den aktuellen Stand gebracht und einige Abhängigkeiten installiert werden:

sudo apt update && sudo apt upgrade
sudo apt install sudo apt install make wget git gcc g++ lhasa libgmp-dev libmpfr-dev
sudo apt install libmpc-dev flex bison gettext texinfo ncurses-dev autoconf rsync 
sudo apt install libreadline-dev

mkdir ~/amiga

Clonen und Compilieren des Repository

git clone https://franke.ms/git/bebbo/amiga-gcc
cd amiga-gcc
make PREFIX=~/amiga NDK=3.2 update
make PREFIX=~/amiga NDK=3.2 all -j8
make PREFIX=~/amiga NDK=3.2 vbcc -j8
make PREFIX=~/amiga NDK=3.2 vlink -j8

Anpassen der Pfade, Setzen von Aliases

Damit amiga-gcc und seine Komponenten einwandfrei aus jedem Pfad heraus arbeiten, müssen die Pfade dem System bekannt gemacht werden. Bei der Gelegenheit kannst du auch gleich ein paar Aliases setzen, die dir Tipparbeit ersparen. Füge am Ende deiner ~.bashrc das Folgende ein:

# Bebbo's amiga-gcc
export VBCC=~/amiga
export AMIGA_GCC=~/amiga
export PATH=$AMIGA_GCC:$AMIGA_GCC/bin:$PATH
alias agcc='m68k-amigaos-gcc'
alias ag++='m68k-amigaos-g++'
alias astrip='m68k-amigaos-strip'

Mache die Änderungen anschließend deiner Shell bekannt:

source ~/.bashrc

Testen der Installation

Gib das folgende, kurze Listing ein und speichere es unter dem Namen hello.c

#include <dos/dos.h>
#include <proto/dos.h>

int main()
{
  Printf("Hello, World!\n");
  return(RETURN_OK);
}

Compiliere es anschließend mit gcc und vbcc, führe die Resultate im Emulator deiner Wahl in einer Amiga Shell aus:

agcc -Wall -lamiga -s -Os hello.c -o hello_gcc -noixemul
hello_gcc

vc -size -lamiga hello.c -o hello_vc
hello_vc

Programme für AmigaOS 1.3 compilieren

Um Programme für das alte Amiga-Betriebssystem mit Kickstart 1.3 zu übersetzen, musst du für gcc und vbcc die entsprechenden Parameter angeben:

gcc:
m68k-amigaos-gcc test.c -o test_gcc -mcrt=nix13

VBCC:
vc +kick13 test.c -o test_vc

Beachte, dass unser Beispiel-Listing so nicht fehlerfrei compiliert werden kann! Unter AmigaOS 1.3 ist zum Einen die Verzeichnisstruktur der Header-Files anders aufgebaut und zum Anderen gab es zu dieser Zeit die interne Printf()-Routine noch nicht. Du musst das Programm also umschreiben:

#include <stdio.h>  
int main(int argc, char *argv[]) 
{ 
  printf("Hello, World!\n"); 
  return(0); 
}

Du findest diesen Artikel hilfreich? Dann freue ich mich über eine kleine finanzielle Anerkennung!

 

Bebbo’s amiga-gcc Cross Compiler Toolchain ist umgezogen

bebbo's amiga-gcc moved

amiga-gcc ist eine C/C++ Cross-Compiler Suite, die Amiga-Programmierern die GNU Compiler Collection gcc und den C-Compiler VBCC, aber auch Werkzeuge wie vamos unter Linux, Windows und macOS zur Verfügung stellt. Die Suite kommt mit zwei vollständigen C-Entwicklungsumgebungen inklusive der Standard-Header und integrierten Erweiterungsbibliotheken, wie z.B. MUI und ReAction, für AmigaOS 1.3 bis AmigaOS 3.2 daher und kann als ein neuer Standard bei der Entwicklung von Programmen auf dem Commodore Amiga (68k) betrachtet werden.

Stefan ‚Bebbo‘ Franke, genialer Programmierer und Schöpfer der amiga-gcc Cross Compiler Toolchain, hat vor einiger Zeit aus Protest seine Repositorien auf GitHub entfernt:

„As a sign of protest against the refusal to restore 2FA accounts, this account is now empty. Some repos are back on https://franke.ms/git/bebbo“

Amiga-Programmierer, die nicht auf den Komfort und die Geschwindigkeit seiner Werkzeuge verzichten wollen, finden amiga-gcc und weitere Werkzeuge nun auf seiner Homepage:

https://franke.ms/git/bebbo

Die Macher der AmigaOS 3.2 Developer Website haben ebenfalls einen Snapshot von Bebbo’s Werken geforkt und stellen ihn öffentlich zur Verfügung:

https://github.com/AmigaPorts/m68k-amigaos-gcc

Zur Installation des amiga-gcc siehe auch https://mbergmann-sh.de/2025/10/04/bebbos-amiga-gcc-unter-debian-linux-installieren/

ENGLISH

amiga-gcc is a C/C++ cross-compiler suite that provides Amiga programmers with the GNU Compiler Collection gcc and the C compiler VBCC, as well as tools such as vamos under Linux, Windows, and macOS. The suite comes with two complete C development environments, including standard headers and integrated extension libraries such as MUI and ReAction, for AmigaOS 1.3 to AmigaOS 3.2, and can be considered a new standard for developing programs on the Commodore Amiga (68k).

Unfortunately Stefan ‘Bebbo’ Franke, brilliant programmer and creator of the amiga-gcc cross compiler toolchain, removed his repositories from GitHub some time ago in protest against GitHub restrictions.

Nevertheless, the tool chain can still be obtained by the follwing links:

https://franke.ms/git/bebbo

https://github.com/AmigaPorts/m68k-amigaos-gcc

Amiga Version String für mit SAS/C, VBCC und amiga-gcc compilierte Programme

Amiga Version String Macro www.mbergmann-sh.de

Auf dem Commodore Amiga besitzen gut geschrieben Programme einen Versions-String, der über die Shell mit dem Befehl ‚version <progname> file full‘ abgefragt werden werden kann.

Gerade dann, wenn man als C-Programmierer zu Testzwecken verschiedene C-Compiler verwendet kann es hilfreich sein, ein Template zu schreiben, um einen solchen Versions-String automatisch zu generieren. Man kann ein solches Template z. B. unter ‚S:myHeader.txt‘ ablegen und bei Bedarf einfach in den Texteditor laden.

Um einen Versions-String per Macro mit dem Programmnamen, der Versionsnummer, dem aktuellen Compilerdatum und Informationen zum verwendeten Compiler zu erstellen, geht man so vor:

#define PROGNAME "meinProgramm"
#define VERSIONR "1.0.0"
#define COPYRIGHT "Copyright © 2025 by Micha B."

/* construct version tag */
#if defined(__VBCC__)
 #define PROGDATE __AMIGADATE__
 #define COMPILER "VBCC"
#endif
#if defined(__SASC)
 #define PROGDATE __AMIGADATE__
 #define COMPILER "SAS/C v6.58"
#endif
#if defined(__GNUC__)
 #define PROGDATE __DATE__
 #define COMPILER "GCC"
#endif

/* AmigaOS Version String */
const char *version = "\0$VER: " PROGNAME " " VERSIONR " (" PROGDATE ") - (" COMPILER ") - " COPYRIGHT "\n";

Warum der Aufwand?

Natürlich könnte man den Versions-String auch einfach so schreiben:

const char *version ="\o$VER: meinProgramm ((01. April 2025)) - (SAS/C) - Copyright by IchSelbst\n";

Man müsste dann halt den String jedesmal verändern wenn die Programmversion wechselt oder ein anderer C-Compiler benutzt wird. Da ist es schon komfortabler, wenn man sich ein entsprechenes Makro angelegt hat.

Ich selbst verwende bei der Programmentwicklung grundsätzlich Templates, da mir das viel Arbeit für Kommentare usw. erspart. Für meine mit dem ReBuild GUI Designer entworfenen Projekte sieht mein Standard-Template so aus:

/*********************************************
 * Project:  ReBuild F.A.Q                   *
 * Purpose:  show some ReAction GUI features *
 * File:     meinprogramm.c                  *
 * Version:  1.0 RELEASE                     *
 * Author:   Michael Bergmann                *
 * Date:     2025/04/04                      *
 *                                           *
 * GUI made with ReBuild v1.3 beta           *
 * Tested Compilers:                         *
 *           SAS/C v6.58                     *
 *           VBCC v0.91 pre                  *
 *           amiga-gcc v6.5                  *
 * HINT: Might be linked against             *
 *       amiga.lib and reaction.lib!         *
 *********************************************
 */
/* --- Put INCLUDE-Files HERE: --- *

 
#define myDebug TRUE  /* Debugging Texts TRUE or FALSE */
#ifdef myDebug
  #include <stdio.h>  /* used for puts(), printf() */
  char *str_greet = "Hello Stranger!\n We're ready to DEBUG now!\n\n";
  char *str_bye = "\n\nAll Done!\nThis Demo quits now.\nHope you liked it?";
#endif

/* construct version tag */
#define PROGNAME "meinProgramm"
#define VERSIONR "1.0.0"
#define COPYRIGHT "Copyright © 2025 by Micha B."

#if defined(__VBCC__)
  #define PROGDATE __AMIGADATE__
  #define COMPILER "VBCC"
#endif
#if defined(__SASC)
  #define PROGDATE __AMIGADATE__
  #define COMPILER "SAS/C v6.58"
#endif
#if defined(__GNUC__)
  #define PROGDATE __DATE__
  #define COMPILER "GCC"
#endif

/* AmigaOS Version String */
const char *version = "\0$VER: " PROGNAME " " VERSIONR " (" PROGDATE ") - (" COMPILER ") - " COPYRIGHT "\n";

/* Function Proto Types */
int main(void);
void window_main( void );
int setup( void );
void cleanup( void );
void runWindow( Object *window_object, int window_id, struct Menu *menu_strip, struct Gadget *win_gadgets[] );

/* --- Additional global stuff goes HERE: --------------------------------------------------------------- */

/* --- Menu IDs ----------------------------------------------------------------------------------------- */
enum menus
{
  /* Menu "Project"  */
  MN_ITEM1
};

/* --- Requesters ---------------------------------------------------------------------------------------- */
/* 'No OS 3.2' box */
struct EasyStruct warnreq =
{
  sizeof(struct EasyStruct),
  0,
  "Error",
  "Needs AmigaOS 3.2.x\n\nNo Chance to run this program on your machine!",
  "Ok"
};

/* 'requester.class problem' box */
struct EasyStruct noreqclassreq =
{
  sizeof(struct EasyStruct),
  0,
  "Critical Error",
  " requester.class could not be opened.\nThis App refuses to start!",
  "Ok"
};

/* --- Function: setup() --------------------------------------------------------------------------------- */
/* --- Open libs, gadgets, classes and other ressources -------------------------------------------------- */
int setup( void )
{
  if( !(IntuitionBase = (struct IntuitionBase*) OpenLibrary("intuition.library",0L)) ) return 0;
  if( !(GadToolsBase = (struct Library*) OpenLibrary("gadtools.library",0L) ) ) return 0;
  if( !(WindowBase = (struct Library*) OpenLibrary("window.class",0L) ) ) return 0;
  if( !(IconBase = (struct Library*) OpenLibrary("icon.library",0L) ) ) return 0;
  
  /* --- Check for a sufficient OS! --- */
  if( !(LayoutBase = (struct Library*) OpenLibrary("gadgets/layout.gadget",47) ) )
  {
    if (myDebug)
       puts(" FAIL: layout.gadget");
    EasyRequest(NULL, &warnreq, NULL);    
    return 0;
  }
  /* Additional Stuff: Place HERE! */
  
} /* END Function setup() */

/* --- Function: cleanup() -------------------------------------------------------------------------------- */
/* --- Close used ressources and clean up for shutdown ---------------------------------------------------- */
void cleanup( void )
{
   /* Copy content of Function cleanup() HERE: */
} /* END Function cleanup() */
 

/* --- Function: runWindow() ------------------------------------------------------------------------------ */
/* --- IDCMP Event Handling is done here ------------------------------------------------------------------ */
void runWindow( Object *window_object, int window_id, struct Menu *menu_strip, struct Gadget *win_gadgets[] )
{
  struct Window	*main_window = NULL;  
  struct MenuItem *menuitem = NULL;
  LONG myItem = 0;                  /* GT menu identifier     */
  ULONG selected;                   /* used for Content query */
  ULONG status = 0;                 /* used for Status query  */
  ULONG req_result = 0;
  if ( window_object )
  {
    if ( main_window = (struct Window *) RA_OpenWindow( window_object ))
    {
      WORD Code;
      ULONG wait = 0, signal = 0, result = 0, done = FALSE;
      GetAttr( WINDOW_SigMask, window_object, &signal );
      if ( menu_strip)  SetMenuStrip( main_window, menu_strip );
      
      if(myDebug)
        printf("%s\n", str_greet);
        
      while ( !done)
      {
        wait = Wait( signal | SIGBREAKF_CTRL_C );

        if ( wait & SIGBREAKF_CTRL_C )
          done = TRUE;
        else
          while (( result = RA_HandleInput( window_object, &Code )) != WMHI_LASTMSG)
          {
            switch ( result & WMHI_CLASSMASK )
            {
              /* --- WINDOW -------------------------------------------- */
              case WMHI_CLOSEWINDOW:
                if(myDebug)
                  printf("%s\n", str_bye);
                done = TRUE;
                break;
                
              /* --- MENUS -------------------------------------------- */
              case WMHI_MENUPICK:
                if(myDebug)
                  puts("\nMenu pick!");
                 
                menuitem = ItemAddress(menu_strip, result & WMHI_MENUMASK);
                if(myDebug)
                  printf(" ItemAdress = %ld\n", menuitem); 
                  
                /* Check if menuitem equals to Zero. If Zero, an enforcer hit will occour when */
                /* attempting to examine, so we do not allow switching on menuitem == 0!       */
                if(!(menuitem == 0))
                {
                  /* --- ...get menu entries by using GadTools' GTMENUITEM_USERDATA field macro --- */
                  myItem = ((long)GTMENUITEM_USERDATA(ItemAddress(menu_strip, result & WMHI_MENUMASK)));
                  /* --- Identify selected menu entry */
                  switch(myItem)
                  {
                    case MN_ITEM1:
                      if(myDebug)
                        puts("\n Menu 'Project': <ITEM> was selected.");
                      
                      break;
                  } /* END switch(myItem) */ 
                } /* END if(!(menuitem == 0)) */
                break;  /* END WMHI_MENUPICK */

              /* --- GADGETS ----------------------------------------- */
              case WMHI_GADGETUP:
                switch (result & WMHI_GADGETMASK)
                {
                  /* --- Gadget 1 --- */
                  case 
                    break;          					
          				           
                } /* END switch (result & WMHI_GADGETMASK) */
                break;  /* END case WMHI_GADGETUP */
                
              /* --- ICONIFY ----------------------------------------- */
              case WMHI_ICONIFY:
                if ( RA_Iconify( window_object ) )
                  main_window = NULL;
                break;

              /* --- UNICONIFY --------------------------------------- */
              case WMHI_UNICONIFY:
                main_window = RA_OpenWindow( window_object );
                if ( menu_strip)  SetMenuStrip( main_window, menu_strip );
              break;
            } /* END switch ( result & WMHI_CLASSMASK ) */
          } /* END while (( result = RA_HandleInput( window_object, &Code )) != WMHI_LASTMSG) */
      } /* END while ( !done) */
    } /* END if ( main_window = (struct Window *) RA_OpenWindow( window_object )) */
  } /* END if ( window_object ) */
} /* END Function runWindow() */


/* --- Function: window_main() ----------------------------------- */
/* --- All window-specific setup for main Window is done here. --- */ 
/* ---'runWindow()' is called for message handling afterwards. --- */
void window_main( void )
{
  /* We changed ReBuild's menu struct output in order to obey to GadTools Menu handling! */
  /* Replaced: Last NULL argument by (APTR) <Item identifier>                            */

} /* END Function window_main() */


/* --- Main Function ---------------------------------------------------------------------------------- */
int main(void)
{
  if ( setup() )    /* This will satisfy all needs... */
  {
    window_main();  /* ...and open Application's main Window + implement Event handling by running 'runWindow()' */
  }
  cleanup();        /* Clean up stuff and exit */
} /* END main() */

Du findest dieses Tutorial hilfreich? Dann freue ich mich über einen kleinen Obolus für meine IT-Kasse. Besten Dank!  🙂

[Übersicht]