view make/common/FileSet.gmk @ 2397:7ad550ee1d67

Fixed make 3.81 incompatibilities
author erikj
date Mon, 04 Jan 2016 13:53:22 +0100
parents 7fe1b08c46b1
children d462c0b4bb7a
line wrap: on
line source
#
# Copyright (c) 2015, 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.
#

ifndef _FILE_SET_GMK
_FILE_SET_GMK := 1

ifeq (,$(_MAKEBASE_GMK))
  $(error You must include MakeBase.gmk prior to including NativeCompilation.gmk)
endif

################################################################################
# A FileSet is a set of files that can be used by various other macros as
# the input for build operations. It can be defined in various different
# ways.
#
# Parameter 1 names the FileSet. This name is used as variable prefix.
#
# Remaining parameters are named arguments:
#
# SRC_SETS: Include all files in the named file sets in this file set.
#
# SRC_BASE_DIR: Each file in the set has an associated base dir. For explicit
#     SRC_FILES it defaults the directory of the file. For files found using
#     SRC_DIRS, it is the src dir it was found beneath. By setting this
#     parameter, all files in the set get one common base dir. What the base dir
#     means depends on the context of how the file set is used. All files in the
#     set must be children of the base dir.
#
# SRC_FILES: List of exact files to include in the set, regardless of
#     include/exclude. May be given as absolute paths or relative to SRC_BASE_DIR.
#
# SRC_DIRS: List of directory roots to search for files in using include/exclude
#
# INCLUDE_PATTERNS: Only include files matching any of these patterns.
# EXCLUDE_PATTERNS: Do not include files matching any of these patterns.
# INCLUDE_CONTAINING: Only include files containing any of these substrings.
# EXCLUDE_CONTAINING: Do not include files containing any of these substrings.
#
# Patterns may contain one % as wildcard. A pattern starting with / is assumed
# to be an absolute path, otherwise it will be anchored and matched at each
# directory in SRC_DIRS.
#
# If combining multiple INCLUDE_* arguments, you get the sum of the includes.
#
# ACCEPT_EMPTY: Set to true to not make it an error if the fileset evaluates to
#    empty. Defaults to false.
#
# Returns:
# $1_FILES contains a list of all files in the set
# $1_BASE_DIRS contains a list of all base dirs in the set
# $1_$(BASE_DIR)_FILES contains a list of all files for a given base dir,
#     relative to that base dir.
# $1_ALL_INCLUDED Set to true if no filtering was done, meaning all files in
#    each dir in SRC_DIRS is included, SRC_BASE_DIR isn't used and no extra
#    files are added.
#
SetupFileSet = $(NamedParamsMacroTemplate)
define SetupFileSetBody
  $1_FILES :=
  $1_BASE_DIRS :=

  ifneq ($$($1_SRC_BASE_DIR), )
    # Remove any trailing /
    $1_SRC_BASE_DIR := $$(patsubst %/, %, $$($1_SRC_BASE_DIR))
    $1_BASE_DIRS := $$($1_SRC_BASE_DIR)
    $1_$$($1_SRC_BASE_DIR)_FILES :=
  endif

  # Nested evals actually need 4 dollars for correct evaluation of their
  # contents, but a loop variable from foreach must be evaluated with just
  # 2 (the same as the foreach itself). To not lose any dollars in the loop
  # variable, compensate using DoubleDollar when accessing them.

  ifneq ($$($1_SRC_FILES), )

    ifneq ($$($1_SRC_BASE_DIR), )
      # For each source file, convert to (a)bsolute and (r)elative path
      # and add them to the results lists
      $$(foreach f, $$($1_SRC_FILES), \
        $$(eval fd := $$(call DoubleDollar, $$(f))) \
        $$(if $$(filter /%, $$(f)), \
          $$(if $$(filter-out $$($1_SRC_BASE_DIR)/%, $$(f)), \
            $$(error $1 $$(f) does not have $$($1_SRC_BASE_DIR) as parent)) \
          $$(eval r := $$$$(patsubst $$$$($1_SRC_BASE_DIR)/%, %, $$$$(fd))) \
          $$(eval a := $$$$(fd)) \
        , \
          $$(eval r := $$$$(fd)) \
          $$(eval a := $$$$($1_SRC_BASE_DIR)/$$$$(fd)) \
        ) \
        $$(eval $1_FILES += $$$$(a)) \
        $$(eval $1_$$($1_SRC_BASE_DIR)_FILES += $$$$(r)) \
      )

    else
      $1_FILES += $$($1_SRC_FILES)
      $$(foreach f, $$($1_SRC_FILES), \
        $$(eval d := $$$$(strip $$$$(patsubst %/, %, \
            $$$$(dir $$(call DoubleDollar, $$(f)))))) \
        $$(eval $1_$$$$(d)_FILES += $$$$(notdir $$(call DoubleDollar, $$(f)))) \
        $$(eval $1_BASE_DIRS += $$$$(d)) \
      )
      $1_BASE_DIRS := $$(call uniq, $$($1_BASE_DIRS))
    endif

  endif

  ifneq ($$($1_SRC_DIRS), )
    # Remove any trailing /
    $1_SRC_DIRS := $$(patsubst %/, %, $$($1_SRC_DIRS))
    # Fail if one is a subdir of another
    $$(foreach d, $$($1_SRC_DIRS), \
        $$(if $$(filter $$(addsuffix /%, $$(d)), $$($1_SRC_DIRS)), \
          $$(error $1 $$(filter $$(addsuffix /%, $$(d)), $$($1_SRC_DIRS)) is a subdir of $$(d))))
    # Remove duplicates
    $1_SRC_DIRS := $$(call uniq, $$($1_SRC_DIRS))

    # Verify existence of src dirs. GNU Make 3.81 sometimes fails to wildcard directories
    # without a trailing slash.
    $1_SRC_DIRS_SLASH := $$(addsuffix /, $$($1_SRC_DIRS))
    ifneq ($$(strip $$($1_SRC_DIRS_SLASH)), $$(strip $$(wildcard $$($1_SRC_DIRS_SLASH))))
      $$(error $1 SRC_DIRS $$(filter-out $$(wildcard $$($1_SRC_DIRS)), $$($1_SRC_DIRS)) \
          does not exist)
    endif

    $1_FILTERED_FILES :=
    $1_ALL_RELATIVE_FILES :=
    $$(foreach d, $$($1_SRC_DIRS), \
        $$(eval f := $$$$(call FindFiles, $$(d))) \
        $$(eval $1_FILTERED_FILES += $$$$(f)) \
        $$(eval $1_ALL_RELATIVE_FILES += $$$$(patsubst $$(d)/%, %, $$$$(f))))

    ifneq ($$($1_INCLUDE_PATTERNS), )
      # Patterns starting with / are considered absolute paths
      $1_INCLUDE_PATTERNS_ABS := $$(filter /%, $$($1_INCLUDE_PATTERNS))
      # Patterns starting with %
      $1_INCLUDE_PATTERNS_WILDCARD := $$(filter \%%, $$($1_INCLUDE_PATTERNS))
      # The rest need to be anchored at each dir
      $1_INCLUDE_PATTERNS_ANCHORED := $$(filter-out $$($1_INCLUDE_PATTERNS_ABS) \
          $$(addprefix \, $$($1_INCLUDE_PATTERNS_WILDCARD)), $$($1_INCLUDE_PATTERNS))
      $1_ALL_INCLUDE_PATTERNS := $$($1_INCLUDE_PATTERNS_ABS) \
          $$($1_INCLUDE_PATTERNS_WILDCARD) \
          $$(foreach d, $$($1_SRC_DIRS), $$(addprefix $$(d)/, $$($1_INCLUDE_PATTERNS_ANCHORED)))
    endif
    ifneq ($$($1_EXCLUDE_PATTERNS), )
      # Patterns starting with / are considered absolute paths
      $1_EXCLUDE_PATTERNS_ABS := $$(filter /%, $$($1_EXCLUDE_PATTERNS))
      # Patterns starting with %
      $1_EXCLUDE_PATTERNS_WILDCARD := $$(filter \%%, $$($1_EXCLUDE_PATTERNS))
      # The rest need to be anchored at each dir
      $1_EXCLUDE_PATTERNS_ANCHORED := $$(filter-out $$($1_EXCLUDE_PATTERNS_ABS) \
          $$(addprefix \, $$($1_EXCLUDE_PATTERNS_WILDCARD)), $$($1_EXCLUDE_PATTERNS))
      $1_ALL_EXCLUDE_PATTERNS := $$($1_EXCLUDE_PATTERNS_ABS) \
          $$($1_EXCLUDE_PATTERNS_WILDCARD) \
          $$(foreach d, $$($1_SRC_DIRS), $$(addprefix $$(d)/, $$($1_EXCLUDE_PATTERNS_ANCHORED)))
    endif

    ifneq ($$($1_INCLUDE_CONTAINING), )
      $1_INCLUDE_CONTAINING_PATTERNS := $$(addprefix %, $$(call containing, \
          $$($1_INCLUDE_CONTAINING), $$($1_ALL_RELATIVE_FILES)))
      $1_ALL_INCLUDE_PATTERNS += $$($1_INCLUDE_CONTAINING_PATTERNS)
      ifeq ($$($1_INCLUDE_CONTAINING_PATTERNS), )
        # If no files contain the pattern, then we have 0 filtered files
        $1_FILTERED_FILES :=
      endif
    endif
    ifneq ($$($1_EXCLUDE_CONTAINING), )
      $1_ALL_EXCLUDE_PATTERNS += $$(addprefix %, $$(call containing, \
          $$($1_EXCLUDE_CONTAINING), $$($1_ALL_RELATIVE_FILES)))
    endif

    ifneq ($$($1_ALL_INCLUDE_PATTERNS), )
      $1_FILTERED_FILES := $$(filter $$($1_ALL_INCLUDE_PATTERNS), $$($1_FILTERED_FILES))
    endif
    ifneq ($$($1_ALL_EXCLUDE_PATTERNS), )
      $1_FILTERED_FILES := $$(filter-out $$($1_ALL_EXCLUDE_PATTERNS), $$($1_FILTERED_FILES))
    endif
    $1_FILES += $$($1_FILTERED_FILES)

    ifneq ($$($1_SRC_BASE_DIR), )
      $1_$$($1_SRC_BASE_DIR)_FILES += $$(patsubst $$($1_SRC_BASE_DIR)/%, %, $$($1_FILTERED_FILES))
    else
      $$(foreach d, $$($1_SRC_DIRS), \
        $$(eval $1_$$(d)_FILES += $$$$(patsubst $$(d)/%, %, $$$$(filter $$(d)/%, $$$$($1_FILTERED_FILES)))))
      $1_BASE_DIRS += $$($1_SRC_DIRS)
    endif
  endif

  ifneq ($$($1_SRC_SETS), )
    $$(foreach s, $$($1_SRC_SETS), \
      $$(eval $1_FILES += $$$$($$(s)_FILES)) \
      $$(eval $1_BASE_DIRS += $$$$($$(s)_BASE_DIRS)) \
      $$(foreach d, $$($$(s)_BASE_DIRS), \
        $$(eval $1_$$(d)_FILES += $$$$($$(s)_$$(d)_FILES)) \
      ) \
    )
    # Nested FileSets may add duplicate base dirs (with different filters).
    $1_BASE_DIRS := $$(call uniq, $$($1_BASE_DIRS))
  endif

  ifneq ($$($1_ACCEPT_EMPTY), true)
    ifeq ($$($1_FILES), )
      $$(error $1 FileSet is empty)
    endif
  endif

  # To be absolutely sure nothing has been excluded, no patterns must have been uesd,
  # no extra source files added and the base dir cannot have been redefined.
  ifeq ($$($1_ALL_EXCLUDE_PATTERNS)$$($1_ALL_INCLUDE_PATTERNS)$$($1_SRC_FILES)$$($1_SRC_BASE_DIR), )
    $1_ALL_INCLUDED := true
  endif
endef

# The InlineFileSet is called without eval and returns the name of the file set.
# This makes it possible to instantiate a file set inline in another macro call:
#
# $(eval $(call SetupFileSet, FILE_SET_A, \
#     SRC_SETS := \
#         $(call InlineFileSet, FILE_SET_B, \
#             SRC_FILES := foo bar, \
#         ), \
#         $(call InlineFileSet, FILE_SET_C, \
#             SRC_DIRS := fobaz, \
#         ), \
# ))
InlineFileSet = $(strip $(eval $$(eval $$(call SetupFileSet, $1 \
    $(patsubst %, $(COMMA)$(DOLLAR)(%), $(PARAM_SEQUENCE))))) $1)

endif # _FILE_SET_GMK