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