summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles BIENVENUE <charles.bienvenue@polymtl.ca>2025-11-05 22:47:07 +0000
committerCharles BIENVENUE <charles.bienvenue@polymtl.ca>2025-11-05 22:47:07 +0000
commit2109f3ade9d6a202c413ed9ad3e3475caa944ae3 (patch)
tree7e9ad87417236520023804b629e15e572bcb7c9d
parent8e8dd16f67ed325e2bf7fca0a9d878a18e6911ae (diff)
Parallel Build, OpenMP Support with Fortran 90, and Improved Module Dependencies
-rw-r--r--Donjon/src/Makefile49
-rwxr-xr-xDragon/data/TEST_GEO_hex_sect_tspc.access4
-rwxr-xr-xDragon/data/TEST_GEO_latt_tspc_S30.access4
-rwxr-xr-xDragon/data/fbr_colorset.access4
-rwxr-xr-xDragon/data/fbr_tone.access4
-rw-r--r--Dragon/src/Makefile66
-rw-r--r--Ganlib/src/Makefile67
-rw-r--r--PyGan/src/Makefile41
-rw-r--r--PyGan/src/setup_cle2000.py56
-rw-r--r--PyGan/src/setup_lcm.py19
-rw-r--r--Trivac/src/Makefile45
-rw-r--r--Utilib/src/Makefile49
-rw-r--r--doc/IGE335/Section6.00.tex6
-rwxr-xr-xscript/make_depend.py279
-rwxr-xr-xscript/make_depend_py3.py58
15 files changed, 494 insertions, 257 deletions
diff --git a/Donjon/src/Makefile b/Donjon/src/Makefile
index f236c5e..b68f26a 100644
--- a/Donjon/src/Makefile
+++ b/Donjon/src/Makefile
@@ -1,7 +1,7 @@
#---------------------------------------------------------------------------
#
# Makefile for building the Donjon library and load module
-# Author : A. Hebert (2018-5-10)
+# Author : A. Hebert (2018-5-10) and C. Bienvenue (2025-11-04)
#
#---------------------------------------------------------------------------
#
@@ -20,6 +20,8 @@ DIRNAME = $(shell uname -sm | sed 's/[ ]/_/')
OS = $(shell uname -s | cut -d"_" -f1)
opt = -O -g
PREPRO = cpp
+DEFAULT_GOAL_PLACEHOLDER :=
+.DEFAULT_GOAL := all
ifeq ($(openmp),1)
COMP = -fopenmp
PREPRO = cpp -D_OPENMP
@@ -46,12 +48,11 @@ else
endif
ifeq ($(OS),AIX)
- python_version_major := 2
+ PY := python
else
- python_version_full := $(wordlist 2,4,$(subst ., ,$(shell python --version 2>&1)))
- python_version_major := $(word 1,${python_version_full})
- ifneq ($(python_version_major),2)
- python_version_major := 3
+ PY := $(shell command -v python3 2>/dev/null)
+ ifeq ($(PY),)
+ PY := $(shell command -v python 2>/dev/null)
endif
endif
@@ -161,7 +162,9 @@ else
lib_module = ../lib/$(DIRNAME)_llvm/modules
INCLUDE = -I../../Ganlib/lib/$(DIRNAME)_llvm/modules/ -I../../Utilib/lib/$(DIRNAME)_llvm/modules/
FFLAGS += -mmlir -fdynamic-heap-array
- LFLAGS += -lclang_rt.osx
+ ifeq ($(OS),Darwin)
+ LFLAGS += -lclang_rt.osx
+ endif
else
lib = ../lib/$(DIRNAME)
libUtl = ../../Utilib/lib/$(DIRNAME)
@@ -181,18 +184,32 @@ ifeq ($(hdf5),1)
LFLAGS += -L${HDF5_API} -lhdf5
endif
-SRCC = $(shell ls *.c)
-SRC77 = $(shell ls *.f)
-SRCF77 = $(shell ls *.F)
-ifeq ($(python_version_major),2)
- SRC90 = $(shell python ../../script/make_depend.py *.f90)
+SRCC = $(shell ls *.c 2>/dev/null)
+SRC77 = $(shell ls *.f 2>/dev/null)
+SRCF77 = $(shell ls *.F 2>/dev/null)
+ifeq ($(PY),)
+ $(warning No Python interpreter found; Fortran dependency ordering may be suboptimal)
+ SRC90 = $(shell ls *.f90 2>/dev/null)
else
- SRC90 = $(shell python3 ../../script/make_depend_py3.py *.f90)
+ SRC90 = $(shell $(PY) ../../script/make_depend.py *.f90 *.F90)
+
endif
OBJC = $(SRCC:.c=.o)
-OBJ90 = $(SRC90:.f90=.o)
+OBJ90 = $(patsubst %.f90,%.o,$(patsubst %.F90,%.o,$(SRC90)))
OBJ77 = $(SRC77:.f=.o)
OBJF77 = $(SRCF77:.F=.o)
+
+# Auto-generated dependency file capturing Fortran module and include deps
+DEPS_MK := .donjon_deps.mk
+-include $(DEPS_MK)
+$(DEPS_MK): $(SRC90) $(SRC77) $(SRCF77)
+ifeq ($(PY),)
+ @echo "# Dependencies not generated: no Python available" > $(DEPS_MK)
+else
+ @echo "# Generating Fortran dependencies into $(DEPS_MK)"; \
+ $(PY) ../../script/make_depend.py --make-deps $(SRC90) $(SRC77) $(SRCF77) > $(DEPS_MK) || { rm -f $(DEPS_MK); exit 1; }
+endif
+
all : sub-make Donjon
ifeq ($(openmp),1)
@echo 'Donjon: openmp is defined'
@@ -227,7 +244,7 @@ $(lib_module)/:
$(lib)/: $(lib_module)/
mkdir -p $(lib)/
libDonjon.a: $(OBJC) $(OBJ90) $(OBJ77) $(OBJF77) $(lib)/
- ar r $@ $(OBJC) $(OBJ90) $(OBJ77) $(OBJF77)
+ ar rcs $@ $(OBJC) $(OBJ90) $(OBJ77) $(OBJF77)
cp $@ $(lib)/$@
cp *.mod $(lib_module)
$(bin)/:
@@ -238,4 +255,4 @@ Donjon: libDonjon.a DONJON.o $(bin)/ sub-make
cp $@ $(bin)/$@
clean:
$(MAKE) -C ../../Dragon/src clean
- /bin/rm -f *.o *.mod *.a sub-make temp.* Donjon
+ /bin/rm -f *.o *.mod *.a sub-make temp.* Donjon $(DEPS_MK)
diff --git a/Dragon/data/TEST_GEO_hex_sect_tspc.access b/Dragon/data/TEST_GEO_hex_sect_tspc.access
index aebf920..6c57516 100755
--- a/Dragon/data/TEST_GEO_hex_sect_tspc.access
+++ b/Dragon/data/TEST_GEO_hex_sect_tspc.access
@@ -27,7 +27,9 @@ if [ -f "$pos"/draglibendfb7r1SHEM315_v5p1.gz ]
then
echo 'gunzipping DLIB_315'
chmod 755 "$pos"
- gunzip "$pos"/draglibendfb7r1SHEM315_v5p1.gz
+ if [ ! -f "$pos"/draglibendfb7r1SHEM315_v5p1 ]; then
+ gunzip "$pos"/draglibendfb7r1SHEM315_v5p1.gz
+ fi
fi
if [ -f "$pos"/draglibendfb7r1SHEM315_v5p1 ]
then
diff --git a/Dragon/data/TEST_GEO_latt_tspc_S30.access b/Dragon/data/TEST_GEO_latt_tspc_S30.access
index bb190e8..10c3098 100755
--- a/Dragon/data/TEST_GEO_latt_tspc_S30.access
+++ b/Dragon/data/TEST_GEO_latt_tspc_S30.access
@@ -27,7 +27,9 @@ if [ -f "$pos"/draglibendfb7r1SHEM315_v5p1.gz ]
then
echo 'gunzipping draglibendfb7r1SHEM315_v5p1'
chmod 755 "$pos"
- gunzip "$pos"/draglibendfb7r1SHEM315_v5p1.gz
+ if [ ! -f "$pos"/draglibendfb7r1SHEM315_v5p1 ]; then
+ gunzip "$pos"/draglibendfb7r1SHEM315_v5p1.gz
+ fi
fi
if [ -f "$pos"/draglibendfb7r1SHEM315_v5p1 ]
then
diff --git a/Dragon/data/fbr_colorset.access b/Dragon/data/fbr_colorset.access
index 298d7b1..c25647b 100755
--- a/Dragon/data/fbr_colorset.access
+++ b/Dragon/data/fbr_colorset.access
@@ -27,7 +27,9 @@ if [ -f "$pos"/draglibendfb7r1SHEM315_v5p1.gz ]
then
echo 'gunzipping DLIB_315'
chmod 755 "$pos"
- gunzip "$pos"/draglibendfb7r1SHEM315_v5p1.gz
+ if [ ! -f "$pos"/draglibendfb7r1SHEM315_v5p1 ]; then
+ gunzip "$pos"/draglibendfb7r1SHEM315_v5p1.gz
+ fi
fi
if [ -f "$pos"/draglibendfb7r1SHEM315_v5p1 ]
then
diff --git a/Dragon/data/fbr_tone.access b/Dragon/data/fbr_tone.access
index 396e3d6..fd8a33e 100755
--- a/Dragon/data/fbr_tone.access
+++ b/Dragon/data/fbr_tone.access
@@ -27,7 +27,9 @@ if [ -f "$pos"/draglibendfb7r1SHEM315_v5p1.gz ]
then
echo 'gunzipping DLIB_315'
chmod 755 "$pos"
- gunzip "$pos"/draglibendfb7r1SHEM315_v5p1.gz
+ if [ ! -f "$pos"/draglibendfb7r1SHEM315_v5p1 ]; then
+ gunzip "$pos"/draglibendfb7r1SHEM315_v5p1.gz
+ fi
fi
if [ -f "$pos"/draglibendfb7r1SHEM315_v5p1 ]
then
diff --git a/Dragon/src/Makefile b/Dragon/src/Makefile
index c675c26..b423600 100644
--- a/Dragon/src/Makefile
+++ b/Dragon/src/Makefile
@@ -1,7 +1,7 @@
#---------------------------------------------------------------------------
#
# Makefile for building the Dragon library and load module
-# Author : A. Hebert (2018-5-10)
+# Author : A. Hebert (2018-5-10) and C. Bienvenue (2025-11-04)
#
#---------------------------------------------------------------------------
#
@@ -20,6 +20,7 @@ DIRNAME = $(shell uname -sm | sed 's/[ ]/_/')
OS = $(shell uname -s | cut -d"_" -f1)
opt = -O -g
PREPRO = cpp
+.DEFAULT_GOAL := all
ifeq ($(openmp),1)
COMP = -fopenmp
PREPRO = cpp -D_OPENMP
@@ -46,12 +47,11 @@ else
endif
ifeq ($(OS),AIX)
- python_version_major := 2
+ PY := python
else
- python_version_full := $(wordlist 2,4,$(subst ., ,$(shell python --version 2>&1)))
- python_version_major := $(word 1,${python_version_full})
- ifneq ($(python_version_major),2)
- python_version_major := 3
+ PY := $(shell command -v python3 2>/dev/null)
+ ifeq ($(PY),)
+ PY := $(shell command -v python 2>/dev/null)
endif
endif
@@ -158,7 +158,9 @@ else
lib_module = ../lib/$(DIRNAME)_llvm/modules
INCLUDE = -I../../Ganlib/lib/$(DIRNAME)_llvm/modules/
FFLAGS += -mmlir -fdynamic-heap-array
- LFLAGS += -lclang_rt.osx
+ ifeq ($(OS),Darwin)
+ LFLAGS += -lclang_rt.osx
+ endif
else
lib = ../lib/$(DIRNAME)
libUtl = ../../Utilib/lib/$(DIRNAME)
@@ -177,18 +179,35 @@ ifeq ($(hdf5),1)
LFLAGS += -L${HDF5_API} -lhdf5
endif
-SRCC = $(shell ls *.c)
-SRC77 = $(shell ls *.f)
-SRCF77 = $(shell ls *.F)
-ifeq ($(python_version_major),2)
- SRC90 = $(shell python ../../script/make_depend.py *.f90)
+FFLAGS += -cpp
+
+SRCC = $(shell ls *.c 2>/dev/null)
+SRC77 = $(filter-out %.pp.f,$(shell ls *.f 2>/dev/null))
+SRCF77 = $(shell ls *.F 2>/dev/null)
+ifeq ($(PY),)
+ $(warning No Python interpreter found; Fortran dependency ordering may be suboptimal)
+ SRC90_RAW = $(shell ls *.f90 *.F90 2>/dev/null)
+ SRC90 = $(filter-out %.pp.f90,$(SRC90_RAW))
else
- SRC90 = $(shell python3 ../../script/make_depend_py3.py *.f90)
+ SRC90_RAW = $(shell $(PY) ../../script/make_depend.py *.f90 *.F90)
+ SRC90 = $(filter-out %.pp.f90,$(SRC90_RAW))
endif
OBJC = $(SRCC:.c=.o)
-OBJ90 = $(SRC90:.f90=.o)
+OBJ90 = $(patsubst %.f90,%.o,$(patsubst %.F90,%.o,$(SRC90)))
OBJ77 = $(SRC77:.f=.o)
OBJF77 = $(SRCF77:.F=.o)
+
+# Auto-generated dependency file capturing Fortran module and include deps
+DEPS_MK := .dragon_deps.mk
+-include $(DEPS_MK)
+$(DEPS_MK): $(SRC90) $(SRC77) $(SRCF77)
+ifeq ($(PY),)
+ @echo "# Dependencies not generated: no Python available" > $(DEPS_MK)
+else
+ @echo "# Generating Fortran dependencies into $(DEPS_MK)"; \
+ $(PY) ../../script/make_depend.py --make-deps $(SRC90) $(SRC77) $(SRCF77) > $(DEPS_MK) || { rm -f $(DEPS_MK); exit 1; }
+endif
+
all : sub-make Dragon
ifeq ($(openmp),1)
@echo 'Dragon: openmp is defined'
@@ -206,26 +225,29 @@ ifeq ($(hdf5),1)
@echo 'Dragon: hdf5 is defined'
endif
sub-make:
+ $(MAKE) openmp=$(openmp) intel=$(intel) nvidia=$(nvidia) llvm=$(llvm) hdf5=$(hdf5) -C ../../Utilib/src
+ $(MAKE) openmp=$(openmp) intel=$(intel) nvidia=$(nvidia) llvm=$(llvm) hdf5=$(hdf5) -C ../../Ganlib/src
$(MAKE) openmp=$(openmp) intel=$(intel) nvidia=$(nvidia) llvm=$(llvm) hdf5=$(hdf5) -C ../../Trivac/src
%.o : %.c
$(C) $(CFLAGS) $(opt) $(COMP) -c $< -o $@
%.o : %.f90
$(F90) $(FFLAGS) $(opt) $(COMP) $(INCLUDE) -c $< -o $@
+%.o : %.F90
+ # Use Fortran compiler's integrated preprocessor instead of cpp -traditional
+ $(F90) $(FFLAGS) $(opt) $(COMP) $(INCLUDE) $(FLAGS) -c $< -o $@
%.o : %.f
- @/bin/rm -f temp.f
$(F90) $(FFLAG77) $(opt) $(COMP) $(INCLUDE) -c $< -o $@
%.o : %.F
- $(PREPRO) -P -W -traditional $(FLAGS) $< temp.f
- $(F90) $(FFLAG77) $(opt) $(COMP) $(INCLUDE) -c temp.f -o $@
- /bin/rm temp.f
+ # Use Fortran compiler's integrated preprocessor only for .F (not for .f)
+ $(F90) $(FFLAG77) -cpp $(opt) $(COMP) $(INCLUDE) $(FLAGS) -c $< -o $@
$(lib_module)/:
mkdir -p $(lib_module)/
$(lib)/: $(lib_module)/
mkdir -p $(lib)/
-libDragon.a: $(OBJC) $(OBJ90) $(OBJ77) $(OBJF77) $(lib)/
- ar r $@ $(OBJC) $(OBJ90) $(OBJ77) $(OBJF77)
+libDragon.a: $(DEPS_MK) $(OBJC) $(OBJ90) $(OBJ77) $(OBJF77) $(lib)/
+ ar rcs $@ $(OBJC) $(OBJ90) $(OBJ77) $(OBJF77)
cp $@ $(lib)/$@
- cp *.mod $(lib_module)
+ if ls *.mod 1> /dev/null 2>&1; then cp *.mod $(lib_module); fi
$(bin)/:
mkdir -p $(bin)/
Dragon: libDragon.a DRAGON.o $(bin)/ sub-make
@@ -234,4 +256,4 @@ Dragon: libDragon.a DRAGON.o $(bin)/ sub-make
cp $@ $(bin)/$@
clean:
$(MAKE) -C ../../Trivac/src clean
- /bin/rm -f *.o *.mod *.a sub-make temp.* Dragon
+ /bin/rm -f *.o *.mod *.a sub-make temp.* Dragon $(DEPS_MK) *.pp.f *.pp.f90
diff --git a/Ganlib/src/Makefile b/Ganlib/src/Makefile
index 0a4ad6f..4235f13 100644
--- a/Ganlib/src/Makefile
+++ b/Ganlib/src/Makefile
@@ -1,7 +1,7 @@
#---------------------------------------------------------------------------
#
# Makefile for building the Ganlib library and load module
-# Author : A. Hebert (2018-5-10)
+# Author : A. Hebert (2018-5-10) and C. Bienvenue (2025-11-04)
#
#---------------------------------------------------------------------------
#
@@ -19,6 +19,7 @@ endif
DIRNAME = $(shell uname -sm | sed 's/[ ]/_/')
OS = $(shell uname -s | cut -d"_" -f1)
opt = -O -g
+.DEFAULT_GOAL := all
PREPRO = cpp
ifeq ($(openmp),1)
COMP = -fopenmp
@@ -54,12 +55,11 @@ else
endif
ifeq ($(OS),AIX)
- python_version_major := 2
+ PY := python
else
- python_version_full := $(wordlist 2,4,$(subst ., ,$(shell python --version 2>&1)))
- python_version_major := $(word 1,${python_version_full})
- ifneq ($(python_version_major),2)
- python_version_major := 3
+ PY := $(shell command -v python3 2>/dev/null)
+ ifeq ($(PY),)
+ PY := $(shell command -v python 2>/dev/null)
endif
endif
@@ -152,7 +152,9 @@ else
bin = ../bin/$(DIRNAME)_llvm
lib_module = ../lib/$(DIRNAME)_llvm/modules
FFLAGS += -mmlir -fdynamic-heap-array
- LFLAGS += -lclang_rt.osx
+ ifeq ($(OS),Darwin)
+ LFLAGS += -lclang_rt.osx
+ endif
else
lib = ../lib/$(DIRNAME)
bin = ../bin/$(DIRNAME)
@@ -167,20 +169,34 @@ ifeq ($(hdf5),1)
LFLAGS += -L${HDF5_API} -lhdf5
endif
-SRCC = $(shell ls *.c)
-SRC77 = $(shell ls *.f)
-SRCF77 = $(shell ls *.F)
-ifeq ($(python_version_major),2)
- SRC90 = $(shell python ../../script/make_depend.py *.f90)
+SRCC = $(shell ls *.c 2>/dev/null)
+SRC77 = $(shell ls *.f 2>/dev/null)
+SRCF77 = $(shell ls *.F 2>/dev/null)
+ifeq ($(PY),)
+ $(warning No Python interpreter found; Fortran dependency ordering may be suboptimal)
+ SRC90 = $(shell ls *.f90 2>/dev/null)
+ SRCF90 = $(shell ls *.F90 2>/dev/null)
else
- SRC90 = $(shell python3 ../../script/make_depend_py3.py *.f90)
+ SRC90 = $(shell $(PY) ../../script/make_depend.py *.f90 *.F90)
+ SRCF90 =
endif
-SRCF90 = $(shell ls *.F90)
OBJC = $(SRCC:.c=.o)
-OBJ90 = $(SRC90:.f90=.o)
+OBJ90 = $(patsubst %.f90,%.o,$(patsubst %.F90,%.o,$(SRC90)))
OBJF90 = $(SRCF90:.F90=.o)
OBJ77 = $(SRC77:.f=.o)
OBJF77 = $(SRCF77:.F=.o)
+
+# Auto-generated dependency file capturing Fortran module and include deps
+DEPS_MK := .ganlib_deps.mk
+-include $(DEPS_MK)
+$(DEPS_MK): $(SRC90) $(SRC77) $(SRCF77)
+ifeq ($(PY),)
+ @echo "# Dependencies not generated: no Python available" > $(DEPS_MK)
+else
+ @echo "# Generating Fortran dependencies into $(DEPS_MK)"; \
+ $(PY) ../../script/make_depend.py --make-deps $(SRC90) $(SRC77) $(SRCF77) > $(DEPS_MK) || { rm -f $(DEPS_MK); exit 1; }
+endif
+
all : sub-make Ganlib
ifeq ($(mpi),1)
@echo 'Ganlib: mpi is defined'
@@ -200,27 +216,26 @@ endif
ifeq ($(hdf5),1)
@echo 'Ganlib: hdf5 is defined'
endif
- @echo 'Ganlib: python version=' $(python_version_major)
+ @echo 'Ganlib: python=' $(PY)
sub-make:
%.o : %.c
$(C) $(CFLAGS) $(FLAGS) $(opt) $(COMP) -c $< -o $@
%.o : %.f90
$(F90) $(FFLAGS) $(opt) $(COMP) -c $< -o $@
%.o : %.F90
- $(PREPRO) -P -W -traditional $(FLAGS) $< temp.f90
- $(F90) $(FFLAGS) $(opt) $(COMP) -c temp.f90 -o $@
- /bin/rm temp.f90
+ $(PREPRO) -P -W -traditional $(FLAGS) $< $(@:.o=.pp.f90)
+ $(F90) $(FFLAGS) $(opt) $(COMP) -c $(@:.o=.pp.f90) -o $@
+ /bin/rm -f $(@:.o=.pp.f90)
%.o : %.f
- @/bin/rm -f temp.f
$(F90) $(FFLAG77) $(opt) $(COMP) -c $< -o $@
%.o : %.F
- $(PREPRO) -P -W -traditional $(FLAGS) $(FMPI) $< temp.f
- $(F90) $(FFLAG77) $(opt) $(COMP) -c temp.f -o $@
- /bin/rm temp.f
+ $(PREPRO) -P -W -traditional $(FLAGS) $(FMPI) $< $(@:.o=.pp.f)
+ $(F90) $(FFLAG77) $(opt) $(COMP) -c $(@:.o=.pp.f) -o $@
+ /bin/rm -f $(@:.o=.pp.f)
$(lib_module)/:
mkdir -p $(lib_module)/
-libGanlib.a: $(OBJC) $(OBJ90) $(OBJF90) $(OBJ77) $(OBJF77) $(lib_module)/
- ar r $@ $(OBJC) $(OBJ90) $(OBJF90) $(OBJ77) $(OBJF77)
+libGanlib.a: $(DEPS_MK) $(OBJC) $(OBJ90) $(OBJF90) $(OBJ77) $(OBJF77) $(lib_module)/
+ ar rcs $@ $(OBJC) $(OBJ90) $(OBJF90) $(OBJ77) $(OBJF77)
cp $@ $(lib)/$@
cp *.mod $(lib_module)
$(bin)/:
@@ -229,4 +244,4 @@ Ganlib: libGanlib.a GANMAIN.o $(bin)/
$(F90) $(opt) $(COMP) GANMAIN.o $(lib)/libGanlib.a $(LFLAGS) -o Ganlib
cp $@ $(bin)/$@
clean:
- /bin/rm -f *.o *.mod *.a sub-make temp.* Ganlib*
+ /bin/rm -f *.o *.mod *.a sub-make temp.* Ganlib* $(DEPS_MK) *.pp.f *.pp.f90
diff --git a/PyGan/src/Makefile b/PyGan/src/Makefile
index f48c98a..8520eef 100644
--- a/PyGan/src/Makefile
+++ b/PyGan/src/Makefile
@@ -16,6 +16,9 @@ PYTHONPATH = $(pylib)/python
$(info set PYTHONPATH="$(PYTHONPATH)")
export PYTHONPATH
+# Build defaults and phony targets
+.DEFAULT_GOAL := all
+
ifeq ($(intel),1)
ifeq ($(INTELTOOLS),)
$(error INTELTOOLS is not set)
@@ -50,11 +53,11 @@ else
endif
endif
export COMPILER
+# export FORTRANPATH
-all:
- $(MAKE) donjon
+all: donjon
checkPython: ; @which python3 > /dev/null
-ganlib: clean sub-make-ganlib pygan-ganlib
+ganlib: sub-make-ganlib pygan-ganlib
ifeq ($(openmp),1)
@echo 'pygan_ganlib: openmp is defined'
endif
@@ -70,7 +73,7 @@ endif
ifeq ($(hdf5),1)
@echo 'pygan_ganlib: hdf5 is defined'
endif
-trivac: clean sub-make-trivac pygan-trivac
+trivac: sub-make-trivac pygan-trivac
ifeq ($(openmp),1)
@echo 'pygan_trivac: openmp is defined'
endif
@@ -86,7 +89,7 @@ endif
ifeq ($(hdf5),1)
@echo 'pygan_trivac: hdf5 is defined'
endif
-dragon: clean sub-make-dragon pygan-dragon
+dragon: sub-make-dragon pygan-dragon
ifeq ($(openmp),1)
@echo 'pygan_dragon: openmp is defined'
endif
@@ -102,7 +105,7 @@ endif
ifeq ($(hdf5),1)
@echo 'pygan_dragon: hdf5 is defined'
endif
-donjon: clean sub-make-donjon pygan-donjon
+donjon: sub-make-donjon pygan-donjon
ifeq ($(openmp),1)
@echo 'pygan_donjon: openmp is defined'
endif
@@ -119,14 +122,14 @@ ifeq ($(hdf5),1)
@echo 'pygan_donjon: hdf5 is defined'
endif
sub-make-ganlib:
- $(MAKE) openmp=$(openmp) hdf5=$(hdf5) -C ../../Ganlib/src
+ $(MAKE) openmp=$(openmp) intel=$(intel) nvidia=$(nvidia) llvm=$(llvm) hdf5=$(hdf5) -C ../../Ganlib/src
sub-make-trivac: sub-make-ganlib
- $(MAKE) openmp=$(openmp) -C ../../Utilib/src
- $(MAKE) openmp=$(openmp) hdf5=$(hdf5) -C ../../Trivac/src
+ $(MAKE) openmp=$(openmp) intel=$(intel) nvidia=$(nvidia) llvm=$(llvm) -C ../../Utilib/src
+ $(MAKE) openmp=$(openmp) intel=$(intel) nvidia=$(nvidia) llvm=$(llvm) hdf5=$(hdf5) -C ../../Trivac/src
sub-make-dragon: sub-make-trivac
- $(MAKE) openmp=$(openmp) hdf5=$(hdf5) -C ../../Dragon/src
+ $(MAKE) openmp=$(openmp) intel=$(intel) nvidia=$(nvidia) llvm=$(llvm) hdf5=$(hdf5) -C ../../Dragon/src
sub-make-donjon: sub-make-dragon
- $(MAKE) openmp=$(openmp) hdf5=$(hdf5) -C ../../Donjon/src
+ $(MAKE) openmp=$(openmp) intel=$(intel) nvidia=$(nvidia) llvm=$(llvm) hdf5=$(hdf5) -C ../../Donjon/src
libGanlib.a: $(lib)/ sub-make-ganlib
cp $(libGan)/libGanlib.a .
ar -d libGanlib.a xabort_c.o
@@ -144,8 +147,8 @@ ifeq ($(openmp),1)
else
export CODE_EMBEDDED=GANLIB; cd $(DIRNAME); python3 setup_cle2000.py install --home=.
endif
- mv $(DIRNAME)/$(pylib)/* $(lib)/
- /bin/rm -r $(DIRNAME)
+ cp -R $(DIRNAME)/$(pylib)/* $(lib)/
+ /bin/rm -rf $(DIRNAME)
pygan-trivac: libGanlib.a sub-make-trivac checkPython
mkdir -p $(DIRNAME)
cp *.[ch] $(DIRNAME)
@@ -157,8 +160,8 @@ ifeq ($(openmp),1)
else
export CODE_EMBEDDED=TRIVAC; cd $(DIRNAME); python3 setup_cle2000.py install --home=.
endif
- mv $(DIRNAME)/$(pylib)/* $(lib)/
- /bin/rm -r $(DIRNAME)
+ cp -R $(DIRNAME)/$(pylib)/* $(lib)/
+ /bin/rm -rf $(DIRNAME)
pygan-dragon: libGanlib.a sub-make-dragon checkPython
mkdir -p $(DIRNAME)
cp *.[ch] $(DIRNAME)
@@ -170,8 +173,8 @@ ifeq ($(openmp),1)
else
export CODE_EMBEDDED=DRAGON; cd $(DIRNAME); python3 setup_cle2000.py install --home=.
endif
- mv $(DIRNAME)/$(pylib)/* $(lib)/
- /bin/rm -r $(DIRNAME)
+ cp -R $(DIRNAME)/$(pylib)/* $(lib)/
+ /bin/rm -rf $(DIRNAME)
pygan-donjon: libGanlib.a sub-make-donjon checkPython
mkdir -p $(DIRNAME)
cp *.[ch] $(DIRNAME)
@@ -183,8 +186,8 @@ ifeq ($(openmp),1)
else
export CODE_EMBEDDED=DONJON; cd $(DIRNAME); python3 setup_cle2000.py install --home=.
endif
- mv $(DIRNAME)/$(pylib)/* $(lib)/
- /bin/rm -r $(DIRNAME)
+ cp -R $(DIRNAME)/$(pylib)/* $(lib)/
+ /bin/rm -rf $(DIRNAME)
@echo 'makefile PYTHONPATH=' $(PYTHONPATH)
clean:
@echo 'clean PyGan'
diff --git a/PyGan/src/setup_cle2000.py b/PyGan/src/setup_cle2000.py
index d416245..c712b26 100644
--- a/PyGan/src/setup_cle2000.py
+++ b/PyGan/src/setup_cle2000.py
@@ -10,14 +10,26 @@ else:
from distutils.core import setup, Extension
import sysconfig
+def _detect_gfortran_dir():
+ import subprocess, os
+ try:
+ out = subprocess.check_output(['gfortran', '-print-file-name=libgfortran.dylib'], text=True).strip()
+ if out and out != 'libgfortran.dylib':
+ d = os.path.dirname(out)
+ if os.path.isdir(d):
+ return d
+ except Exception:
+ pass
+ return None
+
def main():
import os
from sysconfig import get_config_var
mach = os.path.basename(os.getcwd())
Code = os.environ.get("CODE_EMBEDDED", None) # Code selection
Compiler = os.environ.get("COMPILER", None) # Compiler selection
- FortranLib = os.environ.get(Compiler, None) # directory with libfortran.a
- HDF5Lib = os.environ.get("HDF5_API", None) # directory with libhdf5.a
+ FortranLib = _detect_gfortran_dir() # directory with libfortran
+ HDF5Lib = os.environ.get("HDF5_API", None) # directory with libhdf5
pylib = os.path.basename(get_config_var("LIBDIR")) # get lib or lib64
print("install Cle2000 binding to", Code, "on directory",mach, "pylib=",pylib, "Compiler=",Compiler)
if Compiler == "NVTOOLS":
@@ -49,6 +61,14 @@ def main():
libDon="../../../Donjon/lib/"+mach
extralink=["-lgfortran", ]
print("debug Compiler=",Compiler,"libdir=",libdir,"Code=",Code)
+ if FortranLib:
+ print("debug FortranLib=", FortranLib)
+ if HDF5Lib:
+ print("debug HDF5Lib=", HDF5Lib)
+
+ # Build helper lists with None filtered out
+ def _dirs(*args):
+ return [d for d in args if d]
if Code == "GANLIB":
setup (name="Cle2000",
@@ -60,8 +80,8 @@ def main():
ext_modules=[Extension('cle2000',sources=['cle2000module.c'],
extra_link_args = extralink,
include_dirs=["../../../Ganlib/src"],
- library_dirs=[libdir,FortranLib,HDF5Lib],
- runtime_library_dirs=[FortranLib,HDF5Lib],
+ library_dirs=_dirs(libdir,FortranLib,HDF5Lib),
+ runtime_library_dirs=_dirs(FortranLib,HDF5Lib),
libraries=["Ganlib","hdf5"] ) ])
elif Code == "TRIVAC":
setup (name="Cle2000",
@@ -74,8 +94,8 @@ def main():
define_macros=[('__trivac__', None)],
extra_link_args = extralink,
include_dirs=["../../../Ganlib/src"],
- library_dirs=[libdir,FortranLib,HDF5Lib,libUtl,libTri],
- runtime_library_dirs=[FortranLib,HDF5Lib],
+ library_dirs=_dirs(libdir,FortranLib,HDF5Lib,libUtl,libTri),
+ runtime_library_dirs=_dirs(FortranLib,HDF5Lib),
libraries=["Trivac","Utilib","Ganlib","hdf5"] ) ])
elif Code == "DRAGON":
setup (name="Cle2000",
@@ -88,8 +108,8 @@ def main():
define_macros=[('__dragon__', None)],
extra_link_args = extralink,
include_dirs=["../../../Ganlib/src"],
- library_dirs=[libdir,FortranLib,HDF5Lib,libUtl,libTri,libDra],
- runtime_library_dirs=[FortranLib,HDF5Lib],
+ library_dirs=_dirs(libdir,FortranLib,HDF5Lib,libUtl,libTri,libDra),
+ runtime_library_dirs=_dirs(FortranLib,HDF5Lib),
libraries=["Dragon","Trivac","Utilib","Ganlib","hdf5"] ) ])
elif Code == "DONJON":
setup (name="Cle2000",
@@ -102,8 +122,8 @@ def main():
define_macros=[('__donjon__', None)],
extra_link_args = extralink,
include_dirs=["../../../Ganlib/src"],
- library_dirs=[libdir,FortranLib,HDF5Lib,libUtl,libTri,libDra,libDon],
- runtime_library_dirs=[FortranLib,HDF5Lib],
+ library_dirs=_dirs(libdir,FortranLib,HDF5Lib,libUtl,libTri,libDra,libDon),
+ runtime_library_dirs=_dirs(FortranLib,HDF5Lib),
libraries=["Donjon","Dragon","Trivac","Utilib","Ganlib","hdf5"] ) ])
elif Code == "GANLIB_OMP":
setup (name="Cle2000",
@@ -115,8 +135,8 @@ def main():
ext_modules=[Extension('cle2000',sources=['cle2000module.c'],
extra_link_args = ["-lgomp"]+extralink,
include_dirs=["../../../Ganlib/src"],
- library_dirs=[libdir,FortranLib,HDF5Lib],
- runtime_library_dirs=[FortranLib,HDF5Lib],
+ library_dirs=_dirs(libdir,FortranLib,HDF5Lib),
+ runtime_library_dirs=_dirs(FortranLib,HDF5Lib),
libraries=["Ganlib","hdf5"] ) ])
elif Code == "TRIVAC_OMP":
setup (name="Cle2000",
@@ -129,8 +149,8 @@ def main():
define_macros=[('__trivac__', None)],
extra_link_args = ["-lgomp"]+extralink,
include_dirs=["../../../Ganlib/src"],
- library_dirs=[libdir,FortranLib,HDF5Lib,libUtl,libTri],
- runtime_library_dirs=[FortranLib,HDF5Lib],
+ library_dirs=_dirs(libdir,FortranLib,HDF5Lib,libUtl,libTri),
+ runtime_library_dirs=_dirs(FortranLib,HDF5Lib),
libraries=["Trivac","Utilib","Ganlib","hdf5"] ) ])
elif Code == "DRAGON_OMP":
setup (name="Cle2000",
@@ -143,8 +163,8 @@ def main():
define_macros=[('__dragon__', None)],
extra_link_args = ["-lgomp"]+extralink,
include_dirs=["../../../Ganlib/src"],
- library_dirs=[libdir,FortranLib,HDF5Lib,libUtl,libTri,libDra],
- runtime_library_dirs=[FortranLib,HDF5Lib],
+ library_dirs=_dirs(libdir,FortranLib,HDF5Lib,libUtl,libTri,libDra),
+ runtime_library_dirs=_dirs(FortranLib,HDF5Lib),
libraries=["Dragon","Trivac","Utilib","Ganlib","hdf5"] ) ])
elif Code == "DONJON_OMP":
setup (name="Cle2000",
@@ -157,8 +177,8 @@ def main():
define_macros=[('__donjon__', None)],
extra_link_args = ["-lgomp"]+extralink,
include_dirs=["../../../Ganlib/src"],
- library_dirs=[libdir,FortranLib,HDF5Lib,libUtl,libTri,libDra,libDon],
- runtime_library_dirs=[FortranLib,HDF5Lib],
+ library_dirs=_dirs(libdir,FortranLib,HDF5Lib,libUtl,libTri,libDra,libDon),
+ runtime_library_dirs=_dirs(FortranLib,HDF5Lib),
libraries=["Donjon","Dragon","Trivac","Utilib","Ganlib","hdf5"] ) ])
else:
raise ValueError(Code+" is not implemented for setup.py bindings")
diff --git a/PyGan/src/setup_lcm.py b/PyGan/src/setup_lcm.py
index 79e7891..76829b4 100644
--- a/PyGan/src/setup_lcm.py
+++ b/PyGan/src/setup_lcm.py
@@ -22,16 +22,25 @@ def main():
extralink=["-lnvc","-lnvcpumath"]
elif Compiler == "LLVMTOOLS":
libdir="../../lib/"+mach+"_llvm"
- libNv=" "
+ libNv=None
extralink=[ ]
elif Compiler == "INTELTOOLS":
libdir="../../lib/"+mach+"_intel"
- libNv=" "
+ libNv=None
extralink=[ ]
else:
libdir="../../lib/"+mach
- libNv=" "
+ libNv=None
extralink=[ ]
+ # Filter out missing/empty library dirs to avoid "-L " warnings
+ def _dirs(*paths):
+ out=[]
+ for p in paths:
+ if p and isinstance(p, str) and os.path.isdir(p):
+ out.append(p)
+ return out
+ lib_dirs = _dirs(libdir, libNv)
+ rpath_dirs = _dirs(libNv)
setup(name="Lcm",
version="5.0",
description="Python interface for the lcm C library API",
@@ -41,8 +50,8 @@ def main():
ext_modules=[Extension("lcm", ["lcmmodule.c"],
extra_link_args = extralink,
include_dirs=["../../../Ganlib/src",incdir],
- library_dirs=[libdir,libNv],
- runtime_library_dirs=[libNv],
+ library_dirs=lib_dirs,
+ runtime_library_dirs=rpath_dirs,
libraries=["Ganlib"] ) ])
if __name__ == "__main__":
diff --git a/Trivac/src/Makefile b/Trivac/src/Makefile
index 6a70191..2ad728a 100644
--- a/Trivac/src/Makefile
+++ b/Trivac/src/Makefile
@@ -1,7 +1,7 @@
#---------------------------------------------------------------------------
#
# Makefile for building the Trivac library and load module
-# Author : A. Hebert (2018-5-10)
+# Author : A. Hebert (2018-5-10) and C. Bienvenue (2025-11-04)
#
#---------------------------------------------------------------------------
#
@@ -19,6 +19,7 @@ endif
DIRNAME = $(shell uname -sm | sed 's/[ ]/_/')
OS = $(shell uname -s | cut -d"_" -f1)
opt = -O -g
+.DEFAULT_GOAL := all
ifeq ($(openmp),1)
COMP = -fopenmp
else
@@ -44,12 +45,11 @@ else
endif
ifeq ($(OS),AIX)
- python_version_major := 2
+ PY := python
else
- python_version_full := $(wordlist 2,4,$(subst ., ,$(shell python --version 2>&1)))
- python_version_major := $(word 1,${python_version_full})
- ifneq ($(python_version_major),2)
- python_version_major := 3
+ PY := $(shell command -v python3 2>/dev/null)
+ ifeq ($(PY),)
+ PY := $(shell command -v python 2>/dev/null)
endif
endif
@@ -134,7 +134,9 @@ else
bin = ../bin/$(DIRNAME)_llvm
INCLUDE = -I../../Ganlib/lib/$(DIRNAME)_llvm/modules/
FFLAGS += -mmlir -fdynamic-heap-array
- LFLAGS += -lclang_rt.osx
+ ifeq ($(OS),Darwin)
+ LFLAGS += -lclang_rt.osx
+ endif
else
lib = ../lib/$(DIRNAME)
libUtl = ../../Utilib/lib/$(DIRNAME)
@@ -151,14 +153,27 @@ ifeq ($(hdf5),1)
LFLAGS += -L${HDF5_API} -lhdf5
endif
-SRC77 = $(shell ls *.f)
-ifeq ($(python_version_major),2)
- SRC90 = $(shell python ../../script/make_depend.py *.f90)
+SRC77 = $(shell ls *.f 2>/dev/null)
+ifeq ($(PY),)
+ $(warning No Python interpreter found; Fortran dependency ordering may be suboptimal)
+ SRC90 = $(shell ls *.f90 2>/dev/null)
else
- SRC90 = $(shell python3 ../../script/make_depend_py3.py *.f90)
+ SRC90 = $(shell $(PY) ../../script/make_depend.py *.f90 *.F90)
endif
-OBJ90 = $(SRC90:.f90=.o)
+OBJ90 = $(patsubst %.f90,%.o,$(patsubst %.F90,%.o,$(SRC90)))
OBJ77 = $(SRC77:.f=.o)
+
+# Auto-generated dependency file capturing Fortran module and include deps
+DEPS_MK := .trivac_deps.mk
+-include $(DEPS_MK)
+$(DEPS_MK): $(SRC90) $(SRC77) $(SRCF77)
+ifeq ($(PY),)
+ @echo "# Dependencies not generated: no Python available" > $(DEPS_MK)
+else
+ @echo "# Generating Fortran dependencies into $(DEPS_MK)"; \
+ $(PY) ../../script/make_depend.py --make-deps $(SRC90) $(SRC77) $(SRCF77) > $(DEPS_MK) || { rm -f $(DEPS_MK); exit 1; }
+endif
+
all : sub-make Trivac
ifeq ($(openmp),1)
@echo 'Trivac: openmp is defined'
@@ -184,8 +199,8 @@ sub-make:
$(F90) $(FFLAG77) $(opt) $(COMP) $(INCLUDE) -c $< -o $@
$(lib)/:
mkdir -p $(lib)/
-libTrivac.a: $(OBJ90) $(OBJ77) $(lib)/
- ar r $@ $(OBJ90) $(OBJ77)
+libTrivac.a: $(DEPS_MK) $(OBJ90) $(OBJ77) $(lib)/
+ ar rcs $@ $(OBJ90) $(OBJ77)
cp $@ $(lib)/$@
$(bin)/:
mkdir -p $(bin)/
@@ -196,4 +211,4 @@ Trivac: libTrivac.a TRIVAC.o $(bin)/ sub-make
clean:
$(MAKE) -C ../../Utilib/src clean
$(MAKE) -C ../../Ganlib/src clean
- /bin/rm -f *.o *.a sub-make temp.* Trivac
+ /bin/rm -f *.o *.a sub-make temp.* Trivac $(DEPS_MK)
diff --git a/Utilib/src/Makefile b/Utilib/src/Makefile
index 2bb6d73..e56d213 100644
--- a/Utilib/src/Makefile
+++ b/Utilib/src/Makefile
@@ -1,7 +1,7 @@
#---------------------------------------------------------------------------
#
# Makefile for building the Utilib library
-# Author : A. Hebert (2018-5-10)
+# Author : A. Hebert (2018-5-10) and C. Bienvenue (2025-11-04)
#
#---------------------------------------------------------------------------
#
@@ -19,6 +19,7 @@ endif
DIRNAME = $(shell uname -sm | sed 's/[ ]/_/')
OS = $(shell uname -s | cut -d"_" -f1)
opt = -O -g
+.DEFAULT_GOAL := all
ifeq ($(openmp),1)
COMP = -fopenmp
else
@@ -44,12 +45,11 @@ else
endif
ifeq ($(OS),AIX)
- python_version_major := 2
+ PY := python
else
- python_version_full := $(wordlist 2,4,$(subst ., ,$(shell python --version 2>&1)))
- python_version_major := $(word 1,${python_version_full})
- ifneq ($(python_version_major),2)
- python_version_major := 3
+ PY := $(shell command -v python3 2>/dev/null)
+ ifeq ($(PY),)
+ PY := $(shell command -v python 2>/dev/null)
endif
endif
@@ -128,7 +128,9 @@ else
lib = ../lib/$(DIRNAME)_llvm
lib_module = ../lib/$(DIRNAME)_llvm/modules
FFLAGS += -mmlir -fdynamic-heap-array
- LFLAGS += -lclang_rt.osx
+ ifeq ($(OS),Darwin)
+ LFLAGS += -lclang_rt.osx
+ endif
else
lib = ../lib/$(DIRNAME)
lib_module = ../lib/$(DIRNAME)/modules
@@ -136,16 +138,29 @@ else
endif
endif
-SRCC = $(shell ls *.c)
-SRC77 = $(shell ls *.f)
-ifeq ($(python_version_major),2)
- SRC90 = $(shell python ../../script/make_depend.py *.f90)
+SRCC = $(shell ls *.c 2>/dev/null)
+SRC77 = $(shell ls *.f 2>/dev/null)
+ifeq ($(PY),)
+ $(warning No Python interpreter found; Fortran dependency ordering may be suboptimal)
+ SRC90 = $(shell ls *.f90 2>/dev/null)
else
- SRC90 = $(shell python3 ../../script/make_depend_py3.py *.f90)
+ SRC90 = $(shell $(PY) ../../script/make_depend.py *.f90 *.F90)
endif
OBJC = $(SRCC:.c=.o)
-OBJ90 = $(SRC90:.f90=.o)
+OBJ90 = $(patsubst %.f90,%.o,$(patsubst %.F90,%.o,$(SRC90)))
OBJ77 = $(SRC77:.f=.o)
+
+ # Auto-generated dependency file capturing Fortran module and include deps
+DEPS_MK := .utilib_deps.mk
+-include $(DEPS_MK)
+$(DEPS_MK): $(SRC90) $(SRC77) $(SRCF77)
+ifeq ($(PY),)
+ @echo "# Dependencies not generated: no Python available" > $(DEPS_MK)
+else
+ @echo "# Generating Fortran dependencies into $(DEPS_MK)"; \
+ $(PY) ../../script/make_depend.py --make-deps $(SRC90) $(SRC77) $(SRCF77) > $(DEPS_MK) || { rm -f $(DEPS_MK); exit 1; }
+endif
+
all : libUtilib.a
@echo 'Utilib: fflags=' $(FFLAGS)
ifeq ($(openmp),1)
@@ -158,9 +173,9 @@ ifeq ($(nvidia),1)
@echo 'Utilib: nvidia is defined'
endif
ifeq ($(llvm),1)
-] @echo 'Utilib: llvm is defined'
+ @echo 'Utilib: llvm is defined'
endif
- @echo "Utilib: python version=" ${python_version_major}
+ @echo "Utilib: python=" $(PY)
%.o : %.c
$(C) $(CFLAGS) $(opt) $(COMP) -c $< -o $@
%.o : %.f90
@@ -173,8 +188,8 @@ $(lib_module)/:
$(lib)/: $(lib_module)/
mkdir -p $(lib)/
libUtilib.a: $(OBJC) $(OBJ90) $(OBJ77) $(lib)/
- ar r $@ $(OBJC) $(OBJ90) $(OBJ77)
+ ar rcs $@ $(OBJC) $(OBJ90) $(OBJ77)
cp $@ $(lib)/$@
cp *.mod $(lib_module)
clean:
- /bin/rm -f *.o *.mod *.a
+ /bin/rm -f *.o *.mod *.a $(DEPS_MK)
diff --git a/doc/IGE335/Section6.00.tex b/doc/IGE335/Section6.00.tex
index f49f89b..c26d277 100644
--- a/doc/IGE335/Section6.00.tex
+++ b/doc/IGE335/Section6.00.tex
@@ -42,6 +42,12 @@ make
make clean
\end{verbatim}
+To speed up the build, run make with multiple jobs using the \texttt{-jN} option. For example, to run 8 parallel jobs:
+\begin{verbatim}
+make -j8
+make clean
+\end{verbatim}
+
\noindent To build an OpenMP-enabled version, simply write
\begin{verbatim}
make openmp=1
diff --git a/script/make_depend.py b/script/make_depend.py
index 15c656e..ce8f688 100755
--- a/script/make_depend.py
+++ b/script/make_depend.py
@@ -1,57 +1,222 @@
-#!/bin/env python
-""" generation of module dependances for a xxx.f90 or xxx.F90 file """
-
-import string,sys
-from subprocess import Popen, PIPE
-
-def noComment(mot):
- """ remove comment characters in a word """
- ind= string.find(mot,'!')
- if ind != -1:
- mot= mot[:ind]
- return mot
-
-class md9:
- """ a file, its module and its dependances """
- def __init__(self,fic):
- self.name= fic
- self.used= []
- #find all module dependances
- listeLignes= open(self.name,'r').readlines()
- self.module= "dummy"
- for ligne in listeLignes:
- ligne= string.lower(ligne)
- if string.count(ligne,'use'):
- ligne= string.replace(ligne,',',' ')
- listeMots= string.split(ligne)
- if listeMots[0] == 'use':
- mod= noComment(listeMots[1])
- if mod not in self.used and mod != 'intrinsic':
- self.used.append(mod)
- elif string.count(ligne,'module'):
- listeMots= string.split(ligne)
- if listeMots[0] == 'module' and \
- noComment(listeMots[1]) != 'procedure':
- self.module= listeMots[1]
- def utilise(self,other):
- return (other.module in self.used)
-
-listeClasse= list()
-for x in sys.argv[1:]:
- if x.endswith('.f90') or x.endswith('.F90') : listeClasse.append(md9(x))
-#sort the file list
-listeRes= []
-while listeClasse:
- lgav= len(listeClasse)
- for fic in listeClasse:
- if len(filter(lambda x,y=fic:y.utilise(x),listeClasse)) == 0:
- listeRes.append(fic)
- listeClasse.remove(fic)
- lgap= len(listeClasse)
- if lgav == lgap and lgap != 0:
- raise RuntimeError("make_depend: cross-references found")
-#result output
-resstr=''
-for fic in listeRes:
- resstr=resstr+fic.name+' '
-print resstr
+#!/usr/bin/env python
+"""
+Generate Fortran dependencies from sources (*.f90, *.F90).
+
+Usage:
+ - Default: prints a dependency-ordered list of source files.
+ - --make-deps: prints Makefile-style dependency rules.
+"""
+
+from __future__ import print_function
+import sys
+import os
+import io
+import re
+import glob
+
+def strip_comment(line):
+ idx = line.find('!')
+ return line if idx == -1 else line[:idx]
+
+class FortranUnit(object):
+ USE_RE = re.compile(r"^\s*use\s+([a-z0-9_]+)", re.IGNORECASE)
+ MODULE_RE = re.compile(r"^\s*module\s+([a-z0-9_]+)", re.IGNORECASE)
+ MODULE_PROC_RE = re.compile(r"^\s*module\s+procedure\b", re.IGNORECASE)
+ END_MODULE_RE = re.compile(r"^\s*end\s*module\b", re.IGNORECASE)
+ CONTAINS_RE = re.compile(r"^\s*contains\b", re.IGNORECASE)
+ INCLUDE_RE = re.compile(r"^\s*include\s*[\'\"]([^\'\"]+)[\'\"]", re.IGNORECASE)
+
+ def __init__(self, path):
+ self.name = path
+ self.base = os.path.basename(path)
+ self.base_lc = self.base.lower()
+ self.module = None
+ self.uses = []
+ self.includes_in_contains = []
+ self._parse()
+
+ def _parse(self):
+ in_module = False
+ in_contains = False
+ try:
+ with io.open(self.name, 'r') as f:
+ lines = f.readlines()
+ except IOError:
+ return
+ for raw in lines:
+ line = strip_comment(raw).strip('\n')
+ if not line:
+ continue
+ low = line.lower()
+ if self.MODULE_RE.match(low) and not self.MODULE_PROC_RE.match(low):
+ m = self.MODULE_RE.match(low)
+ if m:
+ self.module = m.group(1)
+ in_module = True
+ in_contains = False
+ continue
+ if in_module and self.CONTAINS_RE.match(low):
+ in_contains = True
+ continue
+ if in_module and self.END_MODULE_RE.match(low):
+ in_module = False
+ in_contains = False
+ continue
+ m_use = self.USE_RE.match(low)
+ if m_use:
+ mod = m_use.group(1)
+ if mod != 'intrinsic' and mod not in self.uses:
+ self.uses.append(mod)
+ continue
+ if in_module and in_contains:
+ m_inc = self.INCLUDE_RE.match(low)
+ if m_inc:
+ inc = m_inc.group(1).strip()
+ self.includes_in_contains.append(os.path.basename(inc))
+
+def build_units(paths):
+ exts = (".f90", ".F90", ".f", ".F")
+ return [FortranUnit(p) for p in paths if p.lower().endswith(exts)]
+
+def build_dependency_order(paths):
+ units = build_units(paths)
+ by_base_lc = dict((u.base_lc, u) for u in units)
+ module_to_unit = dict((u.module, u) for u in units if u.module)
+ included_to_container = {}
+ for u in units:
+ if u.module and u.includes_in_contains:
+ for inc in u.includes_in_contains:
+ included_to_container.setdefault(inc.lower(), set()).add(u)
+
+ edges = dict((u, set()) for u in units)
+ indeg = dict((u, 0) for u in units)
+
+ def add_edge(src, dst):
+ if src is dst:
+ return
+ if dst not in edges[src]:
+ edges[src].add(dst)
+ indeg[dst] += 1
+
+ for u in units:
+ for mod in u.uses:
+ v = module_to_unit.get(mod)
+ if not v:
+ continue
+ included_containers = included_to_container.get(u.base_lc, set())
+ if v in included_containers:
+ continue
+ add_edge(v, u)
+
+ for container in units:
+ if container.module and container.includes_in_contains:
+ for inc in container.includes_in_contains:
+ inc_u = by_base_lc.get(inc.lower())
+ if inc_u:
+ add_edge(inc_u, container)
+
+ ordered = []
+ zero = [u for u in units if indeg[u] == 0]
+ zero.sort(key=lambda x: x.base_lc)
+ while zero:
+ n = zero.pop(0)
+ ordered.append(n)
+ for m in list(edges[n]):
+ edges[n].remove(m)
+ indeg[m] -= 1
+ if indeg[m] == 0:
+ zero.append(m)
+ zero.sort(key=lambda x: x.base_lc)
+
+ remaining = [u for u in units if u not in ordered]
+ if remaining:
+ remaining.sort(key=lambda x: (0 if not x.module else 1, x.base_lc))
+ ordered.extend(remaining)
+
+ excluded_bases = set()
+ for u in units:
+ if u.module and u.includes_in_contains:
+ for inc in u.includes_in_contains:
+ excluded_bases.add(inc.lower())
+
+ return [u.name for u in ordered if u.base_lc not in excluded_bases]
+
+def make_obj_name(path):
+ base, ext = os.path.splitext(path)
+ return base + ".o"
+
+def generate_make_deps(paths):
+ units = build_units(paths)
+ if not units:
+ return ""
+ by_base_lc = dict((u.base_lc, u) for u in units)
+ module_to_unit = dict((u.module, u) for u in units if u.module)
+ included_to_container = {}
+ for u in units:
+ if u.module and u.includes_in_contains:
+ for inc in u.includes_in_contains:
+ included_to_container.setdefault(inc.lower(), set()).add(u)
+
+ lines = []
+ for u in units:
+ deps_objs = set()
+ deps_files = set()
+
+ for mod in u.uses:
+ v = module_to_unit.get(mod)
+ if not v:
+ continue
+ included_containers = included_to_container.get(u.base_lc, set())
+ if v in included_containers:
+ continue
+ if v is not u:
+ deps_objs.add(make_obj_name(v.name))
+
+ if u.includes_in_contains:
+ for inc in u.includes_in_contains:
+ inc_u = by_base_lc.get(os.path.basename(inc).lower())
+ if inc_u:
+ deps_files.add(inc_u.name)
+ else:
+ deps_files.add(inc)
+
+ if deps_objs or deps_files:
+ target = make_obj_name(u.name)
+ deps = sorted(deps_objs) + sorted(deps_files)
+ lines.append("{}: {}".format(target, ' '.join(deps)))
+
+ return "\n".join(lines) + ("\n" if lines else "")
+
+def main():
+ argv = sys.argv[1:]
+ if not argv:
+ print("")
+ return
+
+ make_deps = False
+ if "--make-deps" in argv:
+ make_deps = True
+ argv = [a for a in argv if a != "--make-deps"]
+
+ paths = []
+ for a in argv:
+ if any(ch in a for ch in ['*', '?', '[']):
+ paths.extend(glob.glob(a))
+ else:
+ paths.append(a)
+
+ seen = set()
+ unique_paths = []
+ for p in paths:
+ if p not in seen:
+ seen.add(p)
+ unique_paths.append(p)
+
+ if make_deps:
+ sys.stdout.write(generate_make_deps(unique_paths))
+ else:
+ result = build_dependency_order(unique_paths)
+ sys.stdout.write("%s\n" % (" ".join(result)))
+
+if __name__ == '__main__':
+ main()
diff --git a/script/make_depend_py3.py b/script/make_depend_py3.py
deleted file mode 100755
index a47d7fb..0000000
--- a/script/make_depend_py3.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/env python3
-""" generation of module dependances for a xxx.f90 or xxx.F90 file """
-
-import string,sys
-from subprocess import Popen, PIPE
-
-def noComment(mot):
- """ remove comment characters in a word """
- ind= mot.find('!')
- if ind != -1:
- mot= mot[:ind]
- return mot
-
-class md9:
- """ a file, its module and its dependances """
- def __init__(self,fic):
- self.name= fic
- self.used= []
- #find all module dependances
- listeLignes= open(self.name,'r',encoding='utf8',errors='ignore').readlines()
- self.module= "dummy"
- for ligne in listeLignes:
- ligne= ligne.lower()
- if ligne.count('use'):
- ligne= ligne.replace(',',' ')
- listeMots= ligne.split()
- if listeMots[0] == 'use':
- mod= noComment(listeMots[1])
- if mod not in self.used and mod != 'intrinsic':
- self.used.append(mod)
- elif ligne.count('module'):
- listeMots= ligne.split()
- if listeMots[0] == 'module' and \
- noComment(listeMots[1]) != 'procedure':
- self.module= listeMots[1]
- def utilise(self,other):
- return (other.module in self.used)
-
-#list the file names
-listeClasse= list()
-for x in sys.argv[1:]:
- if x.endswith('.f90') or x.endswith('.F90'): listeClasse.append(md9(x))
-#sort the file list
-listeRes= []
-while listeClasse:
- lgav= len(listeClasse)
- for fic in listeClasse:
- if len(list(filter(lambda x,y=fic:y.utilise(x),listeClasse))) == 0:
- listeRes.append(fic)
- listeClasse.remove(fic)
- lgap= len(listeClasse)
- if lgav == lgap and lgap != 0:
- raise RuntimeError("make_depend: cross-references found")
-#result output
-resstr=''
-for fic in listeRes:
- resstr=resstr+fic.name+' '
-print(resstr)