fadden's Makefile System (FMS)
Version 1.2.4 - 15-Sep-2005

This collection of files is a skeleton for a multi-architecture build
system with auto-generated dependencies.  It provides some simple rules
for building executables, static libraries, and shared libraries.  It
is intended for use with GNU make (v3.79.1 or later) and works best with
the GNU C compiler.


License
=======

I, the creator of this work, hereby release it into the public domain.
This applies worldwide.  In case this is not legally possible, I grant
anyone the right to use this work for any purpose, without any conditions.

You may do whatever you want with the files in this collection.  You are
encouraged to delete this README, erase any signs of authorship, and put
your own copyright notice at the top of each file.

This software comes with NO WARRANTY.  It is not supported.  If it erases
all of your source files, don't look at me.


How to Use
==========

The build system understands two primary targets, "all" and "install".
The default, "all", builds the files in this directory and in all
subdirectories.  The "install" target does everything that "all" does,
and also installs the generated binaries in an installation area.

To see it in action, type "make" at the top level.  This actually gets
converted to a "make install" by the top-level makefile, which creates
the installation directories and then runs through the various subdirs
building and installing things.  You can also run "make" or "make install"
in any of the subdirectories.

Some of the examples link against libraries in the installation area.
If you try to build app_three without first doing a "make install" in
the various library directories, the build will fail.  This is something
to bear in mind when deciding where libraries reside when used as linker
inputs.  (The easy fix is to make "install" the default target.)

"make clean" executes recursively, and cleans out object files and
generated source files.  "make clobber" will wipe out all objects,
generated source files, and the entire "install" directory.  You should
be left with a fully pristine installation after a clobber.

There are two prototype platforms configured, "x86" and "mips".  Take
a look at "buildspec.mk" to see how they're selected.

To test the output:

$ make
$ cd install/x86-debug/bin
$ ./app_one
    (the output reflects the build platform)
$ ./app_two a b c
    (demonstrates use of Log function in static lib)
$ ./app_three 12
    (you'll get a shared library error on "libshared.so")
$ LD_LIBRARY_PATH=../lib ./app_three 12
    (that works for Linux sh/bash/zsh; demonstrates shared library usage)
$ ./app_four
    (demonstrates an executable built "manually")

MSYS/MinGW doesn't seem to follow LD_LIBRARY_PATH, so you'll need to cd
to the "lib" directory and run app_three from there.

You should be able to type "make" again and have nothing rebuilt.  If
you touch one of the libraries, it will rebuild the shared libraries
and executables that depend on it.

The output will indicate that it is copying libraries and executables to
the install directory every time, but it's actually using "cp -u", which
only copies files when the source file is newer.  This way we don't end
up touching every library on every "make install".


Integration
===========

To use this in your own project, you only need two files:

    build/makedefs.mk
    build/makerules.mk

Everything else is either part of the sample code or is documentation.
You may also want to retain "build/README", which provides an overview
of the system and describes how best to use it.

Your top-level Makefile will probably look a lot like the one here.
The makefiles you create for each component of your project will probably
look like the ones in "app1", "loglib", or "baselib".  Cutting & pasting
makefiles is the easiest way to get started.

You will need to configure build/makedefs-XXX.mk for each platform you
will support.  How hairy these get depend on what your toolchain setup
looks like.  You will want to set up a default "buildspec.mk", probably
renamed to "buildspec.mk.default", that users can copy and custom-tailor.


Background
==========

Engineers working on consumer electronics projects are accustomed to
building code for multiple platforms.  It's not uncommon to build the
same sources for two or more platforms as well as a native "simulator"
environment.

These same engineers often run into difficulties with "makedepend" tools,
especially when cross-compiling funky code that confuses the dependency
generator.  Some projects go for a while with no dependency information at
all, which can lead to painful debugging sessions and lots of full builds.

Build environments that handle these issues are usually reinvented by
each company.  I got tired of reinventing this particular wheel, and
decided to put some stuff together and place it in the public domain.


Unimplemented
=============

Some things that might be nice to have:

 - General way to perform builds across the set of known platforms.  This
   would make it easy to perform multiple platform builds when testing a
   change, and allow a wide-scale "make clean".  Right now the buildspec.mk
   or environment variables need to be updated before each build.
 - The shared library target (FMS_BUILD_SHLIB) could probably do the
   symbolic linking stuff as well.  This is a little awkward because it
   needs to be tied into the install target.  One approach is to add a
   "shlib-link" target that install-here depends on in each Makefile.
 - The $(MAKELEVEL) tells us how deep we are.  We could use this to
   indent the output, which might be more attractive when building in a
   directory hierarchy.
 - Problems can arise if you delete a header file that is referenced in
   ".d" files.  The easy way to deal with this is "make clean".  There
   should be a better way to handle it.
 - Add Mac OS X support.  Mac OS shared libraries are a little strange.
   Also, the Mach/BSD utilities aren't the same as the GNU utilities, e.g.
   there's no "-u" flag for cp.  This can be cured with a make function
   that evaluates the relative ages of the files, which is nicer in some
   ways because it'll tell you if it's actually copying files around.


Change Log
==========

v1.0.0 - 26-Jul-2005
    Initial release
v1.1.0 - 27-Jul-2005
    Changed the way dependencies for generated code work.
v1.2.0 - 28-Jul-2005
    Added FMS_OBJECTTOP support.
v1.2.1 - 28-Jul-2005
    Adjusted rpath-link handling.
v1.2.2 - 04-Aug-2005
    Reduced glibc dependencies in loglib/log.c.  Changed the way "ln -s"
    is invoked.
v1.2.3 - 12-Aug-2005
    Added $(FMS_BUILD_APP) to .PHONY.
v1.2.4 - 15-Sep-2005
    Don't invoke $(MAKE) to build install-here; it fails for "make -f".

