summaryrefslogtreecommitdiff
path: root/tools/eclipse.py
diff options
context:
space:
mode:
authorarmink <[email protected]>2019-12-17 20:11:46 +0800
committerarmink <[email protected]>2019-12-17 20:11:46 +0800
commit4875ee8a3ab95c4fbf1e09941d3f44d99a9a632b (patch)
tree15c596c04a842bac747bbcf05a703b8da76f8eac /tools/eclipse.py
parentfa46d6ac861f26b472d62abdf1278c445431ce4c (diff)
Sync from master (75a3f3dd3a930eab1dc58fa0258a9d1605a0ac11)
Diffstat (limited to 'tools/eclipse.py')
-rw-r--r--tools/eclipse.py367
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!')