# Load the configure script variables -include configure.mk ## ## Directories ## # Structure: # gray - top level # ├── src - source code # ├── doc - documentation # └── build - build artifacts # ├── bin - binaries # ├── lib - libraries # ├── obj - objects # └── inc - files to #include SRCDIR = src BUILDDIR = build SHAREDIR = build/share BINDIR = build/bin LIBDIR = build/lib OBJDIR = build/obj INCDIR = build/inc PREFIX ?= /usr # Directories that need to be created DIRS = $(BINDIR) $(OBJDIR) $(INCDIR) $(LIBDIR) $(SHAREDIR) ## ## Files ## # All Fortran source files SOURCES = $(wildcard $(SRCDIR)/*.f90) # All Fortran object OBJECTS = $(patsubst $(SRCDIR)/%.f90,$(OBJDIR)/%.o,$(SOURCES)) # Generated makefiles describing object dependencies DEPS = $(OBJECTS:o=d) # Fortran modules to be bundled into libraries MODULES = $(filter-out $(OBJDIR)/main%,$(OBJECTS)) # Build outputs GRAY = $(BINDIR)/gray LIBGRAY = $(LIBDIR)/libgray BINARIES = $(GRAY) LIBRARIES = $(LIBGRAY).so ## ## Git information (used in the version string) ## # Short hash of the latest commit GIT_REV ?= $(shell git rev-parse --short HEAD) # Whether the worktree and the latest commit differs GIT_DIRTY ?= $(shell test -n "$$(git status --porcelain)" && echo "-dirty") ## ## Fortran compiler and flags ## # Note: can't use ?= for FC because GNU Make defaults to f77 FC = gfortran LD = gfortran FFLAGS += -J$(OBJDIR) -I$(INCDIR) -ffree-line-length-none -fPIC CPPFLAGS += -DREVISION=\"$(GIT_REV)$(GIT_DIRTY)\" -DPREFIX=\"$(PREFIX)\" # Static build options ifdef STATIC LIBRARIES := $(LIBRARIES:so=a) LDFLAGS += -static endif # Debug build options ifdef DEBUG FFLAGS += -ggdb -O0 -Wall -Wunused-parameter # Tricks to detect uninitialised memory FFLAGS += -finit-integer=7777777 -finit-real=snan -ffpe-trap=invalid else # Optimization level 3 FFLAGS += -O3 endif ## ## Targets ## .PHONY: all clean install docs all: $(BINARIES) $(LIBRARIES) # Remove all generated files clean: rm -r $(BUILDDIR) # Install libraries, binaries and documentation install: $(BINARIES) $(LIBRARIES) $(SHAREDIR)/doc $(SHAREDIR)/gray.1 install -Dm555 -t $(PREFIX)/bin $(BINDIR)/* install -Dm555 -t $(PREFIX)/lib $(LIBDIR)/* install -Dm644 -t $(PREFIX)/share/doc $(SHAREDIR)/doc/manual.* install -Dm644 -t $(PREFIX)/share/doc/res $(SHAREDIR)/doc/res/* install -Dm644 -t $(PREFIX)/share/man/man1 $(SHAREDIR)/gray.1 # dependencies $(OBJDIR)/%.o: $(OBJDIR)/%.d # GRAY binary $(GRAY): $(shell ./depend $(OBJDIR)/main.o) | $(BINDIR) $(LD) $(LDFLAGS) -o '$@' $^ # GRAY shared library $(LIBGRAY).so: $(MODULES) | $(LIBDIR) $(LD) -shared $(LDFLAGS) -o '$@' $^ # GRAY static library $(LIBGRAY).a($(MODULES)): | $(LIBDIR) $(LIBGRAY).a: $(LIBGRAY).a($(MODULES)) # GRAY static library when compiling from JETTO -include ../include.mk $(JLIBDIR)/libgray.a: $(LIBGRAY).a install -Dm755 '$<' '$@' # All documentation docs: $(SHAREDIR)/gray.1 $(SHAREDIR)/doc $(SHAREDIR)/doc: | $(SHAREDIR) +make -C doc cp -r doc/build/* $(SHAREDIR) # Generated man pages $(SHAREDIR)/gray.1: $(GRAY) doc/gray.1 | $(SHAREDIR) help2man '$<' -i doc/gray.1 -N -n 'beam-tracing code for EC waves' > '$@' # Visualise the dependency graph # Note: requires makefile2graph and graphviz graph.svg: Makefile make -Bdn \ | make2graph -b \ | awk -F'( -> )| ;|[[]' ' \ (/label/ && !/(\.o|bin\/gray)/) {bad[$$1]=1; next} \ /->/ {if (bad[$$1] || bad[$$2]) next} \ {print $$0}' \ | sed 's/label/fontsize=30,label/g; s/\.o//' \ | dot -Tsvg -o '$@' ## ## Generic rules ## # Rebuild everything if the makefile changed .EXTRA_PREREQS += Makefile # Automatic generation of the Fortran prerequisites # Note 1: this is needed because gfortran -M flag doesn't properly work; # Note 2: this assumes matching module/file names and no circular # dependencies (ie. the dependency graph is a DAG); $(OBJDIR)/%.d: $(SRCDIR)/%.f90 | $(OBJDIR) @printf '$(@:d=o): $< \\\n' > '$@' @grep -vE '^[[:blank:]]*use.*(intrinsic|iso_)' '$<' | \ sed -nE 's@^[[:blank:]]*use[[:blank:]]+'\ '([^,[:blank:]&]+).*@$(OBJDIR)/\1.o \\@p' | \ sort -u >> '$@' @sed -nE 's@^#include "(.+)"@$(INCDIR)/\1@p' '$<' >> '$@' # Load the generated rules include $(DEPS) # Compile a generic Fortran source $(OBJDIR)/%.o: $(SRCDIR)/%.f90 | $(OBJDIR) $(INCDIR) $(FC) -cpp $(CPPFLAGS) $(FFLAGS) -c '$<' -o '$@' # Generate Fortran code from shell script $(INCDIR)/%.inc: $(SRCDIR)/%.sh | $(INCDIR) sh '$<' > '$@' # Create directories $(DIRS): mkdir -p '$@'