--- a/common/makefiles/MakeHelpers.gmk Wed Jul 05 18:26:51 2017 +0200
+++ b/common/makefiles/MakeHelpers.gmk Fri Oct 26 14:29:57 2012 -0700
@@ -45,13 +45,130 @@
list_alt_overrides_with_origins=$(filter ALT_%=environment ALT_%=command,$(foreach var,$(.VARIABLES),$(var)=$(firstword $(origin $(var)))))
list_alt_overrides=$(subst =command,,$(subst =environment,,$(list_alt_overrides_with_origins)))
+# Store the build times in this directory.
+BUILDTIMESDIR=$(OUTPUT_ROOT)/tmp/buildtimes
+
+# Global targets are possible to run either with or without a SPEC. The prototypical
+# global target is "help".
+global_targets=help configure
+
##############################
# Functions
##############################
-define fatal-error
+define CheckEnvironment
+ # Find all environment or command line variables that begin with ALT.
+ $(if $(list_alt_overrides),
+ @$(PRINTF) "\nWARNING: You have the following ALT_ variables set:\n"
+ @$(PRINTF) "$(foreach var,$(list_alt_overrides),$(var)=$$$(var))\n"
+ @$(PRINTF) "ALT_ variables are deprecated and will be ignored. Please clean your environment.\n\n"
+ )
+endef
+
+### Functions for timers
+
+# Record starting time for build of a sub repository.
+define RecordStartTime
+ $(MKDIR) -p $(BUILDTIMESDIR)
+ $(DATE) '+%Y %m %d %H %M %S' | $(NAWK) '{ print $$1,$$2,$$3,$$4,$$5,$$6,($$4*3600+$$5*60+$$6) }' > $(BUILDTIMESDIR)/build_time_start_$1
+ $(DATE) '+%Y-%m-%d %H:%M:%S' > $(BUILDTIMESDIR)/build_time_start_$1_human_readable
+endef
+
+# Record ending time and calculate the difference and store it in a
+# easy to read format. Handles builds that cross midnight. Expects
+# that a build will never take 24 hours or more.
+define RecordEndTime
+ $(DATE) '+%Y %m %d %H %M %S' | $(NAWK) '{ print $$1,$$2,$$3,$$4,$$5,$$6,($$4*3600+$$5*60+$$6) }' > $(BUILDTIMESDIR)/build_time_end_$1
+ $(DATE) '+%Y-%m-%d %H:%M:%S' > $(BUILDTIMESDIR)/build_time_end_$1_human_readable
+ $(ECHO) `$(CAT) $(BUILDTIMESDIR)/build_time_start_$1` `$(CAT) $(BUILDTIMESDIR)/build_time_end_$1` $1 | \
+ $(NAWK) '{ F=$$7; T=$$14; if (F > T) { T+=3600*24 }; D=T-F; H=int(D/3600); \
+ M=int((D-H*3600)/60); S=D-H*3600-M*60; printf("%02d:%02d:%02d %s\n",H,M,S,$$15); }' \
+ > $(BUILDTIMESDIR)/build_time_diff_$1
+endef
+
+# Find all build_time_* files and print their contents in a list sorted
+# on the name of the sub repository.
+define ReportBuildTimes
+ $(BUILD_LOG_WRAPPER) $(PRINTF) -- "----- Build times -------\nStart %s\nEnd %s\n%s\n%s\n-------------------------\n" \
+ "`$(CAT) $(BUILDTIMESDIR)/build_time_start_TOTAL_human_readable`" \
+ "`$(CAT) $(BUILDTIMESDIR)/build_time_end_TOTAL_human_readable`" \
+ "`$(LS) $(BUILDTIMESDIR)/build_time_diff_* | $(GREP) -v _TOTAL | $(XARGS) $(CAT) | $(SORT) -k 2`" \
+ "`$(CAT) $(BUILDTIMESDIR)/build_time_diff_TOTAL`"
+endef
+
+define ResetAllTimers
+ $$(shell $(MKDIR) -p $(BUILDTIMESDIR) && $(RM) $(BUILDTIMESDIR)/build_time_*)
+endef
+
+define StartGlobalTimer
+ $(call RecordStartTime,TOTAL)
+endef
+
+define StopGlobalTimer
+ $(call RecordEndTime,TOTAL)
+endef
+
+### Functions for managing makefile structure (start/end of makefile and individual targets)
+
+# Do not indent this function, this will add whitespace at the start which the caller won't handle
+define GetRealTarget
+$(strip $(if $(MAKECMDGOALS),$(MAKECMDGOALS),all))
+endef
+
+# Do not indent this function, this will add whitespace at the start which the caller won't handle
+define LastGoal
+$(strip $(lastword $(call GetRealTarget)))
+endef
+
+# Check if the current target is the final target, as specified by
+# the user on the command line. If so, call AtRootMakeEnd.
+define CheckIfMakeAtEnd
+ # Check if the current target is the last goal
+ $(if $(filter $@,$(call LastGoal)),$(call AtMakeEnd))
+ # If the target is 'foo-only', check if our goal was stated as 'foo'
+ $(if $(filter $(patsubst %-only,%,$@),$(call LastGoal)),$(call AtMakeEnd))
+ # If no goal is given, 'all' is default, but the last target executed for all is 'jdk-only'. Check for that, too.
+ # At most one of the tests can be true.
+ $(if $(subst all,,$(call LastGoal)),,$(if $(filter $@,jdk-only),$(call AtMakeEnd)))
+endef
+
+# Hook to be called when starting to execute a top-level target
+define TargetEnter
+ $(BUILD_LOG_WRAPPER) $(PRINTF) "## Starting $(patsubst %-only,%,$@)\n"
+ $(call RecordStartTime,$(patsubst %-only,%,$@))
+endef
+
+# Hook to be called when finish executing a top-level target
+define TargetExit
+ $(call RecordEndTime,$(patsubst %-only,%,$@))
+ $(BUILD_LOG_WRAPPER) $(PRINTF) "## Finished $(patsubst %-only,%,$@) (build time %s)\n\n" \
+ "`$(CAT) $(BUILDTIMESDIR)/build_time_diff_$(patsubst %-only,%,$@) | $(CUT) -f 1 -d " "`"
+ $(call CheckIfMakeAtEnd)
+endef
+
+# Hook to be called as the very first thing when running a normal build
+define AtMakeStart
+ $(if $(findstring --jobserver,$(MAKEFLAGS)),$(error make -j is not supported, use make JOBS=n))
+ $(call CheckEnvironment)
+ @$(PRINTF) $(LOG_INFO) "Running make as '$(MAKE) $(MFLAGS) $(MAKE_ARGS)'\n"
+ @$(PRINTF) "Building $(PRODUCT_NAME) for target '$(call GetRealTarget)' in configuration '$(CONF_NAME)'\n\n"
+ $(call StartGlobalTimer)
+endef
+
+# Hook to be called as the very last thing for targets that are "top level" targets
+define AtMakeEnd
+ $(if $(SJAVAC_SERVER_DIR),@$(RM) -rf $(SJAVAC_SERVER_DIR)/*.port)
+ $(call StopGlobalTimer)
+ $(call ReportBuildTimes)
+ @$(PRINTF) "Finished building $(PRODUCT_NAME) for target '$(call GetRealTarget)'\n"
+ $(call CheckEnvironment)
+endef
+
+### Functions for parsing and setting up make options from command-line
+
+define FatalError
# If the user specificed a "global" target (e.g. 'help'), do not exit but continue running
- $$(if $$(findstring help,$$(MAKECMDGOALS)),,$$(error Cannot continue))
+ $$(if $$(filter-out $(global_targets),$$(call GetRealTarget)),$$(error Cannot continue))
endef
define ParseLogLevel
@@ -80,14 +197,14 @@
ifeq ($$(LOG),warn)
VERBOSE=-s
else ifeq ($$(LOG),info)
- VERBOSE=
+ VERBOSE=-s
else ifeq ($$(LOG),debug)
VERBOSE=
else ifeq ($$(LOG),trace)
- VERBOSE=-d -p
+ VERBOSE=
else
$$(info Error: LOG must be one of: warn, info, debug or trace.)
- $$(eval $$(call fatal-error))
+ $$(eval $$(call FatalError))
endif
else
ifneq ($$(LOG),)
@@ -95,108 +212,84 @@
# but complain if this is the top-level make call.
ifeq ($$(MAKELEVEL),0)
$$(info Cannot use LOG=$$(LOG) and VERBOSE=$$(VERBOSE) at the same time. Choose one.)
- $$(eval $$(call fatal-error))
+ $$(eval $$(call FatalError))
endif
endif
endif
endef
-# TODO: Fix duplication in MakeBase.gmk
-define SetupLogging
- ifneq ($(findstring $(LOG),debug trace),)
- # Shell redefinition trick inspired by http://www.cmcrossroads.com/ask-mr-make/6535-tracing-rule-execution-in-gnu-make
- OLD_SHELL:=$$(SHELL)
- SHELL = $$(warning Building $$@$$(if $$<, (from $$<))$(if $$?, ($$? newer)))$$(OLD_SHELL) -x
- endif
-endef
-
define ParseConfAndSpec
- ifneq ($$(origin SPEC),undefined)
- # We have been given a SPEC, check that it works out properly
- ifeq ($$(wildcard $$(SPEC)),)
- $$(info Cannot locate spec.gmk, given by SPEC=$$(SPEC))
- $$(eval $$(call fatal-error))
- endif
- ifneq ($$(origin CONF),undefined)
- # We also have a CONF argument. This is OK only if this is a repeated call by ourselves,
- # but complain if this is the top-level make call.
- ifeq ($$(MAKELEVEL),0)
- $$(info Cannot use CONF=$$(CONF) and SPEC=$$(SPEC) at the same time. Choose one.)
- $$(eval $$(call fatal-error))
+ ifneq ($$(filter-out $(global_targets),$$(call GetRealTarget)),)
+ # If we only have global targets, no need to bother with SPEC or CONF
+ ifneq ($$(origin SPEC),undefined)
+ # We have been given a SPEC, check that it works out properly
+ ifeq ($$(wildcard $$(SPEC)),)
+ $$(info Cannot locate spec.gmk, given by SPEC=$$(SPEC))
+ $$(eval $$(call FatalError))
endif
- endif
- # ... OK, we're satisfied, we'll use this SPEC later on
- else
- # Find all spec.gmk files in the build output directory
- output_dir=$$(root_dir)/build
- all_spec_files=$$(wildcard $$(output_dir)/*/spec.gmk)
- ifeq ($$(all_spec_files),)
- $$(info No configurations found for $$(root_dir)! Please run configure to create a configuration.)
- $$(eval $$(call fatal-error))
- endif
- # Extract the configuration names from the path
- all_confs=$$(patsubst %/spec.gmk,%,$$(patsubst $$(output_dir)/%,%,$$(all_spec_files)))
-
- ifneq ($$(origin CONF),undefined)
- # User have given a CONF= argument.
- ifeq ($$(CONF),)
- # If given CONF=, match all configurations
- matching_confs=$$(strip $$(all_confs))
- else
- # Otherwise select those that contain the given CONF string
- matching_confs=$$(strip $$(foreach var,$$(all_confs),$$(if $$(findstring $$(CONF),$$(var)),$$(var))))
- endif
- ifeq ($$(matching_confs),)
- $$(info No configurations found matching CONF=$$(CONF))
- $$(info Available configurations:)
- $$(foreach var,$$(all_confs),$$(info * $$(var)))
- $$(eval $$(call fatal-error))
- else
- ifeq ($$(words $$(matching_confs)),1)
- $$(info Building '$$(matching_confs)' (matching CONF=$$(CONF)))
- else
- $$(info Building the following configurations (matching CONF=$$(CONF)):)
- $$(foreach var,$$(matching_confs),$$(info * $$(var)))
+ ifneq ($$(origin CONF),undefined)
+ # We also have a CONF argument. This is OK only if this is a repeated call by ourselves,
+ # but complain if this is the top-level make call.
+ ifeq ($$(MAKELEVEL),0)
+ $$(info Cannot use CONF=$$(CONF) and SPEC=$$(SPEC) at the same time. Choose one.)
+ $$(eval $$(call FatalError))
endif
endif
-
- # Create a SPEC definition. This will contain the path to one or more spec.gmk files.
- SPEC=$$(addsuffix /spec.gmk,$$(addprefix $$(output_dir)/,$$(matching_confs)))
+ # ... OK, we're satisfied, we'll use this SPEC later on
else
- # No CONF or SPEC given, check the available configurations
- ifneq ($$(words $$(all_spec_files)),1)
- $$(info No CONF or SPEC given, but more than one spec.gmk found in $$(output_dir).)
- $$(info Available configurations:)
- $$(foreach var,$$(all_confs),$$(info * $$(var)))
- $$(info Please retry building with CONF=<config> or SPEC=<specfile>)
- $$(eval $$(call fatal-error))
+ # Find all spec.gmk files in the build output directory
+ output_dir=$$(root_dir)/build
+ all_spec_files=$$(wildcard $$(output_dir)/*/spec.gmk)
+ ifeq ($$(all_spec_files),)
+ $$(info No configurations found for $$(root_dir)! Please run configure to create a configuration.)
+ $$(eval $$(call FatalError))
endif
+ # Extract the configuration names from the path
+ all_confs=$$(patsubst %/spec.gmk,%,$$(patsubst $$(output_dir)/%,%,$$(all_spec_files)))
- # We found exactly one configuration, use it
- SPEC=$$(strip $$(all_spec_files))
+ ifneq ($$(origin CONF),undefined)
+ # User have given a CONF= argument.
+ ifeq ($$(CONF),)
+ # If given CONF=, match all configurations
+ matching_confs=$$(strip $$(all_confs))
+ else
+ # Otherwise select those that contain the given CONF string
+ matching_confs=$$(strip $$(foreach var,$$(all_confs),$$(if $$(findstring $$(CONF),$$(var)),$$(var))))
+ endif
+ ifeq ($$(matching_confs),)
+ $$(info No configurations found matching CONF=$$(CONF))
+ $$(info Available configurations:)
+ $$(foreach var,$$(all_confs),$$(info * $$(var)))
+ $$(eval $$(call FatalError))
+ else
+ ifeq ($$(words $$(matching_confs)),1)
+ $$(info Building '$$(matching_confs)' (matching CONF=$$(CONF)))
+ else
+ $$(info Building target '$(call GetRealTarget)' in the following configurations (matching CONF=$$(CONF)):)
+ $$(foreach var,$$(matching_confs),$$(info * $$(var)))
+ endif
+ endif
+
+ # Create a SPEC definition. This will contain the path to one or more spec.gmk files.
+ SPEC=$$(addsuffix /spec.gmk,$$(addprefix $$(output_dir)/,$$(matching_confs)))
+ else
+ # No CONF or SPEC given, check the available configurations
+ ifneq ($$(words $$(all_spec_files)),1)
+ $$(info No CONF given, but more than one configuration found in $$(output_dir).)
+ $$(info Available configurations:)
+ $$(foreach var,$$(all_confs),$$(info * $$(var)))
+ $$(info Please retry building with CONF=<config pattern> (or SPEC=<specfile>))
+ $$(eval $$(call FatalError))
+ endif
+
+ # We found exactly one configuration, use it
+ SPEC=$$(strip $$(all_spec_files))
+ endif
endif
endif
endef
-define CheckEnvironment
- # Find all environment or command line variables that begin with ALT.
- $(if $(list_alt_overrides),
- @$(PRINTF) "\nWARNING: You have the following ALT_ variables set:\n"
- @$(PRINTF) "$(foreach var,$(list_alt_overrides),$(var)=$$$(var))\n"
- @$(PRINTF) "ALT_ variables are deprecated and will be ignored. Please clean your environment.\n\n"
- )
-endef
-
-define PrintStartMessage
- $(if $(VERBOSE),,@$(ECHO) Running make as $(MAKE) $(MFLAGS) $(MAKE_ARGS))
- $(call CheckEnvironment)
- @$(ECHO) "Building OpenJDK for target $(if $(MAKECMDGOALS),'$(MAKECMDGOALS)','all') in configuration '$(CONF_NAME)'"
-endef
-
-define PrintEndMessage
- @$(ECHO) "Finished building OpenJDK for target '$@'"
- $(call CheckEnvironment)
-endef
+### Convenience functions from Main.gmk
# Cleans the component given as $1
define CleanComponent