1 # 2 # Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 3 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 # 5 # This code is free software; you can redistribute it and/or modify it 6 # under the terms of the GNU General Public License version 2 only, as 7 # published by the Free Software Foundation. Oracle designates this 8 # particular file as subject to the "Classpath" exception as provided 9 # by Oracle in the LICENSE file that accompanied this code. 10 # 11 # This code is distributed in the hope that it will be useful, but WITHOUT 12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 # version 2 for more details (a copy is included in the LICENSE file that 15 # accompanied this code). 16 # 17 # You should have received a copy of the GNU General Public License version 18 # 2 along with this work; if not, write to the Free Software Foundation, 19 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 # 21 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 # or visit www.oracle.com if you need additional information or have any 23 # questions. 24 # 25 26 ################################################################ 27 # 28 # This file contains helper functions for the top-level Makefile that does 29 # not depend on the spec.gmk file having been read. (The purpose of this 30 # file is ju to avoid cluttering the top-level Makefile.) 31 # 32 ################################################################ 33 34 ifndef _MAKEHELPERS_GMK 35 _MAKEHELPERS_GMK := 1 36 37 ############################## 38 # Stuff to run at include time 39 ############################## 40 41 # Find out which variables were passed explicitely on the make command line. These 42 # will be passed on to sub-makes, overriding spec.gmk settings. 43 MAKE_ARGS=$(foreach var,$(subst =command,,$(filter %=command,$(foreach var,$(.VARIABLES),$(var)=$(firstword $(origin $(var)))))),$(var)="$($(var))") 44 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))) 47 48 # Store the build times in this directory. 49 BUILDTIMESDIR=$(OUTPUT_ROOT)/make-support/build-times 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 54 55 ############################## 56 # Functions 57 ############################## 58 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 $(findstring main-wrapper, $(MAKECMDGOALS)), $(MAIN_TARGETS), \ 116 $(if $(MAKECMDGOALS),$(MAKECMDGOALS),default))) 117 endef 118 119 # Do not indent this function, this will add whitespace at the start which the caller won't handle 120 define LastGoal 121 $(strip $(lastword $(call GetRealTarget))) 122 endef 123 124 # Check if the current target is the final target, as specified by 125 # the user on the command line. If so, call AtRootMakeEnd. 126 define CheckIfMakeAtEnd 127 # Check if the current target is the last goal 128 $(if $(filter $@,$(call LastGoal)),$(call AtMakeEnd)) 129 # If the target is 'foo-only', check if our goal was stated as 'foo' 130 $(if $(filter $@,$(call LastGoal)-only),$(call AtMakeEnd)) 131 endef 132 133 # Hook to be called when starting to execute a top-level target 134 define TargetEnter 135 $(PRINTF) "## Starting $(patsubst %-only,%,$@)\n" 136 $(call RecordStartTime,$(patsubst %-only,%,$@)) 137 endef 138 139 # Hook to be called when finish executing a top-level target 140 define TargetExit 141 $(call RecordEndTime,$(patsubst %-only,%,$@)) 142 $(PRINTF) "## Finished $(patsubst %-only,%,$@) (build time %s)\n\n" \ 143 "`$(CAT) $(BUILDTIMESDIR)/build_time_diff_$(patsubst %-only,%,$@) | $(CUT) -f 1 -d ' '`" 144 endef 145 146 # Hook to be called as the very first thing when running a normal build 147 define AtMakeStart 148 $(if $(findstring --jobserver,$(MAKEFLAGS)),$(error make -j is not supported, use make JOBS=n)) 149 $(call CheckEnvironment) 150 $(BUILD_LOG_WRAPPER) $(PRINTF) $(LOG_INFO) "Running make as '$(MAKE) $(MFLAGS) $(MAKE_ARGS)'\n" 151 $(BUILD_LOG_WRAPPER) $(PRINTF) "Building $(PRODUCT_NAME) for target '$(call GetRealTarget)' in configuration '$(CONF_NAME)'\n\n" 152 $(call StartGlobalTimer) 153 endef 154 155 # Hook to be called as the very last thing for targets that are "top level" targets 156 define AtMakeEnd 157 [ -f $(SJAVAC_SERVER_DIR)/server.port ] && echo Stopping sjavac server && $(TOUCH) $(SJAVAC_SERVER_DIR)/server.port.stop; true 158 $(call StopGlobalTimer) 159 $(call ReportBuildTimes) 160 @$(PRINTF) "\nFinished building $(PRODUCT_NAME) for target '$(call GetRealTarget)'\n" 161 $(call CheckEnvironment) 162 endef 163 164 ### Functions for parsing and setting up make options from command-line 165 166 define FatalError 167 # If the user specificed a "global" target (e.g. 'help'), do not exit but continue running 168 $$(if $$(filter-out $(global_targets),$$(call GetRealTarget)),$$(error Cannot continue)) 169 endef 170 171 define ParseLogLevel 172 ifeq ($$(origin VERBOSE),undefined) 173 # Setup logging according to LOG (but only if VERBOSE is not given) 174 175 # If the "nofile" argument is given, act on it and strip it away 176 ifneq ($$(findstring nofile,$$(LOG)),) 177 # Reset the build log wrapper, regardless of other values 178 override BUILD_LOG_WRAPPER= 179 # COMMA is defined in spec.gmk, but that is not included yet 180 COMMA=, 181 # First try to remove ",nofile" if it exists 182 LOG_STRIPPED1=$$(subst $$(COMMA)nofile,,$$(LOG)) 183 # Otherwise just remove "nofile" 184 LOG_STRIPPED2=$$(subst nofile,,$$(LOG_STRIPPED1)) 185 # We might have ended up with a leading comma. Remove it 186 LOG_STRIPPED3=$$(strip $$(patsubst $$(COMMA)%,%,$$(LOG_STRIPPED2))) 187 LOG_LEVEL:=$$(LOG_STRIPPED3) 188 else 189 LOG_LEVEL:=$$(LOG) 190 endif 191 192 ifeq ($$(LOG_LEVEL),) 193 # Set LOG to "warn" as default if not set (and no VERBOSE given) 194 override LOG_LEVEL=warn 195 endif 196 ifeq ($$(LOG_LEVEL),warn) 197 VERBOSE=-s 198 else ifeq ($$(LOG_LEVEL),info) 199 VERBOSE=-s 200 else ifeq ($$(LOG_LEVEL),debug) 201 VERBOSE= 202 else ifeq ($$(LOG_LEVEL),trace) 203 VERBOSE= 204 else 205 $$(info Error: LOG must be one of: warn, info, debug or trace.) 206 $$(eval $$(call FatalError)) 207 endif 208 else 209 # Provide resonable interpretations of LOG_LEVEL if VERBOSE is given. 210 ifeq ($(VERBOSE),) 211 LOG_LEVEL:=debug 212 else 213 LOG_LEVEL:=warn 214 endif 215 ifneq ($$(LOG),) 216 # We have both a VERBOSE and a LOG argument. This is OK only if this is a repeated call by ourselves, 217 # but complain if this is the top-level make call. 218 ifeq ($$(MAKELEVEL),0) 219 $$(info Cannot use LOG=$$(LOG) and VERBOSE=$$(VERBOSE) at the same time. Choose one.) 220 $$(eval $$(call FatalError)) 221 endif 222 endif 223 endif 224 endef 225 226 define ParseConfAndSpec 227 ifneq ($$(filter-out $(global_targets),$$(call GetRealTarget)),) 228 # If we only have global targets, no need to bother with SPEC or CONF 229 ifneq ($$(origin SPEC),undefined) 230 # We have been given a SPEC, check that it works out properly 231 ifeq ($$(wildcard $$(SPEC)),) 232 $$(info Cannot locate spec.gmk, given by SPEC=$$(SPEC)) 233 $$(eval $$(call FatalError)) 234 endif 235 ifneq ($$(origin CONF),undefined) 236 # We also have a CONF argument. This is OK only if this is a repeated call by ourselves, 237 # but complain if this is the top-level make call. 238 ifeq ($$(MAKELEVEL),0) 239 $$(info Cannot use CONF=$$(CONF) and SPEC=$$(SPEC) at the same time. Choose one.) 240 $$(eval $$(call FatalError)) 241 endif 242 endif 243 # ... OK, we're satisfied, we'll use this SPEC later on 244 else 245 # Find all spec.gmk files in the build output directory 246 output_dir=$$(root_dir)/build 247 all_spec_files=$$(wildcard $$(output_dir)/*/spec.gmk) 248 ifeq ($$(all_spec_files),) 249 $$(info No configurations found for $$(root_dir)! Please run configure to create a configuration.) 250 $$(eval $$(call FatalError)) 251 endif 252 # Extract the configuration names from the path 253 all_confs=$$(patsubst %/spec.gmk,%,$$(patsubst $$(output_dir)/%,%,$$(all_spec_files))) 254 255 ifneq ($$(origin CONF),undefined) 256 # User have given a CONF= argument. 257 ifeq ($$(CONF),) 258 # If given CONF=, match all configurations 259 matching_confs=$$(strip $$(all_confs)) 260 else 261 # Otherwise select those that contain the given CONF string 262 matching_confs=$$(strip $$(foreach var,$$(all_confs),$$(if $$(findstring $$(CONF),$$(var)),$$(var)))) 263 endif 264 ifeq ($$(matching_confs),) 265 $$(info No configurations found matching CONF=$$(CONF)) 266 $$(info Available configurations:) 267 $$(foreach var,$$(all_confs),$$(info * $$(var))) 268 $$(eval $$(call FatalError)) 269 else 270 ifeq ($$(words $$(matching_confs)),1) 271 $$(info Building '$$(matching_confs)' (matching CONF=$$(CONF))) 272 else 273 $$(info Building target '$(call GetRealTarget)' in the following configurations (matching CONF=$$(CONF)):) 274 $$(foreach var,$$(matching_confs),$$(info * $$(var))) 275 endif 276 endif 277 278 # Create a SPEC definition. This will contain the path to one or more spec.gmk files. 279 SPEC=$$(addsuffix /spec.gmk,$$(addprefix $$(output_dir)/,$$(matching_confs))) 280 else 281 # No CONF or SPEC given, check the available configurations 282 ifneq ($$(words $$(all_spec_files)),1) 283 $$(info No CONF given, but more than one configuration found in $$(output_dir).) 284 $$(info Available configurations:) 285 $$(foreach var,$$(all_confs),$$(info * $$(var))) 286 $$(info Please retry building with CONF=<config pattern> (or SPEC=<specfile>)) 287 $$(eval $$(call FatalError)) 288 endif 289 290 # We found exactly one configuration, use it 291 SPEC=$$(strip $$(all_spec_files)) 292 endif 293 endif 294 endif 295 endef 296 297 ### Convenience functions from Main.gmk 298 299 # Cleans the dir given as $1 300 define CleanDir 301 @$(PRINTF) "Cleaning $(strip $1) build artifacts ..." 302 @($(CD) $(OUTPUT_ROOT) && $(RM) -r $1) 303 @$(PRINTF) " done\n" 304 endef 305 306 define Clean-gensrc 307 @$(PRINTF) "Cleaning gensrc $(if $1,for $(strip $1) )..." 308 @$(RM) -r $(SUPPORT_OUTPUTDIR)/gensrc/$(strip $1) 309 @$(RM) -r $(SUPPORT_OUTPUTDIR)/gensrc_no_docs/$(strip $1) 310 @$(PRINTF) " done\n" 311 endef 312 313 define Clean-java 314 @$(PRINTF) "Cleaning java $(if $1,for $(strip $1) )..." 315 @$(RM) -r $(JDK_OUTPUTDIR)/modules/$(strip $1) 316 @$(RM) -r $(SUPPORT_OUTPUTDIR)/misc/$(strip $1) 317 @$(PRINTF) " done\n" 318 @$(PRINTF) "Cleaning headers $(if $1,for $(strip $1)) ..." 319 @$(RM) -r $(SUPPORT_OUTPUTDIR)/headers/$(strip $1) 320 @$(PRINTF) " done\n" 321 endef 322 323 define Clean-native 324 @$(PRINTF) "Cleaning native $(if $1,for $(strip $1) )..." 325 @$(RM) -r $(SUPPORT_OUTPUTDIR)/native/$(strip $1) 326 @$(RM) -r $(SUPPORT_OUTPUTDIR)/modules_libs/$(strip $1) 327 @$(RM) -r $(SUPPORT_OUTPUTDIR)/modules_libs-stripped/$(strip $1) 328 @$(RM) -r $(SUPPORT_OUTPUTDIR)/modules_cmds/$(strip $1) 329 @$(RM) -r $(SUPPORT_OUTPUTDIR)/modules_cmds-stripped/$(strip $1) 330 @$(PRINTF) " done\n" 331 endef 332 333 define Clean-include 334 @$(PRINTF) "Cleaning include $(if $1,for $(strip $1) )..." 335 @$(RM) -r $(SUPPORT_OUTPUTDIR)/modules_include/$(strip $1) 336 @$(PRINTF) " done\n" 337 endef 338 339 define CleanModule 340 $(call Clean-gensrc, $1) 341 $(call Clean-java, $1) 342 $(call Clean-native, $1) 343 $(call Clean-include, $1) 344 endef 345 346 347 ################################################################################ 348 349 MAKE_TOPDIR_LIST := $(JDK_TOPDIR) $(CORBA_TOPDIR) $(LANGTOOLS_TOPDIR) 350 MAKE_MAKEDIR_LIST := make 351 352 # Helper macro for DeclareRecipesForPhase 353 # Declare a recipe for calling the module and phase specific makefile. 354 # If there are multiple makefiles to call, create a rule for each topdir 355 # that contains a makefile with the target $module-$suffix-$repodir, 356 # (i.e: java.base-gensrc-jdk) 357 # Normally there is only one makefile, and the target will just be 358 # $module-$suffix 359 # Param 1: Name of list to add targets to 360 # Param 2: Module name 361 # Param 3: Topdir 362 define DeclareRecipeForModuleMakefile 363 ifeq ($$($1_MULTIPLE_MAKEFILES), true) 364 $2-$$($1_TARGET_SUFFIX): $2-$$($1_TARGET_SUFFIX)-$$(notdir $3) 365 $1 += $2-$$($1_TARGET_SUFFIX)-$$(notdir $3) 366 367 $2-$$($1_TARGET_SUFFIX)-$$(notdir $3): 368 else 369 $2-$$($1_TARGET_SUFFIX): 370 endif 371 $(ECHO) $(LOG_INFO) "Building $$@" 372 ifeq ($$($1_USE_WRAPPER), true) 373 +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) \ 374 -f ModuleWrapper.gmk \ 375 $$(addprefix -I, $$(wildcard $$(addprefix $3/, $(MAKE_MAKEDIR_LIST)) \ 376 $$(addsuffix /$$($1_MAKE_SUBDIR), $$(addprefix $3/, $(MAKE_MAKEDIR_LIST))))) \ 377 MODULE=$2 MAKEFILE_PREFIX=$$($1_FILE_PREFIX)) 378 else 379 +($(CD) $$(dir $$(firstword $$(wildcard $$(patsubst %, \ 380 $3/%/$$($1_MAKE_SUBDIR)/$$($1_FILE_PREFIX)-$2.gmk, $(MAKE_MAKEDIR_LIST))))) \ 381 && $(MAKE) $(MAKE_ARGS) \ 382 -f $$($1_FILE_PREFIX)-$2.gmk \ 383 $$(addprefix -I, $$(wildcard $$(addprefix $3/, $(MAKE_MAKEDIR_LIST)) \ 384 $$(addsuffix /$3, $$(addprefix $3/, $(MAKE_MAKEDIR_LIST))))) \ 385 MODULE=$2) 386 endif 387 388 endef 389 390 # Helper macro for DeclareRecipesForPhase 391 # Param 1: Name of list to add targets to 392 # Param 2: Module name 393 define DeclareRecipesForPhaseAndModule 394 $1_$2_TOPDIRS := $$(strip $$(sort $$(foreach d, $(MAKE_TOPDIR_LIST), \ 395 $$(patsubst $$d/%, $$d, $$(filter $$d/%, \ 396 $$(wildcard $$(patsubst %, %/$$($1_MAKE_SUBDIR)/$$($1_FILE_PREFIX)-$2.gmk, \ 397 $$(foreach s, $(MAKE_MAKEDIR_LIST), \ 398 $$(addsuffix /$$s, $(MAKE_TOPDIR_LIST)))))))))) 399 400 # Only declare recipes if there are makefiles to call 401 ifneq ($$($1_$2_TOPDIRS), ) 402 $$(foreach d, $$($1_$2_TOPDIRS), \ 403 $$(eval $$(call DeclareRecipeForModuleMakefile,$1,$2,$$d))) 404 $1 += $2-$$($1_TARGET_SUFFIX) 405 $1_MODULES += $2 406 endif 407 endef 408 409 # Declare recipes for a specific module and build phase if there are makefiles 410 # present for the specific combination. 411 # Param 1: Name of list to add targets to 412 # Named params: 413 # TARGET_SUFFIX : Suffix of target to create for recipe 414 # MAKE_SUBDIR : Subdir for this build phase 415 # FILE_PREFIX : File prefix for this build phase 416 # USE_WRAPPER : Set to true to use ModuleWrapper.gmk 417 # CHECK_MODULES : List of modules to try 418 # MULTIPLE_MAKEFILES : Set to true to handle makefils for the same module in 419 # phase in multiple repos 420 # Exported variables: 421 # $1_MODULES : All modules that had rules generated 422 # $1_TARGETS : All targets generated 423 define DeclareRecipesForPhase 424 $(foreach i,2 3 4 5 6 7, $(if $($i),$(strip $1)_$(strip $($i)))$(NEWLINE)) 425 $(if $(8),$(error Internal makefile error: Too many arguments to \ 426 DeclareRecipesForPhase, please update MakeHelper.gmk)) 427 428 $$(foreach m, $$($(strip $1)_CHECK_MODULES), \ 429 $$(eval $$(call DeclareRecipesForPhaseAndModule,$(strip $1),$$m))) 430 431 $(strip $1)_TARGETS := $$($(strip $1)) 432 endef 433 434 ################################################################################ 435 436 endif # _MAKEHELPERS_GMK