keil.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. #
  2. # File : keil.py
  3. # This file is part of RT-Thread RTOS
  4. # COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License along
  17. # with this program; if not, write to the Free Software Foundation, Inc.,
  18. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. #
  20. # Change Logs:
  21. # Date Author Notes
  22. # 2015-01-20 Bernard Add copyright information
  23. #
  24. import os
  25. import sys
  26. import string
  27. import xml.etree.ElementTree as etree
  28. from xml.etree.ElementTree import SubElement
  29. from utils import _make_path_relative
  30. from utils import xml_indent
  31. fs_encoding = sys.getfilesystemencoding()
  32. def _get_filetype(fn):
  33. if fn.rfind('.cpp') != -1 or fn.rfind('.cxx') != -1:
  34. return 8
  35. if fn.rfind('.c') != -1 or fn.rfind('.C') != -1:
  36. return 1
  37. # assemble file type
  38. if fn.rfind('.s') != -1 or fn.rfind('.S') != -1:
  39. return 2
  40. # header type
  41. if fn.rfind('.h') != -1:
  42. return 5
  43. if fn.rfind('.lib') != -1:
  44. return 4
  45. if fn.rfind('.o') != -1:
  46. return 3
  47. # other filetype
  48. return 5
  49. def MDK4AddGroupForFN(ProjectFiles, parent, name, filename, project_path):
  50. group = SubElement(parent, 'Group')
  51. group_name = SubElement(group, 'GroupName')
  52. group_name.text = name
  53. name = os.path.basename(filename)
  54. path = os.path.dirname (filename)
  55. basename = os.path.basename(path)
  56. path = _make_path_relative(project_path, path)
  57. path = os.path.join(path, name)
  58. files = SubElement(group, 'Files')
  59. file = SubElement(files, 'File')
  60. file_name = SubElement(file, 'FileName')
  61. name = os.path.basename(path)
  62. if name.find('.cpp') != -1:
  63. obj_name = name.replace('.cpp', '.o')
  64. elif name.find('.c') != -1:
  65. obj_name = name.replace('.c', '.o')
  66. elif name.find('.s') != -1:
  67. obj_name = name.replace('.s', '.o')
  68. elif name.find('.S') != -1:
  69. obj_name = name.replace('.s', '.o')
  70. else:
  71. obj_name = name
  72. if ProjectFiles.count(obj_name):
  73. name = basename + '_' + name
  74. ProjectFiles.append(obj_name)
  75. file_name.text = name.decode(fs_encoding)
  76. file_type = SubElement(file, 'FileType')
  77. file_type.text = '%d' % _get_filetype(name)
  78. file_path = SubElement(file, 'FilePath')
  79. file_path.text = path.decode(fs_encoding)
  80. return group
  81. def MDK4AddLibToGroup(ProjectFiles, group, name, filename, project_path):
  82. name = os.path.basename(filename)
  83. path = os.path.dirname (filename)
  84. basename = os.path.basename(path)
  85. path = _make_path_relative(project_path, path)
  86. path = os.path.join(path, name)
  87. files = SubElement(group, 'Files')
  88. file = SubElement(files, 'File')
  89. file_name = SubElement(file, 'FileName')
  90. name = os.path.basename(path)
  91. if name.find('.cpp') != -1:
  92. obj_name = name.replace('.cpp', '.o')
  93. elif name.find('.c') != -1:
  94. obj_name = name.replace('.c', '.o')
  95. elif name.find('.s') != -1:
  96. obj_name = name.replace('.s', '.o')
  97. elif name.find('.S') != -1:
  98. obj_name = name.replace('.s', '.o')
  99. else:
  100. obj_name = name
  101. if ProjectFiles.count(obj_name):
  102. name = basename + '_' + name
  103. ProjectFiles.append(obj_name)
  104. try:
  105. file_name.text = name.decode(fs_encoding)
  106. except:
  107. file_name.text = name
  108. file_type = SubElement(file, 'FileType')
  109. file_type.text = '%d' % _get_filetype(name)
  110. file_path = SubElement(file, 'FilePath')
  111. try:
  112. file_path.text = path.decode(fs_encoding)
  113. except:
  114. file_path.text = path
  115. return group
  116. def MDK4AddGroup(ProjectFiles, parent, name, files, project_path, group_scons):
  117. # don't add an empty group
  118. if len(files) == 0:
  119. return
  120. group = SubElement(parent, 'Group')
  121. group_name = SubElement(group, 'GroupName')
  122. group_name.text = name
  123. for f in files:
  124. fn = f.rfile()
  125. name = fn.name
  126. path = os.path.dirname(fn.abspath)
  127. basename = os.path.basename(path)
  128. path = _make_path_relative(project_path, path)
  129. path = os.path.join(path, name)
  130. files = SubElement(group, 'Files')
  131. file = SubElement(files, 'File')
  132. file_name = SubElement(file, 'FileName')
  133. name = os.path.basename(path)
  134. if name.find('.cpp') != -1:
  135. obj_name = name.replace('.cpp', '.o')
  136. elif name.find('.c') != -1:
  137. obj_name = name.replace('.c', '.o')
  138. elif name.find('.s') != -1:
  139. obj_name = name.replace('.s', '.o')
  140. elif name.find('.S') != -1:
  141. obj_name = name.replace('.s', '.o')
  142. if ProjectFiles.count(obj_name):
  143. name = basename + '_' + name
  144. ProjectFiles.append(obj_name)
  145. file_name.text = name # name.decode(fs_encoding)
  146. file_type = SubElement(file, 'FileType')
  147. file_type.text = '%d' % _get_filetype(name)
  148. file_path = SubElement(file, 'FilePath')
  149. file_path.text = path # path.decode(fs_encoding)
  150. # for local LOCAL_CFLAGS/LOCAL_CXXFLAGS/LOCAL_CCFLAGS/LOCAL_CPPPATH/LOCAL_CPPDEFINES
  151. MiscControls_text = ' '
  152. if file_type.text == '1' and 'LOCAL_CFLAGS' in group_scons:
  153. MiscControls_text = MiscControls_text + group_scons['LOCAL_CFLAGS']
  154. elif file_type.text == '8' and 'LOCAL_CXXFLAGS' in group_scons:
  155. MiscControls_text = MiscControls_text + group_scons['LOCAL_CXXFLAGS']
  156. if 'LOCAL_CCFLAGS' in group_scons:
  157. MiscControls_text = MiscControls_text + group_scons['LOCAL_CCFLAGS']
  158. if MiscControls_text != ' ':
  159. FileOption = SubElement(file, 'FileOption')
  160. FileArmAds = SubElement(FileOption, 'FileArmAds')
  161. Cads = SubElement(FileArmAds, 'Cads')
  162. VariousControls = SubElement(Cads, 'VariousControls')
  163. MiscControls = SubElement(VariousControls, 'MiscControls')
  164. MiscControls.text = MiscControls_text
  165. Define = SubElement(VariousControls, 'Define')
  166. if 'LOCAL_CPPDEFINES' in group_scons:
  167. Define.text = ', '.join(set(group_scons['LOCAL_CPPDEFINES']))
  168. else:
  169. Define.text = ' '
  170. Undefine = SubElement(VariousControls, 'Undefine')
  171. Undefine.text = ' '
  172. IncludePath = SubElement(VariousControls, 'IncludePath')
  173. if 'LOCAL_CPPPATH' in group_scons:
  174. IncludePath.text = ';'.join([_make_path_relative(project_path, os.path.normpath(i)) for i in group_scons['LOCAL_CPPPATH']])
  175. else:
  176. IncludePath.text = ' '
  177. return group
  178. # The common part of making MDK4/5 project
  179. def MDK45Project(tree, target, script):
  180. project_path = os.path.dirname(os.path.abspath(target))
  181. root = tree.getroot()
  182. out = open(target, 'w')
  183. out.write('<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n')
  184. CPPPATH = []
  185. CPPDEFINES = []
  186. LINKFLAGS = ''
  187. CXXFLAGS = ''
  188. CCFLAGS = ''
  189. CFLAGS = ''
  190. ProjectFiles = []
  191. # add group
  192. groups = tree.find('Targets/Target/Groups')
  193. if groups is None:
  194. groups = SubElement(tree.find('Targets/Target'), 'Groups')
  195. groups.clear() # clean old groups
  196. for group in script:
  197. group_tree = MDK4AddGroup(ProjectFiles, groups, group['name'], group['src'], project_path, group)
  198. # get each include path
  199. if 'CPPPATH' in group and group['CPPPATH']:
  200. if CPPPATH:
  201. CPPPATH += group['CPPPATH']
  202. else:
  203. CPPPATH += group['CPPPATH']
  204. # get each group's definitions
  205. if 'CPPDEFINES' in group and group['CPPDEFINES']:
  206. if CPPDEFINES:
  207. CPPDEFINES += group['CPPDEFINES']
  208. else:
  209. CPPDEFINES = group['CPPDEFINES']
  210. # get each group's link flags
  211. if 'LINKFLAGS' in group and group['LINKFLAGS']:
  212. if LINKFLAGS:
  213. LINKFLAGS += ' ' + group['LINKFLAGS']
  214. else:
  215. LINKFLAGS += group['LINKFLAGS']
  216. # get each group's CXXFLAGS flags
  217. if 'CXXFLAGS' in group and group['CXXFLAGS']:
  218. if CXXFLAGS:
  219. CXXFLAGS += ' ' + group['CXXFLAGS']
  220. else:
  221. CXXFLAGS += group['CXXFLAGS']
  222. # get each group's CCFLAGS flags
  223. if 'CCFLAGS' in group and group['CCFLAGS']:
  224. if CCFLAGS:
  225. CCFLAGS += ' ' + group['CCFLAGS']
  226. else:
  227. CCFLAGS += group['CCFLAGS']
  228. # get each group's CFLAGS flags
  229. if 'CFLAGS' in group and group['CFLAGS']:
  230. if CFLAGS:
  231. CFLAGS += ' ' + group['CFLAGS']
  232. else:
  233. CFLAGS += group['CFLAGS']
  234. # get each group's LIBS flags
  235. if 'LIBS' in group and group['LIBS']:
  236. for item in group['LIBS']:
  237. lib_path = ''
  238. for path_item in group['LIBPATH']:
  239. full_path = os.path.join(path_item, item + '.lib')
  240. if os.path.isfile(full_path): # has this library
  241. lib_path = full_path
  242. break
  243. if lib_path != '':
  244. if group_tree != None:
  245. MDK4AddLibToGroup(ProjectFiles, group_tree, group['name'], lib_path, project_path)
  246. else:
  247. group_tree = MDK4AddGroupForFN(ProjectFiles, groups, group['name'], lib_path, project_path)
  248. # write include path, definitions and link flags
  249. IncludePath = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/VariousControls/IncludePath')
  250. IncludePath.text = ';'.join([_make_path_relative(project_path, os.path.normpath(i)) for i in set(CPPPATH)])
  251. Define = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/VariousControls/Define')
  252. Define.text = ', '.join(set(CPPDEFINES))
  253. if 'c99' in CXXFLAGS or 'c99' in CCFLAGS or 'c99' in CFLAGS:
  254. uC99 = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/uC99')
  255. uC99.text = '1'
  256. if 'gnu' in CXXFLAGS or 'gnu' in CCFLAGS or 'gnu' in CFLAGS:
  257. uGnu = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/uGnu')
  258. uGnu.text = '1'
  259. Misc = tree.find('Targets/Target/TargetOption/TargetArmAds/LDads/Misc')
  260. Misc.text = LINKFLAGS
  261. xml_indent(root)
  262. out.write(etree.tostring(root, encoding='utf-8').decode())
  263. out.close()
  264. def MDK4Project(target, script):
  265. if os.path.isfile('template.uvproj') is False:
  266. print ('Warning: The template project file [template.uvproj] not found!')
  267. return
  268. template_tree = etree.parse('template.uvproj')
  269. MDK45Project(template_tree, target, script)
  270. # remove project.uvopt file
  271. project_uvopt = os.path.abspath(target).replace('uvproj', 'uvopt')
  272. if os.path.isfile(project_uvopt):
  273. os.unlink(project_uvopt)
  274. # copy uvopt file
  275. if os.path.exists('template.uvopt'):
  276. import shutil
  277. shutil.copy2('template.uvopt', '{}.uvopt'.format(os.path.splitext(target)[0]))
  278. def MDK5Project(target, script):
  279. if os.path.isfile('template.uvprojx') is False:
  280. print ('Warning: The template project file [template.uvprojx] not found!')
  281. return
  282. template_tree = etree.parse('template.uvprojx')
  283. MDK45Project(template_tree, target, script)
  284. # remove project.uvopt file
  285. project_uvopt = os.path.abspath(target).replace('uvprojx', 'uvoptx')
  286. if os.path.isfile(project_uvopt):
  287. os.unlink(project_uvopt)
  288. # copy uvopt file
  289. if os.path.exists('template.uvoptx'):
  290. import shutil
  291. shutil.copy2('template.uvoptx', '{}.uvoptx'.format(os.path.splitext(target)[0]))
  292. def MDK2Project(target, script):
  293. template = open('template.Uv2', "r")
  294. lines = template.readlines()
  295. project = open(target, "w")
  296. project_path = os.path.dirname(os.path.abspath(target))
  297. line_index = 5
  298. # write group
  299. for group in script:
  300. lines.insert(line_index, 'Group (%s)\r\n' % group['name'])
  301. line_index += 1
  302. lines.insert(line_index, '\r\n')
  303. line_index += 1
  304. # write file
  305. ProjectFiles = []
  306. CPPPATH = []
  307. CPPDEFINES = []
  308. LINKFLAGS = ''
  309. CFLAGS = ''
  310. # number of groups
  311. group_index = 1
  312. for group in script:
  313. # print group['name']
  314. # get each include path
  315. if 'CPPPATH' in group and group['CPPPATH']:
  316. if CPPPATH:
  317. CPPPATH += group['CPPPATH']
  318. else:
  319. CPPPATH += group['CPPPATH']
  320. # get each group's definitions
  321. if 'CPPDEFINES' in group and group['CPPDEFINES']:
  322. if CPPDEFINES:
  323. CPPDEFINES += group['CPPDEFINES']
  324. else:
  325. CPPDEFINES = group['CPPDEFINES']
  326. # get each group's link flags
  327. if 'LINKFLAGS' in group and group['LINKFLAGS']:
  328. if LINKFLAGS:
  329. LINKFLAGS += ' ' + group['LINKFLAGS']
  330. else:
  331. LINKFLAGS += group['LINKFLAGS']
  332. # generate file items
  333. for node in group['src']:
  334. fn = node.rfile()
  335. name = fn.name
  336. path = os.path.dirname(fn.abspath)
  337. basename = os.path.basename(path)
  338. path = _make_path_relative(project_path, path)
  339. path = os.path.join(path, name)
  340. if ProjectFiles.count(name):
  341. name = basename + '_' + name
  342. ProjectFiles.append(name)
  343. lines.insert(line_index, 'File %d,%d,<%s><%s>\r\n'
  344. % (group_index, _get_filetype(name), path, name))
  345. line_index += 1
  346. group_index = group_index + 1
  347. lines.insert(line_index, '\r\n')
  348. line_index += 1
  349. # remove repeat path
  350. paths = set()
  351. for path in CPPPATH:
  352. inc = _make_path_relative(project_path, os.path.normpath(path))
  353. paths.add(inc) #.replace('\\', '/')
  354. paths = [i for i in paths]
  355. CPPPATH = string.join(paths, ';')
  356. definitions = [i for i in set(CPPDEFINES)]
  357. CPPDEFINES = string.join(definitions, ', ')
  358. while line_index < len(lines):
  359. if lines[line_index].startswith(' ADSCINCD '):
  360. lines[line_index] = ' ADSCINCD (' + CPPPATH + ')\r\n'
  361. if lines[line_index].startswith(' ADSLDMC ('):
  362. lines[line_index] = ' ADSLDMC (' + LINKFLAGS + ')\r\n'
  363. if lines[line_index].startswith(' ADSCDEFN ('):
  364. lines[line_index] = ' ADSCDEFN (' + CPPDEFINES + ')\r\n'
  365. line_index += 1
  366. # write project
  367. for line in lines:
  368. project.write(line)
  369. project.close()
  370. def ARMCC_Version():
  371. import rtconfig
  372. import subprocess
  373. import re
  374. path = rtconfig.EXEC_PATH
  375. if(rtconfig.PLATFORM == 'armcc'):
  376. path = os.path.join(path, 'armcc.exe')
  377. elif(rtconfig.PLATFORM == 'armclang'):
  378. path = os.path.join(path, 'armlink.exe')
  379. if os.path.exists(path):
  380. cmd = path
  381. else:
  382. return "0.0"
  383. child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
  384. stdout, stderr = child.communicate()
  385. '''
  386. example stdout:
  387. Product: MDK Plus 5.24
  388. Component: ARM Compiler 5.06 update 5 (build 528)
  389. Tool: armcc [4d3621]
  390. return version: MDK Plus 5.24/ARM Compiler 5.06 update 5 (build 528)/armcc [4d3621]
  391. '''
  392. if not isinstance(stdout, str):
  393. stdout = str(stdout, 'utf8') # Patch for Python 3
  394. version_Product = re.search(r'Product: (.+)', stdout).group(1)
  395. version_Product = version_Product[:-1]
  396. version_Component = re.search(r'Component: (.*)', stdout).group(1)
  397. version_Component = version_Component[:-1]
  398. version_Tool = re.search(r'Tool: (.*)', stdout).group(1)
  399. version_Tool = version_Tool[:-1]
  400. version_str_format = '%s/%s/%s'
  401. version_str = version_str_format % (version_Product, version_Component, version_Tool)
  402. return version_str