common/makefiles/MakeHelpers.gmk

changeset 494
e64f2cb57d05
parent 478
2ba6f4da4bf3
child 507
f2ac4d0edaae
     1.1 --- a/common/makefiles/MakeHelpers.gmk	Wed Oct 24 13:11:42 2012 -0700
     1.2 +++ b/common/makefiles/MakeHelpers.gmk	Fri Oct 26 14:29:57 2012 -0700
     1.3 @@ -45,13 +45,130 @@
     1.4  list_alt_overrides_with_origins=$(filter ALT_%=environment ALT_%=command,$(foreach var,$(.VARIABLES),$(var)=$(firstword $(origin $(var)))))
     1.5  list_alt_overrides=$(subst =command,,$(subst =environment,,$(list_alt_overrides_with_origins)))
     1.6  
     1.7 +# Store the build times in this directory.
     1.8 +BUILDTIMESDIR=$(OUTPUT_ROOT)/tmp/buildtimes
     1.9 +
    1.10 +# Global targets are possible to run either with or without a SPEC. The prototypical
    1.11 +# global target is "help". 
    1.12 +global_targets=help configure
    1.13 +
    1.14  ##############################
    1.15  # Functions
    1.16  ##############################
    1.17  
    1.18 -define fatal-error
    1.19 +define CheckEnvironment
    1.20 +    # Find all environment or command line variables that begin with ALT.
    1.21 +    $(if $(list_alt_overrides),
    1.22 +        @$(PRINTF) "\nWARNING: You have the following ALT_ variables set:\n"
    1.23 +    @$(PRINTF) "$(foreach var,$(list_alt_overrides),$(var)=$$$(var))\n"
    1.24 +    @$(PRINTF) "ALT_ variables are deprecated and will be ignored. Please clean your environment.\n\n"
    1.25 +    )
    1.26 +endef
    1.27 +
    1.28 +### Functions for timers
    1.29 +
    1.30 +# Record starting time for build of a sub repository.
    1.31 +define RecordStartTime
    1.32 +    $(MKDIR) -p $(BUILDTIMESDIR)
    1.33 +    $(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
    1.34 +    $(DATE) '+%Y-%m-%d %H:%M:%S' > $(BUILDTIMESDIR)/build_time_start_$1_human_readable
    1.35 +endef
    1.36 +
    1.37 +# Record ending time and calculate the difference and store it in a
    1.38 +# easy to read format. Handles builds that cross midnight. Expects
    1.39 +# that a build will never take 24 hours or more. 
    1.40 +define RecordEndTime
    1.41 +    $(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
    1.42 +    $(DATE) '+%Y-%m-%d %H:%M:%S' > $(BUILDTIMESDIR)/build_time_end_$1_human_readable
    1.43 +    $(ECHO) `$(CAT) $(BUILDTIMESDIR)/build_time_start_$1` `$(CAT) $(BUILDTIMESDIR)/build_time_end_$1` $1 | \
    1.44 +        $(NAWK) '{ F=$$7; T=$$14; if (F > T) { T+=3600*24 }; D=T-F; H=int(D/3600); \
    1.45 +        M=int((D-H*3600)/60); S=D-H*3600-M*60; printf("%02d:%02d:%02d %s\n",H,M,S,$$15); }' \
    1.46 +        > $(BUILDTIMESDIR)/build_time_diff_$1
    1.47 +endef
    1.48 +
    1.49 +# Find all build_time_* files and print their contents in a list sorted
    1.50 +# on the name of the sub repository.
    1.51 +define ReportBuildTimes
    1.52 +    $(BUILD_LOG_WRAPPER) $(PRINTF) -- "----- Build times -------\nStart %s\nEnd   %s\n%s\n%s\n-------------------------\n" \
    1.53 +        "`$(CAT) $(BUILDTIMESDIR)/build_time_start_TOTAL_human_readable`" \
    1.54 +        "`$(CAT) $(BUILDTIMESDIR)/build_time_end_TOTAL_human_readable`" \
    1.55 +        "`$(LS) $(BUILDTIMESDIR)/build_time_diff_* | $(GREP) -v _TOTAL | $(XARGS) $(CAT) | $(SORT) -k 2`" \
    1.56 +        "`$(CAT) $(BUILDTIMESDIR)/build_time_diff_TOTAL`"
    1.57 +endef
    1.58 +
    1.59 +define ResetAllTimers
    1.60 +    $$(shell $(MKDIR) -p $(BUILDTIMESDIR) &&  $(RM) $(BUILDTIMESDIR)/build_time_*)
    1.61 +endef
    1.62 +
    1.63 +define StartGlobalTimer
    1.64 +    $(call RecordStartTime,TOTAL)
    1.65 +endef
    1.66 +
    1.67 +define StopGlobalTimer
    1.68 +    $(call RecordEndTime,TOTAL)
    1.69 +endef
    1.70 +
    1.71 +### Functions for managing makefile structure (start/end of makefile and individual targets)
    1.72 +
    1.73 +# Do not indent this function, this will add whitespace at the start which the caller won't handle
    1.74 +define GetRealTarget
    1.75 +$(strip $(if $(MAKECMDGOALS),$(MAKECMDGOALS),all))
    1.76 +endef
    1.77 +
    1.78 +# Do not indent this function, this will add whitespace at the start which the caller won't handle
    1.79 +define LastGoal
    1.80 +$(strip $(lastword $(call GetRealTarget)))
    1.81 +endef
    1.82 +
    1.83 +# Check if the current target is the final target, as specified by
    1.84 +# the user on the command line. If so, call AtRootMakeEnd.
    1.85 +define CheckIfMakeAtEnd
    1.86 +    # Check if the current target is the last goal
    1.87 +    $(if $(filter $@,$(call LastGoal)),$(call AtMakeEnd))
    1.88 +    # If the target is 'foo-only', check if our goal was stated as 'foo'
    1.89 +    $(if $(filter $(patsubst %-only,%,$@),$(call LastGoal)),$(call AtMakeEnd))
    1.90 +    # If no goal is given, 'all' is default, but the last target executed for all is 'jdk-only'. Check for that, too.
    1.91 +    # At most one of the tests can be true.
    1.92 +    $(if $(subst all,,$(call LastGoal)),,$(if $(filter $@,jdk-only),$(call AtMakeEnd)))
    1.93 +endef
    1.94 +
    1.95 +# Hook to be called when starting to execute a top-level target
    1.96 +define TargetEnter
    1.97 +    $(BUILD_LOG_WRAPPER) $(PRINTF) "## Starting $(patsubst %-only,%,$@)\n"
    1.98 +    $(call RecordStartTime,$(patsubst %-only,%,$@))
    1.99 +endef
   1.100 +
   1.101 +# Hook to be called when finish executing a top-level target
   1.102 +define TargetExit
   1.103 +    $(call RecordEndTime,$(patsubst %-only,%,$@))
   1.104 +    $(BUILD_LOG_WRAPPER) $(PRINTF) "## Finished $(patsubst %-only,%,$@) (build time %s)\n\n" \
   1.105 +        "`$(CAT) $(BUILDTIMESDIR)/build_time_diff_$(patsubst %-only,%,$@) | $(CUT) -f 1 -d " "`"
   1.106 +    $(call CheckIfMakeAtEnd)
   1.107 +endef
   1.108 +
   1.109 +# Hook to be called as the very first thing when running a normal build
   1.110 +define AtMakeStart
   1.111 +    $(if $(findstring --jobserver,$(MAKEFLAGS)),$(error make -j is not supported, use make JOBS=n))
   1.112 +    $(call CheckEnvironment)
   1.113 +    @$(PRINTF) $(LOG_INFO) "Running make as '$(MAKE) $(MFLAGS) $(MAKE_ARGS)'\n"
   1.114 +    @$(PRINTF) "Building $(PRODUCT_NAME) for target '$(call GetRealTarget)' in configuration '$(CONF_NAME)'\n\n"
   1.115 +    $(call StartGlobalTimer)
   1.116 +endef
   1.117 +
   1.118 +# Hook to be called as the very last thing for targets that are "top level" targets
   1.119 +define AtMakeEnd
   1.120 +    $(if $(SJAVAC_SERVER_DIR),@$(RM) -rf $(SJAVAC_SERVER_DIR)/*.port)
   1.121 +    $(call StopGlobalTimer)
   1.122 +    $(call ReportBuildTimes)
   1.123 +    @$(PRINTF) "Finished building $(PRODUCT_NAME) for target '$(call GetRealTarget)'\n"
   1.124 +    $(call CheckEnvironment)
   1.125 +endef
   1.126 +
   1.127 +### Functions for parsing and setting up make options from command-line
   1.128 +
   1.129 +define FatalError
   1.130      # If the user specificed a "global" target (e.g. 'help'), do not exit but continue running
   1.131 -    $$(if $$(findstring help,$$(MAKECMDGOALS)),,$$(error Cannot continue))
   1.132 +    $$(if $$(filter-out $(global_targets),$$(call GetRealTarget)),$$(error Cannot continue))
   1.133  endef
   1.134  
   1.135  define ParseLogLevel
   1.136 @@ -80,14 +197,14 @@
   1.137          ifeq ($$(LOG),warn)
   1.138              VERBOSE=-s
   1.139          else ifeq ($$(LOG),info)
   1.140 -            VERBOSE=
   1.141 +            VERBOSE=-s
   1.142          else ifeq ($$(LOG),debug)
   1.143              VERBOSE=
   1.144          else ifeq ($$(LOG),trace)
   1.145 -            VERBOSE=-d -p
   1.146 +            VERBOSE=
   1.147          else
   1.148              $$(info Error: LOG must be one of: warn, info, debug or trace.)
   1.149 -            $$(eval $$(call fatal-error))
   1.150 +            $$(eval $$(call FatalError))
   1.151          endif
   1.152      else
   1.153          ifneq ($$(LOG),)
   1.154 @@ -95,108 +212,84 @@
   1.155              # but complain if this is the top-level make call.
   1.156              ifeq ($$(MAKELEVEL),0)
   1.157                  $$(info Cannot use LOG=$$(LOG) and VERBOSE=$$(VERBOSE) at the same time. Choose one.)
   1.158 -                $$(eval $$(call fatal-error))
   1.159 +                $$(eval $$(call FatalError))
   1.160              endif
   1.161          endif
   1.162      endif
   1.163  endef
   1.164  
   1.165 -# TODO: Fix duplication in MakeBase.gmk
   1.166 -define SetupLogging
   1.167 -    ifneq ($(findstring $(LOG),debug trace),)
   1.168 -        # Shell redefinition trick inspired by http://www.cmcrossroads.com/ask-mr-make/6535-tracing-rule-execution-in-gnu-make
   1.169 -        OLD_SHELL:=$$(SHELL)
   1.170 -        SHELL = $$(warning Building $$@$$(if $$<, (from $$<))$(if $$?, ($$? newer)))$$(OLD_SHELL) -x
   1.171 -    endif
   1.172 -endef
   1.173 -
   1.174  define ParseConfAndSpec
   1.175 -    ifneq ($$(origin SPEC),undefined)
   1.176 -        # We have been given a SPEC, check that it works out properly
   1.177 -        ifeq ($$(wildcard $$(SPEC)),)
   1.178 -            $$(info Cannot locate spec.gmk, given by SPEC=$$(SPEC))
   1.179 -            $$(eval $$(call fatal-error))
   1.180 -        endif
   1.181 -        ifneq ($$(origin CONF),undefined)
   1.182 -            # We also have a CONF argument. This is OK only if this is a repeated call by ourselves,
   1.183 -            # but complain if this is the top-level make call.
   1.184 -            ifeq ($$(MAKELEVEL),0)
   1.185 -                $$(info Cannot use CONF=$$(CONF) and SPEC=$$(SPEC) at the same time. Choose one.)
   1.186 -                $$(eval $$(call fatal-error))
   1.187 +    ifneq ($$(filter-out $(global_targets),$$(call GetRealTarget)),)
   1.188 +        # If we only have global targets, no need to bother with SPEC or CONF
   1.189 +        ifneq ($$(origin SPEC),undefined)
   1.190 +            # We have been given a SPEC, check that it works out properly
   1.191 +            ifeq ($$(wildcard $$(SPEC)),)
   1.192 +                $$(info Cannot locate spec.gmk, given by SPEC=$$(SPEC))
   1.193 +                $$(eval $$(call FatalError))
   1.194              endif
   1.195 -        endif
   1.196 -        # ... OK, we're satisfied, we'll use this SPEC later on
   1.197 -    else
   1.198 -        # Find all spec.gmk files in the build output directory
   1.199 -        output_dir=$$(root_dir)/build
   1.200 -        all_spec_files=$$(wildcard $$(output_dir)/*/spec.gmk)
   1.201 -        ifeq ($$(all_spec_files),)
   1.202 -            $$(info No configurations found for $$(root_dir)! Please run configure to create a configuration.)
   1.203 -            $$(eval $$(call fatal-error))
   1.204 -        endif
   1.205 -        # Extract the configuration names from the path
   1.206 -        all_confs=$$(patsubst %/spec.gmk,%,$$(patsubst $$(output_dir)/%,%,$$(all_spec_files)))
   1.207 -
   1.208 -        ifneq ($$(origin CONF),undefined)
   1.209 -            # User have given a CONF= argument.
   1.210 -            ifeq ($$(CONF),)
   1.211 -                # If given CONF=, match all configurations
   1.212 -                matching_confs=$$(strip $$(all_confs))
   1.213 -            else
   1.214 -                # Otherwise select those that contain the given CONF string
   1.215 -                matching_confs=$$(strip $$(foreach var,$$(all_confs),$$(if $$(findstring $$(CONF),$$(var)),$$(var))))
   1.216 -            endif
   1.217 -            ifeq ($$(matching_confs),)
   1.218 -                $$(info No configurations found matching CONF=$$(CONF))
   1.219 -                $$(info Available configurations:)
   1.220 -                $$(foreach var,$$(all_confs),$$(info * $$(var)))
   1.221 -                $$(eval $$(call fatal-error))
   1.222 -            else
   1.223 -                ifeq ($$(words $$(matching_confs)),1)
   1.224 -                    $$(info Building '$$(matching_confs)' (matching CONF=$$(CONF)))
   1.225 -                else
   1.226 -                    $$(info Building the following configurations (matching CONF=$$(CONF)):)
   1.227 -                    $$(foreach var,$$(matching_confs),$$(info * $$(var)))
   1.228 +            ifneq ($$(origin CONF),undefined)
   1.229 +                # We also have a CONF argument. This is OK only if this is a repeated call by ourselves,
   1.230 +                # but complain if this is the top-level make call.
   1.231 +                ifeq ($$(MAKELEVEL),0)
   1.232 +                    $$(info Cannot use CONF=$$(CONF) and SPEC=$$(SPEC) at the same time. Choose one.)
   1.233 +                    $$(eval $$(call FatalError))
   1.234                  endif
   1.235              endif
   1.236 +            # ... OK, we're satisfied, we'll use this SPEC later on
   1.237 +        else
   1.238 +            # Find all spec.gmk files in the build output directory
   1.239 +            output_dir=$$(root_dir)/build
   1.240 +            all_spec_files=$$(wildcard $$(output_dir)/*/spec.gmk)
   1.241 +            ifeq ($$(all_spec_files),)
   1.242 +                $$(info No configurations found for $$(root_dir)! Please run configure to create a configuration.)
   1.243 +                $$(eval $$(call FatalError))
   1.244 +            endif
   1.245 +            # Extract the configuration names from the path
   1.246 +            all_confs=$$(patsubst %/spec.gmk,%,$$(patsubst $$(output_dir)/%,%,$$(all_spec_files)))
   1.247  
   1.248 -            # Create a SPEC definition. This will contain the path to one or more spec.gmk files.
   1.249 -            SPEC=$$(addsuffix /spec.gmk,$$(addprefix $$(output_dir)/,$$(matching_confs)))
   1.250 -        else
   1.251 -            # No CONF or SPEC given, check the available configurations
   1.252 -            ifneq ($$(words $$(all_spec_files)),1)
   1.253 -                $$(info No CONF or SPEC given, but more than one spec.gmk found in $$(output_dir).)
   1.254 -                $$(info Available configurations:)
   1.255 -                $$(foreach var,$$(all_confs),$$(info * $$(var)))
   1.256 -                $$(info Please retry building with CONF=<config> or SPEC=<specfile>)
   1.257 -                $$(eval $$(call fatal-error))
   1.258 +            ifneq ($$(origin CONF),undefined)
   1.259 +                # User have given a CONF= argument.
   1.260 +                ifeq ($$(CONF),)
   1.261 +                    # If given CONF=, match all configurations
   1.262 +                    matching_confs=$$(strip $$(all_confs))
   1.263 +                else
   1.264 +                    # Otherwise select those that contain the given CONF string
   1.265 +                    matching_confs=$$(strip $$(foreach var,$$(all_confs),$$(if $$(findstring $$(CONF),$$(var)),$$(var))))
   1.266 +                endif
   1.267 +                ifeq ($$(matching_confs),)
   1.268 +                    $$(info No configurations found matching CONF=$$(CONF))
   1.269 +                    $$(info Available configurations:)
   1.270 +                    $$(foreach var,$$(all_confs),$$(info * $$(var)))
   1.271 +                    $$(eval $$(call FatalError))
   1.272 +                else
   1.273 +                    ifeq ($$(words $$(matching_confs)),1)
   1.274 +                        $$(info Building '$$(matching_confs)' (matching CONF=$$(CONF)))
   1.275 +                    else
   1.276 +                        $$(info Building target '$(call GetRealTarget)' in the following configurations (matching CONF=$$(CONF)):)
   1.277 +                        $$(foreach var,$$(matching_confs),$$(info * $$(var)))
   1.278 +                    endif
   1.279 +                endif
   1.280 +
   1.281 +                # Create a SPEC definition. This will contain the path to one or more spec.gmk files.
   1.282 +                SPEC=$$(addsuffix /spec.gmk,$$(addprefix $$(output_dir)/,$$(matching_confs)))
   1.283 +            else
   1.284 +                # No CONF or SPEC given, check the available configurations
   1.285 +                ifneq ($$(words $$(all_spec_files)),1)
   1.286 +                    $$(info No CONF given, but more than one configuration found in $$(output_dir).)
   1.287 +                    $$(info Available configurations:)
   1.288 +                    $$(foreach var,$$(all_confs),$$(info * $$(var)))
   1.289 +                    $$(info Please retry building with CONF=<config pattern> (or SPEC=<specfile>))
   1.290 +                    $$(eval $$(call FatalError))
   1.291 +                endif
   1.292 +
   1.293 +                # We found exactly one configuration, use it
   1.294 +                SPEC=$$(strip $$(all_spec_files))
   1.295              endif
   1.296 -
   1.297 -            # We found exactly one configuration, use it
   1.298 -            SPEC=$$(strip $$(all_spec_files))
   1.299          endif
   1.300      endif
   1.301  endef
   1.302  
   1.303 -define CheckEnvironment
   1.304 -    # Find all environment or command line variables that begin with ALT.
   1.305 -    $(if $(list_alt_overrides),
   1.306 -        @$(PRINTF) "\nWARNING: You have the following ALT_ variables set:\n"
   1.307 -    @$(PRINTF) "$(foreach var,$(list_alt_overrides),$(var)=$$$(var))\n"
   1.308 -    @$(PRINTF) "ALT_ variables are deprecated and will be ignored. Please clean your environment.\n\n"
   1.309 -    )
   1.310 -endef
   1.311 -
   1.312 -define PrintStartMessage
   1.313 -    $(if $(VERBOSE),,@$(ECHO) Running make as $(MAKE) $(MFLAGS) $(MAKE_ARGS))
   1.314 -    $(call CheckEnvironment)
   1.315 -    @$(ECHO) "Building OpenJDK for target $(if $(MAKECMDGOALS),'$(MAKECMDGOALS)','all') in configuration '$(CONF_NAME)'"
   1.316 -endef
   1.317 -
   1.318 -define PrintEndMessage
   1.319 -    @$(ECHO) "Finished building OpenJDK for target '$@'"
   1.320 -    $(call CheckEnvironment)
   1.321 -endef
   1.322 +### Convenience functions from Main.gmk
   1.323  
   1.324  # Cleans the component given as $1
   1.325  define CleanComponent

mercurial