# Load the configure script variables -include configure.mk ## ## Directories ## # Structure: # gray - top level # ├── src - source code # └── build - build artifacts # ├── bin - binaries # ├── lib - libraries # └── obj - objects SRCDIR = src BUILDDIR = build BINDIR = build/bin LIBDIR = build/lib OBJDIR = build/obj DIRS = $(BINDIR) $(OBJDIR) $(LIBDIR) ## ## Files ## # All Fortran source files SOURCES = $(wildcard $(SRCDIR)/*.f90) # All Generated makefiles describing object dependencies 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 += -O3 -J$(OBJDIR) CPPFLAGS += -DREVISION=\"$(GIT_REV)$(GIT_DIRTY)\" # Static build options ifdef STATIC LIBRARIES := $(LIBRARIES:so=a) LDFLAGS += -static endif ## ## Targets ## .PHONY: all clean install all: $(BINARIES) $(LIBRARIES) # Remove all generated files clean: rm -r $(BUILDDIR) # Install libraries, binaries and man pages install: $(BINARIES) $(LIBRARIES) doc/gray.1 install -Dm555 -t $(PREFIX)/bin $(BINDIR)/* install -Dm555 -t $(PREFIX)/lib $(LIBDIR)/* install -Dm644 -t $(PREFIX)/share/man/man1 doc/gray.1 # 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)) # 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' > $@ @sed -n 's@^[^!].*use \([^,]\+\),.*@$(OBJDIR)/\1.o \\@p' '$<' | sort -u >> $@ # Load the generated rules include $(DEPS) # Compile a generic Fortran source $(OBJDIR)/%.o: $(SRCDIR)/%.f90 | $(OBJDIR) $(FC) -cpp $(CPPFLAGS) $(FFLAGS) -c $< -o $@ # Create directories $(DIRS): mkdir -p $@