[47064914] | 1 | # a demo is a name that can be make'd into an a.out,
|
---|
| 2 | # that designates a collection of compile units,
|
---|
| 3 | # each with a corresponding .src.c + .o file pair
|
---|
| 4 | SOURCES_IN_DEMO=$(wildcard $1/*.src.c)
|
---|
| 5 | OBJECTS_IN_DEMO=$(patsubst %.src.c,%.o,$(call SOURCES_IN_DEMO,$1))
|
---|
| 6 | ALL_OBJECTS=$(foreach demo,$(DEMOS),$(call OBJECTS_IN_DEMO,$(demo)))
|
---|
| 7 |
|
---|
| 8 | # each recursive subdir gives a demo
|
---|
| 9 | # a demo name may have slashes in middle, but not at start or end (foo, foo/bar)
|
---|
| 10 | DIRS_REC=$(shell find ./* -type d)
|
---|
| 11 | DEMOS_FROM_DIRS=$(patsubst ./%,%,$1)
|
---|
| 12 | DEMO_OF_FILE=$(patsubst %/,%,$(dir $1))
|
---|
| 13 | DEMOS=$(call DEMOS_FROM_DIRS,$(DIRS_REC))
|
---|
| 14 |
|
---|
| 15 | # demos of working code build under target `all`
|
---|
| 16 | # default assumption = demo is working
|
---|
| 17 | # demos named err-% recursively opt out
|
---|
| 18 | ERR_DIRPATS=err-%
|
---|
| 19 | DEMOS_NONERR=$(filter-out $(ERR_DIRPATS),$(DEMOS))
|
---|
| 20 | DEMO_EXECS_NONERR=$(DEMOS_NONERR:=/a.out)
|
---|
| 21 |
|
---|
| 22 | # a recourse is a designated sub-demo of an error case
|
---|
| 23 | # that is expected to build successfully
|
---|
| 24 | RECOURSE_DIRPATS=%/recourse-classic
|
---|
| 25 | DEMOS_RECOURSE=$(filter $(RECOURSE_DIRPATS),$(DEMOS))
|
---|
| 26 | DEMO_EXECS_RECOURSE=$(DEMOS_RECOURSE:=/a.out)
|
---|
| 27 |
|
---|
| 28 | # non-err and recourse demos try to build by default
|
---|
| 29 | ALL=$(DEMO_EXECS_NONERR) $(DEMO_EXECS_RECOURSE)
|
---|
| 30 |
|
---|
| 31 | # a shred is a *.c or *.h file generated from a *.src.c
|
---|
| 32 | SHRED_EXTS=.impl.c .defn.h .tdcl.h
|
---|
| 33 | SHREDS_OF_FILE=$(foreach st,$(SHRED_EXTS),$(1:=$(st)))
|
---|
| 34 | SHREDS_IN_DEMO=$(foreach src,$(call SOURCES_IN_DEMO,$1),$(call SHREDS_OF_FILE,$(src:.src.c=)))
|
---|
| 35 | SHREDS_IN_DEMO_OF_FILE=$(call SHREDS_IN_DEMO,$(call DEMO_OF_FILE,$1))
|
---|
| 36 |
|
---|
| 37 | # a 'classic' demo builds without shredding
|
---|
| 38 | CLASSIC_DIRPATS=%-classic
|
---|
| 39 | DEMOS_CLASSIC=$(filter $(CLASSIC_DIRPATS),$(DEMOS))
|
---|
| 40 | DEMOS_NONSHRED=$(DEMOS_CLASSIC)
|
---|
| 41 | OBJECTS_NONSHRED=$(foreach demo,$(DEMOS_NONSHRED),$(call OBJECTS_IN_DEMO,$(demo)))
|
---|
| 42 |
|
---|
| 43 | # everything else builds via shredding
|
---|
| 44 | DEMOS_SHRED=$(filter-out $(RECOURSE_DIRPATS),$(DEMOS))
|
---|
| 45 | OBJECTS_SHRED=$(foreach demo,$(DEMOS_SHRED),$(call OBJECTS_IN_DEMO,$(demo)))
|
---|
| 46 | ALL_SHREDS=$(foreach demo,$(DEMOS),$(call SHREDS_IN_DEMO,$(demo)))
|
---|
| 47 |
|
---|
| 48 |
|
---|
| 49 | CC=gcc
|
---|
| 50 | CPPP=./cfa-cppp
|
---|
| 51 | CQFLAGS=-Wall -Wextra -Werror
|
---|
| 52 |
|
---|
| 53 |
|
---|
| 54 | .SECONDEXPANSION: # enable dynamic prereqs from $$
|
---|
| 55 | .SUFFIXES: # disable traditional rules like make .o from .c by calling $(CC)
|
---|
| 56 |
|
---|
| 57 |
|
---|
| 58 | all: $(ALL)
|
---|
| 59 |
|
---|
| 60 | # troubleshooting, e.g. `make echo_DEMOS` runs `echo $(DEMOS)`
|
---|
| 61 | echo_% :
|
---|
| 62 | @echo '$($(@:echo_%=%))'
|
---|
| 63 |
|
---|
| 64 | #
|
---|
| 65 | # demo
|
---|
| 66 | #
|
---|
| 67 |
|
---|
| 68 | %/a.out : DEMO=$(@:/a.out=)
|
---|
| 69 | %/a.out : OBJECTS=$(call OBJECTS_IN_DEMO,$(DEMO))
|
---|
| 70 | %/a.out : $$(OBJECTS)
|
---|
| 71 | $(CC) $(OBJECTS) -o $@ $(CFLAGS) $(CQFLAGS)
|
---|
| 72 |
|
---|
| 73 | $(DEMOS) : $$@/a.out
|
---|
| 74 |
|
---|
| 75 | #
|
---|
| 76 | # object
|
---|
| 77 | #
|
---|
| 78 |
|
---|
| 79 | # object of regular, shredded, demo
|
---|
| 80 | # each CU depends on all other CUs' shreds
|
---|
| 81 | # conservative for rebuild (obviates -MMD), but helps do initial build
|
---|
| 82 | $(OBJECTS_SHRED) : CC_SRC=$(@:.o=.impl.c)
|
---|
| 83 | $(OBJECTS_SHRED) : SHREDS=$(call SHREDS_IN_DEMO_OF_FILE,$@)
|
---|
| 84 | $(OBJECTS_SHRED) : $$(SHREDS)
|
---|
| 85 |
|
---|
| 86 | # of nonshredded demo
|
---|
| 87 | $(OBJECTS_NONSHRED) : CC_SRC=$(@:.o=.src.c)
|
---|
| 88 | $(OBJECTS_NONSHRED) : CQFLAGS+= -MMD
|
---|
| 89 |
|
---|
| 90 | -include $(OBJECTS_NONSHRED:.o=.d)
|
---|
| 91 |
|
---|
| 92 | $(ALL_OBJECTS) :
|
---|
| 93 | $(CC) $(CC_SRC) -c -o $@ $(CFLAGS) $(CQFLAGS)
|
---|
| 94 |
|
---|
| 95 | #
|
---|
| 96 | # shred
|
---|
| 97 | #
|
---|
| 98 |
|
---|
| 99 | define SINGLE_SHREDEXT_RULE
|
---|
| 100 | %$1: %.src.c $(CPPP)
|
---|
| 101 | $(CPPP) $$@
|
---|
| 102 | endef
|
---|
| 103 |
|
---|
| 104 | $(foreach sfx,$(call SHREDS_OF_FILE,@),$(eval $(call SINGLE_SHREDEXT_RULE,$(sfx:@%=%))))
|
---|
| 105 |
|
---|
| 106 | #
|
---|
| 107 | # clean, misc
|
---|
| 108 | #
|
---|
| 109 |
|
---|
| 110 | # 2-line body is significant; \n ending 1st line is literal
|
---|
| 111 | define newline
|
---|
| 112 |
|
---|
| 113 |
|
---|
| 114 | endef
|
---|
| 115 |
|
---|
| 116 | CLEANPATS=$(call SHREDS_OF_FILE,*) *.o *.d a.out
|
---|
| 117 | clean:
|
---|
| 118 | $(foreach p,$(CLEANPATS),find . -name '$p' -type f -print -delete$(newline))
|
---|
| 119 |
|
---|
| 120 | .PRECIOUS: %.tdcl.h %.defn.h %.impl.c
|
---|
| 121 | .PHONY: all echo_% clean
|
---|