diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index 68d1dba27ff..b2bbfff1f7f 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. +# 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 @@ -23,9 +23,11 @@ # questions. # -# When you read this source. Remember that $(sort ...) has the side effect -# of removing duplicates. It is actually this side effect that is -# desired whenever sort is used below! +################################################################################ +# This is the top-level entry point for our native compilation and linking. +# It contains the SetupNativeCompilation function, but is supported by helper +# functions in the make/common/native directory. +################################################################################ ifndef _NATIVE_COMPILATION_GMK _NATIVE_COMPILATION_GMK := 1 @@ -34,463 +36,14 @@ ifeq ($(_MAKEBASE_GMK), ) $(error You must include MakeBase.gmk prior to including NativeCompilation.gmk) endif -################################################################################ -# Create exported symbols file for static libraries -################################################################################ - -# get the exported symbols from mapfiles and if there -# is no mapfile, get them from the archive -define GetSymbols - $(RM) $$(@D)/$$(basename $$(@F)).symbols; \ - if [ ! -z $$($1_MAPFILE) -a -e $$($1_MAPFILE) ]; then \ - $(ECHO) "Getting symbols from mapfile $$($1_MAPFILE)"; \ - $(AWK) '/global:/','/local:/' $$($1_MAPFILE) | \ - $(SED) -e 's/#.*//;s/global://;s/local://;s/\;//;s/^[ ]*/_/;/^_$$$$/d' | \ - $(EGREP) -v "JNI_OnLoad|JNI_OnUnload|Agent_OnLoad|Agent_OnUnload|Agent_OnAttach" > \ - $$(@D)/$$(basename $$(@F)).symbols || true; \ - $(NM) $(NMFLAGS) $$($1_TARGET) | $(GREP) " T " | \ - $(EGREP) "JNI_OnLoad|JNI_OnUnload|Agent_OnLoad|Agent_OnUnload|Agent_OnAttach" | \ - $(CUT) -d ' ' -f 3 >> $$(@D)/$$(basename $$(@F)).symbols || true;\ - else \ - $(ECHO) "Getting symbols from nm"; \ - $(NM) $(NMFLAGS) -m $$($1_TARGET) | $(GREP) "__TEXT" | \ - $(EGREP) -v "non-external|private extern|__TEXT,__eh_frame" | \ - $(SED) -e 's/.* //' > $$(@D)/$$(basename $$(@F)).symbols; \ - fi -endef +include native/CompileFile.gmk +include native/DebugSymbols.gmk +include native/Flags.gmk +include native/Link.gmk +include native/Paths.gmk +include native/ToolchainDefinitions.gmk ################################################################################ -# 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 - -################################################################################ -# Define a native toolchain configuration that can be used by -# SetupNativeCompilation calls -# -# Parameter 1 is the name of the toolchain definition -# -# Remaining parameters are named arguments: -# EXTENDS - Optional parent definition to get defaults from -# CC - The C compiler -# CXX - The C++ compiler -# LD - The Linker -# AR - Static linker -# AS - Assembler -# MT - Windows MT tool -# RC - Windows RC tool -# OBJCOPY - The objcopy tool for debug symbol handling -# STRIP - The tool to use for stripping debug symbols -# SYSROOT_CFLAGS - Compiler flags for using the specific sysroot -# SYSROOT_LDFLAGS - Linker flags for using the specific sysroot -DefineNativeToolchain = $(NamedParamsMacroTemplate) -define DefineNativeToolchainBody - # If extending another definition, get default values from that, - # otherwise, nothing more needs to be done as variable assignments - # already happened in NamedParamsMacroTemplate. - ifneq ($$($1_EXTENDS), ) - $$(call SetIfEmpty, $1_CC, $$($$($1_EXTENDS)_CC)) - $$(call SetIfEmpty, $1_CXX, $$($$($1_EXTENDS)_CXX)) - $$(call SetIfEmpty, $1_LD, $$($$($1_EXTENDS)_LD)) - $$(call SetIfEmpty, $1_AR, $$($$($1_EXTENDS)_AR)) - $$(call SetIfEmpty, $1_AS, $$($$($1_EXTENDS)_AS)) - $$(call SetIfEmpty, $1_MT, $$($$($1_EXTENDS)_MT)) - $$(call SetIfEmpty, $1_RC, $$($$($1_EXTENDS)_RC)) - $$(call SetIfEmpty, $1_OBJCOPY, $$($$($1_EXTENDS)_OBJCOPY)) - $$(call SetIfEmpty, $1_STRIP, $$($$($1_EXTENDS)_STRIP)) - $$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $$($$($1_EXTENDS)_SYSROOT_CFLAGS)) - $$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $$($$($1_EXTENDS)_SYSROOT_LDFLAGS)) - endif -endef - -# Create a default toolchain with the main compiler and linker -$(eval $(call DefineNativeToolchain, TOOLCHAIN_DEFAULT, \ - CC := $(CC), \ - CXX := $(CXX), \ - LD := $(LD), \ - AR := $(AR), \ - AS := $(AS), \ - MT := $(MT), \ - RC := $(RC), \ - OBJCOPY := $(OBJCOPY), \ - STRIP := $(STRIP), \ - SYSROOT_CFLAGS := $(SYSROOT_CFLAGS), \ - SYSROOT_LDFLAGS := $(SYSROOT_LDFLAGS), \ -)) - -# Create a toolchain where linking is done with the C++ linker -$(eval $(call DefineNativeToolchain, TOOLCHAIN_LINK_CXX, \ - EXTENDS := TOOLCHAIN_DEFAULT, \ - LD := $(LDCXX), \ -)) - -# Create a toolchain with the BUILD compiler, used for build tools that -# are to be run during the build. -$(eval $(call DefineNativeToolchain, TOOLCHAIN_BUILD, \ - CC := $(BUILD_CC), \ - CXX := $(BUILD_CXX), \ - LD := $(BUILD_LD), \ - AR := $(BUILD_AR), \ - AS := $(BUILD_AS), \ - OBJCOPY := $(BUILD_OBJCOPY), \ - STRIP := $(BUILD_STRIP), \ - SYSROOT_CFLAGS := $(BUILD_SYSROOT_CFLAGS), \ - SYSROOT_LDFLAGS := $(BUILD_SYSROOT_LDFLAGS), \ -)) - -# BUILD toolchain with the C++ linker -$(eval $(call DefineNativeToolchain, TOOLCHAIN_BUILD_LINK_CXX, \ - EXTENDS := TOOLCHAIN_BUILD, \ - LD := $(BUILD_LDCXX), \ -)) - -################################################################################ - -# 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/$$$$/ :/' \ - # - -################################################################################ -# 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) && ' -# 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 - -################################################################################ -# GetEntitlementsFile -# Find entitlements file for executable when signing on macosx. If no -# specialized file is found, returns the default file. -# $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)) \ - ) - -################################################################################ -# 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) -# -SetupCompileNativeFile = $(NamedParamsMacroTemplate) -define SetupCompileNativeFileBody - $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) - - ifeq ($$($1_OPTIMIZATION), ) - $1_OPT_CFLAGS := $$($$($1_BASE)_OPT_CFLAGS) - $1_OPT_CXXFLAGS := $$($$($1_BASE)_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 ($$($$($1_BASE)_PRECOMPILED_HEADER), ) - ifeq ($$(filter $$($1_FILENAME), $$($$($1_BASE)_PRECOMPILED_HEADER_EXCLUDE)), ) - $1_USE_PCH_FLAGS := $$($$($1_BASE)_USE_PCH_FLAGS) - endif - endif - - ifneq ($(DISABLE_WARNING_PREFIX), ) - $1_WARNINGS_FLAGS := $$(addprefix $(DISABLE_WARNING_PREFIX), \ - $$($$($1_BASE)_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$$($1_FILENAME)) \ - $$($$($1_BASE)_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)_$$($1_FILENAME))) - endif - - $1_BASE_CFLAGS := $$($$($1_BASE)_CFLAGS) $$($$($1_BASE)_EXTRA_CFLAGS) \ - $$($$($1_BASE)_SYSROOT_CFLAGS) - $1_BASE_CXXFLAGS := $$($$($1_BASE)_CXXFLAGS) $$($$($1_BASE)_EXTRA_CXXFLAGS) \ - $$($$($1_BASE)_SYSROOT_CFLAGS) $$($1_EXTRA_CXXFLAGS) - $1_BASE_ASFLAGS := $$($$($1_BASE)_ASFLAGS) $$($$($1_BASE)_EXTRA_ASFLAGS) - - 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) -Ta $$($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 - # Setup make rules for creating a native binary (a shared library or an # executable). # @@ -573,9 +126,82 @@ endef # 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 + # Setup variables for the rest of the function to work with + $$(eval $$(call SetupBasicVariables1,$1)) + $$(eval $$(call SetupDebugSymbols,$1)) + $$(eval $$(call SetupBasicVariables2,$1)) + $$(eval $$(call VerifyArguments,$1)) + $$(eval $$(call SetupBasicVariables3,$1)) + # Need to make sure TARGET is first on list + $1 := $$($1_TARGET) + + # Setup the toolchain to be used + $$(eval $$(call SetupToolchain,$1)) + + # Figure out all source files to compile + $$(eval $$(call LocateSourceFiles,$1)) + + # ... and what the output object files will be + $$(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)) + + # Create a PCH, if requested + $$(eval $$(call CreatePrecompiledHeader,$1)) + + # Now call SetupCompileNativeFile for each source file we are going to compile. + $$(foreach file, $$($1_SRCS), \ + $$(eval $$(call SetupCompileNativeFile,$1_$$(notdir $$(file)),\ + FILE := $$(file), \ + BASE := $1, \ + )) \ + ) + + # Have make print information about the library when we start compiling + $$(eval $$(call PrintInfo,$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)) + + # Prepare for linking + $$(eval $$(call SetupLinkerFlags,$1)) + + $$(eval $$(call SetupMapfile,$1)) + + # Handle native debug symbols + $$(eval $$(call CreateDebugSymbols,$1)) + + $$(eval $$(call SetupStrip,$1)) + + $$(eval $$(call SetupObjectFileList,$1)) + + # Link the individually compiled files into a single unit + $$(eval $$(call CreateLinkedResult,$1)) + + ifeq ($(GENERATE_COMPILE_COMMANDS_ONLY), true) + # Override all targets (this is a hack) + $1 := $$($1_ALL_OBJS_JSON) + endif +endef + +################################################################################ +# Setup basic variables, part 1 +define SetupBasicVariables1 # If type is unspecified, default to LIBRARY ifeq ($$($1_TYPE), ) $1_TYPE := LIBRARY @@ -588,9 +214,11 @@ define SetupNativeCompilationBody $1_TYPE := STATIC_LIBRARY endif endif +endef - $$(call SetIfEmpty, $1_COMPILE_WITH_DEBUG_SYMBOLS, $$(COMPILE_WITH_DEBUG_SYMBOLS)) - +################################################################################ +# Setup basic variables, part 2 +define SetupBasicVariables2 # STATIC_LIBS is set from Main.gmk when building static versions of certain # native libraries. ifeq ($(STATIC_LIBS), true) @@ -600,15 +228,6 @@ define SetupNativeCompilationBody # jmods. $1_OBJECT_DIR := $$($1_OBJECT_DIR)/static $1_OUTPUT_DIR := $$($1_OBJECT_DIR) - # 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_TYPE), EXECUTABLE) @@ -628,7 +247,11 @@ define SetupNativeCompilationBody endif endif endif +endef +################################################################################ +# Verify that user passed arguments are valid +define VerifyArguments ifneq ($$($1_NAME), $(basename $$($1_NAME))) $$(error NAME must not contain any directory path in $1) endif @@ -646,229 +269,20 @@ define SetupNativeCompilationBody $$(error If MANIFEST is provided, then MANIFEST_VERSION is required in $1) endif endif +endef +################################################################################ +# Setup basic variables, part 3 +define SetupBasicVariables3 $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)) +endef -# Need to make sure TARGET is first on list - $1 := $$($1_TARGET) - - # Setup the toolchain to be used - $$(call SetIfEmpty, $1_TOOLCHAIN, TOOLCHAIN_DEFAULT) - $$(call SetIfEmpty, $1_CC, $$($$($1_TOOLCHAIN)_CC)) - $$(call SetIfEmpty, $1_CXX, $$($$($1_TOOLCHAIN)_CXX)) - $$(call SetIfEmpty, $1_LD, $$($$($1_TOOLCHAIN)_LD)) - $$(call SetIfEmpty, $1_AR, $$($$($1_TOOLCHAIN)_AR)) - $$(call SetIfEmpty, $1_AS, $$($$($1_TOOLCHAIN)_AS)) - $$(call SetIfEmpty, $1_MT, $$($$($1_TOOLCHAIN)_MT)) - $$(call SetIfEmpty, $1_RC, $$($$($1_TOOLCHAIN)_RC)) - $$(call SetIfEmpty, $1_OBJCOPY, $$($$($1_TOOLCHAIN)_OBJCOPY)) - $$(call SetIfEmpty, $1_STRIP, $$($$($1_TOOLCHAIN)_STRIP)) - $$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $$($$($1_TOOLCHAIN)_SYSROOT_CFLAGS)) - $$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $$($$($1_TOOLCHAIN)_SYSROOT_LDFLAGS)) - - $$(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 := $$($1_SRCS) - $$(foreach i, $$($1_SRC), $$(eval $1_SRCS_WITHOUT_ROOTS := $$(patsubst \ - $$i/%,%, $$($1_SRCS_WITHOUT_ROOTS)))) - $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 - # There can be only a single bin dir root, no need to foreach over the roots. - $1_BINS := $$(wildcard $$($1_OBJECT_DIR)/*$(OBJ_SUFFIX)) - # Now we have a list of all c/c++ files to compile: $$($1_SRCS) - # and we have a list of all existing object files: $$($1_BINS) - - # 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 - - # 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)) - # Are there too many object files on disk? Perhaps because some source file was removed? - $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 - # 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 - - # 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 += $$(STATIC_LIBS_CFLAGS) - 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 - - 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 (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 - +################################################################################ +# Setup machinery needed by the build system +define SetupBuildSystemSupport $1_BUILD_INFO := $$($1_OBJECT_DIR)/_build-info.marker # Track variable changes for all variables that affect the compilation command @@ -879,81 +293,11 @@ define SetupNativeCompilationBody $$($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 - 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 SetupCompileNativeFile, $1_$$(notdir $$($1_GENERATED_PCH_SRC)), \ - FILE := $$($1_GENERATED_PCH_SRC), \ - BASE := $1, \ - EXTRA_CXXFLAGS := -Fp$$($1_PCH_FILE) -Yc$$(notdir $$($1_PRECOMPILED_HEADER)), \ - )) - - $1_USE_PCH_FLAGS := \ - -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 - 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 - - # Now call SetupCompileNativeFile for each source file we are going to compile. - $$(foreach file, $$($1_SRCS), \ - $$(eval $$(call SetupCompileNativeFile, $1_$$(notdir $$(file)),\ - FILE := $$(file), \ - BASE := $1, \ - )) \ - ) - +################################################################################ +# Have make print information about the library when we start compiling +define PrintInfo # 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 @@ -973,47 +317,12 @@ define SetupNativeCompilationBody $$(if $$(filter %.vardeps, $$?), due to makefile changes)))) endif $(TOUCH) $$@ +endef - # On windows we need to create a resource file - ifeq ($(call isTargetOs, windows), true) - 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) $(CC_OUT_OPTION)$$@ \ - $$($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 \ - $(CC_OUT_OPTION)$$($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 - endif - +################################################################################ +# 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 @@ -1031,7 +340,11 @@ define SetupNativeCompilationBody $(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 @@ -1041,328 +354,6 @@ define SetupNativeCompilationBody $1_DEPS_FILE_LOADED := true -include $$($1_DEPS_FILE).old endif - - ifneq ($(DISABLE_MAPFILES), true) - $1_REAL_MAPFILE := $$($1_MAPFILE) - endif - - # 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 - $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)) - - ifneq ($$($1_REAL_MAPFILE), ) - $1_EXTRA_LDFLAGS += $(call SET_SHARED_LIBRARY_MAPFILE,$$($1_REAL_MAPFILE)) - endif - - 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 - - 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) - # Generate debuginfo files. - 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 - $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_BASENAME).pdb \ - $$($1_SYMBOLS_DIR)/$$($1_BASENAME).map - - else ifeq ($(call isTargetOs, linux), true) - $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).debuginfo - # Setup the command line creating debuginfo files, to be run after linking. - # It cannot be run separately since it updates the original target file - # Creating the debuglink is done in another command rather than all at once - # so we can run it after strip is called, since strip can sometimes mangle the - # embedded debuglink, which we want to avoid. - $1_CREATE_DEBUGINFO_CMDS := \ - $$($1_OBJCOPY) --only-keep-debug $$($1_TARGET) $$($1_DEBUGINFO_FILES) $$(NEWLINE) - $1_CREATE_DEBUGLINK_CMDS := $(CD) $$($1_SYMBOLS_DIR) && \ - $$($1_OBJCOPY) --add-gnu-debuglink=$$($1_DEBUGINFO_FILES) $$($1_TARGET) - - else ifeq ($(call isTargetOs, aix), true) - # AIX does not provide the equivalent of OBJCOPY to extract debug symbols, - # so we copy the compiled object with symbols to the .debuginfo file, which - # happens prior to the STRIP_CMD on the original target object file. - $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).debuginfo - $1_CREATE_DEBUGINFO_CMDS := $(CP) $$($1_TARGET) $$($1_DEBUGINFO_FILES) - - 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_CREATE_DEBUGINFO_CMDS := \ - $(DSYMUTIL) --out $$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM $$($1_TARGET) - 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) - ifeq ($(call isTargetOs, windows), true) - $1_DEBUGINFO_ZIP := $$($1_SYMBOLS_DIR)/$$($1_BASENAME).diz - else - $1_DEBUGINFO_ZIP := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).diz - endif - $1 += $$($1_DEBUGINFO_ZIP) - - # 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)) - - endif - endif # !STATIC_LIBRARY - endif # $1_DEBUG_SYMBOLS != false - endif # COPY_DEBUG_SYMBOLS - - # Unless specifically set, stripping should only happen if symbols are also - # being copied. - $$(call SetIfEmpty, $1_STRIP_SYMBOLS, $$($1_COPY_DEBUG_SYMBOLS)) - - ifneq ($$($1_STRIP_SYMBOLS), false) - ifneq ($$($1_STRIP), ) - # Default to using the global STRIPFLAGS. Allow for overriding with an empty value - $1_STRIPFLAGS ?= $(STRIPFLAGS) - $1_STRIP_CMD := $$($1_STRIP) $$($1_STRIPFLAGS) $$($1_TARGET) - endif - endif - - $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 - ifneq ($(COMPILER_COMMAND_FILE_FLAG), ) - $1_LD_OBJ_ARG := $(COMPILER_COMMAND_FILE_FLAG)$$($1_OBJ_FILE_LIST) - else - # ...except for toolchains which don't support them. - $1_LD_OBJ_ARG := `cat $$($1_OBJ_FILE_LIST)` - endif - - # 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 - - ifeq ($$($1_TYPE), STATIC_LIBRARY) - # 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_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) - - # Generating a static library, ie object file archive. - ifeq ($(STATIC_BUILD), true) - ifeq ($$($1_USE_MAPFILE_FOR_SYMBOLS), true) - STATIC_MAPFILE_DEP := $$($1_MAPFILE) - endif - endif - - $1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_RES) $$($1_VARDEPS_FILE) $$(STATIC_MAPFILE_DEP) - - $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) \ - $(LD_OUT_OPTION)$$($1_TARGET_RELOCATABLE) \ - $$($1_LD_OBJ_ARG)) - endif - $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \ - $(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \ - $$($1_AR) $$(ARFLAGS) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_AR_OBJ_ARG) \ - $$($1_RES)) - ifeq ($(STATIC_BUILD), true) - ifeq ($$($1_USE_MAPFILE_FOR_SYMBOLS), true) - $(CP) $$($1_MAPFILE) $$(@D)/$$(basename $$(@F)).symbols - else - $(GetSymbols) - endif - endif - else - # A shared dynamic library or an executable binary has been specified - ifeq ($$($1_TYPE), LIBRARY) - # Generating a dynamic library. - $1_EXTRA_LDFLAGS += $$(call SET_SHARED_LIBRARY_NAME,$$($1_BASENAME)) - - # Create loadmap on AIX. Helps in diagnosing some problems. - ifneq ($(COMPILER_BINDCMD_FILE_FLAG), ) - $1_EXTRA_LDFLAGS += $(COMPILER_BINDCMD_FILE_FLAG)$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).loadmap - endif - endif - - ifeq ($(call isTargetOs, windows), true) - 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 - endif - - $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \ - $$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_MT) \ - $$($1_CREATE_DEBUGINFO_CMDS) $$($1_MANIFEST_VERSION) \ - $$($1_STRIP_CMD) $$($1_CREATE_DEBUGLINK_CMDS) - $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \ - $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps) - - $1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_RES) $$($1_MANIFEST) \ - $$($1_REAL_MAPFILE) $$($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 - # Keep as much as possible on one execution line for best performance - # on Windows - $$(call LogInfo, Linking $$($1_BASENAME)) - $$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR)) - ifeq ($(call isTargetOs, windows), true) - - $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \ - $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ - $(LD_OUT_OPTION)$$($1_TARGET) $$($1_LD_OBJ_ARG) $$($1_RES) \ - $$($1_LIBS) $$($1_EXTRA_LIBS)) \ - | $(GREP) -v "^ Creating library .*\.lib and object .*\.exp" || \ - test "$$$$?" = "1" ; \ - $$($1_CREATE_DEBUGINFO_CMDS) - $$($1_STRIP_CMD) - $$($1_CREATE_DEBUGLINK_CMDS) - ifeq ($(call isBuildOsEnv, windows.wsl2), true) - $$(CHMOD) +x $$($1_TARGET) - endif - else - $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \ - $$(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \ - $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ - $(LD_OUT_OPTION)$$($1_TARGET) $$($1_LD_OBJ_ARG) $$($1_RES) \ - $$($1_LIBS) $$($1_EXTRA_LIBS)) ; \ - $$($1_CREATE_DEBUGINFO_CMDS) - $$($1_STRIP_CMD) - $$($1_CREATE_DEBUGLINK_CMDS) - endif - ifeq ($(call isTargetOs, windows), true) - ifneq ($$($1_MANIFEST), ) - $$($1_MT) -nologo -manifest $$($1_MANIFEST) -identity:"$$($1_NAME).exe, version=$$($1_MANIFEST_VERSION)" -outputresource:$$@;#1 - endif - endif - # On macosx, optionally run codesign on every binary. - # Remove signature explicitly first to avoid warnings if the linker - # added a default adhoc signature. - ifeq ($(MACOSX_CODESIGN_MODE), hardened) - $(CODESIGN) --remove-signature $$@ - $(CODESIGN) -f -s "$(MACOSX_CODESIGN_IDENTITY)" --timestamp --options runtime \ - --entitlements $$(call GetEntitlementsFile, $$@) $$@ - else ifeq ($(MACOSX_CODESIGN_MODE), debug) - $(CODESIGN) --remove-signature $$@ - $(CODESIGN) -f -s - --entitlements $$(call GetEntitlementsFile, $$@) $$@ - endif - endif - - ifeq ($(GENERATE_COMPILE_COMMANDS_ONLY), true) - $1 := $$($1_ALL_OBJS_JSON) - endif endef endif # _NATIVE_COMPILATION_GMK diff --git a/make/common/native/CompileFile.gmk b/make/common/native/CompileFile.gmk new file mode 100644 index 00000000000..c4377468472 --- /dev/null +++ b/make/common/native/CompileFile.gmk @@ -0,0 +1,351 @@ +# +# 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 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/$$$$/ :/' \ + # + +################################################################################ +# 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) +# +SetupCompileNativeFile = $(NamedParamsMacroTemplate) +define SetupCompileNativeFileBody + $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)) + + 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) -Ta $$($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 SetupCompileNativeFile, $1_$$(notdir $$($1_GENERATED_PCH_SRC)), \ + FILE := $$($1_GENERATED_PCH_SRC), \ + BASE := $1, \ + EXTRA_CXXFLAGS := -Fp$$($1_PCH_FILE) -Yc$$(notdir $$($1_PRECOMPILED_HEADER)), \ + )) + + $1_USE_PCH_FLAGS := \ + -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 + 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) $(CC_OUT_OPTION)$$@ \ + $$($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 \ + $(CC_OUT_OPTION)$$($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 diff --git a/make/common/native/DebugSymbols.gmk b/make/common/native/DebugSymbols.gmk new file mode 100644 index 00000000000..ba9db08a1ce --- /dev/null +++ b/make/common/native/DebugSymbols.gmk @@ -0,0 +1,134 @@ +# +# 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 file contains functionality related to native debug symbol handling. + +################################################################################ +define SetupDebugSymbols + $$(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 +endef + +################################################################################ +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 + + 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) + # Generate debuginfo files. + 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 + $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_BASENAME).pdb \ + $$($1_SYMBOLS_DIR)/$$($1_BASENAME).map + + else ifeq ($(call isTargetOs, linux), true) + $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).debuginfo + # Setup the command line creating debuginfo files, to be run after linking. + # It cannot be run separately since it updates the original target file + # Creating the debuglink is done in another command rather than all at once + # so we can run it after strip is called, since strip can sometimes mangle the + # embedded debuglink, which we want to avoid. + $1_CREATE_DEBUGINFO_CMDS := \ + $$($1_OBJCOPY) --only-keep-debug $$($1_TARGET) $$($1_DEBUGINFO_FILES) $$(NEWLINE) + $1_CREATE_DEBUGLINK_CMDS := $(CD) $$($1_SYMBOLS_DIR) && \ + $$($1_OBJCOPY) --add-gnu-debuglink=$$($1_DEBUGINFO_FILES) $$($1_TARGET) + + else ifeq ($(call isTargetOs, aix), true) + # AIX does not provide the equivalent of OBJCOPY to extract debug symbols, + # so we copy the compiled object with symbols to the .debuginfo file, which + # happens prior to the STRIP_CMD on the original target object file. + $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).debuginfo + $1_CREATE_DEBUGINFO_CMDS := $(CP) $$($1_TARGET) $$($1_DEBUGINFO_FILES) + + 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_CREATE_DEBUGINFO_CMDS := \ + $(DSYMUTIL) --out $$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM $$($1_TARGET) + 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) + ifeq ($(call isTargetOs, windows), true) + $1_DEBUGINFO_ZIP := $$($1_SYMBOLS_DIR)/$$($1_BASENAME).diz + else + $1_DEBUGINFO_ZIP := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).diz + endif + $1 += $$($1_DEBUGINFO_ZIP) + + # 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)) + + endif + endif # !STATIC_LIBRARY + endif # $1_DEBUG_SYMBOLS != false + endif # COPY_DEBUG_SYMBOLS +endef diff --git a/make/common/native/Flags.gmk b/make/common/native/Flags.gmk new file mode 100644 index 00000000000..ed0adba33ba --- /dev/null +++ b/make/common/native/Flags.gmk @@ -0,0 +1,209 @@ +# +# 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 file contains functionality related to setting up compiler and linker +# flags, based on various more abstract sources of compilation description, +# like optimization level. + +################################################################################ +define SetupCompileFileFlags + ifeq ($$($1_OPTIMIZATION), ) + $1_OPT_CFLAGS := $$($$($1_BASE)_OPT_CFLAGS) + $1_OPT_CXXFLAGS := $$($$($1_BASE)_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 ($$($$($1_BASE)_PRECOMPILED_HEADER), ) + ifeq ($$(filter $$($1_FILENAME), $$($$($1_BASE)_PRECOMPILED_HEADER_EXCLUDE)), ) + $1_USE_PCH_FLAGS := $$($$($1_BASE)_USE_PCH_FLAGS) + endif + endif + + ifneq ($(DISABLE_WARNING_PREFIX), ) + $1_WARNINGS_FLAGS := $$(addprefix $(DISABLE_WARNING_PREFIX), \ + $$($$($1_BASE)_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$$($1_FILENAME)) \ + $$($$($1_BASE)_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)_$(OPENJDK_TARGET_OS)_$$($1_FILENAME))) + endif + + $1_BASE_CFLAGS := $$($$($1_BASE)_CFLAGS) $$($$($1_BASE)_EXTRA_CFLAGS) \ + $$($$($1_BASE)_SYSROOT_CFLAGS) + $1_BASE_CXXFLAGS := $$($$($1_BASE)_CXXFLAGS) $$($$($1_BASE)_EXTRA_CXXFLAGS) \ + $$($$($1_BASE)_SYSROOT_CFLAGS) $$($1_EXTRA_CXXFLAGS) + $1_BASE_ASFLAGS := $$($$($1_BASE)_ASFLAGS) $$($$($1_BASE)_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 += $$(STATIC_LIBS_CFLAGS) + 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 + + 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 (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 + $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 diff --git a/make/common/native/Link.gmk b/make/common/native/Link.gmk new file mode 100644 index 00000000000..ea528c0d9aa --- /dev/null +++ b/make/common/native/Link.gmk @@ -0,0 +1,262 @@ +# +# 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 file contains functionality related to linking a native binary; +# creating either a dynamic library, a static library or an executable. + +################################################################################ +# Create exported symbols file for static libraries +################################################################################ + +# get the exported symbols from mapfiles and if there +# is no mapfile, get them from the archive +define GetSymbols + $(RM) $$(@D)/$$(basename $$(@F)).symbols; \ + if [ ! -z $$($1_MAPFILE) -a -e $$($1_MAPFILE) ]; then \ + $(ECHO) "Getting symbols from mapfile $$($1_MAPFILE)"; \ + $(AWK) '/global:/','/local:/' $$($1_MAPFILE) | \ + $(SED) -e 's/#.*//;s/global://;s/local://;s/\;//;s/^[ ]*/_/;/^_$$$$/d' | \ + $(EGREP) -v "JNI_OnLoad|JNI_OnUnload|Agent_OnLoad|Agent_OnUnload|Agent_OnAttach" > \ + $$(@D)/$$(basename $$(@F)).symbols || true; \ + $(NM) $(NMFLAGS) $$($1_TARGET) | $(GREP) " T " | \ + $(EGREP) "JNI_OnLoad|JNI_OnUnload|Agent_OnLoad|Agent_OnUnload|Agent_OnAttach" | \ + $(CUT) -d ' ' -f 3 >> $$(@D)/$$(basename $$(@F)).symbols || true;\ + else \ + $(ECHO) "Getting symbols from nm"; \ + $(NM) $(NMFLAGS) -m $$($1_TARGET) | $(GREP) "__TEXT" | \ + $(EGREP) -v "non-external|private extern|__TEXT,__eh_frame" | \ + $(SED) -e 's/.* //' > $$(@D)/$$(basename $$(@F)).symbols; \ + fi +endef + +################################################################################ +# GetEntitlementsFile +# Find entitlements file for executable when signing on macosx. If no +# specialized file is found, returns the default file. +# $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)) \ + ) + +################################################################################ +define SetupMapfile + ifneq ($(DISABLE_MAPFILES), true) + $1_REAL_MAPFILE := $$($1_MAPFILE) + endif + + ifneq ($$($1_REAL_MAPFILE), ) + $1_EXTRA_LDFLAGS += $(call SET_SHARED_LIBRARY_MAPFILE,$$($1_REAL_MAPFILE)) + endif +endef + +################################################################################ +define SetupStrip + # Unless specifically set, stripping should only happen if symbols are also + # being copied. + $$(call SetIfEmpty, $1_STRIP_SYMBOLS, $$($1_COPY_DEBUG_SYMBOLS)) + + ifneq ($$($1_STRIP_SYMBOLS), false) + ifneq ($$($1_STRIP), ) + # Default to using the global STRIPFLAGS. Allow for overriding with an empty value + $1_STRIPFLAGS ?= $(STRIPFLAGS) + $1_STRIP_CMD := $$($1_STRIP) $$($1_STRIPFLAGS) $$($1_TARGET) + endif + endif +endef + +################################################################################ +define CreateLinkedResult + ifeq ($$($1_TYPE), STATIC_LIBRARY) + # 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_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) + + # Generating a static library, ie object file archive. + ifeq ($(STATIC_BUILD), true) + ifeq ($$($1_USE_MAPFILE_FOR_SYMBOLS), true) + STATIC_MAPFILE_DEP := $$($1_MAPFILE) + endif + endif + + $1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_RES) $$($1_VARDEPS_FILE) $$(STATIC_MAPFILE_DEP) + + $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) \ + $(LD_OUT_OPTION)$$($1_TARGET_RELOCATABLE) \ + $$($1_LD_OBJ_ARG)) + endif + $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \ + $(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \ + $$($1_AR) $$(ARFLAGS) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_AR_OBJ_ARG) \ + $$($1_RES)) + ifeq ($(STATIC_BUILD), true) + ifeq ($$($1_USE_MAPFILE_FOR_SYMBOLS), true) + $(CP) $$($1_MAPFILE) $$(@D)/$$(basename $$(@F)).symbols + else + $(GetSymbols) + endif + endif + else + # A shared dynamic library or an executable binary has been specified + ifeq ($$($1_TYPE), LIBRARY) + # Generating a dynamic library. + $1_EXTRA_LDFLAGS += $$(call SET_SHARED_LIBRARY_NAME,$$($1_BASENAME)) + + # Create loadmap on AIX. Helps in diagnosing some problems. + ifneq ($(COMPILER_BINDCMD_FILE_FLAG), ) + $1_EXTRA_LDFLAGS += $(COMPILER_BINDCMD_FILE_FLAG)$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).loadmap + endif + endif + + ifeq ($(call isTargetOs, windows), true) + 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 + endif + + $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \ + $$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_MT) \ + $$($1_CREATE_DEBUGINFO_CMDS) $$($1_MANIFEST_VERSION) \ + $$($1_STRIP_CMD) $$($1_CREATE_DEBUGLINK_CMDS) + $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \ + $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps) + + $1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_RES) $$($1_MANIFEST) \ + $$($1_REAL_MAPFILE) $$($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 + # Keep as much as possible on one execution line for best performance + # on Windows + $$(call LogInfo, Linking $$($1_BASENAME)) + $$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR)) + ifeq ($(call isTargetOs, windows), true) + + $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \ + $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ + $(LD_OUT_OPTION)$$($1_TARGET) $$($1_LD_OBJ_ARG) $$($1_RES) \ + $$($1_LIBS) $$($1_EXTRA_LIBS)) \ + | $(GREP) -v "^ Creating library .*\.lib and object .*\.exp" || \ + test "$$$$?" = "1" ; \ + $$($1_CREATE_DEBUGINFO_CMDS) + $$($1_STRIP_CMD) + $$($1_CREATE_DEBUGLINK_CMDS) + ifeq ($(call isBuildOsEnv, windows.wsl2), true) + $$(CHMOD) +x $$($1_TARGET) + endif + else + $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \ + $$(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \ + $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ + $(LD_OUT_OPTION)$$($1_TARGET) $$($1_LD_OBJ_ARG) $$($1_RES) \ + $$($1_LIBS) $$($1_EXTRA_LIBS)) ; \ + $$($1_CREATE_DEBUGINFO_CMDS) + $$($1_STRIP_CMD) + $$($1_CREATE_DEBUGLINK_CMDS) + endif + ifeq ($(call isTargetOs, windows), true) + ifneq ($$($1_MANIFEST), ) + $$($1_MT) -nologo -manifest $$($1_MANIFEST) -identity:"$$($1_NAME).exe, version=$$($1_MANIFEST_VERSION)" -outputresource:$$@;#1 + endif + endif + # On macosx, optionally run codesign on every binary. + # Remove signature explicitly first to avoid warnings if the linker + # added a default adhoc signature. + ifeq ($(MACOSX_CODESIGN_MODE), hardened) + $(CODESIGN) --remove-signature $$@ + $(CODESIGN) -f -s "$(MACOSX_CODESIGN_IDENTITY)" --timestamp --options runtime \ + --entitlements $$(call GetEntitlementsFile, $$@) $$@ + else ifeq ($(MACOSX_CODESIGN_MODE), debug) + $(CODESIGN) --remove-signature $$@ + $(CODESIGN) -f -s - --entitlements $$(call GetEntitlementsFile, $$@) $$@ + endif + endif +endef diff --git a/make/common/native/Paths.gmk b/make/common/native/Paths.gmk new file mode 100644 index 00000000000..8d7c426eb35 --- /dev/null +++ b/make/common/native/Paths.gmk @@ -0,0 +1,245 @@ +# +# 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 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) && ' +# 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 LocateSourceFiles + $$(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 := $$($1_SRCS) + $$(foreach i, $$($1_SRC), $$(eval $1_SRCS_WITHOUT_ROOTS := $$(patsubst \ + $$i/%,%, $$($1_SRCS_WITHOUT_ROOTS)))) + $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 + # There can be only a single bin dir root, no need to foreach over the roots. + $1_BINS := $$(wildcard $$($1_OBJECT_DIR)/*$(OBJ_SUFFIX)) + # Now we have a list of all c/c++ files to compile: $$($1_SRCS) + # and we have a list of all existing object files: $$($1_BINS) + + # 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)) + # Are there too many object files on disk? Perhaps because some source file was removed? + $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 + # 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 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 + ifneq ($(COMPILER_COMMAND_FILE_FLAG), ) + $1_LD_OBJ_ARG := $(COMPILER_COMMAND_FILE_FLAG)$$($1_OBJ_FILE_LIST) + else + # ...except for toolchains which don't support them. + $1_LD_OBJ_ARG := `cat $$($1_OBJ_FILE_LIST)` + endif + + # 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 diff --git a/make/common/native/ToolchainDefinitions.gmk b/make/common/native/ToolchainDefinitions.gmk new file mode 100644 index 00000000000..b640df83d6a --- /dev/null +++ b/make/common/native/ToolchainDefinitions.gmk @@ -0,0 +1,125 @@ +# +# 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 file contains functionality related to setting up our toolchain +# definition variables. + +################################################################################ +# Define a native toolchain configuration that can be used by +# SetupNativeCompilation calls +# +# Parameter 1 is the name of the toolchain definition +# +# Remaining parameters are named arguments: +# EXTENDS - Optional parent definition to get defaults from +# CC - The C compiler +# CXX - The C++ compiler +# LD - The Linker +# AR - Static linker +# AS - Assembler +# MT - Windows MT tool +# RC - Windows RC tool +# OBJCOPY - The objcopy tool for debug symbol handling +# STRIP - The tool to use for stripping debug symbols +# SYSROOT_CFLAGS - Compiler flags for using the specific sysroot +# SYSROOT_LDFLAGS - Linker flags for using the specific sysroot +DefineNativeToolchain = $(NamedParamsMacroTemplate) +define DefineNativeToolchainBody + # If extending another definition, get default values from that, + # otherwise, nothing more needs to be done as variable assignments + # already happened in NamedParamsMacroTemplate. + ifneq ($$($1_EXTENDS), ) + $$(call SetIfEmpty, $1_CC, $$($$($1_EXTENDS)_CC)) + $$(call SetIfEmpty, $1_CXX, $$($$($1_EXTENDS)_CXX)) + $$(call SetIfEmpty, $1_LD, $$($$($1_EXTENDS)_LD)) + $$(call SetIfEmpty, $1_AR, $$($$($1_EXTENDS)_AR)) + $$(call SetIfEmpty, $1_AS, $$($$($1_EXTENDS)_AS)) + $$(call SetIfEmpty, $1_MT, $$($$($1_EXTENDS)_MT)) + $$(call SetIfEmpty, $1_RC, $$($$($1_EXTENDS)_RC)) + $$(call SetIfEmpty, $1_OBJCOPY, $$($$($1_EXTENDS)_OBJCOPY)) + $$(call SetIfEmpty, $1_STRIP, $$($$($1_EXTENDS)_STRIP)) + $$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $$($$($1_EXTENDS)_SYSROOT_CFLAGS)) + $$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $$($$($1_EXTENDS)_SYSROOT_LDFLAGS)) + endif +endef + +# Create a default toolchain with the main compiler and linker +$(eval $(call DefineNativeToolchain, TOOLCHAIN_DEFAULT, \ + CC := $(CC), \ + CXX := $(CXX), \ + LD := $(LD), \ + AR := $(AR), \ + AS := $(AS), \ + MT := $(MT), \ + RC := $(RC), \ + OBJCOPY := $(OBJCOPY), \ + STRIP := $(STRIP), \ + SYSROOT_CFLAGS := $(SYSROOT_CFLAGS), \ + SYSROOT_LDFLAGS := $(SYSROOT_LDFLAGS), \ +)) + +# Create a toolchain where linking is done with the C++ linker +$(eval $(call DefineNativeToolchain, TOOLCHAIN_LINK_CXX, \ + EXTENDS := TOOLCHAIN_DEFAULT, \ + LD := $(LDCXX), \ +)) + +# Create a toolchain with the BUILD compiler, used for build tools that +# are to be run during the build. +$(eval $(call DefineNativeToolchain, TOOLCHAIN_BUILD, \ + CC := $(BUILD_CC), \ + CXX := $(BUILD_CXX), \ + LD := $(BUILD_LD), \ + AR := $(BUILD_AR), \ + AS := $(BUILD_AS), \ + OBJCOPY := $(BUILD_OBJCOPY), \ + STRIP := $(BUILD_STRIP), \ + SYSROOT_CFLAGS := $(BUILD_SYSROOT_CFLAGS), \ + SYSROOT_LDFLAGS := $(BUILD_SYSROOT_LDFLAGS), \ +)) + +# BUILD toolchain with the C++ linker +$(eval $(call DefineNativeToolchain, TOOLCHAIN_BUILD_LINK_CXX, \ + EXTENDS := TOOLCHAIN_BUILD, \ + LD := $(BUILD_LDCXX), \ +)) + +################################################################################ +# Setup the toolchain to be used +define SetupToolchain + $$(call SetIfEmpty, $1_TOOLCHAIN, TOOLCHAIN_DEFAULT) + $$(call SetIfEmpty, $1_CC, $$($$($1_TOOLCHAIN)_CC)) + $$(call SetIfEmpty, $1_CXX, $$($$($1_TOOLCHAIN)_CXX)) + $$(call SetIfEmpty, $1_LD, $$($$($1_TOOLCHAIN)_LD)) + $$(call SetIfEmpty, $1_AR, $$($$($1_TOOLCHAIN)_AR)) + $$(call SetIfEmpty, $1_AS, $$($$($1_TOOLCHAIN)_AS)) + $$(call SetIfEmpty, $1_MT, $$($$($1_TOOLCHAIN)_MT)) + $$(call SetIfEmpty, $1_RC, $$($$($1_TOOLCHAIN)_RC)) + $$(call SetIfEmpty, $1_OBJCOPY, $$($$($1_TOOLCHAIN)_OBJCOPY)) + $$(call SetIfEmpty, $1_STRIP, $$($$($1_TOOLCHAIN)_STRIP)) + $$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $$($$($1_TOOLCHAIN)_SYSROOT_CFLAGS)) + $$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $$($$($1_TOOLCHAIN)_SYSROOT_LDFLAGS)) +endef