lokinet/vendor/cppbackport-master/make.inc

423 lines
13 KiB
PHP

# This Makefile is intended to be included by another Makefile. It contains a
# number of common functions, variables, recipes. Ideally the calling Makefile
# will only need to define targets for that project.
#
# Features:
# - Shadow building
# - Auto dependency generation
# - debug target uses address sanitizer when available (GCC >= 4.8.0),
# and undefined behavior sanitizer (GCC >=4.9.0)
# - coloured error messages when available (GCC >=4.9.0)
# - pre-configured targets for cleaning .o files, insure leftovers
# - targets for callgrind, memcheck, insure, profiling and code coverage
#
# Organization
# - Supporting functions
# - Definitions of the variables used by this makefile (ex., CXX, WARNINGS)
# - Predefined configurations of variables (ex., DEBUG)
# - File type targets (ex., .o)
# - Named targets (ex., profile)
# - Inclusion of auto-dependencies
#
# TODO Profile guided optimization
# TODO Precompiled headers
# TODO Static analysis
# TODO Clang support
# TODO -fsanitize=integer for clang
# TODO -fsanitize=thread
# TODO ubsan prints messages to the stderr; does not terminate
# TODO dynamic/static libs
# TODO _GLIBCXX_DEBUG and _GLIBCXX_DEBUG_PEDANTIC
# TODO split up makefile into common functions, variables, configurations, recipes
# TODO -B option for TOOLCHAIN
# TODO CONFIG=RELEASE (strip, for example)
# TODO Different debug levels
# TODO CONFIG=HARDENED including some of the following options
# TODO -fstack-protector-strong?
# TODO -Wformat-security
# TODO -pie -fPIE
# TODO full relro -Wl,-z,relro,-z,now
# TODO -pipe
# TODO -flto
# Shadow building ==============================================================
# This gets the directory of the calling Makefile (and, presumably, where the
# source code resides
# Functions ====================================================================
gccversion = $(shell $(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/')
gcc48 = $(shell expr $(gccversion) \>= 40800)
gcc49 = $(shell expr $(gccversion) \>= 40900)
gcc51 = $(shell expr $(gccversion) \>= 50100)
# Convert a word to lowercase
lower = $(shell echo $(1) | tr '[:upper:]' '[:lower:]')
# Convert a word to uppercase
upper = $(shell echo $(1) | tr '[:lower:]' '[:upper:]')
# Variables ====================================================================
#
# The basic variables that this makefile uses
# Toolchain --------------------------------------------------------------------
# Which programs to use during compilation
# Path to a different toolchain (ex., ~/bin/gcc-4.9.0)
TOOLCHAIN =
ifndef TOOLCHAIN
# C++ compiler
CXX = g++
# Archive (.a) program
AR = ar
# Linker
LD = $(CXX)
PROFILER = gprof
else
# Use a particular set of tools
CXX = $(TOOLCHAIN)/bin/g++ -B$(TOOLCHAIN)/bin/
AR = $(TOOLCHAIN)/bin/ar
LD = $(CXX)
PROFILER = $(TOOLCHAIN)/bin/gprof
endif
# Misc
VALGRIND = valgrind
# Compiler flags ---------------------------------------------------------------
# Arguments to the toolchain programs
# Which version of C++ to compile for
STANDARD = -ansi -pedantic
# Optimization flags
OPTIMIZATION = -O2
# Architecture flags
TARGET_ARCH =
# Warnings
WARNINGS = -Wall -Wsign-compare -Wconversion -Wpointer-arith \
-Winit-self -Wcast-qual -Wredundant-decls -Wcast-align -Wwrite-strings \
-Wno-long-long -Woverloaded-virtual -Wformat -Wno-unknown-pragmas \
-Wnon-virtual-dtor -Wno-c++0x-compat
# -Wold-style-cast
ifeq "$(gcc51)" "1"
#WARNINGS += -Wsuggest-attribute=const -Wsuggest-attribute=pure
endif
# Level of debugging information to provide
DEBUGGING = -g
# Machine independent options
#-fno-nonansi-builtins
OPTIONS = -fuse-cxa-atexit -ffor-scope
ifeq "$(gcc49)" "1"
OPTIONS += -fdiagnostics-color
endif
# Flags to use when compiling C++ source into object files
CXXFLAGS = $(STANDARD) $(DEBUGGING) $(OPTIMIZATION) $(WARNINGS) $(OPTIONS) $(TARGET_ARCH)
# Directories to search for includes
INCLUDE =
# Any macros that can be defined on the command line
DEFINES = -D_FORTIFY_SOURCE=1
# Preprocessor flags
CPPFLAGS = $(INCLUDE) $(DEFINES)
# How to build an archive
ARFLAGS = crs
# Linker flags
LDFLAGS =
LDLIBS =
ifdef TOOLCHAIN
# Statically link the GCC and
LDFLAGS += -static-libgcc -static-libstdc++
# Dynamic linking
#LDFLAGS += -Wl,-rpath -Wl,$(TOOLCHAIN)/lib
#LDLIBS = -L$(TOOLCHAIN)/lib
endif
# Printing =====================================================================
# If this is not empty, print messages
VERBOSE =
# Predefined configurations ====================================================
# Combinations of the OPTIMIZATION, etc.
ifdef CONFIG
UCONFIG := $(call upper,$(CONFIG))
# Fast -------------------------------------------------------------------------
# A faster build, primarily for testing
ifeq "$(UCONFIG)" "FAST"
OPTIMIZATION = -O0
endif
# Tune -------------------------------------------------------------------------
# Heavily optimized for a fast application
ifeq "$(UCONFIG)" "TUNE"
ifeq "$(gcc48)" "1"
TARGET_ARCH = -march=native
endif
OPTIMIZATION = -O3 -mtune=native
endif
# Debug ------------------------------------------------------------------------
# Programmer is tracking a bug
ifeq "$(UCONFIG)" "DEBUG"
# Set additional warnings and flags
WARNINGS += -Wshadow -Wfloat-equal
ifeq "$(gcc51)" "1"
WARNINGS += -Wstrict-overflow=5
endif
DEBUGGING = -ggdb3 -fno-omit-frame-pointer -fno-default-inline -fno-inline -fno-merge-constants -ffloat-store
# -fno-elide-constructors
# Set the optimization level
ifeq "$(gcc48)" "1"
OPTIMIZATION = -Og
else
OPTIMIZATION = -O0
endif
# Turn on address sanitizer
ifeq "$(gcc48)" "1"
DEBUGGING += -fsanitize=address
LDFLAGS += -fsanitize=address -static-libasan
endif
# Turn on undefined behavior sanitizer and leak sanitizer
ifeq "$(gcc49)" "1"
DEBUGGING += -fsanitize=undefined -fsanitize=leak
LDFLAGS += -fsanitize=undefined -fsanitize=leak -static-libubsan -static-liblsan
endif
endif
# Profile ----------------------------------------------------------------------
# Programmer wants profile information
ifeq "$(UCONFIG)" "PROFILE"
OPTIMIZATION = -O2 -pg
LDFLAGS += -pg
endif
# Coverage ---------------------------------------------------------------------
# Programmer wants code coverage information
ifeq "$(UCONFIG)" "COVERAGE"
DEBUGGING += --coverage -fno-elide-constructors
LDFLAGS += --coverage
OPTIMIZATION = -O0
endif
# Insure -----------------------------------------------------------------------
# Programmer wants to run insure
ifeq "$(UCONFIG)" "INSURE"
CXX = insure
LDLIBS += -lstdc++
OPTIMIZATION = -O0
endif
endif
# Targets ======================================================================
.PHONY: no_default_goal depend clean_insure clean_objects clean_profile clean_depend distclean coverage profile memcheck callgrind cachegrind help help_common examples
no_default_goal:
$(error "The including Makefile hasn't specified a default goal. It should.")
# Dependency generation --------------------------------------------------------
DEPDIR := .deps
# Build object files with automatic dependency generation
# TODO maybe use LINK.cpp from 'make -p'
%.o: %.cpp
@mkdir -p $(@D)/$(DEPDIR)
ifeq ($(VERBOSE),)
@echo [CXX] $@
@$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -MMD -MP -MF $(@D)/$(DEPDIR)/$(*F).d -o $@ $<
else
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -MMD -MP -MF $(@D)/$(DEPDIR)/$(*F).d -o $@ $<
endif
%.a:
ifeq ($(VERBOSE),)
@echo [AR] $@
@$(AR) $(ARFLAGS) $@ $^ > /dev/null
else
$(AR) $(ARFLAGS) $@ $^ > /dev/null
endif
# A script for combining .a's. Dependency list for the mri should be
# subdirectories containing static libs. Name of the output library
# is inferred from the mri name (abc.mri produces libabc.a)
%.mri:
@echo 'CREATE $(patsubst %.mri,lib%.a,$@)' > $@
@for dir in $^; do echo ADDLIB $$dir >> $@; done
@echo 'SAVE' >> $@
# TODO dynamic libs
# %.so: CXXFLAGS += -fPIC
# %.so: LDFLAGS := -shared
# %.so:
# $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@
# optionally add -Wl,-soname,$(SONAME)
# TODO java classes
# %.class: %.java
# $(JC) -cp . $<
# Code coverage ----------------------------------------------------------------
coverage:
ifdef COVERAGE_OUT
@TMPFILE=`mktemp`; lcov --capture --directory . --output-file $$TMPFILE; genhtml $$TMPFILE --output-directory $(COVERAGE_OUT); $(RM) $$TMPFILE
else
$(error You have not set COVERAGE_OUT)
endif
# Profiling --------------------------------------------------------------------
profile:
ifdef PROFILE_TARGET
$(PROFILE_TARGET) $(PROFILE_TARGET_ARGS)
ifdef PROFILE_OUT
@$(PROFILER) -c $(PROFILE_TARGET) > $(PROFILE_OUT)
else
$(error You have not specified PROFILE_OUT)
endif
else
$(error You have not specified PROFILE_TARGET)
endif
# Memcheck ---------------------------------------------------------------------
# User should set MEMCHECK_TARGET, MEMCHECK_TARGET_ARGS, and a recipe like:
# memcheck: $(MEMCHECK_TARGET)
memcheck:
$(VALGRIND) --tool=memcheck -v --read-var-info=yes --track-origins=yes --show-reachable=yes --leak-check=full --read-inline-info=yes --keep-stacktraces=alloc-and-free $(VALGRIND_TARGET) $(VALGRIND_TARGET_ARGS) 2> $(MEMCHECK_OUT)
# Callgrind --------------------------------------------------------------------
# User should set CALLGRIND_TARGET, CALLGRIND_TARGET_ARGS, and a recipe like:
# callgrind: $(CALLGRIND_TARGET)
callgrind:
$(VALGRIND) --tool=callgrind $(VALGRIND_TARGET) $(VALGRIND_TARGET_ARGS)
cachegrind:
$(VALGRIND) --tool=cachegrind --branch-sim=yes $(VALGRIND_TARGET) $(VALGRIND_TARGET_ARGS)
# Clean targets ----------------------------------------------------------------
# remove all .o files
clean_objects:
ifeq ($(VERBOSE),)
@find -name '*.o' -exec $(RM) '{}' \;
else
find -name '*.o' -exec $(RM) '{}' \;
endif
# remove all files left by insure
clean_insure:
ifeq ($(VERBOSE),)
@find -name '*.tcl' -exec $(RM) '{}' \;
@$(RM) tca.map tca.log
else
find -name '*.tcl' -exec $(RM) '{}' \;
$(RM) tca.map tca.log
endif
# remove all files left by gprof
clean_profile:
ifeq ($(VERBOSE),)
@$(RM) profile
@find \( -name '*.gcda' -o -name '*.gcno' \) -exec $(RM) '{}' \;
else
$(RM) profile
find \( -name '*.gcda' -o -name '*.gcno' \) -exec $(RM) '{}' \;
endif
clean_depend:
ifeq ($(VERBOSE),)
@find -depth -name $(DEPDIR) -type d -exec $(RM) -r '{}' \;
else
find -depth -name $(DEPDIR) -type d -exec $(RM) -r '{}' \;
endif
depend: clean clean_depend
distclean: depend
# Documentation ----------------------------------------------------------------
help_common:
@echo "==================================================================="
@echo "Here are some standard Makefile variables and their defaults:"
@echo " CXX ($(CXX))"
@echo " CPPFLAGS ($(CPPFLAGS))"
@echo " LDFLAGS ($(LDFLAGS))"
@echo " LDLIBS ($(LDLIBS))"
@echo " AR ($(AR))"
@echo " ARFLAGS ($(ARFLAGS))"
@echo
@echo "You can set the TOOLCHAIN variable to use a different compiler,"
@echo "linker, profiler. Ex., (~/bin/gcc-4.9.0)"
@echo
@echo "The CXXFLAGS variable is comprised of a number of other variables:"
@echo " STANDARD ($(STANDARD))"
@echo " DEBUGGING ($(DEBUGGING))"
@echo " OPTIMIZATION ($(OPTIMIZATION))"
@echo " WARNINGS ($(WARNINGS))"
@echo " TARGET_ARCH ($(TARGET_ARCH))"
@echo
@echo "For convenience, several preconfigured options are available by"
@echo "setting the CONFIG variale:"
@echo " DEBUG - Turns on debugging info; turns down optimization; enables"
@echo " address sanitizer, etc. if available"
@echo " PROFILE - Keeps optimization for release build; adds debugging"
@echo " and gprof flags"
@echo " COVERAGE - Don't inline functions"
@echo " INSURE - Build the target with the insure compiler"
@echo " TUNE - High optimization level; CPU-specific instructions"
@echo " FAST - A fast compilation with low optimization level"
@echo
@echo "==================================================================="
@echo "Here are some special targets and variables that affect them"
@echo
@echo " profile - First build a target with CONFIG=PROFILE and run it."
@echo " PROFILE_TARGET the name of the program to profile"
@echo " (default: $(PROFILE_TARGET))"
@echo " PROFILE_TARGET_ARGS arguments to the program to profile"
@echo " (default: $(PROFILE_TARGET_ARGS))"
@echo " PROFILE_OUT the file to place the profile data in"
@echo " (default: $(PROFILE_OUT))"
@echo " PROFILER Path to profiler"
@echo " (default: $(PROFILER))"
@echo " coverage - First build a target with CONFIG=COVERAGE and run it."
@echo " COVERAGE_OUT specifies where to put the resulting web pages"
@echo " (default: $(COVERAGE_OUT))"
@echo
@echo " memcheck - Run memcheck for VALGRIND_TARGET, testing memory access"
@echo " callgrind - Run callgrind for VALGRIND_TARGET, testing performance"
@echo " cachegrind - Run cachegrind for VALGRIND_TARGET, testing cache"
@echo " VALGRIND_TARGET The program to check"
@echo " (default: $(VALGRIND_TARGET))"
@echo " VALGRIND_TARGET_ARGS The arguments to VALGRIND_TARGET"
@echo " (default: $(VALGRIND_TARGET_ARGS))"
@echo " MEMCHECK_OUT Where to put the memcheck results"
@echo " (default: $(MEMCHECK_OUT))"
@echo "==================================================================="
help: help_common
# ==============================================================================
# Include dependencies which are stored as .d files in the $(DEPDIR) directories
# TODO prefer -wholename to -path, but old version of find doesn't have wholename
-include $(shell find -path '*/$(DEPDIR)/*.d')