初始提交
This commit is contained in:
		
							
								
								
									
										959
									
								
								Project/Src/rt-thread/tools/building.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										959
									
								
								Project/Src/rt-thread/tools/building.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,959 @@ | ||||
| # | ||||
| # File      : building.py | ||||
| # This file is part of RT-Thread RTOS | ||||
| # COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team | ||||
| # | ||||
| #  This program is free software; you can redistribute it and/or modify | ||||
| #  it under the terms of the GNU General Public License as published by | ||||
| #  the Free Software Foundation; either version 2 of the License, or | ||||
| #  (at your option) any later version. | ||||
| # | ||||
| #  This program is distributed in the hope that it will be useful, | ||||
| #  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| #  GNU General Public License for more details. | ||||
| # | ||||
| #  You should have received a copy of the GNU General Public License along | ||||
| #  with this program; if not, write to the Free Software Foundation, Inc., | ||||
| #  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
| # | ||||
| # Change Logs: | ||||
| # Date           Author       Notes | ||||
| # 2015-01-20     Bernard      Add copyright information | ||||
| # 2015-07-25     Bernard      Add LOCAL_CCFLAGS/LOCAL_CPPPATH/LOCAL_CPPDEFINES for | ||||
| #                             group definition. | ||||
| # | ||||
|  | ||||
| import os | ||||
| import sys | ||||
| import string | ||||
| import utils | ||||
|  | ||||
| from SCons.Script import * | ||||
| from utils import _make_path_relative | ||||
| from mkdist import do_copy_file | ||||
|  | ||||
| BuildOptions = {} | ||||
| Projects = [] | ||||
| Rtt_Root = '' | ||||
| Env = None | ||||
|  | ||||
| # SCons PreProcessor patch | ||||
| def start_handling_includes(self, t=None): | ||||
|     """ | ||||
|     Causes the PreProcessor object to start processing #import, | ||||
|     #include and #include_next lines. | ||||
|  | ||||
|     This method will be called when a #if, #ifdef, #ifndef or #elif | ||||
|     evaluates True, or when we reach the #else in a #if, #ifdef, | ||||
|     #ifndef or #elif block where a condition already evaluated | ||||
|     False. | ||||
|  | ||||
|     """ | ||||
|     d = self.dispatch_table | ||||
|     p = self.stack[-1] if self.stack else self.default_table | ||||
|  | ||||
|     for k in ('import', 'include', 'include_next', 'define'): | ||||
|         d[k] = p[k] | ||||
|  | ||||
| def stop_handling_includes(self, t=None): | ||||
|     """ | ||||
|     Causes the PreProcessor object to stop processing #import, | ||||
|     #include and #include_next lines. | ||||
|  | ||||
|     This method will be called when a #if, #ifdef, #ifndef or #elif | ||||
|     evaluates False, or when we reach the #else in a #if, #ifdef, | ||||
|     #ifndef or #elif block where a condition already evaluated True. | ||||
|     """ | ||||
|     d = self.dispatch_table | ||||
|     d['import'] = self.do_nothing | ||||
|     d['include'] =  self.do_nothing | ||||
|     d['include_next'] =  self.do_nothing | ||||
|     d['define'] =  self.do_nothing | ||||
|  | ||||
| PatchedPreProcessor = SCons.cpp.PreProcessor | ||||
| PatchedPreProcessor.start_handling_includes = start_handling_includes | ||||
| PatchedPreProcessor.stop_handling_includes = stop_handling_includes | ||||
|  | ||||
| class Win32Spawn: | ||||
|     def spawn(self, sh, escape, cmd, args, env): | ||||
|         # deal with the cmd build-in commands which cannot be used in | ||||
|         # subprocess.Popen | ||||
|         if cmd == 'del': | ||||
|             for f in args[1:]: | ||||
|                 try: | ||||
|                     os.remove(f) | ||||
|                 except Exception as e: | ||||
|                     print ('Error removing file: ' + e) | ||||
|                     return -1 | ||||
|             return 0 | ||||
|  | ||||
|         import subprocess | ||||
|  | ||||
|         newargs = ' '.join(args[1:]) | ||||
|         cmdline = cmd + " " + newargs | ||||
|  | ||||
|         # Make sure the env is constructed by strings | ||||
|         _e = dict([(k, str(v)) for k, v in env.items()]) | ||||
|  | ||||
|         # Windows(tm) CreateProcess does not use the env passed to it to find | ||||
|         # the executables. So we have to modify our own PATH to make Popen | ||||
|         # work. | ||||
|         old_path = os.environ['PATH'] | ||||
|         os.environ['PATH'] = _e['PATH'] | ||||
|  | ||||
|         try: | ||||
|             proc = subprocess.Popen(cmdline, env=_e, shell=False) | ||||
|         except Exception as e: | ||||
|             print ('Error in calling command:' + cmdline.split(' ')[0]) | ||||
|             print ('Exception: ' + os.strerror(e.errno)) | ||||
|             if (os.strerror(e.errno) == "No such file or directory"): | ||||
|                 print ("\nPlease check Toolchains PATH setting.\n") | ||||
|  | ||||
|             return e.errno | ||||
|         finally: | ||||
|             os.environ['PATH'] = old_path | ||||
|  | ||||
|         return proc.wait() | ||||
|  | ||||
| # generate cconfig.h file | ||||
| def GenCconfigFile(env, BuildOptions): | ||||
|     import rtconfig | ||||
|  | ||||
|     if rtconfig.PLATFORM == 'gcc': | ||||
|         contents = '' | ||||
|         if not os.path.isfile('cconfig.h'): | ||||
|             import gcc | ||||
|             gcc.GenerateGCCConfig(rtconfig) | ||||
|  | ||||
|         # try again | ||||
|         if os.path.isfile('cconfig.h'): | ||||
|             f = open('cconfig.h', 'r') | ||||
|             if f: | ||||
|                 contents = f.read() | ||||
|                 f.close() | ||||
|  | ||||
|                 prep = PatchedPreProcessor() | ||||
|                 prep.process_contents(contents) | ||||
|                 options = prep.cpp_namespace | ||||
|  | ||||
|                 BuildOptions.update(options) | ||||
|  | ||||
|                 # add HAVE_CCONFIG_H definition | ||||
|                 env.AppendUnique(CPPDEFINES = ['HAVE_CCONFIG_H']) | ||||
|  | ||||
| def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = []): | ||||
|     import rtconfig | ||||
|  | ||||
|     global BuildOptions | ||||
|     global Projects | ||||
|     global Env | ||||
|     global Rtt_Root | ||||
|  | ||||
|     # ===== Add option to SCons ===== | ||||
|     AddOption('--dist', | ||||
|                       dest = 'make-dist', | ||||
|                       action = 'store_true', | ||||
|                       default = False, | ||||
|                       help = 'make distribution') | ||||
|     AddOption('--dist-strip', | ||||
|                       dest = 'make-dist-strip', | ||||
|                       action = 'store_true', | ||||
|                       default = False, | ||||
|                       help = 'make distribution and strip useless files') | ||||
|     AddOption('--cscope', | ||||
|                       dest = 'cscope', | ||||
|                       action = 'store_true', | ||||
|                       default = False, | ||||
|                       help = 'Build Cscope cross reference database. Requires cscope installed.') | ||||
|     AddOption('--clang-analyzer', | ||||
|                       dest = 'clang-analyzer', | ||||
|                       action = 'store_true', | ||||
|                       default = False, | ||||
|                       help = 'Perform static analyze with Clang-analyzer. ' + \ | ||||
|                            'Requires Clang installed.\n' + \ | ||||
|                            'It is recommended to use with scan-build like this:\n' + \ | ||||
|                            '`scan-build scons --clang-analyzer`\n' + \ | ||||
|                            'If things goes well, scan-build will instruct you to invoke scan-view.') | ||||
|     AddOption('--buildlib', | ||||
|                       dest = 'buildlib', | ||||
|                       type = 'string', | ||||
|                       help = 'building library of a component') | ||||
|     AddOption('--cleanlib', | ||||
|                       dest = 'cleanlib', | ||||
|                       action = 'store_true', | ||||
|                       default = False, | ||||
|                       help = 'clean up the library by --buildlib') | ||||
|     AddOption('--target', | ||||
|                       dest = 'target', | ||||
|                       type = 'string', | ||||
|                       help = 'set target project: mdk/mdk4/mdk5/iar/vs/vsc/ua/cdk/ses') | ||||
|     AddOption('--genconfig', | ||||
|                 dest = 'genconfig', | ||||
|                 action = 'store_true', | ||||
|                 default = False, | ||||
|                 help = 'Generate .config from rtconfig.h') | ||||
|     AddOption('--useconfig', | ||||
|                 dest = 'useconfig', | ||||
|                 type = 'string', | ||||
|                 help = 'make rtconfig.h from config file.') | ||||
|     AddOption('--verbose', | ||||
|                 dest = 'verbose', | ||||
|                 action = 'store_true', | ||||
|                 default = False, | ||||
|                 help = 'print verbose information during build') | ||||
|  | ||||
|     Env = env | ||||
|     Rtt_Root = os.path.abspath(root_directory) | ||||
|  | ||||
|     # make an absolute root directory | ||||
|     RTT_ROOT = Rtt_Root | ||||
|     Export('RTT_ROOT') | ||||
|  | ||||
|     # set RTT_ROOT in ENV | ||||
|     Env['RTT_ROOT'] = Rtt_Root | ||||
|     # set BSP_ROOT in ENV | ||||
|     Env['BSP_ROOT'] = Dir('#').abspath | ||||
|  | ||||
|     sys.path = sys.path + [os.path.join(Rtt_Root, 'tools')] | ||||
|  | ||||
|     # {target_name:(CROSS_TOOL, PLATFORM)} | ||||
|     tgt_dict = {'mdk':('keil', 'armcc'), | ||||
|                 'mdk4':('keil', 'armcc'), | ||||
|                 'mdk5':('keil', 'armcc'), | ||||
|                 'iar':('iar', 'iar'), | ||||
|                 'vs':('msvc', 'cl'), | ||||
|                 'vs2012':('msvc', 'cl'), | ||||
|                 'vsc' : ('gcc', 'gcc'), | ||||
|                 'cb':('keil', 'armcc'), | ||||
|                 'ua':('gcc', 'gcc'), | ||||
|                 'cdk':('gcc', 'gcc'), | ||||
|                 'ses' : ('gcc', 'gcc')} | ||||
|     tgt_name = GetOption('target') | ||||
|  | ||||
|     if tgt_name: | ||||
|         # --target will change the toolchain settings which clang-analyzer is | ||||
|         # depend on | ||||
|         if GetOption('clang-analyzer'): | ||||
|             print ('--clang-analyzer cannot be used with --target') | ||||
|             sys.exit(1) | ||||
|  | ||||
|         SetOption('no_exec', 1) | ||||
|         try: | ||||
|             rtconfig.CROSS_TOOL, rtconfig.PLATFORM = tgt_dict[tgt_name] | ||||
|             # replace the 'RTT_CC' to 'CROSS_TOOL' | ||||
|             os.environ['RTT_CC'] = rtconfig.CROSS_TOOL | ||||
|             utils.ReloadModule(rtconfig) | ||||
|         except KeyError: | ||||
|             print ('Unknow target: '+ tgt_name+'. Avaible targets: ' +', '.join(tgt_dict.keys())) | ||||
|             sys.exit(1) | ||||
|     elif (GetDepend('RT_USING_NEWLIB') == False and GetDepend('RT_USING_NOLIBC') == False) \ | ||||
|         and rtconfig.PLATFORM == 'gcc': | ||||
|         AddDepend('RT_USING_MINILIBC') | ||||
|  | ||||
|     # auto change the 'RTT_EXEC_PATH' when 'rtconfig.EXEC_PATH' get failed | ||||
|     if not os.path.exists(rtconfig.EXEC_PATH): | ||||
|         if 'RTT_EXEC_PATH' in os.environ: | ||||
|             # del the 'RTT_EXEC_PATH' and using the 'EXEC_PATH' setting on rtconfig.py | ||||
|             del os.environ['RTT_EXEC_PATH'] | ||||
|             utils.ReloadModule(rtconfig) | ||||
|  | ||||
|     # add compability with Keil MDK 4.6 which changes the directory of armcc.exe | ||||
|     if rtconfig.PLATFORM == 'armcc': | ||||
|         if not os.path.isfile(os.path.join(rtconfig.EXEC_PATH, 'armcc.exe')): | ||||
|             if rtconfig.EXEC_PATH.find('bin40') > 0: | ||||
|                 rtconfig.EXEC_PATH = rtconfig.EXEC_PATH.replace('bin40', 'armcc/bin') | ||||
|                 Env['LINKFLAGS'] = Env['LINKFLAGS'].replace('RV31', 'armcc') | ||||
|  | ||||
|         # reset AR command flags | ||||
|         env['ARCOM'] = '$AR --create $TARGET $SOURCES' | ||||
|         env['LIBPREFIX'] = '' | ||||
|         env['LIBSUFFIX'] = '.lib' | ||||
|         env['LIBLINKPREFIX'] = '' | ||||
|         env['LIBLINKSUFFIX'] = '.lib' | ||||
|         env['LIBDIRPREFIX'] = '--userlibpath ' | ||||
|  | ||||
|     elif rtconfig.PLATFORM == 'iar': | ||||
|         env['LIBPREFIX'] = '' | ||||
|         env['LIBSUFFIX'] = '.a' | ||||
|         env['LIBLINKPREFIX'] = '' | ||||
|         env['LIBLINKSUFFIX'] = '.a' | ||||
|         env['LIBDIRPREFIX'] = '--search ' | ||||
|  | ||||
|     # patch for win32 spawn | ||||
|     if env['PLATFORM'] == 'win32': | ||||
|         win32_spawn = Win32Spawn() | ||||
|         win32_spawn.env = env | ||||
|         env['SPAWN'] = win32_spawn.spawn | ||||
|  | ||||
|     if env['PLATFORM'] == 'win32': | ||||
|         os.environ['PATH'] = rtconfig.EXEC_PATH + ";" + os.environ['PATH'] | ||||
|     else: | ||||
|         os.environ['PATH'] = rtconfig.EXEC_PATH + ":" + os.environ['PATH'] | ||||
|  | ||||
|     # add program path | ||||
|     env.PrependENVPath('PATH', rtconfig.EXEC_PATH) | ||||
|     # add rtconfig.h/BSP path into Kernel group | ||||
|     DefineGroup("Kernel", [], [], CPPPATH=[str(Dir('#').abspath)]) | ||||
|  | ||||
|     # add library build action | ||||
|     act = SCons.Action.Action(BuildLibInstallAction, 'Install compiled library... $TARGET') | ||||
|     bld = Builder(action = act) | ||||
|     Env.Append(BUILDERS = {'BuildLib': bld}) | ||||
|  | ||||
|     # parse rtconfig.h to get used component | ||||
|     PreProcessor = PatchedPreProcessor() | ||||
|     f = open('rtconfig.h', 'r') | ||||
|     contents = f.read() | ||||
|     f.close() | ||||
|     PreProcessor.process_contents(contents) | ||||
|     BuildOptions = PreProcessor.cpp_namespace | ||||
|  | ||||
|     if GetOption('clang-analyzer'): | ||||
|         # perform what scan-build does | ||||
|         env.Replace( | ||||
|                 CC   = 'ccc-analyzer', | ||||
|                 CXX  = 'c++-analyzer', | ||||
|                 # skip as and link | ||||
|                 LINK = 'true', | ||||
|                 AS   = 'true',) | ||||
|         env["ENV"].update(x for x in os.environ.items() if x[0].startswith("CCC_")) | ||||
|         # only check, don't compile. ccc-analyzer use CCC_CC as the CC. | ||||
|         # fsyntax-only will give us some additional warning messages | ||||
|         env['ENV']['CCC_CC']  = 'clang' | ||||
|         env.Append(CFLAGS=['-fsyntax-only', '-Wall', '-Wno-invalid-source-encoding']) | ||||
|         env['ENV']['CCC_CXX'] = 'clang++' | ||||
|         env.Append(CXXFLAGS=['-fsyntax-only', '-Wall', '-Wno-invalid-source-encoding']) | ||||
|         # remove the POST_ACTION as it will cause meaningless errors(file not | ||||
|         # found or something like that). | ||||
|         rtconfig.POST_ACTION = '' | ||||
|  | ||||
|     # generate cconfig.h file | ||||
|     GenCconfigFile(env, BuildOptions) | ||||
|  | ||||
|     # auto append '_REENT_SMALL' when using newlib 'nano.specs' option | ||||
|     if rtconfig.PLATFORM == 'gcc' and str(env['LINKFLAGS']).find('nano.specs') != -1: | ||||
|         env.AppendUnique(CPPDEFINES = ['_REENT_SMALL']) | ||||
|  | ||||
|     if GetOption('genconfig'): | ||||
|         from genconf import genconfig | ||||
|         genconfig() | ||||
|         exit(0) | ||||
|  | ||||
|     if env['PLATFORM'] != 'win32': | ||||
|         AddOption('--menuconfig', | ||||
|                     dest = 'menuconfig', | ||||
|                     action = 'store_true', | ||||
|                     default = False, | ||||
|                     help = 'make menuconfig for RT-Thread BSP') | ||||
|         if GetOption('menuconfig'): | ||||
|             from menuconfig import menuconfig | ||||
|             menuconfig(Rtt_Root) | ||||
|             exit(0) | ||||
|  | ||||
|     AddOption('--pyconfig', | ||||
|                 dest = 'pyconfig', | ||||
|                 action = 'store_true', | ||||
|                 default = False, | ||||
|                 help = 'make menuconfig for RT-Thread BSP') | ||||
|     AddOption('--pyconfig-silent', | ||||
|                 dest = 'pyconfig_silent', | ||||
|                 action = 'store_true', | ||||
|                 default = False, | ||||
|                 help = 'Don`t show pyconfig window') | ||||
|  | ||||
|     if GetOption('pyconfig_silent'):     | ||||
|         from menuconfig import pyconfig_silent | ||||
|  | ||||
|         pyconfig_silent(Rtt_Root) | ||||
|         exit(0) | ||||
|     elif GetOption('pyconfig'): | ||||
|         from menuconfig import pyconfig | ||||
|  | ||||
|         pyconfig(Rtt_Root) | ||||
|         exit(0) | ||||
|  | ||||
|     configfn = GetOption('useconfig') | ||||
|     if configfn: | ||||
|         from menuconfig import mk_rtconfig | ||||
|         mk_rtconfig(configfn) | ||||
|         exit(0) | ||||
|  | ||||
|  | ||||
|     if not GetOption('verbose'): | ||||
|         # override the default verbose command string | ||||
|         env.Replace( | ||||
|             ARCOMSTR = 'AR $TARGET', | ||||
|             ASCOMSTR = 'AS $TARGET', | ||||
|             ASPPCOMSTR = 'AS $TARGET', | ||||
|             CCCOMSTR = 'CC $TARGET', | ||||
|             CXXCOMSTR = 'CXX $TARGET', | ||||
|             LINKCOMSTR = 'LINK $TARGET' | ||||
|         ) | ||||
|  | ||||
|     # fix the linker for C++ | ||||
|     if GetDepend('RT_USING_CPLUSPLUS'): | ||||
|         if env['LINK'].find('gcc') != -1: | ||||
|             env['LINK'] = env['LINK'].replace('gcc', 'g++') | ||||
|  | ||||
|     # we need to seperate the variant_dir for BSPs and the kernels. BSPs could | ||||
|     # have their own components etc. If they point to the same folder, SCons | ||||
|     # would find the wrong source code to compile. | ||||
|     bsp_vdir = 'build' | ||||
|     kernel_vdir = 'build/kernel' | ||||
|     # board build script | ||||
|     objs = SConscript('SConscript', variant_dir=bsp_vdir, duplicate=0) | ||||
|     # include kernel | ||||
|     objs.extend(SConscript(Rtt_Root + '/src/SConscript', variant_dir=kernel_vdir + '/src', duplicate=0)) | ||||
|     # include libcpu | ||||
|     if not has_libcpu: | ||||
|         objs.extend(SConscript(Rtt_Root + '/libcpu/SConscript', | ||||
|                     variant_dir=kernel_vdir + '/libcpu', duplicate=0)) | ||||
|  | ||||
|     # include components | ||||
|     objs.extend(SConscript(Rtt_Root + '/components/SConscript', | ||||
|                            variant_dir=kernel_vdir + '/components', | ||||
|                            duplicate=0, | ||||
|                            exports='remove_components')) | ||||
|  | ||||
|     return objs | ||||
|  | ||||
| def PrepareModuleBuilding(env, root_directory, bsp_directory): | ||||
|     import rtconfig | ||||
|  | ||||
|     global BuildOptions | ||||
|     global Env | ||||
|     global Rtt_Root | ||||
|  | ||||
|     # patch for win32 spawn | ||||
|     if env['PLATFORM'] == 'win32': | ||||
|         win32_spawn = Win32Spawn() | ||||
|         win32_spawn.env = env | ||||
|         env['SPAWN'] = win32_spawn.spawn | ||||
|  | ||||
|     Env = env | ||||
|     Rtt_Root = root_directory | ||||
|  | ||||
|     # parse bsp rtconfig.h to get used component | ||||
|     PreProcessor = PatchedPreProcessor() | ||||
|     f = open(bsp_directory + '/rtconfig.h', 'r') | ||||
|     contents = f.read() | ||||
|     f.close() | ||||
|     PreProcessor.process_contents(contents) | ||||
|     BuildOptions = PreProcessor.cpp_namespace | ||||
|  | ||||
|     # add build/clean library option for library checking | ||||
|     AddOption('--buildlib', | ||||
|               dest='buildlib', | ||||
|               type='string', | ||||
|               help='building library of a component') | ||||
|     AddOption('--cleanlib', | ||||
|               dest='cleanlib', | ||||
|               action='store_true', | ||||
|               default=False, | ||||
|               help='clean up the library by --buildlib') | ||||
|  | ||||
|     # add program path | ||||
|     env.PrependENVPath('PATH', rtconfig.EXEC_PATH) | ||||
|  | ||||
| def GetConfigValue(name): | ||||
|     assert type(name) == str, 'GetConfigValue: only string parameter is valid' | ||||
|     try: | ||||
|         return BuildOptions[name] | ||||
|     except: | ||||
|         return '' | ||||
|  | ||||
| def GetDepend(depend): | ||||
|     building = True | ||||
|     if type(depend) == type('str'): | ||||
|         if not depend in BuildOptions or BuildOptions[depend] == 0: | ||||
|             building = False | ||||
|         elif BuildOptions[depend] != '': | ||||
|             return BuildOptions[depend] | ||||
|  | ||||
|         return building | ||||
|  | ||||
|     # for list type depend | ||||
|     for item in depend: | ||||
|         if item != '': | ||||
|             if not item in BuildOptions or BuildOptions[item] == 0: | ||||
|                 building = False | ||||
|  | ||||
|     return building | ||||
|  | ||||
| def LocalOptions(config_filename): | ||||
|     from SCons.Script import SCons | ||||
|  | ||||
|     # parse wiced_config.h to get used component | ||||
|     PreProcessor = SCons.cpp.PreProcessor() | ||||
|  | ||||
|     f = open(config_filename, 'r') | ||||
|     contents = f.read() | ||||
|     f.close() | ||||
|  | ||||
|     PreProcessor.process_contents(contents) | ||||
|     local_options = PreProcessor.cpp_namespace | ||||
|  | ||||
|     return local_options | ||||
|  | ||||
| def GetLocalDepend(options, depend): | ||||
|     building = True | ||||
|     if type(depend) == type('str'): | ||||
|         if not depend in options or options[depend] == 0: | ||||
|             building = False | ||||
|         elif options[depend] != '': | ||||
|             return options[depend] | ||||
|  | ||||
|         return building | ||||
|  | ||||
|     # for list type depend | ||||
|     for item in depend: | ||||
|         if item != '': | ||||
|             if not item in options or options[item] == 0: | ||||
|                 building = False | ||||
|  | ||||
|     return building | ||||
|  | ||||
| def AddDepend(option): | ||||
|     BuildOptions[option] = 1 | ||||
|  | ||||
| def MergeGroup(src_group, group): | ||||
|     src_group['src'] = src_group['src'] + group['src'] | ||||
|     if 'CCFLAGS' in group: | ||||
|         if 'CCFLAGS' in src_group: | ||||
|             src_group['CCFLAGS'] = src_group['CCFLAGS'] + group['CCFLAGS'] | ||||
|         else: | ||||
|             src_group['CCFLAGS'] = group['CCFLAGS'] | ||||
|     if 'CPPPATH' in group: | ||||
|         if 'CPPPATH' in src_group: | ||||
|             src_group['CPPPATH'] = src_group['CPPPATH'] + group['CPPPATH'] | ||||
|         else: | ||||
|             src_group['CPPPATH'] = group['CPPPATH'] | ||||
|     if 'CPPDEFINES' in group: | ||||
|         if 'CPPDEFINES' in src_group: | ||||
|             src_group['CPPDEFINES'] = src_group['CPPDEFINES'] + group['CPPDEFINES'] | ||||
|         else: | ||||
|             src_group['CPPDEFINES'] = group['CPPDEFINES'] | ||||
|     if 'ASFLAGS' in group: | ||||
|         if 'ASFLAGS' in src_group: | ||||
|             src_group['ASFLAGS'] = src_group['ASFLAGS'] + group['ASFLAGS'] | ||||
|         else: | ||||
|             src_group['ASFLAGS'] = group['ASFLAGS'] | ||||
|  | ||||
|     # for local CCFLAGS/CPPPATH/CPPDEFINES | ||||
|     if 'LOCAL_CCFLAGS' in group: | ||||
|         if 'LOCAL_CCFLAGS' in src_group: | ||||
|             src_group['LOCAL_CCFLAGS'] = src_group['LOCAL_CCFLAGS'] + group['LOCAL_CCFLAGS'] | ||||
|         else: | ||||
|             src_group['LOCAL_CCFLAGS'] = group['LOCAL_CCFLAGS'] | ||||
|     if 'LOCAL_CPPPATH' in group: | ||||
|         if 'LOCAL_CPPPATH' in src_group: | ||||
|             src_group['LOCAL_CPPPATH'] = src_group['LOCAL_CPPPATH'] + group['LOCAL_CPPPATH'] | ||||
|         else: | ||||
|             src_group['LOCAL_CPPPATH'] = group['LOCAL_CPPPATH'] | ||||
|     if 'LOCAL_CPPDEFINES' in group: | ||||
|         if 'LOCAL_CPPDEFINES' in src_group: | ||||
|             src_group['LOCAL_CPPDEFINES'] = src_group['LOCAL_CPPDEFINES'] + group['LOCAL_CPPDEFINES'] | ||||
|         else: | ||||
|             src_group['LOCAL_CPPDEFINES'] = group['LOCAL_CPPDEFINES'] | ||||
|  | ||||
|     if 'LINKFLAGS' in group: | ||||
|         if 'LINKFLAGS' in src_group: | ||||
|             src_group['LINKFLAGS'] = src_group['LINKFLAGS'] + group['LINKFLAGS'] | ||||
|         else: | ||||
|             src_group['LINKFLAGS'] = group['LINKFLAGS'] | ||||
|     if 'LIBS' in group: | ||||
|         if 'LIBS' in src_group: | ||||
|             src_group['LIBS'] = src_group['LIBS'] + group['LIBS'] | ||||
|         else: | ||||
|             src_group['LIBS'] = group['LIBS'] | ||||
|     if 'LIBPATH' in group: | ||||
|         if 'LIBPATH' in src_group: | ||||
|             src_group['LIBPATH'] = src_group['LIBPATH'] + group['LIBPATH'] | ||||
|         else: | ||||
|             src_group['LIBPATH'] = group['LIBPATH'] | ||||
|     if 'LOCAL_ASFLAGS' in group: | ||||
|         if 'LOCAL_ASFLAGS' in src_group: | ||||
|             src_group['LOCAL_ASFLAGS'] = src_group['LOCAL_ASFLAGS'] + group['LOCAL_ASFLAGS'] | ||||
|         else: | ||||
|             src_group['LOCAL_ASFLAGS'] = group['LOCAL_ASFLAGS'] | ||||
|  | ||||
| def DefineGroup(name, src, depend, **parameters): | ||||
|     global Env | ||||
|     if not GetDepend(depend): | ||||
|         return [] | ||||
|  | ||||
|     # find exist group and get path of group | ||||
|     group_path = '' | ||||
|     for g in Projects: | ||||
|         if g['name'] == name: | ||||
|             group_path = g['path'] | ||||
|     if group_path == '': | ||||
|         group_path = GetCurrentDir() | ||||
|  | ||||
|     group = parameters | ||||
|     group['name'] = name | ||||
|     group['path'] = group_path | ||||
|     if type(src) == type([]): | ||||
|         group['src'] = File(src) | ||||
|     else: | ||||
|         group['src'] = src | ||||
|  | ||||
|     if 'CCFLAGS' in group: | ||||
|         Env.AppendUnique(CCFLAGS = group['CCFLAGS']) | ||||
|     if 'CPPPATH' in group: | ||||
|         paths = [] | ||||
|         for item in group['CPPPATH']: | ||||
|             paths.append(os.path.abspath(item)) | ||||
|         group['CPPPATH'] = paths | ||||
|         Env.AppendUnique(CPPPATH = group['CPPPATH']) | ||||
|     if 'CPPDEFINES' in group: | ||||
|         Env.AppendUnique(CPPDEFINES = group['CPPDEFINES']) | ||||
|     if 'LINKFLAGS' in group: | ||||
|         Env.AppendUnique(LINKFLAGS = group['LINKFLAGS']) | ||||
|     if 'ASFLAGS' in group: | ||||
|         Env.AppendUnique(ASFLAGS = group['ASFLAGS']) | ||||
|     if 'LOCAL_CPPPATH' in group: | ||||
|         paths = [] | ||||
|         for item in group['LOCAL_CPPPATH']: | ||||
|             paths.append(os.path.abspath(item)) | ||||
|         group['LOCAL_CPPPATH'] = paths | ||||
|  | ||||
|     import rtconfig | ||||
|     if rtconfig.PLATFORM == 'gcc': | ||||
|         if 'CCFLAGS' in group: | ||||
|             group['CCFLAGS'] = utils.GCCC99Patch(group['CCFLAGS']) | ||||
|         if 'LOCAL_CCFLAGS' in group: | ||||
|             group['LOCAL_CCFLAGS'] = utils.GCCC99Patch(group['LOCAL_CCFLAGS']) | ||||
|  | ||||
|     # check whether to clean up library | ||||
|     if GetOption('cleanlib') and os.path.exists(os.path.join(group['path'], GroupLibFullName(name, Env))): | ||||
|         if group['src'] != []: | ||||
|             print ('Remove library:'+ GroupLibFullName(name, Env)) | ||||
|             fn = os.path.join(group['path'], GroupLibFullName(name, Env)) | ||||
|             if os.path.exists(fn): | ||||
|                 os.unlink(fn) | ||||
|  | ||||
|     if 'LIBS' in group: | ||||
|         Env.AppendUnique(LIBS = group['LIBS']) | ||||
|     if 'LIBPATH' in group: | ||||
|         Env.AppendUnique(LIBPATH = group['LIBPATH']) | ||||
|  | ||||
|     # check whether to build group library | ||||
|     if 'LIBRARY' in group: | ||||
|         objs = Env.Library(name, group['src']) | ||||
|     else: | ||||
|         # only add source | ||||
|         objs = group['src'] | ||||
|  | ||||
|     # merge group | ||||
|     for g in Projects: | ||||
|         if g['name'] == name: | ||||
|             # merge to this group | ||||
|             MergeGroup(g, group) | ||||
|             return objs | ||||
|  | ||||
|     # add a new group | ||||
|     Projects.append(group) | ||||
|  | ||||
|     return objs | ||||
|  | ||||
| def GetCurrentDir(): | ||||
|     conscript = File('SConscript') | ||||
|     fn = conscript.rfile() | ||||
|     name = fn.name | ||||
|     path = os.path.dirname(fn.abspath) | ||||
|     return path | ||||
|  | ||||
| PREBUILDING = [] | ||||
| def RegisterPreBuildingAction(act): | ||||
|     global PREBUILDING | ||||
|     assert callable(act), 'Could only register callable objects. %s received' % repr(act) | ||||
|     PREBUILDING.append(act) | ||||
|  | ||||
| def PreBuilding(): | ||||
|     global PREBUILDING | ||||
|     for a in PREBUILDING: | ||||
|         a() | ||||
|  | ||||
| def GroupLibName(name, env): | ||||
|     import rtconfig | ||||
|     if rtconfig.PLATFORM == 'armcc': | ||||
|         return name + '_rvds' | ||||
|     elif rtconfig.PLATFORM == 'gcc': | ||||
|         return name + '_gcc' | ||||
|  | ||||
|     return name | ||||
|  | ||||
| def GroupLibFullName(name, env): | ||||
|     return env['LIBPREFIX'] + GroupLibName(name, env) + env['LIBSUFFIX'] | ||||
|  | ||||
| def BuildLibInstallAction(target, source, env): | ||||
|     lib_name = GetOption('buildlib') | ||||
|     for Group in Projects: | ||||
|         if Group['name'] == lib_name: | ||||
|             lib_name = GroupLibFullName(Group['name'], env) | ||||
|             dst_name = os.path.join(Group['path'], lib_name) | ||||
|             print ('Copy '+lib_name+' => ' +dst_name) | ||||
|             do_copy_file(lib_name, dst_name) | ||||
|             break | ||||
|  | ||||
| def DoBuilding(target, objects): | ||||
|  | ||||
|     # merge all objects into one list | ||||
|     def one_list(l): | ||||
|         lst = [] | ||||
|         for item in l: | ||||
|             if type(item) == type([]): | ||||
|                 lst += one_list(item) | ||||
|             else: | ||||
|                 lst.append(item) | ||||
|         return lst | ||||
|  | ||||
|     # handle local group | ||||
|     def local_group(group, objects): | ||||
|         if 'LOCAL_CCFLAGS' in group or 'LOCAL_CPPPATH' in group or 'LOCAL_CPPDEFINES' in group or 'LOCAL_ASFLAGS' in group: | ||||
|             CCFLAGS = Env.get('CCFLAGS', '') + group.get('LOCAL_CCFLAGS', '') | ||||
|             CPPPATH = Env.get('CPPPATH', ['']) + group.get('LOCAL_CPPPATH', ['']) | ||||
|             CPPDEFINES = Env.get('CPPDEFINES', ['']) + group.get('LOCAL_CPPDEFINES', ['']) | ||||
|             ASFLAGS = Env.get('ASFLAGS', '') + group.get('LOCAL_ASFLAGS', '') | ||||
|  | ||||
|             for source in group['src']: | ||||
|                 objects.append(Env.Object(source, CCFLAGS = CCFLAGS, ASFLAGS = ASFLAGS, | ||||
|                     CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)) | ||||
|  | ||||
|             return True | ||||
|  | ||||
|         return False | ||||
|  | ||||
|     objects = one_list(objects) | ||||
|  | ||||
|     program = None | ||||
|     # check whether special buildlib option | ||||
|     lib_name = GetOption('buildlib') | ||||
|     if lib_name: | ||||
|         objects = [] # remove all of objects | ||||
|         # build library with special component | ||||
|         for Group in Projects: | ||||
|             if Group['name'] == lib_name: | ||||
|                 lib_name = GroupLibName(Group['name'], Env) | ||||
|                 if not local_group(Group, objects): | ||||
|                     objects = Env.Object(Group['src']) | ||||
|  | ||||
|                 program = Env.Library(lib_name, objects) | ||||
|  | ||||
|                 # add library copy action | ||||
|                 Env.BuildLib(lib_name, program) | ||||
|  | ||||
|                 break | ||||
|     else: | ||||
|         # remove source files with local flags setting | ||||
|         for group in Projects: | ||||
|             if 'LOCAL_CCFLAGS' in group or 'LOCAL_CPPPATH' in group or 'LOCAL_CPPDEFINES' in group: | ||||
|                 for source in group['src']: | ||||
|                     for obj in objects: | ||||
|                         if source.abspath == obj.abspath or (len(obj.sources) > 0 and source.abspath == obj.sources[0].abspath): | ||||
|                             objects.remove(obj) | ||||
|  | ||||
|         # re-add the source files to the objects | ||||
|         for group in Projects: | ||||
|             local_group(group, objects) | ||||
|  | ||||
|         program = Env.Program(target, objects) | ||||
|  | ||||
|     EndBuilding(target, program) | ||||
|  | ||||
| def GenTargetProject(program = None): | ||||
|  | ||||
|     if GetOption('target') == 'mdk': | ||||
|         from keil import MDKProject | ||||
|         from keil import MDK4Project | ||||
|         from keil import MDK5Project | ||||
|  | ||||
|         template = os.path.isfile('template.Uv2') | ||||
|         if template: | ||||
|             MDKProject('project.Uv2', Projects) | ||||
|         else: | ||||
|             template = os.path.isfile('template.uvproj') | ||||
|             if template: | ||||
|                 MDK4Project('project.uvproj', Projects) | ||||
|             else: | ||||
|                 template = os.path.isfile('template.uvprojx') | ||||
|                 if template: | ||||
|                     MDK5Project('project.uvprojx', Projects) | ||||
|                 else: | ||||
|                     print ('No template project file found.') | ||||
|  | ||||
|     if GetOption('target') == 'mdk4': | ||||
|         from keil import MDK4Project | ||||
|         MDK4Project('project.uvproj', Projects) | ||||
|  | ||||
|     if GetOption('target') == 'mdk5': | ||||
|         from keil import MDK5Project | ||||
|         MDK5Project('project.uvprojx', Projects) | ||||
|  | ||||
|     if GetOption('target') == 'iar': | ||||
|         from iar import IARProject | ||||
|         IARProject('project.ewp', Projects) | ||||
|  | ||||
|     if GetOption('target') == 'vs': | ||||
|         from vs import VSProject | ||||
|         VSProject('project.vcproj', Projects, program) | ||||
|  | ||||
|     if GetOption('target') == 'vs2012': | ||||
|         from vs2012 import VS2012Project | ||||
|         VS2012Project('project.vcxproj', Projects, program) | ||||
|  | ||||
|     if GetOption('target') == 'cb': | ||||
|         from codeblocks import CBProject | ||||
|         CBProject('project.cbp', Projects, program) | ||||
|  | ||||
|     if GetOption('target') == 'ua': | ||||
|         from ua import PrepareUA | ||||
|         PrepareUA(Projects, Rtt_Root, str(Dir('#'))) | ||||
|  | ||||
|     if GetOption('target') == 'vsc': | ||||
|         from vsc import GenerateVSCode | ||||
|         GenerateVSCode(Env) | ||||
|  | ||||
|     if GetOption('target') == 'cdk': | ||||
|         from cdk import CDKProject | ||||
|         CDKProject('project.cdkproj', Projects) | ||||
|  | ||||
|     if GetOption('target') == 'ses': | ||||
|         from ses import SESProject | ||||
|         SESProject(Env) | ||||
|  | ||||
| def EndBuilding(target, program = None): | ||||
|     import rtconfig | ||||
|  | ||||
|     need_exit = False | ||||
|  | ||||
|     Env['target']  = program | ||||
|     Env['project'] = Projects | ||||
|  | ||||
|     if hasattr(rtconfig, 'BSP_LIBRARY_TYPE'): | ||||
|         Env['bsp_lib_type'] = rtconfig.BSP_LIBRARY_TYPE | ||||
|  | ||||
|     if hasattr(rtconfig, 'dist_handle'): | ||||
|         Env['dist_handle'] = rtconfig.dist_handle | ||||
|  | ||||
|     Env.AddPostAction(target, rtconfig.POST_ACTION) | ||||
|     # Add addition clean files | ||||
|     Clean(target, 'cconfig.h') | ||||
|     Clean(target, 'rtua.py') | ||||
|     Clean(target, 'rtua.pyc') | ||||
|  | ||||
|     if GetOption('target'): | ||||
|         GenTargetProject(program) | ||||
|  | ||||
|     BSP_ROOT = Dir('#').abspath | ||||
|     if GetOption('make-dist') and program != None: | ||||
|         from mkdist import MkDist | ||||
|         MkDist(program, BSP_ROOT, Rtt_Root, Env) | ||||
|     if GetOption('make-dist-strip') and program != None: | ||||
|         from mkdist import MkDist_Strip | ||||
|         MkDist_Strip(program, BSP_ROOT, Rtt_Root, Env) | ||||
|         need_exit = True | ||||
|     if GetOption('cscope'): | ||||
|         from cscope import CscopeDatabase | ||||
|         CscopeDatabase(Projects) | ||||
|  | ||||
|     if not GetOption('help') and not GetOption('target'): | ||||
|         if not os.path.exists(rtconfig.EXEC_PATH): | ||||
|             print ("Error: the toolchain path (" + rtconfig.EXEC_PATH + ") is not exist, please check 'EXEC_PATH' in path or rtconfig.py.") | ||||
|             need_exit = True | ||||
|  | ||||
|     if need_exit: | ||||
|         exit(0) | ||||
|  | ||||
| def SrcRemove(src, remove): | ||||
|     if not src: | ||||
|         return | ||||
|  | ||||
|     src_bak = src[:] | ||||
|  | ||||
|     if type(remove) == type('str'): | ||||
|         if os.path.isabs(remove): | ||||
|             remove = os.path.relpath(remove, GetCurrentDir()) | ||||
|         remove = os.path.normpath(remove) | ||||
|  | ||||
|         for item in src_bak: | ||||
|             if type(item) == type('str'): | ||||
|                 item_str = item | ||||
|             else: | ||||
|                 item_str = item.rstr() | ||||
|  | ||||
|             if os.path.isabs(item_str): | ||||
|                 item_str = os.path.relpath(item_str, GetCurrentDir()) | ||||
|             item_str = os.path.normpath(item_str) | ||||
|  | ||||
|             if item_str == remove: | ||||
|                 src.remove(item) | ||||
|     else: | ||||
|         for remove_item in remove: | ||||
|             remove_str = str(remove_item) | ||||
|             if os.path.isabs(remove_str): | ||||
|                 remove_str = os.path.relpath(remove_str, GetCurrentDir()) | ||||
|             remove_str = os.path.normpath(remove_str) | ||||
|  | ||||
|             for item in src_bak: | ||||
|                 if type(item) == type('str'): | ||||
|                     item_str = item | ||||
|                 else: | ||||
|                     item_str = item.rstr() | ||||
|  | ||||
|                 if os.path.isabs(item_str): | ||||
|                     item_str = os.path.relpath(item_str, GetCurrentDir()) | ||||
|                 item_str = os.path.normpath(item_str) | ||||
|  | ||||
|                 if item_str == remove_str: | ||||
|                     src.remove(item) | ||||
|  | ||||
| def GetVersion(): | ||||
|     import SCons.cpp | ||||
|     import string | ||||
|  | ||||
|     rtdef = os.path.join(Rtt_Root, 'include', 'rtdef.h') | ||||
|  | ||||
|     # parse rtdef.h to get RT-Thread version | ||||
|     prepcessor = PatchedPreProcessor() | ||||
|     f = open(rtdef, 'r') | ||||
|     contents = f.read() | ||||
|     f.close() | ||||
|     prepcessor.process_contents(contents) | ||||
|     def_ns = prepcessor.cpp_namespace | ||||
|  | ||||
|     version = int(filter(lambda ch: ch in '0123456789.', def_ns['RT_VERSION'])) | ||||
|     subversion = int(filter(lambda ch: ch in '0123456789.', def_ns['RT_SUBVERSION'])) | ||||
|  | ||||
|     if 'RT_REVISION' in def_ns: | ||||
|         revision = int(filter(lambda ch: ch in '0123456789.', def_ns['RT_REVISION'])) | ||||
|         return '%d.%d.%d' % (version, subversion, revision) | ||||
|  | ||||
|     return '0.%d.%d' % (version, subversion) | ||||
|  | ||||
| def GlobSubDir(sub_dir, ext_name): | ||||
|     import os | ||||
|     import glob | ||||
|  | ||||
|     def glob_source(sub_dir, ext_name): | ||||
|         list = os.listdir(sub_dir) | ||||
|         src = glob.glob(os.path.join(sub_dir, ext_name)) | ||||
|  | ||||
|         for item in list: | ||||
|             full_subdir = os.path.join(sub_dir, item) | ||||
|             if os.path.isdir(full_subdir): | ||||
|                 src += glob_source(full_subdir, ext_name) | ||||
|         return src | ||||
|  | ||||
|     dst = [] | ||||
|     src = glob_source(sub_dir, ext_name) | ||||
|     for item in src: | ||||
|         dst.append(os.path.relpath(item, sub_dir)) | ||||
|     return dst | ||||
|  | ||||
| def PackageSConscript(package): | ||||
|     from package import BuildPackage | ||||
|  | ||||
|     return BuildPackage(package) | ||||
		Reference in New Issue
	
	Block a user