Keyboard firmwares for Atmel AVR and Cortex-M
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. """
  2. mbed SDK
  3. Copyright (c) 2011-2013 ARM Limited
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. """
  14. import re
  15. import sys
  16. from os import stat, walk
  17. from copy import copy
  18. from time import time, sleep
  19. from types import ListType
  20. from shutil import copyfile
  21. from os.path import join, splitext, exists, relpath, dirname, basename, split
  22. from inspect import getmro
  23. from multiprocessing import Pool, cpu_count
  24. from workspace_tools.utils import run_cmd, mkdir, rel_path, ToolException, split_path
  25. from workspace_tools.settings import BUILD_OPTIONS, MBED_ORG_USER
  26. import workspace_tools.hooks as hooks
  27. #Disables multiprocessing if set to higher number than the host machine CPUs
  28. CPU_COUNT_MIN = 1
  29. def print_notify(event, silent=False):
  30. """ Default command line notification
  31. """
  32. if event['type'] in ['info', 'debug']:
  33. print event['message']
  34. elif event['type'] == 'cc':
  35. event['severity'] = event['severity'].title()
  36. event['file'] = basename(event['file'])
  37. print '[%(severity)s] %(file)s@%(line)s: %(message)s' % event
  38. elif event['type'] == 'progress':
  39. if not silent:
  40. print '%s: %s' % (event['action'].title(), basename(event['file']))
  41. def print_notify_verbose(event, silent=False):
  42. """ Default command line notification with more verbose mode
  43. """
  44. if event['type'] in ['info', 'debug']:
  45. print_notify(event) # standard handle
  46. elif event['type'] == 'cc':
  47. event['severity'] = event['severity'].title()
  48. event['file'] = basename(event['file'])
  49. event['mcu_name'] = "None"
  50. event['toolchain'] = "None"
  51. event['target_name'] = event['target_name'].upper() if event['target_name'] else "Unknown"
  52. event['toolchain_name'] = event['toolchain_name'].upper() if event['toolchain_name'] else "Unknown"
  53. print '[%(severity)s] %(target_name)s::%(toolchain_name)s::%(file)s@%(line)s: %(message)s' % event
  54. elif event['type'] == 'progress':
  55. print_notify(event) # standard handle
  56. def compile_worker(job):
  57. results = []
  58. for command in job['commands']:
  59. _, _stderr, _rc = run_cmd(command, job['work_dir'])
  60. results.append({
  61. 'code': _rc,
  62. 'output': _stderr,
  63. 'command': command
  64. })
  65. return {
  66. 'source': job['source'],
  67. 'object': job['object'],
  68. 'commands': job['commands'],
  69. 'results': results
  70. }
  71. class Resources:
  72. def __init__(self, base_path=None):
  73. self.base_path = base_path
  74. self.inc_dirs = []
  75. self.headers = []
  76. self.s_sources = []
  77. self.c_sources = []
  78. self.cpp_sources = []
  79. self.lib_dirs = set([])
  80. self.objects = []
  81. self.libraries = []
  82. # mbed special files
  83. self.lib_builds = []
  84. self.lib_refs = []
  85. self.repo_dirs = []
  86. self.repo_files = []
  87. self.linker_script = None
  88. # Other files
  89. self.hex_files = []
  90. self.bin_files = []
  91. def add(self, resources):
  92. self.inc_dirs += resources.inc_dirs
  93. self.headers += resources.headers
  94. self.s_sources += resources.s_sources
  95. self.c_sources += resources.c_sources
  96. self.cpp_sources += resources.cpp_sources
  97. self.lib_dirs |= resources.lib_dirs
  98. self.objects += resources.objects
  99. self.libraries += resources.libraries
  100. self.lib_builds += resources.lib_builds
  101. self.lib_refs += resources.lib_refs
  102. self.repo_dirs += resources.repo_dirs
  103. self.repo_files += resources.repo_files
  104. if resources.linker_script is not None:
  105. self.linker_script = resources.linker_script
  106. self.hex_files += resources.hex_files
  107. self.bin_files += resources.bin_files
  108. def relative_to(self, base, dot=False):
  109. for field in ['inc_dirs', 'headers', 's_sources', 'c_sources',
  110. 'cpp_sources', 'lib_dirs', 'objects', 'libraries',
  111. 'lib_builds', 'lib_refs', 'repo_dirs', 'repo_files', 'hex_files', 'bin_files']:
  112. v = [rel_path(f, base, dot) for f in getattr(self, field)]
  113. setattr(self, field, v)
  114. if self.linker_script is not None:
  115. self.linker_script = rel_path(self.linker_script, base, dot)
  116. def win_to_unix(self):
  117. for field in ['inc_dirs', 'headers', 's_sources', 'c_sources',
  118. 'cpp_sources', 'lib_dirs', 'objects', 'libraries',
  119. 'lib_builds', 'lib_refs', 'repo_dirs', 'repo_files', 'hex_files', 'bin_files']:
  120. v = [f.replace('\\', '/') for f in getattr(self, field)]
  121. setattr(self, field, v)
  122. if self.linker_script is not None:
  123. self.linker_script = self.linker_script.replace('\\', '/')
  124. def __str__(self):
  125. s = []
  126. for (label, resources) in (
  127. ('Include Directories', self.inc_dirs),
  128. ('Headers', self.headers),
  129. ('Assembly sources', self.s_sources),
  130. ('C sources', self.c_sources),
  131. ('C++ sources', self.cpp_sources),
  132. ('Library directories', self.lib_dirs),
  133. ('Objects', self.objects),
  134. ('Libraries', self.libraries),
  135. ('Hex files', self.hex_files),
  136. ('Bin files', self.bin_files),
  137. ):
  138. if resources:
  139. s.append('%s:\n ' % label + '\n '.join(resources))
  140. if self.linker_script:
  141. s.append('Linker Script: ' + self.linker_script)
  142. return '\n'.join(s)
  143. # Support legacy build conventions: the original mbed build system did not have
  144. # standard labels for the "TARGET_" and "TOOLCHAIN_" specific directories, but
  145. # had the knowledge of a list of these directories to be ignored.
  146. LEGACY_IGNORE_DIRS = set([
  147. 'LPC11U24', 'LPC1768', 'LPC2368', 'LPC4088', 'LPC812', 'KL25Z',
  148. 'ARM', 'GCC_ARM', 'GCC_CR', 'GCC_CS', 'IAR', 'uARM'
  149. ])
  150. LEGACY_TOOLCHAIN_NAMES = {
  151. 'ARM_STD':'ARM', 'ARM_MICRO': 'uARM',
  152. 'GCC_ARM': 'GCC_ARM', 'GCC_CR': 'GCC_CR', 'GCC_CS': 'GCC_CS',
  153. 'IAR': 'IAR',
  154. }
  155. class mbedToolchain:
  156. VERBOSE = True
  157. CORTEX_SYMBOLS = {
  158. "Cortex-M0" : ["__CORTEX_M0", "ARM_MATH_CM0"],
  159. "Cortex-M0+": ["__CORTEX_M0PLUS", "ARM_MATH_CM0PLUS"],
  160. "Cortex-M1" : ["__CORTEX_M3", "ARM_MATH_CM1"],
  161. "Cortex-M3" : ["__CORTEX_M3", "ARM_MATH_CM3"],
  162. "Cortex-M4" : ["__CORTEX_M4", "ARM_MATH_CM4"],
  163. "Cortex-M4F" : ["__CORTEX_M4", "ARM_MATH_CM4", "__FPU_PRESENT=1"],
  164. "Cortex-M7" : ["__CORTEX_M7", "ARM_MATH_CM7"],
  165. "Cortex-M7F" : ["__CORTEX_M7", "ARM_MATH_CM7", "__FPU_PRESENT=1"],
  166. "Cortex-A9" : ["__CORTEX_A9", "ARM_MATH_CA9", "__FPU_PRESENT", "__CMSIS_RTOS", "__EVAL", "__MBED_CMSIS_RTOS_CA9"],
  167. }
  168. GOANNA_FORMAT = "[Goanna] warning [%FILENAME%:%LINENO%] - [%CHECKNAME%(%SEVERITY%)] %MESSAGE%"
  169. GOANNA_DIAGNOSTIC_PATTERN = re.compile(r'"\[Goanna\] (?P<severity>warning) \[(?P<file>[^:]+):(?P<line>\d+)\] \- (?P<message>.*)"')
  170. def __init__(self, target, options=None, notify=None, macros=None, silent=False):
  171. self.target = target
  172. self.name = self.__class__.__name__
  173. self.hook = hooks.Hook(target, self)
  174. self.silent = silent
  175. self.legacy_ignore_dirs = LEGACY_IGNORE_DIRS - set([target.name, LEGACY_TOOLCHAIN_NAMES[self.name]])
  176. self.notify_fun = notify if notify is not None else print_notify
  177. self.options = options if options is not None else []
  178. self.macros = macros or []
  179. self.options.extend(BUILD_OPTIONS)
  180. if self.options:
  181. self.info("Build Options: %s" % (', '.join(self.options)))
  182. self.obj_path = join("TARGET_"+target.name, "TOOLCHAIN_"+self.name)
  183. self.symbols = None
  184. self.labels = None
  185. self.has_config = False
  186. self.build_all = False
  187. self.timestamp = time()
  188. self.jobs = 1
  189. self.CHROOT = None
  190. self.mp_pool = None
  191. def notify(self, event):
  192. """ Little closure for notify functions
  193. """
  194. return self.notify_fun(event, self.silent)
  195. def __exit__(self):
  196. if self.mp_pool is not None:
  197. self.mp_pool.terminate()
  198. def goanna_parse_line(self, line):
  199. if "analyze" in self.options:
  200. return self.GOANNA_DIAGNOSTIC_PATTERN.match(line)
  201. else:
  202. return None
  203. def get_symbols(self):
  204. if self.symbols is None:
  205. # Target and Toolchain symbols
  206. labels = self.get_labels()
  207. self.symbols = ["TARGET_%s" % t for t in labels['TARGET']]
  208. self.symbols.extend(["TOOLCHAIN_%s" % t for t in labels['TOOLCHAIN']])
  209. # Config support
  210. if self.has_config:
  211. self.symbols.append('HAVE_MBED_CONFIG_H')
  212. # Cortex CPU symbols
  213. if self.target.core in mbedToolchain.CORTEX_SYMBOLS:
  214. self.symbols.extend(mbedToolchain.CORTEX_SYMBOLS[self.target.core])
  215. # Symbols defined by the on-line build.system
  216. self.symbols.extend(['MBED_BUILD_TIMESTAMP=%s' % self.timestamp, '__MBED__=1'])
  217. if MBED_ORG_USER:
  218. self.symbols.append('MBED_USERNAME=' + MBED_ORG_USER)
  219. # Add target's symbols
  220. self.symbols += self.target.macros
  221. # Add extra symbols passed via 'macros' parameter
  222. self.symbols += self.macros
  223. # Form factor variables
  224. if hasattr(self.target, 'supported_form_factors'):
  225. self.symbols.extend(["TARGET_FF_%s" % t for t in self.target.supported_form_factors])
  226. return self.symbols
  227. def get_labels(self):
  228. if self.labels is None:
  229. toolchain_labels = [c.__name__ for c in getmro(self.__class__)]
  230. toolchain_labels.remove('mbedToolchain')
  231. self.labels = {
  232. 'TARGET': self.target.get_labels(),
  233. 'TOOLCHAIN': toolchain_labels
  234. }
  235. return self.labels
  236. def need_update(self, target, dependencies):
  237. if self.build_all:
  238. return True
  239. if not exists(target):
  240. return True
  241. target_mod_time = stat(target).st_mtime
  242. for d in dependencies:
  243. # Some objects are not provided with full path and here we do not have
  244. # information about the library paths. Safe option: assume an update
  245. if not d or not exists(d):
  246. return True
  247. if stat(d).st_mtime >= target_mod_time:
  248. return True
  249. return False
  250. def scan_resources(self, path):
  251. labels = self.get_labels()
  252. resources = Resources(path)
  253. self.has_config = False
  254. """ os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
  255. When topdown is True, the caller can modify the dirnames list in-place
  256. (perhaps using del or slice assignment), and walk() will only recurse into
  257. the subdirectories whose names remain in dirnames; this can be used to prune
  258. the search, impose a specific order of visiting, or even to inform walk()
  259. about directories the caller creates or renames before it resumes walk()
  260. again. Modifying dirnames when topdown is False is ineffective, because in
  261. bottom-up mode the directories in dirnames are generated before dirpath
  262. itself is generated.
  263. """
  264. for root, dirs, files in walk(path):
  265. # Remove ignored directories
  266. for d in copy(dirs):
  267. if d == '.hg':
  268. dir_path = join(root, d)
  269. resources.repo_dirs.append(dir_path)
  270. resources.repo_files.extend(self.scan_repository(dir_path))
  271. if ((d.startswith('.') or d in self.legacy_ignore_dirs) or
  272. (d.startswith('TARGET_') and d[7:] not in labels['TARGET']) or
  273. (d.startswith('TOOLCHAIN_') and d[10:] not in labels['TOOLCHAIN'])):
  274. dirs.remove(d)
  275. # Add root to include paths
  276. resources.inc_dirs.append(root)
  277. for file in files:
  278. file_path = join(root, file)
  279. _, ext = splitext(file)
  280. ext = ext.lower()
  281. if ext == '.s':
  282. resources.s_sources.append(file_path)
  283. elif ext == '.c':
  284. resources.c_sources.append(file_path)
  285. elif ext == '.cpp':
  286. resources.cpp_sources.append(file_path)
  287. elif ext == '.h' or ext == '.hpp':
  288. if basename(file_path) == "mbed_config.h":
  289. self.has_config = True
  290. resources.headers.append(file_path)
  291. elif ext == '.o':
  292. resources.objects.append(file_path)
  293. elif ext == self.LIBRARY_EXT:
  294. resources.libraries.append(file_path)
  295. resources.lib_dirs.add(root)
  296. elif ext == self.LINKER_EXT:
  297. if resources.linker_script is not None:
  298. self.info("Warning: Multiple linker scripts detected: %s -> %s" % (resources.linker_script, file_path))
  299. resources.linker_script = file_path
  300. elif ext == '.lib':
  301. resources.lib_refs.append(file_path)
  302. elif ext == '.bld':
  303. resources.lib_builds.append(file_path)
  304. elif file == '.hgignore':
  305. resources.repo_files.append(file_path)
  306. elif ext == '.hex':
  307. resources.hex_files.append(file_path)
  308. elif ext == '.bin':
  309. resources.bin_files.append(file_path)
  310. return resources
  311. def scan_repository(self, path):
  312. resources = []
  313. for root, dirs, files in walk(path):
  314. # Remove ignored directories
  315. for d in copy(dirs):
  316. if d == '.' or d == '..':
  317. dirs.remove(d)
  318. for file in files:
  319. file_path = join(root, file)
  320. resources.append(file_path)
  321. return resources
  322. def copy_files(self, files_paths, trg_path, rel_path=None):
  323. # Handle a single file
  324. if type(files_paths) != ListType: files_paths = [files_paths]
  325. for source in files_paths:
  326. if source is None:
  327. files_paths.remove(source)
  328. for source in files_paths:
  329. if rel_path is not None:
  330. relative_path = relpath(source, rel_path)
  331. else:
  332. _, relative_path = split(source)
  333. target = join(trg_path, relative_path)
  334. if (target != source) and (self.need_update(target, [source])):
  335. self.progress("copy", relative_path)
  336. mkdir(dirname(target))
  337. copyfile(source, target)
  338. def relative_object_path(self, build_path, base_dir, source):
  339. source_dir, name, _ = split_path(source)
  340. obj_dir = join(build_path, relpath(source_dir, base_dir))
  341. mkdir(obj_dir)
  342. return join(obj_dir, name + '.o')
  343. def compile_sources(self, resources, build_path, inc_dirs=None):
  344. # Web IDE progress bar for project build
  345. files_to_compile = resources.s_sources + resources.c_sources + resources.cpp_sources
  346. self.to_be_compiled = len(files_to_compile)
  347. self.compiled = 0
  348. #for i in self.build_params:
  349. # self.debug(i)
  350. # self.debug("%s" % self.build_params[i])
  351. inc_paths = resources.inc_dirs
  352. if inc_dirs is not None:
  353. inc_paths.extend(inc_dirs)
  354. objects = []
  355. queue = []
  356. prev_dir = None
  357. # The dependency checking for C/C++ is delegated to the compiler
  358. base_path = resources.base_path
  359. files_to_compile.sort()
  360. for source in files_to_compile:
  361. _, name, _ = split_path(source)
  362. object = self.relative_object_path(build_path, base_path, source)
  363. # Avoid multiple mkdir() calls on same work directory
  364. work_dir = dirname(object)
  365. if work_dir is not prev_dir:
  366. prev_dir = work_dir
  367. mkdir(work_dir)
  368. # Queue mode (multiprocessing)
  369. commands = self.compile_command(source, object, inc_paths)
  370. if commands is not None:
  371. queue.append({
  372. 'source': source,
  373. 'object': object,
  374. 'commands': commands,
  375. 'work_dir': work_dir,
  376. 'chroot': self.CHROOT
  377. })
  378. else:
  379. objects.append(object)
  380. # Use queues/multiprocessing if cpu count is higher than setting
  381. jobs = self.jobs if self.jobs else cpu_count()
  382. if jobs > CPU_COUNT_MIN and len(queue) > jobs:
  383. return self.compile_queue(queue, objects)
  384. else:
  385. return self.compile_seq(queue, objects)
  386. def compile_seq(self, queue, objects):
  387. for item in queue:
  388. result = compile_worker(item)
  389. self.compiled += 1
  390. self.progress("compile", item['source'], build_update=True)
  391. for res in result['results']:
  392. self.debug("Command: %s" % ' '.join(res['command']))
  393. self.compile_output([
  394. res['code'],
  395. res['output'],
  396. res['command']
  397. ])
  398. objects.append(result['object'])
  399. return objects
  400. def compile_queue(self, queue, objects):
  401. jobs_count = int(self.jobs if self.jobs else cpu_count())
  402. p = Pool(processes=jobs_count)
  403. results = []
  404. for i in range(len(queue)):
  405. results.append(p.apply_async(compile_worker, [queue[i]]))
  406. itr = 0
  407. while True:
  408. itr += 1
  409. if itr > 30000:
  410. p.terminate()
  411. p.join()
  412. raise ToolException("Compile did not finish in 5 minutes")
  413. pending = 0
  414. for r in results:
  415. if r._ready is True:
  416. try:
  417. result = r.get()
  418. results.remove(r)
  419. self.compiled += 1
  420. self.progress("compile", result['source'], build_update=True)
  421. for res in result['results']:
  422. self.debug("Command: %s" % ' '.join(res['command']))
  423. self.compile_output([
  424. res['code'],
  425. res['output'],
  426. res['command']
  427. ])
  428. objects.append(result['object'])
  429. except ToolException, err:
  430. p.terminate()
  431. p.join()
  432. raise ToolException(err)
  433. else:
  434. pending += 1
  435. if pending > jobs_count:
  436. break
  437. if len(results) == 0:
  438. break
  439. sleep(0.01)
  440. results = None
  441. p.terminate()
  442. p.join()
  443. return objects
  444. def compile_command(self, source, object, includes):
  445. # Check dependencies
  446. _, ext = splitext(source)
  447. ext = ext.lower()
  448. if ext == '.c' or ext == '.cpp':
  449. base, _ = splitext(object)
  450. dep_path = base + '.d'
  451. deps = self.parse_dependencies(dep_path) if (exists(dep_path)) else []
  452. if len(deps) == 0 or self.need_update(object, deps):
  453. if ext == '.c':
  454. return self.compile_c(source, object, includes)
  455. else:
  456. return self.compile_cpp(source, object, includes)
  457. elif ext == '.s':
  458. deps = [source]
  459. if self.need_update(object, deps):
  460. return self.assemble(source, object, includes)
  461. else:
  462. return False
  463. return None
  464. def compile_output(self, output=[]):
  465. _rc = output[0]
  466. _stderr = output[1]
  467. command = output[2]
  468. # Parse output for Warnings and Errors
  469. self.parse_output(_stderr)
  470. self.debug("Return: %s"% _rc)
  471. for error_line in _stderr.splitlines():
  472. self.debug("Output: %s"% error_line)
  473. # Check return code
  474. if _rc != 0:
  475. for line in _stderr.splitlines():
  476. self.tool_error(line)
  477. raise ToolException(_stderr)
  478. def compile(self, cc, source, object, includes):
  479. _, ext = splitext(source)
  480. ext = ext.lower()
  481. command = cc + ['-D%s' % s for s in self.get_symbols()] + ["-I%s" % i for i in includes] + ["-o", object, source]
  482. if hasattr(self, "get_dep_opt"):
  483. base, _ = splitext(object)
  484. dep_path = base + '.d'
  485. command.extend(self.get_dep_opt(dep_path))
  486. if hasattr(self, "cc_extra"):
  487. command.extend(self.cc_extra(base))
  488. return [command]
  489. def compile_c(self, source, object, includes):
  490. return self.compile(self.cc, source, object, includes)
  491. def compile_cpp(self, source, object, includes):
  492. return self.compile(self.cppc, source, object, includes)
  493. def build_library(self, objects, dir, name):
  494. lib = self.STD_LIB_NAME % name
  495. fout = join(dir, lib)
  496. if self.need_update(fout, objects):
  497. self.info("Library: %s" % lib)
  498. self.archive(objects, fout)
  499. def link_program(self, r, tmp_path, name):
  500. ext = 'bin'
  501. if hasattr(self.target, 'OUTPUT_EXT'):
  502. ext = self.target.OUTPUT_EXT
  503. if hasattr(self.target, 'OUTPUT_NAMING'):
  504. self.var("binary_naming", self.target.OUTPUT_NAMING)
  505. if self.target.OUTPUT_NAMING == "8.3":
  506. name = name[0:8]
  507. ext = ext[0:3]
  508. filename = name+'.'+ext
  509. elf = join(tmp_path, name + '.elf')
  510. bin = join(tmp_path, filename)
  511. if self.need_update(elf, r.objects + r.libraries + [r.linker_script]):
  512. self.progress("link", name)
  513. self.link(elf, r.objects, r.libraries, r.lib_dirs, r.linker_script)
  514. if self.need_update(bin, [elf]):
  515. self.progress("elf2bin", name)
  516. self.binary(r, elf, bin)
  517. self.var("compile_succeded", True)
  518. self.var("binary", filename)
  519. return bin
  520. def default_cmd(self, command):
  521. _stdout, _stderr, _rc = run_cmd(command)
  522. # Print all warning / erros from stderr to console output
  523. for error_line in _stderr.splitlines():
  524. print error_line
  525. self.debug("Command: %s"% ' '.join(command))
  526. self.debug("Return: %s"% _rc)
  527. for output_line in _stdout.splitlines():
  528. self.debug("Output: %s"% output_line)
  529. for error_line in _stderr.splitlines():
  530. self.debug("Errors: %s"% error_line)
  531. if _rc != 0:
  532. for line in _stderr.splitlines():
  533. self.tool_error(line)
  534. raise ToolException(_stderr)
  535. ### NOTIFICATIONS ###
  536. def info(self, message):
  537. self.notify({'type': 'info', 'message': message})
  538. def debug(self, message):
  539. if self.VERBOSE:
  540. if type(message) is ListType:
  541. message = ' '.join(message)
  542. message = "[DEBUG] " + message
  543. self.notify({'type': 'debug', 'message': message})
  544. def cc_info(self, severity, file, line, message, target_name=None, toolchain_name=None):
  545. self.notify({'type': 'cc',
  546. 'severity': severity,
  547. 'file': file,
  548. 'line': line,
  549. 'message': message,
  550. 'target_name': target_name,
  551. 'toolchain_name': toolchain_name})
  552. def progress(self, action, file, build_update=False):
  553. msg = {'type': 'progress', 'action': action, 'file': file}
  554. if build_update:
  555. msg['percent'] = 100. * float(self.compiled) / float(self.to_be_compiled)
  556. self.notify(msg)
  557. def tool_error(self, message):
  558. self.notify({'type': 'tool_error', 'message': message})
  559. def var(self, key, value):
  560. self.notify({'type': 'var', 'key': key, 'val': value})
  561. from workspace_tools.settings import ARM_BIN
  562. from workspace_tools.settings import GCC_ARM_PATH, GCC_CR_PATH, GCC_CS_PATH, CW_EWL_PATH, CW_GCC_PATH
  563. from workspace_tools.settings import IAR_PATH
  564. TOOLCHAIN_BIN_PATH = {
  565. 'ARM': ARM_BIN,
  566. 'uARM': ARM_BIN,
  567. 'GCC_ARM': GCC_ARM_PATH,
  568. 'GCC_CS': GCC_CS_PATH,
  569. 'GCC_CR': GCC_CR_PATH,
  570. 'GCC_CW_EWL': CW_EWL_PATH,
  571. 'GCC_CW_NEWLIB': CW_GCC_PATH,
  572. 'IAR': IAR_PATH
  573. }
  574. from workspace_tools.toolchains.arm import ARM_STD, ARM_MICRO
  575. from workspace_tools.toolchains.gcc import GCC_ARM, GCC_CS, GCC_CR
  576. from workspace_tools.toolchains.gcc import GCC_CW_EWL, GCC_CW_NEWLIB
  577. from workspace_tools.toolchains.iar import IAR
  578. TOOLCHAIN_CLASSES = {
  579. 'ARM': ARM_STD,
  580. 'uARM': ARM_MICRO,
  581. 'GCC_ARM': GCC_ARM,
  582. 'GCC_CS': GCC_CS,
  583. 'GCC_CR': GCC_CR,
  584. 'GCC_CW_EWL': GCC_CW_EWL,
  585. 'GCC_CW_NEWLIB': GCC_CW_NEWLIB,
  586. 'IAR': IAR
  587. }
  588. TOOLCHAINS = set(TOOLCHAIN_CLASSES.keys())