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 := examples/navierstokes.c $(filter-out $(wildcard **/smartsim/*), $(sort $(wildcard $(PROBLEMDIR)/*.c)) $(sort $(wildcard $(SRCDIR)/*.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 CPPFLAGS += -I$(SMARTREDIS_DIR)/include 86 LDFLAGS += -L$(SMARTREDIS_DIR)/lib $(call pkgconf, --variable=ldflag_rpath $(petsc.pc))$(SMARTREDIS_DIR)/lib 87 LDLIBS += -lsmartredis 88 src.c += $(sort $(wildcard $(SRCDIR)/smartsim/*.c)) 89endif 90 91all: navierstokes 92 93# Diagnostic information 94info-basic: 95 $(info -----------------------------------------) 96 $(info | __ ______ _ ______________ |) 97 $(info | / / / / __ \/ | / / ____/ ____/ |) 98 $(info | / /_/ / / / / |/ / __/ / __/ |) 99 $(info | / __ / /_/ / /| / /___/ /___ |) 100 $(info | /_/ /_/\____/_/ |_/_____/_____/ |) 101 $(info -----------------------------------------) 102 $(info ) 103 $(info -----------------------------------------) 104 $(info ) 105 $(info Dependencies:) 106 $(info CEED_DIR = $(CEED_DIR)) 107 $(info PETSC_DIR = $(PETSC_DIR)) 108 $(info PETSC_ARCH = $(PETSC_ARCH)) 109 $(info ) 110 $(info Optional Dependencies:) 111 $(info SMARTREDIS_DIR = $(or $(SMARTREDIS_DIR),(not found))) 112 $(info USE_TORCH = $(USE_TORCH)) 113 $(info ) 114 $(info -----------------------------------------) 115 $(info ) 116 @true 117 118info: 119 $(info -----------------------------------------) 120 $(info | __ ______ _ ______________ |) 121 $(info | / / / / __ \/ | / / ____/ ____/ |) 122 $(info | / /_/ / / / / |/ / __/ / __/ |) 123 $(info | / __ / /_/ / /| / /___/ /___ |) 124 $(info | /_/ /_/\____/_/ |_/_____/_____/ |) 125 $(info -----------------------------------------) 126 $(info ) 127 $(info -----------------------------------------) 128 $(info ) 129 $(info Dependencies:) 130 $(info CEED_DIR = $(CEED_DIR)) 131 $(info PETSC_DIR = $(PETSC_DIR)) 132 $(info PETSC_ARCH = $(PETSC_ARCH)) 133 $(info ) 134 $(info Optional Dependencies:) 135 $(info SMARTREDIS_DIR = $(or $(SMARTREDIS_DIR),(not found))) 136 $(info USE_TORCH = $(USE_TORCH)) 137 $(info ) 138 $(info -----------------------------------------) 139 $(info ) 140 $(info Build Options:) 141 $(info CC = $(CC)) 142 $(info CFLAGS = $(CFLAGS)) 143 $(info CPPFLAGS = $(CPPFLAGS)) 144 $(info LDFLAGS = $(LDFLAGS)) 145 $(info LDLIBS = $(LDLIBS)) 146 $(info AR = $(AR)) 147 $(info ARFLAGS = $(ARFLAGS)) 148 $(info OPT = $(OPT)) 149 $(info AFLAGS = $(AFLAGS)) 150 $(info ASAN = $(or $(ASAN),(empty))) 151 $(info VERBOSE = $(or $(V),(empty)) [verbose=$(if $(V),on,off)]) 152 $(info ) 153 $(info -----------------------------------------) 154 $(info ) 155 $(info Format and Style Options:) 156 $(info CLANG_FORMAT = $(CLANG_FORMAT)) 157 $(info FORMAT_OPTS = $(FORMAT_OPTS)) 158 $(info CLANG_TIDY = $(CLANG_TIDY)) 159 $(info TIDY_OPTS = $(TIDY_OPTS)) 160 $(info TIDY_FILE_OPTS = $(TIDY_FILE_OPTS)) 161 $(info ) 162 $(info -----------------------------------------) 163 $(info ) 164 $(info Git:) 165 $(info describe = $(GIT_DESCRIBE)) 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 177$(OBJDIR)/navierstokes: $(src.o) | navierstokes 178navierstokes: $(src.o) | $(petsc.pc) $(ceed.pc) 179 $(call quiet,LINK.o) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $(OBJDIR)/$@ 180 181.SECONDEXPANSION: # to expand $$(@D)/.DIR 182%/.DIR : 183 @mkdir -p $(@D) 184 @touch $@ 185 186# Quiet, color output 187quiet ?= $($(1)) 188 189# Inject Git/version macros when compiling honee-version.c 190GIT_DESCRIBE := $(shell git -c safe.directory=$PWD describe --always --dirty 2>/dev/null || printf "unknown\n") 191 192$(OBJDIR)/src/honee-config.o: Makefile 193$(OBJDIR)/src/honee-config.o src/honee-config.c.tidy: CONFIGFLAGS += -DHONEE_GIT_VERSION="\"$(GIT_DESCRIBE)\"" 194$(OBJDIR)/src/honee-config.o src/honee-config.c.tidy: CONFIGFLAGS += -DHONEE_BUILD_CONFIGURATION="\"// Build Configuration:$(foreach v,$(CONFIG_VARS),\n$(v) = $($(v)))\"" 195 196$(OBJDIR)/%.o : %.c | $$(@D)/.DIR 197 $(call quiet,CC) $(CPPFLAGS) $(CFLAGS) $(CONFIGFLAGS) -c -o $@ $(abspath $<) 198 199$(OBJDIR)/%.o : %.cpp | $$(@D)/.DIR 200 $(call quiet,CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(abspath $<) 201 202print: $(petsc.pc) $(ceed.pc) 203 $(info CC : $(CC)) 204 $(info CFLAGS : $(CFLAGS)) 205 $(info CPPFLAGS: $(CPPFLAGS)) 206 $(info LDFLAGS : $(LDFLAGS)) 207 $(info LDLIBS : $(LDLIBS)) 208 $(info OPT : $(OPT)) 209 @true 210 211print-% : 212 $(info [ variable name]: $*) 213 $(info [ origin]: $(origin $*)) 214 $(info [ flavor]: $(flavor $*)) 215 $(info [ value]: $(value $*)) 216 $(info [expanded value]: $($*)) 217 $(info ) 218 @true 219 220clean: 221 $(RM) -r $(OBJDIR) navierstokes *.vtu *.bin* *.csv *.png 222 223$(petsc.pc): 224 $(if $(wildcard $@),,$(error \ 225 PETSc config not found. Please set PETSC_DIR and PETSC_ARCH)) 226 227.PHONY: all print clean 228 229# Define test files 230examples.c := $(sort $(wildcard examples/*.c)) 231examples := $(examples.c:examples/%.c=$(OBJDIR)/%) 232tests.smartsim := test-smartsim 233tests += $(tests.smartsim:%=$(OBJDIR)/%) 234 235$(tests.smartsim:%=$(OBJDIR)/%): $(OBJDIR)/navierstokes 236 237# Documentation 238DOXYGEN ?= doxygen 239DOXYGENOPTS ?= -q 240doxygen : 241 $(DOXYGEN) $(DOXYGENOPTS) Doxyfile 242 243SPHINXOPTS = 244SPHINXBUILD = sphinx-build 245SPHINXAUTOBUILD = sphinx-autobuild 246SPHINXPROJ = HONEE 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) $(CONFIGFLAGS) --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) --search '$(subsearch)' $(<:$(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 329subsearch ?= .* 330realsearch = $(search:%=%%) 331matched = $(foreach pattern,$(realsearch),$(filter $(OBJDIR)/$(pattern),$(tests) $(examples))) 332 333# Test 334test : $(matched:$(OBJDIR)/%=run-%) 335 336tst : ;@$(MAKE) $(MFLAGS) V=$(V) test 337 338# Test with TAP output 339prove : $(matched) 340 $(info Running unit tests) 341 $(info - Testing with libCEED backends: $(CEED_BACKENDS)) 342 $(info - Testing on $(NPROC_TEST) processes) 343 $(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)' 344 345prv : ;@$(MAKE) $(MFLAGS) V=$(V) prove 346 347prove-all : 348 +$(MAKE) prove realsearch=% 349 350# Test with JUNIT output 351junit-% : $(OBJDIR)/% 352 @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)/%=%) 353 354junit : $(matched:$(OBJDIR)/%=junit-%) 355 356 357# Configure 358# "make configure" detects any variables passed on the command line or 359# previously set in config.mk, caching them in config.mk as simple 360# (:=) variables. Variables set in config.mk or on the command line 361# take precedence over the defaults provided in the file. Typical 362# usage: 363# 364# make configure CC=/path/to/my/cc CUDA_DIR=/opt/cuda 365# make 366# make prove 367# 368# The values in the file can be updated by passing them on the command 369# line, e.g., 370# 371# make configure CC=/path/to/other/clang 372 373# All variables to consider for caching 374CONFIG_VARS = CEED_DIR PETSC_DIR PETSC_ARCH OPT CFLAGS CPPFLAGS AR ARFLAGS LDFLAGS LDLIBS SED USE_TORCH SMARTREDIS_DIR 375 376# $(call needs_save,CFLAGS) returns true (a nonempty string) if CFLAGS 377# was set on the command line or in config.mk (where it will appear as 378# a simple variable). 379needs_save = $(or $(filter command line,$(origin $(1))),$(filter simple,$(flavor $(1)))) 380 381configure : 382 $(file > $(CONFIG)) 383 $(foreach v,$(CONFIG_VARS),$(if $(call needs_save,$(v)),$(file >> $(CONFIG),$(v) := $($(v))))) 384 @echo "Configuration cached in $(CONFIG):" 385 @cat $(CONFIG) 386 387-include $(src.o:%.o=%.d) 388