Index: pylib/gyp/generator/xcode.py |
=================================================================== |
--- pylib/gyp/generator/xcode.py (revision 761) |
+++ pylib/gyp/generator/xcode.py (working copy) |
@@ -74,6 +74,17 @@ |
'mac_bundle_resources', |
] |
+ |
+def CreateXCConfigurationList(configuration_names): |
+ xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) |
+ for configuration_name in configuration_names: |
+ xcbc = gyp.xcodeproj_file.XCBuildConfiguration({ |
+ 'name': configuration_name}) |
+ xccl.AppendProperty('buildConfigurations', xcbc) |
+ xccl.SetProperty('defaultConfigurationName', configuration_names[0]) |
+ return xccl |
+ |
+ |
class XcodeProject(object): |
def __init__(self, gyp_path, path, build_file_dict): |
self.gyp_path = gyp_path |
@@ -116,11 +127,7 @@ |
# a new one specifying all of the configuration names used by the various |
# targets. |
try: |
- xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) |
- for configuration in configurations: |
- xcbc = gyp.xcodeproj_file.XCBuildConfiguration({'name': configuration}) |
- xccl.AppendProperty('buildConfigurations', xcbc) |
- xccl.SetProperty('defaultConfigurationName', configurations[0]) |
+ xccl = CreateXCConfigurationList(configurations) |
self.project.SetProperty('buildConfigurationList', xccl) |
except: |
import sys |
@@ -160,9 +167,11 @@ |
# ordinary_targets are ordinary targets that are already in the project |
# file. run_test_targets are the targets that run unittests and should be |
- # used for the Run All Tests target. |
+ # used for the Run All Tests target. support_targets are the action/rule |
+ # targets used by GYP file targets, just kept for the assert check. |
ordinary_targets = [] |
run_test_targets = [] |
+ support_targets = [] |
# targets is full list of targets in the project. |
targets = [] |
@@ -186,6 +195,9 @@ |
assert xcode_target in self.project._properties['targets'] |
targets.append(xcode_target) |
ordinary_targets.append(xcode_target) |
+ if xcode_target.support_target: |
+ support_targets.append(xcode_target.support_target) |
+ targets.append(xcode_target.support_target) |
if not int(target.get('suppress_wildcard', False)): |
targets_for_all.append(xcode_target) |
@@ -200,9 +212,11 @@ |
if target.get('run_as') or is_test: |
# Make a target to run something. It should have one |
# dependency, the parent xcode target. |
+ xccl = CreateXCConfigurationList(configurations) |
run_target = gyp.xcodeproj_file.PBXAggregateTarget({ |
- 'name': 'Run ' + target_name, |
- 'productName': xcode_target.GetProperty('productName'), |
+ 'name': 'Run ' + target_name, |
+ 'productName': xcode_target.GetProperty('productName'), |
+ 'buildConfigurationList': xccl, |
}, |
parent=self.project) |
run_target.AddDependency(xcode_target) |
@@ -263,7 +277,8 @@ |
# Make sure that the list of targets being replaced is the same length as |
# the one replacing it, but allow for the added test runner targets. |
- assert len(self.project._properties['targets']) == len(ordinary_targets) |
+ assert len(self.project._properties['targets']) == \ |
+ len(ordinary_targets) + len(support_targets) |
self.project._properties['targets'] = targets |
@@ -279,12 +294,7 @@ |
# "All" target first so that people opening up the project for the first |
# time will build everything by default. |
if len(targets_for_all) > 1 and not has_custom_all: |
- xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) |
- for configuration in configurations: |
- xcbc = gyp.xcodeproj_file.XCBuildConfiguration({'name': configuration}) |
- xccl.AppendProperty('buildConfigurations', xcbc) |
- xccl.SetProperty('defaultConfigurationName', configurations[0]) |
- |
+ xccl = CreateXCConfigurationList(configurations) |
all_target = gyp.xcodeproj_file.PBXAggregateTarget( |
{ |
'buildConfigurationList': xccl, |
@@ -302,11 +312,7 @@ |
# The same, but for run_test_targets. |
if len(run_test_targets) > 1: |
- xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) |
- for configuration in configurations: |
- xcbc = gyp.xcodeproj_file.XCBuildConfiguration({'name': configuration}) |
- xccl.AppendProperty('buildConfigurations', xcbc) |
- xccl.SetProperty('defaultConfigurationName', configurations[0]) |
+ xccl = CreateXCConfigurationList(configurations) |
run_all_tests_target = gyp.xcodeproj_file.PBXAggregateTarget( |
{ |
'buildConfigurationList': xccl, |
@@ -581,12 +587,7 @@ |
# Set up the configurations for the target according to the list of names |
# supplied. |
- xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) |
- for configuration_name in configuration_names: |
- xcbc = gyp.xcodeproj_file.XCBuildConfiguration({ |
- 'name': configuration_name}) |
- xccl.AppendProperty('buildConfigurations', xcbc) |
- xccl.SetProperty('defaultConfigurationName', configuration_names[0]) |
+ xccl = CreateXCConfigurationList(configuration_names) |
# Create an XCTarget subclass object for the target. We use the type |
# with "+bundle" appended if the target has "mac_bundle" set. |
@@ -621,8 +622,9 @@ |
else: |
xctarget_type = gyp.xcodeproj_file.PBXAggregateTarget |
- if 'product_name' in spec: |
- target_properties['productName'] = spec['product_name'] |
+ target_product_name = spec.get('product_name', None) |
+ if target_product_name: |
+ target_properties['productName'] = target_product_name |
xct = xctarget_type(target_properties, parent=pbxp, |
force_extension=spec.get('product_extension', None)) |
@@ -638,10 +640,38 @@ |
if type == 'loadable_module' and not is_bundle: |
xccl.SetBuildSetting('MACH_O_TYPE', 'mh_bundle') |
+ spec_actions = spec.get('actions', []) |
+ spec_rules = spec.get('rules', []) |
+ |
+ # Xcode has some "issues" with checking dependencies for the "Compile |
+ # sources" step with any source files/headers generated by actions/rules. |
+ # To work around this, if a target is building anything directly (not |
+ # type "none"), then a second target as used to run the GYP actions/rules |
+ # and is made a dependency of this target. This way the work is done |
+ # before the dependency checks for what should be recompiled. |
+ support_xct = None |
+ if type != 'none' and (spec_actions or spec_rules): |
+ support_xccl = CreateXCConfigurationList(configuration_names); |
+ support_target_properties = { |
+ 'buildConfigurationList': support_xccl, |
+ 'name': target_name + ' Support', |
+ } |
+ if target_product_name: |
+ support_target_properties['productName'] = \ |
+ target_product_name + ' Support' |
+ support_xct = \ |
+ gyp.xcodeproj_file.PBXAggregateTarget(support_target_properties, |
+ parent=pbxp) |
+ pbxp.AppendProperty('targets', support_xct) |
+ xct.AddDependency(support_xct) |
+ # Hang the support target off the main target so it can be tested/found |
+ # by the generator during Finalize. |
+ xct.support_target = support_xct |
+ |
prebuild_index = 0 |
# Add custom shell script phases for "actions" sections. |
- for action in spec.get('actions', []): |
+ for action in spec_actions: |
# There's no need to write anything into the script to ensure that the |
# output directories already exist, because Xcode will look at the |
# declared outputs and automatically ensure that they exist for us. |
@@ -677,11 +707,14 @@ |
'showEnvVarsInLog': 0, |
}) |
- # TODO(mark): this assumes too much knowledge of the internals of |
- # xcodeproj_file; some of these smarts should move into xcodeproj_file |
- # itself. |
- xct._properties['buildPhases'].insert(prebuild_index, ssbp) |
- prebuild_index = prebuild_index + 1 |
+ if support_xct: |
+ support_xct.AppendProperty('buildPhases', ssbp) |
+ else: |
+ # TODO(mark): this assumes too much knowledge of the internals of |
+ # xcodeproj_file; some of these smarts should move into xcodeproj_file |
+ # itself. |
+ xct._properties['buildPhases'].insert(prebuild_index, ssbp) |
+ prebuild_index = prebuild_index + 1 |
# TODO(mark): Should verify that at most one of these is specified. |
if int(action.get('process_outputs_as_sources', False)): |
@@ -734,7 +767,7 @@ |
# variables. This is a low-prioroty problem and is not a |
# show-stopper. |
rules_by_ext = {} |
- for rule in spec.get('rules', []): |
+ for rule in spec_rules: |
rules_by_ext[rule['extension']] = rule |
# First, some definitions: |
@@ -952,11 +985,14 @@ |
'showEnvVarsInLog': 0, |
}) |
- # TODO(mark): this assumes too much knowledge of the internals of |
- # xcodeproj_file; some of these smarts should move into xcodeproj_file |
- # itself. |
- xct._properties['buildPhases'].insert(prebuild_index, ssbp) |
- prebuild_index = prebuild_index + 1 |
+ if support_xct: |
+ support_xct.AppendProperty('buildPhases', ssbp) |
+ else: |
+ # TODO(mark): this assumes too much knowledge of the internals of |
+ # xcodeproj_file; some of these smarts should move into xcodeproj_file |
+ # itself. |
+ xct._properties['buildPhases'].insert(prebuild_index, ssbp) |
+ prebuild_index = prebuild_index + 1 |
# Extra rule inputs also go into the project file. Concrete outputs were |
# already added when they were computed. |
@@ -1042,6 +1078,10 @@ |
if 'dependencies' in spec: |
for dependency in spec['dependencies']: |
xct.AddDependency(xcode_targets[dependency]) |
+ # The support project also gets the dependencies (in case they are |
+ # needed for the actions/rules to work). |
+ if support_xct: |
+ support_xct.AddDependency(xcode_targets[dependency]) |
if 'libraries' in spec: |
for library in spec['libraries']: |