Skip to content

Instantly share code, notes, and snippets.

@BimManager
Created May 25, 2019 10:04
Show Gist options
  • Save BimManager/3000595334acd49972b85df245f62ceb to your computer and use it in GitHub Desktop.
Save BimManager/3000595334acd49972b85df245f62ceb to your computer and use it in GitHub Desktop.
Syntax for Make scripts
# Simplified form of a rule
target1 target2 target3: prerequisite1 prerequisite2
command1
command2
command3
# Additional dependencies appended to target
vpath.o: vpath.c make.h config.h getopt.h gettext.h dep.h
vpath.o: filedef.h hash.h job.h commands.h variable.h vpath.h
# Make ’s wildcards are identical to the Bourne
# shell’s: ~ , * , ? , [...] , and [^...]
prog: *.c
$(CC) -o $@ $^
# .PHONY tells make that a target is not a real file
# In addition to marking a target as always out of date
.PHONY: clean
clean:
rm -f *.o lexer.c
# Standard phony targets
#
# all - Perform all tasks to build the application
# install - Create an installation of the application from the compiled binaries
# clean - Delete the binary files generated from sources
# distclean - Delete all the generated files that were not in the original source distribution
# TAGS - Create a tags table for use by editors
# info - Create GNU info files from their Texinfo sources
# check - Run any tests associated with this application
# Automatic Variables
#
# $@ - The filename representing the target
#
# $% - The filename element of an archive member specification
#
# $< - The filename of the first prerequisite
#
# $? - The names of all prerequisites that are newer than the target,
# separated by spaces
#
# $^ - The filenames of all the prerequisites, separated by spaces.
# This list has duplicate filenames removed since for most uses,
# such as compiling, copying, etc., duplicates are not wanted
#
# $+ - Similar to $^ , this is the names of all the prerequisites
# separated by spaces, except that $+ includes duplicates. This variable
# was created for specific situations such as arguments to linkers
# where duplicate values have meaning
#
# $* - The stem of the target filename. A stem is typically a filename
# without its suffix
#
# One variant returns only the directory portion of the value.
# This is indicated by appending a “D” to the symbol, $(@D) , $(<D) , etc.
# The other variant returns only the file portion of the value.
# This is indicated by appending an F to the symbol, $(@F) , $(<F) , etc.
# VPATH variable consists of a list of directories to search
VPATH = src
# The vpath directive is a more precise
# vpath pattern directory-list
vpath %.c src
vpath %.h include
# Pattern rules
%.o: %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
# %,v
# s%.o
# wrapper_%
# Static pattern rules - objs: pattern: prereq
$(OBJECTS): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
# The Implicit Rules Database
# make --print-data-base / make -p
# Special Targets
# The .PHONY target is the most common special target
#
# .INTERMEDIATE
# Prerequisites of this special target are treated as intermediate files.
# If make creates the file while updating another target, the file will
# be deleted automatically when make exits. If the file already exists when
# make considers updating the file, the file will not be deleted
#
# .SECONDARY
# Prerequisites of this special target are treated as intermediate files
# but are never automatically deleted. The most common use of .SECONDARY
# is to mark object files stored in libraries
#
# .PRECIOUS
# When make is interrupted during execution, it may delete the target
# file it is updating if the file was modified since make started. If you
# mark the file as precious, make will never delete the file if interrupted
#
# .DELETE_ON_ERROR
# This is sort of the opposite of .PRECIOUS
# When libraries appear as prerequisites, they can be referenced using
# either a standard filename or with the -l syntax
xpong: $(OBJECTS) -lX11 -lXaw
$(LINK) $^ -o $@
# The pattern for recognizing libraries from the -l format is stored in
# .LIBPATTERNS and can be customized for other library filename formats
# Double-Colon Rules
#
# Same target to be updated with different commands depending on which set
# of prerequisites are newer than the target
file-list:: generate-list-script
chmod +x $<
generate-list-script $(files) > file-list
file-list:: $(files)
generate-list-script $(files) > file-list
# To get the value of a variable:
# $(var), $letter, ${var}
# Macro
define create-jar
@echo Creating $@...
$(RM) $(TMP_JAR_DIR)
endef
# Call macro
$(UI_JAR): $(UI_CLASSES)
$(create-jar)
# Expansion of b
# a = b - Deferred
# a ?= b - Deferred
# a := b - Immediate
# a += b - Deferred or immediate
# Target-Specific Variables
gui.o: CPPFLAGS += -DUSE_NEW_MALLOC=1
gui.o: gui.h
$(COMPILE.c) $(OUTPUT_OPTION) $<
# The general syntax for target-specific variables is:
# target...: variable = value
# target...: variable := value
# target...: variable += value
# target...: variable ?= value
# Conditional and include Processing
#
# COMSPEC is defined only on Windows
ifdef COMSPEC
PATH_SEP := ;
EXE_EXT := .exe
else
PATH_SEP := :
EXE_EXT :=
endif
# The basic syntax of the conditional directive is:
#
# if-condition
# text if the condition is true
# endif
#
# or:
#
# if-condition
# text if the condition is true
# else
# text if the condition is false
# endif
#
# The if-condition can be one of:
#
# ifdef variable-name
# ifndef variable-name
# ifeq test
# ifneq test
#
# The variable-name should not be surrounded by $( )
# for the ifdef / ifndef test.
# Finally, the test can be expressed as either of:
# "a" "b"
# (a,b)
#
# Whitespace in conditional processing can be tricky to handle.
# For instance, when using the parenthesis form of the test,
# whitespace after the comma is ignored, but all other
# whitespace is significant:
ifeq (a, a)
# These are equal
endif
ifeq ( b, b )
# These are not equal - ' b' != 'b '
endif
# Personally, I stick with the quoted forms of equality:
ifeq "a" "a"
# These are equal
endif
ifeq 'b' 'b'
# So are these
endif
libGui.a: $(gui_objects)
$(AR) $(ARFLAGS) $@ $<
ifdef RANLIB
$(RANLIB) $@
endif
# Include directive
include definitions.mk
# Standard make Variables
# MAKE_VERSION
# This is the version number of GNU make
#
# CURDIR
# This variable contains the current working directory (cwd)
# of the executing make process
#
# MAKEFILE_LIST
# This variable contains a list of each file make has read including the default
# makefile and makefiles specified on the command line or through
# include directives
#
# MAKECMDGOALS
# The MAKECMDGOALS variable contains a list of all the targets specified
# on the command line for the current execution of make . It does not include
# command-line options or variable assignments
#
# .VARIABLES
# This contains a list of the names of all the variables defined in makefiles
# read so far, with the exception of target-specific variables. The variable
# is read-only and any assignment to it is ignored
# Functions
define parent
echo "parent has two parameters: $1, $2"
$(call child,$1)
endef
define child
echo "child has one parameter: $1"
echo "but child can also see parent's second parameter: $2!"
endef
scoping_issue:
@$(call parent,one,two)
# Field references in awk are written as $1 , $2 , etc. These would be
# treated as make variables if we did not quote them in some way.
# We can tell make to pass the $n reference to awk instead of expanding
# it itself by escaping the dollar sign in $n with an additional dollar
# sign, $$n . make will see the double dollar sign, collapse it to a
# single dollar sign and pass it to the subshell
# Built-in Functions
$(filter pattern...,text)
# The filter function treats text as a sequence of space separated words and
# returns a list of those words matching pattern
$(ui_library): $(filter ui/%.o,$(objects))
$(AR) $(ARFLAGS) $@ $^
$(filter-out pattern...,text)
# The filter-out function does the opposite of filter, selecting every
# word that does not match the pattern. Here we select all files
# that are not C headers
all_source := count_words.c counter.c lexer.l counter.h lexer.h
to_compile := $(filter-out %.h, $(all_source))
$(findstring string,text)
# This function looks for string in text. If the string is found,
# the function returns string; otherwise, it returns nothing
$(subst search-string,replace-string,text)
# This is a simple, nonwildcard, search and replace. One of its most common uses
# is to replace one suffix with another in a list of filenames:
sources := count_words.c counter.c lexer.c
objects := $(subst .c,.o,$(sources))
$(patsubst search-pattern , replace-pattern , text)
# This is the wildcard version of search and replace
strip-trailing-slash = $(patsubst %/,%,$(directory-path))
$(words text)
# This returns the number of words in text
$(word n,text)
# This returns the n th word in text
$(firstword text)
# This returns the first word in text
$(wordlist start,end,text)
# This returns the words in text from start to end, inclusive. As with the word
# function, the first word is numbered 1
$(sort list)
# The sort function sorts its list argument and removes duplicates
$(shell command)
# The shell function accepts a single argument that is expanded
# (like all arguments) and passed to a subshell for execution
$(wildcard pattern...)
# The wildcard function accepts a list of patterns and performs
# expansion on each one
sources := $(wildcard *.c *.h)
$(dir list...)
# The dir function returns the directory portion of each word in list
$(notdir name...)
# The notdir function returns the filename portion of a file path
$(suffix name...)
# The suffix function returns the suffix of each word in its argument
$(basename name...)
# The basename function is the complement of suffix
$(addsuffix suffix,name...)
# The addsuffix function appends the given suffix text to each word in name
$(addprefix prefix,name...)
# The addprefix function is the complement of addsuffix
$(join prefix-list,suffix-list)
# The join function is the complement of dir and notdir
$(if condition,then-part,else-part)
$(error text)
#The error function is used for printing fatal error messages
$(foreach variable,list,body)
# The foreach function provides a way to expand text repeatedly while
# substituting different values into each expansion
letters := $(foreach letter,a b c d,$(letter))
show-words:
# letters has $(words $(letters)) words: '$(letters)'
$(strip text)
# The strip function removes all leading and trailing whitespace from text and
# replaces all internal whitespace with a single space
$(origin variable)
# The origin function returns a string describing the origin of a variable
# The possible return values of origin are:
undefined
# The variable has never been defined
default
# The variable’s definition came from make ’s built-in database.
# If you alter the value of a built-in variable, origin returns the
# origin of the most recent definition
environment
# The variable’s definition came from the environment (and the
# --environment-overrides option is not turned on)
environment override
# The variable’s definition came from the environment (and the
# --environment-overrides option is turned on)
file
# The variable’s definition came from the makefile
command line
# The variable’s definition came from the command line
override
# The variable’s definition came from an override directive
automatic
# The variable is an automatic variable defined by make
$(warning text)
# The warning function is similar to the error function except that it does not
# cause make to exit
$(eval sources := foo.c bar.c)
# The eval function is completely different from the rest of the built-in
# functions. Its purpose is to feed text directly to the make parser
# Escapes:
.INTERMEDIATE: file_list
file_list:
for d in logic ui; \
do \
echo $$d/*.java; \
done > $@
$(config): $(config_template)
if [ ! -d $(dir $@) ]; \
then \
$(MKDIR) $(dir $@); \
else \
true; \
fi
$(M4) $^ > $@
# Command modifiers
@
# Do not echo the command. For historical compatibility, you can make your
# target a prerequisite of the special target .SILENT
QUIET = @
hairy_script:
$(QUIET) complex script
-
# The dash prefix indicates that errors in the command should be ignored by make
+
# The plus modifier tells make to execute the command even if the --just-print
# (or -n ) command-line option is given to make
# Shell
#
# When make needs to pass a command line to a subshell, it uses /bin/sh.
# You can change the shell by setting the make variable SHELL
# One such sacrifice is to explicitly set the SHELL variable to /usr/bin/bash
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment