common/makefiles/MakeHelpers.gmk
changeset 14111 2a82ecb35fc7
parent 13697 5262b00bc10c
child 14379 b449aa34783e
equal deleted inserted replaced
14104:8d9d430b4244 14111:2a82ecb35fc7
    43 MAKE_ARGS=$(foreach var,$(subst =command,,$(filter %=command,$(foreach var,$(.VARIABLES),$(var)=$(firstword $(origin $(var)))))),$(var)=$($(var)))
    43 MAKE_ARGS=$(foreach var,$(subst =command,,$(filter %=command,$(foreach var,$(.VARIABLES),$(var)=$(firstword $(origin $(var)))))),$(var)=$($(var)))
    44 
    44 
    45 list_alt_overrides_with_origins=$(filter ALT_%=environment ALT_%=command,$(foreach var,$(.VARIABLES),$(var)=$(firstword $(origin $(var)))))
    45 list_alt_overrides_with_origins=$(filter ALT_%=environment ALT_%=command,$(foreach var,$(.VARIABLES),$(var)=$(firstword $(origin $(var)))))
    46 list_alt_overrides=$(subst =command,,$(subst =environment,,$(list_alt_overrides_with_origins)))
    46 list_alt_overrides=$(subst =command,,$(subst =environment,,$(list_alt_overrides_with_origins)))
    47 
    47 
       
    48 # Store the build times in this directory.
       
    49 BUILDTIMESDIR=$(OUTPUT_ROOT)/tmp/buildtimes
       
    50 
       
    51 # Global targets are possible to run either with or without a SPEC. The prototypical
       
    52 # global target is "help". 
       
    53 global_targets=help configure
       
    54 
    48 ##############################
    55 ##############################
    49 # Functions
    56 # Functions
    50 ##############################
    57 ##############################
    51 
    58 
    52 define fatal-error
    59 define CheckEnvironment
       
    60     # Find all environment or command line variables that begin with ALT.
       
    61     $(if $(list_alt_overrides),
       
    62         @$(PRINTF) "\nWARNING: You have the following ALT_ variables set:\n"
       
    63     @$(PRINTF) "$(foreach var,$(list_alt_overrides),$(var)=$$$(var))\n"
       
    64     @$(PRINTF) "ALT_ variables are deprecated and will be ignored. Please clean your environment.\n\n"
       
    65     )
       
    66 endef
       
    67 
       
    68 ### Functions for timers
       
    69 
       
    70 # Record starting time for build of a sub repository.
       
    71 define RecordStartTime
       
    72     $(MKDIR) -p $(BUILDTIMESDIR)
       
    73     $(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
       
    74     $(DATE) '+%Y-%m-%d %H:%M:%S' > $(BUILDTIMESDIR)/build_time_start_$1_human_readable
       
    75 endef
       
    76 
       
    77 # Record ending time and calculate the difference and store it in a
       
    78 # easy to read format. Handles builds that cross midnight. Expects
       
    79 # that a build will never take 24 hours or more. 
       
    80 define RecordEndTime
       
    81     $(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
       
    82     $(DATE) '+%Y-%m-%d %H:%M:%S' > $(BUILDTIMESDIR)/build_time_end_$1_human_readable
       
    83     $(ECHO) `$(CAT) $(BUILDTIMESDIR)/build_time_start_$1` `$(CAT) $(BUILDTIMESDIR)/build_time_end_$1` $1 | \
       
    84         $(NAWK) '{ F=$$7; T=$$14; if (F > T) { T+=3600*24 }; D=T-F; H=int(D/3600); \
       
    85         M=int((D-H*3600)/60); S=D-H*3600-M*60; printf("%02d:%02d:%02d %s\n",H,M,S,$$15); }' \
       
    86         > $(BUILDTIMESDIR)/build_time_diff_$1
       
    87 endef
       
    88 
       
    89 # Find all build_time_* files and print their contents in a list sorted
       
    90 # on the name of the sub repository.
       
    91 define ReportBuildTimes
       
    92     $(BUILD_LOG_WRAPPER) $(PRINTF) -- "----- Build times -------\nStart %s\nEnd   %s\n%s\n%s\n-------------------------\n" \
       
    93         "`$(CAT) $(BUILDTIMESDIR)/build_time_start_TOTAL_human_readable`" \
       
    94         "`$(CAT) $(BUILDTIMESDIR)/build_time_end_TOTAL_human_readable`" \
       
    95         "`$(LS) $(BUILDTIMESDIR)/build_time_diff_* | $(GREP) -v _TOTAL | $(XARGS) $(CAT) | $(SORT) -k 2`" \
       
    96         "`$(CAT) $(BUILDTIMESDIR)/build_time_diff_TOTAL`"
       
    97 endef
       
    98 
       
    99 define ResetAllTimers
       
   100     $$(shell $(MKDIR) -p $(BUILDTIMESDIR) &&  $(RM) $(BUILDTIMESDIR)/build_time_*)
       
   101 endef
       
   102 
       
   103 define StartGlobalTimer
       
   104     $(call RecordStartTime,TOTAL)
       
   105 endef
       
   106 
       
   107 define StopGlobalTimer
       
   108     $(call RecordEndTime,TOTAL)
       
   109 endef
       
   110 
       
   111 ### Functions for managing makefile structure (start/end of makefile and individual targets)
       
   112 
       
   113 # Do not indent this function, this will add whitespace at the start which the caller won't handle
       
   114 define GetRealTarget
       
   115 $(strip $(if $(MAKECMDGOALS),$(MAKECMDGOALS),all))
       
   116 endef
       
   117 
       
   118 # Do not indent this function, this will add whitespace at the start which the caller won't handle
       
   119 define LastGoal
       
   120 $(strip $(lastword $(call GetRealTarget)))
       
   121 endef
       
   122 
       
   123 # Check if the current target is the final target, as specified by
       
   124 # the user on the command line. If so, call AtRootMakeEnd.
       
   125 define CheckIfMakeAtEnd
       
   126     # Check if the current target is the last goal
       
   127     $(if $(filter $@,$(call LastGoal)),$(call AtMakeEnd))
       
   128     # If the target is 'foo-only', check if our goal was stated as 'foo'
       
   129     $(if $(filter $(patsubst %-only,%,$@),$(call LastGoal)),$(call AtMakeEnd))
       
   130     # If no goal is given, 'all' is default, but the last target executed for all is 'jdk-only'. Check for that, too.
       
   131     # At most one of the tests can be true.
       
   132     $(if $(subst all,,$(call LastGoal)),,$(if $(filter $@,jdk-only),$(call AtMakeEnd)))
       
   133 endef
       
   134 
       
   135 # Hook to be called when starting to execute a top-level target
       
   136 define TargetEnter
       
   137     $(BUILD_LOG_WRAPPER) $(PRINTF) "## Starting $(patsubst %-only,%,$@)\n"
       
   138     $(call RecordStartTime,$(patsubst %-only,%,$@))
       
   139 endef
       
   140 
       
   141 # Hook to be called when finish executing a top-level target
       
   142 define TargetExit
       
   143     $(call RecordEndTime,$(patsubst %-only,%,$@))
       
   144     $(BUILD_LOG_WRAPPER) $(PRINTF) "## Finished $(patsubst %-only,%,$@) (build time %s)\n\n" \
       
   145         "`$(CAT) $(BUILDTIMESDIR)/build_time_diff_$(patsubst %-only,%,$@) | $(CUT) -f 1 -d " "`"
       
   146     $(call CheckIfMakeAtEnd)
       
   147 endef
       
   148 
       
   149 # Hook to be called as the very first thing when running a normal build
       
   150 define AtMakeStart
       
   151     $(if $(findstring --jobserver,$(MAKEFLAGS)),$(error make -j is not supported, use make JOBS=n))
       
   152     $(call CheckEnvironment)
       
   153     @$(PRINTF) $(LOG_INFO) "Running make as '$(MAKE) $(MFLAGS) $(MAKE_ARGS)'\n"
       
   154     @$(PRINTF) "Building $(PRODUCT_NAME) for target '$(call GetRealTarget)' in configuration '$(CONF_NAME)'\n\n"
       
   155     $(call StartGlobalTimer)
       
   156 endef
       
   157 
       
   158 # Hook to be called as the very last thing for targets that are "top level" targets
       
   159 define AtMakeEnd
       
   160     $(if $(SJAVAC_SERVER_DIR),@$(RM) -rf $(SJAVAC_SERVER_DIR)/*.port)
       
   161     $(call StopGlobalTimer)
       
   162     $(call ReportBuildTimes)
       
   163     @$(PRINTF) "Finished building $(PRODUCT_NAME) for target '$(call GetRealTarget)'\n"
       
   164     $(call CheckEnvironment)
       
   165 endef
       
   166 
       
   167 ### Functions for parsing and setting up make options from command-line
       
   168 
       
   169 define FatalError
    53     # If the user specificed a "global" target (e.g. 'help'), do not exit but continue running
   170     # If the user specificed a "global" target (e.g. 'help'), do not exit but continue running
    54     $$(if $$(findstring help,$$(MAKECMDGOALS)),,$$(error Cannot continue))
   171     $$(if $$(filter-out $(global_targets),$$(call GetRealTarget)),$$(error Cannot continue))
    55 endef
   172 endef
    56 
   173 
    57 define ParseLogLevel
   174 define ParseLogLevel
    58     ifeq ($$(origin VERBOSE),undefined)
   175     ifeq ($$(origin VERBOSE),undefined)
    59         # Setup logging according to LOG (but only if VERBOSE is not given)
   176         # Setup logging according to LOG (but only if VERBOSE is not given)
    78             override LOG=warn
   195             override LOG=warn
    79         endif
   196         endif
    80         ifeq ($$(LOG),warn)
   197         ifeq ($$(LOG),warn)
    81             VERBOSE=-s
   198             VERBOSE=-s
    82         else ifeq ($$(LOG),info)
   199         else ifeq ($$(LOG),info)
    83             VERBOSE=
   200             VERBOSE=-s
    84         else ifeq ($$(LOG),debug)
   201         else ifeq ($$(LOG),debug)
    85             VERBOSE=
   202             VERBOSE=
    86         else ifeq ($$(LOG),trace)
   203         else ifeq ($$(LOG),trace)
    87             VERBOSE=-d -p
   204             VERBOSE=
    88         else
   205         else
    89             $$(info Error: LOG must be one of: warn, info, debug or trace.)
   206             $$(info Error: LOG must be one of: warn, info, debug or trace.)
    90             $$(eval $$(call fatal-error))
   207             $$(eval $$(call FatalError))
    91         endif
   208         endif
    92     else
   209     else
    93         ifneq ($$(LOG),)
   210         ifneq ($$(LOG),)
    94             # We have both a VERBOSE and a LOG argument. This is OK only if this is a repeated call by ourselves,
   211             # We have both a VERBOSE and a LOG argument. This is OK only if this is a repeated call by ourselves,
    95             # but complain if this is the top-level make call.
   212             # but complain if this is the top-level make call.
    96             ifeq ($$(MAKELEVEL),0)
   213             ifeq ($$(MAKELEVEL),0)
    97                 $$(info Cannot use LOG=$$(LOG) and VERBOSE=$$(VERBOSE) at the same time. Choose one.)
   214                 $$(info Cannot use LOG=$$(LOG) and VERBOSE=$$(VERBOSE) at the same time. Choose one.)
    98                 $$(eval $$(call fatal-error))
   215                 $$(eval $$(call FatalError))
    99             endif
   216             endif
   100         endif
   217         endif
   101     endif
   218     endif
   102 endef
   219 endef
   103 
   220 
   104 # TODO: Fix duplication in MakeBase.gmk
   221 define ParseConfAndSpec
   105 define SetupLogging
   222     ifneq ($$(filter-out $(global_targets),$$(call GetRealTarget)),)
   106     ifneq ($(findstring $(LOG),debug trace),)
   223         # If we only have global targets, no need to bother with SPEC or CONF
   107         # Shell redefinition trick inspired by http://www.cmcrossroads.com/ask-mr-make/6535-tracing-rule-execution-in-gnu-make
   224         ifneq ($$(origin SPEC),undefined)
   108         OLD_SHELL:=$$(SHELL)
   225             # We have been given a SPEC, check that it works out properly
   109         SHELL = $$(warning Building $$@$$(if $$<, (from $$<))$(if $$?, ($$? newer)))$$(OLD_SHELL) -x
   226             ifeq ($$(wildcard $$(SPEC)),)
       
   227                 $$(info Cannot locate spec.gmk, given by SPEC=$$(SPEC))
       
   228                 $$(eval $$(call FatalError))
       
   229             endif
       
   230             ifneq ($$(origin CONF),undefined)
       
   231                 # We also have a CONF argument. This is OK only if this is a repeated call by ourselves,
       
   232                 # but complain if this is the top-level make call.
       
   233                 ifeq ($$(MAKELEVEL),0)
       
   234                     $$(info Cannot use CONF=$$(CONF) and SPEC=$$(SPEC) at the same time. Choose one.)
       
   235                     $$(eval $$(call FatalError))
       
   236                 endif
       
   237             endif
       
   238             # ... OK, we're satisfied, we'll use this SPEC later on
       
   239         else
       
   240             # Find all spec.gmk files in the build output directory
       
   241             output_dir=$$(root_dir)/build
       
   242             all_spec_files=$$(wildcard $$(output_dir)/*/spec.gmk)
       
   243             ifeq ($$(all_spec_files),)
       
   244                 $$(info No configurations found for $$(root_dir)! Please run configure to create a configuration.)
       
   245                 $$(eval $$(call FatalError))
       
   246             endif
       
   247             # Extract the configuration names from the path
       
   248             all_confs=$$(patsubst %/spec.gmk,%,$$(patsubst $$(output_dir)/%,%,$$(all_spec_files)))
       
   249 
       
   250             ifneq ($$(origin CONF),undefined)
       
   251                 # User have given a CONF= argument.
       
   252                 ifeq ($$(CONF),)
       
   253                     # If given CONF=, match all configurations
       
   254                     matching_confs=$$(strip $$(all_confs))
       
   255                 else
       
   256                     # Otherwise select those that contain the given CONF string
       
   257                     matching_confs=$$(strip $$(foreach var,$$(all_confs),$$(if $$(findstring $$(CONF),$$(var)),$$(var))))
       
   258                 endif
       
   259                 ifeq ($$(matching_confs),)
       
   260                     $$(info No configurations found matching CONF=$$(CONF))
       
   261                     $$(info Available configurations:)
       
   262                     $$(foreach var,$$(all_confs),$$(info * $$(var)))
       
   263                     $$(eval $$(call FatalError))
       
   264                 else
       
   265                     ifeq ($$(words $$(matching_confs)),1)
       
   266                         $$(info Building '$$(matching_confs)' (matching CONF=$$(CONF)))
       
   267                     else
       
   268                         $$(info Building target '$(call GetRealTarget)' in the following configurations (matching CONF=$$(CONF)):)
       
   269                         $$(foreach var,$$(matching_confs),$$(info * $$(var)))
       
   270                     endif
       
   271                 endif
       
   272 
       
   273                 # Create a SPEC definition. This will contain the path to one or more spec.gmk files.
       
   274                 SPEC=$$(addsuffix /spec.gmk,$$(addprefix $$(output_dir)/,$$(matching_confs)))
       
   275             else
       
   276                 # No CONF or SPEC given, check the available configurations
       
   277                 ifneq ($$(words $$(all_spec_files)),1)
       
   278                     $$(info No CONF given, but more than one configuration found in $$(output_dir).)
       
   279                     $$(info Available configurations:)
       
   280                     $$(foreach var,$$(all_confs),$$(info * $$(var)))
       
   281                     $$(info Please retry building with CONF=<config pattern> (or SPEC=<specfile>))
       
   282                     $$(eval $$(call FatalError))
       
   283                 endif
       
   284 
       
   285                 # We found exactly one configuration, use it
       
   286                 SPEC=$$(strip $$(all_spec_files))
       
   287             endif
       
   288         endif
   110     endif
   289     endif
   111 endef
   290 endef
   112 
   291 
   113 define ParseConfAndSpec
   292 ### Convenience functions from Main.gmk
   114     ifneq ($$(origin SPEC),undefined)
       
   115         # We have been given a SPEC, check that it works out properly
       
   116         ifeq ($$(wildcard $$(SPEC)),)
       
   117             $$(info Cannot locate spec.gmk, given by SPEC=$$(SPEC))
       
   118             $$(eval $$(call fatal-error))
       
   119         endif
       
   120         ifneq ($$(origin CONF),undefined)
       
   121             # We also have a CONF argument. This is OK only if this is a repeated call by ourselves,
       
   122             # but complain if this is the top-level make call.
       
   123             ifeq ($$(MAKELEVEL),0)
       
   124                 $$(info Cannot use CONF=$$(CONF) and SPEC=$$(SPEC) at the same time. Choose one.)
       
   125                 $$(eval $$(call fatal-error))
       
   126             endif
       
   127         endif
       
   128         # ... OK, we're satisfied, we'll use this SPEC later on
       
   129     else
       
   130         # Find all spec.gmk files in the build output directory
       
   131         output_dir=$$(root_dir)/build
       
   132         all_spec_files=$$(wildcard $$(output_dir)/*/spec.gmk)
       
   133         ifeq ($$(all_spec_files),)
       
   134             $$(info No configurations found for $$(root_dir)! Please run configure to create a configuration.)
       
   135             $$(eval $$(call fatal-error))
       
   136         endif
       
   137         # Extract the configuration names from the path
       
   138         all_confs=$$(patsubst %/spec.gmk,%,$$(patsubst $$(output_dir)/%,%,$$(all_spec_files)))
       
   139 
       
   140         ifneq ($$(origin CONF),undefined)
       
   141             # User have given a CONF= argument.
       
   142             ifeq ($$(CONF),)
       
   143                 # If given CONF=, match all configurations
       
   144                 matching_confs=$$(strip $$(all_confs))
       
   145             else
       
   146                 # Otherwise select those that contain the given CONF string
       
   147                 matching_confs=$$(strip $$(foreach var,$$(all_confs),$$(if $$(findstring $$(CONF),$$(var)),$$(var))))
       
   148             endif
       
   149             ifeq ($$(matching_confs),)
       
   150                 $$(info No configurations found matching CONF=$$(CONF))
       
   151                 $$(info Available configurations:)
       
   152                 $$(foreach var,$$(all_confs),$$(info * $$(var)))
       
   153                 $$(eval $$(call fatal-error))
       
   154             else
       
   155                 ifeq ($$(words $$(matching_confs)),1)
       
   156                     $$(info Building '$$(matching_confs)' (matching CONF=$$(CONF)))
       
   157                 else
       
   158                     $$(info Building the following configurations (matching CONF=$$(CONF)):)
       
   159                     $$(foreach var,$$(matching_confs),$$(info * $$(var)))
       
   160                 endif
       
   161             endif
       
   162 
       
   163             # Create a SPEC definition. This will contain the path to one or more spec.gmk files.
       
   164             SPEC=$$(addsuffix /spec.gmk,$$(addprefix $$(output_dir)/,$$(matching_confs)))
       
   165         else
       
   166             # No CONF or SPEC given, check the available configurations
       
   167             ifneq ($$(words $$(all_spec_files)),1)
       
   168                 $$(info No CONF or SPEC given, but more than one spec.gmk found in $$(output_dir).)
       
   169                 $$(info Available configurations:)
       
   170                 $$(foreach var,$$(all_confs),$$(info * $$(var)))
       
   171                 $$(info Please retry building with CONF=<config> or SPEC=<specfile>)
       
   172                 $$(eval $$(call fatal-error))
       
   173             endif
       
   174 
       
   175             # We found exactly one configuration, use it
       
   176             SPEC=$$(strip $$(all_spec_files))
       
   177         endif
       
   178     endif
       
   179 endef
       
   180 
       
   181 define CheckEnvironment
       
   182     # Find all environment or command line variables that begin with ALT.
       
   183     $(if $(list_alt_overrides),
       
   184         @$(PRINTF) "\nWARNING: You have the following ALT_ variables set:\n"
       
   185     @$(PRINTF) "$(foreach var,$(list_alt_overrides),$(var)=$$$(var))\n"
       
   186     @$(PRINTF) "ALT_ variables are deprecated and will be ignored. Please clean your environment.\n\n"
       
   187     )
       
   188 endef
       
   189 
       
   190 define PrintStartMessage
       
   191     $(if $(VERBOSE),,@$(ECHO) Running make as $(MAKE) $(MFLAGS) $(MAKE_ARGS))
       
   192     $(call CheckEnvironment)
       
   193     @$(ECHO) "Building OpenJDK for target $(if $(MAKECMDGOALS),'$(MAKECMDGOALS)','all') in configuration '$(CONF_NAME)'"
       
   194 endef
       
   195 
       
   196 define PrintEndMessage
       
   197     @$(ECHO) "Finished building OpenJDK for target '$@'"
       
   198     $(call CheckEnvironment)
       
   199 endef
       
   200 
   293 
   201 # Cleans the component given as $1
   294 # Cleans the component given as $1
   202 define CleanComponent
   295 define CleanComponent
   203     @$(PRINTF) "Cleaning $1 build artifacts ..."
   296     @$(PRINTF) "Cleaning $1 build artifacts ..."
   204     @($(CD) $(OUTPUT_ROOT) && $(RM) -r $1)
   297     @($(CD) $(OUTPUT_ROOT) && $(RM) -r $1)