The aim of this short article is to get you started with creation of TOS binaries with GCC cross-compiler(actually it can be any compiler) and SCons (which is modern, Python based build system similar in functionality to GNU build tools).
The example is provided for Linux, but it should work fine under Windows too (with some minor modifications like path names etc..).
There will be shown how easy is to replace gcc m68k assembler (gas) with VASM which is much more user friendly and has devpac like syntax).

Prerequisities

You will need m68k cross compiler, install SCons from this site. For second example you will need installed VASM on your machine and visible from your environment. It would be good to have some idea about Python, but you can take look at it later.

There are several ways to get the cross compiler for your system. Here isthe info's that you will need (http://vincent.riviere.free.fr/soft/m68k-atari-mint). There is Cygwin installator and ready Debian/Ubuntu x86 and amd64 packages. You can also build everything from sources, but it will be rather time consuming.

What we will be doing

We will create standard 'Hello world' application (minimal and more expanded version), additionally we will be building everything in separate folders (out of source code directory build) - which is good practice. For example we can build two versions of our program debug (compiled with debug information enabled, turned off optimisations and so on) and release build (stripped symbols, turned on optimisations etc.).

SCONS first dive-in

First example is most straghtforward one. We have one file 'main.c' which can look like this:

main.c
#include <stdio.h> int main(void){ printf('Hello world!\n'); return 0; }

And we want to build TOS compatible binary out of it. After that we create file named 'SConstruct' in the same directory as the sourcefile which contains:

SConstruct
import sys import os env = Environment(tools=['default']) #output executable name OUTPUT_EXE='main.tos' #we will be building everything in the same directory, where the sources are OUTPUT_DIR='./' #here we set our tools names env["CC"] = 'm68k-atari-mint-gcc' env["CXX"] = 'm68k-atari-mint-g++' env["AS"] = 'm68k-atari-mint-as' env['AR'] = 'm68k-atari-mint-ar' env['OBJCOPY'] = 'm68k-atari-mint-objcopy' env['STRIP'] = 'm68k-atari-mint-strip -s' env['STACK'] = 'm68k-atari-mint-stack' # here we set default paths to headers and libraries env["CPPPATH"] = '/usr/m68k-atari-mint/include' env["LIBPATH"] = '/usr/m68k-atari-mint/lib' #if we want to add extra defines for C compiler we can specify them here. 'TOS' will show up as '-DTOS' during compilation. This is an example, so you can add anything you like. env["CDEFINES"] = 'TOS' # as above but for C++ compiler env["CXXDEFINES"] = 'TOSCPP' ################## Setting flags example ST_CFLAGS='-s -Os -std=c99 -fomit-frame-pointer -m68000' ST_CXXFLAGS='-Os -fno-rtti -fno-exceptions -fomit-frame-pointer -m68000' ST_LDFLAGS='-s -Os -fomit-frame-pointer -m68000 -Wl,--traditional-format ' ST_ASM_FLAGS = '-m68000' env["CFLAGS"] = ST_CFLAGS env["CXXFLAGS"] = ST_CXXFLAGS env["LDFLAGS"] = ST_LDFLAGS env["ASFLAGS"] = ST_ASM_FLAGS ########################### main program entry, sources list source_files= ["main.c"] env.Program(target = OUTPUT_EXE,source = source_files)


After that, go to console, go to the sources directory with 'main.c' and type in command 'scons'. After that you will see output from compiler (as in usual makefile builds). If everything will be fine then you should have 'main.tos' binary in your source folder compiled for m68k cpu. You can test it on real machine or under emulator.
If you need to rebuild everything type in 'scons -c' to clean all output files and binary and type 'scons' once again.

Second example

Let's assume that all our source files are in 'src' folder and we will be building our program in two versions 'debug' and 'release', in two directories one level above 'src' directory path. Additionally we will have one file which is m68k source and we want to assemble it, but not with gcc gas, but VASM. File will be targeted for Falcon030 (,but it can be easily changed to other Atari platform by changing processor flags).

Our sources are: main.c, hello.s. We need to create two files: 'SConscript' and 'SConstruct'(as in prevoius example):

SConstruct
SConscript('SConscript', variant_dir='../build_release', duplicate=0, exports={'MODE':'release'}) SConscript('SConscript', variant_dir='../build_debug', duplicate=0, exports={'MODE':'debug'})


SConstript
import sys import os env = Environment(tools=['default']) # you can uncomment following line to display current environment settings # it's useful for debug purposes #print env.Dump() #output executable name OUTPUT_EXE='main.tos' #we will build everything one level above the sources folder inside 'build' catalog OUTPUT_DIR='../build/' env["CC"] = 'm68k-atari-mint-gcc' env["CXX"] = 'm68k-atari-mint-g++' env["AS"] = 'vasmm68k_mot' #here we exchange gas to VASM env['AR'] = 'm68k-atari-mint-ar' env['OBJCOPY'] = 'm68k-atari-mint-objcopy' env['STRIP'] = 'm68k-atari-mint-strip -s' env['STACK'] = 'm68k-atari-mint-stack' env["CPPPATH"] = '/usr/m68k-atari-mint/include' env["LIBPATH"] = '/usr/m68k-atari-mint/lib' env["CDEFINES"] = 'TOS' env["CXXDEFINES"] = 'TOSCPP' # VASM tool settings, this is optional. Maybe you will use this environment in the future. env['VASM'] = 'vasmm68k_mot' ################### F030 settings F030_CFLAGS = '-g -std=c99 -fomit-frame-pointer -m68030 -m68881 -ffast-math' F030_CXXFLAGS = '-Os -fno-rtti -fno-exceptions -fomit-frame-pointer -m68030 -m68881 -ffast-math' F030_LDFLAGS = '-fno-exceptions -fno-rtti -fomit-frame-pointer -m68030 -m68881 -Wl,--traditional-format' F030_VASM_FLAGS = '-Faout -quiet -m68030 -m68881 -spaces -showopt -no-opt' ################################################################################# #TODO get target platform (parameter) and set compiler flags # more info in the SCons docs: http://www.scons.org/doc/production/HTML/scons-user/a4916.html env["CFLAGS"] = F030_CFLAGS # c only options env["CXXFLAGS"] = F030_CXXFLAGS env["LINKFLAGS"] = F030_LDFLAGS env["ASFLAGS"] = F030_VASM_FLAGS ########################### main program entry source_files= ["main.c","hello.s",] env.Program(target = OUTPUT_EXE, source = source_files)


As you see now inside the 'Sconstruct' we invoke two times the same script('SConscript') to perform two builds.
In the end we add two source files - minimal m68k assembler source code and c code:

hello.s
XDEF _hello ;export symbol hello: ;now we call CConws() to display null terminated string movem.l d1-d2/a0-2,-(sp) move.l #hi_msg,-(sp) move.w #$09,-(sp) trap #1 addq.l #6,sp movem.l (sp)+,d1-d2/a0-2 rts hi_msg: dc.b "Hi from 68k!",$0d,$0a,$00



main.c
#include <mintbind.h> extern void hello(void); int main(int argc, char **argv){ hello(); Cconws("Hello world from C!\n"); Cconws("Press any key...\n"); Cconin(); return 0; }


note: If we want to to compile everything for C++ (it's detected automatically via extension) then we have to exchange following line:

extern void hello(void);


with

extern "C"{ void hello(void); }


to keep compiler happy.

And that's it. SCons has alot more features that make developer life easier. Afterall we should focus more on software we do, not fight the tools, automate all boring tasks and delegate them to our personal computer.
You can take a look at official site and read the SCons documentation, to get an idea what is possible.