yotta/lib/cmakegen.py
def generate(
            self, builddir, modbuilddir, component, active_dependencies, immediate_dependencies, all_dependencies, application, toplevel
        ):
        ''' active_dependencies is the dictionary of components that need to be
            built for this component, but will not already have been built for
            another component.
        '''

        include_root_dirs = ''
        if application is not None and component is not application:
            include_root_dirs += 'include_directories("%s")\n' % replaceBackslashes(application.path)

        include_sys_dirs = ''
        include_other_dirs = ''
        for name, c in itertools.chain(((component.getName(), component),), all_dependencies.items()):
            if c is not component and c.isTestDependency():
                continue
            include_root_dirs += 'include_directories("%s")\n' % replaceBackslashes(c.path)
            dep_sys_include_dirs = c.getExtraSysIncludes()
            for d in dep_sys_include_dirs:
                include_sys_dirs += 'include_directories(SYSTEM "%s")\n' % replaceBackslashes(os.path.join(c.path, d))
            dep_extra_include_dirs = c.getExtraIncludes()
            for d in dep_extra_include_dirs:
                include_other_dirs += 'include_directories("%s")\n' % replaceBackslashes(os.path.join(c.path, d))

        add_depend_subdirs = ''
        for name, c in active_dependencies.items():
            depend_subdir = replaceBackslashes(os.path.join(modbuilddir, name))
            relpath = replaceBackslashes(os.path.relpath(depend_subdir, self.buildroot))
            add_depend_subdirs += \
                'add_subdirectory(\n' \
                '   "%s"\n' \
                '   "${CMAKE_BINARY_DIR}/%s"\n' \
                ')\n' \
                % (depend_subdir, relpath)

        delegate_to_existing = None
        delegate_build_dir = None

        module_is_empty = False
        if os.path.isfile(os.path.join(component.path, 'CMakeLists.txt')) and not component.ignores('CMakeLists.txt'):
            # adding custom CMake is a promise to generate a library: so the
            # module is never empty in this case.
            delegate_to_existing = component.path
            add_own_subdirs = []
            logger.debug("delegate to build dir: %s", builddir)
            delegate_build_dir = os.path.join(builddir, 'existing')
        else:
            # !!! TODO: if they don't exist, that should possibly be a fatal
            # error, not just a warning
            self._validateListedSubdirsExist(component)

            subdirs = self._listSubDirectories(component, toplevel)
            manual_subdirs      = subdirs['manual']
            autogen_subdirs     = subdirs['auto']
            binary_subdirs      = subdirs['bin']
            lib_subdirs         = subdirs['lib']
            test_subdirs        = subdirs['test']
            resource_subdirs    = subdirs['resource']
            header_subdirs      = subdirs['headers']
            logger.debug("%s lib subdirs: %s, bin subdirs: %s", component, lib_subdirs, binary_subdirs)

            add_own_subdirs = []
            for f in manual_subdirs:
                if os.path.isfile(os.path.join(component.path, f, 'CMakeLists.txt')):
                    # if this module is a test dependency, then don't recurse
                    # to building its own tests.
                    if f in test_subdirs and component.isTestDependency():
                        continue
                    add_own_subdirs.append(
                        (os.path.join(component.path, f), f)
                    )
            # names of all directories at this level with stuff in: used to figure
            # out what to link automatically
            all_subdirs = manual_subdirs + [x[0] for x in autogen_subdirs]

            # first check if this module is empty:
            if component.isTestDependency():
                if len(autogen_subdirs) + len(add_own_subdirs) == 0:
                    module_is_empty = True
            else:
                if len(autogen_subdirs) + len(add_own_subdirs) <= len(test_subdirs):
                    module_is_empty = True

            # autogenerate CMakeLists for subdirectories as appropriate:
            for f, source_files in autogen_subdirs:
                if f in test_subdirs:
                    # if this module is a test dependency, then don't recurse
                    # to building its own tests.
                    if component.isTestDependency():
                        continue
                    self.generateTestDirList(
                        builddir, f, source_files, component, immediate_dependencies, toplevel=toplevel, module_is_empty=module_is_empty
                    )
                else:
                    if f in binary_subdirs:
                        is_executable = True
                        object_name = binary_subdirs[f]
                    else:
                        # not a test subdir or binary subdir: it must be a lib
                        # subdir
                        assert(f in lib_subdirs)
                        object_name = lib_subdirs[f]

                    for header_dir, header_files in header_subdirs:
                        source_files.extend(header_files)

                    self.generateSubDirList(
                                      builddir = builddir,
                                       dirname = f,
                                  source_files = source_files,
                                     component = component,
                                   all_subdirs = all_subdirs,
                        immediate_dependencies = immediate_dependencies,
                                   object_name = object_name,
                              resource_subdirs = resource_subdirs,
                                 is_executable = (f in binary_subdirs)
                    )
                add_own_subdirs.append(
                    (os.path.join(builddir, f), f)
                )

            # from now on, completely forget that this component had any tests
            # if it is itself a test dependency:
            if component.isTestDependency():
                test_subdirs = []

            # if we're not building anything other than tests, and this is a
            # library module (not a binary) then we need to generate a dummy
            # library so that this component can still be linked against
            if module_is_empty:
                if len(binary_subdirs):
                    logger.warning('nothing to build!')
                else:
                    add_own_subdirs.append(self.createDummyLib(
                        component, builddir, [x[0] for x in immediate_dependencies.items() if not x[1].isTestDependency()]
                    ))

        toolchain_file_path = os.path.join(builddir, 'toolchain.cmake')
        if toplevel:
            # generate the top-level toolchain file:
            template = jinja_environment.get_template('toolchain.cmake')
            file_contents = template.render({  #pylint: disable=no-member
                                   # toolchain files are provided in hierarchy
                                   # order, but the template needs them in reverse
                                   # order (base-first):
                "toolchain_files": self.target.getToolchainFiles()
            })
            self._writeFile(toolchain_file_path, file_contents)

        # generate the top-level CMakeLists.txt
        template = jinja_environment.get_template('base_CMakeLists.txt')

        relpath = os.path.relpath(builddir, self.buildroot)

        file_contents = template.render({ #pylint: disable=no-member
                            "toplevel": toplevel,
                         "target_name": self.target.getName(),
                     "set_definitions": self.set_toplevel_definitions,
                      "toolchain_file": toolchain_file_path,
                           "component": component,
                             "relpath": relpath,
                   "include_root_dirs": include_root_dirs,
                    "include_sys_dirs": include_sys_dirs,
                  "include_other_dirs": include_other_dirs,
                  "add_depend_subdirs": add_depend_subdirs,
                     "add_own_subdirs": add_own_subdirs,
                 "config_include_file": self.config_include_file,
                         "delegate_to": delegate_to_existing,
                  "delegate_build_dir": delegate_build_dir,
                 "active_dependencies": active_dependencies,
                     "module_is_empty": module_is_empty,
                      "cmake_includes": self.target.getAdditionalIncludes()
        })
        self._writeFile(os.path.join(builddir, 'CMakeLists.txt'), file_contents)
def generate(
            self, builddir, modbuilddir, component, active_dependencies, immediate_dependencies, all_dependencies, application, toplevel
        ):
        ''' active_dependencies is the dictionary of components that need to be
            built for this component, but will not already have been built for
            another component.
        '''

        include_root_dirs = ''
        if application is not None and component is not application:
            include_root_dirs += 'include_directories("%s")\n' % replaceBackslashes(application.path)

        include_sys_dirs = ''
        include_other_dirs = ''
        for name, c in itertools.chain(((component.getName(), component),), all_dependencies.items()):
            if c is not component and c.isTestDependency():
                continue
            include_root_dirs += 'include_directories("%s")\n' % replaceBackslashes(c.path)
            dep_sys_include_dirs = c.getExtraSysIncludes()
            for d in dep_sys_include_dirs:
                include_sys_dirs += 'include_directories(SYSTEM "%s")\n' % replaceBackslashes(os.path.join(c.path, d))
            dep_extra_include_dirs = c.getExtraIncludes()
            for d in dep_extra_include_dirs:
                include_other_dirs += 'include_directories("%s")\n' % replaceBackslashes(os.path.join(c.path, d))

        add_depend_subdirs = ''
        for name, c in active_dependencies.items():
            depend_subdir = replaceBackslashes(os.path.join(modbuilddir, name))
            relpath = replaceBackslashes(os.path.relpath(depend_subdir, self.buildroot))
            add_depend_subdirs += \
                'add_subdirectory(\n' \
                '   "%s"\n' \
                '   "${CMAKE_BINARY_DIR}/%s"\n' \
                ')\n' \
                % (depend_subdir, relpath)

        delegate_to_existing = None
        delegate_build_dir = None

        module_is_empty = False
        if os.path.isfile(os.path.join(component.path, 'CMakeLists.txt')) and not component.ignores('CMakeLists.txt'):
            # adding custom CMake is a promise to generate a library: so the
            # module is never empty in this case.
            delegate_to_existing = component.path
            add_own_subdirs = []
            logger.debug("delegate to build dir: %s", builddir)
            delegate_build_dir = os.path.join(builddir, 'existing')
        else:
            # !!! TODO: if they don't exist, that should possibly be a fatal
            # error, not just a warning
            self._validateListedSubdirsExist(component)

            subdirs = self._listSubDirectories(component, toplevel)
            manual_subdirs      = subdirs['manual']
            autogen_subdirs     = subdirs['auto']
            binary_subdirs      = subdirs['bin']
            lib_subdirs         = subdirs['lib']
            test_subdirs        = subdirs['test']
            resource_subdirs    = subdirs['resource']
            header_subdirs      = subdirs['headers']
            logger.debug("%s lib subdirs: %s, bin subdirs: %s", component, lib_subdirs, binary_subdirs)

            add_own_subdirs = []
            for f in manual_subdirs:
                if os.path.isfile(os.path.join(component.path, f, 'CMakeLists.txt')):
                    # if this module is a test dependency, then don't recurse
                    # to building its own tests.
                    if f in test_subdirs and component.isTestDependency():
                        continue
                    add_own_subdirs.append(
                        (os.path.join(component.path, f), f)
                    )
            # names of all directories at this level with stuff in: used to figure
            # out what to link automatically
            all_subdirs = manual_subdirs + [x[0] for x in autogen_subdirs]

            # first check if this module is empty:
            if component.isTestDependency():
                if len(autogen_subdirs) + len(add_own_subdirs) == 0:
                    module_is_empty = True
            else:
                if len(autogen_subdirs) + len(add_own_subdirs) <= len(test_subdirs):
                    module_is_empty = True

            # autogenerate CMakeLists for subdirectories as appropriate:
            for f, source_files in autogen_subdirs:
                if f in test_subdirs:
                    # if this module is a test dependency, then don't recurse
                    # to building its own tests.
                    if component.isTestDependency():
                        continue
                    self.generateTestDirList(
                        builddir, f, source_files, component, immediate_dependencies, toplevel=toplevel, module_is_empty=module_is_empty
                    )
                else:
                    if f in binary_subdirs:
                        is_executable = True
                        object_name = binary_subdirs[f]
                    else:
                        # not a test subdir or binary subdir: it must be a lib
                        # subdir
                        assert(f in lib_subdirs)
                        object_name = lib_subdirs[f]

                    for header_dir, header_files in header_subdirs:
                        source_files.extend(header_files)

                    self.generateSubDirList(
                                      builddir = builddir,
                                       dirname = f,
                                  source_files = source_files,
                                     component = component,
                                   all_subdirs = all_subdirs,
                        immediate_dependencies = immediate_dependencies,
                                   object_name = object_name,
                              resource_subdirs = resource_subdirs,
                                 is_executable = (f in binary_subdirs)
                    )
                add_own_subdirs.append(
                    (os.path.join(builddir, f), f)
                )

            # from now on, completely forget that this component had any tests
            # if it is itself a test dependency:
            if component.isTestDependency():
                test_subdirs = []

            # if we're not building anything other than tests, and this is a
            # library module (not a binary) then we need to generate a dummy
            # library so that this component can still be linked against
            if module_is_empty:
                if len(binary_subdirs):
                    logger.warning('nothing to build!')
                else:
                    add_own_subdirs.append(self.createDummyLib(
                        component, builddir, [x[0] for x in immediate_dependencies.items() if not x[1].isTestDependency()]
                    ))

        toolchain_file_path = os.path.join(builddir, 'toolchain.cmake')
        if toplevel:
            # generate the top-level toolchain file:
            template = jinja_environment.get_template('toolchain.cmake')
            file_contents = template.render({  #pylint: disable=no-member
                                   # toolchain files are provided in hierarchy
                                   # order, but the template needs them in reverse
                                   # order (base-first):
                "toolchain_files": self.target.getToolchainFiles()
            })
            self._writeFile(toolchain_file_path, file_contents)

        # generate the top-level CMakeLists.txt
        template = jinja_environment.get_template('base_CMakeLists.txt')

        relpath = os.path.relpath(builddir, self.buildroot)

        file_contents = template.render({ #pylint: disable=no-member
                            "toplevel": toplevel,
                         "target_name": self.target.getName(),
                     "set_definitions": self.set_toplevel_definitions,
                      "toolchain_file": toolchain_file_path,
                           "component": component,
                             "relpath": relpath,
                   "include_root_dirs": include_root_dirs,
                    "include_sys_dirs": include_sys_dirs,
                  "include_other_dirs": include_other_dirs,
                  "add_depend_subdirs": add_depend_subdirs,
                     "add_own_subdirs": add_own_subdirs,
                 "config_include_file": self.config_include_file,
                         "delegate_to": delegate_to_existing,
                  "delegate_build_dir": delegate_build_dir,
                 "active_dependencies": active_dependencies,
                     "module_is_empty": module_is_empty,
                      "cmake_includes": self.target.getAdditionalIncludes()
        })
        self._writeFile(os.path.join(builddir, 'CMakeLists.txt'), file_contents)
def generate ( self , builddir , modbuilddir , component , active_dependencies , immediate_dependencies , all_dependencies , application , toplevel ) : include_root_dirs = '' if application is not None and component is not application : include_root_dirs += 'include_directories("%s")\n' % replaceBackslashes ( application . path ) include_sys_dirs = '' include_other_dirs = '' for name , c in itertools . chain ( ( ( component . getName ( ) , component ) , ) , all_dependencies . items ( ) ) : if c is not component and c . isTestDependency ( ) : continue include_root_dirs += 'include_directories("%s")\n' % replaceBackslashes ( c . path ) dep_sys_include_dirs = c . getExtraSysIncludes ( ) for d in dep_sys_include_dirs : include_sys_dirs += 'include_directories(SYSTEM "%s")\n' % replaceBackslashes ( os . path . join ( c . path , d ) ) dep_extra_include_dirs = c . getExtraIncludes ( ) for d in dep_extra_include_dirs : include_other_dirs += 'include_directories("%s")\n' % replaceBackslashes ( os . path . join ( c . path , d ) ) add_depend_subdirs = '' for name , c in active_dependencies . items ( ) : depend_subdir = replaceBackslashes ( os . path . join ( modbuilddir , name ) ) relpath = replaceBackslashes ( os . path . relpath ( depend_subdir , self . buildroot ) ) add_depend_subdirs += 'add_subdirectory(\n' '   "%s"\n' '   "${CMAKE_BINARY_DIR}/%s"\n' ')\n' % ( depend_subdir , relpath ) delegate_to_existing = None delegate_build_dir = None module_is_empty = False if os . path . isfile ( os . path . join ( component . path , 'CMakeLists.txt' ) ) and not component . ignores ( 'CMakeLists.txt' ) : # adding custom CMake is a promise to generate a library: so the # module is never empty in this case. delegate_to_existing = component . path add_own_subdirs = [ ] logger . debug ( "delegate to build dir: %s" , builddir ) delegate_build_dir = os . path . join ( builddir , 'existing' ) else : # !!! TODO: if they don't exist, that should possibly be a fatal # error, not just a warning self . _validateListedSubdirsExist ( component ) subdirs = self . _listSubDirectories ( component , toplevel ) manual_subdirs = subdirs [ 'manual' ] autogen_subdirs = subdirs [ 'auto' ] binary_subdirs = subdirs [ 'bin' ] lib_subdirs = subdirs [ 'lib' ] test_subdirs = subdirs [ 'test' ] resource_subdirs = subdirs [ 'resource' ] header_subdirs = subdirs [ 'headers' ] logger . debug ( "%s lib subdirs: %s, bin subdirs: %s" , component , lib_subdirs , binary_subdirs ) add_own_subdirs = [ ] for f in manual_subdirs : if os . path . isfile ( os . path . join ( component . path , f , 'CMakeLists.txt' ) ) : # if this module is a test dependency, then don't recurse # to building its own tests. if f in test_subdirs and component . isTestDependency ( ) : continue add_own_subdirs . append ( ( os . path . join ( component . path , f ) , f ) ) # names of all directories at this level with stuff in: used to figure # out what to link automatically all_subdirs = manual_subdirs + [ x [ 0 ] for x in autogen_subdirs ] # first check if this module is empty: if component . isTestDependency ( ) : if len ( autogen_subdirs ) + len ( add_own_subdirs ) == 0 : module_is_empty = True else : if len ( autogen_subdirs ) + len ( add_own_subdirs ) <= len ( test_subdirs ) : module_is_empty = True # autogenerate CMakeLists for subdirectories as appropriate: for f , source_files in autogen_subdirs : if f in test_subdirs : # if this module is a test dependency, then don't recurse # to building its own tests. if component . isTestDependency ( ) : continue self . generateTestDirList ( builddir , f , source_files , component , immediate_dependencies , toplevel = toplevel , module_is_empty = module_is_empty ) else : if f in binary_subdirs : is_executable = True object_name = binary_subdirs [ f ] else : # not a test subdir or binary subdir: it must be a lib # subdir assert ( f in lib_subdirs ) object_name = lib_subdirs [ f ] for header_dir , header_files in header_subdirs : source_files . extend ( header_files ) self . generateSubDirList ( builddir = builddir , dirname = f , source_files = source_files , component = component , all_subdirs = all_subdirs , immediate_dependencies = immediate_dependencies , object_name = object_name , resource_subdirs = resource_subdirs , is_executable = ( f in binary_subdirs ) ) add_own_subdirs . append ( ( os . path . join ( builddir , f ) , f ) ) # from now on, completely forget that this component had any tests # if it is itself a test dependency: if component . isTestDependency ( ) : test_subdirs = [ ] # if we're not building anything other than tests, and this is a # library module (not a binary) then we need to generate a dummy # library so that this component can still be linked against if module_is_empty : if len ( binary_subdirs ) : logger . warning ( 'nothing to build!' ) else : add_own_subdirs . append ( self . createDummyLib ( component , builddir , [ x [ 0 ] for x in immediate_dependencies . items ( ) if not x [ 1 ] . isTestDependency ( ) ] ) ) toolchain_file_path = os . path . join ( builddir , 'toolchain.cmake' ) if toplevel : # generate the top-level toolchain file: template = jinja_environment . get_template ( 'toolchain.cmake' ) file_contents = template . render ( { #pylint: disable=no-member # toolchain files are provided in hierarchy # order, but the template needs them in reverse # order (base-first): "toolchain_files" : self . target . getToolchainFiles ( ) } ) self . _writeFile ( toolchain_file_path , file_contents ) # generate the top-level CMakeLists.txt template = jinja_environment . get_template ( 'base_CMakeLists.txt' ) relpath = os . path . relpath ( builddir , self . buildroot ) file_contents = template . render ( { #pylint: disable=no-member "toplevel" : toplevel , "target_name" : self . target . getName ( ) , "set_definitions" : self . set_toplevel_definitions , "toolchain_file" : toolchain_file_path , "component" : component , "relpath" : relpath , "include_root_dirs" : include_root_dirs , "include_sys_dirs" : include_sys_dirs , "include_other_dirs" : include_other_dirs , "add_depend_subdirs" : add_depend_subdirs , "add_own_subdirs" : add_own_subdirs , "config_include_file" : self . config_include_file , "delegate_to" : delegate_to_existing , "delegate_build_dir" : delegate_build_dir , "active_dependencies" : active_dependencies , "module_is_empty" : module_is_empty , "cmake_includes" : self . target . getAdditionalIncludes ( ) } ) self . _writeFile ( os . path . join ( builddir , 'CMakeLists.txt' ) , file_contents )
active_dependencies is the dictionary of components that need to be
            built for this component, but will not already have been built for
            another component.
active_dependencies is the dictionary of components that need to be built for this component but will not already have been built for another component .