gray/Makefile

287 lines
7.3 KiB
Makefile
Raw Normal View History

2021-12-15 02:30:48 +01:00
# Load the configure script variables
-include configure.mk
##
## Directories
##
# Structure:
# gray - top level
# ├── src - source code
2021-12-15 02:30:58 +01:00
# ├── doc - documentation
2023-12-18 00:52:11 +01:00
# ├── tests - integration tests
# └── build - build artifacts
# ├── bin - binaries
# ├── lib - libraries
# ├── obj - objects
# └── inc - files to #include
SRCDIR = src
BUILDDIR = build
2021-12-15 02:30:58 +01:00
SHAREDIR = build/share
BINDIR = build/bin
LIBDIR = build/lib
OBJDIR = build/obj
INCDIR = build/inc
2021-12-15 02:30:58 +01:00
2022-05-03 19:56:55 +02:00
PREFIX ?= /usr
2024-12-10 17:34:31 +01:00
PYTHON_VERSION = $(shell python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
PYTHON_PREFIX ?= $(PREFIX)/lib/python$(PYTHON_VERSION)/site-packages
2021-12-15 02:30:58 +01:00
# Directories that need to be created
DIRS = $(BINDIR) $(OBJDIR) $(INCDIR) $(LIBDIR) $(SHAREDIR)
##
## Files
##
# All Fortran source files
SOURCES = $(shell find '$(SRCDIR)' -name '*.f90')
# All Fortran object
OBJECTS = $(addprefix $(OBJDIR)/,$(notdir $(SOURCES:f90=o)))
# 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.so
2024-12-10 17:34:31 +01:00
BINARIES = $(GRAY) $(GRAY)-convert $(GRAY)-visual
LIBRARIES = $(LIBGRAY)
MANPAGES = $(addprefix $(SHAREDIR)/,gray.1 gray-convert.1 gray.ini.5 \
2024-10-09 18:09:15 +02:00
profiles.txt.5 beamdata.txt.5 magneticdata.txt.5)
##
## Version information
##
ifneq ($(wildcard .git/*),)
# We are building from a git checkout
# 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")
REVISION ?= $(GIT_REV)$(GIT_DIRTY)
else
# We are building from a release archive, use the version
REVISION ?= v$(file < .version)
endif
2024-02-08 17:37:17 +01:00
# Source date
ifndef SOURCE_DATE_EPOCH
# Use current date
SOURCE_DATE_EPOCH=$(shell awk 'BEGIN {print srand(srand())}')
endif
DATE=$(shell LC_TIME=C date -d @$(SOURCE_DATE_EPOCH) '+%B %Y')
##
## Fortran compiler and flags
##
2024-10-09 18:09:15 +02:00
LD = $(FC)
FFLAGS += -I$(INCDIR) -fpic
LDFLAGS += -L$(LIBDIR)
CPPFLAGS += -DREVISION=\"$(REVISION)\" -DPREFIX=\"$(PREFIX)\"
2024-10-09 18:09:15 +02:00
# Compiler-specific flags
ifdef GNU
FFLAGS += -J$(OBJDIR) -frecursive
FFLAGS += -fmax-errors=1 -ffree-line-length-none
CPPFLAGS += -DGNU
endif
ifdef INTEL
FFLAGS += -module $(OBJDIR) -assume recursion -heap-arrays
FFLAGS += -diag-error-limit=1
CPPFLAGS += -DINTEL
endif
ifdef PARALLEL
FFLAGS += -ftree-parallelize-loops=$(PARALLEL) -fopt-info-loop
LDFLAGS += -fopenmp
endif
2024-04-12 17:31:53 +02:00
# Sync the output from jobs running in parallel
MAKEFLAGS += --output-sync
ifndef DETERMINISTIC
ifdef AR_DEFAULT_DETERMINISTIC
# Write timestamps to allow partial updates
ARFLAGS = crU
endif
endif
# Static build options
ifdef STATIC
LIBGRAY := $(LIBGRAY:so=a)
LIBRARIES := $(LIBRARIES:so=a)
2023-11-25 18:11:52 +01:00
ifndef SEMISTATIC
LDFLAGS += -static
2023-11-25 18:11:52 +01:00
endif
else
2024-10-09 18:09:15 +02:00
LDFLAGS += -Wl,-rpath='$$ORIGIN/../lib/'
endif
2021-12-15 02:31:06 +01:00
# 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
2023-10-20 13:42:06 +02:00
else
# Optimization level 3
FFLAGS += -O3
2021-12-15 02:31:06 +01:00
endif
##
## Targets
##
.PHONY: all
all: $(BINARIES) $(LIBRARIES)
# Remove all generated files
.PHONY: clean
2012-06-21 14:38:29 +02:00
clean:
rm -r $(BUILDDIR)
2024-04-12 17:31:53 +02:00
# Run all tests
.PHONY: check
2024-04-12 17:31:53 +02:00
check: $(shell python -Bm tests --list-cases)
# Run a test case
tests.%: $(GRAY)
python -Bm tests '$@' --binary '$(GRAY)' --buffer
2023-12-18 00:52:11 +01:00
2021-12-15 02:30:58 +01:00
# Install libraries, binaries and documentation
.PHONY: install-bin
install-bin: $(BINARIES) $(LIBRARIES)
mkdir -p $(PREFIX)/{bin,lib}
2024-12-10 17:34:31 +01:00
install -m555 -t $(PREFIX)/bin $(BINARIES)
cp -fr -t $(PREFIX)/lib $(LIBRARIES)
.PHONY: install-python
install-python: scripts/gray
mkdir -p $(PYTHON_PREFIX)
cp -fr -t $(PYTHON_PREFIX) $^
.PHONY: install-doc
install-doc: $(SHAREDIR)/doc $(MANPAGES)
mkdir -p $(PREFIX)/share/{doc/res,man/man{1,5}}
install -m644 -t $(PREFIX)/share/doc $(SHAREDIR)/doc/manual.*
install -m644 -t $(PREFIX)/share/doc/res $(SHAREDIR)/doc/res/*
2024-02-08 17:37:17 +01:00
install -m644 -t $(PREFIX)/share/man/man1 $(SHAREDIR)/*.1
install -m644 -t $(PREFIX)/share/man/man5 $(SHAREDIR)/*.5
.PHONY: install
2024-12-10 17:34:31 +01:00
install: install-bin install-python install-doc
# dependencies
$(OBJDIR)/%.o: $(OBJDIR)/%.d
# GRAY binary
$(GRAY): $(OBJDIR)/main.o $(LIBGRAY) | $(BINDIR)
$(LD) $(LDFLAGS) -o '$@' $< -lgray
# gray-convert binary
$(GRAY)-convert: $(OBJDIR)/main_convert.o $(LIBGRAY) | $(BINDIR)
$(LD) $(LDFLAGS) -o '$@' $< -lgray
2024-12-10 17:34:31 +01:00
# gray-visual script
$(GRAY)-visual: | $(BINDIR)
echo '#!/usr/bin/env python' > $@
echo 'from gray.visual import main; main()' >> $@
chmod +x $@
# GRAY shared library
$(LIBDIR)/libgray.so: $(MODULES) | $(LIBDIR)
2021-12-15 02:31:18 +01:00
$(LD) -shared $(LDFLAGS) -o '$@' $^
# GRAY static library
$(LIBDIR)/libgray.a($(MODULES)): | $(LIBDIR)
$(LIBDIR)/libgray.a: $(LIBDIR)/libgray.a($(MODULES))
# Don't update archives in parallel, it's unsupported
.NOTPARALLEL: $(LIBDIR)/libgray.a
2022-09-27 18:30:03 +02:00
# GRAY static library when compiling from JETTO
-include ../include.mk
$(JLIBDIR)/libgray.a: $(LIBDIR)/libgray.a
mkdir -p $(LIBDIR)
install -m755 '$<' '$@'
2022-09-27 18:30:03 +02:00
2021-12-15 02:30:58 +01:00
# All documentation
.PHONY: doc
2024-02-08 17:37:17 +01:00
docs: $(SHAREDIR)/doc $(MANPAGES)
.PHONY: $(SHAREDIR)/doc
$(SHAREDIR)/doc: | $(SHAREDIR)
2021-12-15 02:31:17 +01:00
+make -C doc
2021-12-15 02:30:58 +01:00
2021-12-15 02:31:17 +01:00
# Generated man pages
2024-02-08 17:37:17 +01:00
$(SHAREDIR)/gray.1: $(GRAY) doc/man/gray.1 | $(SHAREDIR)
help2man '$<' -i doc/man/gray.1 -N -n 'beam-tracing code for EC waves' > '$@'
$(SHAREDIR)/gray-convert.1: $(GRAY)-convert | $(SHAREDIR)
help2man '$<' -N -n 'configuration format converter' > '$@'
2024-02-08 17:37:17 +01:00
$(SHAREDIR)/%: doc/man/%.md $(GRAY) | $(SHAREDIR)
pandoc -s '$<' -t man \
-V date='$(DATE)' \
-V footer='$(shell $(GRAY) --version | sed -n 1p)' \
-V author='$(shell $(GRAY) --version | sed -n "3 s/.$$//p")' \
-o '$@'
2021-12-15 02:31:17 +01:00
# 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//' \
2021-12-15 02:31:18 +01:00
| dot -Tsvg -o '$@'
##
## Generic rules
##
# Rebuild everything if the makefile changed
.EXTRA_PREREQS += Makefile
# Search for source code in vendor/ subdirectory
vpath %.f90 $(SRCDIR):$(SRCDIR)/vendor
# 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: %.f90 | $(OBJDIR)
2021-12-15 02:31:18 +01:00
@printf '$(@:d=o): $< \\\n' > '$@'
2024-10-09 18:09:15 +02:00
@grep -vE '^[[:blank:]]*use.*(intrinsic|iso_|ifport)' '$<' | \
sed -nE 's@^[[:blank:]]*use[[:blank:]]+'\
'([^,[:blank:]&]+).*@$(OBJDIR)/\1.o \\@p' | \
2021-12-15 02:31:18 +01:00
sort -u >> '$@'
@sed -nE 's@^#include "(.+)"@$(INCDIR)/\1 \\@p' '$<' >> '$@'
# Load the generated rules
include $(DEPS)
# Compile a generic Fortran source
$(OBJDIR)/%.o: %.f90 | $(OBJDIR) $(INCDIR)
$(FC) -cpp $(CPPFLAGS) $(FFLAGS) -c '$<' -o '$@'
# Generate Fortran code from awk script
$(INCDIR)/%.inc: $(SRCDIR)/%.awk | $(INCDIR)
awk -f '$<' > '$@'
# Create directories
$(DIRS):
2021-12-15 02:31:18 +01:00
mkdir -p '$@'