xref: /honee/Makefile (revision a39fefe2f8165811cd0b417fe1598d64201cc77a)
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
96all: navierstokes
97
98$(OBJDIR)/navierstokes: $(src.o) | navierstokes
99navierstokes: $(src.o) | $(petsc.pc) $(ceed.pc)
100	$(call quiet,LINK.o) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $(OBJDIR)/$@
101
102.SECONDEXPANSION: # to expand $$(@D)/.DIR
103%/.DIR :
104	@mkdir -p $(@D)
105	@touch $@
106
107# Quiet, color output
108quiet ?= $($(1))
109
110$(OBJDIR)/%.o : %.c  Makefile | $$(@D)/.DIR
111	$(call quiet,CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(abspath $<)
112
113$(OBJDIR)/%.o : %.cpp Makefile | $$(@D)/.DIR
114	$(call quiet,CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(abspath $<)
115
116print: $(petsc.pc) $(ceed.pc)
117	$(info CC      : $(CC))
118	$(info CFLAGS  : $(CFLAGS))
119	$(info CPPFLAGS: $(CPPFLAGS))
120	$(info LDFLAGS : $(LDFLAGS))
121	$(info LDLIBS  : $(LDLIBS))
122	$(info OPT     : $(OPT))
123	@true
124
125print-% :
126	$(info [ variable name]: $*)
127	$(info [        origin]: $(origin $*))
128	$(info [        flavor]: $(flavor $*))
129	$(info [         value]: $(value $*))
130	$(info [expanded value]: $($*))
131	$(info )
132	@true
133
134clean:
135	$(RM) -r $(OBJDIR) navierstokes *.vtu *.bin* *.csv *.png
136
137$(petsc.pc):
138	$(if $(wildcard $@),,$(error \
139	  PETSc config not found. Please set PETSC_DIR and PETSC_ARCH))
140
141.PHONY: all print clean
142
143# Fluid Dynamics Examples
144fluidsexamples.c  := $(sort $(wildcard *.c))
145fluidsexamples.py := smartsim_regression_framework.py
146fluidsexamples    := $(fluidsexamples.c:%.c=$(OBJDIR)/%)
147fluidsexamples    += $(fluidsexamples.py:%.py=$(OBJDIR)/%)
148
149$(OBJDIR)/$(fluidsexamples.py): $(OBJDIR)/navierstokes
150
151examples := $(fluidsexamples)
152
153$(examples) : $(libceed)
154$(tests) : $(libceed)
155
156# Tidy
157CLANG_TIDY     ?= clang-tidy
158TIDY_OPTS      ?= --quiet
159TIDY_FILE_OPTS += $(CPPFLAGS) --std=c99
160
161%.c.tidy : %.c
162	$(call quiet,CLANG_TIDY) $(TIDY_OPTS) $^ -- $(TIDY_FILE_OPTS)
163
164tidy-c   : $(src.c:%=%.tidy)
165
166tidy     : tidy-c
167
168# Style
169CLANG_FORMAT  ?= clang-format
170FORMAT_OPTS   += -style=file -i
171AUTOPEP8      ?= autopep8
172AUTOPEP8_OPTS += --in-place --aggressive --max-line-length 120
173SED_FMT_OPTS  += -r 's/\s+$$//' -i
174
175%.format : %
176	$(call quiet,CLANG_FORMAT) $(FORMAT_OPTS) $^
177
178format.ch := $(shell git ls-files *.[ch]pp *.[ch])
179format.py := $(filter-out tests/junit-xml/junit_xml/__init__.py, $(shell git ls-files '*.py'))
180format.ot := $(shell git ls-files *.md)
181
182format-c  :
183	$(call quiet,CLANG_FORMAT) $(FORMAT_OPTS) $(format.ch)
184
185format-py :
186	$(call quiet,AUTOPEP8) $(AUTOPEP8_OPTS) $(format.py)
187
188format-ot :
189	$(call quiet,SED) $(SED_FMT_OPTS) $(format.ot)
190
191format    : format-c format-py format-ot
192
193# Testing
194ifeq ($(COVERAGE), 1)
195  CFLAGS  += --coverage
196  LDFLAGS += --coverage
197endif
198
199PROVE      ?= prove
200PROVE_OPTS ?= -j $(NPROCS)
201
202# Set libCEED backends for testing
203CEED_BACKENDS ?= /cpu/self
204export CEED_BACKENDS
205
206# Set number processes for testing
207NPROC_TEST ?= 1
208export NPROC_TEST
209
210# Set pool size for testing
211NPROC_POOL ?= 1
212export NPROC_POOL
213
214JUNIT_BATCH ?= ''
215
216run-% : $(OBJDIR)/%
217	@$(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)/%=%)
218
219# The test and prove targets can be controlled via pattern searches. The default
220# is to run all tests and examples. Examples of finer grained control:
221#
222#   make prove search='t3'    # t3xx series tests
223#   make junit search='t ex'  # core tests and examples
224search    ?= navierstokes
225realsearch = $(search:%=%%)
226matched    = $(foreach pattern,$(realsearch),$(filter $(OBJDIR)/$(pattern),$(tests) $(examples)))
227
228# Test
229test    : $(matched:$(OBJDIR)/%=run-%)
230
231tst     : ;@$(MAKE) $(MFLAGS) V=$(V) test
232
233# Test with TAP output
234prove   : $(matched)
235	$(info Running unit tests)
236	$(info - Testing with libCEED backends: $(CEED_BACKENDS))
237	$(info - Testing on $(NPROC_TEST) processes)
238	$(PROVE) $(PROVE_OPTS) --exec '$(PYTHON) tests/junit.py --petsc-arch $(or $(PETSC_ARCH),$(PETSC_DIR)) --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)/%=%)
239
240prv     : ;@$(MAKE) $(MFLAGS) V=$(V) prove
241
242prove-all :
243	+$(MAKE) prove realsearch=%
244
245# Test with JUNIT output
246junit-% : $(OBJDIR)/%
247	@printf "  %10s %s\n" TEST $(<:$(OBJDIR)/%=%); $(PYTHON) tests/junit.py --junit-batch $(JUNIT_BATCH) --petsc-arch $(or $(PETSC_ARCH),$(PETSC_DIR)) --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)/%=%)
248
249junit   : $(matched:$(OBJDIR)/%=junit-%)
250
251
252# Configure
253# "make configure" detects any variables passed on the command line or
254# previously set in config.mk, caching them in config.mk as simple
255# (:=) variables.  Variables set in config.mk or on the command line
256# take precedence over the defaults provided in the file.  Typical
257# usage:
258#
259#   make configure CC=/path/to/my/cc CUDA_DIR=/opt/cuda
260#   make
261#   make prove
262#
263# The values in the file can be updated by passing them on the command
264# line, e.g.,
265#
266#   make configure CC=/path/to/other/clang
267
268# All variables to consider for caching
269CONFIG_VARS = CEED_DIR PETSC_DIR PETSC_ARCH CCOPT CFLAGS CPPFLAGS AR ARFLAGS LDFLAGS LDLIBS SED USE_TORCH SMARTREDIS_DIR
270
271# $(call needs_save,CFLAGS) returns true (a nonempty string) if CFLAGS
272# was set on the command line or in config.mk (where it will appear as
273# a simple variable).
274needs_save = $(or $(filter command line,$(origin $(1))),$(filter simple,$(flavor $(1))))
275
276configure :
277	$(file > $(CONFIG))
278	$(foreach v,$(CONFIG_VARS),$(if $(call needs_save,$(v)),$(file >> $(CONFIG),$(v) := $($(v)))))
279	@echo "Configuration cached in $(CONFIG):"
280	@cat $(CONFIG)
281
282-include $(src.o:%.o=%.d)
283