jdk-24/make/common/NativeCompilation.gmk
2024-09-03 15:31:19 +00:00

413 lines
17 KiB
Plaintext

#
# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
################################################################################
# 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.
################################################################################
ifndef _NATIVE_COMPILATION_GMK
_NATIVE_COMPILATION_GMK := 1
ifeq ($(_MAKEBASE_GMK), )
$(error You must include MakeBase.gmk prior to including NativeCompilation.gmk)
endif
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
# 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)
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 # _NATIVE_COMPILATION_GMK