mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Compute source folders exclusions.
							parent
							
								
									e717c781b0
								
							
						
					
					
						commit
						9e84338178
					
				| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
 | 
			
		||||
<?fileVersion 4.0.0?>
 | 
			
		||||
<!-- Generated by the GNU ARM Eclipse exporter from an mBed project. -->
 | 
			
		||||
<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
 | 
			
		||||
	<storageModule moduleId="org.eclipse.cdt.core.settings">
 | 
			
		||||
		<cconfiguration id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.{{debug_config_uid}}">
 | 
			
		||||
			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.{{debug_config_uid}}" moduleId="org.eclipse.cdt.core.settings" name="Debug">
 | 
			
		||||
| 
						 | 
				
			
			@ -156,7 +158,7 @@
 | 
			
		|||
						</toolChain>
 | 
			
		||||
					</folderInfo>
 | 
			
		||||
					<sourceEntries>
 | 
			
		||||
						<entry excluding="mbed-os" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
 | 
			
		||||
						<entry excluding="{{excluded_folders}}" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
 | 
			
		||||
					</sourceEntries>
 | 
			
		||||
				</configuration>
 | 
			
		||||
			</storageModule>
 | 
			
		||||
| 
						 | 
				
			
			@ -313,7 +315,7 @@
 | 
			
		|||
						</toolChain>
 | 
			
		||||
					</folderInfo>
 | 
			
		||||
					<sourceEntries>
 | 
			
		||||
						<entry excluding="mbed-os" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
 | 
			
		||||
						<entry excluding="{{excluded_folders}}" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
 | 
			
		||||
					</sourceEntries>
 | 
			
		||||
				</configuration>
 | 
			
		||||
			</storageModule>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- Generated by the GNU ARM Eclipse exporter from an mBed project. -->
 | 
			
		||||
<projectDescription>
 | 
			
		||||
	<name>{{name}}</name>
 | 
			
		||||
	<comment>This file was automagically generated by mbed.org. For more information, see http://mbed.org/handbook/Exporting-To-GNU-ARM-Eclipse</comment>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,22 +13,38 @@ distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
 | 
			
		||||
Title: GNU ARM Eclipse (http://gnuarmeclipse.github.io) exporter.
 | 
			
		||||
 | 
			
		||||
Description: Creates a managed build project that can be imported by 
 | 
			
		||||
the GNU ARM Eclipse plug-ins.
 | 
			
		||||
 | 
			
		||||
Author: Liviu Ionescu <ilg@livius.net>
 | 
			
		||||
"""
 | 
			
		||||
from tools.export.exporters import Exporter
 | 
			
		||||
from os.path import splitext, basename, relpath
 | 
			
		||||
from os.path import splitext, basename, relpath, dirname
 | 
			
		||||
from random import randint
 | 
			
		||||
import os
 | 
			
		||||
import copy
 | 
			
		||||
 | 
			
		||||
from tools.targets import TARGET_MAP
 | 
			
		||||
from tools.utils import NotSupportedException
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UID:
 | 
			
		||||
    """
 | 
			
		||||
    Helper class, used to generate unique ids required by .cproject symbols.
 | 
			
		||||
    """
 | 
			
		||||
    @property
 | 
			
		||||
    def id(self):
 | 
			
		||||
        return "%0.9u" % randint(0, 999999999)
 | 
			
		||||
 | 
			
		||||
# Global UID generator instance.
 | 
			
		||||
# Passed to the template engine, and referred as {{u.id}}.
 | 
			
		||||
# Each invocation generates a new number.
 | 
			
		||||
u = UID()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GNUARMEclipse(Exporter):
 | 
			
		||||
    NAME = 'GNU ARM Eclipse'
 | 
			
		||||
    TOOLCHAIN = 'GCC_ARM'
 | 
			
		||||
| 
						 | 
				
			
			@ -39,6 +55,9 @@ class GNUARMEclipse(Exporter):
 | 
			
		|||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def filter_dot(s):
 | 
			
		||||
        """
 | 
			
		||||
        Remove the './' prefix, if present.
 | 
			
		||||
        """
 | 
			
		||||
        if s == None:
 | 
			
		||||
            return None
 | 
			
		||||
        if s[:2] == './':
 | 
			
		||||
| 
						 | 
				
			
			@ -54,6 +73,9 @@ class GNUARMEclipse(Exporter):
 | 
			
		|||
        ld_flags     - linker flags
 | 
			
		||||
        asm_flags    - assembler flags
 | 
			
		||||
        common_flags - common options
 | 
			
		||||
 | 
			
		||||
        The difference from the parent function is that it does not
 | 
			
		||||
        add macro definitions, since they are passed separately.
 | 
			
		||||
        """
 | 
			
		||||
        config_header = self.toolchain.get_config_header()
 | 
			
		||||
        flags = {key + "_flags": copy.deepcopy(value) for key, value
 | 
			
		||||
| 
						 | 
				
			
			@ -66,9 +88,129 @@ class GNUARMEclipse(Exporter):
 | 
			
		|||
                config_header)
 | 
			
		||||
        return flags
 | 
			
		||||
 | 
			
		||||
    def dump_tree(self, node, depth=0):
 | 
			
		||||
        for k in node.keys():
 | 
			
		||||
            n = node[k]
 | 
			
		||||
            pn = n['parent']['name'] if 'parent' in n.keys() else ''
 | 
			
		||||
            print '  ' * depth, n['name'], n['is_used'], pn
 | 
			
		||||
            if len(n['children'].keys()) != 0:
 | 
			
		||||
                self.dump_tree(n['children'], depth + 1)
 | 
			
		||||
 | 
			
		||||
    def dump_paths(self, node, depth=0):
 | 
			
		||||
        for k in node.keys():
 | 
			
		||||
            n = node[k]
 | 
			
		||||
            x = []
 | 
			
		||||
            ni = n
 | 
			
		||||
            while True:
 | 
			
		||||
                x.insert(0, ni['name'])
 | 
			
		||||
                if 'parent' not in ni:
 | 
			
		||||
                    break
 | 
			
		||||
                ni = ni['parent']
 | 
			
		||||
            path = '/'.join(x)
 | 
			
		||||
            print path, n['is_used']
 | 
			
		||||
            self.dump_paths(n['children'], depth + 1)
 | 
			
		||||
 | 
			
		||||
    def recurse_excludings(self, node):
 | 
			
		||||
        """
 | 
			
		||||
        Recurse the tree and collect all unused folders; descend
 | 
			
		||||
        the hierarchy only for used nodes.
 | 
			
		||||
        """
 | 
			
		||||
        for k in node.keys():
 | 
			
		||||
            n = node[k]
 | 
			
		||||
            if n['is_used'] == False:
 | 
			
		||||
                x = []
 | 
			
		||||
                ni = n
 | 
			
		||||
                while True:
 | 
			
		||||
                    x.insert(0, ni['name'])
 | 
			
		||||
                    if 'parent' not in ni:
 | 
			
		||||
                        break
 | 
			
		||||
                    ni = ni['parent']
 | 
			
		||||
                path = '/'.join(x)
 | 
			
		||||
                # print path
 | 
			
		||||
                self.excluded_folders.append(path)
 | 
			
		||||
            else:
 | 
			
		||||
                self.recurse_excludings(n['children'])
 | 
			
		||||
 | 
			
		||||
    def add_source_folder_to_tree(self, path, is_used=False):
 | 
			
		||||
        """
 | 
			
		||||
        Decompose a path in an array of folder names and create the tree.
 | 
			
		||||
        On the second pass the nodes should be already there; mark them
 | 
			
		||||
        as used.
 | 
			
		||||
        """
 | 
			
		||||
        # print path, is_used
 | 
			
		||||
        a = path.split(os.sep)
 | 
			
		||||
        n = self.source_tree
 | 
			
		||||
        p = None
 | 
			
		||||
        for s in a:
 | 
			
		||||
            if s[0] == '.':
 | 
			
		||||
                continue
 | 
			
		||||
            if s not in n.keys():
 | 
			
		||||
                nn = {}
 | 
			
		||||
                nn['name'] = s
 | 
			
		||||
                nn['children'] = {}
 | 
			
		||||
                if p != None:
 | 
			
		||||
                    nn['parent'] = p
 | 
			
		||||
                n[s] = nn
 | 
			
		||||
            n[s]['is_used'] = is_used
 | 
			
		||||
            p = n[s]
 | 
			
		||||
            n = n[s]['children']
 | 
			
		||||
 | 
			
		||||
    def compute_exclusions(self):
 | 
			
		||||
        """
 | 
			
		||||
        With the project root as the only source folder known to CDT,
 | 
			
		||||
        based on the list of source files, compute the folders to not
 | 
			
		||||
        be included in the build.
 | 
			
		||||
 | 
			
		||||
        The steps are:
 | 
			
		||||
        - get the list of source folders, as dirname(source_file)
 | 
			
		||||
        - compute the top folders (subfolders of the project folders)
 | 
			
		||||
        - iterate all subfolders and add them to a tree, with all 
 | 
			
		||||
        nodes markes as 'not used'
 | 
			
		||||
        - iterate the source folders and mark them as 'used' in the
 | 
			
		||||
        tree, including all intermediate nodes
 | 
			
		||||
        - recurse the tree and collect all unused folders; descend
 | 
			
		||||
        the hierarchy only for used nodes
 | 
			
		||||
        """
 | 
			
		||||
        source_folders = [self.filter_dot(s) for s in set(dirname(
 | 
			
		||||
            src) for src in self.resources.c_sources + self.resources.cpp_sources + self.resources.s_sources)]
 | 
			
		||||
        source_folders.remove('.')
 | 
			
		||||
        # print 'source folders'
 | 
			
		||||
        # print source_folders
 | 
			
		||||
 | 
			
		||||
        top_folders = [f for f in set(s.split(os.sep)[0]
 | 
			
		||||
                                      for s in source_folders)]
 | 
			
		||||
        # print 'top folders'
 | 
			
		||||
        # print top_folders
 | 
			
		||||
 | 
			
		||||
        self.source_tree = {}
 | 
			
		||||
        for top_folder in top_folders:
 | 
			
		||||
            for root, dirs, files in os.walk(top_folder):
 | 
			
		||||
                if len(dirs) == 0:
 | 
			
		||||
                    self.add_source_folder_to_tree(root)
 | 
			
		||||
 | 
			
		||||
        for folder in source_folders:
 | 
			
		||||
            self.add_source_folder_to_tree(folder, True)
 | 
			
		||||
 | 
			
		||||
        # print
 | 
			
		||||
        # print self.source_tree
 | 
			
		||||
        # self.dump_paths(self.source_tree)
 | 
			
		||||
 | 
			
		||||
        # print 'excludings'
 | 
			
		||||
        self.excluded_folders = []
 | 
			
		||||
        self.recurse_excludings(self.source_tree)
 | 
			
		||||
 | 
			
		||||
    def generate(self):
 | 
			
		||||
        """
 | 
			
		||||
        Override the parent method with code generation.
 | 
			
		||||
        """
 | 
			
		||||
        if not self.resources.linker_script:
 | 
			
		||||
            raise NotSupportedException("No linker script found.")
 | 
			
		||||
 | 
			
		||||
        # TODO: Check if this is needed.
 | 
			
		||||
        # self.resources.win_to_unix()
 | 
			
		||||
 | 
			
		||||
        libraries = []
 | 
			
		||||
        print self.resources.libraries
 | 
			
		||||
        for lib in self.resources.libraries:
 | 
			
		||||
            l, _ = splitext(basename(lib))
 | 
			
		||||
            libraries.append(l[3:])
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +230,7 @@ class GNUARMEclipse(Exporter):
 | 
			
		|||
        core = self.toolchain.target.core
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            # cortex-m0, cortex-m0-small-multiply, cortex-m0plus, 
 | 
			
		||||
            # cortex-m0, cortex-m0-small-multiply, cortex-m0plus,
 | 
			
		||||
            # cortex-m0plus-small-multiply, cortex-m1, cortex-m1-small-multiply,
 | 
			
		||||
            # cortex-m3, cortex-m4, cortex-m7.
 | 
			
		||||
            target_mcpu = MCPUS[core]['mcpu']
 | 
			
		||||
| 
						 | 
				
			
			@ -101,16 +243,21 @@ class GNUARMEclipse(Exporter):
 | 
			
		|||
 | 
			
		||||
            if target_fpu_unit != None:
 | 
			
		||||
                target_fpu_abi = 'hard'
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
        except AttributeError:
 | 
			
		||||
            # TODO filter out projects with toolchain core not supported,
 | 
			
		||||
            # instead of raising an exception.
 | 
			
		||||
            raise NotSupportedException('Target core {0} not supported.'.format(core))
 | 
			
		||||
            raise NotSupportedException(
 | 
			
		||||
                'Target core {0} not supported.'.format(core))
 | 
			
		||||
 | 
			
		||||
        # TODO: clarify how to use objects; enabling this adds another
 | 
			
		||||
        # object 'main.o'.
 | 
			
		||||
        objects = [] # self.resources.objects
 | 
			
		||||
        print self.resources.objects
 | 
			
		||||
        # TODO: get the list from existing .cproject
 | 
			
		||||
        build_folders = ['Debug', 'Release']
 | 
			
		||||
 | 
			
		||||
        objects = [self.filter_dot(s) for s in self.resources.objects]
 | 
			
		||||
        for bf in build_folders:
 | 
			
		||||
            objects = [o for o in objects if not o.startswith(bf + '/')]
 | 
			
		||||
        print 'objects'
 | 
			
		||||
        print objects
 | 
			
		||||
 | 
			
		||||
        f = self.flags
 | 
			
		||||
        print 'common_flags'
 | 
			
		||||
| 
						 | 
				
			
			@ -124,10 +271,16 @@ class GNUARMEclipse(Exporter):
 | 
			
		|||
        print 'ld_flags'
 | 
			
		||||
        print f['ld_flags']
 | 
			
		||||
 | 
			
		||||
        source_folders = [self.filter_dot(s) for s in set(dirname(
 | 
			
		||||
            src) for src in self.resources.c_sources + self.resources.cpp_sources + self.resources.s_sources)]
 | 
			
		||||
        source_folders.remove('.')
 | 
			
		||||
 | 
			
		||||
        self.compute_exclusions()
 | 
			
		||||
 | 
			
		||||
        asm_defines = self.toolchain.get_symbols(True)
 | 
			
		||||
        c_defines = self.toolchain.get_symbols()
 | 
			
		||||
        cpp_defines = self.toolchain.get_symbols()
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        include_paths = [self.filter_dot(s) for s in self.resources.inc_dirs]
 | 
			
		||||
 | 
			
		||||
        library_paths = [self.filter_dot(s) for s in self.resources.lib_dirs]
 | 
			
		||||
| 
						 | 
				
			
			@ -136,6 +289,7 @@ class GNUARMEclipse(Exporter):
 | 
			
		|||
 | 
			
		||||
        ctx = {
 | 
			
		||||
            'name': self.project_name,
 | 
			
		||||
            'excluded_folders': '|'.join(self.excluded_folders),
 | 
			
		||||
            'include_paths': include_paths,
 | 
			
		||||
            'library_paths': library_paths,
 | 
			
		||||
            'object_files': objects,
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +320,26 @@ class GNUARMEclipse(Exporter):
 | 
			
		|||
            'u': u,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # ctx.update(f)
 | 
			
		||||
 | 
			
		||||
        self.gen_file('gnuarmeclipse/.project.tmpl', ctx, '.project')
 | 
			
		||||
        self.gen_file('gnuarmeclipse/.cproject.tmpl', ctx, '.cproject')
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def build(project_name, log_name="build_log.txt", cleanup=True):
 | 
			
		||||
        """
 | 
			
		||||
        Build GNU ARM Eclipse project.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        ret_code = 0
 | 
			
		||||
 | 
			
		||||
        # TODO: add code to run the build in a headless configuration.
 | 
			
		||||
 | 
			
		||||
        # Cleanup the exported and built files
 | 
			
		||||
        if cleanup:
 | 
			
		||||
            os.remove('.project')
 | 
			
		||||
            os.remove('.cproject')
 | 
			
		||||
 | 
			
		||||
        if ret_code !=0:
 | 
			
		||||
            # Seems like something went wrong.
 | 
			
		||||
            return -1
 | 
			
		||||
        else:
 | 
			
		||||
            return 0
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue