# -*- makefile-gmake -*- # Tests simple: echo Simple test >simple uptodate: echo Not up to date >$@ target1 target2: echo $@ >$@ %.echo: echo $* >$@ first_dep: a.echo b.echo c.echo echo $< >$@ all_deps: a.echo b.echo c.echo echo $^ >$@ newer_dep: new_dep echo Updated newer_dep >$@ older_dep: old_dep echo Updated older_dep >$@ # Variables FOO = .foo %.bar: %$(FOO) perl -pe 'tr/a-z/A-Z/' $< > $@ $A.baz: $A.bar echo "Baz!" >$@ cat $< >>$@ echo "I said Baz!" >> $@ $A.$B.foo: echo b= $B a= $A >$@ XYZ := $(ABC) xyz DEF ?= $(ABC) ABC = abc vars%: echo ABC=$(ABC) DEF=$(DEF) XYZ=$(XYZ) >$@ VALUE = $(ABC) xyz value: echo '$(value VALUE)' >$@ hyphenated-var = This variable is hyphenated hyphenated_var: echo $(hyphenated-var) >$@ unbound_var: echo $(nonexistent_variable) >$@ DEPS := yorks.lancasters.foo starks.lannisters.foo multi_targets_from_var: $(DEPS) cat $(DEPS) >$@ S := hello S += world append_var: echo $S >$@ RECURSIVE_VAR1 = hello RECURSIVE_VAR2 = $(RECURSIVE_VAR1) RECURSIVE_VAR1 += there RECURSIVE_VAR2 += world append_recursive_var: echo $(RECURSIVE_VAR2) >$@ SIMPLE_VAR1 := hello SIMPLE_VAR2 := $(SIMPLE_VAR1) SIMPLE_VAR1 += there SIMPLE_VAR2 += world append_simple_var: echo $(SIMPLE_VAR2) >$@ # General syntax escape_dollar: echo $$ >$@ %_in_body: echo % vs $* >$@ silent: @echo silent >$@ one_line: ; echo Recipe on one line >$@ one_line_with_deps: one_line; cp $< $@ comment_in_rule: # comment inside rule echo First line >$@ # another comment inside rule # it can be more than one line echo Second line >>$@ comment_in_deps: realdep # commentdep cat $< >$@ realdep: echo This is a legit dep >$@ # biomake's output for split_recipe_lines is as the GNU Make documentation describes, # but not (in our experience) the way GNU Make actually behaves... # GNU Make 3.81 vs https://www.gnu.org/software/make/manual/html_node/Splitting-Recipe-Lines.html split_recipe_lines : ; @(echo 'hello \ world'; echo "hello \ world") >$@ split_target_lines: \ split_target_lines_dep1 \ split_target_lines_dep2 cat $^ >$@ split_target_lines_dep1 split_target_lines_dep2: echo $@ >$@ wdep1 wdep2: touch $@ wildcard_deps: wdep1 ../dir/* wdep2 echo $^ >$@ # Functions firstword: echo $(firstword $S) >$@ lastword: echo $(lastword $S) >$@ word2: echo $(word 2,$S) >$@ words: echo $(words $S) >$@ wordlist: echo $(wordlist 3,5,He who controls the spice controls the universe) >$@ # test a parenthetical variable nested inside a command FEAR = Fear is the mind killer var_in_command: echo $(wordlist 3,4,$(FEAR)) >$@ # various substitutions subst: echo $(subst bcd,xyz,abcdefg bcd) >$@ patsubst: echo $(patsubst %.c,%.o,a.c b.d e.c f.c) >$@ substref: echo $(FEAR:killer=thriller) >$@ substref_list: echo $(FEAR:r=RRR) >$@ # more text functions strip: echo $(strip this string has lots of redundant space) >$@ findstring1: echo $(findstring rabbit,fox cow rabbit duck) >$@ findstring2: echo $(findstring rabbit,fox cow duck) >$@ filter: echo $(filter %.c,rabbit.c fox.h cow.c duck.cpp) >$@ filter_out: echo $(filter-out %.c,rabbit.c fox.h cow.c duck.cpp) >$@ sort: echo $(sort rabbit cow duck fox duck elephant) >$@ dir: echo $(dir a/bc/def/g hij/k/l m/n/o/p/q) >$@ notdir: echo $(notdir a/bc/def/g hij/k/l m/n/o/p/q) >$@ basename: echo $(basename punk.rock classical.music thrash.metal) >$@ suffix: echo $(suffix punk.rock classical.music thrash.metal) >$@ addprefix: echo $(addprefix soap ,dish opera bar) >$@ addsuffix: echo $(addsuffix cake,fruit pan pat-a-) >$@ join: echo $(join inter super D,national star J) >$@ wildcard: echo $(wildcard ../dir/*) >$@ wildcard_nonexistent: echo $(wildcard ../dir/this_file_does_not_exist) >$@ abspath: echo $(abspath /usr/share/../lib) >$@ echo $(abspath /etc//hosts) >>$@ echo $(abspath /this/file/does/not/exist) >>$@ realpath: echo $(realpath /this/file/does/not/exist) >$@ FIRST_PERSON_SINGULAR_PRONOUN = i I_LOVE_PICKLES = $(wildcard ../dir/*) function_whose_args_are_both_expressions: echo $(filter-out $(FIRST_PERSON_SINGULAR_PRONOUN), $(notdir $(I_LOVE_PICKLES))) >$@ # computed vars x1 = y1 y1 = z a1 := $($(x1)) computed_var1: echo $(a1) >$@ x2 = y2 y2 = z2 z2 = u a2 := $($($(x2))) computed_var2: echo $(a2) >$@ x3 = $(y3) y3 = z3 z3 = Hello a3 := $($(x3)) computed_var3: echo $(a3) >$@ bar2lines = Bar define two-lines = echo foo >$@ echo $(bar2lines) >$@ endef test_at = echo hello >$@ test_at: $(test_at) two_lines: $(two-lines) split_lines = split \ over \ multiple \ lines split_lines: echo $(split_lines) >$@ FUNC = echo $1 is $2 call: $(call FUNC,chris,reekin) >$@ $(call FUNC,ian,tidy) >>$@ shell: echo '$(shell echo hello world)' >$@ shell_assign != echo hello there shell_assign: echo $(shell_assign) >$@ # advanced automatic variables subdir/target_file: echo $(@F) >$@ subdir/target_dir: echo $(@D) >$@ %_file.txt: echo $(*F) >$@ %_dir.txt: echo $(*D) >$@ dep_file: subdir/foo echo $($@ dep_dir: subdir/foo echo $($@ deps_file: subdir/foo subdir/bar/empty echo $(^F) >$@ deps_dir: subdir/foo subdir/bar/empty echo $(^D) >$@ # forced rebuild forced_rebuild_setup := $(shell touch forced_rebuild) forced_rebuild: FORCE echo test2 >$@ FORCE: echo wrong >forced_rebuild # more functions foreach: echo $(foreach thing,Life Death Tax,$(thing) is constant.) >$@ bad_function_syntax: echo $(non sense) >$@ if1: echo $(if xyz,abc,def) >$@ if2: echo $(if ,abc,def) >$@ if3: echo $(if xyz,abc) >$@ if4: echo $(if ,abc) >$@ or1: echo $(or abc,def,ghi) >$@ or2: echo $(or ,def,) >$@ or3: echo $(or ,,) >$@ and1: echo $(and abc,def,ghi) >$@ and2: echo $(and abc,,ghi) >$@ what_if: what_if_dep echo Updated what_if >$@ old_file_target: old_file_target_dep echo Updated old_file_target >$@ old_file_dep: old_file_dep_dep echo Updated old_file_dep >$@ # command-line options keep_going: echo Bravely, in the face of all odds >$@ stop_on_error1: echo Should not get here >$@ stop_on_error2: echo Should not get here either >$@ touch: echo Updated touch >$@ multi_arg: echo Updated multi_arg >$@ NON_EVAL_VAR=expected cmdline_eval%: echo Value of NON_EVAL_VAR is $(NON_EVAL_VAR) >$@ echo Value of CMDLINE_VAR is $(CMDLINE_VAR) >>$@ echo Value of EVAL_VAR is $(EVAL_VAR) >>$@ # arithmetic functions iota: echo $(iota 10) >$@ iota2: echo $(iota 3,6) >$@ add: echo $(add 10,1 2 3) >$@ multiply: echo $(multiply 3,2 4 6) >$@ divide: echo $(divide 2,1 3 8) >$@ iota_add_multiply: echo $(multiply 2,$(add 10,$(iota 3,6))) >$@ # alternate pattern rules to build a target %.type1: %.type2 cat $< >$@ echo building type1 from type2: $< >>$@ %.type1: %.type3 cat $< >$@ echo building type1 from type3: $< >>$@ %.type3: %.type4 cat $< >$@ echo building type3 from type4: $< >>$@ %.type4: %.type5 cat $< >$@ echo building type4 from type5: $< >>$@ altrules1.type4: echo Starting from type4 >$@ altrules2.type5: echo Starting from type5 >$@