/
gmakefile.test
381 lines (323 loc) · 14.7 KB
/
gmakefile.test
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
# -*- mode: makefile-gmake -*-
CONFIGDIR := config
# TESTSRCDIR is always relative to gmakefile.test
# This must be before includes
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
TESTSRCDIR := $(dir $(mkfile_path))src
include $(PERMON_SVM_DIR)/lib/permonsvm/conf/permonsvm_variables
TESTDIR ?= ./$(PETSC_ARCH)/tests
MODDIR := $(PETSC_DIR)/$(PETSC_ARCH)/include
TESTLOGTAPFILE ?= $(TESTDIR)/test_$(PETSC_ARCH)_tap.log
TESTLOGERRFILE ?= $(TESTDIR)/test_$(PETSC_ARCH)_err.log
EXAMPLESDIR := $(TESTSRCDIR)
pkgs := tutorials
petscconf := $(PETSC_DIR)/$(PETSC_ARCH)/include/petscconf.h
petscvariables := $(PETSC_DIR)/$(PETSC_ARCH)/lib/petsc/conf/petscvariables
generatedtest := $(TESTDIR)/testfiles
.SECONDEXPANSION: # to expand $$(@D)/.DIR
TESTFLAGS := # Initialize as simple variable
#workarround old cygwin versions
ifeq ($(PETSC_CYGWIN_BROKEN_PIPE),1)
ifeq ($(shell basename $(AR)),ar)
V ?=1
endif
endif
V ?= $(if $(findstring s,$(MAKEFLAGS)),0)
ifeq ($(V),) # Default
quiet_HELP := "Use \"$(MAKE) V=1\" to see verbose compile lines, \"$(MAKE) V=0\" to suppress.\n"
quiet = @printf $(quiet_HELP)$(eval quiet_HELP:=)" %10s %s\n" "$1$2" "$@"; $($1)
quiettest = @printf " %10s %s\n" "TEST" "$(@:$(TESTDIR)/counts/%.counts=%)";
else ifeq ($(V),0) # Suppress entire command
quiet = @$($1)
quiettest = @
TESTFLAGS += -o err_only
else # Show the full command line
quiet = $($1)
quiettest =
TESTFLAGS += -v
endif
ifeq ($(FORCE),1)
TESTFLAGS += -f # force test execution
endif
ifeq ($(VALGRIND),1)
TESTFLAGS += -V # Add valgrind to the flags
endif
ifeq ($(REPLACE),1)
TESTFLAGS += -m # Replace results by passing -m to petscdiff
endif
ifeq ($(OUTPUT),1)
TESTFLAGS += -o 'err_only' # Show only the errors on stdout
endif
ifeq ($(ALT),1)
TESTFLAGS += -M # Replace alt files by passing -M to petscdiff
endif
PRINTONLY ?= 0
ifeq ($(PRINTONLY),1)
TESTFLAGS += -p # Pass -p to petscdiff to print only command
endif
ifeq ($(DIFF_NUMBERS),1)
TESTFLAGS += -j # Pass -j to petscdiff to diff the actual numbers
endif
ifdef OPTIONS
TESTFLAGS += -a '$(OPTIONS)' # override arguments
endif
ifdef EXTRA_OPTIONS
TESTFLAGS += -e '$(EXTRA_OPTIONS)' # add extra arguments
endif
ifdef NP
TESTFLAGS += -n $(NP) # set number of processes
endif
# Override the default timeout that may be found at the top of config/petsc_harness.sh
# This must be an integer. It is given in seconds.
ifdef TIMEOUT
TESTFLAGS += -t $(TIMEOUT) # Override the default timeout
endif
PETSCCONFIGDIR ?= $(PETSC_DIR)/config
ifeq ($(wildcard $(PETSCCONFIGDIR)/gmakegentest.py),)
PETSCCONFIGDIR := $(PETSC_DIR)/share/petsc/examples/config
endif
$(generatedtest) : $(petscconf) $(petscvariables) $(PETSCCONFIGDIR)/gmakegentest.py $(TESTDIR)/.DIR | $$(@D)/.DIR
$(PYTHON) $(PETSCCONFIGDIR)/gmakegentest.py --petsc-dir=$(PETSC_DIR) --petsc-arch=$(PETSC_ARCH) --testdir=$(TESTDIR) --srcdir=$(TESTSRCDIR) --pkg-dir=$(PERMON_SVM_DIR) --pkg-name=permonsvm --pkg-pkgs=$(pkgs) --pkg-arch=$(PETSC_ARCH)
ifneq ($(filter-out clean check,$(MAKECMDGOALS:clean%=clean)),)
include $(generatedtest)
endif
ifeq ($(PETSC_LANGUAGE),CXXONLY)
cc_name := CXX
else
cc_name := CC
endif
PETSC_COMPILE.c = $(call quiet,$(cc_name)) -c $(PCC_FLAGS) $(CFLAGS) $(CCPPFLAGS) $(C_DEPFLAGS)
PETSC_COMPILE.cxx = $(call quiet,CXX) -c $(CXX_FLAGS) $(CFLAGS) $(CCPPFLAGS) $(CXX_DEPFLAGS)
PETSC_COMPILE.cu = $(call quiet,CUDAC) -c $(CUDAC_FLAGS) --compiler-options="$(PCC_FLAGS) $(CXXFLAGS) $(CCPPFLAGS)"
PETSC_GENDEPS.cu = $(call quiet,CUDAC,.dep) --generate-dependencies --output-directory=$(@D) $(CUDAC_FLAGS) --compiler-options="$(PCC_FLAGS) $(CXXFLAGS) $(CCPPFLAGS)"
PETSC_COMPILE.F = $(call quiet,FC) -c $(FC_FLAGS) $(FFLAGS) $(FCPPFLAGS) $(FC_DEPFLAGS)
PERMON_SVM_COMPILE.c = $(PETSC_COMPILE.c) $(PERMON_SVM_CC_INCLUDES)
PERMON_SVM_COMPILE.cxx = $(PETSC_COMPILE.cxx) $(PERMON_SVM_CC_INCLUDES)
testlangs := c cu cxx F F90
$(foreach lang, $(testlangs), $(eval \
testexe.$(lang) = $(foreach pkg, $(pkgs), $(testsrcs-$(pkg).$(lang):%.$(lang)=$(TESTDIR)/%))))
concattestlang = $(foreach lang, $(2), $(testsrcs-$(1).$(lang):%.$(lang)=$(TESTDIR)/%.o))
testsrcs.o := $(foreach pkg, $(pkgs), $(call concattestlang,$(pkg),$(testlangs)))
testsrcs-rel := $(foreach pkg, $(pkgs), $(foreach lang, $(testlangs), $(testsrcs-$(pkg).$(lang))))
testsrcs := $(foreach sfile, $(testsrcs-rel), $(TESTSRCDIR)/$(sfile))
# Refresh testfiles when sources change, but don't balk if the source file is nonexistent (deleted)
$(generatedtest) : $(testsrcs)
$(testsrcs) :
$(TESTDIR)/%.o : $(EXAMPLESDIR)/%.c | $$(@D)/.DIR
$(PERMON_SVM_COMPILE.c) $(abspath $<) -o $@
$(TESTDIR)/%.o : $(EXAMPLESDIR)/%.cxx | $$(@D)/.DIR
$(PERMON_SVM_COMPILE.cxx) $(abspath $<) -o $@
$(TESTDIR)/%.o : $(EXAMPLESDIR)/%.cu | $$(@D)/.DIR
$(PETSC_COMPILE.cu) $(abspath $<) -o $@ # Compile first so that if there is an error, it comes from a normal compile
@$(PETSC_GENDEPS.cu) $(abspath $<) -o $(@:%.o=%.d) # Generate the dependencies for later
# Test modules go in the same directory as the target *.o
TESTMODDIR = $(@D)
FCMOD = cd
$(TESTDIR)/%.o : $(EXAMPLESDIR)/%.F | $$(@D)/.DIR
ifeq ($(FC_MODULE_OUTPUT_FLAG),)
$(call quiet,FCMOD) $(TESTMODDIR) && $(FC) -c $(FC_FLAGS) $(FFLAGS) $(FCPPFLAGS) $(FC_DEPFLAGS) -I$(dir $<) $(abspath $<) -o $(abspath $@)
else
$(PETSC_COMPILE.F) -I$(dir $<) $(abspath $<) -o $@ $(FC_MODULE_OUTPUT_FLAG)$(TESTMODDIR) $(FC_MODULE_FLAG)$(TESTMODDIR)
endif
-@$(GFORTRAN_DEP_CLEANUP)
$(TESTDIR)/%.o : $(EXAMPLESDIR)/%.F90 | $$(@D)/.DIR
ifeq ($(FC_MODULE_OUTPUT_FLAG),)
$(call quiet,FCMOD) $(TESTMODDIR) && $(FC) -c $(FC_FLAGS) $(FFLAGS) $(FCPPFLAGS) $(FC_DEPFLAGS) -I$(dir $<) $(abspath $<) -o $(abspath $@)
else
$(PETSC_COMPILE.F) -I$(dir $<) $(abspath $<) -o $@ $(FC_MODULE_OUTPUT_FLAG)$(TESTMODDIR) $(FC_MODULE_FLAG)$(TESTMODDIR)
endif
-@$(GFORTRAN_DEP_CLEANUP)
# This is a hack to fix a broken gfortran.
define GFORTRAN_DEP_CLEANUP
if test -e "$(@:%.o=%.d)" && head -1 "$(@:%.o=%.d)" | grep -F -q -v : ; then\
echo "$(@): \\" > $(@:%.o=%.dtemp) ; \
tr '\n' '@' < $(@:%.o=%.d) | cut -d: -f2- | tr '@' '\n' >> $(@:%.o=%.dtemp) ; \
mv $(@:%.o=%.dtemp) $(@:%.o=%.d); \
fi
endef
PERMON_SVM_TEST_LIB = $(PERMON_SVM_LIB)
# Test executables
$(testexe.c) $(testexe.cu) : $(TESTDIR)/% : $(TESTDIR)/%.o $$^ $(libpermonall)
$(call quiet,CLINKER) -o $@ $^ $(PERMON_SVM_TEST_LIB)
$(testexe.cxx) : $(TESTDIR)/% : $(TESTDIR)/%.o $$^ $(libpermonall)
$(call quiet,CXXLINKER) -o $@ $^ $(PERMON_SVM_TEST_LIB)
# Testing convenience targets
.PHONY: test pre-clean
test: report_tests check-test-errors
pre-clean:
@$(RM) -rf $(TESTDIR)/counts $(TESTLOGTAPFILE) $(TESTLOGERRFILE)
@touch $(TESTLOGTAPFILE) $(TESTLOGERRFILE)
@echo "Using MAKEFLAGS:" ${MAKEFLAGS}
check-test-errors:
@grep '^not ok' $(TESTLOGTAPFILE) | grep -v 'Exceeded timeout' | tee $(TESTDIR)/allgtests-tap-err.log
@test ! -s $(TESTDIR)/allgtests-tap-err.log
.PHONY: $(foreach pkg, $(pkgs), test-$(pkg) $(foreach lang, $(testlangs), test-$(pkg).$(lang) test-rm-$(pkg).$(lang)))
testpkgs := $(foreach pkg, $(pkgs), test-$(pkg))
# Targets to run tests in test-$pkg.$lang and delete the executables, language by language
$(testpkgs) : test-% : $(foreach lang, $(testlangs), test-rm-%.$(lang))
# List of raw test run targets
alltesttargets := $(foreach tp, $(testpkgs), $(foreach lang, $(testlangs), $($(tp).$(lang))))
# Run targets
$(alltesttargets) : % : $(TESTDIR)/counts/%.counts
.PHONY: $(alltesttargets)
$(TESTDIR)/counts/%.counts :
$(quiettest) $< $(TESTFLAGS)
# Targets to run tests and remove executables, by package-lang pairs.
# Run the tests in each batch using recursive invocation of make because
# we need all of them to complete before removing the executables. Make
# doesn't guarantee an exploration order for the graph. Only recursive
# if there is something to be done.
alltest-rm := $(foreach pkg, $(pkgs), $(foreach lang, $(testlangs), test-rm-$(pkg).$(lang)))
$(alltest-rm) : test-rm-% : test-%
ifneq ($(NO_RM),1)
$(call quiet,RM) $(addprefix $(TESTDIR)/,$(basename $($(@:test-rm-%=testsrcs-%))))
endif
# Remove intermediate .o files
# This only removes the files at the end which is insufficient
#.INTERMEDIATE: $(testsrcs.o:%.o=%)
# all sources should get recompiled when petscvariables changes (i.e when configure is rerun or when petscvariables is manually edited.)
$(testsrcs.o) : $(petscvariables)
%/.DIR :
@mkdir -p $(@D)
@touch $@
.PRECIOUS: %/.DIR
.SUFFIXES: # Clear .SUFFIXES because we don't use implicit rules
.DELETE_ON_ERROR: # Delete likely-corrupt target file if rule fails
.PHONY: clean cleantest all
cleantest:
${RM} -r $(TESTDIR) $(generatedtest)
clean: cleantest
alltest.d := $(testsrcs.o:%.o=%.d)
# Tell make that alltest.d are all up to date. Without this, the include
# below has quadratic complexity, taking more than one second for a
# do-nothing build of PETSc (much worse for larger projects)
$(alltest.d) : ;
-include $(alltest.d)
# Tests can be generated by searching
# Percent is a wildcard (only one allowed):
# make -f gmakefile test search=sys%ex2
# To match internal substrings (matches *ex2*):
# make -f gmakefile test searchin=ex2
# Search and searchin can be combined:
# make -f gmakefile test search='sys%' searchin=ex2
# For args:
# make -f gmakefile test argsearch=cuda
# For general glob-style searching using python:
# NOTE: uses shell which is possibly slower and is possibly more brittle
# make -f gmakefile test globsearch='sys*ex2*'
ifdef search
TESTTARGETS := $(filter $(search),$(alltesttargets))
ifdef searchin
TESTTARGETS2 := $(foreach v,$(TESTTARGETS),$(if $(findstring $(searchin),$(v)),$(v)))
TESTTARGETS := $(TESTTARGETS2)
endif
else ifdef searchin
TESTTARGETS := $(foreach v,$(alltesttargets),$(if $(findstring $(searchin),$(v)),$(v)))
else ifdef argsearch
TESTTARGETS := $(foreach v,$(alltesttargets),$(if $(findstring $(argsearch),$($(v)_ARGS)),$(v)))
else ifdef globsearch
TESTTARGETS := $(shell $(PYTHON) -c"import sys,fnmatch,itertools; m=[fnmatch.filter(sys.argv[2].split(),p) for p in sys.argv[1].split()]; print(' '.join(list(itertools.chain.from_iterable(m))))" '$(globsearch)' '$(alltesttargets)')
else ifdef test-fail
TESTTARGETS := $(shell $(PETSC_ARCH)/tests/echofailures.sh)
else ifdef query
TESTTARGETS := $(shell $(PYTHON) config/query_tests.py '$(query)' '$(queryval)')
else # No filter - run them all, but delete the executables as we go
TESTTARGETS := $(testpkgs)
endif
.PHONY: report_tests print-test
print-test:
-@echo $(TESTTARGETS)
# Don't start running tests until starttime has completed
$(alltesttargets:%=$(TESTDIR)/counts/%.counts) : starttime
# Ensure that libpermon (if it is a prerequisite) has been built and clean the counts/logs before starting timer
starttime: pre-clean $(libpermonall)
@$(eval STARTTIME := $(shell date +%s))
report_tests: starttime $(TESTTARGETS)
@$(eval ENDTIME := $(shell date +%s))
-@if test ${PRINTONLY} -ne 1; then elapsed_time=$$(($(ENDTIME)- $(STARTTIME))) && \
$(PYTHON) $(PETSCCONFIGDIR)/report_tests.py -m $(MAKE) -d $(TESTDIR)/counts -t 5 -e $${elapsed_time};\
fi
check_output:
$(PYTHON) $(PETSCCONFIGDIR)/gmakegentest.py --petsc-dir=$(PETSC_DIR) --petsc-arch=$(PETSC_ARCH) --testdir=$(TESTDIR) --check-output
# Do not how how to invoke test from makefile
HASGMAKEFILE := $(filter gmakefile,$(MAKEFILE_LIST))
ifeq ($(HASGMAKEFILE),gmakefile)
helpdeps:=help-make help-targets
makefile="gmakefile"
other_help="To see full test help: make -f gmakefile.test help"
else
helpdeps:=help-make help-targets help-test
makefile="gmakefile.test"
other_help=""
endif
help: ${helpdeps}
-@echo "Above is from: ${helpdeps}"
-@echo "${other_help}"
help-make:
-@echo
-@echo "Basic build usage:"
-@echo " make -f ${makefile} <options>"
-@echo
-@echo "Options:"
-@echo " V=0 Very quiet builds"
-@echo " V=1 Verbose builds"
-@echo
help-targets:
-@echo "All makefile targets and their dependencies:"
-@grep ^[a-z] ${makefile} | grep : | grep -v =
-@echo
-@echo
help-test:
-@echo "Basic test usage:"
-@echo " make -f ${makefile} test <options>"
-@echo
-@echo "Options:"
-@echo " NO_RM=1 Do not remove the executables after running"
-@echo " REPLACE=1 Replace the output in PETSC_DIR source tree (-m to test scripts)"
-@echo " OUTPUT=1 Show only the errors on stdout"
-@echo " ALT=1 Replace 'alt' output in PETSC_DIR source tree (-M to test scripts)"
-@echo " DIFF_NUMBERS=1 Diff the numbers in the output (-j to test scripts and petscdiff)"
-@echo " VALGRIND=1 Execute the tests using valgrind (-V to test scripts)"
-@echo " NP=<num proc> Set a number of processors to pass to scripts."
-@echo " FORCE=1 Force SKIP or TODO tests to run"
-@echo " PRINTONLY=1 Print the command, but do not run. For loops print first command"
-@echo " TIMEOUT=<time> Test timeout limit in seconds (default in config/petsc_harness.sh)"
-@echo " TESTDIR='tests' Subdirectory where tests are run ($${PETSC_DIR}/$${PETSC_ARCH}/$${TESTDIR}"
-@echo " or $${PREFIX_DIR}/$${TESTDIR}"
-@echo " or $${PREFIX_DIR}/share/petsc/examples/$${TESTDIR})"
-@echo " TESTBASE='tests' Subdirectory where tests are run ($${PETSC_DIR}/$${PETSC_ARCH}/$${TESTDIR}"
-@echo " OPTIONS='<args>' Override options to scripts (-a to test scripts)"
-@echo " EXTRA_OPTIONS='<args>' Add options to scripts (-e to test scripts)"
-@echo
-@echo "Tests can be generated by searching:"
-@echo " Percent is a wildcard (only one allowed):"
-@echo " make -f ${makefile} test search=sys%ex2"
-@echo
-@echo " To match internal substrings (matches *ex2*):"
-@echo " make -f ${makefile} test searchin=ex2"
-@echo
-@echo " Search and searchin can be combined:"
-@echo " make -f ${makefile} test search='sys%' searchin=ex2"
-@echo
-@echo " To match patterns in the arguments:"
-@echo " make -f ${makefile} test argsearch=cuda"
-@echo
-@echo " For general glob-style searching using python:"
-@echo " NOTE: uses shell which is possibly slower and more brittle"
-@echo " make -f ${makefile} test globsearch='sys*ex2*'"
-@echo
-@echo " To re-run the last tests which failed:"
-@echo " make -f ${makefile} test test-fail='1'"
-@echo
-@echo " To search for fields from the original test definitions:"
-@echo " make -f ${makefile} test query='requires' queryval='*MPI_PROCESS_SHARED_MEMORY*'"
-@echo
-@echo " To see which targets match a given pattern (useful for doing a specific target):"
-@echo " make -f ${makefile} print-test search=sys%"
-@echo " which is equivalent to:"
-@echo " make -f ${makefile} print VAR=TESTTARGETS search='sys%'"
-@echo
-@echo " To build an executable, give full path to location:"
-@echo ' make -f ${makefile} $${PETSC_ARCH}/tests/sys/examples/tests/ex1'
-@echo " or make the test with NO_RM=1"
-@echo