1# boilermake: A reusable, but flexible, boilerplate Makefile.
2#
3# Copyright 2008, 2009, 2010 Dan Moulding, Alan T. DeKok
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18# Caution: Don't edit this Makefile! Create your own main.mk and other
19#          submakefiles, which will be included by this Makefile.
20#          Only edit this if you need to modify boilermake's behavior (fix
21#          bugs, add features, etc).
22
23# Note: Parameterized "functions" in this makefile that are marked with
24#       "USE WITH EVAL" are only useful in conjuction with eval. This is
25#       because those functions result in a block of Makefile syntax that must
26#       be evaluated after expansion. Since they must be used with eval, most
27#       instances of "$" within them need to be escaped with a second "$" to
28#       accomodate the double expansion that occurs when eval is invoked.
29
30#  Before doing ANYTHING, initialize submodules...if the version of
31#  git is compatible.
32gitv := $(shell git --version | cut -d\  -f 3 | cut -c 1)
33ifeq (1, $(gitv))
34  gitv := $(shell git --version | cut -d\  -f 3)
35  $(error git '$(shell which git)' version '$(gitv)' too old; at least version 2.12 is required)
36endif
37
38ifeq ($(wildcard utility/src/Makefile), )
39  $(info $(shell git submodule update --init utility))
40  $(info $(space))
41endif
42ifeq ($(wildcard meryl/src/Makefile), )
43  $(info $(shell git submodule update --init meryl))
44  $(info $(space))
45endif
46ifeq ($(wildcard seqrequester/src/Makefile), )
47  $(info $(shell git submodule update --init seqrequester))
48  $(info $(space))
49endif
50
51# ADD_CLEAN_RULE - Parameterized "function" that adds a new rule and phony
52#   target for cleaning the specified target (removing its build-generated
53#   files).
54#
55#   USE WITH EVAL
56#
57define ADD_CLEAN_RULE
58    clean: clean_${1}
59    .PHONY: clean_${1}
60    clean_${1}:
61	$$(strip rm -f ${TARGET_DIR}/${1} $${${1}_OBJS:%.o=%.[doP]})
62	$${${1}_POSTCLEAN}
63endef
64
65# ADD_OBJECT_RULE - Parameterized "function" that adds a pattern rule for
66#   building object files from source files with the filename extension
67#   specified in the second argument. The first argument must be the name of the
68#   base directory where the object files should reside (such that the portion
69#   of the path after the base directory will match the path to corresponding
70#   source files). The third argument must contain the rules used to compile the
71#   source files into object code form.
72#
73#   USE WITH EVAL
74#
75define ADD_OBJECT_RULE
76${1}/%.o: ${2} utility/src/utility/version.H
77	${3}
78endef
79
80# ADD_TARGET_RULE - Parameterized "function" that adds a new target to the
81#   Makefile. The target may be an executable or a library. The two allowable
82#   types of targets are distinguished based on the name: library targets must
83#   end with the traditional ".a" extension.
84#
85#   USE WITH EVAL
86#
87define ADD_TARGET_RULE
88    ifeq "$$(suffix ${1})" ".a"
89        # Add a target for creating a static library.
90        $${TARGET_DIR}/${1}: $${${1}_OBJS}
91	        @mkdir -p $$(dir $$@)
92	        $$(strip $${AR} $${ARFLAGS} $$@ $${${1}_OBJS})
93	        $${${1}_POSTMAKE}
94    else
95      # Add a target for linking an executable. First, attempt to select the
96      # appropriate front-end to use for linking. This might not choose the
97      # right one (e.g. if linking with a C++ static library, but all other
98      # sources are C sources), so the user makefile is allowed to specify a
99      # linker to be used for each target.
100      ifeq "$$(strip $${${1}_LINKER})" ""
101          # No linker was explicitly specified to be used for this target. If
102          # there are any C++ sources for this target, use the C++ compiler.
103          # For all other targets, default to using the C compiler.
104          ifneq "$$(strip $$(filter $${CXX_SRC_EXTS},$${${1}_SOURCES}))" ""
105              ${1}_LINKER = $${CXX}
106          else
107              ${1}_LINKER = $${CC}
108          endif
109      endif
110
111      $${TARGET_DIR}/${1}: $${${1}_OBJS} $${${1}_PREREQS}
112	      @mkdir -p $$(dir $$@)
113	      $$(strip $${${1}_LINKER} -o $$@ $${LDFLAGS} $${${1}_LDFLAGS} $${${1}_OBJS} $${${1}_LDLIBS} $${LDLIBS})
114	      $${${1}_POSTMAKE}
115  endif
116endef
117
118# CANONICAL_PATH - Given one or more paths, converts the paths to the canonical
119#   form. The canonical form is the path, relative to the project's top-level
120#   directory (the directory from which "make" is run), and without
121#   any "./" or "../" sequences. For paths that are not  located below the
122#   top-level directory, the canonical form is the absolute path (i.e. from
123#   the root of the filesystem) also without "./" or "../" sequences.
124define CANONICAL_PATH
125$(patsubst ${CURDIR}/%,%,$(abspath ${1}))
126endef
127
128# COMPILE_C_CMDS - Commands for compiling C source code.
129define COMPILE_C_CMDS
130	@mkdir -p $(dir $@)
131	$(strip ${CC} -o $@ -c -MD ${CFLAGS} ${SRC_CFLAGS} ${INCDIRS} \
132	    ${SRC_INCDIRS} ${SRC_DEFS} ${DEFS} $<)
133	@cp ${@:%$(suffix $@)=%.d} ${@:%$(suffix $@)=%.P}; \
134	 sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
135	     -e '/^$$/ d' -e 's/$$/ :/' < ${@:%$(suffix $@)=%.d} \
136	     >> ${@:%$(suffix $@)=%.P}; \
137	 rm -f ${@:%$(suffix $@)=%.d}
138endef
139
140# COMPILE_CXX_CMDS - Commands for compiling C++ source code.
141define COMPILE_CXX_CMDS
142	@mkdir -p $(dir $@)
143	$(strip ${CXX} -o $@ -c -MD ${CXXFLAGS} ${SRC_CXXFLAGS} ${INCDIRS} \
144	    ${SRC_INCDIRS} ${SRC_DEFS} ${DEFS} $<)
145	@cp ${@:%$(suffix $@)=%.d} ${@:%$(suffix $@)=%.P}; \
146	 sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
147	     -e '/^$$/ d' -e 's/$$/ :/' < ${@:%$(suffix $@)=%.d} \
148	     >> ${@:%$(suffix $@)=%.P}; \
149	 rm -f ${@:%$(suffix $@)=%.d}
150endef
151
152# INCLUDE_SUBMAKEFILE - Parameterized "function" that includes a new
153#   "submakefile" fragment into the overall Makefile. It also recursively
154#   includes all submakefiles of the specified submakefile fragment.
155#
156#   USE WITH EVAL
157#
158define INCLUDE_SUBMAKEFILE
159    # Initialize all variables that can be defined by a makefile fragment, then
160    # include the specified makefile fragment.
161    TARGET        :=
162    TGT_CFLAGS    :=
163    TGT_CXXFLAGS  :=
164    TGT_DEFS      :=
165    TGT_INCDIRS   :=
166    TGT_LDFLAGS   :=
167    TGT_LDLIBS    :=
168    TGT_LINKER    :=
169    TGT_POSTCLEAN :=
170    TGT_POSTMAKE  :=
171    TGT_PREREQS   :=
172
173    SOURCES       :=
174    SRC_CFLAGS    :=
175    SRC_CXXFLAGS  :=
176    SRC_DEFS      :=
177    SRC_INCDIRS   :=
178
179    SUBMAKEFILES  :=
180
181    # A directory stack is maintained so that the correct paths are used as we
182    # recursively include all submakefiles. Get the makefile's directory and
183    # push it onto the stack.
184    DIR := $(call CANONICAL_PATH,$(dir ${1}))
185    DIR_STACK := $$(call PUSH,$${DIR_STACK},$${DIR})
186
187    include ${1}
188
189    # Initialize internal local variables.
190    OBJS :=
191
192    # Determine which target this makefile's variables apply to. A stack is
193    # used to keep track of which target is the "current" target as we
194    # recursively include other submakefiles.
195    ifneq "$$(strip $${TARGET})" ""
196        # This makefile defined a new target. Target variables defined by this
197        # makefile apply to this new target. Initialize the target's variables.
198
199        ifeq "$$(suffix $${TARGET})" ".a"
200          TGT := $$(addprefix lib/, $$(strip $${TARGET}))
201        else
202          TGT := $$(addprefix bin/, $$(strip $${TARGET}))
203        endif
204        ALL_TGTS += $${TGT}
205        $${TGT}_CFLAGS    := $${TGT_CFLAGS}
206        $${TGT}_CXXFLAGS  := $${TGT_CXXFLAGS}
207        $${TGT}_DEFS      := $${TGT_DEFS}
208        $${TGT}_DEPS      :=
209        TGT_INCDIRS       := $$(call QUALIFY_PATH,$${DIR},$${TGT_INCDIRS})
210        TGT_INCDIRS       := $$(call CANONICAL_PATH,$${TGT_INCDIRS})
211        $${TGT}_INCDIRS   := $${TGT_INCDIRS}
212        $${TGT}_LDFLAGS   := $${TGT_LDFLAGS}
213        $${TGT}_LDLIBS    := $${TGT_LDLIBS}
214        $${TGT}_LINKER    := $${TGT_LINKER}
215        $${TGT}_OBJS      :=
216        $${TGT}_POSTCLEAN := $${TGT_POSTCLEAN}
217        $${TGT}_POSTMAKE  := $${TGT_POSTMAKE}
218        $${TGT}_PREREQS   := $$(addprefix $${TARGET_DIR}/lib/,$${TGT_PREREQS})
219        $${TGT}_SOURCES   :=
220    else
221        # The values defined by this makefile apply to the the "current" target
222        # as determined by which target is at the top of the stack.
223        TGT := $$(strip $$(call PEEK,$${TGT_STACK}))
224        $${TGT}_CFLAGS    += $${TGT_CFLAGS}
225        $${TGT}_CXXFLAGS  += $${TGT_CXXFLAGS}
226        $${TGT}_DEFS      += $${TGT_DEFS}
227        TGT_INCDIRS       := $$(call QUALIFY_PATH,$${DIR},$${TGT_INCDIRS})
228        TGT_INCDIRS       := $$(call CANONICAL_PATH,$${TGT_INCDIRS})
229        $${TGT}_INCDIRS   += $${TGT_INCDIRS}
230        $${TGT}_LDFLAGS   += $${TGT_LDFLAGS}
231        $${TGT}_LDLIBS    += $${TGT_LDLIBS}
232        $${TGT}_POSTCLEAN += $${TGT_POSTCLEAN}
233        $${TGT}_POSTMAKE  += $${TGT_POSTMAKE}
234        $${TGT}_PREREQS   += $${TGT_PREREQS}
235    endif
236
237    # Push the current target onto the target stack.
238    TGT_STACK := $$(call PUSH,$${TGT_STACK},$${TGT})
239
240    ifneq "$$(strip $${SOURCES})" ""
241        # This makefile builds one or more objects from source. Validate the
242        # specified sources against the supported source file types.
243        BAD_SRCS := $$(strip $$(filter-out $${ALL_SRC_EXTS},$${SOURCES}))
244        ifneq "$${BAD_SRCS}" ""
245            $$(error Unsupported source file(s) found in ${1} [$${BAD_SRCS}])
246        endif
247
248        # Qualify and canonicalize paths.
249        SOURCES     := $$(call QUALIFY_PATH,$${DIR},$${SOURCES})
250        SOURCES     := $$(call CANONICAL_PATH,$${SOURCES})
251        SRC_INCDIRS := $$(call QUALIFY_PATH,$${DIR},$${SRC_INCDIRS})
252        SRC_INCDIRS := $$(call CANONICAL_PATH,$${SRC_INCDIRS})
253
254        # Save the list of source files for this target.
255        $${TGT}_SOURCES += $${SOURCES}
256
257        # Convert the source file names to their corresponding object file
258        # names.
259        OBJS := $$(addprefix $${BUILD_DIR}/$$(call CANONICAL_PATH,$${TGT})/,\
260                   $$(addsuffix .o,$$(basename $${SOURCES})))
261
262        # Add the objects to the current target's list of objects, and create
263        # target-specific variables for the objects based on any source
264        # variables that were defined.
265        $${TGT}_OBJS += $${OBJS}
266        $${TGT}_DEPS += $${OBJS:%.o=%.P}
267        $${OBJS}: SRC_CFLAGS   := $${$${TGT}_CFLAGS} $${SRC_CFLAGS}
268        $${OBJS}: SRC_CXXFLAGS := $${$${TGT}_CXXFLAGS} $${SRC_CXXFLAGS}
269        $${OBJS}: SRC_DEFS     := $$(addprefix -D,$${$${TGT}_DEFS} $${SRC_DEFS})
270        $${OBJS}: SRC_INCDIRS  := $$(addprefix -I,\
271                                     $${$${TGT}_INCDIRS} $${SRC_INCDIRS})
272    endif
273
274    ifneq "$$(strip $${SUBMAKEFILES})" ""
275        # This makefile has submakefiles. Recursively include them.
276        $$(foreach MK,$${SUBMAKEFILES},\
277           $$(eval $$(call INCLUDE_SUBMAKEFILE,\
278                      $$(call CANONICAL_PATH,\
279                         $$(call QUALIFY_PATH,$${DIR},$${MK})))))
280    endif
281
282    # Reset the "current" target to it's previous value.
283    TGT_STACK := $$(call POP,$${TGT_STACK})
284    TGT := $$(call PEEK,$${TGT_STACK})
285
286    # Reset the "current" directory to it's previous value.
287    DIR_STACK := $$(call POP,$${DIR_STACK})
288    DIR := $$(call PEEK,$${DIR_STACK})
289endef
290
291
292# MIN - Parameterized "function" that results in the minimum lexical value of
293#   the two values given.
294define MIN
295$(firstword $(sort ${1} ${2}))
296endef
297
298# PEEK - Parameterized "function" that results in the value at the top of the
299#   specified colon-delimited stack.
300define PEEK
301$(lastword $(subst :, ,${1}))
302endef
303
304# POP - Parameterized "function" that pops the top value off of the specified
305#   colon-delimited stack, and results in the new value of the stack. Note that
306#   the popped value cannot be obtained using this function; use peek for that.
307define POP
308${1:%:$(lastword $(subst :, ,${1}))=%}
309endef
310
311# PUSH - Parameterized "function" that pushes a value onto the specified colon-
312#   delimited stack, and results in the new value of the stack.
313define PUSH
314${2:%=${1}:%}
315endef
316
317# QUALIFY_PATH - Given a "root" directory and one or more paths, qualifies the
318#   paths using the "root" directory (i.e. appends the root directory name to
319#   the paths) except for paths that are absolute.
320define QUALIFY_PATH
321$(addprefix ${1}/,$(filter-out /%,${2})) $(filter /%,${2})
322endef
323
324###############################################################################
325#
326# Start of Makefile Evaluation
327#
328###############################################################################
329
330# Older versions of GNU Make lack capabilities needed by boilermake.
331# With older versions, "make" may simply output "nothing to do", likely leading
332# to confusion. To avoid this, check the version of GNU make up-front and
333# inform the user if their version of make doesn't meet the minimum required.
334
335MIN_MAKE_VERSION := 3.81
336MIN_MAKE_VER_MSG := boilermake requires GNU Make ${MIN_MAKE_VERSION} or greater
337ifeq "${MAKE_VERSION}" ""
338    $(info GNU Make not detected)
339    $(error ${MIN_MAKE_VER_MSG})
340endif
341ifneq "${MIN_MAKE_VERSION}" "$(call MIN,${MIN_MAKE_VERSION},${MAKE_VERSION})"
342    $(info This is GNU Make version ${MAKE_VERSION})
343    $(error ${MIN_MAKE_VER_MSG})
344endif
345
346# Define the source file extensions that we know how to handle.
347
348C_SRC_EXTS := %.c
349CXX_SRC_EXTS := %.C %.cc %.cp %.cpp %.CPP %.cxx %.c++
350JAVA_EXTS    := %.jar %.tar
351ALL_SRC_EXTS := ${C_SRC_EXTS} ${CXX_SRC_EXTS} ${JAVA_EXTS}
352
353# Initialize global variables.
354
355ALL_TGTS :=
356DEFS :=
357DIR_STACK :=
358INCDIRS :=
359TGT_STACK :=
360
361# Discover our OS and architecture.  These were previously used to set
362# BUILD_DIR and TARGET_DIR to allow multi-platform builds.  DESTDIR will do
363# that for us too.
364
365OSTYPE      := $(shell echo `uname`)
366OSVERSION   := $(shell echo `uname -r`)
367MACHINETYPE := $(shell echo `uname -m`)
368
369ifeq (${MACHINETYPE}, x86_64)
370  MACHINETYPE = amd64
371endif
372
373ifeq (${MACHINETYPE}, Power Macintosh)
374  MACHINETYPE = ppc
375endif
376
377ifeq (${OSTYPE}, SunOS)
378  MACHINETYPE = ${shell echo `uname -p`}
379  ifeq (${MACHINETYPE}, sparc)
380    ifeq (${shell /usr/bin/isainfo -b}, 64)
381      MACHINETYPE = sparc64
382    else
383      MACHINETYPE = sparc32
384    endif
385  endif
386endif
387
388#  Set paths for building and installing.  If DESTDIR doesn't exist, use the
389#  directory just above us.
390
391ifeq "$(strip ${DESTDIR})" ""
392  BUILD_DIR    := $(realpath ..)/build/obj
393  TARGET_DIR   := $(realpath ..)/build
394  OBSOLETE_DIR := $(realpath ..)/${OSTYPE}-${MACHINETYPE}
395else
396  BUILD_DIR    := $(DESTDIR)/$(MODULE)/build/obj
397  TARGET_DIR   := $(DESTDIR)/$(MODULE)/build
398  OBSOLETE_DIR := $(DESTDIR)/$(MODULE)/${OSTYPE}-${MACHINETYPE}
399endif
400
401#
402#  Set compiler and flags based on discovered hardware
403#
404#  By default, debug symbols are included in all builds (even optimized).
405#
406#  BUILDOPTIMIZED  will disable debug symbols (leaving it just optimized)
407#  BUILDDEBUG      will disable optimization  (leaving it just with debug symbols)
408#  BUILDSTACKTRACE will enable stack trace on crashes, only works for Linux
409#                  set to 0 on command line to disable (it's enabled by default for Linux)
410#
411#  BUILDPROFILE used to add -pg to LDFLAGS, and remove -D_GLIBCXX_PARALLE from CXXFLAGS and LDFLAGS,
412#  and remove -fomit-frame-pointer from CXXFLAGS.  It added a bunch of complication and wasn't
413#  really used.
414#
415#  BUILDJEMALLOC will enable jemalloc library support.
416#
417
418ifeq ($(origin CXXFLAGS), undefined)
419  ifeq ($(BUILDOPTIMIZED), 1)
420  else
421    CXXFLAGS += -g3
422  endif
423
424  ifeq ($(BUILDDEBUG), 1)
425  else
426    CXXFLAGS += -O4 -funroll-loops -fexpensive-optimizations -finline-functions -fomit-frame-pointer
427  endif
428
429  ifeq ($(BUILDJEMALLOC), 1)
430    CXXFLAGS += -DJEMALLOC -I`jemalloc-config --includedir`
431    LDFLAGS  += -L`jemalloc-config --libdir` -Wl,-rpath,`jemalloc-config --libdir` -ljemalloc `jemalloc-config --libs`
432  endif
433
434  #  Enable some warnings.
435  #     gcc7:  -Wno-format-truncation  - sprintf() into possibly smaller buffer
436  #            -Wno-parentheses
437  CXXFLAGS += -Wall -Wextra -Wformat
438  CXXFLAGS += -Wno-char-subscripts
439  CXXFLAGS += -Wno-sign-compare
440  CXXFLAGS += -Wno-unused-function
441  CXXFLAGS += -Wno-unused-parameter
442  CXXFLAGS += -Wno-unused-variable
443  CXXFLAGS += -Wno-deprecated-declarations
444  CXXFLAGS += -Wno-format-truncation
445  CXXFLAGS += -std=c++11
446
447  CFLAGS += -Wall -Wextra -Wformat
448  CFLAGS += -Wno-char-subscripts
449  CFLAGS += -Wno-sign-compare
450  CFLAGS += -Wno-unused-function
451  CFLAGS += -Wno-unused-parameter
452  CFLAGS += -Wno-unused-variable
453  CFLAGS += -Wno-deprecated-declarations
454  CFLAGS += -Wno-format-truncation
455else
456  CXXFLAGSUSER := ${CXXFLAGS}
457endif
458
459
460
461
462ifeq (${OSTYPE}, Linux)
463  CC        ?= gcc
464  CXX       ?= g++
465
466  CXXFLAGS  += -pthread -fopenmp -fPIC
467  LDFLAGS   += -pthread -fopenmp -lm
468
469  BUILDSTACKTRACE ?= 1
470endif
471
472
473#  The default MacOS compiler - even as of 10.13 High Sierra - doesn't support OpenMP.
474#  Clang 6.0 installed from MacPorts supports OpenMP, but fails to compile Canu.
475#  So, we require gcc9 (from MacPorts) or gcc8 (from hommebrew).
476#
477#  If from MacPorts:
478#    port install gcc9
479#    port select gcc mp-gcc9
480#
481#  If CC is set to 'cc', the GNU make default, we'll automagically search for other
482#  versions and use those if found.
483#
484
485define TEST_COMPILER
486  ifeq ($${CC}, cc)
487    CCTEST  := $$(shell echo `which gcc-${1}`)
488    CXXTEST := $$(shell echo `which g++-${1}`)
489
490    ifdef CXXTEST
491      CC  := $${CCTEST}
492      CXX := $${CXXTEST}
493    endif
494  endif
495endef
496
497ifeq (${OSTYPE}, Darwin)
498  $(foreach suffix,mp-9 9  mp-8 8  mp-7 7,$(eval $(call TEST_COMPILER,${suffix})))
499
500  ifneq ($(shell echo `$(CXX) --version 2>&1 | grep -c clang`), 0)
501     CPATH := $(shell echo `which $(CXX)`)
502     CLANG := $(shell echo `$(CXX) --version 2>&1 | grep clang`)
503     space :=
504
505     $(warning )
506     ifeq ($(CXX), $(CPATH))
507       $(warning Compiler '$(CXX)' reports version '$(CLANG)'.)
508     else
509       $(warning Compiler '$(CXX)' at '$(CPATH)' reports version '$(CLANG)'.)
510     endif
511     $(warning )
512     $(warning Canu cannot be compiled with this compiler.  Please install GCC and/or)
513     $(warning specify a non-Clang compiler on the command line, e.g.,)   #  Quite the evil trick to get
514     $(warning $(space)    make CC=/path/to/gcc CXX=/path/to/g++);        #  this line indented!
515     $(warning )
516     $(error unsupported compiler)
517  endif
518
519  CXXFLAGS += -fopenmp -pthread -fPIC -m64 -Wno-format
520  LDFLAGS  += -fopenmp -pthread -lm
521endif
522
523
524ifeq (${OSTYPE}, FreeBSD)
525ifeq (${CANU_BUILD_ENV}, ports)
526
527  # If building in the FreeBSD ports system, use the architecture as defined
528  # there (technically, -p, not -m) and assume compiler and most options
529  # are already defined correctly.
530
531  MACHINETYPE=${ARCH}
532
533  CXXFLAGS  += -pthread -fopenmp -fPIC
534  LDFLAGS   += -pthread -fopenmp
535
536else
537
538  # Ignore the gmake default 'c++' and force g++9.
539	ifeq ($(origin CXX), default)
540    CC    = gcc9
541    CXX   = g++9
542    CCLIB = -rpath /usr/local/lib/gcc9
543  endif
544
545  #  GCC
546  CXXFLAGS  += -I/usr/local/include -pthread -fopenmp -fPIC
547  LDFLAGS   += -L/usr/local/lib     -pthread -fopenmp ${CCLIB} -lm -lexecinfo
548
549  #  CLANG
550  #CXXFLAGS  += -I/usr/local/include -pthread -fPIC
551  #LDFLAGS   += -L/usr/local/lib     -pthread -lm -lexecinfo -lgomp
552
553  #  Google Performance Tools malloc and heapchecker (HEAPCHECK=normal)
554  #CXXFLAGS  +=
555  #LDFLAGS   += -ltcmalloc
556
557  #  Google Performance Tools cpu profiler (CPUPROFILE=/path)
558  #CXXFLAGS  +=
559  #LDFLAGS   += -lprofiler
560
561  #  callgrind
562  #CXXFLAGS  += -g3 -Wa,--gstabs -save-temps
563endif
564endif
565
566
567ifneq (,$(findstring CYGWIN, ${OSTYPE}))
568  CC        ?= gcc
569  CXX       ?= g++
570
571  CXXFLAGS  := -fopenmp -pthread
572  LDFLAGS   := -fopenmp -pthread -lm
573endif
574
575
576#  Stack tracing support.  Wow, what a pain.  Only Linux is supported.  This is just documentation,
577#  don't actually enable any of this stuff!
578#
579#  backward-cpp looks very nice, only a single header file.  But it needs libberty (-liberty) and
580#  libbfd (-lbfd).  The former should be installed with gcc, and the latter is in elfutils.  On
581#  three out of our three development machines, it fails for various reasons.
582#
583#  libunwind is pretty basic.
584#
585#  libbacktrace works (on Linux) and is simple enough to include in our tree.
586#
587#  None of these give any useful information on BSDs (which includes OS X aka macOS).
588#
589#
590#  Backtraces with libunwind.  Not informative on FreeBSD.
591#CXXFLAGS  += -DLIBUNWIND
592#LDFLAGS   +=
593#LDLIBS    += -lunwind -lunwind-x86_64
594#
595#
596#  Backtraces with libbacktrace.  FreeBSD works, but trace is empty.
597#BUILDSTACK = 1
598#CXXFLAGS  += -DLIBBACKTRACE
599#LDFLAGS   +=
600#LDLIBS    +=
601#
602#
603#  Backtraces with backward-cpp.
604#
605#  Stack walking:
606#    BACKWARD_HAS_UNWIND    - used by gcc/clang for exception handling
607#    BACKWARD_HAS_BACKTRACE - part of glib, not as accurate, more portable
608#
609#  Stack interpretation:
610#    BACKWARE_HAS_DW               - most information, libdw, (elfutils or libdwarf)
611#    BACKWARD_HAS_BFD              - some information, libbfd
612#    BACKWARD_HAS_BACKTRACE_SYMBOL - minimal information (file and function), portable
613#
614#  helix   fails with: cannot find -liberty
615#  gryphon fails with: cannot find -lbfd
616#  freebsd can't install a working elfutils, needed for libdw"
617#    In file included from AS_UTL/AS_UTL_stackTrace.C:183:0:
618#    AS_UTL/backward.hpp:241:30: fatal error: elfutils/libdw.h: No such file or directory
619#     #  include <elfutils/libdw.h>
620#
621#CXXFLAGS  += -DBACKWARDCPP -DBACKWARD_HAS_BFD
622#LDFLAGS   +=
623#LDLIBS    += -lbfd -liberty -ldl -lz
624#
625#  Needs libdw, elfutils
626#CXXFLAGS  += -DBACKWARDCPP -DBACKWARD_HAS_DW
627#LDFLAGS   +=
628#LDLIBS    += -ldl -lz
629#
630#  Generates nothing useful, no function names, just binary names
631#CXXFLAGS  += -DBACKWARDCPP
632#LDFLAGS   +=
633#LDLIBS    += -ldl -lz
634#
635#
636#  No backtrace support.
637#CXXFLAGS   += -DNOBACKTRACE
638
639#  But, if we we have an old GCC, stack tracing support isn't there.  The
640#  second test is because gcc7 (and only gcc7) reports '7' for -dumpversion.
641
642GXX_45 := $(shell expr `${CXX} -dumpversion     | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/'` \>= 40500)
643GXX_VV := $(shell ${CXX} -dumpversion)
644
645ifneq (,$(filter ${GXX_VV}, 7 8 9))
646GXX_45 := $(shell expr `${CXX} -dumpfullversion | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/'` \>= 40500)
647GXX_VV := $(shell ${CXX} -dumpfullversion)
648endif
649
650ifeq (${BUILDSTACKTRACE}, 1)
651ifeq (${GXX_45}, 0)
652$(info WARNING:)
653$(info WARNING: ${CXX} ${GXX_VV} detected, disabling stack trace support.  Please upgrade to GCC 4.7 or higher.)
654$(info WARNING:)
655BUILDSTACKTRACE = 0
656endif
657endif
658
659ifeq (${BUILDSTACKTRACE}, 1)
660CXXFLAGS  += -DLIBBACKTRACE
661else
662CXXFLAGS  += -DNOBACKTRACE
663endif
664
665
666# Include the main user-supplied submakefile. This also recursively includes
667# all other user-supplied submakefiles.
668$(eval $(call INCLUDE_SUBMAKEFILE,main.mk))
669
670# Perform post-processing on global variables as needed.
671DEFS := $(addprefix -D,${DEFS})
672INCDIRS := $(addprefix -I,$(call CANONICAL_PATH,${INCDIRS}))
673
674# Define the "all" target (which simply builds all user-defined targets) as the
675# default goal.
676.PHONY: all
677all: $(addprefix ${TARGET_DIR}/,${ALL_TGTS}) \
678     ${TARGET_DIR}/bin/canu \
679     ${TARGET_DIR}/bin/canu-time \
680     ${TARGET_DIR}/bin/draw-tig \
681     ${TARGET_DIR}/bin/canu.defaults \
682     ${TARGET_DIR}/share/java/classes/mhap-2.1.3.jar \
683     ${TARGET_DIR}/lib/site_perl/canu/Consensus.pm \
684     ${TARGET_DIR}/lib/site_perl/canu/CorrectReads.pm \
685     ${TARGET_DIR}/lib/site_perl/canu/HaplotypeReads.pm \
686     ${TARGET_DIR}/lib/site_perl/canu/Configure.pm \
687     ${TARGET_DIR}/lib/site_perl/canu/Defaults.pm \
688     ${TARGET_DIR}/lib/site_perl/canu/Execution.pm \
689     ${TARGET_DIR}/lib/site_perl/canu/SequenceStore.pm \
690     ${TARGET_DIR}/lib/site_perl/canu/Grid.pm \
691     ${TARGET_DIR}/lib/site_perl/canu/Grid_Cloud.pm \
692     ${TARGET_DIR}/lib/site_perl/canu/Grid_DNANexus.pm \
693     ${TARGET_DIR}/lib/site_perl/canu/Grid_LSF.pm \
694     ${TARGET_DIR}/lib/site_perl/canu/Grid_Local.pm \
695     ${TARGET_DIR}/lib/site_perl/canu/Grid_PBSTorque.pm \
696     ${TARGET_DIR}/lib/site_perl/canu/Grid_SGE.pm \
697     ${TARGET_DIR}/lib/site_perl/canu/Grid_Slurm.pm \
698     ${TARGET_DIR}/lib/site_perl/canu/Meryl.pm \
699     ${TARGET_DIR}/lib/site_perl/canu/Output.pm \
700     ${TARGET_DIR}/lib/site_perl/canu/OverlapBasedTrimming.pm \
701     ${TARGET_DIR}/lib/site_perl/canu/OverlapErrorAdjustment.pm \
702     ${TARGET_DIR}/lib/site_perl/canu/OverlapInCore.pm \
703     ${TARGET_DIR}/lib/site_perl/canu/OverlapMhap.pm \
704     ${TARGET_DIR}/lib/site_perl/canu/OverlapMMap.pm \
705     ${TARGET_DIR}/lib/site_perl/canu/OverlapStore.pm \
706     ${TARGET_DIR}/lib/site_perl/canu/Report.pm \
707     ${TARGET_DIR}/lib/site_perl/canu/Unitig.pm
708	@if [ -e ${OBSOLETE_DIR}/bin/canu ] ; then echo "Moving obsolete installation from ${OBSOLETE_DIR} to ${OBSOLETE_DIR}-OBSOLETE."; mv ${OBSOLETE_DIR} ${OBSOLETE_DIR}-OBSOLETE ; fi
709	@echo ""
710	@echo "Success!"
711	@echo "${MODULE} installed in ${TARGET_DIR}/bin/${MODULE}"
712	@echo ""
713
714# Add a new target rule for each user-defined target.
715$(foreach TGT,${ALL_TGTS},\
716  $(eval $(call ADD_TARGET_RULE,${TGT})))
717
718# Add pattern rule(s) for creating compiled object code from C source.
719$(foreach TGT,${ALL_TGTS},\
720  $(foreach EXT,${C_SRC_EXTS},\
721    $(eval $(call ADD_OBJECT_RULE,${BUILD_DIR}/$(call CANONICAL_PATH,${TGT}),\
722             ${EXT},$${COMPILE_C_CMDS}))))
723
724# Add pattern rule(s) for creating compiled object code from C++ source.
725$(foreach TGT,${ALL_TGTS},\
726  $(foreach EXT,${CXX_SRC_EXTS},\
727    $(eval $(call ADD_OBJECT_RULE,${BUILD_DIR}/$(call CANONICAL_PATH,${TGT}),\
728             ${EXT},$${COMPILE_CXX_CMDS}))))
729
730# Add "clean" rules to remove all build-generated files.
731.PHONY: clean
732$(foreach TGT,${ALL_TGTS},\
733  $(eval $(call ADD_CLEAN_RULE,${TGT})))
734
735# Include generated rules that define additional (header) dependencies.
736$(foreach TGT,${ALL_TGTS},\
737  $(eval -include ${${TGT}_DEPS}))
738
739
740${TARGET_DIR}/bin/canu: pipelines/canu.pl
741	cp -pf pipelines/canu.pl ${TARGET_DIR}/bin/canu
742	@chmod +x ${TARGET_DIR}/bin/canu
743
744${TARGET_DIR}/bin/canu-time: pipelines/canu-time.pl
745	cp -pf pipelines/canu-time.pl ${TARGET_DIR}/bin/canu-time
746	@chmod +x ${TARGET_DIR}/bin/canu-time
747
748${TARGET_DIR}/bin/draw-tig: pipelines/draw-tig.pl
749	cp -pf pipelines/draw-tig.pl ${TARGET_DIR}/bin/draw-tig
750	@chmod +x ${TARGET_DIR}/bin/draw-tig
751
752
753${TARGET_DIR}/bin/canu.defaults:
754	@echo > ${TARGET_DIR}/bin/canu.defaults  "# Add site specific options (for setting up Grid or limiting memory/threads) here."
755
756
757${TARGET_DIR}/share/java/classes/mhap-2.1.3.jar: mhap/mhap-2.1.3.jar
758	cp -pf mhap/mhap-2.1.3.jar ${TARGET_DIR}/share/java/classes/mhap-2.1.3.jar
759
760
761${TARGET_DIR}/lib/site_perl/canu/Consensus.pm: pipelines/canu/Consensus.pm
762	cp -pf pipelines/canu/Consensus.pm ${TARGET_DIR}/lib/site_perl/canu/
763
764${TARGET_DIR}/lib/site_perl/canu/CorrectReads.pm: pipelines/canu/CorrectReads.pm
765	cp -pf pipelines/canu/CorrectReads.pm ${TARGET_DIR}/lib/site_perl/canu/
766
767${TARGET_DIR}/lib/site_perl/canu/HaplotypeReads.pm: pipelines/canu/HaplotypeReads.pm
768	cp -pf pipelines/canu/HaplotypeReads.pm ${TARGET_DIR}/lib/site_perl/canu/
769
770${TARGET_DIR}/lib/site_perl/canu/Configure.pm: pipelines/canu/Configure.pm
771	cp -pf pipelines/canu/Configure.pm ${TARGET_DIR}/lib/site_perl/canu/
772
773${TARGET_DIR}/lib/site_perl/canu/Defaults.pm: pipelines/canu/Defaults.pm
774	cp -pf pipelines/canu/Defaults.pm ${TARGET_DIR}/lib/site_perl/canu/
775
776${TARGET_DIR}/lib/site_perl/canu/ErrorEstimate.pm: pipelines/canu/ErrorEstimate.pm
777	cp -pf pipelines/canu/ErrorEstimate.pm ${TARGET_DIR}/lib/site_perl/canu/
778
779${TARGET_DIR}/lib/site_perl/canu/Execution.pm: pipelines/canu/Execution.pm
780	cp -pf pipelines/canu/Execution.pm ${TARGET_DIR}/lib/site_perl/canu/
781
782${TARGET_DIR}/lib/site_perl/canu/SequenceStore.pm: pipelines/canu/SequenceStore.pm
783	cp -pf pipelines/canu/SequenceStore.pm ${TARGET_DIR}/lib/site_perl/canu/
784
785${TARGET_DIR}/lib/site_perl/canu/Grid.pm: pipelines/canu/Grid.pm
786	cp -pf pipelines/canu/Grid.pm ${TARGET_DIR}/lib/site_perl/canu/
787
788${TARGET_DIR}/lib/site_perl/canu/Grid_Cloud.pm: pipelines/canu/Grid_Cloud.pm
789	cp -pf pipelines/canu/Grid_Cloud.pm ${TARGET_DIR}/lib/site_perl/canu/
790
791${TARGET_DIR}/lib/site_perl/canu/Grid_DNANexus.pm: pipelines/canu/Grid_DNANexus.pm
792	cp -pf pipelines/canu/Grid_DNANexus.pm ${TARGET_DIR}/lib/site_perl/canu/
793
794${TARGET_DIR}/lib/site_perl/canu/Grid_LSF.pm: pipelines/canu/Grid_LSF.pm
795	cp -pf pipelines/canu/Grid_LSF.pm ${TARGET_DIR}/lib/site_perl/canu/
796
797${TARGET_DIR}/lib/site_perl/canu/Grid_Local.pm: pipelines/canu/Grid_Local.pm
798	cp -pf pipelines/canu/Grid_Local.pm ${TARGET_DIR}/lib/site_perl/canu/
799
800${TARGET_DIR}/lib/site_perl/canu/Grid_PBSTorque.pm: pipelines/canu/Grid_PBSTorque.pm
801	cp -pf pipelines/canu/Grid_PBSTorque.pm ${TARGET_DIR}/lib/site_perl/canu/
802
803${TARGET_DIR}/lib/site_perl/canu/Grid_SGE.pm: pipelines/canu/Grid_SGE.pm
804	cp -pf pipelines/canu/Grid_SGE.pm ${TARGET_DIR}/lib/site_perl/canu/
805
806${TARGET_DIR}/lib/site_perl/canu/Grid_Slurm.pm: pipelines/canu/Grid_Slurm.pm
807	cp -pf pipelines/canu/Grid_Slurm.pm ${TARGET_DIR}/lib/site_perl/canu/
808
809${TARGET_DIR}/lib/site_perl/canu/Meryl.pm: pipelines/canu/Meryl.pm
810	cp -pf pipelines/canu/Meryl.pm ${TARGET_DIR}/lib/site_perl/canu/
811
812${TARGET_DIR}/lib/site_perl/canu/Output.pm: pipelines/canu/Output.pm
813	cp -pf pipelines/canu/Output.pm ${TARGET_DIR}/lib/site_perl/canu/
814
815${TARGET_DIR}/lib/site_perl/canu/OverlapBasedTrimming.pm: pipelines/canu/OverlapBasedTrimming.pm
816	cp -pf pipelines/canu/OverlapBasedTrimming.pm ${TARGET_DIR}/lib/site_perl/canu/
817
818${TARGET_DIR}/lib/site_perl/canu/OverlapErrorAdjustment.pm: pipelines/canu/OverlapErrorAdjustment.pm
819	cp -pf pipelines/canu/OverlapErrorAdjustment.pm ${TARGET_DIR}/lib/site_perl/canu/
820
821${TARGET_DIR}/lib/site_perl/canu/OverlapInCore.pm: pipelines/canu/OverlapInCore.pm
822	cp -pf pipelines/canu/OverlapInCore.pm ${TARGET_DIR}/lib/site_perl/canu/
823
824${TARGET_DIR}/lib/site_perl/canu/OverlapMhap.pm: pipelines/canu/OverlapMhap.pm
825	cp -pf pipelines/canu/OverlapMhap.pm ${TARGET_DIR}/lib/site_perl/canu/
826
827${TARGET_DIR}/lib/site_perl/canu/OverlapMMap.pm: pipelines/canu/OverlapMMap.pm
828	cp -pf pipelines/canu/OverlapMMap.pm ${TARGET_DIR}/lib/site_perl/canu/
829
830${TARGET_DIR}/lib/site_perl/canu/OverlapStore.pm: pipelines/canu/OverlapStore.pm
831	cp -pf pipelines/canu/OverlapStore.pm ${TARGET_DIR}/lib/site_perl/canu/
832
833${TARGET_DIR}/lib/site_perl/canu/Report.pm: pipelines/canu/Report.pm
834	cp -pf pipelines/canu/Report.pm ${TARGET_DIR}/lib/site_perl/canu/
835
836${TARGET_DIR}/lib/site_perl/canu/Unitig.pm: pipelines/canu/Unitig.pm
837	cp -pf pipelines/canu/Unitig.pm ${TARGET_DIR}/lib/site_perl/canu/
838
839#  Makefile processed.  Regenerate the version number file, make some
840#  directories, and report that we're starting the build.
841
842$(eval $(shell ../scripts/version_update.pl $(MODULE) utility/src/utility/version.H))
843
844$(shell mkdir -p ${TARGET_DIR}/lib/site_perl/canu)
845$(shell mkdir -p ${TARGET_DIR}/share/java/classes)
846$(shell mkdir -p ${TARGET_DIR}/bin)
847
848$(info For '${OSTYPE}' '${OSVERSION}' as '${MACHINETYPE}' into '${TARGET_DIR}/{bin,obj}'.)
849$(info Using '$(shell which ${CXX})' version '${GXX_VV}'.)
850ifneq ($(origin CXXFLAGSUSER), undefined)
851$(info Using user-supplied CXXFLAGS '${CXXFLAGSUSER}'.)
852endif
853$(info )
854