Skip to content

Crazy Makefiles I Have known

Vitorio edited this page Nov 3, 2013 · 4 revisions

Hey, this page is super deprecated, now. Good philosophy, old instructions. See How to write a new 0.142 makefile instead.


Some quick tips I've picked up while compiling about a dozen systems in the jsmess tree.

The Philosophy

It's important to understand that JSMESS is doing something MESS doesn't specifically want to do, that is, split up the emulation function down to the single emulated platform level. The point of the MESS executable is that whatever you throw at it, it deals with it, and that the way to avoid bloated executables is to share functions as cleanly and clearly as possible, as is done in MAME. So, all the machines that use the 6502 chip, all reference the same function set that emulates the 6502.

This is the ideal, anyway, and cases where the ideal is not completely followed, can be dealt with, but the system generally works. Since MESS is meant to be built as a monolith, it works out.

For the purposes of testing, MESS provides a "tiny make" which builds just one system (the Colecovision) by referencing only the files needed for that system. This was the sign to the JSMESS project that it was possible to build a one-system-only version of MESS, and which we've been doing. Over the years, others have asked the question about "can we build by system" and it appears to be a controversy of some amount by the developers as to the wisdom of this, or what the possible purpose could be.

JSMESS is now doing this wholescale, because Javascript can't sustain a fully converted-to-JS MESS executable. Believe us, if we could do that, we'd have done it. Javascript is portable, an open standard, and very flexible. But it's not quite ready to take this thing on face first.

Therefore, our big work is in generating these tiny Makefiles for each emulated system we wish to cover in JSMESS. (Generally, we want to cover successfully emulated systems that will be of use in a browser window.) They don't exist in MESS and MESS does not, currently, make it easy. But we're doing it!

So You're Going to Make a Tiny Makefile

The Colecovision platform makefile is the one that gives insight into how to reference MESS internals easily. Observe:

###########################################################################
#
#   colecovision.mak
#
# ColecoVision-specific Makefile
#
###########################################################################

# disable messui for tiny build
MESSUI = 0

# include MESS core defines
include $(SRC)/mess/messcore.mak
include $(SRC)/mess/osd/$(OSD)/$(OSD).mak

#-------------------------------------------------
# Specify all the CPU cores necessary for the
# drivers referenced in colecovision.lst
#-------------------------------------------------

CPUS += Z80
CPUS += MCS48

#-------------------------------------------------
# Specify all the sound cores necessary for the
# drivers referenced in colecovision.lst
#-------------------------------------------------

SOUNDS += SN76496

#-------------------------------------------------
# This is the list of files that are necessary
# for building all of the drivers referenced
# in colecovision.lst
#-------------------------------------------------

DRVLIBS = \
        $(EMUOBJ)/drivers/emudummy.o \
        $(MESS_DRIVERS)/coleco.o \
        $(MESS_MACHINE)/coleco.o \

#-------------------------------------------------
# MESS special OSD rules
#-------------------------------------------------

include $(SRC)/mess/osd/$(OSD)/$(OSD).mak

For the purposes of the barbarians-at-the-gate methodology JSMESS is using, the key three areas of this are the CPUS += directives, the SOUNDS += directives, and the DRVLIBS directive.

MESS has support for dozens of different CPU and audio chips, all emulated to various degrees and used by a host of machines. A given arcade machine, console or computer will use a handful of these to get the job done, especially during the period of the 1970s and 1980s, when everyone was using similar core chips to get the workhorse jobs done.

In this case, the Colecovision uses the Z80 and MCS48 chips for the CPU, and the SN76496 for sound.

There are then driver files used by the code to make the system work. Colecovision is easily one of the smallest, with just two "coleco" c files used to drive it, hence its use for the test-environment "tiny" build. Most aren't this simple.

For example, here's the drivers for the Atari 800:

DRVLIBS = \
        $(EMUOBJ)/drivers/emudummy.o \
  $(EMUOBJ)/machine/6821pia.o \
  $(OBJ)/mame/video/atari.o \
  $(OBJ)/mame/video/antic.o \
  $(OBJ)/mame/video/gtia.o \
  $(OBJ)/mame/machine/atari.o \
  $(MESS_DEVICES)/appldriv.o           \
  $(OBJ)/lib/formats/flopimg.o         \
  $(OBJ)/lib/formats/fdi_dsk.o         \
  $(OBJ)/lib/formats/td0_dsk.o         \
  $(OBJ)/lib/formats/imd_dsk.o         \
  $(OBJ)/lib/formats/cqm_dsk.o         \
  $(OBJ)/lib/formats/dsk_dsk.o         \
  $(OBJ)/lib/formats/d88_dsk.o         \
  $(OBJ)/lib/formats/atari_dsk.o \
  $(MESS_MACHINE)/ataricrt.o \
  $(MESS_MACHINE)/atarifdc.o \
  $(MESS_DRIVERS)/atari400.o  \

Woah! Well, what's going on here is that the Atari has a floppy drive, so all those file formats for floppy disks, as well as a driver to emulate a floppy drive, get included. ataricrt emulates the cartridge slot. atari400, well... apparently there are some routines the atari 800 needs in the atari400 driver.

When doing MAKEs, these little dependencies start popping up like crazy. To assist with this, there's a script called SMARTFIND.sh which will look for c files named after a search string, which will then figure out the format to work well in a makefile. So, if you know something has CBM in the name, you can use SMARTFIND and get this back:

      $(MESS_DRIVERS)/cbmb.o     \
      $(MESS_FORMATS)/cbm_snqk.o     \
      $(MESS_MACHINE)/cbm.o     \
      $(MESS_MACHINE)/cbmb.o     \
      $(MESS_MACHINE)/cbmiec.o     \
      $(MESS_MACHINE)/cbmipt.o     \
      $(MESS_VIDEO)/cbmb.o     \

So, a lot of effort is saved for you. EXCEPT for the fact that not all of these routines are necessarily needed for the driver to function - some might just share the string name. This is when it becomes "art".

To make life marginally better for you, there's been a makefile template created (it's called supermak.mak which contains every known CPU routine, every known SOUND routine, and the standard build lines that every makefile seems to need. In this way, you've just been saved the tedium of what possible CPUs there are and what possible SOUNDS need to be added. So there's that.

Also lucky for you, the mess executable will give you a lot of hints as to what goes into a specific driver. Just type something in the form of:

mess -listxml [driver]

And MESS will dump a huge bundle of knowledge about the driver, including cpu usage, native resolution, what sort of media (carts, cassettes) it uses, and so on. This is a great place to start.

A popular method with the team at the moment is the "build the bridge and drive trucks over it until it breaks" approach, which involves compiling the system in question natively, i.e.:

make SYSTEM=[driver] NATIVE_DEBUG=1

Which will go along happily until it runs out of dependencies to track, and then wonders where the routines are. From these failed routines, you get a hint as to where to look next. Sometimes it's a CPU setting, other times a c file that needs to be thrown in. SMARTFIND may help a lot - put that basic string in, and sometimes there's a driver just waiting for you.

jsmess# ./SMARTFIND.sh wd17
      $(EMUOBJ)/machine/wd17xx.o     \

Therein lies the art. It's a case of chasing down these dependences and building until it all is covered in your limited Makefile.

Coming soon: Some of the more common "answers" that are cropping up over and over.