blob: aadfaa9954fb832e668feebe0b332dd6ecc3e5ec [file] [log] [blame]
# Copyright (c) 2014 The Native Client Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from __future__ import print_function
from conditions import *
"""Nodes for scons to gn
Nodes class provides a means to store, explore and write out a tree
describing the table generated by interating over the scons file. The
tree is created in the form of:
TopNode
Condition
Object
Condition
Property
"""
REMAP = {
'arm' : 'arm',
'AND' : 'android',
'CHR' : 'chrome',
'LIN' : 'linux',
'MAC' : 'mac',
'IOS' : 'ios',
'WIN' : 'win',
'x86' : 'x86',
'x64' : 'x64',
'glibc' : 'glibc',
'newlib' : 'newlib',
'pnacl' : 'pnacl'
}
def Express(use, avail, tag):
use = sorted([REMAP[x] for x in use])
avail = sorted([REMAP[x] for x in avail])
if use == avail:
return None
if len(use) == 1:
return '(%s == "%s")' % (tag, use[0])
luse = len(use)
lavail = len(avail)
if luse > (lavail - luse):
items = ['%s != "%s"' % (tag, i) for i in avail if i not in use]
return '(' + ' || '.join(items) + ')'
items = ['%s == "%s"' % (tag, i) for i in use]
return '(' + ' || '.join(items) + ')'
def Condition(os_use, os_avail, cpu_use, cpu_avail):
# We can not hash a list, so we sometimes use a space sperated string.
if isinstance(cpu_use, str):
cpu_use = cpu_use.split(' ')
if isinstance(cpu_avail, str):
cpu_avail = cpu_avail.split(' ')
o_cond = Express(os_use, os_avail, 'os')
c_cond = Express(cpu_use, cpu_avail, 'cpu_arch')
if not o_cond and not c_cond:
return None
if o_cond and c_cond:
return 'if (%s && %s) {' % (o_cond, c_cond)
if o_cond:
return 'if %s {' % o_cond
return 'if %s {' % c_cond
#
# TopNode
# Condition
# Object
# Condition
# Property
#
class Node(object):
def __init__(self, name=''):
self.children = []
self.name = name
self.parent = None
def DumpInfo(self, depth=0):
print('%s%s(%s)' % (' ' * depth, str(type(self)), self.name))
for child in self.children:
child.DumpInfo(depth+1)
def Write(self, fileobj, depth, text):
for line in text.split('\n'):
string = ' ' * depth + line + '\n'
fileobj.write(string)
def Dump(self, fileobj, depth):
adjust = self.DumpStart(fileobj, depth)
for idx, child in enumerate(self.children):
self.DumpChild(fileobj, child, adjust)
if idx != len(self.children) - 1:
fileobj.write('\n')
self.DumpEnd(fileobj, depth)
def DumpStart(self, fileobj, depth):
self.Write(fileobj, depth, self.name)
return depth
def DumpEnd(self, fileobj, depth):
pass
def DumpChild(self, fileobj, child, depth):
child.Dump(fileobj, depth)
def AddChild(self, child):
self.children.append(child)
child.parent = self
def Examine(self, obj):
obj.Enter(self)
for child in self.children:
child.Examine(obj)
obj.Exit(self)
class TopNode(Node):
def __init__(self, name):
Node.__init__(self, name)
def DumpStart(self, fileobj, depth):
self.Write(fileobj, depth, "# Autogenerated from %s.\n\n" % self.name)
return depth
class ConditionNode(Node):
def __init__(self, os_use, os_avail, cpu_use, cpu_avail):
name = Condition(os_use, os_avail, cpu_use, cpu_avail)
Node.__init__(self, name)
def Dump(self, fileobj, depth):
if self.name:
self.Write(fileobj, depth, self.name)
depth += 1
for child in self.children:
child.Dump(fileobj, depth)
if self.name:
self.Write(fileobj, depth - 1, '}')
class ObjectNode(Node):
def __init__(self, name, obj_type):
Node.__init__(self, name)
self.obj_type = obj_type
self.conditional = set()
self.unconditional = set()
def DumpStart(self, fileobj, depth):
self.Write(fileobj, depth, '%s("%s") {' % (self.obj_type, self.name))
depth += 1
# For every conditional only property, set and empty array
for cond in self.conditional:
if cond not in self.unconditional:
self.Write(fileobj, depth, '%s = []' % cond)
return depth
def DumpEnd(self, fileobj, depth):
self.Write(fileobj, depth, '}')
class PropertyNode(Node):
def __init__(self, name):
Node.__init__(self, name)
def Dump(self, fileobj, depth):
if self.parent.name:
self.Write(fileobj, depth, '%s += [' % self.name)
else:
self.Write(fileobj, depth, '%s = [' % self.name)
for child in self.children:
child.Dump(fileobj, depth + 1)
self.Write(fileobj, depth, ']')
class ValueNode(Node):
def __init__(self, name):
Node.__init__(self, name)
def Dump(self, fileobj, depth):
self.Write(fileobj, depth, '"%s",' % self.name)
class OrganizeProperties(object):
def __init__(self):
self.cond = None
self.obj = None
pass
def Enter(self, node):
if isinstance(node, ObjectNode):
self.obj = node
if isinstance(node, ConditionNode):
self.cond = node.name
if isinstance(node, PropertyNode):
if self.cond == None:
self.obj.unconditional |= set([node.name])
else:
self.obj.conditional |= set([node.name])
node.children = sorted(node.children, key=lambda x: x.name)
def Exit(self, node):
pass