ticgt.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. # Texas Instruments code generator support (experimental)
  4. # When reporting issues, please directly assign the bug to the maintainer.
  5. __author__ = __maintainer__ = "Jérôme Carretero <cJ-waf@zougloub.eu>"
  6. __copyright__ = "Jérôme Carretero, 2012"
  7. """
  8. TI cgt6x is a compiler suite for TI DSPs.
  9. The toolchain does pretty weird things, and I'm sure I'm missing some of them.
  10. But still, the tool saves time.
  11. What this tool does is:
  12. - create a TI compiler environment
  13. - create TI compiler features, to handle some specifics about this compiler
  14. It has a few idiosyncracies, such as not giving the liberty of the .o file names
  15. - automatically activate them when using the TI compiler
  16. - handle the tconf tool
  17. The tool
  18. TODO:
  19. - the set_platform_flags() function is not nice
  20. - more tests
  21. - broaden tool scope, if needed
  22. """
  23. import os, re
  24. from waflib import Options, Utils, Task, TaskGen
  25. from waflib.Tools import c, ccroot, c_preproc
  26. from waflib.Configure import conf
  27. from waflib.TaskGen import feature, before_method
  28. from waflib.Tools.c import cprogram
  29. opj = os.path.join
  30. @conf
  31. def find_ticc(conf):
  32. conf.find_program(['cl6x'], var='CC', path_list=opj(getattr(Options.options, 'ti-cgt-dir', ""), 'bin'))
  33. conf.env.CC_NAME = 'ticc'
  34. @conf
  35. def find_tild(conf):
  36. conf.find_program(['lnk6x'], var='LINK_CC', path_list=opj(getattr(Options.options, 'ti-cgt-dir', ""), 'bin'))
  37. conf.env.LINK_CC_NAME = 'tild'
  38. @conf
  39. def find_tiar(conf):
  40. conf.find_program(['ar6x'], var='AR', path_list=opj(getattr(Options.options, 'ti-cgt-dir', ""), 'bin'))
  41. conf.env.AR_NAME = 'tiar'
  42. conf.env.ARFLAGS = 'qru'
  43. @conf
  44. def ticc_common_flags(conf):
  45. v = conf.env
  46. if not v['LINK_CC']:
  47. v['LINK_CC'] = v['CC']
  48. v['CCLNK_SRC_F'] = []
  49. v['CCLNK_TGT_F'] = ['-o']
  50. v['CPPPATH_ST'] = '-I%s'
  51. v['DEFINES_ST'] = '-d%s'
  52. v['LIB_ST'] = '-l%s' # template for adding libs
  53. v['LIBPATH_ST'] = '-i%s' # template for adding libpaths
  54. v['STLIB_ST'] = '-l=%s.lib'
  55. v['STLIBPATH_ST'] = '-i%s'
  56. # program
  57. v['cprogram_PATTERN'] = '%s.out'
  58. # static lib
  59. #v['LINKFLAGS_cstlib'] = ['-Wl,-Bstatic']
  60. v['cstlib_PATTERN'] = '%s.lib'
  61. def configure(conf):
  62. v = conf.env
  63. v.TI_CGT_DIR = getattr(Options.options, 'ti-cgt-dir', "")
  64. v.TI_DSPLINK_DIR = getattr(Options.options, 'ti-dsplink-dir', "")
  65. v.TI_BIOSUTILS_DIR = getattr(Options.options, 'ti-biosutils-dir', "")
  66. v.TI_DSPBIOS_DIR = getattr(Options.options, 'ti-dspbios-dir', "")
  67. v.TI_XDCTOOLS_DIR = getattr(Options.options, 'ti-xdctools-dir', "")
  68. conf.find_ticc()
  69. conf.find_tiar()
  70. conf.find_tild()
  71. conf.ticc_common_flags()
  72. conf.cc_load_tools()
  73. conf.cc_add_flags()
  74. conf.link_add_flags()
  75. conf.find_program(['tconf'], var='TCONF', path_list=v.TI_XDCTOOLS_DIR)
  76. conf.env.TCONF_INCLUDES += [
  77. opj(conf.env.TI_DSPBIOS_DIR, 'packages'),
  78. ]
  79. conf.env.INCLUDES += [
  80. opj(conf.env.TI_CGT_DIR, 'include'),
  81. ]
  82. conf.env.LIBPATH += [
  83. opj(conf.env.TI_CGT_DIR, "lib"),
  84. ]
  85. conf.env.INCLUDES_DSPBIOS += [
  86. opj(conf.env.TI_DSPBIOS_DIR, 'packages', 'ti', 'bios', 'include'),
  87. ]
  88. conf.env.LIBPATH_DSPBIOS += [
  89. opj(conf.env.TI_DSPBIOS_DIR, 'packages', 'ti', 'bios', 'lib'),
  90. ]
  91. conf.env.INCLUDES_DSPLINK += [
  92. opj(conf.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'inc'),
  93. ]
  94. @conf
  95. def ti_set_debug(cfg, debug=1):
  96. """
  97. Sets debug flags for the compiler.
  98. TODO:
  99. - for each TI CFLAG/INCLUDES/LINKFLAGS/LIBPATH replace RELEASE by DEBUG
  100. - -g --no_compress
  101. """
  102. if debug:
  103. cfg.env.CFLAGS += "-d_DEBUG -dDEBUG -dDDSP_DEBUG".split()
  104. @conf
  105. def ti_dsplink_set_platform_flags(cfg, splat, dsp, dspbios_ver, board):
  106. """
  107. Sets the INCLUDES, LINKFLAGS for DSPLINK and TCONF_INCLUDES
  108. For the specific hardware.
  109. Assumes that DSPLINK was built in its own folder.
  110. :param splat: short platform name (eg. OMAPL138)
  111. :param dsp: DSP name (eg. 674X)
  112. :param dspbios_ver: string identifying DspBios version (eg. 5.XX)
  113. :param board: board name (eg. OMAPL138GEM)
  114. """
  115. d1 = opj(cfg.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'inc', 'DspBios', dspbios_ver)
  116. d = opj(cfg.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'inc', 'DspBios', dspbios_ver, board)
  117. cfg.env.TCONF_INCLUDES += [d1, d]
  118. cfg.env.INCLUDES_DSPLINK += [
  119. opj(cfg.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'inc', dsp),
  120. d,
  121. ]
  122. cfg.env.LINKFLAGS_DSPLINK += [
  123. opj(cfg.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'export', 'BIN', 'DspBios', splat, board+'_0', 'RELEASE', 'dsplink%s.lib' % x)
  124. for x in ('', 'pool', 'mpcs', 'mplist', 'msg', 'data', 'notify', 'ringio')
  125. ]
  126. def options(opt):
  127. opt.add_option('--with-ti-cgt', type='string', dest='ti-cgt-dir', help = 'Specify alternate cgt root folder', default="")
  128. opt.add_option('--with-ti-biosutils', type='string', dest='ti-biosutils-dir', help = 'Specify alternate biosutils folder', default="")
  129. opt.add_option('--with-ti-dspbios', type='string', dest='ti-dspbios-dir', help = 'Specify alternate dspbios folder', default="")
  130. opt.add_option('--with-ti-dsplink', type='string', dest='ti-dsplink-dir', help = 'Specify alternate dsplink folder', default="")
  131. opt.add_option('--with-ti-xdctools', type='string', dest='ti-xdctools-dir', help = 'Specify alternate xdctools folder', default="")
  132. class ti_cprogram(cprogram):
  133. """
  134. Link object files into a c program
  135. Changes:
  136. - the linked executable to have a relative path (because we can)
  137. - put the LIBPATH first
  138. """
  139. run_str = '${LINK_CC} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LINKFLAGS} ${CCLNK_SRC_F}${SRC} ${CCLNK_TGT_F}${TGT[0].bldpath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} '
  140. @feature("c")
  141. @before_method('apply_link')
  142. def use_ti_cprogram(self):
  143. """
  144. Automatically uses ti_cprogram link process
  145. """
  146. if 'cprogram' in self.features and self.env.CC_NAME == 'ticc':
  147. self.features.insert(0, "ti_cprogram")
  148. class ti_c(Task.Task):
  149. """
  150. Compile task for the TI codegen compiler
  151. This compiler does not allow specifying the output file name, only the output path.
  152. """
  153. "Compile C files into object files"
  154. run_str = '${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${SRC} -c ${OUT} ${CPPFLAGS}'
  155. vars = ['CCDEPS'] # unused variable to depend on, just in case
  156. ext_in = ['.h'] # set the build order easily by using ext_out=['.h']
  157. scan = c_preproc.scan
  158. def create_compiled_task(self, name, node):
  159. """
  160. Overrides ccroot.create_compiled_task to support ti_c
  161. """
  162. out = '%s' % (node.change_ext('.obj').name)
  163. if self.env.CC_NAME == 'ticc':
  164. name = 'ti_c'
  165. task = self.create_task(name, node, node.parent.find_or_declare(out))
  166. self.env.OUT = '-fr%s' % (node.parent.get_bld().abspath())
  167. try:
  168. self.compiled_tasks.append(task)
  169. except AttributeError:
  170. self.compiled_tasks = [task]
  171. return task
  172. @TaskGen.extension('.c')
  173. def c_hook(self, node):
  174. "Bind the c file extension to the creation of a :py:class:`waflib.Tools.c.c` instance"
  175. if self.env.CC_NAME == 'ticc':
  176. return create_compiled_task(self, 'ti_c', node)
  177. else:
  178. return self.create_compiled_task('c', node)
  179. @feature("ti-tconf")
  180. @before_method('process_source')
  181. def apply_tconf(self):
  182. sources = [x.get_src() for x in self.to_nodes(self.source, path=self.path.get_src())]
  183. node = sources[0]
  184. assert(sources[0].name.endswith(".tcf"))
  185. if len(sources) > 1:
  186. assert(sources[1].name.endswith(".cmd"))
  187. target = getattr(self, 'target', self.source)
  188. target_node = node.get_bld().parent.find_or_declare(node.name)
  189. procid = "%d" % int(getattr(self, 'procid', 0))
  190. importpaths = []
  191. includes = Utils.to_list(getattr(self, 'includes', []))
  192. for x in includes + self.env.TCONF_INCLUDES:
  193. if x == os.path.abspath(x):
  194. importpaths.append(x)
  195. else:
  196. relpath = self.path.find_node(x).path_from(target_node.parent)
  197. importpaths.append(relpath)
  198. task = self.create_task('ti_tconf', sources, target_node.change_ext('.cdb'))
  199. task.path = self.path
  200. task.includes = includes
  201. task.cwd = target_node.parent.abspath()
  202. task.env = self.env.derive()
  203. task.env["TCONFSRC"] = node.path_from(target_node.parent)
  204. task.env["TCONFINC"] = '-Dconfig.importPath=%s' % ";".join(importpaths)
  205. task.env['TCONFPROGNAME'] = '-Dconfig.programName=%s' % target
  206. task.env['PROCID'] = procid
  207. task.outputs = [
  208. target_node.change_ext("cfg_c.c"),
  209. target_node.change_ext("cfg.s62"),
  210. target_node.change_ext("cfg.cmd"),
  211. ]
  212. create_compiled_task(self, 'ti_c', task.outputs[1])
  213. ctask = create_compiled_task(self, 'ti_c', task.outputs[0])
  214. ctask.env = self.env.derive()
  215. self.add_those_o_files(target_node.change_ext("cfg.cmd"))
  216. if len(sources) > 1:
  217. self.add_those_o_files(sources[1])
  218. self.source = []
  219. re_tconf_include = re.compile(r'(?P<type>utils\.importFile)\("(?P<file>.*)"\)',re.M)
  220. class ti_tconf(Task.Task):
  221. run_str = '${TCONF} ${TCONFINC} ${TCONFPROGNAME} ${TCONFSRC} ${PROCID}'
  222. color = 'PINK'
  223. def scan(self):
  224. includes = Utils.to_list(getattr(self, 'includes', []))
  225. def deps(node):
  226. nodes, names = [], []
  227. if node:
  228. code = Utils.readf(node.abspath())
  229. for match in re_tconf_include.finditer(code):
  230. path = match.group('file')
  231. if path:
  232. for x in includes:
  233. filename = opj(x, path)
  234. fi = self.path.find_resource(filename)
  235. if fi:
  236. subnodes, subnames = deps(fi)
  237. nodes += subnodes
  238. names += subnames
  239. nodes.append(fi)
  240. names.append(path)
  241. break
  242. return nodes, names
  243. return deps(self.inputs[0])