Have you ever wanted a simple, easy to configure, flexible Makefile for everyday development? Don’t want to have to invoke automake/autoconf or construct new Makefiles for every little test program? This may be what you’re looking for:

edam’s general-purpose Makefile!

Features:

  • Easy configuration (documented below)
  • Support for C, C++, assembly (nasm only) and D (gdc only) source files
  • Build modes (normal, debug and profile mode)
  • Subdirectories (for automatic recursion when building and cleaning)
  • A sophisticated dependency file generation system

Download: Makefile (version 2.3, 5KB)

Configuration

Target Settings

The TARGET variable specifies the name of the target.

If uncommented, MKSTATICLIB and MKSHAREDLIB cause a static library or a shared library to be built instead of a binary executable.

For example, to build your libtim.so, you might have:

#MKSTATICLIB    := 1
MKSHAREDLIB := 1
TARGET    := libtim.so

Specifying Build Input

Specify all source files you want to build, libraries you want to link against and subdirectories that you want to build first in the variable SOURCES, LIBRARIES and SUBDIRS respectively. All three variables takes a space-separated list.

For example:

SOURCES  := foo.cc bar.cc
LIBRARIES   := gl glu
SUBDIRS  := subdir1 subdir2

How a file is compiled depends on it’s extension. The following extension types are recognised:

  • C source files: .c
  • C++ source files: .cc, .C, .cpp
  • assembly source files: .s, .S, .asm
  • D source files: .d

Please note that while you can happily mix different source file types in the SOURCES variable, you can not have two files named the same thing, but with a different extension (such as “foo.cc” and “foo.c”). For one thing, when compiled, they’d produce object files with the same name.

Build Flags

If you need more control over build flags, use the following variables:

  • CPPFLAGS are passed to the C, C++ and D compiler
  • CFLAGS is only passed to the C compiler
  • CXXFLAGS is only passed to the C++ compiler
  • DFLAGS is only passed to the D compiler
  • ASFLAGS is only passed to the assembler
  • LDFLAGS is passed to the linker before the list of object files
  • LDPOSTFLAGS is passed to the linker after the list of object files

For example:

CPPFLAGS    := `pkg-config --cflags gtkmm-2.4`
CFLAGS    :=
CXXFLAGS    :=
DFLAGS    :=
ASFLAGS  :=
LDFLAGS  :=
LDPOSTFLAGS := `pkg-config --libs gtkmm-2.4`

Build Modes

When running make, there are three build modes:

  • release — this is the default. Output is optimised and symbol information stripped
  • debug — for use in everyday development with gdb.
  • profile — for profilling with gprof

Specifying the Build Mode

With no overriding options, the Makefile will build in release mode. There are several ways to initiate a build other than the default. You can:

  • Create the environment variables DEBUGMODE and PROFILEMODE and set them to the value “1″. Like this:
    $ export DEBUGMODE=1

    Alternatively, they should be unset (a value of “0″ will not unset them!), like this:

    $ unset DEBUGMODE
  • Specify a build mode on the make command line, like this:
    $ make DEBUGMODE=1

    or like this:

    $ make DEBUGMODE=

    This overrides any environment variables set as above.

  • Uncomment the build-mode variables at the top of the Makefile to hard-code the build mode (although this is probably a less preferable method!)

This allows for some fairly flexible configurations. What I would recommend for development purposes is to add the line

export DEBUGMODE=1

to your ~/.bashrc so that you are always building in debug-mode by default. Then, when you want to build in release-mode, run make like this:

$ make DEBUGMODE=

or to build in profile-mode, like this:

$ make PROFILEMODE=1

Build Mode Specific Files

Obviously, when compiling, the Makefile will generate .obj files. The release-, debug- and profile-mode versions of these files must be kept separate, as must the resulting executable or library.

To differentiate between build modes, debug-mode files have “_d” appended to them and profile-mode files have “_p” appended to them. So, for example, “test.cc” will compile into “test_d.o” in debug-mode. This in turn may compile into the executable “test_d”. Similarly, in profile-mode, “test.cc” would compile in to “test_p.o”, which in turn would become part of the executable “test_p”.

Dependency Files

In addition to the .obj files, .dep files are generated to track the build dependencies between files. Unlike the .obj files, these are not generated separately for each build-mode. In fact, they are only built in debug-mode.

In a nutshell, dependency files are built as a by-product of compilation (rather than separately), do not include system headers, and include dummy targets to prevent make complaining when depended-upon files are deleted or renamed.

For more information about the dependency file generation system, see this excellent article on advanced auto-dependency generation. The full system outlined in the article is implemented with the slight improvement that dummy targets are created at compile-time, not in post-processing by an unsightly sed command. The unsightly sed command is still used, however, for other, less-able compilers/assemblers.

On a final note, dependency files are not generated for D.

Make Goals

The full list of goals for the general-purpose Makefile are:

  • all — the default; builds any subdirectories and then any target
  • subdirs — builds the subdirectories (but not any target)
  • target — builds the target (but not any subdirectories)
  • run — builds the target (but not any subdirectories) and, on success, executes it
  • clean — removes intermediate build files for the target only
  • clean_all — removes intermediate build files for the target and any subdirectories
  • <subdir> — you can specify a specific subdirectory to build (so long as it is defined in SUBDIRS)
  • <file> — you can also specify any object files, or the target, as with most Makefiles

Finally

There have been many revisions of this Makefile. If you find any errors, or have any suggestions for its improvement, please email me. I would love to hear about them.

No Comments

Leave a comment