undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

114
make/common/CopyFiles.gmk Normal file
View file

@ -0,0 +1,114 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# Code for handling the SetupCopyFiles macro.
################################################################################
define AddFileToCopy
# Helper macro for SetupCopyFiles
# 1 : Source file
# 2 : Dest file
# 3 : Variable to add targets to
# 4 : Macro to call for copy operation
# 5 : Action text to log
$2: $1
$$(call LogInfo, $(strip $5) $$(patsubst $(OUTPUTDIR)/%,%,$$(call DecodeSpace, $$@)))
$$($$(strip $4))
$3 += $2
$3_SOURCES += $1
endef
# Returns the value of the first argument
identity = \
$(strip $1)
# Setup make rules for copying files, with an option to do more complex
# processing instead of copying.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# The list of all source files is returned in $1_SOURCES.
#
# Remaining parameters are named arguments. These include:
# SRC : Source root dir (defaults to dir of first file)
# DEST : Dest root dir
# FILES : List of files to copy with absolute paths, or path relative to SRC.
# Must be in SRC.
# FLATTEN : Set to flatten the directory structure in the DEST dir.
# MACRO : Optionally override the default macro used for making the copy.
# Default is 'install-file'
# NAME_MACRO : Optionally supply a macro that rewrites the target file name
# based on the source file name
# LOG_ACTION : Optionally specify a different action text for log messages
SetupCopyFiles = $(NamedParamsMacroTemplate)
define SetupCopyFilesBody
ifeq ($$($1_MACRO), )
$1_MACRO := install-file
endif
# Default SRC to the dir of the first file.
ifeq ($$($1_SRC), )
$1_SRC := $$(dir $$(firstword $$($1_FILES)))
endif
ifeq ($$($1_NAME_MACRO), )
$1_NAME_MACRO := identity
endif
ifeq ($$($1_LOG_ACTION), )
$1_LOG_ACTION := Copying
endif
# Remove any trailing slash from SRC and DEST
$1_SRC := $$(patsubst %/,%,$$($1_SRC))
$1_DEST := $$(patsubst %/,%,$$($1_DEST))
# Need to wrap arguments in DoubleDollar because of the eval nested inside an
# eval macro body.
$$(foreach f, $$(patsubst $$($1_SRC)/%,%,$$($1_FILES)), \
$$(eval $$(call AddFileToCopy, \
$$(call DoubleDollar, $$($1_SRC)/$$f), \
$$(call DoubleDollar, \
$$($1_DEST)/$$(call $$(strip $$($1_NAME_MACRO)),$$(if $$($1_FLATTEN),$$(notdir $$f),$$f)) \
), \
$1, \
$$($1_MACRO), \
$$($1_LOG_ACTION) \
)) \
)
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,58 @@
#
# Copyright (c) 2024, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# Common debuginfo utility functions
################################################################################
################################################################################
# Find native debuginfo files in a directory
#
# Param 1 - dir to find debuginfo files in
FindDebuginfoFiles = \
$(wildcard $(addprefix $1/*, $(DEBUGINFO_SUFFIXES)) \
$(addprefix $1/*/*, $(DEBUGINFO_SUFFIXES)) \
$(addprefix $1/*/*/*, $(DEBUGINFO_SUFFIXES)))
# Pick the correct debug info files to copy, either zipped or not.
ifeq ($(ZIP_EXTERNAL_DEBUG_SYMBOLS), true)
DEBUGINFO_SUFFIXES += .diz
else
DEBUGINFO_SUFFIXES := .debuginfo .pdb .map
# On Macosx, if debug symbols have not been zipped, find all files inside *.dSYM
# dirs.
ifeq ($(call isTargetOs, macosx), true)
$(call FillFindCache, \
$(SUPPORT_OUTPUTDIR)/modules_libs $(SUPPORT_OUTPUTDIR)/modules_cmds)
FindDebuginfoFiles = \
$(if $(wildcard $1), $(call containing, .dSYM/, $(call FindFiles, $1)))
endif
endif
endif # include guard
include MakeIncludeEnd.gmk

222
make/common/Execute.gmk Normal file
View file

@ -0,0 +1,222 @@
#
# Copyright (c) 2019, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# Code for handling the SetupExecute macro.
################################################################################
################################################################################
# Setup make rules for executing an arbitrary command.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# You need to specify a COMMAND, the actual command line to execute. You are
# strongly recommended to provide a INFO with the text to display for LOG=info
# on what operation is performed. You can use DEPS to provide additional
# dependencies for your command to run. You can optionally include a PRE_COMMAND
# and a POST_COMMAND, intended for simple pre- and post-processing. The latter
# might be e.g. a mv from a temporary file to the final destination, the former
# e.g. a simple sed replacement on the input file. If the operations are
# unrelated to the main COMMAND, this is not a suitable solution.
#
# Before execution, the current working directory is changed to SUPPORT_DIR.
# This can be overridden with WORKING_DIR.
#
# If your command outputs a variety of files, or if it's really a single file
# but you don't really care about the output from the perspective, you can just
# supply an OUTPUT_DIR. You are supposed to make sure the command creates files
# in this directory (which will be created for you if it does not exist), but
# this can't be enforced by SetupExecute. Additional support files (like logs
# and markers) are created in this directory. If you want support files in a
# separate directory (e.g. if you're targeting an OUTPUT_DIR in the image
# directly), you can specify a SUPPORT_DIR. If your command outputs only a
# single file, you can get rid of the marker files (but not the log files) by
# specifying OUTPUT_FILE. Note that if you specify an OUTPUT_FILE, support log
# files will be placed in the same directory as the OUTPUT_FILE. If you do not
# want that, use SUPPORT_DIR as well.
#
# After the call to SetupExecute, $1 will contain references to all generated
# files (that make knows about), and $1_TARGET will contain a reference to the
# final target (that is OUTPUT_FILE if it exists, or the $1_exec.marker file
# otherwise).
#
# All the above keep functioning as expected even if PRE_COMMAND and
# POST_COMMAND are given. One special case worth noting is that if OUTPUT_FILE
# and POST_COMMAND is both given, the actual OUTPUT_FILE is considered to be a
# result of running the POST_COMMAND.
#
# Remaining parameters are named arguments. These include:
# COMMAND : The command to execute
# PRE_COMMAND : A helper command to execute before COMMAND
# POST_COMMAND: A helper command to execute after COMMAND
# OUTPUT_DIR : The directory that will contain the result from the command
# OUTPUT_FILE : Use this if the command results in a single output file
# SUPPORT_DIR : Where to store generated support files
# WORKING_DIR : Directory to cd to before executing the command
# INFO : Message to display at LOG=info level when running command (optional)
# WARN : Message to display at LOG=warn level when running command (optional)
# DEPS : Dependencies for the execution to take place
# DRYRUN : Set to true to perform everything but executing the command \
# (defaults to false, primarily intended for debugging)
#
# Setup make rules for copying files, with an option to do more complex
SetupExecute = $(NamedParamsMacroTemplate)
define SetupExecuteBody
ifeq ($$($1_COMMAND), )
$$(error COMMAND is missing in SetupExecute $1)
endif
ifneq ($$($1_OUTPUT_FILE), )
ifneq ($$($1_OUTPUT_DIR), )
$$(error Cannot specify both OUTPUT_DIR and OUTPUT_FILE in SetupExecute $1)
endif
# We need to know output dir since we will make sure it is created.
$1_OUTPUT_DIR := $$(patsubst %/,%, $$(dir $$($1_OUTPUT_FILE)))
ifeq ($$($1_SUPPORT_DIR), )
# If support dir is not given, use base dir of output file.
$1_SUPPORT_DIR := $$($1_OUTPUT_DIR)
endif
else ifneq ($$($1_OUTPUT_DIR), )
ifeq ($$($1_SUPPORT_DIR), )
# If support dir is not given, use output dir.
$1_SUPPORT_DIR := $$($1_OUTPUT_DIR)
endif
else
$$(error OUTPUT_DIR or OUTPUT_FILE is required in SetupExecute $1)
endif
$1_BASE := $$($1_SUPPORT_DIR)/_$1
$1_PRE_MARKER := $$($1_BASE)_pre.marker
$1_EXEC_MARKER := $$($1_BASE)_exec.marker
$1_POST_MARKER := $$($1_BASE)_post.marker
ifeq ($$($1_OUTPUT_FILE), )
# No specified output file, use markers everywhere
$1_EXEC_RESULT := $$($1_EXEC_MARKER)
ifeq ($$($1_POST_COMMAND), )
$1_FINAL_RESULT := $$($1_EXEC_MARKER)
else
$1_FINAL_RESULT := $$($1_POST_MARKER)
endif
else
# If we have a single output file, we don't need a separate marker
ifeq ($$($1_POST_COMMAND), )
$1_EXEC_RESULT := $$($1_OUTPUT_FILE)
$1_FINAL_RESULT := $$($1_EXEC_RESULT)
else
$1_EXEC_RESULT := $$($1_EXEC_MARKER)
$1_FINAL_RESULT := $$($1_OUTPUT_FILE)
endif
endif
ifeq ($$($1_WORKING_DIR), )
$1_WORKING_DIR := $$($1_SUPPORT_DIR)
endif
ifeq ($$($1_INFO)$$($1_WARN), )
# If neither info nor warn is provided, add basic info text.
$1_INFO := Running commands for $1
endif
$1_VARDEPS := $$($1_COMMAND) $$($1_PRE_COMMAND) $$($1_POST_COMMAND)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_BASE)_exec.vardeps)
ifneq ($$($1_PRE_COMMAND), )
$$($1_PRE_MARKER): $$($1_DEPS) $$($1_VARDEPS_FILE)
ifneq ($$($1_WARN), )
$$(call LogWarn, $$($1_WARN))
endif
ifneq ($$($1_INFO), )
$$(call LogInfo, $$($1_INFO))
endif
$$(call MakeDir, $$(call EncodeSpace, $$($1_WORKING_DIR)) $$(call EncodeSpace, $$($1_SUPPORT_DIR)) $$(call EncodeSpace, $$($1_OUTPUT_DIR)))
$$(call ExecuteWithLog, $$($1_BASE)_pre, \
cd $$($1_WORKING_DIR) && $$($1_PRE_COMMAND))
$$(TOUCH) $$@
$$($1_EXEC_RESULT): $$($1_PRE_MARKER)
ifneq ($$($1_DRYRUN), true)
$$(call ExecuteWithLog, $$($1_BASE)_exec, \
cd $$($1_WORKING_DIR) && $$($1_COMMAND))
else
$$(call LogWarn, DRYRUN enabled for $1, not actually running command)
$$(TOUCH) $$@
endif
ifeq ($$($1_EXEC_RESULT), $$($1_EXEC_MARKER))
$$(TOUCH) $$@
endif
$1 := $$($1_PRE_MARKER) $$($1_EXEC_RESULT)
else
$$($1_EXEC_RESULT): $$($1_DEPS) $$($1_VARDEPS_FILE)
ifneq ($$($1_WARN), )
$$(call LogWarn, $$($1_WARN))
endif
ifneq ($$($1_INFO), )
$$(call LogInfo, $$($1_INFO))
endif
$$(call MakeDir, $$(call EncodeSpace, $$($1_WORKING_DIR)) $$(call EncodeSpace, $$($1_SUPPORT_DIR)) $$(call EncodeSpace, $$($1_OUTPUT_DIR)))
ifneq ($$($1_DRYRUN), true)
$$(call ExecuteWithLog, $$($1_BASE)_exec, \
cd $$($1_WORKING_DIR) && $$($1_COMMAND))
else
$$(call LogWarn, DRYRUN enabled for $1, not actually running command)
$$(TOUCH) $$@
endif
ifeq ($$($1_EXEC_RESULT), $$($1_EXEC_MARKER))
$$(TOUCH) $$@
endif
$1 := $$($1_EXEC_RESULT)
endif
ifneq ($$($1_POST_COMMAND), )
$$($1_FINAL_RESULT): $$($1_EXEC_RESULT)
$$(call ExecuteWithLog, $$($1_BASE)_post, \
cd $$($1_WORKING_DIR) && $$($1_POST_COMMAND))
$$(TOUCH) $$@
$1 += $$($1_FINAL_RESULT)
endif
# Export all our generated targets in $1, and the final target in $1_TARGET.
$1_TARGET := $$($1_FINAL_RESULT)
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

311
make/common/FileUtils.gmk Normal file
View file

@ -0,0 +1,311 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# 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
################################################################################
include MakeIncludeEnd.gmk
endif # include guard

100
make/common/FindTests.gmk Normal file
View file

@ -0,0 +1,100 @@
#
# Copyright (c) 2017, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# TEST_BASEDIRS might have been set by a custom extension
TEST_BASEDIRS += $(TOPDIR)/test $(TOPDIR)
# JTREG_TESTROOTS might have been set by a custom extension
JTREG_TESTROOTS += $(addprefix $(TOPDIR)/test/, hotspot/jtreg jdk langtools jaxp lib-test docs)
# Extract the names of the Jtreg group files from the TEST.ROOT files. The
# TEST.ROOT files being properties files can be interpreted as makefiles so
# use include to get at the contents instead of expensive shell calls. We are
# looking for the "groups" property in each file.
JTREG_ROOT_FILES := $(addsuffix /TEST.ROOT, $(JTREG_TESTROOTS))
JTREG_GROUP_FILES :=
$(foreach root, $(JTREG_TESTROOTS), \
$(if $(wildcard $(root)/TEST.ROOT), \
$(eval include $(root)/TEST.ROOT) \
$(eval $(root)_JTREG_GROUP_FILES := $$(addprefix $(root)/, $$(groups))) \
$(eval JTREG_GROUP_FILES += $$($(root)_JTREG_GROUP_FILES)) \
) \
)
# Cache the expensive to calculate test names in a generated makefile.
FIND_TESTS_CACHE_FILE := $(MAKESUPPORT_OUTPUTDIR)/find-tests.gmk
ifeq ($(GENERATE_FIND_TESTS_FILE), true)
# If this file is deemed outdated, it will automatically get regenerated
# by this rule before being included below.
$(FIND_TESTS_CACHE_FILE): $(JTREG_ROOT_FILES) $(JTREG_GROUP_FILES) \
$(TOPDIR)/test/make/TestMake.gmk
$(call MakeTargetDir)
( $(foreach root, $(JTREG_TESTROOTS), \
$(ECHO) ""; \
$(PRINTF) "\n%s_JTREG_TEST_GROUPS := " "$(root)"; \
$(SED) -n -e 's/^\#.*//g' -e 's/\([^ ]*\)\w*=.*/\1/gp' \
$($(root)_JTREG_GROUP_FILES) \
| $(SORT) -u | $(TR) '\n' ' ' ; \
) \
) > $@
$(ECHO) "" >> $@
$(PRINTF) "MAKE_TEST_TARGETS := " >> $@
$(MAKE) -s --no-print-directory $(MAKE_ARGS) \
SPEC=$(SPEC) -f $(TOPDIR)/test/make/TestMake.gmk print-targets \
TARGETS_FILE=$@
endif
-include $(FIND_TESTS_CACHE_FILE)
# Create a list of all available Jtreg test groups in all components
JTREG_TEST_GROUPS += $(sort $(foreach root, $(JTREG_TESTROOTS), \
$($(root)_JTREG_TEST_GROUPS)))
# Add Jtreg test groups to list of named tests (test groups, test list, etc)
# ALL_NAMED_TESTS might have been set by a custom extension
ALL_NAMED_TESTS += $(JTREG_TEST_GROUPS)
# Add the make test targets
ALL_NAMED_TESTS += $(addprefix make-, $(MAKE_TEST_TARGETS))
# Add Gtest
ALL_NAMED_TESTS += gtest
# Add microbenchmarks
ALL_NAMED_TESTS += micro
# Add special tests
ALL_NAMED_TESTS += failure-handler make
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

287
make/common/JarArchive.gmk Normal file
View file

@ -0,0 +1,287 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
include MakeIO.gmk
FALSE_FIND_PATTERN := -name FILE_NAME_THAT_DOESNT_EXIST
# Setup make rules for creating a jar archive.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# Remaining parameters are named arguments. These include:
# DEPENDENCIES List of dependencies for the jar target. If left empty,
# dependencies are calculated automatically from the source files found.
# For this to work, the source files must exist when the makefile is
# parsed.
# SRCS List of directories in where to find files to add to archive
# BIN Directory where to store build control files
# SUFFIXES File suffixes to include in jar
# INCLUDES List of directories/packages in SRCS that should be included
# EXCLUDES List of directories/packages in SRCS that should be excluded
# EXCLUDE_FILES List of files in SRCS that should be excluded
# EXTRA_FILES List of files in SRCS that should be included regardless of suffix match.
# JAR Jar file to create
# MANIFEST Optional manifest file template.
# JARMAIN Optional main class to add to manifest
# JARINDEX true means generate the index in the jar file.
# SKIP_METAINF Set to prevent contents of an META-INF directory to be automatically
# added to the archive.
# EXTRA_MANIFEST_ATTR Extra attribute to add to manifest.
# CHECK_COMPRESS_JAR Check the COMPRESS_JAR variable
# JAR_CMD Optionally override the jar command to use when creating the archive.
SetupJarArchive = $(NamedParamsMacroTemplate)
define SetupJarArchiveBody
$1_JARMAIN := $(strip $$($1_JARMAIN))
$1_JARNAME := $$(notdir $$($1_JAR))
$1_JAR_OUTPUT_DIR := $$(patsubst %/, %, $$(dir $$($1_JAR)))
$$(call SetIfEmpty, $1_BIN, $$($1_JAR_OUTPUT_DIR))
$1_MANIFEST_FILE := $$($1_BIN)/_the.$$($1_JARNAME)_manifest
$1_DELETESS_FILE := $$($1_BIN)/_the.$$($1_JARNAME)_deletess
$1_DELETES_FILE := $$($1_BIN)/_the.$$($1_JARNAME)_deletes
$$(call SetIfEmpty, $1_JAR_CMD, $$(JAR))
ifeq ($$($1_SUFFIXES), )
# No suffix was set, default to classes.
$1_SUFFIXES := .class
endif
# Convert suffixes to a find expression
$1_FIND_PATTERNS := $(FALSE_FIND_PATTERN) $$(patsubst %,$(SPACE)-o$(SPACE)-name$(SPACE)$(DQUOTE)*%$(DQUOTE),$$($1_SUFFIXES))
# On windows, a lot of includes/excludes risk making the command line too long, so
# writing the grep patterns to files.
# Grep returns 1 if nothing is matched. Do not fail the build for this.
ifneq ($$($1_INCLUDES), )
$1_GREP_INCLUDE_PATTERNS := $$(call EscapeDollar, \
$$(foreach src,$$($1_SRCS), $$(addprefix $$(src)/,$$($1_INCLUDES))))
# If there are a lot of include patterns, output to file to shorten command lines
ifeq ($$(word 20, $$($1_GREP_INCLUDE_PATTERNS)), )
$1_GREP_INCLUDES := | ( $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS)) \
|| test "$$$$?" = "1" )
else
$1_GREP_INCLUDE_OUTPUT = \
$$(eval $$(call ListPathsSafely, $1_GREP_INCLUDE_PATTERNS, \
$$($1_BIN)/_the.$$($1_JARNAME)_include))
$1_GREP_INCLUDES := | ( $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include \
|| test "$$$$?" = "1" )
endif
endif
ifneq ($$($1_EXCLUDES)$$($1_EXCLUDE_FILES), )
$1_GREP_EXCLUDE_PATTERNS := $$(call EscapeDollar, \
$$(foreach src, $$($1_SRCS), $$(addprefix $$(src)/, \
$$($1_EXCLUDES) $$($1_EXCLUDE_FILES))))
# If there are a lot of include patterns, output to file to shorten command lines
ifeq ($$(word 20, $$($1_GREP_EXCLUDE_PATTERNS)), )
$1_GREP_EXCLUDES := | ( $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS)) \
|| test "$$$$?" = "1" )
else
$1_GREP_EXCLUDE_OUTPUT = \
$$(eval $$(call ListPathsSafely, $1_GREP_EXCLUDE_PATTERNS, \
$$($1_BIN)/_the.$$($1_JARNAME)_exclude))
$1_GREP_EXCLUDES := | ( $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude \
|| test "$$$$?" = "1" )
endif
endif
# Check if this jar needs to have its index generated.
ifneq ($$($1_JARINDEX), )
$1_JARINDEX = (cd $$(dir $$@) && $$($1_JAR_CMD) -i $$(notdir $$@))
else
$1_JARINDEX = true
endif
# When this macro is run in the same makefile as the java compilation, dependencies are
# transferred in make variables. When the macro is run in a different makefile than the
# java compilation, the dependencies need to be found in the filesystem.
$1_ORIG_DEPS := $$($1_DEPENDENCIES)
ifeq ($$($1_DEPENDENCIES), )
# Add all source roots to the find cache since we are likely going to run find
# on these more than once. The cache will only be updated if necessary.
$$(call FillFindCache, $$($1_FIND_LIST))
$1_DEPENDENCIES := $$(filter $$(addprefix %, $$($1_SUFFIXES)), \
$$(call FindFiles, $$($1_SRCS)))
ifneq ($$($1_GREP_INCLUDE_PATTERNS), )
$1_DEPENDENCIES := $$(filter $$(addsuffix %, $$($1_GREP_INCLUDE_PATTERNS)), $$($1_DEPENDENCIES))
endif
ifneq ($$($1_GREP_EXCLUDE_PATTERNS), )
$1_DEPENDENCIES := $$(filter-out $$(addsuffix %, $$($1_GREP_EXCLUDE_PATTERNS)), $$($1_DEPENDENCIES))
endif
# Look for EXTRA_FILES in all SRCS dirs and as absolute paths.
$1_DEPENDENCIES += $$(wildcard $$(foreach src, $$($1_SRCS), \
$$(addprefix $$(src)/, $$($1_EXTRA_FILES))) $$($1_EXTRA_FILES))
ifeq ($$($1_SKIP_METAINF), )
$1_DEPENDENCIES += $$(call FindFiles, $$(wildcard $$(addsuffix /META-INF, $$($1_SRCS))))
endif
endif
# The dependency list should never be empty
ifeq ($$(strip $$($1_DEPENDENCIES)), )
$$(warning No dependencies found for $1)
endif
# Utility macros, to make the shell script receipt somewhat easier to decipher.
# Capture extra files is the same for both CAPTURE_CONTENTS and SCAPTURE_CONTENTS so
# only define it once to avoid duplication.
# The list of extra files might be long, so need to use ListPathsSafely to print
# them out to a separate file. Then process the contents of that file to rewrite
# into -C <dir> <file> lines.
# The EXTRA_FILES_RESOLVED variable must be set in the macro so that it's evaluated
# in the recipe when the files are guaranteed to exist.
$1_CAPTURE_EXTRA_FILES = \
$$(eval $1_EXTRA_FILES_RESOLVED := $$(call DoubleDollar, \
$$(wildcard $$(foreach src, $$($1_SRCS), \
$$(addprefix $$(src)/, $$($1_EXTRA_FILES))) $$($1_EXTRA_FILES)))) \
$$(if $$($1_EXTRA_FILES_RESOLVED), \
$$(eval $$(call ListPathsSafely, $1_EXTRA_FILES_RESOLVED, \
$$($1_BIN)/_the.$$($1_JARNAME)_contents.extra)) \
$(SED) $$(foreach src, $$($1_SRCS), -e 's|$$(src)/|-C $$(src) |g') \
$$($1_BIN)/_the.$$($1_JARNAME)_contents.extra \
>> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE))
# The capture contents macro finds all files (matching the patterns, typically
# .class and .prp) that are newer than the jar-file, ie the new content to be put into the jar.
# NOTICE: please leave the parentheses space separated otherwise the AIX build will break!
$1_CAPTURE_CONTENTS = \
$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) \
$$(foreach src, $$($1_SRCS), \
$(FIND) $$(src) -type f -a \( $$($1_FIND_PATTERNS) \) -a -newer $$@ $$($1_GREP_INCLUDES) \
$$($1_GREP_EXCLUDES) | $(SED) 's|$$(src)/|-C $$(src) |g' \
>> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)) \
$$($1_CAPTURE_EXTRA_FILES)
# The capture metainf macro finds all files below the META-INF directory that are newer than the jar-file.
# Find returns non zero if the META-INF dir does not exist, ignore this.
ifeq ($$($1_SKIP_METAINF), )
$1_CAPTURE_METAINF = $$(foreach src, $$($1_SRCS), \
( ( $(FIND) $$(src)/META-INF -type f -a -newer $$@ 2> /dev/null || true ) \
| $(SED) 's|$$(src)/|-C $$(src) |g' >> \
$$($1_BIN)/_the.$$($1_JARNAME)_contents ) $$(NEWLINE) )
endif
# The capture deletes macro finds all deleted files and concatenates them. The resulting file
# tells us what to remove from the jar-file.
$1_CAPTURE_DELETES = $$(foreach src, $$($1_SRCS), ($(FIND) $$(src) -name _the.package.deleted -newer $$@ \
-exec $(SED) 's|$$(src)||g' \{\} >> $$($1_DELETES_FILE) \;) $$(NEWLINE))
# The update contents macro updates the jar file with the previously capture contents.
# Use 'wc -w' to see if the contents file is empty.
$1_UPDATE_CONTENTS = \
if [ "`$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'`" -gt "0" ]; then \
$(ECHO) " updating" `$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'` files && \
$(SORT) $$($1_BIN)/_the.$$($1_JARNAME)_contents > $$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted && \
$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted; \
fi $$(NEWLINE)
# The s-variants of the above macros are used when the jar is created from scratch.
# NOTICE: please leave the parentheses space separated otherwise the AIX build will break!
$1_SCAPTURE_CONTENTS = \
$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) \
$$(foreach src, $$($1_SRCS), \
$(FIND) $$(src) -type f -a \( $$($1_FIND_PATTERNS) \) $$($1_GREP_INCLUDES) \
$$($1_GREP_EXCLUDES) | $(SED) 's|$$(src)/|-C $$(src) |g' \
>> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)) \
$$($1_CAPTURE_EXTRA_FILES)
# Find returns non zero if the META-INF dir does not exist, ignore this.
ifeq ($$($1_SKIP_METAINF), )
$1_SCAPTURE_METAINF = $$(foreach src, $$($1_SRCS), \
( ( $(FIND) $$(src)/META-INF -type f 2> /dev/null || true ) \
| $(SED) 's|$$(src)/|-C $$(src) |g' >> \
$$($1_BIN)/_the.$$($1_JARNAME)_contents) $$(NEWLINE) )
endif
$1_SUPDATE_CONTENTS = \
$(SORT) $$($1_BIN)/_the.$$($1_JARNAME)_contents > $$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted && \
$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted $$(NEWLINE)
# Use a slightly shorter name for logging, but with enough path to identify this jar.
$1_NAME := $$(subst $$(OUTPUTDIR)/,,$$($1_JAR))
# If reproducible build and the boot jdk jar supports --date option
# then specify the --date using SOURCE_DATE in ISO-8601
$1_JAR_OPTIONS :=
ifeq ($$(BOOT_JDK_JAR_SUPPORTS_DATE), true)
$1_JAR_OPTIONS += --date $(SOURCE_DATE_ISO_8601)
endif
ifneq ($$($1_CHECK_COMPRESS_JAR), )
ifneq ($(COMPRESS_JARS), true)
$1_JAR_OPTIONS += --no-compress
endif
endif
# Include all variables of significance in the vardeps file
$1_VARDEPS := $$($1_JAR_CMD) $$($1_JAR_OPTIONS) $$($1_MANIFEST) \
$$($1_JARMAIN) $$($1_EXTRA_MANIFEST_ATTR) $$($1_ORIG_DEPS) $$($1_SRCS) \
$$($1_INCLUDES) $$($1_EXCLUDES) $$($1_EXCLUDE_FILES) $$($1_EXTRA_FILES)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_BIN)/_the.$$($1_JARNAME).vardeps)
# Here is the rule that creates/updates the jar file.
$$($1_JAR) : $$($1_DEPENDENCIES) $$($1_MANIFEST) $$($1_VARDEPS_FILE)
$$(call MakeTargetDir)
$$(call MakeDir, $$($1_BIN))
$$($1_GREP_INCLUDE_OUTPUT)
$$($1_GREP_EXCLUDE_OUTPUT)
# If the vardeps file is part of the newer prereq list, it means that
# either the jar file does not exist, or we need to recreate it from
# from scratch anyway since a simple update will not catch all the
# potential changes.
$$(if $$(filter $$($1_VARDEPS_FILE) $$($1_MANIFEST), $$?), \
$$(if $$($1_MANIFEST), \
$(CP) $$($1_MANIFEST) $$($1_MANIFEST_FILE) $$(NEWLINE) \
, \
$(RM) $$($1_MANIFEST_FILE) && $(TOUCH) $$($1_MANIFEST_FILE) $$(NEWLINE)) \
$$(if $$($1_JARMAIN), \
$(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
$$(if $$($1_EXTRA_MANIFEST_ATTR), \
$(ECHO) "$$($1_EXTRA_MANIFEST_ATTR)" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
$(ECHO) Creating $$($1_NAME) $$(NEWLINE) \
$$($1_JAR_CMD) --create $$($1_JAR_OPTIONS) --file $$@ --manifest $$($1_MANIFEST_FILE) $$(NEWLINE) \
$$($1_SCAPTURE_CONTENTS) \
$$($1_SCAPTURE_METAINF) \
$$($1_SUPDATE_CONTENTS) \
$$($1_JARINDEX) && true \
, \
$(ECHO) Modifying $$($1_NAME) $$(NEWLINE) \
$$($1_CAPTURE_CONTENTS) \
$$($1_CAPTURE_METAINF) \
$(RM) $$($1_DELETES_FILE) $$(NEWLINE) \
$$($1_CAPTURE_DELETES) \
$(CAT) $$($1_DELETES_FILE) > $$($1_DELETESS_FILE) $$(NEWLINE) \
if [ -s $$($1_DELETESS_FILE) ]; then \
$(ECHO) " deleting" `$(WC) -l $$($1_DELETESS_FILE) | $(AWK) '{ print $$$$1 }'` files && \
$(ZIPEXE) -q -d $$@ `$(CAT) $$($1_DELETESS_FILE)` ; \
fi $$(NEWLINE) \
$$($1_UPDATE_CONTENTS) true $$(NEWLINE) \
$$($1_JARINDEX) && true )
# Add jar to target list
$1 += $$($1_JAR)
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,568 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
include MakeIO.gmk
# Java compilation needs SetupJarArchive if we're generating a jar file
include JarArchive.gmk
###
### Definitions for common release targets
###
# Create classes that can run on the bootjdk
# -Xlint:-options is added to avoid the warning
# "system modules path not set in conjunction with -source"
TARGET_RELEASE_BOOTJDK := -source $(OLDEST_BOOT_JDK_VERSION) \
-target $(OLDEST_BOOT_JDK_VERSION) -Xlint:-options
# Create classes that can be used in (or be a part of) the new jdk we're
# building
TARGET_RELEASE_NEWJDK := -source $(JDK_SOURCE_TARGET_VERSION) \
-target $(JDK_SOURCE_TARGET_VERSION)
# Create classes that can be used in JDK 8, for legacy support
TARGET_RELEASE_JDK8 := --release 8
# Create classes for the new jdk, relying only on the modules of the new jdk
TARGET_RELEASE_NEWJDK_UPGRADED := $(TARGET_RELEASE_NEWJDK) \
--upgrade-module-path $(JDK_OUTPUTDIR)/modules --system none
define add_file_to_copy
# param 1 = BUILD_MYPACKAGE
# parma 2 = The source file to copy.
$2_TARGET := $2
# Remove the source prefix.
$$(foreach i, $$($1_SRC), $$(eval $$(call remove_string,$$i,$2_TARGET)))
# To allow for automatic overrides, do not create a rule for a target file that
# already has one
ifneq ($$($1_COPY_$$($2_TARGET)), 1)
$1_COPY_$$($2_TARGET) := 1
# Now we can setup the dependency that will trigger the copying.
$$($1_BIN)$$($1_MODULE_SUBDIR)$$($2_TARGET) : $2
$$(call LogInfo, Copying $$(patsubst $$(OUTPUTDIR)/%,%, $$@))
$$(install-file)
$(CHMOD) -f ug+w $$@
# And do not forget this target
$1_ALL_COPY_TARGETS += $$($1_BIN)$$($1_MODULE_SUBDIR)$$($2_TARGET)
endif
endef
# This macro is used only for properties files that are to be
# copied over to the classes directory in cleaned form.
#
# An empty echo ensures that the input to sed always ends with a newline.
# Certain implementations (e.g. Solaris) will skip the last line without
# it.
#
# The sed expression does this:
# 1. Add a backslash before any :, = or ! that do not have a backslash already.
# 2. Delete all lines starting with #.
# 3. Delete empty lines.
# 4. Append lines ending with \ with the next line.
# 5. Remove leading and trailing white space. Note that tabs must be explicit
# as sed on macosx does not understand '\t'.
# 6. Replace the first \= with just =.
# 7. Finally it's all sorted to create a stable output.
#
# It is assumed that = is the character used for separating names and values.
define add_file_to_clean
# param 1 = BUILD_MYPACKAGE
# parma 2 = The source file to copy and clean.
$2_TARGET := $2
# Remove the source prefix.
$$(foreach i, $$($1_SRC), $$(eval $$(call remove_string,$$i,$2_TARGET)))
# Now we can setup the dependency that will trigger the copying.
# To allow for automatic overrides, do not create a rule for a target file that
# already has one
ifneq ($$($1_CLEAN_$$($2_TARGET)), 1)
$1_CLEAN_$$($2_TARGET) := 1
$$($1_BIN)$$($1_MODULE_SUBDIR)$$($2_TARGET) : $2
$$(call LogInfo, Cleaning $$(patsubst $$(OUTPUTDIR)/%,%, $$@))
$$(call MakeTargetDir)
( $(CAT) $$< && $(ECHO) "" ) \
| $(SED) -e 's/\([^\\]\):/\1\\:/g' -e 's/\([^\\]\)=/\1\\=/g' \
-e 's/\([^\\]\)!/\1\\!/g' -e 's/^[ ]*#.*/#/g' \
| $(SED) -e '/^#/d' -e '/^$$$$/d' \
-e :a -e '/\\$$$$/N; s/\\\n//; ta' \
-e 's/^[ ]*//;s/[ ]*$$$$//' \
-e 's/\\=/=/' \
| $(SORT) > $$@
$(CHMOD) -f ug+w $$@
# And do not forget this target
$1_ALL_COPY_CLEAN_TARGETS += $$($1_BIN)$$($1_MODULE_SUBDIR)$$($2_TARGET)
endif
endef
define remove_string
$2 := $$(subst $1,,$$($2))
endef
# Setup make rules for compiling Java source code to class files and/or a
# resulting jar file.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# The target for public API digest is returned in $1_API_TARGET.
#
# Remaining parameters are named arguments. These include:
# SMALL_JAVA set to false to run javac as a "big" java app
# COMPILER bootjdk or interim, the latter is default
# TARGET_RELEASE javac flags to set the targeted jdk release (-source/-target or --release)
# Defaults to $(TARGET_RELEASE_NEWJDK).
# JAVAC_FLAGS javac flags to append to the default ones.
# JAVA_FLAGS flags to be appended to the java launching the compiler
# DISABLED_WARNINGS list of Xlint warnings that should be disabled
# SRC one or more directories to search for sources. The order of the source roots
# is significant. The first found file of a certain name has priority.
# BIN store classes here
# MODULE Name of module being compiled. If set, classes are put in BIN/MODULE.
# CLASSPATH a list of additional entries to set as classpath to javac
# INCLUDES myapp.foo means will only compile java files in myapp.foo or any of its sub-packages.
# EXCLUDES myapp.foo means will do not compile java files in myapp.foo or any of its sub-packages.
# COPY .prp means copy all prp files to the corresponding package in BIN.
# COPY_FILES myapp/foo/setting.txt means copy this file over to the package myapp/foo
# CLEAN .properties means copy and clean all properties file to the corresponding package in BIN.
# CLEAN_FILES myapp/foo/setting.txt means clean this file over to the package myapp/foo
# INCLUDE_FILES "com/sun/SolarisFoobar.java" means only compile this file!
# EXCLUDE_FILES "com/sun/SolarisFoobar.java" means do not compile this particular file!
# "SolarisFoobar.java" means do not compile SolarisFoobar, wherever it is found.
# EXCLUDE_PATTERNS Exclude files matching any of these substrings
# EXTRA_FILES List of extra source files to include in compilation. Can be used to
# specify files that need to be generated by other rules first.
# HEADERS path to directory where all generated c-headers are written.
# DEPENDS Extra dependency
# KEEP_DUPS Do not remove duplicate file names from different source roots.
# FAIL_NO_SRC Set to false to not fail the build if no source files are found,
# default is true.
# CREATE_API_DIGEST Set to true to use a javac plugin to generate a public API
# hash which can be used for down stream dependencies to only rebuild
# when the API changes.
# KEEP_ALL_TRANSLATIONS Set to true to skip translation filtering
SetupJavaCompilation = $(NamedParamsMacroTemplate)
define SetupJavaCompilationBody
# Verify arguments
ifeq ($$($1_BIN), )
$$(error Must specify BIN (in $1))
endif
ifneq ($$($1_MODULE), )
$1_MODULE_SUBDIR := /$$($1_MODULE)
endif
$1_SAFE_NAME := $$(strip $$(subst /,_, $1))
ifeq ($$($1_LOG_ACTION), )
$1_LOG_ACTION := Compiling
endif
ifeq ($$($1_SMALL_JAVA), )
# If unspecified, default to true
$1_SMALL_JAVA := true
endif
ifeq ($$($1_COMPILER), )
# If unspecified, default to interim compiler
$1_COMPILER := interim
endif
ifeq ($$($1_COMPILER), bootjdk)
# Javac server is not available when using the bootjdk compiler.
$1_JAVAC_CMD := $$(JAVAC) -J$$(JAVA_FLAGS_TMPDIR)
ifeq ($$($1_SMALL_JAVA), true)
$1_FLAGS += $$(addprefix -J, $$(JAVA_FLAGS_SMALL))
endif
ifeq ($$($1_JAVA_FLAGS), true)
$1_FLAGS += $$(addprefix -J, $$($1_JAVA_FLAGS))
endif
ifeq ($$($1_TARGET_RELEASE), )
# If unspecified, default to the new jdk we're building
$1_TARGET_RELEASE := $$(TARGET_RELEASE_BOOTJDK)
endif
else ifeq ($$($1_COMPILER), buildjdk)
$1_JAVAC_CMD := $$(BUILD_JAVAC) -J$$(JAVA_FLAGS_TMPDIR)
ifeq ($$($1_TARGET_RELEASE), )
# If unspecified, default to the new jdk we're building
$1_TARGET_RELEASE := $$(TARGET_RELEASE_NEWJDK)
endif
else ifeq ($$($1_COMPILER), interim)
# Use java server if it is enabled, and the user does not want a specialized
# class path.
ifeq ($$(ENABLE_JAVAC_SERVER)+$$($1_CLASSPATH), true+)
# Create a configuration file with the needed information for the javac
# server to function properly.
$1_JAVAC_SERVER_CONFIG := $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$$($1_SAFE_NAME)-javacserver.conf
# Arguments needed to launch the javacserver client, as well as for the
# client to launch the server.
$1_JAVAC_SERVER_ARGS := $$(INTERIM_LANGTOOLS_ARGS) \
-cp $(BUILDTOOLS_OUTPUTDIR)/langtools_javacserver_classes
# The portfile contains the tcp/ip on which the server listens
# and the cookie necessary to talk to the server.
$1_JAVAC_PORT_FILE := $$(call FixPath, $$(JAVAC_SERVER_DIR)/server.port)
# The javacmd tells the client how to run java to launch the server.
$1_JAVAC_SERVER_JAVA_CMD := $$(call FixPath, $$(JAVA) $$($1_JAVA_FLAGS) \
$$($1_JAVAC_SERVER_ARGS))
$1_CONFIG_VARDEPS := $$($1_JAVAC_PORT_FILE) $$($1_JAVAC_SERVER_JAVA_CMD)
$1_CONFIG_VARDEPS_FILE := $$(call DependOnVariable, $1_CONFIG_VARDEPS, \
$$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1.config_vardeps)
# Write these values to a config file
$$($1_JAVAC_SERVER_CONFIG): $$($1_CONFIG_VARDEPS_FILE)
$(ECHO) portfile=$$($1_JAVAC_PORT_FILE) > $$@
$(ECHO) javacmd=$$($1_JAVAC_SERVER_JAVA_CMD) >> $$@
# Always use small java to launch client
$1_JAVAC_CMD := $$(JAVA_SMALL) $$($1_JAVA_FLAGS) $$($1_JAVAC_SERVER_ARGS) \
javacserver.Main --conf=$$($1_JAVAC_SERVER_CONFIG)
else
# No javac server
$1_JAVAC := $$(INTERIM_LANGTOOLS_ARGS) -m jdk.compiler.interim/com.sun.tools.javac.Main
ifeq ($$($1_SMALL_JAVA), true)
$1_JAVAC_CMD := $$(JAVA_SMALL) $$($1_JAVA_FLAGS) $$($1_JAVAC)
else
$1_JAVAC_CMD := $$(JAVA) $$($1_JAVA_FLAGS) $$($1_JAVAC)
endif
endif
ifeq ($$($1_TARGET_RELEASE), )
# If unspecified, default to the new jdk we're building
$1_TARGET_RELEASE := $$(TARGET_RELEASE_NEWJDK)
endif
else
$$(error Invalid value for COMPILER in SetupJavaCompilation for $1: '$$($1_COMPILER)')
endif
# Tell javac to do exactly as told and no more
PARANOIA_FLAGS := -implicit:none -Xprefer:source -XDignore.symbol.file=true
$1_FLAGS += -g -Xlint:all $$($1_TARGET_RELEASE) $$(PARANOIA_FLAGS)
$1_FLAGS += $$($1_JAVAC_FLAGS)
# Set character encoding in source
$1_FLAGS += -encoding utf-8
ifeq ($$(JAVA_WARNINGS_AS_ERRORS), true)
$1_FLAGS += -Werror
endif
ifneq ($$($1_DISABLED_WARNINGS), )
$1_FLAGS += -Xlint:$$(call CommaList, $$(addprefix -, $$($1_DISABLED_WARNINGS)))
endif
$1_AUGMENTED_CLASSPATH := $$($1_CLASSPATH)
$1_API_TARGET := $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1_pubapi
$1_API_INTERNAL := $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1_internalapi
ifeq ($$($1_CREATE_API_DIGEST), true)
$1_API_DIGEST_FLAGS := \
-Xplugin:"depend $$($1_API_TARGET)" \
"-XDinternalAPIPath=$$($1_API_INTERNAL)" \
"-XDLOG_LEVEL=$(LOG_LEVEL)" \
#
$1_EXTRA_DEPS := $$(BUILDTOOLS_OUTPUTDIR)/depend/_the.COMPILE_DEPEND_batch
# including the compilation output on the classpath, so that incremental
# compilations in unnamed module can refer to other classes from the same
# source root, which are not being recompiled in this compilation:
$1_AUGMENTED_CLASSPATH += $$(BUILDTOOLS_OUTPUTDIR)/depend $$($1_BIN)
endif
ifneq ($$($1_AUGMENTED_CLASSPATH), )
$1_FLAGS += -cp $$(call PathList, $$($1_AUGMENTED_CLASSPATH))
endif
# Make sure the dirs exist, or that one of the EXTRA_FILES, that may not
# exist yet, is in it.
$$(foreach d, $$($1_SRC), \
$$(if $$(wildcard $$d), , \
$$(if $$(filter $$d%, $$($1_EXTRA_FILES)), , \
$$(error SRC specified to SetupJavaCompilation $1 contains missing directory >$$d<) \
) \
) \
)
$$(call MakeDir, $$($1_BIN))
# Order src files according to the order of the src dirs. Correct ordering is
# needed for correct overriding between different source roots.
$1_ALL_SRC_RAW := $$(call FindFiles, $$($1_SRC))
$1_ALL_SRCS := $$($1_EXTRA_FILES) \
$$(foreach d, $$($1_SRC), $$(filter $$d%, $$($1_ALL_SRC_RAW)))
# Extract the java files.
$1_SRCS := $$(filter %.java, $$($1_ALL_SRCS))
# Translate include/exclude into patterns
ifneq ($$($1_EXCLUDE_FILES), )
$1_EXCLUDE_PATTERN := $$(addprefix %, $$($1_EXCLUDE_FILES))
endif
ifneq ($$($1_INCLUDE_FILES), )
$1_INCLUDE_PATTERN := $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$($1_INCLUDE_FILES)))
endif
ifneq ($$($1_EXCLUDES), )
$1_EXCLUDE_PATTERN += $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$(addsuffix /%, $$($1_EXCLUDES))))
endif
ifneq ($$($1_INCLUDES), )
$1_INCLUDE_PATTERN += $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$(addsuffix /%, $$($1_INCLUDES))))
endif
ifneq ($$($1_EXCLUDE_PATTERNS), )
# We must not match the exclude pattern against the src roots, so first
# strip the src prefixes from the absolute file paths in SRCS.
$1_SRCS_WITHOUT_ROOTS := $$(foreach i, $$($1_SRC), \
$$(patsubst $$i/%,%, $$(filter $$i/%, $$($1_SRCS))))
$1_EXCLUDE_PATTERNS_WITHOUT_ROOTS := $$(call containing, \
$$($1_EXCLUDE_PATTERNS), $$($1_SRCS_WITHOUT_ROOTS))
# The add back all possible src prefixes; this will generate more paths
# than really exists, but it does not matter since we will use this as
# input to filter-out.
$1_EXCLUDE_PATTERN += $$(foreach i, $$($1_SRC), $$(addprefix $$i/, \
$$($1_EXCLUDE_PATTERNS_WITHOUT_ROOTS)))
endif
# Apply include/exclude patterns to java sources
ifneq ($$($1_EXCLUDE_PATTERN), )
$1_SRCS := $$(filter-out $$($1_EXCLUDE_PATTERN), $$($1_SRCS))
endif
ifneq ($$($1_INCLUDE_PATTERN), )
$1_SRCS := $$(filter $$($1_INCLUDE_PATTERN) $$($1_EXTRA_FILES), $$($1_SRCS))
endif
ifneq ($$($1_KEEP_DUPS), true)
# Remove duplicate source files by keeping the first found of each duplicate.
# This allows for automatic overrides with custom or platform specific versions
# source files. Need to call DoubleDollar as we have java classes with '$' in
# their names.
$1_SRCS := $$(strip $$(foreach s, $$($1_SRCS), \
$$(eval relative_src := $$(call remove-prefixes, $$($1_SRC), \
$$(call DoubleDollar, $$(s)))) \
$$(if $$($1_$$(relative_src)), \
, \
$$(eval $1_$$(relative_src) := 1) $$(s))))
endif
# Filter out any excluded translations
ifneq ($$($1_KEEP_ALL_TRANSLATIONS), true)
$1_SRCS := $$(call FilterExcludedTranslations, $$($1_SRCS), .java)
endif
ifeq ($$(strip $$($1_SRCS)), )
ifneq ($$($1_FAIL_NO_SRC), false)
$$(error No source files found for $1)
endif
else
# All files below META-INF are always copied.
$1_ALL_COPIES := $$(filter $$(addsuffix /META-INF%, $$($1_SRC)), $$($1_ALL_SRCS))
# Find all files to be copied from source to bin.
ifneq ($$($1_COPY)$$($1_COPY_FILES), )
# Search for all files to be copied.
$1_ALL_COPIES += $$(filter $$(addprefix %, $$($1_COPY)), $$($1_ALL_SRCS))
# Copy these explicitly
$1_ALL_COPIES += $$($1_COPY_FILES)
endif
# Copy must also respect filters.
ifneq ($$($1_INCLUDE_PATTERN), )
$1_ALL_COPIES := $$(filter $$($1_INCLUDE_PATTERN), $$($1_ALL_COPIES))
endif
ifneq ($$($1_EXCLUDE_PATTERN), )
$1_ALL_COPIES := $$(filter-out $$($1_EXCLUDE_PATTERN), $$($1_ALL_COPIES))
endif
# Filter out any excluded translations
ifneq ($$($1_KEEP_ALL_TRANSLATIONS), true)
$1_ALL_COPIES := $$(call FilterExcludedTranslations, $$($1_ALL_COPIES), .properties)
endif
ifneq ($$($1_ALL_COPIES), )
# Yep, there are files to be copied!
$1_ALL_COPY_TARGETS :=
$$(foreach i, $$($1_ALL_COPIES), $$(eval $$(call add_file_to_copy,$1,$$i)))
# Now we can depend on $$($1_ALL_COPY_TARGETS) to copy all files!
endif
# Find all property files to be copied and cleaned from source to bin.
ifneq ($$($1_CLEAN)$$($1_CLEAN_FILES), )
# Search for all files to be copied.
$1_ALL_CLEANS := $$(filter $$(addprefix %, $$($1_CLEAN)), $$($1_ALL_SRCS))
# Clean these explicitly
$1_ALL_CLEANS += $$($1_CLEAN_FILES)
# Copy and clean must also respect filters.
ifneq ($$($1_INCLUDE_PATTERN), )
$1_ALL_CLEANS := $$(filter $$($1_INCLUDE_PATTERN), $$($1_ALL_CLEANS))
endif
ifneq ($$($1_EXCLUDE_PATTERN), )
$1_ALL_CLEANS := $$(filter-out $$($1_EXCLUDE_PATTERN), $$($1_ALL_CLEANS))
endif
# Filter out any excluded translations
ifneq ($$($1_KEEP_ALL_TRANSLATIONS), true)
$1_ALL_CLEANS := $$(call FilterExcludedTranslations, $$($1_ALL_CLEANS), .properties)
endif
ifneq ($$($1_ALL_CLEANS), )
# Yep, there are files to be copied and cleaned!
$1_ALL_COPY_CLEAN_TARGETS :=
$$(foreach i, $$($1_ALL_CLEANS), $$(eval $$(call add_file_to_clean,$1,$$i)))
# Now we can depend on $$($1_ALL_COPY_CLEAN_TARGETS) to copy all files!
endif
endif
# Create a sed expression to remove the source roots and to replace / with .
# and remove .java at the end.
$1_REWRITE_INTO_CLASSES := $$(foreach i, $$($1_SRC), -e 's|$$i/||g') -e 's|/|.|g' -e 's|.java$$$$||g'
$1_COMPILE_TARGET := $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1_batch
$1_FILELIST := $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1_batch.filelist
$1_MODFILELIST := $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1_batch.modfiles
$1_MODFILELIST_FIXED := $$($1_MODFILELIST).fixed
# Put headers in a temp dir to filter out those that actually
# changed before copying them to the real header dir.
ifneq ($$($1_HEADERS), )
$1_HEADERS_ARG := -h $$($1_HEADERS).$1.tmp
$$($1_HEADERS)/_the.$1_headers: $$($1_COMPILE_TARGET)
$$(call MakeTargetDir)
if [ -d "$$($1_HEADERS).$1.tmp" ]; then \
for f in `$(CD) $$($1_HEADERS).$1.tmp && $(FIND) . -type f`; do \
if [ ! -f "$$($1_HEADERS)/$$$$f" ] \
|| [ "`$(DIFF) $$($1_HEADERS)/$$$$f $$($1_HEADERS).$1.tmp/$$$$f`" != "" ]; then \
$(MKDIR) -p `$(DIRNAME) $$($1_HEADERS)/$$$$f`; \
$(CP) -f $$($1_HEADERS).$1.tmp/$$$$f $$($1_HEADERS)/$$$$f; \
fi; \
done; \
fi
$(RM) -r $$($1_HEADERS).$1.tmp
$(TOUCH) $$@
$1_HEADER_TARGETS := $$($1_HEADERS)/_the.$1_headers
endif
$1_VARDEPS := $$($1_JAVAC_CMD) $$($1_FLAGS) $$($1_BIN) \
$$($1_HEADERS_ARG) $$($1_EXCLUDES) $$($1_INCLUDES) \
$$($1_EXCLUDE_FILES) $$($1_INCLUDE_FILES)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
$$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1.vardeps)
# Create a file with all sources, to pass to javac in an @file.
# $$($1_VARDEPS_FILE) is used as dependency to track changes in set of
# list of files.
$$($1_FILELIST): $$($1_SRCS) $$($1_VARDEPS_FILE)
$$(call MakeDir, $$(@D))
$$(call LogWarn, $$($1_LOG_ACTION) up to $$(words $$($1_SRCS)) files for $1)
$$(eval $$(call ListPathsSafely, $1_SRCS, $$($1_FILELIST)))
# Create a $$($1_MODFILELIST) file with significant modified dependencies
# (either sources files or the other mark dependencies).
# It is then sent using a side-channel
# to the custom Depend plugin. The Depend plugin will check the provided list
# of modified files, and if none of the Java source files is changed in a way
# observable from outside of the file, and the list of modified files does
# not include a non-Java source file, it will only compile the modified files.
# Otherwise, all module's sources will be compiled. If a non-Java file is included,
# it will be considered to be a significant change, and all module source will
# be recompiled
$$($1_MODFILELIST): $$($1_SRCS) $$($1_DEPENDS) \
$$($1_VARDEPS_FILE) $$($1_EXTRA_DEPS) $$($1_JAVAC_SERVER_CONFIG)
$$(eval $1_MODFILES := $$?)
$$(eval $$(call ListPathsSafely, $1_MODFILES, $$($1_MODFILELIST)))
# Convert the paths in the MODFILELIST file to Windows-style paths
# on Windows. This is needed because javac operates on Windows-style paths
# when running on Windows. On other platforms this just copies the MODFILELIST file.
$$($1_MODFILELIST_FIXED): $$($1_MODFILELIST)
$$(call FixPathFile, $$($1_MODFILELIST), $$($1_MODFILELIST_FIXED))
# Do the actual compilation
$$($1_COMPILE_TARGET): $$($1_SRCS) $$($1_FILELIST) $$($1_DEPENDS) \
$$($1_VARDEPS_FILE) $$($1_EXTRA_DEPS) $$($1_JAVAC_SERVER_CONFIG) \
$$($1_MODFILELIST_FIXED)
$$(call MakeDir, $$(@D))
$$(call ExecuteWithLog, $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$$($1_SAFE_NAME)_batch, \
$$($1_JAVAC_CMD) $$($1_FLAGS) \
$$($1_API_DIGEST_FLAGS) \
-XDmodifiedInputs=$$($1_MODFILELIST_FIXED) \
-d $$($1_BIN) $$($1_HEADERS_ARG) @$$($1_FILELIST)) && \
$(TOUCH) $$@
# Add all targets to main variable
$1 := $$($1_ALL_COPY_TARGETS) $$($1_ALL_COPY_CLEAN_TARGETS) $$($1_COMPILE_TARGET) \
$$($1_HEADER_TARGETS)
# Check if a jar file was specified, then setup the rules for the jar.
ifneq ($$($1_JAR), )
# If no suffixes was explicitly set for this jar file.
# Use class and the cleaned/copied properties file suffixes as the default
# for the types of files to be put into the jar.
ifeq ($$($1_SUFFIXES), )
$1_SUFFIXES := .class $$($1_CLEAN) $$($1_COPY)
endif
$$(eval $$(call SetupJarArchive, ARCHIVE_$1, \
DEPENDENCIES := $$($1), \
SRCS := $$($1_BIN)$$($1_MODULE_SUBDIR), \
SUFFIXES := $$($1_SUFFIXES), \
EXCLUDE := $$($1_EXCLUDES), \
INCLUDES := $$($1_INCLUDES), \
EXTRA_FILES := $$($1_ALL_COPY_TARGETS) $$($1_ALL_COPY_CLEAN_TARGETS), \
JAR := $$($1_JAR), \
JARMAIN := $$($1_JARMAIN), \
MANIFEST := $$($1_MANIFEST), \
EXTRA_MANIFEST_ATTR := $$($1_EXTRA_MANIFEST_ATTR), \
JARINDEX := $$($1_JARINDEX), \
HEADERS := $$($1_HEADERS), \
))
# Add jar to target list
$1 += $$($1_JAR)
endif
endif # Source files found
endef
# Use this macro to find the correct target to depend on when the original
# SetupJavaCompilation is declared in a different makefile, to avoid having
# to declare and evaluate it again.
# param 1 is for example BUILD_MYPACKAGE
# param 2 is the output directory (BIN)
SetupJavaCompilationCompileTarget = \
$(strip $2)/_the.$(strip $1)_batch
SetupJavaCompilationApiTarget = \
$(strip $2)/_the.$(strip $1)_pubapi
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,543 @@
#
# Copyright (c) 2018, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
include NativeCompilation.gmk
ifeq ($(call isCompiler, gcc), true)
# --disable-new-dtags forces use of RPATH instead of RUNPATH for rpaths.
# This protects internal library dependencies within the JDK from being
# overridden using LD_LIBRARY_PATH. See JDK-8326891 for more information.
SetExecutableOrigin = \
-Wl,-rpath,\$(DOLLAR)ORIGIN$1 -Wl,--disable-new-dtags
SetSharedLibraryOrigin = \
-Wl,-z,origin -Wl,-rpath,\$(DOLLAR)ORIGIN$1 -Wl,--disable-new-dtags
else ifeq ($(call isCompiler, clang), true)
ifeq ($(call isTargetOs, macosx), true)
SetExecutableOrigin = \
-Wl,-rpath,@loader_path$(or $1,/.)
SetSharedLibraryOrigin = \
-Wl,-rpath,@loader_path$(or $1,/.)
else ifeq ($(call isTargetOs, aix), true)
SetExecutableOrigin =
SetSharedLibraryOrigin =
else
ifeq ($(call isTargetOs, linux), true)
SetExecutableOrigin = \
-Wl,-rpath,\$(DOLLAR)ORIGIN$1 -Wl,--disable-new-dtags
else
SetExecutableOrigin = \
-Wl,-rpath,\$(DOLLAR)ORIGIN$1
endif
ifeq ($(call isTargetOs, arm), true)
SetSharedLibraryOrigin = \
-Wl,-rpath,\$(DOLLAR)ORIGIN$1
else
SetSharedLibraryOrigin = \
-Wl,-z,origin -Wl,-rpath,\$(DOLLAR)ORIGIN$1
endif
endif
else ifeq ($(call isCompiler, microsoft), true)
SetExecutableOrigin =
SetSharedLibraryOrigin =
else
$(error Unknown toolchain)
endif
FindSrcDirsForComponent += \
$(call uniq, $(wildcard \
$(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS)/native/$(strip $2) \
$(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/native/$(strip $2) \
$(TOPDIR)/src/$(strip $1)/share/native/$(strip $2)))
# Find a library. Used for declaring dependencies on libraries in different
# modules.
# Param 1 - module name
# Param 2 - library name
# Param 3 - optional subdir for library
FindLib = \
$(call FindLibDirForModule, \
$(strip $1))$(strip $3)/$(LIBRARY_PREFIX)$(strip $2)$(SHARED_LIBRARY_SUFFIX)
# Find a static library
# Param 1 - module name
# Param 2 - library name
# Param 3 - optional subdir for library
FindStaticLib = \
$(addprefix $(SUPPORT_OUTPUTDIR)/native/, \
$(strip $1)$(strip $3)/$(LIBRARY_PREFIX)$(strip $2)$(STATIC_LIBRARY_SUFFIX))
# If only generating compile_commands.json, make these return empty to avoid
# declaring dependencies.
ifeq ($(GENERATE_COMPILE_COMMANDS_ONLY), true)
FindLib =
FindStaticLib =
endif
# If building static versions of libraries, make these return empty to avoid
# declaring dependencies.
ifeq ($(STATIC_LIBS), true)
FindLib =
FindStaticLib =
endif
# Returns the module specific java header dir if it exists.
# Param 1 - module name
GetJavaHeaderDir = \
$(if $(strip $1),$(wildcard $(SUPPORT_OUTPUTDIR)/headers/$(strip $1)))
HOTSPOT_INCLUDE_DIR := $(TOPDIR)/src/hotspot/share/include \
$(TOPDIR)/src/hotspot/os/$(HOTSPOT_TARGET_OS_TYPE)/include
# Preprocess a source dir destination. Pass on absolute paths unchanged. Expand
# description such as "java.base:headers" into a set of proper absolute paths,
# by looking in $MODULE/[shared|$OS|$OSTYPE]/native.
# Treat *:libjvm as a special case, and replace it with the proper hotspot
# include directories.
ProcessSrcDir = \
$(if $(findstring :, $1), \
$(if $(filter %:libjvm, $1), \
$(HOTSPOT_INCLUDE_DIR) \
, \
$(call FindSrcDirsForComponent, $(firstword $(subst :, , $1)), \
$(lastword $(subst :, , $1))) \
) \
, \
$(if $(filter /%, $1), \
$1 \
, \
$(if $(filter libjvm, $1), \
$(HOTSPOT_INCLUDE_DIR) \
, \
$(call FindSrcDirsForComponent, $(MODULE), $1) \
) \
) \
)
# Create a proper LIBPATH for the given library. Sets result in $1_$2_LIBPATH.
# $1: The name of the rule (namespace)
# $2: The safe namespace of the library
define ResolveLibPath
# Determine proper LIBPATH. This is quite messy due to historical reasons,
# and because we need to have special treatment for "gtest:" and ":jvm".
ifneq ($$($1_$2_MODULE), gtest)
ifneq ($$($1_$2_NAME), jvm)
# This is the common case
ifeq ($$(call isTargetOs, windows), true)
$1_$2_LIBPATH := $$(SUPPORT_OUTPUTDIR)/native/$$($1_$2_MODULE)/lib$$($1_$2_NAME)
else
ifeq ($(STATIC_LIBS), true)
$1_$2_LIBPATH := $$(SUPPORT_OUTPUTDIR)/native/$$($1_$2_MODULE)/lib$$($1_$2_NAME)/static
else ifeq ($$($1_$2_STATIC_LIBRARY), true)
$1_$2_LIBPATH := $$(SUPPORT_OUTPUTDIR)/native/$$($1_$2_MODULE)
else
$1_$2_LIBPATH := $$(SUPPORT_OUTPUTDIR)/modules_libs/$$($1_$2_MODULE)
endif
endif
else
# Special treatment for hotspot
ifeq ($(CREATING_BUILDJDK), true)
# When building a buildjdk, it's always only the server variant
$1_$2_JVM_VARIANT_PATH := server
else
$1_$2_JVM_VARIANT_PATH := $(JVM_VARIANT_MAIN)
endif
ifeq ($$(call isTargetOs, windows), true)
ifeq ($(STATIC_LIBS), true)
$1_$2_LIBPATH := $$(HOTSPOT_OUTPUTDIR)/variant-$$($1_$2_JVM_VARIANT_PATH)/libjvm/objs/static
else
$1_$2_LIBPATH := $$(SUPPORT_OUTPUTDIR)/modules_libs/$$($1_$2_MODULE)
endif
else
ifeq ($(STATIC_LIBS), true)
$1_$2_LIBPATH := $$(HOTSPOT_OUTPUTDIR)/variant-$$($1_$2_JVM_VARIANT_PATH)/libjvm/objs/static
else
$1_$2_LIBPATH := $$(SUPPORT_OUTPUTDIR)/modules_libs/$$($1_$2_MODULE)/$$($1_$2_JVM_VARIANT_PATH)
endif
endif
endif
else
# Special treatment for virtual module "gtest"
ifeq ($$($1_$2_NAME), jvm)
ifeq ($$(call isTargetOs, windows), true)
ifeq ($(STATIC_LIBS), true)
$1_$2_LIBPATH := $$(JVM_OUTPUTDIR)/gtest/objs/static
else
$1_$2_LIBPATH := $$(JVM_OUTPUTDIR)/gtest/objs
endif
else
ifeq ($(STATIC_LIBS), true)
$1_$2_LIBPATH := $$(JVM_OUTPUTDIR)/gtest/objs/static
else
$1_$2_LIBPATH := $$(JVM_OUTPUTDIR)/gtest
endif
endif
else ifeq ($$($1_$2_NAME), gtest)
$1_$2_LIBPATH := $$(JVM_OUTPUTDIR)/libgtest
ifeq ($(STATIC_LIBS), true)
$1_$2_LIBPATH := $$(JVM_OUTPUTDIR)/libgtest/objs/static
else
$1_$2_LIBPATH := $$(JVM_OUTPUTDIR)/libgtest
endif
endif
endif
endef
# Process a JDK library designation such as "java.desktop:jawt" into the needed
# additions to EXTRA_LINK_DEPS, LDFLAGS, LIBS and EXTRA_HEADER_DIRS.
# $1: The name of the rule (namespace)
# $2: The safe namespace of the library
# $3: The actual string given to represent the library
define AddJdkLibrary
$1_$2_NAME := $$(strip $$(lastword $$(subst :, , $3)))
$1_$2_MODULE := $$(strip $$(patsubst %$$($1_$2_NAME), %, $3))
ifeq ($$(filter lib%, $$($1_$2_NAME)), )
$$(error Library name $$($1_$2_NAME) missing lib prefix in $1)
endif
$1_$2_NAME := $$(strip $$(patsubst lib%, %, $$($1_$2_NAME)))
ifeq ($$($1_$2_MODULE), )
$1_$2_MODULE := $$(MODULE)
else
$1_$2_MODULE := $$(strip $$(patsubst %:, %, $$($1_$2_MODULE)))
endif
# Determine if the library in question is static.
# Ideally, we should not hardcode these
ifeq ($(call isTargetOs, aix)+$$($1_$2_MODULE):$$($1_$2_NAME), true+java.base:jli)
$1_$2_STATIC_LIBRARY := true
endif
ifeq ($$($1_$2_MODULE):$$($1_$2_NAME), gtest:gtest)
$1_$2_STATIC_LIBRARY := true
endif
# Setup $1_$2_LIBPATH.
$$(eval $$(call ResolveLibPath,$1,$2))
$1_EXTRA_HEADER_DIRS += $$($1_$2_MODULE):lib$$($1_$2_NAME)
ifneq ($(STATIC_LIBS), true)
ifeq ($$(call isTargetOs, windows), true)
ifeq ($$(filter -libpath:$$($1_$2_LIBPATH), $$($1_LDFLAGS)), )
$1_LDFLAGS += -libpath:$$($1_$2_LIBPATH)
endif
$1_LIBS += $$($1_$2_NAME)$(STATIC_LIBRARY_SUFFIX)
$1_$2_LIBFILE := $(LIBRARY_PREFIX)$$($1_$2_NAME)$(STATIC_LIBRARY_SUFFIX)
else
ifeq ($$(filter -L$$($1_$2_LIBPATH), $$($1_LDFLAGS)), )
$1_LDFLAGS += -L$$($1_$2_LIBPATH)
endif
$1_LIBS += -l$$($1_$2_NAME)
ifeq ($$($1_$2_STATIC_LIBRARY), true)
$1_$2_LIBFILE := $(LIBRARY_PREFIX)$$($1_$2_NAME)$(STATIC_LIBRARY_SUFFIX)
else
$1_$2_LIBFILE := $(LIBRARY_PREFIX)$$($1_$2_NAME)$(SHARED_LIBRARY_SUFFIX)
endif
endif
$1_EXTRA_LINK_DEPS += $$($1_$2_LIBPATH)/$$($1_$2_LIBFILE)
endif
endef
GLOBAL_VERSION_INFO_RESOURCE := $(TOPDIR)/src/java.base/windows/native/common/version.rc
# \xA9 is the copyright symbol in ANSI encoding (Windows-1252), which rc.exe
# assumes the resource file is in.
JDK_RCFLAGS=$(RCFLAGS) \
-D"JDK_VERSION_STRING=$(VERSION_STRING)" \
-D"JDK_COMPANY=$(JDK_RC_COMPANY_NAME)" \
-D"JDK_VER=$(VERSION_NUMBER_FOUR_POSITIONS)" \
-D"JDK_COPYRIGHT=Copyright \xA9 $(COPYRIGHT_YEAR)" \
-D"JDK_NAME=$(JDK_RC_NAME) $(VERSION_SHORT)" \
-D"JDK_FVER=$(subst .,$(COMMA),$(VERSION_NUMBER_FOUR_POSITIONS))"
# Setup make rules for creating a native binary with suitable defaults
# for the OpenJDK project. This macro is mostly considered to be an internal
# support version. Please use SetupJdkLibrary or SetupJdkExecutable instead.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# Remaining parameters are named arguments. These are all passed on to
# SetupNativeCompilation. This macro also adds the following additional
# arguments:
#
# SRC -- this is passed on after preprocessing. The preprocessing will pass on
# absolute paths unchanged, but relative paths will be expanded to include
# all directories with this name in $MODULE/[shared|$OS|$OSTYPE]/native.
# EXTRA_SRC -- additional directories to look for source in. This is processed
# like SRC.
# EXCLUDE_SRC_PATTERNS -- exclude source dirs matching these patterns from
# appearing in SRC.
# EXTRA_HEADER_DIRS -- additional directories to look for headers in. This can
# be specified either as an absolute path, or relative directory names which
# are preprocessed like SRC, or in the format <module>:<directory>, which
# will be processed like SRC but for the given module. The names
# "java.base:libjvm" and "gtest:libjvm" symbolise virtual libraries that
# will be replaced with proper values for hotspot.
# HEADERS_FROM_SRC -- if false, does not add source dirs automatically as
# header include dirs. (Defaults to true.)
# JAVA_HEADERS -- if false, does not add the directory with the generated
# headers from the Java compilation of the current module to the search
# path for include files. (Defaults to true.)
# JDK_LIBS -- libraries generated by the JDK build system to link against.
# These take the form <module>:<basename>. For the current module, the
# module name and colon can be omitted. The basename should be specified
# as the source directory, e.g. "libjava". The gtest module is a virtual
# module that will be replaced with correct values for gtest. When
# specifying JDK_LIBS, suitable values for EXTRA_LINK_DEPS, LDFLAGS, LIBS
# and EXTRA_HEADER_DIRS will be added.
# JDK_LIBS_<os> or JDK_LIBS_<osType> -- additional JDK_LIBS for the given OS
# or OS type only
# ONLY_EXPORTED -- if true, this library will be flagged as not
# to be included for this module when building static libs
# EXTRA_RCFLAGS -- additional RCFLAGS to append.
# RC_FILEDESC -- override the default FILEDESC for Windows version.rc
# DEFAULT_LIBCXX -- if false, do not add LIBCXX to LIBS for C++ compilations
# DEFAULT_CFLAGS -- if false, do not add default CFLAGS and CXXFLAGS
# DEFAULT_LDFLAGS -- if false, do not add default LDFLAGS
# CFLAGS_FILTER_OUT -- flags to filter out from default CFLAGS
# CXXFLAGS_FILTER_OUT -- flags to filter out from default CXXFLAGS
# LDFLAGS_FILTER_OUT -- flags to filter out from default LDFLAGS
# LD_SET_ORIGIN -- if false, do not add SET_*_ORIGIN flags to LDFLAGS
# APPEND_LDFLAGS -- a quirk to have additional LDFLAGS that will be set after
# the origin flags
# DEFAULT_VERSIONINFO_RESOURCE -- if false, do not set the default
# VERSIONINFO_RESOURCE
#
SetupJdkNativeCompilation = $(NamedParamsMacroTemplate)
define SetupJdkNativeCompilationBody
ifeq ($$($1_TYPE), EXECUTABLE)
$1_NATIVE_DIR_PREFIX :=
$1_MODULES_PATH := modules_cmds
$1_RC_EXT := exe
$1_RC_FTYPE := 0x1L
else
$1_NATIVE_DIR_PREFIX := lib
$1_MODULES_PATH := modules_libs
$1_RC_EXT := dll
$1_RC_FTYPE := 0x2L
endif
ifneq ($$(MODULE), )
# Record the fact that this native library is part of the current module
# (unless told otherwise). This variable stores information about all
# created libraries, and is read by ModuleWrapper.
ifneq ($$($1_ONLY_EXPORTED), true)
$$(MODULE)_INCLUDED_LIBS += $$($1_NAME)
endif
endif
ifeq ($$($1_OUTPUT_DIR), )
ifneq ($$(MODULE), )
ifeq ($$($1_TYPE), STATIC_LIBRARY)
$1_OUTPUT_DIR := $$(SUPPORT_OUTPUTDIR)/native/$$(MODULE)
else
$1_OUTPUT_DIR := $$(SUPPORT_OUTPUTDIR)/$$($1_MODULES_PATH)/$$(strip $$(MODULE))
endif
else
$$(error Must specify OUTPUT_DIR in a MODULE free context)
endif
endif
ifeq ($$($1_OBJECT_DIR), )
ifneq ($$(MODULE), )
$1_OBJECT_DIR := $$(SUPPORT_OUTPUTDIR)/native/$$(MODULE)/$$($1_NATIVE_DIR_PREFIX)$$($1_NAME)
else
$$(error Must specify OBJECT_DIR in a MODULE free context)
endif
endif
ifneq ($$($1_DEFAULT_LIBCXX), false)
ifeq ($$($1_LINK_TYPE), C++)
$1_LIBS += $(LIBCXX)
endif
endif
ifeq ($$($1_SRC), )
ifneq ($$(MODULE), )
$1_SRC := $$(call FindSrcDirsForComponent, $$(MODULE), $$($1_NATIVE_DIR_PREFIX)$$($1_NAME))
else
ifeq ($$($1_EXTRA_FILES), )
$$(error Must specify SRC or EXTRA_FILES in a MODULE free context)
endif
endif
else
$1_SRC := $$(foreach dir, $$($1_SRC), $$(call ProcessSrcDir, $$(dir)))
endif
ifneq ($$($1_EXTRA_SRC), )
$1_SRC += $$(foreach dir, $$($1_EXTRA_SRC), $$(call ProcessSrcDir, $$(dir)))
endif
ifneq ($$($1_EXCLUDE_SRC_PATTERNS), )
$1_SRC_WITHOUT_WORKSPACE_ROOT := $$(patsubst $$(WORKSPACE_ROOT)/%, %, $$($1_SRC))
$1_EXCLUDE_SRC := $$(addprefix %, $$(call containing, $$($1_EXCLUDE_SRC_PATTERNS), \
$$($1_SRC_WITHOUT_WORKSPACE_ROOT)))
$1_SRC := $$(filter-out $$($1_EXCLUDE_SRC), $$($1_SRC))
endif
ifneq ($$($1_DEFAULT_VERSIONINFO_RESOURCE), false)
ifeq ($$($1_VERSIONINFO_RESOURCE), )
$1_VERSIONINFO_RESOURCE := $$(GLOBAL_VERSION_INFO_RESOURCE)
endif
endif
ifeq ($$($1_RC_FILEDESC), )
$1_RC_FILEDESC := $(JDK_RC_NAME) binary
endif
$1_RCFLAGS := $(JDK_RCFLAGS) \
-D"JDK_FILEDESC=$$($1_RC_FILEDESC)" \
-D"JDK_FNAME=$$($1_NAME).$$($1_RC_EXT)" \
-D"JDK_INTERNAL_NAME=$$($1_NAME)" \
-D"JDK_FTYPE=$$($1_RC_FTYPE)" \
-I$(TOPDIR)/src/java.base/windows/native/common \
$$($1_EXTRA_RCFLAGS)
ifneq ($$($1_HEADERS_FROM_SRC), false)
$1_SRC_HEADER_FLAGS := $$(addprefix -I, $$(wildcard $$($1_SRC)))
endif
# Add the module specific java header dir
ifneq ($$(MODULE), )
ifneq ($$($1_JAVA_HEADERS), false)
$1_SRC_HEADER_FLAGS += $$(addprefix -I, $$(call GetJavaHeaderDir, $$(MODULE)))
endif
endif
$1_JDK_LIBS += $$($1_JDK_LIBS_$$(OPENJDK_TARGET_OS))
$1_JDK_LIBS += $$($1_JDK_LIBS_$$(OPENJDK_TARGET_OS_TYPE))
$$(foreach lib, $$($1_JDK_LIBS), \
$$(eval $$(call AddJdkLibrary,$1,$$(subst :,_,$$(lib)),$$(lib))) \
)
# Add the include path for jni.h to all native compilations
$1_EXTRA_HEADER_DIRS += \
$(SUPPORT_OUTPUTDIR)/modules_include/java.base \
java.base:include \
#
$1_PROCESSED_EXTRA_HEADER_DIRS := $$(foreach dir, $$($1_EXTRA_HEADER_DIRS), \
$$(call ProcessSrcDir, $$(dir)))
$1_EXTRA_HEADER_FLAGS := $$(addprefix -I, $$($1_PROCESSED_EXTRA_HEADER_DIRS))
ifneq ($$($1_DEFAULT_CFLAGS), false)
ifeq ($$($1_TYPE), EXECUTABLE)
# Set the default flags first to be able to override
$1_CFLAGS := $$(filter-out $$($1_CFLAGS_FILTER_OUT), $$(CFLAGS_JDKEXE)) $$($1_CFLAGS)
# Set the default flags first to be able to override
$1_CXXFLAGS := $$(filter-out $$($1_CXXFLAGS_FILTER_OUT), $$(CXXFLAGS_JDKEXE)) $$($1_CXXFLAGS)
else
# Set the default flags first to be able to override
$1_CFLAGS := $$(filter-out $$($1_CFLAGS_FILTER_OUT), $$(CFLAGS_JDKLIB)) $$($1_CFLAGS)
# Set the default flags first to be able to override
$1_CXXFLAGS := $$(filter-out $$($1_CXXFLAGS_FILTER_OUT), $$(CXXFLAGS_JDKLIB)) $$($1_CXXFLAGS)
endif
endif
ifneq ($$($1_CFLAGS), )
$1_CFLAGS += $$($1_SRC_HEADER_FLAGS) $$($1_EXTRA_HEADER_FLAGS)
endif
ifneq ($$($1_CXXFLAGS), )
$1_CXXFLAGS += $$($1_SRC_HEADER_FLAGS) $$($1_EXTRA_HEADER_FLAGS)
endif
ifeq ($$($1_CFLAGS)$$($1_CXXFLAGS), )
$1_CFLAGS += $$($1_SRC_HEADER_FLAGS) $$($1_EXTRA_HEADER_FLAGS)
endif
ifneq ($$($1_DEFAULT_LDFLAGS), false)
ifeq ($$($1_TYPE), EXECUTABLE)
# Set the default flags first to be able to override
$1_LDFLAGS := $$(filter-out $$($1_LDFLAGS_FILTER_OUT), $$(LDFLAGS_JDKEXE) $$($1_LDFLAGS))
else
# Set the default flags first to be able to override
$1_LDFLAGS := $$(filter-out $$($1_LDFLAGS_FILTER_OUT), $$(LDFLAGS_JDKLIB) $$($1_LDFLAGS))
endif
endif
ifneq ($$($1_LD_SET_ORIGIN), false)
ifeq ($$($1_TYPE), EXECUTABLE)
$1_LDFLAGS += $$(call SetExecutableOrigin)
else
$1_LDFLAGS += $$(call SetSharedLibraryOrigin)
endif
endif
# APPEND_LDFLAGS, if it exists, must be set after the origin flags
# This is a workaround to keep existing behavior
$1_LDFLAGS += $$($1_APPEND_LDFLAGS)
# Since we reuse the rule name ($1), all our arguments will pass through.
# We lose in transparency, but gain in brevity in this call...
$$(eval $$(call SetupNativeCompilation, $1))
endef
# Setup make rules for creating a native library with suitable defaults
# for the OpenJDK project. The default is to create a shared library,
# but by passing TYPE := STATIC_LIBARY, a static library can be created.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# Remaining parameters are named arguments. These are all passed on to
# SetupJdkNativeCompilation. Please see that macro for details.
SetupJdkLibrary = $(NamedParamsMacroTemplate)
define SetupJdkLibraryBody
# If type is unspecified, default to LIBRARY
ifeq ($$($1_TYPE), )
$1_TYPE := LIBRARY
endif
# Since we reuse the rule name ($1), all our arguments will pass through.
# We lose in transparency, but gain in brevity in this call...
$$(eval $$(call SetupJdkNativeCompilation, $1))
endef
# Setup make rules for creating a native executable with suitable defaults
# for the OpenJDK project.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# Remaining parameters are named arguments. These are all passed on to
# SetupJdkNativeCompilation. Please see that macro for details.
SetupJdkExecutable = $(NamedParamsMacroTemplate)
define SetupJdkExecutableBody
$1_TYPE := EXECUTABLE
# Since we reuse the rule name ($1), all our arguments will pass through.
# We lose in transparency, but gain in brevity in this call...
$$(eval $$(call SetupJdkNativeCompilation, $1))
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

132
make/common/LogUtils.gmk Normal file
View file

@ -0,0 +1,132 @@
#
# Copyright (c) 2011, 2025, 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.
#
include $(TOPDIR)/make/common/MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# This file contains helper functions for logging.
################################################################################
# Look for a given option in the LOG variable, and if found, set a variable
# and remove the option from the LOG variable
# $1: The option to look for
# $2: The variable to set to "true" if the option is found
define ParseLogOption
ifneq ($$(findstring $1, $$(LOG)), )
override $2 := true
# First try to remove ",<option>" if it exists, otherwise just remove "<option>"
LOG_STRIPPED := $$(subst $1,, $$(subst $$(COMMA)$$(strip $1),, $$(LOG)))
# We might have ended up with a leading comma. Remove it. Need override
# since LOG is set from the command line.
override LOG := $$(strip $$(patsubst $$(COMMA)%, %, $$(LOG_STRIPPED)))
endif
endef
# Look for a given option with an assignment in the LOG variable, and if found,
# set a variable to that value and remove the option from the LOG variable
# $1: The option to look for
# $2: The variable to set to the value of the option, if found
define ParseLogValue
ifneq ($$(findstring $1=, $$(LOG)), )
# Make words of out comma-separated list and find the one with opt=val
value := $$(strip $$(subst $$(strip $1)=,, $$(filter $$(strip $1)=%, $$(subst $$(COMMA), , $$(LOG)))))
override $2 := $$(value)
# First try to remove ",<option>" if it exists, otherwise just remove "<option>"
LOG_STRIPPED := $$(subst $$(strip $1)=$$(value),, \
$$(subst $$(COMMA)$$(strip $1)=$$(value),, $$(LOG)))
# We might have ended up with a leading comma. Remove it. Need override
# since LOG is set from the command line.
override LOG := $$(strip $$(patsubst $$(COMMA)%, %, $$(LOG_STRIPPED)))
endif
endef
define ParseLogLevel
# Setup logging according to LOG
# If "nofile" is present, do not log to a file
$$(eval $$(call ParseLogOption, nofile, LOG_NOFILE))
# If "cmdline" is present, print all executes "important" command lines.
$$(eval $$(call ParseLogOption, cmdlines, LOG_CMDLINES))
# If "report" is present, use non-standard reporting options at build failure.
$$(eval $$(call ParseLogValue, report, LOG_REPORT))
ifneq ($$(LOG_REPORT), )
ifeq ($$(filter $$(LOG_REPORT), none all default), )
$$(info Error: LOG=report has invalid value: $$(LOG_REPORT).)
$$(info Valid values: LOG=report=<none>|<all>|<default>)
$$(error Cannot continue)
endif
endif
# If "profile-to-log" is present, write shell times in build log
$$(eval $$(call ParseLogOption, profile-to-log, LOG_PROFILE_TIMES_LOG))
# If "profile" is present, write shell times in separate log file
# IMPORTANT: $(ParseLogOption profile-to-log) should go first. Otherwise
# parsing of 'LOG=debug,profile-to-log,nofile' ends up in the following error:
# Error: LOG contains unknown option or log level: debug-to-log.
$$(eval $$(call ParseLogOption, profile, LOG_PROFILE_TIMES_FILE))
# If "flow" is present, log makefile execution flow
$$(eval $$(call ParseLogOption, flow, LOG_FLOW))
# Treat LOG=profile-to-log as if it were LOG=profile,profile-to-log
LOG_PROFILE_TIMES_FILE := $$(firstword $$(LOG_PROFILE_TIMES_FILE) $$(LOG_PROFILE_TIMES_LOG))
override LOG_LEVEL := $$(LOG)
ifeq ($$(LOG_LEVEL), )
# Set LOG to "warn" as default if not set
override LOG_LEVEL := warn
endif
ifeq ($$(LOG_LEVEL), warn)
override MAKE_LOG_FLAGS := -s
else ifeq ($$(LOG_LEVEL), info)
override MAKE_LOG_FLAGS := -s
else ifeq ($$(LOG_LEVEL), debug)
override MAKE_LOG_FLAGS :=
else ifeq ($$(LOG_LEVEL), trace)
override MAKE_LOG_FLAGS :=
else
$$(info Error: LOG contains unknown option or log level: $$(LOG).)
$$(info LOG can be <level>[,<opt>[...]] where <opt> is nofile | cmdlines | profile | profile-to-log)
$$(info and <level> is warn | info | debug | trace)
$$(error Cannot continue)
endif
endef
MAKE_LOG_VARS = $(foreach v, \
LOG_LEVEL LOG_NOFILE LOG_CMDLINES LOG_REPORT LOG_PROFILE_TIMES_LOG \
LOG_PROFILE_TIMES_FILE LOG_FLOW, \
$v=$($v) \
)
################################################################################
endif # include guard
include $(TOPDIR)/make/common/MakeIncludeEnd.gmk

385
make/common/MakeBase.gmk Normal file
View file

@ -0,0 +1,385 @@
#
# Copyright (c) 2011, 2026, 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.
#
MAKEBASE_INCLUDED := true
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# MakeBase provides the core functionality needed and used by all makefiles. It
# should be included by all makefiles. MakeBase provides essential
# functionality for named parameter functions, variable dependency, tool
# execution, logging and fixpath functionality.
################################################################################
# By defining this pseudo target, make will automatically remove targets
# if their recipe fails so that a rebuild is automatically triggered on the
# next make invocation.
.DELETE_ON_ERROR:
################################################################################
# Definitions for special characters
################################################################################
# When calling macros, the spaces between arguments are
# often semantically important! Sometimes we need to subst
# spaces and commas, therefore we need the following macros.
X :=
SPACE := $(X) $(X)
COMMA := ,
DOLLAR := $$
HASH := \#
LEFT_PAREN := (
RIGHT_PAREN := )
SQUOTE := '
#'
DQUOTE := "
#"
define NEWLINE
endef
# Certain features only work in newer version of GNU Make. The build will still
# function in 3.81, but will be less performant.
ifeq (4.0, $(firstword $(sort 4.0 $(MAKE_VERSION))))
HAS_FILE_FUNCTION := true
CORRECT_FUNCTION_IN_RECIPE_EVALUATION := true
RWILDCARD_WORKS := true
endif
# For convenience, MakeBase.gmk continues to include these separate files, at
# least for now.
# Utils.gmk must be included before FileUtils.gmk, since it uses some of the
# basic utility functions there.
include $(TOPDIR)/make/common/Utils.gmk
include $(TOPDIR)/make/common/FileUtils.gmk
################################################################################
# Make sure we have a value (could be overridden on command line by caller)
CREATING_BUILDJDK ?= false
################################################################################
define SetupLogging
ifeq ($$(LOG_PROFILE_TIMES_FILE), true)
ifeq ($$(IS_GNU_TIME), yes)
SHELL := $$(BASH) $$(TOPDIR)/make/scripts/shell-profiler.sh \
gnutime $$(TIME) \
$$(OUTPUTDIR)/build-profile.log $$(SHELL)
else ifneq ($$(FLOCK), )
SHELL := $$(BASH) $$(TOPDIR)/make/scripts/shell-profiler.sh \
flock $$(FLOCK) \
$$(OUTPUTDIR)/build-profile.log $$(SHELL)
endif
endif
ifneq ($$(findstring $$(LOG_LEVEL), debug trace), )
SHELL := $$(SHELL) -x
endif
ifeq ($$(LOG_LEVEL), trace)
SHELL_NO_RECURSE := $$(SHELL)
# Shell redefinition trick inspired by http://www.cmcrossroads.com/ask-mr-make/6535-tracing-rule-execution-in-gnu-make
# For each target executed, will print
# Building <TARGET> (from <FIRST PREREQUISITE>) (<ALL NEWER PREREQUISITES> newer)
# but with a limit of 20 on <ALL NEWER PREREQUISITES>, to avoid cluttering logs too much
# (and causing a crash on Cygwin).
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
endif
# The LOG_PREFIX is set for sub recursive calls like buildjdk and bootcycle.
# The warn level can never be turned off
LogWarn = $$(info $(LOG_PREFIX)$$(strip $$1))
LOG_WARN :=
ifneq ($$(findstring $$(LOG_LEVEL), info debug trace), )
LogInfo = $$(info $(LOG_PREFIX)$$(strip $$1))
LOG_INFO :=
else
LogInfo =
LOG_INFO := > /dev/null
endif
ifneq ($$(findstring $$(LOG_LEVEL), debug trace), )
LogDebug = $$(info $(LOG_PREFIX)$$(strip $$1))
LOG_DEBUG :=
else
LogDebug =
LOG_DEBUG := > /dev/null
endif
ifneq ($$(findstring $$(LOG_LEVEL), trace), )
LogTrace = $$(info $(LOG_PREFIX)$$(strip $$1))
LOG_TRACE :=
else
LogTrace =
LOG_TRACE := > /dev/null
endif
endef
# Make sure logging is setup for everyone that includes MakeBase.gmk.
$(eval $(call SetupLogging))
################################################################################
# Make does not have support for VARARGS, you can send variable amount
# of arguments, but you can for example not append a list at the end.
# It is therefore not easy to send the elements of a list of unknown
# length as argument to a function. This can somewhat be worked around
# by sending a list as an argument, and then interpreting each element
# of the list as an argument to the function. However, Make is
# limited, and using this method you can not easily send spaces.
#
# We need to quote strings for two reasons when sending them as
# "variable append packs":
#
# 1) variable appends can include spaces, and those must be preserved
# 2) variable appends can include assignment strings ":=", and those
# must be quoted to a form so that we can recognise the "append pack".
# We recognise an "append pack" by its lack of strict assignment ":="
Q := $(HASH)
SpaceQ := $(Q)s
AppendQ := $(Q)+
AssignQ := $(Q)a
QQ := $(Q)$(Q)
# $(call Quote,echo "#trala:=") -> echo#s"##trala#a"
Quote = $(subst :=,$(AssignQ),$(subst $(SPACE),$(SpaceQ),$(subst $(Q),$(QQ),$1)))
# $(call Unquote,echo#s"##trala#a") -> echo "#trala:="
Unquote = $(subst $(QQ),$(Q),$(subst $(SpaceQ),$(SPACE),$(subst $(AssignQ),:=,$1)))
# $(call QuoteAppend,name,some value) -> name#+some#svalue
# $(call QuoteAppend,bad+=name,some value) -> error
QuoteAppend = $(if $(findstring +=,$1),$(error you can not have += in a variable name: "$1"),$(call Quote,$1)$(AppendQ)$(call Quote,$2))
# $(call UnquoteAppendIndex,name#+some#svalue,1) -> name
# $(call UnquoteAppendIndex,name#+some#svalue,2) -> some value
UnquoteAppendIndex = $(call Unquote,$(word $2,$(subst $(AppendQ),$(SPACE),$1)))
# $(call FilterFiles,dir,%.cpp) -> file1.cpp file2.cpp (without path)
FilterFiles = $(filter $2,$(notdir $(call FindFiles,$1)))
# $(call Unpack module_,file1.cpp_CXXFLAGS#+-Wconversion file2.cpp_CXXFLAGS#+-Wconversion) -> module_file1.cpp_CXXFLAGS += -Wconversion
# module_file2.cpp_CXXFLAGS += -Wconversion
Unpack = $(foreach pair,$2,$1$(call UnquoteAppendIndex,$(pair),1) += $(call UnquoteAppendIndex,$(pair),2)$(NEWLINE))
# This macro takes four arguments:
# $1: directory where to find files (striped), example: $(TOPDIR)/src/hotspot/share/gc/g1
# $2: filter to match what to keep (striped), example: g1Concurrent%.cpp
# $3: what flags to override (striped), example: _CXXFLAGS
# $4: what value to append to the flag (striped), example: $(CFLAGS_CONVERSION_WARNINGS)
#
# The result will be a quoted string that can be unpacked to a list of
# variable appendings (see macro Unpack above). You do not need to take
# care of unpacking, it is done in NamedParamsMacroTemplate.
#
# This feature should only be used for warnings that we want to
# incrementally add to the rest of the code base.
#
# $(call ExtendFlags,dir,%.cpp,_CXXFLAGS,-Wconversion) -> file1.cpp_CXXFLAGS#+-Wconversion file2.cpp_CXXFLAGS#+-Wconversion
ExtendFlags = $(foreach file,$(call FilterFiles,$(strip $1),$(strip $2)),$(call QuoteAppend,$(file)$(strip $3),$(strip $4)))
################################################################################
MAX_PARAMS := 96
PARAM_SEQUENCE := $(call sequence, 2, $(MAX_PARAMS))
# Template for creating a macro taking named parameters. To use it, assign the
# template to a variable with the name you want for your macro, using '='
# assignment. Then define a macro body with the suffix "Body". The Body macro
# should take 1 parameter which should be a unique string for that invocation
# of the macro.
# Ex:
# SetupFoo = $(NamedParamsMacroTemplate)
# define SetupFooBody
# # do something
# # access parameters as $$($1_BAR)
# endef
# Call it like this
# $(eval $(call SetupFoo, BUILD_SOMETHING, \
# BAR := some parameter value, \
# ))
define NamedParamsMacroTemplate
$(if $($(MAX_PARAMS)), $(error Internal makefile error: \
Too many named arguments to macro, please update MAX_PARAMS in MakeBase.gmk))
# Iterate over 2 3 4... and evaluate the named parameters with $1_ as prefix
$(foreach i, $(PARAM_SEQUENCE), $(if $(strip $($i)), \
$(if $(findstring :=,$($i)), \
$(strip $1)_$(strip $(call EscapeHash, $(call DoubleDollar, $($i))))$(NEWLINE), \
$(call Unpack,$(strip $1)_,$($i)))))
# Debug print all named parameter names and values
$(if $(findstring $(LOG_LEVEL), trace), \
$(info $0 $(strip $1) $(foreach i, $(PARAM_SEQUENCE), \
$(if $(strip $($i)),$(NEWLINE) $(strip [$i] $(if $(filter $(LOG_LEVEL), trace), \
$($i), $(wordlist 1, 20, $($(i))) $(if $(word 21, $($(i))), ...)))))))
$(if $(DEBUG_$(strip $1)),
$(info -------- <<< Begin expansion of $(strip $1)) \
$(info $(call $(0)Body,$(strip $1))) \
$(info -------- >>> End expansion of $(strip $1)) \
)
$(call $(0)Body,$(strip $1))
endef
################################################################################
# FixPath
#
# On Windows, converts a path from cygwin/unix style (e.g. /bin/foo) into
# "mixed mode" (e.g. c:/cygwin/bin/foo). On other platforms, return the path
# unchanged.
# This also converts a colon-separated list of paths to a semicolon-separated
# list.
# This is normally not needed since we use the FIXPATH prefix for command lines,
# but might be needed in certain circumstances.
#
# FixPathFile is the file version of FixPath. It instead takes a file with paths in $1
# and outputs the 'fixed' paths into the file in $2. If the file in $2 already exists
# it is overwritten.
# On non-Windows platforms this instead does a copy, so that $2 can still be used
# as a depenendency of a make rule, instead of having to conditionally depend on
# $1 instead, based on the target platform.
ifeq ($(call isTargetOs, windows), true)
FixPath = \
$(strip $(subst \,\\, $(shell $(FIXPATH_BASE) print $(patsubst $(FIXPATH), , $1))))
FixPathFile = \
$(shell $(FIXPATH_BASE) convert $1 $2)
else
FixPath = \
$1
FixPathFile = \
$(shell $(CP) $1 $2)
endif
################################################################################
# DependOnVariable
#
# This macro takes a variable name and puts the value in a file only if the
# value has changed since last. The name of the file is returned. This can be
# used to create rule dependencies on make variable values. The following
# example would get rebuilt if the value of SOME_VAR was changed:
#
# path/to/some-file: $(call DependOnVariable, SOME_VAR)
# echo $(SOME_VAR) > $@
#
# Note that leading and trailing white space in the value is ignored.
#
# Defines the sub directory structure to store variable value file in
DependOnVariableDirName = \
$(strip $(addsuffix $(if $(MODULE),/$(MODULE)), \
$(subst $(WORKSPACE_ROOT)/,, $(if $(filter /%, $(firstword $(MAKEFILE_LIST))), \
$(firstword $(MAKEFILE_LIST)), \
$(CURDIR)/$(firstword $(MAKEFILE_LIST))))))
# Defines the name of the file to store variable value in. Generates a name
# unless parameter 2 is given.
# Param 1 - Name of variable
# Param 2 - (optional) name of file to store value in
DependOnVariableFileName = \
$(strip $(if $(strip $2), $2, \
$(MAKESUPPORT_OUTPUTDIR)/vardeps/$(DependOnVariableDirName)/$(strip $1).vardeps))
# Writes the vardeps file. Assumes $1_filename has been setup
# Param 1 - Name of variable
DependOnVariableWriteFile = \
$(call MakeDir, $(dir $($1_filename))) \
$(call WriteFile, $1_old := $(call DoubleDollar,$(call EscapeHash,$($1))), \
$($1_filename)) \
# Does the actual work with parameters stripped.
# If the file exists AND the contents is the same as the variable, do nothing
# else print a new file.
# Always returns the name of the file where the value was printed.
# Param 1 - Name of variable
# Param 2 - (optional) name of file to store value in
DependOnVariableHelper = \
$(strip \
$(eval $1_filename := $(call DependOnVariableFileName, $1, $2)) \
$(if $(wildcard $($1_filename)), \
$(eval include $($1_filename)) \
$(if $(call equals, $(strip $($1)), $(strip $($1_old))),, \
$(if $(findstring $(LOG_LEVEL), trace), \
$(info NewVariable $1: >$(strip $($1))<) \
$(info OldVariable $1: >$(strip $($1_old))<) \
) \
$(call DependOnVariableWriteFile,$1) \
) \
, \
$(call DependOnVariableWriteFile,$1) \
) \
$($1_filename) \
)
# Main macro
# Param 1 - Name of variable
# Param 2 - (optional) name of file to store value in
DependOnVariable = \
$(call DependOnVariableHelper,$(strip $1),$(strip $2))
# LogCmdlines is only intended to be used by ExecuteWithLog
ifeq ($(LOG_CMDLINES), true)
LogCmdlines = $(info $(strip $1))
else
LogCmdlines =
endif
# Check if the command line contains redirection, that is <, > or >>,
# and if so, return a value that is interpreted as true in a make $(if)
# construct.
is_redirect = \
$(if $(filter < > >>, $1), true)
################################################################################
# ExecuteWithLog will run a command and log the output appropriately. This is
# meant to be used by commands that do "real" work, like a compilation.
# The output is stored in a specified log file, which is displayed at the end
# of the build in case of failure. The command line itself is stored in a file,
# and also logged to stdout if the LOG=cmdlines option has been given.
#
# Param 1 - The path to base the name of the log file / command line file on
# Param 2 - The command to run
ExecuteWithLog = \
$(call LogCmdlines, Executing: \
[$(if $(call is_redirect, $2),$(LEFT_PAREN) )$(strip $2)$(if $(call \
is_redirect, $2), $(RIGHT_PAREN))]) \
$(call MakeDir, $(dir $(strip $1)) $(MAKESUPPORT_OUTPUTDIR)/failure-logs) \
$(call WriteFile, $2, $(strip $1).cmdline) \
( $(RM) $(strip $1).log && \
$(if $(call is_redirect, $2),$(LEFT_PAREN) )$(strip $2)$(if $(call \
is_redirect, $2), $(RIGHT_PAREN)) \
> >($(TEE) -a $(strip $1).log) 2> >($(TEE) -a $(strip $1).log >&2) || \
( exitcode=$(DOLLAR)? && \
$(CP) $(strip $1).log $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst \
/,_,$(patsubst $(OUTPUTDIR)/%,%,$(strip $1))).log && \
$(CP) $(strip $1).cmdline $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst \
/,_,$(patsubst $(OUTPUTDIR)/%,%,$(strip $1))).cmdline && \
exit $(DOLLAR)exitcode ) )
################################################################################
include MakeIncludeEnd.gmk
endif # include guard

View file

@ -0,0 +1,42 @@
#
# Copyright (c) 2025, 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.
#
################################################################################
# MakeFileEnd.gmk should be included last of all in all top-level makefiles
################################################################################
# Hook to include the corresponding custom file, if present.
ifneq ($(NO_CUSTOM_EXTENSIONS), true)
CUSTOM_POST_NAME := $(subst .gmk,-post.gmk, $(THIS_MAKEFILE))
$(eval $(call IncludeCustomExtension, $(CUSTOM_POST_NAME)))
endif
all: $(TARGETS)
ifeq ($(LOG_FLOW), true)
$(info :Leave $(THIS_MAKEFILE) [now executing rules])
endif
.PHONY: default all

View file

@ -0,0 +1,66 @@
#
# Copyright (c) 2025, 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.
#
################################################################################
# MakeFileStart.gmk should be included first of all in all top-level makefiles
################################################################################
# This must be the first rule
default: $(if $(DEFAULT_TARGET), $(DEFAULT_TARGET), all)
THIS_MAKEFILE_PATH := $(firstword $(MAKEFILE_LIST))
ifeq ($(SPEC), )
$(error $(THIS_MAKEFILE_PATH): SPEC is not set)
endif
ifeq ($(wildcard $(SPEC)), )
$(error $(THIS_MAKEFILE_PATH): spec.gmk file $(SPEC) is missing)
endif
ifneq ($(words $(MAKEFILE_LIST)), 2)
$(error $(THIS_MAKEFILE_PATH): This file is not supposed to be included)
endif
# We need spec.gmk to get $(TOPDIR)
include $(SPEC)
THIS_MAKEFILE := $(patsubst make/%,%,$(patsubst $(TOPDIR_ALT)/make/%,%,$(patsubst $(TOPDIR)/%,%,$(THIS_MAKEFILE_PATH))))
ifeq ($(LOG_FLOW), true)
$(info :Enter $(THIS_MAKEFILE))
endif
include $(TOPDIR)/make/common/MakeBase.gmk
TARGETS :=
all:
# Hook to include the corresponding custom file, if present.
ifneq ($(NO_CUSTOM_EXTENSIONS), true)
CUSTOM_PRE_NAME := $(subst .gmk,-pre.gmk, $(THIS_MAKEFILE))
$(eval $(call IncludeCustomExtension, $(CUSTOM_PRE_NAME)))
endif

244
make/common/MakeIO.gmk Normal file
View file

@ -0,0 +1,244 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# Functions for dealing with reading and writing from makefiles. Prior to GNU
# Make 4.0, this was tricky business.
################################################################################
################################################################################
# ListPathsSafely can be used to print command parameters to a file. This is
# typically done if the command line length risk being too long for the
# OS/shell. In later make versions, the file function can be used for this
# purpose. For earlier versions, a more complex implementation is provided.
#
# The function ListPathsSafely can be called either directly or, more commonly
# from a recipe line. If called from a recipe, it will be executed in the
# evaluation phase of that recipe, which means that it will write to the file
# before any other line in the recipe has been run.
ifeq ($(HAS_FILE_FUNCTION), true)
# Param 1 - Name of variable containing paths/arguments to output
# Param 2 - File to print to
# Param 3 - Set to true to append to file instead of overwriting
define ListPathsSafely
$$(call MakeDir, $$(dir $$(strip $2)))
$$(file $$(if $$(filter true, $$(strip $3)),>>,>) \
$$(strip $2),$$(subst $$(SPACE),$$(NEWLINE),$$(strip $$($$(strip $1)))))
endef
else # HAS_FILE_FUNCTION = false
$(eval compress_paths = \
$(strip $(shell $(CAT) $(TOPDIR)/make/common/support/ListPathsSafely-pre-compress.incl)))
compress_paths += \
$(subst $(TOPDIR),X97, \
$(subst $(OUTPUTDIR),X98, \
$(subst X,X00, \
$(subst $(SPACE),\n,$(strip $1)))))
$(eval compress_paths += \
$(strip $(shell $(CAT) $(TOPDIR)/make/common/support/ListPathsSafely-post-compress.incl)))
decompress_paths = $(SED) -f $(TOPDIR)/make/common/support/ListPathsSafely-uncompress.sed \
-e 's|X99|\\n|g' \
-e 's|X98|$(OUTPUTDIR)|g' -e 's|X97|$(TOPDIR)|g' \
-e 's|X00|X|g'
ListPathsSafely_IfPrintf = \
$(if $(word $3, $($(strip $1))), \
$(shell $(PRINTF) -- "$(strip $(call EscapeDollar, \
$(call compress_paths, $(wordlist $3, $4, $($(strip $1))))))\n" \
| $(decompress_paths) >> $2))
# Param 1 - Name of variable containing paths/arguments to output
# Param 2 - File to print to
# Param 3 - Set to true to append to file instead of overwriting
define ListPathsSafely
ifneq ($$(word 30001, $$($$(strip $1))), )
$$(error Cannot list safely more than 30000 paths. $1 has $$(words $$($$(strip $1))) paths!)
endif
$$(call MakeDir, $$(dir $2))
ifneq ($$(strip $3), true)
$$(shell $(RM) $$(strip $2))
endif
$$(call ListPathsSafely_IfPrintf,$1,$2,1,250)
$$(call ListPathsSafely_IfPrintf,$1,$2,251,500)
$$(call ListPathsSafely_IfPrintf,$1,$2,501,750)
$$(call ListPathsSafely_IfPrintf,$1,$2,751,1000)
$$(call ListPathsSafely_IfPrintf,$1,$2,1001,1250)
$$(call ListPathsSafely_IfPrintf,$1,$2,1251,1500)
$$(call ListPathsSafely_IfPrintf,$1,$2,1501,1750)
$$(call ListPathsSafely_IfPrintf,$1,$2,1751,2000)
$$(call ListPathsSafely_IfPrintf,$1,$2,2001,2250)
$$(call ListPathsSafely_IfPrintf,$1,$2,2251,2500)
$$(call ListPathsSafely_IfPrintf,$1,$2,2501,2750)
$$(call ListPathsSafely_IfPrintf,$1,$2,2751,3000)
$$(call ListPathsSafely_IfPrintf,$1,$2,3001,3250)
$$(call ListPathsSafely_IfPrintf,$1,$2,3251,3500)
$$(call ListPathsSafely_IfPrintf,$1,$2,3501,3750)
$$(call ListPathsSafely_IfPrintf,$1,$2,3751,4000)
$$(call ListPathsSafely_IfPrintf,$1,$2,4001,4250)
$$(call ListPathsSafely_IfPrintf,$1,$2,4251,4500)
$$(call ListPathsSafely_IfPrintf,$1,$2,4501,4750)
$$(call ListPathsSafely_IfPrintf,$1,$2,4751,5000)
$$(call ListPathsSafely_IfPrintf,$1,$2,5001,5250)
$$(call ListPathsSafely_IfPrintf,$1,$2,5251,5500)
$$(call ListPathsSafely_IfPrintf,$1,$2,5501,5750)
$$(call ListPathsSafely_IfPrintf,$1,$2,5751,6000)
$$(call ListPathsSafely_IfPrintf,$1,$2,6001,6250)
$$(call ListPathsSafely_IfPrintf,$1,$2,6251,6500)
$$(call ListPathsSafely_IfPrintf,$1,$2,6501,6750)
$$(call ListPathsSafely_IfPrintf,$1,$2,6751,7000)
$$(call ListPathsSafely_IfPrintf,$1,$2,7001,7250)
$$(call ListPathsSafely_IfPrintf,$1,$2,7251,7500)
$$(call ListPathsSafely_IfPrintf,$1,$2,7501,7750)
$$(call ListPathsSafely_IfPrintf,$1,$2,7751,8000)
$$(call ListPathsSafely_IfPrintf,$1,$2,8001,8250)
$$(call ListPathsSafely_IfPrintf,$1,$2,8251,8500)
$$(call ListPathsSafely_IfPrintf,$1,$2,8501,8750)
$$(call ListPathsSafely_IfPrintf,$1,$2,8751,9000)
$$(call ListPathsSafely_IfPrintf,$1,$2,9001,9250)
$$(call ListPathsSafely_IfPrintf,$1,$2,9251,9500)
$$(call ListPathsSafely_IfPrintf,$1,$2,9501,9750)
$$(call ListPathsSafely_IfPrintf,$1,$2,9751,10000)
$$(call ListPathsSafely_IfPrintf,$1,$2,10001,10250)
$$(call ListPathsSafely_IfPrintf,$1,$2,10251,10500)
$$(call ListPathsSafely_IfPrintf,$1,$2,10501,10750)
$$(call ListPathsSafely_IfPrintf,$1,$2,10751,11000)
$$(call ListPathsSafely_IfPrintf,$1,$2,11001,11250)
$$(call ListPathsSafely_IfPrintf,$1,$2,11251,11500)
$$(call ListPathsSafely_IfPrintf,$1,$2,11501,11750)
$$(call ListPathsSafely_IfPrintf,$1,$2,11751,12000)
$$(call ListPathsSafely_IfPrintf,$1,$2,12001,12250)
$$(call ListPathsSafely_IfPrintf,$1,$2,12251,12500)
$$(call ListPathsSafely_IfPrintf,$1,$2,12501,12750)
$$(call ListPathsSafely_IfPrintf,$1,$2,12751,13000)
$$(call ListPathsSafely_IfPrintf,$1,$2,13001,13250)
$$(call ListPathsSafely_IfPrintf,$1,$2,13251,13500)
$$(call ListPathsSafely_IfPrintf,$1,$2,13501,13750)
$$(call ListPathsSafely_IfPrintf,$1,$2,13751,14000)
$$(call ListPathsSafely_IfPrintf,$1,$2,14001,14250)
$$(call ListPathsSafely_IfPrintf,$1,$2,14251,14500)
$$(call ListPathsSafely_IfPrintf,$1,$2,14501,14750)
$$(call ListPathsSafely_IfPrintf,$1,$2,14751,15000)
$$(call ListPathsSafely_IfPrintf,$1,$2,15001,15250)
$$(call ListPathsSafely_IfPrintf,$1,$2,15251,15500)
$$(call ListPathsSafely_IfPrintf,$1,$2,15501,15750)
$$(call ListPathsSafely_IfPrintf,$1,$2,15751,16000)
$$(call ListPathsSafely_IfPrintf,$1,$2,16001,16250)
$$(call ListPathsSafely_IfPrintf,$1,$2,16251,16500)
$$(call ListPathsSafely_IfPrintf,$1,$2,16501,16750)
$$(call ListPathsSafely_IfPrintf,$1,$2,16751,17000)
$$(call ListPathsSafely_IfPrintf,$1,$2,17001,17250)
$$(call ListPathsSafely_IfPrintf,$1,$2,17251,17500)
$$(call ListPathsSafely_IfPrintf,$1,$2,17501,17750)
$$(call ListPathsSafely_IfPrintf,$1,$2,17751,18000)
$$(call ListPathsSafely_IfPrintf,$1,$2,18001,18250)
$$(call ListPathsSafely_IfPrintf,$1,$2,18251,18500)
$$(call ListPathsSafely_IfPrintf,$1,$2,18501,18750)
$$(call ListPathsSafely_IfPrintf,$1,$2,18751,19000)
$$(call ListPathsSafely_IfPrintf,$1,$2,19001,19250)
$$(call ListPathsSafely_IfPrintf,$1,$2,19251,19500)
$$(call ListPathsSafely_IfPrintf,$1,$2,19501,19750)
$$(call ListPathsSafely_IfPrintf,$1,$2,19751,20000)
$$(call ListPathsSafely_IfPrintf,$1,$2,20001,20250)
$$(call ListPathsSafely_IfPrintf,$1,$2,20251,20500)
$$(call ListPathsSafely_IfPrintf,$1,$2,20501,20750)
$$(call ListPathsSafely_IfPrintf,$1,$2,20751,21000)
$$(call ListPathsSafely_IfPrintf,$1,$2,21001,21250)
$$(call ListPathsSafely_IfPrintf,$1,$2,21251,21500)
$$(call ListPathsSafely_IfPrintf,$1,$2,21501,21750)
$$(call ListPathsSafely_IfPrintf,$1,$2,21751,22000)
$$(call ListPathsSafely_IfPrintf,$1,$2,22001,22250)
$$(call ListPathsSafely_IfPrintf,$1,$2,22251,22500)
$$(call ListPathsSafely_IfPrintf,$1,$2,22501,22750)
$$(call ListPathsSafely_IfPrintf,$1,$2,22751,23000)
$$(call ListPathsSafely_IfPrintf,$1,$2,23001,23250)
$$(call ListPathsSafely_IfPrintf,$1,$2,23251,23500)
$$(call ListPathsSafely_IfPrintf,$1,$2,23501,23750)
$$(call ListPathsSafely_IfPrintf,$1,$2,23751,24000)
$$(call ListPathsSafely_IfPrintf,$1,$2,24001,24250)
$$(call ListPathsSafely_IfPrintf,$1,$2,24251,24500)
$$(call ListPathsSafely_IfPrintf,$1,$2,24501,24750)
$$(call ListPathsSafely_IfPrintf,$1,$2,24751,25000)
$$(call ListPathsSafely_IfPrintf,$1,$2,25001,25250)
$$(call ListPathsSafely_IfPrintf,$1,$2,25251,25500)
$$(call ListPathsSafely_IfPrintf,$1,$2,25501,25750)
$$(call ListPathsSafely_IfPrintf,$1,$2,25751,26000)
$$(call ListPathsSafely_IfPrintf,$1,$2,26001,26250)
$$(call ListPathsSafely_IfPrintf,$1,$2,26251,26500)
$$(call ListPathsSafely_IfPrintf,$1,$2,26501,26750)
$$(call ListPathsSafely_IfPrintf,$1,$2,26751,27000)
$$(call ListPathsSafely_IfPrintf,$1,$2,27001,27250)
$$(call ListPathsSafely_IfPrintf,$1,$2,27251,27500)
$$(call ListPathsSafely_IfPrintf,$1,$2,27501,27750)
$$(call ListPathsSafely_IfPrintf,$1,$2,27751,28000)
$$(call ListPathsSafely_IfPrintf,$1,$2,28001,28250)
$$(call ListPathsSafely_IfPrintf,$1,$2,28251,28500)
$$(call ListPathsSafely_IfPrintf,$1,$2,28501,28750)
$$(call ListPathsSafely_IfPrintf,$1,$2,28751,29000)
$$(call ListPathsSafely_IfPrintf,$1,$2,29001,29250)
$$(call ListPathsSafely_IfPrintf,$1,$2,29251,29500)
$$(call ListPathsSafely_IfPrintf,$1,$2,29501,29750)
$$(call ListPathsSafely_IfPrintf,$1,$2,29751,30000)
endef
endif # HAS_FILE_FUNCTION
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,50 @@
#
# Copyright (c) 2025, 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.
#
################################################################################
# MakeIncludeEnd.gmk should be included last of all in all include files
################################################################################
ifneq ($(INCLUDE_GUARD_$(THIS_INCLUDE)), true)
# This was the first time this file was included. Prevent future inclusion.
INCLUDE_GUARD_$(THIS_INCLUDE) := true
# Hook to include the corresponding custom file, if present.
ifneq ($(NO_CUSTOM_EXTENSIONS), true)
CUSTOM_POST_NAME := $(subst .gmk,-post.gmk, $(THIS_INCLUDE))
$(eval $(call IncludeCustomExtension, $(CUSTOM_POST_NAME)))
endif
endif
# Pop our helper name off the stack
INCLUDE_STACK := $(wordlist 2, $(words $(INCLUDE_STACK)), $(INCLUDE_STACK))
# Print an indented message, also counting the top-level makefile as a level
ifeq ($(LOG_FLOW), true)
$(info :$(foreach s, top $(INCLUDE_STACK) $(SNIPPET_STACK), )Leave $(THIS_INCLUDE))
endif
# Restore the previous helper name
THIS_INCLUDE := $(firstword $(INCLUDE_STACK))

View file

@ -0,0 +1,82 @@
#
# Copyright (c) 2025, 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.
#
################################################################################
# MakeIncludeStart.gmk should be included first of all in all include files
################################################################################
# Get the next to last word (by prepending a padding element)
THIS_INCLUDE_PATH := $(word $(words ${MAKEFILE_LIST}),padding ${MAKEFILE_LIST})
THIS_INCLUDE := $(patsubst $(TOPDIR_ALT)/make/%,%,$(patsubst $(TOPDIR)/make/%,%,$(THIS_INCLUDE_PATH)))
# Print an indented message, also counting the top-level makefile as a level
ifneq ($(INCLUDE_GUARD_$(THIS_INCLUDE)), true)
THIS_INCLUDE_MSG := include
else
THIS_INCLUDE_MSG := included already
endif
ifeq ($(LOG_FLOW), true)
$(info :$(foreach s, top $(INCLUDE_STACK) $(SNIPPET_STACK), )Enter $(THIS_INCLUDE) [$(THIS_INCLUDE_MSG)])
endif
ifneq ($(filter $(THIS_INCLUDE), $(INCLUDE_STACK)), )
$(error Internal makefile error: Include loop detected: $(THIS_INCLUDE) $(INCLUDE_STACK))
endif
ifeq ($(words $(MAKEFILE_LIST)), 2)
$(error $(THIS_INCLUDE_PATH): This file is supposed to be included)
endif
# In a preinit environment, we do not have any SPEC
ifneq ($(IS_PREINIT_ENV), true)
ifeq ($(SPEC), )
$(error $(THIS_INCLUDE_PATH): SPEC is not set)
endif
ifeq ($(wildcard $(SPEC)), )
$(error $(THIS_INCLUDE_PATH): spec.gmk file $(SPEC) is missing)
endif
ifneq ($(MAKEBASE_INCLUDED), true)
$(error $(THIS_INCLUDE_PATH): MakeBase.gmk is not included)
endif
endif
# Push our helper name onto the stack
INCLUDE_STACK := $(THIS_INCLUDE) $(INCLUDE_STACK)
# Setup an automatic include guard
ifneq ($(INCLUDE_GUARD_$(THIS_INCLUDE)), true)
INCLUDE := true
# Hook to include the corresponding custom file, if present.
ifneq ($(NO_CUSTOM_EXTENSIONS), true)
CUSTOM_PRE_NAME := $(subst .gmk,-pre.gmk, $(THIS_INCLUDE))
$(eval $(call IncludeCustomExtension, $(CUSTOM_PRE_NAME)))
endif
else
INCLUDE := false
endif

View file

@ -0,0 +1,45 @@
#
# Copyright (c) 2025, 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.
#
################################################################################
# MakeSnippetEnd.gmk should be included after including a makefile snippet
################################################################################
# Hook to include the corresponding custom file, if present.
ifneq ($(NO_CUSTOM_EXTENSIONS), true)
CUSTOM_POST_NAME := $(subst .gmk,-post.gmk, $(THIS_SNIPPET))
$(eval $(call IncludeCustomExtension, $(CUSTOM_POST_NAME)))
endif
# Pop our helper name off the stack
SNIPPET_STACK := $(wordlist 2, $(words $(SNIPPET_STACK)), $(SNIPPET_STACK))
# Print an indented message, also counting the top-level makefile as a level
ifeq ($(LOG_FLOW), true)
$(info :$(foreach s, top $(INCLUDE_STACK) $(SNIPPET_STACK), )Leave $(THIS_SNIPPET))
endif
# Restore the previous helper name
THIS_SNIPPET := $(firstword $(SNIPPET_STACK))

View file

@ -0,0 +1,46 @@
#
# Copyright (c) 2025, 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.
#
################################################################################
# MakeSnippetStart.gmk should be included before including a makefile snippet
################################################################################
ifeq ($(THIS_SNIPPET), )
$(error Internal makefile error: THIS_SNIPPET is not defined)
endif
# Print an indented message, also counting the top-level makefile as a level
ifeq ($(LOG_FLOW), true)
$(info :$(foreach s, top $(INCLUDE_STACK) $(SNIPPET_STACK), )Enter $(THIS_SNIPPET) [snippet])
endif
# Push our helper name onto the stack
SNIPPET_STACK := $(THIS_SNIPPET) $(SNIPPET_STACK)
# Hook to include the corresponding custom file, if present.
ifneq ($(NO_CUSTOM_EXTENSIONS), true)
CUSTOM_PRE_NAME := $(subst .gmk,-pre.gmk, $(THIS_SNIPPET))
$(eval $(call IncludeCustomExtension, $(CUSTOM_PRE_NAME)))
endif

336
make/common/Modules.gmk Normal file
View file

@ -0,0 +1,336 @@
#
# Copyright (c) 2014, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# Setup module sets for classloaders
include $(TOPDIR)/make/conf/module-loader-map.conf
# Append platform-specific and upgradeable modules
PLATFORM_MODULES += $(PLATFORM_MODULES_$(OPENJDK_TARGET_OS)) \
$(UPGRADEABLE_PLATFORM_MODULES) $(CUSTOM_UPGRADEABLE_PLATFORM_MODULES)
################################################################################
# Setup module sets for docs
include $(TOPDIR)/make/conf/docs-modules.conf
################################################################################
# Setup module sets needed by the build system
include $(TOPDIR)/make/conf/build-module-sets.conf
################################################################################
# Depending on the configuration, we might need to filter out some modules that
# normally should have been included
# Some platforms don't have the serviceability agent
ifeq ($(INCLUDE_SA), false)
MODULES_FILTER += jdk.hotspot.agent
endif
# Filter out jvmci specific modules if jvmci is disabled
ifeq ($(INCLUDE_JVMCI), false)
MODULES_FILTER += jdk.internal.vm.ci
MODULES_FILTER += jdk.graal.compiler
MODULES_FILTER += jdk.graal.compiler.management
endif
# jpackage is only on windows, macosx, and linux
ifeq ($(call isTargetOs, windows macosx linux), false)
MODULES_FILTER += jdk.jpackage
endif
################################################################################
# Module list macros
# Use append so that the custom extension may add to these variables
GENERATED_SRC_DIRS += \
$(SUPPORT_OUTPUTDIR)/gensrc \
#
TOP_SRC_DIRS += \
$(TOPDIR)/src \
#
SRC_SUBDIRS += $(OPENJDK_TARGET_OS)/classes
ifneq ($(OPENJDK_TARGET_OS), $(OPENJDK_TARGET_OS_TYPE))
SRC_SUBDIRS += $(OPENJDK_TARGET_OS_TYPE)/classes
endif
SRC_SUBDIRS += share/classes
SPEC_SUBDIRS += share/specs
MAN_SUBDIRS += share/man $(TARGET_OS)/man
# The docs should include the sum of all man pages for all platforms
MAN_DOCS_SUBDIRS += share/man windows/man
# Find all module-info.java files for the current build target platform and
# configuration.
# Param 1 - Module to find for, set to * for finding all
FindAllModuleInfos = \
$(sort $(wildcard \
$(foreach sub, $(SRC_SUBDIRS), \
$(patsubst %,%/$(strip $1)/$(sub)/module-info.java, $(TOP_SRC_DIRS))) \
$(patsubst %,%/$(strip $1)/module-info.java, $(IMPORT_MODULES_SRC))))
# Find module-info.java files in the specific source dir
# Param 1 - Src dir to find module-info.java files in
FindModuleInfosForSrcDir = \
$(wildcard \
$(foreach sub, $(SRC_SUBDIRS), \
$(patsubst %,%/*/$(sub)/module-info.java, $(strip $1)) \
) \
$(patsubst %,%/*/module-info.java, $(strip $1)) \
)
# Extract the module names from the paths of module-info.java files. The
# position of the module directory differs depending on if this is an imported
# src dir or not.
GetModuleNameFromModuleInfo = \
$(strip $(foreach mi, $1, \
$(if $(filter $(addsuffix %, $(IMPORT_MODULES_SRC)), $(mi)), \
$(notdir $(patsubst %/,%, $(dir $(mi)))), \
$(notdir $(patsubst %/,%, $(dir $(patsubst %/,%, $(dir $(patsubst %/,%, $(dir $(mi)))))))))))
# Find all modules by looking for module-info.java files and looking at parent
# directories.
FindAllModules = \
$(sort $(filter-out $(MODULES_FILTER), \
$(call GetModuleNameFromModuleInfo, $(MODULE_INFOS))))
# Find all modules in a specific src dir
# Param 1 - Src dir to find modules in
FindModulesForSrcDir = \
$(sort $(filter-out $(MODULES_FILTER), \
$(call GetModuleNameFromModuleInfo, $(call FindModuleInfosForSrcDir, $1)) \
))
FindImportedModules = \
$(filter-out $(MODULES_FILTER), \
$(if $(IMPORT_MODULES_CLASSES), $(notdir $(wildcard $(IMPORT_MODULES_CLASSES)/*))))
# Find all source dirs for a particular module
# $1 - Module to find source dirs for
FindModuleSrcDirs = \
$(strip $(wildcard \
$(addsuffix /$(strip $1), $(GENERATED_SRC_DIRS) $(IMPORT_MODULES_SRC)) \
$(foreach sub, $(SRC_SUBDIRS), $(addsuffix /$(strip $1)/$(sub), $(TOP_SRC_DIRS)))))
# Find all specs dirs for a particular module
# $1 - Module to find specs dirs for
FindModuleSpecsDirs = \
$(strip $(wildcard \
$(foreach sub, $(SPEC_SUBDIRS), $(addsuffix /$(strip $1)/$(sub), $(TOP_SRC_DIRS)))))
# Find all man dirs for a particular module
# $1 - Module to find man dirs for
FindModuleManDirs = \
$(strip $(wildcard \
$(foreach sub, $(MAN_SUBDIRS), $(addsuffix /$(strip $1)/$(sub), $(TOP_SRC_DIRS)))))
FindModuleManDirsForDocs = \
$(strip $(wildcard \
$(foreach sub, $(MAN_DOCS_SUBDIRS), $(addsuffix /$(strip $1)/$(sub), $(TOP_SRC_DIRS)))))
# Construct the complete module source path
GetModuleSrcPath = \
$(call PathList, \
$(addsuffix /*, $(GENERATED_SRC_DIRS) $(IMPORT_MODULES_SRC)) \
$(foreach sub, $(SRC_SUBDIRS), $(addsuffix /*/$(sub), $(TOP_SRC_DIRS))))
################################################################################
# Extract module dependencies from module-info.java files, both normal
# dependencies ("requires"), and indirect exports ("requires transitive").
MODULE_DEPS_MAKEFILE := $(MAKESUPPORT_OUTPUTDIR)/module-deps.gmk
MODULE_INFOS := $(call FindAllModuleInfos, *)
ifeq ($(GENERATE_MODULE_DEPS_FILE), true)
$(MODULE_DEPS_MAKEFILE): $(MODULE_INFOS) \
$(call DependOnVariable, MODULE_INFOS, $(MAKESUPPORT_OUTPUTDIR)/MODULE_INFOS.vardeps)
$(call MakeTargetDir)
$(RM) $@
$(foreach m, $(MODULE_INFOS), \
( $(PRINTF) "DEPS_%s := " "$(call GetModuleNameFromModuleInfo, $m)" && \
$(AWK) -v MODULE=$(call GetModuleNameFromModuleInfo, $m) ' \
BEGIN { if (MODULE != "java.base") printf(" java.base"); } \
/^ *requires/ { sub(/;/, ""); \
sub(/requires /, " "); \
sub(/ static /, " "); \
sub(/ transitive /, " "); \
sub(/\/\/.*/, ""); \
sub(/\/\*.*\*\//, ""); \
gsub(/^ +\*.*/, ""); \
gsub(/ /, ""); \
gsub(/\r/, ""); \
printf(" %s", $$0) } \
END { printf("\n") }' $m && \
$(PRINTF) "TRANSITIVE_MODULES_%s := " "$(call GetModuleNameFromModuleInfo, $m)" && \
$(AWK) -v MODULE=$(call GetModuleNameFromModuleInfo, $m) ' \
BEGIN { if (MODULE != "java.base") printf(" java.base"); } \
/^ *requires *transitive/ { \
sub(/;/, ""); \
sub(/requires/, ""); \
sub(/transitive/, ""); \
sub(/\/\/.*/, ""); \
sub(/\/\*.*\*\//, ""); \
gsub(/^ +\*.*/, ""); \
gsub(/ /, ""); \
gsub(/\r/, ""); \
printf(" %s", $$0) } \
END { printf("\n") }' $m \
) >> $@ $(NEWLINE))
endif
-include $(MODULE_DEPS_MAKEFILE)
# Find dependencies ("requires") for a given module.
# Param 1: Module to find dependencies for.
FindDepsForModule = \
$(filter-out $(IMPORT_MODULES), $(DEPS_$(strip $1)))
# Find dependencies ("requires") transitively in 3 levels for a given module.
# Param 1: Module to find dependencies for.
FindTransitiveDepsForModule = \
$(sort $(call FindDepsForModule, $1) \
$(foreach m, $(call FindDepsForModule, $1), \
$(call FindDepsForModule, $m) \
$(foreach n, $(call FindDepsForModule, $m), \
$(call FindDepsForModule, $n))))
# Find dependencies ("requires") transitively in 3 levels for a set of modules.
# Param 1: List of modules to find dependencies for.
FindTransitiveDepsForModules = \
$(sort $(foreach m, $1, $(call FindTransitiveDepsForModule, $m)))
# Find indirect exported modules ("requires transitive") for a given module .
# Param 1: Module to find indirect exported modules for.
FindIndirectExportsForModule = \
$(TRANSITIVE_MODULES_$(strip $1))
# Finds indirect exported modules transitively in 3 levels for a given module.
# Param 1: Module to find indirect exported modules for.
FindTransitiveIndirectDepsForModule = \
$(sort $(call FindIndirectExportsForModule, $1) \
$(foreach m, $(call FindIndirectExportsForModule, $1), \
$(call FindIndirectExportsForModule, $m) \
$(foreach n, $(call FindIndirectExportsForModule, $m), \
$(call FindIndirectExportsForModule, $n))))
# Finds indirect exported modules transitively in 3 levels for a set of modules.
# Param 1: List of modules to find indirect exported modules for.
FindTransitiveIndirectDepsForModules = \
$(sort $(foreach m, $1, $(call FindTransitiveIndirectDepsForModule, $m)))
# Upgradeable modules are those that are either defined as upgradeable or that
# require an upradeable module.
FindAllUpgradeableModules = \
$(sort $(filter-out $(MODULES_FILTER), \
$(UPGRADEABLE_PLATFORM_MODULES) $(CUSTOM_UPGRADEABLE_PLATFORM_MODULES)))
################################################################################
LEGAL_SUBDIRS += $(OPENJDK_TARGET_OS)/legal
ifneq ($(OPENJDK_TARGET_OS), $(OPENJDK_TARGET_OS_TYPE))
LEGAL_SUBDIRS += $(OPENJDK_TARGET_OS_TYPE)/legal
endif
LEGAL_SUBDIRS += share/legal
# Find all legal src dirs for a particular module
# $1 - Module to find legal dirs for
FindModuleLegalSrcDirs = \
$(strip $(wildcard \
$(addsuffix /$(strip $1), $(IMPORT_MODULES_LEGAL)) \
$(foreach sub, $(LEGAL_SUBDIRS), $(addsuffix /$(strip $1)/$(sub), $(TOP_SRC_DIRS))) \
))
################################################################################
# Param 1 - Name of module
define ReadSingleImportMetaData
ifneq ($$(wildcard $(IMPORT_MODULES_MAKE)/$$(strip $1)/build.properties), )
classloader :=
include_in_jre :=
include_in_jdk :=
include $(IMPORT_MODULES_MAKE)/$$(strip $1)/build.properties
ifeq ($$(include_in_jre), true)
JRE_MODULES += $1
endif
ifeq ($$(include_in_jdk), true)
JDK_MODULES += $1
endif
ifeq ($$(classloader), boot)
BOOT_MODULES += $1
else ifeq ($$(classloader), ext)
PLATFORM_MODULES += $1
endif
ifneq ($$(include_in_docs), false)
# defaults to true if unspecified
DOCS_MODULES += $1
endif
else
# Default to include in all
JRE_MODULES += $1
JDK_MODULES += $1
endif
endef
# Reading the imported modules metadata has a cost, so to make it available,
# a makefile needs to eval-call this macro first. After calling this, the
# following variables are populated with data from the imported modules:
# * JRE_MODULES
# * JDK_MODULES
# * BOOT_MODULES
# * PLATFORM_MODULES
define ReadImportMetaData
IMPORTED_MODULES := $$(call FindImportedModules)
$$(foreach m, $$(IMPORTED_MODULES), \
$$(eval $$(call ReadSingleImportMetaData, $$m)))
endef
################################################################################
# Get a full snippet path for the current module and a given base name.
#
# Param 1 - The base name of the snippet file to include
GetModuleSnippetName = \
$(if $(CUSTOM_MODULE_MAKE_ROOT), \
$(if $(wildcard $(CUSTOM_MODULE_MAKE_ROOT)/$(MODULE)/$(strip $1).gmk), \
$(CUSTOM_MODULE_MAKE_ROOT)/$(MODULE)/$(strip $1).gmk, \
$(wildcard modules/$(MODULE)/$(strip $1).gmk) \
), \
$(wildcard modules/$(MODULE)/$(strip $1).gmk) \
)
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,413 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# This is the top-level entry point for our native compilation and linking.
# It contains the SetupNativeCompilation macro, but is supported by helper
# macros in the make/common/native directory.
################################################################################
include MakeIO.gmk
include native/CompileFile.gmk
include native/DebugSymbols.gmk
include native/Flags.gmk
include native/Link.gmk
include native/LinkMicrosoft.gmk
include native/Paths.gmk
################################################################################
# Setup make rules for creating a native binary (a shared library or an
# executable).
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# Remaining parameters are named arguments. These include:
# NAME The base name for the resulting binary, excluding decorations (like *.exe)
# TYPE Type of binary (EXECUTABLE, LIBRARY or STATIC_LIBRARY). Default is LIBRARY.
# SUFFIX Override the default suffix for the output file
# TARGET_TYPE The type to target, BUILD or TARGET. Defaults to TARGET.
# LINK_TYPE The language to use for the linker, C or C++. Defaults to C.
# SRC one or more directory roots to scan for C/C++ files.
# CFLAGS the compiler flags to be used, used both for C and C++.
# CXXFLAGS the compiler flags to be used for c++, if set overrides CFLAGS.
# LDFLAGS the linker flags to be used, used both for C and C++.
# LDFLAGS_<toolchain> the linker flags to be used for the specified toolchain,
# used both for C and C++.
# LDFLAGS_<OS> the linker flags to be used for the specified target OS,
# used both for C and C++.
# LDFLAGS_<toolchain>_<OS> the linker flags to be used for the specified
# toolchain and target OS, used both for C and C++.
# LIBS the libraries to link to
# LIBS_<OS> the libraries to link to for the specified target OS,
# used both for C and C++.
# LIBS_<toolchain> the libraries to link to for the specified toolchain,
# used both for C and C++.
# LIBS_<toolchain>_<OS> the libraries to link to for the specified target
# OS and toolchain, used both for C and C++.
# OBJECT_DIR the directory where we store the object files
# OUTPUT_DIR the directory where the resulting binary is put
# SYMBOLS_DIR the directory where the debug symbols are put, defaults to OUTPUT_DIR
# INCLUDES only pick source from these directories
# EXCLUDES do not pick source from these directories
# INCLUDE_FILES only compile exactly these files!
# EXCLUDE_FILES with these names
# EXCLUDE_PATTERN exclude files matching any of these substrings
# EXTRA_FILES List of extra files not in any of the SRC dirs
# EXTRA_OBJECT_FILES List of extra object files to include when linking
# EXTRA_DEPS List of extra dependencies to be added to each compiled file
# EXTRA_LINK_DEPS List of extra dependencies to be added to the link stage
# VERSIONINFO_RESOURCE Input file for RC. Setting this implies that RC will be run
# RCFLAGS flags for RC.
# EMBED_MANIFEST if true, embed manifest on Windows.
# CC the C compiler to use
# CXX the C++ compiler to use
# LD the Linker to use
# AR the static linker to use
# LIB the Windows lib tool to use for creating static libraries
# AS the assembler to use
# MT the Windows MT tool to use
# RC the Windows RC tool to use
# OBJCOPY the objcopy tool for debug symbol handling
# STRIP the tool to use for stripping debug symbols
# SYSROOT_CFLAGS the compiler flags for using the specific sysroot
# SYSROOT_LDFLAGS the linker flags for using the specific sysroot
# OPTIMIZATION sets optimization level to NONE, LOW, HIGH, HIGHEST, HIGHEST_JVM, SIZE
# LINK_TIME_OPTIMIZATION if set to true, enables link time optimization
# DISABLED_WARNINGS_<toolchain> Disable the given warnings for the specified toolchain
# DISABLED_WARNINGS_<toolchain>_<OS> Disable the given warnings for the specified
# toolchain and target OS
# DISABLED_WARNINGS_C_<toolchain> Disable the given warnings for the specified toolchain
# when compiling C code
# DISABLED_WARNINGS_C_<toolchain>_<OS> Disable the given warnings for the specified
# toolchain and target OS when compiling C code
# DISABLED_WARNINGS_CXX_<toolchain> Disable the given warnings for the specified
# toolchain when compiling C++ code
# DISABLED_WARNINGS_CXX_<toolchain>_<OS> Disable the given warnings for the specified
# toolchain and target OS when compiling C++ code
# DISABLED_WARNINGS_<toolchain>_<filename> Disable the given warnings for the specified
# toolchain when compiling the file specified by filename
# DISABLED_WARNINGS_<toolchain>_<OS>_<filename> Disable the given warnings for the specified
# toolchain and target OS when compiling the file specified by filename
# STRIP_SYMBOLS Set to false to override global strip policy and always leave
# symbols in the binary, if the toolchain allows for it
# DEBUG_SYMBOLS Set to false to disable generation of debug symbols
# COPY_DEBUG_SYMBOLS Set to false to override global setting of debug symbol copying
# ZIP_EXTERNAL_DEBUG_SYMBOLS Set to false to override global setting of debug symbol
# zipping
# STRIPFLAGS Optionally change the flags given to the strip command
# PRECOMPILED_HEADER Header file to use as precompiled header
# PRECOMPILED_HEADER_EXCLUDE List of source files that should not use PCH
# BUILD_INFO_LOG_MACRO Overrides log level of the build info log message, default LogWarn
# STATIC_LIB_EXCLUDE_OBJS exclude objects that matches from static library
#
# After being called, some variables are exported from this macro, all prefixed
# with parameter 1 followed by a '_':
# TARGET The library or executable created by the macro
# TARGET_DEPS All prerequisites for the target calculated by the macro
# ALL_OBJS All object files
# IMPORT_LIBRARY The import library created for a shared library on Windows
#
SetupNativeCompilation = $(NamedParamsMacroTemplate)
define SetupNativeCompilationBody
# When reading this code, note that macros named Setup<Foo> are just setting
# variables, and macros called Create<Foo> are setting up rules to create
# files. Macros starting with any other verb are more complicated, and can do
# all of the above, and also call directly to the shell.
###
### Prepare for compilation and linking
###
$$(eval $$(call VerifyArguments,$1))
# Setup variables for the rest of this macro to work with
$$(eval $$(call SetupBasicVariables,$1))
# Setup the toolchain to be used
$$(eval $$(call SetupToolchain,$1))
# Find all source files to compile and determine the output object file names
$$(eval $$(call SetupSourceFiles,$1))
$$(eval $$(call SetupOutputFiles,$1))
# Setup CFLAGS/CXXFLAGS based on warnings, optimizations, extra flags etc.
$$(eval $$(call SetupCompilerFlags,$1))
# Machinery needed for the build to function properly
$$(eval $$(call SetupBuildSystemSupport,$1))
$$(eval $$(call RemoveSuperfluousOutputFiles,$1))
# Need to make sure TARGET is first on list before starting to create files
$1 := $$($1_TARGET)
# Have make print information about the library when we start compiling
$$(eval $$(call PrintStartInfo,$1))
###
### Compile all native source code files
###
# Create a PCH, if requested
$$(eval $$(call CreatePrecompiledHeader,$1))
# Now call CreateCompiledNativeFile for each source file we are going to compile.
$$(foreach file, $$($1_SRCS), \
$$(eval $$(call CreateCompiledNativeFile,$1_$$(notdir $$(file)), \
FILE := $$(file), \
BASE := $1, \
)) \
)
ifeq ($(call isTargetOs, windows), true)
# On windows we need to create a resource file
$$(eval $$(call CreateWindowsResourceFile,$1))
endif
# Setup a library-wide dependency file from individual object file dependency
# files, and import it in the makefile.
$$(eval $$(call CreateDependencyFile,$1))
$$(eval $$(call ImportDependencyFile,$1))
###
### Link the object files into a native output library/executable
###
# Handle native debug symbols
$$(eval $$(call CreateDebugSymbols,$1))
# Prepare for linking
$$(eval $$(call SetupLinkerFlags,$1))
ifneq ($(TOOLCHAIN_TYPE), microsoft)
$$(eval $$(call SetupLinking,$1))
endif
$$(eval $$(call SetupObjectFileList,$1))
# Link the individually compiled files into a single unit
ifneq ($(TOOLCHAIN_TYPE), microsoft)
$$(eval $$(call CreateLinkedResult,$1))
else
$$(eval $$(call CreateLinkedResultMicrosoft,$1))
endif
ifeq ($(GENERATE_COMPILE_COMMANDS_ONLY), true)
# Override all targets (this is a hack)
$1 := $$($1_ALL_OBJS_JSON) $$($1_LDFLAGS_FILE)
TARGETS := $(filter $(MAKESUPPORT_OUTPUTDIR)/compile-commands/%, $(TARGETS))
endif
endef
################################################################################
# Verify that user passed arguments are valid
define VerifyArguments
ifeq ($$($1_NAME), )
$$(error NAME must not be empty in $1)
endif
ifneq ($$($1_NAME), $(basename $$($1_NAME)))
$$(error NAME must not contain any directory path in $1)
endif
ifneq ($(findstring $$($1_SUFFIX), $$($1_NAME)), )
$$(error NAME should be specified without suffix: $$($1_SUFFIX) in $1)
endif
ifneq ($(findstring $$($1_PREFIX), $$($1_NAME)), )
$$(error NAME should be specified without prefix: $$($1_PREFIX) in $1)
endif
ifeq ($$($1_OUTPUT_DIR), )
$$(error OUTPUT_DIR is missing in $1)
endif
ifneq ($$($1_MANIFEST), )
ifeq ($$($1_MANIFEST_VERSION), )
$$(error If MANIFEST is provided, then MANIFEST_VERSION is required in $1)
endif
endif
endef
################################################################################
# Setup basic variables
define SetupBasicVariables
# If type is unspecified, default to LIBRARY
ifeq ($$($1_TYPE), )
$1_TYPE := LIBRARY
endif
# STATIC_LIBS is set from Main.gmk when building static versions of certain
# native libraries.
ifeq ($(STATIC_LIBS), true)
$1_TYPE := STATIC_LIBRARY
# The static versions need to be redirected to different output dirs, both
# to not interfere with the main build as well as to not end up inside the
# jmods.
$1_OBJECT_DIR := $$($1_OBJECT_DIR)/static
$1_OUTPUT_DIR := $$($1_OBJECT_DIR)
endif
ifeq ($$($1_TYPE), EXECUTABLE)
$1_PREFIX :=
ifeq ($$($1_SUFFIX), )
$1_SUFFIX := $(EXECUTABLE_SUFFIX)
endif
else
$1_PREFIX := $(LIBRARY_PREFIX)
ifeq ($$($1_TYPE), LIBRARY)
ifeq ($$($1_SUFFIX), )
$1_SUFFIX := $(SHARED_LIBRARY_SUFFIX)
endif
else ifeq ($$($1_TYPE), STATIC_LIBRARY)
ifeq ($$($1_SUFFIX), )
$1_SUFFIX := $(STATIC_LIBRARY_SUFFIX)
endif
endif
endif
$1_BASENAME := $$($1_PREFIX)$$($1_NAME)$$($1_SUFFIX)
$1_TARGET := $$($1_OUTPUT_DIR)/$$($1_BASENAME)
$1_NOSUFFIX := $$($1_PREFIX)$$($1_NAME)
$1_SAFE_NAME := $$(strip $$(subst /,_, $1))
$1_UNIQUE_NAME = $$($1_TYPE)_$$(subst /,_,$$(patsubst $$(OUTPUTDIR)/%/,%,$$(dir $$($1_OBJECT_DIR))))_$$($1_NOSUFFIX)
endef
################################################################################
# Setup the toolchain variables
define SetupToolchain
ifeq ($$($1_TARGET_TYPE), BUILD)
$$(call SetIfEmpty, $1_CC, $$(BUILD_CC))
$$(call SetIfEmpty, $1_CXX, $$(BUILD_CXX))
$$(call SetIfEmpty, $1_AR, $$(BUILD_AR))
$$(call SetIfEmpty, $1_LIB, $$(BUILD_LIB))
$$(call SetIfEmpty, $1_AS, $$(BUILD_AS))
$$(call SetIfEmpty, $1_OBJCOPY, $$(BUILD_OBJCOPY))
$$(call SetIfEmpty, $1_STRIP, $$(BUILD_STRIP))
$$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $$(BUILD_SYSROOT_CFLAGS))
$$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $$(BUILD_SYSROOT_LDFLAGS))
ifeq ($$($1_LINK_TYPE), C++)
$$(call SetIfEmpty, $1_LD, $$(BUILD_LDCXX))
else
$$(call SetIfEmpty, $1_LD, $$(BUILD_LD))
endif
else
$$(call SetIfEmpty, $1_CC, $$(CC))
$$(call SetIfEmpty, $1_CXX, $$(CXX))
$$(call SetIfEmpty, $1_AR, $$(AR))
$$(call SetIfEmpty, $1_LIB, $$(LIB))
$$(call SetIfEmpty, $1_AS, $$(AS))
$$(call SetIfEmpty, $1_MT, $$(MT))
$$(call SetIfEmpty, $1_RC, $$(RC))
$$(call SetIfEmpty, $1_OBJCOPY, $$(OBJCOPY))
$$(call SetIfEmpty, $1_STRIP, $$(STRIP))
$$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $$(SYSROOT_CFLAGS))
$$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $$(SYSROOT_LDFLAGS))
ifeq ($$($1_LINK_TYPE), C++)
$$(call SetIfEmpty, $1_LD, $$(LDCXX))
else
$$(call SetIfEmpty, $1_LD, $$(LD))
endif
endif
endef
################################################################################
# Setup machinery needed by the build system
define SetupBuildSystemSupport
# Track variable changes for all variables that affect the compilation command
# lines for all object files in this setup. This includes at least all the
# variables used in the call to add_native_source below.
$1_COMPILE_VARDEPS := $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \
$$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) $$($1_OPT_CFLAGS) $$($1_OPT_CXXFLAGS) \
$$($1_CC) $$($1_CXX) $$($1_AS) $$($1_ASFLAGS)
$1_COMPILE_VARDEPS_FILE := $$(call DependOnVariable, $1_COMPILE_VARDEPS, \
$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).comp.vardeps)
endef
################################################################################
# Have make print information about the library when we start compiling
define PrintStartInfo
# Setup rule for printing progress info when compiling source files.
# This is a rough heuristic and may not always print accurate information.
# The $1_BUILD_INFO and $1_BUILD_INFO_DEPS variables are used in
# TestFilesCompilation.gmk.
$$(call SetIfEmpty, $1_BUILD_INFO_LOG_MACRO, LogWarn)
$1_BUILD_INFO_DEPS := $$($1_SRCS) $$($1_COMPILE_VARDEPS_FILE)
$1_BUILD_INFO := $$($1_OBJECT_DIR)/_build-info.marker
$$($1_BUILD_INFO): $$($1_BUILD_INFO_DEPS)
ifeq ($$(wildcard $$($1_TARGET)), )
$$(call $$($1_BUILD_INFO_LOG_MACRO), \
Creating $$(subst $$(OUTPUTDIR)/,,$$($1_TARGET)) from $$(words \
$$(filter-out %.vardeps, $$?)) file(s))
else
$$(call $$($1_BUILD_INFO_LOG_MACRO), \
$$(strip Updating $$(subst $$(OUTPUTDIR)/,,$$($1_TARGET)) \
$$(if $$(filter-out %.vardeps, $$?), \
due to $$(words $$(filter-out %.vardeps, $$?)) file(s), \
$$(if $$(filter %.vardeps, $$?), due to makefile changes))))
endif
$(TOUCH) $$@
endef
################################################################################
# Setup a library-wide dependency file from individual object file dependency
# files
define CreateDependencyFile
# Create a rule to collect all the individual make dependency files into a
# single makefile.
$1_DEPS_FILE := $$($1_OBJECT_DIR)/$1.d
$$($1_DEPS_FILE): $$($1_ALL_OBJS) $$($1_RES)
$(RM) $$@
# CD into dir to reduce risk of hitting command length limits, which
# could otherwise happen if TOPDIR is a very long path.
$(CD) $$($1_OBJECT_DIR) && $(CAT) *.d > $$@.tmp
$(CD) $$($1_OBJECT_DIR) && $(CAT) *.d.targets | $(SORT) -u >> $$@.tmp
# After generating the file, which happens after all objects have been
# compiled, copy it to .old extension. On the next make invocation, this
# .old file will be included by make.
$(CP) $$@.tmp $$@.old
$(MV) $$@.tmp $$@
$1 += $$($1_DEPS_FILE)
endef
################################################################################
# Import the dependency file into the makefile
define ImportDependencyFile
# The include must be on the .old file, which represents the state from the
# previous invocation of make. The file being included must not have a rule
# defined for it as otherwise make will think it has to run the rule before
# being able to include the file, which would be wrong since we specifically
# need the file as it was generated by a previous make invocation.
ifneq ($$(wildcard $$($1_DEPS_FILE).old), )
$1_DEPS_FILE_LOADED := true
-include $$($1_DEPS_FILE).old
endif
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,189 @@
# Copyright (c) 2017, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
include TextFileProcessing.gmk
# Helper function for SetupProcessMarkdown
# $1: The $1 from SetupProcessMarkdown
# $2: The name of the current source file, relative to the dir given in $3
# $3: The directory of the current source file
define ProcessMarkdown
$1_$2_OUTPUT_FILE := $$($1_DEST)/$$(basename $2)$$($1_FILE_EXT)
$1_$2_TARGET_DIR := $$(dir $$($1_$2_OUTPUT_FILE))
$1_$2_INPUT_FILE := $3/$2
$1_$2_MARKER := $$(subst /,_,$1_$2)
# Only continue if this target file hasn't been processed already. This lets
# the first found source file override any other with the same name.
ifeq ($$($1_$2_OUTPUT_FILE_PROCESSED), )
$1_$2_OUTPUT_FILE_PROCESSED := true
ifneq ($$($1_REPLACEMENTS), )
$1_$2_PANDOC_INPUT := $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_pre.tmp
$$(eval $$(call SetupTextFileProcessing, $1_$2_PREPROCESSED, \
SOURCE_FILES := $$($1_$2_INPUT_FILE), \
OUTPUT_FILE := $$($1_$2_PANDOC_INPUT), \
REPLACEMENTS := $$($1_REPLACEMENTS), \
))
else
$1_$2_PANDOC_INPUT := $$($1_$2_INPUT_FILE)
endif
ifneq ($$($1_POST_PROCESS), )
$1_$2_PANDOC_OUTPUT := $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_post.tmp
else
$1_$2_PANDOC_OUTPUT := $$($1_$2_OUTPUT_FILE)
endif
ifneq ($$($1_CSS), )
ifneq ($$(findstring https:/, $$($1_CSS)), )
$1_$2_CSS_OPTION := --css '$$($1_CSS)'
else
$1_$2_CSS := $$(strip $$(call RelativePath, $$($1_CSS), $$($1_$2_TARGET_DIR)))
$1_$2_CSS_OPTION := --css '$$($1_$2_CSS)'
endif
endif
# This does not need to be included in VARDEPS since it's from the actual
# source file. Only run the shell if the recipe gets executed below.
$1_$2_OPTIONS_FROM_SRC = \
$$(shell $$(GREP) _pandoc-options_: $3/$2 | $$(CUT) -d : -f 2-)
ifneq ($$($1_FILTER), )
$1_$2_OPTIONS := --filter $$($1_FILTER)
endif
$1_$2_VARDEPS := $$($1_OPTIONS) $$($1_$2_OPTIONS) $$($1_CSS) \
$$($1_REPLACEMENTS) $$($1_POST_PROCESS)
$1_$2_VARDEPS_FILE := $$(call DependOnVariable, $1_$2_VARDEPS, \
$$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER).vardeps)
$$($1_$2_PANDOC_OUTPUT): $$($1_$2_PANDOC_INPUT) $$($1_$2_VARDEPS_FILE) $$($1_EXTRA_DEPS)
$$(call LogInfo, Converting $2 to $$($1_FORMAT))
$$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$(dir $$($1_$2_PANDOC_OUTPUT)))
$$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER), \
$$(PANDOC) $$($1_OPTIONS) -f $$(PANDOC_MARKDOWN_FLAG) \
-t $$($1_FORMAT) --eol=lf --standalone \
$$($1_$2_CSS_OPTION) $$($1_$2_OPTIONS_FROM_SRC) $$($1_$2_OPTIONS) \
'$$($1_$2_PANDOC_INPUT)' -o '$$($1_$2_PANDOC_OUTPUT)')
ifneq ($$(findstring $$(LOG_LEVEL), debug trace), )
TOO_LONG_LINES=`$$(GREP) -E -e '^.{80}.+$$$$' $$<` || true ; \
if [ "x$$$$TOO_LONG_LINES" != x ]; then \
$$(ECHO) "Warning: Unsuitable markdown in $$<:" ; \
$$(ECHO) "The following lines are longer than 80 characters:" ; \
$$(GREP) -E -n -e '^.{80}.+$$$$' $$< || true ; \
fi
endif
# If we have no post processing, PANDOC_OUTPUT is set to OUTPUT_FILE. Otherwise
# PANDOC_OUTPUT is a temporary file, and we must now create the real OUTPUT_FILE.
ifneq ($$($1_POST_PROCESS), )
$$($1_$2_OUTPUT_FILE): $$($1_$2_PANDOC_OUTPUT)
$$(call LogInfo, Post-processing markdown file $2)
$$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$($1_$2_TARGET_DIR))
$$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_post, \
$$($1_POST_PROCESS) $$($1_$2_PANDOC_OUTPUT) > $$($1_$2_OUTPUT_FILE) )
endif
$1 += $$($1_$2_OUTPUT_FILE)
endif
endef
################################################################################
# Setup make rules for converting a markdown file to html.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# Remaining parameters are named arguments. These include:
# DEST : Destination root dir
# FILES : List of files to copy with absolute paths, or path relative to SRC.
# SRC : Source root dir; if given keep input files hierarchy relative to
# SRC in DEST, otherwise flatten structure into DEST.
# FORMAT : The target format (defaults to html5)
# FILE_EXT : The file extension to replace .md with (defaults to .html)
# OPTIONS : Additional options to pandoc
# EXTRA_DEPS : Additional dependencies to add to each pandoc call
# FILTER : Optional pandoc filter command
# POST_PROCESS : Optional command-line to post-process generated markdown
# REPLACEMENTS : Text replacements to perform on input file before processing
#
SetupProcessMarkdown = $(NamedParamsMacroTemplate)
define SetupProcessMarkdownBody
ifeq ($$($1_FILES), )
$$(error FILES is missing in SetupProcessMarkdown $1)
endif
ifeq ($$($1_DEST), )
$$(error DEST is missing in SetupProcessMarkdown $1)
endif
# If no target format is specified, default to html5.
ifeq ($$($1_FORMAT), )
$1_FORMAT := html5
endif
ifeq ($$($1_FORMAT), man)
# If no file extension is specified, default to '.1'.
ifeq ($$($1_FILE_EXT), )
$1_FILE_EXT := .1
endif
else ifeq ($$($1_FORMAT), html5)
ifeq ($$($1_FILE_EXT), )
$1_FILE_EXT := .html
endif
else ifeq ($$($1_FORMAT), html)
ifeq ($$($1_FILE_EXT), )
$1_FILE_EXT := .html
endif
endif
# Remove any trailing slash
$1_DEST := $$(patsubst %/,%,$$($1_DEST))
ifeq ($$($1_SRC), )
# No SRC given, assume we're flattening all files into output dir.
$$(foreach f, $$($1_FILES), \
$$(eval $$(call ProcessMarkdown,$1,$$(notdir $$f),$$(patsubst %/,%,$$(dir $$f)))) \
)
else
# Remove any trailing slash
$1_SRC := $$(patsubst %/,%,$$($1_SRC))
$$(foreach f, $$(patsubst $$($1_SRC)/%,%,$$($1_FILES)), \
$$(eval $$(call ProcessMarkdown,$1,$$f,$$($1_SRC))) \
)
endif
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,148 @@
#
# Copyright (c) 2015, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
include JdkNativeCompilation.gmk
# Setup make rules for creating a set of native test files (libraries or
# executables). This will locate native files matching a certain pattern,
# and compile these into libraries or executables.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# Remaining parameters are named arguments. These include:
# TYPE Must be either PROGRAM or LIBRARY.
# SOURCE_DIRS A list of source directories to search
# OUTPUT_DIR Where to put the resulting files
# EXCLUDE A list of filenames to exclude from compilation
# EXTRA_FILES List of extra files not in SOURCE_DIRS
# CFLAGS List of extra CFLAGS to pass on for each test
# LDFLAGS List of extra LDFLAGS to pass on for each test
# LIBS List of extra LIBS to pass on for each test
SetupTestFilesCompilation = $(NamedParamsMacroTemplate)
define SetupTestFilesCompilationBody
# Check for duplicate base file names. That would have failed later anyhow, but
# this gives a better error message.
$1_DUPLICATED_NAMES := $$(call dups, $$(notdir $$($1_FILE_LIST)))
ifneq ($$($1_DUPLICATED_NAMES), )
$$(error There are duplicate test file names for $1: $$($1_DUPLICATED_NAMES))
endif
# The list to depend on starts out empty
$1 :=
ifeq ($$($1_TYPE), LIBRARY)
$1_PREFIX = lib
$1_OUTPUT_SUBDIR := lib
$1_COMPILATION_TYPE := LIBRARY
$1_LOG_TYPE := library
else ifeq ($$($1_TYPE), PROGRAM)
$1_PREFIX = exe
$1_OUTPUT_SUBDIR := bin
$1_COMPILATION_TYPE := EXECUTABLE
$1_LOG_TYPE := executable
$1_LD_SET_ORIGIN := false
else
$$(error Unknown type: $$($1_TYPE))
endif
# Locate all files with the matching prefix
$1_FILE_LIST := \
$$(call FindFiles, $$($1_SOURCE_DIRS), $$($1_PREFIX)*.c $$($1_PREFIX)*.cpp $$($1_PREFIX)*.m)
$1_EXCLUDE_PATTERN := $$(addprefix %/, $$($1_EXCLUDE))
$1_FILTERED_FILE_LIST := $$(filter-out $$($1_EXCLUDE_PATTERN), $$($1_FILE_LIST))
$1_BUILD_INFO := $$($1_OUTPUT_DIR)/_$1-build-info.marker
# Tests are built with internal debug symbols where supported.
# With Visual Studio or on macosx, we revert to external.
$1_COPY_DEBUG_SYMBOLS := false
ifeq ($(TOOLCHAIN_TYPE), microsoft)
$1_COPY_DEBUG_SYMBOLS := true
else ifeq ($(call isTargetOs, macosx), true)
$1_COPY_DEBUG_SYMBOLS := true
endif
# Always include common test functionality
TEST_CFLAGS := -I$(TOPDIR)/test/lib/native
# Setup a compilation for each and every one of them
$$(foreach file, $$($1_FILTERED_FILE_LIST), \
$$(eval name := $$(strip $$(basename $$(notdir $$(file))))) \
$$(eval unprefixed_name := $$(patsubst $$($1_PREFIX)%, %, $$(name))) \
$$(eval $$(call SetupJdkNativeCompilation, BUILD_TEST_$$(name), \
NAME := $$(unprefixed_name), \
TYPE := $$($1_COMPILATION_TYPE), \
LINK_TYPE := $(if $$(filter %.cpp, $$(file)), C++, C), \
EXTRA_HEADER_DIRS := \
java.base:libjava \
java.base:libjvm, \
EXTRA_FILES := $$(file) $$($1_EXTRA_FILES), \
OBJECT_DIR := $$($1_OUTPUT_DIR)/support/$$(name), \
OUTPUT_DIR := $$($1_OUTPUT_DIR)/$$($1_OUTPUT_SUBDIR), \
CFLAGS := $$(TEST_CFLAGS) $$($1_CFLAGS) $$($1_CFLAGS_$$(name)), \
CXXFLAGS := $$(TEST_CFLAGS) $$($1_CFLAGS) $$($1_CFLAGS_$$(name)), \
LD_SET_ORIGIN := $$($1_LD_SET_ORIGIN), \
LDFLAGS := $$($1_LDFLAGS) $$($1_LDFLAGS_$$(name)), \
DISABLED_WARNINGS_gcc := format undef unused-but-set-variable \
unused-const-variable unused-function unused-value \
unused-variable, \
DISABLED_WARNINGS_clang := format-nonliteral \
missing-field-initializers sometimes-uninitialized undef \
unused-but-set-variable unused-function unused-variable, \
DEFAULT_LIBCXX := false, \
JDK_LIBS := $$($1_JDK_LIBS_$$(name)), \
LIBS := $$($1_LIBS) $$($1_LIBS_$$(name)), \
DEFAULT_VERSIONINFO_RESOURCE := false, \
OPTIMIZATION := $$(if $$($1_OPTIMIZATION_$$(name)), $$($1_OPTIMIZATION_$$(name)), LOW), \
COPY_DEBUG_SYMBOLS := $$($1_COPY_DEBUG_SYMBOLS), \
STRIP_SYMBOLS := $$(if $$($1_STRIP_SYMBOLS_$$(name)), $$($1_STRIP_SYMBOLS_$$(name)), false), \
BUILD_INFO_LOG_MACRO := LogInfo, \
)) \
$$(eval $1 += $$(BUILD_TEST_$$(name)) ) \
$$(eval $1_BUILD_INFO_DEPS += $$(BUILD_TEST_$$(name)_BUILD_INFO_DEPS)) \
$$(eval $$(BUILD_TEST_$$(name)_BUILD_INFO): | $$($1_BUILD_INFO)) \
)
# Setup rule for printing a summary of all the tests being compiled. On Warn
# log level, this replaces the individual build info logging done by
# SetupJdkNativeCompilation.
$$($1_BUILD_INFO): $$($1_BUILD_INFO_DEPS)
$$(call LogWarn, $$(strip Creating $$(words $$(filter-out %.vardeps, $$?)) \
test $$($1_LOG_TYPE) file(s) for $1))
$(TOUCH) $$@
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,230 @@
#
# Copyright (c) 2013, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# Helper function for SetupTextFileProcessing; adds a rule for a single file
# to be processed.
# param 1 = The namespace argument, e.g. BUILD_VERSION_FILE
# param 2 = the source file name (full path)
# param 3 = the target base directory
# param 4 = the target file name (possibly with a partial path)
define SetupSingleTextFileForProcessing
$(strip $3)/$(strip $4): $2 $$($1_VARDEPS_FILE)
$$(call LogInfo, Processing $(strip $4))
$$(call MakeDir, $$(@D))
$(RM) '$$@' '$$@.includes.tmp' '$$@.replacements.tmp' ; \
$$($1_INCLUDES_COMMAND_LINE) < '$$<' > '$$@.includes.tmp' ; \
$$($1_REPLACEMENTS_COMMAND_LINE) < '$$@.includes.tmp' > '$$@.replacements.tmp' ; \
$(RM) '$$@.includes.tmp' ; \
$(MV) '$$@.replacements.tmp' '$$@'
$1 += $(strip $3)/$(strip $4)
endef
# Setup make rules for processing one or more text files, in which specified
# markers are replaced with a given text, or with the contents of a given file.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# Remaining parameters are named arguments. These include:
# SOURCE_DIRS one or more directory roots to search for files to process
# SOURCE_FILES complete paths to one or more files to process
# OUTPUT_DIR the directory where we store the processed files.
# OUTPUT_FILE the name of the resulting file. Only allowed if processing a
# single file.
# SOURCE_BASE_DIR a common root to all SOURCE_DIRS or SOURCE_FILES.
# If specified, files will keep the path relative to the base in the
# OUTPUT_DIR. Otherwise, the hierarchy will be flattened into the OUTPUT_DIR.
# INCLUDE_FILES only include files matching these patterns (used only with
# SOURCE_DIRS)
# EXCLUDE_FILES exclude files matching these patterns (used only with
# SOURCE_DIRS)
# INCLUDES replace the occurrences of a pattern with the contents of a file;
# one or more such include pattern, using the syntax:
# PLACEHOLDER => FILE_TO_INCLUDE ; ...
# Each PLACEHOLDER must be on a single, otherwise empty line (whitespace
# padding is allowed).
# REPLACEMENTS one or more text replacement patterns, using the syntax:
# PATTERN => REPLACEMENT_TEXT ; ...
#
# If both INCLUDES or REPLACEMENTS are present, then the includes will be
# processed first, and replacements will be done on the included fragments as well.
# If neither is present, the files will just be copied without modifications.
#
SetupTextFileProcessing = $(NamedParamsMacroTemplate)
define SetupTextFileProcessingBody
ifneq ($$($1_SOURCE_FILES), )
ifneq ($$($1_SOURCE_DIRS), )
$$(error Cannot use both SOURCE_FILES and SOURCE_DIRS (in $1))
endif
ifneq ($$($1_EXCLUDE_FILES)$$($1_INCLUDE_FILES), )
$$(error Cannot INCLUDE/EXCLUDE_FILES with SOURCE_FILES (in $1))
endif
else
ifeq ($$($1_SOURCE_DIRS), )
$$(error Must specify either SOURCE_FILES or SOURCE_DIRS (in $1))
endif
# Find all files in the source trees. Sort to remove duplicates.
$$(foreach src, $$($1_SOURCE_DIRS), $$(if $$(wildcard $$(src)), , \
$$(error SOURCE_DIRS contains missing directory $$(src) (in $1))))
ifneq ($$($1_SOURCE_BASE_DIR), )
$$(foreach src, $$($1_SOURCE_DIRS), \
$$(if $$(findstring $$($1_SOURCE_BASE_DIR), $$(src)), , \
$$(error SOURCE_DIRS contains directory $$(src) outside \
SOURCE_BASE_DIR $$($1_SOURCE_BASE_DIR) (in $1))))
endif
$1_SOURCE_FILES := $$(sort $$(call FindFiles,$$($1_SOURCE_DIRS)))
$1_EXCLUDE_FILES := $$(foreach i, $$($1_SOURCE_DIRS), $$(addprefix $$i/, $$($1_EXCLUDE_FILES)))
$1_INCLUDE_FILES := $$(foreach i, $$($1_SOURCE_DIRS), $$(addprefix $$i/, $$($1_INCLUDE_FILES)))
$1_SOURCE_FILES := $$(filter-out $$($1_EXCLUDE_FILES), $$($1_SOURCE_FILES))
ifneq ($$(strip $$($1_INCLUDE_FILES)), )
$1_SOURCE_FILES := $$(filter $$($1_INCLUDE_FILES), $$($1_SOURCE_FILES))
endif
ifeq ($$($1_SOURCE_FILES), )
$$(info No sources found for $1 when looking inside the dirs $$($1_SRC))
endif
endif
ifneq ($$($1_REPLACEMENTS), )
# We have a replacement request, prepare it for the recipe
ifneq ($$(findstring /, $$($1_REPLACEMENTS)), )
# Cannot use / as separator
ifneq ($$(findstring @, $$($1_REPLACEMENTS)), )
# Cannot use @ as separator
ifneq ($$(findstring |, $$($1_REPLACEMENTS)), )
# Cannot use | as separator
ifneq ($$(findstring !, $$($1_REPLACEMENTS)), )
# Cannot use ! as separator. Give up.
$$(error No suitable sed separator can be found for $1. Tested /, @, | and !)
else
$1_SEP := !
endif
else
$1_SEP := |
endif
else
$1_SEP := @
endif
else
$1_SEP := /
endif
# If we have a trailing "=>" (i.e. last rule replaces with empty, and is not
# terminated by a ;), add a trailing ; to minimize the number of corner
# cases in the hairy subst expression..
ifeq ($$(lastword $$($1_REPLACEMENTS)), =>)
$1_REPLACEMENTS += ;
endif
# If we have a trailing ";", add a dummy replacement, since there is no easy
# way to delete the last word in make.
ifeq ($$(lastword $$($1_REPLACEMENTS)), ;)
$1_REPLACEMENTS += DUMMY_REPLACEMENT => DUMMY_REPLACEMENT
endif
# Convert the REPLACEMENTS syntax ( A => B ; C => D ; ...) to a sed command
# line (-e "s/A/B/g" -e "s/C/D/g" ...), basically by replacing '=>' with '/'
# and ';' with '/g" -e "s/', and adjusting for edge cases.
# '&' has special meaning in sed so needs to be escaped.
$1_REPLACEMENTS_COMMAND_LINE := $(SED) -e 's$$($1_SEP)$$(subst $$(SPACE);$$(SPACE),$$($1_SEP)g' \
-e 's$$($1_SEP),$$(subst $$(SPACE)=>$$(SPACE),$$($1_SEP),$$(subst $$(SPACE)=>$$(SPACE);$$(SPACE),$$($1_SEP)$$($1_SEP)g' \
-e 's$$($1_SEP),$$(subst &,\&,$$(strip $$($1_REPLACEMENTS))))))$$($1_SEP)g'
else
# We don't have any replacements, just pipe the file through cat.
$1_REPLACEMENTS_COMMAND_LINE := $(CAT)
endif
ifneq ($$($1_INCLUDES), )
# We have a include request, prepare it for the recipe.
# Convert an INCLUDE like this PATTERN_1 => file1 ; PATTERN_2 => file2 ;
# into an awk script fragment like this:
# {
# if (matches("PATTERN_1")) { include("file1") } else
# if (matches("PATTERN_2")) { include("file2") } else
# print
# }
$1_INCLUDES_HEADER_AWK := \
function matches(pattern) { return ($$$$0 ~ "^[ \t]*" pattern "[ \t]*$$$$") } \
function include(filename) { while ((getline < filename) == 1) print ; close(filename) }
$1_INCLUDES_PARTIAL_AWK := $$(subst $$(SPACE);,,$$(subst $$(SPACE)=>$$(SPACE),"$$(RIGHT_PAREN)$$(RIGHT_PAREN) \
{ include$$(LEFT_PAREN)",$$(subst $$(SPACE);$$(SPACE),"$$(RIGHT_PAREN) } \
else if $$(LEFT_PAREN)matches$$(LEFT_PAREN)",$$(strip $$($1_INCLUDES)))))
$1_INCLUDES_COMMAND_LINE := $(AWK) '$$($1_INCLUDES_HEADER_AWK) \
{ if (matches("$$($1_INCLUDES_PARTIAL_AWK)") } else print }'
else
# We don't have any includes, just pipe the file through cat.
$1_INCLUDES_COMMAND_LINE := $(CAT)
endif
$1_VARDEPS := $$($1_INCLUDES_COMMAND_LINE) $$($1_REPLACEMENTS_COMMAND_LINE)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS)
# Reset target list before populating it
$1 :=
ifneq ($$($1_OUTPUT_FILE), )
ifneq ($$(words $$($1_SOURCE_FILES)), 1)
$$(error Cannot use OUTPUT_FILE for more than one source file (in $1))
endif
# Note that $1 is space sensitive and must disobey whitespace rules
$$(eval $$(call SetupSingleTextFileForProcessing,$1, $$($1_SOURCE_FILES), \
$$(patsubst %/, %, $$(dir $$($1_OUTPUT_FILE))), $$(notdir $$($1_OUTPUT_FILE))))
else
ifeq ($$($1_OUTPUT_DIR), )
$$(error Neither OUTPUT_FILE nor OUTPUT_DIR was specified (in $1))
endif
# Now call add_native_source for each source file we are going to process.
ifeq ($$($1_SOURCE_BASE_DIR), )
# With no base dir specified, put all files in target dir, flattening any
# hierarchies. Note that $1 is space sensitive and must disobey whitespace
# rules.
$$(foreach src, $$($1_SOURCE_FILES), \
$$(eval $$(call SetupSingleTextFileForProcessing,$1, $$(src), \
$$(patsubst %/, %, $$($1_OUTPUT_DIR)), $$(notdir $$(src)))))
else
# With a base dir, extract the relative portion of the path. Note that $1
# is space sensitive and must disobey whitespace rules, and so is the
# arguments to patsubst.
$$(foreach src, $$($1_SOURCE_FILES), \
$$(eval $$(call SetupSingleTextFileForProcessing,$1, $$(src), \
$$(patsubst %/, %, $$($1_OUTPUT_DIR)), \
$$(patsubst $$($1_SOURCE_BASE_DIR)/%,%,$$(src)))))
endif
endif
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

438
make/common/Utils.gmk Normal file
View file

@ -0,0 +1,438 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# Basic utility functions available to MakeBase.gmk itself
################################################################################
# String equals
equals = \
$(if $(strip $1)$(strip $2),$(strip \
$(and $(findstring $(strip $1),$(strip $2)), \
$(findstring $(strip $2),$(strip $1)))), \
true \
)
# Convert the string given to upper case, without any $(shell)
# Inspired by http://lists.gnu.org/archive/html/help-make/2013-09/msg00009.html
uppercase_table := a,A b,B c,C d,D e,E f,F g,G h,H i,I j,J k,K l,L m,M n,N o,O \
p,P q,Q r,R s,S t,T u,U v,V w,W x,X y,Y z,Z
uppercase_internal = \
$(if $(strip $1), $$(subst $(firstword $1), $(call uppercase_internal, \
$(wordlist 2, $(words $1), $1), $2)), $2)
# Convert a string to upper case. Works only on a-z.
# $1 - The string to convert
uppercase = \
$(strip \
$(eval uppercase_result := $(call uppercase_internal, $(uppercase_table), $1)) \
$(uppercase_result) \
)
lowercase_table := A,a B,b C,c D,d E,e F,f G,g H,h I,i J,j K,k L,l M,m N,n O,o \
P,p Q,q R,r S,s T,t U,u V,v W,w X,x Y,y Z,z
lowercase_internal = \
$(if $(strip $1), $$(subst $(firstword $1), $(call lowercase_internal, \
$(wordlist 2, $(words $1), $1), $2)), $2)
# Convert a string to lower case. Works only on a-z.
# $1 - The string to convert
lowercase = \
$(strip \
$(eval lowercase_result := $(call lowercase_internal, $(lowercase_table), $1)) \
$(lowercase_result) \
)
lowercase_letters := a b c d e f g h i j k l m n o p q r s t u v w x y z
uppercase_letters := A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
titlecase_internal = \
$(strip $(or \
$(strip $(foreach l, $(lowercase_letters) $(uppercase_letters), \
$(if $(filter $l%, $1), \
$(call uppercase, $l)$(call lowercase, $(patsubst $l%,%,$1))))), \
$1))
# Convert a string to Title Case. Works only on a-z.
# $1 - The string to convert
titlecase = \
$(strip $(foreach w, $1, $(call titlecase_internal, $w)))
# Returns the first character of a string. Works only on a-z.
# $1 - The string to extract the first character from
firstchar = \
$(strip $(foreach l, $(lowercase_letters) $(uppercase_letters), \
$(if $(filter $l%, $(firstword $1)), $l)))
################################################################################
# Creates a sequence of increasing numbers (inclusive).
# Param 1 - starting number
# Param 2 - ending number
sequence = \
$(wordlist $1, $2, $(strip \
$(eval SEQUENCE_COUNT := ) \
$(call _sequence-do,$(strip $2))))
_sequence-do = \
$(if $(word $1, $(SEQUENCE_COUNT)),, \
$(eval SEQUENCE_COUNT += .) \
$(words $(SEQUENCE_COUNT)) \
$(call _sequence-do,$1))
################################################################################
# This macro translates $ into \$ to protect the $ from expansion in the shell.
# To make this macro resilient against already escaped strings, first remove
# any present escapes before escaping so that no double escapes are added.
EscapeDollar = $(subst $$,\$$,$(subst \$$,$$,$(strip $1)))
################################################################################
# This macro works just like EscapeDollar above, but for #.
EscapeHash = $(subst $(HASH),\$(HASH),$(subst \$(HASH),$(HASH),$(strip $1)))
################################################################################
# This macro translates $ into $$ to protect the string from make itself.
DoubleDollar = $(subst $$,$$$$,$(strip $1))
################################################################################
# ShellQuote
#
# Quotes a string with single quotes and replaces single quotes with '\'' so
# that the contents survives being given to the shell.
ShellQuote = \
$(SQUOTE)$(subst $(SQUOTE),$(SQUOTE)\$(SQUOTE)$(SQUOTE),$(strip $1))$(SQUOTE)
################################################################################
# Write to and read from file
# Param 1 - File to read
ReadFile = \
$(shell $(CAT) $1)
# Param 1 - Text to write
# Param 2 - File to write to
ifeq ($(HAS_FILE_FUNCTION), true)
WriteFile = \
$(file >$2,$(strip $1))
else
# Use printf to get consistent behavior on all platforms.
WriteFile = \
$(shell $(PRINTF) "%s\n" $(strip $(call ShellQuote, $1)) > $2)
endif
# Param 1 - Text to write
# Param 2 - File to write to
ifeq ($(HAS_FILE_FUNCTION), true)
AppendFile = \
$(file >>$2,$(strip $1))
else
# Use printf to get consistent behavior on all platforms.
AppendFile = \
$(shell $(PRINTF) "%s\n" $(strip $(call ShellQuote, $1)) >> $2)
endif
################################################################################
# Make directory without forking mkdir if not needed.
#
# If a directory with an encoded space is provided, the wildcard function
# sometimes returns false answers (typically if the dir existed when the
# makefile was parsed, but was deleted by a previous rule). In that case, always
# call mkdir regardless of what wildcard says.
#
# 1: List of directories to create
MakeDir = \
$(strip \
$(eval MakeDir_dirs_to_make := $(strip $(foreach d, $1, \
$(if $(findstring ?, $d), '$(call DecodeSpace, $d)', \
$(if $(wildcard $d), , $d) \
) \
))) \
$(if $(MakeDir_dirs_to_make), $(shell $(MKDIR) -p $(MakeDir_dirs_to_make))) \
)
################################################################################
# Check if our build or target conforms to certain restrictions. This set of
# functions all work in similar ways, testing the property that the name
# implies, so e.g. isTargetCpu test the CPU of the target system.
#
# $1 - A property, or a space separated list of properties to test for.
#
# Returns true if the actual property matches one of the properties in the list,
# and false otherwise.
#
# Examples: $(call isTargetOs, linux windows) will return true when executed
# on either linux or windows, and false otherwise.
# $(call isBuildCpuArch, x86) will return true iff the build CPU Arch is x86.
isTargetOs = \
$(strip $(if $(filter $(OPENJDK_TARGET_OS), $1), true, false))
isTargetOsType = \
$(strip $(if $(filter $(OPENJDK_TARGET_OS_TYPE), $1), true, false))
isTargetCpu = \
$(strip $(if $(filter $(OPENJDK_TARGET_CPU), $1), true, false))
isTargetCpuArch = \
$(strip $(if $(filter $(OPENJDK_TARGET_CPU_ARCH), $1), true, false))
isTargetCpuBits = \
$(strip $(if $(filter $(OPENJDK_TARGET_CPU_BITS), $1), true, false))
isBuildOs = \
$(strip $(if $(filter $(OPENJDK_BUILD_OS), $1), true, false))
isBuildOsType = \
$(strip $(if $(filter $(OPENJDK_BUILD_OS_TYPE), $1), true, false))
isBuildOsEnv = \
$(strip $(if $(filter $(OPENJDK_BUILD_OS_ENV), $1), true, false))
isBuildCpu = \
$(strip $(if $(filter $(OPENJDK_BUILD_CPU), $1), true, false))
isBuildCpuArch = \
$(strip $(if $(filter $(OPENJDK_BUILD_CPU_ARCH), $1), true, false))
isCompiler = \
$(strip $(if $(filter $(TOOLCHAIN_TYPE), $1), true, false))
################################################################################
#
# Common utility functions
#
################################################################################
### Debug functions
# Prints the name and value of a variable
PrintVar = \
$(info $(strip $1) >$($(strip $1))<)
################################################################################
# Strip both arguments. Append the first argument to the second argument. If the
# first argument is empty, return the empty string.
IfAppend = \
$(if $(strip $1),$(strip $1)$(strip $2),)
################################################################################
# Assign a variable only if it is empty
# Param 1 - Variable to assign
# Param 2 - Value to assign
SetIfEmpty = \
$(if $($(strip $1)),,$(eval $(strip $1) := $2))
################################################################################
# Filter out duplicate sub strings while preserving order. Keeps the first occurrence.
uniq = \
$(strip $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))))
# Returns all whitespace-separated words in $2 where at least one of the
# whitespace-separated words in $1 is a substring.
containing = \
$(strip \
$(foreach v,$(strip $2), \
$(call uniq,$(foreach p,$(strip $1),$(if $(findstring $p,$v),$v)))))
# Returns all whitespace-separated words in $2 where none of the
# whitespace-separated words in $1 is a substring.
not-containing = \
$(strip $(filter-out $(call containing,$1,$2),$2))
# Return a list of all string elements that are duplicated in $1.
dups = \
$(strip $(foreach v, $(sort $1), $(if $(filter-out 1, \
$(words $(filter $v, $1))), $v)))
# Remove a whole list of prefixes
# $1 - List of prefixes
# $2 - List of elements to process
remove-prefixes = \
$(strip $(if $1,$(patsubst $(firstword $1)%,%, \
$(call remove-prefixes,$(filter-out $(firstword $1),$1),$2)),$2))
################################################################################
# Boolean operators.
# Return the word "true" if all the boolean words given as argument is "true",
# and returns "false" otherwise. Boolean words must be "true" or "false". It is
# an error to supply a non-boolean word. An empty string is considered "true".
And = \
$(strip $(if $(filter-out true false, $1), $(error Non-boolean values: $1)) \
$(if $(strip $(filter-out true, $1)), false, true))
# Return the word "false" if all the boolean words given as argument is "false",
# and returns "true" otherwise. Boolean words must be "true" or "false". It is
# an error to supply a non-boolean word. An empty string is considered "false".
Or = \
$(strip $(if $(filter-out true false, $1), $(error Non-boolean values: $1)) \
$(if $(strip $(filter-out false, $1)), true, false))
################################################################################
# Convert an UNIX epoch based timestamp (as an integer) to an ISO 8601 date
# string.
# Param 1 - timestamp
ifeq ($(IS_GNU_DATE), yes)
EpochToISO8601 = \
$(shell $(DATE) --utc --date="@$(strip $1)" \
+"$(ISO_8601_FORMAT_STRING)" 2> /dev/null)
else
EpochToISO8601 = \
$(shell $(DATE) -u -j -f "%s" "$(strip $1)" \
+"$(ISO_8601_FORMAT_STRING)" 2> /dev/null)
endif
################################################################################
# Parse a multiple-keyword variable, like FOO="KEYWORD1=val1;KEYWORD2=val2;..."
# These will be converted into a series of variables like FOO_KEYWORD1=val1,
# FOO_KEYWORD2=val2, etc. Unknown keywords will cause an error.
#
# Parameter 1 is the name of the rule, and is also the name of the variable.
#
# Remaining parameters are named arguments. These include:
# SINGLE_KEYWORDS A list of valid keywords with single string values
# STRING_KEYWORDS A list of valid keywords, processed as string. This means
# that '%20' will be replaced by ' ' to allow for multi-word strings.
#
ParseKeywordVariable = $(NamedParamsMacroTemplate)
define ParseKeywordVariableBody
ifneq ($$($1), )
# To preserve spaces, substitute them with a hopefully unique pattern
# before splitting and then re-substitute spaces back.
$1_MANGLED := $$(subst $$(SPACE),||||,$$($1))
$$(foreach mangled_part, $$(subst ;, , $$($1_MANGLED)), \
$$(eval mangled_part_eval := $$(call DoubleDollar, $$(mangled_part))) \
$$(eval part := $$$$(subst ||||,$$$$(SPACE),$$$$(mangled_part_eval))) \
$$(eval $1_NO_MATCH := true) \
$$(if $$(filter help, $$(part)), \
$$(info Valid keywords for $1:) \
$$(info $$($1_SINGLE_KEYWORDS) $$($1_STRING_KEYWORDS).) \
$$(error Re-run without 'help' to continue)) \
$$(foreach keyword, $$($1_SINGLE_KEYWORDS), \
$$(eval keyword_eval := $$(call DoubleDollar, $$(keyword))) \
$$(if $$(filter $$(keyword)=%, $$(part)), \
$$(eval $(strip $1)_$$$$(keyword_eval) := $$$$(strip $$$$(patsubst $$$$(keyword_eval)=%, %, $$$$(part)))) \
$$(eval $1_NO_MATCH := ) \
) \
) \
$$(foreach keyword, $$($1_STRING_KEYWORDS), \
$$(eval keyword_eval := $$(call DoubleDollar, $$(keyword))) \
$$(if $$(filter $$(keyword)=%, $$(part)), \
$$(eval $(strip $1)_$$$$(keyword_eval) := $$$$(strip $$$$(subst %20, , $$$$(patsubst $$$$(keyword_eval)=%, %, $$$$(part))))) \
$$(eval $1_NO_MATCH := ) \
) \
) \
$$(if $$($1_NO_MATCH), \
$$(if $$(filter $$(part), $$($1_SINGLE_KEYWORDS) $$($1_STRING_KEYWORDS)), \
$$(info Keyword $$(part) for $1 needs to be assigned a value.) \
, \
$$(info $$(part) is not a valid keyword for $1.) \
$$(info Valid keywords: $$($1_SINGLE_KEYWORDS) $$($1_STRING_KEYWORDS).) \
) \
$$(error Cannot continue) \
) \
)
endif
endef
################################################################################
# Find lib dir for module
# Param 1 - module name
FindLibDirForModule = \
$(SUPPORT_OUTPUTDIR)/modules_libs/$(strip $1)
################################################################################
# Find executable dir for module
# Param 1 - module name
FindExecutableDirForModule = \
$(SUPPORT_OUTPUTDIR)/modules_cmds/$(strip $1)
################################################################################
# Return a string suitable for use after a -classpath or --module-path option. It
# will be correct and safe to use on all platforms. Arguments are given as space
# separate classpath entries. Safe for multiple nested calls.
# param 1 : A space separated list of classpath entries
# The surrounding strip is needed to keep additional whitespace out
PathList = \
"$(subst $(SPACE),:,$(strip $(subst $(DQUOTE),,$1)))"
################################################################################
# Check if a specified hotspot variant is being built, or at least one of a
# list of variants. Will return 'true' or 'false'.
# $1 - the variant to test for
check-jvm-variant = \
$(strip \
$(if $(filter-out $(VALID_JVM_VARIANTS), $1), \
$(error Internal error: Invalid variant tested: $1)) \
$(if $(filter $1, $(JVM_VARIANTS)), true, false))
################################################################################
# Converts a space separated list to a comma separated list.
#
# Replacing double-comma with a single comma is to workaround the issue with
# some version of make on windows that doesn't substitute spaces with one comma
# properly.
CommaList = \
$(strip \
$(subst $(COMMA)$(COMMA),$(COMMA),$(subst $(SPACE),$(COMMA),$(strip $1))) \
)
################################################################################
# Converts a space separated list to a colon separated list.
#
# Replacing double-colon with a single colon is to workaround the issue with
# some version of make on windows that doesn't substitute spaces with one colon
# properly.
ColonList = \
$(strip \
$(subst ::,:,$(subst $(SPACE),:,$(strip $1))) \
)
################################################################################
# Given a list of files, filters out locale specific files for translations
# that should be excluded from this build.
# $1 - The list of files to filter
# $2 - The suffix of the files that should be considered (.java or .properties)
FilterExcludedTranslations = \
$(strip $(if $(EXCLUDE_TRANSLATIONS), \
$(filter-out \
$(foreach suffix, $2, \
$(addprefix %_, $(addsuffix $(suffix), $(EXCLUDE_TRANSLATIONS))) \
), \
$1 \
), \
$1 \
))
################################################################################
include MakeIncludeEnd.gmk
endif # include guard

196
make/common/ZipArchive.gmk Normal file
View file

@ -0,0 +1,196 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# Depends on build tools for MakeZipReproducible
include $(TOPDIR)/make/ToolsJdk.gmk
# Setup make rules for creating a zip archive.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# Remaining parameters are named arguments. These include:
# SRC
# ZIP
# INCLUDES
# INCLUDE_FILES
# EXCLUDES
# EXCLUDE_FILES
# EXCLUDE_PATTERNS - Patterns with at most one % wildcard matching filenames
# and not directories.
# EXCLUDE_PATTERNS_$dir - Exclude patterns just like above but specific to one
# src dir
# SUFFIXES
# EXTRA_DEPS
# FOLLOW_SYMLINKS - Set to explicitly follow symlinks. Affects performance of
# finding files.
# ZIP_OPTIONS extra options to pass to zip
# REPRODUCIBLE set to false to disable the step that makes zip reproducible
SetupZipArchive = $(NamedParamsMacroTemplate)
define SetupZipArchiveBody
# Create a version $1_SRC with a guaranteed trailing slash
$1_SRC_SLASH := $$(addsuffix /, $$(patsubst %/, %, $$($1_SRC)))
# To avoid running find over too large sets of files, which causes make to crash
# on some configurations (cygwin), use INCLUDES and INCLUDE_FILES to build a set
# of directories to run find in, if available.
ifneq ($$($1_INCLUDES)$$($1_INCLUDE_FILES), )
$1_FIND_LIST := $$(wildcard $$(foreach s, $$($1_SRC_SLASH), \
$$(addprefix $$s, $$($1_INCLUDES) $$($1_INCLUDE_FILES))))
else
$1_FIND_LIST := $$($1_SRC_SLASH)
endif
# Find all files in the source tree.
# If asked to, follow symlinks in this find since that is what zip does. To do
# this, we need to call ShellFindFiles directly.
ifeq ($$($1_FOLLOW_SYMLINKS), true)
$1_ALL_SRCS := $$(call not-containing, _the., $$(call ShellFindFiles, $$($1_FIND_LIST), , -L))
else
$1_ALL_SRCS := $$(call not-containing, _the., $$(call FindFiles, $$($1_FIND_LIST)))
endif
# Filter on suffixes if set
ifneq ($$($1_SUFFIXES), )
$1_ALL_SRCS := $$(filter $$(addprefix %, $$($1_SUFFIXES)), $$($1_ALL_SRCS))
endif
ifneq ($$($1_INCLUDES), )
ifneq ($$($1_SUFFIXES), )
$1_ZIP_INCLUDES := $$(foreach s, $$($1_SUFFIXES), \
$$(addprefix -i$(SPACE)$(DQUOTE), $$(addsuffix /*$$s$(DQUOTE), $$($1_INCLUDES))))
else
$1_ZIP_INCLUDES := $$(addprefix -i$(SPACE)$(DQUOTE), $$(addsuffix /*$(DQUOTE), $$($1_INCLUDES)))
endif
else
ifneq ($$($1_SUFFIXES), )
$1_ZIP_INCLUDES := $$(foreach s, $$($1_SUFFIXES), \
$$(addprefix -i$(SPACE)$(DQUOTE), *$$s$(DQUOTE)))
endif
endif
ifneq ($$($1_INCLUDE_FILES), )
$1_ZIP_INCLUDES += $$(addprefix -i$(SPACE), $$($1_INCLUDE_FILES))
endif
ifneq ($$($1_EXCLUDES), )
$1_ZIP_EXCLUDES := $$(addprefix -x$(SPACE)$(DQUOTE), $$(addsuffix /*$(DQUOTE), $$($1_EXCLUDES)))
$1_SRC_EXCLUDES := $$(foreach s, $$($1_SRC_SLASH), $$(addprefix $$s, $$(addsuffix /%, $$($1_EXCLUDES))))
$1_ALL_SRCS := $$(filter-out $$($1_SRC_EXCLUDES), $$($1_ALL_SRCS))
endif
ifneq ($$($1_EXCLUDE_FILES), )
$1_SRC_EXCLUDE_FILES := $$(addprefix %, $$($1_EXCLUDE_FILES)) $$($1_EXCLUDE_FILES)
$1_ALL_SRCS := $$(filter-out $$($1_SRC_EXCLUDE_FILES), $$($1_ALL_SRCS))
$$(foreach s, $$($1_SRC_SLASH), \
$$(eval $1_ZIP_EXCLUDES_$$s += \
$$(addprefix -x$$(SPACE), $$(patsubst $$s%,%, $$($1_EXCLUDE_FILES))) \
) \
)
endif
ifneq ($$($1_EXCLUDE_PATTERNS), )
$1_ALL_SRCS := $$(filter-out $$($1_EXCLUDE_PATTERNS), $$($1_ALL_SRCS))
$1_ZIP_EXCLUDES += $$(addprefix -x$(SPACE), $$(subst %,\*,$$($1_EXCLUDE_PATTERNS)))
endif
# Rewrite src dir specific exclude patterns to zip excludes
$$(foreach s, $$($1_SRC_SLASH), \
$$(if $$($1_EXCLUDE_PATTERNS_$$s), \
$$(eval $1_ZIP_EXCLUDES_$$s += \
$$(addprefix -x$$(SPACE), $$(subst %,\*,$$($1_EXCLUDE_PATTERNS_$$s))) \
) \
) \
)
ifeq ($$($1_REPRODUCIBLE), )
$1_REPRODUCIBLE := true
endif
# Use a slightly shorter name for logging, but with enough path to identify this zip.
$1_NAME := $$(subst $$(OUTPUTDIR)/,,$$($1_ZIP))
# Now $1_ALL_SRCS should contain all sources that are going to be put into the zip.
# I.e. the zip -i and -x options should match the filtering done in the makefile.
# Explicitly excluded files can be given with absolute path. The patsubst solution
# isn't perfect but the likelihood of an absolute path to match something in a src
# dir is very small.
# If zip has nothing to do, it returns 12 and would fail the build. Check for 12
# and only fail if it's not.
# For reproducible builds set the zip access & modify times to SOURCE_DATE_EPOCH
# by using a ziptmp folder to generate final zip from using MakeZipReproducible.
$$($1_ZIP) : $$($1_ALL_SRCS) $$($1_EXTRA_DEPS)
$$(call LogWarn, Updating $$($1_NAME))
$$(call MakeTargetDir)
# Find duplicate file names in the SRC and generate excludes for all
# instances that should not be included. Run this rather expensive
# calculation as part of the recipe to avoid running it when nothing
# needs to be rebuilt. The drawback is that we cannot exclude these
# files from the make prerequisites list, but the number of files is
# usually small so a very rare unnecessary rebuild is worth it.
# (The inner most foreach here is used instead of eval to declare a
# local variable.)
$$(foreach root, $$($1_SRC_SLASH), \
$$(foreach file, $$(filter $$(root)%, $$($1_ALL_SRCS)), \
$$(foreach relfile, $$(patsubst $$(root)%, %, $$(file)), \
$$(if $$($1_relfiles_$$(call DoubleDollar, $$(relfile))), \
$$(eval $1_ZIP_EXCLUDES_$$(root) += -x $$(relfile)) \
, \
$$(eval $1_relfiles_$$(call DoubleDollar, $$(relfile)) := 1) \
) \
) \
) \
)
$$(foreach s, $$($1_SRC_SLASH), $$(call ExecuteWithLog, \
$$(SUPPORT_OUTPUTDIR)/zip/$$(patsubst $$(OUTPUTDIR)/%,%, $$@), \
(cd $$s && $(ZIPEXE) -qru $$($1_ZIP_OPTIONS) $$@ . \
$$($1_ZIP_INCLUDES) $$($1_ZIP_EXCLUDES) -x \*_the.\* \
$$($1_ZIP_EXCLUDES_$$s) \
|| test "$$$$?" = "12" \
))$$(NEWLINE) \
) true
ifeq ($$($1_REPRODUCIBLE), true)
$$(call ExecuteWithLog, \
$$(SUPPORT_OUTPUTDIR)/makezipreproducible/$$(patsubst $$(OUTPUTDIR)/%,%, $$@), \
($(RM) $$(SUPPORT_OUTPUTDIR)/ziptmp/$1/tmp.zip && \
$(MKDIR) -p $$(SUPPORT_OUTPUTDIR)/ziptmp/$1 && \
$(TOOL_MAKEZIPREPRODUCIBLE) -f $$(SUPPORT_OUTPUTDIR)/ziptmp/$1/tmp.zip \
-t $(SOURCE_DATE_EPOCH) $$@ && \
$(RM) $$@ && \
$(MV) $$(SUPPORT_OUTPUTDIR)/ziptmp/$1/tmp.zip $$@ \
))
endif
$(TOUCH) $$@
# Add zip to target list
$1 += $$($1_ZIP)
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,100 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
include CopyFiles.gmk
LIB_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE)
CONF_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_conf/$(MODULE)
LEGAL_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_legal/$(MODULE)
COMMON_LEGAL_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_legal/common
################################################################################
#
# Copy exported include headers files to output directory, if present.
#
INCLUDE_TARGET_DIR := $(SUPPORT_OUTPUTDIR)/modules_include/$(MODULE)
INCLUDE_SOURCE_DIR := $(TOPDIR)/src/$(MODULE)/share/native/include
ifneq ($(wildcard $(INCLUDE_SOURCE_DIR)/*), )
$(eval $(call SetupCopyFiles, COPY_EXPORTED_INCLUDE, \
SRC := $(INCLUDE_SOURCE_DIR), \
DEST := $(INCLUDE_TARGET_DIR), \
FILES := $(filter %.h, $(call FindFiles, $(INCLUDE_SOURCE_DIR))), \
))
TARGETS += $(COPY_EXPORTED_INCLUDE)
endif
# Use the most specific of OS and OS_TYPE.
INCLUDE_SOURCE_OS_DIR := $(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS)/native/include
ifeq ($(wildcard $(INCLUDE_SOURCE_OS_DIR)/*), )
INCLUDE_SOURCE_OS_DIR := $(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/include
endif
ifneq ($(wildcard $(INCLUDE_SOURCE_OS_DIR)/*), )
$(eval $(call SetupCopyFiles, COPY_EXPORTED_INCLUDE_OS, \
SRC := $(INCLUDE_SOURCE_OS_DIR), \
DEST := $(INCLUDE_TARGET_DIR)/$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR), \
FILES := $(filter %.h, $(call FindFiles, $(INCLUDE_SOURCE_OS_DIR))), \
))
TARGETS += $(COPY_EXPORTED_INCLUDE_OS)
endif
################################################################################
# Setup make rules for copying legal files. This is only needed if the files
# need to be filtered due to optional components being enabled/disabled.
# Otherwise CreateJmods.gmk will find the legal files in the original src dirs.
# If multiple license files with the same name are found, only the first one
# found will get copied.
#
# Parameter 1 is the name of the rule.
#
# Remaining parameters are named arguments. These include:
# EXCLUDES : List of filenames to exclude from copy
SetupCopyLegalFiles = $(NamedParamsMacroTemplate)
define SetupCopyLegalFilesBody
$$(foreach f, $$(filter-out $$(addprefix %/, $$($1_EXCLUDES)), \
$$(wildcard $$(addsuffix /*, $$(call FindModuleLegalSrcDirs, $$(MODULE))))), \
$$(if $$(filter $$($1_$$(notdir $$f)), $$($1)), , \
$$(eval $$(call SetupCopyFiles, $1_$$(notdir $$f), \
DEST := $$(LEGAL_DST_DIR), \
FILES := $$f, \
)) \
$$(eval $1 += $$($1_$$(notdir $$f))) \
) \
)
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,37 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
include JavaCompilation.gmk
include $(TOPDIR)/make/ToolsJdk.gmk
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,53 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
include Execute.gmk
include TextFileProcessing.gmk
include $(TOPDIR)/make/ToolsJdk.gmk
################################################################################
# Sets up a rule that creates a version.properties file in the gensrc output
# directory.
# Param 1 - Variable to add generated file name to
# Param 2 - Name of version.properties file including packages from the src
# root.
define SetupVersionProperties
$(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/$$(strip $2):
$$(call MakeTargetDir)
$(PRINTF) "jdk=%s\nfull=%s\nrelease=%s\n" \
$(VERSION_NUMBER) $(VERSION_STRING) $(VERSION_SHORT) > $$@
$$(strip $1) += $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/$$(strip $2)
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,101 @@
#
# Copyright (c) 2015, 2025, 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.
#
include MakeFileStart.gmk
################################################################################
# This file makes modifications to module-info.java files based on the build
# configuration.
#
# Depending on build platform, imported modules and optional parts of the build
# being active, some modules need to have extra exports, provides or uses
# declarations added to them. These optional extras are defined in .extra files:
#
# src/<module>/<share,platform>/classes/module-info.java.extra
#
# The contents of the .extra files are simply extra lines that could fit into
# the module-info file.
#
# This makefile is called once for each from-module with the variable
# MODULE naming the from-module.
#
# The modified module-info.java files are put in the gensrc directory where
# they will automatically override the static versions in the src tree.
################################################################################
include Modules.gmk
################################################################################
# Define this here since jdk/make/Tools.gmk cannot be included from the top
# make directory. Should probably move some tools away from the jdk repo.
TOOL_GENMODULEINFOSOURCE = $(JAVA_SMALL) \
$(INTERIM_LANGTOOLS_ARGS) \
-cp "$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes" \
build.tools.module.GenModuleInfoSource
################################################################################
# Name of modification file.
MOD_FILENAME := module-info.java.extra
# Construct all possible src directories for the module.
MODULE_CLASSES_DIRS := $(call FindModuleSrcDirs, $(MODULE))
# Find all the .extra files in the src dirs.
MOD_FILES := $(wildcard $(foreach f, $(MOD_FILENAME), $(addsuffix /$(f), \
$(MODULE_CLASSES_DIRS))))
ifneq ($(MOD_FILES), )
# Only make this call if modification files are found for this module
ALL_MODULES := $(call FindAllModules)
$(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java: \
$(firstword $(call FindAllModuleInfos, $(MODULE))) \
$(BUILD_TOOLS_JDK) \
$(MOD_FILES) \
$(call DependOnVariable, ALL_MODULES)
$(call MakeTargetDir)
$(RM) $@ $@.tmp
$(TOOL_GENMODULEINFOSOURCE) \
$(if $(call equals, $(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT), true), -d) \
-o $@.tmp \
--source-file $< \
--modules $(call CommaList, $(ALL_MODULES)) \
$(MOD_FILES)
$(MV) $@.tmp $@
TARGETS += $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java
else
# If no modifications are found for this module, remove any module-info.java
# created by a previous build since that is no longer valid.
ifneq ($(wildcard $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java), )
$(shell $(RM) $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java)
endif
endif
################################################################################
include MakeFileEnd.gmk

View file

@ -0,0 +1,154 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# This file defines macros that sets up rules for generating java classes
# from resource bundle properties files.
################################################################################
include JavaCompilation.gmk
################################################################################
# Helper macro for SetupCopy-zh_HK.
define SetupOneCopy-zh_HK
$1_$2_TARGET := $$(patsubst $(TOPDIR)/src/$(MODULE)/share/classes/%, \
$(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/%, \
$$(subst _zh_TW,_zh_HK, $2))
$$($1_$2_TARGET): $2
$$(call MakeTargetDir)
$(CAT) $$< | $(SED) -e '/class/s/_zh_TW/_zh_HK/' > $$@
$1 += $$($1_$2_TARGET)
endef
################################################################################
# Creates rules for copying zh_TW resources to zh_HK.
# Param 1 - Variable to add targets to
# Param 2 - Files to copy from
define SetupCopy-zh_HK
$$(foreach f, $2, $$(eval $$(call SetupOneCopy-zh_HK,$1,$$f)))
endef
################################################################################
# Setup make rules that runs CompileProperties on a set of properties files.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# Remaining parameters are named arguments. These include:
# SRC_DIRS Directories containing properties files to process.
# EXTRA_FILES Also include these specifically named files
# EXCLUDE Exclude files matching this pattern.
# CLASS The super class for the generated classes.
# TYPE Whether to use "langtools" or normal compiler.
# MODULE_PATH_ROOT Module path root, defaults to $(TOPDIR)/src.
# KEEP_ALL_TRANSLATIONS Set to true to skip filtering of excluded translations.
SetupCompileProperties = $(NamedParamsMacroTemplate)
define SetupCompilePropertiesBody
# Set default value unless overridden
ifeq ($$($1_MODULE_PATH_ROOT), )
$1_MODULE_PATH_ROOT := $(TOPDIR)/src
endif
# Locate all properties files in the given source dirs.
$1_SRC_FILES := $$(call FindFiles, $$($1_SRC_DIRS), *.properties)
$1_SRC_FILES += $$($1_EXTRA_FILES)
ifneq ($$($1_EXCLUDE), )
$1_SRC_FILES := $$(filter-out $$($1_EXCLUDE), $$($1_SRC_FILES))
endif
# Filter out any excluded translations
ifneq ($$($1_KEEP_ALL_TRANSLATIONS), true)
$1_SRC_FILES := $$(call FilterExcludedTranslations, $$($1_SRC_FILES), .properties)
endif
# Convert .../src/<module>/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties
# to .../support/gensrc/<module>/com/sun/tools/javac/resources/javac_zh_CN.java
$1_JAVAS := $$(patsubst $$($1_MODULE_PATH_ROOT)/%, \
$(SUPPORT_OUTPUTDIR)/gensrc/%, \
$$(patsubst %.properties, %.java, \
$$(subst /$(OPENJDK_TARGET_OS)/classes,, \
$$(subst /$(OPENJDK_TARGET_OS_TYPE)/classes,, \
$$(subst /share/classes,, $$($1_SRC_FILES))))))
# Generate the package dirs for the to be generated java files. Sort to remove
# duplicates.
$1_DIRS := $$(sort $$(dir $$($1_JAVAS)))
# Now generate a sequence of:
# "-compile ...javac_zh_CN.properties ...javac_zh_CN.java java.util.ListResourceBundle"
# suitable to be fed into the CompileProperties command.
$1_CMDLINE := $$(subst _SPACE_, $(SPACE), \
$$(join $$(addprefix -compile_SPACE_, $$($1_SRC_FILES)), \
$$(addsuffix _SPACE_$$($1_CLASS), \
$$(addprefix _SPACE_, $$($1_JAVAS)))))
$1_TARGET := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.marker
$1_CMDLINE_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.cmdline
$1_EXEC_MARKER := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.exec
ifeq ($$($1_TYPE), langtools)
$1_TOOL := -cp $(BUILDTOOLS_OUTPUTDIR)/langtools_tools_classes \
compileproperties.CompileProperties
$1_TOOL_DEPS := $(BUILD_TOOLS_LANGTOOLS)
else
$1_TOOL := -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
build.tools.compileproperties.CompileProperties
$1_TOOL_DEPS := $(BUILD_TOOLS_JDK)
endif
ifeq ($(findstring $(LOG_LEVEL), debug trace), )
$1_QUIET := -quiet
endif
# Now setup the rule for the generation of the resource bundles.
$$($1_TARGET): $$($1_SRC_FILES) $$($1_JAVAS) $$($1_TOOL_DEPS)
$$(call LogWarn, Compiling $$(words $$($1_SRC_FILES)) properties into resource bundles for $(MODULE))
$$(call MakeDir, $$(@D) $$($1_DIRS))
$$(eval $$(call ListPathsSafely, $1_CMDLINE, $$($1_CMDLINE_FILE)))
$$(call ExecuteWithLog, $$($1_EXEC_MARKER), \
$(JAVA_SMALL) $$($1_TOOL) $$($1_QUIET) @$$($1_CMDLINE_FILE))
$(TOUCH) $$@
$$($1_JAVAS): $$($1_SRC_FILES)
# Create zh_HK versions of all zh_TW files created above
$$(eval $$(call SetupCopy-zh_HK,$1_HK,$$(filter %_zh_TW.java, $$($1_JAVAS))))
# The zh_HK copy must wait for the compile properties tool to run
$$($1_HK): $$($1_TARGET)
$1 += $$($1_JAVAS) $$($1_TARGET) $$($1_HK)
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,228 @@
#
# Copyright (c) 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# This file defines macros that sets up rules for running the spp.Spp build tool
################################################################################
include Execute.gmk
include $(TOPDIR)/make/ToolsJdk.gmk
NON_BYTE_NUMBER_TYPES := char short int long float double
NUMBER_TYPES := byte $(NON_BYTE_NUMBER_TYPES)
PRIMITIVE_TYPES := boolean $(NUMBER_TYPES)
################################################################################
# The Conv function converts a type given as first argument (as a normal Java
# native type name), into one of several corresponding strings, depending on
# the aspect given in the second argument
#
# The implementation dispatches the call to one of several Conv_<aspect> macros.
#
# arg $1: the type to convert
# arg $2: the aspect to convert for
# arg $3: byte order (only needed for certain aspects)
#
Conv = \
$(strip $(call Conv_$(strip $2),$(strip $1),$(strip $3)))
################################################################################
# Conv_<aspect> implementations
# Return a single letter representing the type (lowercase first letter)
Conv_x = \
$(call firstchar, $1)
# Return capitalized type name
Conv_Type = \
$(call titlecase, $1)
# Return the full descriptive name of the type, e.g. int -> integer
Conv_fulltype = \
$(if $(filter char, $1), \
character, \
$(if $(filter int, $1), \
integer, \
$1 \
) \
)
# Return the capitalized full descriptive name of the type, e.g. int -> Integer
Conv_Fulltype = \
$(call titlecase, $(call Conv_fulltype, $1))
# Return log2 bits per value (0-3)
Conv_LBPV = \
$(if $(filter byte, $1), \
0, \
$(if $(filter char short, $1), \
1, \
$(if $(filter int float, $1), \
2, \
$(if $(filter long double, $1), \
3))))
# Return float or int category
Conv_category = \
$(if $(filter float double, $1), \
floatingPointType, \
integralType \
)
# Return stream information for char
Conv_streams = \
$(if $(filter char, $1), streamableType)
# Return stream type information for char
Conv_streamtype = \
$(if $(filter char, $1), int)
# Return capitalized stream type information for char
Conv_Streamtype = \
$(if $(filter char, $1), Int)
# Return article to use for type in English text
Conv_a = \
$(if $(filter int, $1), an, a)
# Return capitalized article to use for type in English text
Conv_A = \
$(if $(filter int, $1), An, A)
# Return integer type with same size as the type
Conv_memtype = \
$(if $(filter float, $1), int, $(if $(filter double, $1), long, $1))
# Return capitalized integer type with same size as the type
Conv_Memtype = \
$(call titlecase, $(call Conv, $1, memtype))
# Return capitalized full descriptive name for integer type with same size as the type
Conv_FullMemtype = \
$(call Conv, $(call Conv, $1, memtype), Fulltype)
# Return Type or Memtype depending on byte order
# arg $2: BYTE_ORDER
Conv_Swaptype = \
$(if $(filter U, $2), \
$(call Conv, $1, Type), \
$(call Conv, $1, Memtype))
# Return fromBits method name for floating types, depending on byte order
# arg $2: BYTE_ORDER
Conv_fromBits = \
$(if $(filter float double, $1), \
$(if $(filter U, $2), , \
$(call Conv, $1, Type).$(call Conv, $1, memtype)BitsTo$(call Conv, $1, Type)))
# Return toBits method name for floating types, depending on byte order
# arg $2: BYTE_ORDER
Conv_toBits = \
$(if $(filter float double, $1), \
$(if $(filter U, $2), , \
$(call Conv, $1, Type).$1ToRaw$(call Conv, $(call Conv, $1, memtype), Type)Bits))
# Return swap method name, depending on byte order
# arg $2: BYTE_ORDER
Conv_swap = \
$(if $(filter S, $2), Bits.swap)
# Return word describing the number of bytes required by type
Conv_nbytes = \
$(if $(filter 0, $(call Conv, $1, LBPV)), one, \
$(if $(filter 1, $(call Conv, $1, LBPV)), two, \
$(if $(filter 2, $(call Conv, $1, LBPV)), four, \
$(if $(filter 3, $(call Conv, $1, LBPV)), eight))))
# Return word describing the number of bytes required by type, minus one
Conv_nbytesButOne = \
$(if $(filter 0, $(call Conv, $1, LBPV)), zero, \
$(if $(filter 1, $(call Conv, $1, LBPV)), one, \
$(if $(filter 2, $(call Conv, $1, LBPV)), three, \
$(if $(filter 3, $(call Conv, $1, LBPV)), seven))))
################################################################################
# Setup make rules that runs the spp.Spp build tool on an input file.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# Remaining parameters are named arguments. These include:
# BEGIN_END Set to true to exclude everything outside #begin/#end (default: false)
# SUBST_EMPTY_LINES Set to false to not generate empty lines for removed lines (default: true)
# SOURCE_FILE The input file to process (required)
# OUTPUT_FILE The output file (required)
# INFO Override default message to print (optional)
# KEYS One or more keys to control the generation (optional)
# REPLACEMENTS one or more text replacement patterns, using the syntax:
# VAR=VALUE [VAR=VALUE] ...
#
SetupStreamPreProcessing = $(NamedParamsMacroTemplate)
define SetupStreamPreProcessingBody
# Verify arguments
ifeq ($$($1_SOURCE_FILE), )
$$(error Must specify SOURCE_FILE (in $1))
endif
ifeq ($$($1_OUTPUT_FILE), )
$$(error Must specify OUTPUT_FILE (in $1))
endif
$1_COMMAND_LINE :=
ifeq ($$($1_BEGIN_END), true)
$1_COMMAND_LINE += -be
endif
ifeq ($$($1_SUBST_EMPTY_LINES), false)
$1_COMMAND_LINE += -nel
endif
$1_COMMAND_LINE += $$(foreach k, $$($1_KEYS), -K$$k)
$1_COMMAND_LINE += $$(subst $$$$(SPACE), ,$$(foreach d, $$($1_REPLACEMENTS), -D$$d))
$1_COMMAND_LINE += -i$$($1_SOURCE_FILE) -o$$($1_OUTPUT_FILE).tmp
ifeq ($$($1_INFO), )
$1_INFO := Preprocessing $$(notdir $$($1_SOURCE_FILE)) for $(MODULE)
endif
$$(eval $$(call SetupExecute, RUN_SPP_$1, \
INFO := $$($1_INFO), \
DEPS := $$($1_SOURCE_FILE) $$(BUILD_TOOLS_JDK), \
OUTPUT_FILE := $$($1_OUTPUT_FILE), \
COMMAND := $$(TOOL_SPP) $$($1_COMMAND_LINE), \
PRE_COMMAND := $$(RM) $$($1_OUTPUT_FILE).tmp $$($1_OUTPUT_FILE), \
POST_COMMAND := $$(MV) $$($1_OUTPUT_FILE).tmp $$($1_OUTPUT_FILE), \
))
$1 += $$(RUN_SPP_$1)
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,300 @@
#
# Copyright (c) 2011, 2026, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
include CopyFiles.gmk
include JdkNativeCompilation.gmk
include Modules.gmk
include ProcessMarkdown.gmk
include $(TOPDIR)/make/ToolsJdk.gmk
LAUNCHER_SRC := $(TOPDIR)/src/java.base/share/native/launcher
ifeq ($(call isTargetOs, aix), true)
ADD_PLATFORM_INCLUDE_DIR := -I$(TOPDIR)/src/java.base/aix/native/include
endif
LAUNCHER_CFLAGS += -I$(TOPDIR)/src/java.base/share/native/launcher \
-I$(TOPDIR)/src/java.base/share/native/libjli \
$(ADD_PLATFORM_INCLUDE_DIR) \
-I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli \
-I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libjli \
#
MACOSX_PLIST_DIR := $(TOPDIR)/src/java.base/macosx/native/launcher
JAVA_MANIFEST := $(TOPDIR)/src/java.base/windows/native/launcher/java.manifest
INCLUDED_LAUNCHERS_FILE := $(SUPPORT_OUTPUTDIR)/modules_static-launchers/$(MODULE)/module-included-launchers.txt
INCLUDED_LAUNCHERS :=
################################################################################
# Build standard launcher.
# Setup make rules for building a standard launcher.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name. It is also
# used as the name of the executable.
#
# Remaining parameters are named arguments. These include:
# MAIN_CLASS The Java main class to launch
# JAVA_ARGS Additional arguments to pass to Java when launching the main class
# EXPAND_CLASSPATH_WILDCARDS Set to true to pass EXPAND_CLASSPATH_WILDCARDS
# ENABLE_ARG_FILES Set to true to pass ENABLE_ARG_FILES
# WINDOWS_JAVAW Set to true to pass JAVAW on Windows
# EXTRA_RCFLAGS Additional EXTRA_RCFLAGS
# MACOSX_PRIVILEGED On macosx, allow to access other processes
# OPTIMIZATION Override default optimization level (LOW)
# OUTPUT_DIR Override default output directory
# VERSION_INFO_RESOURCE Override default Windows resource file
# STATIC_LAUNCHER If true, will use settings for building a static launcher
# LIBS Additional libraries to pass as LIBS argument to SetupJdkExecutable
SetupBuildLauncher = $(NamedParamsMacroTemplate)
define SetupBuildLauncherBody
# Setup default values (unless overridden)
ifeq ($$($1_OPTIMIZATION), )
$1_OPTIMIZATION := LOW
endif
$1_MAIN_MODULE := $(MODULE)
$1_RELAUNCHER_ARGUMENTS :=
ifneq ($$($1_MAIN_CLASS), )
$1_JAVA_ARGS += -Xms8m
$1_LAUNCHER_CLASS := -m $$($1_MAIN_MODULE)/$$($1_MAIN_CLASS)
endif
ifeq ($$($1_ENABLE_ARG_FILES), true)
$1_CFLAGS += -DDISABLE_ARGFILE=JNI_FALSE
else
$1_CFLAGS += -DDISABLE_ARGFILE=JNI_TRUE
# This must be the first argument given, if it should be present
$1_RELAUNCHER_ARGUMENTS += -DjavaLauncherArgFiles=false
endif
ifeq ($$($1_EXPAND_CLASSPATH_WILDCARDS), true)
$1_CFLAGS += -DCLASSPATH_WILDCARDS=JNI_TRUE
else
$1_CFLAGS += -DCLASSPATH_WILDCARDS=JNI_FALSE
$1_RELAUNCHER_ARGUMENTS += -DjavaLauncherWildcards=false
endif
$1_RELAUNCHER_ARGUMENTS += -DjavaLauncherProgname=$1
ifeq ($(call isTargetOs, windows), true)
ifeq ($$($1_WINDOWS_JAVAW), true)
$1_CFLAGS += -DJAVAW
endif
endif
ifneq ($$($1_JAVA_ARGS), )
$1_PREFIXED_JAVA_ARGS := $$(addprefix -J, $$($1_JAVA_ARGS)) \
$$($1_LAUNCHER_CLASS)
$1_JAVA_ARGS_STR := '{ $$(strip $$(foreach a, $$($1_PREFIXED_JAVA_ARGS), \
"$$a"$(COMMA) )) }'
$1_CFLAGS += -DJAVA_ARGS=$$($1_JAVA_ARGS_STR)
# To preserve spaces, substitute them with a hopefully unique pattern
$1_RELAUNCHER_ARGUMENTS += \
-DjavaLauncherArgs=$$(subst $$(SPACE),||||,$$($1_PREFIXED_JAVA_ARGS))
endif
ifeq ($(call isTargetOs, macosx), true)
ifeq ($$($1_MACOSX_PRIVILEGED), true)
$1_PLIST_EXTRA := <key>SecTaskAccess</key><string>allowed</string>
endif
$1_PLIST_FILE := $$(SUPPORT_OUTPUTDIR)/native/$$(MODULE)/$1/Info.plist
$$(eval $$(call SetupTextFileProcessing, BUILD_PLIST_$1, \
SOURCE_FILES := $(TOPDIR)/make/data/bundle/cmdline-Info.plist.template, \
OUTPUT_FILE := $$($1_PLIST_FILE), \
REPLACEMENTS := \
@@ID@@ => $(MACOSX_BUNDLE_ID_BASE).$1 ; \
@@VERSION@@ => $(VERSION_NUMBER) ; \
@@BUILD_VERSION@@ => $(MACOSX_BUNDLE_BUILD_VERSION) ; \
@@EXTRA@@ => $$($1_PLIST_EXTRA), \
))
$1_LDFLAGS += -sectcreate __TEXT __info_plist $$($1_PLIST_FILE)
endif
$1_EXTRA_FILES := $(LAUNCHER_SRC)/main.c
ifeq ($(ASAN_ENABLED), true)
$1_EXTRA_FILES += $(TOPDIR)/make/data/asan/asan_default_options.c
endif
ifeq ($(LSAN_ENABLED), true)
$1_EXTRA_FILES += $(TOPDIR)/make/data/lsan/lsan_default_options.c
endif
ifneq ($$($1_STATIC_LAUNCHER), true)
$1_JDK_LIBS := java.base:libjli
$1_JDK_LIBS_windows := java.base:libjava
else
ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), )
$1_LDFLAGS_FILTER_OUT := -Wl$(COMMA)--exclude-libs$(COMMA)ALL
endif
endif
##############################################################################
## Build launcher "$1"
##############################################################################
$$(eval $$(call SetupJdkExecutable, BUILD_LAUNCHER_$1, \
NAME := $1, \
EXTRA_FILES := $$($1_EXTRA_FILES), \
OPTIMIZATION := $$($1_OPTIMIZATION), \
CFLAGS := $$(LAUNCHER_CFLAGS) \
$$(VERSION_CFLAGS) \
-DLAUNCHER_NAME='"$$(LAUNCHER_NAME)"' \
-DPROGNAME='"$1"' \
$$($1_CFLAGS), \
EXTRA_HEADER_DIRS := java.base:libjvm, \
JAVA_HEADERS := false, \
DISABLED_WARNINGS_gcc := unused-function unused-variable, \
DISABLED_WARNINGS_clang := unused-function, \
LDFLAGS := $$($1_LDFLAGS), \
LDFLAGS_linux := $$(call SetExecutableOrigin,/../lib), \
LDFLAGS_macosx := $$(call SetExecutableOrigin,/../lib), \
LDFLAGS_FILTER_OUT := $$($1_LDFLAGS_FILTER_OUT), \
JDK_LIBS := $$($1_JDK_LIBS), \
JDK_LIBS_windows := $$($1_JDK_LIBS_windows), \
LIBS := $$($1_LIBS), \
LINK_TYPE := $$($1_LINK_TYPE), \
OUTPUT_DIR := $$($1_OUTPUT_DIR), \
OBJECT_DIR := $$($1_OBJECT_DIR), \
VERSIONINFO_RESOURCE := $$($1_VERSION_INFO_RESOURCE), \
EXTRA_RCFLAGS := $$($1_EXTRA_RCFLAGS), \
MANIFEST := $(JAVA_MANIFEST), \
MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS), \
))
$1 += $$(BUILD_LAUNCHER_$1)
$1_RELAUNCHER_ARGUMENTS_FILE := \
$$(SUPPORT_OUTPUTDIR)/static-native/relaunchers/$$(MODULE)/$1-relauncher-arguments.txt
$1_VARDEPS := $$($1_RELAUNCHER_ARGUMENTS)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
$$($1_RELAUNCHER_ARGUMENTS_FILE).vardeps)
$$($1_RELAUNCHER_ARGUMENTS_FILE):
$$(call MakeDir, $$(@D))
$$(ECHO) '$$($1_RELAUNCHER_ARGUMENTS)' > $$@
$1 += $$($1_RELAUNCHER_ARGUMENTS_FILE)
TARGETS += $$($1)
# Record the fact that this launcher is part of the current module.
INCLUDED_LAUNCHERS += $1
# Add a dependency from this launcher to the launcher list
$$(INCLUDED_LAUNCHERS_FILE): $$($1)
$$(BUILD_LAUNCHER_$1): $$(BUILD_PLIST_$1)
ifeq ($(call isTargetOs, macosx), true)
$$(BUILD_LAUNCHER_$1): $$($1_PLIST_FILE)
endif
endef
################################################################################
# Create man pages for jmod to pick up. There should be a one-to-one
# relationship between executables and man pages (even if this is not always
# the case), so piggyback man page generation on the launcher compilation. This
# file may be included from other places as well, so only process man pages
# when called from <module>/Launcher.gmk.
ifeq ($(call isTargetOsType, unix)+$(MAKEFILE_PREFIX), true+Launcher)
# Only build manpages on unix systems.
# We assume all our man pages should reside in section 1.
MAN_FILES_MD := $(wildcard $(addsuffix /*.md, $(call FindModuleManDirs, $(MODULE))))
ifneq ($(MAN_FILES_MD), )
ifeq ($(ENABLE_PANDOC), true)
# Create dynamic man pages from markdown using pandoc. We need
# PANDOC_TROFF_MANPAGE_FILTER, a wrapper around
# PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT. This is created by buildtools-jdk.
# We should also depend on the source code for the filter
PANDOC_TROFF_MANPAGE_FILTER_SOURCE := $(call FindFiles, \
$(TOPDIR)/make/jdk/src/classes/build/tools/pandocfilter)
# The norm in man pages is to display code literals as bold, but pandoc
# "correctly" converts these constructs (encoded in markdown using `...`
# or ```...```) to \f[C]. Ideally, we should use the filter to encapsulate
# the Code/CodeBlock in Strong. While this works for Code, pandoc cannot
# correctly render man page output for CodeBlock wrapped in Strong. So we
# take the easy way out, and post-process the troff output, replacing
# \f[C] with \f[CB]. This has the added benefit of working correctly on
# pandoc prior to version 2.0, which cannot properly produced nested
# formatting in man pages (see https://github.com/jgm/pandoc/issues/3568).
#
# As of pandoc 2.3, the termination of formatting is still broken
# (see https://github.com/jgm/pandoc/issues/4973). We need to replace
# \f[] with \f[R].
MAN_POST_PROCESS := $(SED) -e 's/\\f\[C\]/\\f\[CB\]/g' \
-e 's/\\f\[\]/\\f\[R\]/g'
# Now generate the man pages from markdown using pandoc
$(eval $(call SetupProcessMarkdown, BUILD_MAN_PAGES, \
DEST := $(SUPPORT_OUTPUTDIR)/modules_man/$(MODULE)/man1, \
FILES := $(MAN_FILES_MD), \
FORMAT := man, \
FILTER := $(PANDOC_TROFF_MANPAGE_FILTER), \
POST_PROCESS := $(MAN_POST_PROCESS), \
REPLACEMENTS := \
@@COPYRIGHT_YEAR@@ => $(COPYRIGHT_YEAR) ; \
@@VERSION_SHORT@@ => $(VERSION_SHORT) ; \
@@VERSION_SPECIFICATION@@ => $(VERSION_SPECIFICATION), \
EXTRA_DEPS := $(PANDOC_TROFF_MANPAGE_FILTER) \
$(PANDOC_TROFF_MANPAGE_FILTER_SOURCE), \
))
TARGETS += $(BUILD_MAN_PAGES)
endif
endif
endif
################################################################################
# We need to keep track of which launchers are created by this module. This
# information is required for static builds, to know which relaunchers to
# create. The file module-included-launchers.txt is then read in StaticLibs.gmk.
$(INCLUDED_LAUNCHERS_FILE):
$(call MakeDir, $(@D))
$(ECHO) $(INCLUDED_LAUNCHERS) > $@
TARGETS += $(INCLUDED_LAUNCHERS_FILE)
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,36 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
include JdkNativeCompilation.gmk
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,371 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# This file contains functionality related to compiling a single native source
# file (C, C++ or Objective-C) into an object file. It also harbours related
# functionality for generating PCH (precompiled headers) and Windows resource
# files.
################################################################################
################################################################################
# Creates a recipe that creates a compile_commands.json fragment. Remove any
# occurrences of FIXPATH programs from the command to show the actual invocation.
#
# Param 1: Name of file to create
# Param 2: Working directory
# Param 3: Source file
# Param 4: Compile command
################################################################################
define WriteCompileCommandsFragment
$(call LogInfo, Creating compile commands fragment for $(notdir $3))
$(call MakeDir, $(dir $1))
$(call WriteFile, { \
"directory": "$(strip $(call FixPath, $2))"$(COMMA) \
"file": "$(strip $(call FixPath, $3))"$(COMMA) \
"command": "$(strip $(subst $(DQUOTE),\$(DQUOTE),$(subst \,\\, \
$(subst $(FIXPATH),,$(call FixPath, $4)))))" \
}$(COMMA), \
$1)
endef
################################################################################
# Extensions of files handled by this macro.
NATIVE_SOURCE_EXTENSIONS := %.S %.c %.cpp %.cc %.m %.mm
# Replaces native source extensions with the object file extension in a string.
# Param 1: the string containing source file names with extensions
# The surrounding strip is needed to keep additional whitespace out
define replace_with_obj_extension
$(strip \
$(foreach extension, $(NATIVE_SOURCE_EXTENSIONS), \
$(patsubst $(extension),%$(OBJ_SUFFIX), $(filter $(extension), $1))) \
)
endef
################################################################################
# This pattern is used to transform the output of the microsoft CL compiler
# into a make syntax dependency file (.d)
WINDOWS_SHOWINCLUDE_SED_PATTERN := \
-e '/^Note: including file:/!d' \
-e 's|Note: including file: *||' \
-e 's|\r||g' \
-e 's|\\|/|g' \
-e 's|^\([a-zA-Z]\):|$(WINENV_PREFIX)/\1|g' \
-e '\|$(TOPDIR)|I !d' \
-e 's|$$$$| \\|g' \
#
################################################################################
# This pattern is used to transform a dependency file (.d) to a list
# of make targets for dependent files (.d.targets)
DEPENDENCY_TARGET_SED_PATTERN := \
-e 's/\#.*//' \
-e 's/^[^:]*: *//' \
-e 's/ *\\$$$$//' \
-e 's/^[ ]*//' \
-e '/^$$$$/ d' \
-e 's/$$$$/ :/' \
#
################################################################################
# Setup compiler-specific argument to specify output file
ifeq ($(call isCompiler, microsoft), true)
CC_OUT_OPTION := -Fo
else
CC_OUT_OPTION := -o$(SPACE)
endif
################################################################################
# Create the recipe needed to compile a single native source file.
#
# Parameter 1 is the name of the rule, based on the name of the library/
# program being build and the name of the source code file, e.g.
# BUILD_LIBFOO_fooMain.cpp.
#
# Remaining parameters are named arguments:
# FILE - The full path of the source file to compiler
# BASE - The name of the rule for the entire binary to build ($1)
#
CreateCompiledNativeFile = $(NamedParamsMacroTemplate)
define CreateCompiledNativeFileBody
$1_FILENAME := $$(notdir $$($1_FILE))
# The target file to be generated.
$1_OBJ := $$($$($1_BASE)_OBJECT_DIR)/$$(call replace_with_obj_extension, \
$$($1_FILENAME))
# Generate the corresponding compile_commands.json fragment.
$1_OBJ_JSON = $$(MAKESUPPORT_OUTPUTDIR)/compile-commands/$$(subst /,_,$$(subst \
$$(OUTPUTDIR)/,,$$($1_OBJ))).json
$$($1_BASE)_ALL_OBJS_JSON += $$($1_OBJ_JSON)
# Only continue if this object file hasn't been processed already. This lets
# the first found source file override any other with the same name.
ifeq ($$($1_OBJ_PROCESSED), )
$1_OBJ_PROCESSED := true
# This is the definite source file to use for $1_FILENAME.
$1_SRC_FILE := $$($1_FILE)
$$(eval $$(call SetupCompileFileFlags,$1,$$($1_BASE)))
ifneq ($$(filter %.c, $$($1_FILENAME)), )
# Compile as a C file
$1_CFLAGS += $$($1_WARNINGS_FLAGS)
$1_FLAGS := $(CFLAGS_CCACHE) $$($1_USE_PCH_FLAGS) $$($1_BASE_CFLAGS) \
$$($1_OPT_CFLAGS) $$($1_CFLAGS) -c
$1_COMPILER := $$($$($1_BASE)_CC)
else ifneq ($$(filter %.m, $$($1_FILENAME)), )
# Compile as an Objective-C file
$1_CFLAGS += $$($1_WARNINGS_FLAGS)
$1_FLAGS := -x objective-c $(CFLAGS_CCACHE) $$($1_USE_PCH_FLAGS) \
$$($1_BASE_CFLAGS) $$($1_OPT_CFLAGS) $$($1_CFLAGS) -c
$1_COMPILER := $$($$($1_BASE)_CC)
else ifneq ($$(filter %.S, $$($1_FILENAME)), )
# Compile as preprocessed assembler file
$1_FLAGS := $(BASIC_ASFLAGS) $$($1_BASE_ASFLAGS)
$1_COMPILER := $(AS)
# gcc or clang assembly files must contain an appropriate relative .file
# path for reproducible builds.
ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), )
# If no absolute paths allowed, work out relative source file path
# for assembly .file substitution, otherwise use full file path
ifeq ($(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT), false)
$1_REL_ASM_SRC := $$(call RelativePath, $$($1_FILE), $(WORKSPACE_ROOT))
else
$1_REL_ASM_SRC := $$($1_FILE)
endif
$1_FLAGS := $$($1_FLAGS) -DASSEMBLY_SRC_FILE='"$$($1_REL_ASM_SRC)"' \
-include $(TOPDIR)/make/data/autoheaders/assemblyprefix.h
endif
else ifneq ($$(filter %.cpp %.cc %.mm, $$($1_FILENAME)), )
# Compile as a C++ or Objective-C++ file
$1_CXXFLAGS += $$($1_WARNINGS_FLAGS)
$1_FLAGS := $(CFLAGS_CCACHE) $$($1_USE_PCH_FLAGS) $$($1_BASE_CXXFLAGS) \
$$($1_OPT_CXXFLAGS) $$($1_CXXFLAGS) -c
$1_COMPILER := $$($$($1_BASE)_CXX)
else
$$(error Internal error in NativeCompilation.gmk: no compiler for file $$($1_FILENAME))
endif
# And this is the dependency file for this obj file.
$1_DEPS_FILE := $$(patsubst %$(OBJ_SUFFIX),%.d,$$($1_OBJ))
# The dependency target file lists all dependencies as empty targets to
# avoid make error "No rule to make target" for removed files
$1_DEPS_TARGETS_FILE := $$(patsubst %$(OBJ_SUFFIX),%.d.targets,$$($1_OBJ))
# Only try to load individual dependency information files if the global
# file hasn't been loaded (could happen if make was interrupted).
ifneq ($$($$($1_BASE)_DEPS_FILE_LOADED), true)
# Include previously generated dependency information. (if it exists)
-include $$($1_DEPS_FILE)
-include $$($1_DEPS_TARGETS_FILE)
endif
ifneq ($$(strip $$($1_CFLAGS) $$($1_CXXFLAGS) $$($1_OPTIMIZATION)), )
$1_VARDEPS := $$($1_CFLAGS) $$($1_CXXFLAGS) $$($1_OPTIMIZATION)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_OBJ).vardeps)
endif
$1_OBJ_DEPS := $$($1_SRC_FILE) $$($$($1_BASE)_COMPILE_VARDEPS_FILE) \
$$($$($1_BASE)_EXTRA_DEPS) $$($1_VARDEPS_FILE)
$1_COMPILE_OPTIONS := $$($1_FLAGS) $(CC_OUT_OPTION)$$($1_OBJ) $$($1_SRC_FILE)
# For reproducible builds with gcc and clang ensure random symbol generation is
# seeded deterministically
ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), )
$1_COMPILE_OPTIONS += -frandom-seed="$$($1_FILENAME)"
endif
$$($1_OBJ_JSON): $$($1_OBJ_DEPS)
$$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$($1_SRC_FILE), \
$$($1_COMPILER) $$($1_COMPILE_OPTIONS))
$$($1_OBJ): $$($1_OBJ_DEPS) | $$($$($1_BASE)_BUILD_INFO)
$$(call LogInfo, Compiling $$($1_FILENAME) (for $$($$($1_BASE)_BASENAME)))
$$(call MakeDir, $$(@D))
ifneq ($(TOOLCHAIN_TYPE), microsoft)
$$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
$$($1_COMPILER) $$(GENDEPS_FLAGS) \
$$(addsuffix .tmp, $$($1_DEPS_FILE)) \
$$($1_COMPILE_OPTIONS)))
ifneq ($$($1_DEPS_FILE), )
$$(call fix-deps-file, $$($1_DEPS_FILE))
# Create a dependency target file from the dependency file.
# Solution suggested by:
# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
$(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_DEPS_FILE) \
> $$($1_DEPS_TARGETS_FILE)
endif
else
# The Visual Studio compiler lacks a feature for generating make
# dependencies, but by setting -showIncludes, all included files are
# printed. These are filtered out and parsed into make dependences.
#
# Keep as much as possible on one execution line for best performance
# on Windows. No need to save exit code from compilation since
# pipefail is always active on Windows.
ifeq ($$(filter %.S, $$($1_FILENAME)), )
$$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
$$($1_COMPILER) -showIncludes $$($1_COMPILE_OPTIONS))) \
| $(TR) -d '\r' | $(GREP) -v -e "^Note: including file:" \
-e "^$$($1_FILENAME)$$$$" || test "$$$$?" = "1" ; \
$(ECHO) $$@: \\ > $$($1_DEPS_FILE) ; \
$(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_OBJ).log \
| $(SORT) -u >> $$($1_DEPS_FILE) ; \
$(ECHO) >> $$($1_DEPS_FILE) ; \
$(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_DEPS_FILE) > $$($1_DEPS_TARGETS_FILE)
else
# For assembler calls just create empty dependency lists
$$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
$$($1_COMPILER) $$($1_FLAGS) \
$(CC_OUT_OPTION)$$($1_OBJ) $(AS_NON_ASM_EXTENSION_OPTION) $$($1_SRC_FILE))) \
| $(TR) -d '\r' | $(GREP) -v -e "Assembling:" || test "$$$$?" = "1" ; \
$(ECHO) > $$($1_DEPS_FILE) ; \
$(ECHO) > $$($1_DEPS_TARGETS_FILE)
endif
endif
endif
endef
################################################################################
define CreatePrecompiledHeader
ifneq ($$($1_PRECOMPILED_HEADER), )
ifeq ($(USE_PRECOMPILED_HEADER), true)
ifeq ($(TOOLCHAIN_TYPE), microsoft)
$1_PCH_FILE := $$($1_OBJECT_DIR)/$1.pch
$1_GENERATED_PCH_SRC := $$($1_OBJECT_DIR)/$1_pch.cpp
$1_GENERATED_PCH_OBJ := $$($1_OBJECT_DIR)/$1_pch$(OBJ_SUFFIX)
$$(eval $$(call CreateCompiledNativeFile, $1_$$(notdir $$($1_GENERATED_PCH_SRC)), \
FILE := $$($1_GENERATED_PCH_SRC), \
BASE := $1, \
EXTRA_CXXFLAGS := -I$$(dir $$($1_PRECOMPILED_HEADER)) -Fp$$($1_PCH_FILE) \
-Yc$$(notdir $$($1_PRECOMPILED_HEADER)), \
))
$1_USE_PCH_FLAGS := \
-FI$$(notdir $$($1_PRECOMPILED_HEADER)) -Fp$$($1_PCH_FILE) \
-Yu$$(notdir $$($1_PRECOMPILED_HEADER))
$$($1_ALL_OBJS): $$($1_GENERATED_PCH_OBJ)
# Explicitly add the pch obj file first to ease comparing to old
# hotspot build.
$1_ALL_OBJS := $$($1_GENERATED_PCH_OBJ) $$($1_ALL_OBJS)
$$($1_GENERATED_PCH_SRC):
$(ECHO) "#include \"$$(notdir $$($1_PRECOMPILED_HEADER))\"" > $$@
else ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), )
ifeq ($(TOOLCHAIN_TYPE), gcc)
$1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).gch
$1_USE_PCH_FLAGS := -I$$($1_OBJECT_DIR)/precompiled \
-include $$(notdir $$($1_PRECOMPILED_HEADER))
else ifeq ($(TOOLCHAIN_TYPE), clang)
$1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).pch
$1_USE_PCH_FLAGS := -include-pch $$($1_PCH_FILE)
endif
$1_PCH_DEPS_FILE := $$($1_PCH_FILE).d
$1_PCH_DEPS_TARGETS_FILE := $$($1_PCH_FILE).d.targets
-include $$($1_PCH_DEPS_FILE)
-include $$($1_PCH_DEPS_TARGETS_FILE)
$1_PCH_COMMAND := $$($1_CC) $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \
$$($1_OPT_CFLAGS) -x c++-header -c $(GENDEPS_FLAGS) \
$$(addsuffix .tmp, $$($1_PCH_DEPS_FILE))
$$($1_PCH_FILE): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE)
$$(call LogInfo, Generating precompiled header)
$$(call MakeDir, $$(@D))
$$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
$$($1_PCH_COMMAND) $$< -o $$@))
$$(call fix-deps-file, $$($1_PCH_DEPS_FILE))
$(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_PCH_DEPS_FILE) \
> $$($1_PCH_DEPS_TARGETS_FILE)
$$($1_ALL_OBJS): $$($1_PCH_FILE)
# Generate the corresponding compile_commands.json fragment.
$1_PCH_FILE_JSON := $$(MAKESUPPORT_OUTPUTDIR)/compile-commands/$$(subst /,_,$$(subst \
$$(OUTPUTDIR)/,,$$($1_PCH_FILE))).json
$1_ALL_OBJS_JSON += $$($1_PCH_FILE_JSON)
$$($1_PCH_FILE_JSON): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE)
$$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$<, \
$$($1_PCH_COMMAND) $$< -o $$($1_PCH_FILE))
endif
endif
endif
endef
################################################################################
define CreateWindowsResourceFile
ifneq ($$($1_VERSIONINFO_RESOURCE), )
$1_RES := $$($1_OBJECT_DIR)/$$($1_BASENAME).res
$1_RES_DEPS_FILE := $$($1_RES).d
$1_RES_DEPS_TARGETS_FILE := $$($1_RES).d.targets
-include $$($1_RES_DEPS_FILE)
-include $$($1_RES_DEPS_TARGETS_FILE)
$1_RES_VARDEPS := $$($1_RC) $$($1_RCFLAGS)
$1_RES_VARDEPS_FILE := $$(call DependOnVariable, $1_RES_VARDEPS, \
$$($1_RES).vardeps)
$$($1_RES): $$($1_VERSIONINFO_RESOURCE) $$($1_RES_VARDEPS_FILE)
$$(call LogInfo, Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$($1_BASENAME)))
$$(call MakeDir, $$(@D) $$($1_OBJECT_DIR))
$$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \
$$($1_RC) $$($1_RCFLAGS) $$($1_SYSROOT_CFLAGS) -Fo$$@ \
$$($1_VERSIONINFO_RESOURCE) 2>&1 ))
# Windows RC compiler does not support -showIncludes, so we mis-use CL
# for this. Filter out RC specific arguments that are unknown to CL.
# For some unknown reason, in this case CL actually outputs the show
# includes to stderr so need to redirect it to hide the output from the
# main log.
$$(call ExecuteWithLog, $$($1_RES_DEPS_FILE)$(OBJ_SUFFIX), \
$$($1_CC) $$(filter-out -l%, $$($1_RCFLAGS)) \
$$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \
-Fo$$($1_RES_DEPS_FILE)$(OBJ_SUFFIX) -P -Fi$$($1_RES_DEPS_FILE).pp \
$$($1_VERSIONINFO_RESOURCE)) 2>&1 \
| $(TR) -d '\r' | $(GREP) -v -e "^Note: including file:" \
-e "^$$(notdir $$($1_VERSIONINFO_RESOURCE))$$$$" || test "$$$$?" = "1" ; \
$(ECHO) $$($1_RES): \\ > $$($1_RES_DEPS_FILE) ; \
$(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEPS_FILE)$(OBJ_SUFFIX).log \
>> $$($1_RES_DEPS_FILE) ; \
$(ECHO) >> $$($1_RES_DEPS_FILE) ; \
$(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_RES_DEPS_FILE) \
> $$($1_RES_DEPS_TARGETS_FILE)
endif
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,109 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# This file contains functionality related to native debug symbol handling.
################################################################################
################################################################################
define CreateDebugSymbols
ifneq ($$($1_COPY_DEBUG_SYMBOLS), false)
$1_COPY_DEBUG_SYMBOLS := $(COPY_DEBUG_SYMBOLS)
endif
ifneq ($$($1_ZIP_EXTERNAL_DEBUG_SYMBOLS), false)
$1_ZIP_EXTERNAL_DEBUG_SYMBOLS := $(ZIP_EXTERNAL_DEBUG_SYMBOLS)
endif
$1_CREATE_DEBUGINFO := false
ifeq ($$($1_COPY_DEBUG_SYMBOLS), true)
ifneq ($$($1_DEBUG_SYMBOLS), false)
$$(call SetIfEmpty, $1_SYMBOLS_DIR, $$($1_OUTPUT_DIR))
# Only copy debug symbols for dynamic libraries and programs.
ifneq ($$($1_TYPE), STATIC_LIBRARY)
$1_CREATE_DEBUGINFO := true
# Setup where the platform specific debuginfo files end up
ifeq ($(call isTargetOs, windows), true)
$1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_BASENAME).pdb \
$$($1_SYMBOLS_DIR)/$$($1_BASENAME).map
$1_DEBUGINFO_ZIP := $$($1_SYMBOLS_DIR)/$$($1_BASENAME).diz
else ifeq ($(call isTargetOs, macosx), true)
$1_DEBUGINFO_FILES := \
$$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM/Contents/Info.plist \
$$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM/Contents/Resources/DWARF/$$($1_BASENAME)
$1_DEBUGINFO_ZIP := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).diz
else ifeq ($(call isTargetOsType, unix), true)
$1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).debuginfo
$1_DEBUGINFO_ZIP := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).diz
endif
ifeq ($(call isTargetOs, windows), true)
$1_EXTRA_LDFLAGS += -debug "-pdb:$$($1_SYMBOLS_DIR)/$$($1_BASENAME).pdb" \
"-map:$$($1_SYMBOLS_DIR)/$$($1_BASENAME).map"
ifeq ($(SHIP_DEBUG_SYMBOLS), public)
$1_EXTRA_LDFLAGS += "-pdbstripped:$$($1_SYMBOLS_DIR)/$$($1_BASENAME).stripped.pdb"
endif
endif
# Since the link rule creates more than one file that we want to track,
# we have to use some tricks to get make to cooperate. To properly
# trigger downstream dependants of $$($1_DEBUGINFO_FILES), we must have
# a recipe in the rule below. To avoid rerunning the recipe every time
# have it touch the target. If a debuginfo file is deleted by something
# external, explicitly delete the TARGET to trigger a rebuild of both.
ifneq ($$(wildcard $$($1_DEBUGINFO_FILES)), $$($1_DEBUGINFO_FILES))
$$(call LogDebug, Deleting $$($1_BASENAME) because debuginfo files are missing)
$$(shell $(RM) $$($1_TARGET))
endif
$$($1_DEBUGINFO_FILES): $$($1_TARGET)
$$(if $$(CORRECT_FUNCTION_IN_RECIPE_EVALUATION), \
$$(if $$(wildcard $$@), , $$(error $$@ was not created for $$<)) \
)
$(TOUCH) $$@
$1 += $$($1_DEBUGINFO_FILES)
ifeq ($$($1_ZIP_EXTERNAL_DEBUG_SYMBOLS), true)
# The dependency on TARGET is needed for debuginfo files
# to be rebuilt properly.
$$($1_DEBUGINFO_ZIP): $$($1_DEBUGINFO_FILES) $$($1_TARGET)
$(CD) $$($1_SYMBOLS_DIR) && \
$(ZIPEXE) -q -r $$@ $$(subst $$($1_SYMBOLS_DIR)/,, $$($1_DEBUGINFO_FILES))
$1 += $$($1_DEBUGINFO_ZIP)
endif
endif # !STATIC_LIBRARY
endif # $1_DEBUG_SYMBOLS != false
endif # COPY_DEBUG_SYMBOLS
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,251 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# This file contains functionality related to setting up compiler and linker
# flags, based on various more abstract sources of compilation description,
# like optimization level.
################################################################################
################################################################################
# $1 is the prefix of the file to be compiled
# $2 is the prefix of the library, i.e. $$($1_BASE)
define SetupCompileFileFlags
ifeq ($$($1_OPTIMIZATION), )
$1_OPT_CFLAGS := $$($2_OPT_CFLAGS)
$1_OPT_CXXFLAGS := $$($2_OPT_CXXFLAGS)
else
ifeq ($$($1_OPTIMIZATION), NONE)
$1_OPT_CFLAGS := $(C_O_FLAG_NONE)
$1_OPT_CXXFLAGS := $(CXX_O_FLAG_NONE)
else ifeq ($$($1_OPTIMIZATION), LOW)
$1_OPT_CFLAGS := $(C_O_FLAG_NORM)
$1_OPT_CXXFLAGS := $(CXX_O_FLAG_NORM)
else ifeq ($$($1_OPTIMIZATION), HIGH)
$1_OPT_CFLAGS := $(C_O_FLAG_HI)
$1_OPT_CXXFLAGS := $(CXX_O_FLAG_HI)
else ifeq ($$($1_OPTIMIZATION), HIGHEST)
$1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST)
$1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST)
else ifeq ($$($1_OPTIMIZATION), HIGHEST_JVM)
$1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST_JVM)
$1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST_JVM)
else ifeq ($$($1_OPTIMIZATION), SIZE)
$1_OPT_CFLAGS := $(C_O_FLAG_SIZE)
$1_OPT_CXXFLAGS := $(CXX_O_FLAG_SIZE)
else
$$(error Unknown value for file OPTIMIZATION: $$($1_OPTIMIZATION))
endif
endif
ifneq ($$($2_PRECOMPILED_HEADER), )
ifeq ($$(filter $$($1_FILENAME), $$($2_PRECOMPILED_HEADER_EXCLUDE)), )
$1_USE_PCH_FLAGS := $$($2_USE_PCH_FLAGS)
endif
endif
ifneq ($(DISABLE_WARNING_PREFIX), )
$1_WARNINGS_FLAGS := $$(addprefix $(DISABLE_WARNING_PREFIX), \
$$($2_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$$($1_FILENAME)) \
$$($2_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)_$$($1_FILENAME)))
endif
$1_BASE_CFLAGS := $$($2_CFLAGS) $$($2_EXTRA_CFLAGS) \
$$($2_SYSROOT_CFLAGS)
$1_BASE_CXXFLAGS := $$($2_CXXFLAGS) $$($2_EXTRA_CXXFLAGS) \
$$($2_SYSROOT_CFLAGS) $$($1_EXTRA_CXXFLAGS)
$1_BASE_ASFLAGS := $$($2_ASFLAGS) $$($2_EXTRA_ASFLAGS)
endef
################################################################################
define SetupCompilerFlags
# Pickup extra OPENJDK_TARGET_OS_TYPE, OPENJDK_TARGET_OS, TOOLCHAIN_TYPE and
# OPENJDK_TARGET_OS plus OPENJDK_TARGET_CPU pair dependent variables for CFLAGS.
$1_EXTRA_CFLAGS := $$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_CFLAGS_$(OPENJDK_TARGET_OS)) \
$$($1_CFLAGS_$(TOOLCHAIN_TYPE)) \
$$($1_CFLAGS_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU))
ifneq ($(DEBUG_LEVEL), release)
# Pickup extra debug dependent variables for CFLAGS
$1_EXTRA_CFLAGS += $$($1_CFLAGS_debug)
$1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)_debug)
$1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_debug)
$1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU)_debug)
else
$1_EXTRA_CFLAGS += $$($1_CFLAGS_release)
$1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)_release)
$1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_release)
$1_EXTRA_CFLAGS += $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU)_release)
endif
ifeq ($(STATIC_LIBS), true)
$1_EXTRA_CFLAGS += -DSTATIC_BUILD=1
endif
# Pickup extra OPENJDK_TARGET_OS_TYPE, OPENJDK_TARGET_OS and/or TOOLCHAIN_TYPE
# dependent variables for CXXFLAGS.
$1_EXTRA_CXXFLAGS := $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)) \
$$($1_CXXFLAGS_$(TOOLCHAIN_TYPE))
ifneq ($(DEBUG_LEVEL), release)
# Pickup extra debug dependent variables for CXXFLAGS
$1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_debug)
$1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS_TYPE)_debug)
$1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)_debug)
else
$1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_release)
$1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS_TYPE)_release)
$1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)_release)
endif
ifeq ($(STATIC_LIBS), true)
$1_EXTRA_CXXFLAGS += $$(STATIC_LIB_CFLAGS)
endif
# If no C++ flags are explicitly set, default to using the C flags.
# After that, we can set additional C++ flags that should not interfere
# with the mechanism for copying the C flags by default.
ifeq ($$($1_CXXFLAGS), )
$1_CXXFLAGS := $$($1_CFLAGS)
endif
ifeq ($$(strip $$($1_EXTRA_CXXFLAGS)), )
$1_EXTRA_CXXFLAGS := $$($1_EXTRA_CFLAGS)
endif
$$(call SetIfEmpty, $1_COMPILE_WITH_DEBUG_SYMBOLS, $$(COMPILE_WITH_DEBUG_SYMBOLS))
ifeq ($(STATIC_LIBS), true)
# For release builds where debug symbols are configured to be moved to
# separate debuginfo files, disable debug symbols for static libs instead.
# We don't currently support this configuration and we don't want symbol
# information in release builds unless explicitly asked to provide it.
ifeq ($(DEBUG_LEVEL), release)
ifeq ($(COPY_DEBUG_SYMBOLS), true)
$1_COMPILE_WITH_DEBUG_SYMBOLS := false
endif
endif
endif
ifeq ($$($1_COMPILE_WITH_DEBUG_SYMBOLS), true)
$1_EXTRA_CFLAGS += $$(CFLAGS_DEBUG_SYMBOLS)
$1_EXTRA_CXXFLAGS += $$(CFLAGS_DEBUG_SYMBOLS)
$1_EXTRA_ASFLAGS += $$(ASFLAGS_DEBUG_SYMBOLS)
endif
# Pass the library name for static JNI library naming
ifeq ($$($1_TYPE), STATIC_LIBRARY)
$1_EXTRA_CFLAGS += -DLIBRARY_NAME=$$($1_NAME)
$1_EXTRA_CXXFLAGS += -DLIBRARY_NAME=$$($1_NAME)
endif
# Pick up disabled warnings, if possible on this platform.
ifneq ($(DISABLE_WARNING_PREFIX), )
$1_EXTRA_CFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), \
$$(DISABLED_WARNINGS) \
$$(DISABLED_WARNINGS_C) \
$$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)) \
$$($1_DISABLED_WARNINGS_C_$(TOOLCHAIN_TYPE)) \
$$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)) \
$$($1_DISABLED_WARNINGS_C_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)))
$1_EXTRA_CXXFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), \
$$(DISABLED_WARNINGS) \
$$(DISABLED_WARNINGS_CXX) \
$$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)) \
$$($1_DISABLED_WARNINGS_CXX_$(TOOLCHAIN_TYPE)) \
$$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)) \
$$($1_DISABLED_WARNINGS_CXX_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)))
endif
# Check if warnings should be considered errors.
# Pick first binary and toolchain specific, then binary specific, then general setting.
ifeq ($$($1_WARNINGS_AS_ERRORS_$(TOOLCHAIN_TYPE)), )
ifeq ($$($1_WARNINGS_AS_ERRORS), )
$1_WARNINGS_AS_ERRORS_$(TOOLCHAIN_TYPE) := $$(WARNINGS_AS_ERRORS)
else
$1_WARNINGS_AS_ERRORS_$(TOOLCHAIN_TYPE) := $$($1_WARNINGS_AS_ERRORS)
endif
endif
ifeq ($$($1_WARNINGS_AS_ERRORS_$(TOOLCHAIN_TYPE)), true)
$1_EXTRA_CFLAGS += $(CFLAGS_WARNINGS_ARE_ERRORS)
$1_EXTRA_CXXFLAGS += $(CFLAGS_WARNINGS_ARE_ERRORS)
endif
ifeq (true, $$($1_LINK_TIME_OPTIMIZATION))
$1_EXTRA_CFLAGS += $(C_O_FLAG_LTO)
$1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_LTO)
endif
ifeq (NONE, $$($1_OPTIMIZATION))
$1_OPT_CFLAGS := $(C_O_FLAG_NONE)
$1_OPT_CXXFLAGS := $(CXX_O_FLAG_NONE)
else ifeq (LOW, $$($1_OPTIMIZATION))
$1_OPT_CFLAGS := $(C_O_FLAG_NORM)
$1_OPT_CXXFLAGS := $(CXX_O_FLAG_NORM)
else ifeq (HIGH, $$($1_OPTIMIZATION))
$1_OPT_CFLAGS := $(C_O_FLAG_HI)
$1_OPT_CXXFLAGS := $(CXX_O_FLAG_HI)
else ifeq (HIGHEST, $$($1_OPTIMIZATION))
$1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST)
$1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST)
else ifeq (HIGHEST_JVM, $$($1_OPTIMIZATION))
$1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST_JVM)
$1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST_JVM)
else ifeq (SIZE, $$($1_OPTIMIZATION))
$1_OPT_CFLAGS := $(C_O_FLAG_SIZE)
$1_OPT_CXXFLAGS := $(CXX_O_FLAG_SIZE)
else ifneq (, $$($1_OPTIMIZATION))
$$(error Unknown value for OPTIMIZATION: $$($1_OPTIMIZATION))
endif
endef
################################################################################
define SetupLinkerFlags
# Pickup extra OPENJDK_TARGET_OS_TYPE, OPENJDK_TARGET_OS and TOOLCHAIN_TYPE
# dependent variables for LDFLAGS and LIBS, and additionally the pair dependent
# TOOLCHAIN_TYPE plus OPENJDK_TARGET_OS
ifeq ($$($1_LINK_TIME_OPTIMIZATION), true)
$1_EXTRA_LDFLAGS += $(LDFLAGS_LTO)
# Instruct the ld64 linker not to delete the temporary object file
# generated during Link Time Optimization
ifeq ($(call isTargetOs, macosx), true)
$1_EXTRA_LDFLAGS += -Wl,-object_path_lto,$$($1_OBJECT_DIR)/$$($1_NAME)_lto_helper.o
endif
ifeq ($(TOOLCHAIN_TYPE), microsoft)
$1_EXTRA_LDFLAGS += -LTCGOUT:$$($1_OBJECT_DIR)/$$($1_NAME).iobj
endif
endif
$1_EXTRA_LDFLAGS += $$($1_LDFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_LDFLAGS_$(OPENJDK_TARGET_OS)) \
$$($1_LDFLAGS_$(TOOLCHAIN_TYPE)) $$($1_LDFLAGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS))
$1_EXTRA_LIBS += $$($1_LIBS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_LIBS_$(OPENJDK_TARGET_OS)) \
$$($1_LIBS_$(TOOLCHAIN_TYPE)) $$($1_LIBS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS))
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

247
make/common/native/Link.gmk Normal file
View file

@ -0,0 +1,247 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# This file contains functionality related to linking a native binary;
# creating either a dynamic library, a static library or an executable.
################################################################################
################################################################################
# GetEntitlementsFile
# Find entitlements file for executable when signing on macosx. If no
# specialized file is found, returns the default file.
# This macro might be called from custom makefiles.
# $1 Executable to find entitlements file for.
ENTITLEMENTS_DIR := $(TOPDIR)/make/data/macosxsigning
ifeq ($(MACOSX_CODESIGN_MODE), debug)
CODESIGN_PLIST_SUFFIX := -debug
else
CODESIGN_PLIST_SUFFIX :=
endif
DEFAULT_ENTITLEMENTS_FILE := $(ENTITLEMENTS_DIR)/default$(CODESIGN_PLIST_SUFFIX).plist
GetEntitlementsFile = \
$(foreach f, $(ENTITLEMENTS_DIR)/$(strip $(notdir $1))$(CODESIGN_PLIST_SUFFIX).plist, \
$(if $(wildcard $f), $f, $(DEFAULT_ENTITLEMENTS_FILE)) \
)
ifeq ($(call isCompiler, gcc), true)
SetSharedLibraryName = \
-Wl,-soname=$1
else ifeq ($(call isCompiler, clang), true)
ifeq ($(call isTargetOs, macosx), true)
SetSharedLibraryName = \
-Wl,-install_name,@rpath/$1
else ifeq ($(call isTargetOs, aix), true)
SetSharedLibraryName =
else
# Default works for linux, might work on other platforms as well.
SetSharedLibraryName = \
-Wl,-soname=$1
endif
else ifeq ($(call isCompiler, microsoft), true)
SetSharedLibraryName =
else
$(error Unknown toolchain)
endif
################################################################################
define SetupLinking
# Unless specifically set, stripping should only happen if symbols are also
# being copied.
$$(call SetIfEmpty, $1_STRIP_SYMBOLS, $$($1_COPY_DEBUG_SYMBOLS))
# Default to using the global STRIPFLAGS. Allow for overriding with an
# empty value
$1_STRIPFLAGS ?= $(STRIPFLAGS)
endef
################################################################################
define CreateLinkedResult
ifeq ($$($1_TYPE), STATIC_LIBRARY)
$$(eval $$(call CreateStaticLibrary,$1))
else
$$(eval $$(call CreateDynamicLibraryOrExecutable,$1))
endif
endef
################################################################################
define CreateStaticLibrary
# Include partial linking when building the static library with clang on linux
ifeq ($(call isTargetOs, linux), true)
ifneq ($(findstring $(TOOLCHAIN_TYPE), clang), )
$1_ENABLE_PARTIAL_LINKING := true
endif
endif
$1_VARDEPS := $$($1_AR) $$(ARFLAGS) $$($1_LIBS) \
$$($1_EXTRA_LIBS)
ifeq ($$($1_ENABLE_PARTIAL_LINKING), true)
$1_VARDEPS += $$($1_LD) $$($1_SYSROOT_LDFLAGS)
endif
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
$1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_EXTRA_LINK_DEPS) $$($1_VARDEPS_FILE)
$1_AR_OBJ_ARG := $$($1_LD_OBJ_ARG)
# With clang on linux, partial linking is enabled and 'AR' takes the output
# object from the partial linking step.
ifeq ($$($1_ENABLE_PARTIAL_LINKING), true)
$1_TARGET_RELOCATABLE := $$($1_OBJECT_DIR)/$$($1_PREFIX)$$($1_NAME)_relocatable$(OBJ_SUFFIX)
$1_AR_OBJ_ARG := $$($1_TARGET_RELOCATABLE)
endif
$$($1_TARGET): $$($1_TARGET_DEPS)
ifneq ($$($1_OBJ_FILE_LIST), )
ifeq ($$($1_LINK_OBJS_RELATIVE), true)
$$(eval $$(call ListPathsSafely, $1_ALL_OBJS_RELATIVE, $$($1_OBJ_FILE_LIST)))
else
$$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST)))
endif
endif
$$(call LogInfo, Building static library $$($1_BASENAME))
$$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR))
# Do partial linking.
ifeq ($$($1_ENABLE_PARTIAL_LINKING), true)
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_partial_link, \
$(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \
$$($1_LD) $(LDFLAGS_CXX_PARTIAL_LINKING) $$($1_SYSROOT_LDFLAGS) \
-o $$($1_TARGET_RELOCATABLE) $$($1_LD_OBJ_ARG))
# 'ld -r' might invalidate the .llvm_addrsig section, and this will cause subsequent
# calls to lld (with '-Wl,--icf=safe') to fail when linking with this library, so
# remove that section.
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_objcopy_remove_llvm_addrsig_section, \
$$($1_OBJCOPY) --remove-section=.llvm_addrsig $$($1_TARGET_RELOCATABLE))
endif
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_run_ar, \
$(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \
$$($1_AR) $$(ARFLAGS) -r -cs $$($1_TARGET) \
$$($1_AR_OBJ_ARG) $$($1_RES))
$$(ECHO) $$(strip $$($1_LIBS) $$($1_EXTRA_LIBS)) > $$($1_TARGET).lib-flags.txt
endef
################################################################################
define CreateDynamicLibraryOrExecutable
# A shared dynamic library or an executable binary has been specified
ifeq ($$($1_TYPE), LIBRARY)
# Generating a dynamic library.
$1_EXTRA_LDFLAGS += $$(call SetSharedLibraryName,$$($1_BASENAME))
endif
ifeq ($(MACOSX_CODESIGN_MODE), hardened)
$1_CODESIGN_OPTS := "$(MACOSX_CODESIGN_IDENTITY)" --timestamp \
--options runtime
else ifeq ($(MACOSX_CODESIGN_MODE), debug)
$1_CODESIGN_OPTS := -
endif
$1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) \
$$($1_EXTRA_LDFLAGS) $$($1_LIBS) $$($1_EXTRA_LIBS) \
$$($1_DEBUGINFO_FILES) $$($1_STRIPFLAGS)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
$1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_EXTRA_LINK_DEPS) $$($1_VARDEPS_FILE)
$$($1_TARGET): $$($1_TARGET_DEPS)
ifneq ($$($1_OBJ_FILE_LIST), )
ifeq ($$($1_LINK_OBJS_RELATIVE), true)
$$(eval $$(call ListPathsSafely, $1_ALL_OBJS_RELATIVE, $$($1_OBJ_FILE_LIST)))
else
$$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST)))
endif
endif
$$(call LogInfo, Linking $$($1_BASENAME))
$$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR))
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_run_ld, \
$$(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \
$$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \
$$($1_SYSROOT_LDFLAGS) -o $$($1_TARGET) $$($1_LD_OBJ_ARG) \
$$($1_LIBS) $$($1_EXTRA_LIBS))
ifeq ($$($1_CREATE_DEBUGINFO), true)
ifeq ($(call isTargetOs, linux), true)
# This cannot be run separately since it updates the original target
# file.
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_create_debuginfo, \
$$($1_OBJCOPY) --only-keep-debug $$($1_TARGET) $$($1_DEBUGINFO_FILES))
$$(CHMOD) -x $$($1_DEBUGINFO_FILES)
else ifeq ($(call isTargetOs, aix), true)
# AIX does not provide the equivalent of objcopy to extract debug
# symbols, so we copy unstripped library instead.
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_create_debuginfo, \
$(CP) $$($1_TARGET) $$($1_DEBUGINFO_FILES))
else ifeq ($(call isTargetOs, macosx), true)
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_create_debuginfo, \
$(DSYMUTIL) --out $$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM $$($1_TARGET))
endif
endif
ifneq ($$($1_STRIP_SYMBOLS), false)
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_strip, \
$$($1_STRIP) $$($1_STRIPFLAGS) $$($1_TARGET))
endif
ifeq ($$($1_CREATE_DEBUGINFO), true)
ifeq ($(call isTargetOs, linux), true)
# Run this after strip is called, since strip can sometimes mangle
# the embedded debuglink, which we want to avoid.
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_add_debuginfo_link, \
$(CD) $$($1_SYMBOLS_DIR) && \
$$($1_OBJCOPY) --add-gnu-debuglink=$$($1_DEBUGINFO_FILES) $$($1_TARGET))
endif
endif
ifneq ($(MACOSX_CODESIGN_MODE), disabled)
# Remove signature explicitly first to avoid warnings if the linker
# added a default adhoc signature.
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_codesign_clear, \
$(CODESIGN) --remove-signature $$@)
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_codesign_add, \
$(CODESIGN) -f -s $$($1_CODESIGN_OPTS) --entitlements \
$$(call GetEntitlementsFile, $$@) $$@)
endif
ifneq ($(SIGNING_HOOK), )
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_call_signing_hook, \
$(SIGNING_HOOK) $$($1_TARGET))
endif
# This is for IDE integration purposes only, and is not normally generated
$1_LDFLAGS_FILE := $$(MAKESUPPORT_OUTPUTDIR)/compile-commands/$$($1_UNIQUE_NAME)-ldflags.txt
$1_ALL_LD_ARGS := $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \
$$($1_LIBS) $$($1_EXTRA_LIBS)
$$($1_LDFLAGS_FILE): $$($1_VARDEPS_FILE)
$$(call LogInfo, Creating compile commands linker flags output for $$($1_BASENAME))
$$(call MakeDir, $$(dir $$@))
$$(ECHO) $$($1_ALL_LD_ARGS) > $$@
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,130 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# This file contains functionality related to linking a native binary;
# creating either a dynamic library, a static library or an executable.
################################################################################
################################################################################
define CreateLinkedResultMicrosoft
ifeq ($$($1_TYPE), STATIC_LIBRARY)
$$(eval $$(call CreateStaticLibraryMicrosoft,$1))
else
$$(eval $$(call CreateDynamicLibraryOrExecutableMicrosoft,$1))
endif
endef
################################################################################
define CreateStaticLibraryMicrosoft
$1_VARDEPS := $$($1_LIB) $$(LIBFLAGS) $$($1_LIBS) \
$$($1_EXTRA_LIBS)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
$1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_RES) $$($1_EXTRA_LINK_DEPS) \
$$($1_VARDEPS_FILE)
$$($1_TARGET): $$($1_TARGET_DEPS)
ifneq ($$($1_OBJ_FILE_LIST), )
$$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST)))
endif
$$(call LogInfo, Building static library $$($1_BASENAME))
$$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR))
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_run_lib, \
$$($1_LIB) -nologo $$(LIBFLAGS) -out:$$($1_TARGET) \
$$($1_LD_OBJ_ARG))
$$(ECHO) $$(strip $$($1_LIBS) $$($1_EXTRA_LIBS)) > $$($1_TARGET).lib-flags.txt
endef
################################################################################
define CreateDynamicLibraryOrExecutableMicrosoft
ifeq ($$($1_EMBED_MANIFEST), true)
$1_EXTRA_LDFLAGS += -manifest:embed
endif
$1_IMPORT_LIBRARY := $$($1_OBJECT_DIR)/$$($1_NAME).lib
$1_EXTRA_LDFLAGS += "-implib:$$($1_IMPORT_LIBRARY)"
ifeq ($$($1_TYPE), LIBRARY)
# To properly trigger downstream dependants of the import library, just as
# for debug files, we must have a recipe in the rule. To avoid rerunning
# the recipe every time have it touch the target. If an import library
# file is deleted by something external, explicitly delete the target to
# trigger a rebuild of both.
ifneq ($$(wildcard $$($1_IMPORT_LIBRARY)), $$($1_IMPORT_LIBRARY))
$$(call LogDebug, Deleting $$($1_BASENAME) because import library is missing)
$$(shell $(RM) $$($1_TARGET))
endif
$$($1_IMPORT_LIBRARY): $$($1_TARGET)
$(TOUCH) $$@
$1 += $$($1_IMPORT_LIBRARY)
endif
$1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) \
$$($1_EXTRA_LDFLAGS) $$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_MT) \
$$($1_MANIFEST_VERSION)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
$1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_RES) $$($1_MANIFEST) \
$$($1_EXTRA_LINK_DEPS) $$($1_VARDEPS_FILE)
$$($1_TARGET): $$($1_TARGET_DEPS)
ifneq ($$($1_OBJ_FILE_LIST), )
$$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST)))
endif
$$(call LogInfo, Linking $$($1_BASENAME))
$$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR))
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_run_ld, \
$$($1_LD) -nologo $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \
$$($1_SYSROOT_LDFLAGS) -out:$$($1_TARGET) $$($1_LD_OBJ_ARG) \
$$($1_RES) $$($1_LIBS) $$($1_EXTRA_LIBS)) \
| $(GREP) -v "^ Creating library .*\.lib and object .*\.exp" || \
test "$$$$?" = "1"
ifeq ($(call isBuildOsEnv, windows.wsl2), true)
$$(CHMOD) +x $$($1_TARGET)
endif
ifneq ($$($1_MANIFEST), )
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_run_mt, \
$$($1_MT) -nologo -manifest $$($1_MANIFEST) \
-identity:"$$($1_NAME).exe$$(COMMA) version=$$($1_MANIFEST_VERSION)" \
'-outputresource:$$($1_TARGET);$$(HASH)1')
endif
ifneq ($(SIGNING_HOOK), )
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_call_signing_hook, \
$(SIGNING_HOOK) $$($1_TARGET))
endif
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1,250 @@
#
# Copyright (c) 2011, 2025, 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.
#
include MakeIncludeStart.gmk
ifeq ($(INCLUDE), true)
################################################################################
# This file contains functionality related to handling paths for source files
# and object files. This is complicated by the fact that we usually, but not
# always, use absolute instead of relative paths. It is further complicated
# by the fact that not all tools allow inputting large lists of files as
# "@-files", which we normally use to avoid hitting command line length limits.
# Finally this file contains functionality for locating all source code files
# that should be included in the compilation.
################################################################################
################################################################################
# When absolute paths are not allowed in the output, and the compiler does not
# support any options to avoid it, we need to rewrite compile commands to use
# relative paths. By doing this, the __FILE__ macro will resolve to relative
# paths. The relevant input paths on the command line are the -I flags and the
# path to the source file itself.
#
# The macro MakeCommandRelative is used to rewrite the command line like this:
# 'CD $(WORKSPACE_ROOT) && <cmd>'
# and changes all paths in cmd to be relative to the workspace root. This only
# works properly if the build dir is inside the workspace root. If it's not,
# relative paths are still calculated, but depending on the distance between the
# dirs, paths in the build dir may end up as essentially absolute anyway.
#
# The fix-deps-file macro is used to adjust the contents of the generated make
# dependency files to contain paths compatible with make.
#
REWRITE_PATHS_RELATIVE = false
ifeq ($(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT)-$(FILE_MACRO_CFLAGS), false-)
REWRITE_PATHS_RELATIVE = true
endif
# CCACHE_BASEDIR needs fix-deps-file as makefiles use absolute filenames for
# object files while CCACHE_BASEDIR will make ccache relativize all paths for
# its compiler. The compiler then produces relative dependency files.
# make does not know a relative and absolute filename is the same so it will
# ignore such dependencies. This only applies when the OUTPUTDIR is inside
# the WORKSPACE_ROOT.
ifneq ($(CCACHE), )
ifneq ($(filter $(WORKSPACE_ROOT)/%, $(OUTPUTDIR)), )
REWRITE_PATHS_RELATIVE = true
endif
endif
ifeq ($(REWRITE_PATHS_RELATIVE), true)
# Need to handle -I flags as both '-Ifoo' and '-I foo'.
MakeCommandRelative = \
$(CD) $(WORKSPACE_ROOT) && \
$(foreach o, $1, \
$(if $(filter $(WORKSPACE_ROOT)/% $(OUTPUTDIR)/%, $o), \
$(call RelativePath, $o, $(WORKSPACE_ROOT)) \
, \
$(if $(filter -I$(WORKSPACE_ROOT)/%, $o), \
-I$(call RelativePath, $(patsubst -I%, %, $o), $(WORKSPACE_ROOT)) \
, \
$o \
) \
) \
)
# When compiling with relative paths, the deps file may come out with relative
# paths, and that path may start with './'. First remove any leading ./, then
# add WORKSPACE_ROOT to any line not starting with /, while allowing for
# leading spaces. There may also be multiple entries on the same line, so start
# with splitting such lines.
# Non GNU sed (BSD on macosx) cannot substitute in literal \n using regex.
# Instead use a bash escaped literal newline. To avoid having unmatched quotes
# ruin the ability for an editor to properly syntax highlight this file, define
# that newline sequence as a separate variable and add the closing quote behind
# a comment.
sed_newline := \'$$'\n''#'
define fix-deps-file
$(SED) \
-e 's|\([^ ]\) \{1,\}\([^\\:]\)|\1 \\$(sed_newline) \2|g' \
$1.tmp \
| $(SED) \
-e 's|^\([ ]*\)\./|\1|' \
-e '/^[ ]*[^/ ]/s|^\([ ]*\)|\1$(WORKSPACE_ROOT)/|' \
> $1
endef
else
# By default the MakeCommandRelative macro does nothing.
MakeCommandRelative = $1
# No adjustment is needed.
define fix-deps-file
$(MV) $1.tmp $1
endef
endif
################################################################################
define SetupSourceFiles
$$(foreach d, $$($1_SRC), $$(if $$(wildcard $$d), , \
$$(error SRC specified to SetupNativeCompilation $1 contains missing directory $$d)))
$1_SRCS_RAW := $$(call FindFiles, $$($1_SRC))
# Order src files according to the order of the src dirs
$1_SRCS := $$(foreach d, $$($1_SRC), $$(filter $$d%, $$($1_SRCS_RAW)))
$1_SRCS := $$(filter $$(NATIVE_SOURCE_EXTENSIONS), $$($1_SRCS))
# Extract the C/C++ files.
ifneq ($$($1_EXCLUDE_PATTERNS), )
# We must not match the exclude pattern against the src root(s).
$1_SRCS_WITHOUT_ROOTS := $$(foreach i, $$($1_SRC), \
$$(patsubst $$i/%,%, $$(filter $$i/%, $$($1_SRCS))))
$1_ALL_EXCLUDE_FILES := $$(call containing, $$($1_EXCLUDE_PATTERNS), \
$$($1_SRCS_WITHOUT_ROOTS))
endif
ifneq ($$($1_EXCLUDE_FILES), )
$1_ALL_EXCLUDE_FILES += $$($1_EXCLUDE_FILES)
endif
ifneq ($$($1_ALL_EXCLUDE_FILES), )
$1_EXCLUDE_FILES_PAT := $$($1_ALL_EXCLUDE_FILES) \
$$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$($1_ALL_EXCLUDE_FILES)))
$1_EXCLUDE_FILES_PAT := $$(addprefix %, $$($1_EXCLUDE_FILES_PAT))
$1_SRCS := $$(filter-out $$($1_EXCLUDE_FILES_PAT), $$($1_SRCS))
endif
ifneq ($$($1_INCLUDE_FILES), )
$1_INCLUDE_FILES_PAT := $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$($1_INCLUDE_FILES)))
$1_SRCS := $$(filter $$($1_INCLUDE_FILES_PAT), $$($1_SRCS))
endif
# Now we have a list of all c/c++ files to compile: $$($1_SRCS)
# Prepend the source/bin path to the filter expressions. Then do the filtering.
ifneq ($$($1_INCLUDES), )
$1_SRC_INCLUDES := $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$(addsuffix /%, $$($1_INCLUDES))))
$1_SRCS := $$(filter $$($1_SRC_INCLUDES), $$($1_SRCS))
endif
ifneq ($$($1_EXCLUDES), )
$1_SRC_EXCLUDES := $$(addsuffix /%, $$($1_EXCLUDES))
$1_SRC_EXCLUDES += $$(foreach i, $$($1_SRC), $$(addprefix $$i/, $$(addsuffix /%, $$($1_EXCLUDES))))
$1_SRCS := $$(filter-out $$($1_SRC_EXCLUDES), $$($1_SRCS))
endif
$1_SRCS += $$($1_EXTRA_FILES)
ifeq ($$($1_SRCS), )
$$(error No sources found for $1 when looking inside the dirs $$($1_SRC))
endif
ifeq ($$($1_TYPE), EXECUTABLE)
ifeq ($(UBSAN_ENABLED), true)
# We need to set the default options for UBSan. This needs to be included in every executable.
# Rather than copy and paste code to everything with a main function, we add an additional
# source file to every executable that exports __ubsan_default_options.
ifneq ($$(filter %.cpp %.cc, $$($1_SRCS)), )
$1_SRCS += $(TOPDIR)/make/data/ubsan/ubsan_default_options.cpp
else
$1_SRCS += $(TOPDIR)/make/data/ubsan/ubsan_default_options.c
endif
endif
endif
endef
################################################################################
define SetupOutputFiles
# Calculate the expected output from compiling the sources
$1_EXPECTED_OBJS_FILENAMES := $$(call replace_with_obj_extension, $$(notdir $$($1_SRCS)))
$1_EXPECTED_OBJS := $$(addprefix $$($1_OBJECT_DIR)/, $$($1_EXPECTED_OBJS_FILENAMES))
# Sort to remove duplicates and provide a reproducible order on the input files to the linker.
$1_ALL_OBJS := $$(sort $$($1_EXPECTED_OBJS) $$($1_EXTRA_OBJECT_FILES))
ifeq ($(STATIC_LIBS), true)
# Exclude the object files that match with $1_STATIC_LIB_EXCLUDE_OBJS.
ifneq ($$($1_STATIC_LIB_EXCLUDE_OBJS), )
$1_ALL_OBJS := $$(call not-containing, $$($1_STATIC_LIB_EXCLUDE_OBJS), $$($1_ALL_OBJS))
endif
endif
endef
################################################################################
define RemoveSuperfluousOutputFiles
# Are there too many object files on disk? Perhaps because some source file was removed?
$1_BINS := $$(wildcard $$($1_OBJECT_DIR)/*$(OBJ_SUFFIX))
$1_SUPERFLOUS_OBJS := $$(sort $$(filter-out $$($1_EXPECTED_OBJS), $$($1_BINS)))
# Clean out the superfluous object files.
ifneq ($$($1_SUPERFLUOUS_OBJS), )
$$(shell $(RM) -f $$($1_SUPERFLUOUS_OBJS))
endif
endef
################################################################################
define SetupObjectFileList
$1_LD_OBJ_ARG := $$($1_ALL_OBJS)
# If there are many object files, use an @-file...
ifneq ($$(word 17, $$($1_ALL_OBJS)), )
$1_OBJ_FILE_LIST := $$($1_OBJECT_DIR)/_$1_objectfilenames.txt
$1_LD_OBJ_ARG := @$$($1_OBJ_FILE_LIST)
# If we are building static library, 'AR' on macosx/aix may not support @-file.
ifeq ($$($1_TYPE), STATIC_LIBRARY)
ifeq ($(call isTargetOs, macosx aix), true)
$1_LD_OBJ_ARG := `cat $$($1_OBJ_FILE_LIST)`
endif
endif
endif
# Unfortunately the @-file trick does not work reliably when using clang.
# Clang does not propagate the @-file parameter to the ld sub process, but
# instead puts the full content on the command line. At least the llvm ld
# does not even support an @-file.
#
# When linking a large amount of object files, we risk hitting the limit
# of the command line length even on posix systems if the path length of
# the output dir is very long due to our use of absolute paths. To
# mitigate this, use paths relative to the output dir when linking over
# 500 files with clang and the output dir path is deep.
ifneq ($$(word 500, $$($1_ALL_OBJS)), )
ifeq ($$(TOOLCHAIN_TYPE), clang)
# There is no strlen function in make, but checking path depth is a
# reasonable approximation.
ifneq ($$(word 10, $$(subst /, ,$$(OUTPUTDIR))), )
$1_LINK_OBJS_RELATIVE := true
$1_ALL_OBJS_RELATIVE := $$(patsubst $$(OUTPUTDIR)/%, %, $$($1_ALL_OBJS))
endif
endif
endif
endef
################################################################################
endif # include guard
include MakeIncludeEnd.gmk

View file

@ -0,0 +1 @@
))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))

View file

@ -0,0 +1 @@
$(subst share/classes,X01,$(subst internal,X02,$(subst com/sun/org,X03,$(subst java,X04,$(subst javax,X05,$(subst sun/io,X06,$(subst com/sun,X07,$(subst java/io,X08,$(subst org/omg,X09,$(subst org/w3c,X10,$(subst org/xml,X11,$(subst sun/awt,X12,$(subst sun/net,X13,$(subst sun/nio,X14,$(subst sun/rmi,X15,$(subst java/awt,X16,$(subst java/net,X17,$(subst java/nio,X18,$(subst java/rmi,X19,$(subst META-INF,X20,$(subst sun/font,X21,$(subst sun/misc,X22,$(subst sun/text,X23,$(subst sun/util,X24,$(subst java/lang,X25,$(subst java/math,X26,$(subst java/text,X27,$(subst java/util,X28,$(subst javax/jws,X29,$(subst javax/net,X30,$(subst javax/rmi,X31,$(subst javax/xml,X32,$(subst sun/corba,X33,$(subst sun/print,X34,$(subst sun/swing,X35,$(subst java/beans,X36,$(subst javax/lang,X37,$(subst sun/applet,X38,$(subst sun/java2d,X39,$(subst java/applet,X40,$(subst javax/print,X41,$(subst javax/sound,X42,$(subst javax/swing,X43,$(subst javax/tools,X44,$(subst jdk/classes,X45,$(subst org/relaxng,X46,$(subst sun/reflect,X47,$(subst javax/crypto,X48,$(subst javax/naming,X49,$(subst jaxp/classes,X50,$(subst sun/security,X51,$(subst corba/classes,X52,$(subst java/security,X53,$(subst javax/imageio,X54,$(subst jdk/btclasses,X55,$(subst javax/activity,X56,$(subst javax/security,X57,$(subst jdk/newclasses,X58,$(subst sun/instrument,X59,$(subst sun/management,X60,$(subst corba/btclasses,X61,$(subst jdk/democlasses,X62,$(subst javax/activation,X63,$(subst javax/annotation,X64,$(subst javax/management,X65,$(subst javax/transaction,X66,$(subst jaxws/jaf_classes,X67,$(subst langtools/classes,X68,$(subst META-INF/services,X69,$(subst jdk/newdemoclasses,X70,$(subst javax/accessibility,X71,$(subst jaxws/jaxws_classes,X72,

View file

@ -0,0 +1,72 @@
s|X01|share/classes|g
s|X02|internal|g
s|X03|com/sun/org|g
s|X04|java|g
s|X05|javax|g
s|X06|sun/io|g
s|X07|com/sun|g
s|X08|java/io|g
s|X09|org/omg|g
s|X10|org/w3c|g
s|X11|org/xml|g
s|X12|sun/awt|g
s|X13|sun/net|g
s|X14|sun/nio|g
s|X15|sun/rmi|g
s|X16|java/awt|g
s|X17|java/net|g
s|X18|java/nio|g
s|X19|java/rmi|g
s|X20|META-INF|g
s|X21|sun/font|g
s|X22|sun/misc|g
s|X23|sun/text|g
s|X24|sun/util|g
s|X25|java/lang|g
s|X26|java/math|g
s|X27|java/text|g
s|X28|java/util|g
s|X29|javax/jws|g
s|X30|javax/net|g
s|X31|javax/rmi|g
s|X32|javax/xml|g
s|X33|sun/corba|g
s|X34|sun/print|g
s|X35|sun/swing|g
s|X36|java/beans|g
s|X37|javax/lang|g
s|X38|sun/applet|g
s|X39|sun/java2d|g
s|X40|java/applet|g
s|X41|javax/print|g
s|X42|javax/sound|g
s|X43|javax/swing|g
s|X44|javax/tools|g
s|X45|jdk/classes|g
s|X46|org/relaxng|g
s|X47|sun/reflect|g
s|X48|javax/crypto|g
s|X49|javax/naming|g
s|X50|jaxp/classes|g
s|X51|sun/security|g
s|X52|corba/classes|g
s|X53|java/security|g
s|X54|javax/imageio|g
s|X55|jdk/btclasses|g
s|X56|javax/activity|g
s|X57|javax/security|g
s|X58|jdk/newclasses|g
s|X59|sun/instrument|g
s|X60|sun/management|g
s|X61|corba/btclasses|g
s|X62|jdk/democlasses|g
s|X63|javax/activation|g
s|X64|javax/annotation|g
s|X65|javax/management|g
s|X66|javax/transaction|g
s|X67|jaxws/jaf_classes|g
s|X68|langtools/classes|g
s|X69|META-INF/services|g
s|X70|jdk/newdemoclasses|g
s|X71|javax/accessibility|g
s|X72|jaxws/jaxws_classes|g