mirror of https://github.com/lukechilds/node.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
5.7 KiB
199 lines
5.7 KiB
# Copyright (c) 2011 Google Inc. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""
|
|
SCons generator.
|
|
|
|
This contains class definitions and supporting functions for generating
|
|
pieces of SCons files for the different types of GYP targets.
|
|
"""
|
|
|
|
import os
|
|
|
|
|
|
def WriteList(fp, list, prefix='',
|
|
separator=',\n ',
|
|
preamble=None,
|
|
postamble=None):
|
|
fp.write(preamble or '')
|
|
fp.write((separator or ' ').join([prefix + l for l in list]))
|
|
fp.write(postamble or '')
|
|
|
|
|
|
class TargetBase(object):
|
|
"""
|
|
Base class for a SCons representation of a GYP target.
|
|
"""
|
|
is_ignored = False
|
|
target_prefix = ''
|
|
target_suffix = ''
|
|
def __init__(self, spec):
|
|
self.spec = spec
|
|
def full_product_name(self):
|
|
"""
|
|
Returns the full name of the product being built:
|
|
|
|
* Uses 'product_name' if it's set, else prefix + 'target_name'.
|
|
* Prepends 'product_dir' if set.
|
|
* Appends SCons suffix variables for the target type (or
|
|
product_extension).
|
|
"""
|
|
suffix = self.target_suffix
|
|
product_extension = self.spec.get('product_extension')
|
|
if product_extension:
|
|
suffix = '.' + product_extension
|
|
prefix = self.spec.get('product_prefix', self.target_prefix)
|
|
name = self.spec['target_name']
|
|
name = prefix + self.spec.get('product_name', name) + suffix
|
|
product_dir = self.spec.get('product_dir')
|
|
if product_dir:
|
|
name = os.path.join(product_dir, name)
|
|
else:
|
|
name = os.path.join(self.out_dir, name)
|
|
return name
|
|
|
|
def write_input_files(self, fp):
|
|
"""
|
|
Writes the definition of the input files (sources).
|
|
"""
|
|
sources = self.spec.get('sources')
|
|
if not sources:
|
|
fp.write('\ninput_files = []\n')
|
|
return
|
|
preamble = '\ninput_files = [\n '
|
|
postamble = ',\n]\n'
|
|
WriteList(fp, map(repr, sources), preamble=preamble, postamble=postamble)
|
|
|
|
def builder_call(self):
|
|
"""
|
|
Returns the actual SCons builder call to build this target.
|
|
"""
|
|
name = self.full_product_name()
|
|
return 'env.%s(env.File(%r), input_files)' % (self.builder_name, name)
|
|
def write_target(self, fp, src_dir='', pre=''):
|
|
"""
|
|
Writes the lines necessary to build this target.
|
|
"""
|
|
fp.write('\n' + pre)
|
|
fp.write('_outputs = %s\n' % self.builder_call())
|
|
fp.write('target_files.extend(_outputs)\n')
|
|
|
|
|
|
class NoneTarget(TargetBase):
|
|
"""
|
|
A GYP target type of 'none', implicitly or explicitly.
|
|
"""
|
|
def write_target(self, fp, pre=''):
|
|
fp.write('\ntarget_files.extend(input_files)\n')
|
|
|
|
|
|
class SettingsTarget(TargetBase):
|
|
"""
|
|
A GYP target type of 'settings'.
|
|
"""
|
|
is_ignored = True
|
|
|
|
|
|
compilable_sources_template = """
|
|
_result = []
|
|
for infile in input_files:
|
|
if env.compilable(infile):
|
|
if (type(infile) == type('')
|
|
and (infile.startswith(%(src_dir)r)
|
|
or not os.path.isabs(env.subst(infile)))):
|
|
# Force files below the build directory by replacing all '..'
|
|
# elements in the path with '__':
|
|
base, ext = os.path.splitext(os.path.normpath(infile))
|
|
base = [d == '..' and '__' or d for d in base.split('/')]
|
|
base = os.path.join(*base)
|
|
object = '${OBJ_DIR}/${COMPONENT_NAME}/${TARGET_NAME}/' + base
|
|
if not infile.startswith(%(src_dir)r):
|
|
infile = %(src_dir)r + infile
|
|
infile = env.%(name)s(object, infile)[0]
|
|
else:
|
|
infile = env.%(name)s(infile)[0]
|
|
_result.append(infile)
|
|
input_files = _result
|
|
"""
|
|
|
|
class CompilableSourcesTargetBase(TargetBase):
|
|
"""
|
|
An abstract base class for targets that compile their source files.
|
|
|
|
We explicitly transform compilable files into object files,
|
|
even though SCons could infer that for us, because we want
|
|
to control where the object file ends up. (The implicit rules
|
|
in SCons always put the object file next to the source file.)
|
|
"""
|
|
intermediate_builder_name = None
|
|
def write_target(self, fp, src_dir='', pre=''):
|
|
if self.intermediate_builder_name is None:
|
|
raise NotImplementedError
|
|
if src_dir and not src_dir.endswith('/'):
|
|
src_dir += '/'
|
|
variables = {
|
|
'src_dir': src_dir,
|
|
'name': self.intermediate_builder_name,
|
|
}
|
|
fp.write(compilable_sources_template % variables)
|
|
super(CompilableSourcesTargetBase, self).write_target(fp)
|
|
|
|
|
|
class ProgramTarget(CompilableSourcesTargetBase):
|
|
"""
|
|
A GYP target type of 'executable'.
|
|
"""
|
|
builder_name = 'GypProgram'
|
|
intermediate_builder_name = 'StaticObject'
|
|
target_prefix = '${PROGPREFIX}'
|
|
target_suffix = '${PROGSUFFIX}'
|
|
out_dir = '${TOP_BUILDDIR}'
|
|
|
|
|
|
class StaticLibraryTarget(CompilableSourcesTargetBase):
|
|
"""
|
|
A GYP target type of 'static_library'.
|
|
"""
|
|
builder_name = 'GypStaticLibrary'
|
|
intermediate_builder_name = 'StaticObject'
|
|
target_prefix = '${LIBPREFIX}'
|
|
target_suffix = '${LIBSUFFIX}'
|
|
out_dir = '${LIB_DIR}'
|
|
|
|
|
|
class SharedLibraryTarget(CompilableSourcesTargetBase):
|
|
"""
|
|
A GYP target type of 'shared_library'.
|
|
"""
|
|
builder_name = 'GypSharedLibrary'
|
|
intermediate_builder_name = 'SharedObject'
|
|
target_prefix = '${SHLIBPREFIX}'
|
|
target_suffix = '${SHLIBSUFFIX}'
|
|
out_dir = '${LIB_DIR}'
|
|
|
|
|
|
class LoadableModuleTarget(CompilableSourcesTargetBase):
|
|
"""
|
|
A GYP target type of 'loadable_module'.
|
|
"""
|
|
builder_name = 'GypLoadableModule'
|
|
intermediate_builder_name = 'SharedObject'
|
|
target_prefix = '${SHLIBPREFIX}'
|
|
target_suffix = '${SHLIBSUFFIX}'
|
|
out_dir = '${TOP_BUILDDIR}'
|
|
|
|
|
|
TargetMap = {
|
|
None : NoneTarget,
|
|
'none' : NoneTarget,
|
|
'settings' : SettingsTarget,
|
|
'executable' : ProgramTarget,
|
|
'static_library' : StaticLibraryTarget,
|
|
'shared_library' : SharedLibraryTarget,
|
|
'loadable_module' : LoadableModuleTarget,
|
|
}
|
|
|
|
|
|
def Target(spec):
|
|
return TargetMap[spec.get('type')](spec)
|
|
|