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