1414from typing import Generator , List , Optional , Union , cast
1515
1616from misc .utility .color import print_error , print_info , print_warning
17+ from platform_methods import detect_arch
1718
1819# Get the "Godot" folder name ahead of time
1920base_folder = Path (__file__ ).resolve ().parent
@@ -1067,8 +1068,22 @@ def get_dependencies(file, env, exts, headers, sources, others):
10671068 platform = env ["platform" ]
10681069 target = env ["target" ]
10691070 arch = env ["arch" ]
1071+ host_arch = detect_arch ()
1072+
1073+ host_platform = "windows"
1074+ if (
1075+ sys .platform .startswith ("linux" )
1076+ or sys .platform .startswith ("dragonfly" )
1077+ or sys .platform .startswith ("freebsd" )
1078+ or sys .platform .startswith ("netbsd" )
1079+ or sys .platform .startswith ("openbsd" )
1080+ ):
1081+ host_platform = "linuxbsd"
1082+ elif sys .platform == "darwin" :
1083+ host_platform = "macos"
10701084
10711085 vs_configuration = {}
1086+ host_vs_configuration = {}
10721087 common_build_prefix = []
10731088 confs = []
10741089 for x in sorted (glob .glob ("platform/*" )):
@@ -1097,6 +1112,12 @@ def get_dependencies(file, env, exts, headers, sources, others):
10971112 if platform == platform_name :
10981113 common_build_prefix = msvs .get_build_prefix (env )
10991114 vs_configuration = vsconf
1115+ if platform_name == host_platform :
1116+ host_vs_configuration = vsconf
1117+ for a in vsconf ["arches" ]:
1118+ if host_arch == a ["architecture" ]:
1119+ host_arch = a ["platform" ]
1120+ break
11001121 except Exception :
11011122 pass
11021123
@@ -1254,12 +1275,11 @@ def get_dependencies(file, env, exts, headers, sources, others):
12541275 properties .append (
12551276 "<ActiveProjectItemList_%s>;%s;</ActiveProjectItemList_%s>" % (x , ";" .join (itemlist [x ]), x )
12561277 )
1257- output = f "bin\\ godot{ env ['PROGSUFFIX' ]} "
1278+ output = os . path . join ( "bin" , f" godot{ env ['PROGSUFFIX' ]} ")
12581279
12591280 with open ("misc/msvs/props.template" , "r" , encoding = "utf-8" ) as file :
12601281 props_template = file .read ()
12611282
1262- props_template = props_template .replace ("%%VSCONF%%" , vsconf )
12631283 props_template = props_template .replace ("%%CONDITION%%" , condition )
12641284 props_template = props_template .replace ("%%PROPERTIES%%" , "\n " .join (properties ))
12651285 props_template = props_template .replace ("%%EXTRA_ITEMS%%" , "\n " .join (extraItems ))
@@ -1272,6 +1292,7 @@ def get_dependencies(file, env, exts, headers, sources, others):
12721292
12731293 proplist = [str (j ) for j in env ["CPPPATH" ]]
12741294 proplist += [str (j ) for j in env .get ("VSHINT_INCLUDES" , [])]
1295+ proplist += [str (j ) for j in get_default_include_paths (env )]
12751296 props_template = props_template .replace ("%%INCLUDES%%" , ";" .join (proplist ))
12761297
12771298 proplist = env ["CCFLAGS" ]
@@ -1307,17 +1328,17 @@ def get_dependencies(file, env, exts, headers, sources, others):
13071328
13081329 commands = "scons"
13091330 if len (common_build_prefix ) == 0 :
1310- commands = "echo Starting SCons && cmd /V /C " + commands
1331+ commands = "echo Starting SCons & " + commands
13111332 else :
1312- common_build_prefix [0 ] = "echo Starting SCons && cmd /V /C " + common_build_prefix [0 ]
1333+ common_build_prefix [0 ] = "echo Starting SCons & " + common_build_prefix [0 ]
13131334
1314- cmd = " ^& " .join (common_build_prefix + [" " .join ([commands ] + common_build_postfix )])
1335+ cmd = " " .join (common_build_prefix + [" " .join ([commands ] + common_build_postfix )])
13151336 props_template = props_template .replace ("%%BUILD%%" , cmd )
13161337
1317- cmd = " ^& " .join (common_build_prefix + [" " .join ([commands ] + cmd_rebuild )])
1338+ cmd = " " .join (common_build_prefix + [" " .join ([commands ] + cmd_rebuild )])
13181339 props_template = props_template .replace ("%%REBUILD%%" , cmd )
13191340
1320- cmd = " ^& " .join (common_build_prefix + [" " .join ([commands ] + cmd_clean )])
1341+ cmd = " " .join (common_build_prefix + [" " .join ([commands ] + cmd_clean )])
13211342 props_template = props_template .replace ("%%CLEAN%%" , cmd )
13221343
13231344 with open (
@@ -1348,18 +1369,45 @@ def get_dependencies(file, env, exts, headers, sources, others):
13481369 section2 = []
13491370 for conf in confs :
13501371 godot_platform = conf ["platform" ]
1372+ has_editor = "editor" in conf ["targets" ]
1373+
1374+ # Skip any platforms that can build the editor and don't match the host platform.
1375+ #
1376+ # When both Windows and Mac define an editor target, it's defined as platform+target+arch (windows+editor+x64 for example).
1377+ # VS only supports two attributes, a "Configuration" and a "Platform", and we currently map our target to the Configuration
1378+ # (i.e. editor/template_debug/template_release), and our architecture to the "Platform" (i.e. x64, arm64, etc).
1379+ # Those two are not enough to disambiguate multiple godot targets for different godot platforms with the same architecture,
1380+ # i.e. editor|x64 would currently match both windows editor intel 64 and linux editor intel 64.
1381+ #
1382+ # TODO: More work is needed in order to support generating VS projects that unambiguously support all platform+target+arch variations.
1383+ # The VS "Platform" has to be a known architecture that VS recognizes, so we can only play around with the "Configuration" part of the combo.
1384+ if has_editor and godot_platform != host_vs_configuration ["platform" ]:
1385+ continue
1386+
13511387 for p in conf ["arches" ]:
13521388 sln_plat = p ["platform" ]
13531389 proj_plat = sln_plat
13541390 godot_arch = p ["architecture" ]
13551391
1356- # Redirect editor configurations for non-Windows platforms to the Windows one, so the solution has all the permutations
1357- # and VS doesn't complain about missing project configurations.
1392+ # Redirect editor configurations for platforms that don't support the editor target to the default editor target on the
1393+ # active host platform, so the solution has all the permutations and VS doesn't complain about missing project configurations.
13581394 # These configurations are disabled, so they show up but won't build.
1359- if godot_platform != "windows" :
1395+ if not has_editor :
13601396 section1 += [f"editor|{ sln_plat } = editor|{ proj_plat } " ]
1361- section2 += [
1362- f"{{{ proj_uuid } }}.editor|{ proj_plat } .ActiveCfg = editor|{ proj_plat } " ,
1397+ section2 += [f"{{{ proj_uuid } }}.editor|{ proj_plat } .ActiveCfg = editor|{ host_arch } " ]
1398+
1399+ configurations += [
1400+ f'<ProjectConfiguration Include="editor|{ proj_plat } ">' ,
1401+ " <Configuration>editor</Configuration>" ,
1402+ f" <Platform>{ proj_plat } </Platform>" ,
1403+ "</ProjectConfiguration>" ,
1404+ ]
1405+
1406+ properties += [
1407+ f"<PropertyGroup Condition=\" '$(Configuration)|$(Platform)'=='editor|{ proj_plat } '\" >" ,
1408+ " <GodotConfiguration>editor</GodotConfiguration>" ,
1409+ f" <GodotPlatform>{ proj_plat } </GodotPlatform>" ,
1410+ "</PropertyGroup>" ,
13631411 ]
13641412
13651413 for t in conf ["targets" ]:
@@ -1383,21 +1431,6 @@ def get_dependencies(file, env, exts, headers, sources, others):
13831431 "</PropertyGroup>" ,
13841432 ]
13851433
1386- if godot_platform != "windows" :
1387- configurations += [
1388- f'<ProjectConfiguration Include="editor|{ proj_plat } ">' ,
1389- " <Configuration>editor</Configuration>" ,
1390- f" <Platform>{ proj_plat } </Platform>" ,
1391- "</ProjectConfiguration>" ,
1392- ]
1393-
1394- properties += [
1395- f"<PropertyGroup Condition=\" '$(Configuration)|$(Platform)'=='editor|{ proj_plat } '\" >" ,
1396- " <GodotConfiguration>editor</GodotConfiguration>" ,
1397- f" <GodotPlatform>{ proj_plat } </GodotPlatform>" ,
1398- "</PropertyGroup>" ,
1399- ]
1400-
14011434 p = f"{ project_name } .{ godot_platform } .{ godot_target } .{ godot_arch } .generated.props"
14021435 imports += [
14031436 f'<Import Project="$(MSBuildProjectDirectory)\\ { p } " Condition="Exists(\' $(MSBuildProjectDirectory)\\ { p } \' )"/>'
@@ -1606,3 +1639,18 @@ def to_raw_cstring(value: Union[str, List[str]]) -> str:
16061639 else :
16071640 # Wrap multiple segments in parenthesis to suppress `string-concatenation` warnings on clang.
16081641 return "({})" .format (" " .join (f'R"<!>({ segment .decode ()} )<!>"' for segment in split ))
1642+
1643+
1644+ def get_default_include_paths (env ):
1645+ if env .msvc :
1646+ return []
1647+ compiler = env .subst ("$CXX" )
1648+ target = os .path .join (env .Dir ("#main" ).abspath , "main.cpp" )
1649+ args = [compiler , target , "-x" , "c++" , "-v" ]
1650+ ret = subprocess .run (args , stdout = subprocess .PIPE , stderr = subprocess .STDOUT , text = True )
1651+ output = ret .stdout
1652+ match = re .search (r"#include <\.\.\.> search starts here:([\S\s]*)End of search list." , output )
1653+ if not match :
1654+ print_warning ("Failed to find the include paths in the compiler output." )
1655+ return []
1656+ return [x .strip () for x in match [1 ].strip ().splitlines ()]
0 commit comments