diff options
Diffstat (limited to 'tools/eclipse.py')
| -rw-r--r-- | tools/eclipse.py | 367 |
1 files changed, 252 insertions, 115 deletions
diff --git a/tools/eclipse.py b/tools/eclipse.py index 78acc8904e..253db37bea 100644 --- a/tools/eclipse.py +++ b/tools/eclipse.py @@ -102,15 +102,15 @@ def ExcludeFiles(infiles, files): # caluclate the exclude path for project -def ExcludePaths(filepath, paths): +def ExcludePaths(rootpath, paths): ret = [] - files = os.listdir(filepath) + files = os.listdir(rootpath) for file in files: if file.startswith('.'): continue - fullname = os.path.join(filepath, file) + fullname = os.path.join(rootpath, file) if os.path.isdir(fullname): # print(fullname) @@ -122,133 +122,244 @@ def ExcludePaths(filepath, paths): return ret -def ConverToEclipsePathFormat(path): - if path.startswith('.'): - path = path[1:] - return '"${workspace_loc:/${ProjName}/' + path + '}"' +rtt_path_prefix = '"${workspace_loc://${ProjName}//' -def HandleToolOption(tools, env, project): +def ConverToRttEclipsePathFormat(path): + return rtt_path_prefix + path + '}"' + + +def IsRttEclipsePathFormat(path): + if path.startswith(rtt_path_prefix): + return True + else : + return False + + +def HandleToolOption(tools, env, project, reset): BSP_ROOT = os.path.abspath(env['BSP_ROOT']) CPPDEFINES = project['CPPDEFINES'] - paths = [ConverToEclipsePathFormat(RelativeProjectPath(env, os.path.normpath(i)).replace('\\', '/')) for i in project['CPPPATH']] + paths = [ConverToRttEclipsePathFormat(RelativeProjectPath(env, os.path.normpath(i)).replace('\\', '/')) for i in project['CPPPATH']] + + compile_include_paths_option = None + compile_include_files_option = None + compile_defs_option = None + linker_scriptfile_option = None + linker_script_option = None + linker_nostart_option = None + linker_libs_option = None + linker_paths_option = None + linker_newlib_nano_option = None for tool in tools: + if tool.get('id').find('c.compile') != 1: options = tool.findall('option') + # find all compile options for option in options: - if option.get('id').find('c.compiler.include.paths') != -1: - # find all of paths in this project - include_paths = option.findall('listOptionValue') - project_paths = [] - for item in include_paths: - project_paths += [item.get('value')] - - if len(project_paths) > 0: - cproject_paths = set(paths) - set(project_paths) - else: - cproject_paths = paths - - # print('c.compiler.include.paths') - cproject_paths = sorted(cproject_paths) - for item in cproject_paths: - SubElement(option, 'listOptionValue', {'builtIn': 'false', 'value': item}) - - if option.get('id').find('c.compiler.defs') != -1: - defs = option.findall('listOptionValue') - project_defs = [] - for item in defs: - project_defs += [item.get('value')] - if len(project_defs) > 0: - cproject_defs = set(CPPDEFINES) - set(project_defs) - else: - cproject_defs = CPPDEFINES - - # print('c.compiler.defs') - cproject_defs = sorted(cproject_defs) - for item in cproject_defs: - SubElement(option, 'listOptionValue', {'builtIn': 'false', 'value': item}) + if option.get('id').find('c.compiler.include.paths') != -1 or option.get('id').find('c.compiler.option.includepaths') != -1: + compile_include_paths_option = option + elif option.get('id').find('c.compiler.include.files') != -1 or option.get('id').find('c.compiler.option.includefiles') != -1 : + compile_include_files_option = option + elif option.get('id').find('c.compiler.defs') != -1 or option.get('id').find('c.compiler.option.definedsymbols') != -1: + compile_defs_option = option if tool.get('id').find('c.linker') != -1: options = tool.findall('option') + # find all linker options for option in options: if option.get('id').find('c.linker.scriptfile') != -1: - linker_script = 'link.lds' - items = env['LINKFLAGS'].split(' ') - if '-T' in items: - linker_script = items[items.index('-T') + 1] - linker_script = ConverToEclipsePathFormat(linker_script) + linker_scriptfile_option = option + elif option.get('id').find('c.linker.option.script') != -1: + linker_script_option = option + elif option.get('id').find('c.linker.nostart') != -1: + linker_nostart_option = option + elif option.get('id').find('c.linker.libs') != -1 and env.has_key('LIBS'): + linker_libs_option = option + elif option.get('id').find('c.linker.paths') != -1 and env.has_key('LIBPATH'): + linker_paths_option = option + elif option.get('id').find('c.linker.usenewlibnano') != -1: + linker_newlib_nano_option = option - listOptionValue = option.find('listOptionValue') - if listOptionValue != None: - listOptionValue.set('value', linker_script) - else: - SubElement(option, 'listOptionValue', {'builtIn': 'false', 'value': linker_script}) + # change the inclue path + if compile_include_paths_option is not None : + option = compile_include_paths_option + # find all of paths in this project + include_paths = option.findall('listOptionValue') + for item in include_paths: + if reset is True or IsRttEclipsePathFormat(item.get('value')) : + # clean old configuration + option.remove(item) + # print('c.compiler.include.paths') + paths = sorted(paths) + for item in paths: + SubElement(option, 'listOptionValue', {'builtIn': 'false', 'value': item}) + # change the inclue files (default) or definitions + if compile_include_files_option is not None: + option = compile_include_files_option + # add '_REENT_SMALL' to CPPDEFINES when --specs=nano.specs has select + if linker_newlib_nano_option is not None and linker_newlib_nano_option.get('value') == 'true' and '_REENT_SMALL' not in CPPDEFINES: + CPPDEFINES += ['_REENT_SMALL'] - if option.get('id').find('c.linker.nostart') != -1: - if env['LINKFLAGS'].find('-nostartfiles') != -1: - option.set('value', 'true') - else: - option.set('value', 'false') + file_header = ''' +#ifndef RTCONFIG_PREINC_H__ +#define RTCONFIG_PREINC_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread pre-include file */ + +''' + file_tail = '\n#endif /*RTCONFIG_PREINC_H__*/\n' + rtt_pre_inc_item = '"${workspace_loc:/${ProjName}/rtconfig_preinc.h}"' + # save the CPPDEFINES in to rtconfig_preinc.h + with open('rtconfig_preinc.h', mode = 'w+') as f: + f.write(file_header) + for cppdef in CPPDEFINES: + f.write("#define " + cppdef + '\n') + f.write(file_tail) + # change the c.compiler.include.files + files = option.findall('listOptionValue') + find_ok = False + for item in files: + if item.get('value') == rtt_pre_inc_item: + find_ok = True + break + if find_ok is False: + SubElement(option, 'listOptionValue', {'builtIn': 'false', 'value': rtt_pre_inc_item}) + elif compile_defs_option is not None : + option = compile_defs_option + defs = option.findall('listOptionValue') + project_defs = [] + for item in defs: + if reset is True: + # clean all old configuration + option.remove(item) + else: + project_defs += [item.get('value')] + if len(project_defs) > 0: + cproject_defs = set(CPPDEFINES) - set(project_defs) + else: + cproject_defs = CPPDEFINES + + # print('c.compiler.defs') + cproject_defs = sorted(cproject_defs) + for item in cproject_defs: + SubElement(option, 'listOptionValue', {'builtIn': 'false', 'value': item}) + + # update linker script config + if linker_scriptfile_option is not None : + option = linker_scriptfile_option + linker_script = 'link.lds' + items = env['LINKFLAGS'].split(' ') + if '-T' in items: + linker_script = items[items.index('-T') + 1] + linker_script = ConverToRttEclipsePathFormat(linker_script) + + listOptionValue = option.find('listOptionValue') + if listOptionValue != None: + listOptionValue.set('value', linker_script) + else: + SubElement(option, 'listOptionValue', {'builtIn': 'false', 'value': linker_script}) + # scriptfile in stm32cubeIDE + if linker_script_option is not None : + option = linker_script_option + items = env['LINKFLAGS'].split(' ') + if '-T' in items: + linker_script = ConverToRttEclipsePathFormat(items[items.index('-T') + 1]).strip('"') + option.set('value', linker_script) + # update nostartfiles config + if linker_nostart_option is not None : + option = linker_nostart_option + if env['LINKFLAGS'].find('-nostartfiles') != -1: + option.set('value', 'true') + else: + option.set('value', 'false') + # update libs + if linker_libs_option is not None : + option = linker_libs_option + # remove old libs + for item in option.findall('listOptionValue'): + option.remove(item) + # add new libs + for lib in env['LIBS']: + SubElement(option, 'listOptionValue', {'builtIn': 'false', 'value': lib}) + # update lib paths + if linker_paths_option is not None : + option = linker_paths_option + # remove old lib paths + for item in option.findall('listOptionValue'): + option.remove(item) + # add new old lib paths + for path in env['LIBPATH']: + SubElement(option, 'listOptionValue', {'builtIn': 'false', 'value': path}) return -def UpdateProjectStructure(env): + +def UpdateProjectStructure(env, prj_name): bsp_root = env['BSP_ROOT'] rtt_root = env['RTT_ROOT'] - if not rtt_root.startswith(bsp_root): - to_SubElement = True - # print('handle virtual root') + project = etree.parse('.project') + root = project.getroot() - # always use '/' path separator - rtt_root = rtt_root.replace('\\', '/') + if rtt_root.startswith(bsp_root): + linkedResources = root.find('linkedResources') + if linkedResources == None: + linkedResources = SubElement(root, 'linkedResources') - # TODO create the virtual folder + links = linkedResources.findall('link') + # delete all RT-Thread folder links + for link in links: + if link.find('name').text.startswith('rt-thread'): + linkedResources.remove(link) -# project = etree.parse('.project') -# root = project.getroot() -# -# linkedResources = root.find('linkedResources') -# if linkedResources == None: -# # add linkedResources -# linkedResources = SubElement(root, 'linkedResources') -# # print('add linkedResources') -# else: -# links = linkedResources.findall('link') -# # search exist 'rt-thread' virtual folder -# for link in links: -# if link.find('name').text == 'rt-thread': -# # handle location -# to_SubElement = False -# location = link.find('location') -# location.text = rtt_root -# -# if to_SubElement: -# # print('to subelement for virtual folder') -# link = SubElement(linkedResources, 'link') -# name = SubElement(link, 'name') -# name.text = 'rt-thread' -# type = SubElement(link, 'type') -# type.text = '2' -# location = SubElement(link, 'location') -# location.text = rtt_root -# -# out = open('.project', 'w') -# out.write('<?xml version="1.0" encoding="UTF-8"?>\n') -# xml_indent(root) -# out.write(etree.tostring(root, encoding='utf-8')) -# out.close() + if prj_name: + name = root.find('name') + if name == None: + name = SubElement(root, 'name') + name.text = prj_name + + out = open('.project', 'w') + out.write('<?xml version="1.0" encoding="UTF-8"?>\n') + xml_indent(root) + out.write(etree.tostring(root, encoding = 'utf-8')) + out.close() return + def GenExcluding(env, project): rtt_root = os.path.abspath(env['RTT_ROOT']) + bsp_root = os.path.abspath(env['BSP_ROOT']) coll_dirs = CollectPaths(project['DIRS']) all_paths = [OSPath(path) for path in coll_dirs] - exclude_paths = ExcludePaths(rtt_root, all_paths) + # remove unused path + for path in all_paths: + if not path.startswith(rtt_root) and not path.startswith(bsp_root): + all_paths.remove(path) + + if bsp_root.startswith(rtt_root): + # bsp folder is in the RT-Thread root folder, such as the RT-Thread source code on GitHub + exclude_paths = ExcludePaths(rtt_root, all_paths) + elif rtt_root.startswith(bsp_root): + # RT-Thread root folder is in the bsp folder, such as project folder which generate by 'scons --dist' cmd + check_path = [] + exclude_paths = [] + # analyze the primary folder which relative to BSP_ROOT and in all_paths + for path in all_paths : + if path.startswith(bsp_root) : + folders = RelativeProjectPath(env, path).split('\\') + if folders[0] != '.' and '\\' + folders[0] not in check_path: + check_path += ['\\' + folders[0]] + # exclue the folder which has managed by scons + for path in check_path: + exclude_paths += ExcludePaths(bsp_root + path, all_paths) + else: + exclude_paths = ExcludePaths(rtt_root, all_paths) + exclude_paths += ExcludePaths(bsp_root, all_paths) paths = exclude_paths exclude_paths = [] @@ -264,15 +375,16 @@ def GenExcluding(env, project): exclude_paths += [path] exclude_paths = [RelativeProjectPath(env, path).replace('\\', '/') for path in exclude_paths] - env['ExPaths'] = exclude_paths all_files = CollectFiles(all_paths, source_pattern) src_files = project['FILES'] exclude_files = ExcludeFiles(all_files, src_files) exclude_files = [RelativeProjectPath(env, file).replace('\\', '/') for file in exclude_files] + + env['ExPaths'] = exclude_paths env['ExFiles'] = exclude_files - + return exclude_paths + exclude_files @@ -287,12 +399,39 @@ def RelativeProjectPath(env, path): return 'rt-thread/' + _make_path_relative(rtt_root, path) # TODO add others folder - print('ERROR: the ' + path + 'not support') + print('ERROR: the ' + path + ' not support') return path -def UpdateCproject(env, project, excluding): +def HandleExcludingOption(entry, sourceEntries, excluding): + old_excluding = [] + if entry != None: + old_excluding = entry.get('excluding').split('|') + sourceEntries.remove(entry) + + value = '' + for item in old_excluding: + if item.startswith('//') : + old_excluding.remove(item) + else : + if value == '': + value = item + else: + value += '|' + item + + for item in excluding: + # add special excluding path prefix for RT-Thread + item = '//' + item + if value == '': + value = item + else: + value += '|' + item + + SubElement(sourceEntries, 'entry', {'excluding': value, 'flags': 'VALUE_WORKSPACE_PATH|RESOLVED', 'kind':'sourcePath', 'name':""}) + + +def UpdateCproject(env, project, excluding, reset, prj_name): excluding = sorted(excluding) cproject = etree.parse('.cproject') @@ -301,21 +440,19 @@ def UpdateCproject(env, project, excluding): cconfigurations = root.findall('storageModule/cconfiguration') for cconfiguration in cconfigurations: tools = cconfiguration.findall('storageModule/configuration/folderInfo/toolChain/tool') - HandleToolOption(tools, env, project) + HandleToolOption(tools, env, project, reset) sourceEntries = cconfiguration.find('storageModule/configuration/sourceEntries') entry = sourceEntries.find('entry') - if entry != None: - sourceEntries.remove(entry) - - value = '' - for item in excluding: - if value == '': - value = item - else: - value += '|' + item - - SubElement(sourceEntries, 'entry', {'excluding': value, 'flags': 'VALUE_WORKSPACE_PATH|RESOLVED', 'kind':'sourcePath', 'name':""}) + HandleExcludingOption(entry, sourceEntries, excluding) + # update refreshScope + if prj_name: + prj_name = '/' + prj_name + configurations = root.findall('storageModule/configuration') + for configuration in configurations: + resource = configuration.find('resource') + configuration.remove(resource) + SubElement(configuration, 'resource', {'resourceType': "PROJECT", 'workspacePath': prj_name}) # write back to .cproject out = open('.cproject', 'w') @@ -326,7 +463,7 @@ def UpdateCproject(env, project, excluding): out.close() -def TargetEclipse(env): +def TargetEclipse(env, reset = False, prj_name = None): global source_pattern print('Update eclipse setting...') @@ -338,13 +475,13 @@ def TargetEclipse(env): project = ProjectInfo(env) # update the project file structure info on '.project' file - UpdateProjectStructure(env) + UpdateProjectStructure(env, prj_name) # generate the exclude paths and files excluding = GenExcluding(env, project) # update the project configuration on '.cproject' file - UpdateCproject(env, project, excluding) + UpdateCproject(env, project, excluding, reset, prj_name) print('done!') |
