@ -774,161 +774,6 @@ def add_to_vs_project(env, sources):
env . vs_srcs + = [ basename + " .cpp " ]
def generate_vs_project ( env , original_args , project_name = " godot " ) :
batch_file = find_visual_c_batch_file ( env )
filtered_args = original_args . copy ( )
# Ignore the "vsproj" option to not regenerate the VS project on every build
filtered_args . pop ( " vsproj " , None )
# The "platform" option is ignored because only the Windows platform is currently supported for VS projects
filtered_args . pop ( " platform " , None )
# The "target" option is ignored due to the way how targets configuration is performed for VS projects (there is a separate project configuration for each target)
filtered_args . pop ( " target " , None )
# The "progress" option is ignored as the current compilation progress indication doesn't work in VS
filtered_args . pop ( " progress " , None )
if batch_file :
class ModuleConfigs ( Mapping ) :
# This version information (Win32, x64, Debug, Release) seems to be
# required for Visual Studio to understand that it needs to generate an NMAKE
# project. Do not modify without knowing what you are doing.
PLATFORMS = [ " Win32 " , " x64 " ]
PLATFORM_IDS = [ " x86_32 " , " x86_64 " ]
CONFIGURATIONS = [ " editor " , " template_release " , " template_debug " ]
DEV_SUFFIX = " .dev " if env [ " dev_build " ] else " "
@staticmethod
def for_every_variant ( value ) :
return [ value for _ in range ( len ( ModuleConfigs . CONFIGURATIONS ) * len ( ModuleConfigs . PLATFORMS ) ) ]
def __init__ ( self ) :
shared_targets_array = [ ]
self . names = [ ]
self . arg_dict = {
" variant " : [ ] ,
" runfile " : shared_targets_array ,
" buildtarget " : shared_targets_array ,
" cpppaths " : [ ] ,
" cppdefines " : [ ] ,
" cmdargs " : [ ] ,
}
self . add_mode ( ) # default
def add_mode (
self ,
name : str = " " ,
includes : str = " " ,
cli_args : str = " " ,
defines = None ,
) :
if defines is None :
defines = [ ]
self . names . append ( name )
self . arg_dict [ " variant " ] + = [
f ' { config } { f " _[ { name } ] " if name else " " } | { platform } '
for config in ModuleConfigs . CONFIGURATIONS
for platform in ModuleConfigs . PLATFORMS
]
self . arg_dict [ " runfile " ] + = [
f ' bin \\ godot.windows. { config } { ModuleConfigs . DEV_SUFFIX } { " .double " if env [ " precision " ] == " double " else " " } . { plat_id } { f " . { name } " if name else " " } .exe '
for config in ModuleConfigs . CONFIGURATIONS
for plat_id in ModuleConfigs . PLATFORM_IDS
]
self . arg_dict [ " cpppaths " ] + = ModuleConfigs . for_every_variant ( env [ " CPPPATH " ] + [ includes ] )
self . arg_dict [ " cppdefines " ] + = ModuleConfigs . for_every_variant ( list ( env [ " CPPDEFINES " ] ) + defines )
self . arg_dict [ " cmdargs " ] + = ModuleConfigs . for_every_variant ( cli_args )
def build_commandline ( self , commands ) :
configuration_getter = (
" $(Configuration "
+ " " . join ( [ f ' .Replace( " { name } " , " " ) ' for name in self . names [ 1 : ] ] )
+ ' .Replace( " _[] " , " " ) '
+ " ) "
)
common_build_prefix = [
' cmd /V /C set " plat=$(PlatformTarget) " ' ,
' (if " $(PlatformTarget) " == " x64 " (set " plat=x86_amd64 " )) ' ,
' call " ' + batch_file + ' " !plat! ' ,
]
# Windows allows us to have spaces in paths, so we need
# to double quote off the directory. However, the path ends
# in a backslash, so we need to remove this, lest it escape the
# last double quote off, confusing MSBuild
common_build_postfix = [
" --directory= \" $(ProjectDir.TrimEnd( ' \\ ' )) \" " ,
" platform=windows " ,
f " target= { configuration_getter } " ,
" progress=no " ,
]
for arg , value in filtered_args . items ( ) :
common_build_postfix . append ( f " { arg } = { value } " )
result = " ^& " . join ( common_build_prefix + [ " " . join ( [ commands ] + common_build_postfix ) ] )
return result
# Mappings interface definitions
def __iter__ ( self ) - > Iterator [ str ] :
for x in self . arg_dict :
yield x
def __len__ ( self ) - > int :
return len ( self . names )
def __getitem__ ( self , k : str ) :
return self . arg_dict [ k ]
add_to_vs_project ( env , env . core_sources )
add_to_vs_project ( env , env . drivers_sources )
add_to_vs_project ( env , env . main_sources )
add_to_vs_project ( env , env . modules_sources )
add_to_vs_project ( env , env . scene_sources )
add_to_vs_project ( env , env . servers_sources )
if env [ " tests " ] :
add_to_vs_project ( env , env . tests_sources )
if env . editor_build :
add_to_vs_project ( env , env . editor_sources )
for header in glob_recursive ( " **/*.h " ) :
env . vs_incs . append ( str ( header ) )
module_configs = ModuleConfigs ( )
if env . get ( " module_mono_enabled " ) :
mono_defines = [ ( " GD_MONO_HOT_RELOAD " , ) ] if env . editor_build else [ ]
module_configs . add_mode (
" mono " ,
cli_args = " module_mono_enabled=yes " ,
defines = mono_defines ,
)
scons_cmd = " scons "
path_to_venv = os . getenv ( " VIRTUAL_ENV " )
path_to_scons_exe = Path ( str ( path_to_venv ) ) / " Scripts " / " scons.exe "
if path_to_venv and path_to_scons_exe . exists ( ) :
scons_cmd = str ( path_to_scons_exe )
env [ " MSVSBUILDCOM " ] = module_configs . build_commandline ( scons_cmd )
env [ " MSVSREBUILDCOM " ] = module_configs . build_commandline ( f " { scons_cmd } vsproj=yes " )
env [ " MSVSCLEANCOM " ] = module_configs . build_commandline ( f " { scons_cmd } --clean " )
if not env . get ( " MSVS " ) :
env [ " MSVS " ] [ " PROJECTSUFFIX " ] = " .vcxproj "
env [ " MSVS " ] [ " SOLUTIONSUFFIX " ] = " .sln "
env . MSVSProject (
target = [ " # " + project_name + env [ " MSVSPROJECTSUFFIX " ] ] ,
incs = env . vs_incs ,
srcs = env . vs_srcs ,
auto_build_solution = 1 ,
* * module_configs ,
)
else :
print ( " Could not locate Visual Studio batch file to set up the build environment. Not generating VS project. " )
def precious_program ( env , program , sources , * * args ) :
program = env . ProgramOriginal ( program , sources , * * args )
env . Precious ( program )
@ -1229,3 +1074,456 @@ def dump(env):
with open ( " .scons_env.json " , " w " ) as f :
dump ( env . Dictionary ( ) , f , indent = 4 , default = non_serializable )
# Custom Visual Studio project generation logic that supports any platform that has a msvs.py
# script, so Visual Studio can be used to run scons for any platform, with the right defines per target.
# Invoked with scons vsproj=yes
#
# Only platforms that opt in to vs proj generation by having a msvs.py file in the platform folder are included.
# Platforms with a msvs.py file will be added to the solution, but only the current active platform+target+arch
# will have a build configuration generated, because we only know what the right defines/includes/flags/etc are
# on the active build target.
#
# Platforms that don't support an editor target will have a dummy editor target that won't do anything on build,
# but will have the files and configuration for the windows editor target.
#
# To generate build configuration files for all platforms+targets+arch combinations, users can call
# scons vsproj=yes
# for each combination of platform+target+arch. This will generate the relevant vs project files but
# skip the build process. This lets project files be quickly generated even if there are build errors.
#
# To generate AND build from the command line:
# scons vsproj=yes vsproj_gen_only=yes
def generate_vs_project ( env , original_args , project_name = " godot " ) :
# Augmented glob_recursive that also fills the dirs argument with traversed directories that have content.
def glob_recursive_2 ( pattern , dirs , node = " . " ) :
from SCons import Node
from SCons . Script import Glob
results = [ ]
for f in Glob ( str ( node ) + " /* " , source = True ) :
if type ( f ) is Node . FS . Dir :
results + = glob_recursive_2 ( pattern , dirs , f )
r = Glob ( str ( node ) + " / " + pattern , source = True )
if len ( r ) > 0 and not str ( node ) in dirs :
d = " "
for part in str ( node ) . split ( " \\ " ) :
d + = part
if not d in dirs :
dirs . append ( d )
d + = " \\ "
results + = r
return results
def get_bool ( args , option , default ) :
from SCons . Variables . BoolVariable import _text2bool
val = args . get ( option , default )
if val is not None :
try :
return _text2bool ( val )
except :
return default
else :
return default
def format_key_value ( v ) :
if type ( v ) in [ tuple , list ] :
return v [ 0 ] if len ( v ) == 1 else f " { v [ 0 ] } = { v [ 1 ] } "
return v
filtered_args = original_args . copy ( )
# Ignore the "vsproj" option to not regenerate the VS project on every build
filtered_args . pop ( " vsproj " , None )
# This flag allows users to regenerate the proj files but skip the building process.
# This lets projects be regenerated even if there are build errors.
filtered_args . pop ( " vsproj_gen_only " , None )
# The "progress" option is ignored as the current compilation progress indication doesn't work in VS
filtered_args . pop ( " progress " , None )
# We add these three manually because they might not be explicitly passed in, and it's important to always set them.
filtered_args . pop ( " platform " , None )
filtered_args . pop ( " target " , None )
filtered_args . pop ( " arch " , None )
platform = env [ " platform " ]
target = env [ " target " ]
arch = env [ " arch " ]
vs_configuration = { }
common_build_prefix = [ ]
confs = [ ]
for x in sorted ( glob . glob ( " platform/* " ) ) :
# Only platforms that opt in to vs proj generation are included.
if not os . path . isdir ( x ) or not os . path . exists ( x + " /msvs.py " ) :
continue
tmppath = " ./ " + x
sys . path . insert ( 0 , tmppath )
import msvs
vs_plats = [ ]
vs_confs = [ ]
try :
platform_name = x [ 9 : ]
vs_plats = msvs . get_platforms ( )
vs_confs = msvs . get_configurations ( )
val = [ ]
for plat in vs_plats :
val + = [ { " platform " : plat [ 0 ] , " architecture " : plat [ 1 ] } ]
vsconf = { " platform " : platform_name , " targets " : vs_confs , " arches " : val }
confs + = [ vsconf ]
# Save additional information about the configuration for the actively selected platform,
# so we can generate the platform-specific props file with all the build commands/defines/etc
if platform == platform_name :
common_build_prefix = msvs . get_build_prefix ( env )
vs_configuration = vsconf
except Exception :
pass
sys . path . remove ( tmppath )
sys . modules . pop ( " msvs " )
headers = [ ]
headers_dirs = [ ]
for file in glob_recursive_2 ( " *.h " , headers_dirs ) :
headers . append ( str ( file ) . replace ( " / " , " \\ " ) )
for file in glob_recursive_2 ( " *.hpp " , headers_dirs ) :
headers . append ( str ( file ) . replace ( " / " , " \\ " ) )
sources = [ ]
sources_dirs = [ ]
for file in glob_recursive_2 ( " *.cpp " , sources_dirs ) :
sources . append ( str ( file ) . replace ( " / " , " \\ " ) )
for file in glob_recursive_2 ( " *.c " , sources_dirs ) :
sources . append ( str ( file ) . replace ( " / " , " \\ " ) )
others = [ ]
others_dirs = [ ]
for file in glob_recursive_2 ( " *.natvis " , others_dirs ) :
others . append ( str ( file ) . replace ( " / " , " \\ " ) )
for file in glob_recursive_2 ( " *.glsl " , others_dirs ) :
others . append ( str ( file ) . replace ( " / " , " \\ " ) )
skip_filters = False
import hashlib
import json
md5 = hashlib . md5 (
json . dumps ( headers + headers_dirs + sources + sources_dirs + others + others_dirs , sort_keys = True ) . encode (
" utf-8 "
)
) . hexdigest ( )
if os . path . exists ( f " { project_name } .vcxproj.filters " ) :
existing_filters = open ( f " { project_name } .vcxproj.filters " , " r " ) . read ( )
match = re . search ( r " (?ms)^<!-- CHECKSUM$.([0-9a-f] {32} ) " , existing_filters )
if match is not None and md5 == match . group ( 1 ) :
skip_filters = True
import uuid
# Don't regenerate the filters file if nothing has changed, so we keep the existing UUIDs.
if not skip_filters :
print ( f " Regenerating { project_name } .vcxproj.filters " )
filters_template = open ( " misc/msvs/vcxproj.filters.template " , " r " ) . read ( )
for i in range ( 1 , 10 ) :
filters_template = filters_template . replace ( f " %%UUID { i } %% " , str ( uuid . uuid4 ( ) ) )
filters = " "
for d in headers_dirs :
filters + = f ' <Filter Include= " Header Files \\ { d } " ><UniqueIdentifier> {{ { str ( uuid . uuid4 ( ) ) } }} </UniqueIdentifier></Filter> \n '
for d in sources_dirs :
filters + = f ' <Filter Include= " Source Files \\ { d } " ><UniqueIdentifier> {{ { str ( uuid . uuid4 ( ) ) } }} </UniqueIdentifier></Filter> \n '
for d in others_dirs :
filters + = f ' <Filter Include= " Other Files \\ { d } " ><UniqueIdentifier> {{ { str ( uuid . uuid4 ( ) ) } }} </UniqueIdentifier></Filter> \n '
filters_template = filters_template . replace ( " %% FILTERS %% " , filters )
filters = " "
for file in headers :
filters + = (
f ' <ClInclude Include= " { file } " ><Filter>Header Files \\ { os . path . dirname ( file ) } </Filter></ClInclude> \n '
)
filters_template = filters_template . replace ( " %% INCLUDES %% " , filters )
filters = " "
for file in sources :
filters + = (
f ' <ClCompile Include= " { file } " ><Filter>Source Files \\ { os . path . dirname ( file ) } </Filter></ClCompile> \n '
)
filters_template = filters_template . replace ( " %% COMPILES %% " , filters )
filters = " "
for file in others :
filters + = f ' <None Include= " { file } " ><Filter>Other Files \\ { os . path . dirname ( file ) } </Filter></None> \n '
filters_template = filters_template . replace ( " %% OTHERS %% " , filters )
filters_template = filters_template . replace ( " %% HASH %% " , md5 )
with open ( f " { project_name } .vcxproj.filters " , " w " ) as f :
f . write ( filters_template )
envsources = [ ]
envsources + = env . core_sources
envsources + = env . drivers_sources
envsources + = env . main_sources
envsources + = env . modules_sources
envsources + = env . scene_sources
envsources + = env . servers_sources
if env . editor_build :
envsources + = env . editor_sources
envsources + = env . platform_sources
headers_active = [ ]
sources_active = [ ]
others_active = [ ]
for x in envsources :
fname = " "
if type ( x ) == type ( " " ) :
fname = env . File ( x ) . path
else :
# Some object files might get added directly as a File object and not a list.
try :
fname = env . File ( x ) [ 0 ] . path
except :
fname = x . path
pass
if fname :
fname = fname . replace ( " \\ \\ " , " / " )
parts = os . path . splitext ( fname )
basename = parts [ 0 ]
ext = parts [ 1 ]
idx = fname . find ( env [ " OBJSUFFIX " ] )
if ext in [ " .h " , " .hpp " ] :
headers_active + = [ fname ]
elif ext in [ " .c " , " .cpp " ] :
sources_active + = [ fname ]
elif idx > 0 :
basename = fname [ : idx ]
if os . path . isfile ( basename + " .h " ) :
headers_active + = [ basename + " .h " ]
elif os . path . isfile ( basename + " .hpp " ) :
headers_active + = [ basename + " .hpp " ]
elif basename . endswith ( " .gen " ) and os . path . isfile ( basename [ : - 4 ] + " .h " ) :
headers_active + = [ basename [ : - 4 ] + " .h " ]
if os . path . isfile ( basename + " .c " ) :
sources_active + = [ basename + " .c " ]
elif os . path . isfile ( basename + " .cpp " ) :
sources_active + = [ basename + " .cpp " ]
else :
fname = os . path . relpath ( os . path . abspath ( fname ) , env . Dir ( " " ) . abspath )
others_active + = [ fname ]
all_items = [ ]
properties = [ ]
activeItems = [ ]
extraItems = [ ]
set_headers = set ( headers_active )
set_sources = set ( sources_active )
set_others = set ( others_active )
for file in headers :
all_items . append ( f ' <ClInclude Include= " { file } " > ' )
all_items . append (
f " <ExcludedFromBuild Condition= \" !$(ActiveProjectItemList.Contains( ' ; { file } ; ' )) \" >true</ExcludedFromBuild> "
)
all_items . append ( " </ClInclude> " )
if file in set_headers :
activeItems . append ( file )
for file in sources :
all_items . append ( f ' <ClCompile Include= " { file } " > ' )
all_items . append (
f " <ExcludedFromBuild Condition= \" !$(ActiveProjectItemList.Contains( ' ; { file } ; ' )) \" >true</ExcludedFromBuild> "
)
all_items . append ( " </ClCompile> " )
if file in set_sources :
activeItems . append ( file )
for file in others :
all_items . append ( f ' <None Include= " { file } " > ' )
all_items . append (
f " <ExcludedFromBuild Condition= \" !$(ActiveProjectItemList.Contains( ' ; { file } ; ' )) \" >true</ExcludedFromBuild> "
)
all_items . append ( " </None> " )
if file in set_others :
activeItems . append ( file )
if vs_configuration :
vsconf = " "
for a in vs_configuration [ " arches " ] :
if arch == a [ " architecture " ] :
vsconf = f ' { target } | { a [ " platform " ] } '
break
condition = " ' $(Configuration)|$(Platform) ' == ' " + vsconf + " ' "
properties . append ( " <ActiveProjectItemList>; " + " ; " . join ( activeItems ) + " ;</ActiveProjectItemList> " )
output = f ' bin \\ godot { env [ " PROGSUFFIX " ] } '
props_template = open ( " misc/msvs/props.template " , " r " ) . read ( )
props_template = props_template . replace ( " %% VSCONF %% " , vsconf )
props_template = props_template . replace ( " %% CONDITION %% " , condition )
props_template = props_template . replace ( " %% PROPERTIES %% " , " \n " . join ( properties ) )
props_template = props_template . replace ( " %% EXTRA_ITEMS %% " , " \n " . join ( extraItems ) )
props_template = props_template . replace ( " %% OUTPUT %% " , output )
props_template = props_template . replace (
" %% DEFINES %% " , " ; " . join ( [ format_key_value ( v ) for v in list ( env [ " CPPDEFINES " ] ) ] )
)
props_template = props_template . replace ( " %% INCLUDES %% " , " ; " . join ( [ str ( j ) for j in env [ " CPPPATH " ] ] ) )
props_template = props_template . replace (
" %% OPTIONS %% " ,
" " . join ( env [ " CCFLAGS " ] ) + " " + " " . join ( [ x for x in env [ " CXXFLAGS " ] if not x . startswith ( " $ " ) ] ) ,
)
# Windows allows us to have spaces in paths, so we need
# to double quote off the directory. However, the path ends
# in a backslash, so we need to remove this, lest it escape the
# last double quote off, confusing MSBuild
common_build_postfix = [
" --directory="$(ProjectDir.TrimEnd(' \\ '))" " ,
" progress=no " ,
f " platform= { platform } " ,
f " target= { target } " ,
f " arch= { arch } " ,
]
for arg , value in filtered_args . items ( ) :
common_build_postfix . append ( f " { arg } = { value } " )
cmd_rebuild = [
" vsproj=yes " ,
f " vsproj_name= { project_name } " ,
] + common_build_postfix
cmd_clean = [
" --clean " ,
] + common_build_postfix
commands = " scons "
if len ( common_build_prefix ) == 0 :
commands = " echo Starting SCons && cmd /V /C " + commands
else :
common_build_prefix [ 0 ] = " echo Starting SCons && cmd /V /C " + common_build_prefix [ 0 ]
cmd = " ^& " . join ( common_build_prefix + [ " " . join ( [ commands ] + common_build_postfix ) ] )
props_template = props_template . replace ( " %% BUILD %% " , cmd )
cmd = " ^& " . join ( common_build_prefix + [ " " . join ( [ commands ] + cmd_rebuild ) ] )
props_template = props_template . replace ( " %% REBUILD %% " , cmd )
cmd = " ^& " . join ( common_build_prefix + [ " " . join ( [ commands ] + cmd_clean ) ] )
props_template = props_template . replace ( " %% CLEAN %% " , cmd )
with open ( f " { project_name } . { platform } . { target } . { arch } .generated.props " , " w " ) as f :
f . write ( props_template )
proj_uuid = str ( uuid . uuid4 ( ) )
sln_uuid = str ( uuid . uuid4 ( ) )
if os . path . exists ( f " { project_name } .sln " ) :
for line in open ( f " { project_name } .sln " , " r " ) . read ( ) . splitlines ( ) :
if line . startswith ( ' Project( " { 8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942} " ) ' ) :
proj_uuid = re . search (
r " \" { ( \ b[0-9a-fA-F] {8} \ b-[0-9a-fA-F] {4} -[0-9a-fA-F] {4} -[0-9a-fA-F] {4} - \ b[0-9a-fA-F] {12} \ b)} \" $ " ,
line ,
) . group ( 1 )
elif line . strip ( ) . startswith ( " SolutionGuid = " ) :
sln_uuid = re . search (
r " { ( \ b[0-9a-fA-F] {8} \ b-[0-9a-fA-F] {4} -[0-9a-fA-F] {4} -[0-9a-fA-F] {4} - \ b[0-9a-fA-F] {12} \ b)} " , line
) . group ( 1 )
break
configurations = [ ]
imports = [ ]
properties = [ ]
section1 = [ ]
section2 = [ ]
for conf in confs :
godot_platform = conf [ " platform " ]
for p in conf [ " arches " ] :
sln_plat = p [ " platform " ]
proj_plat = sln_plat
godot_arch = p [ " architecture " ]
# Redirect editor configurations for non-Windows platforms to the Windows one, so the solution has all the permutations
# and VS doesn't complain about missing project configurations.
# These configurations are disabled, so they show up but won't build.
if godot_platform != " windows " :
section1 + = [ f " editor| { sln_plat } = editor| { proj_plat } " ]
section2 + = [
f " {{ { proj_uuid } }} .editor| { proj_plat } .ActiveCfg = editor| { proj_plat } " ,
]
for t in conf [ " targets " ] :
godot_target = t
# Windows x86 is a special little flower that requires a project platform == Win32 but a solution platform == x86.
if godot_platform == " windows " and godot_target == " editor " and godot_arch == " x86_32 " :
sln_plat = " x86 "
configurations + = [
f ' <ProjectConfiguration Include= " { godot_target } | { proj_plat } " > ' ,
f " <Configuration> { godot_target } </Configuration> " ,
f " <Platform> { proj_plat } </Platform> " ,
" </ProjectConfiguration> " ,
]
if godot_platform != " windows " :
configurations + = [
f ' <ProjectConfiguration Include= " editor| { proj_plat } " > ' ,
f " <Configuration>editor</Configuration> " ,
f " <Platform> { proj_plat } </Platform> " ,
" </ProjectConfiguration> " ,
]
p = f " { project_name } . { godot_platform } . { godot_target } . { godot_arch } .generated.props "
imports + = [
f ' <Import Project= " $(MSBuildProjectDirectory) \\ { p } " Condition= " Exists( \' $(MSBuildProjectDirectory) \\ { p } \' ) " /> '
]
section1 + = [ f " { godot_target } | { sln_plat } = { godot_target } | { sln_plat } " ]
section2 + = [
f " {{ { proj_uuid } }} . { godot_target } | { sln_plat } .ActiveCfg = { godot_target } | { proj_plat } " ,
f " {{ { proj_uuid } }} . { godot_target } | { sln_plat } .Build.0 = { godot_target } | { proj_plat } " ,
]
section1 = sorted ( section1 )
section2 = sorted ( section2 )
proj_template = open ( " misc/msvs/vcxproj.template " , " r " ) . read ( )
proj_template = proj_template . replace ( " %% UUID %% " , proj_uuid )
proj_template = proj_template . replace ( " %% CONFS %% " , " \n " . join ( configurations ) )
proj_template = proj_template . replace ( " %% IMPORTS %% " , " \n " . join ( imports ) )
proj_template = proj_template . replace ( " %% DEFAULT_ITEMS %% " , " \n " . join ( all_items ) )
proj_template = proj_template . replace ( " %% PROPERTIES %% " , " \n " . join ( properties ) )
with open ( f " { project_name } .vcxproj " , " w " ) as f :
f . write ( proj_template )
sln_template = open ( " misc/msvs/sln.template " , " r " ) . read ( )
sln_template = sln_template . replace ( " %% NAME %% " , project_name )
sln_template = sln_template . replace ( " %% UUID %% " , proj_uuid )
sln_template = sln_template . replace ( " %% SLNUUID %% " , sln_uuid )
sln_template = sln_template . replace ( " %% SECTION1 %% " , " \n " . join ( section1 ) )
sln_template = sln_template . replace ( " %% SECTION2 %% " , " \n " . join ( section2 ) )
with open ( f " { project_name } .sln " , " w " ) as f :
f . write ( sln_template )
if get_bool ( original_args , " vsproj_gen_only " , True ) :
sys . exit ( )