slntool.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 #
00003 # @brief Visual Studio solution generator
00004 # @date $Date: 2008-03-06 06:46:37 $
00005 # @author Norkai Ando <n-ando@aist.go.jp>
00006 #
00007 # Copyright (C) 2008
00008 #     Noriaki Ando
00009 #     Task-intelligence Research Group,
00010 #     Intelligent Systems Research Institute,
00011 #     National Institute of
00012 #         Advanced Industrial Science and Technology (AIST), Japan
00013 #     All rights reserved.
00014 #
00015 # $Id: slntool.py 1863 2010-02-11 06:31:11Z n-ando $
00016 #
00017 
00018 import sys
00019 import re
00020 import yaml
00021 import yat
00022 
00023 #------------------------------------------------------------
00024 # Generic vcproj template
00025 #------------------------------------------------------------
00026 vcversions = {"VC8": {"sln": "9.00", "vc": "2005"},
00027               "VC9": {"sln": "10.00", "vc": "2008"},
00028               "VC10": {"sln": "11.00", "vc": "2010"}
00029               }
00030 sln_template = """Microsoft Visual Studio Solution File, Format Version %s
00031 # Visual Studio %s
00032 [for proj in Projects]
00033 Project("{[SolutionGUID]}") = "[proj.Name]", "[proj.FileName]", "{[proj.GUID]}"
00034         ProjectSection(ProjectDependencies) = postProject
00035 [if-any proj.Depend]
00036 [for dep in proj.Depend]
00037                 {[dep]} = {[dep]}
00038 [endfor]
00039 [endif]
00040         EndProjectSection
00041 EndProject
00042 [endfor]
00043 Global
00044         GlobalSection(SolutionConfigurationPlatforms) = preSolution
00045 [for conf in Configurations]
00046                 [conf] = [conf]
00047 
00048 [endfor]
00049         EndGlobalSection
00050         GlobalSection(ProjectConfigurationPlatforms) = postSolution
00051 [for proj in Projects]
00052 [for conf in Configurations]
00053                 {[proj.GUID]}.[conf].ActiveCfg = [conf]
00054 
00055                 {[proj.GUID]}.[conf].Build.0   = [conf]
00056 
00057 [endfor]
00058 [endfor]
00059         EndGlobalSection
00060         GlobalSection(SolutionProperties) = preSolution
00061                 HideSolutionNode = FALSE
00062         EndGlobalSection
00063 EndGlobal
00064 """
00065 
00066 
00067 sln_yaml = """
00068 SolutionGUID: 8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942
00069 Configurations:
00070   - Release|Win32
00071   - Debug|Win32
00072 """
00073 
00074 
00075 def usage():
00076     print """
00077 Usage:
00078   slntool.py --dep dep_file [--outfile outfile] vcproj_files...
00079 
00080 Options:
00081     --vcversion: Visual C++'s version [VC8|VC9|VC10]
00082     --dep: dependency file
00083     --out or --output: output file name
00084 
00085 Example:
00086  * make solution from all of found vcprojs
00087   slntool.py --dep dep_file --outfile MyApp.sln \
00088     `find ./ --name '*.vcproj'`
00089  * output solution to stdout
00090   slntool.py --dep dep_file *.vcproj
00091 
00092 Depfile examples: The rule is similar to Makefile's dependency rule
00093   All of entries should be Projectname.
00094   [target Projectname]: [dependent projectsname...]
00095 
00096 In the following App.dep file, "App" dpends on "Lib1" and "Lib2".
00097 "Lib2" depends on "Lib1", "Lib1" has no dependency.
00098 For this solution, "App", "Lib1" and "Lib2"'s project files are necessary.
00099 
00100 -- App.dep --
00101 App: Lib1 Lib2
00102 Lib2: Lib1
00103 -------------
00104 
00105 """
00106 
00107 
00108 def get_projinfo(fname):
00109     name = None
00110     guid = None
00111     re_guid = re.compile('^.*?ProjectGUID=\"{(.*)}\"')
00112     re_name = re.compile('^.*?Name=\"(.*)\"')
00113     fd = open(fname, "r")
00114     pj = fd.readlines()
00115     for t in pj:
00116         n = re_name.match(t)
00117         g = re_guid.match(t)
00118 
00119         if name == None and n:
00120             name = n.group(1)
00121         if guid == None and g:
00122             guid = g.group(1)
00123 
00124         if name and guid:
00125             break
00126     fd.close()
00127     return {"Name": name, "GUID": guid, "FileName": fname}
00128 
00129 def get_projinfo(fname,vcversion):
00130     name = None
00131     guid = None
00132     regexs = {"VC8": {"guid":'^.*?ProjectGUID=\"{(.*)}\"',"name":'^.*?Name=\"(.*)\"'}, 
00133               "VC9": {"guid":'^.*?ProjectGUID=\"{(.*)}\"',"name":'^.*?Name=\"(.*)\"'}, 
00134               "VC10": {"guid":'^.*?<ProjectGuid>{(.*)}</ProjectGuid>',"name":'^.*<ProjectName>(.*)</ProjectName>'}
00135              }
00136     re_guid = re.compile(regexs[vcversion]["guid"])
00137     re_name = re.compile(regexs[vcversion]["name"])
00138     fd = open(fname, "r")
00139     pj = fd.readlines()
00140     for t in pj:
00141         n = re_name.match(t)
00142         g = re_guid.match(t)
00143 
00144         if name == None and n:
00145             name = n.group(1)
00146         if guid == None and g:
00147             guid = g.group(1)
00148 
00149         if name and guid:
00150             break
00151     fd.close()
00152     return {"Name": name, "GUID": guid, "FileName": fname}
00153 
00154 def get_dependencies(fname):
00155     if fname == None: return {}
00156     depdic = {}
00157     fd = open(fname, "r")
00158     for l in fd.readlines():
00159         (key, val) = l.split(":")
00160         vals = val.split()
00161         depdic[key] = vals
00162     return depdic
00163 
00164 def parse_args(argv):
00165     argc = len(argv)
00166     depfile = None
00167     outfile = None
00168     vcversion = "VC8"
00169     flist = []
00170     i = 0
00171     while i < argc:
00172         opt = argv[i]
00173         if opt == "--dep":
00174             i += 1
00175             if i < argc: depfile = argv[i]
00176             else: raise InvalidOption(opt + " needs value")
00177         elif opt == "--output" or opt == "--out":
00178             i += 1
00179             if i < argc: outfile = argv[i]
00180             else: raise InvalidOption(opt + " needs value")
00181         elif opt == "--vcversion":
00182             i += 1
00183             if i < argc: vcversion = argv[i]
00184             else: raise InvalidOption(opt + " needs value")
00185             if not vcversions.has_key(vcversion):
00186                 allowedvers = vcversions.keys().__repr__()
00187                 raise InvalidOption("allowed vcversions are " + allowedvers)
00188         else:
00189             while i < argc and argv[i][:2] != "--":
00190                 flist.append(argv[i])
00191                 i += 1
00192         i += 1
00193     return (vcversion, depfile, outfile, flist)
00194 
00195 def get_slnyaml(depfile, projfiles):
00196     depdict = get_dependencies(depfile)
00197     projs = []
00198     projlist = """Projects:
00199 """
00200     for f in projfiles:
00201         pj = get_projinfo(f)
00202         if depdict.has_key(pj["Name"]):
00203             pj["Depend"] = depdict[pj["Name"]]
00204         projs.append(pj)
00205     def depsort(d0, d1):
00206         """
00207         d0  < d1: return -1 
00208         d0 == d1: return  0 
00209         d0  > d1: return  1 
00210         """
00211         d0_depends = d0.has_key("Depend")
00212         d1_depends = d1.has_key("Depend")
00213         if not d0_depends and not d1_depends:
00214             # both d0, d1 has no dependency 
00215             return 0
00216 
00217         if not d0_depends and d1_depends:
00218             # only "d1" has dependency: d0 < d1
00219             return -1 
00220 
00221         if d0_depends and not d1_depends:
00222             # only "d0" has dependency: d1 < d0
00223             return 1 
00224 
00225         # d0 and d1 has dependency
00226         d0_in_dep = depdict.has_key(d0["Name"])
00227         d1_in_dep = depdict.has_key(d1["Name"])
00228         if not d0_in_dep and not d1_in_dep:
00229             return 0
00230         if not d0_in_dep and d1_in_dep:
00231             return -1
00232         if d0_in_dep and not d1_in_dep:
00233             return 1
00234         
00235         # both d0 and d1 have several dependency
00236         if depdict[d0["Name"]].count(d1["Name"]) > 0:
00237             return 1
00238         if depdict[d1["Name"]].count(d0["Name"]) > 0:
00239             return -1
00240         return 0
00241 
00242     projs.sort(depsort)
00243     for pj in projs:
00244         list = """  - Name: %s
00245     FileName: %s
00246     GUID: &%s %s
00247     Depend:
00248 """ % (pj["Name"], pj["FileName"], pj["Name"], pj["GUID"])
00249         if pj.has_key("Depend"):
00250             for dep in pj["Depend"]:
00251                 dep = """      - *%s
00252 """ % (dep)
00253                 list += dep
00254         projlist += list
00255     yaml_text = sln_yaml + projlist
00256     return yaml_text
00257         
00258 def get_slnyaml(depfile, projfiles, vcversion):
00259     depdict = get_dependencies(depfile)
00260     projs = []
00261     projlist = """Projects:
00262 """
00263     for f in projfiles:
00264         pj = get_projinfo(f, vcversion)
00265         if depdict.has_key(pj["Name"]):
00266             pj["Depend"] = depdict[pj["Name"]]
00267         projs.append(pj)
00268     def depsort(d0, d1):
00269         """
00270         d0  < d1: return -1 
00271         d0 == d1: return  0 
00272         d0  > d1: return  1 
00273         """
00274         d0_depends = d0.has_key("Depend")
00275         d1_depends = d1.has_key("Depend")
00276         if not d0_depends and not d1_depends:
00277             # both d0, d1 has no dependency 
00278             return 0
00279 
00280         if not d0_depends and d1_depends:
00281             # only "d1" has dependency: d0 < d1
00282             return -1 
00283 
00284         if d0_depends and not d1_depends:
00285             # only "d0" has dependency: d1 < d0
00286             return 1 
00287 
00288         # d0 and d1 has dependency
00289         d0_in_dep = depdict.has_key(d0["Name"])
00290         d1_in_dep = depdict.has_key(d1["Name"])
00291         if not d0_in_dep and not d1_in_dep:
00292             return 0
00293         if not d0_in_dep and d1_in_dep:
00294             return -1
00295         if d0_in_dep and not d1_in_dep:
00296             return 1
00297         
00298         # both d0 and d1 have several dependency
00299         if depdict[d0["Name"]].count(d1["Name"]) > 0:
00300             return 1
00301         if depdict[d1["Name"]].count(d0["Name"]) > 0:
00302             return -1
00303         return 0
00304 
00305     projs.sort(depsort)
00306     for pj in projs:
00307         list = """  - Name: %s
00308     FileName: %s
00309     GUID: &%s %s
00310     Depend:
00311 """ % (pj["Name"], pj["FileName"], pj["Name"], pj["GUID"])
00312         if pj.has_key("Depend"):
00313             for dep in pj["Depend"]:
00314                 dep = """      - *%s
00315 """ % (dep)
00316                 list += dep
00317         projlist += list
00318     yaml_text = sln_yaml + projlist
00319     return yaml_text
00320 
00321 def gen_solution(version, yaml_text):
00322 
00323     dict = yaml.load(yaml_text)
00324     t = yat.Template(sln_template 
00325                      % (vcversions[version]["sln"],
00326                         vcversions[version]["vc"]))
00327     return t.generate(dict).replace("\r\n", "\n").replace("\n", "\r\n")
00328 
00329 
00330 class SlnToolException:
00331     pass
00332 
00333 class InvalidOption(SlnToolException):
00334     def __init__(self, msg):
00335         self.msg = "Error: InvalidOption:\n    "
00336         self.msg += msg
00337 
00338 #------------------------------------------------------------
00339 # main function
00340 #------------------------------------------------------------
00341 def main(argv):
00342     if len(argv) == 0:
00343         usage()
00344         sys.exit(-1)
00345     try:
00346         res = parse_args(argv)
00347     except SlnToolException, e:
00348         print "\n" + e.msg + "\n"
00349         usage()
00350         sys.exit(-1)
00351 
00352     version = res[0]
00353     depfile = res[1]
00354     outfile = res[2]
00355     flist   = res[3]
00356     #sln_text = gen_solution(version, get_slnyaml(depfile, flist))
00357     sln_text = gen_solution(version, get_slnyaml(depfile, flist, version))
00358 
00359     if outfile == None:
00360         fd = sys.stdout
00361     else:
00362         fd = open(outfile, "wb")
00363 
00364     fd.write(sln_text)
00365 
00366 #------------------------------------------------------------
00367 # tests
00368 #------------------------------------------------------------
00369 def test_getprojinfo():
00370     for f in sys.argv[1:]:
00371         print get_projinfo(f)
00372 
00373 def test_getdep():
00374     print get_dependencies(sys.argv[1])
00375 
00376 def test_getslnyaml():
00377     print gen_solution(get_slnyaml("dep.yaml", sys.argv[1:]))
00378 
00379 #------------------------------------------------------------
00380 # entry point
00381 #------------------------------------------------------------
00382 if __name__ == "__main__":
00383     main(sys.argv[1:])
00384     


openrtm_aist
Author(s): Noriaki Ando
autogenerated on Thu Aug 27 2015 14:16:39