00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 import sys
00019 import re
00020 import yaml
00021 import yat
00022
00023
00024
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
00215 return 0
00216
00217 if not d0_depends and d1_depends:
00218
00219 return -1
00220
00221 if d0_depends and not d1_depends:
00222
00223 return 1
00224
00225
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
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
00278 return 0
00279
00280 if not d0_depends and d1_depends:
00281
00282 return -1
00283
00284 if d0_depends and not d1_depends:
00285
00286 return 1
00287
00288
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
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
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
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
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
00381
00382 if __name__ == "__main__":
00383 main(sys.argv[1:])
00384