Hi
I written a script that allows you to compile python with the free .NET
Framework SDK. It reads in the XML file and uses a rule set to build the
commands. At the moment it just executes them but I'm going to write a
Makefile writter (GNU make is all I know though) It's probably possible
to write rules to compile with mingw32 as well.
What would be a real help is if someone could send me the console output
from the Debug and Release buiilds when you use command line devstudio
to build it as some of the xml properties make no sense but I could
probably work out what they mean. Things like 'RuntimeLibrary="2"' have
no meaning unless I can see the output.
You need the free .NET framework SDK and the Platform SDK both available
for free from microsoft
Just put the two python files in the PCBuild directory and run
vcproj_read.py pythoncore.vcproj "Release|Win32"
or
vcproj_read.py pythoncore.vcproj "Debug|Win32"
I've only tested it with pythoncode.vcproj and python.vcproj so if you
get a keyerror around line 187 you need to add more rules to interpret
the settings.
Cheers
Garth
import sys
from xml.dom.ext.reader import Sax2
import xml.dom.ext
import file_rules
if len(sys.argv) < 3:
print "<XML_PROJECT FILE> <CONFIG>"
sys.exit(1)
xml_file = file( sys.argv[1], 'rU' )
reader = Sax2.Reader()
doc = reader.fromStream( xml_file )
xml_file.close()
vsproj = doc.getElementsByTagName('VisualStudioProject')[0]
def attributes2dict(dom):
"""
"""
d = {}
for attr in dom.attributes:
#print attr
d[attr.name] = attr.nodeValue
return d
def xmlnode2dict( dom ):
#print dom
#print dir(dom)
#self = { }
self = attributes2dict( dom )
if dom.hasChildNodes():
for child in dom.childNodes:
try:
childdict = xmlnode2dict( child )
try:
self[child.nodeName].append( childdict )
except KeyError:
self[child.nodeName] = [ childdict ]
except TypeError:
pass #print "skipping",child
return self
project = xmlnode2dict( vsproj )
# Select the configuration
for config in project['Configurations'][0]['Configuration']:
if config['Name'] == sys.argv[2]:
currentconfig = config
try:
print "Config selected", currentconfig['Name']
except NameError:
print "Couldn't find config",sys.argv[2]
sys.exit(1)
file_rules.currentconfig = currentconfig
# write the makefile by sening ocommand off to MakfileWrite class
# For now just exe
objectlist = []
import os
for f in project['Files'][0]['File']:
print "Processing ",f['RelativePath']
cmdline,obj = file_rules.generate_command_line( f )
print cmdline
if cmdline:
os.system( cmdline )
objectlist.append( obj )
# Now link.....
print "link ",objectlist
print "When I get around to writing it"
import os.path
# Tool rule setting
# Sometimes file setting s override trhe config rule and sometimes they
# just add to it maybe this is wrong?
TOOL_RULE_OVERRIDE = 0
TOOL_RULE_BOTH = 1
currentconfig = None
def find_file_config( fileconfig ):
for config in fileconfig['FileConfiguration']:
if config['Name'] == currentconfig['Name']:
return config
def find_tool_settings( fileconfig, name, setting, rule):
settings = []
try:
currentfileconfig = find_file_config( fileconfig )
for tool in currentfileconfig['Tool']:
if tool['Name'] == name:
if tool[setting] != '':
settings.append( tool[setting] )
if rule == TOOL_RULE_OVERRIDE:
return tool[setting]
except KeyError:
# OK no file specific config for this file
pass
for tool in currentconfig['Tool']:
if tool['Name'] == name:
settings.append( tool[setting] )
if rule == TOOL_RULE_BOTH:
return settings
else:
return tool[setting]
raise KeyError,"DAMN" + str(fileconfig) + str(name) + str(setting)
# Guessing at this.. need to fill in the real values
DebugInformationFormatmap = {'3' : '-Zi'}
Optimizationmap = {'0' : "",
'1' : "/O1",
'2' : "/O2",
'3' : "/Ox"}
def option_list( fconfig, tool, var, delimiter, prefix ):
"""
"""
options = find_tool_settings( fconfig, tool,var,TOOL_RULE_BOTH)
optionlist = []
for option in options:
optionlist += option.split( delimiter )
return prefix + prefix.join( optionlist )
def option_param( fconfig, tool, var, prefix ):
"""
"""
option = find_tool_settings( fconfig, tool,var,TOOL_RULE_OVERRIDE)
return prefix + option
def option_bool( fconfig, tool, boolname, prefix ):
"""
"""
line = ""
b = find_tool_settings( fconfig, 'VCCLCompilerTool',boolname,TOOL_RULE_OVERRIDE)
if bool(b):
line = prefix
return line
def option_bool_param(fconfig, tool, boolname, paramname, prefix ):
"""
"""
line = ""
b = find_tool_settings( fconfig, 'VCCLCompilerTool',boolname,TOOL_RULE_OVERRIDE)
if bool(b):
paramvalue = find_tool_settings( fconfig, 'VCCLCompilerTool',paramname,TOOL_RULE_OVERRIDE)
line = prefix + paramvalue
return line
def option_map( fconfig, tool, var, optionmap ):
"""
"""
option = find_tool_settings( fconfig, tool,var,TOOL_RULE_OVERRIDE)
return optionmap[ option ]
toolextmap = {'c' : 'VCCLCompilerTool',
'rc': 'VCResourceCompilerTool',
'ico' : None,}
# HMM are the ones I'm not sure about...
OPTION_TYPE_HMM = 0
OPTION_TYPE_BOOL = 1
OPTION_TYPE_BOOL_PARAM = 2
OPTION_TYPE_MAP = 3
OPTION_TYPE_PARAM = 4
OPTION_TYPE_LIST = 5
# IGNORE is there as they are probably used in some other
# parameter thing
OPTION_TYPE_IGNORE = 6
toolmap = {'VCCLCompilerTool' : { 'pre' : 'cl ' ,
'post' : ' -c ',
'objpath': 'ObjectFile',
'objext' : 'obj',
#'Name': {'type' : OPTION_TYPE_IGNORE },
'AdditionalOptions' : {'type' : OPTION_TYPE_PARAM,
'flag' : '',
},
'PrecompiledHeaderFile': {'type' : OPTION_TYPE_IGNORE },
'EnableFunctionLevelLinking' : { 'type' : OPTION_TYPE_BOOL,
'flag' : '-Gy'
},
'StringPooling': { 'type' : OPTION_TYPE_BOOL,
'flag' : '-Gf'
},
# Not sure about this one
'InlineFunctionExpansion': { 'type' : OPTION_TYPE_BOOL,
'flag' : '-Ob1'
},
'ProgramDataBaseFileName' : {'type' : OPTION_TYPE_IGNORE },
'RuntimeLibrary' : {'type' : OPTION_TYPE_HMM },
'AssemblerListingLocation' : {'type' : OPTION_TYPE_HMM },
'CompileAs' : {'type' : OPTION_TYPE_HMM },
'AdditionalIncludeDirectories' : {'type' : OPTION_TYPE_LIST,
'delim' : ',',
'flag' : ' -I',
},
'PreprocessorDefinitions' : {'type' : OPTION_TYPE_LIST,
'delim' : ';',
'flag' : ' -D',
},
'BrowseInformation' : { 'type' : OPTION_TYPE_BOOL_PARAM,
'paramname' :'ProgramDataBaseFileName',
'flag' : '-FR'
},
'DebugInformationFormat' : { 'type' : OPTION_TYPE_MAP,
'map' : DebugInformationFormatmap,
},
'ObjectFile' : {'type' : OPTION_TYPE_PARAM,
'flag' : '-Fo',
},
'Optimization': { 'type' : OPTION_TYPE_MAP,
'map' : Optimizationmap,
},
'WarningLevel' : {'type' : OPTION_TYPE_PARAM,
'flag' : '-W',
},
'UsePrecompiledHeader': { 'type' : OPTION_TYPE_BOOL_PARAM,
'paramname' :'PrecompiledHeaderFile',
'flag' : '-YX',
},
'SuppressStartupBanner' : { 'type' : OPTION_TYPE_BOOL,
'flag' : '-nologo'
},
},
'VCResourceCompilerTool' : {'pre' : 'rc ' ,
'post' : '',
'objpath': None,
'objext' : 'res',
'Name': {'type' : OPTION_TYPE_IGNORE },
'PreprocessorDefinitions' : {'type' : OPTION_TYPE_LIST,
'delim' : ';',
'flag' : ' -d',
},
'AdditionalIncludeDirectories' : {'type' : OPTION_TYPE_LIST,
'delim' : ',',
'flag' : ' -i',
},
'Culture': {'type' : OPTION_TYPE_PARAM,
'flag' : '-l',
},
}
}
def run_option( f, tool, option ):
"""
"""
line = ""
oinfo = toolmap[tool][option]
# print oinfo
if oinfo['type'] == OPTION_TYPE_HMM:
print "Option ", option, "Not implemented yet!"
pass
elif oinfo['type'] == OPTION_TYPE_BOOL:
line = option_bool(f, tool, option, oinfo['flag'] )
elif oinfo['type'] == OPTION_TYPE_BOOL_PARAM :
line = option_bool_param( f, tool, option, oinfo['paramname'], oinfo['flag'] )
elif oinfo['type'] == OPTION_TYPE_MAP:
line = option_map( f, tool, option, Optimizationmap)
elif oinfo['type'] == OPTION_TYPE_PARAM:
line = option_param( f, tool, option, oinfo['flag'] )
elif oinfo['type'] == OPTION_TYPE_LIST:
line = option_list( f, tool, option, oinfo['delim'], oinfo['flag'] )
return line
def generate_command_line( f ):
"""
"""
cmd = ""
obj = ""
ext = f['RelativePath'].split(".")[-1]
toolname = toolextmap[ ext ]
if toolname:
lines = []
for tool in currentconfig['Tool']:
if tool['Name'] == toolname:
for setting in tool:
lines.append( run_option( f, toolname, setting) )
cmd = toolmap[ toolname ]['pre']
cmd += (" ".join( lines ))
cmd += toolmap[ toolname ]['post']
cmd += " " + f['RelativePath']
if toolmap[ toolname ]['objpath']:
objectpath = find_tool_settings( f, toolname, toolmap[ toolname ]['objpath'] ,TOOL_RULE_OVERRIDE)
else:
objectpath = os.path.split( f['RelativePath'] )[0]
objectfile = "".join( os.path.splitext( os.path.split( f['RelativePath'] )[1] )[0] ) + toolmap[ toolname ]['objext']
obj = os.path.join(objectpath,objectfile)
return ( cmd, obj)
def generate_command_line_old( f ):
"""
"""
ext = f['RelativePath'].split(".")[-1]
cmdlinefunc = filetype[ ext ]
return cmdlinefunc( f )
def generate_link_line( files ):
"""
"""
line = ['link']
raise SystemError,"WriteME!"