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
@@ -1055,8 +1056,22 @@ def get_dependencies(file, env, exts, headers, sources, others):
10551056 platform = env ["platform" ]
10561057 target = env ["target" ]
10571058 arch = env ["arch" ]
1059+ host_arch = detect_arch ()
1060+
1061+ host_platform = "windows"
1062+ if (
1063+ sys .platform .startswith ("linux" )
1064+ or sys .platform .startswith ("dragonfly" )
1065+ or sys .platform .startswith ("freebsd" )
1066+ or sys .platform .startswith ("netbsd" )
1067+ or sys .platform .startswith ("openbsd" )
1068+ ):
1069+ host_platform = "linuxbsd"
1070+ elif sys .platform == "darwin" :
1071+ host_platform = "macos"
10581072
10591073 vs_configuration = {}
1074+ host_vs_configuration = {}
10601075 common_build_prefix = []
10611076 confs = []
10621077 for x in sorted (glob .glob ("platform/*" )):
@@ -1085,6 +1100,12 @@ def get_dependencies(file, env, exts, headers, sources, others):
10851100 if platform == platform_name :
10861101 common_build_prefix = msvs .get_build_prefix (env )
10871102 vs_configuration = vsconf
1103+ if platform_name == host_platform :
1104+ host_vs_configuration = vsconf
1105+ for a in vsconf ["arches" ]:
1106+ if host_arch == a ["architecture" ]:
1107+ host_arch = a ["platform" ]
1108+ break
10881109 except Exception :
10891110 pass
10901111
@@ -1242,12 +1263,11 @@ def get_dependencies(file, env, exts, headers, sources, others):
12421263 properties .append (
12431264 "<ActiveProjectItemList_%s>;%s;</ActiveProjectItemList_%s>" % (x , ";" .join (itemlist [x ]), x )
12441265 )
1245- output = f "bin\\ godot{ env ['PROGSUFFIX' ]} "
1266+ output = os . path . join ( "bin" , f" godot{ env ['PROGSUFFIX' ]} ")
12461267
12471268 with open ("misc/msvs/props.template" , "r" , encoding = "utf-8" ) as file :
12481269 props_template = file .read ()
12491270
1250- props_template = props_template .replace ("%%VSCONF%%" , vsconf )
12511271 props_template = props_template .replace ("%%CONDITION%%" , condition )
12521272 props_template = props_template .replace ("%%PROPERTIES%%" , "\n " .join (properties ))
12531273 props_template = props_template .replace ("%%EXTRA_ITEMS%%" , "\n " .join (extraItems ))
@@ -1260,6 +1280,7 @@ def get_dependencies(file, env, exts, headers, sources, others):
12601280
12611281 proplist = [str (j ) for j in env ["CPPPATH" ]]
12621282 proplist += [str (j ) for j in env .get ("VSHINT_INCLUDES" , [])]
1283+ proplist += [str (j ) for j in get_default_include_paths (env )]
12631284 props_template = props_template .replace ("%%INCLUDES%%" , ";" .join (proplist ))
12641285
12651286 proplist = env ["CCFLAGS" ]
@@ -1295,17 +1316,17 @@ def get_dependencies(file, env, exts, headers, sources, others):
12951316
12961317 commands = "scons"
12971318 if len (common_build_prefix ) == 0 :
1298- commands = "echo Starting SCons && cmd /V /C " + commands
1319+ commands = "echo Starting SCons & " + commands
12991320 else :
1300- common_build_prefix [0 ] = "echo Starting SCons && cmd /V /C " + common_build_prefix [0 ]
1321+ common_build_prefix [0 ] = "echo Starting SCons & " + common_build_prefix [0 ]
13011322
1302- cmd = " ^& " .join (common_build_prefix + [" " .join ([commands ] + common_build_postfix )])
1323+ cmd = " " .join (common_build_prefix + [" " .join ([commands ] + common_build_postfix )])
13031324 props_template = props_template .replace ("%%BUILD%%" , cmd )
13041325
1305- cmd = " ^& " .join (common_build_prefix + [" " .join ([commands ] + cmd_rebuild )])
1326+ cmd = " " .join (common_build_prefix + [" " .join ([commands ] + cmd_rebuild )])
13061327 props_template = props_template .replace ("%%REBUILD%%" , cmd )
13071328
1308- cmd = " ^& " .join (common_build_prefix + [" " .join ([commands ] + cmd_clean )])
1329+ cmd = " " .join (common_build_prefix + [" " .join ([commands ] + cmd_clean )])
13091330 props_template = props_template .replace ("%%CLEAN%%" , cmd )
13101331
13111332 with open (
@@ -1336,18 +1357,45 @@ def get_dependencies(file, env, exts, headers, sources, others):
13361357 section2 = []
13371358 for conf in confs :
13381359 godot_platform = conf ["platform" ]
1360+ has_editor = "editor" in conf ["targets" ]
1361+
1362+ # Skip any platforms that can build the editor and don't match the host platform.
1363+ #
1364+ # When both Windows and Mac define an editor target, it's defined as platform+target+arch (windows+editor+x64 for example).
1365+ # VS only supports two attributes, a "Configuration" and a "Platform", and we currently map our target to the Configuration
1366+ # (i.e. editor/template_debug/template_release), and our architecture to the "Platform" (i.e. x64, arm64, etc).
1367+ # Those two are not enough to disambiguate multiple godot targets for different godot platforms with the same architecture,
1368+ # i.e. editor|x64 would currently match both windows editor intel 64 and linux editor intel 64.
1369+ #
1370+ # TODO: More work is needed in order to support generating VS projects that unambiguously support all platform+target+arch variations.
1371+ # 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.
1372+ if has_editor and godot_platform != host_vs_configuration ["platform" ]:
1373+ continue
1374+
13391375 for p in conf ["arches" ]:
13401376 sln_plat = p ["platform" ]
13411377 proj_plat = sln_plat
13421378 godot_arch = p ["architecture" ]
13431379
1344- # Redirect editor configurations for non-Windows platforms to the Windows one, so the solution has all the permutations
1345- # and VS doesn't complain about missing project configurations.
1380+ # Redirect editor configurations for platforms that don't support the editor target to the default editor target on the
1381+ # active host platform, so the solution has all the permutations and VS doesn't complain about missing project configurations.
13461382 # These configurations are disabled, so they show up but won't build.
1347- if godot_platform != "windows" :
1383+ if not has_editor :
13481384 section1 += [f"editor|{ sln_plat } = editor|{ proj_plat } " ]
1349- section2 += [
1350- f"{{{ proj_uuid } }}.editor|{ proj_plat } .ActiveCfg = editor|{ proj_plat } " ,
1385+ section2 += [f"{{{ proj_uuid } }}.editor|{ proj_plat } .ActiveCfg = editor|{ host_arch } " ]
1386+
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>" ,
13511399 ]
13521400
13531401 for t in conf ["targets" ]:
@@ -1371,21 +1419,6 @@ def get_dependencies(file, env, exts, headers, sources, others):
13711419 "</PropertyGroup>" ,
13721420 ]
13731421
1374- if godot_platform != "windows" :
1375- configurations += [
1376- f'<ProjectConfiguration Include="editor|{ proj_plat } ">' ,
1377- " <Configuration>editor</Configuration>" ,
1378- f" <Platform>{ proj_plat } </Platform>" ,
1379- "</ProjectConfiguration>" ,
1380- ]
1381-
1382- properties += [
1383- f"<PropertyGroup Condition=\" '$(Configuration)|$(Platform)'=='editor|{ proj_plat } '\" >" ,
1384- " <GodotConfiguration>editor</GodotConfiguration>" ,
1385- f" <GodotPlatform>{ proj_plat } </GodotPlatform>" ,
1386- "</PropertyGroup>" ,
1387- ]
1388-
13891422 p = f"{ project_name } .{ godot_platform } .{ godot_target } .{ godot_arch } .generated.props"
13901423 imports += [
13911424 f'<Import Project="$(MSBuildProjectDirectory)\\ { p } " Condition="Exists(\' $(MSBuildProjectDirectory)\\ { p } \' )"/>'
@@ -1594,3 +1627,18 @@ def to_raw_cstring(value: Union[str, List[str]]) -> str:
15941627 else :
15951628 # Wrap multiple segments in parenthesis to suppress `string-concatenation` warnings on clang.
15961629 return "({})" .format (" " .join (f'R"<!>({ segment .decode ()} )<!>"' for segment in split ))
1630+
1631+
1632+ def get_default_include_paths (env ):
1633+ if env .msvc :
1634+ return []
1635+ compiler = env .subst ("$CXX" )
1636+ target = os .path .join (env .Dir ("#main" ).abspath , "main.cpp" )
1637+ args = [compiler , target , "-x" , "c++" , "-v" ]
1638+ ret = subprocess .run (args , stdout = subprocess .PIPE , stderr = subprocess .STDOUT , text = True )
1639+ output = ret .stdout
1640+ match = re .search (r"#include <\.\.\.> search starts here:([\S\s]*)End of search list." , output )
1641+ if not match :
1642+ print_warning ("Failed to find the include paths in the compiler output." )
1643+ return []
1644+ return [x .strip () for x in match [1 ].strip ().splitlines ()]
0 commit comments