-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmakefile.test
More file actions
280 lines (231 loc) · 10.6 KB
/
Copy pathmakefile.test
File metadata and controls
280 lines (231 loc) · 10.6 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
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
# -*- mode: makefile-gmake -*-
ifneq ($(PETSC_ARCH),)
CONFIGDIR := $(PETSC_DIR)/config
else
CONFIGDIR := $(PETSC_DIR)/share/petsc/examples/config
endif
# TESTSRCDIR is always relative to makefile.test
# This must be before includes
mkfile_path := $(abspath $(MAKEFILE_LIST))
TESTSRCDIR := $(dir $(abspath $(firstword $(MAKEFILE_LIST))))src
include $(PETSC_DIR)/$(PETSC_ARCH)/lib/petsc/conf/petscvariables
include $(PETSC_DIR)/lib/petsc/conf/variables
include $(PETSCOPT_DIR)/lib/petscopt/conf/testvariables
TESTDIR := ./$(PETSCOPT_ARCH)/tests
MODDIR := $(PETSC_DIR)/$(PETSC_ARCH)/include
# this is hardcoded inside ${PETSC_DIR}/config/example_template.py
TESTLOGFILE := $(TESTDIR)/examples_$(PETSCOPT_ARCH).log
EXAMPLESDIR := $(TESTSRCDIR)
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 = @
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 ($(ALT),1)
TESTFLAGS += -M # Replace alt files by passing -M to petscdiff
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
spkgs := ts,tao,mfemopt
pkgs := ts tao mfemopt
testlangs := c cpp
$(generatedtest) : $(generated) $(petscconf) $(petscvariables) $(CONFIGDIR)/gmakegentest.py $(TESTDIR)/.DIR | $$(@D)/.DIR
$(PYTHON) $(CONFIGDIR)/gmakegentest.py --petsc-dir=$(PETSC_DIR) --petsc-arch=$(PETSC_ARCH) --testdir=$(TESTDIR) --srcdir=$(EXAMPLESDIR) --pkg-dir=$(PETSCOPT_DIR) --pkg-name=petscopt --pkg-arch=$(PETSCOPT_ARCH) --pkg-pkgs=$(spkgs)
-include $(generatedtest)
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.cpp = $(call quiet,CXX) -c $(CXX_FLAGS) $(CXXFLAGS) $(CXXCPPFLAGS) $(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)
$(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
$(PETSC_COMPILE.c) $(abspath $<) -o $@
$(TESTDIR)/%.o : $(EXAMPLESDIR)/%.cpp | $$(@D)/.DIR
$(PETSC_COMPILE.cpp) $(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)" | fgrep -q -v : ; then\
echo "$(@): \\" > $(@:%.o=%.dtemp) ; \
tr '\n' '@' < $(@:%.o=%.d) | cut -d: -f2- | tr '@' '\n' >> $(@:%.o=%.dtemp) ; \
mv $(@:%.o=%.dtemp) $(@:%.o=%.d); \
fi
endef
# link line constructed differently for makefile vs makefile.test invocation
ifeq ($(libpetscall),)
PETSC_TEST_LIB = $(PETSC_LIB)
else
PETSC_TEST_LIB = $(C_SH_LIB_PATH) $(PETSC_EXTERNAL_LIB_BASIC)
endif
# Test executables
$(testexe.F) $(testexe.F90) : $(TESTDIR)/% : $(TESTDIR)/%.o $$^ $(libpetscall)
$(call quiet,FLINKER) -o $@ $^ $(PETSC_TEST_LIB)
$(testexe.c) $(testexe.cu) : $(TESTDIR)/% : $(TESTDIR)/%.o $$^ $(libpetscall)
$(call quiet,CLINKER) -o $@ $^ $(PETSC_TEST_LIB)
$(testexe.cpp) : $(TESTDIR)/% : $(TESTDIR)/%.o $$^ $(libpetscall)
$(call quiet,CXXLINKER) -o $@ $^ $(PETSC_TEST_LIB)
# Fortran source files need petsc*.mod, which isn't explicitly managed in the makefile.
$(foreach pkg, $(pkgs), $(call concattestlang,$(pkg),F F90)) : $(libpetscall)
# Testing convenience targets
.PHONY: test pre-clean
test: alllib pre-clean report_tests
pre-clean:
@$(RM) -rf $(TESTDIR)/counts $(TESTLOGFILE)
@touch $(TESTLOGFILE)
.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)
-@$(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 test search=sys%ex2
# To match internal substrings (matches *ex2*):
# make test searchin=ex2
# Search and searchin can be combined:
# make test search='sys%' searchin=ex2
# For args:
# make test argsearch=cuda
# For general glob-style searching using python:
# NOTE: uses shell which is possibly slower and is possibly more brittle
# make 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) $(CONFIGDIR)/query_tests.py 'name' '$(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 # No filter - run them all, but delete the executables as we go
TESTTARGETS := $(testpkgs)
endif
.PHONY: report_tests print-test
print-test:
-@echo $(TESTTARGETS)
# Ensure that libpetsc (if it is a prerequisite) has been built and clean the counts/logs before starting timer
starttime: pre-clean $(libpetscall)
@$(eval STARTTIME := $(shell date +%s))
report_tests: starttime $(TESTTARGETS)
@$(eval ENDTIME := $(shell date +%s))
-@elapsed_time=$$(($(ENDTIME)- $(STARTTIME))) && \
$(PYTHON) $(CONFIGDIR)/report_tests.py -m $(MAKE) -d $(TESTDIR)/counts -t 5 -e $${elapsed_time} -s