1
0
mirror of https://github.com/adambard/learnxinyminutes-docs.git synced 2025-08-12 09:44:24 +02:00

tiny white space changes

This commit is contained in:
robochat
2015-09-21 14:06:38 +00:00
parent 1079fe87ac
commit 55e22c0a8c

View File

@@ -1,243 +1,243 @@
--- ---
language: make language: make
contributors: contributors:
- ["Robert Steed", "https://github.com/robochat"] - ["Robert Steed", "https://github.com/robochat"]
filename: Makefile filename: Makefile
--- ---
A Makefile defines a graph of rules for creating a target (or targets). A Makefile defines a graph of rules for creating a target (or targets).
Its purpose is to do the minimum amount of work needed to update a Its purpose is to do the minimum amount of work needed to update a
target to the most recent version of the source. Famously written over a target to the most recent version of the source. Famously written over a
weekend by Stuart Feldman in 1976, it is still widely used (particularly weekend by Stuart Feldman in 1976, it is still widely used (particularly
on Unix) despite many competitors and criticisms. on Unix) despite many competitors and criticisms.
There are many varieties of make in existance, this article assumes that There are many varieties of make in existance, this article assumes that
we are using GNU make which is the standard on Linux. we are using GNU make which is the standard on Linux.
```make ```make
# Comments can be written like this. # Comments can be written like this.
# Files should be named Makefile and then be can run as `make <target>`. # Files should be named Makefile and then be can run as `make <target>`.
# Otherwise we use `make -f "filename" <target>`. # Otherwise we use `make -f "filename" <target>`.
# Warning - only use TABS to indent in Makefiles, never spaces! # Warning - only use TABS to indent in Makefiles, never spaces!
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Basics # Basics
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# A rule - this rule will only run if file0.txt doesn't exist. # A rule - this rule will only run if file0.txt doesn't exist.
file0.txt: file0.txt:
echo "foo" > file0.txt echo "foo" > file0.txt
# Even comments in these 'recipe' sections get passed to the shell. # Even comments in these 'recipe' sections get passed to the shell.
# Try `make file0.txt` or simply `make` - first rule is the default. # Try `make file0.txt` or simply `make` - first rule is the default.
# This rule will only run if file0.txt is newer than file1.txt. # This rule will only run if file0.txt is newer than file1.txt.
file1.txt: file0.txt file1.txt: file0.txt
cat file0.txt > file1.txt cat file0.txt > file1.txt
# use the same quoting rules as in the shell. # use the same quoting rules as in the shell.
@cat file0.txt >> file1.txt @cat file0.txt >> file1.txt
# @ stops the command from being echoed to stdout. # @ stops the command from being echoed to stdout.
-@echo 'hello' -@echo 'hello'
# - means that make will keep going in the case of an error. # - means that make will keep going in the case of an error.
# Try `make file1.txt` on the commandline. # Try `make file1.txt` on the commandline.
# A rule can have multiple targets and multiple prerequisites # A rule can have multiple targets and multiple prerequisites
file2.txt file3.txt: file0.txt file1.txt file2.txt file3.txt: file0.txt file1.txt
touch file2.txt touch file2.txt
touch file3.txt touch file3.txt
# Make will complain about multiple recipes for the same rule. Empty # Make will complain about multiple recipes for the same rule. Empty
# recipes don't count though and can be used to add new dependencies. # recipes don't count though and can be used to add new dependencies.
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Phony Targets # Phony Targets
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# A phony target. Any target that isn't a file. # A phony target. Any target that isn't a file.
# It will never be up to date so make will always try to run it. # It will never be up to date so make will always try to run it.
all: maker process all: maker process
# We can declare things out of order. # We can declare things out of order.
maker: maker:
touch ex0.txt ex1.txt touch ex0.txt ex1.txt
# Can avoid phony rules breaking when a real file has the same name by # Can avoid phony rules breaking when a real file has the same name by
.PHONY: all maker process .PHONY: all maker process
# This is a special target. There are several others. # This is a special target. There are several others.
# A rule with a dependency on a phony target will always run # A rule with a dependency on a phony target will always run
ex0.txt ex1.txt: maker ex0.txt ex1.txt: maker
# Common phony targets are: all make clean install ... # Common phony targets are: all make clean install ...
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Automatic Variables & Wildcards # Automatic Variables & Wildcards
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
process: file*.txt #using a wildcard to match filenames process: file*.txt #using a wildcard to match filenames
@echo $^ # $^ is a variable containing the list of prerequisites @echo $^ # $^ is a variable containing the list of prerequisites
@echo $@ # prints the target name @echo $@ # prints the target name
#(for multiple target rules, $@ is whichever caused the rule to run) #(for multiple target rules, $@ is whichever caused the rule to run)
@echo $< # the first prerequisite listed @echo $< # the first prerequisite listed
@echo $? # only the dependencies that are out of date @echo $? # only the dependencies that are out of date
@echo $+ # all dependencies including duplicates (unlike normal) @echo $+ # all dependencies including duplicates (unlike normal)
#@echo $| # all of the 'order only' prerequisites #@echo $| # all of the 'order only' prerequisites
# Even if we split up the rule dependency definitions, $^ will find them # Even if we split up the rule dependency definitions, $^ will find them
process: ex1.txt file0.txt process: ex1.txt file0.txt
# ex1.txt will be found but file0.txt will be deduplicated. # ex1.txt will be found but file0.txt will be deduplicated.
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Patterns # Patterns
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Can teach make how to convert certain files into other files. # Can teach make how to convert certain files into other files.
%.png: %.svg %.png: %.svg
inkscape --export-png %.svg inkscape --export-png %.svg
# Pattern rules will only do anything if make decides to create the \ # Pattern rules will only do anything if make decides to create the \
target. target.
# Directory paths are normally ignored when matching pattern rules. But # Directory paths are normally ignored when matching pattern rules. But
# make will try to use the most appropriate rule available. # make will try to use the most appropriate rule available.
small/%.png: %.svg small/%.png: %.svg
inkscape --export-png --export-dpi 30 %.svg inkscape --export-png --export-dpi 30 %.svg
# make will use the last version for a pattern rule that it finds. # make will use the last version for a pattern rule that it finds.
%.png: %.svg %.png: %.svg
@echo this rule is chosen @echo this rule is chosen
# However make will use the first pattern rule that can make the target # However make will use the first pattern rule that can make the target
%.png: %.ps %.png: %.ps
@echo this rule is not chosen if %.svg and %.ps are both present @echo this rule is not chosen if %.svg and %.ps are both present
# make already has some pattern rules built-in. For instance, it knows # make already has some pattern rules built-in. For instance, it knows
# how to turn *.c files into *.o files. # how to turn *.c files into *.o files.
# Older makefiles might use suffix rules instead of pattern rules # Older makefiles might use suffix rules instead of pattern rules
.png.ps: .png.ps:
@echo this rule is similar to a pattern rule. @echo this rule is similar to a pattern rule.
# Tell make about the suffix rule # Tell make about the suffix rule
.SUFFIXES: .png .SUFFIXES: .png
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Variables # Variables
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# aka. macros # aka. macros
# Variables are basically all string types # Variables are basically all string types
name = Ted name = Ted
name2="Sarah" name2="Sarah"
echo: echo:
@echo $(name) @echo $(name)
@echo ${name2} @echo ${name2}
@echo $name # This won't work, treated as $(n)ame. @echo $name # This won't work, treated as $(n)ame.
@echo $(name3) # Unknown variables are treated as empty strings. @echo $(name3) # Unknown variables are treated as empty strings.
# There are 4 places to set variables. # There are 4 places to set variables.
# In order of priority from highest to lowest: # In order of priority from highest to lowest:
# 1: commandline arguments # 1: commandline arguments
# 2: Makefile # 2: Makefile
# 3: shell enviroment variables - make imports these automatically. # 3: shell enviroment variables - make imports these automatically.
# 4: make has some predefined variables # 4: make has some predefined variables
name4 ?= Jean name4 ?= Jean
# Only set the variable if enviroment variable is not already defined. # Only set the variable if enviroment variable is not already defined.
override name5 = David override name5 = David
# Stops commandline arguments from changing this variable. # Stops commandline arguments from changing this variable.
name4 +=grey name4 +=grey
# Append values to variable (includes a space). # Append values to variable (includes a space).
# Pattern-specific variable values (GNU extension). # Pattern-specific variable values (GNU extension).
echo: name2 = Sara # True within the matching rule echo: name2 = Sara # True within the matching rule
# and also within its remade recursive dependencies # and also within its remade recursive dependencies
# (except it can break when your graph gets too complicated!) # (except it can break when your graph gets too complicated!)
# Some variables defined automatically by make. # Some variables defined automatically by make.
echo_inbuilt: echo_inbuilt:
echo $(CC) echo $(CC)
echo ${CXX)} echo ${CXX)}
echo $(FC) echo $(FC)
echo ${CFLAGS)} echo ${CFLAGS)}
echo $(CPPFLAGS) echo $(CPPFLAGS)
echo ${CXXFLAGS} echo ${CXXFLAGS}
echo $(LDFLAGS) echo $(LDFLAGS)
echo ${LDLIBS} echo ${LDLIBS}
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Variables 2 # Variables 2
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# The first type of variables are evaluated each time they are used. # The first type of variables are evaluated each time they are used.
# This can be expensive, so a second type of variable exists which is # This can be expensive, so a second type of variable exists which is
# only evaluated once. (This is a GNU make extension) # only evaluated once. (This is a GNU make extension)
var := hello var := hello
var2 ::= $(var) hello var2 ::= $(var) hello
#:= and ::= are equivalent. #:= and ::= are equivalent.
# These variables are evaluated procedurely (in the order that they # These variables are evaluated procedurely (in the order that they
# appear), thus breaking with the rest of the language ! # appear), thus breaking with the rest of the language !
# This doesn't work # This doesn't work
var3 ::= $(var4) and good luck var3 ::= $(var4) and good luck
var4 ::= good night var4 ::= good night
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Functions # Functions
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# make has lots of functions available. # make has lots of functions available.
sourcefiles = $(wildcard *.c */*.c) sourcefiles = $(wildcard *.c */*.c)
objectfiles = $(patsubst %.c,%.o,$(sourcefiles)) objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
# Format is $(func arg0,arg1,arg2...) # Format is $(func arg0,arg1,arg2...)
# Some examples # Some examples
ls: * src/* ls: * src/*
@echo $(filter %.txt, $^) @echo $(filter %.txt, $^)
@echo $(notdir $^) @echo $(notdir $^)
@echo $(join $(dir $^),$(notdir $^)) @echo $(join $(dir $^),$(notdir $^))
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Directives # Directives
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Include other makefiles, useful for platform specific code # Include other makefiles, useful for platform specific code
include foo.mk include foo.mk
sport = tennis sport = tennis
# Conditional compilation # Conditional compilation
report: report:
ifeq ($(sport),tennis) ifeq ($(sport),tennis)
@echo 'game, set, match' @echo 'game, set, match'
else else
@echo 'They think it's all over; it is now' @echo 'They think it's all over; it is now'
endif endif
# There are also ifneq, ifdef, ifndef # There are also ifneq, ifdef, ifndef
foo = true foo = true
ifdef $(foo) ifdef $(foo)
bar = 'hello' bar = 'hello'
endif endif
``` ```
### More Resources ### More Resources
+ [gnu make documentation](https://www.gnu.org/software/make/manual/) + [gnu make documentation](https://www.gnu.org/software/make/manual/)
+ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/) + [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
+ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html) + learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)