Index: pylib/gyp/generator/msvs.py |
diff --git a/pylib/gyp/generator/msvs.py b/pylib/gyp/generator/msvs.py |
index 51acf2eb3e8e00901a58ba8dfef436660aa622a7..2b2af3f7a0b473f3b5100045800cf1b93feecf15 100644 |
--- a/pylib/gyp/generator/msvs.py |
+++ b/pylib/gyp/generator/msvs.py |
@@ -66,6 +66,10 @@ generator_additional_non_configuration_keys = [ |
'msvs_cygwin_shell', |
'msvs_large_pdb', |
'msvs_shard', |
+ 'msvs_external_builder', |
+ 'msvs_external_builder_out_dir', |
+ 'msvs_external_builder_build_cmd', |
+ 'msvs_external_builder_clean_cmd', |
] |
@@ -1695,14 +1699,58 @@ def _CreateProjectObjects(target_list, target_dicts, options, msvs_version): |
obj.set_msbuild_toolset( |
_GetMsbuildToolsetOfProject(proj_path, spec, msvs_version)) |
projects[qualified_target] = obj |
- # Set all the dependencies |
+ # Set all the dependencies, but not if we are using an external builder like |
+ # ninja |
for project in projects.values(): |
- deps = project.spec.get('dependencies', []) |
- deps = [projects[d] for d in deps] |
- project.set_dependencies(deps) |
+ if not project.spec.get('msvs_external_builder'): |
+ deps = project.spec.get('dependencies', []) |
+ deps = [projects[d] for d in deps] |
+ project.set_dependencies(deps) |
return projects |
+def _InitNinjaFlavor(options, target_list, target_dicts): |
+ """Initialize targets for the ninja flavor. |
+ |
+ This sets up the necessary variables in the targets to generate msvs projects |
+ that use ninja as an external builder. The variables in the spec are only set |
+ if they have not been set. This allows individual specs to override the |
+ default values initialized here. |
+ Arguments: |
+ options: Options provided to the generator. |
+ target_list: List of target pairs: 'base/base.gyp:base'. |
+ target_dicts: Dict of target properties keyed on target pair. |
+ """ |
+ for qualified_target in target_list: |
+ spec = target_dicts[qualified_target] |
+ if spec.get('msvs_external_builder'): |
+ # The spec explicitly defined an external builder, so don't change it. |
+ continue |
+ |
+ path_to_ninja = spec.get('msvs_path_to_ninja', 'ninja.exe') |
+ |
+ spec['msvs_external_builder'] = 'ninja' |
+ if not spec.get('msvs_external_builder_out_dir'): |
+ spec['msvs_external_builder_out_dir'] = \ |
+ options.depth + '/out/$(Configuration)' |
+ if not spec.get('msvs_external_builder_build_cmd'): |
+ spec['msvs_external_builder_build_cmd'] = [ |
+ path_to_ninja, |
+ '-C', |
+ '$(OutDir)', |
+ '$(ProjectName)', |
+ ] |
+ if not spec.get('msvs_external_builder_clean_cmd'): |
+ spec['msvs_external_builder_clean_cmd'] = [ |
+ path_to_ninja, |
+ '-C', |
+ '$(OutDir)', |
+ '-t', |
+ 'clean', |
+ '$(ProjectName)', |
+ ] |
+ |
+ |
def CalculateVariables(default_variables, params): |
"""Generated variables that require params to be known.""" |
@@ -1774,6 +1822,10 @@ def GenerateOutput(target_list, target_dicts, data, params): |
(target_list, target_dicts) = MSVSUtil.InsertLargePdbShims( |
target_list, target_dicts, generator_default_variables) |
+ # Optionally configure each spec to use ninja as the external builder. |
+ if params.get('flavor') == 'ninja': |
+ _InitNinjaFlavor(options, target_list, target_dicts) |
+ |
# Prepare the set of configurations. |
configs = set() |
for qualified_target in target_list: |
@@ -2560,6 +2612,10 @@ def _GetMSBuildAttributes(spec, config, build_file): |
target_name = prefix + product_name |
msbuild_attributes['TargetName'] = target_name |
+ if spec.get('msvs_external_builder'): |
+ external_out_dir = spec.get('msvs_external_builder_out_dir', '.') |
+ msbuild_attributes['OutputDirectory'] = _FixPath(external_out_dir) + '\\' |
+ |
# Make sure that 'TargetPath' matches 'Lib.OutputFile' or 'Link.OutputFile' |
# (depending on the tool used) to avoid MSB8012 warning. |
msbuild_tool_map = { |
@@ -2958,22 +3014,29 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): |
targets_files_of_rules = set() |
extension_to_rule_name = {} |
list_excluded = generator_flags.get('msvs_list_excluded_files', True) |
- _GenerateRulesForMSBuild(project_dir, options, spec, |
- sources, excluded_sources, |
- props_files_of_rules, targets_files_of_rules, |
- actions_to_add, extension_to_rule_name) |
+ |
+ # Don't generate rules if we are using an external builder like ninja. |
+ if not spec.get('msvs_external_builder'): |
+ _GenerateRulesForMSBuild(project_dir, options, spec, |
+ sources, excluded_sources, |
+ props_files_of_rules, targets_files_of_rules, |
+ actions_to_add, extension_to_rule_name) |
+ |
sources, excluded_sources, excluded_idl = ( |
_AdjustSourcesAndConvertToFilterHierarchy(spec, options, |
project_dir, sources, |
excluded_sources, |
list_excluded)) |
- _AddActions(actions_to_add, spec, project.build_file) |
- _AddCopies(actions_to_add, spec) |
- # NOTE: this stanza must appear after all actions have been decided. |
- # Don't excluded sources with actions attached, or they won't run. |
- excluded_sources = _FilterActionsFromExcluded( |
- excluded_sources, actions_to_add) |
+ # Don't add actions if we are using an external builder like ninja. |
+ if not spec.get('msvs_external_builder'): |
+ _AddActions(actions_to_add, spec, project.build_file) |
+ _AddCopies(actions_to_add, spec) |
+ |
+ # NOTE: this stanza must appear after all actions have been decided. |
+ # Don't excluded sources with actions attached, or they won't run. |
+ excluded_sources = _FilterActionsFromExcluded( |
+ excluded_sources, actions_to_add) |
exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl) |
actions_spec, sources_handled_by_action = _GenerateActionsForMSBuild( |
@@ -3022,6 +3085,9 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): |
content += import_cpp_targets_section |
content += _GetMSBuildExtensionTargets(targets_files_of_rules) |
+ if spec.get('msvs_external_builder'): |
+ content += _GetMSBuildExternalBuilderTargets(spec) |
+ |
# TODO(jeanluc) File a bug to get rid of runas. We had in MSVS: |
# has_run_as = _WriteMSVSUserFile(project.path, version, spec) |
@@ -3030,6 +3096,31 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): |
return missing_sources |
+def _GetMSBuildExternalBuilderTargets(spec): |
+ """Return a list of MSBuild targets for external builders. |
+ |
+ Right now, only "Build" and "Clean" targets are generated. |
+ |
+ Arguments: |
+ spec: The gyp target spec. |
+ Returns: |
+ List of MSBuild 'Target' specs. |
+ """ |
+ build_cmd = _BuildCommandLineForRuleRaw( |
+ spec, spec['msvs_external_builder_build_cmd'], |
+ False, False, False, False) |
+ build_target = ['Target', {'Name': 'Build'}] |
+ build_target.append(['Exec', {'Command': build_cmd}]) |
+ |
+ clean_cmd = _BuildCommandLineForRuleRaw( |
+ spec, spec['msvs_external_builder_clean_cmd'], |
+ False, False, False, False) |
+ clean_target = ['Target', {'Name': 'Clean'}] |
+ clean_target.append(['Exec', {'Command': clean_cmd}]) |
+ |
+ return [build_target, clean_target] |
+ |
+ |
def _GetMSBuildExtensions(props_files_of_rules): |
extensions = ['ImportGroup', {'Label': 'ExtensionSettings'}] |
for props_file in props_files_of_rules: |