| OLD | NEW |
| (Empty) |
| 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) | |
| OLD | NEW |