OLD | NEW |
1 # Copyright (c) 2012 Google Inc. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 from compiler.ast import Const | 5 from compiler.ast import Const |
6 from compiler.ast import Dict | 6 from compiler.ast import Dict |
7 from compiler.ast import Discard | 7 from compiler.ast import Discard |
8 from compiler.ast import List | 8 from compiler.ast import List |
9 from compiler.ast import Module | 9 from compiler.ast import Module |
10 from compiler.ast import Node | 10 from compiler.ast import Node |
(...skipping 2087 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2098 VALID_TARGET_TYPES = ('executable', 'loadable_module', | 2098 VALID_TARGET_TYPES = ('executable', 'loadable_module', |
2099 'static_library', 'shared_library', | 2099 'static_library', 'shared_library', |
2100 'none') | 2100 'none') |
2101 target_type = target_dict.get('type', None) | 2101 target_type = target_dict.get('type', None) |
2102 if target_type not in VALID_TARGET_TYPES: | 2102 if target_type not in VALID_TARGET_TYPES: |
2103 raise Exception("Target %s has an invalid target type '%s'. " | 2103 raise Exception("Target %s has an invalid target type '%s'. " |
2104 "Must be one of %s." % | 2104 "Must be one of %s." % |
2105 (target, target_type, '/'.join(VALID_TARGET_TYPES))) | 2105 (target, target_type, '/'.join(VALID_TARGET_TYPES))) |
2106 | 2106 |
2107 | 2107 |
| 2108 def ValidateSourcesInTarget(target, target_dict, build_file): |
| 2109 # TODO: Check if MSVC allows this for non-static_library targets. |
| 2110 if target_dict.get('type', None) != 'static_library': |
| 2111 return |
| 2112 sources = target_dict.get('sources', []) |
| 2113 basenames = {} |
| 2114 for source in sources: |
| 2115 name, ext = os.path.splitext(source) |
| 2116 is_compiled_file = ext in [ |
| 2117 '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S'] |
| 2118 if not is_compiled_file: |
| 2119 continue |
| 2120 basename = os.path.basename(name) # Don't include extension. |
| 2121 basenames.setdefault(basename, []).append(source) |
| 2122 |
| 2123 error = '' |
| 2124 for basename, files in basenames.iteritems(): |
| 2125 if len(files) > 1: |
| 2126 error += ' %s: %s\n' % (basename, ' '.join(files)) |
| 2127 |
| 2128 if error: |
| 2129 print ('static library %s has several files with the same basename:\n' % |
| 2130 target + error + 'Some build systems, e.g. MSVC08, ' |
| 2131 'cannot handle that.') |
| 2132 raise KeyError, 'Duplicate basenames in sources section, see list above' |
| 2133 |
| 2134 |
2108 def ValidateRulesInTarget(target, target_dict, extra_sources_for_rules): | 2135 def ValidateRulesInTarget(target, target_dict, extra_sources_for_rules): |
2109 """Ensures that the rules sections in target_dict are valid and consistent, | 2136 """Ensures that the rules sections in target_dict are valid and consistent, |
2110 and determines which sources they apply to. | 2137 and determines which sources they apply to. |
2111 | 2138 |
2112 Arguments: | 2139 Arguments: |
2113 target: string, name of target. | 2140 target: string, name of target. |
2114 target_dict: dict, target spec containing "rules" and "sources" lists. | 2141 target_dict: dict, target spec containing "rules" and "sources" lists. |
2115 extra_sources_for_rules: a list of keys to scan for rule matches in | 2142 extra_sources_for_rules: a list of keys to scan for rule matches in |
2116 addition to 'sources'. | 2143 addition to 'sources'. |
2117 """ | 2144 """ |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2155 (source_root, source_extension) = os.path.splitext(source) | 2182 (source_root, source_extension) = os.path.splitext(source) |
2156 if source_extension.startswith('.'): | 2183 if source_extension.startswith('.'): |
2157 source_extension = source_extension[1:] | 2184 source_extension = source_extension[1:] |
2158 if source_extension == extension: | 2185 if source_extension == extension: |
2159 rule_sources.append(source) | 2186 rule_sources.append(source) |
2160 | 2187 |
2161 if len(rule_sources) > 0: | 2188 if len(rule_sources) > 0: |
2162 rule['rule_sources'] = rule_sources | 2189 rule['rule_sources'] = rule_sources |
2163 | 2190 |
2164 | 2191 |
2165 def ValidateActionsInTarget(target, target_dict, build_file): | |
2166 '''Validates the inputs to the actions in a target.''' | |
2167 target_name = target_dict.get('target_name') | |
2168 actions = target_dict.get('actions', []) | |
2169 for action in actions: | |
2170 action_name = action.get('action_name') | |
2171 if not action_name: | |
2172 raise Exception("Anonymous action in target %s. " | |
2173 "An action must have an 'action_name' field." % | |
2174 target_name) | |
2175 inputs = action.get('inputs', []) | |
2176 action_command = action.get('action') | |
2177 if action_command and not action_command[0]: | |
2178 raise Exception("Empty action as command in target %s." % target_name) | |
2179 | |
2180 | |
2181 def ValidateRunAsInTarget(target, target_dict, build_file): | 2192 def ValidateRunAsInTarget(target, target_dict, build_file): |
2182 target_name = target_dict.get('target_name') | 2193 target_name = target_dict.get('target_name') |
2183 run_as = target_dict.get('run_as') | 2194 run_as = target_dict.get('run_as') |
2184 if not run_as: | 2195 if not run_as: |
2185 return | 2196 return |
2186 if not isinstance(run_as, dict): | 2197 if not isinstance(run_as, dict): |
2187 raise Exception("The 'run_as' in target %s from file %s should be a " | 2198 raise Exception("The 'run_as' in target %s from file %s should be a " |
2188 "dictionary." % | 2199 "dictionary." % |
2189 (target_name, build_file)) | 2200 (target_name, build_file)) |
2190 action = run_as.get('action') | 2201 action = run_as.get('action') |
(...skipping 10 matching lines...) Expand all Loading... |
2201 raise Exception("The 'working_directory' for 'run_as' in target %s " | 2212 raise Exception("The 'working_directory' for 'run_as' in target %s " |
2202 "in file %s should be a string." % | 2213 "in file %s should be a string." % |
2203 (target_name, build_file)) | 2214 (target_name, build_file)) |
2204 environment = run_as.get('environment') | 2215 environment = run_as.get('environment') |
2205 if environment and not isinstance(environment, dict): | 2216 if environment and not isinstance(environment, dict): |
2206 raise Exception("The 'environment' for 'run_as' in target %s " | 2217 raise Exception("The 'environment' for 'run_as' in target %s " |
2207 "in file %s should be a dictionary." % | 2218 "in file %s should be a dictionary." % |
2208 (target_name, build_file)) | 2219 (target_name, build_file)) |
2209 | 2220 |
2210 | 2221 |
| 2222 def ValidateActionsInTarget(target, target_dict, build_file): |
| 2223 '''Validates the inputs to the actions in a target.''' |
| 2224 target_name = target_dict.get('target_name') |
| 2225 actions = target_dict.get('actions', []) |
| 2226 for action in actions: |
| 2227 action_name = action.get('action_name') |
| 2228 if not action_name: |
| 2229 raise Exception("Anonymous action in target %s. " |
| 2230 "An action must have an 'action_name' field." % |
| 2231 target_name) |
| 2232 inputs = action.get('inputs', []) |
| 2233 action_command = action.get('action') |
| 2234 if action_command and not action_command[0]: |
| 2235 raise Exception("Empty action as command in target %s." % target_name) |
| 2236 |
| 2237 |
2211 def TurnIntIntoStrInDict(the_dict): | 2238 def TurnIntIntoStrInDict(the_dict): |
2212 """Given dict the_dict, recursively converts all integers into strings. | 2239 """Given dict the_dict, recursively converts all integers into strings. |
2213 """ | 2240 """ |
2214 # Use items instead of iteritems because there's no need to try to look at | 2241 # Use items instead of iteritems because there's no need to try to look at |
2215 # reinserted keys and their associated values. | 2242 # reinserted keys and their associated values. |
2216 for k, v in the_dict.items(): | 2243 for k, v in the_dict.items(): |
2217 if isinstance(v, int): | 2244 if isinstance(v, int): |
2218 v = str(v) | 2245 v = str(v) |
2219 the_dict[k] = v | 2246 the_dict[k] = v |
2220 elif isinstance(v, dict): | 2247 elif isinstance(v, dict): |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2386 ProcessListFiltersInDict(target, target_dict) | 2413 ProcessListFiltersInDict(target, target_dict) |
2387 | 2414 |
2388 # Make sure that the rules make sense, and build up rule_sources lists as | 2415 # Make sure that the rules make sense, and build up rule_sources lists as |
2389 # needed. Not all generators will need to use the rule_sources lists, but | 2416 # needed. Not all generators will need to use the rule_sources lists, but |
2390 # some may, and it seems best to build the list in a common spot. | 2417 # some may, and it seems best to build the list in a common spot. |
2391 # Also validate actions and run_as elements in targets. | 2418 # Also validate actions and run_as elements in targets. |
2392 for target in flat_list: | 2419 for target in flat_list: |
2393 target_dict = targets[target] | 2420 target_dict = targets[target] |
2394 build_file = gyp.common.BuildFile(target) | 2421 build_file = gyp.common.BuildFile(target) |
2395 ValidateTargetType(target, target_dict) | 2422 ValidateTargetType(target, target_dict) |
| 2423 ValidateSourcesInTarget(target, target_dict, build_file) |
2396 ValidateRulesInTarget(target, target_dict, extra_sources_for_rules) | 2424 ValidateRulesInTarget(target, target_dict, extra_sources_for_rules) |
2397 ValidateRunAsInTarget(target, target_dict, build_file) | 2425 ValidateRunAsInTarget(target, target_dict, build_file) |
2398 ValidateActionsInTarget(target, target_dict, build_file) | 2426 ValidateActionsInTarget(target, target_dict, build_file) |
2399 | 2427 |
2400 # Generators might not expect ints. Turn them into strs. | 2428 # Generators might not expect ints. Turn them into strs. |
2401 TurnIntIntoStrInDict(data) | 2429 TurnIntIntoStrInDict(data) |
2402 | 2430 |
2403 # TODO(mark): Return |data| for now because the generator needs a list of | 2431 # TODO(mark): Return |data| for now because the generator needs a list of |
2404 # build files that came in. In the future, maybe it should just accept | 2432 # build files that came in. In the future, maybe it should just accept |
2405 # a list, and not the whole data dict. | 2433 # a list, and not the whole data dict. |
2406 return [flat_list, targets, data] | 2434 return [flat_list, targets, data] |
OLD | NEW |