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