| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 | # This python script parses the spec files from MSBuild to create# mappings from compiler options to IDE XML specifications.  For# more information see here:#  http://blogs.msdn.com/vcblog/archive/2008/12/16/msbuild-task.aspx#  "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/1033/cl.xml"#  "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/1033/lib.xml"#  "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/1033/link.xml"#  "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V110/1033/cl.xml"#  "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V110/1033/lib.xml"#  "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V110/1033/link.xml"#  "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/cl.xml"#  "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/lib.xml"#  "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/link.xml"#  "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V140/1033/cl.xml"#  "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V140/1033/lib.xml"#  "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V140/1033/link.xml"##  BoolProperty  <Name>true|false</Name>#   simple example:#     <BoolProperty ReverseSwitch="Oy-" Name="OmitFramePointers"#      Category="Optimization" Switch="Oy">#   <BoolProperty.DisplayName>  <BoolProperty.Description># <CLCompile>#     <OmitFramePointers>true</OmitFramePointers>#  </ClCompile>##  argument means it might be this: /MP3#   example with argument:#   <BoolProperty Name="MultiProcessorCompilation" Category="General" Switch="MP">#      <BoolProperty.DisplayName>#        <sys:String>Multi-processor Compilation</sys:String>#      </BoolProperty.DisplayName>#      <BoolProperty.Description>#        <sys:String>Multi-processor Compilation</sys:String>#      </BoolProperty.Description>#      <Argument Property="ProcessorNumber" IsRequired="false" />#    </BoolProperty># <CLCompile>#   <MultiProcessorCompilation>true</MultiProcessorCompilation>#   <ProcessorNumber>4</ProcessorNumber>#  </ClCompile>#  IntProperty#     not used AFIT#  <IntProperty Name="ProcessorNumber" Category="General" Visible="false">#  per config options example#    <EnableFiberSafeOptimizations Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EnableFiberSafeOptimizations>##  EnumProperty#   <EnumProperty Name="Optimization" Category="Optimization">#      <EnumProperty.DisplayName>#       <sys:String>Optimization</sys:String>#     </EnumProperty.DisplayName>#     <EnumProperty.Description>#       <sys:String>Select option for code optimization; choose Custom to use specific optimization options.     (/Od, /O1, /O2, /Ox)</sys:String>#     </EnumProperty.Description>#      <EnumValue Name="MaxSpeed" Switch="O2">#       <EnumValue.DisplayName>#         <sys:String>Maximize Speed</sys:String>#       </EnumValue.DisplayName>#       <EnumValue.Description>#         <sys:String>Equivalent to /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy</sys:String>#       </EnumValue.Description>#     </EnumValue>#     <EnumValue Name="MinSpace" Switch="O1">#       <EnumValue.DisplayName>#         <sys:String>Minimize Size</sys:String>#       </EnumValue.DisplayName>#       <EnumValue.Description>#         <sys:String>Equivalent to /Og /Os /Oy /Ob2 /Gs /GF /Gy</sys:String>#       </EnumValue.Description>#     </EnumValue>#     example for O2 would be this:#     <Optimization>MaxSpeed</Optimization>#     example for O1 would be this:#     <Optimization>MinSpace</Optimization>##  StringListProperty#   <StringListProperty Name="PreprocessorDefinitions" Category="Preprocessor" Switch="D ">#     <StringListProperty.DisplayName>#       <sys:String>Preprocessor Definitions</sys:String>#     </StringListProperty.DisplayName>#     <StringListProperty.Description>#       <sys:String>Defines a preprocessing symbols for your source file.</sys:String>#     </StringListProperty.Description>#   </StringListProperty>#   <StringListProperty Subtype="folder" Name="AdditionalIncludeDirectories" Category="General" Switch="I">#     <StringListProperty.DisplayName>#       <sys:String>Additional Include Directories</sys:String>#     </StringListProperty.DisplayName>#     <StringListProperty.Description>#       <sys:String>Specifies one or more directories to add to the include path; separate with semi-colons if more than one.     (/I[path])</sys:String>#     </StringListProperty.Description>#   </StringListProperty>#  StringProperty# Example add bill include:#   <AdditionalIncludeDirectories>..\..\..\..\..\..\bill;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>import sysfrom xml.dom.minidom import parse, parseStringdef getText(node):    nodelist = node.childNodes    rc = ""    for child in nodelist:        if child.nodeType == child.TEXT_NODE:            rc = rc + child.data    return rcdef print_tree(document, spaces=""):  for i in range(len(document.childNodes)):    if document.childNodes[i].nodeType == document.childNodes[i].ELEMENT_NODE:      print spaces+str(document.childNodes[i].nodeName )    print_tree(document.childNodes[i],spaces+"----")  pass############################################################################################Data structure that stores a property of MSBuildclass Property:  #type = type of MSBuild property (ex. if the property is EnumProperty type should be "Enum")  #attributeNames = a list of any attributes that this property could have (ex. if this was a EnumProperty it should be ["Name","Category"])  #document = the dom file that's root node is the Property node (ex. if you were parsing a BoolProperty the root node should be something like <BoolProperty Name="RegisterOutput" Category="General" IncludeInCommandLine="false">  def __init__(self,type,attributeNames,document=None):    self.suffix_type = "Property"    self.prefix_type = type    self.attributeNames = attributeNames    self.attributes = {}    self.DisplayName = ""    self.Description = ""    self.argumentProperty = ""    self.argumentIsRequired = ""    self.values = []    if document is not None:      self.populate(document)    pass  #document = the dom file that's root node is the Property node (ex. if you were parsing a BoolProperty the root node should be something like <BoolProperty Name="RegisterOutput" Category="General" IncludeInCommandLine="false">  #spaces = do not use  def populate(self,document, spaces = ""):    if document.nodeName == self.prefix_type+self.suffix_type:      for i in self.attributeNames:        self.attributes[i] = document.getAttribute(i)    for i in range(len(document.childNodes)):      child = document.childNodes[i]      if child.nodeType == child.ELEMENT_NODE:        if child.nodeName == self.prefix_type+self.suffix_type+".DisplayName":          self.DisplayName = getText(child.childNodes[1])        if child.nodeName == self.prefix_type+self.suffix_type+".Description":          self.Description = getText(child.childNodes[1])        if child.nodeName == "Argument":          self.argumentProperty = child.getAttribute("Property")          self.argumentIsRequired = child.getAttribute("IsRequired")        if child.nodeName == self.prefix_type+"Value":          va = Property(self.prefix_type,["Name","DisplayName","Switch"])          va.suffix_type = "Value"          va.populate(child)          self.values.append(va)      self.populate(child,spaces+"----")      pass  #toString function  def __str__(self):    toReturn = self.prefix_type+self.suffix_type+":"    for i in self.attributeNames:      toReturn += "\n    "+i+": "+self.attributes[i]    if self.argumentProperty != "":      toReturn += "\n    Argument:\n        Property: "+self.argumentProperty+"\n        IsRequired: "+self.argumentIsRequired    for i in self.values:        toReturn+="\n    "+str(i).replace("\n","\n    ")    return toReturn#######################################################################################################################################################################################Class that populates itself from an MSBuild file and outputs it in CMake#formatclass MSBuildToCMake:  #document = the entire MSBuild xml file  def __init__(self,document=None):    self.enumProperties = []    self.stringProperties = []    self.stringListProperties = []    self.boolProperties = []    self.intProperties = []    if document!=None :      self.populate(document)    pass  #document = the entire MSBuild xml file  #spaces = don't use  #To add a new property (if they exist) copy and paste this code and fill in appropriate places  #  #if child.nodeName == "<Name>Property":  #        self.<Name>Properties.append(Property("<Name>",[<List of attributes>],child))  #  #Replace <Name> with the name of the new property (ex. if property is StringProperty replace <Name> with String)  #Replace <List of attributes> with a list of attributes in your property's root node  #in the __init__ function add the line self.<Name>Properties = []  #  #That is all that is required to add new properties  #  def populate(self,document, spaces=""):    for i in range(len(document.childNodes)):      child = document.childNodes[i]      if child.nodeType == child.ELEMENT_NODE:        if child.nodeName == "EnumProperty":          self.enumProperties.append(Property("Enum",["Name","Category"],child))        if child.nodeName == "StringProperty":          self.stringProperties.append(Property("String",["Name","Subtype","Separator","Category","Visible","IncludeInCommandLine","Switch","DisplayName","ReadOnly"],child))        if child.nodeName == "StringListProperty":           self.stringListProperties.append(Property("StringList",["Name","Category","Switch","DisplayName","Subtype"],child))        if child.nodeName == "BoolProperty":           self.boolProperties.append(Property("Bool",["ReverseSwitch","Name","Category","Switch","DisplayName","SwitchPrefix","IncludeInCommandLine"],child))        if child.nodeName == "IntProperty":           self.intProperties.append(Property("Int",["Name","Category","Visible"],child))      self.populate(child,spaces+"----")    pass  #outputs information that CMake needs to know about MSBuild xml files  def toCMake(self):    toReturn = "static cmVS7FlagTable cmVS10CxxTable[] =\n{\n"    toReturn += "\n  //Enum Properties\n"    lastProp = {}    for i in self.enumProperties:      if i.attributes["Name"] == "CompileAsManaged":        #write these out after the rest of the enumProperties        lastProp = i        continue      for j in i.values:        #hardcore Brad King's manual fixes for cmVS10CLFlagTable.h        if i.attributes["Name"] == "PrecompiledHeader" and j.attributes["Switch"] != "":          toReturn+="  {\""+i.attributes["Name"]+"\", \""+j.attributes["Switch"]+"\",\n   \""+j.attributes["DisplayName"]+"\", \""+j.attributes["Name"]+"\",\n   cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},\n"        else:          #default (normal, non-hardcoded) case          toReturn+="  {\""+i.attributes["Name"]+"\", \""+j.attributes["Switch"]+"\",\n   \""+j.attributes["DisplayName"]+"\", \""+j.attributes["Name"]+"\", 0},\n"      toReturn += "\n"    if lastProp != {}:      for j in lastProp.values:          toReturn+="  {\""+lastProp.attributes["Name"]+"\", \""+j.attributes["Switch"]+"\",\n   \""+j.attributes["DisplayName"]+"\", \""+j.attributes["Name"]+"\", 0},\n"      toReturn += "\n"    toReturn += "\n  //Bool Properties\n"    for i in self.boolProperties:      if i.argumentProperty == "":        if i.attributes["ReverseSwitch"] != "":          toReturn += "  {\""+i.attributes["Name"]+"\", \""+i.attributes["ReverseSwitch"]+"\", \"\", \"false\", 0},\n"        if i.attributes["Switch"] != "":          toReturn += "  {\""+i.attributes["Name"]+"\", \""+i.attributes["Switch"]+"\", \"\", \"true\", 0},\n"    toReturn += "\n  //Bool Properties With Argument\n"    for i in self.boolProperties:      if i.argumentProperty != "":        if i.attributes["ReverseSwitch"] != "":          toReturn += "  {\""+i.attributes["Name"]+"\", \""+i.attributes["ReverseSwitch"]+"\", \"\", \"false\",\n   cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},\n"          toReturn += "  {\""+i.attributes["Name"]+"\", \""+i.attributes["ReverseSwitch"]+"\", \""+i.attributes["DisplayName"]+"\", \"\",\n   cmVS7FlagTable::UserValueRequired},\n"        if i.attributes["Switch"] != "":          toReturn += "  {\""+i.attributes["Name"]+"\", \""+i.attributes["Switch"]+"\", \"\", \"true\",\n   cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},\n"          toReturn += "  {\""+i.argumentProperty+"\", \""+i.attributes["Switch"]+"\", \""+i.attributes["DisplayName"]+"\", \"\",\n   cmVS7FlagTable::UserValueRequired},\n"    toReturn += "\n  //String List Properties\n"    for i in self.stringListProperties:      if i.attributes["Switch"] == "":        toReturn += "  // Skip [" + i.attributes["Name"] + "] - no command line Switch.\n";      else:        toReturn +="  {\""+i.attributes["Name"]+"\", \""+i.attributes["Switch"]+"\",\n   \""+i.attributes["DisplayName"]+"\",\n   \"\", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},\n"    toReturn += "\n  //String Properties\n"    for i in self.stringProperties:      if i.attributes["Switch"] == "":        if i.attributes["Name"] == "PrecompiledHeaderFile":          #more hardcoding          toReturn += "  {\"PrecompiledHeaderFile\", \"Yc\",\n"          toReturn += "   \"Precompiled Header Name\",\n"          toReturn += "   \"\", cmVS7FlagTable::UserValueRequired},\n"          toReturn += "  {\"PrecompiledHeaderFile\", \"Yu\",\n"          toReturn += "   \"Precompiled Header Name\",\n"          toReturn += "   \"\", cmVS7FlagTable::UserValueRequired},\n"        else:          toReturn += "  // Skip [" + i.attributes["Name"] + "] - no command line Switch.\n";      else:        toReturn +="  {\""+i.attributes["Name"]+"\", \""+i.attributes["Switch"]+i.attributes["Separator"]+"\",\n   \""+i.attributes["DisplayName"]+"\",\n   \"\", cmVS7FlagTable::UserValue},\n"    toReturn += "  {0,0,0,0,0}\n};"    return toReturn    pass  #toString function  def __str__(self):    toReturn = ""    allList = [self.enumProperties,self.stringProperties,self.stringListProperties,self.boolProperties,self.intProperties]    for p in allList:      for i in p:        toReturn += "==================================================\n"+str(i).replace("\n","\n    ")+"\n==================================================\n"    return toReturn####################################################################################################################################################################################### main functiondef main(argv):  xml_file = None  help = """  Please specify an input xml file with -x  Exiting...  Have a nice day :)"""  for i in range(0,len(argv)):    if argv[i] == "-x":      xml_file = argv[i+1]    if argv[i] == "-h":      print help      sys.exit(0)    pass  if xml_file == None:    print help    sys.exit(1)  f = open(xml_file,"r")  xml_str = f.read()  xml_dom = parseString(xml_str)  convertor = MSBuildToCMake(xml_dom)  print convertor.toCMake()  xml_dom.unlink()############################################################################################ main entry pointif __name__ == "__main__":  main(sys.argv)sys.exit(0)
 |