1 #
2 # Copyright (c) 2011, 2024, 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 # This file contains helper functions for Init.gmk.
28 # It is divided in two parts, depending on if a SPEC is present or not
29 # (HAS_SPEC is true or not).
30 ################################################################################
31
32 ifndef _INITSUPPORT_GMK
33 _INITSUPPORT_GMK := 1
34
35 ifeq ($(HAS_SPEC), )
36
37 # COMMA is defined in spec.gmk, but that is not included yet
38 COMMA := ,
39
40 # Include the corresponding closed file, if present.
41 ifneq ($(CUSTOM_MAKE_DIR), )
42 -include $(CUSTOM_MAKE_DIR)/InitSupport.gmk
43 endif
44
45 ##############################################################################
46 # Helper functions for the initial part of Init.gmk, before the spec file is
47 # loaded. Most of these functions provide parsing and setting up make options
48 # from the command-line.
49 ##############################################################################
50
51 # Make control variables, handled by Init.gmk
52 INIT_CONTROL_VARIABLES += LOG CONF CONF_NAME SPEC JOBS TEST_JOBS CONF_CHECK \
53 COMPARE_BUILD JTREG GTEST MICRO TEST_OPTS TEST_VM_OPTS
54
55 # All known make control variables
56 MAKE_CONTROL_VARIABLES := $(INIT_CONTROL_VARIABLES) TEST JDK_FILTER SPEC_FILTER
57
58 # Define a simple reverse function.
59 # Should maybe move to MakeBase.gmk, but we can't include that file now.
60 reverse = \
61 $(if $(strip $(1)), $(call reverse, $(wordlist 2, $(words $(1)), $(1)))) \
62 $(firstword $(1))
63
64 # The variable MAKEOVERRIDES contains variable assignments from the command
65 # line, but in reverse order to what the user entered.
66 # The '§' <=> '\ 'dance is needed to keep values with space in them connected.
67 COMMAND_LINE_VARIABLES := $(subst §,\ , $(call reverse, $(subst \ ,§,$(MAKEOVERRIDES))))
68
69 # A list like FOO="val1" BAR="val2" containing all user-supplied make
70 # variables that we should propagate.
71 # The '§' <=> '\ 'dance is needed to keep values with space in them connected.
72 USER_MAKE_VARS := $(subst §,\ , $(filter-out $(addsuffix =%, $(INIT_CONTROL_VARIABLES)), \
73 $(subst \ ,§,$(MAKEOVERRIDES))))
74
75 # Setup information about available configurations, if any.
76 ifneq ($(CUSTOM_ROOT), )
77 build_dir = $(CUSTOM_ROOT)/build
78 else
79 build_dir = $(topdir)/build
80 endif
81 all_spec_files = $(wildcard $(build_dir)/*/spec.gmk)
82 # Extract the configuration names from the path
83 all_confs = $(patsubst %/spec.gmk, %, $(patsubst $(build_dir)/%, %, $(all_spec_files)))
84
85 # Check for unknown command-line variables
86 define CheckControlVariables
87 command_line_variables := $$(strip $$(foreach var, \
88 $$(subst \ ,_,$$(MAKEOVERRIDES)), \
89 $$(firstword $$(subst =, , $$(var)))))
90 unknown_command_line_variables := $$(strip \
91 $$(filter-out $$(MAKE_CONTROL_VARIABLES), $$(command_line_variables)))
92 ifneq ($$(unknown_command_line_variables), )
93 $$(info Note: Command line contains non-control variables:)
94 $$(foreach var, $$(unknown_command_line_variables), $$(info * $$(var)=$$($$(var))))
95 $$(info Make sure it is not mistyped, and that you intend to override this variable.)
96 $$(info 'make help' will list known control variables.)
97 $$(info )
98 endif
99 endef
100
101 # Check for deprecated ALT_ variables
102 define CheckDeprecatedEnvironment
103 defined_alt_variables := $$(filter ALT_%, $$(.VARIABLES))
104 ifneq ($$(defined_alt_variables), )
105 $$(info Warning: You have the following ALT_ variables set:)
106 $$(foreach var, $$(defined_alt_variables), $$(info * $$(var)=$$($$(var))))
107 $$(info ALT_ variables are deprecated, and may result in a failed build.)
108 $$(info Please clean your environment.)
109 $$(info )
110 endif
111 endef
112
113 # Check for invalid make flags like -j
114 define CheckInvalidMakeFlags
115 # This is a trick to get this rule to execute before any other rules
116 # MAKEFLAGS only indicate -j if read in a recipe (!)
117 $$(topdir)/make/Init.gmk: .FORCE
118 $$(if $$(findstring --jobserver, $$(MAKEFLAGS)), \
119 $$(info Error: 'make -jN' is not supported, use 'make JOBS=N') \
120 $$(error Cannot continue) \
121 )
122 .FORCE:
123 .PHONY: .FORCE
124 endef
125
126 # Check that the CONF_CHECK option is valid and set up handling
127 define ParseConfCheckOption
128 ifeq ($$(CONF_CHECK), )
129 # Default behavior is fail
130 CONF_CHECK := fail
131 else ifneq ($$(filter-out auto fail ignore, $$(CONF_CHECK)), )
132 $$(info Error: CONF_CHECK must be one of: auto, fail or ignore.)
133 $$(error Cannot continue)
134 endif
135 endef
136
137 define ParseConfAndSpec
138 ifneq ($$(origin SPEC), undefined)
139 # We have been given a SPEC, check that it works out properly
140 ifneq ($$(origin CONF), undefined)
141 # We also have a CONF argument. We can't have both.
142 $$(info Error: Cannot use CONF=$$(CONF) and SPEC=$$(SPEC) at the same time. Choose one.)
143 $$(error Cannot continue)
144 endif
145 ifneq ($$(origin CONF_NAME), undefined)
146 # We also have a CONF_NAME argument. We can't have both.
147 $$(info Error: Cannot use CONF_NAME=$$(CONF_NAME) and SPEC=$$(SPEC) at the same time. Choose one.)
148 $$(error Cannot continue)
149 endif
150 ifeq ($$(wildcard $$(SPEC)), )
151 $$(info Error: Cannot locate spec.gmk, given by SPEC=$$(SPEC).)
152 $$(error Cannot continue)
153 endif
154 ifeq ($$(filter /%, $$(SPEC)), )
155 # If given with relative path, make it absolute
156 SPECS := $$(CURDIR)/$$(strip $$(SPEC))
157 else
158 SPECS := $$(SPEC)
159 endif
160
161 # For now, unset this SPEC variable.
162 override SPEC :=
163 else
164 # Use spec.gmk files in the build output directory
165 ifeq ($$(all_spec_files), )
166 ifneq ($(CUSTOM_ROOT), )
167 $$(info Error: No configurations found for $$(CUSTOM_ROOT).)
168 else
169 $$(info Error: No configurations found for $$(topdir).)
170 endif
171 $$(info Please run 'bash configure' to create a configuration.)
172 $$(info )
173 $$(error Cannot continue)
174 endif
175
176 ifneq ($$(origin CONF_NAME), undefined)
177 ifneq ($$(origin CONF), undefined)
178 # We also have a CONF argument. We can't have both.
179 $$(info Error: Cannot use CONF=$$(CONF) and CONF_NAME=$$(CONF_NAME) at the same time. Choose one.)
180 $$(error Cannot continue)
181 endif
182 matching_conf := $$(strip $$(filter $$(CONF_NAME), $$(all_confs)))
183 ifeq ($$(matching_conf), )
184 $$(info Error: No configurations found matching CONF_NAME=$$(CONF_NAME).)
185 $$(info Available configurations in $$(build_dir):)
186 $$(foreach var, $$(all_confs), $$(info * $$(var)))
187 $$(error Cannot continue)
188 else ifneq ($$(words $$(matching_conf)), 1)
189 $$(info Error: Matching more than one configuration CONF_NAME=$$(CONF_NAME).)
190 $$(info Available configurations in $$(build_dir):)
191 $$(foreach var, $$(all_confs), $$(info * $$(var)))
192 $$(error Cannot continue)
193 else
194 $$(info Building configuration '$$(matching_conf)' (matching CONF_NAME=$$(CONF_NAME)))
195 endif
196 # Create a SPEC definition. This will contain the path to exactly one spec file.
197 SPECS := $$(build_dir)/$$(matching_conf)/spec.gmk
198 else ifneq ($$(origin CONF), undefined)
199 # User have given a CONF= argument.
200 ifeq ($$(CONF), )
201 # If given CONF=, match all configurations
202 matching_confs := $$(strip $$(all_confs))
203 else
204 # Otherwise select those that contain the given CONF string
205 ifeq ($$(patsubst !%,,$$(CONF)), )
206 # A CONF starting with ! means we should negate the search term
207 matching_confs := $$(strip $$(foreach var, $$(all_confs), \
208 $$(if $$(findstring $$(subst !,,$$(CONF)), $$(var)), ,$$(var))))
209 else
210 matching_confs := $$(strip $$(foreach var, $$(all_confs), \
211 $$(if $$(findstring $$(CONF), $$(var)), $$(var))))
212 endif
213 ifneq ($$(filter $$(CONF), $$(matching_confs)), )
214 # If we found an exact match, use that
215 matching_confs := $$(CONF)
216 # Don't repeat this output on make restarts caused by including
217 # generated files.
218 ifeq ($$(MAKE_RESTARTS), )
219 $$(info Using exact match for CONF=$$(CONF) (other matches are possible))
220 endif
221 endif
222 endif
223 ifeq ($$(matching_confs), )
224 $$(info Error: No configurations found matching CONF=$$(CONF).)
225 $$(info Available configurations in $$(build_dir):)
226 $$(foreach var, $$(all_confs), $$(info * $$(var)))
227 $$(error Cannot continue)
228 else
229 # Don't repeat this output on make restarts caused by including
230 # generated files.
231 ifeq ($$(MAKE_RESTARTS), )
232 ifeq ($$(words $$(matching_confs)), 1)
233 ifneq ($$(findstring $$(LOG_LEVEL), info debug trace), )
234 $$(info Building configuration '$$(matching_confs)' (matching CONF=$$(CONF)))
235 endif
236 else
237 $$(info Building these configurations (matching CONF=$$(CONF)):)
238 $$(foreach var, $$(matching_confs), $$(info * $$(var)))
239 endif
240 endif
241 endif
242
243 # Create a SPEC definition. This will contain the path to one or more spec.gmk files.
244 SPECS := $$(addsuffix /spec.gmk, $$(addprefix $$(build_dir)/, $$(matching_confs)))
245 else
246 # No CONF or SPEC given, check the available configurations
247 ifneq ($$(words $$(all_spec_files)), 1)
248 $$(info Error: No CONF given, but more than one configuration found.)
249 $$(info Available configurations in $$(build_dir):)
250 $$(foreach var, $$(all_confs), $$(info * $$(var)))
251 $$(info Please retry building with CONF=<config pattern> (or SPEC=<spec file>).)
252 $$(info )
253 $$(error Cannot continue)
254 endif
255
256 # We found exactly one configuration, use it
257 SPECS := $$(strip $$(all_spec_files))
258 endif
259 endif
260 endef
261
262 # Extract main targets from Main.gmk using the spec provided in $2.
263 #
264 # Param 1: FORCE = force generation of main-targets.gmk or LAZY = do not force.
265 # Param 2: The SPEC file to use.
266 define DefineMainTargets
267
268 # We will start by making sure the main-targets.gmk file is removed, if
269 # make has not been restarted. By the -include, we will trigger the
270 # rule for generating the file (which is never there since we removed it),
271 # thus generating it fresh, and make will restart, incrementing the restart
272 # count.
273 main_targets_file := $$(dir $(strip $2))make-support/main-targets.gmk
274
275 ifeq ($$(MAKE_RESTARTS), )
276 # Only do this if make has not been restarted, and if we do not force it.
277 ifeq ($(strip $1), FORCE)
278 $$(shell rm -f $$(main_targets_file))
279 endif
280 endif
281
282 $$(main_targets_file):
283 @( cd $$(topdir) && \
284 $$(MAKE) $$(MAKE_LOG_FLAGS) -r -R -f $$(topdir)/make/Main.gmk \
285 -I $$(topdir)/make/common SPEC=$(strip $2) NO_RECIPES=true \
286 $$(MAKE_LOG_VARS) \
287 create-main-targets-include )
288
289 # Now include main-targets.gmk. This will define ALL_MAIN_TARGETS.
290 -include $$(main_targets_file)
291 endef
292
293 define PrintConfCheckFailed
294 @echo ' '
295 @echo "Please rerun configure! Easiest way to do this is by running"
296 @echo "'make reconfigure'."
297 @echo "This behavior may also be changed using CONF_CHECK=<ignore|auto>."
298 @echo ' '
299 endef
300
301 else # $(HAS_SPEC)=true
302 ##############################################################################
303 # Helper functions for the 'main' target. These functions assume a single,
304 # proper and existing SPEC is included.
305 ##############################################################################
306
307 include $(TOPDIR)/make/common/MakeBase.gmk
308
309 # Define basic logging setup
310 BUILD_LOG := $(OUTPUTDIR)/build.log
311 BUILD_PROFILE_LOG := $(OUTPUTDIR)/build-profile.log
312
313 BUILD_LOG_PIPE := > >($(TEE) -a $(BUILD_LOG)) 2> >($(TEE) -a $(BUILD_LOG) >&2) && wait
314 # Use this for simple echo/printf commands that are never expected to print
315 # to stderr.
316 BUILD_LOG_PIPE_SIMPLE := | $(TEE) -a $(BUILD_LOG)
317
318 ifneq ($(CUSTOM_ROOT), )
319 topdir = $(CUSTOM_ROOT)
320 else
321 topdir = $(TOPDIR)
322 endif
323
324 # Setup the build environment to match the requested specification on
325 # level of reproducible builds
326 define SetupReproducibleBuild
327 ifeq ($$(SOURCE_DATE), updated)
328 # For static values of SOURCE_DATE (not "updated"), these are set in spec.gmk
329 export SOURCE_DATE_EPOCH := $$(shell $$(DATE) +"%s")
330 export SOURCE_DATE_ISO_8601 := $$(call EpochToISO8601, $$(SOURCE_DATE_EPOCH))
331 endif
332 endef
333
334 # Parse COMPARE_BUILD into COMPARE_BUILD_*
335 # Syntax: COMPARE_BUILD=CONF=<configure options>:PATCH=<patch file>:
336 # MAKE=<make targets>:COMP_OPTS=<compare script options>:
337 # COMP_DIR=<compare script base dir>|<default>:
338 # FAIL=<bool>
339 # If neither CONF or PATCH is given, assume <default> means CONF if it
340 # begins with "--", otherwise assume it means PATCH.
341 # MAKE and COMP_OPTS can only be used with CONF and/or PATCH specified.
342 # If any value contains "+", it will be replaced by space.
343 # FAIL can be set to false to have the return value of compare be ignored.
344 define ParseCompareBuild
345 ifneq ($$(COMPARE_BUILD), )
346 COMPARE_BUILD_OUTPUTDIR := $(topdir)/build/compare-build/$(CONF_NAME)
347 COMPARE_BUILD_FAIL := true
348
349 ifneq ($$(findstring :, $$(COMPARE_BUILD)), )
350 $$(foreach part, $$(subst :, , $$(COMPARE_BUILD)), \
351 $$(if $$(filter PATCH=%, $$(part)), \
352 $$(eval COMPARE_BUILD_PATCH = $$(strip $$(patsubst PATCH=%, %, $$(part)))) \
353 ) \
354 $$(if $$(filter CONF=%, $$(part)), \
355 $$(eval COMPARE_BUILD_CONF = $$(strip $$(subst +, , $$(patsubst CONF=%, %, $$(part))))) \
356 ) \
357 $$(if $$(filter MAKE=%, $$(part)), \
358 $$(eval COMPARE_BUILD_MAKE = $$(strip $$(subst +, , $$(patsubst MAKE=%, %, $$(part))))) \
359 ) \
360 $$(if $$(filter COMP_OPTS=%, $$(part)), \
361 $$(eval COMPARE_BUILD_COMP_OPTS = $$(strip $$(subst +, , $$(patsubst COMP_OPTS=%, %, $$(part))))) \
362 ) \
363 $$(if $$(filter COMP_DIR=%, $$(part)), \
364 $$(eval COMPARE_BUILD_COMP_DIR = $$(strip $$(subst +, , $$(patsubst COMP_DIR=%, %, $$(part))))) \
365 ) \
366 $$(if $$(filter FAIL=%, $$(part)), \
367 $$(eval COMPARE_BUILD_FAIL = $$(strip $$(subst +, , $$(patsubst FAIL=%, %, $$(part))))) \
368 ) \
369 $$(if $$(filter NODRYRUN=%, $$(part)), \
370 $$(eval COMPARE_BUILD_NODRYRUN = $$(strip $$(subst +, , $$(patsubst NODRYRUN=%, %, $$(part))))) \
371 ) \
372 )
373 else
374 # Separate handling for single field case, to allow for spaces in values.
375 ifneq ($$(filter PATCH=%, $$(COMPARE_BUILD)), )
376 COMPARE_BUILD_PATCH = $$(strip $$(patsubst PATCH=%, %, $$(COMPARE_BUILD)))
377 else ifneq ($$(filter CONF=%, $$(COMPARE_BUILD)), )
378 COMPARE_BUILD_CONF = $$(strip $$(subst +, , $$(patsubst CONF=%, %, $$(COMPARE_BUILD))))
379 else ifneq ($$(filter --%, $$(COMPARE_BUILD)), )
380 # Assume CONF if value begins with --
381 COMPARE_BUILD_CONF = $$(strip $$(subst +, , $$(COMPARE_BUILD)))
382 else
383 # Otherwise assume patch file
384 COMPARE_BUILD_PATCH = $$(strip $$(COMPARE_BUILD))
385 endif
386 endif
387 ifneq ($$(COMPARE_BUILD_PATCH), )
388 ifneq ($$(wildcard $$(topdir)/$$(COMPARE_BUILD_PATCH)), )
389 # Assume relative path, if file exists
390 COMPARE_BUILD_PATCH := $$(wildcard $$(topdir)/$$(COMPARE_BUILD_PATCH))
391 else ifeq ($$(wildcard $$(COMPARE_BUILD_PATCH)), )
392 $$(error Patch file $$(COMPARE_BUILD_PATCH) does not exist)
393 endif
394 ifneq ($$(COMPARE_BUILD_NODRYRUN), true)
395 PATCH_DRY_RUN := $$(shell cd $$(topdir) && $$(PATCH) --dry-run -p1 < $$(COMPARE_BUILD_PATCH) > /dev/null 2>&1 || $$(ECHO) FAILED)
396 ifeq ($$(PATCH_DRY_RUN), FAILED)
397 $$(error Patch file $$(COMPARE_BUILD_PATCH) does not apply cleanly)
398 endif
399 endif
400 endif
401 ifneq ($$(COMPARE_BUILD_FAIL), true)
402 COMPARE_BUILD_IGNORE_RESULT := || true
403 endif
404 endif
405 endef
406
407 # Prepare for a comparison rebuild
408 define PrepareCompareBuild
409 $(ECHO) "Preparing for comparison rebuild"
410 # Apply patch, if any
411 $(if $(COMPARE_BUILD_PATCH), cd $(topdir) && $(PATCH) -p1 < $(COMPARE_BUILD_PATCH))
412 # Move the first build away temporarily
413 $(RM) -r $(topdir)/build/.compare-build-temp
414 $(MKDIR) -p $(topdir)/build/.compare-build-temp
415 $(MV) $(OUTPUTDIR) $(topdir)/build/.compare-build-temp
416 # Restore an old compare-build, or create a new compare-build directory.
417 if test -d $(COMPARE_BUILD_OUTPUTDIR); then \
418 $(MV) $(COMPARE_BUILD_OUTPUTDIR) $(OUTPUTDIR); \
419 else \
420 $(MKDIR) -p $(OUTPUTDIR); \
421 fi
422 # Re-run configure with the same arguments (and possibly some additional),
423 # must be done after patching.
424 ( cd $(CONFIGURE_START_DIR) && PATH="$(ORIGINAL_PATH)" \
425 $(BASH) $(topdir)/configure $(CONFIGURE_COMMAND_LINE) $(COMPARE_BUILD_CONF))
426 endef
427
428 # Cleanup after a compare build
429 define CleanupCompareBuild
430 # If running with a COMPARE_BUILD patch, reverse-apply it, but continue
431 # even if that fails (can happen with removed files).
432 $(if $(COMPARE_BUILD_PATCH), cd $(topdir) && $(PATCH) -R -p1 < $(COMPARE_BUILD_PATCH) || true)
433 # Move this build away and restore the original build
434 $(MKDIR) -p $(topdir)/build/compare-build
435 $(MV) $(OUTPUTDIR) $(COMPARE_BUILD_OUTPUTDIR)
436 $(MV) $(topdir)/build/.compare-build-temp/$(CONF_NAME) $(OUTPUTDIR)
437 $(RM) -r $(topdir)/build/.compare-build-temp
438 endef
439
440 # Do the actual comparison of two builds
441 define CompareBuildDoComparison
442 # Compare first and second build. Ignore any error code from compare.sh.
443 $(ECHO) "Comparing between comparison rebuild (this/new) and baseline (other/old)"
444 $(if $(COMPARE_BUILD_COMP_DIR), \
445 +(cd $(COMPARE_BUILD_OUTPUTDIR) && ./compare.sh --diffs $(COMPARE_BUILD_COMP_OPTS) \
446 -2dirs $(COMPARE_BUILD_OUTPUTDIR)/$(COMPARE_BUILD_COMP_DIR) \
447 $(OUTPUTDIR)/$(COMPARE_BUILD_COMP_DIR) $(COMPARE_BUILD_IGNORE_RESULT)), \
448 +(cd $(COMPARE_BUILD_OUTPUTDIR) && ./compare.sh --diffs $(COMPARE_BUILD_COMP_OPTS) \
449 -o $(OUTPUTDIR) $(COMPARE_BUILD_IGNORE_RESULT)) \
450 )
451 endef
452
453 define PrintFailureReports
454 $(if $(filter none, $(LOG_REPORT)), , \
455 $(RM) $(MAKESUPPORT_OUTPUTDIR)/failure-summary.log ; \
456 $(if $(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*.log), \
457 ( \
458 $(PRINTF) "\n=== Output from failing command(s) repeated here ===\n" ; \
459 $(foreach logfile, $(sort $(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*.log)), \
460 $(PRINTF) "* For target $(notdir $(basename $(logfile))):\n" ; \
461 $(if $(filter all, $(LOG_REPORT)), \
462 $(GREP) -v -e "^Note: including file:" < $(logfile) || true ; \
463 , \
464 ($(GREP) -v -e "^Note: including file:" < $(logfile) || true) | $(HEAD) -n 15 ; \
465 if test `$(WC) -l < $(logfile)` -gt 15; then \
466 $(ECHO) " ... (rest of output omitted)" ; \
467 fi ; \
468 ) \
469 ) \
470 $(PRINTF) "\n* All command lines available in $(MAKESUPPORT_OUTPUTDIR)/failure-logs.\n" ; \
471 $(PRINTF) "=== End of repeated output ===\n" ; \
472 ) >> $(MAKESUPPORT_OUTPUTDIR)/failure-summary.log \
473 ) \
474 )
475 endef
476
477 define PrintBuildLogFailures
478 $(if $(filter none, $(LOG_REPORT)), , \
479 if $(GREP) -q "recipe for target .* failed" $(BUILD_LOG) 2> /dev/null; then \
480 $(PRINTF) "\n=== Make failed targets repeated here ===\n" ; \
481 $(GREP) "recipe for target .* failed" $(BUILD_LOG) ; \
482 $(PRINTF) "=== End of repeated output ===\n" ; \
483 $(PRINTF) "\nHELP: Try searching the build log for the name of the first failed target.\n" ; \
484 else \
485 $(PRINTF) "\nNo indication of failed target found.\n" ; \
486 $(PRINTF) "HELP: Try searching the build log for '] Error'.\n" ; \
487 fi >> $(MAKESUPPORT_OUTPUTDIR)/failure-summary.log ; \
488 $(CAT) $(MAKESUPPORT_OUTPUTDIR)/failure-summary.log \
489 )
490 endef
491
492 define RotateLogFiles
493 $(RM) $(BUILD_LOG).old 2> /dev/null && \
494 $(MV) $(BUILD_LOG) $(BUILD_LOG).old 2> /dev/null || true
495 $(if $(findstring true, $(LOG_PROFILE_TIMES_FILE)), \
496 $(RM) $(BUILD_PROFILE_LOG).old 2> /dev/null && \
497 $(MV) $(BUILD_PROFILE_LOG) $(BUILD_PROFILE_LOG).old 2> /dev/null || true \
498 )
499 endef
500
501 # Failure logs are only supported for "parallel" main targets, not the
502 # (trivial) sequential make targets (such as clean and reconfigure),
503 # since the failure-logs directory creation will conflict with clean.
504 # We also make sure the javatmp directory exists, which is needed if a java
505 # process (like javac) is using java.io.tmpdir.
506 define PrepareFailureLogs
507 $(RM) -r $(MAKESUPPORT_OUTPUTDIR)/failure-logs 2> /dev/null && \
508 $(MKDIR) -p $(MAKESUPPORT_OUTPUTDIR)/failure-logs
509 $(MKDIR) -p $(JAVA_TMP_DIR)
510 $(RM) $(MAKESUPPORT_OUTPUTDIR)/exit-with-error 2> /dev/null
511 endef
512
513 # Remove any javac server logs and port files. This
514 # prevents a new make run to reuse the previous servers.
515 define PrepareJavacServer
516 $(if $(JAVAC_SERVER_DIR), \
517 $(RM) -r $(JAVAC_SERVER_DIR) 2> /dev/null && \
518 $(MKDIR) -p $(JAVAC_SERVER_DIR) \
519 )
520 endef
521
522 define CleanupJavacServer
523 [ -f $(JAVAC_SERVER_DIR)/server.port ] && $(ECHO) Stopping javac server && \
524 $(TOUCH) $(JAVAC_SERVER_DIR)/server.port.stop; true
525 endef
526
527 ifeq ($(call isBuildOs, windows), true)
528 # On windows we need to synchronize with the javac server to be able to
529 # move or remove the build output directory. Since we have no proper
530 # synchronization process, wait for a while and hope it helps. This is only
531 # used by build comparisons.
532 define WaitForJavacServerFinish
533 $(if $(JAVAC_SERVER_DIR), \
534 sleep 5 \
535 )
536 endef
537 else
538 define WaitForJavacServerFinish
539 endef
540 endif
541
542 ##############################################################################
543 # Functions for timers
544 ##############################################################################
545
546 # Store the build times in this directory.
547 BUILDTIMESDIR = $(OUTPUTDIR)/make-support/build-times
548
549 # Record starting time for build of a sub repository.
550 define RecordStartTime
551 $(DATE) '+%Y %m %d %H %M %S' | $(AWK) '{ print $$1,$$2,$$3,$$4,$$5,$$6,($$4*3600+$$5*60+$$6) }' > $(BUILDTIMESDIR)/build_time_start_$(strip $1) && \
552 $(DATE) '+%Y-%m-%d %H:%M:%S' > $(BUILDTIMESDIR)/build_time_start_$(strip $1)_human_readable
553 endef
554
555 # Record ending time and calculate the difference and store it in a
556 # easy to read format. Handles builds that cross midnight. Expects
557 # that a build will never take 24 hours or more.
558 define RecordEndTime
559 $(DATE) '+%Y %m %d %H %M %S' | $(AWK) '{ print $$1,$$2,$$3,$$4,$$5,$$6,($$4*3600+$$5*60+$$6) }' > $(BUILDTIMESDIR)/build_time_end_$(strip $1)
560 $(DATE) '+%Y-%m-%d %H:%M:%S' > $(BUILDTIMESDIR)/build_time_end_$(strip $1)_human_readable
561 $(ECHO) `$(CAT) $(BUILDTIMESDIR)/build_time_start_$(strip $1)` `$(CAT) $(BUILDTIMESDIR)/build_time_end_$(strip $1)` $1 | \
562 $(AWK) '{ F=$$7; T=$$14; if (F > T) { T+=3600*24 }; D=T-F; H=int(D/3600); \
563 M=int((D-H*3600)/60); S=D-H*3600-M*60; printf("%02d:%02d:%02d %s\n",H,M,S,$$15); }' \
564 > $(BUILDTIMESDIR)/build_time_diff_$(strip $1)
565 endef
566
567 define StartGlobalTimer
568 $(RM) -r $(BUILDTIMESDIR) 2> /dev/null && \
569 $(MKDIR) -p $(BUILDTIMESDIR) && \
570 $(call RecordStartTime,TOTAL)
571 endef
572
573 define StopGlobalTimer
574 $(call RecordEndTime,TOTAL)
575 endef
576
577 # Find all build_time_* files and print their contents in a list sorted
578 # on the name of the sub repository.
579 define ReportBuildTimes
580 $(PRINTF) $(LOG_INFO) -- \
581 "----- Build times -------\nStart %s\nEnd %s\n%s\n%s\n-------------------------\n" \
582 "`$(CAT) $(BUILDTIMESDIR)/build_time_start_TOTAL_human_readable`" \
583 "`$(CAT) $(BUILDTIMESDIR)/build_time_end_TOTAL_human_readable`" \
584 "`$(LS) $(BUILDTIMESDIR)/build_time_diff_* | $(GREP) -v _TOTAL | \
585 $(XARGS) $(CAT) | $(SORT) -k 2`" \
586 "`$(CAT) $(BUILDTIMESDIR)/build_time_diff_TOTAL`" \
587 $(BUILD_LOG_PIPE_SIMPLE)
588 endef
589
590 define ReportProfileTimes
591 $(if $(findstring true, $(LOG_PROFILE_TIMES_LOG)), \
592 [ ! -f $(BUILD_PROFILE_LOG) ] || \
593 { $(ECHO) Begin $(notdir $(BUILD_PROFILE_LOG)) && \
594 $(CAT) $(BUILD_PROFILE_LOG) && \
595 $(ECHO) End $(notdir $(BUILD_PROFILE_LOG)); \
596 } \
597 $(BUILD_LOG_PIPE_SIMPLE)
598 )
599 endef
600
601 endif # HAS_SPEC
602
603 # Look for a given option in the LOG variable, and if found, set a variable
604 # and remove the option from the LOG variable
605 # $1: The option to look for
606 # $2: The variable to set to "true" if the option is found
607 define ParseLogOption
608 ifneq ($$(findstring $1, $$(LOG)), )
609 override $2 := true
610 # First try to remove ",<option>" if it exists, otherwise just remove "<option>"
611 LOG_STRIPPED := $$(subst $1,, $$(subst $$(COMMA)$$(strip $1),, $$(LOG)))
612 # We might have ended up with a leading comma. Remove it. Need override
613 # since LOG is set from the command line.
614 override LOG := $$(strip $$(patsubst $$(COMMA)%, %, $$(LOG_STRIPPED)))
615 endif
616 endef
617
618 # Look for a given option with an assignment in the LOG variable, and if found,
619 # set a variable to that value and remove the option from the LOG variable
620 # $1: The option to look for
621 # $2: The variable to set to the value of the option, if found
622 define ParseLogValue
623 ifneq ($$(findstring $1=, $$(LOG)), )
624 # Make words of out comma-separated list and find the one with opt=val
625 value := $$(strip $$(subst $$(strip $1)=,, $$(filter $$(strip $1)=%, $$(subst $$(COMMA), , $$(LOG)))))
626 override $2 := $$(value)
627 # First try to remove ",<option>" if it exists, otherwise just remove "<option>"
628 LOG_STRIPPED := $$(subst $$(strip $1)=$$(value),, \
629 $$(subst $$(COMMA)$$(strip $1)=$$(value),, $$(LOG)))
630 # We might have ended up with a leading comma. Remove it. Need override
631 # since LOG is set from the command line.
632 override LOG := $$(strip $$(patsubst $$(COMMA)%, %, $$(LOG_STRIPPED)))
633 endif
634 endef
635
636
637 define ParseLogLevel
638 # Catch old-style VERBOSE= command lines.
639 ifneq ($$(origin VERBOSE), undefined)
640 $$(info Error: VERBOSE is deprecated. Use LOG=<warn|info|debug|trace> instead.)
641 $$(error Cannot continue)
642 endif
643
644 # Setup logging according to LOG
645
646 # If "nofile" is present, do not log to a file
647 $$(eval $$(call ParseLogOption, nofile, LOG_NOFILE))
648
649 # If "cmdline" is present, print all executes "important" command lines.
650 $$(eval $$(call ParseLogOption, cmdlines, LOG_CMDLINES))
651
652 # If "report" is present, use non-standard reporting options at build failure.
653 $$(eval $$(call ParseLogValue, report, LOG_REPORT))
654 ifneq ($$(LOG_REPORT), )
655 ifeq ($$(filter $$(LOG_REPORT), none all default), )
656 $$(info Error: LOG=report has invalid value: $$(LOG_REPORT).)
657 $$(info Valid values: LOG=report=<none>|<all>|<default>)
658 $$(error Cannot continue)
659 endif
660 endif
661
662 # If "profile-to-log" is present, write shell times in build log
663 $$(eval $$(call ParseLogOption, profile-to-log, LOG_PROFILE_TIMES_LOG))
664
665 # If "profile" is present, write shell times in separate log file
666 # IMPORTANT: $(ParseLogOption profile-to-log) should go first. Otherwise
667 # parsing of 'LOG=debug,profile-to-log,nofile' ends up in the following error:
668 # Error: LOG contains unknown option or log level: debug-to-log.
669 $$(eval $$(call ParseLogOption, profile, LOG_PROFILE_TIMES_FILE))
670
671 # Treat LOG=profile-to-log as if it were LOG=profile,profile-to-log
672 LOG_PROFILE_TIMES_FILE := $$(firstword $$(LOG_PROFILE_TIMES_FILE) $$(LOG_PROFILE_TIMES_LOG))
673
674 override LOG_LEVEL := $$(LOG)
675
676 ifeq ($$(LOG_LEVEL), )
677 # Set LOG to "warn" as default if not set
678 override LOG_LEVEL := warn
679 endif
680
681 ifeq ($$(LOG_LEVEL), warn)
682 override MAKE_LOG_FLAGS := -s
683 else ifeq ($$(LOG_LEVEL), info)
684 override MAKE_LOG_FLAGS := -s
685 else ifeq ($$(LOG_LEVEL), debug)
686 override MAKE_LOG_FLAGS :=
687 else ifeq ($$(LOG_LEVEL), trace)
688 override MAKE_LOG_FLAGS :=
689 else
690 $$(info Error: LOG contains unknown option or log level: $$(LOG).)
691 $$(info LOG can be <level>[,<opt>[...]] where <opt> is nofile | cmdlines | profile | profile-to-log)
692 $$(info and <level> is warn | info | debug | trace)
693 $$(error Cannot continue)
694 endif
695 endef
696
697 MAKE_LOG_VARS = $(foreach v, \
698 LOG_LEVEL LOG_NOFILE LOG_CMDLINES LOG_REPORT LOG_PROFILE_TIMES_LOG \
699 LOG_PROFILE_TIMES_FILE, \
700 $v=$($v) \
701 )
702
703 endif # _INITSUPPORT_GMK
--- EOF ---