Search notes:

make

Makefiles commonly describe the dependencies of source files, intermediate files (such as object files) and executables.

Recursively turn each cpp file into an executable

SOURCES=$(shell find -type f -iname '*.cpp')

all: $(SOURCES:.cpp=)
See this stackoverflow answer.

Rules

A rule consists of three parts:
target: dependency-1 dependency-2 …
	command-1
	command-2
	…
A target is usually a file (but compare with phony targets).
The commands must be prepended by a tab.
The first rule in a makefile is the default rule.

Targets

The macro $@ evaluates to the name of the current target.
foo: $(objs)
	$(CXX) -o $@ $(objs)
If make is invoked without stating an explicit target, it tries to update the first target in the makefile.

Default goal

The first target that does not start with a dot is the default goal.
The default goal can be overridden

Suffix rules

Two types of suffix rules(?)
Example for double suffix rule:
.c.o:
	$(CC) $(CFLAGS) -c $<
Suffix rules are obsoleted by pattern rules (which contain % signs).
The example above is equivalent to the following pattern rule:
%.o : %.c
	$(CC) $(CFLAGS) -c $<

Macros

Macros seem to the make specific term for variables.
Macros can be defined when make is invoked:
$ make CFLAGS=-g

Multiple processors

With multiple processors (or cores), the compilation time can be reduced by parallelizing the tasks.
This can be achieved with export MAKEFLAGS='-j 2' or just make -j2.
The number of available processing units can be determined with nproc (MAKEFLAGS="-j $(nproc)").

Standard targets

all: Default target (same as just invoking make). Builds the executables, libraries, documentation etc.
install: install built things.
install-strip: like install, but additionally strip debugging symbols.
By default, make install will install the files in /usr/local/bin, /usr/local/lib etc. (That is: under prefix, which can be overwritten with ./configure[./configure --prefix=...`).
clean: opposite of make install
distclean: Also get rid of any files that ./configure has created.
check: run tests (if available)
installcheck: check the installed libraries.
dist: create PACKAGE-VERSION.tar.gz
distcheck: like dist with additional sanity checks. Prefer distcheck over dist.
maintainer-clean

Show make's default rules

The -p option prints the rules and variable values (referred to as database) that take effect with the given Makefile.
The -f option specifies the makefile (default is: Makefile), thus -f /dev/null makes sure that no Makefile is read.
make -p
make -p -f/dev/null
make calls these default rules the »internal database«.

Misc Makefile examples

does-not-exist: @
	echo Without @, the command is repeated
	@echo @ith, the command is not printed
Github repository about-Makefile, path: /@
# vim: ft=make

#
# Read the output of a shell command.
#

FILES=$(shell ls -1)
$(info $(FILES))

all:
	@true
Github repository about-Makefile, path: /shell
# vim: ft=make

FILES=\
 dir_1/sub_dir_a/file_1_a_i \
 dir_1/sub_dir_a/file_1_a_ii \
 dir_1/sub_dir_a/file_1_a_iii \
 dir_1/sub_dir_b/file_1_b_i \
 dir_1/sub_dir_b/file_1_b_ii \
 dir_2/sub_dir_y/file_2_y_i \
 dir_2/sub_dir_z/file_2_z_i

DIRS=$(dir $(FILES))

DIRS_UNIQUE=$(shell for DIR in $(DIRS); do echo $$DIR; done | sort | uniq)

all:
	@echo $(DIRS)
	@echo
	@(for DIR in $(DIRS); do echo $$DIR; done | sort | uniq)
	@echo
	@echo $(DIRS_UNIQUE)
Github repository about-Makefile, path: /dir
# vim: ft=make

VAR=foo bar baz

# Print some information with $(info …)
#
$(info )
$(info static text)
$(info $$VAR=$(VAR))

all:
	@true
Github repository about-Makefile, path: /info
# vim: ft=make

# 
# Apparently, ifeq is not allowed outside of a target.
#

var=foo


all:

  ifeq ($(var),foo)
	  @echo $(var) == foo
  else
  	@echo $(var) != foo
  endif

  ifeq ($(var),bar)
	  @echo $(var) == bar
  else
	  @echo $(var) != bar
  endif
Github repository about-Makefile, path: /ifeq
# vim: ft=make

#
#  make -f origin VAR=something
#

FRUIT=apple

$(info $(origin CC)       ) # default
$(info $(origin FRUIT)    ) # file
$(info $(origin VAR)      ) # command line
$(info $(origin HOME)     ) # environment
$(info $(origin FOOBARBAZ)) # undefined

all:
	@true
Github repository about-Makefile, path: /origin
# vim: ft=make

# 
# Apparently, ifdef is not allowed outside of a target.
#

FOO=defined
VAR_F=FOO
VAR_B=BAR

all:

  ifdef FOO
	  @echo FOO is defined
  else
	  @echo FOO is not defined
  endif

  ifdef BAR
	  @echo BAR is defined
  else
	  @echo BAR is not defined
  endif

  ifdef $(VAR_F)
	  @echo $(VAR_F) is defined
  else
	  @echo $(VAR_F) is not defined
  endif

  ifdef $(VAR_B)
	  @echo $(VAR_B) is defined
  else
	  @echo $(VAR_B) is not defined
  endif
Github repository about-Makefile, path: /ifdef

Turning each c files into an executable

If a directory contains three c files: foo.c, bar.c and baz.c, then they can be compiled into the three executables foo, bar and baz with the following simple make file:
all: foo bar baz

Functions

TODO: they're gone here.

TODO

Variables in make.
MinGW seems to name the make executable mingw32-make.exe.
Strawberry Perl seems to name it gmake.exe. It also comes with a dmake.exe...
gvmake

See also

Using the variable $(OS) to detect the operating system under which make is running.
AC_SUBST
automake.
make-targets: A script that shows the targets of a makefile.
phony targets
The GCC options -M and especially -MM can be used to create a copy-pastable dependency line from a C compilation unit.
nmake.exe

Links

The GNU Make Standard Library s a collection of functions implemented using native GNU Make functionality that provide list and string manipulation, integer arithmetic, associative arrays, stacks, and debugging facilities.
https://github.com/mbcrawfo/GenericMakefile

Index