build_mn.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #!/usr/bin/env python
  2. # Ymake MatrixNet support
  3. import sys
  4. import os
  5. import shutil
  6. import re
  7. import subprocess
  8. def get_value(val):
  9. dct = val.split('=', 1)
  10. if len(dct) > 1:
  11. return dct[1]
  12. return ''
  13. class BuildMnBase(object):
  14. def Run(self, mninfo, mnname, mnrankingSuffix, mncppPath, check=False, ptr=False, multi=False):
  15. self.mninfo = mninfo
  16. self.mnname = mnname
  17. self.mnrankingSuffix = mnrankingSuffix
  18. self.mncppPath = mncppPath
  19. self.check = check
  20. self.ptr = ptr
  21. self.multi = multi
  22. dataprefix = "MN_External_"
  23. mninfoName = os.path.basename(self.mninfo)
  24. data = dataprefix + mnname
  25. datasize = data + "Size"
  26. if self.multi:
  27. if self.ptr:
  28. mntype = "const NMatrixnet::TMnMultiCategPtr"
  29. mnload = "(new NMatrixnet::TMnMultiCateg( {1}, {2}, \"{0}\"))".format(mninfoName, data, datasize)
  30. else:
  31. mntype = "const NMatrixnet::TMnMultiCateg"
  32. mnload = "({1}, {2}, \"{0}\")".format(mninfoName, data, datasize)
  33. else:
  34. if self.ptr:
  35. mntype = "const NMatrixnet::TMnSsePtr"
  36. mnload = "(new NMatrixnet::TMnSseInfo({1}, {2}, \"{0}\"))".format(mninfoName, data, datasize)
  37. else:
  38. mntype = "const NMatrixnet::TMnSseInfo"
  39. mnload = "({1}, {2}, \"{0}\")".format(mninfoName, data, datasize)
  40. if self.check:
  41. self.CheckMn()
  42. mncpptmpPath = self.mncppPath + ".tmp"
  43. mncpptmp = open(mncpptmpPath, 'w')
  44. if self.multi:
  45. mncpptmp.write("#include <kernel/matrixnet/mn_multi_categ.h>\n")
  46. else:
  47. mncpptmp.write("#include <kernel/matrixnet/mn_sse.h>\n")
  48. rodatapath = os.path.dirname(self.mncppPath) + "/" + dataprefix + self.mnname + ".rodata"
  49. mncpptmp.write("namespace{\n")
  50. mncpptmp.write(" extern \"C\" {\n")
  51. mncpptmp.write(" extern const unsigned char {1}{0}[];\n".format(self.mnname, dataprefix))
  52. mncpptmp.write(" extern const ui32 {1}{0}Size;\n".format(self.mnname, dataprefix))
  53. mncpptmp.write(" }\n")
  54. mncpptmp.write("}\n")
  55. archiverCall = subprocess.Popen([self.archiver, "-q", "-p", "-o", rodatapath, self.mninfo], stdout=None, stderr=subprocess.PIPE)
  56. archiverCall.wait()
  57. mncpptmp.write("extern {0} {1};\n".format(mntype, self.mnname))
  58. mncpptmp.write("{0} {1}{2};".format(mntype, self.mnname, mnload))
  59. mncpptmp.close()
  60. shutil.move(mncpptmpPath, self.mncppPath)
  61. def CheckMn(self):
  62. if not self.fml_unused_tool:
  63. print >>sys.stderr, "fml_unused_tool undefined!"
  64. failed_msg = "fml_unused_tool failed: {0} -A {1} -e -r {2}".format(self.fml_unused_tool, self.SrcRoot, self.mninfo)
  65. assert not subprocess.call([self.fml_unused_tool, "-A", self.SrcRoot, "-e", "-r", self.mninfo]), failed_msg
  66. class BuildMn(BuildMnBase):
  67. def Run(self, argv):
  68. if len(argv) < 6:
  69. print >>sys.stderr, "BuildMn.Run(<ARCADIA_ROOT> <archiver> <mninfo> <mnname> <mnrankingSuffix> <cppOutput> [params...])"
  70. sys.exit(1)
  71. self.SrcRoot = argv[0]
  72. self.archiver = argv[1]
  73. mninfo = argv[2]
  74. mnname = argv[3]
  75. mnrankingSuffix = argv[4]
  76. mncppPath = argv[5]
  77. check = False
  78. ptr = False
  79. multi = False
  80. self.fml_unused_tool = ''
  81. for param in argv[6:]:
  82. if param == "CHECK":
  83. check = True
  84. elif param == "PTR":
  85. ptr = True
  86. elif param == "MULTI":
  87. multi = True
  88. elif param.startswith('fml_tool='):
  89. self.fml_unused_tool = get_value(param)
  90. else:
  91. print >>sys.stdout, "Unknown param: {0}".format(param)
  92. super(BuildMn, self).Run(mninfo, mnname, mnrankingSuffix, mncppPath, check=check, ptr=ptr, multi=multi)
  93. class BuildMns(BuildMnBase):
  94. def InitBase(self, listname, mnrankingSuffix):
  95. self.autogen = '// DO NOT EDIT THIS FILE DIRECTLY, AUTOGENERATED!\n'
  96. self.mnrankingSuffix = mnrankingSuffix
  97. self.mnlistname = listname + mnrankingSuffix
  98. self.mnlistelem = "const NMatrixnet::TMnSsePtr*"
  99. mnlisttype = "TMap< TString, {0} >".format(self.mnlistelem)
  100. self.mnlist = "const {0} {1}".format(mnlisttype, self.mnlistname)
  101. self.mnmultilistname = "{0}{1}Multi".format(listname, self.mnrankingSuffix)
  102. self.mnmultilistelem = "const NMatrixnet::TMnMultiCategPtr*"
  103. mnmultilisttype = "TMap< TString, {0} >".format(self.mnmultilistelem)
  104. self.mnmultilist = "const {0} {1}".format(mnmultilisttype, self.mnmultilistname)
  105. def InitForAll(self, argv):
  106. if len(argv) < 8:
  107. print >>sys.stderr, "BuildMns.InitForAll(<ARCADIA_ROOT> <BINDIR> <archiver> <listname> <mnranking_suffix> <hdrfile> <srcfile> <mninfos> [fml_tool=<fml_unused_tool> CHECK])"
  108. sys.exit(1)
  109. bmns_args = []
  110. self.check = False
  111. self.fml_unused_tool = ''
  112. for arg in argv:
  113. if arg == "CHECK":
  114. self.check = True
  115. elif arg.startswith('fml_tool='):
  116. self.fml_unused_tool = get_value(arg)
  117. else:
  118. bmns_args.append(arg)
  119. self.SrcRoot = bmns_args[0]
  120. self.BINDIR = bmns_args[1]
  121. self.archiver = bmns_args[2]
  122. self.listname = bmns_args[3]
  123. self.mnrankingSuffix = get_value(bmns_args[4])
  124. self.hdrfile = bmns_args[5]
  125. self.srcfile = bmns_args[6]
  126. self.mninfos = bmns_args[7:]
  127. self.InitBase(self.listname, self.mnrankingSuffix)
  128. def InitForHeader(self, argv):
  129. if len(argv) < 4:
  130. print >>sys.stderr, "BuildMns.InitForHeader(<listname> <rankingSuffix> <hdrfile> <mninfos...>)"
  131. sys.exit(1)
  132. self.listname = argv[0]
  133. self.mnrankingSuffix = get_value(argv[1])
  134. self.hdrfile = argv[2]
  135. self.mninfos = argv[3:]
  136. self.InitBase(self.listname, self.mnrankingSuffix)
  137. def InitForCpp(self, argv):
  138. if len(argv) < 5:
  139. print >>sys.stderr, "BuildMns.InitForCpp(<listname> <rankingSuffix> <hdrfile> <srcfile> <mninfos...>)"
  140. sys.exit(1)
  141. self.listname = argv[0]
  142. self.mnrankingSuffix = get_value(argv[1])
  143. self.hdrfile = argv[2]
  144. self.srcfile = argv[3]
  145. self.mninfos = argv[4:]
  146. self.InitBase(self.listname, self.mnrankingSuffix)
  147. def InitForFiles(self, argv):
  148. if len(argv) < 7:
  149. print >>sys.stderr, "BuildMns.InitForFiles(<ARCADIA_ROOT> <BINDIR> <archiver> <fml_unused_tool> <listname> <rankingSuffix> <mninfos...> [CHECK])"
  150. sys.exit(1)
  151. bmns_args = []
  152. self.check = False
  153. self.fml_unused_tool = ''
  154. for arg in argv:
  155. if arg == "CHECK":
  156. self.check = True
  157. elif arg.startswith('fml_tool='):
  158. self.fml_unused_tool = get_value(arg)
  159. else:
  160. bmns_args.append(arg)
  161. self.SrcRoot = bmns_args[0]
  162. self.BINDIR = bmns_args[1]
  163. self.archiver = bmns_args[2]
  164. self.listname = bmns_args[3]
  165. self.mnrankingSuffix = get_value(bmns_args[4])
  166. self.mninfos = bmns_args[5:]
  167. def BuildMnsHeader(self):
  168. if self.mninfos:
  169. self.mninfos = sorted(set(self.mninfos))
  170. tmpHdrPath = self.hdrfile + ".tmp"
  171. tmpHdrFile = open(tmpHdrPath, 'w')
  172. tmpHdrFile.write(self.autogen)
  173. tmpHdrFile.write("#include <kernel/matrixnet/mn_sse.h>\n")
  174. tmpHdrFile.write("#include <kernel/matrixnet/mn_multi_categ.h>\n\n")
  175. tmpHdrFile.write("extern {0};\n".format(self.mnlist))
  176. tmpHdrFile.write("extern {0};\n".format(self.mnmultilist))
  177. for item in self.mninfos:
  178. mnfilename = os.path.basename(item)
  179. mnfilename, ext = os.path.splitext(mnfilename)
  180. mnname = re.sub("[^-a-zA-Z0-9_]", "_", mnfilename)
  181. if ext == ".info":
  182. mnname = "staticMn{0}{1}Ptr".format(self.mnrankingSuffix, mnname)
  183. tmpHdrFile.write("extern const NMatrixnet::TMnSsePtr {0};\n".format(mnname))
  184. elif ext == ".mnmc":
  185. mnname = "staticMnMulti{0}{1}Ptr".format(self.mnrankingSuffix, mnname)
  186. tmpHdrFile.write("extern const NMatrixnet::TMnMultiCategPtr {0};\n".format(mnname))
  187. tmpHdrFile.close()
  188. shutil.move(tmpHdrPath, self.hdrfile)
  189. def BuildMnFiles(self):
  190. for item in self.mninfos:
  191. mnfilename = os.path.basename(item)
  192. mnfilename, ext = os.path.splitext(mnfilename)
  193. mnname = re.sub("[^-a-zA-Z0-9_]", "_", mnfilename)
  194. if ext == ".info":
  195. mnname = "staticMn{0}{1}Ptr".format(self.mnrankingSuffix, mnname)
  196. super(BuildMns, self).Run(item, mnname, self.mnrankingSuffix, self.BINDIR + "/mn.{0}.cpp".format(mnname), check=self.check, ptr=True, multi=False)
  197. elif ext == ".mnmc":
  198. mnname = "staticMnMulti{0}{1}Ptr".format(self.mnrankingSuffix, mnname)
  199. # BUILD_MN_PTR_MULTI
  200. super(BuildMns, self).Run(item, mnname, self.mnrankingSuffix, self.BINDIR + "/mnmulti.{0}.cpp".format(mnname), check=False, ptr=True, multi=True)
  201. def BuildMnsCpp(self):
  202. if self.mninfos:
  203. self.mninfos = sorted(set(self.mninfos))
  204. tmpSrcPath = self.srcfile + ".tmp"
  205. tmpSrcFile = open(tmpSrcPath, 'w')
  206. hdrrel = os.path.basename(self.hdrfile)
  207. mnnames = []
  208. mnmultinames = []
  209. for item in self.mninfos:
  210. mnfilename = os.path.basename(item)
  211. mnfilename, ext = os.path.splitext(mnfilename)
  212. if ext == ".info":
  213. mnnames.append(mnfilename)
  214. elif ext == ".mnmc":
  215. mnmultinames.append(mnfilename)
  216. tmpSrcFile.write(self.autogen)
  217. tmpSrcFile.write("#include \"{0}\"\n\n".format(hdrrel))
  218. if mnnames:
  219. mndata = self.mnlistname + "_data"
  220. tmpSrcFile.write("static const std::pair< TString, {0} > {1}[] = {{\n".format(self.mnlistelem, mndata))
  221. for item in mnnames:
  222. mnname = re.sub("[^-a-zA-Z0-9_]", "_", item)
  223. tmpSrcFile.write(" std::make_pair(TString(\"{0}\"), &staticMn{1}{2}Ptr),\n".format(item, self.mnrankingSuffix, mnname))
  224. tmpSrcFile.write("};\n")
  225. tmpSrcFile.write("{0}({1},{1} + sizeof({1}) / sizeof({1}[0]));\n\n".format(self.mnlist, mndata))
  226. else:
  227. tmpSrcFile.write("{0};\n\n".format(self.mnlist))
  228. if mnmultinames:
  229. mnmultidata = self.mnmultilistname + "_data"
  230. tmpSrcFile.write("static const std::pair< TString, {0} > {1}[] = {{\n".format(self.mnmultilistelem, mnmultidata))
  231. for item in mnmultinames:
  232. mnname = re.sub("[^-a-zA-Z0-9_]", "_", item)
  233. tmpSrcFile.write(" std::make_pair(TString(\"{0}\"), &staticMnMulti{1}{2}Ptr),\n".format(item, self.mnrankingSuffix, mnname))
  234. tmpSrcFile.write("};\n")
  235. tmpSrcFile.write("{0}({1},{1} + sizeof({1}) / sizeof({1}[0]));\n".format(self.mnmultilist, mnmultidata))
  236. else:
  237. tmpSrcFile.write("{0};\n".format(self.mnmultilist))
  238. tmpSrcFile.close()
  239. shutil.move(tmpSrcPath, self.srcfile)
  240. def BuildMnsAllF(argv):
  241. bldMns = BuildMns()
  242. bldMns.InitForAll(argv)
  243. bldMns.BuildMnsCpp()
  244. bldMns.BuildMnsHeader()
  245. bldMns.BuildMnFiles()
  246. def BuildMnsCppF(argv):
  247. bldMns = BuildMns()
  248. bldMns.InitForCpp(argv)
  249. bldMns.BuildMnsCpp()
  250. def BuildMnsHeaderF(argv):
  251. bldMns = BuildMns()
  252. bldMns.InitForHeader(argv)
  253. bldMns.BuildMnsHeader()
  254. def BuildMnsFilesF(argv):
  255. bldMns = BuildMns()
  256. bldMns.InitForFiles(argv)
  257. bldMns.BuildMnFiles()
  258. def BuildMnF(argv):
  259. bldMn = BuildMn()
  260. bldMn.Run(argv)
  261. if __name__ == '__main__':
  262. if len(sys.argv) < 2:
  263. print >>sys.stderr, "Usage: build_mn.py <funcName> <args...>"
  264. sys.exit(1)
  265. if (sys.argv[2:]):
  266. globals()[sys.argv[1]](sys.argv[2:])
  267. else:
  268. globals()[sys.argv[1]]()