OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 # Copyright (c) 2009 Google Inc. All rights reserved. | 3 # Copyright (c) 2009 Google Inc. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 import filecmp | 7 import filecmp |
8 import gyp.common | 8 import gyp.common |
9 import gyp.xcodeproj_file | 9 import gyp.xcodeproj_file |
10 import errno | 10 import errno |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 'mac_bundle', | 67 'mac_bundle', |
68 'mac_bundle_resources', | 68 'mac_bundle_resources', |
69 'xcode_create_dependents_test_runner', | 69 'xcode_create_dependents_test_runner', |
70 ] | 70 ] |
71 | 71 |
72 # We want to let any rules apply to files that are resources also. | 72 # We want to let any rules apply to files that are resources also. |
73 generator_extra_sources_for_rules = [ | 73 generator_extra_sources_for_rules = [ |
74 'mac_bundle_resources', | 74 'mac_bundle_resources', |
75 ] | 75 ] |
76 | 76 |
| 77 |
| 78 def CreateXCConfigurationList(configuration_names): |
| 79 xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) |
| 80 for configuration_name in configuration_names: |
| 81 xcbc = gyp.xcodeproj_file.XCBuildConfiguration({ |
| 82 'name': configuration_name}) |
| 83 xccl.AppendProperty('buildConfigurations', xcbc) |
| 84 xccl.SetProperty('defaultConfigurationName', configuration_names[0]) |
| 85 return xccl |
| 86 |
| 87 |
77 class XcodeProject(object): | 88 class XcodeProject(object): |
78 def __init__(self, gyp_path, path, build_file_dict): | 89 def __init__(self, gyp_path, path, build_file_dict): |
79 self.gyp_path = gyp_path | 90 self.gyp_path = gyp_path |
80 self.path = path | 91 self.path = path |
81 self.project = gyp.xcodeproj_file.PBXProject(path=path) | 92 self.project = gyp.xcodeproj_file.PBXProject(path=path) |
82 projectDirPath = gyp.common.RelativePath( | 93 projectDirPath = gyp.common.RelativePath( |
83 os.path.dirname(os.path.abspath(self.gyp_path)), | 94 os.path.dirname(os.path.abspath(self.gyp_path)), |
84 os.path.dirname(path) or '.') | 95 os.path.dirname(path) or '.') |
85 self.project.SetProperty('projectDirPath', projectDirPath) | 96 self.project.SetProperty('projectDirPath', projectDirPath) |
86 self.project_file = \ | 97 self.project_file = \ |
(...skipping 22 matching lines...) Expand all Loading... |
109 xcbcs = xccl.GetProperty('buildConfigurations') | 120 xcbcs = xccl.GetProperty('buildConfigurations') |
110 for xcbc in xcbcs: | 121 for xcbc in xcbcs: |
111 name = xcbc.GetProperty('name') | 122 name = xcbc.GetProperty('name') |
112 if name not in configurations: | 123 if name not in configurations: |
113 configurations.append(name) | 124 configurations.append(name) |
114 | 125 |
115 # Replace the XCConfigurationList attached to the PBXProject object with | 126 # Replace the XCConfigurationList attached to the PBXProject object with |
116 # a new one specifying all of the configuration names used by the various | 127 # a new one specifying all of the configuration names used by the various |
117 # targets. | 128 # targets. |
118 try: | 129 try: |
119 xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) | 130 xccl = CreateXCConfigurationList(configurations) |
120 for configuration in configurations: | |
121 xcbc = gyp.xcodeproj_file.XCBuildConfiguration({'name': configuration}) | |
122 xccl.AppendProperty('buildConfigurations', xcbc) | |
123 xccl.SetProperty('defaultConfigurationName', configurations[0]) | |
124 self.project.SetProperty('buildConfigurationList', xccl) | 131 self.project.SetProperty('buildConfigurationList', xccl) |
125 except: | 132 except: |
126 import sys | 133 import sys |
127 sys.stderr.write("Problem with gyp file %s\n" % self.gyp_path) | 134 sys.stderr.write("Problem with gyp file %s\n" % self.gyp_path) |
128 raise | 135 raise |
129 | 136 |
130 # The need for this setting is explained above where _intermediate_var is | 137 # The need for this setting is explained above where _intermediate_var is |
131 # defined. The comments below about wanting to avoid project-wide build | 138 # defined. The comments below about wanting to avoid project-wide build |
132 # settings apply here too, but this needs to be set on a project-wide basis | 139 # settings apply here too, but this needs to be set on a project-wide basis |
133 # so that files relative to the _intermediate_var setting can be displayed | 140 # so that files relative to the _intermediate_var setting can be displayed |
(...skipping 19 matching lines...) Expand all Loading... |
153 # tree view for UI display. | 160 # tree view for UI display. |
154 for xck, xcv in self.build_file_dict.get('xcode_settings', {}).iteritems(): | 161 for xck, xcv in self.build_file_dict.get('xcode_settings', {}).iteritems(): |
155 xccl.SetBuildSetting(xck, xcv) | 162 xccl.SetBuildSetting(xck, xcv) |
156 | 163 |
157 # Sort the targets based on how they appeared in the input. | 164 # Sort the targets based on how they appeared in the input. |
158 # TODO(mark): Like a lot of other things here, this assumes internal | 165 # TODO(mark): Like a lot of other things here, this assumes internal |
159 # knowledge of PBXProject - in this case, of its "targets" property. | 166 # knowledge of PBXProject - in this case, of its "targets" property. |
160 | 167 |
161 # ordinary_targets are ordinary targets that are already in the project | 168 # ordinary_targets are ordinary targets that are already in the project |
162 # file. run_test_targets are the targets that run unittests and should be | 169 # file. run_test_targets are the targets that run unittests and should be |
163 # used for the Run All Tests target. | 170 # used for the Run All Tests target. support_targets are the action/rule |
| 171 # targets used by GYP file targets, just kept for the assert check. |
164 ordinary_targets = [] | 172 ordinary_targets = [] |
165 run_test_targets = [] | 173 run_test_targets = [] |
| 174 support_targets = [] |
166 | 175 |
167 # targets is full list of targets in the project. | 176 # targets is full list of targets in the project. |
168 targets = [] | 177 targets = [] |
169 | 178 |
170 # does the it define it's own "all"? | 179 # does the it define it's own "all"? |
171 has_custom_all = False | 180 has_custom_all = False |
172 | 181 |
173 # targets_for_all is the list of ordinary_targets that should be listed | 182 # targets_for_all is the list of ordinary_targets that should be listed |
174 # in this project's "All" target. It includes each non_runtest_target | 183 # in this project's "All" target. It includes each non_runtest_target |
175 # that does not have suppress_wildcard set. | 184 # that does not have suppress_wildcard set. |
176 targets_for_all = [] | 185 targets_for_all = [] |
177 | 186 |
178 for target in self.build_file_dict['targets']: | 187 for target in self.build_file_dict['targets']: |
179 target_name = target['target_name'] | 188 target_name = target['target_name'] |
180 toolset = target['toolset'] | 189 toolset = target['toolset'] |
181 qualified_target = gyp.common.QualifiedTarget(self.gyp_path, target_name, | 190 qualified_target = gyp.common.QualifiedTarget(self.gyp_path, target_name, |
182 toolset) | 191 toolset) |
183 xcode_target = xcode_targets[qualified_target] | 192 xcode_target = xcode_targets[qualified_target] |
184 # Make sure that the target being added to the sorted list is already in | 193 # Make sure that the target being added to the sorted list is already in |
185 # the unsorted list. | 194 # the unsorted list. |
186 assert xcode_target in self.project._properties['targets'] | 195 assert xcode_target in self.project._properties['targets'] |
187 targets.append(xcode_target) | 196 targets.append(xcode_target) |
188 ordinary_targets.append(xcode_target) | 197 ordinary_targets.append(xcode_target) |
| 198 if xcode_target.support_target: |
| 199 support_targets.append(xcode_target.support_target) |
| 200 targets.append(xcode_target.support_target) |
189 | 201 |
190 if not int(target.get('suppress_wildcard', False)): | 202 if not int(target.get('suppress_wildcard', False)): |
191 targets_for_all.append(xcode_target) | 203 targets_for_all.append(xcode_target) |
192 | 204 |
193 if target_name.lower() == 'all': | 205 if target_name.lower() == 'all': |
194 has_custom_all = True; | 206 has_custom_all = True; |
195 | 207 |
196 # If this target has a 'run_as' attribute, or is a test, add its | 208 # If this target has a 'run_as' attribute, or is a test, add its |
197 # target to the targets, and (if it's a test) add it the to the | 209 # target to the targets, and (if it's a test) add it the to the |
198 # test targets. | 210 # test targets. |
199 is_test = int(target.get('test', 0)) | 211 is_test = int(target.get('test', 0)) |
200 if target.get('run_as') or is_test: | 212 if target.get('run_as') or is_test: |
201 # Make a target to run something. It should have one | 213 # Make a target to run something. It should have one |
202 # dependency, the parent xcode target. | 214 # dependency, the parent xcode target. |
| 215 xccl = CreateXCConfigurationList(configurations) |
203 run_target = gyp.xcodeproj_file.PBXAggregateTarget({ | 216 run_target = gyp.xcodeproj_file.PBXAggregateTarget({ |
204 'name': 'Run ' + target_name, | 217 'name': 'Run ' + target_name, |
205 'productName': xcode_target.GetProperty('productName'), | 218 'productName': xcode_target.GetProperty('productName'), |
| 219 'buildConfigurationList': xccl, |
206 }, | 220 }, |
207 parent=self.project) | 221 parent=self.project) |
208 run_target.AddDependency(xcode_target) | 222 run_target.AddDependency(xcode_target) |
209 | 223 |
210 # The test runner target has a build phase that executes the | 224 # The test runner target has a build phase that executes the |
211 # test, if this has the 'test' attribute. If the 'run_as' tag | 225 # test, if this has the 'test' attribute. If the 'run_as' tag |
212 # doesn't exist (meaning that this must be a test), then we | 226 # doesn't exist (meaning that this must be a test), then we |
213 # define a default test command line. | 227 # define a default test command line. |
214 command = target.get('run_as', { | 228 command = target.get('run_as', { |
215 'action': ['${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}'] | 229 'action': ['${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}'] |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 | 270 |
257 # Add the run target to the project file. | 271 # Add the run target to the project file. |
258 targets.append(run_target) | 272 targets.append(run_target) |
259 if is_test: | 273 if is_test: |
260 run_test_targets.append(run_target) | 274 run_test_targets.append(run_target) |
261 xcode_target.test_runner = run_target | 275 xcode_target.test_runner = run_target |
262 | 276 |
263 | 277 |
264 # Make sure that the list of targets being replaced is the same length as | 278 # Make sure that the list of targets being replaced is the same length as |
265 # the one replacing it, but allow for the added test runner targets. | 279 # the one replacing it, but allow for the added test runner targets. |
266 assert len(self.project._properties['targets']) == len(ordinary_targets) | 280 assert len(self.project._properties['targets']) == \ |
| 281 len(ordinary_targets) + len(support_targets) |
267 | 282 |
268 self.project._properties['targets'] = targets | 283 self.project._properties['targets'] = targets |
269 | 284 |
270 # Get rid of unnecessary levels of depth in groups like the Source group. | 285 # Get rid of unnecessary levels of depth in groups like the Source group. |
271 self.project.RootGroupsTakeOverOnlyChildren(True) | 286 self.project.RootGroupsTakeOverOnlyChildren(True) |
272 | 287 |
273 # Sort the groups nicely. Do this after sorting the targets, because the | 288 # Sort the groups nicely. Do this after sorting the targets, because the |
274 # Products group is sorted based on the order of the targets. | 289 # Products group is sorted based on the order of the targets. |
275 self.project.SortGroups() | 290 self.project.SortGroups() |
276 | 291 |
277 # Create an "All" target if there's more than one target in this project | 292 # Create an "All" target if there's more than one target in this project |
278 # file and the project didn't define its own "All" target. Put a generated | 293 # file and the project didn't define its own "All" target. Put a generated |
279 # "All" target first so that people opening up the project for the first | 294 # "All" target first so that people opening up the project for the first |
280 # time will build everything by default. | 295 # time will build everything by default. |
281 if len(targets_for_all) > 1 and not has_custom_all: | 296 if len(targets_for_all) > 1 and not has_custom_all: |
282 xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) | 297 xccl = CreateXCConfigurationList(configurations) |
283 for configuration in configurations: | |
284 xcbc = gyp.xcodeproj_file.XCBuildConfiguration({'name': configuration}) | |
285 xccl.AppendProperty('buildConfigurations', xcbc) | |
286 xccl.SetProperty('defaultConfigurationName', configurations[0]) | |
287 | |
288 all_target = gyp.xcodeproj_file.PBXAggregateTarget( | 298 all_target = gyp.xcodeproj_file.PBXAggregateTarget( |
289 { | 299 { |
290 'buildConfigurationList': xccl, | 300 'buildConfigurationList': xccl, |
291 'name': 'All', | 301 'name': 'All', |
292 }, | 302 }, |
293 parent=self.project) | 303 parent=self.project) |
294 | 304 |
295 for target in targets_for_all: | 305 for target in targets_for_all: |
296 all_target.AddDependency(target) | 306 all_target.AddDependency(target) |
297 | 307 |
298 # TODO(mark): This is evil because it relies on internal knowledge of | 308 # TODO(mark): This is evil because it relies on internal knowledge of |
299 # PBXProject._properties. It's important to get the "All" target first, | 309 # PBXProject._properties. It's important to get the "All" target first, |
300 # though. | 310 # though. |
301 self.project._properties['targets'].insert(0, all_target) | 311 self.project._properties['targets'].insert(0, all_target) |
302 | 312 |
303 # The same, but for run_test_targets. | 313 # The same, but for run_test_targets. |
304 if len(run_test_targets) > 1: | 314 if len(run_test_targets) > 1: |
305 xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) | 315 xccl = CreateXCConfigurationList(configurations) |
306 for configuration in configurations: | |
307 xcbc = gyp.xcodeproj_file.XCBuildConfiguration({'name': configuration}) | |
308 xccl.AppendProperty('buildConfigurations', xcbc) | |
309 xccl.SetProperty('defaultConfigurationName', configurations[0]) | |
310 run_all_tests_target = gyp.xcodeproj_file.PBXAggregateTarget( | 316 run_all_tests_target = gyp.xcodeproj_file.PBXAggregateTarget( |
311 { | 317 { |
312 'buildConfigurationList': xccl, | 318 'buildConfigurationList': xccl, |
313 'name': 'Run All Tests', | 319 'name': 'Run All Tests', |
314 }, | 320 }, |
315 parent=self.project) | 321 parent=self.project) |
316 for run_test_target in run_test_targets: | 322 for run_test_target in run_test_targets: |
317 run_all_tests_target.AddDependency(run_test_target) | 323 run_all_tests_target.AddDependency(run_test_target) |
318 | 324 |
319 # Insert after the "All" target, which must exist if there is more than | 325 # Insert after the "All" target, which must exist if there is more than |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 qualified_target) | 580 qualified_target) |
575 configuration_names = [spec['default_configuration']] | 581 configuration_names = [spec['default_configuration']] |
576 for configuration_name in sorted(spec['configurations'].keys()): | 582 for configuration_name in sorted(spec['configurations'].keys()): |
577 if configuration_name not in configuration_names: | 583 if configuration_name not in configuration_names: |
578 configuration_names.append(configuration_name) | 584 configuration_names.append(configuration_name) |
579 xcp = xcode_projects[build_file] | 585 xcp = xcode_projects[build_file] |
580 pbxp = xcp.project | 586 pbxp = xcp.project |
581 | 587 |
582 # Set up the configurations for the target according to the list of names | 588 # Set up the configurations for the target according to the list of names |
583 # supplied. | 589 # supplied. |
584 xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) | 590 xccl = CreateXCConfigurationList(configuration_names) |
585 for configuration_name in configuration_names: | |
586 xcbc = gyp.xcodeproj_file.XCBuildConfiguration({ | |
587 'name': configuration_name}) | |
588 xccl.AppendProperty('buildConfigurations', xcbc) | |
589 xccl.SetProperty('defaultConfigurationName', configuration_names[0]) | |
590 | 591 |
591 # Create an XCTarget subclass object for the target. We use the type | 592 # Create an XCTarget subclass object for the target. We use the type |
592 # with "+bundle" appended if the target has "mac_bundle" set. | 593 # with "+bundle" appended if the target has "mac_bundle" set. |
593 _types = { | 594 _types = { |
594 'executable': 'com.apple.product-type.tool', | 595 'executable': 'com.apple.product-type.tool', |
595 'loadable_module': 'com.apple.product-type.library.dynamic', | 596 'loadable_module': 'com.apple.product-type.library.dynamic', |
596 'shared_library': 'com.apple.product-type.library.dynamic', | 597 'shared_library': 'com.apple.product-type.library.dynamic', |
597 'static_library': 'com.apple.product-type.library.static', | 598 'static_library': 'com.apple.product-type.library.static', |
598 'executable+bundle': 'com.apple.product-type.application', | 599 'executable+bundle': 'com.apple.product-type.application', |
599 'loadable_module+bundle': 'com.apple.product-type.bundle', | 600 'loadable_module+bundle': 'com.apple.product-type.bundle', |
(...skipping 14 matching lines...) Expand all Loading... |
614 xctarget_type = gyp.xcodeproj_file.PBXNativeTarget | 615 xctarget_type = gyp.xcodeproj_file.PBXNativeTarget |
615 try: | 616 try: |
616 target_properties['productType'] = _types[type_bundle_key] | 617 target_properties['productType'] = _types[type_bundle_key] |
617 except KeyError, e: | 618 except KeyError, e: |
618 gyp.common.ExceptionAppend(e, "-- unknown product type while " | 619 gyp.common.ExceptionAppend(e, "-- unknown product type while " |
619 "writing target %s" % target_name) | 620 "writing target %s" % target_name) |
620 raise | 621 raise |
621 else: | 622 else: |
622 xctarget_type = gyp.xcodeproj_file.PBXAggregateTarget | 623 xctarget_type = gyp.xcodeproj_file.PBXAggregateTarget |
623 | 624 |
624 if 'product_name' in spec: | 625 target_product_name = spec.get('product_name', None) |
625 target_properties['productName'] = spec['product_name'] | 626 if target_product_name: |
| 627 target_properties['productName'] = target_product_name |
626 | 628 |
627 xct = xctarget_type(target_properties, parent=pbxp, | 629 xct = xctarget_type(target_properties, parent=pbxp, |
628 force_extension=spec.get('product_extension', None)) | 630 force_extension=spec.get('product_extension', None)) |
629 pbxp.AppendProperty('targets', xct) | 631 pbxp.AppendProperty('targets', xct) |
630 xcode_targets[qualified_target] = xct | 632 xcode_targets[qualified_target] = xct |
631 xcode_target_to_target_dict[xct] = spec | 633 xcode_target_to_target_dict[xct] = spec |
632 | 634 |
633 # Xcode does not have a distinct type for loadable_modules that are pure | 635 # Xcode does not have a distinct type for loadable_modules that are pure |
634 # BSD targets (ie-unbundled). It uses the same setup as a shared_library | 636 # BSD targets (ie-unbundled). It uses the same setup as a shared_library |
635 # but the mach-o type is explictly set in the settings. So before we do | 637 # but the mach-o type is explictly set in the settings. So before we do |
636 # anything else, for this one case, we stuff in that one setting. This | 638 # anything else, for this one case, we stuff in that one setting. This |
637 # would allow the other data in the spec to change it if need be. | 639 # would allow the other data in the spec to change it if need be. |
638 if type == 'loadable_module' and not is_bundle: | 640 if type == 'loadable_module' and not is_bundle: |
639 xccl.SetBuildSetting('MACH_O_TYPE', 'mh_bundle') | 641 xccl.SetBuildSetting('MACH_O_TYPE', 'mh_bundle') |
640 | 642 |
| 643 spec_actions = spec.get('actions', []) |
| 644 spec_rules = spec.get('rules', []) |
| 645 |
| 646 # Xcode has some "issues" with checking dependencies for the "Compile |
| 647 # sources" step with any source files/headers generated by actions/rules. |
| 648 # To work around this, if a target is building anything directly (not |
| 649 # type "none"), then a second target as used to run the GYP actions/rules |
| 650 # and is made a dependency of this target. This way the work is done |
| 651 # before the dependency checks for what should be recompiled. |
| 652 support_xct = None |
| 653 if type != 'none' and (spec_actions or spec_rules): |
| 654 support_xccl = CreateXCConfigurationList(configuration_names); |
| 655 support_target_properties = { |
| 656 'buildConfigurationList': support_xccl, |
| 657 'name': target_name + ' Support', |
| 658 } |
| 659 if target_product_name: |
| 660 support_target_properties['productName'] = \ |
| 661 target_product_name + ' Support' |
| 662 support_xct = \ |
| 663 gyp.xcodeproj_file.PBXAggregateTarget(support_target_properties, |
| 664 parent=pbxp) |
| 665 pbxp.AppendProperty('targets', support_xct) |
| 666 xct.AddDependency(support_xct) |
| 667 # Hang the support target off the main target so it can be tested/found |
| 668 # by the generator during Finalize. |
| 669 xct.support_target = support_xct |
| 670 |
641 prebuild_index = 0 | 671 prebuild_index = 0 |
642 | 672 |
643 # Add custom shell script phases for "actions" sections. | 673 # Add custom shell script phases for "actions" sections. |
644 for action in spec.get('actions', []): | 674 for action in spec_actions: |
645 # There's no need to write anything into the script to ensure that the | 675 # There's no need to write anything into the script to ensure that the |
646 # output directories already exist, because Xcode will look at the | 676 # output directories already exist, because Xcode will look at the |
647 # declared outputs and automatically ensure that they exist for us. | 677 # declared outputs and automatically ensure that they exist for us. |
648 | 678 |
649 # Do we have a message to print when this action runs? | 679 # Do we have a message to print when this action runs? |
650 message = action.get('message') | 680 message = action.get('message') |
651 if message: | 681 if message: |
652 message = 'echo note: ' + gyp.common.EncodePOSIXShellArgument(message) | 682 message = 'echo note: ' + gyp.common.EncodePOSIXShellArgument(message) |
653 else: | 683 else: |
654 message = '' | 684 message = '' |
(...skipping 15 matching lines...) Expand all Loading... |
670 # exits signalling an error. | 700 # exits signalling an error. |
671 script += 'exec ' + action_string_sh + '\nexit 1\n' | 701 script += 'exec ' + action_string_sh + '\nexit 1\n' |
672 ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ | 702 ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ |
673 'inputPaths': action['inputs'], | 703 'inputPaths': action['inputs'], |
674 'name': 'Action "' + action['action_name'] + '"', | 704 'name': 'Action "' + action['action_name'] + '"', |
675 'outputPaths': action['outputs'], | 705 'outputPaths': action['outputs'], |
676 'shellScript': script, | 706 'shellScript': script, |
677 'showEnvVarsInLog': 0, | 707 'showEnvVarsInLog': 0, |
678 }) | 708 }) |
679 | 709 |
680 # TODO(mark): this assumes too much knowledge of the internals of | 710 if support_xct: |
681 # xcodeproj_file; some of these smarts should move into xcodeproj_file | 711 support_xct.AppendProperty('buildPhases', ssbp) |
682 # itself. | 712 else: |
683 xct._properties['buildPhases'].insert(prebuild_index, ssbp) | 713 # TODO(mark): this assumes too much knowledge of the internals of |
684 prebuild_index = prebuild_index + 1 | 714 # xcodeproj_file; some of these smarts should move into xcodeproj_file |
| 715 # itself. |
| 716 xct._properties['buildPhases'].insert(prebuild_index, ssbp) |
| 717 prebuild_index = prebuild_index + 1 |
685 | 718 |
686 # TODO(mark): Should verify that at most one of these is specified. | 719 # TODO(mark): Should verify that at most one of these is specified. |
687 if int(action.get('process_outputs_as_sources', False)): | 720 if int(action.get('process_outputs_as_sources', False)): |
688 for output in action['outputs']: | 721 for output in action['outputs']: |
689 AddSourceToTarget(output, pbxp, xct) | 722 AddSourceToTarget(output, pbxp, xct) |
690 | 723 |
691 if int(action.get('process_outputs_as_mac_bundle_resources', False)): | 724 if int(action.get('process_outputs_as_mac_bundle_resources', False)): |
692 for output in action['outputs']: | 725 for output in action['outputs']: |
693 AddResourceToTarget(output, pbxp, xct) | 726 AddResourceToTarget(output, pbxp, xct) |
694 | 727 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 # compile. The rule action script would need to touch the dummy. | 760 # compile. The rule action script would need to touch the dummy. |
728 # 6584839 I need a way to declare additional inputs to a custom rule. | 761 # 6584839 I need a way to declare additional inputs to a custom rule. |
729 # A possible workaround is a shell script phase prior to | 762 # A possible workaround is a shell script phase prior to |
730 # compilation that touches a rule's primary input files if any | 763 # compilation that touches a rule's primary input files if any |
731 # would-be additional inputs are newer than the output. Modifying | 764 # would-be additional inputs are newer than the output. Modifying |
732 # the source tree - even just modification times - feels dirty. | 765 # the source tree - even just modification times - feels dirty. |
733 # 6564240 Xcode "custom script" build rules always dump all environment | 766 # 6564240 Xcode "custom script" build rules always dump all environment |
734 # variables. This is a low-prioroty problem and is not a | 767 # variables. This is a low-prioroty problem and is not a |
735 # show-stopper. | 768 # show-stopper. |
736 rules_by_ext = {} | 769 rules_by_ext = {} |
737 for rule in spec.get('rules', []): | 770 for rule in spec_rules: |
738 rules_by_ext[rule['extension']] = rule | 771 rules_by_ext[rule['extension']] = rule |
739 | 772 |
740 # First, some definitions: | 773 # First, some definitions: |
741 # | 774 # |
742 # A "rule source" is a file that was listed in a target's "sources" | 775 # A "rule source" is a file that was listed in a target's "sources" |
743 # list and will have a rule applied to it on the basis of matching the | 776 # list and will have a rule applied to it on the basis of matching the |
744 # rule's "extensions" attribute. Rule sources are direct inputs to | 777 # rule's "extensions" attribute. Rule sources are direct inputs to |
745 # rules. | 778 # rules. |
746 # | 779 # |
747 # Rule definitions may specify additional inputs in their "inputs" | 780 # Rule definitions may specify additional inputs in their "inputs" |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 fi | 978 fi |
946 exec "${DEVELOPER_BIN_DIR}/make" -f "${PROJECT_FILE_PATH}/%s" -j "${JOB_COUNT}" | 979 exec "${DEVELOPER_BIN_DIR}/make" -f "${PROJECT_FILE_PATH}/%s" -j "${JOB_COUNT}" |
947 exit 1 | 980 exit 1 |
948 """ % makefile_name | 981 """ % makefile_name |
949 ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ | 982 ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ |
950 'name': 'Rule "' + rule['rule_name'] + '"', | 983 'name': 'Rule "' + rule['rule_name'] + '"', |
951 'shellScript': script, | 984 'shellScript': script, |
952 'showEnvVarsInLog': 0, | 985 'showEnvVarsInLog': 0, |
953 }) | 986 }) |
954 | 987 |
955 # TODO(mark): this assumes too much knowledge of the internals of | 988 if support_xct: |
956 # xcodeproj_file; some of these smarts should move into xcodeproj_file | 989 support_xct.AppendProperty('buildPhases', ssbp) |
957 # itself. | 990 else: |
958 xct._properties['buildPhases'].insert(prebuild_index, ssbp) | 991 # TODO(mark): this assumes too much knowledge of the internals of |
959 prebuild_index = prebuild_index + 1 | 992 # xcodeproj_file; some of these smarts should move into xcodeproj_file |
| 993 # itself. |
| 994 xct._properties['buildPhases'].insert(prebuild_index, ssbp) |
| 995 prebuild_index = prebuild_index + 1 |
960 | 996 |
961 # Extra rule inputs also go into the project file. Concrete outputs were | 997 # Extra rule inputs also go into the project file. Concrete outputs were |
962 # already added when they were computed. | 998 # already added when they were computed. |
963 for group in ['inputs', 'inputs_excluded']: | 999 for group in ['inputs', 'inputs_excluded']: |
964 for item in rule.get(group, []): | 1000 for item in rule.get(group, []): |
965 pbxp.AddOrGetFileInRootGroup(item) | 1001 pbxp.AddOrGetFileInRootGroup(item) |
966 | 1002 |
967 # Add "sources". | 1003 # Add "sources". |
968 for source in spec.get('sources', []): | 1004 for source in spec.get('sources', []): |
969 (source_root, source_extension) = posixpath.splitext(source) | 1005 (source_root, source_extension) = posixpath.splitext(source) |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 # libraries. On some systems, ld is finicky and even requires the | 1071 # libraries. On some systems, ld is finicky and even requires the |
1036 # libraries to be ordered in such a way that unresolved symbols in | 1072 # libraries to be ordered in such a way that unresolved symbols in |
1037 # earlier-listed libraries may only be resolved by later-listed libraries. | 1073 # earlier-listed libraries may only be resolved by later-listed libraries. |
1038 # The Mac linker doesn't work that way, but other platforms do, and so | 1074 # The Mac linker doesn't work that way, but other platforms do, and so |
1039 # their linker invocations need to be constructed in this way. There's | 1075 # their linker invocations need to be constructed in this way. There's |
1040 # no compelling reason for Xcode's linker invocations to differ. | 1076 # no compelling reason for Xcode's linker invocations to differ. |
1041 | 1077 |
1042 if 'dependencies' in spec: | 1078 if 'dependencies' in spec: |
1043 for dependency in spec['dependencies']: | 1079 for dependency in spec['dependencies']: |
1044 xct.AddDependency(xcode_targets[dependency]) | 1080 xct.AddDependency(xcode_targets[dependency]) |
| 1081 # The support project also gets the dependencies (in case they are |
| 1082 # needed for the actions/rules to work). |
| 1083 if support_xct: |
| 1084 support_xct.AddDependency(xcode_targets[dependency]) |
1045 | 1085 |
1046 if 'libraries' in spec: | 1086 if 'libraries' in spec: |
1047 for library in spec['libraries']: | 1087 for library in spec['libraries']: |
1048 xct.FrameworksPhase().AddFile(library) | 1088 xct.FrameworksPhase().AddFile(library) |
1049 # Add the library's directory to LIBRARY_SEARCH_PATHS if necessary. | 1089 # Add the library's directory to LIBRARY_SEARCH_PATHS if necessary. |
1050 # I wish Xcode handled this automatically. | 1090 # I wish Xcode handled this automatically. |
1051 # TODO(mark): this logic isn't right. There are certain directories | 1091 # TODO(mark): this logic isn't right. There are certain directories |
1052 # that are always searched, we should check to see if the library is | 1092 # that are always searched, we should check to see if the library is |
1053 # in one of those directories, and if not, we should do the | 1093 # in one of those directories, and if not, we should do the |
1054 # AppendBuildSetting thing. | 1094 # AppendBuildSetting thing. |
(...skipping 30 matching lines...) Expand all Loading... |
1085 | 1125 |
1086 for build_file in build_files: | 1126 for build_file in build_files: |
1087 xcode_projects[build_file].Finalize1(xcode_targets, serialize_all_tests) | 1127 xcode_projects[build_file].Finalize1(xcode_targets, serialize_all_tests) |
1088 | 1128 |
1089 for build_file in build_files: | 1129 for build_file in build_files: |
1090 xcode_projects[build_file].Finalize2(xcode_targets, | 1130 xcode_projects[build_file].Finalize2(xcode_targets, |
1091 xcode_target_to_target_dict) | 1131 xcode_target_to_target_dict) |
1092 | 1132 |
1093 for build_file in build_files: | 1133 for build_file in build_files: |
1094 xcode_projects[build_file].Write() | 1134 xcode_projects[build_file].Write() |
OLD | NEW |