1# -*- mode: makefile-gmake -*- 2include petscdir.mk 3 4# If $(PETSC_ARCH) is empty, this defines it and PETSC_DIR 5include ./$(PETSC_ARCH)/lib/petsc/conf/petscvariables 6include ./lib/petsc/conf/variables 7 8OBJDIR := $(PETSC_ARCH)/obj 9LIBDIR := $(PETSC_ARCH)/lib 10 11pkgs := sys vec mat dm ksp snes ts tao 12pkgs_reverse := tao ts snes ksp dm mat vec sys 13 14# $(call SONAME_FUNCTION,libfoo,abiversion) 15SONAME_FUNCTION ?= $(1).$(SL_LINKER_SUFFIX).$(2) 16# $(call SL_LINKER_FUNCTION,libfoo,abiversion,libversion) 17SL_LINKER_FUNCTION ?= -shared -Wl,-soname,$(call SONAME_FUNCTION,$(notdir $(1)),$(2)) 18 19PETSC_VERSION_MAJOR := $(shell awk '/define PETSC_VERSION_MAJOR/{print $$3;}' ./include/petscversion.h) 20PETSC_VERSION_MINOR := $(shell awk '/define PETSC_VERSION_MINOR/{print $$3;}' ./include/petscversion.h) 21PETSC_VERSION_SUBMINOR := $(shell awk '/define PETSC_VERSION_SUBMINOR/{print $$3;}' ./include/petscversion.h) 22PETSC_VERSION_RELEASE := $(shell awk '/define PETSC_VERSION_RELEASE/{print $$3;}' ./include/petscversion.h) 23 24libpetsc_abi_version := $(PETSC_VERSION_MAJOR).$(if $(filter $(PETSC_VERSION_RELEASE), 0 -2 -3 -4 -5),0)$(PETSC_VERSION_MINOR) 25libpetsc_lib_version := $(libpetsc_abi_version).$(PETSC_VERSION_SUBMINOR) 26soname_function = $(call SONAME_FUNCTION,$(1),$(libpetsc_abi_version)) 27libname_function = $(call SONAME_FUNCTION,$(1),$(libpetsc_lib_version)) 28absbasename_all = $(basename $(basename $(basename $(basename $(abspath $(1))))))# arch/lib/libpetsc.so.3.8.0 -> /path/to/arch/lib/libpetsc 29sl_linker_args = $(call SL_LINKER_FUNCTION,$(call absbasename_all,$@),$(libpetsc_abi_version),$(libpetsc_lib_version)) 30 31libpetsc_shared := $(LIBDIR)/libpetsc.$(SL_LINKER_SUFFIX) 32libpetsc_soname := $(call soname_function,$(LIBDIR)/libpetsc) 33libpetsc_libname := $(call libname_function,$(LIBDIR)/libpetsc) 34libpetsc_static := $(LIBDIR)/libpetsc.$(AR_LIB_SUFFIX) 35libpetscpkgs_shared := $(foreach pkg, $(pkgs), $(LIBDIR)/libpetsc$(pkg).$(SL_LINKER_SUFFIX)) 36libpetscpkgs_soname := $(foreach pkg, $(pkgs), $(call soname_function,$(LIBDIR)/libpetsc$(pkg))) 37libpetscpkgs_libname := $(foreach pkg, $(pkgs), $(call libname_function,$(LIBDIR)/libpetsc$(pkg))) 38libpetscpkgs_static := $(foreach pkg, $(pkgs_reverse), $(LIBDIR)/libpetsc$(pkg).$(AR_LIB_SUFFIX)) 39 40ifeq ($(PETSC_WITH_EXTERNAL_LIB),) 41 libpetscall_shared := $(libpetscpkgs_shared) 42 libpetscall_soname := $(libpetscpkgs_soname) 43 libpetscall_libname := $(libpetscpkgs_libname) 44 libpetscall_static := $(libpetscpkgs_static) 45else 46 libpetscall_shared := $(libpetsc_shared) 47 libpetscall_soname := $(libpetsc_soname) 48 libpetscall_libname := $(libpetsc_libname) 49 libpetscall_static := $(libpetsc_static) 50endif 51libpetscall := $(if $(filter-out no,$(BUILDSHAREDLIB)),$(libpetscall_shared),$(libpetscall_static)) 52 53generated := $(PETSC_ARCH)/lib/petsc/conf/files 54 55libs : $(libpetscall) 56 57.PHONY: libs 58 59.SECONDEXPANSION: # to expand $$(@D)/.DIR 60 61# Test framework includes rules and variables relevant to both build and test 62include ./gmakefile.test # This must be below the all target because it includes rules 63 64$(generated) : $(petscconf) $(petscvariables) config/gmakegen.py 65 $(PYTHON) ./config/gmakegen.py --petsc-arch=$(PETSC_ARCH) 66 67# Skip including generated files (which triggers rebuilding them) when we're just going to clean anyway. 68ifneq ($(filter-out help clean distclean check info gmakeinfo checkbadSource checkbadFileChange deletefortranstubs allfortranstubs allfortranstubsinplace alletags clangformat checkclangformat lint get%,$(MAKECMDGOALS:clean%=clean)),) 69include $(generated) 70endif 71 72# implies shared libraries with MS compilers 73ifeq ($(PETSC_DLL_EXPORTS),1) 74$(OBJDIR)/%.o : CCPPFLAGS+=-Dpetsc_EXPORTS 75$(OBJDIR)/%.o : CXXCPPFLAGS+=-Dpetsc_EXPORTS 76$(OBJDIR)/%.o : CUDACPPFLAGS+=-Dpetsc_EXPORTS 77endif 78 79langs := F F90 cxx c 80ifneq ($(CUDAC),) 81langs += cu 82endif 83ifneq ($(HIPC),) 84langs += hip.cpp 85endif 86ifneq ($(SYCLC),) 87langs += sycl.cxx 88endif 89ifneq ($(KOKKOS_LIB),) 90langs += kokkos.cxx 91endif 92 93concatlang = $(foreach lang, $(langs), $(srcs-$(1).$(lang):%.$(lang)=$(OBJDIR)/%.o)) 94srcs.o := $(foreach pkg, $(pkgs), $(call concatlang,$(pkg))) 95srcs.tidy := $(foreach pkg, $(pkgs), $(srcs-$(pkg).c:%.c=$(OBJDIR)/%.tidy)) 96concatlangsrc = $(foreach lang, $(langs), $(srcs-$(1).$(lang))) 97csrc := $(foreach pkg, $(pkgs), $(srcs-$(pkg).c)) 98showcsrc: 99 -@echo $(csrc) 100 101define SHARED_RECIPE_DLL 102 @$(RM) $@ dllcmd.${PETSC_ARCH} 103 @cygpath -w $^ > dllcmd.${PETSC_ARCH} 104 $(call quiet,CLINKER) $(sl_linker_args) -o $@ @dllcmd.${PETSC_ARCH} $(PETSC_EXTERNAL_LIB_BASIC) 105 @$(RM) dllcmd.${PETSC_ARCH} 106endef 107 108define SHARED_RECIPE_ATFILE 109 $(file > $@.args,$^) 110 $(call quiet,CLINKER) $(sl_linker_args) -o $@ @$@.args $(PETSC_EXTERNAL_LIB_BASIC) 111 @$(RM) $@.args 112endef 113 114define SHARED_RECIPE_DEFAULT 115 $(call quiet,CLINKER) $(sl_linker_args) -o $@ $^ $(PETSC_EXTERNAL_LIB_BASIC) 116endef 117 118GMAKE4 = $(if $(findstring 3.99,$(firstword $(sort 3.99 $(MAKE_VERSION)))),1,) 119SHARED_RECIPE = $(if $(findstring -LD,$(SL_LINKER_FUNCTION)),$(SHARED_RECIPE_DLL),$(if $(PCC_AT_FILE),$(if $(GMAKE4),$(SHARED_RECIPE_ATFILE),$(SHARED_RECIPE_DEFAULT)),$(SHARED_RECIPE_DEFAULT))) 120 121# with-single-library=1 (default) 122$(libpetsc_libname) : $(srcs.o) | $$(@D)/.DIR 123 $(SHARED_RECIPE) 124ifneq ($(DSYMUTIL),true) 125 $(call quiet,DSYMUTIL) $@ 126endif 127 128$(libpetsc_static) : obj := $(srcs.o) 129 130define ARCHIVE_RECIPE_WIN32FE_LIB 131 @$(RM) $@ $@.args 132 @cygpath -w $^ > $@.args 133 $(call quiet,AR) $(AR_FLAGS) $@ @$@.args 134 @$(RM) $@.args 135endef 136 137define ARCHIVE_RECIPE_ARGFILE 138 @$(RM) $@ 139 $(file > $@.args,$^) 140 $(call quiet,AR) $(AR_FLAGS) $@ @$@.args 141 @$(RM) $@.args 142 $(call quiet,RANLIB) $@ 143endef 144 145define ARCHIVE_RECIPE_DEFAULT 146 @$(RM) $@ 147 $(call quiet,AR) $(AR_FLAGS) $@ $^ 148 $(call quiet,RANLIB) $@ 149endef 150 151%.$(AR_LIB_SUFFIX) : $$(obj) | $$(@D)/.DIR 152 $(if $(findstring win32fe_lib,$(AR)),$(ARCHIVE_RECIPE_WIN32FE_LIB),$(if $(findstring yes,$(AR_ARGFILE)),$(if $(GMAKE4),$(ARCHIVE_RECIPE_ARGFILE),$(ARCHIVE_RECIPE_DEFAULT)),$(ARCHIVE_RECIPE_DEFAULT))) 153 154# with-single-library=0 155libpkg = $(foreach pkg, $1, $(LIBDIR)/libpetsc$(pkg).$(SL_LINKER_SUFFIX)) 156define pkg_template 157 $(LIBDIR)/libpetsc$(1).$(AR_LIB_SUFFIX) : $(call concatlang,$(1)) 158 $(call libname_function,$(LIBDIR)/libpetsc$(1)) : $(call concatlang,$(1)) 159endef 160$(foreach pkg,$(pkgs),$(eval $(call pkg_template,$(pkg)))) 161$(call libname_function,$(LIBDIR)/libpetscvec) : libdep := $(call libpkg,sys) 162$(call libname_function,$(LIBDIR)/libpetscmat) : libdep := $(call libpkg,vec sys) 163$(call libname_function,$(LIBDIR)/libpetscdm) : libdep := $(call libpkg,mat vec sys) 164$(call libname_function,$(LIBDIR)/libpetscksp) : libdep := $(call libpkg,dm mat vec sys) 165$(call libname_function,$(LIBDIR)/libpetscsnes) : libdep := $(call libpkg,ksp dm mat vec sys) 166$(call libname_function,$(LIBDIR)/libpetscts) : libdep := $(call libpkg,snes ksp dm mat vec sys) 167$(call libname_function,$(LIBDIR)/libpetsctao) : libdep := $(call libpkg,snes ksp dm mat vec sys) 168 169# The package libraries technically depend on each other (not just in an order-only way), but only 170# ABI changes like new or removed symbols requires relinking the dependent libraries. ABI should 171# only occur when a header is changed, which would trigger recompilation and relinking anyway. 172# RELINK=1 causes dependent libraries to be relinked anyway. 173ifeq ($(RELINK),1) 174 libdep_true = $$(libdep) 175 libdep_order = 176else 177 libdep_true = 178 libdep_order = $$(libdep) 179endif 180$(libpetscpkgs_libname) : $(libdep_true) | $(libdep_order) $$(@D)/.DIR 181 $(SHARED_RECIPE) 182ifneq ($(DSYMUTIL),true) 183 $(call quiet,DSYMUTIL) $@ 184endif 185 186%.$(SL_LINKER_SUFFIX) : $(call libname_function,%) | $(call soname_function,%) 187 @ln -sf $(notdir $<) $@ 188 189$(call soname_function,%) : $(call libname_function,%) 190 @ln -sf $(notdir $<) $@ 191 192.PRECIOUS: $(call soname_function,%) 193 194$(OBJDIR)/%.o : %.sycl.cxx | $$(@D)/.DIR 195 $(PETSC_COMPILE.sycl.cxx) $(abspath $<) -o $@ 196 197$(OBJDIR)/%.o : %.c | $$(@D)/.DIR 198 $(PETSC_COMPILE.c) $(abspath $<) -o $@ 199 200$(OBJDIR)/%.o : %.kokkos.cxx | $$(@D)/.DIR 201 $(PETSC_COMPILE.kokkos.cxx) $(abspath $<) -o $@ 202 203$(OBJDIR)/%.o : %.cxx | $$(@D)/.DIR 204 $(PETSC_COMPILE.cxx) $(abspath $<) -o $@ 205 206$(OBJDIR)/%.o : %.hip.cpp | $$(@D)/.DIR 207 $(PETSC_COMPILE.hip.cpp) $(abspath $<) -o $@ 208 209$(OBJDIR)/%.o : %.cu | $$(@D)/.DIR 210 $(PETSC_COMPILE.cu) $(abspath $<) -o $@ # Compile first so that if there is an error, it comes from a normal compile 211 @$(PETSC_GENDEPS.cu) $(abspath $<) -o $(@:%.o=%.d) # Generate the dependencies for later 212 213FCMOD = cd 214$(OBJDIR)/%.o : %.F | $$(@D)/.DIR 215ifeq ($(FC_MODULE_OUTPUT_FLAG),) 216 $(call quiet,FCMOD) $(MODDIR) && $(FC) -c $(FC_FLAGS) $(FFLAGS) $(FCPPFLAGS) $(FC_DEPFLAGS) $(abspath $<) -o $(abspath $@) 217else 218 $(PETSC_COMPILE.F) $(abspath $<) -o $@ $(FC_MODULE_OUTPUT_FLAG)$(MODDIR) 219endif 220 -@$(GFORTRAN_DEP_CLEANUP) 221 222$(OBJDIR)/%.o : %.F90 | $$(@D)/.DIR 223ifeq ($(FC_MODULE_OUTPUT_FLAG),) 224 $(call quiet,FCMOD) $(MODDIR) && $(FC) -c $(FC_FLAGS) $(FFLAGS) $(FCPPFLAGS) $(FC_DEPFLAGS) $(abspath $<) -o $(abspath $@) 225else 226 $(PETSC_COMPILE.F) $(abspath $<) -o $@ $(FC_MODULE_OUTPUT_FLAG)$(MODDIR) 227endif 228 -@$(GFORTRAN_DEP_CLEANUP) 229 230# Combine with Jacob's massive lint project? 231# Only works with ./configure --with-mpi=0 since clang-tidy cannot find MPI include files (love MPI compiler wrappers, the worse thing to come from MPI) 232$(OBJDIR)/%.tidy : %.c | $$(@D)/.DIR 233 @clang-tidy --checks='clang-diagnostic-*,-clang-analyzer-*,-clang-analyzer-security.insecureAPI.rand,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,clang-analyzer-deadcode.DeadStores,bugprone-too-small-loop-variable' $(abspath $<) -- ${CCPPFLAGS} 234 235clang-tidy: $(srcs.tidy) 236 237# Hack: manual dependencies on object files 238ifeq ($(MPI_IS_MPIUNI),1) 239 MPIUNI_MOD := $(MODDIR)/mpiuni.mod 240 $(OBJDIR)/src/sys/mpiuni/fsrc/somempifort.o : $(OBJDIR)/src/sys/mpiuni/f90-mod/mpiunimod.o 241endif 242$(OBJDIR)/src/sys/f90-mod/petscsysmod.o : $(if $(MPIUNI_MOD),$(OBJDIR)/src/sys/mpiuni/f90-mod/mpiunimod.o) 243$(OBJDIR)/src/vec/f90-mod/petscvecmod.o : $(OBJDIR)/src/sys/f90-mod/petscsysmod.o 244$(OBJDIR)/src/mat/f90-mod/petscmatmod.o : $(OBJDIR)/src/vec/f90-mod/petscvecmod.o 245$(OBJDIR)/src/dm/f90-mod/petscdmmod.o : $(OBJDIR)/src/mat/f90-mod/petscmatmod.o 246$(OBJDIR)/src/dm/f90-mod/petscdmdamod.o : $(OBJDIR)/src/dm/f90-mod/petscdmmod.o 247$(OBJDIR)/src/dm/f90-mod/petscdmplexmod.o : $(OBJDIR)/src/dm/f90-mod/petscdmmod.o 248$(OBJDIR)/src/dm/f90-mod/petscdmswarmmod.o : $(OBJDIR)/src/dm/f90-mod/petscdmmod.o 249$(OBJDIR)/src/ksp/f90-mod/petsckspdefmod.o : $(OBJDIR)/src/dm/f90-mod/petscdmplexmod.o 250$(OBJDIR)/src/ksp/f90-mod/petscpcmod.o : $(OBJDIR)/src/ksp/f90-mod/petsckspdefmod.o 251$(OBJDIR)/src/ksp/f90-mod/petsckspmod.o : $(OBJDIR)/src/ksp/f90-mod/petscpcmod.o 252$(OBJDIR)/src/snes/f90-mod/petscsnesmod.o : $(OBJDIR)/src/ksp/f90-mod/petsckspmod.o 253$(OBJDIR)/src/ts/f90-mod/petsctsmod.o : $(OBJDIR)/src/snes/f90-mod/petscsnesmod.o 254$(OBJDIR)/src/tao/f90-mod/petsctaomod.o : $(OBJDIR)/src/ts/f90-mod/petsctsmod.o 255# F2003 interface 256$(OBJDIR)/src/sys/objects/f2003-src/fsrc/optionenum.o : $(OBJDIR)/src/sys/f90-mod/petscsysmod.o 257$(OBJDIR)/src/sys/classes/bag/f2003-src/fsrc/bagenum.o : $(OBJDIR)/src/sys/f90-mod/petscsysmod.o 258 259# all sources should get recompiled when petscvariables changes (i.e when configure is rerun or when petscvariables is manually edited.) 260$(srcs.o) : $(petscvariables) 261 262.PHONY: clean all print clang-tidy 263 264clean: 265 ${RM} -r $(OBJDIR) $(LIBDIR)/libpetsc* $(MODDIR)/petsc*.mod $(MPIUNI_MOD) $(generated) 266 267# make print VAR=the-variable 268print: 269 $(info $($(VAR))) 270 @true 271 272 273allobj.d := $(srcs.o:%.o=%.d) 274# Tell make that allobj.d are all up to date. Without this, the include 275# below has quadratic complexity, taking more than one second for a 276# do-nothing build of PETSc (much worse for larger projects) 277$(allobj.d) : ; 278 279gmakeinfo: 280 -@echo "==========================================" 281 -@echo " " 282 -@echo "See documentation/faq.html and documentation/bugreporting.html" 283 -@echo "for help with installation problems. Please send EVERYTHING" 284 -@echo "printed out below when reporting problems. Please check the" 285 -@echo "mailing list archives and consider subscribing." 286 -@echo " " 287 -@echo " https://petsc.org/release/community/mailing/" 288 -@echo " " 289 -@echo "==========================================" 290 -@echo Starting make run on `hostname` at `date +'%a, %d %b %Y %H:%M:%S %z'` 291 -@echo Machine characteristics: `uname -a` 292 -@echo "-----------------------------------------" 293 -@echo "Using PETSc directory: ${PETSC_DIR}" 294 -@echo "Using PETSc arch: ${PETSC_ARCH}" 295 -@echo "-----------------------------------------" 296 -@grep "define PETSC_VERSION" ${PETSC_DIR}/include/petscversion.h | ${SED} "s/........//" | head -n 7 297 -@echo "-----------------------------------------" 298 -@echo "Using configure Options: ${CONFIGURE_OPTIONS}" 299 -@echo "Using configuration flags:" 300 -@grep "#define " ${PETSCCONF_H} | tail -n +2 301 -@echo "-----------------------------------------" 302 -@echo "Using C compile: ${PETSC_CCOMPILE_SINGLE}" 303 -@if [ "${MPICC_SHOW}" != "" ]; then \ 304 printf "mpicc -show: %b\n" "${MPICC_SHOW}";\ 305 fi; \ 306 printf "C compiler version: %b\n" "${C_VERSION}"; \ 307 if [ "${CXX}" != "" ]; then \ 308 echo "Using C++ compile: ${PETSC_CXXCOMPILE_SINGLE}";\ 309 if [ "${MPICXX_SHOW}" != "" ]; then \ 310 printf "mpicxx -show: %b\n" "${MPICXX_SHOW}"; \ 311 fi;\ 312 printf "C++ compiler version: %b\n" "${Cxx_VERSION}"; \ 313 fi 314 -@if [ "${FC}" != "" ]; then \ 315 echo "Using Fortran compile: ${PETSC_FCOMPILE_SINGLE}";\ 316 if [ "${MPIFC_SHOW}" != "" ]; then \ 317 printf "mpif90 -show: %b\n" "${MPIFC_SHOW}"; \ 318 fi; \ 319 printf "Fortran compiler version: %b\n" "${FC_VERSION}"; \ 320 fi 321 -@if [ "${CUDAC}" != "" ]; then \ 322 echo "Using CUDA compile: ${PETSC_CUCOMPILE_SINGLE}";\ 323 fi 324 -@if [ "${CLANGUAGE}" = "CXX" ]; then \ 325 echo "Using C++ compiler to compile PETSc";\ 326 fi 327 -@echo "-----------------------------------------" 328 -@echo "Using C/C++ linker: ${PCC_LINKER}" 329 -@echo "Using C/C++ flags: ${PCC_LINKER_FLAGS}" 330 -@if [ "${FC}" != "" ]; then \ 331 echo "Using Fortran linker: ${FC_LINKER}";\ 332 echo "Using Fortran flags: ${FC_LINKER_FLAGS}";\ 333 fi 334 -@echo "-----------------------------------------" 335 -@echo "Using system modules: ${LOADEDMODULES}" 336 -@if [ "${MPI_IS_MPIUNI}" = "1" ]; then \ 337 echo Using mpi.h: mpiuni; \ 338 else \ 339 TESTDIR=`mktemp -q -d -t petscmpi-XXXXXXXX` && \ 340 echo '#include <mpi.h>' > $${TESTDIR}/mpitest.c && \ 341 BUF=`${CPP} ${PETSC_CPPFLAGS} ${PETSC_CC_INCLUDES} $${TESTDIR}/mpitest.c |grep 'mpi\.h' | ( head -1 ; cat > /dev/null )` && \ 342 echo Using mpi.h: $${BUF}; ${RM} -rf $${TESTDIR}; \ 343 fi 344 -@echo "-----------------------------------------" 345 -@echo "Using libraries: ${PETSC_LIB}" 346 -@echo "------------------------------------------" 347 -@echo "Using mpiexec: ${MPIEXEC}" 348 -@echo "------------------------------------------" 349 -@echo "Using MAKE: ${MAKE}" 350 -@echo "Default MAKEFLAGS: MAKE_NP:${MAKE_NP} MAKE_LOAD:${MAKE_LOAD} MAKEFLAGS:${MAKEFLAGS}" 351 -@echo "==========================================" 352 353-include $(allobj.d) 354