-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathCPEPP.mak
More file actions
167 lines (110 loc) · 3.91 KB
/
CPEPP.mak
File metadata and controls
167 lines (110 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# CPE Problem Preparation v1.0
# GitHub: https://github.com/yipo/cpe-pp
# Author: Yi-Pu Guo (YiPo)
# License: MIT
check-all:
# The default target.
# To check all the things needed to be checked.
# Use the `check' function to add tasks in.
VER ?= a b
# The suffixes indicating different versions of i/o files.
# There are usually 2 versions (a and b), and more versions are also allowed.
# An empty $(VER) means there is only one version
# (in this case, we don't have to add any suffix to i/o files).
define \n
endef
# The newline character.
DIFF ?= diff
ifeq ($(findstring Win,$(OS)),)
fix_path = $1
else
fix_path = $(subst /,\,$1)
endif
# For Windows compatibility.
# The `auto_detect' command
# ---
# Instead of specifying the `check' function call one by one,
# `auto_detect' command find all the problems and the corresponding authors
# of each problem, then call the `check' function automatically.
ad_codes = $(notdir $(basename $(wildcard $(addprefix code/$1*.,c cpp java))))
ad_problems = $(sort $(foreach i,$(ad_codes),$(firstword $(subst _, ,$i))))
ad_authors = $(foreach i,$(call ad_codes,$1),$(lastword $(subst _, ,$i)))
auto_detect = $(foreach problem,$(ad_problems),\
$(call check,$(problem),$(call ad_authors,$(problem))))
# The `check' function
# ---
# For each version of i/o of one problem,
# check whether all the output files are the same.
# - Syntax:
# $(call check,<problem>,<author-list>)
# <author-list> = [<author>...]
# - Result: (for each version <ver>)
# check-all: diff-<problem><ver>
# diff-<problem><ver>: io/<problem><ver>.out \
# <problem>_<author><ver>.out... [tk/<problem><ver>.out]
# <problem>_<author><ver>.out...: <problem><ver>.in
vpath %.in io
vpath %.out io
# Where to find the i/o files.
define check_rule
check-all: diff-$1$2
diff-$1$2: $1$2.out $(foreach i,$3,$1_$i$2.out) $$(wildcard tk/$1$2.*)
$(foreach i,$3,$1_$i$2.out): $1$2.in
endef
# $1: <problem>, $2: <#ver>, $3: <author-list>
# The output file of toolkit presents, only when the file exist.
# Using 2 dollar signs before the `wildcard' function
# to avoid the file name becoming a comment.
# A `*' is required in the argument of wildcard function on Windows.
# Since, any filename extension is OK for output files of toolkit now.
# Using .out or .txt will be fine.
check = $(if $(VER), \
$(foreach ver,$(VER), \
$(eval $(call check_rule,$1,\\\#$(ver),$2))),\
$(eval $(call check_rule,$1,,$2)))
# The `diff-%' rule
# ---
# Compare the first file (in prerequisites list) with the others by `diff'.
diff-%:
@echo [$*]
$(foreach i,$(call except_first,$^),\
-$(DIFF) $(call fix_path,$(firstword $^) $i)$(\n))
except_first = $(wordlist 2,$(words $1),$1)
# The rules of generating .out files
# ---
define fout_rule
%$1.out: %.exe
> $$@ < $$(word 2,$$^) $(call fix_path,./"$$<")
%$1.out: %.class
> $$@ < $$(word 2,$$^) java $$*
endef
# There are 2 ways to generate an output file.
# $1: the version suffix (with `#') which can be empty.
# The file extension `.exe' is needed to generate the .out file
# via 2 implicit rules from .c/.cpp source code.
$(if $(VER), \
$(foreach ver,$(VER), \
$(eval $(call fout_rule,\#$(ver)))),\
$(eval $(call fout_rule,)))
# Generate the `fout_rule's for each version of i/o.
# The rules of generating .exe and .class
# ---
vpath %.c code
vpath %.cpp code
vpath %.java code
# Where to find the source codes.
.SECONDARY:
# Avoid the intermediate files being killed after making.
%.exe: %.c
$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@
%.exe: %.cpp
$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@
# These 2 commands are the same as the built-in rules from `make -p'.
%.class: %.java
javac -encoding utf-8 -d . $<
# There is no built-in rule for java source codes so we write our own.
# Use `-d .' to put the .class at current directory not at code/.
# clean
# ---
clean:
$(RM) *.out *.exe *.class