rework the build system

- unify the three makefiles into a single generic one

- automatically generate link targets (via the `depend` script)
  and object dependencies (via a make rule)

- move all build artifacts under the build/ directory

- replace svn with git for the version information

- add a `static` variable to toggle between static/shared builds

- add a target to build the dependency graph of GRAY modules
This commit is contained in:
Michele Guerini Rocco 2021-11-18 15:02:53 +00:00 committed by Michele Guerini Rocco
parent 3a9fb6539f
commit ad7852d9c2
Signed by: rnhmjoj
GPG Key ID: BFBAF4C975F76450
5 changed files with 157 additions and 278 deletions

2
.gitignore vendored Executable file
View File

@ -0,0 +1,2 @@
.DS_store
build

194
Makefile
View File

@ -1,81 +1,137 @@
# Executable name ##
EXE=gray ## Directories
##
# Objects list # Structure:
MAINOBJ=main.o # gray - top level
OTHOBJ= beamdata.o beams.o conical.o const_and_precisions.o coreprofiles.o \ # ├── src - source code
dierckx.o dispersion.o eccd.o eierf.o errcodes.o graycore.o \ # └── build - build artifacts
gray_params.o equilibrium.o limiter.o magsurf_data.o math.o minpack.o multipass.o \ # ├── bin - binaries
numint.o pec.o polarization.o quadpack.o reflections.o simplespline.o units.o utils.o # ├── lib - libraries
# └── obj - objects
SRCDIR = src
BUILDDIR = build
BINDIR = build/bin
LIBDIR = build/lib
OBJDIR = build/obj
DIRS = $(BINDIR) $(OBJDIR) $(LIBDIR)
# Alternative search paths ##
vpath %.f90 src ## Files
vpath %.f src ##
# Fortran compiler name and flags # 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) $(GRAY)sum
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 FC = gfortran
LD = gfortran LD = gfortran
FFLAGS=-O3 -fPIC FFLAGS += -O3 -J$(OBJDIR)
LDFLAGS= -static-libgfortran -static-libgcc CPPFLAGS += -DREVISION=\"$(GIT_REV)$(GIT_DIRTY)\"
# LDFLAGS= -static-libgfortran -lgfortran -lgcc -lSystem -nodefaultlibs
LIBS= /usr/local/lib/libquadmath.a
# FFLAGS=-Wall -g -finit-real=nan -ffpe-trap=invalid -fcheck=all -fbounds-check
DIRECTIVES = -DREVISION="'$(shell svnversion src)'" # Static build options
ifdef STATIC
LIBRARIES := $(LIBRARIES:so=a)
LDFLAGS += -static
endif
all: $(EXE) ##
## Targets
##
# Build executable from object files .PHONY: all clean install
$(EXE): $(MAINOBJ) $(OTHOBJ)
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
# Dependencies on modules all: $(BINARIES) $(LIBRARIES)
main.o: const_and_precisions.o beams.o coreprofiles.o equilibrium.o \
graycore.o gray_params.o reflections.o
graycore.o: const_and_precisions.o beamdata.o beams.o coreprofiles.o \
dispersion.o eccd.o equilibrium.o errcodes.o gray_params.o \
pec.o polarization.o limiter.o units.o utils.o reflections.o multipass.o
beams.o: const_and_precisions.o dierckx.o reflections.o simplespline.o utils.o
beamdata.o: const_and_precisions.o gray_params.o
conical.o: const_and_precisions.o
coreprofiles.o: const_and_precisions.o dierckx.o gray_params.o simplespline.o \
utils.o
dierckx.o: const_and_precisions.o
dispersion.o: const_and_precisions.o eierf.o errcodes.o math.o quadpack.o
eccd.o: const_and_precisions.o conical.o dierckx.o errcodes.o magsurf_data.o \
numint.o
eierf.o: const_and_precisions.o
errcodes.o: const_and_precisions.o
gray_params.o: const_and_precisions.o utils.o
equilibrium.o: const_and_precisions.o dierckx.o limiter.o minpack.o \
reflections.o simplespline.o utils.o gray_params.o
magsurf_data.o: const_and_precisions.o gray_params.o equilibrium.o dierckx.o \
reflections.o simplespline.o units.o utils.o
math.o: const_and_precisions.o
minpack.o: const_and_precisions.o
multipass.o: const_and_precisions.o beamdata.o equilibrium.o gray_params.o \
polarization.o reflections.o
numint.o: const_and_precisions.o
pec.o: const_and_precisions.o beamdata.o equilibrium.o gray_params.o \
magsurf_data.o utils.o
polarization.o: const_and_precisions.o
quadpack.o: const_and_precisions.o
reflections.o: const_and_precisions.o limiter.o utils.o
simplespline.o: const_and_precisions.o
utils.o: const_and_precisions.o
# General object compilation command # Remove all generated files
%.o: %.f90
$(FC) -cpp $(DIRECTIVES) $(FFLAGS) -c $<
.PHONY: clean install
# Remove output files
clean: clean:
rm -rf *.o *.mod $(EXE) rm -r $(BUILDDIR)
install: # Install libraries, binaries and man pages
@if [ -f $(EXE) ]; then \ install: $(BINARIES) $(LIBRARIES) gray.1
cp $(EXE) ~/bin/; \ install -Dm555 -t $(PREFIX)/bin $(BINDIR)/*
else \ install -Dm555 -t $(PREFIX)/lib $(LIBDIR)/*
echo File $(EXE) does not exist. Run \'make\' first; \ install -Dm644 -t $(PREFIX)/share/man/man1 gray.1
fi
# GRAY binary
$(GRAY): $(shell ./depend $(OBJDIR)/main.o) | $(BINDIR)
$(LD) $(LDFLAGS) -o $@ $^
# sum variant
$(GRAY)sum: $(shell ./depend $(OBJDIR)/main-sum.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 $@

View File

@ -1,132 +0,0 @@
# Makefile for JETTO fortran 90 library 'gray'
# Author: Lorenzo Figini (figini@ifp.cnr.it)
#
# Derived from
# Makefile for JETTO fortran 77 library 'frantic'
# Author: Derek Harting (d.harting@fz-juelich.de)
# and
# Makefile for ITCequ Fortran 90 library - definitions
# P. Strand, elfps@chalmers.se
# G. Corrigan, gcor@jet.uk
# D. Harting, d.harting@fz-juelich.de
# Set the environment from the top-level Makefile of JETTO
# --------------------------------------------------------
include ../include.mk
# Alternative search paths
vpath %.f90 src
DIRECTIVES = -DEXTBES -DREVISION="rev.166 JETTO" #'$(shell svnversion src)'"
# library name
# ------------
LIBNAME=$(JLIBDIR)/libgray.a
# List source and object files
# ----------------------------
FSRC=$(wildcard src/*.f90)
FOBJ0=$(subst src/,,$(FSRC))
FOBJ=$(FOBJ0:.f90=.o)
########################################
# Set up compiler specific environment #
########################################
# set default compiler
# --------------------
FC=$(F90)
# Set compiler debug and optimization flags
# -----------------------------------------
ifeq ("$(DBG)","")
FFLAGS= $(AUTO) -O3 -Mpreprocess
# FFLAGS=-O3 -cpp
else
FFLAGS= $(AUTO) -O0 -Mpreprocess -g -Minform=inform -Mbounds -Mchkptr
# FFLAGS=-Wall -g -finit-real=nan -ffpe-trap=invalid -fcheck=all -fbounds-check
endif
# Set include directories
# -----------------------
#INC=-I$(JCOMMON_STD)
INC=
#####################################
# Set up RULES specific environment #
#####################################
# suffixes
# --------
.SUFFIXES: .f90 .o .mod
# PHONY targets
# -------------
.PHONY: all clean realclean $(MASTER_RULES) gray
# default target
# --------------
all:
@($(MAKE) -C ../ all) || exit $$?
# Set rules passed to top-level Makefile
# --------------------------------------
$(MASTER_RULES):
@($(MAKE) -C ../ $@) || exit $$?
# rule for libgray.a
# --------------------
$(LIBNAME): $(FOBJ)
ar vr $(LIBNAME) $?
# synonym for libgray.a
# -----------------------
gray: $(LIBNAME)
# create rule for compiling f90 files
# -----------------------------------
%.o: %.f90
$(FC) -c $(DIRECTIVES) $(FFLAGS) $(INC) $<
# make 'realclean' option
# -----------------------
realclean:
rm -f *.o *.mod $(LIBNAME)
# make 'clean' option
# -------------------
clean:
rm -f *.o
# Dependencies
# ------------
gray_jetto1beam.o: const_and_precisions.o beams.o graycore.o gray_params.o \
reflections.o units.o
graycore.o: const_and_precisions.o beamdata.o beams.o coreprofiles.o \
dispersion.o eccd.o equilibrium.o errcodes.o gray_params.o \
pec.o polarization.o limiter.o units.o utils.o
beams.o: const_and_precisions.o dierckx.o reflections.o simplespline.o utils.o
beamdata.o: const_and_precisions.o gray_params.o
conical.o: const_and_precisions.o
coreprofiles.o: const_and_precisions.o dierckx.o gray_params.o simplespline.o \
utils.o
dierckx.o: const_and_precisions.o
dispersion.o: const_and_precisions.o eierf.o errcodes.o math.o quadpack.o
eccd.o: const_and_precisions.o conical.o dierckx.o errcodes.o magsurf_data.o \
numint.o
eierf.o: const_and_precisions.o
errcodes.o: const_and_precisions.o
gray_params.o: const_and_precisions.o utils.o
equilibrium.o: const_and_precisions.o dierckx.o limiter.o minpack.o \
reflections.o simplespline.o utils.o gray_params.o
magsurf_data.o: const_and_precisions.o gray_params.o equilibrium.o dierckx.o \
reflections.o simplespline.o units.o utils.o
math.o: const_and_precisions.o
minpack.o: const_and_precisions.o
numint.o: const_and_precisions.o
pec.o: const_and_precisions.o beamdata.o equilibrium.o gray_params.o \
magsurf_data.o utils.o
polarization.o: const_and_precisions.o
quadpack.o: const_and_precisions.o
reflections.o: const_and_precisions.o limiter.o utils.o
simplespline.o: const_and_precisions.o
utils.o: const_and_precisions.o

View File

@ -1,75 +0,0 @@
# Executable name
EXE=sumgray
# Objects list
MAINOBJ=main-sum.o
OTHOBJ= beamdata.o beams.o conical.o const_and_precisions.o coreprofiles.o \
dierckx.o dispersion.o eccd.o eierf.o errcodes.o sumcore.o \
gray_params.o equilibrium.o limiter.o magsurf_data.o math.o minpack.o numint.o \
pec.o polarization.o quadpack.o reflections.o simplespline.o units.o utils.o
# Alternative search paths
vpath %.f90 src
vpath %.f src
# Fortran compiler name and flags
FC=gfortran
FFLAGS=-O3
#FFLAGS=-Wall -g -finit-real=nan -ffpe-trap=invalid -fcheck=all -fbounds-check
DIRECTIVES = -DREVISION="'$(shell svnversion src)'"
all: $(EXE)
# Build executable from object files
$(EXE): $(MAINOBJ) $(OTHOBJ)
$(FC) $(FFLAGS) -o $@ $^
# Dependencies on modules
main-sum.o: const_and_precisions.o beams.o coreprofiles.o equilibrium.o \
sumcore.o gray_params.o reflections.o
sumcore.o: const_and_precisions.o beamdata.o beams.o coreprofiles.o \
dispersion.o eccd.o equilibrium.o errcodes.o gray_params.o \
pec.o polarization.o limiter.o units.o utils.o
beams.o: const_and_precisions.o dierckx.o reflections.o simplespline.o utils.o
beamdata.o: const_and_precisions.o gray_params.o
conical.o: const_and_precisions.o
coreprofiles.o: const_and_precisions.o dierckx.o gray_params.o simplespline.o \
utils.o
dierckx.o: const_and_precisions.o
dispersion.o: const_and_precisions.o eierf.o errcodes.o math.o quadpack.o
eccd.o: const_and_precisions.o conical.o dierckx.o errcodes.o magsurf_data.o \
numint.o
eierf.o: const_and_precisions.o
errcodes.o: const_and_precisions.o
gray_params.o: const_and_precisions.o utils.o
equilibrium.o: const_and_precisions.o dierckx.o limiter.o minpack.o \
reflections.o simplespline.o utils.o gray_params.o
magsurf_data.o: const_and_precisions.o gray_params.o equilibrium.o dierckx.o \
reflections.o simplespline.o units.o utils.o
math.o: const_and_precisions.o
minpack.o: const_and_precisions.o
numint.o: const_and_precisions.o
pec.o: const_and_precisions.o beamdata.o equilibrium.o gray_params.o \
magsurf_data.o utils.o
polarization.o: const_and_precisions.o
quadpack.o: const_and_precisions.o
reflections.o: const_and_precisions.o limiter.o utils.o
simplespline.o: const_and_precisions.o
utils.o: const_and_precisions.o
# General object compilation command
%.o: %.f90
$(FC) -cpp $(DIRECTIVES) $(FFLAGS) -c $<
.PHONY: clean install
# Remove output files
clean:
rm -rf *.o *.mod $(EXE)
install:
@if [ -f $(EXE) ]; then \
cp $(EXE) ~/bin/; \
else \
echo File $(EXE) does not exist. Run \'make\' first; \
fi

28
depend Executable file
View File

@ -0,0 +1,28 @@
#!/bin/sh
# Compute the dependencies (direct and transitive) of an object
# This is used to collect all objects needed to link a program.
# Bail out when .d files are missing
test -f "${1%.o}.d" || exit 1
# Check whether $1 contains substring $2
contains(){ test "${1#*$2}" != "$1"; }
# Walk the dependency graph (consinting of the set of all .d files)
# and output the visited nodes (objects).
walk_dag(){
while read -r line; do
# skip the first line (file own name)
contains "$line" ': ' && continue
line="${line% \\}"
contains "$visited" "$line" && continue
visited="$line:$visited"
printf '%s ' "$line"
# whether the node is a leaf
test "$(wc -l < "${line%.o}.d")" -gt 1 && walk_dag < "${line%.o}.d"
done
}
printf '%s ' "$1" # the object itself
walk_dag < "${1%.o}.d"