Introduce xwalk-extensions-common
[platform/framework/web/xwalk-extensions-common.git] / tools / gyp / pylib / gyp / SCons.py
1 # Copyright (c) 2012 Google Inc. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """
6 SCons generator.
7
8 This contains class definitions and supporting functions for generating
9 pieces of SCons files for the different types of GYP targets.
10 """
11
12 import os
13
14
15 def WriteList(fp, list, prefix='',
16                         separator=',\n    ',
17                         preamble=None,
18                         postamble=None):
19   fp.write(preamble or '')
20   fp.write((separator or ' ').join([prefix + l for l in list]))
21   fp.write(postamble or '')
22
23
24 class TargetBase(object):
25   """
26   Base class for a SCons representation of a GYP target.
27   """
28   is_ignored = False
29   target_prefix = ''
30   target_suffix = ''
31   def __init__(self, spec):
32     self.spec = spec
33   def full_product_name(self):
34     """
35     Returns the full name of the product being built:
36
37       * Uses 'product_name' if it's set, else prefix + 'target_name'.
38       * Prepends 'product_dir' if set.
39       * Appends SCons suffix variables for the target type (or
40         product_extension).
41     """
42     suffix = self.target_suffix
43     product_extension = self.spec.get('product_extension')
44     if product_extension:
45       suffix = '.' + product_extension
46     prefix = self.spec.get('product_prefix', self.target_prefix)
47     name = self.spec['target_name']
48     name = prefix + self.spec.get('product_name', name) + suffix
49     product_dir = self.spec.get('product_dir')
50     if product_dir:
51       name = os.path.join(product_dir, name)
52     else:
53       name = os.path.join(self.out_dir, name)
54     return name
55
56   def write_input_files(self, fp):
57     """
58     Writes the definition of the input files (sources).
59     """
60     sources = self.spec.get('sources')
61     if not sources:
62       fp.write('\ninput_files = []\n')
63       return
64     preamble = '\ninput_files = [\n    '
65     postamble = ',\n]\n'
66     WriteList(fp, map(repr, sources), preamble=preamble, postamble=postamble)
67
68   def builder_call(self):
69     """
70     Returns the actual SCons builder call to build this target.
71     """
72     name = self.full_product_name()
73     return 'env.%s(env.File(%r), input_files)' % (self.builder_name, name)
74   def write_target(self, fp, src_dir='', pre=''):
75     """
76     Writes the lines necessary to build this target.
77     """
78     fp.write('\n' + pre)
79     fp.write('_outputs = %s\n' % self.builder_call())
80     fp.write('target_files.extend(_outputs)\n')
81
82
83 class NoneTarget(TargetBase):
84   """
85   A GYP target type of 'none', implicitly or explicitly.
86   """
87   def write_target(self, fp, src_dir='', pre=''):
88     fp.write('\ntarget_files.extend(input_files)\n')
89
90
91 class SettingsTarget(TargetBase):
92   """
93   A GYP target type of 'settings'.
94   """
95   is_ignored = True
96
97
98 compilable_sources_template = """
99 _result = []
100 for infile in input_files:
101   if env.compilable(infile):
102     if (type(infile) == type('')
103         and (infile.startswith(%(src_dir)r)
104              or not os.path.isabs(env.subst(infile)))):
105       # Force files below the build directory by replacing all '..'
106       # elements in the path with '__':
107       base, ext = os.path.splitext(os.path.normpath(infile))
108       base = [d == '..' and '__' or d for d in base.split('/')]
109       base = os.path.join(*base)
110       object = '${OBJ_DIR}/${COMPONENT_NAME}/${TARGET_NAME}/' + base
111       if not infile.startswith(%(src_dir)r):
112         infile = %(src_dir)r + infile
113       infile = env.%(name)s(object, infile)[0]
114     else:
115       infile = env.%(name)s(infile)[0]
116   _result.append(infile)
117 input_files = _result
118 """
119
120 class CompilableSourcesTargetBase(TargetBase):
121   """
122   An abstract base class for targets that compile their source files.
123
124   We explicitly transform compilable files into object files,
125   even though SCons could infer that for us, because we want
126   to control where the object file ends up.  (The implicit rules
127   in SCons always put the object file next to the source file.)
128   """
129   intermediate_builder_name = None
130   def write_target(self, fp, src_dir='', pre=''):
131     if self.intermediate_builder_name is None:
132       raise NotImplementedError
133     if src_dir and not src_dir.endswith('/'):
134       src_dir += '/'
135     variables = {
136         'src_dir': src_dir,
137         'name': self.intermediate_builder_name,
138     }
139     fp.write(compilable_sources_template % variables)
140     super(CompilableSourcesTargetBase, self).write_target(fp)
141
142
143 class ProgramTarget(CompilableSourcesTargetBase):
144   """
145   A GYP target type of 'executable'.
146   """
147   builder_name = 'GypProgram'
148   intermediate_builder_name = 'StaticObject'
149   target_prefix = '${PROGPREFIX}'
150   target_suffix = '${PROGSUFFIX}'
151   out_dir = '${TOP_BUILDDIR}'
152
153
154 class StaticLibraryTarget(CompilableSourcesTargetBase):
155   """
156   A GYP target type of 'static_library'.
157   """
158   builder_name = 'GypStaticLibrary'
159   intermediate_builder_name = 'StaticObject'
160   target_prefix = '${LIBPREFIX}'
161   target_suffix = '${LIBSUFFIX}'
162   out_dir = '${LIB_DIR}'
163
164
165 class SharedLibraryTarget(CompilableSourcesTargetBase):
166   """
167   A GYP target type of 'shared_library'.
168   """
169   builder_name = 'GypSharedLibrary'
170   intermediate_builder_name = 'SharedObject'
171   target_prefix = '${SHLIBPREFIX}'
172   target_suffix = '${SHLIBSUFFIX}'
173   out_dir = '${LIB_DIR}'
174
175
176 class LoadableModuleTarget(CompilableSourcesTargetBase):
177   """
178   A GYP target type of 'loadable_module'.
179   """
180   builder_name = 'GypLoadableModule'
181   intermediate_builder_name = 'SharedObject'
182   target_prefix = '${SHLIBPREFIX}'
183   target_suffix = '${SHLIBSUFFIX}'
184   out_dir = '${TOP_BUILDDIR}'
185
186
187 TargetMap = {
188   None : NoneTarget,
189   'none' : NoneTarget,
190   'settings' : SettingsTarget,
191   'executable' : ProgramTarget,
192   'static_library' : StaticLibraryTarget,
193   'shared_library' : SharedLibraryTarget,
194   'loadable_module' : LoadableModuleTarget,
195 }
196
197
198 def Target(spec):
199   return TargetMap[spec.get('type')](spec)