xref: /honee/Makefile (revision 7ecf6641c340caefd7fa9f7fc7a6efebf89ae19d)
1CONFIG ?= config.mk
2-include $(CONFIG)
3COMMON ?= common.mk
4-include $(COMMON)
5
6pkgconf-path = $(if $(wildcard $(1)/$(2).pc),$(1)/$(2).pc,$(2))
7
8# Library dependencies
9# Note: PETSC_ARCH can be undefined or empty for installations which do not use
10#       PETSC_ARCH - for example when using PETSc installed through Spack.
11ifneq ($(wildcard ../petsc/lib/libpetsc.*),)
12  PETSC_DIR ?= ../petsc
13endif
14petsc.pc := $(call pkgconf-path,$(PETSC_DIR)/$(PETSC_ARCH)/lib/pkgconfig,petsc)
15
16CEED_DIR ?= $(if $(wildcard $(PETSC_DIR)/$(PETSC_ARCH)/lib/pkgconfig/ceed.pc),$(PETSC_DIR)/$(PETSC_ARCH),../libCEED)
17ceed.pc  := $(call pkgconf-path,$(CEED_DIR)/lib/pkgconfig,ceed)
18
19pkgconf   = $(shell pkg-config $(if $(STATIC),--static) $1 | $(SED) -e 's/^"//g' -e 's/"$$//g')
20
21# Error checking flags
22PEDANTIC      ?=
23PEDANTICFLAGS ?= -Werror -pedantic
24
25CC        = $(call pkgconf, --variable=ccompiler $(petsc.pc) $(ceed.pc))
26CFLAGS    = -std=c99 \
27  $(call pkgconf, --variable=cflags_extra $(petsc.pc)) \
28  $(call pkgconf, --cflags-only-other $(petsc.pc)) \
29  $(OPT) \
30  $(if $(PEDANTIC),$(PEDANTICFLAGS))
31CPPFLAGS  = $(call pkgconf, --cflags-only-I $(petsc.pc) $(ceed.pc)) \
32  $(call pkgconf, --variable=cflags_dep $(petsc.pc)) \
33  $(if $(PEDANTIC),$(PEDANTICFLAGS))
34CXX       = $(call pkgconf, --variable=cxxcompiler $(petsc.pc) $(ceed.pc)) $(if $(PEDANTIC),$(PEDANTICFLAGS))
35CXXFLAGS  = -std=c++17 -Wno-deprecated -Wno-tautological-compare
36LDFLAGS   = $(call pkgconf, --libs-only-L --libs-only-other $(petsc.pc) $(ceed.pc))
37LDFLAGS  += $(patsubst -L%, $(call pkgconf, --variable=ldflag_rpath $(petsc.pc))%, $(call pkgconf, --libs-only-L $(petsc.pc) $(ceed.pc)))
38LDLIBS    = $(call pkgconf, --libs-only-l $(petsc.pc) $(ceed.pc)) -lm -lstdc++
39
40# ASAN must be left empty if you don't want to use it
41ASAN    ?=
42
43AFLAGS  ?= -fsanitize=address
44CFLAGS  += $(if $(ASAN),$(AFLAGS))
45FFLAGS  += $(if $(ASAN),$(AFLAGS))
46LDFLAGS += $(if $(ASAN),$(AFLAGS))
47
48CPPFLAGS += -I./include
49
50# External tools
51PYTHON   ?= python3
52SED      ?= sed
53
54# LibTorch
55USE_TORCH ?=
56ifeq ($(USE_TORCH),1)
57  libtorch.pc := $(shell $(PYTHON) ./pytorch_pkgconfig.py)
58  CPPFLAGS    += $(call pkgconf, --cflags-only-I $(libtorch.pc))
59  CXXFLAGS    += $(call pkgconf, --cflags-only-other $(libtorch.pc))
60  LDFLAGS     += $(call pkgconf, --libs-only-L --libs-only-other $(libtorch.pc))
61  LDFLAGS     += $(patsubst -L%, $(call pkgconf, --variable=ldflag_rpath $(petsc.pc))%, $(call pkgconf, --libs-only-L $(libtorch.pc)))
62  LDLIBS      += $(call pkgconf, --libs-only-l $(libtorch.pc))
63
64  src.cpp += $(sort $(wildcard $(PROBLEMDIR)/torch/*.cpp))
65  src.c   += $(sort $(wildcard $(PROBLEMDIR)/torch/*.c))
66
67  # Intel Pytorch EXtension (IPEX)
68  IPEX_DIR ?=
69  ifdef IPEX_DIR
70      LDFLAGS += -L$(IPEX_DIR)/lib/
71      LDFLAGS += -Wl,-rpath,$(IPEX_DIR)/lib/
72      LDLIBS  += -lintel-ext-pt-gpu
73  endif
74endif
75
76# Source Files
77OBJDIR := build
78SRCDIR := src
79PROBLEMDIR := problems
80
81src.c := examples/navierstokes.c $(filter-out $(wildcard **/smartsim/*), $(sort $(wildcard $(PROBLEMDIR)/*.c)) $(sort $(wildcard $(SRCDIR)/*.c)) $(sort $(wildcard $(SRCDIR)/**/*.c)))
82src.o = $(src.c:%.c=$(OBJDIR)/%.o) $(src.cpp:%.cpp=$(OBJDIR)/%.o)
83
84# Path to install directory for SmartRedis. Example: /software/smartredis/install
85SMARTREDIS_DIR ?=
86ifdef SMARTREDIS_DIR
87	CPPFLAGS += -I$(SMARTREDIS_DIR)/include
88	LDFLAGS += -L$(SMARTREDIS_DIR)/lib $(call pkgconf, --variable=ldflag_rpath $(petsc.pc))$(SMARTREDIS_DIR)/lib
89	LDLIBS +=  -lsmartredis
90	src.c += $(sort $(wildcard $(SRCDIR)/smartsim/*.c))
91endif
92
93all: navierstokes
94
95# Diagnostic information
96info-basic:
97	$(info -----------------------------------------)
98	$(info |      __  ______  _   ______________   |)
99	$(info |     / / / / __ \/ | / / ____/ ____/   |)
100	$(info |    / /_/ / / / /  |/ / __/ / __/      |)
101	$(info |   / __  / /_/ / /|  / /___/ /___      |)
102	$(info |  /_/ /_/\____/_/ |_/_____/_____/      |)
103	$(info -----------------------------------------)
104	$(info )
105	$(info -----------------------------------------)
106	$(info )
107	$(info Dependencies:)
108	$(info CEED_DIR       = $(CEED_DIR))
109	$(info PETSC_DIR      = $(PETSC_DIR))
110	$(info PETSC_ARCH     = $(PETSC_ARCH))
111	$(info )
112	$(info Optional Dependencies:)
113	$(info SMARTREDIS_DIR = $(or $(SMARTREDIS_DIR),(not found)))
114	$(info USE_TORCH      = $(USE_TORCH))
115	$(info )
116	$(info -----------------------------------------)
117	$(info )
118	@true
119
120info:
121	$(info -----------------------------------------)
122	$(info |      __  ______  _   ______________   |)
123	$(info |     / / / / __ \/ | / / ____/ ____/   |)
124	$(info |    / /_/ / / / /  |/ / __/ / __/      |)
125	$(info |   / __  / /_/ / /|  / /___/ /___      |)
126	$(info |  /_/ /_/\____/_/ |_/_____/_____/      |)
127	$(info -----------------------------------------)
128	$(info )
129	$(info -----------------------------------------)
130	$(info )
131	$(info Dependencies:)
132	$(info CEED_DIR        = $(CEED_DIR))
133	$(info PETSC_DIR       = $(PETSC_DIR))
134	$(info PETSC_ARCH      = $(PETSC_ARCH))
135	$(info )
136	$(info Optional Dependencies:)
137	$(info SMARTREDIS_DIR = $(or $(SMARTREDIS_DIR),(not found)))
138	$(info USE_TORCH      = $(USE_TORCH))
139	$(info )
140	$(info -----------------------------------------)
141	$(info )
142	$(info Build Options:)
143	$(info CC              = $(CC))
144	$(info CFLAGS          = $(CFLAGS))
145	$(info CPPFLAGS        = $(CPPFLAGS))
146	$(info LDFLAGS         = $(LDFLAGS))
147	$(info LDLIBS          = $(LDLIBS))
148	$(info AR              = $(AR))
149	$(info ARFLAGS         = $(ARFLAGS))
150	$(info OPT             = $(OPT))
151	$(info AFLAGS          = $(AFLAGS))
152	$(info ASAN            = $(or $(ASAN),(empty)))
153	$(info VERBOSE         = $(or $(V),(empty)) [verbose=$(if $(V),on,off)])
154	$(info )
155	$(info -----------------------------------------)
156	$(info )
157	$(info Format and Style Options:)
158	$(info CLANG_FORMAT    = $(CLANG_FORMAT))
159	$(info FORMAT_OPTS     = $(FORMAT_OPTS))
160	$(info CLANG_TIDY      = $(CLANG_TIDY))
161	$(info TIDY_OPTS       = $(TIDY_OPTS))
162	$(info TIDY_FILE_OPTS  = $(TIDY_FILE_OPTS))
163	$(info )
164	$(info -----------------------------------------)
165	$(info )
166	$(info Git:)
167	$(info describe        = $(GIT_DESCRIBE))
168	$(info )
169	$(info -----------------------------------------)
170	$(info )
171	@true
172
173# Get number of processors of the machine
174NPROCS := $(shell getconf _NPROCESSORS_ONLN)
175# prepare make options to run in parallel
176MFLAGS := -j $(NPROCS) --warn-undefined-variables \
177                       --no-print-directory --no-keep-going
178
179$(OBJDIR)/navierstokes: $(src.o) | navierstokes
180navierstokes: $(src.o) | $(petsc.pc) $(ceed.pc)
181	$(call quiet,LINK.o) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $(OBJDIR)/$@
182
183.SECONDEXPANSION: # to expand $$(@D)/.DIR
184%/.DIR :
185	@mkdir -p $(@D)
186	@touch $@
187
188# Quiet, color output
189quiet ?= $($(1))
190
191# Inject Git/version macros when compiling honee-version.c
192GIT_DESCRIBE := $(shell git -c safe.directory=$PWD describe --always --dirty 2>/dev/null || printf "unknown\n")
193
194$(OBJDIR)/src/honee-config.o: Makefile
195$(OBJDIR)/src/honee-config.o src/honee-config.c.tidy: CONFIGFLAGS += -DHONEE_GIT_VERSION="\"$(GIT_DESCRIBE)\""
196$(OBJDIR)/src/honee-config.o src/honee-config.c.tidy: CONFIGFLAGS += -DHONEE_BUILD_CONFIGURATION="\"// Build Configuration:$(foreach v,$(CONFIG_VARS),\n$(v) = $($(v)))\""
197
198$(OBJDIR)/%.o : %.c | $$(@D)/.DIR
199	$(call quiet,CC) $(CPPFLAGS) $(CFLAGS) $(CONFIGFLAGS) -c -o $@ $(abspath $<)
200
201$(OBJDIR)/%.o : %.cpp | $$(@D)/.DIR
202	$(call quiet,CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(abspath $<)
203
204print: $(petsc.pc) $(ceed.pc)
205	$(info CC      : $(CC))
206	$(info CFLAGS  : $(CFLAGS))
207	$(info CPPFLAGS: $(CPPFLAGS))
208	$(info LDFLAGS : $(LDFLAGS))
209	$(info LDLIBS  : $(LDLIBS))
210	$(info OPT     : $(OPT))
211	@true
212
213print-% :
214	$(info [ variable name]: $*)
215	$(info [        origin]: $(origin $*))
216	$(info [        flavor]: $(flavor $*))
217	$(info [         value]: $(value $*))
218	$(info [expanded value]: $($*))
219	$(info )
220	@true
221
222clean:
223	$(RM) -r $(OBJDIR) navierstokes *.vtu *.bin* *.csv *.png
224
225$(petsc.pc):
226	$(if $(wildcard $@),,$(error \
227	  PETSc config not found. Please set PETSC_DIR and PETSC_ARCH))
228
229.PHONY: all print clean
230
231# Define test files
232examples.c     := $(sort $(wildcard examples/*.c))
233examples       := $(examples.c:examples/%.c=$(OBJDIR)/%)
234tests.smartsim := test-smartsim
235tests          += $(tests.smartsim:%=$(OBJDIR)/%)
236
237$(tests.smartsim:%=$(OBJDIR)/%): $(OBJDIR)/navierstokes
238
239# Documentation
240DOXYGEN ?= doxygen
241DOXYGENOPTS ?= -q
242doxygen :
243	$(DOXYGEN) $(DOXYGENOPTS) Doxyfile
244
245SPHINXOPTS      =
246SPHINXBUILD     = sphinx-build
247SPHINXAUTOBUILD = sphinx-autobuild
248SPHINXPROJ      = HONEE
249SPHINXBUILDDIR  = doc/build
250
251doc-html doc-dirhtml doc-latexpdf doc-epub doc-help : doc-% : doxygen
252	@$(SPHINXBUILD) -M $* . "$(SPHINXBUILDDIR)" $(SPHINXOPTS)
253
254doc-livehtml : doxygen
255	@$(SPHINXAUTOBUILD) . "$(SPHINXBUILDDIR)" $(SPHINXOPTS)
256
257doc : doc-html
258
259doc-clean:
260	$(RM) -r doc/html doc/build
261
262# Tidy
263CLANG_TIDY     ?= clang-tidy
264TIDY_OPTS      ?= --quiet
265TIDY_FILE_OPTS += $(CPPFLAGS) $(CONFIGFLAGS) --std=c99
266
267%.c.tidy : %.c
268	$(call quiet,CLANG_TIDY) $(TIDY_OPTS) $^ -- $(TIDY_FILE_OPTS)
269
270tidy-c   : $(src.c:%=%.tidy)
271
272tidy     : tidy-c
273
274# Style
275CLANG_FORMAT  ?= clang-format
276FORMAT_OPTS   += -style=file -i
277AUTOPEP8      ?= autopep8
278AUTOPEP8_OPTS += --in-place --aggressive --max-line-length 120
279SED_FMT_OPTS  += -r 's/\s+$$//' -i
280
281%.format : %
282	$(call quiet,CLANG_FORMAT) $(FORMAT_OPTS) $^
283
284format.ch := $(shell git ls-files '*.[ch]pp' '*.[ch]')
285format.py := $(filter-out tests/junit-xml/junit_xml/__init__.py, $(shell git ls-files '*.py'))
286format.ot := $(shell git ls-files '*.md')
287
288format-c  :
289	$(call quiet,CLANG_FORMAT) $(FORMAT_OPTS) $(format.ch)
290
291format-py :
292	$(call quiet,AUTOPEP8) $(AUTOPEP8_OPTS) $(format.py)
293
294format-ot :
295	$(call quiet,SED) $(SED_FMT_OPTS) $(format.ot)
296
297format    : format-c format-py format-ot
298
299# Testing
300ifeq ($(COVERAGE), 1)
301  CFLAGS  += --coverage
302  LDFLAGS += --coverage
303endif
304
305PROVE      ?= prove
306PROVE_OPTS ?= -j $(NPROCS)
307
308# Set libCEED backends for testing
309CEED_BACKENDS ?= /cpu/self
310export CEED_BACKENDS
311
312# Set number processes for testing
313NPROC_TEST ?= 1
314export NPROC_TEST
315
316# Set pool size for testing
317NPROC_POOL ?= 1
318export NPROC_POOL
319
320JUNIT_BATCH ?= ''
321
322run-% : $(OBJDIR)/%
323	@$(PYTHON) tests/junit.py --ceed-backends $(CEED_BACKENDS) --mode tap $(if $(SMARTREDIS_DIR),--smartredis-dir $(SMARTREDIS_DIR) ) $(if $(USE_TORCH),--has-torch $(USE_TORCH) )--nproc $(NPROC_TEST) --pool-size $(NPROC_POOL) --search '$(subsearch)' $(<:$(OBJDIR)/%=%)
324
325# The test and prove targets can be controlled via pattern searches. The default
326# is to run all tests and examples. Examples of finer grained control:
327#
328#   make prove search='t3'    # t3xx series tests
329#   make junit search='t ex'  # core tests and examples
330search    ?= navierstokes
331subsearch ?= .*
332realsearch = $(search:%=%%)
333matched    = $(foreach pattern,$(realsearch),$(filter $(OBJDIR)/$(pattern),$(tests) $(examples)))
334
335# Test
336test    : $(matched:$(OBJDIR)/%=run-%)
337
338tst     : ;@$(MAKE) $(MFLAGS) V=$(V) test
339
340# Test with TAP output
341prove   : $(matched)
342	$(info Running unit tests)
343	$(info - Testing with libCEED backends: $(CEED_BACKENDS))
344	$(info - Testing on $(NPROC_TEST) processes)
345	$(PROVE) $(PROVE_OPTS) --exec '$(PYTHON) tests/junit.py' $(matched:$(OBJDIR)/%=%) :: --ceed-backends $(CEED_BACKENDS) --mode tap $(if $(SMARTREDIS_DIR),--smartredis-dir $(SMARTREDIS_DIR) ) $(if $(USE_TORCH),--has-torch $(USE_TORCH) )--nproc $(NPROC_TEST) --pool-size $(NPROC_POOL) --search '$(subsearch)'
346
347prv     : ;@$(MAKE) $(MFLAGS) V=$(V) prove
348
349prove-all :
350	+$(MAKE) prove realsearch=%
351
352# Test with JUNIT output
353junit-% : $(OBJDIR)/%
354	@printf "  %10s %s\n" TEST $(<:$(OBJDIR)/%=%); $(PYTHON) tests/junit.py --junit-batch $(JUNIT_BATCH) --ceed-backends $(CEED_BACKENDS) $(if $(SMARTREDIS_DIR),--smartredis-dir $(SMARTREDIS_DIR) ) $(if $(USE_TORCH),--has-torch $(USE_TORCH) )--nproc $(NPROC_TEST) --pool-size $(NPROC_POOL) --search '$(subsearch)' $(<:$(OBJDIR)/%=%)
355
356junit   : $(matched:$(OBJDIR)/%=junit-%)
357
358
359# Configure
360# "make configure" detects any variables passed on the command line or
361# previously set in config.mk, caching them in config.mk as simple
362# (:=) variables.  Variables set in config.mk or on the command line
363# take precedence over the defaults provided in the file.  Typical
364# usage:
365#
366#   make configure CC=/path/to/my/cc CUDA_DIR=/opt/cuda
367#   make
368#   make prove
369#
370# The values in the file can be updated by passing them on the command
371# line, e.g.,
372#
373#   make configure CC=/path/to/other/clang
374
375# All variables to consider for caching
376CONFIG_VARS = CEED_DIR PETSC_DIR PETSC_ARCH OPT CFLAGS CPPFLAGS AR ARFLAGS LDFLAGS LDLIBS SED USE_TORCH SMARTREDIS_DIR
377
378# $(call needs_save,CFLAGS) returns true (a nonempty string) if CFLAGS
379# was set on the command line or in config.mk (where it will appear as
380# a simple variable).
381needs_save = $(or $(filter command line,$(origin $(1))),$(filter simple,$(flavor $(1))))
382
383configure :
384	$(file > $(CONFIG))
385	$(foreach v,$(CONFIG_VARS),$(if $(call needs_save,$(v)),$(file >> $(CONFIG),$(v) := $($(v)))))
386	@echo "Configuration cached in $(CONFIG):"
387	@cat $(CONFIG)
388
389
390GITSRC = '*.[chF]' '*.hpp' '*.cpp' '*.cxx'
391checkbadSource:
392	@git --no-pager grep -n -P 'self\.gitcommit' -- config/BuildSystem/config/packages | grep 'origin/' ; if [[ "$$?" == "0" ]]; then echo "Error: Do not use a branch name in a configure package file"; false; fi
393	-@${RM} -f checkbadSource.out
394	-@touch checkbadSource.out
395	-@${PYTHON} ${PETSC_DIR}/lib/petsc/bin/maint/check_header_guard.py --action=check --kind=pragma_once -- ./src ./include >> checkbadSource.out
396	-@echo "----- Double blank lines in file -----------------------------------" >> checkbadSource.out
397	-@git --no-pager grep -n -P '^$$' -- ${GITSRC} > doublelinecheck.out
398	-@${PYTHON} ${PETSC_DIR}/lib/petsc/bin/maint/doublelinecheck.py doublelinecheck.out >> checkbadSource.out
399	-@${RM} -f doublelinecheck.out
400	-@echo "----- Tabs in file -------------------------------------------------" >> checkbadSource.out
401	-@git --no-pager grep -n -P '\t' -- ${GITSRC} >> checkbadSource.out;true
402	-@echo "----- Tabs in makefiles --------------------------------------------" >> checkbadSource.out
403	-@git --no-pager grep -n -P '[ ]*[#A-Za-z0-9][ :=_A-Za-z0-9]*\t' -- makefile  >> checkbadSource.out;true
404	-@echo "----- White space at end of line -----------------------------------" >> checkbadSource.out
405	-@git --no-pager grep -n -P ' $$' -- ${GITSRC} >> checkbadSource.out;true
406	-@echo "----- Two ;; -------------------------------------------------------" >> checkbadSource.out
407	-@git --no-pager grep -n -P -e ';;' -- ${GITSRC} | grep -v ' for (' >> checkbadSource.out;true
408	-@echo "----- PetscCall for an MPI error code ------------------------------" >> checkbadSource.out
409	-@git --no-pager grep -n -P -e 'PetscCall\(MPI[U]*_\w*\(.*\)\);' -- ${GITSRC} | grep -Ev 'MPIU_File' >> checkbadSource.out;true
410	-@echo "----- DOS file (with DOS newlines) ---------------------------------" >> checkbadSource.out
411	-@git --no-pager grep -n -P '\r' -- ${GITSRC} >> checkbadSource.out;true
412	-@echo "----- { before SETERRQ ---------------------------------------------" >> checkbadSource.out
413	-@git --no-pager grep -n -P '{SETERRQ' -- ${GITSRC} >> checkbadSource.out;true
414	-@echo "----- PetscCall following SETERRQ ----------------------------------" >> checkbadSource.out
415	-@git --no-pager grep -n -P 'SETERRQ' -- ${GITSRC} | grep ";PetscCall" >> checkbadSource.out;true
416	-@echo "----- SETERRQ() without defined error code -------------------------" >> checkbadSource.out
417	-@git --no-pager grep -n -P 'SETERRQ\((?!\))' -- ${GITSRC} | grep -v PETSC_ERR  | grep " if " | grep -v "__VA_ARGS__" | grep -v "then;" | grep -v flow.c >> checkbadSource.out;true
418	-@echo "----- SETERRQ() with trailing newline ------------------------------" >> checkbadSource.out
419	-@git --no-pager grep -n -P "SETERRQ[1-9]?.*\\\n\"" -- ${GITSRC} >> checkbadSource.out;true
420	-@echo "----- Using if (condition) SETERRQ(...) instead of PetscCheck() ----" >> checkbadSource.out
421	-@git --no-pager grep -n -P ' if +(.*) *SETERRQ' -- ${GITSRC} | grep -v 'PetscUnlikelyDebug' | grep -v 'petscerror.h' | grep -v "then;" | grep -v "__VA_ARGS__"  >> checkbadSource.out;true
422	-@echo "----- Using if (PetscUnlikelyDebug(condition)) SETERRQ(...) instead of PetscAssert()" >> checkbadSource.out
423	-@git --no-pager grep -n -P -E ' if +\(PetscUnlikelyDebug.*\) *SETERRQ' -- ${GITSRC} | grep -v petscerror.h >> checkbadSource.out;true
424	-@echo "----- Using PetscFunctionReturn(ierr) ------------------------------" >> checkbadSource.out
425	-@git --no-pager grep -n -P 'PetscFunctionReturn(ierr)' -- ${GITSRC} >> checkbadSource.out;true
426	-@echo "----- Defining a returning macro without PetscMacroReturns() -------" >> checkbadSource.out
427	-@git --no-pager grep -n -P 'define .*\w+;\s+do' -- ${GITSRC} | grep -E -v '(PetscMacroReturns|PetscDrawCollectiveBegin|MatPreallocateBegin|PetscOptionsBegin|PetscObjectOptionsBegin|PetscOptionsHeadEnd)' >> checkbadSource.out;true
428	-@echo "----- Defining an error checking macro using CHKERR style ----------" >> checkbadSource.out
429	-@git --no-pager grep -n -P 'define\s+CHKERR\w*\(.*\)\s*do\s+{' -- ${GITSRC} >> checkbadSource.out;true
430	-@echo "----- Using Petsc[Array|Mem]cpy() for ops instead of assignment ----" >> checkbadSource.out
431	-@git --no-pager grep -n -P 'cpy\(.*(.|->)ops, .*\)' -- ${GITSRC} >> checkbadSource.out;true
432	-@echo "----- Using PetscInfo() without carriage return --------------------" >> checkbadSource.out
433	-@git --no-pager grep -n -P 'PetscCall\(PetscInfo\(' -- ${GITSRC} | grep -v '\\n' >> checkbadSource.out;true
434	-@echo "----- Using Petsc(Assert|Check)() with carriage return -------------" >> checkbadSource.out
435	-@git --no-pager grep -n -P -E 'Petsc(Assert|Check)\(.*[^\]\\\n' -- ${GITSRC} >> checkbadSource.out;true
436	-@echo "----- Extra \"\" after format specifier ending a string --------------" >> checkbadSource.out
437	-@git --no-pager grep -n -P -E '_FMT \"\",' -- ${GITSRC} >> checkbadSource.out;true
438	-@echo "----- First blank line ---------------------------------------------" >> checkbadSource.out
439	-@git --no-pager grep -n -P \^\$$ -- ${GITSRC} | grep ':1:' >> checkbadSource.out;true
440	-@echo "----- Blank line after PetscFunctionBegin and derivatives ----------" >> checkbadSource.out
441	-@git --no-pager grep -n -E -A 1 '  PetscFunctionBegin(User|Hot){0,1};' -- ${GITSRC} | grep -E '\-[0-9]+-$$' | grep -v '^--$$' >> checkbadSource.out;true
442	-@echo "----- Blank line before PetscFunctionReturn ------------------------" >> checkbadSource.out
443	-@git --no-pager grep -n -E -B 1 '  PetscFunctionReturn' -- ${GITSRC} | grep -E '\-[0-9]+-$$' | grep -v '^--$$' >> checkbadSource.out;true
444	-@echo "----- No blank line before PetscFunctionBegin and derivatives ------" >> checkbadSource.out
445	-@git --no-pager grep -n -E -B 1 '  PetscFunctionBegin(User|Hot){0,1};' -- ${GITSRC} ':!src/sys/tests/*' ':!src/sys/tutorials/*' | grep -E '\-[0-9]+-.*;' | grep -v '^--$$' | grep -v '\\' >> checkbadSource.out;true
446	-@echo "----- Unneeded parentheses [!&~*](foo[->|.]bar) --------------------" >> checkbadSource.out
447	-@git --no-pager grep -n -P -E '([\!\&\~\*\(]|\)\)|\([^,\*\(]+\**\))\(([a-zA-Z0-9_]+((\.|->)[a-zA-Z0-9_]+|\[[a-zA-Z0-9_ \%\+\*\-]+\])+)\)' -- ${GITSRC} >> checkbadSource.out;true
448	-@echo "----- Use PetscSafePointerPlusOffset(ptr, n) instead of ptr ? ptr + n : NULL" >> checkbadSource.out
449	-@git --no-pager grep -n -Po ' ([^()\ ]+) \? (?1) \+ (.)* : NULL' -- ${GITSRC} >> checkbadSource.out;true
450	-@echo "----- Wrong PETSc capitalization -----------------------------------" >> checkbadSource.out
451	-@git --no-pager grep -n -P -E '[^a-zA-Z_*>{.]petsc [^+=]' -- ${GITSRC} | grep -v 'mat_solver_type petsc' | grep -v ' PETSc ' >> checkbadSource.out;true
452	-@echo "----- Unnecessary braces around one-liners -------------------------" >> checkbadSource.out
453	-@git --no-pager grep -n -P -E '[ ]*(if|for|while|do|else) \(.*\) \{[^;]*;[^;]*\}( \\)?$$' -- ${GITSRC} >> checkbadSource.out;true
454	-@echo "----- MPI_(Allreduce|Irecv|Isend) instead of MPIU_(Allreduce|Irecv|Isend)" >> checkbadSource.out
455	-@git --no-pager grep -n -P -E '\(MPI_(Allreduce|Irecv|Isend)\([^\)]' -- ${GITSRC} ':!*/tests/*' ':!*/tutorials/*' ':!src/sys/objects/pinit.c' >> checkbadSource.out;true
456	@a=`cat checkbadSource.out | wc -l`; l=`expr $$a - 36` ;\
457         if [ $$l -gt 0 ] ; then \
458           echo $$l " files with errors detected in source code formatting" ;\
459           cat checkbadSource.out ;\
460         else \
461	   ${RM} -f checkbadSource.out;\
462         fi;\
463         test ! $$l -gt 0
464	-@git --no-pager grep -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" -- ${GITSRC} > badSourceChar.out;true
465	-@w=`cat badSourceChar.out | wc -l`;\
466         if [ $$w -gt 0 ] ; then \
467           echo "Source files with non-ASCII characters ----------------" ;\
468           cat badSourceChar.out ;\
469         else \
470	   ${RM} -f badSourceChar.out;\
471         fi
472	@test ! -s badSourceChar.out
473
474-include $(src.o:%.o=%.d)
475