The AHA Model  Revision: 12809
Reference implementation 04 (HEDG02_04)
Makefile
Go to the documentation of this file.
1 #-------------------------------------------------------------------------------
2 # SVN version info:
3 # $Id: Makefile 11235 2021-06-08 12:38:54Z sbu062 $
4 # Build model automatically generating include files for PRNG and IEEE
5 # author Sergey Budaev <sbudaev@gmail.com>
6 #-------------------------------------------------------------------------------
7 ##//! @file Makefile GNU Make build configuration.
8 ##//! @brief Makefile to build the model executable from the source code.
9 ##//! @details This is a standard GNU Make "Makefile" to build the model from
10 ##//! the sources. It also automatically generates some platform and
11 ##//! compiler specific include files for the `BASE_RANDOM` and the
12 ##//! IEEE math modules. See @ref intro_main "Working with the model"
13 ##//! section and the @ref README.md for details.
14 ##//!
15 ##//! ### Dependencies ###
16 ##//! In addition to the GNU Make, this Makefile also depends on the
17 ##//! `grep`, `cut`, `sed` and `awk` utilities that are installed on any
18 ##//! Unix/Linux system, but usually absent on Windows. For Windows
19 ##//! they can be obtained from several locations on the web, e.g.
20 ##//! Cygwin or GnuWin32. See http://ahamodel.uib.no/doc/ar01s01.html for
21 ##//! more information.
22 ##//!
23 ##//! ### Main adjustable parameters ###
24 ##//! @param FC sets the default compiler type from the above. Normally GNU
25 ##//! gfortran.
26 ##//! @param HOST_HPC_ROOT is the hostname to run the model executable in the
27 ##//! HPC batch mode. If the hostname the Makefile is called in is this
28 ##//! system, `make run` starts a new batch task. Otherwise, the model
29 ##//! executable is just started normally.
30 ##//! @param SRC is the name of the main source code (can be several files).
31 ##//! @param DRV is the source code of the model "driver", that is the main
32 ##//! Fortran program that produces the executable. It should be very
33 ##//! very small. The "driver" is a separate file from the AHA Model
34 ##//! modules.
35 ##//! @param OUT is the executable file name that is actually run, on the
36 ##//! Windows platform must have the `.exe` suffix. By default, the
37 ##//! executable name is set to `MODEL.exe` for maximum portability.
38 ##//! @param DOXYCFG the Doxygen documentation system configuration file name.
39 ##//! @param DOXYPATH defines the Doxygen output directory where the
40 ##//! documentation is generated. This could be set manually or parsed
41 ##//! automatically using the `grep` command. Note that the output
42 ##//! directory is set in the `Doxyfile` as:
43 ##//! `OUTPUT_DIRECTORY = ./model_docs`.
44 ##//! @param HEDTOOLS is the list of HEDTOOLS Fortran source files that are
45 ##//! used in the AHA Model. Note that `BASE_STRINGS` in the list must
46 ##//! go before `BASE_CSV_IO` because `BASE_CSV_IO` depends on
47 ##//! procedures from `BASE_STRINGS`.
48 ##//! @param HEDTOOLSDIR defines the path to the HEDTOOLS source code.
49 ##//! @param IEEEPATH defines the path to the IEEE non-intrinsic math modules
50 ##//! (part of HEDTOOLS).
51 ##//! @param WINRM defines the command that is used to delete files and
52 ##//! directories on the Windows platform; can be set either `del` or
53 ##//! `rm`.
54 ##//! @note The native file delete command on the Windows platform is 'del' or
55 ##//! 'erase'. However, if Cygwin is used, this native file removal
56 ##//! command may not call with a "command not found" error. In such a
57 ##//! case, use the Unix 'rm' tool provided by Cygwin.
58 ##//!
59 ##//! The source code of the @ref Makefile contains many other parameters and
60 ##//! is well documented throughout.
61 ##//! @cond
62 # Doxygen note: block marked with cond .. endcond is excluded from Doxygen
63 # processing. Therefore, everything below to the end of the
64 # Makefile is not parsed. Makefile is not normally supported
65 # by Doxygen.
66 
67 #===============================================================================
68 
69 # Supported Fortran compiler types
70 GF_FC = gfortran
71 IF_FC = ifort
72 SF_FC = f95
73 
74 # Choose the default compiler type
75 FC = $(GF_FC)
76 
77 # Graphics library to use, for example:
78 # PGPLOT, if installed by the system:
79 # -lpgplot
80 # If PGPLOT is manually installed by the user into /usr/local/pgplot with
81 # X11 development libraries in /usr/lib/x86_64-linux-gnu (as in a
82 # Debian system), use this value for GRAPHLIB:
83 # -L/usr/local/pgplot -L/usr/lib/x86_64-linux-gnu -lpgplot -lX11
84 # --------------------------------------
85 # PLPLOT:
86 # -lplplotf95d -lplplotf95cd -lplf95demolibd -I/usr/lib/fortran/modules/plplot
87 GRAPHLIB =
88 
89 # Root of the host name to run in HPC cluster / batch mode, not directly
90 HOST_HPC_ROOT=fimm
91 
92 # Define what version control system is used, This is a default value used if
93 # VCS_TYPE is not set from command line of environment variable.
94 VCS_TYPE ?= SVN
95 
96 #===============================================================================
97 # Main building blocks, define the main program source, executable name (-o)
98 # and possible module (.mod) names.
99 
100 # These names should be set for particular project,
101 # Most probably they should be edited manually for each specific project
102 # SRC is the name of the main source code (can be several files). Note that
103 # Intel fortran doesn't like f95 file extension, use f90
104 # DRV is the source code of the model "driver", that is the main Fortran
105 # program that produces the executable. It should be very very small.
106 # The "driver" is a separate file from the modules.
107 # OUT is the executable file, on the Windows platform has the .exe suffix.
108 
109 SRC = m_common.f90 m_fileio.f90 m_env.f90 m_genome.f90 m_hormon.f90 \
110  m_body.f90 m_neuro.f90 m_behav.f90 m_indiv.f90 m_popul.f90 m_evolut.f90
111 
112 DRV = mod_drv.f90
113 
114 OUT = MODEL.exe
115 
116 # Doxygen configuration file within the same directory.
117 DOXYCFG = Doxyfile
118 
119 # Doxygen output directory, can be grepped from Configuration file.
120 # OUTPUT_DIRECTORY = ./model_docs
121 # DOXYPATH = model_docs
122 DOXYPATH = $(shell $(GREP) ^OUTPUT_DIRECTORY Doxyfile | $(CUT) -d '=' -f 2)
123 
124 #===============================================================================
125 # HEDTOOLS sources and module files:
126 # Warning: BASE_STRINGS must go before BASE_CSV_IO because BASE_CSV_IO now
127 # depends on procedures from BASE_STRINGS.
128 
129 HEDTOOLS = BASE_UTILS.f90 BASE_STRINGS.f90 BASE_CSV_IO.f90 BASE_LOGGER.f90 \
130  BASE_RANDOM.f90
131 
132 # Path to HEDTOOLS and IEEE non-intrinsic libs (part of HEDTOOLS).
133 HEDTOOLSDIR = ../HEDTOOLS
134 IEEEPATH = $(HEDTOOLSDIR)/IEEE
135 
136 # Path to the unit tests using pfUnit framework.
137 PFUNIT_PATH = pfunit
138 
139 #===============================================================================
140 # The name of the network server, where the data zip file is pushed by scp
141 # on `make zipsend` command. The server string must contain the complete
142 # destination in the scp notation (see `man scp`): [user@]host:]path
143 # e.g. budaev@bio0215550.klient.uib.no:/cygdrive/d/
144 # @note Note that the zip file as well as all files having the same root
145 # names (including zip extension) are transferred, e.g. `model_1.zip`
146 # along with `model_1.zip.md5` `model_1.zip.notes` `model_1.zip.txt`.
147 
148 AHA_STORAGE_SERVER_STR = budaev@bio0215550.klient.uib.no:/cygdrive/d/AHA-ZDATA/
149 
150 #===============================================================================
151 # Notification command for execution termination
152 
153 AHA_NOTIFY_CMD_WIN = c:\python27\python.exe o:\bin\xsendnc.py sbu062@tegsvn.uib.no 'Model run terminated'
154 AHA_NOTIFY_CMD_UNIX = xsendnc.py sbu062@tegsvn.uib.no "Model run terminated on `hostname`"
155 
156 #===============================================================================
157 # Accessory settings for the build environment
158 
159 # The native file delete command on the Windows platform is 'del' or 'erase'.
160 # However, if Cygwin is used, this native file removal command may not call
161 # with a "command not found" error. In such a case, use the Unix 'rm' tool
162 # provided by Cygwin.
163 WINRM := rm -fr
164 
165 #===============================================================================
166 # Define compiler options
167 
168 # #### Options for GNU Fortran
169 # Note: link-time optimisations -flto do not work on Windows, falls with the
170 # segmentation fault. On Linux, it builds without any problem, but seems
171 # to break the LOGGER module output, it loses the logger unit and log
172 # data go to fort.1. More testing is needed, -flto disabled so far.
173 GF_STATIC = -static-libgfortran -static -static-libgcc
174 GF_TRAPS = -ffpe-trap=
175 GF_RCHECKS = -Wall -fbounds-check
176 # Memory leaks sanitize checks for GCC using libasan, work on Linux and OSX
177 GF_MEMCHECK = -fsanitize=address -static-libasan
178 #GF_FFLAGS = $(GF_STATIC) $(GF_TRAPS) $(GF_RCHECKS) -O3
179 GF_FFLAGS = -O3 -march=native -funroll-loops -fforce-addr $(GF_STATIC)
180 GF_FFLAGS_WINDOWS = -O3 -funroll-loops -fforce-addr $(GF_STATIC)
181 #-ffpe-trap=zero,invalid,overflow,underflow
182 # GC_FFLAGS are for gcc C compiler (C may be used for IEEEs)
183 GC_FFLAGS = -O3
184 # On Windows might need -mwindows
185 
186 # #### Options for Intel Fortran
187 IF_ANNOTATE = -qopt-report-phase=vec -qopt-report-annotate=html
188 IF_REPORT_OPT = -qopt-report=3
189 IF_STATIC = -static
190 IF_TRAPS = -fpe3
191 IF_RCHECKS = -gen-interfaces -warn -check bounds,pointers,format,uninit
192 # Intel Fortran compiler options maximizing speed for the whole program: -fast
193 # Linux: -ipo, -O3, -no-prec-div, -static, -fp-model fast=2, and -xHost
194 # Note: Build with -ipo crashes on building the the $(OBJ) main model target
195 # with "Segmentation violation signal raised" (ifort 17.0.4 and earlier,
196 # starting at SVN rev. 5010). For this reason, -ipo option is disabled here
197 # (therefore -fast would not work either). When only the latest $(OUT)
198 # target includes -ipo option, a warning appears
199 # ipo: warning #11003: no IR in object file xxx
200 # and IPO optimisation should not probably be there either.
201 # Update: As to ifort 19.0.4.243 20190416, `IPO` works without `parallel`
202 # Base option: IF_FFLAGS = -sox -parallel -O3 -ipo
203 IF_FFLAGS = -sox -O3 -ipo $(IF_STATIC) -heap-arrays -fp-model fast=2 \
204  -xHost -finline-functions $(IF_REPORT_OPT) $(IF_ANNOTATE)
205 # For Intel Fortran, options are somewhat different on Windows platform.
206 # Note: Windows stack size is insufficient for the large number of concurrent
207 # threads and huge arrays used in the model. Therefore, stack overflow
208 # error is issued (ifort 17) with the default build options. Stack size
209 # available for the program is controlled by the /Fn option (n is in
210 # bytes). Setting a huge value resolves the stack overflow issue on the
211 # Windows platform. This can sometimes occur on the Linux and Mac OS X
212 # platforms too. To fix it on Linux, issue this command:
213 # ulimit -s unlimited
214 # Increasing stack size on Mac OS X is described here:
215 # https://developer.apple.com/library/content/qa/qa1419/_index.html.
216 # Base option: /Qsox /Qparallel
217 
218 # Note: The following worked on W7 but O2 optimization resulted
219 # in access violation crash on W10, O1 seems to work on W10
220 # IF_FFLAGS_WINDOWS = /Qsox /Qparallel /Ot /static /heap-arrays /fp:fast=2 \
221 # /QxHost /Ob2 /warn /fpe:0 /F100000000
222 IF_FFLAGS_WINDOWS = /Qsox /O1 /static /heap-arrays /warn /fpe:0 /F100000000
223 
224 #IF_FFLAGS = -sox -fast -parallel $(IF_STATIC) $(IF_TRAPS)
225 # -fpe3 no traps; -fpe0 all traps
226 # -O3
227 # Aggressive optimizations: -fast = -O3 –ipo –static
228 
229 # #### Options for Sun/Oracle Solaris Studio
230 SF_STATIC = -Bstatic -dn
231 SF_TRAPS = -ftrap=%none
232 SF_RCHECKS = -C
233 SF_FFLAGS = -O1 -depend=yes
234 # NOTE: optimisations exceeding -O1 might not work with all CSV_IO routines
235 # SF_FFLAGS = -fast -autopar -depend=yes
236 # -fast = O5
237 # -ftrap=common is a macro for -ftrap=invalid,overflow,division.
238 # -ftrap=%all, %none, common
239 
240 #-------------------------------------------------------------------------------
241 
242 # DEBUG turns off all optimisations and keeps debug symbols. Note that
243 # SNaNs are initialising all values in case of intel Fortran (-init=snan).
244 ifdef DEBUG
245  GF_FFLAGS = -O0 -g -ffpe-trap=zero,invalid,overflow,underflow \
246  -Warray-temporaries $(GF_RCHECKS)
247  GF_FFLAGS_WINDOWS = $(GF_FFLAGS)
248  IF_FFLAGS = -O0 -heap-arrays -gen-interfaces -g -debug all -fpe0 -traceback \
249  -init=snan $(IF_RCHECKS)
250  SF_FFLAGS = -O0 -g -ftrap=common
251  IF_FFLAGS_WINDOWS = /Qsox /optimize:0 /fpe:0 /heap-arrays /debug:all \
252  /traceback /Qinit:snan /gen-interfaces /check /warn \
253  /F100000000
254  RUNFLAG = DEBUG
255 endif
256 
257 # PROFILE adds profiling options (-pg on GNU). Then running the program provides
258 # a profiling report: gmon.out. It can be read with: gprof MODEL.exe
259 ifdef PROFILE
260  GF_FFLAGS += -pg
261 endif
262 
263 #-------------------------------------------------------------------------------
264 # Set other build options depending on the specific compiler
265 
266 ifeq ($(FC),$(GF_FC))
267  FFLAGS = $(GF_FFLAGS)
268  STATIC = $(GF_STATIC)
269  TRAPS = $(GF_TRAPS)
270  RCHECKS = $(GF_RCHECKS)
271  CC=gcc
272 endif
273 
274 ifeq ($(FC),$(IF_FC))
275  FFLAGS = $(IF_FFLAGS)
276  STATIC = $(IF_STATIC)
277  TRAPS = $(IF_TRAPS)
278  RCHECKS = $(IF_RCHECKS)
279 endif
280 
281 ifeq ($(FC),$(SF_FC))
282  FFLAGS = $(SF_FFLAGS)
283  STATIC = $(SF_STATIC)
284  TRAPS = $(SF_TRAPS)
285  RCHECKS = $(SF_RCHECKS)
286 endif
287 
288 #===============================================================================
289 # Determine what is the build platform, Windows / non-Windows
290 
291 # Use uname -- but it may not be installed on Windows. Probably the method
292 # based on ComSpec is safer. Note that the -c switch on grep suppresses normal
293 # output and just prints count.
294 ##PLATFORM = $(shell uname)
295 ##IS_WINDOWS = $(shell uname | grep -ci windows)
296 
297 # A safer way to check platform if uname is not available, ComSpec on Windows
298 # Note that ComSpec is (may be?) case-sensitive, check with env.exe
299 # Quirk: - Microsoft Windows echo does not require escaping quotes parentheses
300 # and other symbols and outputrs them as is into redirected shell
301 # output, e.g. in $(shell echo "bla bla bla" >> file.txt), i.e
302 # file.txt gets "bla bla bla". Linux echo, in contrast deletes the
303 # quites, which can create portability problems if a piece of code
304 # (e.g. include file) is auto-generated in such a way.
305 # One way to ensure identical behaviour on all platforms is to use
306 # a third-party echo.exe program from Cygwin, GnuWin32 of Linux
307 # subsystem on Windows 10 (WSL).
308 # - Windows 10 does not seem to use third-party `echo.exe` (e.g. from
309 # GNUwin32 or Linux subsystem if simple echo is referred under shell.
310 # This requires redefining ECHO to refer to a specific `exe`
311 # explicitly.
312 ifdef ComSpec
313  PLATFORM_TYPE=Windows
314  IS_WINDOWS=1
315  WHICH_CMD=where
316  NULLDEV=":NULL"
317  RM := $(WINRM)
318  MV := move
319  GREP := grep
320  CUT := cut
321  UNAME := uname
322  ECHO := "$(shell $(WHICH_CMD) echo.exe)"
323 else
324  PLATFORM_TYPE=Unix
325  IS_WINDOWS=0
326  WHICH_CMD=which
327  NULLDEV="/dev/null"
328  RM := rm -fr
329  MV := mv -f
330  GREP := grep
331  CUT := cut
332  UNAME := uname
333  ECHO := echo
334 endif
335 
336 # Check if certain required executables exist and are callable in path. This is
337 # important on the Windows platform because such GNU command line utilities as
338 # uname and zip are not installed by default.
339 REQUIRED_EXECS = zip a2x md5sum ifort f95 gfortran svn $(CUT) $(GREP)
340 K := $(foreach exec,$(REQUIRED_EXECS),\
341  $(if $(shell $(WHICH_CMD) $(exec) ),check executables,\
342  $(warning ============ $(exec) unavailable in PATH ============)))
343 
344 # Check if we build on Windows platform with GNU gfortran Compiler. Compiler
345 # may differ in this case. Notably, GCC -flto option crashes compiler.
346 # also, memory sanitizer GF_MEMCHECK is disabled on Windows
347 ifeq ($(PLATFORM_TYPE)$(FC),Windowsgfortran)
348  GF_FFLAGS:=$(GF_FFLAGS_WINDOWS)
349 else
350  GF_RCHECKS := $(GF_RCHECKS) $(GF_MEMCHECK)
351 endif
352 
353 # Check if we build on Windows platform with Intel Compiler. It is specific in
354 # two ways: (1) build options are different, start with slash and often have Q
355 # and (2) .obj is used as the extension for object files rather than .o
356 # here we check if with an emulated AND condition. Do this by simply
357 # concatenating two things into Windowsifort.
358 ifeq ($(PLATFORM_TYPE)$(FC),Windowsifort)
359  OBJEXT=obj
360  OBJ = $(addsuffix .$(OBJEXT), $(basename $(SRC)))
361  IF_FFLAGS:=$(IF_FFLAGS_WINDOWS)
362 else
363  OBJEXT=o
364  OBJ = $(addsuffix .$(OBJEXT), $(basename $(SRC)))
365 endif
366 
367 #===============================================================================
368 # HEDTOOLS object files:
369 # Warning: BASE_STRINGS must go before BASE_CSV_IO because BASE_CSV_IO now
370 # depends on procedures from BASE_STRINGS. This should be set by
371 # correct ordering of components in the HEDTOOLS variable.
372 
373 HTOOLOBJ = $(addsuffix .$(OBJEXT), $(basename $(HEDTOOLS)))
374 
375 #===============================================================================
376 # Generate the list of modules used in the source.
377 # First, get the list of module calls from the 'use' statements within the
378 # source code
379 # NOTE: Make turns $$ into $ in awk call, otherwise it goes empty.
380 # The sort GNU make function produces a sorted list deleting duplicates.
381 MOD_LIST = $(sort $(shell $(GREP) -i "^ *use " $(SRC) | sed -e 's/,//g' | awk '{printf(" %s ",$$2) }'))
382 
383 # Second, produce the final list of all .mod files that are to be generated.
384 # MOD_ALL is a list of Fortran modules generated by the main program as well
385 # as HEDTOOLS. So far MOD_ALL is not used for anything very important, only in
386 # cleaning temporary files, so can be set to .mod files remaining after make
387 # clean/distclean. Modules can be included into prerequisites?
388 # NOTE: The code automatically generating the list of modules uses the MOD_LIST
389 # variable that gets the list of modules by applying Unix 'grep' to the
390 # source code files; extracts basename (just in case) and adds the
391 # '.mod' suffix to each file.
392 MOD_ALL = $(addsuffix .mod, $(basename $(call lowercase, $(MOD_LIST))))
393 
394 #===============================================================================
395 # Auto-generated include file setting compiler/platform specific code for PRNG
396 # The module BASE_RANDOM includes some non-portable header code that
397 # depends on the compiler type. It is auto-generated here. The Fortran Module
398 # code contains INCLUDE statement. The appropriate include file is then
399 # auto-generated during the build process.
400 # The strategy of the build is two-step:
401 # (1) Provide comment macro for the include file as well as the code adapted
402 # for the specific compiler type and platform
403 # (2) Select macro from the above list specific for the
404 # compiler type
405 # (3) build the BASE_RANDOM.o, the first statement is the include
406 # auto-generation macro, then follow the compile instructions.
407 
408 # Header file setting compiler/platform specific code for PRNG module
409 AUTOGEN_HEADER_RAND = $(HEDTOOLSDIR)/BASE_RANDOM.inc
410 
411 # Auto-generated include files, note that the first two lines do doxygen
412 # comments.
413 define AUTOGEN_COMMENT_RANDOM
414  $(shell $(ECHO) "!> @file $(AUTOGEN_HEADER_RAND)" > $(AUTOGEN_HEADER_RAND))
415  $(shell $(ECHO) "!! Autogenerated header for module RANDOM built with $(FC)" >> $(AUTOGEN_HEADER_RAND))
416  $(shell $(ECHO) "!! Sets compiler-specific code for random number generator" >> $(AUTOGEN_HEADER_RAND))
417  $(shell $(ECHO) "!+---------------------------------------------------------+" >> $(AUTOGEN_HEADER_RAND))
418  $(shell $(ECHO) "!| WARNING: auto-generated file, do NOT edit |" >> $(AUTOGEN_HEADER_RAND))
419  $(shell $(ECHO) "!| Sets compiler-specific code for random number generator |" >> $(AUTOGEN_HEADER_RAND))
420  $(shell $(ECHO) "!+---------------------------------------------------------+" >> $(AUTOGEN_HEADER_RAND))
421 endef
422 
423 # Include file code for GNU
424 define AUTOGEN_CODE_GF
425  $(shell $(ECHO) "! GNU Fortran compiler:" >> $(AUTOGEN_HEADER_RAND))
426  $(shell $(ECHO) "use ISO_FORTRAN_ENV, only: int64" >> $(AUTOGEN_HEADER_RAND))
427  $(shell $(ECHO) "implicit none" >> $(AUTOGEN_HEADER_RAND))
428  $(shell $(ECHO) "integer, allocatable :: seed(:)" >> $(AUTOGEN_HEADER_RAND))
429  $(shell $(ECHO) "integer :: i, n, un, istat, dt(8), pid" >> $(AUTOGEN_HEADER_RAND))
430  $(shell $(ECHO) "integer(int64) :: t">> $(AUTOGEN_HEADER_RAND))
431 endef
432 
433 # Include file code for Intel
434 define AUTOGEN_CODE_IF
435  $(shell $(ECHO) "! Intel Fortran compiler:" >> $(AUTOGEN_HEADER_RAND))
436  $(shell $(ECHO) "use ISO_FORTRAN_ENV, only: int64 " >> $(AUTOGEN_HEADER_RAND))
437  $(shell $(ECHO) "use IFPORT, only : getpid" >> $(AUTOGEN_HEADER_RAND))
438  $(shell $(ECHO) "implicit none" >> $(AUTOGEN_HEADER_RAND))
439  $(shell $(ECHO) "integer, allocatable :: seed(:)" >> $(AUTOGEN_HEADER_RAND))
440  $(shell $(ECHO) "integer :: i, n, un, istat, dt(8), pid" >> $(AUTOGEN_HEADER_RAND))
441  $(shell $(ECHO) "integer(int64) :: t" >> $(AUTOGEN_HEADER_RAND))
442 endef
443 
444 # Include file code for Oracle
445 define AUTOGEN_CODE_SF
446  $(shell $(ECHO) "! Intel Oracle compiler:" >> $(AUTOGEN_HEADER_RAND))
447  $(shell $(ECHO) "implicit none" >> $(AUTOGEN_HEADER_RAND))
448  $(shell $(ECHO) "integer, allocatable :: seed(:)" >> $(AUTOGEN_HEADER_RAND))
449  $(shell $(ECHO) "integer :: i, n, un, istat, dt(8), pid" >> $(AUTOGEN_HEADER_RAND))
450  $(shell $(ECHO) "integer, parameter :: int64 = selected_int_kind(18)" >> $(AUTOGEN_HEADER_RAND))
451  $(shell $(ECHO) "integer(int64) :: t" >> $(AUTOGEN_HEADER_RAND))
452  $(shell $(ECHO) "include \"system.inc\"" >> $(AUTOGEN_HEADER_RAND))
453 endef
454 
455 # Select autogeneration of include file for the specific compiler type
456 ifeq ($(FC),$(GF_FC))
457  AUTOGEN_CODE_RANDOM=$(AUTOGEN_CODE_GF)
458 endif
459 
460 ifeq ($(FC),$(IF_FC))
461  AUTOGEN_CODE_RANDOM=$(AUTOGEN_CODE_IF)
462 endif
463 
464 ifeq ($(FC),$(SF_FC))
465  AUTOGEN_CODE_RANDOM=$(AUTOGEN_CODE_SF)
466 endif
467 
468 #===============================================================================
469 # Determine compiler versions, we may need GCC version > 5 to use
470 # non-intrinsic IEEE math modules for gfortran < 5, GCC > 5 fully
471 # supports intrinsic IEEE math.
472 # IEEE should work with recent versions
473 
474 # Check GCC version and need for non-intrinsic modules
475 GFORTVERSION = $(shell $(GF_FC) -dumpversion)
476 GFORT_LESS_5 = $(shell expr `echo $(GFORTVERSION) | $(CUT) -d. -f1` < 5)
477 ifeq ($(GFORT_LESS_5),1)
478  COMPILE_NONINTRINSIC_IEEE=YES
479 else
480  COMPILE_NONINTRINSIC_IEEE=NO
481 endif
482 
483 # IEEE non-intrinsic modules, list of sources
484 IEEE_NON_INTRINSIC_SRC = precision_m.f90 IEEE_FEATURES.f90 IEEE_EXCEPTIONS.f90 \
485  IEEE_ARITHMETIC.f90 c_control.c
486 
487 IEEEMOD = ieee_arithmetic.mod ieee_exceptions.mod ieee_features.mod \
488  precision.mod
489 
490 # IEEE non-intrinsic objects
491 IEEEOBJ = precision_m.$(OBJEXT) c_control.$(OBJEXT) IEEE_FEATURES.$(OBJEXT) \
492  IEEE_EXCEPTIONS.$(OBJEXT) IEEE_ARITHMETIC.$(OBJEXT)
493 
494 # Macros to auto-generate F90 headers for IEEE modules -- AUTOGEN_HEADER_FILE
495 AUTOGEN_HEADER_IEEE = IEEE_wrap.inc
496 
497 # Check if the source does include IEEE calls at all, disable non-intrinsic IEEE
498 # if the Fortran source does never refer to them
499 IEEE_GREPPED_SRC = $(shell $(GREP) -ci $(AUTOGEN_HEADER_IEEE) $(SRC))
500 ifeq ($(IEEE_GREPPED_SRC),0)
501  COMPILE_NONINTRINSIC_IEEE=NO
502 endif
503 
504 ifneq ($(FC),gfortran)
505  COMPILE_NONINTRINSIC_IEEE=NO
506 endif
507 
508 # Autogenerated include files
509 define AUTOGEN_COMMENT_HEADER_F90
510  $(shell $(ECHO) "!> @file $(AUTOGEN_HEADER_IEEE)" > $(AUTOGEN_HEADER_IEEE))
511  $(shell $(ECHO) "!! Autogenerated header for IEEE math modules built with $(FC)" >> $(AUTOGEN_HEADER_IEEE))
512  $(shell $(ECHO) "!! Calls intrinsic or non-intrinsic IEEE math modules" >> $(AUTOGEN_HEADER_IEEE))
513  $(shell $(ECHO) "!+-----------------------------------------------------+" >> $(AUTOGEN_HEADER_IEEE))
514  $(shell $(ECHO) "!| WARNING: auto-generated file, do NOT edit |" >> $(AUTOGEN_HEADER_IEEE))
515  $(shell $(ECHO) "!| Calls intrinsic or non-intrinsic IEEE math modules |" >> $(AUTOGEN_HEADER_IEEE))
516  $(shell $(ECHO) "!+-----------------------------------------------------+" >> $(AUTOGEN_HEADER_IEEE))
517 endef
518 
519 # Now only use IEEE_EXCEPTIONS are managed. Other modules may be added:
520 # IEEE_FEATURES IEEE_ARITHMETIC IEEE_EXCEPTIONS
521 define AUTOGEN_INTRINSIC
522  $(AUTOGEN_COMMENT_HEADER_F90)
523  $(shell $(ECHO) "use, intrinsic :: IEEE_ARITHMETIC" >> $(AUTOGEN_HEADER_IEEE))
524  $(shell $(ECHO) "use, intrinsic :: IEEE_EXCEPTIONS" >> $(AUTOGEN_HEADER_IEEE))
525 endef
526 
527 # Now only use IEEE_EXCEPTIONS are managed. Other modules may be added:
528 # IEEE_FEATURES IEEE_ARITHMETIC IEEE_EXCEPTIONS
529 define AUTOGEN_NON_INTRINSIC
530  $(AUTOGEN_COMMENT_HEADER_F90)
531  $(shell $(ECHO) "use, non_intrinsic :: IEEE_ARITHMETIC" >> $(AUTOGEN_HEADER_IEEE))
532  $(shell $(ECHO) "use, non_intrinsic :: IEEE_EXCEPTIONS" >> $(AUTOGEN_HEADER_IEEE))
533 endef
534 
535 #-------------------------------------------------------------------------------
536 
537 # Function to convert UPPERCASE to lowercase by Eric Melski, taken from
538 # https://stackoverflow.com/questions/664601/in-gnu-make-how-do-i-convert-a-variable-to-lower-case
539 # It looks a little clunky, but it gets the job done...
540 lowercase = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1))))))))))))))))))))))))))
541 
542 #-------------------------------------------------------------------------------
543 
544 # Determine this makefile's path. Be sure to place this BEFORE `include`s
545 THIS_FILE := $(lastword $(MAKEFILE_LIST))
546 
547 # This is the search paths for looking for components, separated by blanks
548 VPATH = $(HEDTOOLSDIR) $(IEEEPATH)
549 
550 # Determine if we are running on HPC cluster
551 RUNHOST_HPC = $(shell hostname | $(GREP) -c $(HOST_HPC_ROOT))
552 
553 # Determine current SVN version of the code
554 ifeq ($(VCS_TYPE),SVN)
555  SVN_VER = $(shell svn info --show-item last-changed-revision)
556 endif
557 ifeq ($(VCS_TYPE),HG)
558  SVN_VER = $(shell hg summary | $(GREP) parent: | $(CUT) -d " " -f 2 | $(CUT) -d ":" -f 2 )
559 endif
560 ifndef VCS_TYPE
561  SVN_VER = "unknown"
562 endif
563 
564 # Build the data zip file name: data are compressed for make zipdata
565 ZIPDATA_NAME = model_data_rev$(SVN_VER)_$(shell hostname).zip
566 
567 #===============================================================================
568 # targets follow
569 #===============================================================================
570 
571 # Default build target = executable
572 all: exec
573 
574 docs: $(DOXYCFG)
575  doxygen $(DOXYCFG)
576 
577 # Short help on the options
578 # For Intel Fortran compiler on Windows, we have to call the batch file to setup
579 # the build environment. This command is taken from the Command Prompt
580 # shortcut in the Intel Parallel Studio menu:
581 #C:\Windows\SysWOW64\cmd.exe /E:ON /V:ON /K ""C:\Program Files (x86)\Intel\Composer XE 2013\bin\ipsxe-comp-vars.bat" intel64 vs2010"
582 # This mitght be different on different systems, depending on the
583 # installation options for Intel Parallel Studio and the Windows platform
584 # type (e.g. 32 vs. 64 bit)
585 help:
586  @echo ""
587  @echo ------------------------------------------------------------------------
588  @echo "Building model $(SRC) ------ via $(THIS_FILE)"
589  @echo ------------------------------------------------------------------------
590  @echo "BUILD:"
591  @echo ""
592  @echo "Normal build: make (uses $(FC) by default)"
593  @echo ""
594  @echo "Main (re)build (for different compiler type targets):"
595  @echo " make gnu, make intel, make sun"
596  @echo ""
597  @echo "Compile HEDTOOLS modelling tools: make tools"
598  @echo ""
599  @echo "Autogenerate documentation with Doxygen (config: $(DOXYCFG))"
600  @echo " make docs"
601  @echo ""
602  @echo "Produce system-specific include headers (PRNG and IEEE): make inc"
603  @echo ""
604  @echo "Produce debug symbols: define DEBUG, e.g.: make DEBUG=1"
605  @echo " profiling output (GNU): define PROFILE, e.g.: make PROFILE=1"
606  @echo ""
607  @echo "RUN:"
608  @echo ""
609  @echo "Run model: make run (make run_local to force local run)"
610  @echo ""
611  @echo "DATA:"
612  @echo ""
613  @echo "Compress output data: make zipdata (compress CSV: make gzipcsv)"
614  @echo "Check zip file and produce md5 checksum: make zipcheck"
615  @echo "Send zip data (and others) to the remote server AHA_STORAGE_SERVER_STR"
616  @echo " = $(AHA_STORAGE_SERVER_STR): make zipsend"
617  @echo ""
618  @echo "UNIT TESTS:"
619  @echo ""
620  @echo "Run unit tests using pfunt test framework: make tests"
621  @echo ""
622  @echo "CLEAN UP:"
623  @echo ""
624  @echo "Cleaning: make clean, make cleandata (model data only),"
625  @echo " make distclean (everything, leaving the distro state!)"
626  @echo ------------------------------------------------------------------------
627  @echo "NOTES:"
628  @echo " 1. IEEE non-intrinsic modules: make ieee, needed only for GCC < 5"
629  @echo " 2. Intel Fortran compiler under Windows: set up environment for "
630  @echo " Microsoft Visual Studio 2010 x64 tools before calling make."
631  @echo " Call to the shortcuts from the Command Prompt menu under Intel "
632  @echo " Parallel Studio XE"
633  @echo ------------------------------------------------------------------------
634  @echo PROJECT: Rev: $(SVN_VER) \‍($(VCS_TYPE)\‍), $(PLATFORM_TYPE), HPC \‍($(HOST_HPC_ROOT)\‍) $(RUNHOST_HPC)
635  @echo Source: $(SRC) -- $(OUT) -- $(OBJ)
636  @echo ------------------------------------------------------------------------
637 
638 # shortcut to build for GNU Fortran
639 .PHONY: gnu
640 gnu:
641  @$(MAKE) -f $(THIS_FILE) FC=gfortran
642 
643 # shortcut to build for Intel Fortran
644 .PHONY: intel
645 intel:
646  @$(MAKE) -f $(THIS_FILE) FC=ifort
647 
648 # shortcut to build for Solaris Studio Fortran
649 .PHONY: sun
650 sun:
651  @$(MAKE) -f $(THIS_FILE) FC=f95
652 
653 # Run through PBS job script on HPC, check if we are on cluster RUNHOST_HPC
654 #run: $(OUT) $(JOB) $(SRC)
655 run: $(OUT) $(SRC)
656 ifeq ($(RUNHOST_HPC),1)
657  qsub $(JOB)
658  @echo "NOTE: fimm job created"
659  @echo "Batch commands:"
660  @echo " showq -u USER = show user's jobs'"
661  @echo " qstat = display all jobs"
662  @echo " qdel jobid = delete job"
663  @echo " qhold = pause job"
664  @echo " qrls = resume job"
665  @echo "https://docs.hpc.uib.no/wiki/Job_execution_(Fimm)"
666 else
667  @$(MAKE) -f $(THIS_FILE) run_local
668 endif
669 
670 # Note -- this is local start/run on all supported systems.
671 # If the DEBUG flag was set when starting make, the executable also
672 # starts in the DEBUG mode (command line DEBUG flag).
673 run_local: $(OUT) $(SRC)
674  $(info ====================================================================)
675  $(info Executing model $(OUT) now)
676  $(info ====================================================================)
677 ifeq ($(IS_WINDOWS),1)
678  $(OUT) $(RUNFLAG)
679  $(AHA_NOTIFY_CMD_WIN)
680 else
681  ./$(OUT) $(RUNFLAG) ; $(AHA_NOTIFY_CMD_UNIX)
682 endif
683 
684 # Main build the executable
685 exec: $(OUT)
686 
687 # Build object files only without the final executable
688 objects: $(OBJ) $(HTOOLOBJ)
689 
690 # Produce include file for PRNG module
691 inc: $(AUTOGEN_HEADER_RAND) $(AUTOGEN_HEADER_IEEE)
692 
693 # Compile the HEDTOOLS modelling tools
694 tools: $(HTOOLOBJ)
695 
696 # Compile the HEDTOOLS modelling tools
697 headtools: $(HTOOLOBJ)
698 
699 # Run unit tests. Note that pFunit is non-essential and any build errors are
700 # ignored in this main Makefile.
701 .PHONY: tests
702 tests:
703  @echo Running unit tests in $(PFUNIT_PATH). Warning: Any errors IGNORED.
704  -$(MAKE) -C $(PFUNIT_PATH)
705 
706 # Cleanup data files, quotes needed on Windows if file starts from blank
707 cleandata: neat
708  -$(RM) HED*.txt ?HED*.txt HED18*.log behaviour gene*
709  -$(RM) debug* *.csv *.ps *.png *.svg *gz
710 ifeq ($(IS_WINDOWS),1)
711  -$(RM) "?HED*.txt" "HED*.txt"
712 endif
713 
714 # Return to default state, delete all generated files.
715 distclean: clean cleandata cleanzip
716  -$(RM) $(AUTOGEN_HEADER_RAND) $(AUTOGEN_HEADER_IEEE) $(HTOOLOBJ) $(MOD_ALL) \
717  $(IEEEOBJ) $(IEEEMOD) gmon.out *.mod *.log *.o *.obj *.pdb *.patch \
718  *.md5
719  -$(RM) $(DOXYPATH)
720  @echo Cleaning unit tests in $(PFUNIT_PATH).
721  @echo NOTE: Any errors IGNORED.
722  -$(MAKE) -C $(PFUNIT_PATH) distclean
723 
724 # Clean obj etc for new build of the model, but we don't clean HEDTOOLS and
725 # any .mod files.
726 clean: neat
727  -$(RM) $(OBJ) $(OUT) *.csv *.ps *.png
728 
729 # Cean temporary files and conflict that remain from syncthing synchronisation.
730 neat:
731  -$(RM) *conflict* .syncthing* ~syncthing* fort.* *.tmp *.orig *.lock \
732  *.annot.html *.annot *.optrpt
733 
734 # Compress all generation-based CSV data using gzip. This should
735 # normally be done automatically at run time if the environment variable
736 # AHA_ZIP_FILES=YES
737 gzipcsv:
738  gzip agents*csv behaviours*csv food_*csv genomes*csv memory*csv \
739  movements*csv timesteps*csv
740 
741 # Compress all output data from the latest model run. This is a shortcut
742 # calling the actual zip target.
743 zipdata: $(ZIPDATA_NAME)
744 
745 # Compress all output data from the latest model run. This is the actual zipper.
746 $(ZIPDATA_NAME):
747  @echo Producing zipfile: $(ZIPDATA_NAME)
748  -zip $(ZIPDATA_NAME) *.csv *.log *.ps *.gz *.patch
749  @echo "NOTE: If the $(OUT) target is rebuilt at this stage, re-run model!"
750  @echo " To check zip run make zipcheck"
751  @echo " Produced $(ZIPDATA_NAME)"
752 
753 # Check the integrity of the compressed data zip file and produce the md5
754 # checksum.
755 zipcheck: $(ZIPDATA_NAME)
756  @echo Check zip and produce MD5 checksum file.
757  @echo NOTE: Any errors are IGNORED.
758  -zip -T $(ZIPDATA_NAME)
759  -md5sum $(ZIPDATA_NAME) > $(ZIPDATA_NAME).md5
760 
761 # Sending the data zip file to an external server for storage or data analysis.
762 # The data file is sent using scp command. Note that the zip file as well as
763 # all files having the same root names are transferred, e.g..
764 # model_1.zip along with model_1.zip.md5 model_1.zip.notes model_1.zip.txt
765 zipsend: $(ZIPDATA_NAME)
766  @echo Sending $(ZIPDATA_NAME) to $(AHA_STORAGE_SERVER_STR)
767  @echo NOTE: Any errors are IGNORED. Data transfer may take a long time!
768  -scp $(ZIPDATA_NAME)* $(AHA_STORAGE_SERVER_STR)
769 
770 # Clean any compressed data.
771 cleanzip:
772  -$(RM) *zip *gz *bz2
773 
774 #-------------------------------------------------------------------------------
775 #-------------------------------------------------------------------------------
776 # Automatic build follows, usually there is no need to edit the code below...
777 
778 $(OUT): $(DRV) $(OBJ) $(HTOOLOBJ)
779  @$(MAKE) -f $(THIS_FILE) inc
780 ifeq ($(COMPILE_NONINTRINSIC_IEEE),YES)
781  $(FC) $(FFLAGS) -o $(OUT) $^ $(IEEEOBJ) $(GRAPHLIB)
782 else
783  $(FC) $(FFLAGS) -o $(OUT) $^ $(GRAPHLIB)
784 endif
785 
786 $(OBJ): $(SRC) $(HTOOLOBJ)
787 ifeq ($(COMPILE_NONINTRINSIC_IEEE),YES)
788  @$(MAKE) -f $(THIS_FILE) ieee_need
789 else
790  @$(MAKE) -f $(THIS_FILE) ieee_not_need
791 endif
792  $(FC) $(FFLAGS) -c $^ $(GRAPHLIB)
793 
794 #-------------------------------------------------------------------------------
795 # Build HEDTOOLS
796 
797 # Produce tweaked include file for PRNG
798 $(AUTOGEN_HEADER_RAND): $(BASE_RANDOM.f90) $(THIS_FILE)
799  $(AUTOGEN_COMMENT_RANDOM)
800  $(AUTOGEN_CODE_RANDOM)
801  @echo Generated include: $(AUTOGEN_HEADER_RAND) for $(FC) using $(ECHO)
802 
803 # Compile HEDTOOLS modules. Note that the extension (.o or .obj)
804 # is set via $(OBJEXT). .obj is used on Intel Fortran on Windows.
805 # Also note that generic pattern rules are used here, with the
806 # include files as additional prerequisites.
807 # NOTE: generic pattern with include as prerequisite is disabled
808 # here because it does not work for some reason from within
809 # Code:Blocks, even though works on raw terminal
810 # --- GENERIC UNUSED ---
811 ##%.$(OBJEXT) : %.f90 $(AUTOGEN_HEADER_RAND) $(AUTOGEN_HEADER_IEEE) $(THIS_FILE)
812 ## $(FC) $(FFLAGS) -c $<
813 # --- GENERIC UNUSED ---
814 # So far, use individual builds for each of the HEDTOOLS source files:
815 BASE_UTILS.$(OBJEXT): BASE_UTILS.f90
816  $(FC) $(FFLAGS) -c $<
817 BASE_CSV_IO.$(OBJEXT): BASE_CSV_IO.f90
818  $(FC) $(FFLAGS) -c $<
819 BASE_LOGGER.$(OBJEXT): BASE_LOGGER.f90
820  $(FC) $(FFLAGS) -c $<
821 BASE_RANDOM.$(OBJEXT): BASE_RANDOM.f90 $(THIS_FILE)
822  @$(MAKE) -f $(THIS_FILE) inc
823  $(FC) $(FFLAGS) -c $<
824 BASE_STRINGS.$(OBJEXT): BASE_STRINGS.f90
825  $(FC) $(FFLAGS) -c $<
826 
827 #-------------------------------------------------------------------------------
828 # Build IEEE non-intrinsic modules for GNU Fortran if needed
829 
830 # Generate IEEE include file
831 $(AUTOGEN_HEADER_IEEE): $(THIS_FILE)
832 ifeq ($(COMPILE_NONINTRINSIC_IEEE),YES)
833  $(AUTOGEN_NON_INTRINSIC)
834  @echo Generated include: $(AUTOGEN_HEADER_IEEE) for $(FC) v. $(GFORTVERSION) using $(ECHO)
835 else
836  $(AUTOGEN_INTRINSIC)
837  @echo Generated include: $(AUTOGEN_HEADER_IEEE) for $(FC) using $(ECHO)
838 endif
839 
840 #-------------------------------------------------------------------------------
841 # Compile all IEEE non-intrinsic math modules if needed
842 ieee:
843 ifeq ($(COMPILE_NONINTRINSIC_IEEE),YES)
844  @$(MAKE) -f $(THIS_FILE) ieee_need
845 else
846  @$(MAKE) -f $(THIS_FILE) ieee_not_need
847 endif
848 
849 # just issue note that we do not need IEEEs
850 ieee_not_need:
851  @echo ------------------------------------------------------------------------
852  @echo We do not need non-intrinsic IEEE modules: $(FC), $(GREP) test $(IEEE_GREPPED_SRC)
853  @echo ------------------------------------------------------------------------
854 
855 # build IEEEs assuming we do need them (GNU)
856 ieee_need: $(IEEEOBJ)
857  @echo ------------------------------------------------------------------------
858  @echo GNU Fortran version: $(GFORTVERSION). We NEED NON-INTRINSIC IEEE MODULES.
859  @echo ------------------------------------------------------------------------
860 
861 # specific components of IEEE modules are below
862 precision_m.$(OBJEXT): precision_m.f90
863  $(FC) -c $(FFLAGS) $<
864 c_control.$(OBJEXT): c_control.c
865  $(CC) -c $(GC_FFLAGS) $<
866 IEEE_FEATURES.$(OBJEXT): IEEE_FEATURES.f90
867  $(FC) -c -fno-range-check $(FFLAGS) $<
868 IEEE_EXCEPTIONS.$(OBJEXT): IEEE_EXCEPTIONS.f90
869  $(FC) -c -fno-range-check $(FFLAGS) $<
870 IEEE_ARITHMETIC.$(OBJEXT): IEEE_ARITHMETIC.f90
871  $(FC) -c -fno-range-check $(FFLAGS) $<
872 
873 ##//! @endcond