a522d216b5
Reviewed-by: lucy, ihse
310 lines
12 KiB
Plaintext
310 lines
12 KiB
Plaintext
#
|
|
# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
|
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
#
|
|
# This code is free software; you can redistribute it and/or modify it
|
|
# under the terms of the GNU General Public License version 2 only, as
|
|
# published by the Free Software Foundation. Oracle designates this
|
|
# particular file as subject to the "Classpath" exception as provided
|
|
# by Oracle in the LICENSE file that accompanied this code.
|
|
#
|
|
# This code is distributed in the hope that it will be useful, but WITHOUT
|
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
# version 2 for more details (a copy is included in the LICENSE file that
|
|
# accompanied this code).
|
|
#
|
|
# You should have received a copy of the GNU General Public License version
|
|
# 2 along with this work; if not, write to the Free Software Foundation,
|
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
#
|
|
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
# or visit www.oracle.com if you need additional information or have any
|
|
# questions.
|
|
#
|
|
|
|
ifeq ($(_MAKEBASE_GMK), )
|
|
$(error You must include MakeBase.gmk prior to including FileUtils.gmk)
|
|
endif
|
|
|
|
################################################################################
|
|
#
|
|
# Common file utility functions
|
|
#
|
|
################################################################################
|
|
|
|
################################################################################
|
|
# Replace question marks with space in string. This macro needs to be called on
|
|
# files from FindFiles in case any of them contains space in their file name,
|
|
# since FindFiles replaces space with ?.
|
|
# Param 1 - String to replace in
|
|
DecodeSpace = \
|
|
$(subst ?,$(SPACE),$(strip $1))
|
|
|
|
EncodeSpace = \
|
|
$(subst $(SPACE),?,$(strip $1))
|
|
|
|
################################################################################
|
|
# Take two paths and return the path of the last common directory.
|
|
# Ex: /foo/bar/baz, /foo/bar/banan -> /foo/bar
|
|
# foo/bar/baz, /foo/bar -> <empty>
|
|
#
|
|
# The x prefix is used to preserve the presence of the initial slash
|
|
# On Windows paths are treated as case-insensitive
|
|
#
|
|
# $1 - Path to compare
|
|
# $2 - Other path to compare
|
|
FindCommonPathPrefix = \
|
|
$(call DecodeSpace,$(patsubst x%,%,$(subst $(SPACE),/,$(strip \
|
|
$(call FindCommonPathPrefixHelper1, \
|
|
$(subst /,$(SPACE),x$(call EncodeSpace,$(strip $1))), \
|
|
$(subst /,$(SPACE),x$(call EncodeSpace,$(strip $2)))) \
|
|
))))
|
|
|
|
FindCommonPathPrefixHelper1 = \
|
|
$(if $(filter $(OPENJDK_TARGET_OS), windows), \
|
|
$(call FindCommonPathPrefixHelper2,$(call uppercase,$1),$(call uppercase,$2),$1), \
|
|
$(call FindCommonPathPrefixHelper2,$1,$2,$1))
|
|
|
|
FindCommonPathPrefixHelper2 = \
|
|
$(if $(call equals, $(firstword $1), $(firstword $2)), \
|
|
$(if $(call equals, $(firstword $1),),, \
|
|
$(firstword $3) \
|
|
$(call FindCommonPathPrefixHelper2, \
|
|
$(wordlist 2, $(words $1), $1), \
|
|
$(wordlist 2, $(words $2), $2), \
|
|
$(wordlist 2, $(words $3), $3) \
|
|
) \
|
|
) \
|
|
)
|
|
|
|
# Computes the relative path from a directory to a file
|
|
# $1 - File to compute the relative path to
|
|
# $2 - Directory to compute the relative path from
|
|
RelativePath = \
|
|
$(call DecodeSpace,$(strip $(call RelativePathHelper,$(call EncodeSpace \
|
|
,$(strip $1)),$(call EncodeSpace \
|
|
,$(strip $2)),$(call EncodeSpace \
|
|
,$(call FindCommonPathPrefix,$1,$2)))))
|
|
|
|
RelativePathHelper = \
|
|
$(eval $3_prefix_length := $(words $(subst /,$(SPACE),$3))) \
|
|
$(eval $1_words := $(subst /,$(SPACE),$1)) \
|
|
$(eval $2_words := $(subst /,$(SPACE),$2)) \
|
|
$(if $(call equals,$($3_prefix_length),0),, \
|
|
$(eval $1_words := $(wordlist 2,$(words $($1_words)),$(wordlist \
|
|
$($3_prefix_length),$(words $($1_words)),$($1_words)))) \
|
|
$(eval $2_words := $(wordlist 2,$(words $($2_words)),$(wordlist \
|
|
$($3_prefix_length),$(words $($2_words)),$($2_words)))) \
|
|
) \
|
|
$(eval $1_suffix := $(subst $(SPACE),/,$($1_words))) \
|
|
$(eval $2_dotdots := $(subst $(SPACE),/,$(foreach d,$($2_words),..))) \
|
|
$(if $($1_suffix), \
|
|
$(if $($2_dotdots), $($2_dotdots)/$($1_suffix), $($1_suffix)), \
|
|
$(if $($2_dotdots), $($2_dotdots), .))
|
|
|
|
# Make directory for target file. Should handle spaces in filenames. Just
|
|
# calling $(call MakeDir $(@D)) will not work if the directory contains a space
|
|
# and the target file already exists. In that case, the target file will have
|
|
# its wildcard ? resolved and the $(@D) will evaluate each space separated dir
|
|
# part on its own.
|
|
MakeTargetDir = \
|
|
$(call MakeDir, $(dir $(call EncodeSpace, $@)))
|
|
|
|
################################################################################
|
|
# All install-file and related macros automatically call DecodeSpace when needed.
|
|
|
|
ifeq ($(call isTargetOs, macosx), true)
|
|
# On mac, extended attributes sometimes creep into the source files, which may later
|
|
# cause the creation of ._* files which confuses testing. Clear these with xattr if
|
|
# set. Some files get their write permissions removed after being copied to the
|
|
# output dir. When these are copied again to images, xattr would fail. By only clearing
|
|
# attributes when they are present, failing on this is avoided.
|
|
#
|
|
# If copying a soft link to a directory, need to delete the target first to avoid
|
|
# weird errors.
|
|
define install-file
|
|
$(call MakeTargetDir)
|
|
$(RM) '$(call DecodeSpace, $@)'
|
|
# Work around a weirdness with cp on Macosx. When copying a symlink, if
|
|
# the target of the link is write protected (e.g. 444), cp will add
|
|
# write permission for the user on the target file (644). Avoid this by
|
|
# using ln to create a new link instead.
|
|
if [ -h '$(call DecodeSpace, $<)' ]; then \
|
|
$(LN) -s "`$(READLINK) '$(call DecodeSpace, $<)'`" '$(call DecodeSpace, $@)'; \
|
|
else \
|
|
$(CP) -fRP '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'; \
|
|
fi
|
|
if [ -n "`$(XATTR) -ls '$(call DecodeSpace, $@)'`" ]; then \
|
|
$(CHMOD) -h u+w '$(call DecodeSpace, $@)'; \
|
|
$(XATTR) -cs '$(call DecodeSpace, $@)'; \
|
|
fi
|
|
endef
|
|
else
|
|
define install-file
|
|
$(call MakeTargetDir)
|
|
$(CP) -fP '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'
|
|
endef
|
|
endif
|
|
|
|
# Variant of install file that does not preserve symlinks
|
|
define install-file-nolink
|
|
$(call MakeTargetDir)
|
|
$(CP) -f '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'
|
|
endef
|
|
|
|
################################################################################
|
|
# link-file-* works similarly to install-file but creates a symlink instead.
|
|
# There are two versions, either creating a relative or an absolute link. Be
|
|
# careful when using this on Windows since the symlink created is only valid in
|
|
# the unix emulation environment.
|
|
# In msys2 we use mklink /J because its ln would perform a deep copy of the target.
|
|
# This inhibits performance and can lead to issues with long paths. With mklink /J
|
|
# relative linking does not work, so we handle the link as absolute path.
|
|
ifeq ($(OPENJDK_BUILD_OS_ENV), windows.msys2)
|
|
define link-file-relative
|
|
$(call MakeTargetDir)
|
|
$(RM) '$(call DecodeSpace, $@)'
|
|
cmd //c "mklink /J $(call FixPath, $(call DecodeSpace, $@)) $(call FixPath, $(call DecodeSpace, $<))"
|
|
endef
|
|
else
|
|
define link-file-relative
|
|
$(call MakeTargetDir)
|
|
$(RM) '$(call DecodeSpace, $@)'
|
|
$(LN) -s '$(call DecodeSpace, $(call RelativePath, $<, $(@D)))' '$(call DecodeSpace, $@)'
|
|
endef
|
|
endif
|
|
|
|
ifeq ($(OPENJDK_BUILD_OS_ENV), windows.msys2)
|
|
define link-file-absolute
|
|
$(call MakeTargetDir)
|
|
$(RM) '$(call DecodeSpace, $@)'
|
|
cmd //c "mklink /J $(call FixPath, $(call DecodeSpace, $@)) $(call FixPath, $(call DecodeSpace, $<))"
|
|
endef
|
|
else
|
|
define link-file-absolute
|
|
$(call MakeTargetDir)
|
|
$(RM) '$(call DecodeSpace, $@)'
|
|
$(LN) -s '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'
|
|
endef
|
|
endif
|
|
|
|
define copy-and-chmod-executable
|
|
$(install-file)
|
|
$(CHMOD) a+rx $@
|
|
endef
|
|
|
|
################################################################################
|
|
|
|
# Recursive wildcard function. Walks down directories recursively and matches
|
|
# files with the search patterns. Patterns use standard file wildcards (* and
|
|
# ?).
|
|
#
|
|
# $1 - Directories to start search in
|
|
# $2 - Search patterns
|
|
rwildcard = \
|
|
$(strip \
|
|
$(foreach d, \
|
|
$(patsubst %/,%,$(sort $(dir $(wildcard $(addsuffix /*/*, $(strip $1)))))), \
|
|
$(call rwildcard,$d,$2) \
|
|
) \
|
|
$(call DoubleDollar, $(wildcard $(foreach p, $2, $(addsuffix /$(strip $p), $(strip $1))))) \
|
|
)
|
|
|
|
# Find non directories using recursive wildcard function. This function may
|
|
# be used directly when a small amount of directories is expected to be
|
|
# searched and caching is not expected to be of use.
|
|
#
|
|
# $1 - Directory to start search in
|
|
# $2 - Optional search patterns, defaults to '*'.
|
|
WildcardFindFiles = \
|
|
$(sort $(strip \
|
|
$(eval WildcardFindFiles_result := $(call rwildcard,$(patsubst %/,%,$1),$(if $(strip $2),$2,*))) \
|
|
$(filter-out $(patsubst %/,%,$(sort $(dir $(WildcardFindFiles_result)))), \
|
|
$(WildcardFindFiles_result) \
|
|
) \
|
|
))
|
|
|
|
# Find non directories using the find utility in the shell. Safe to call for
|
|
# non existing directories, or directories containing wildcards.
|
|
#
|
|
# Files containing space will get spaces replaced with ? because GNU Make
|
|
# cannot handle lists of files with space in them. By using ?, make will match
|
|
# the wildcard to space in many situations so we don't need to replace back
|
|
# to space on every use. While not a complete solution it does allow some uses
|
|
# of FindFiles to function with spaces in file names, including for
|
|
# SetupCopyFiles. Unfortunately this does not work for WildcardFindFiles so
|
|
# if files with spaces are anticipated, use ShellFindFiles directly.
|
|
#
|
|
# $1 - Directories to start search in.
|
|
# $2 - Optional search patterns, empty means find everything. Patterns use
|
|
# standard file wildcards (* and ?) and should not be quoted.
|
|
# $3 - Optional options to find.
|
|
ShellFindFiles = \
|
|
$(if $(wildcard $1), \
|
|
$(sort \
|
|
$(shell $(FIND) $3 $(patsubst %/,%,$(wildcard $1)) \( -type f -o -type l \) \
|
|
$(if $(strip $2), -a \( -name "$(firstword $2)" \
|
|
$(foreach p, $(filter-out $(firstword $2), $2), -o -name "$(p)") \)) \
|
|
| $(TR) ' ' '?' \
|
|
) \
|
|
) \
|
|
)
|
|
|
|
# Find non directories using the method most likely to work best for the
|
|
# current build host
|
|
#
|
|
# $1 - Directory to start search in
|
|
# $2 - Optional search patterns, defaults to '*'.
|
|
ifeq ($(OPENJDK_BUILD_OS)-$(RWILDCARD_WORKS), windows-true)
|
|
DirectFindFiles = $(WildcardFindFiles)
|
|
else
|
|
DirectFindFiles = $(ShellFindFiles)
|
|
endif
|
|
|
|
# Finds files using a cache that is populated by FillFindCache below. If any of
|
|
# the directories given have not been cached, DirectFindFiles is used for
|
|
# everything. Caching is especially useful in Cygwin, where file finds are very
|
|
# costly.
|
|
#
|
|
# $1 - Directories to start search in.
|
|
# $2 - Optional search patterns. If used, no caching is done.
|
|
CacheFindFiles_CACHED_DIRS :=
|
|
CacheFindFiles_CACHED_FILES :=
|
|
CacheFindFiles = \
|
|
$(if $2, \
|
|
$(call DirectFindFiles, $1, $2) \
|
|
, \
|
|
$(if $(filter-out $(addsuffix /%, $(CacheFindFiles_CACHED_DIRS)) \
|
|
$(CacheFindFiles_CACHED_DIRS), $1), \
|
|
$(call DirectFindFiles, $1) \
|
|
, \
|
|
$(filter $(addsuffix /%,$(patsubst %/,%,$1)) $1,$(CacheFindFiles_CACHED_FILES)) \
|
|
) \
|
|
)
|
|
|
|
# Explicitly adds files to the find cache used by CacheFindFiles.
|
|
#
|
|
# $1 - Directories to start search in
|
|
FillFindCache = \
|
|
$(eval CacheFindFiles_NEW_DIRS := $$(filter-out $$(addsuffix /%, \
|
|
$$(CacheFindFiles_CACHED_DIRS)) $$(CacheFindFiles_CACHED_DIRS), $1)) \
|
|
$(if $(CacheFindFiles_NEW_DIRS), \
|
|
$(eval CacheFindFiles_CACHED_DIRS += $$(patsubst %/,%,$$(CacheFindFiles_NEW_DIRS))) \
|
|
$(eval CacheFindFiles_CACHED_FILES := $$(sort $$(CacheFindFiles_CACHED_FILES) \
|
|
$$(call DirectFindFiles, $$(CacheFindFiles_NEW_DIRS)))) \
|
|
)
|
|
|
|
# Findfiles is the default macro that should be used to find files in the file
|
|
# system. This function does not always support files with spaces in the names.
|
|
# If files with spaces are anticipated, use ShellFindFiles directly.
|
|
#
|
|
# $1 - Directories to start search in.
|
|
# $2 - Optional search patterns, empty means find everything. Patterns use
|
|
# standard file wildcards (* and ?) and should not be quoted.
|
|
ifeq ($(DISABLE_CACHE_FIND), true)
|
|
FindFiles = $(DirectFindFiles)
|
|
else
|
|
FindFiles = $(CacheFindFiles)
|
|
endif
|