Introduction
gcc -c -Wall -ansi -I/pkg/chempak/include dat2csv.c
Lesson Example
- Automated laboratory equipment runs experiments in batches to create files like this:
Concentration: 0.0050
Yield: 11.41
Time: 2.5094
Concentration: 0.0055
Yield: 11.20
Time: 3.7440
Concentration: 0.0060
Yield: 10.90
- Currently there are only 20 - 30 of that .dat files being produced, but there may one day be many thousand
- Nigel needs to transform his .dat files to a CSV (Comma Separated Values) format using a tool called dat2csv
Hello, Make
hydroxyl_422.csv : hydroxyl_422.dat
dat2csv hydroxyl_422.dat > hydroxyl_422.csv
Note: The second line is indent with a tab, not 8 spaces. It's not pretty, and rather hard to debug if you forget, but that's just the way it is.
Nigel next runs the make -f hello.mk to run his build.
- Make sees that the csv file is dependent on the dat file
- Since the csv does not exist, make executes the dat2csv program with the given arguments

- A target
- It's prerequisite
- And an action -- this is what Make will do on your behalf in the rule
Targets
hydroxyl_422.csv : hydroxyl_422.dat
dat2csv hydroxyl_422.dat > hydroxyl_422.csv
methyl_422.csv : methyl_422.dat
dat2csv methyl_422.dat > methyl_422.csv
all : hydroxyl_422.csv methyl_422.csv
hydroxyl_422.csv : hydroxyl_422.dat
dat2csv hydroxyl_422.dat > hydroxyl_422.csv
methyl_422.csv : methyl_422.dat
dat2csv methyl_422.dat > methyl_422.csv
Other than all common phony targets are:
- clean - removes all files produced by the build; both final and temperary
- configure - do any necessary environment setup such as creating output directories and setting variables
- install - copy produced artifacts to another location
Dependencies

Automatic Variables
The automatic variables available to you in Make are:
- $@ - The rule's target
- $< - The rule's first prerequisite
- $? - All the out of date prerequisites
- $^ - All prerequisites
all : hydroxyl_422.csv methyl_422.csv
hydroxyl_422.csv : hydroxyl_422.dat
@dat2csv $< > $@
methyl_422.csv : methyl_422.dat
@dat2csv $< > $@
clean :
@rm -f *.csv
While he is at it he renames his file from hello.mk to Makefile which is the default name make expects for its files which means make all is what he now types to convert his files. Hurray for less typing!
Pattern Matching
Nigel's Makefile is getting increasingly powerful, but increasingly complex but it lets him convert his files by typing just two words in the console. But what if he added another compound to his experiment? hydroxyl_480.csv for example. He would have to edit the Makefile to create a new rule.
He can however avoid this by using Make's pattern matching capabilities. Based upon the fact that most project manipulate similar types of files in a similar manner, Make has a single wildcard, %, which matches the stem portion of a file.
all : hydroxyl_422.csv methyl_422.csv hydroxyl_480.csv
%.csv : %.dat
dat2csv $< > $@
clean :
rm -f *.csv
Here we see a target that will match all csv files, and which depends on all the dat files.
Somethings to note here are:
- We have sacrificed another bit of clarity (individual rule) for power (a more powerful single rule)
- Nigel still has to add new csv files to the all rule, but that is easier than writing a whole new rule
- When using pattern matching, you must use automatic variables in the action. This is because Make does not know the actual name of either the target or prerequisite files until runtime.
More Dependencies
all : hydroxyl_all.csv methyl_all.csvNow when Nigel does a make all,
%_all.csv : %_422.csv %_480.csv
summarize $^ > $@
%.csv : %.dat
dat2csv $< > $@
clean :
@rm -f *.csv
- the %_all.csv rule is checked for any dependencies
- the %.cvs rule is triggered to run the dat2csv file and create new csv files
- the %_all.csv action runs the summarize command producing both hydroxyl_all.csv and methyl_all.csv
- it then deletes all the csv files it created while producing the ones asked for (in this case hydroxyl_422.csv, methyl_422.csv and hydroxyl_480.csv)
Macros
INPUT_DIR = /lab/gamma2100
OUTPUT_DIR = /tmp
all : ${OUTPUT_DIR}/hydroxyl_all.csv ${OUTPUT_DIR}/methyl_all.csv
${OUTPUT_DIR}/%_all.csv : ${OUTPUT_DIR}/%_422.csv ${OUTPUT_DIR}/%_480.csv
@summarize $^ > $@
${OUTPUT_DIR}/%.csv : ${INPUT_DIR}/%.dat
@dat2csv $< > $@
clean :
@rm -f *.csv
- To set a value, you assign it with an =
- To access a value, you reference the variable with a $ and put {} around it. If you forget the {}, you will be accessing $O followed by the characters UTPUT_DIR after it instead of ${OUTPUT_DIR}
- By convention, macro names are in all uppercase
Passing Values to Make
Functions
OUTPUT_DIR = /tmp
CHEMICALS = hydroxyl methyl
SUMMARIES = $(addprefix ${OUTPUT_DIR}/,$(addsuffix _all.csv,${CHEMICALS}))
all : ${SUMMARIES}
${OUTPUT_DIR}/%_all.csv : ${OUTPUT_DIR}/%_422.csv ${OUTPUT_DIR}/%_480.csv
@summarize $^ > $@
${OUTPUT_DIR}/%.csv : ${INPUT_DIR}/%.dat
@dat2csv $< > $@
clean :
@rm -f *.csv
- $(addprefix prefix,filenames) - Add a prefix to each filename in a list
- $(addsuffix suffix,filenames) - Add a suffix to each filename in a list
- $(dir filenames) - Extract the directory name portion of each filename in a list
- $(filter pattern,text) - Keep words in text that match pattern
- $(filter-out pattern,text) - Keep words in text that don't match pattern
- $(patsubst pattern,replacement,text) - Replace everything that matches pattern in text
- $(sort text) - Sort the words in text, removing duplicates
- $(strip text) - Remove leading and trailing whitespace from text
- $(subst from,to,text) - Replace from with to in text
- $(wildcard pattern) - Create a list of filenames that match a pattern
Summary
Regardless of the system though, the principles remain the same
- Automate repetitive tasks
- Remove duplication within your Makefile, and
- Build you Makefile incrementally from least to greatest complexity