generate.py 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124
  1. #!/usr/bin/python
  2. import sys
  3. import os
  4. import copy
  5. import xml.etree.ElementTree as etree
  6. import uuid
  7. import getopt
  8. import zipfile
  9. import shutil
  10. EXT_MAPPING = { ".c": "c", ".cc": "cpp", ".cpp": "cpp", ".h": "h", ".s": "s"}
  11. def parseError(str):
  12. print("*** error: \""+str+"\"\n");
  13. def platformCompare(a, b):
  14. return cmp(a.count('*'), b.count('*'))
  15. def platformSubseteqTest(a, b):
  16. a4=a.split("-")
  17. b4=b.split("-")
  18. ret=len(a4)==len(b4)
  19. i=0
  20. while i<len(a4) and i<len(b4):
  21. ret=ret and (a4[i]==b4[i] or b4[i]=="*")
  22. i=i+1
  23. # sys.stderr.write("platformSubseteqTest("+a+", "+b+")="+str(ret))
  24. return ret
  25. def parseFile(node, ctx, list):
  26. path=node.attrib["path"]
  27. abs_path=os.path.join(ctx["base"], ctx["root"], path)
  28. # sys.stderr.write "path="+abs_path
  29. filterMatch=True
  30. if "platform" in node.attrib:
  31. filter=node.attrib["platform"]
  32. filterMatch=platformSubseteqTest(ctx["platform"], filter)
  33. if filterMatch:
  34. file_ext=os.path.splitext(path)[1]
  35. if file_ext in EXT_MAPPING:
  36. ext=EXT_MAPPING[file_ext]
  37. if os.path.exists(abs_path):
  38. install=None
  39. if "install" in node.attrib and node.attrib["install"]=="yes":
  40. install=os.path.dirname(os.path.relpath(abs_path, ctx["root"]))
  41. ## sys.stderr.write install
  42. file_item={ "path": abs_path, "ext": ext, "install": install }
  43. if "x" in node.attrib:
  44. file_item["x"]=node.attrib["x"]
  45. list.append(file_item)
  46. else:
  47. parseError("file "+abs_path+" does not exist!")
  48. else:
  49. parseError("extension "+file_ext+" is unknown")
  50. def parseFiles(target, node, ctx):
  51. for child in list(node):
  52. if child.tag=="file":
  53. parseFile(child, ctx, target)
  54. else:
  55. parseError("unhandled element: "+child.tag)
  56. def setAttr(dict, node, tag):
  57. if tag in node.attrib:
  58. dict[tag]=node.attrib[tag]
  59. def fallbackCompare(a, b):
  60. return -cmp(a.count('-'), b.count('-'))
  61. def generateFallbackList(platform):
  62. ret=[]
  63. p4=platform.split("-")
  64. for i in range(1<<len(p4)):
  65. p=""
  66. for j in range(len(p4)):
  67. m=(i&(1<<j))==(1<<j)
  68. # print " "+str(i)+" "+str(j)+" "+str(m)+" "+p
  69. if m:
  70. if len(p)>0:
  71. p=p+"-"
  72. p=p+p4[j]
  73. if len(p)>0:
  74. ret.append(p)
  75. ret.sort(fallbackCompare)
  76. return ret
  77. def updateCtx(conf, ctx, node):
  78. if "root" in node.attrib:
  79. root=ctx["root"]
  80. ctx=copy.copy(ctx)
  81. rel_prj_path=os.path.split(ctx["root"])[1]
  82. prjconfigdir=os.path.join(ctx["config"], rel_prj_path, "config")
  83. # print "rel_prj_path="+rel_prj_path+" prjconfigdir="+prjconfigdir
  84. v=node.attrib["root"].format(platform=ctx["platform"], config=os.path.join(ctx["config"], "config"), prjconfig=prjconfigdir)
  85. f=node.attrib["root"].format(platform="{platform}", config=os.path.join(ctx["config"], "config"), prjconfig=prjconfigdir)
  86. if v!=f:
  87. conf["format"][os.path.join(root, v)]=os.path.join(root, f)
  88. ctx_root=os.path.join(root, v)
  89. if not os.path.exists(ctx_root):
  90. list=generateFallbackList(ctx["platform"])
  91. for p in list:
  92. v=node.attrib["root"].format(platform=p, config=os.path.join(ctx["config"], "config"), prjconfig=prjconfigdir)
  93. if os.path.exists(os.path.join(root, v)):
  94. map=os.path.join(root, v)
  95. conf["mapping"][map]=ctx_root
  96. ctx_root=map
  97. list=[]
  98. if not os.path.exists(ctx_root) and "platforms" in conf and ctx["platform"] in conf["platforms"] and "family" in conf["platforms"][ctx["platform"]]:
  99. family=conf["platforms"][ctx["platform"]]["family"]
  100. list=generateFallbackList(family)
  101. # print "list="+str(list)
  102. for p in list:
  103. v=node.attrib["root"].format(platform=p, config=os.path.join(ctx["config"], "config"), prjconfig= prjconfigdir)
  104. if os.path.exists(os.path.join(root, v)):
  105. map=os.path.join(root, v)
  106. conf["mapping"][map]=ctx_root
  107. ctx_root=map
  108. list=[]
  109. ctx["root"]=ctx_root
  110. return ctx
  111. def parseDefines(ctx, node, dict):
  112. value=None
  113. if "value" in node.attrib:
  114. value=node.attrib["value"]
  115. if "name" in node.attrib:
  116. name=node.attrib["name"]
  117. dict[name]=value
  118. else:
  119. parseError("define syntax invalid ("+nv+")");
  120. def parseSettings(conf, node, ctx, lib):
  121. if node.tag=="settings":
  122. tag="defines"
  123. elif node.tag=="export":
  124. tag="exports"
  125. else:
  126. parseError("unknown setting: "+node.tag);
  127. for child in list(node):
  128. if child.tag=="define":
  129. parseDefines(ctx, child, lib[tag])
  130. else:
  131. parseError("unhanded element: "+child.tag)
  132. def parseDeps(node):
  133. if "dep" in node.attrib:
  134. dep=node.attrib["dep"].split()
  135. return dep
  136. else:
  137. return []
  138. def parseLibrary(conf, node, ctx, seq_type):
  139. lib_name=node.attrib["name"]
  140. lib_uuid=uuid.uuid5(uuid.NAMESPACE_URL, "urn:lib:"+lib_name)
  141. lib={"name": lib_name, "uuid": lib_uuid, "source": { "files": []}, "header": { "files": [], "target": "", "includes": [] }, "defines": {}, "exports": {}, "deps": parseDeps(node), "mode": "c90", "align": "", "external": False }
  142. ctx=updateCtx(conf, ctx, node)
  143. setAttr(lib, node, "mode")
  144. setAttr(lib, node, "align")
  145. if not(lib_name in ctx["externals"]) or not("external" in ctx["externals"][lib_name]) or not(ctx["externals"][lib_name]["external"]):
  146. for child in list(node):
  147. if child.tag=="source":
  148. parseFiles(lib["source"]["files"], list(child), updateCtx(conf, ctx, child))
  149. elif child.tag=="header":
  150. setAttr(lib["header"], child, "target")
  151. child_ctx=updateCtx(conf, ctx, child)
  152. lib["header"]["includes"].append(child_ctx["root"])
  153. parseFiles(lib["header"]["files"], list(child), child_ctx)
  154. elif child.tag=="settings":
  155. parseSettings(conf, child, ctx, lib)
  156. elif child.tag=="export":
  157. parseSettings(conf, child, ctx, lib)
  158. else:
  159. parseError("unhanded element: "+child.tag)
  160. else:
  161. sys.stderr.write("using external "+lib_name)
  162. lib["external"]=True
  163. conf[seq_type].append(lib)
  164. def isExcluded(conf, ctx, lib):
  165. # sys.stderr.write conf["platforms"]
  166. if ctx["platform"] in conf["platforms"]:
  167. platform=conf["platforms"][ctx["platform"]]
  168. return lib in platform["exclude"]
  169. else:
  170. return False
  171. def parsePlatform(conf, node, ctx):
  172. if "name" in node.attrib:
  173. name=node.attrib["name"]
  174. platform={ "exclude": {}, "libs": [], "ldflags": "" }
  175. setAttr(platform, node, "family")
  176. setAttr(platform, node, "cc")
  177. setAttr(platform, node, "ar")
  178. setAttr(platform, node, "ld")
  179. setAttr(platform, node, "cflags")
  180. setAttr(platform, node, "cflags_c")
  181. setAttr(platform, node, "cflags_cpp")
  182. setAttr(platform, node, "cppflags")
  183. setAttr(platform, node, "ldflags")
  184. setAttr(platform, node, "host")
  185. if "exclude" in node.attrib:
  186. for prj in node.attrib["exclude"].split(" "):
  187. platform["exclude"][prj]=None
  188. # sys.stderr.write platform["exclude"]
  189. if "libs" in node.attrib:
  190. platform["libs"].extend(node.attrib["libs"].split(" "))
  191. conf["platforms"][name]=platform
  192. else:
  193. parseError("no name given for platform")
  194. def parseTargets(conf, node, ctx):
  195. for child in list(node):
  196. if child.tag=="include":
  197. path=os.path.abspath(os.path.join(ctx["root"], child.attrib["path"]))
  198. new_ctx=copy.copy(ctx)
  199. new_ctx["root"]=os.path.dirname(path)
  200. parseConfiguration(conf, path, new_ctx)
  201. elif child.tag=="library":
  202. parseLibrary(conf, child, ctx, "libraries")
  203. elif child.tag=="tool":
  204. parseLibrary(conf, child, ctx, "tools")
  205. elif child.tag=="platform":
  206. parsePlatform(conf, child, ctx)
  207. else:
  208. parseError("unhanded element: "+child.tag)
  209. def parseConfiguration(conf, filename, ctx):
  210. sys.stderr.write("parsing "+filename+"\n")
  211. tree=etree.parse(filename)
  212. if tree is not None:
  213. parseTargets(conf, tree.getroot(), ctx)
  214. else:
  215. parseError("failed to open file \""+filename+"\"")
  216. def depClosure2(conf, deps, ignoreExternal):
  217. ret=[]
  218. gray=set(deps)
  219. black=set()
  220. while len(gray)>0:
  221. for lib in conf["libraries"]:
  222. if lib["name"] in gray:
  223. gray.remove(lib["name"])
  224. black.add(lib["name"])
  225. if not(ignoreExternal) or not(lib["external"]):
  226. ret.append((lib, []))
  227. lib_deps=lib["deps"]
  228. for lib_dep in lib_deps:
  229. if not lib_dep in black:
  230. gray.add(lib_dep)
  231. return ret
  232. def depCompare(a, b):
  233. if a[0] in b[1]:
  234. return 1
  235. elif b[0] in a[1]:
  236. return -1
  237. else:
  238. return 0
  239. def depClosureStr(req_deps, deps):
  240. ret="depClosure("+str(req_deps)+") ="
  241. for lib in deps:
  242. ret=ret+" "+lib[0]["name"]+"<"
  243. for x in lib[1]:
  244. ret=ret+" "+x[0]["name"]
  245. ret=ret+" >"
  246. return ret
  247. def depClosure(conf, req_deps, ignoreExternal):
  248. deps=depClosure2(conf, req_deps, ignoreExternal)
  249. for lib in deps:
  250. lib[1].extend(depClosure2(conf, lib[0]["deps"], ignoreExternal))
  251. # print depClosureStr(req_deps, deps)
  252. # deps.sort(depCompare)
  253. # print depClosureStr(req_deps, deps)
  254. ret=[]
  255. for lib in deps:
  256. ret.append(lib[0]["name"])
  257. # print "\n"
  258. return ret
  259. def gatherIncludeDirs(conf, ctx, deps):
  260. ret=[]
  261. aux={}
  262. for lib in conf["libraries"]:
  263. if lib["name"] in deps:
  264. for file in lib["header"]["files"]:
  265. if file["install"] is not None:
  266. dir=os.path.dirname(file["path"])
  267. dir=os.path.abspath(dir.rstrip(file["install"]))
  268. dir=os.path.relpath(dir, ctx["base"])
  269. if dir not in aux:
  270. aux[dir]=None
  271. ret.append(dir)
  272. # sys.stderr.write ret
  273. return ret
  274. def gatherSources(conf, ctx, lib):
  275. sources=[]
  276. for file in lib["source"]["files"]:
  277. rel_source=os.path.relpath(file["path"], ctx["base"])
  278. sources.append((rel_source, file))
  279. return sources
  280. #def generateOBJS(conf, ctx, lib, out, obj_dir, cppflags):
  281. # objs=[]
  282. # for file in lib["source"]["files"]:
  283. # rel_source=os.path.relpath(file["path"], ctx["base"])
  284. # rel_obj=os.path.join(obj_dir, os.path.splitext(rel_source)[0]+".o")
  285. # out_dir=os.path.dirname(rel_obj)
  286. # out.write(rel_obj+": "+rel_source+"\n")
  287. # out.write("\t@mkdir -p "+out_dir+"\n")
  288. # specific=""
  289. # if file["ext"]=="c":
  290. # specific ="$(CFLAGS_C) "
  291. # elif file["ext"]=="cpp":
  292. # specific ="$(CFLAGS_CPP) "
  293. # out.write("\t$(CC) -c $(CFLAGS) "+ specific +"$(CPPFLAGS)"+cppflags+" "+ rel_source+" -o "+rel_obj+"\n")
  294. # objs.append(rel_obj)
  295. # return objs
  296. def generateDEPS(conf, ctx, lib, out, obj_dir, cppflags, filename):
  297. for file in lib["source"]["files"]:
  298. rel_source=os.path.relpath(file["path"], ctx["base"])
  299. specific=""
  300. if file["ext"]=="c":
  301. specific ="$(CFLAGS_C) "
  302. elif file["ext"]=="cpp":
  303. specific ="$(CFLAGS_CPP) "
  304. out.write("\tmakedepend -a -f"+filename+" $(CPPFLAGS)"+cppflags+" "+ rel_source+"\n")
  305. def generateCPPFLAGS(conf, ctx, lib, build_dir):
  306. cppflags=""
  307. for define in lib["defines"]:
  308. if lib["defines"][define] is None:
  309. cppflags=cppflags+" -D"+define
  310. else:
  311. cppflags=cppflags+" -D"+define+"="+lib["defines"][define]
  312. for dir in lib["header"]["includes"]:
  313. abs_dir=os.path.abspath(dir)
  314. rel_dir=os.path.relpath(abs_dir, os.path.join(ctx["base"], build_dir))
  315. # sys.stderr.write("abs_dir="+str(abs_dir)+" build_dir="+os.path.join(ctx["base"], build_dir)+" rel_dir="+str(rel_dir))
  316. cppflags=cppflags+" -I"+rel_dir
  317. dep_closure=depClosure(conf, lib["deps"], False)
  318. dep_dirs=gatherIncludeDirs(conf, ctx, dep_closure)
  319. for dir in dep_dirs:
  320. abs_dir=os.path.abspath(dir)
  321. rel_dir=os.path.relpath(abs_dir, os.path.join(ctx["base"], build_dir))
  322. # sys.stderr.write("abs_dir="+str(abs_dir)+" build_dir="+os.path.join(ctx["base"], build_dir)+" rel_dir="+str(rel_dir))
  323. cppflags=cppflags+" -I"+rel_dir
  324. for dep_lib in conf["libraries"]:
  325. if dep_lib["name"] in ctx["externals"]:
  326. ext_lib=ctx["externals"][dep_lib["name"]]
  327. if "external" in ext_lib and ext_lib["external"]:
  328. if "cppflags" in ext_lib:
  329. cppflags=cppflags+" "+ext_lib["cppflags"]
  330. return cppflags
  331. def generateVCXPROJ(conf, ctx, lib, type):
  332. filename=os.path.abspath("win32\\"+lib["name"]+"\\"+lib["name"]+".vcxproj")
  333. filepath=os.path.dirname(filename)
  334. prj_uuid=lib["uuid"]
  335. sys.stderr.write("generating "+filename+"\n")
  336. try:
  337. os.makedirs(os.path.dirname(filename))
  338. except OSError:
  339. pass
  340. out=open(filename, "w")
  341. out.write("<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
  342. out.write("<ItemGroup Label=\"ProjectConfigurations\">\n");
  343. out.write(" <ProjectConfiguration Include=\"Debug|Win32\">\n");
  344. out.write(" <Configuration>Debug</Configuration>\n");
  345. out.write(" <Platform>Win32</Platform>\n");
  346. out.write(" </ProjectConfiguration>\n");
  347. out.write("<ProjectConfiguration Include=\"Release|Win32\">\n");
  348. out.write(" <Configuration>Release</Configuration>\n");
  349. out.write(" <Platform>Win32</Platform>\n");
  350. out.write("</ProjectConfiguration>\n");
  351. out.write("</ItemGroup>\n");
  352. out.write("<PropertyGroup Label=\"Globals\">\n");
  353. out.write(" <ProjectGuid>{"+str(prj_uuid)+"}</ProjectGuid>\n");
  354. out.write(" <Keyword>Win32Proj</Keyword>\n");
  355. out.write(" <RootNamespace>"+lib["name"]+"</RootNamespace>\n");
  356. out.write("</PropertyGroup>\n");
  357. out.write("<Import Project=\"$(VCTargetsPath)\Microsoft.Cpp.default.props\" />\n");
  358. out.write(" <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n");
  359. out.write(" <ConfigurationType>"+type+"</ConfigurationType>\n");
  360. out.write(" <UseDebugLibraries>true</UseDebugLibraries>\n");
  361. out.write(" <CharacterSet>Unicode</CharacterSet>\n");
  362. out.write(" </PropertyGroup>\n");
  363. out.write(" <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n");
  364. out.write(" <ConfigurationType>"+type+"</ConfigurationType>\n");
  365. out.write(" <UseDebugLibraries>false</UseDebugLibraries>\n");
  366. out.write(" <WholeProgramOptimization>true</WholeProgramOptimization>\n");
  367. out.write(" <CharacterSet>Unicode</CharacterSet>\n");
  368. out.write(" </PropertyGroup>\n");
  369. out.write("<Import Project=\"$(VCTargetsPath)\Microsoft.Cpp.props\" />\n");
  370. out.write("<ImportGroup Label=\"ExtensionSettings\" />\n");
  371. out.write("<ImportGroup Label=\"PropertySheets\" />\n");
  372. out.write("<PropertyGroup Label=\"UserMacros\" />\n");
  373. out.write("<PropertyGroup />\n");
  374. out.write("<ItemDefinitionGroup>\n");
  375. out.write("<ClCompile>\n");
  376. dep_closure=depClosure(conf, lib["deps"], False)
  377. cpp_defs="WIN32;"
  378. for define in lib["defines"]:
  379. if lib["defines"][define] is None:
  380. cpp_defs=cpp_defs+define+";"
  381. else:
  382. cpp_defs=cpp_defs+define+"="+lib["defines"][define]+";"
  383. for dep in dep_closure:
  384. for dep_lib in conf["libraries"]:
  385. if dep_lib["name"]==dep and not isExcluded(conf, ctx, dep):
  386. for define in dep_lib["exports"]:
  387. if dep_lib["exports"][define] is None:
  388. cpp_defs=cpp_defs+define+";"
  389. else:
  390. cpp_defs=cpp_defs+define+"="+dep_lib["defines"][define]+";"
  391. cpp_defs=cpp_defs+"_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)"
  392. out.write("<PreprocessorDefinitions>"+cpp_defs+"</PreprocessorDefinitions>\n" )
  393. AdditionalIncludeDirectories=""
  394. for dir in lib["header"]["includes"]:
  395. AdditionalIncludeDirectories=AdditionalIncludeDirectories+os.path.relpath(os.path.abspath(dir), filepath)+";"
  396. dep_dirs=gatherIncludeDirs(conf, ctx, dep_closure)
  397. for dir in dep_dirs:
  398. abs_path=os.path.relpath(os.path.abspath(dir), filepath)
  399. AdditionalIncludeDirectories=AdditionalIncludeDirectories+abs_path+";"
  400. AdditionalIncludeDirectories=AdditionalIncludeDirectories+"%(AdditionalIncludeDirectories)"
  401. out.write("<AdditionalIncludeDirectories>"+AdditionalIncludeDirectories+"</AdditionalIncludeDirectories>\n")
  402. if "c99"==lib["mode"]:
  403. out.write("<CompileAs>CompileAsCpp</CompileAs>\n");
  404. if ""!=lib["align"]:
  405. out.write("<StructMemberAlignment>"+lib["align"]+"Byte</StructMemberAlignment>\n");
  406. out.write("</ClCompile>\n");
  407. if "Application"==type:
  408. out.write("<Link>\n");
  409. out.write("<AdditionalDependencies>")
  410. if ctx["platform"] in conf["platforms"]:
  411. ext_libs=conf["platforms"][ctx["platform"]]["libs"]
  412. else:
  413. ext_libs={}
  414. # sys.stderr.write ext_libs
  415. for ext_lib in ext_libs:
  416. # sys.stderr.write ext_lib
  417. out.write(ext_lib+";")
  418. out.write("%(AdditionalDependencies)</AdditionalDependencies> \n")
  419. out.write("</Link>\n");
  420. out.write("</ItemDefinitionGroup>\n");
  421. out.write("<ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n")
  422. out.write("<ClCompile>\n");
  423. out.write("<WarningLevel>Level3</WarningLevel>\n")
  424. out.write("<Optimization>Disabled</Optimization>\n")
  425. out.write("<DisableSpecificWarnings>4996</DisableSpecificWarnings>\n")
  426. out.write("</ClCompile>\n");
  427. if "Application"==type:
  428. out.write("<Link>\n");
  429. out.write("<GenerateDebugInformation>true</GenerateDebugInformation>\n")
  430. out.write("<SubSystem>Console</SubSystem>\n")
  431. out.write("</Link>\n");
  432. out.write("</ItemDefinitionGroup>\n");
  433. out.write("<ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n")
  434. out.write("<ClCompile>\n")
  435. out.write("<Optimization>MaxSpeed</Optimization>\n")
  436. out.write("<DisableSpecificWarnings>4996</DisableSpecificWarnings>\n")
  437. out.write("<FunctionLevelLinking>true</FunctionLevelLinking> \n")
  438. out.write("<IntrinsicFunctions>true</IntrinsicFunctions> \n")
  439. out.write("</ClCompile>\n");
  440. if "Application"==type:
  441. out.write("<Link>\n");
  442. out.write("<GenerateDebugInformation>false</GenerateDebugInformation>\n")
  443. out.write("<SubSystem>Console</SubSystem>\n")
  444. out.write("<EnableCOMDATFolding>true</EnableCOMDATFolding>\n")
  445. out.write("<OptimizeReferences>true</OptimizeReferences>\n")
  446. out.write("</Link>\n");
  447. out.write("</ItemDefinitionGroup>\n");
  448. out.write("<ItemGroup>\n");
  449. for file in lib["header"]["files"]:
  450. if "h"==file["ext"]:
  451. out.write(" <ClInclude Include=\""+os.path.relpath(file["path"], filepath)+"\"/>\n");
  452. out.write("</ItemGroup>\n");
  453. out.write("<ItemGroup>\n");
  454. for file in lib["source"]["files"]:
  455. if "cpp"==file["ext"] or "c"==file["ext"] or "s"==file["ext"]:
  456. out.write(" <ClCompile Include=\""+os.path.relpath(file["path"], filepath)+"\">\n");
  457. out.write(" </ClCompile>\n");
  458. out.write("</ItemGroup>\n");
  459. out.write("<ItemGroup>\n");
  460. for dep in dep_closure:
  461. for dep_lib in conf["libraries"]:
  462. if dep_lib["name"]==dep and not isExcluded(conf, ctx, dep_lib["name"]):
  463. out.write("<ProjectReference Include=\"../"+dep_lib["name"]+"/"+dep_lib["name"]+".vcxproj\">\n")
  464. out.write("<Project>{"+str(dep_lib["uuid"])+"}</Project>\n")
  465. out.write("</ProjectReference>\n")
  466. out.write("</ItemGroup>\n")
  467. out.write("<Import Project=\"$(VCTargetsPath)\Microsoft.Cpp.targets\" />\n");
  468. out.write("<ImportGroup Label=\"ExtensionTargets\" />\n");
  469. out.write("</Project>\n");
  470. out.close()
  471. def writeProject(out, solution_uuid, lib):
  472. out.write("Project(\"{"+str(solution_uuid)+"}\") = \""+lib["name"]+"\", \""+lib["name"]+"\\"+lib["name"]+".vcxproj\", \"{"+str(lib["uuid"])+"}\"\n")
  473. out.write("EndProject\n")
  474. def generatePlatformList(conf, ctx):
  475. add=[]
  476. for platform in conf["platforms"]:
  477. if platformSubseteqTest(ctx["platform"], platform):
  478. add.append(platform)
  479. #add.sort(platformCompare)
  480. add.sort()
  481. return add
  482. def generateConfiguration(ctx, includes, platform):
  483. conf={ "libraries": [], "tools": [], "platforms": {}, "mapping": {}, "format": {} }
  484. ctx["platform"]=platform
  485. for include in includes:
  486. parseConfiguration(conf, include, ctx)
  487. if ctx["platform"] not in conf["platforms"]:
  488. add=generatePlatformList(conf, ctx);
  489. if len(add)>0:
  490. conf["platforms"][ctx["platform"]]=conf["platforms"][add[0]]
  491. return conf
  492. def generateWin32(ctx, source):
  493. platform=ctx["platforms"][0]
  494. conf=generateConfiguration(ctx, [source], platform)
  495. sys.stderr.write("generate win32 project")
  496. for lib in conf["libraries"]:
  497. if not isExcluded(conf, ctx, lib["name"]):
  498. generateVCXPROJ(conf, ctx, lib, "StaticLibrary")
  499. for tool in conf["tools"]:
  500. if not isExcluded(conf, ctx, tool["name"]):
  501. generateVCXPROJ(conf, ctx, tool, "Application")
  502. solution_file=os.path.abspath("win32\\solution.sln")
  503. solution_uuid=uuid.uuid5(uuid.NAMESPACE_URL, solution_file)
  504. out=open(solution_file, "w")
  505. out.write("\n")
  506. out.write("Microsoft Visual Studio Solution File, Format Version 11.00\n")
  507. for lib in conf["libraries"]:
  508. if not isExcluded(conf, ctx, lib["name"]):
  509. writeProject(out, solution_uuid, lib)
  510. for tool in conf["tools"]:
  511. if not isExcluded(conf, ctx, tool["name"]):
  512. writeProject(out, solution_uuid, tool)
  513. out.write("\n")
  514. out.close()
  515. def writeSourceRules(conf, ctx, lib_type, out, lib, build_dir):
  516. dirs={}
  517. sources=gatherSources(conf, ctx, lib)
  518. out.write("objs_"+lib["name"]+"=\\\n")
  519. for source in sources:
  520. out.write(" $(BUILD_DIR)/"+os.path.splitext(source[0])[0]+".o\\\n")
  521. dirs[os.path.dirname(source[0])]=None
  522. out.write(" \n")
  523. out.write(lib["name"]+"_includes="+generateCPPFLAGS(conf, ctx, lib, build_dir)+"\n")
  524. out.write("\n")
  525. includes="$("+lib["name"]+"_includes)"
  526. lib_type_flags=""
  527. if lib_type=="shared":
  528. if platformSubseteqTest(ctx["platform"], "linux-*-gcc-*"):
  529. lib_type_flags=" -fPIC -DPIC"
  530. elif platformSubseteqTest(ctx["platform"], "darwin-*-gcc-*"):
  531. lib_type_flags=" -fno-common"
  532. # write special rules
  533. for source in sources:
  534. file=source[1]
  535. if "x" in file:
  536. special="-x "+file["x"]+" "
  537. out.write("$(BUILD_DIR)/"+os.path.splitext(source[0])[0]+".o: $(SRC_DIR)/"+source[0]+"\n")
  538. out.write("\t@mkdir -p $(dir $@)\n")
  539. out.write("\t$(CC) $(CFLAGS) $(CFLAGS_C) $(CPPFLAGS) "+special+includes+lib_type_flags+" -c \"$<\" -o \"$@\"\n")
  540. # write generic rules
  541. for dir in dirs:
  542. for ext in EXT_MAPPING:
  543. if EXT_MAPPING[ext]=='c' or EXT_MAPPING[ext]=='s':
  544. out.write("$(BUILD_DIR)/"+dir+"/%.o: $(SRC_DIR)/"+dir+"/%"+ext+"\n")
  545. out.write("\t@mkdir -p $(dir $@)\n")
  546. out.write("\t$(CC) $(CFLAGS) $(CFLAGS_C) $(CPPFLAGS) "+includes+lib_type_flags+" -c \"$<\" -o \"$@\"\n")
  547. out.write("\n")
  548. elif EXT_MAPPING[ext]=='cpp':
  549. out.write("$(BUILD_DIR)/"+dir+"/%.o: $(SRC_DIR)/"+dir+"/%"+ext+"\n")
  550. out.write("\t@mkdir -p $(dir $@)\n")
  551. out.write("\t$(CC) $(CFLAGS) $(CFLAGS_CPP) $(CPPFLAGS) "+includes+lib_type_flags+" -c \"$<\" -o \"$@\"\n")
  552. out.write("\n")
  553. def writeMakefileFlags(conf, ctx, out):
  554. platform=ctx["platform"]
  555. out.write("CC="+conf["platforms"][platform]["cc"]+"\n");
  556. out.write("AR="+conf["platforms"][platform]["ar"]+"\n");
  557. out.write("CFLAGS="+conf["platforms"][platform]["cflags"]+"\n")
  558. out.write("CFLAGS_C="+conf["platforms"][platform]["cflags_c"]+"\n")
  559. out.write("CFLAGS_CPP="+conf["platforms"][platform]["cflags_cpp"]+"\n")
  560. out.write("CPPFLAGS="+conf["platforms"][platform]["cppflags"]+"\n");
  561. out.write("LDFLAGS="+conf["platforms"][platform]["ldflags"]+"\n");
  562. def getSharedExt(conf, ctx):
  563. if platformSubseteqTest(ctx["platform"], "darwin-*-gcc-*"):
  564. return ".dylib"
  565. else:
  566. return ".so"
  567. def generateExtLDFlags(conf, ctx):
  568. ext_ldflags=""
  569. for dep_lib in conf["libraries"]:
  570. if dep_lib["name"] in ctx["externals"]:
  571. ext_lib=ctx["externals"][dep_lib["name"]]
  572. if "external" in ext_lib and ext_lib["external"]:
  573. if "ldflags" in ext_lib:
  574. ext_ldflags=ext_ldflags+" "+ext_lib["ldflags"]
  575. return ext_ldflags
  576. def generateLDFlags(conf, ctx, lib_type, initial_deps, exclude_deps, lib_form):
  577. ret=""
  578. deps=depClosure(conf, initial_deps, True)
  579. for dep in deps:
  580. if not(dep in exclude_deps):
  581. if lib_type=="static":
  582. ret=ret+" $(BUILD_DIR)/lib"+dep+".a"
  583. if lib_type=="shared":
  584. if lib_form:
  585. ret=ret+" -L$(BUILD_DIR) -l"+dep
  586. else:
  587. ret=ret+" $(BUILD_DIR)/lib"+dep+getSharedExt(conf, ctx)
  588. return ret
  589. def generateLibraryMakefile(conf, ctx, lib_type, lib, filename, build_dir, src_dir):
  590. sys.stderr.write("generating "+filename+"\n")
  591. if not os.path.exists(os.path.dirname(filename)):
  592. os.makedirs(os.path.dirname(filename))
  593. out=open(filename, "w")
  594. out.write("# Generated.\n")
  595. # compiler flags
  596. writeMakefileFlags(conf, ctx, out)
  597. out.write("BUILD_DIR=.\n")
  598. out.write("SRC_DIR="+src_dir+"\n")
  599. out.write("\n")
  600. out.write(".PHONY: all clean\n")
  601. out.write("\n")
  602. out.write("# library "+lib["name"]+"\n")
  603. out.write("all:")
  604. if lib_type=="static":
  605. out.write(" $(BUILD_DIR)/lib"+lib["name"]+".a")
  606. if lib_type=="shared":
  607. out.write(" $(BUILD_DIR)/lib"+lib["name"]+getSharedExt(conf, ctx))
  608. out.write("\n\n")
  609. writeSourceRules(conf, ctx, lib_type, out, lib, build_dir)
  610. if lib_type=="static":
  611. out.write("$(BUILD_DIR)/lib"+lib["name"]+".a: $(objs_"+lib["name"]+")\n")
  612. out.write("\t$(AR) -rcs $(BUILD_DIR)/lib"+lib["name"]+".a $(objs_"+lib["name"]+")\n")
  613. out.write("\n")
  614. if lib_type=="shared":
  615. ld_deps=generateLDFlags(conf, ctx, lib_type, lib["deps"], [lib["name"]], True)+generateExtLDFlags(conf, ctx)
  616. out.write("$(BUILD_DIR)/lib"+lib["name"]+getSharedExt(conf, ctx)+": $(objs_"+lib["name"]+")\n")
  617. if platformSubseteqTest(ctx["platform"], "darwin-*-gcc-*"):
  618. out.write("\t$(CC) -dynamiclib -install_name lib"+lib["name"]+getSharedExt(conf, ctx)+" -o $(BUILD_DIR)/lib"+lib["name"]+getSharedExt(conf, ctx)+" $(objs_"+lib["name"]+")"+ld_deps+"\n")
  619. else:
  620. out.write("\t$(CC) -shared -Wl,-soname,lib"+lib["name"]+getSharedExt(conf, ctx)+" -Wl,-z,defs -fPIC -o $(BUILD_DIR)/lib"+lib["name"]+getSharedExt(conf, ctx)+" $(objs_"+lib["name"]+")"+ld_deps+" -lc\n")
  621. out.write("\tstrip --remove-section=.comment --remove-section=.note --strip-unneeded $(BUILD_DIR)/lib"+lib["name"]+getSharedExt(conf, ctx))
  622. out.write("\n")
  623. out.write("clean:\n")
  624. out.write("\trm -rf $(BUILD_DIR)/lib"+lib["name"]+".a $(BUILD_DIR)/lib"+lib["name"]+getSharedExt(conf, ctx)+" $(objs_"+lib["name"]+")\n")
  625. out.close()
  626. def generateLibraryInclude(conf, ctx, lib, filename, build_dir, src_dir):
  627. sys.stderr.write("generating "+filename+"\n")
  628. if not os.path.exists(os.path.dirname(filename)):
  629. os.makedirs(os.path.dirname(filename))
  630. ret=[]
  631. lib_deps=lib["deps"]
  632. lib_deps.append(lib["name"])
  633. # out.write("deps="+str(lib["deps"])+"\n");
  634. dep_closure=depClosure(conf, lib_deps, False)
  635. dep_dirs=gatherIncludeDirs(conf, ctx, dep_closure)
  636. for dep in dep_dirs:
  637. dep_dir=os.path.join(ctx["base"], str(dep))
  638. if dep_dir in conf["mapping"]:
  639. dep_dir=conf["mapping"][dep_dir]
  640. if dep_dir in conf["format"]:
  641. ln_src=os.path.join(build_dir, "include", os.path.relpath(conf["format"][dep_dir], ctx["base"]).format(platform="platform").replace(os.sep, "_"))
  642. ln_dst=os.path.join(src_dir, dep)
  643. if os.path.exists(ln_src):
  644. os.remove(ln_src)
  645. print("symlink("+ln_dst+", "+ln_src+")"+str(os.path.exists(ln_src)))
  646. os.symlink(ln_dst, ln_src)
  647. ret.append(ln_src)
  648. else:
  649. ret.append(dep)
  650. out=open(filename, "w")
  651. for file in ret:
  652. out.write(file+"\n")
  653. out.close()
  654. def generateToolMakefile(conf, ctx, lib_type, tool, filename, build_dir, src_dir):
  655. sys.stderr.write("generating "+filename+"\n")
  656. if not os.path.exists(os.path.dirname(filename)):
  657. os.makedirs(os.path.dirname(filename))
  658. out=open(filename, "w")
  659. out.write("# Generated.\n")
  660. # compiler flags
  661. writeMakefileFlags(conf, ctx, out)
  662. out.write("BUILD_DIR=.\n")
  663. out.write("SRC_DIR="+src_dir+"\n")
  664. out.write("\n")
  665. out.write(".PHONY: all clean\n")
  666. out.write("\n")
  667. out.write("# tool "+tool["name"]+"\n")
  668. out.write("all: $(BUILD_DIR)/"+ tool["name"]+"\n\n")
  669. writeSourceRules(conf, ctx, "static", out, tool, build_dir)
  670. out.write(tool["name"]+"_ld="+generateLDFlags(conf, ctx, lib_type, tool["deps"], [], False)+"\n")
  671. # deps=depClosure(conf, tool["deps"], True)
  672. # for dep in deps:
  673. # if lib_type=="static":
  674. # out.write(" $(BUILD_DIR)/lib"+ dep +".a")
  675. # if lib_type=="shared":
  676. # out.write(" $(BUILD_DIR)/lib"+ dep +getSharedExt(conf, ctx))
  677. # out.write("\n")
  678. ext_ldflags=generateExtLDFlags(conf, ctx)
  679. # ext_ldflags=""
  680. # for dep_lib in conf["libraries"]:
  681. # if dep_lib["name"] in ctx["externals"]:
  682. # ext_lib=ctx["externals"][dep_lib["name"]]
  683. # if "external" in ext_lib and ext_lib["external"]:
  684. # if "ldflags" in ext_lib:
  685. # ext_ldflags=ext_ldflags+" "+ext_lib["ldflags"]
  686. out.write("$(BUILD_DIR)/"+tool["name"]+": $(objs_"+tool["name"]+") $("+tool["name"]+"_ld)\n")
  687. static_flag=""
  688. if lib_type=="static" and platformSubseteqTest(ctx["platform"], "linux-*-gcc-*"):
  689. static_flag=" --static"
  690. out.write("\t$(CC) $(CFLAGS) $(CPPFLAGS) -o $(BUILD_DIR)/"+tool["name"]+" $(objs_"+tool["name"]+") "+generateLDFlags(conf, ctx, lib_type, tool["deps"], [], True)+ ext_ldflags+" $(LDFLAGS)\n")
  691. out.write("\n")
  692. out.write("clean:\n")
  693. out.write("\trm -f $(BUILD_DIR)/"+tool["name"]+" $(objs_"+tool["name"]+")\n")
  694. def generateTypedMakefile(conf, ctx, lib_type):
  695. obj_dir=os.path.join("build", ctx["platform"], lib_type)
  696. filename=os.path.join(obj_dir, "Makefile")
  697. sys.stderr.write("generating "+filename+"\n")
  698. if not os.path.exists(os.path.dirname(filename)):
  699. os.makedirs(os.path.dirname(filename))
  700. out=open(filename, "w")
  701. out.write("# Generated.\n")
  702. # generate phony targets
  703. out.write(".PHONY: all clean tools dep")
  704. for lib in conf["libraries"]:
  705. if not lib["external"]:
  706. out.write(" "+lib["name"])
  707. for tool in conf["tools"]:
  708. out.write(" "+tool["name"])
  709. out.write("\n")
  710. # all
  711. out.write("all:")
  712. for lib in conf["libraries"]:
  713. if not lib["external"]:
  714. out.write(" "+lib["name"])
  715. out.write(" tools\n")
  716. # tools
  717. out.write("tools:")
  718. for tool in conf["tools"]:
  719. out.write(" "+tool["name"])
  720. out.write("\n")
  721. # generate libs
  722. for lib in conf["libraries"]:
  723. if not lib["external"]:
  724. makefile=os.path.join(obj_dir, "Makefile."+lib["name"])
  725. generateLibraryMakefile(conf, ctx, lib_type, lib, makefile, obj_dir, os.path.join("..", "..", ".."))
  726. libincludefile=os.path.join(obj_dir, "include", lib["name"]+".inc")
  727. generateLibraryInclude(conf, ctx, lib, libincludefile, obj_dir, os.path.join("..", "..", "..", ".."))
  728. out.write(lib["name"]+":")
  729. deps=depClosure(conf, lib["deps"], True)
  730. for dep in deps:
  731. if lib["name"]!=dep:
  732. out.write(" "+dep)
  733. out.write("\n")
  734. out.write("\t$(MAKE) -f "+"Makefile."+lib["name"]+"\n\n")
  735. # generate tools
  736. for tool in conf["tools"]:
  737. makefile=os.path.join(obj_dir, "Makefile."+tool["name"])
  738. generateToolMakefile(conf, ctx, lib_type, tool, makefile, obj_dir, os.path.join("..", "..", ".."))
  739. deps=depClosure(conf, tool["deps"], True)
  740. out.write(tool["name"]+":")
  741. for dep in deps:
  742. if tool["name"]!=dep:
  743. out.write(" "+dep)
  744. out.write("\n")
  745. out.write("\t$(MAKE) -f "+"Makefile."+ tool["name"]+"\n\n")
  746. out.write("clean:\n")
  747. for lib in conf["libraries"]:
  748. if not lib["external"]:
  749. out.write("\t$(MAKE) -f "+"Makefile."+lib["name"]+" clean\n")
  750. for tool in conf["tools"]:
  751. out.write("\t$(MAKE) -f "+"Makefile."+tool["name"]+" clean\n")
  752. # out.write("dep:\n")
  753. # for lib in conf["libraries"]:
  754. # generateDEPS(conf, ctx, lib, out, obj_dir, generateCPPFLAGS(conf, ctx, lib), filename)
  755. # for tool in conf["tools"]:
  756. # generateDEPS(conf, ctx, tool, out, obj_dir, generateCPPFLAGS(conf, ctx, tool), filename)
  757. out.write("package: all\n")
  758. out.write("\tcd ../../.. && ./generate.py --include Makefile.xml");
  759. for ext_lib in ctx["externals"]:
  760. if ctx["externals"][ext_lib]["external"]:
  761. name=ext_lib
  762. if "xml"==ext_lib:
  763. name="libxml"
  764. out.write(" --with-"+name+"=yes")
  765. if "cppflags" in ctx["externals"][ext_lib]:
  766. out.write(" --with-"+name+"-cppflags=\""+ctx["externals"][ext_lib]["cppflags"]+"\"")
  767. if "ldflags" in ctx["externals"][ext_lib]:
  768. out.write(" --with-"+name+"-ldflags=\""+ctx["externals"][ext_lib]["ldflags"]+"\"")
  769. out.write(" --package package_"+lib_type+".zip --type "+lib_type)
  770. out.write(" --config-dir "+ctx["config"]+" "+ctx["platform"])
  771. out.write("\n")
  772. obj_dir=os.path.join(ctx["base"], "build", ctx["platform"], lib_type)
  773. tool_ext=""
  774. if lib_type=="static":
  775. lib_ext=".a"
  776. else:
  777. lib_ext=getSharedExt(conf, ctx)
  778. lib_prefix="lib"
  779. base="$(DESTDIR)/usr/"
  780. out.write("install: all\n")
  781. for lib in conf["libraries"]:
  782. if not lib["external"] and not isExcluded(conf, ctx, lib["name"]):
  783. for include in lib["header"]["files"]:
  784. if None!=include["install"]:
  785. target=base+"include/"
  786. if len(include["install"])>0:
  787. target=target+include["install"]+"/"
  788. target=target+os.path.split(include["path"])[1]
  789. out.write("\t@mkdir -p "+os.path.dirname(target)+"\n")
  790. out.write("\t@cp "+include["path"]+" "+target+"\n")
  791. target=base+"lib/"+lib_prefix+lib["name"]+lib_ext
  792. out.write("\t@mkdir -p "+os.path.dirname(target)+"\n")
  793. if lib_type=="shared":
  794. out.write("\t@cp "+os.path.join(obj_dir, lib_prefix+lib["name"]+lib_ext)+" "+target+".1\n")
  795. out.write("\tldconfig -v -n "+os.path.dirname(target)+"\n")
  796. else:
  797. out.write("\t@cp "+os.path.join(obj_dir, lib_prefix+lib["name"]+lib_ext)+" "+target+"\n")
  798. for tool in conf["tools"]:
  799. if not isExcluded(conf, ctx, tool["name"]):
  800. target=base+"bin/"+tool["name"]+tool_ext
  801. out.write("\t@mkdir -p "+os.path.dirname(target)+"\n")
  802. out.write("\t@cp "+os.path.join(obj_dir, tool["name"]+tool_ext)+" "+target+"\n")
  803. target=base+"lib/pkgconfig/libopc.pc"
  804. out.write("\t@mkdir -p "+os.path.dirname(target)+"\n")
  805. out.write("\t@cp "+os.path.join(ctx["base"], "config", "libopc.pc")+" "+target+"\n")
  806. out.close()
  807. def generateTypedMakefiles(ctx, source, lib_types):
  808. for platform in ctx["platforms"]:
  809. conf=generateConfiguration(ctx, [source], platform)
  810. if ctx["platform"] in conf["platforms"]:
  811. for lib_type in lib_types:
  812. generateTypedMakefile(conf, ctx, lib_type)
  813. else:
  814. parseError("platform "+ctx["platform"]+" is unknown.")
  815. sys.stderr.write("available platforms:");
  816. for platform in conf["platforms"]:
  817. sys.stderr.write(platform+"\n")
  818. out=open("Makefile", "w")
  819. out.write(".PHONY: all clean");
  820. for platform in ctx["platforms"]:
  821. for lib_type in lib_types:
  822. out.write(" "+platform+"."+lib_type);
  823. for lib_type in lib_types:
  824. out.write(" "+lib_type);
  825. out.write("\n");
  826. out.write("all:");
  827. for lib_type in lib_types:
  828. out.write(" "+lib_type);
  829. out.write("\n");
  830. for lib_type in lib_types:
  831. out.write(lib_type+":");
  832. for platform in ctx["platforms"]:
  833. out.write(" "+platform+"."+lib_type);
  834. out.write("\n");
  835. for lib_type in lib_types:
  836. for platform in ctx["platforms"]:
  837. out.write(platform+"."+lib_type+": build"+os.sep+platform+os.sep+lib_type+os.sep+"Makefile\n");
  838. out.write("\t@$(MAKE) -C build"+os.sep+platform+os.sep+lib_type+"\n");
  839. out.write("clean:\n")
  840. for lib_type in lib_types:
  841. for platform in ctx["platforms"]:
  842. out.write("\t@$(MAKE) -C build"+os.sep+platform+os.sep+lib_type+" clean\n");
  843. out.write("package:\n")
  844. for lib_type in lib_types:
  845. for platform in ctx["platforms"]:
  846. out.write("\t@$(MAKE) -C build"+os.sep+platform+os.sep+lib_type+" package\n")
  847. out.write("install:\n")
  848. for lib_type in lib_types:
  849. for platform in ctx["platforms"]:
  850. out.write("\t@$(MAKE) -C build"+os.sep+platform+os.sep+lib_type+" install\n")
  851. out.close()
  852. def dumpEnvironment(ctx, includes, platform):
  853. conf=generateConfiguration(ctx, includes, platform)
  854. if platform in conf["platforms"]:
  855. p=conf["platforms"][platform]
  856. # print(str(p))
  857. host=""
  858. if "host" in p:
  859. host="HOST=\""+p["host"]+"\" "
  860. sys.stdout.write("export CC=\""+p["cc"]+"\" "+
  861. "export AR=\""+p["ar"]+"\" "+
  862. "export LD=\""+p["ld"]+"\" "
  863. "export CPPFLAGS=\""+p["cppflags"]+"\" "
  864. "export CFLAGS=\""+p["cflags"]+"\" "+
  865. host
  866. )
  867. else:
  868. parseError("platform "+platform+" is unknown.")
  869. sys.stderr.write("available platforms:");
  870. for platform in conf["platforms"]:
  871. sys.stderr.write(platform)
  872. def set_external_flag(ctx, lib, flag, value):
  873. # sys.stderr.write("SETTING "+lib+" "+flag+" "+str(value)+"\n")
  874. if lib in ctx["externals"]:
  875. ctx["externals"][lib][flag]=value
  876. else:
  877. ctx["externals"][lib]={flag: value}
  878. def is_external(ctx, lib):
  879. if lib in ctx["externals"]:
  880. if "external" in ctx["externals"][lib]:
  881. return ctx["externals"][lib]["external"]
  882. else:
  883. return False
  884. else:
  885. return False
  886. def generateZipPackage(ctx, source, lib_type, install_zip):
  887. zip=zipfile.ZipFile(install_zip, 'w', zipfile.ZIP_DEFLATED)
  888. base=os.path.splitext(install_zip)[0]+"/"
  889. platform=ctx["platforms"][0]
  890. conf=generateConfiguration(ctx, [source], platform)
  891. if platformSubseteqTest(ctx["platforms"][0], "win32-*-*"):
  892. obj_dir=os.path.join("win32", ctx["platform"].split('-')[1])
  893. tool_ext=".exe"
  894. lib_exts=[".lib"]
  895. if (lib_type=="shared"):
  896. shared_exts.append(".dll")
  897. lib_prefix=""
  898. else:
  899. obj_dir=os.path.join("build", ctx["platform"], lib_type)
  900. tool_ext=""
  901. if lib_type=="shared":
  902. lib_exts=[".dylib"]
  903. else:
  904. lib_exts=[".a"]
  905. lib_prefix="lib"
  906. for lib in conf["libraries"]:
  907. if not lib["external"] and not isExcluded(conf, ctx, lib["name"]):
  908. for include in lib["header"]["files"]:
  909. if None!=include["install"]:
  910. target=base+"include/"
  911. if len(include["install"])>0:
  912. target=target+include["install"]+"/"
  913. target=target+os.path.split(include["path"])[1]
  914. zip.write(include["path"], target)
  915. for lib_ext in lib_exts:
  916. target=base+"lib/"+lib_prefix+lib["name"]+lib_ext
  917. # print "ADD "+os.path.join(obj_dir, lib_prefix+lib["name"]+lib_ext)
  918. zip.write(os.path.join(obj_dir, lib_prefix+lib["name"]+lib_ext), target)
  919. for tool in conf["tools"]:
  920. if not isExcluded(conf, ctx, tool["name"]):
  921. target=base+"bin/"+tool["name"]+tool_ext
  922. zip.write(os.path.join(obj_dir, tool["name"]+tool_ext), target)
  923. zip.write(os.path.join("third_party", "LICENSE"), base+"/LICENSE.THIRD_PARTY")
  924. zip.write("LICENSE", base+"/LICENSE")
  925. zip.close()
  926. def installFiles(ctx, source, lib_type, base):
  927. copy_ctx=None
  928. platform=ctx["platforms"][0]
  929. conf=generateConfiguration(ctx, [source], platform)
  930. if platformSubseteqTest(ctx["platforms"][0], "win32-*-*"):
  931. obj_dir=os.path.join("win32", ctx["platform"].split('-')[1])
  932. tool_ext=".exe"
  933. lib_exts=[".lib"]
  934. lib_prefix=""
  935. else:
  936. obj_dir=os.path.join("build", ctx["platform"], lib_type)
  937. tool_ext=""
  938. lib_exts=[".a", getSharedExt(conf, ctx)]
  939. lib_prefix="lib"
  940. for lib in conf["libraries"]:
  941. if not lib["external"] and not isExcluded(conf, ctx, lib["name"]):
  942. for include in lib["header"]["files"]:
  943. if None!=include["install"]:
  944. target=base+"include/"
  945. if len(include["install"])>0:
  946. target=target+include["install"]+"/"
  947. target=target+os.path.split(include["path"])[1]
  948. copyFile(copy_ctx, include["path"], target)
  949. for lib_ext in lib_exts:
  950. target=base+"lib/"+lib_prefix+lib["name"]+lib_ext
  951. copyFile(copy_ctx, os.path.join(obj_dir, lib_prefix+lib["name"]+lib_ext), target)
  952. for tool in conf["tools"]:
  953. if not isExcluded(conf, ctx, tool["name"]):
  954. target=base+"bin/"+tool["name"]+tool_ext
  955. copyFile(copy_ctx, os.path.join(obj_dir, tool["name"]+tool_ext), target)
  956. copyFile(copy_ctx, os.path.join("third_party", "LICENSE"), base+"/LICENSE.THIRD_PARTY")
  957. copyFile(copy_ctx, "LICENSE", base+"/LICENSE")
  958. def usage():
  959. print("usage:")
  960. print(" generate [--include \"Makefile.xml\"]")
  961. print(" [--config-dir \"config/\"]")
  962. print(" [--print-env \"linux-release-gcc\"]")
  963. print(" [--package \"xyz.zip/\"]")
  964. if __name__ == "__main__":
  965. try:
  966. opts, args = getopt.getopt(sys.argv[1:], "h", ["help", "include=", "config-dir=", "print-env=",
  967. "package=", "install=",
  968. "with-zlib-cppflags=", "with-zlib-ldflags=", "with-zlib=",
  969. "with-libxml-cppflags=", "with-libxml-ldflags=", "with-libxml=",
  970. "type="])
  971. except(getopt.GetoptError, err):
  972. # print help information and exit:
  973. print(str(err)) # will print something like "option -a not recognized"
  974. usage()
  975. sys.exit(2)
  976. ctx={ "base": os.path.abspath(os.curdir), "root": os.path.abspath(os.curdir), "platform": "?-?-?", "platforms": [], "externals": {} }
  977. ctx["config"]=ctx["base"]
  978. includes=[]
  979. dump_env=[]
  980. install_zip=None
  981. target_type="static"
  982. for o, a in opts:
  983. if o in ("-h", "--help"):
  984. usage()
  985. sys.exit(0)
  986. elif o in ("--include"):
  987. includes.append(a)
  988. elif o in ("--config-dir"):
  989. ctx["config"]=os.path.join(ctx["base"], a)
  990. elif o in ("--print-env"):
  991. args=[]
  992. dump_env=[a]
  993. elif o in ("--package"):
  994. install_zip=a
  995. elif o in ("--install"):
  996. install_files=a
  997. elif o in ("--with-zlib"):
  998. set_external_flag(ctx, "zlib", "external", "yes"==a)
  999. elif o in ("--with-zlib-cppflags"):
  1000. set_external_flag(ctx, "zlib", "cppflags", a)
  1001. elif o in ("--with-zlib-ldflags"):
  1002. set_external_flag(ctx, "zlib", "ldflags", a)
  1003. elif o in ("--with-libxml"):
  1004. set_external_flag(ctx, "xml", "external", "yes"==a)
  1005. elif o in ("--with-libxml-cppflags"):
  1006. set_external_flag(ctx, "xml", "cppflags", a)
  1007. elif o in ("--with-libxml-ldflags"):
  1008. set_external_flag(ctx, "xml", "ldflags", a)
  1009. elif o in ("--type"):
  1010. target_type=a
  1011. for platform in args:
  1012. ctx["platforms"].append(platform)
  1013. if 1==len(ctx["platforms"]) and None!=install_zip and 1==len(includes):
  1014. ctx["root"]=os.path.abspath(os.path.split(includes[0])[0])
  1015. generateZipPackage(ctx, includes[0], target_type, install_zip)
  1016. elif 1==len(ctx["platforms"]) and platformSubseteqTest(ctx["platforms"][0], "win32-*-msvc-*") and 1==len(includes):
  1017. ctx["root"]=os.path.abspath(os.path.split(includes[0])[0])
  1018. generateWin32(ctx, includes[0])
  1019. else:
  1020. if is_external(ctx, "zlib") and is_external(ctx, "xml"):
  1021. lib_types=["static", "shared"]
  1022. else:
  1023. lib_types=["static"]
  1024. if not os.path.exists("build"):
  1025. os.makedirs("build")
  1026. f=open(os.path.join("build", "configure.ctx"), "w")
  1027. f.write(str(ctx))
  1028. f.close()
  1029. for include in includes:
  1030. ctx["root"]=os.path.abspath(os.path.split(include)[0])
  1031. generateTypedMakefiles(ctx, include, lib_types)
  1032. for platform in dump_env:
  1033. dumpEnvironment(ctx, includes, platform)