Some additional common targets are included in most Makefiles, such as "install" to install the binaries, libraries, and documentation, and "clean" to clean up files generated by the Makefile. These targets are not actual files and usually have no associated source, and are only executed if specified as a command line argument to make. Note that make builds the first target it finds in the Makefile by default, but if we provide the name of a target as a command line argument, it builds only that target instead.
To ensure that they behave properly even if a file exists with
the same name as the target, they should be marked as phony
by listing them as sources to the .PHONY
target.
Otherwise, if there happens to be a file called "install" or
"clean" in the directory, its time stamp will determine
whether the install or clean targets actually run.
# Values that the user cannot override BIN = myprog OBJS = myprog.o math.o # Set only if the user (or package manager) has not provided a value # -Wall: Issue all possible compiler warnings # -g: Compile with debug info to help locate crashes, etc. CC ?= cc CFLAGS ?= -Wall -O -g LD = ${CC} LDFLAGS += -lm # Defaults for commands that may be provided by the package manager MKDIR ?= mkdir INSTALL ?= install RM ?= rm # Most build systems should perform a staged install (install to a # temporary location indicated by ${DESTDIR}) rather than install # directly to the final destination, such as /usr/local. The package # manager can then check the staged install under ${DESTDIR} for # problems before copying to the final target. # Defaults for paths that may be provided by the package manager. # This will install under ./stage/usr/local unless the user or package # manager provides a different location. DESTDIR ?= ./stage PREFIX ?= /usr/local ${BIN}: ${OBJS} ${LD} -o ${BIN} ${OBJS} ${LDFLAGS} myprog.o: myprog.c Makefile ${CC} -c ${CFLAGS} myprog.c math.o: math.c ${CC} -c ${CFLAGS} math.c .PHONY: install clean install: ${MKDIR} -p ${DESTDIR}${PREFIX}/bin ${INSTALL} -c -m 0755 ${BIN} ${DESTDIR}${PREFIX}/bin clean: ${RM} -f ${BIN} *.o
shell-prompt: make install cc -c myprog.c cc -c math.c cc -o myprog myprog.o math.o mkdir -p ./stage/usr/local/bin install -c -m 0755 myprog ./stage/usr/local/bin shell-prompt: make clean rm -f myprog *.o
PREFIX
is a standard make
variable that indicates the common parent directory for all
installed files. Executables (binaries) and scripts are
typically installed in ${PREFIX}/bin
,
libraries in ${PREFIX}/lib
, header files in
${PREFIX}/include/project-name
, and data
files in ${PREFIX}/share/project-name
.
Some projects might also install auxiliary programs or scripts
not meant to be run directly by the user. These typically go under
${PREFIX}/libexec/project-name
. Using
a project-name
subdirectory minimizes
collisions, where multiple projects install
files with the same name. For example, several FreeBSD ports
install files called version.h
, but there
is no collision since they install them under their own directories:
/usr/local/include/alsa/version.h /usr/local/include/assimp/version.h /usr/local/include/bash/version.h
DESTDIR
is another standard variable that was
created to protect systems against install collisions. We do
not use subdirectories under bin
, and
occasionally two projects will install a program or script by
the same name. For example, the
open source projects splay and
mp3blaster both install a
program called splay. Poorly designed Makefiles or other build systems
may not check for collisions, and will simply clobber (overwrite)
files previous installed by another project. Most package
managers now require that the project install target use
DESTDIR
, so that the package manager can safely
perform a staged install under a temporary directory, and then
use its own safe methods to copy the installed files to their
final destination, while watching for collisions. A staged
installation also allows the package manager to check for
proper permissions and verify that the installation conforms to
filesystem
hierarchy standards. Makefiles do not need to set
DESTDIR
, but they should prefix all install
destinations with it.
We do not need a '/' between DESTDIR
and
PREFIX
, since PREFIX
should
be an absolute path name, which already begins with one.
# Wrong ${MKDIR} -p ${DESTDIR}/${PREFIX}/bin ${INSTALL} -c -m 0755 ${BIN} ${DESTDIR}/${PREFIX}/bin # Right ${MKDIR} -p ${DESTDIR}${PREFIX}/bin ${INSTALL} -c -m 0755 ${BIN} ${DESTDIR}${PREFIX}/bin
Which target in a makefile is checked first, if no target is specified in the make command?
How do we ensure that the install target runs when specified, even if there is a file called "install" in the directory?