NAME

antimake - Minimal Automake syntax on plain GNU Make

DESCRIPTION

Antimake makes possible to use GNU Automake conventions to describe builds in ordinary Makefiles for GNU Make.

It’s main abstractions are target lists and target variables. Target list describes target type and where to install. Target variables give source files and additional flags for build.

EXAMPLE

# target list
bin_PROGRAMS = prog

# target variables for 'prog'
prog_SOURCES = prog.c prog.h
prog_LDADD = libutil.a

# target list
noinst_LIBRARIES = libutil.a

# target variables for 'libutil.a'
libutil_a_SOURCES = util.c util.h

# load Antimake
include antimake.mk

Terminology

Primary

target type, describes how to build and install particular type of targets.

Target

a file that needs to be built and/or installed.

Distribute

Include file in source .tar.gz. Non-distributed files are skipped when building .tar.gz and are cleaned during make distclean.

Source

Source files are files that appear in ..._SOURCES per-target variable. They are distributed by default. They may or may not result in object files. It’s fine to put both .h and .c files into _SOURCES.

TARGET LISTS

Target lists are variables that contain file names that need to be built and installed. They are specially named so that the name also describes how they are built, how and where they will be installed.

The target list name contains 3 parts, separated with underscore, in following order:

  1. Optional flags. Flags are: nodist, dist, nobase, base. (Default: base, nodist)

  2. Destination directory name. Destination directory called bin actual location is stored in Make variable $(bindir). Some common values: bin, lib, include. There are more and the list can be extended. Special name noinst means the target file should not be installed.

  3. Target type, also called "primary". This will describe how the target needs to be built. Common values: PROGRAMS, LIBRARIES, DATA

For details, what the various values mean, see next sections.

Examples:
bin_PROGRAMS = prog1 prog2
# flags: base, nodist
# dest: $(bindir)
# type: PROGRAMS

noinst_LIBRARIES = lib1.a lib2.a
# flags: base, nodist
# dest: noinst
# type: LIBRARIES

nobase_dist_doc_DATA = docs/README
# flags: dist, nobase
# dest: $(docdir)/docs
# type: DATA

Primaries

PROGRAMS

executable programs, linked together from objects built from source files

LIBARIES

static libraries, linked together from objects built from source files

LTLIBRARIES

dynamic or static libraries, linked together from objects built from source files

HEADERS

header files, no default build method, the target files have dist flag by default.

MANS

man pages, no default build method, installed into manX subdir.

SCRIPTS

scripts, executable file, no default build method

DATA

data, non-executable file, no default build method

Target list flags

dist

The target should be distributed with other sources. Default for HEADERS type, others have nodist by default.

nodist

Target is not distributed and should be cleaned with distclean. Default for all primaries, except HEADERS.

base

On install relative path is ignored, all files end up in destination directory. Always default.

nobase

On install relative path is kept. Eg: if includedir=/usr/include then nobase_include_HEADERS=mylib/common.h is installed to /usr/include/mylib/common.h.

noinst

Target is built as part of build process, but is not installed.

EXTRA

Targets in such list are not built, nor installed. Useful to make sure that sources for dynamically configured targets will end up in source tarball. Unlike other target list ariables, EXTRA_<primary> may contain targets already defined in other target lists, they will be filtered out from this list then.

Target variables

Only big targets take additional variables: PROGRAMS/LIBRARIES/LTLIBRARIES.

<tgt>_SOURCES

All source files, *.c *.h *.cpp *.hpp.

nodist_<tgt>_SOURCES

Source files that should not be distributed.

EXTRA_<tgt>_SOURCES

In case tgt_SOURCES is dynamic, here is non-dynamic list of sources for distribution. Only dynamic sources need to be listed here.

<tgt>_DEPENDENCIES

Add dependencies that need to be build before target build will start.

<tgt>_CFLAGS, <tgt>_CPPFLAGS, <tgt>_LDFLAGS, <tgt>_LIBTOOLFLAGS

Override corresponging AM_xx variable

<tgt>_LDADD

Add dependencies that are used during linking. For PROGRAMS only. They will be added to linker command line.

<tgt>_LIBADD

Add dependencies that are used during linking. For LIBRARIES/LTLIBRARIES only. They will be added to linker command line.

<tgt>_AR

Overrides $(AR) $(ARFLAGS). For LIBRARIES only.

Example:
bin_PROGRAMS = prog
prog_SOURCE = main.c util.c util.h
prog_CFLAGS = $(GTK_CFLAGS)
prog_LDADD = $(GTK_LIBS)

Global variables

They can be set before antimake.mk inclusion to change build behaviour.

EXTRA_DIST

Additional files to include in source archive.

CLEANFILES

Additional files to make clean.

DISTCLEANFILES

Additional files to make distclean.

MAINTAINERCLEANFILES

Additional files to make maintainer-clean.

SUBDIRS

Subdirectories of current directory where Make needs to be recursively launched. If subdirectory Makefile is Antimake-base, it should set SUBLOC.

SUBLOC

Current diretory location in overall source tree. This can stay unset in top directory. Needed for subdirectiories entered with SUBDIRS to find its position in source tree.

DIST_SUBDIRS

Subdirs that only make dist, make distclean and make maintainer-clean will enter.

EMBED_SUBDIRS

Subdirectories that are built non-recursively: they need to contain Makefile.am that contains makefile-fragment with Antimake syntax that describes local targets using relative filenames. The fragment is included in main makefile and file and variable names are converted and merged with top-level targets.

AM_FEATURES

List of extensions to load. Extensions are Makefile fragments that are loaded before actual rules are generated, so they can change or add targets.

More details on EMBED_SUBDIRS

It acts like include $(dir)/Makefile.am for each directory, except it converts file and variable names. Example:

Makefile:
  EMBED_SUBDIRS = src

src/Makefile.am:
  bin_PROGRAMS = hello
  hello_SOURCES = main.c
  hello_CPPFLAGS = -I./include

Conversion results as if top-level Makefile had contained following rows:

bin_PROGRAMS += src/hello
src_hello_SOURCES = src/main.c
src_hello_CPPFLAGS = -I./src/include

Variables, where file names are converted:

  • SUBDIRS, DIST_SUBDIRS, EMBED_SUBDIRS

  • DISTFILES, CLEANFILES, DISTCLEANFILES, MAINTAINERCLEANFILES

  • target lists

  • <tgt>_SOURCES, <tgt>_LDADD, <tgt>_LIBADD

Variables, where -L and -I flags are converted:

  • <tgt>_CFLAGS

  • <tgt>_CPPFLAGS

  • <tgt>_LDFLAGS

Makefile should be written in a way that those conversions would be enough.

Global variables for current location

  • srcdir, builddir - relative path to source dir and build dir.

  • top_srcdir, top_builddir - relative path to top-level source and build dir.

  • abs_srcdir, abs_builddir - absolute path to source and build dir

  • abs_top_srcdir, abs_top_builddir - absolute path to top-level source and build dir

  • nosub_top_srcdir, nosub_top_builddir - relative path from top of builddir to srcdir and builddir.

Global variables that target can override

  • AM_CPPFLAGS

  • AM_CFLAGS

  • AM_LDFLAGS

  • AM_LIBTOOLFLAGS

  • AM_DEFS

  • AM_MAKEFLAGS

Global variables from autoconf

These variables come usually from autoconf, but also have reasonable defaults:

CC, DEFS, CPPFLAGS, CFLAGS, LDFLAGS, LIBS,
LIBTOOL, LIBTOOLFLAGS, AR, ARFLAGS, RANLIB,
CXX, CXXFLAGS, INSTALL, MKDIR_P, LN_S

Global variables for extending Antimake

AM_DIST_DEFAULT

Default format(s) for make dist target. One or more of: gzip, bzip2, xz, zip. Default: gzip.

AM_DESTINATIONS

Additional directory names to consider as valid destinations. Expects corresponding dir-variable to be set.

AM_SMALL_PRIMARIES

Additional single-file primaries. (Builtin: HEADERS, SCRIPTS, DATA, MANS)

AM_BIG_PRIMARIES

Additional primaries built from objects. (Builtin: PROGRAMS, LIBRARIES, LTLIBRARIES)

AM_LANGUAGES

Additional language names. Antimake expects variables AM_LANG_$(name)_SRCEXTS, AM_LANG_$(name)_COMPILE and AM_LANG_$(name)_LINK to be set.

Variables for command-line usage

DESTDIR

Relocate installation root.

AM_TRACE

Turns on function-call debug info. Can be set from command-line.

Hacking variables

GNUMAKE380, GNUMAKE381, GNUMAKE382

If we have at least that version of GNU Make. GNUMAKE380 is always set, others may not be. If Makefile uses features from newer GNU Make it would be good idea to use those flags and error out with clear error message, instead having mysterious failures.

Libtool flags

Useful Libtool flags that can be put int tgt_LDFLAGS for a LTLIBRARY:

  • -export-dynamic

  • -export-symbols symfile

  • -export-symbols-regex regex

  • -module

See libtool "Versioning" chapter about those:

  • -avoid-version

  • -version-info current[:revision[:age]]

  • -version-number major[:minor[:revision]]

  • -release major[:minor[:revision]]

Top-level pseudo-targets

all

The default target when no other target is given on command-line. Builds all target files.

Simple targets

These are simple - either the file already exists, or the user needs to give build command.

Object-based targets

The targets in primaries PROGRAMS, LIBRARIES and LTLIBRARIES consist of multiple source files that need to be compiled into objects. Then the objects need to be linked into final target. The process is roughly following:

  1. Dependencies are built (_LDADD, _LIBADD, _DEPENDENCIES).

  2. Source list is filtered for extensions that can be compiled into object files, object file list is created based on them. The rest of files are used and dependencies for target, but otherwise ignored.

  3. Object files are built.

  4. Linker is picked based on source files - as there can be files in multiple languages, the most advanced language wins (the one that appears later in AM_LANGUAGES)

  5. Final executable is linked.

install

Install all targets to their destination directories, which is mentioned in their target list variable name. Eg. bin_PROGRAMS will be installed to $(bindir). If destination is named noinst, it will not be installed.

If the flag nobase is given, the relative filename is kept, otherwise basename is taken and it will appear directly under destination directory.

Example:
include_HEADERS = func1.h lib/func2.h
# Files will end up in:
#   $(includedir)/func1.h
#   $(includedir)/func2.h

nobase_include_HEADERS = func1.h lib/func2.h
# Files will end up in:
#   $(includedir)/func1.h
#   $(includedir)/lib/func2.h

clean

  • Remove files in $(CLEANFILES)

  • Remove built objects.

  • Remove target files, unless they are marked as dist. (Note: HEADERS primary is dist by default, all other are nodist)

distclean

  • Remove files in $(DISTCLEANFILES)

  • Remove sources tagged with nodist. All sources as dist by default.

maintainer-clean

  • Remove files in $(MAINTAINERCLEANFILES)

help

Describe top-level targets.

am-test

Regression test for low-level Antimake functions.

am-debug

Show Antimake internal state.

FEATURES

Done:

  • Big primaries: PROGRAMS, LIBRARIES, LTLIBRARIES

  • Small primaries: DATA, SCRIPTS, MANS, HEADERS

  • Flags: base nobase dist nodist noinst EXTRA

  • Target vars: SOURCES, CPPFLAGS, CFLAGS, LDFLAGS, LDADD/LIBADD

  • Separate build dir

  • Per-target objects

  • Languages: C, CXX

  • SUBDIRS, DIST_SUBDIRS

  • EMBED_SUBDIRS

Todo:

  • Improve docs

  • Standardize and document how to extend

  • Deps with non-gcc?

  • Long if-s to support O= seems to break GNU Make 3.80. Drop O= or drop 3.80?

Probably out of scope:

  • make uninstall

  • make distcheck

  • make dist from separate build dir

  • install-(exec|data)-hook - based on dir not primary

  • Default file list for EXTRA_DIST. (Problem: distclean / maintainer-clean)

Definitely out of scope:

  • automake conditionals

  • automake extras (autoconf macros, ltdl)

  • automake nanny mode (gnu/gnits)

SEE ALSO

Recursive Make Considered Harmful: http://miller.emu.id.au/pmiller/books/rmch/

Paul’s Rules of Makefiles: http://make.mad-scientist.us/rules.html

Small BSD-ish build system: https://webkeks.org/hg/buildsys/

GNU Make Standard Library: http://sourceforge.net/projects/gmsl/