Skip to content

Commit 2384044

Browse files
richard-townsend-armtargos
authored andcommitted
tools,gyp: add support for MSVC cross-compilation
This change means that GYP can now generate two sets of projects: one exclusively for a host x64 machine and one containing a mix of x64 and Arm targets. The names of host targets are fixed up to end with _host.exe, and any actions involving them are fixed up. This allows compilation of Node on an x64 server for a Windows on Arm target. PR-URL: #32867 Reviewed-By: Christian Clauss <cclauss@me.com> Reviewed-By: João Reis <reis@janeasystems.com>
1 parent d4e8714 commit 2384044

1 file changed

Lines changed: 81 additions & 38 deletions

File tree

  • tools/gyp/pylib/gyp/generator

‎tools/gyp/pylib/gyp/generator/msvs.py‎

Lines changed: 81 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
# letters.
4141
VALID_MSVS_GUID_CHARS=re.compile(r'^[A-F0-9\-]+$')
4242

43+
generator_supports_multiple_toolsets=gyp.common.CrossCompileRequested()
4344

4445
generator_default_variables= {
4546
'DRIVER_PREFIX': '',
@@ -51,7 +52,7 @@
5152
'STATIC_LIB_SUFFIX': '.lib',
5253
'SHARED_LIB_SUFFIX': '.dll',
5354
'INTERMEDIATE_DIR': '$(IntDir)',
54-
'SHARED_INTERMEDIATE_DIR': '$(OutDir)obj/global_intermediate',
55+
'SHARED_INTERMEDIATE_DIR': '$(OutDir)/obj/global_intermediate',
5556
'OS': 'win',
5657
'PRODUCT_DIR': '$(OutDir)',
5758
'LIB_DIR': '$(OutDir)lib',
@@ -286,7 +287,7 @@ def _ConfigTargetVersion(config_data):
286287
returnconfig_data.get('msvs_target_version', 'Windows7')
287288

288289

289-
def_ConfigPlatform(config_data):
290+
def_ConfigPlatform(config_data, spec):
290291
returnconfig_data.get('msvs_configuration_platform', 'Win32')
291292

292293

@@ -297,8 +298,8 @@ def _ConfigBaseName(config_name, platform_name):
297298
returnconfig_name
298299

299300

300-
def_ConfigFullName(config_name, config_data):
301-
platform_name=_ConfigPlatform(config_data)
301+
def_ConfigFullName(config_name, config_data, spec):
302+
platform_name=_ConfigPlatform(config_data, spec)
302303
return'%s|%s'% (_ConfigBaseName(config_name, platform_name), platform_name)
303304

304305

@@ -951,7 +952,7 @@ def _GetMsbuildToolsetOfProject(proj_path, spec, version):
951952
returntoolset
952953

953954

954-
def_GenerateProject(project, options, version, generator_flags):
955+
def_GenerateProject(project, options, version, generator_flags, spec):
955956
"""Generates a vcproj file.
956957
957958
Arguments:
@@ -969,7 +970,7 @@ def _GenerateProject(project, options, version, generator_flags):
969970
return []
970971

971972
ifversion.UsesVcxproj():
972-
return_GenerateMSBuildProject(project, options, version, generator_flags)
973+
return_GenerateMSBuildProject(project, options, version, generator_flags, spec)
973974
else:
974975
return_GenerateMSVSProject(project, options, version, generator_flags)
975976

@@ -1091,7 +1092,7 @@ def _GetUniquePlatforms(spec):
10911092
# Gather list of unique platforms.
10921093
platforms=OrderedSet()
10931094
forconfigurationinspec['configurations']:
1094-
platforms.add(_ConfigPlatform(spec['configurations'][configuration]))
1095+
platforms.add(_ConfigPlatform(spec['configurations'][configuration], spec))
10951096
platforms=list(platforms)
10961097
returnplatforms
10971098

@@ -1801,6 +1802,8 @@ def _GatherSolutionFolders(sln_projects, project_objects, flat):
18011802
# Convert into a tree of dicts on path.
18021803
forpinsln_projects:
18031804
gyp_file, target=gyp.common.ParseQualifiedTarget(p)[0:2]
1805+
ifp.endswith("#host"):
1806+
target+="_host"
18041807
gyp_dir=os.path.dirname(gyp_file)
18051808
path_dict=_GetPathDict(root, gyp_dir)
18061809
path_dict[target+'.vcproj'] =project_objects[p]
@@ -1819,7 +1822,10 @@ def _GetPathOfProject(qualified_target, spec, options, msvs_version):
18191822
default_config=_GetDefaultConfiguration(spec)
18201823
proj_filename=default_config.get('msvs_existing_vcproj')
18211824
ifnotproj_filename:
1822-
proj_filename= (spec['target_name'] +options.suffix+
1825+
proj_filename=spec['target_name']
1826+
ifspec['toolset'] =='host':
1827+
proj_filename+="_host"
1828+
proj_filename= (proj_filename+options.suffix+
18231829
msvs_version.ProjectExtension())
18241830

18251831
build_file=gyp.common.BuildFile(qualified_target)
@@ -1838,10 +1844,12 @@ def _GetPlatformOverridesOfProject(spec):
18381844
# solution configurations for this target.
18391845
config_platform_overrides= {}
18401846
forconfig_name, cinspec['configurations'].items():
1841-
config_fullname=_ConfigFullName(config_name, c)
1842-
platform=c.get('msvs_target_platform', _ConfigPlatform(c))
1847+
config_fullname=_ConfigFullName(config_name, c, spec)
1848+
platform=c.get('msvs_target_platform', _ConfigPlatform(c, spec))
18431849
fixed_config_fullname='%s|%s'% (
1844-
_ConfigBaseName(config_name, _ConfigPlatform(c)), platform)
1850+
_ConfigBaseName(config_name, _ConfigPlatform(c, spec)), platform)
1851+
ifspec['toolset'] =='host'andgenerator_supports_multiple_toolsets:
1852+
fixed_config_fullname='%s|x64'% (config_name,)
18451853
config_platform_overrides[config_fullname] =fixed_config_fullname
18461854
returnconfig_platform_overrides
18471855

@@ -1862,19 +1870,18 @@ def _CreateProjectObjects(target_list, target_dicts, options, msvs_version):
18621870
projects= {}
18631871
forqualified_targetintarget_list:
18641872
spec=target_dicts[qualified_target]
1865-
ifspec['toolset'] !='target':
1866-
raiseGypError(
1867-
'Multiple toolsets not supported in msvs build (target %s)'%
1868-
qualified_target)
18691873
proj_path, fixpath_prefix=_GetPathOfProject(qualified_target, spec,
18701874
options, msvs_version)
18711875
guid=_GetGuidOfProject(proj_path, spec)
18721876
overrides=_GetPlatformOverridesOfProject(spec)
18731877
build_file=gyp.common.BuildFile(qualified_target)
18741878
# Create object for this project.
1879+
target_name=spec['target_name']
1880+
ifspec['toolset'] =='host':
1881+
target_name+='_host'
18751882
obj=MSVSNew.MSVSProject(
18761883
proj_path,
1877-
name=spec['target_name'],
1884+
name=target_name,
18781885
guid=guid,
18791886
spec=spec,
18801887
build_file=build_file,
@@ -2041,7 +2048,10 @@ def GenerateOutput(target_list, target_dicts, data, params):
20412048
forqualified_targetintarget_list:
20422049
spec=target_dicts[qualified_target]
20432050
forconfig_name, configinspec['configurations'].items():
2044-
configs.add(_ConfigFullName(config_name, config))
2051+
config_name=_ConfigFullName(config_name, config, spec)
2052+
configs.add(config_name)
2053+
ifconfig_name=='Release|arm64':
2054+
configs.add("Release|x64")
20452055
configs=list(configs)
20462056

20472057
# Figure out all the projects that will be generated and their guids
@@ -2053,11 +2063,14 @@ def GenerateOutput(target_list, target_dicts, data, params):
20532063
forprojectinproject_objects.values():
20542064
fixpath_prefix=project.fixpath_prefix
20552065
missing_sources.extend(_GenerateProject(project, options, msvs_version,
2056-
generator_flags))
2066+
generator_flags, spec))
20572067
fixpath_prefix=None
20582068

20592069
forbuild_fileindata:
20602070
# Validate build_file extension
2071+
target_only_configs=configs
2072+
ifgenerator_supports_multiple_toolsets:
2073+
target_only_configs= [iforiinconfigsifi.endswith('arm64')]
20612074
ifnotbuild_file.endswith('.gyp'):
20622075
continue
20632076
sln_path=os.path.splitext(build_file)[0] +options.suffix+'.sln'
@@ -2072,7 +2085,7 @@ def GenerateOutput(target_list, target_dicts, data, params):
20722085
# Create solution.
20732086
sln=MSVSNew.MSVSSolution(sln_path,
20742087
entries=root_entries,
2075-
variants=configs,
2088+
variants=target_only_configs,
20762089
websiteProperties=False,
20772090
version=msvs_version)
20782091
sln.Write()
@@ -2674,21 +2687,23 @@ def _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules):
26742687
easy_xml.WriteXmlIfChanged(content, xml_path, pretty=True, win32=True)
26752688

26762689

2677-
def_GetConfigurationAndPlatform(name, settings):
2690+
def_GetConfigurationAndPlatform(name, settings, spec):
26782691
configuration=name.rsplit('_', 1)[0]
26792692
platform=settings.get('msvs_configuration_platform', 'Win32')
2693+
ifspec['toolset'] =='host'andplatform=='arm64':
2694+
platform='x64'# Host-only tools are always built for x64
26802695
return (configuration, platform)
26812696

26822697

2683-
def_GetConfigurationCondition(name, settings):
2698+
def_GetConfigurationCondition(name, settings, spec):
26842699
return (r"'$(Configuration)|$(Platform)'=='%s|%s'"%
2685-
_GetConfigurationAndPlatform(name, settings))
2700+
_GetConfigurationAndPlatform(name, settings, spec))
26862701

26872702

2688-
def_GetMSBuildProjectConfigurations(configurations):
2703+
def_GetMSBuildProjectConfigurations(configurations, spec):
26892704
group= ['ItemGroup', {'Label': 'ProjectConfigurations'}]
26902705
for (name, settings) insorted(configurations.items()):
2691-
configuration, platform=_GetConfigurationAndPlatform(name, settings)
2706+
configuration, platform=_GetConfigurationAndPlatform(name, settings, spec)
26922707
designation='%s|%s'% (configuration, platform)
26932708
group.append(
26942709
['ProjectConfiguration', {'Include': designation},
@@ -2740,7 +2755,7 @@ def _GetMSBuildGlobalProperties(spec, version, guid, gyp_file_name):
27402755
platform_name=None
27412756
msvs_windows_sdk_version=None
27422757
forconfigurationinspec['configurations'].values():
2743-
platform_name=platform_nameor_ConfigPlatform(configuration)
2758+
platform_name=platform_nameor_ConfigPlatform(configuration, spec)
27442759
msvs_windows_sdk_version= (msvs_windows_sdk_versionor
27452760
_ConfigWindowsTargetPlatformVersion(configuration, version))
27462761
ifplatform_nameandmsvs_windows_sdk_version:
@@ -2762,7 +2777,7 @@ def _GetMSBuildConfigurationDetails(spec, build_file):
27622777
properties= {}
27632778
forname, settingsinspec['configurations'].items():
27642779
msbuild_attributes=_GetMSBuildAttributes(spec, settings, build_file)
2765-
condition=_GetConfigurationCondition(name, settings)
2780+
condition=_GetConfigurationCondition(name, settings, spec)
27662781
character_set=msbuild_attributes.get('CharacterSet')
27672782
config_type=msbuild_attributes.get('ConfigurationType')
27682783
_AddConditionalProperty(properties, condition, 'ConfigurationType',
@@ -2790,12 +2805,12 @@ def _GetMSBuildLocalProperties(msbuild_toolset):
27902805
returnproperties
27912806

27922807

2793-
def_GetMSBuildPropertySheets(configurations):
2808+
def_GetMSBuildPropertySheets(configurations, spec):
27942809
user_props=r'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props'
27952810
additional_props= {}
27962811
props_specified=False
27972812
forname, settingsinsorted(configurations.items()):
2798-
configuration=_GetConfigurationCondition(name, settings)
2813+
configuration=_GetConfigurationCondition(name, settings, spec)
27992814
if'msbuild_props'insettings:
28002815
additional_props[configuration] =_FixPaths(settings['msbuild_props'])
28012816
props_specified=True
@@ -2946,7 +2961,7 @@ def _GetMSBuildConfigurationGlobalProperties(spec, configurations, build_file):
29462961

29472962
properties= {}
29482963
for (name, configuration) insorted(configurations.items()):
2949-
condition=_GetConfigurationCondition(name, configuration)
2964+
condition=_GetConfigurationCondition(name, configuration, spec)
29502965
attributes=_GetMSBuildAttributes(spec, configuration, build_file)
29512966
msbuild_settings=configuration['finalized_msbuild_settings']
29522967
_AddConditionalProperty(properties, condition, 'IntDir',
@@ -3055,7 +3070,9 @@ def _GetMSBuildToolSettingsSections(spec, configurations):
30553070
for (name, configuration) insorted(configurations.items()):
30563071
msbuild_settings=configuration['finalized_msbuild_settings']
30573072
group= ['ItemDefinitionGroup',
3058-
{'Condition': _GetConfigurationCondition(name, configuration)}
3073+
{'Condition':
3074+
_GetConfigurationCondition(name, configuration, spec)
3075+
}
30593076
]
30603077
fortool_name, tool_settingsinsorted(msbuild_settings.items()):
30613078
# Skip the tool named '' which is a holder of global settings handled
@@ -3277,7 +3294,9 @@ def _AddSources2(spec, sources, exclusions, grouped_sources,
32773294
extensions_excluded_from_precompile= ['.c']
32783295

32793296
ifprecompiled_source==source:
3280-
condition=_GetConfigurationCondition(config_name, configuration)
3297+
condition=_GetConfigurationCondition(
3298+
config_name, configuration, spec
3299+
)
32813300
detail.append(['PrecompiledHeader',
32823301
{'Condition': condition},
32833302
'Create'
@@ -3296,12 +3315,26 @@ def _AddSources2(spec, sources, exclusions, grouped_sources,
32963315
_GetUniquePlatforms(spec))
32973316
grouped_sources[group].append([element, {'Include': source}] +detail)
32983317

3299-
3300-
def_GetMSBuildProjectReferences(project):
3318+
def_GetMSBuildProjectReferences(project, spec):
3319+
current_configuration=spec['default_configuration']
33013320
references= []
33023321
ifproject.dependencies:
33033322
group= ['ItemGroup']
3323+
added_dependency_set=set()
33043324
fordependencyinproject.dependencies:
3325+
dependency_spec=dependency.spec
3326+
should_skip_dep=False
3327+
ifproject.spec["toolset"] =='target':
3328+
ifdependency_spec['toolset'] =='host':
3329+
ifdependency_spec['type'] =='static_library':
3330+
should_skip_dep=True
3331+
ifdependency.name.startswith('run_'):
3332+
should_skip_dep=False
3333+
ifshould_skip_dep:
3334+
continue
3335+
3336+
canonical_name=dependency.name.replace('_host', '')
3337+
added_dependency_set.add(canonical_name)
33053338
guid=dependency.guid
33063339
project_dir=os.path.split(project.path)[0]
33073340
relative_path=gyp.common.RelativePath(dependency.path, project_dir)
@@ -3323,7 +3356,7 @@ def _GetMSBuildProjectReferences(project):
33233356
returnreferences
33243357

33253358

3326-
def_GenerateMSBuildProject(project, options, version, generator_flags):
3359+
def_GenerateMSBuildProject(project, options, version, generator_flags, spec):
33273360
spec=project.spec
33283361
configurations=spec['configurations']
33293362
project_dir, project_file_name=os.path.split(project.path)
@@ -3411,7 +3444,7 @@ def _GenerateMSBuildProject(project, options, version, generator_flags):
34113444
'DefaultTargets': 'Build'
34123445
}]
34133446

3414-
content+=_GetMSBuildProjectConfigurations(configurations)
3447+
content+=_GetMSBuildProjectConfigurations(configurations, spec)
34153448
content+=_GetMSBuildGlobalProperties(spec, version, project.guid,
34163449
project_file_name)
34173450
content+=import_default_section
@@ -3422,18 +3455,18 @@ def _GenerateMSBuildProject(project, options, version, generator_flags):
34223455
content+=_GetMSBuildLocalProperties(project.msbuild_toolset)
34233456
content+=import_cpp_props_section
34243457
content+=import_masm_props_section
3425-
ifspec.get('msvs_enable_marmasm'):
3458+
ifspec.get('msvs_enable_marmasm')orTrue:
34263459
content+=import_marmasm_props_section
34273460
content+=_GetMSBuildExtensions(props_files_of_rules)
3428-
content+=_GetMSBuildPropertySheets(configurations)
3461+
content+=_GetMSBuildPropertySheets(configurations, spec)
34293462
content+=macro_section
34303463
content+=_GetMSBuildConfigurationGlobalProperties(spec, configurations,
34313464
project.build_file)
34323465
content+=_GetMSBuildToolSettingsSections(spec, configurations)
34333466
content+=_GetMSBuildSources(
34343467
spec, sources, exclusions, rule_dependencies, extension_to_rule_name,
34353468
actions_spec, sources_handled_by_action, list_excluded)
3436-
content+=_GetMSBuildProjectReferences(project)
3469+
content+=_GetMSBuildProjectReferences(project, spec)
34373470
content+=import_cpp_targets_section
34383471
content+=import_masm_targets_section
34393472
ifspec.get('msvs_enable_marmasm'):
@@ -3516,15 +3549,25 @@ def _GenerateActionsForMSBuild(spec, actions_to_add):
35163549
sources_handled_by_action=OrderedSet()
35173550
actions_spec= []
35183551
forprimary_input, actionsinactions_to_add.items():
3552+
ifgenerator_supports_multiple_toolsets:
3553+
primary_input=primary_input.replace(".exe", "_host.exe")
35193554
inputs=OrderedSet()
35203555
outputs=OrderedSet()
35213556
descriptions= []
35223557
commands= []
35233558
foractioninactions:
3559+
deffixup_host_exe(i):
3560+
if"$(OutDir)"ini:
3561+
i=i.replace('.exe', '_host.exe')
3562+
returni
3563+
ifgenerator_supports_multiple_toolsets:
3564+
action['inputs'] = [fixup_host_exe(i) foriinaction['inputs']]
35243565
inputs.update(OrderedSet(action['inputs']))
35253566
outputs.update(OrderedSet(action['outputs']))
35263567
descriptions.append(action['description'])
35273568
cmd=action['command']
3569+
ifgenerator_supports_multiple_toolsets:
3570+
cmd=cmd.replace('.exe', "_host.exe")
35283571
# For most actions, add 'call' so that actions that invoke batch files
35293572
# return and continue executing. msbuild_use_call provides a way to
35303573
# disable this but I have not seen any adverse effect from doing that

0 commit comments

Comments
 (0)