# Copyright (c) Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. ORIG_SHELL = $(shell echo "$$SHELL") SHELL = bash -e -o pipefail -u ORIG_SHELL_PATH = $(shell printf "%s" "$$PATH") # Make infer crash a bit more often to detect issues in the way we call infer within this repo, eg, # using deprecated options. export INFER_STRICT_MODE=1 include $(ROOT_DIR)/Makefile.autoconf PLATFORM = $(shell uname) COPY = cp -f COPY_DIR = cp -Rf REMOVE = rm -f REMOVE_DIR = rm -rf ABSOLUTE_ROOT_DIR = $(shell cd $(ROOT_DIR) && pwd) DEPENDENCIES_DIR = $(ABSOLUTE_ROOT_DIR)/dependencies DOCKER_DIR = $(ABSOLUTE_ROOT_DIR)/docker EXAMPLES_DIR = $(ABSOLUTE_ROOT_DIR)/examples INFER_DIR = $(ABSOLUTE_ROOT_DIR)/infer FCP_DIR = $(ABSOLUTE_ROOT_DIR)/facebook-clang-plugins M4_DIR = $(ABSOLUTE_ROOT_DIR)/m4 SCRIPT_DIR = $(ABSOLUTE_ROOT_DIR)/scripts WEBSITE_DIR = $(ABSOLUTE_ROOT_DIR)/website FCP_CLANG_OCAML_DIR = $(FCP_DIR)/clang-ocaml ANNOTATIONS_DIR = $(INFER_DIR)/annotations BIN_DIR = $(INFER_DIR)/bin ETC_DIR = $(INFER_DIR)/etc LIB_DIR = $(INFER_DIR)/lib MAN_DIR = $(INFER_DIR)/man MODELS_DIR = $(INFER_DIR)/models JAVA_BUILTINS_DIR = $(MODELS_DIR)/java/builtins JAVA_MODELS_DIR = $(MODELS_DIR)/java/src SRC_DIR = $(INFER_DIR)/src BUILD_DIR = $(INFER_DIR)/_build JAVA_LIB_DIR = $(LIB_DIR)/java SPECS_LIB_DIR = $(LIB_DIR)/specs INFER_BIN = $(BIN_DIR)/infer INFER_COMMANDS = \ infer-analyze \ infer-capture \ infer-compile \ infer-explore \ infer-report \ infer-reportdiff \ infer-run \ INFERTOP_BIN = $(BIN_DIR)/infertop.bc.exe INFERUNIT_BIN = $(BIN_DIR)/inferunit.bc.exe CHECKCOPYRIGHT_BIN = $(BIN_DIR)/checkCopyright INFER_CREATE_TRACEVIEW_LINKS = InferCreateTraceViewLinks INFER_CREATE_TRACEVIEW_LINKS_BIN = $(BIN_DIR)/$(INFER_CREATE_TRACEVIEW_LINKS) INFER_COMMAND_MANUALS = $(INFER_COMMANDS:%=$(MAN_DIR)/man1/%.1) INFER_COMMAND_TEXT_MANUALS = $(INFER_COMMANDS:%=$(MAN_DIR)/man1/%.txt) INFER_MANUAL = $(MAN_DIR)/man1/infer.1 INFER_GROFF_MANUALS = $(INFER_COMMAND_MANUALS) $(INFER_MANUAL) INFER_GROFF_MANUALS_GZIPPED = $(INFER_GROFF_MANUALS:=.gz) INFER_TEXT_MANUAL = $(MAN_DIR)/man1/infer.txt INFER_FULL_TEXT_MANUAL = $(MAN_DIR)/man1/infer-full.txt INFER_TEXT_MANUALS = $(INFER_COMMAND_TEXT_MANUALS) $(INFER_TEXT_MANUAL) $(INFER_FULL_TEXT_MANUAL) INFER_MANUALS = $(INFER_GROFF_MANUALS) $(INFER_TEXT_MANUALS) ifeq ($(BUILD_JAVA_ANALYZERS),yes) JAVA_HOME=$(USER_JAVA_HOME) endif # marker to keep track of when models have been rebuilt MODELS_RESULTS_FILE = $(SPECS_LIB_DIR)/models ANDROID_JAR = $(LIB_DIR)/java/android/android-23.jar GUAVA_JAR = $(DEPENDENCIES_DIR)/java/guava/guava-23.0.jar INFER_ANNOTATIONS_JAR = $(ANNOTATIONS_DIR)/annotations.jar JACKSON_JAR = $(DEPENDENCIES_DIR)/java/jackson/jackson-2.2.3.jar JSR_305_JAR = $(DEPENDENCIES_DIR)/java/jsr-305/jsr305.jar JAVA_MODELS_JAR = $(LIB_DIR)/java/models.jar JAVA_DEPS_NO_MODELS = \ $(ANDROID_JAR) $(GUAVA_JAR) $(JACKSON_JAR) $(JSR_305_JAR) $(INFER_ANNOTATIONS_JAR) \ $(INFER_BIN) JAVA_DEPS = $(JAVA_DEPS_NO_MODELS) $(JAVA_MODELS_JAR) $(MODELS_RESULTS_FILE) CLANG_DEPS_NO_MODELS = $(INFER_BIN) CLANG_DEPS = $(CLANG_DEPS_NO_MODELS) $(MODELS_RESULTS_FILE) ifeq ($(HAS_OBJC),yes) XCODE_ISYSROOT = $(XCODE_BASE)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk endif define copy_or_same_file $(COPY) "$(1)" "$(2)" || diff -q "$(1)" "$(2)" endef INTERACTIVE = $(shell [ -t 0 ] && echo 1) SILENT = $(findstring s,$(filter-out -%,$(firstword $(MAKEFLAGS)))) ifeq (1,$(INTERACTIVE)) TERM_ERROR = $(shell printf '\e[31;1m') TERM_INFO = $(shell printf '\e[;1m') TERM_SUCCESS = $(shell printf '\e[;2m') TERM_RESET = $(shell printf '\e[0m') endif ifneq ($(VERBOSE),1) # quiet QUIET = @ endif MAKE := $(MAKE) INTERACTIVE=$(INTERACTIVE) # 99999 PIDs ought to be enough for anybody, but check if pid_max can be found just in case MAX_PID_SIZE = \ $(shell PID_MAX=$$(cat /proc/sys/kernel/pid_max 2>/dev/null); echo $${\#PID_MAX} || echo 5) # Arguments: # $(1) is a string describing the command # $(2) is the command to run # ifeq ($(VERBOSE),1) define silent_on_success $(2) endef else # Run and time the command and redirect its stdout and stderr to files. Display info about the # command only in case of error. Try to be as helpful as possible in the error case. # # The PID of the process is used in the names of the output files, and as a prefix for each error # message so that it's possible to piece error messages together even when they are interleaved with # other messages from concurrent `make` processes. # # Detect if we are already wrapped inside a silent_on_success call and try not to clutter the output # too much in that case. define silent_on_success if [ -n "$${INSIDE_SILENT_ON_SUCCESS-}" ]; then \ echo '*** inner $(1)'; \ echo '*** inner command: $(2)'; \ echo '*** inner CWD: $(CURDIR)'; \ ($(2)); \ exit $$?; \ fi; \ export INSIDE_SILENT_ON_SUCCESS=1; \ HASH="$$$$"; \ UNIX_START_DATE=$$(date +"%s"); \ HUMAN_START_DATE=$$(date +"%H:%M:%S"); \ if [ -z $(SILENT) ]; then \ printf '[%s][%$(MAX_PID_SIZE)s] $(TERM_INFO)%s...$(TERM_RESET)\n' \ "$$HUMAN_START_DATE" "$$HASH" "$(1)"; \ fi; \ $(MKDIR_P) $(ABSOLUTE_ROOT_DIR)/_build_logs; \ ERRCODE=0; \ ($(2)) 1>$(ABSOLUTE_ROOT_DIR)/_build_logs/cmd-$$HASH.out \ 2>$(ABSOLUTE_ROOT_DIR)/_build_logs/cmd-$$HASH.err \ || ERRCODE=$$?; \ if [ $$ERRCODE != 0 ]; then \ echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** ERROR '$(1)'$(TERM_RESET)" >&2; \ echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** command: '$(2)'$(TERM_RESET)" >&2; \ echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** CWD: '$(CURDIR)'$(TERM_RESET)" >&2; \ echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** stdout:$(TERM_RESET)" >&2; \ sed -e "s/^\(.*\)$$/$(TERM_ERROR)[*ERROR**][$$HASH]$(TERM_RESET) \1/" \ $(ABSOLUTE_ROOT_DIR)/_build_logs/cmd-$$HASH.out; >&2; \ echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** stderr:$(TERM_RESET)" >&2; \ sed -e "s/^\(.*\)$$/$(TERM_ERROR)[*ERROR**][$$HASH]$(TERM_RESET) \1/" \ $(ABSOLUTE_ROOT_DIR)/_build_logs/cmd-$$HASH.err; >&2; \ exit $$ERRCODE; \ elif [ -z $(SILENT) ]; then \ UNIX_END_DATE=$$(date +"%s"); \ printf '[%7ss][%$(MAX_PID_SIZE)s] $(TERM_SUCCESS)SUCCESS %s$(TERM_RESET)\n' \ "$$(($$UNIX_END_DATE - $$UNIX_START_DATE))" "$$HASH" "$(1)"; \ fi endef endif # print any variable for Makefile debugging print-%: $(QUIET)echo '$*=$($*)' TESTLOCK = $(INFER_DIR)/tests/testlock.py