aboutsummaryrefslogtreecommitdiffhomepage
path: root/platform_tools/android/gyp_gen/vars_dict_lib.py
blob: 6be2402a04828015610ab56e86edaa501fed3d07 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/usr/bin/python

# Copyright 2014 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import collections
import types

# The goal of this class is to store a set of unique items in the order in
# which they are inserted. This is important for the final makefile, where
# we want to make sure the image decoders are in a particular order. See
# images.gyp for more information.
class OrderedSet(object):
  """Ordered set of unique items that supports addition and removal.

  Retains the order in which items are inserted.
  """

  def __init__(self):
    self.__ordered_set = []

  def add(self, item):
    """Add item, if it is not already in the set.

    item is appended to the end if it is not already in the set.

    Args:
      item: The item to add.
    """
    if item not in self.__ordered_set:
      self.__ordered_set.append(item)

  def __contains__(self, item):
    """Whether the set contains item.

    Args:
      item: The item to search for in the set.

    Returns:
      bool: Whether the item is in the set.
    """
    return item in self.__ordered_set

  def __iter__(self):
    """Iterator for the set.
    """
    return self.__ordered_set.__iter__()

  def remove(self, item):
    """
    Remove item from the set.

    Args:
      item: Item to be removed.

    Raises:
      ValueError if item is not in the set.
    """
    self.__ordered_set.remove(item)

  def __len__(self):
    """Number of items in the set.
    """
    return len(self.__ordered_set)

  def __getitem__(self, index):
    """Return item at index.
    """
    return self.__ordered_set[index]

  def reset(self):
    """Reset to empty.
    """
    self.__ordered_set = []

  def set(self, other):
    """Replace this ordered set with another.

    Args:
      other: OrderedSet to replace this one. After this call, this OrderedSet
        will contain exactly the same elements as other.
    """
    self.__ordered_set = list(other.__ordered_set)

VAR_NAMES = ['LOCAL_CFLAGS',
             'LOCAL_CPPFLAGS',
             'LOCAL_SRC_FILES',
             'LOCAL_SHARED_LIBRARIES',
             'LOCAL_STATIC_LIBRARIES',
             'LOCAL_C_INCLUDES',
             'LOCAL_EXPORT_C_INCLUDE_DIRS',
             'DEFINES',
             'KNOWN_TARGETS',
             # These are not parsed by gyp, but set manually.
             'LOCAL_MODULE_TAGS',
             'LOCAL_MODULE']

class VarsDict(collections.namedtuple('VarsDict', VAR_NAMES)):
  """Custom class for storing the arguments to Android.mk variables.

  Can also be treated as a dictionary with fixed keys.
  """

  __slots__ = ()

  def __new__(cls):
    lists = []
    # TODO (scroggo): Is there a better way add N items?
    for __unused__ in range(len(VAR_NAMES)):
      lists.append(OrderedSet())
    return tuple.__new__(cls, lists)

  def keys(self):
    """Return the field names as strings.
    """
    return self._fields

  def __getitem__(self, index):
    """Return an item, indexed by a number or a string.
    """
    if type(index) == types.IntType:
      # Treat the index as an array index into a tuple.
      return tuple.__getitem__(self, index)
    if type(index) == types.StringType:
      # Treat the index as a key into a dictionary.
      return eval('self.%s' % index)
    return None


def intersect(var_dict_list):
  """Compute intersection of VarsDicts.

  Find the intersection of a list of VarsDicts and trim each input to its
  unique entries.

  Args:
    var_dict_list: list of VarsDicts. WARNING: each VarsDict will be
      modified in place, to remove the common elements!
  Returns:
    VarsDict containing list entries common to all VarsDicts in
      var_dict_list
  """
  intersection = VarsDict()
  # First VarsDict
  var_dict_a = var_dict_list[0]
  # The rest.
  other_var_dicts = var_dict_list[1:]

  for key in var_dict_a.keys():
    # Copy A's list, so we can continue iterating after modifying the original.
    a_list = list(var_dict_a[key])
    for item in a_list:
      # If item is in all lists, add to intersection, and remove from all.
      in_all_lists = True
      for var_dict in other_var_dicts:
        if not item in var_dict[key]:
          in_all_lists = False
          break
      if in_all_lists:
        intersection[key].add(item)
        for var_dict in var_dict_list:
          var_dict[key].remove(item)
  return intersection