1# 2# Copyright (c) 2011, 2020, 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# Setup common utility functions. 29# 30################################################################ 31 32ifndef _MAKEBASE_GMK 33_MAKEBASE_GMK := 1 34 35ifeq ($(wildcard $(SPEC)),) 36 $(error MakeBase.gmk needs SPEC set to a proper spec.gmk) 37endif 38 39# By defining this pseudo target, make will automatically remove targets 40# if their recipe fails so that a rebuild is automatically triggered on the 41# next make invocation. 42.DELETE_ON_ERROR: 43 44################################################################################ 45# Definitions for special characters 46################################################################################ 47 48# When calling macros, the spaces between arguments are 49# often semantically important! Sometimes we need to subst 50# spaces and commas, therefore we need the following macros. 51X:= 52SPACE:=$(X) $(X) 53COMMA:=, 54DOLLAR:=$$ 55HASH:=\# 56LEFT_PAREN:=( 57RIGHT_PAREN:=) 58SQUOTE:=' 59#' 60DQUOTE:=" 61#" 62define NEWLINE 63 64 65endef 66 67# Certain features only work in newer version of GNU Make. The build will still 68# function in 3.81, but will be less performant. 69ifeq (4.0, $(firstword $(sort 4.0 $(MAKE_VERSION)))) 70 HAS_FILE_FUNCTION := true 71 CORRECT_FUNCTION_IN_RECIPE_EVALUATION := true 72 RWILDCARD_WORKS := true 73endif 74 75 76# For convenience, MakeBase.gmk continues to include these separate files, at 77# least for now. 78 79include $(TOPDIR)/make/common/Utils.gmk 80include $(TOPDIR)/make/common/MakeIO.gmk 81include $(TOPDIR)/make/common/CopyFiles.gmk 82 83################################################################################ 84# Functions for timers 85################################################################################ 86 87# Store the build times in this directory. 88BUILDTIMESDIR=$(OUTPUTDIR)/make-support/build-times 89 90# Record starting time for build of a sub repository. 91define RecordStartTime 92 $(DATE) '+%Y %m %d %H %M %S' | $(NAWK) '{ print $$1,$$2,$$3,$$4,$$5,$$6,($$4*3600+$$5*60+$$6) }' > $(BUILDTIMESDIR)/build_time_start_$(strip $1) && \ 93 $(DATE) '+%Y-%m-%d %H:%M:%S' > $(BUILDTIMESDIR)/build_time_start_$(strip $1)_human_readable 94endef 95 96# Record ending time and calculate the difference and store it in a 97# easy to read format. Handles builds that cross midnight. Expects 98# that a build will never take 24 hours or more. 99define RecordEndTime 100 $(DATE) '+%Y %m %d %H %M %S' | $(NAWK) '{ print $$1,$$2,$$3,$$4,$$5,$$6,($$4*3600+$$5*60+$$6) }' > $(BUILDTIMESDIR)/build_time_end_$(strip $1) 101 $(DATE) '+%Y-%m-%d %H:%M:%S' > $(BUILDTIMESDIR)/build_time_end_$(strip $1)_human_readable 102 $(ECHO) `$(CAT) $(BUILDTIMESDIR)/build_time_start_$(strip $1)` `$(CAT) $(BUILDTIMESDIR)/build_time_end_$(strip $1)` $1 | \ 103 $(NAWK) '{ F=$$7; T=$$14; if (F > T) { T+=3600*24 }; D=T-F; H=int(D/3600); \ 104 M=int((D-H*3600)/60); S=D-H*3600-M*60; printf("%02d:%02d:%02d %s\n",H,M,S,$$15); }' \ 105 > $(BUILDTIMESDIR)/build_time_diff_$(strip $1) 106endef 107 108# Hook to be called when starting to execute a top-level target 109define TargetEnter 110 $(PRINTF) "## Starting $(patsubst %-only,%,$@)\n" 111 $(call RecordStartTime,$(patsubst %-only,%,$@)) 112endef 113 114# Hook to be called when finish executing a top-level target 115define TargetExit 116 $(call RecordEndTime,$(patsubst %-only,%,$@)) 117 $(PRINTF) "## Finished $(patsubst %-only,%,$@) (build time %s)\n\n" \ 118 "`$(CAT) $(BUILDTIMESDIR)/build_time_diff_$(patsubst %-only,%,$@) | $(CUT) -f 1 -d ' '`" 119endef 120 121################################################################################ 122 123# A file containing a way to uniquely identify the source code revision that 124# the build was created from 125SOURCE_REVISION_TRACKER := $(SUPPORT_OUTPUTDIR)/src-rev/source-revision-tracker 126 127# Locate all hg repositories included in the forest, as absolute paths 128FindAllReposAbs = \ 129 $(strip $(sort $(dir $(filter-out $(TOPDIR)/build/%, $(wildcard \ 130 $(addprefix $(TOPDIR)/, .hg */.hg */*/.hg */*/*/.hg */*/*/*/.hg) \ 131 $(addprefix $(TOPDIR)/, .git */.git */*/.git */*/*/.git */*/*/*/.git) \ 132 ))))) 133 134# Locate all hg repositories included in the forest, as relative paths 135FindAllReposRel = \ 136 $(strip $(subst $(TOPDIR)/,.,$(patsubst $(TOPDIR)/%/, %, $(FindAllReposAbs)))) 137 138################################################################################ 139 140define SetupLogging 141 ifeq ($$(LOG_PROFILE_TIMES_FILE), true) 142 ifeq ($$(IS_GNU_TIME), yes) 143 SHELL := $$(BASH) $$(TOPDIR)/make/scripts/shell-profiler.sh \ 144 gnutime $$(TIME) \ 145 $$(OUTPUTDIR)/build-profile.log $$(SHELL) 146 else ifneq ($$(FLOCK), ) 147 SHELL := $$(BASH) $$(TOPDIR)/make/scripts/shell-profiler.sh \ 148 flock $$(FLOCK) \ 149 $$(OUTPUTDIR)/build-profile.log $$(SHELL) 150 endif 151 endif 152 153 ifeq ($$(LOG_LEVEL), trace) 154 SHELL_NO_RECURSE := $$(SHELL) 155 # Shell redefinition trick inspired by http://www.cmcrossroads.com/ask-mr-make/6535-tracing-rule-execution-in-gnu-make 156 # For each target executed, will print 157 # Building <TARGET> (from <FIRST PREREQUISITE>) (<ALL NEWER PREREQUISITES> newer) 158 # but with a limit of 20 on <ALL NEWER PREREQUISITES>, to avoid cluttering logs too much 159 # (and causing a crash on Cygwin). 160 SHELL = $$(warning $$(if $$@,Building $$@,Running shell command) $$(if $$<, (from $$<))$$(if $$?, ($$(wordlist 1, 20, $$?) $$(if $$(wordlist 21, 22, $$?), ... [in total $$(words $$?) files]) newer)))$$(SHELL_NO_RECURSE) -x 161 endif 162 163 # The LOG_PREFIX is set for sub recursive calls like buildjdk and bootcycle. 164 # The warn level can never be turned off 165 LogWarn = $$(info $(LOG_PREFIX)$$(strip $$1)) 166 LOG_WARN := 167 ifneq ($$(findstring $$(LOG_LEVEL), info debug trace),) 168 LogInfo = $$(info $(LOG_PREFIX)$$(strip $$1)) 169 LOG_INFO := 170 else 171 LogInfo = 172 LOG_INFO := > /dev/null 173 endif 174 ifneq ($$(findstring $$(LOG_LEVEL), debug trace),) 175 LogDebug = $$(info $(LOG_PREFIX)$$(strip $$1)) 176 LOG_DEBUG := 177 else 178 LogDebug = 179 LOG_DEBUG := > /dev/null 180 endif 181 ifneq ($$(findstring $$(LOG_LEVEL), trace),) 182 LogTrace = $$(info $(LOG_PREFIX)$$(strip $$1)) 183 LOG_TRACE := 184 else 185 LogTrace = 186 LOG_TRACE := > /dev/null 187 endif 188endef 189 190# Make sure logging is setup for everyone that includes MakeBase.gmk. 191$(eval $(call SetupLogging)) 192 193################################################################################ 194 195MAX_PARAMS := 36 196PARAM_SEQUENCE := $(call sequence, 2, $(MAX_PARAMS)) 197 198# Template for creating a macro taking named parameters. To use it, assign the 199# template to a variable with the name you want for your macro, using '=' 200# assignment. Then define a macro body with the suffix "Body". The Body macro 201# should take 1 parameter which should be a unique string for that invocation 202# of the macro. 203# Ex: 204# SetupFoo = $(NamedParamsMacroTemplate) 205# define SetupFooBody 206# # do something 207# # access parameters as $$($1_BAR) 208# endef 209# Call it like this 210# $(eval $(call SetupFoo, BUILD_SOMETHING, \ 211# BAR := some parameter value, \ 212# )) 213define NamedParamsMacroTemplate 214 $(if $($(MAX_PARAMS)),$(error Internal makefile error: \ 215 Too many named arguments to macro, please update MAX_PARAMS in MakeBase.gmk)) 216 # Iterate over 2 3 4... and evaluate the named parameters with $1_ as prefix 217 $(foreach i,$(PARAM_SEQUENCE), $(if $(strip $($i)),\ 218 $(strip $1)_$(strip $(call EscapeHash, $(call DoubleDollar, $($i))))$(NEWLINE))) 219 # Debug print all named parameter names and values 220 $(if $(findstring $(LOG_LEVEL),debug trace), \ 221 $(info $0 $(strip $1) $(foreach i,$(PARAM_SEQUENCE), \ 222 $(if $(strip $($i)),$(NEWLINE) $(strip [$i] $(if $(filter $(LOG_LEVEL), trace), \ 223 $($i), $(wordlist 1, 20, $($(i))) $(if $(word 21, $($(i))), ...))))))) 224 225 $(if $(DEBUG_$(strip $1)), 226 $(info -------- <<< Begin expansion of $(strip $1)) \ 227 $(info $(call $(0)Body,$(strip $1))) \ 228 $(info -------- >>> End expansion of $(strip $1)) \ 229 ) 230 231 $(call $(0)Body,$(strip $1)) 232endef 233 234################################################################################ 235# Make directory without forking mkdir if not needed. 236# 237# If a directory with an encoded space is provided, the wildcard function 238# sometimes returns false answers (typically if the dir existed when the 239# makefile was parsed, but was deleted by a previous rule). In that case, always 240# call mkdir regardless of what wildcard says. 241# 242# 1: List of directories to create 243MakeDir = \ 244 $(strip \ 245 $(eval MakeDir_dirs_to_make := $(strip $(foreach d, $1, \ 246 $(if $(findstring ?, $d), '$(call DecodeSpace, $d)', \ 247 $(if $(wildcard $d), , $d) \ 248 ) \ 249 ))) \ 250 $(if $(MakeDir_dirs_to_make), $(shell $(MKDIR) -p $(MakeDir_dirs_to_make))) \ 251 ) 252 253# Make directory for target file. Should handle spaces in filenames. Just 254# calling $(call MakeDir $(@D)) will not work if the directory contains a space 255# and the target file already exists. In that case, the target file will have 256# its wildcard ? resolved and the $(@D) will evaluate each space separated dir 257# part on its own. 258MakeTargetDir = \ 259 $(call MakeDir, $(dir $(call EncodeSpace, $@))) 260 261################################################################################ 262# All install-file and related macros automatically call DecodeSpace when needed. 263 264ifeq ($(call isTargetOs, macosx), true) 265 # On mac, extended attributes sometimes creep into the source files, which may later 266 # cause the creation of ._* files which confuses testing. Clear these with xattr if 267 # set. Some files get their write permissions removed after being copied to the 268 # output dir. When these are copied again to images, xattr would fail. By only clearing 269 # attributes when they are present, failing on this is avoided. 270 # 271 # If copying a soft link to a directory, need to delete the target first to avoid 272 # weird errors. 273 define install-file 274 $(call MakeTargetDir) 275 $(RM) '$(call DecodeSpace, $@)' 276 # Work around a weirdness with cp on Macosx. When copying a symlink, if 277 # the target of the link is write protected (e.g. 444), cp will add 278 # write permission for the user on the target file (644). Avoid this by 279 # using ln to create a new link instead. 280 if [ -h '$(call DecodeSpace, $<)' ]; then \ 281 $(LN) -s "`$(READLINK) '$(call DecodeSpace, $<)'`" '$(call DecodeSpace, $@)'; \ 282 else \ 283 $(CP) -fRP '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'; \ 284 fi 285 if [ -n "`$(XATTR) -ls '$(call DecodeSpace, $@)'`" ]; then \ 286 $(XATTR) -cs '$(call DecodeSpace, $@)'; \ 287 fi 288 endef 289else 290 define install-file 291 $(call MakeTargetDir) 292 $(CP) -fP '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)' 293 endef 294endif 295 296# Variant of install file that does not preserve symlinks 297define install-file-nolink 298 $(call MakeTargetDir) 299 $(CP) -f '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)' 300endef 301 302################################################################################ 303# link-file-* works similarly to install-file but creates a symlink instead. 304# There are two versions, either creating a relative or an absolute link. Be 305# careful when using this on Windows since the symlink created is only valid in 306# the unix emulation environment. 307define link-file-relative 308 $(call MakeTargetDir) 309 $(RM) '$(call DecodeSpace, $@)' 310 $(LN) -s '$(call DecodeSpace, $(call RelativePath, $<, $(@D)))' '$(call DecodeSpace, $@)' 311endef 312 313define link-file-absolute 314 $(call MakeTargetDir) 315 $(RM) '$(call DecodeSpace, $@)' 316 $(LN) -s '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)' 317endef 318 319################################################################################ 320 321# Recursive wildcard function. Walks down directories recursively and matches 322# files with the search patterns. Patterns use standard file wildcards (* and 323# ?). 324# 325# $1 - Directories to start search in 326# $2 - Search patterns 327rwildcard = \ 328 $(strip \ 329 $(foreach d, \ 330 $(patsubst %/,%,$(sort $(dir $(wildcard $(addsuffix /*/*, $(strip $1)))))), \ 331 $(call rwildcard,$d,$2) \ 332 ) \ 333 $(call DoubleDollar, $(wildcard $(foreach p, $2, $(addsuffix /$(strip $p), $(strip $1))))) \ 334 ) 335 336# Find non directories using recursive wildcard function. This function may 337# be used directly when a small amount of directories is expected to be 338# searched and caching is not expected to be of use. 339# 340# $1 - Directory to start search in 341# $2 - Optional search patterns, defaults to '*'. 342WildcardFindFiles = \ 343 $(sort $(strip \ 344 $(eval WildcardFindFiles_result := $(call rwildcard,$(patsubst %/,%,$1),$(if $(strip $2),$2,*))) \ 345 $(filter-out $(patsubst %/,%,$(sort $(dir $(WildcardFindFiles_result)))), \ 346 $(WildcardFindFiles_result) \ 347 ) \ 348 )) 349 350# Find non directories using the find utility in the shell. Safe to call for 351# non existing directories, or directories containing wildcards. 352# 353# Files containing space will get spaces replaced with ? because GNU Make 354# cannot handle lists of files with space in them. By using ?, make will match 355# the wildcard to space in many situations so we don't need to replace back 356# to space on every use. While not a complete solution it does allow some uses 357# of FindFiles to function with spaces in file names, including for 358# SetupCopyFiles. Unfortunately this does not work for WildcardFindFiles so 359# if files with spaces are anticipated, use ShellFindFiles directly. 360# 361# $1 - Directories to start search in. 362# $2 - Optional search patterns, empty means find everything. Patterns use 363# standard file wildcards (* and ?) and should not be quoted. 364# $3 - Optional options to find. 365ShellFindFiles = \ 366 $(if $(wildcard $1), \ 367 $(sort \ 368 $(shell $(FIND) $3 $(patsubst %/,%,$(wildcard $1)) \( -type f -o -type l \) \ 369 $(if $(strip $2), -a \( -name "$(firstword $2)" \ 370 $(foreach p, $(filter-out $(firstword $2), $2), -o -name "$(p)") \)) \ 371 | $(TR) ' ' '?' \ 372 ) \ 373 ) \ 374 ) 375 376# Find non directories using the method most likely to work best for the 377# current build host 378# 379# $1 - Directory to start search in 380# $2 - Optional search patterns, defaults to '*'. 381ifeq ($(OPENJDK_BUILD_OS)-$(RWILDCARD_WORKS), windows-true) 382 DirectFindFiles = $(WildcardFindFiles) 383else 384 DirectFindFiles = $(ShellFindFiles) 385endif 386 387# Finds files using a cache that is populated by FillFindCache below. If any of 388# the directories given have not been cached, DirectFindFiles is used for 389# everything. Caching is especially useful in Cygwin, where file finds are very 390# costly. 391# 392# $1 - Directories to start search in. 393# $2 - Optional search patterns. If used, no caching is done. 394CacheFindFiles_CACHED_DIRS := 395CacheFindFiles_CACHED_FILES := 396CacheFindFiles = \ 397 $(if $2, \ 398 $(call DirectFindFiles, $1, $2) \ 399 , \ 400 $(if $(filter-out $(addsuffix /%, $(CacheFindFiles_CACHED_DIRS)) \ 401 $(CacheFindFiles_CACHED_DIRS), $1), \ 402 $(call DirectFindFiles, $1) \ 403 , \ 404 $(filter $(addsuffix /%,$(patsubst %/,%,$1)) $1,$(CacheFindFiles_CACHED_FILES)) \ 405 ) \ 406 ) 407 408# Explicitly adds files to the find cache used by CacheFindFiles. 409# 410# $1 - Directories to start search in 411FillFindCache = \ 412 $(eval CacheFindFiles_NEW_DIRS := $$(filter-out $$(addsuffix /%,\ 413 $$(CacheFindFiles_CACHED_DIRS)) $$(CacheFindFiles_CACHED_DIRS), $1)) \ 414 $(if $(CacheFindFiles_NEW_DIRS), \ 415 $(eval CacheFindFiles_CACHED_DIRS += $$(patsubst %/,%,$$(CacheFindFiles_NEW_DIRS))) \ 416 $(eval CacheFindFiles_CACHED_FILES := $$(sort $$(CacheFindFiles_CACHED_FILES) \ 417 $$(call DirectFindFiles, $$(CacheFindFiles_NEW_DIRS)))) \ 418 ) 419 420# Findfiles is the default macro that should be used to find files in the file 421# system. This function does not always support files with spaces in the names. 422# If files with spaces are anticipated, use ShellFindFiles directly. 423# 424# $1 - Directories to start search in. 425# $2 - Optional search patterns, empty means find everything. Patterns use 426# standard file wildcards (* and ?) and should not be quoted. 427ifeq ($(DISABLE_CACHE_FIND), true) 428 FindFiles = $(DirectFindFiles) 429else 430 FindFiles = $(CacheFindFiles) 431endif 432 433################################################################################ 434# FixPath 435# 436# On Windows, converts a path from cygwin/unix style (e.g. /bin/foo) into 437# "mixed mode" (e.g. c:/cygwin/bin/foo). On other platforms, return the path 438# unchanged. 439# This is normally not needed since we use the FIXPATH prefix for command lines, 440# but might be needed in certain circumstances. 441ifeq ($(call isTargetOs, windows), true) 442 ifeq ($(call isBuildOsEnv, windows.wsl), true) 443 FixPath = \ 444 $(shell $(WSLPATH) -m $1) 445 else 446 FixPath = \ 447 $(shell $(CYGPATH) -m $1) 448 endif 449else 450 FixPath = \ 451 $1 452endif 453 454################################################################################ 455# FixPathList 456# 457# On Windows, converts a cygwin/unix style path list (colon-separated) into 458# the native format (mixed mode, semicolon-separated). On other platforms, 459# return the path list unchanged. 460################################################################################ 461ifeq ($(call isTargetOs, windows), true) 462 FixPathList = \ 463 $(subst @,$(SPACE),$(subst $(SPACE),;,$(foreach entry,$(subst :,$(SPACE),\ 464 $(subst $(SPACE),@,$(strip $1))),$(call FixPath, $(entry))))) 465else 466 FixPathList = \ 467 $1 468endif 469 470################################################################################ 471# DependOnVariable 472# 473# This macro takes a variable name and puts the value in a file only if the 474# value has changed since last. The name of the file is returned. This can be 475# used to create rule dependencies on make variable values. The following 476# example would get rebuilt if the value of SOME_VAR was changed: 477# 478# path/to/some-file: $(call DependOnVariable, SOME_VAR) 479# echo $(SOME_VAR) > $@ 480# 481# Note that leading and trailing white space in the value is ignored. 482# 483 484# Defines the sub directory structure to store variable value file in 485DependOnVariableDirName = \ 486 $(strip $(addsuffix $(if $(MODULE),/$(MODULE)), \ 487 $(subst $(TOPDIR)/,, $(if $(filter /%, $(firstword $(MAKEFILE_LIST))), \ 488 $(firstword $(MAKEFILE_LIST)), \ 489 $(CURDIR)/$(firstword $(MAKEFILE_LIST)))))) 490 491# Defines the name of the file to store variable value in. Generates a name 492# unless parameter 2 is given. 493# Param 1 - Name of variable 494# Param 2 - (optional) name of file to store value in 495DependOnVariableFileName = \ 496 $(strip $(if $(strip $2), $2, \ 497 $(MAKESUPPORT_OUTPUTDIR)/vardeps/$(DependOnVariableDirName)/$(strip $1).vardeps)) 498 499# Does the actual work with parameters stripped. 500# If the file exists AND the contents is the same as the variable, do nothing 501# else print a new file. 502# Always returns the name of the file where the value was printed. 503# Param 1 - Name of variable 504# Param 2 - (optional) name of file to store value in 505DependOnVariableHelper = \ 506 $(strip \ 507 $(eval $1_filename := $(call DependOnVariableFileName, $1, $2)) \ 508 $(if $(wildcard $($1_filename)), $(eval include $($1_filename))) \ 509 $(if $(call equals, $(strip $($1)), $(strip $($1_old))),,\ 510 $(call MakeDir, $(dir $($1_filename))) \ 511 $(if $(findstring $(LOG_LEVEL), trace), \ 512 $(info NewVariable $1: >$(strip $($1))<) \ 513 $(info OldVariable $1: >$(strip $($1_old))<)) \ 514 $(call WriteFile, $1_old:=$(call DoubleDollar,$(call EscapeHash,$($1))), \ 515 $($1_filename))) \ 516 $($1_filename) \ 517 ) 518 519# Main macro 520# Param 1 - Name of variable 521# Param 2 - (optional) name of file to store value in 522DependOnVariable = \ 523 $(call DependOnVariableHelper,$(strip $1),$(strip $2)) 524 525# LogCmdlines is only intended to be used by ExecuteWithLog 526ifeq ($(LOG_CMDLINES), true) 527 LogCmdlines = $(info $(strip $1)) 528else 529 LogCmdlines = 530endif 531 532################################################################################ 533# ExecuteWithLog will run a command and log the output appropriately. This is 534# meant to be used by commands that do "real" work, like a compilation. 535# The output is stored in a specified log file, which is displayed at the end 536# of the build in case of failure. The command line itself is stored in a file, 537# and also logged to stdout if the LOG=cmdlines option has been given. 538# 539# NOTE: If the command redirects stdout, the caller needs to wrap it in a 540# subshell (by adding parentheses around it), otherwise the redirect to the 541# subshell tee process will create a race condition where the target file may 542# not be fully written when the make recipe is done. 543# 544# Param 1 - The path to base the name of the log file / command line file on 545# Param 2 - The command to run 546ExecuteWithLog = \ 547 $(call LogCmdlines, Executing: [$(strip $2)]) \ 548 $(call MakeDir, $(dir $(strip $1)) $(MAKESUPPORT_OUTPUTDIR)/failure-logs) \ 549 $(call WriteFile, $2, $(strip $1).cmdline) \ 550 ( $(RM) $(strip $1).log && $(strip $2) > >($(TEE) -a $(strip $1).log) 2> >($(TEE) -a $(strip $1).log >&2) || \ 551 ( exitcode=$(DOLLAR)? && \ 552 $(CP) $(strip $1).log $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst /,_,$(patsubst $(OUTPUTDIR)/%,%,$(strip $1))).log && \ 553 $(CP) $(strip $1).cmdline $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst /,_,$(patsubst $(OUTPUTDIR)/%,%,$(strip $1))).cmdline && \ 554 exit $(DOLLAR)exitcode ) ) 555 556################################################################################ 557 558# Hook to include the corresponding custom file, if present. 559$(eval $(call IncludeCustomExtension, common/MakeBase.gmk)) 560 561endif # _MAKEBASE_GMK 562