From 4bcc8490b2e3d477a0847dfe1b94f635a796e0a2 Mon Sep 17 00:00:00 2001 From: Marshall Ward Date: Tue, 14 Jun 2022 16:51:29 -0400 Subject: [PATCH] Makedep (#1) * Autoconf: Fix makedep path The current path of makedep in the autoconf build assumes a directory tree as in .testing. This patch uses the generalized @srcdir@ to support more general autoconf builds. Other minor changes: * The `depend` rule was split into an explicit Makefile.dep rule and a phony rule to support `make depend` * SRC_DIRS shell assignment is replaced with an Autoconf macro. * A "self-generate" rule was added to `Makefile.in`, so that changes to `Makefile.in` do not trigger a full `./configure` run and regeneration of `.config.status`. This could possibly be extended to support `make depend` but let's first see how this one goes. * Autoconf: makedep uses autoconf var conventions This patch changes the makedep script to use autoconf environment variable conventions rather than mkmf ones: * FCFLAGS in place of FFLAGS * DEFS in place of CPPDEFS * LDFLAGS and LIBS rather than just LDFLAGS (NOTE: This differs from Makefile's LDLFLAGS/LDLIBS) This also allowed us to remove the custom build rule in the FMS build. Note that we now use an autoconf-friendly rule, rather than the default Makefile rule (which was arguably for fixed-format Fortran anyway). The description of autoconf->mkmf translation from the Makefile templates has also been removed, since they're no longer relevant. Some other minor changes in this build: * The `make depend` rule was added to the FMS Makefile template. * @srcdir@ is directly passed to FMS makedep, rather than identically re-defining it in a variable. * Testing: Resolve makedep paths This patch resolves some issues relating to finding the path to makedep in both .testing and more generalized autoconf builds. An explicit autoconf test for makedep has been added, with a default path which includes the `ac` directory relative to `deps`. The .testing directory, which does not lie within `ac`, instead modifies the PATH to allow autoconf to find makedep. The absolute path is determined and substituted into the appropriate Makefile.in template. Some redundant operations in .testing/Makefile have been removed, but I suspect there are even more. Much of the structure required to support mkmf and list_paths is probably no longer needed. --- .testing/Makefile | 3 +- ac/Makefile.in | 65 +++++++++++----------------------------- ac/configure.ac | 17 +++++++---- ac/deps/Makefile | 16 ++++------ ac/deps/Makefile.fms.in | 59 ++++++------------------------------ ac/deps/configure.fms.ac | 22 +++++++++----- ac/makedep | 12 ++++---- 7 files changed, 64 insertions(+), 130 deletions(-) diff --git a/.testing/Makefile b/.testing/Makefile index 6e61ec8f39..972c213032 100644 --- a/.testing/Makefile +++ b/.testing/Makefile @@ -324,7 +324,7 @@ $(TARGET_CODEBASE): # FMS # Set up the FMS build environment variables -FMS_ENV = PATH="${PATH}:../../bin" FCFLAGS="$(FCFLAGS_DEBUG)" +FMS_ENV = PATH="${PATH}:$(realpath ../ac)" FCFLAGS="$(FCFLAGS_DEBUG)" # TODO: *.mod dependencies? $(DEPS)/lib/libFMS.a: $(DEPS)/fms/build/libFMS.a @@ -335,7 +335,6 @@ $(DEPS)/fms/build/libFMS.a: $(DEPS)/fms/build/Makefile $(DEPS)/fms/build/Makefile: $(DEPS)/fms/src/configure $(DEPS)/Makefile.fms.in $(FMS_ENV) $(MAKE) -C $(DEPS) fms/build/Makefile - $(MAKE) -C $(DEPS) fms/build/Makefile $(DEPS)/Makefile.fms.in: ../ac/deps/Makefile.fms.in $(DEPS)/Makefile cp $< $(DEPS) diff --git a/ac/Makefile.in b/ac/Makefile.in index 711fab1f6f..2e482ab0c5 100644 --- a/ac/Makefile.in +++ b/ac/Makefile.in @@ -2,65 +2,34 @@ # # Compiler flags are configured by autoconf's configure script. # -# Source code dependencies are configured by mkmf and list_paths, specified in -# the `Makefile.mkmf` file. -# -# mkmf conventions are close, but not identical, to autoconf. We attempt to -# map the autoconf variables to the mkmf variables. -# -# The following variables are used by Makefiles generated by mkmf. -# -# CC C compiler -# CXX C++ compiler -# FC Fortran compiler (f77 and f90) -# LD Linker -# AR Archiver -# -# CPPDEFS Preprocessor macros -# CPPFLAGS C preprocessing flags -# CXXFLAGS C++ preprocessing flags -# FPPFLAGS Fortran preprocessing flags -# -# CFLAGS C compiler flags -# FFLAGS Fortran compiler flags -# LDFLAGS Linker flags + libraries -# ARFLAGS Archiver flags -# -# OTHERFLAGS Additional flags for all languages (C, C++, Fortran) -# OTHER_CFLAGS Optional C flags -# OTHER_CXXFLAGS Optional C++ flags -# OTHER_FFLAGS Optional Fortran flags -# TMPFILES Placeholder for `make clean` deletion (as `make neat`). -# -# -# NOTES: -# - FPPFLAGS and FFLAGS always appear as a pair, and autoconf does not use -# FPPFLAGS, so FPPFLAGS does not serve much purpose. -# -# - mkmf's FFLAGS does not distinguish between autoconf's fixed-format -# FFLAGS and free-format FCFLAGS. -# -# - LDFLAGS does not distinguish between autoconf's LDFLAGS and LIBS. -# It also places both after the executable rather than just LIBS. +# Source code dependencies are configured by makedep and saved to Makefile.dep. FC = @FC@ LD = @FC@ +MAKEDEP = @MAKEDEP@ -CPPDEFS = @DEFS@ +DEFS = @DEFS@ CPPFLAGS = @CPPFLAGS@ -FFLAGS = @FCFLAGS@ -LDFLAGS = @LDFLAGS@ @LIBS@ - +FCFLAGS = @FCFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ SRC_DIRS = @SRC_DIRS@ -# Gather modulefiles -TMPFILES = $(wildcard *.mod) -include Makefile.dep + +# Generate Makefile from template +Makefile: @srcdir@/ac/Makefile.in config.status + ./config.status + + +# Generate dependencies .PHONY: depend -depend: - ../../../ac/makedep -o Makefile.dep $(SRC_DIRS) +depend: Makefile.dep +Makefile.dep: + $(MAKEDEP) -o Makefile.dep $(SRC_DIRS) + # Delete any files associated with configuration (including the Makefile). .PHONY: distclean diff --git a/ac/configure.ac b/ac/configure.ac index 02e39c63a0..15a14708e0 100644 --- a/ac/configure.ac +++ b/ac/configure.ac @@ -223,13 +223,20 @@ AC_COMPILE_IFELSE( ] ) -SRC_DIRS="${srcdir}/src ${MODEL_FRAMEWORK} ${srcdir}/config_src/external ${DRIVER_DIR} ${MEM_LAYOUT}" -AC_CONFIG_COMMANDS([Makefile.dep], - [make depend]) + +# Verify that makedep is available +AC_PATH_PROG([MAKEDEP], [makedep], [${srcdir}/ac/makedep]) +AC_SUBST([MAKEDEP]) + + +# Generate source list and configure dependency command +AC_SUBST([SRC_DIRS], + ["${srcdir}/src ${MODEL_FRAMEWORK} ${srcdir}/config_src/external ${DRIVER_DIR} ${MEM_LAYOUT}"] +) +AC_CONFIG_COMMANDS([Makefile.dep], [make depend]) # Prepare output -AC_SUBST(CPPFLAGS) -AC_SUBST(SRC_DIRS) +AC_SUBST([CPPFLAGS]) AC_CONFIG_FILES([Makefile:${srcdir}/ac/Makefile.in]) AC_OUTPUT diff --git a/ac/deps/Makefile b/ac/deps/Makefile index f56b762883..af567f6a72 100644 --- a/ac/deps/Makefile +++ b/ac/deps/Makefile @@ -6,7 +6,6 @@ SHELL = bash # Disable implicit variables MAKEFLAGS += -R - # FMS framework FMS_URL ?= https://github.com/NOAA-GFDL/FMS.git FMS_COMMIT ?= 2019.01.03 @@ -26,14 +25,8 @@ FMS_SOURCE = $(call SOURCE,fms/src) # Rules .PHONY: all -all: bin/makedep lib/libFMS.a - -#--- -# makedep script +all: lib/libFMS.a -bin/makedep: ../../ac/makedep - mkdir -p $(@D) - cp $^ $@ #--- # FMS build @@ -45,7 +38,7 @@ bin/makedep: ../../ac/makedep # TODO: track *.mod copy? -lib/libFMS.a: fms/build/libFMS.a fms/build/Makefile +lib/libFMS.a: fms/build/libFMS.a mkdir -p {lib,include} cp fms/build/libFMS.a lib/libFMS.a cp fms/build/*.mod include @@ -55,7 +48,7 @@ fms/build/libFMS.a: fms/build/Makefile make -C fms/build libFMS.a -fms/build/Makefile: Makefile.fms.in fms/src/configure bin/makedep +fms/build/Makefile: Makefile.fms.in fms/src/configure mkdir -p fms/build cp Makefile.fms.in fms/src/Makefile.in cd $(@D) && ../src/configure --srcdir=../src @@ -67,6 +60,7 @@ fms/src/configure: configure.fms.ac $(FMS_SOURCE) | fms/src cp -r m4 $(@D) cd $(@D) && autoreconf -i + fms/src: git clone $(FMS_URL) $@ git -C $@ checkout $(FMS_COMMIT) @@ -74,7 +68,7 @@ fms/src: .PHONY: clean clean: - rm -rf fms/build lib include bin + rm -rf fms/build lib include .PHONY: distclean distclean: clean diff --git a/ac/deps/Makefile.fms.in b/ac/deps/Makefile.fms.in index 499a1a6a72..fc580a8c9e 100644 --- a/ac/deps/Makefile.fms.in +++ b/ac/deps/Makefile.fms.in @@ -1,66 +1,25 @@ -# Makefile template for autoconf builds using mkmf +# Makefile template for FMS # # Compiler flags are configured by autoconf's configure script. # -# Source code dependencies are configured by mkmf and list_paths, specified in -# the `Makefile.mkmf` file. -# -# mkmf conventions are close, but not identical, to autoconf. We attempt to -# map the autoconf variables to the mkmf variables. -# -# The following variables are used by Makefiles generated by mkmf. -# -# CC C compiler -# CXX C++ compiler -# FC Fortran compiler (f77 and f90) -# LD Linker -# AR Archiver -# -# CPPDEFS Preprocessor macros -# CPPFLAGS C preprocessing flags -# CXXFLAGS C++ preprocessing flags -# FPPFLAGS Fortran preprocessing flags -# -# CFLAGS C compiler flags -# FFLAGS Fortran compiler flags -# LDFLAGS Linker flags + libraries -# ARFLAGS Archiver flags -# -# OTHERFLAGS Additional flags for all languages (C, C++, Fortran) -# OTHER_CFLAGS Optional C flags -# OTHER_CXXFLAGS Optional C++ flags -# OTHER_FFLAGS Optional Fortran flags -# TMPFILES Placeholder for `make clean` deletion (as `make neat`). -# -# -# NOTES: -# - FPPFLAGS and FFLAGS always appear as a pair, and autoconf does not use -# FPPFLAGS, so FPPFLAGS does not serve much purpose. -# -# - mkmf's FFLAGS does not distinguish between autoconf's fixed-format -# FFLAGS and free-format FCFLAGS. -# -# - LDFLAGS does not distinguish between autoconf's LDFLAGS and LIBS. -# It also places both after the executable rather than just LIBS. +# Source code dependencies are configured by makedep and saved to Makefile.dep. CC = @CC@ FC = @FC@ LD = @FC@ AR = @AR@ +MAKEDEP = @MAKEDEP@ -CPPDEFS = @DEFS@ +DEFS = @DEFS@ CPPFLAGS = @CPPFLAGS@ -FFLAGS = @FCFLAGS@ +FCFLAGS = @FCFLAGS@ LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ ARFLAGS = @ARFLAGS@ -SRC_DIRS = @SRC_DIRS@ - -# Gather modulefiles -TMPFILES = $(wildcard *.mod) - -include Makefile.dep .PHONY: depend -depend: - ../../bin/makedep -o Makefile.dep -f '$$(FC) $$(CPPFLAGS) $$(CPPDEFS) $$(FFLAGS) -c $$<' -x libFMS.a -d $(SRC_DIRS) +depend: Makefile.dep +Makefile.dep: + $(MAKEDEP) -o Makefile.dep -x libFMS.a @srcdir@ diff --git a/ac/deps/configure.fms.ac b/ac/deps/configure.fms.ac index 4dc1a6614f..4e0c0f1390 100644 --- a/ac/deps/configure.fms.ac +++ b/ac/deps/configure.fms.ac @@ -158,20 +158,26 @@ AX_FC_ALLOW_ARG_MISMATCH FCFLAGS="$FCFLAGS $ALLOW_ARG_MISMATCH_FCFLAGS" +# Verify makedep +AC_PATH_PROGS([MAKEDEP], [makedep], [], ["${PATH}:${srcdir}/../../.."]) +AS_IF([test -n "${MAKEDEP}"], [ + AC_SUBST([MAKEDEP]) +], [ + AC_MSG_ERROR(["Could not find makedep."]) +]) + # Autoconf does not configure the archiver (ar), as it is handled by Automake. # TODO: Properly configure this tool. For now, we hard-set this to `ar`. AR=ar ARFLAGS=rv -AC_SUBST(AR) -AC_SUBST(ARFLAGS) +AC_SUBST([AR]) +AC_SUBST([ARFLAGS]) + +AC_CONFIG_COMMANDS([Makefile.dep], [make depend]) -SRC_DIRS="../src" -AC_CONFIG_COMMANDS([Makefile.dep], - [make depend]) +AC_SUBST([CPPFLAGS]) # Prepare output -AC_SUBST(CPPFLAGS) -AC_SUBST(SRC_DIRS) -AC_CONFIG_FILES(Makefile) +AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/ac/makedep b/ac/makedep index cb0a8896e3..74d9200ce8 100755 --- a/ac/makedep +++ b/ac/makedep @@ -16,7 +16,7 @@ usage() { echo " -x EXEC Name of executable to build. Fails if more than one" echo " is found. If EXEC ends in .a then a library is built." echo " -f CMD String to use in compile rule. Default is:" - echo " '$(FC) $(FFLAGS) $(CPPFLAGS) -c $<'" + echo " '$(FC) $(DEFS) $(FCFLAGS) $(CPPFLAGS) -c $<'" } # Defaults @@ -24,7 +24,7 @@ makefile=Makefile.dep debug=0 executable="" librarymode=0 -compile_line='$(FC) $(FFLAGS) $(CPPFLAGS) -c $<' +compile_line='$(FC) $(DEFS) $(FCFLAGS) $(CPPFLAGS) -c $<' while getopts dho:x:f: option do @@ -61,7 +61,7 @@ for F in ${A}; do # F is the relative path to source file u=`echo $u | sed s:$m::g` fi if [ ${#u} -ne 0 ]; then o2use["$o"]=$u; fi - H=$(/lib/cpp -E -MM $I $F | tr -d '\n' | sed 's:\\::g') # line of form a.o: a.F b.h c.h ... + H=$(cpp -E -MM $I $F | tr -d '\n' | sed 's:\\::g') # line of form a.o: a.F b.h c.h ... o2H["$o"]=$H h=`echo ${H} | cut -d\ -f3- ` # header files if [ ${#h} -ne 0 ]; then o2head["$o"]=$h; fi @@ -91,7 +91,7 @@ for F in ${A}; do # F is the relative path to source file f=`basename $F` # file name stripped of path o=${f/.c/}.o # object file name o2c["$o"]=$F - H=$(/lib/cpp -E -MM $I $F | tr -d '\n' | sed 's:\\::g') # line of form a.o: a.F b.h c.h ... + H=$(cpp -E -MM $I $F | tr -d '\n' | sed 's:\\::g') # line of form a.o: a.F b.h c.h ... o2H["$o"]=$H h=`echo ${H} | cut -d\ -f3- ` # header files if [ ${#h} -ne 0 ]; then o2head["$o"]=$h; fi @@ -189,7 +189,7 @@ for o in ${OC[@]}; do echo "# incpath:" $i >> ${makefile} fi echo $H ${U[@]} >> ${makefile} # a.mod a.o: a.F b.mod - echo -e '\t$(CC) $(CPPDEFS) $(CPPFLAGS) $(CFLAGS) -c $<' ${i} >> ${makefile} # compile rule + echo -e '\t$(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $<' ${i} >> ${makefile} # compile rule done if [ ${#lib} -ne 0 ]; then # rule to build library @@ -207,7 +207,7 @@ if [ ${#p2o[@]} -ne 0 ]; then # write rules for linking executables o=${p2o[$p]} l=$(make -f ${makefile} -B -n -t $o | egrep "\.o$" | sed 's:touch ::' | sort) echo $p: $l ${externals[@]} >> ${makefile} - echo -e '\t$(LD) -o $@ $^ $(LDFLAGS)' >> ${makefile} # link rule + echo -e '\t$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)' >> ${makefile} # link rule done elif [ -z "$lib" ]; then echo "Warning: no library target specified (with -x) and no programs found!"