xref: /honee/Makefile (revision 02e7dc5c683ed2638684b2b258e5f0f564852bde)
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)
30CPPFLAGS  = $(call pkgconf, --cflags-only-I $(petsc.pc) $(ceed.pc)) \
31  $(call pkgconf, --variable=cflags_dep $(petsc.pc))
32CXX       = $(call pkgconf, --variable=cxxcompiler $(petsc.pc) $(ceed.pc))
33CXXFLAGS  = -std=c++17 -Wno-deprecated -Wno-tautological-compare
34LDFLAGS   = $(call pkgconf, --libs-only-L --libs-only-other $(petsc.pc) $(ceed.pc))
35LDFLAGS  += $(patsubst -L%, $(call pkgconf, --variable=ldflag_rpath $(petsc.pc))%, $(call pkgconf, --libs-only-L $(petsc.pc) $(ceed.pc)))
36LDLIBS    = $(call pkgconf, --libs-only-l $(petsc.pc) $(ceed.pc)) -lm -lstdc++
37
38# ASAN must be left empty if you don't want to use it
39ASAN    ?=
40
41AFLAGS  ?= -fsanitize=address
42CFLAGS  += $(if $(ASAN),$(AFLAGS))
43FFLAGS  += $(if $(ASAN),$(AFLAGS))
44LDFLAGS += $(if $(ASAN),$(AFLAGS))
45
46CPPFLAGS += -I./include
47
48# External tools
49PYTHON   ?= python3
50SED      ?= sed
51
52# LibTorch
53USE_TORCH ?=
54ifeq ($(USE_TORCH),1)
55  libtorch.pc := $(shell $(PYTHON) ./pytorch_pkgconfig.py)
56  CPPFLAGS    += $(call pkgconf, --cflags-only-I $(libtorch.pc))
57  CXXFLAGS    += $(call pkgconf, --cflags-only-other $(libtorch.pc))
58  LDFLAGS     += $(call pkgconf, --libs-only-L --libs-only-other $(libtorch.pc))
59  LDFLAGS     += $(patsubst -L%, $(call pkgconf, --variable=ldflag_rpath $(petsc.pc))%, $(call pkgconf, --libs-only-L $(libtorch.pc)))
60  LDLIBS      += $(call pkgconf, --libs-only-l $(libtorch.pc))
61
62  src.cpp += $(sort $(wildcard $(PROBLEMDIR)/torch/*.cpp))
63  src.c   += $(sort $(wildcard $(PROBLEMDIR)/torch/*.c))
64
65  # Intel Pytorch EXtension (IPEX)
66  IPEX_DIR ?=
67  ifdef IPEX_DIR
68      LDFLAGS += -L$(IPEX_DIR)/lib/
69      LDFLAGS += -Wl,-rpath,$(IPEX_DIR)/lib/
70      LDLIBS  += -lintel-ext-pt-gpu
71  endif
72endif
73
74# Source Files
75OBJDIR := build
76SRCDIR := src
77PROBLEMDIR := problems
78
79src.c := navierstokes.c $(sort $(wildcard $(PROBLEMDIR)/*.c)) $(sort $(wildcard $(SRCDIR)/*.c))
80src.o = $(src.c:%.c=$(OBJDIR)/%.o) $(src.cpp:%.cpp=$(OBJDIR)/%.o)
81
82# Path to install directory for SmartRedis. Example: /software/smartredis/install
83SMARTREDIS_DIR ?=
84ifdef SMARTREDIS_DIR
85	hiredis.pc := $(SMARTREDIS_DIR)/lib/pkgconfig/hiredis.pc
86	lsmartredis:= -lsmartredis
87	redis++.pc = $(wildcard $(SMARTREDIS_DIR)/lib/pkgconfig/redis++.pc $(SMARTREDIS_DIR)/lib64/pkgconfig/redis++.pc)
88
89	CPPFLAGS += $(call pkgconf, --cflags-only-I $(hiredis.pc) $(redis++.pc))
90	LDFLAGS += $(call pkgconf, --libs-only-L --libs-only-other $(hiredis.pc) $(redis++.pc))
91	LDFLAGS += $(patsubst -L%, $(call pkgconf, --variable=ldflag_rpath $(petsc.pc))%, $(call pkgconf, --libs-only-L $(hiredis.pc) $(redis++.pc)))
92	LDLIBS += $(call pkgconf, --libs-only-l $(hiredis.pc) $(redis++.pc)) $(lsmartredis)
93	src.c += $(sort $(wildcard $(SRCDIR)/smartsim/*.c))
94endif
95
96
97
98# Diagnostic information
99info-basic:
100	$(info -----------------------------------------)
101	$(info |      __  ______  _   ______________   |)
102	$(info |     / / / / __ \/ | / / ____/ ____/   |)
103	$(info |    / /_/ / / / /  |/ / __/ / __/      |)
104	$(info |   / __  / /_/ / /|  / /___/ /___      |)
105	$(info |  /_/ /_/\____/_/ |_/_____/_____/      |)
106	$(info -----------------------------------------)
107	$(info )
108	$(info -----------------------------------------)
109	$(info )
110	$(info Dependencies:)
111	$(info CEED_DIR       = $(CEED_DIR))
112	$(info PETSC_DIR      = $(PETSC_DIR))
113	$(info PETSC_ARCH     = $(PETSC_ARCH))
114	$(info )
115	$(info Optional Dependencies:)
116	$(info SMARTREDIS_DIR = $(or $(SMARTREDIS_DIR),(not found)))
117	$(info USE_TORCH      = $(USE_TORCH))
118	$(info )
119	$(info -----------------------------------------)
120	$(info )
121	@true
122
123info:
124	$(info -----------------------------------------)
125	$(info |      __  ______  _   ______________   |)
126	$(info |     / / / / __ \/ | / / ____/ ____/   |)
127	$(info |    / /_/ / / / /  |/ / __/ / __/      |)
128	$(info |   / __  / /_/ / /|  / /___/ /___      |)
129	$(info |  /_/ /_/\____/_/ |_/_____/_____/      |)
130	$(info -----------------------------------------)
131	$(info )
132	$(info -----------------------------------------)
133	$(info )
134	$(info Dependencies:)
135	$(info CEED_DIR        = $(CEED_DIR))
136	$(info PETSC_DIR       = $(PETSC_DIR))
137	$(info PETSC_ARCH      = $(PETSC_ARCH))
138	$(info )
139	$(info Optional Dependencies:)
140	$(info SMARTREDIS_DIR = $(or $(SMARTREDIS_DIR),(not found)))
141	$(info USE_TORCH      = $(USE_TORCH))
142	$(info )
143	$(info -----------------------------------------)
144	$(info )
145	$(info Build Options:)
146	$(info CC              = $(CC))
147	$(info CFLAGS          = $(CFLAGS))
148	$(info CPPFLAGS        = $(CPPFLAGS))
149	$(info LDFLAGS         = $(LDFLAGS))
150	$(info LDLIBS          = $(LDLIBS))
151	$(info AR              = $(AR))
152	$(info ARFLAGS         = $(ARFLAGS))
153	$(info OPT             = $(OPT))
154	$(info AFLAGS          = $(AFLAGS))
155	$(info ASAN            = $(or $(ASAN),(empty)))
156	$(info VERBOSE         = $(or $(V),(empty)) [verbose=$(if $(V),on,off)])
157	$(info )
158	$(info -----------------------------------------)
159	$(info )
160	$(info Format and Style Options:)
161	$(info CLANG_FORMAT    = $(CLANG_FORMAT))
162	$(info FORMAT_OPTS     = $(FORMAT_OPTS))
163	$(info CLANG_TIDY      = $(CLANG_TIDY))
164	$(info TIDY_OPTS       = $(TIDY_OPTS))
165	$(info TIDY_FILE_OPTS  = $(TIDY_FILE_OPTS))
166	$(info )
167	$(info -----------------------------------------)
168	$(info )
169	@true
170
171# Get number of processors of the machine
172NPROCS := $(shell getconf _NPROCESSORS_ONLN)
173# prepare make options to run in parallel
174MFLAGS := -j $(NPROCS) --warn-undefined-variables \
175                       --no-print-directory --no-keep-going
176
177all: navierstokes
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$(OBJDIR)/%.o : %.c  Makefile | $$(@D)/.DIR
192	$(call quiet,CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(abspath $<)
193
194$(OBJDIR)/%.o : %.cpp Makefile | $$(@D)/.DIR
195	$(call quiet,CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(abspath $<)
196
197print: $(petsc.pc) $(ceed.pc)
198	$(info CC      : $(CC))
199	$(info CFLAGS  : $(CFLAGS))
200	$(info CPPFLAGS: $(CPPFLAGS))
201	$(info LDFLAGS : $(LDFLAGS))
202	$(info LDLIBS  : $(LDLIBS))
203	$(info OPT     : $(OPT))
204	@true
205
206print-% :
207	$(info [ variable name]: $*)
208	$(info [        origin]: $(origin $*))
209	$(info [        flavor]: $(flavor $*))
210	$(info [         value]: $(value $*))
211	$(info [expanded value]: $($*))
212	$(info )
213	@true
214
215clean:
216	$(RM) -r $(OBJDIR) navierstokes *.vtu *.bin* *.csv *.png
217
218$(petsc.pc):
219	$(if $(wildcard $@),,$(error \
220	  PETSc config not found. Please set PETSC_DIR and PETSC_ARCH))
221
222.PHONY: all print clean
223
224# Fluid Dynamics Examples
225fluidsexamples.c  := $(sort $(wildcard *.c))
226fluidsexamples.py := smartsim_regression_framework.py
227fluidsexamples    := $(fluidsexamples.c:%.c=$(OBJDIR)/%)
228fluidsexamples    += $(fluidsexamples.py:%.py=$(OBJDIR)/%)
229
230$(OBJDIR)/$(fluidsexamples.py): $(OBJDIR)/navierstokes
231
232examples := $(fluidsexamples)
233
234$(examples) : $(libceed)
235$(tests) : $(libceed)
236
237# Documentation
238DOXYGEN ?= doxygen
239DOXYGENOPTS ?= -q
240doxygen :
241	$(DOXYGEN) $(DOXYGENOPTS) Doxyfile
242
243SPHINXOPTS      =
244SPHINXBUILD     = sphinx-build
245SPHINXAUTOBUILD = sphinx-autobuild
246SPHINXPROJ      = Ratel
247SPHINXBUILDDIR  = doc/build
248
249doc-html doc-dirhtml doc-latexpdf doc-epub doc-help : doc-% : doxygen
250	@$(SPHINXBUILD) -M $* . "$(SPHINXBUILDDIR)" $(SPHINXOPTS)
251
252doc-livehtml : doxygen
253	@$(SPHINXAUTOBUILD) . "$(SPHINXBUILDDIR)" $(SPHINXOPTS)
254
255doc : doc-html
256
257doc-clean:
258	$(RM) -r doc/html doc/build
259
260# Tidy
261CLANG_TIDY     ?= clang-tidy
262TIDY_OPTS      ?= --quiet
263TIDY_FILE_OPTS += $(CPPFLAGS) --std=c99
264
265%.c.tidy : %.c
266	$(call quiet,CLANG_TIDY) $(TIDY_OPTS) $^ -- $(TIDY_FILE_OPTS)
267
268tidy-c   : $(src.c:%=%.tidy)
269
270tidy     : tidy-c
271
272# Style
273CLANG_FORMAT  ?= clang-format
274FORMAT_OPTS   += -style=file -i
275AUTOPEP8      ?= autopep8
276AUTOPEP8_OPTS += --in-place --aggressive --max-line-length 120
277SED_FMT_OPTS  += -r 's/\s+$$//' -i
278
279%.format : %
280	$(call quiet,CLANG_FORMAT) $(FORMAT_OPTS) $^
281
282format.ch := $(shell git ls-files *.[ch]pp *.[ch])
283format.py := $(filter-out tests/junit-xml/junit_xml/__init__.py, $(shell git ls-files '*.py'))
284format.ot := $(shell git ls-files *.md)
285
286format-c  :
287	$(call quiet,CLANG_FORMAT) $(FORMAT_OPTS) $(format.ch)
288
289format-py :
290	$(call quiet,AUTOPEP8) $(AUTOPEP8_OPTS) $(format.py)
291
292format-ot :
293	$(call quiet,SED) $(SED_FMT_OPTS) $(format.ot)
294
295format    : format-c format-py format-ot
296
297# Testing
298ifeq ($(COVERAGE), 1)
299  CFLAGS  += --coverage
300  LDFLAGS += --coverage
301endif
302
303PROVE      ?= prove
304PROVE_OPTS ?= -j $(NPROCS)
305
306# Set libCEED backends for testing
307CEED_BACKENDS ?= /cpu/self
308export CEED_BACKENDS
309
310# Set number processes for testing
311NPROC_TEST ?= 1
312export NPROC_TEST
313
314# Set pool size for testing
315NPROC_POOL ?= 1
316export NPROC_POOL
317
318JUNIT_BATCH ?= ''
319
320run-% : $(OBJDIR)/%
321	@$(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) $(<:$(OBJDIR)/%=%)
322
323# The test and prove targets can be controlled via pattern searches. The default
324# is to run all tests and examples. Examples of finer grained control:
325#
326#   make prove search='t3'    # t3xx series tests
327#   make junit search='t ex'  # core tests and examples
328search    ?= navierstokes
329realsearch = $(search:%=%%)
330matched    = $(foreach pattern,$(realsearch),$(filter $(OBJDIR)/$(pattern),$(tests) $(examples)))
331
332# Test
333test    : $(matched:$(OBJDIR)/%=run-%)
334
335tst     : ;@$(MAKE) $(MFLAGS) V=$(V) test
336
337# Test with TAP output
338prove   : $(matched)
339	$(info Running unit tests)
340	$(info - Testing with libCEED backends: $(CEED_BACKENDS))
341	$(info - Testing on $(NPROC_TEST) processes)
342	$(PROVE) $(PROVE_OPTS) --exec '$(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)' $(matched:$(OBJDIR)/%=%)
343
344prv     : ;@$(MAKE) $(MFLAGS) V=$(V) prove
345
346prove-all :
347	+$(MAKE) prove realsearch=%
348
349# Test with JUNIT output
350junit-% : $(OBJDIR)/%
351	@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) $(<:$(OBJDIR)/%=%)
352
353junit   : $(matched:$(OBJDIR)/%=junit-%)
354
355
356# Configure
357# "make configure" detects any variables passed on the command line or
358# previously set in config.mk, caching them in config.mk as simple
359# (:=) variables.  Variables set in config.mk or on the command line
360# take precedence over the defaults provided in the file.  Typical
361# usage:
362#
363#   make configure CC=/path/to/my/cc CUDA_DIR=/opt/cuda
364#   make
365#   make prove
366#
367# The values in the file can be updated by passing them on the command
368# line, e.g.,
369#
370#   make configure CC=/path/to/other/clang
371
372# All variables to consider for caching
373CONFIG_VARS = CEED_DIR PETSC_DIR PETSC_ARCH CCOPT CFLAGS CPPFLAGS AR ARFLAGS LDFLAGS LDLIBS SED USE_TORCH SMARTREDIS_DIR
374
375# $(call needs_save,CFLAGS) returns true (a nonempty string) if CFLAGS
376# was set on the command line or in config.mk (where it will appear as
377# a simple variable).
378needs_save = $(or $(filter command line,$(origin $(1))),$(filter simple,$(flavor $(1))))
379
380configure :
381	$(file > $(CONFIG))
382	$(foreach v,$(CONFIG_VARS),$(if $(call needs_save,$(v)),$(file >> $(CONFIG),$(v) := $($(v)))))
383	@echo "Configuration cached in $(CONFIG):"
384	@cat $(CONFIG)
385
386-include $(src.o:%.o=%.d)
387