blob: 1cbf4d3c8f0d9b6509b4eca51c3638f36d650112 [file] [log] [blame]
# Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Tool module for adding, to a construction environment, Chromium-specific
wrappers around SCons builders. This gives us a central place for any
customization we need to make to the different things we build.
"""
import sys
from SCons.Script import *
import SCons.Node
import SCons.Util
class Null(object):
def __new__(cls, *args, **kwargs):
if '_inst' not in vars(cls):
cls._inst = super(type, cls).__new__(cls, *args, **kwargs)
return cls._inst
def __init__(self, *args, **kwargs): pass
def __call__(self, *args, **kwargs): return self
def __repr__(self): return "Null()"
def __nonzero__(self): return False
def __getattr__(self, name): return self
def __setattr__(self, name, val): return self
def __delattr__(self, name): return self
def __getitem__(self, name): return self
class FileList(object):
def __init__(self, entries=None):
if isinstance(entries, FileList):
entries = entries.entries
self.entries = entries or []
def __getitem__(self, i):
return self.entries[i]
def __setitem__(self, i, item):
self.entries[i] = item
def __delitem__(self, i):
del self.entries[i]
def __add__(self, other):
if isinstance(other, FileList):
return self.__class__(self.entries + other.entries)
elif isinstance(other, type(self.entries)):
return self.__class__(self.entries + other)
else:
return self.__class__(self.entries + list(other))
def __radd__(self, other):
if isinstance(other, FileList):
return self.__class__(other.entries + self.entries)
elif isinstance(other, type(self.entries)):
return self.__class__(other + self.entries)
else:
return self.__class__(list(other) + self.entries)
def __iadd__(self, other):
if isinstance(other, FileList):
self.entries += other.entries
elif isinstance(other, type(self.entries)):
self.entries += other
else:
self.entries += list(other)
return self
def append(self, item):
return self.entries.append(item)
def extend(self, item):
return self.entries.extend(item)
def index(self, item, *args):
return self.entries.index(item, *args)
def remove(self, item):
return self.entries.remove(item)
def FileListWalk(top, topdown=True, onerror=None):
"""
"""
try:
entries = top.entries
except AttributeError, err:
if onerror is not None:
onerror(err)
return
dirs, nondirs = [], []
for entry in entries:
if hasattr(entry, 'entries'):
dirs.append(entry)
else:
nondirs.append(entry)
if topdown:
yield top, dirs, nondirs
for entry in dirs:
for x in FileListWalk(entry, topdown, onerror):
yield x
if not topdown:
yield top, dirs, nondirs
class ChromeFileList(FileList):
def Append(self, *args):
for element in args:
self.append(element)
def Extend(self, *args):
for element in args:
self.extend(element)
def Remove(self, *args):
for top, lists, nonlists in FileListWalk(self, topdown=False):
for element in args:
try:
top.remove(element)
except ValueError:
pass
def Replace(self, old, new):
for top, lists, nonlists in FileListWalk(self, topdown=False):
try:
i = top.index(old)
except ValueError:
pass
else:
if SCons.Util.is_List(new):
top[i:i+1] = new
else:
top[i] = new
def FilterOut(self, **kw):
"""Removes values from existing construction variables in an Environment.
The values to remove should be a list. For example:
self.FilterOut(CPPDEFINES=['REMOVE_ME', 'ME_TOO'])
Args:
self: Environment to alter.
kw: (Any other named arguments are values to remove).
"""
kw = SCons.Environment.copy_non_reserved_keywords(kw)
for key, val in kw.items():
envval = self.get(key, None)
if envval is None:
# No existing variable in the environment, so nothing to delete.
continue
for vremove in val:
# Use while not if, so we can handle duplicates.
while vremove in envval:
envval.remove(vremove)
self[key] = envval
# TODO(sgk): SCons.Environment.Append() has much more logic to deal
# with various types of values. We should handle all those cases in here
# too. (If variable is a dict, etc.)
import __builtin__
__builtin__.ChromeFileList = ChromeFileList
non_compilable_suffixes = {
'LINUX' : set([
'.bdic',
'.css',
'.dat',
'.fragment',
'.gperf',
'.h',
'.html',
'.hxx',
'.idl',
'.js',
'.mk',
'.rc',
'.sigs',
]),
'WINDOWS' : set([
'.h',
'.dat',
'.idl',
]),
}
def compilable(env, file):
base, ext = os.path.splitext(str(file))
if ext in non_compilable_suffixes[env['TARGET_PLATFORM']]:
return False
return True
def compilable_files(env, sources):
if not hasattr(sources, 'entries'):
return [x for x in sources if compilable(env, x)]
result = []
for top, folders, nonfolders in FileListWalk(sources):
result.extend([x for x in nonfolders if compilable(env, x)])
return result
def ChromeProgram(env, target, source, *args, **kw):
source = compilable_files(env, source)
result = env.Program('$TOP_BUILDDIR/' + str(target), source, *args, **kw)
if env.get('INCREMENTAL'):
env.Precious(result)
return result
def ChromeTestProgram(env, target, source, *args, **kw):
source = compilable_files(env, source)
result = env.Program('$TOP_BUILDDIR/' + str(target), source, *args, **kw)
if env.get('INCREMENTAL'):
env.Precious(*result)
return result
def ChromeLibrary(env, target, source, *args, **kw):
source = compilable_files(env, source)
result = env.Library('$LIB_DIR/' + str(target), source, *args, **kw)
return result
def ChromeLoadableModule(env, target, source, *args, **kw):
source = compilable_files(env, source)
if env.get('_GYP'):
result = env.LoadableModule(target, source, *args, **kw)
else:
kw['COMPONENT_STATIC'] = True
result = env.LoadableModule(target, source, *args, **kw)
return result
def ChromeStaticLibrary(env, target, source, *args, **kw):
source = compilable_files(env, source)
if env.get('_GYP'):
result = env.StaticLibrary('$LIB_DIR/' + str(target), source, *args, **kw)
else:
kw['COMPONENT_STATIC'] = True
result = env.ComponentLibrary(target, source, *args, **kw)
return result
def ChromeSharedLibrary(env, target, source, *args, **kw):
source = compilable_files(env, source)
if env.get('_GYP'):
result = env.SharedLibrary('$LIB_DIR/' + str(target), source, *args, **kw)
else:
kw['COMPONENT_STATIC'] = False
result = [env.ComponentLibrary(target, source, *args, **kw)[0]]
if env.get('INCREMENTAL'):
env.Precious(result)
return result
def ChromeObject(env, *args, **kw):
if env.get('_GYP'):
result = env.Object(target, source, *args, **kw)
else:
result = env.ComponentObject(*args, **kw)
return result
def generate(env):
env.AddMethod(ChromeProgram)
env.AddMethod(ChromeTestProgram)
env.AddMethod(ChromeLibrary)
env.AddMethod(ChromeLoadableModule)
env.AddMethod(ChromeStaticLibrary)
env.AddMethod(ChromeSharedLibrary)
env.AddMethod(ChromeObject)
env.AddMethod(FilterOut)
# Add the grit tool to the base environment because we use this a lot.
sys.path.append(env.Dir('$SRC_DIR/tools/grit').abspath)
env.Tool('scons', toolpath=[env.Dir('$SRC_DIR/tools/grit/grit')])
# Add the repack python script tool that we use in multiple places.
sys.path.append(env.Dir('$SRC_DIR/tools/data_pack').abspath)
env.Tool('scons', toolpath=[env.Dir('$SRC_DIR/tools/data_pack/')])
def exists(env):
return True