CMakefile is an automatic build system for C/C++ based on
make
. CMakefile is configurable by a PROJECT file. It is appropriate
for small to medium-sized C/C++ projects.
- Easy to use. In simple cases just copying the Makefile into your project directory suffices.
- Automatic detection of C, C++, Flex and Yacc/Bison sources based on file extensions.
- Automatic dependency generation.
- Automatic creation of executables based on the presence of the
main
function. - Support for subdirectories.
- Support for library creation.
- Support for multiple user-defined build configurations (e.g. DEBUG, RELEASE).
- Configurable compiler, linker, flex and yacc executable names and flags.
- Configurable build and source directories.
- Extensible with arbitrary make rules read from
Makefile-include
.
- GNU make
- bash, grep, sed, find
If all your sources are in a single directory, then the simplest way
to use CMakefile is to copy Makefile
into your source
directory. Running make
will then create executables for all files
containing definitions of main
. If your project directory contains
the src
subdirectory with all sources, then you can copy Makefile
into the project directory instead of into src
.
Compiler flags, subdirectories, program sources, build directory and more can be specified via project options (see below).
You can also add arbitrary make rules by putting them in
Makefile-include
.
The examples/
directory contains some examples.
all
: Build all programs and libraries. This is the default target.clean
: Remove all build files. Removes the build directory entirely if it is different from.
.depend
: Create the*.d
dependency files.
The PROJECT
file should contain project option declarations, each on
a separate line. The declarations have two forms.
- Global declarations.
OPTION = VALUE
- Configuration-local declarations.
CFG1 .. CFGn OPTION = VALUE
Prefixing an option with build configurations CFG1 .. CFGn
indicates
that the declaration should be used only if the current build
configuration is one of CFG1
,...,CFGn
. The current build
configuration is specified by the CONFIG
option.
For instance, the following declarations will set the CFLAGS
option
to -Wall -g -O0
.
CONFIG = DEBUG
DEBUG CFLAGS = -Wall -g -O0
RELEASE CFLAGS = -O2 -DNDEBUG
The idea is that the value of CONFIG
may be easily changed affecting
multiple options at once. Typical values for CONFIG
are RELEASE
and DEBUG
, but any word can be used.
Two configurations may be conjoined with the +
symbol. For example,
CONFIG = X86+RELEASE
DEBUG CFLAGS = -Wall -g -O0
RELEASE CFLAGS = -O2 -DNDEBUG
X86 CFLAGS = -march=i386
X86+RELEASE CLFAGS = -mmmx
X86+DEBUG CFLAGS = -DX86DEBUG
sets CFLAGS
to -O2 -DNDEBUG -march=i386 -mmmx
.
The project options may also be specified on the command line,
overriding the declarations in PROJECT
. For example,
make CONFIG=DEBUG
sets the current build configuration to DEBUG
overriding the
declaration of CONFIG
in PROJECT
.
All options are available for use as variables in Makefile-include
.
Lines of PROJECT
which begin with #
are treated as comments. Note
that #
must be the first character in the line for it to be treated
as a comment.
Aside of the CONFIG
option which should have only one declaration,
there are two types of project options: concatenable and
replaceable. For concatenable options, when there exist both global
and local declarations of the option, their values are
concatenated. For replaceable options, the local declaration overrides
the global one.
Concatenable options can be locally overriden using the overriding
assignment :=
. For example,
CONFIG = DEBUG
CFLAGS = -DNDEBUG -O2
DEBUG CFLAGS := -DDEBUG
sets CFLAGS
to -DDEBUG
.
PROGRAMS
: Program executables to create (paths relative to the source directory). Default: basenames without extension of source files containing definitions ofmain
.SUBDIRS
: Subdirectories of the source directory (SRCDIR
) included in the search for sources. Default: empty.RSUBDIRS
: Same asSUBDIRS
but also recursively includes all subdirectories of the listed directories, the subdirectories of the subdirectories of the listed directories, and so on. Default: empty.IGNORE
: Source files to ignore (paths are relative to the source directory). Default: empty.CFLAGS
: C compiler flags. Default: empty.CXXFLAGS
: C++ compiler flags. Default: empty.CDEPFLAGS
: C flags for dependency generation. Default:CFLAGS
.CXXDEPFLAGS
: C++ flags for dependency generation. Default:CXXFLAGS
.YFLAGS
: Yacc flags. Default:-d
.LEXFLAGS
: Lex flags. Default: empty.CCLDFLAGS
: C linker flags. Default: empty.CXXLDFLAGS
: C++ linker flags. Default: empty.LDFLAGS
: Linker flags common to C and C++ linkers. Default: empty.LIBFLAGS
: Librarian flags. The flag-o
must occur at the end ofLIBFLAGS
iflibtool
is used. Forar
compatibility,-o
is not added automatically. Default:-static -o
.
SRCDIR
: Source directory. Default:src
if it exists, current directory otherwise.BUILDDIR
: Build directory. Default:_build
. Warning: if different from.
then the build directory is entirely removed bymake clean
.LIB
: Library to create. Default: empty.CC
: C compiler executable. Default:gcc
.CXX
: C++ compiler executable. Default:g++
.YACC
: Yacc executable. Default:bison
.LEX
: Lex executable. Default:flex
.CCLD
: C linker. Default:CC
if there are no C++ sources,CXX
otherwise.CXXLD
: C++ linker. Default:CXX
.LIBTOOL
: Librarian. Default:libtool
.
-
Source files must have recognised extensions: .c, .cpp, .cxx, .cc, .lex, .y.
-
File names cannot contain whitespace.
-
Detection of the
main
function is very crude - it is based on matching the regular expression\bint[ \t]+main\b
. This may give a false positive if anything in your sources that is not a definition ofmain
matches, or a false negative when, e.g., you have a newline betweenint
andmain
. -
The
+
operator is not commutative and conjoined configurations must occur verbatim in the option specifications. For example, the following setsCFLAGS
to just-march=i386
.CONFIG = X86+DEBUG+FAST X86 CFLAGS = -march=i386 X86+DEBUG CFLAGS = -g FAST+X86+DEBUG CFLAGS = -O3
Copyright (C) 2008-2023 by Lukasz Czajka.
Distributed under the MIT license. See LICENSE.