building.py 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  1. #
  2. # File : building.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. # 2015-07-25 Bernard Add LOCAL_CCFLAGS/LOCAL_CPPPATH/LOCAL_CPPDEFINES for
  24. # group definition.
  25. #
  26. import os
  27. import sys
  28. import string
  29. import utils
  30. import operator
  31. import rtconfig
  32. import platform
  33. from SCons.Script import *
  34. from utils import _make_path_relative
  35. from mkdist import do_copy_file
  36. from options import AddOptions
  37. BuildOptions = {}
  38. Projects = []
  39. Dtc = {}
  40. Rtt_Root = ''
  41. Env = None
  42. # SCons PreProcessor patch
  43. def start_handling_includes(self, t=None):
  44. """
  45. Causes the PreProcessor object to start processing #import,
  46. #include and #include_next lines.
  47. This method will be called when a #if, #ifdef, #ifndef or #elif
  48. evaluates True, or when we reach the #else in a #if, #ifdef,
  49. #ifndef or #elif block where a condition already evaluated
  50. False.
  51. """
  52. d = self.dispatch_table
  53. p = self.stack[-1] if self.stack else self.default_table
  54. for k in ('import', 'include', 'include_next', 'define'):
  55. d[k] = p[k]
  56. def stop_handling_includes(self, t=None):
  57. """
  58. Causes the PreProcessor object to stop processing #import,
  59. #include and #include_next lines.
  60. This method will be called when a #if, #ifdef, #ifndef or #elif
  61. evaluates False, or when we reach the #else in a #if, #ifdef,
  62. #ifndef or #elif block where a condition already evaluated True.
  63. """
  64. d = self.dispatch_table
  65. d['import'] = self.do_nothing
  66. d['include'] = self.do_nothing
  67. d['include_next'] = self.do_nothing
  68. d['define'] = self.do_nothing
  69. PatchedPreProcessor = SCons.cpp.PreProcessor
  70. PatchedPreProcessor.start_handling_includes = start_handling_includes
  71. PatchedPreProcessor.stop_handling_includes = stop_handling_includes
  72. class Win32Spawn:
  73. def spawn(self, sh, escape, cmd, args, env):
  74. # deal with the cmd build-in commands which cannot be used in
  75. # subprocess.Popen
  76. if cmd == 'del':
  77. for f in args[1:]:
  78. try:
  79. os.remove(f)
  80. except Exception as e:
  81. print('Error removing file: ' + e)
  82. return -1
  83. return 0
  84. import subprocess
  85. newargs = ' '.join(args[1:])
  86. cmdline = cmd + " " + newargs
  87. # Make sure the env is constructed by strings
  88. _e = dict([(k, str(v)) for k, v in env.items()])
  89. # Windows(tm) CreateProcess does not use the env passed to it to find
  90. # the executables. So we have to modify our own PATH to make Popen
  91. # work.
  92. old_path = os.environ['PATH']
  93. os.environ['PATH'] = _e['PATH']
  94. try:
  95. proc = subprocess.Popen(cmdline, env=_e, shell=False)
  96. except Exception as e:
  97. print('Error in calling command:' + cmdline.split(' ')[0])
  98. print('Exception: ' + os.strerror(e.errno))
  99. if (os.strerror(e.errno) == "No such file or directory"):
  100. print ("\nPlease check Toolchains PATH setting.\n")
  101. return e.errno
  102. finally:
  103. os.environ['PATH'] = old_path
  104. return proc.wait()
  105. # generate cconfig.h file
  106. def GenCconfigFile(env, BuildOptions):
  107. if rtconfig.PLATFORM in ['gcc']:
  108. contents = ''
  109. if not os.path.isfile('cconfig.h'):
  110. import gcc
  111. gcc.GenerateGCCConfig(rtconfig)
  112. # try again
  113. if os.path.isfile('cconfig.h'):
  114. f = open('cconfig.h', 'r')
  115. if f:
  116. contents = f.read()
  117. f.close()
  118. prep = PatchedPreProcessor()
  119. prep.process_contents(contents)
  120. options = prep.cpp_namespace
  121. BuildOptions.update(options)
  122. # add HAVE_CCONFIG_H definition
  123. env.AppendUnique(CPPDEFINES = ['HAVE_CCONFIG_H'])
  124. def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = [], app = False):
  125. global BuildOptions
  126. global Projects
  127. global Env
  128. global Rtt_Root
  129. AddOptions()
  130. Env = env
  131. Rtt_Root = os.path.abspath(root_directory)
  132. # make an absolute root directory
  133. RTT_ROOT = Rtt_Root
  134. Export('RTT_ROOT')
  135. # set RTT_ROOT in ENV
  136. Env['RTT_ROOT'] = Rtt_Root
  137. # set BSP_ROOT in ENV
  138. Env['BSP_ROOT'] = Dir('#').abspath
  139. sys.path = sys.path + [os.path.join(Rtt_Root, 'tools')]
  140. # {target_name:(CROSS_TOOL, PLATFORM)}
  141. tgt_dict = {'mdk':('keil', 'armcc'),
  142. 'mdk4':('keil', 'armcc'),
  143. 'mdk5':('keil', 'armcc'),
  144. 'iar':('iar', 'iccarm'),
  145. 'vs':('msvc', 'cl'),
  146. 'vs2012':('msvc', 'cl'),
  147. 'vsc' : ('gcc', 'gcc'),
  148. 'cb':('keil', 'armcc'),
  149. 'ua':('gcc', 'gcc'),
  150. 'cdk':('gcc', 'gcc'),
  151. 'makefile':('gcc', 'gcc'),
  152. 'eclipse':('gcc', 'gcc'),
  153. 'ses' : ('gcc', 'gcc'),
  154. 'cmake':('gcc', 'gcc'),
  155. 'cmake-armclang':('keil', 'armclang'),
  156. 'xmake':('gcc', 'gcc'),
  157. 'codelite' : ('gcc', 'gcc'),
  158. 'esp-idf': ('gcc', 'gcc'),
  159. 'cic':('gcc', 'gcc')}
  160. tgt_name = GetOption('target')
  161. if tgt_name:
  162. # --target will change the toolchain settings which clang-analyzer is
  163. # depend on
  164. if GetOption('clang-analyzer'):
  165. print ('--clang-analyzer cannot be used with --target')
  166. sys.exit(1)
  167. SetOption('no_exec', 1)
  168. try:
  169. rtconfig.CROSS_TOOL, rtconfig.PLATFORM = tgt_dict[tgt_name]
  170. # replace the 'RTT_CC' to 'CROSS_TOOL'
  171. os.environ['RTT_CC'] = rtconfig.CROSS_TOOL
  172. except KeyError:
  173. print('Unknow target: '+ tgt_name+'. Avaible targets: ' +', '.join(tgt_dict.keys()))
  174. sys.exit(1)
  175. exec_prefix = GetOption('exec-prefix')
  176. if exec_prefix:
  177. os.environ['RTT_CC_PREFIX'] = exec_prefix
  178. build_type = GetOption('build-type')
  179. if build_type:
  180. if build_type in ['debug', 'release']:
  181. os.environ['BUILD_TYPE'] = build_type
  182. else:
  183. sys.stderr.write("Invalid option for --build-type: {}. Must be 'debug' or 'release'.\n".format(build_type))
  184. sys.exit(1)
  185. # auto change the 'RTT_EXEC_PATH' when 'rtconfig.EXEC_PATH' get failed
  186. if not os.path.exists(rtconfig.EXEC_PATH):
  187. if 'RTT_EXEC_PATH' in os.environ:
  188. # del the 'RTT_EXEC_PATH' and using the 'EXEC_PATH' setting on rtconfig.py
  189. del os.environ['RTT_EXEC_PATH']
  190. exec_path = GetOption('exec-path')
  191. if exec_path:
  192. os.environ['RTT_EXEC_PATH'] = exec_path
  193. utils.ReloadModule(rtconfig) # update environment variables to rtconfig.py
  194. # some env variables have loaded in Environment() of SConstruct before re-load rtconfig.py;
  195. # after update rtconfig.py's variables, those env variables need to synchronize
  196. if exec_prefix:
  197. env['CC'] = rtconfig.CC
  198. env['CXX'] = rtconfig.CXX
  199. env['AS'] = rtconfig.AS
  200. env['AR'] = rtconfig.AR
  201. env['LINK'] = rtconfig.LINK
  202. if exec_path:
  203. env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
  204. env['ASCOM'] = env['ASPPCOM']
  205. env['LINKCOM'] = '$LINK -o build/$TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS -Wl,--start-group $_LIBFLAGS -Wl,--end-group'
  206. if GetOption('strict-compiling'):
  207. STRICT_FLAGS = ''
  208. if rtconfig.PLATFORM in ['gcc']:
  209. STRICT_FLAGS += ' -Werror' #-Wextra
  210. env.Append(CFLAGS=STRICT_FLAGS, CXXFLAGS=STRICT_FLAGS)
  211. # add compability with Keil MDK 4.6 which changes the directory of armcc.exe
  212. if rtconfig.PLATFORM in ['armcc', 'armclang']:
  213. if rtconfig.PLATFORM == 'armcc' and not os.path.isfile(os.path.join(rtconfig.EXEC_PATH, 'armcc.exe')):
  214. if rtconfig.EXEC_PATH.find('bin40') > 0:
  215. rtconfig.EXEC_PATH = rtconfig.EXEC_PATH.replace('bin40', 'armcc/bin')
  216. Env['LINKFLAGS'] = Env['LINKFLAGS'].replace('RV31', 'armcc')
  217. # reset AR command flags
  218. env['ARCOM'] = '$AR --create $TARGET $SOURCES'
  219. env['LIBPREFIX'] = ''
  220. env['LIBSUFFIX'] = '.lib'
  221. env['LIBLINKPREFIX'] = ''
  222. env['LIBLINKSUFFIX'] = '.lib'
  223. env['LIBDIRPREFIX'] = '--userlibpath '
  224. elif rtconfig.PLATFORM == 'iccarm':
  225. env['LIBPREFIX'] = ''
  226. env['LIBSUFFIX'] = '.a'
  227. env['LIBLINKPREFIX'] = ''
  228. env['LIBLINKSUFFIX'] = '.a'
  229. env['LIBDIRPREFIX'] = '--search '
  230. # patch for win32 spawn
  231. if env['PLATFORM'] == 'win32':
  232. win32_spawn = Win32Spawn()
  233. win32_spawn.env = env
  234. env['SPAWN'] = win32_spawn.spawn
  235. if env['PLATFORM'] == 'win32':
  236. os.environ['PATH'] = rtconfig.EXEC_PATH + ";" + os.environ['PATH']
  237. else:
  238. os.environ['PATH'] = rtconfig.EXEC_PATH + ":" + os.environ['PATH']
  239. # add program path
  240. env.PrependENVPath('PATH', os.environ['PATH'])
  241. # add rtconfig.h/BSP path into Kernel group
  242. DefineGroup("Kernel", [], [], CPPPATH=[str(Dir('#').abspath)])
  243. # add library build action
  244. act = SCons.Action.Action(BuildLibInstallAction, 'Install compiled library... $TARGET')
  245. bld = Builder(action = act)
  246. Env.Append(BUILDERS = {'BuildLib': bld})
  247. # parse rtconfig.h to get used component
  248. PreProcessor = PatchedPreProcessor()
  249. f = open('rtconfig.h', 'r')
  250. contents = f.read()
  251. f.close()
  252. f = open(os.path.join(RTT_ROOT, 'include', 'kconfig', rtconfig.CHIP, 'kconfig.h'), 'r')
  253. contents += f.read()
  254. f.close()
  255. PreProcessor.process_contents(contents)
  256. BuildOptions = PreProcessor.cpp_namespace
  257. if GetOption('clang-analyzer'):
  258. # perform what scan-build does
  259. env.Replace(
  260. CC = 'ccc-analyzer',
  261. CXX = 'c++-analyzer',
  262. # skip as and link
  263. LINK = 'true',
  264. AS = 'true',)
  265. env["ENV"].update(x for x in os.environ.items() if x[0].startswith("CCC_"))
  266. # only check, don't compile. ccc-analyzer use CCC_CC as the CC.
  267. # fsyntax-only will give us some additional warning messages
  268. env['ENV']['CCC_CC'] = 'clang'
  269. env.Append(CFLAGS=['-fsyntax-only', '-Wall', '-Wno-invalid-source-encoding'])
  270. env['ENV']['CCC_CXX'] = 'clang++'
  271. env.Append(CXXFLAGS=['-fsyntax-only', '-Wall', '-Wno-invalid-source-encoding'])
  272. # remove the POST_ACTION as it will cause meaningless errors(file not
  273. # found or something like that).
  274. rtconfig.POST_ACTION = ''
  275. # generate cconfig.h file
  276. # GenCconfigFile(env, BuildOptions)
  277. # auto append '_REENT_SMALL' when using newlib 'nano.specs' option
  278. if rtconfig.PLATFORM in ['gcc'] and str(env['LINKFLAGS']).find('nano.specs') != -1:
  279. env.AppendUnique(CPPDEFINES = ['_REENT_SMALL'])
  280. attach_global_macros = GetOption('global-macros')
  281. if attach_global_macros:
  282. attach_global_macros = attach_global_macros.split(',')
  283. if isinstance(attach_global_macros, list):
  284. for config in attach_global_macros:
  285. if isinstance(config, str):
  286. AddDepend(attach_global_macros)
  287. env.Append(CFLAGS=' -D' + config, CXXFLAGS=' -D' + config, AFLAGS=' -D' + config)
  288. else:
  289. print('--global-macros arguments are illegal!')
  290. else:
  291. print('--global-macros arguments are illegal!')
  292. if GetOption('genconfig'):
  293. from genconf import genconfig
  294. genconfig()
  295. exit(0)
  296. if GetOption('stackanalysis'):
  297. from WCS import ThreadStackStaticAnalysis
  298. ThreadStackStaticAnalysis(Env)
  299. exit(0)
  300. if GetOption('menuconfig'):
  301. from menu import menu
  302. menu(Rtt_Root)
  303. exit(0)
  304. if GetOption('pyconfig-silent'):
  305. from menu import guiconfig_silent
  306. guiconfig_silent(Rtt_Root)
  307. exit(0)
  308. elif GetOption('pyconfig'):
  309. from menu import guiconfig
  310. guiconfig(Rtt_Root)
  311. exit(0)
  312. configfn = GetOption('useconfig')
  313. if configfn:
  314. from menu import mk_rtconfig
  315. mk_rtconfig(configfn)
  316. exit(0)
  317. if not GetOption('verbose'):
  318. # override the default verbose command string
  319. env.Replace(
  320. ARCOMSTR = ' AR $TARGET',
  321. ASCOMSTR = ' AS $TARGET',
  322. ASPPCOMSTR = ' AS $TARGET',
  323. CCCOMSTR = ' CC $TARGET',
  324. CXXCOMSTR = ' CXX $TARGET',
  325. LINKCOMSTR = ' LINK $TARGET',
  326. DTCCOMSTR = ' DTC $TARGET',
  327. LDCOMSTR = ' LD $TARGET'
  328. )
  329. if GetOption('app_pkg'):
  330. from app_pkg import pack_bin
  331. debug_mode = GetOption('debug_mode') or 0
  332. pack_bin(GetOption('app_pkg'), debug_mode)
  333. exit(0)
  334. # fix the linker for C++
  335. if GetDepend('RT_USING_CPLUSPLUS'):
  336. if env['LINK'].find('gcc') != -1:
  337. env['LINK'] = env['LINK'].replace('gcc', 'g++')
  338. # we need to seperate the variant_dir for BSPs and the kernels. BSPs could
  339. # have their own components etc. If they point to the same folder, SCons
  340. # would find the wrong source code to compile.
  341. bsp_vdir = 'build'
  342. # board build script
  343. objs = SConscript('SConscript', variant_dir=bsp_vdir, duplicate=0)
  344. if not app:
  345. kernel_vdir = 'build/kernel'
  346. # include kernel
  347. objs.extend(SConscript(Rtt_Root + '/src/SConscript', variant_dir=kernel_vdir + '/src', duplicate=0))
  348. # include libcpu
  349. if not has_libcpu:
  350. objs.extend(SConscript(Rtt_Root + '/libcpu/SConscript',
  351. variant_dir=kernel_vdir + '/libcpu', duplicate=0))
  352. # include components
  353. objs.extend(SConscript(Rtt_Root + '/components/SConscript',
  354. variant_dir=kernel_vdir + '/components',
  355. duplicate=0,
  356. exports='remove_components'))
  357. # include examples
  358. if os.path.isfile(os.path.join(Rtt_Root, 'examples/SConscript')):
  359. objs.extend(SConscript(os.path.join(Rtt_Root, 'examples/SConscript'),
  360. variant_dir=kernel_vdir + '/examples',
  361. duplicate=0))
  362. # include testcases
  363. if os.path.isfile(os.path.join(Rtt_Root, 'testcases/SConscript')):
  364. objs.extend(SConscript(os.path.join(Rtt_Root, 'testcases/SConscript'),
  365. variant_dir=kernel_vdir + '/testcases',
  366. duplicate=0))
  367. return objs
  368. def PrepareModuleBuilding(env, root_directory, bsp_directory):
  369. global BuildOptions
  370. global Env
  371. global Rtt_Root
  372. # patch for win32 spawn
  373. if env['PLATFORM'] == 'win32':
  374. win32_spawn = Win32Spawn()
  375. win32_spawn.env = env
  376. env['SPAWN'] = win32_spawn.spawn
  377. Env = env
  378. Rtt_Root = root_directory
  379. # parse bsp rtconfig.h to get used component
  380. PreProcessor = PatchedPreProcessor()
  381. f = open(bsp_directory + '/rtconfig.h', 'r')
  382. contents = f.read()
  383. f.close()
  384. f = open(bsp_directory + '/kconfig.h', 'r')
  385. contents += f.read()
  386. f.close()
  387. PreProcessor.process_contents(contents)
  388. BuildOptions = PreProcessor.cpp_namespace
  389. AddOption('--buildlib',
  390. dest = 'buildlib',
  391. type = 'string',
  392. help = 'building library of a component')
  393. AddOption('--cleanlib',
  394. dest = 'cleanlib',
  395. action = 'store_true',
  396. default = False,
  397. help = 'clean up the library by --buildlib')
  398. # add program path
  399. env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
  400. def GetConfigValue(name):
  401. assert type(name) == str, 'GetConfigValue: only string parameter is valid'
  402. try:
  403. return BuildOptions[name]
  404. except:
  405. return ''
  406. def GetDepend(depend):
  407. building = True
  408. if type(depend) == type('str'):
  409. if not depend in BuildOptions or BuildOptions[depend] == 0:
  410. building = False
  411. elif BuildOptions[depend] != '':
  412. return BuildOptions[depend]
  413. return building
  414. # for list type depend
  415. for item in depend:
  416. if item != '':
  417. if not item in BuildOptions or BuildOptions[item] == 0:
  418. building = False
  419. return building
  420. def LocalOptions(config_filename):
  421. from SCons.Script import SCons
  422. # parse wiced_config.h to get used component
  423. PreProcessor = SCons.cpp.PreProcessor()
  424. f = open(config_filename, 'r')
  425. contents = f.read()
  426. f.close()
  427. PreProcessor.process_contents(contents)
  428. local_options = PreProcessor.cpp_namespace
  429. return local_options
  430. def GetLocalDepend(options, depend):
  431. building = True
  432. if type(depend) == type('str'):
  433. if not depend in options or options[depend] == 0:
  434. building = False
  435. elif options[depend] != '':
  436. return options[depend]
  437. return building
  438. # for list type depend
  439. for item in depend:
  440. if item != '':
  441. if not item in options or options[item] == 0:
  442. building = False
  443. return building
  444. def AddDepend(option):
  445. if isinstance(option, str):
  446. BuildOptions[option] = 1
  447. elif isinstance(option, list):
  448. for obj in option:
  449. if isinstance(obj, str):
  450. BuildOptions[obj] = 1
  451. else:
  452. print('AddDepend arguements are illegal!')
  453. else:
  454. print('AddDepend arguements are illegal!')
  455. def Preprocessing(input, suffix, output = None, CPPPATH = None):
  456. if hasattr(rtconfig, "CPP") and hasattr(rtconfig, "CPPFLAGS"):
  457. if output == None:
  458. import re
  459. output = re.sub(r'[\.]+.*', suffix, input)
  460. inc = ' '
  461. cpppath = CPPPATH
  462. for cpppath_item in cpppath:
  463. inc += ' -I' + cpppath_item
  464. CPP = rtconfig.EXEC_PATH + '/' + rtconfig.CPP
  465. if not os.path.exists(CPP):
  466. CPP = rtconfig.CPP
  467. CPP += rtconfig.CPPFLAGS
  468. path = GetCurrentDir() + '/'
  469. os.system(CPP + inc + ' ' + path + input + ' -o ' + path + output)
  470. else:
  471. print('CPP tool or CPPFLAGS is undefined in rtconfig!')
  472. def MergeGroup(src_group, group):
  473. src_group['src'] = src_group['src'] + group['src']
  474. src_group['src'].sort()
  475. if 'CFLAGS' in group:
  476. if 'CFLAGS' in src_group:
  477. src_group['CFLAGS'] = src_group['CFLAGS'] + group['CFLAGS']
  478. else:
  479. src_group['CFLAGS'] = group['CFLAGS']
  480. if 'CCFLAGS' in group:
  481. if 'CCFLAGS' in src_group:
  482. src_group['CCFLAGS'] = src_group['CCFLAGS'] + group['CCFLAGS']
  483. else:
  484. src_group['CCFLAGS'] = group['CCFLAGS']
  485. if 'CXXFLAGS' in group:
  486. if 'CXXFLAGS' in src_group:
  487. src_group['CXXFLAGS'] = src_group['CXXFLAGS'] + group['CXXFLAGS']
  488. else:
  489. src_group['CXXFLAGS'] = group['CXXFLAGS']
  490. if 'CPPPATH' in group:
  491. if 'CPPPATH' in src_group:
  492. src_group['CPPPATH'] = src_group['CPPPATH'] + group['CPPPATH']
  493. else:
  494. src_group['CPPPATH'] = group['CPPPATH']
  495. if 'CPPDEFINES' in group:
  496. if 'CPPDEFINES' in src_group:
  497. src_group['CPPDEFINES'] = src_group['CPPDEFINES'] + group['CPPDEFINES']
  498. else:
  499. src_group['CPPDEFINES'] = group['CPPDEFINES']
  500. if 'ASFLAGS' in group:
  501. if 'ASFLAGS' in src_group:
  502. src_group['ASFLAGS'] = src_group['ASFLAGS'] + group['ASFLAGS']
  503. else:
  504. src_group['ASFLAGS'] = group['ASFLAGS']
  505. # for local CCFLAGS/CPPPATH/CPPDEFINES
  506. if 'LOCAL_CFLAGS' in group:
  507. if 'LOCAL_CFLAGS' in src_group:
  508. src_group['LOCAL_CFLAGS'] = src_group['LOCAL_CFLAGS'] + group['LOCAL_CFLAGS']
  509. else:
  510. src_group['LOCAL_CFLAGS'] = group['LOCAL_CFLAGS']
  511. if 'LOCAL_CCFLAGS' in group:
  512. if 'LOCAL_CCFLAGS' in src_group:
  513. src_group['LOCAL_CCFLAGS'] = src_group['LOCAL_CCFLAGS'] + group['LOCAL_CCFLAGS']
  514. else:
  515. src_group['LOCAL_CCFLAGS'] = group['LOCAL_CCFLAGS']
  516. if 'LOCAL_CXXFLAGS' in group:
  517. if 'LOCAL_CXXFLAGS' in src_group:
  518. src_group['LOCAL_CXXFLAGS'] = src_group['LOCAL_CXXFLAGS'] + group['LOCAL_CXXFLAGS']
  519. else:
  520. src_group['LOCAL_CXXFLAGS'] = group['LOCAL_CXXFLAGS']
  521. if 'LOCAL_CPPPATH' in group:
  522. if 'LOCAL_CPPPATH' in src_group:
  523. src_group['LOCAL_CPPPATH'] = src_group['LOCAL_CPPPATH'] + group['LOCAL_CPPPATH']
  524. else:
  525. src_group['LOCAL_CPPPATH'] = group['LOCAL_CPPPATH']
  526. if 'LOCAL_CPPDEFINES' in group:
  527. if 'LOCAL_CPPDEFINES' in src_group:
  528. src_group['LOCAL_CPPDEFINES'] = src_group['LOCAL_CPPDEFINES'] + group['LOCAL_CPPDEFINES']
  529. else:
  530. src_group['LOCAL_CPPDEFINES'] = group['LOCAL_CPPDEFINES']
  531. if 'LINKFLAGS' in group:
  532. if 'LINKFLAGS' in src_group:
  533. src_group['LINKFLAGS'] = src_group['LINKFLAGS'] + group['LINKFLAGS']
  534. else:
  535. src_group['LINKFLAGS'] = group['LINKFLAGS']
  536. if 'LIBS' in group:
  537. if 'LIBS' in src_group:
  538. src_group['LIBS'] = src_group['LIBS'] + group['LIBS']
  539. else:
  540. src_group['LIBS'] = group['LIBS']
  541. if 'LIBPATH' in group:
  542. if 'LIBPATH' in src_group:
  543. src_group['LIBPATH'] = src_group['LIBPATH'] + group['LIBPATH']
  544. else:
  545. src_group['LIBPATH'] = group['LIBPATH']
  546. if 'LOCAL_ASFLAGS' in group:
  547. if 'LOCAL_ASFLAGS' in src_group:
  548. src_group['LOCAL_ASFLAGS'] = src_group['LOCAL_ASFLAGS'] + group['LOCAL_ASFLAGS']
  549. else:
  550. src_group['LOCAL_ASFLAGS'] = group['LOCAL_ASFLAGS']
  551. def _PretreatListParameters(target_list):
  552. while '' in target_list: # remove null strings
  553. target_list.remove('')
  554. while ' ' in target_list: # remove ' '
  555. target_list.remove(' ')
  556. if(len(target_list) == 0):
  557. return False # ignore this list, don't add this list to the parameter
  558. return True # permit to add this list to the parameter
  559. def PrepareDTC(src, depend, **parameters):
  560. global Dtc
  561. if not GetDepend(depend):
  562. return []
  563. if Dtc != {}:
  564. return []
  565. Dtc = parameters
  566. Dtc['path'] = GetCurrentDir()
  567. Dtc['src'] = File(src)
  568. if 'DTCFLAGS' in Dtc:
  569. target = Dtc['DTCFLAGS']
  570. if len(target) > 0:
  571. Env.AppendUnique(DTCFLAGS = target)
  572. if 'DTCPATH' in Dtc:
  573. target = Dtc['DTCPATH']
  574. if _PretreatListParameters(target) == True:
  575. paths = []
  576. for item in target:
  577. paths.append(os.path.abspath(item))
  578. target = paths
  579. Env.AppendUnique(DTCPATH = target)
  580. return []
  581. def DefineGroup(name, src, depend, **parameters):
  582. global Env
  583. if not GetDepend(depend):
  584. if GetOption('gen-sdk-config'):
  585. add_unused_group(name, Rtt_Root, GetCurrentDir())
  586. return []
  587. # find exist group and get path of group
  588. group_path = ''
  589. for g in Projects:
  590. if g['name'] == name:
  591. group_path = g['path']
  592. if group_path == '':
  593. group_path = GetCurrentDir()
  594. group = parameters
  595. group['name'] = name
  596. group['path'] = group_path
  597. if type(src) == type([]):
  598. # remove duplicate elements from list
  599. src = list(set(src))
  600. group['src'] = File(src)
  601. else:
  602. group['src'] = src
  603. if group['name'] != 'Kernel':
  604. o_files = []
  605. cwd = GetCurrentDir()
  606. for root, dirs, files in os.walk(cwd):
  607. for file in files:
  608. if file.endswith(".o"):
  609. o_file = os.path.join(root, file)
  610. o_files.append(o_file)
  611. for s in group['src']:
  612. s_no_suffix, ext1 = os.path.splitext(str(s))
  613. o_file_no_suffix, ext2 = os.path.splitext(o_file)
  614. if s_no_suffix == o_file_no_suffix:
  615. group['src'].remove(s)
  616. for o_file in o_files:
  617. group['src'] += Glob(o_file)
  618. if 'CFLAGS' in group:
  619. target = group['CFLAGS']
  620. if len(target) > 0:
  621. Env.AppendUnique(CFLAGS = target)
  622. if 'CCFLAGS' in group:
  623. target = group['CCFLAGS']
  624. if len(target) > 0:
  625. Env.AppendUnique(CCFLAGS = target)
  626. if 'CXXFLAGS' in group:
  627. target = group['CXXFLAGS']
  628. if len(target) > 0:
  629. Env.AppendUnique(CXXFLAGS = target)
  630. if 'CPPPATH' in group:
  631. target = group['CPPPATH']
  632. if _PretreatListParameters(target) == True:
  633. paths = []
  634. for item in target:
  635. paths.append(os.path.abspath(item))
  636. target = paths
  637. Env.AppendUnique(CPPPATH = target)
  638. if 'CPPDEFINES' in group:
  639. target = group['CPPDEFINES']
  640. if _PretreatListParameters(target) == True:
  641. Env.AppendUnique(CPPDEFINES = target)
  642. if 'LINKFLAGS' in group:
  643. target = group['LINKFLAGS']
  644. if len(target) > 0:
  645. Env.AppendUnique(LINKFLAGS = target)
  646. if 'ASFLAGS' in group:
  647. target = group['ASFLAGS']
  648. if len(target) > 0:
  649. Env.AppendUnique(ASFLAGS = target)
  650. if 'LOCAL_CPPPATH' in group:
  651. paths = []
  652. for item in group['LOCAL_CPPPATH']:
  653. paths.append(os.path.abspath(item))
  654. group['LOCAL_CPPPATH'] = paths
  655. if rtconfig.PLATFORM in ['gcc']:
  656. if 'CFLAGS' in group:
  657. group['CFLAGS'] = utils.GCCC99Patch(group['CFLAGS'])
  658. if 'CCFLAGS' in group:
  659. group['CCFLAGS'] = utils.GCCC99Patch(group['CCFLAGS'])
  660. if 'CXXFLAGS' in group:
  661. group['CXXFLAGS'] = utils.GCCC99Patch(group['CXXFLAGS'])
  662. if 'LOCAL_CCFLAGS' in group:
  663. group['LOCAL_CCFLAGS'] = utils.GCCC99Patch(group['LOCAL_CCFLAGS'])
  664. if 'LOCAL_CXXFLAGS' in group:
  665. group['LOCAL_CXXFLAGS'] = utils.GCCC99Patch(group['LOCAL_CXXFLAGS'])
  666. if 'LOCAL_CFLAGS' in group:
  667. group['LOCAL_CFLAGS'] = utils.GCCC99Patch(group['LOCAL_CFLAGS'])
  668. # check whether to clean up library
  669. if GetOption('cleanlib') and os.path.exists(os.path.join(group['path'], GroupLibFullName(name, Env))):
  670. if group['src'] != []:
  671. print('Remove library:'+ GroupLibFullName(name, Env))
  672. fn = os.path.join(group['path'], GroupLibFullName(name, Env))
  673. if os.path.exists(fn):
  674. os.unlink(fn)
  675. if 'LIBS' in group:
  676. target = group['LIBS']
  677. if _PretreatListParameters(target) == True:
  678. Env.AppendUnique(LIBS = target)
  679. if 'LIBPATH' in group:
  680. target = group['LIBPATH']
  681. if _PretreatListParameters(target) == True:
  682. Env.AppendUnique(LIBPATH = target)
  683. # check whether to build group library
  684. if 'LIBRARY' in group:
  685. objs = Env.Library(name, group['src'])
  686. else:
  687. # only add source
  688. objs = group['src']
  689. # merge group
  690. for g in Projects:
  691. if g['name'] == name:
  692. # merge to this group
  693. MergeGroup(g, group)
  694. return objs
  695. def PriorityInsertGroup(groups, group):
  696. length = len(groups)
  697. for i in range(0, length):
  698. if operator.gt(groups[i]['name'].lower(), group['name'].lower()):
  699. groups.insert(i, group)
  700. return
  701. groups.append(group)
  702. # add a new group
  703. PriorityInsertGroup(Projects, group)
  704. return objs
  705. def GetCurrentDir():
  706. conscript = File('SConscript')
  707. fn = conscript.rfile()
  708. name = fn.name
  709. path = os.path.dirname(fn.abspath)
  710. return path
  711. PREBUILDING = []
  712. def RegisterPreBuildingAction(act):
  713. global PREBUILDING
  714. assert callable(act), 'Could only register callable objects. %s received' % repr(act)
  715. PREBUILDING.append(act)
  716. def PreBuilding():
  717. global PREBUILDING
  718. for a in PREBUILDING:
  719. a()
  720. def GroupLibName(name, env):
  721. if rtconfig.PLATFORM in ['armcc']:
  722. return name + '_rvds'
  723. elif rtconfig.PLATFORM in ['gcc']:
  724. return name + '_gcc'
  725. return name
  726. def GroupLibFullName(name, env):
  727. return env['LIBPREFIX'] + GroupLibName(name, env) + env['LIBSUFFIX']
  728. def BuildLibInstallAction(target, source, env):
  729. lib_name = GetOption('buildlib')
  730. for Group in Projects:
  731. if Group['name'] == lib_name:
  732. lib_name = GroupLibFullName(Group['name'], env)
  733. dst_name = os.path.join(Group['path'], lib_name)
  734. print('Copy '+lib_name+' => ' + dst_name)
  735. do_copy_file(lib_name, dst_name)
  736. break
  737. def DoBuilding(target, objects):
  738. # merge all objects into one list
  739. def one_list(l):
  740. lst = []
  741. for item in l:
  742. if type(item) == type([]):
  743. lst += one_list(item)
  744. else:
  745. lst.append(item)
  746. return lst
  747. def dt_cmd(target, source, env):
  748. name = os.path.basename(source)
  749. path = os.path.dirname(os.path.join('build', os.path.splitext(source)[0]))
  750. if not os.path.exists(path):
  751. os.makedirs(path)
  752. dtb_d_pre_tmp = os.path.join(path, '%s.dtb.d.pre.tmp' % name)
  753. dtb_dts_tmp = os.path.join(path, '%s.dtb.dts.tmp' % name)
  754. dtb_d_dtc_tmp = os.path.join(path, '%s.dtb.d.dtc.tmp' % name)
  755. cpp_cmd = '%s -E -Wp,-MMD,%s -nostdinc ' % (env['CPP'], dtb_d_pre_tmp)
  756. for dtcpath in env['DTCPATH']:
  757. cpp_cmd += '-I%s ' % (dtcpath)
  758. cpp_cmd += '-undef -D__DTS__ -x assembler-with-cpp -o %s %s' % (dtb_dts_tmp, source)
  759. dtc_cmd = '%s -o build/%s %s -d %s %s' % (env['DTC'], target, env['DTCFLAGS'],
  760. dtb_d_dtc_tmp, dtb_dts_tmp)
  761. return [cpp_cmd, dtc_cmd]
  762. def dt_action(target, source, env):
  763. import subprocess
  764. cmd = dt_cmd(str(target[0]), str(source[0]), env)
  765. p = SCons.Action._subproc(env, cmd[0], stdin='devnull', shell=True)
  766. status = p.wait()
  767. if status:
  768. return status
  769. p = SCons.Action._subproc(env, cmd[1], stdin='devnull', shell=True)
  770. status = p.wait()
  771. if status:
  772. return status
  773. return 0
  774. def dt_string(target, source, env):
  775. cmd = dt_cmd(str(target[0]), str(source[0]), env)
  776. return cmd[0] + '\n' + cmd[1]
  777. dt_scanner = SCons.Scanner.ClassicCPP("CScanner", ".dts", "DTCPATH",
  778. '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")')
  779. if 'DTCCOMSTR' in Env and Env['DTCCOMSTR']:
  780. dt_action = Action(dt_action, '$DTCCOMSTR')
  781. else:
  782. dt_action = Action(dt_action, dt_string)
  783. dt_builder = SCons.Builder.Builder(action = dt_action,
  784. src_suffix = '.dts',
  785. suffix = '.dtb',
  786. source_scanner = dt_scanner,
  787. single_source=True)
  788. Env.Append(BUILDERS = {'DTC': dt_builder})
  789. global Dtc
  790. if Dtc != {}:
  791. # Env.DTC(target.split('.')[0] + '.dtb', Dtc['src'])
  792. Env.DTC('board.dtb', Dtc['src'])
  793. # handle local group
  794. def local_group(group, objects):
  795. if 'LOCAL_CFLAGS' in group or 'LOCAL_CXXFLAGS' in group or 'LOCAL_CCFLAGS' in group or 'LOCAL_CPPPATH' in group or 'LOCAL_CPPDEFINES' in group or 'LOCAL_ASFLAGS' in group:
  796. CFLAGS = Env.get('CFLAGS', '') + group.get('LOCAL_CFLAGS', '')
  797. CCFLAGS = Env.get('CCFLAGS', '') + group.get('LOCAL_CCFLAGS', '')
  798. CXXFLAGS = Env.get('CXXFLAGS', '') + group.get('LOCAL_CXXFLAGS', '')
  799. CPPPATH = list(Env.get('CPPPATH', [''])) + group.get('LOCAL_CPPPATH', [''])
  800. CPPDEFINES = list(Env.get('CPPDEFINES', [''])) + group.get('LOCAL_CPPDEFINES', [''])
  801. ASFLAGS = Env.get('ASFLAGS', '') + group.get('LOCAL_ASFLAGS', '')
  802. for source in group['src']:
  803. file_ext = source.get_suffix()
  804. if file_ext == '.o':
  805. if source not in objects:
  806. objects.append(source)
  807. continue
  808. objects.append(Env.Object(source, CFLAGS = CFLAGS, CCFLAGS = CCFLAGS, CXXFLAGS = CXXFLAGS, ASFLAGS = ASFLAGS,
  809. CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES))
  810. return True
  811. return False
  812. PreBuilding()
  813. objects = one_list(objects)
  814. program = None
  815. # check whether special buildlib option
  816. lib_name = GetOption('buildlib')
  817. if lib_name:
  818. objects = [] # remove all of objects
  819. # build library with special component
  820. for Group in Projects:
  821. if Group['name'] == lib_name:
  822. lib_name = GroupLibName(Group['name'], Env)
  823. if not local_group(Group, objects):
  824. objects = Env.Object(Group['src'])
  825. program = Env.Library(lib_name, objects)
  826. # add library copy action
  827. Env.BuildLib(lib_name, program)
  828. break
  829. else:
  830. objects = []
  831. # remove source files with local flags setting
  832. for group in Projects:
  833. group_objects = []
  834. CFLAGS = Env.get('CFLAGS', '')
  835. CCFLAGS = Env.get('CCFLAGS', '')
  836. CXXFLAGS = Env.get('CXXFLAGS', '')
  837. CPPPATH = Env.get('CPPPATH', [''])
  838. CPPDEFINES = Env.get('CPPDEFINES', [''])
  839. ASFLAGS = Env.get('ASFLAGS', '')
  840. if 'LOCAL_CFLAGS' in group or 'LOCAL_CXXFLAGS' in group or 'LOCAL_CCFLAGS' in group or 'LOCAL_CPPPATH' in group or 'LOCAL_CPPDEFINES' in group:
  841. CFLAGS = CFLAGS + group.get('LOCAL_CFLAGS', '')
  842. CCFLAGS = CCFLAGS + group.get('LOCAL_CCFLAGS', '')
  843. CXXFLAGS = CXXFLAGS + group.get('LOCAL_CXXFLAGS', '')
  844. CPPPATH = CPPPATH + group.get('LOCAL_CPPPATH', [''])
  845. CPPDEFINES = list(CPPDEFINES) + group.get('LOCAL_CPPDEFINES', [''])
  846. ASFLAGS = ASFLAGS + group.get('LOCAL_ASFLAGS', '')
  847. for source in group['src']:
  848. file_ext = source.get_suffix()
  849. if file_ext == '.o':
  850. if source not in objects:
  851. objects.append(source)
  852. continue
  853. group_objects.append(Env.Object(source, CFLAGS = CFLAGS, CCFLAGS = CCFLAGS,
  854. CXXFLAGS = CXXFLAGS, ASFLAGS = ASFLAGS,
  855. CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES))
  856. group_objects = sorted(group_objects)
  857. if group_objects:
  858. name = File(os.path.join(os.getcwd(), 'build', '%s-builtin.o' % group['name']))
  859. big_object= Env.Command(target=name, source=group_objects, action=Action('$LD -r -o $TARGET $SOURCES', '$LDCOMSTR'))
  860. objects.append(big_object)
  861. objects = sorted(objects)
  862. program = Env.Program(target, objects)
  863. EndBuilding(target, program)
  864. def GenTargetProject(program = None):
  865. if GetOption('target') in ['mdk', 'mdk4', 'mdk5']:
  866. from keil import MDK2Project, MDK4Project, MDK5Project, ARMCC_Version
  867. if os.path.isfile('template.uvprojx') and GetOption('target') not in ['mdk4']: # Keil5
  868. MDK5Project(GetOption('project-name') + '.uvprojx', Projects)
  869. print("Keil5 project is generating...")
  870. elif os.path.isfile('template.uvproj') and GetOption('target') not in ['mdk5']: # Keil4
  871. MDK4Project(GetOption('project-name') + '.uvproj', Projects)
  872. print("Keil4 project is generating...")
  873. elif os.path.isfile('template.Uv2') and GetOption('target') not in ['mdk4', 'mdk5']: # Keil2
  874. MDK2Project(GetOption('project-name') + '.Uv2', Projects)
  875. print("Keil2 project is generating...")
  876. else:
  877. print ('No template project file found.')
  878. exit(1)
  879. print("Keil Version: " + ARMCC_Version())
  880. print("Keil-MDK project has generated successfully!")
  881. if GetOption('target') == 'iar':
  882. from iar import IARProject, IARVersion
  883. print("IAR Version: " + IARVersion())
  884. IARProject(GetOption('project-name') + '.ewp', Projects)
  885. print("IAR project has generated successfully!")
  886. if GetOption('target') == 'vs':
  887. from vs import VSProject
  888. VSProject(GetOption('project-name') + '.vcproj', Projects, program)
  889. if GetOption('target') == 'vs2012':
  890. from vs2012 import VS2012Project
  891. VS2012Project(GetOption('project-name') + '.vcxproj', Projects, program)
  892. if GetOption('target') == 'cb':
  893. from codeblocks import CBProject
  894. CBProject(GetOption('project-name') + '.cbp', Projects, program)
  895. if GetOption('target') == 'ua':
  896. from ua import PrepareUA
  897. PrepareUA(Projects, Rtt_Root, str(Dir('#')))
  898. if GetOption('target') == 'vsc':
  899. from vsc import GenerateVSCode
  900. GenerateVSCode(Env)
  901. if GetOption('cmsispack'):
  902. from vscpyocd import GenerateVSCodePyocdConfig
  903. GenerateVSCodePyocdConfig(GetOption('cmsispack'))
  904. if GetOption('target') == 'cdk':
  905. from cdk import CDKProject
  906. CDKProject(GetOption('project-name') + '.cdkproj', Projects)
  907. if GetOption('target') == 'ses':
  908. from ses import SESProject
  909. SESProject(Env)
  910. if GetOption('target') == 'makefile':
  911. from makefile import TargetMakefile
  912. TargetMakefile(Env)
  913. if GetOption('target') == 'eclipse':
  914. from eclipse import TargetEclipse
  915. TargetEclipse(Env, GetOption('reset-project-config'), GetOption('project-name'))
  916. if GetOption('target') == 'codelite':
  917. from codelite import TargetCodelite
  918. TargetCodelite(Projects, program)
  919. if GetOption('target') == 'cmake' or GetOption('target') == 'cmake-armclang':
  920. from cmake import CMakeProject
  921. CMakeProject(Env,Projects)
  922. if GetOption('target') == 'xmake':
  923. from xmake import XMakeProject
  924. XMakeProject(Env, Projects)
  925. if GetOption('target') == 'esp-idf':
  926. from esp_idf import ESPIDFProject
  927. ESPIDFProject(Env, Projects)
  928. if GetOption('target') == 'cic':
  929. from cic import GenerateCIC
  930. GenerateCIC(Env, Rtt_Root, str(Dir('#')))
  931. def EndBuilding(target, program = None):
  932. from mkdist import MkDist
  933. need_exit = False
  934. Env['target'] = program
  935. Env['project'] = Projects
  936. if hasattr(rtconfig, 'BSP_LIBRARY_TYPE'):
  937. Env['bsp_lib_type'] = rtconfig.BSP_LIBRARY_TYPE
  938. if hasattr(rtconfig, 'dist_handle'):
  939. Env['dist_handle'] = rtconfig.dist_handle
  940. Env.AddPostAction(target, rtconfig.POST_ACTION)
  941. # Add addition clean files
  942. Clean(target, 'cconfig.h')
  943. Clean(target, 'rtua.py')
  944. Clean(target, 'rtua.pyc')
  945. Clean(target, '.sconsign.dblite')
  946. Clean(target, 'build/app.bin')
  947. Clean(target, 'build/app.elf')
  948. Clean(target, 'build/app.map')
  949. Clean(target, 'build/app.img')
  950. if GetOption('target'):
  951. GenTargetProject(program)
  952. need_exit = True
  953. BSP_ROOT = Dir('#').abspath
  954. project_name = GetOption('project-name')
  955. project_path = GetOption('project-path')
  956. config_name = GetOption('gen-sdk-config')
  957. if config_name:
  958. add_compiled_group(Projects, Rtt_Root)
  959. save_sdk_info(config_name, Rtt_Root)
  960. config_name = GetOption('gen-sdk')
  961. Env['config_name'] = config_name
  962. Env['project_name'] = project_name
  963. Env['chip'] = rtconfig.CHIP
  964. if config_name:
  965. print(target)
  966. action = SCons.Action.Action(gen_sdk, '\nGen %s SDK....' % project_name)
  967. y = Env.Command(target='nothing', source=None, action=action)
  968. Env.Depends(y, target)
  969. if GetOption('make-dist') and program != None:
  970. MkDist(program, BSP_ROOT, Rtt_Root, Env, project_name, project_path)
  971. need_exit = True
  972. if GetOption('cscope'):
  973. from cscope import CscopeDatabase
  974. CscopeDatabase(Projects)
  975. if not GetOption('help') and not GetOption('target'):
  976. if not os.path.exists(rtconfig.EXEC_PATH):
  977. print ("Error: the toolchain path (" + rtconfig.EXEC_PATH + ") is not exist, please check 'EXEC_PATH' in path or rtconfig.py.")
  978. need_exit = True
  979. if need_exit:
  980. exit(0)
  981. def SrcRemove(src, remove):
  982. if not src:
  983. return
  984. src_bak = src[:]
  985. if type(remove) == type('str'):
  986. if os.path.isabs(remove):
  987. remove = os.path.relpath(remove, GetCurrentDir())
  988. remove = os.path.normpath(remove)
  989. for item in src_bak:
  990. if type(item) == type('str'):
  991. item_str = item
  992. else:
  993. item_str = item.rstr()
  994. if os.path.isabs(item_str):
  995. item_str = os.path.relpath(item_str, GetCurrentDir())
  996. item_str = os.path.normpath(item_str)
  997. if item_str == remove:
  998. src.remove(item)
  999. else:
  1000. for remove_item in remove:
  1001. remove_str = str(remove_item)
  1002. if os.path.isabs(remove_str):
  1003. remove_str = os.path.relpath(remove_str, GetCurrentDir())
  1004. remove_str = os.path.normpath(remove_str)
  1005. for item in src_bak:
  1006. if type(item) == type('str'):
  1007. item_str = item
  1008. else:
  1009. item_str = item.rstr()
  1010. if os.path.isabs(item_str):
  1011. item_str = os.path.relpath(item_str, GetCurrentDir())
  1012. item_str = os.path.normpath(item_str)
  1013. if item_str == remove_str:
  1014. src.remove(item)
  1015. def GetVersion():
  1016. import SCons.cpp
  1017. import string
  1018. rtdef = os.path.join(Rtt_Root, 'include', 'rtdef.h')
  1019. # parse rtdef.h to get RT-Thread version
  1020. prepcessor = PatchedPreProcessor()
  1021. f = open(rtdef, 'r')
  1022. contents = f.read()
  1023. f.close()
  1024. prepcessor.process_contents(contents)
  1025. def_ns = prepcessor.cpp_namespace
  1026. version = int([ch for ch in def_ns['RT_VERSION_MAJOR'] if ch in '0123456789.'])
  1027. subversion = int([ch for ch in def_ns['RT_VERSION_MINOR'] if ch in '0123456789.'])
  1028. if 'RT_VERSION_PATCH' in def_ns:
  1029. revision = int([ch for ch in def_ns['RT_VERSION_PATCH'] if ch in '0123456789.'])
  1030. return '%d.%d.%d' % (version, subversion, revision)
  1031. return '0.%d.%d' % (version, subversion)
  1032. def GlobSubDir(sub_dir, ext_name):
  1033. import os
  1034. import glob
  1035. def glob_source(sub_dir, ext_name):
  1036. list = os.listdir(sub_dir)
  1037. src = glob.glob(os.path.join(sub_dir, ext_name))
  1038. for item in list:
  1039. full_subdir = os.path.join(sub_dir, item)
  1040. if os.path.isdir(full_subdir):
  1041. src += glob_source(full_subdir, ext_name)
  1042. return src
  1043. dst = []
  1044. src = glob_source(sub_dir, ext_name)
  1045. for item in src:
  1046. dst.append(os.path.relpath(item, sub_dir))
  1047. return dst
  1048. def PackageSConscript(package):
  1049. from package import BuildPackage
  1050. return BuildPackage(package)