def make_build_config(repo_context, build_flags_parser, uplid, ufid,
                      default_rules, debug_keys=[]):
    """Create a build configuration for repository.

    Args:
        repo_context (RepoContext): Repository structure and metadata.
        build_flags_parser (BuildFlagsParser): Parser for build flags.
        uplid (Uplid): Build platform id.
        ufid (Ufid): Build flags id.
        default_rules (list of OptionRule): Option rules that is the base of
            all UORs.
        debug_keys (list of str): Print some debug information for some
            option keys.
    """

    build_config = buildconfig.BuildConfig(repo_context.root_path, uplid,
                                           ufid)

    for unit in repo_context.units.values():
        if unit.type_ == repounits.UnitType.THIRD_PARTY_DIR:
            build_config.third_party_dirs[unit.name] = unit

    uor_dep_graph = repocontextutil.get_uor_digraph(repo_context)
    uor_map = repocontextutil.get_uor_map(repo_context)

    build_config.external_dep = graphutil.find_external_nodes(uor_dep_graph)

    # BDE_CXXINCLUDES is hard coded in bde_build
    initial_options = {
        'BDE_CXXINCLUDES': '$(BDE_CXXINCLUDE)'
    }

    # Waf already knows about the flags necessary for building shared objects,
    # so don't get the necessary flags from opts files.  We don't have to the
    # operation below once we remove the the option rules for 'shr' in the
    # default option files.

    effective_ufid = copy.deepcopy(build_config.ufid)
    effective_ufid.flags.discard('shr')
    def_oe = optionsevaluator.OptionsEvaluator(build_config.uplid,
                                               effective_ufid,
                                               initial_options)

    def_oe.store_option_rules(default_rules, debug_keys)

    def_oe_copy = copy.deepcopy(def_oe)
    def_oe_copy.evaluate()
    build_config.default_flags = get_build_flags_from_opts(
        build_flags_parser, def_oe_copy.results, def_oe_copy.results)

    # These custom environment variables comes from default_internal.opts and
    # needs to be set when building dpkg.
    env_variables = ('SET_TMPDIR', 'XLC_LIBPATH')
    setenv_re = re.compile(r'^([^=]+)=(.*)$')
    for e in env_variables:
        if e in def_oe_copy.results:
            m = setenv_re.match(def_oe_copy.results[e])
            if m:
                build_config.custom_envs[m.group(1)] = m.group(2)

    def set_unit_loc(oe, unit):
        oe.results['%s_LOCN' %
                   unit.name.upper().replace('+', '_')] = unit.path

    def load_uor(uor):
        # Preserve the existing behavior of loading defs, opts and cap files as
        # bde_build:
        #
        # - Exported options of an UOR: read the defs files of its dependencies
        #   follow by itself. The files of the dependencies should be read in
        #   topological order, if the order of certain dependencies are
        #   ambiguous, order them first by dependency levels, and then by their
        #   name.
        #
        # - Internal options of an UOR: read the defs files in the same way,
        #   followed by its own opts file.

        dep_levels = graphutil.levelize(uor_dep_graph,
                                        uor_dep_graph[uor.name])

        oe = copy.deepcopy(def_oe)
        # We load options in levelized order instead of any topological order
        # to preserve the behavior with bde_build (older version of the build
        # tool).  Note that we cannot cache intermediate results because later
        # option rules may change the results from the preivous rule.
        for level in dep_levels:
            for dep_name in sorted(level):
                if dep_name not in build_config.external_dep and \
                   dep_name not in build_config.third_party_dirs:
                    dep_uor = uor_map[dep_name]
                    oe.store_option_rules(dep_uor.cap)
                    oe.store_option_rules(dep_uor.defs)

        if (build_config.uplid.os_type == 'windows' and
                build_config.uplid.comp_type == 'cl'):
            # By default, Visual Studio uses a single pdb file for all object
            # files compiled from a particular directory named
            # vc<vs_version>.pdb.  We want to use a separate pdb file for each
            # package group and standard alone package.
            #
            # BDE_CXXFLAGS and BDE_CFLAGS are defined by default.opts, so the
            # code below is a bit hackish.
            pdb_option = ' /Fd%s\\%s.pdb' % (
                os.path.relpath(uor.path, build_config.root_path), uor.name)
            oe.results['BDE_CXXFLAGS'] += pdb_option
            oe.results['BDE_CFLAGS'] += pdb_option

        if uor.type_ == repounits.UnitType.GROUP:
            uor_bc = buildconfig.PackageGroupBuildConfig()
        elif uor.type_ in repounits.UnitTypeCategory.PACKAGE_STAND_ALONE_CAT:
            uor_bc = buildconfig.StdalonePackageBuildConfig()
        else:
            assert(False)

        uor_bc.name = uor.name
        uor_bc.path = uor.path
        uor_bc.doc = uor.doc
        uor_bc.version = uor.version
        uor_bc.dep = uor.dep - build_config.external_dep
        uor_bc.external_dep = uor.dep & build_config.external_dep

        # Store options from dependencies, options for exports, and internal
        # options separately

        dep_oe = copy.deepcopy(oe)
        dep_oe.evaluate()
        oe.store_option_rules(uor.cap)
        oe.store_option_rules(uor.defs)
        set_unit_loc(oe, uor)
        export_oe = copy.deepcopy(oe)
        int_oe = copy.deepcopy(oe)
        export_oe.evaluate()
        if export_oe.results.get('CAPABILITY') == 'NEVER':
            logutil.warn('Skipped non-supported UOR %s' % uor.name)
            return

        int_oe.store_option_rules(uor.opts)

        # Copy unevaluted internal options to be used by packages within
        # package groups.
        int_oe_copy = copy.deepcopy(int_oe)
        if debug_keys:
            logutil.info('--Evaluating %s' % uor.name)
        int_oe.evaluate(debug_keys)

        # Remove export flags of an uor's dependencies from its own export
        # flags.  This implementation is not very optimal, but it's gets the
        # job done.
        dep_flags = get_build_flags_from_opts(build_flags_parser,
                                              dep_oe.results, dep_oe.results)

        uor_bc.flags = get_build_flags_from_opts(
            build_flags_parser, int_oe.results, export_oe.results,
            dep_flags.export_flags, dep_flags.export_libs)

        if uor.type_ == repounits.UnitType.GROUP:
            load_package_group(uor, uor_bc, int_oe_copy)
        elif uor.type_ in repounits.UnitTypeCategory.PACKAGE_STAND_ALONE_CAT:
            load_sa_package(uor, uor_bc)
        else:
            assert(False)

    def load_sa_package(package, package_bc):
        package_bc.components = package.components
        package_bc.type_ = package.type_
        package_bc.has_dums = package.has_dums
        package_bc.app_main = package.app_main
        build_config.stdalone_packages[package_bc.name] = package_bc

    def load_package_group(group, group_bc, oe):
        skipped_packages = set()
        for package_name in group.mem:
            is_skipped = not load_normal_package(package_name, oe)
            if is_skipped:
                skipped_packages.add(package_name)

        group_bc.mem = group.mem - skipped_packages
        build_config.package_groups[group_bc.name] = group_bc

    def load_normal_package(package_name, oe):
        package = repo_context.units[package_name]
        int_oe = copy.deepcopy(oe)
        int_oe.store_option_rules(package.opts)
        int_oe.store_option_rules(package.cap)
        set_unit_loc(int_oe, package)

        if debug_keys:
            logutil.info('--Evaluating %s' % package_name)
        int_oe.evaluate(debug_keys)

        if int_oe.results.get('CAPABILITY') == 'NEVER':
            logutil.warn('Skipped non-supported package %s' % package_name)
            return False

        if package.type_ == repounits.PackageType.PACKAGE_PLUS:
            package_bc = buildconfig.PlusPackageBuildConfig()
        else:
            package_bc = buildconfig.InnerPackageBuildConfig()

        package_bc.name = package.name
        package_bc.path = package.path
        package_bc.dep = package.dep
        package_bc.type_ = package.type_
        package_bc.flags = get_build_flags_from_opts(build_flags_parser,
                                                     int_oe.results)
        package_bc.has_dums = package.has_dums

        if package.type_ == repounits.PackageType.PACKAGE_PLUS:
            package_bc.headers = package.pt_extras.headers
            package_bc.cpp_sources = package.pt_extras.cpp_sources
            package_bc.cpp_tests = package.pt_extras.cpp_tests
            package_bc.c_tests = package.pt_extras.c_tests
        else:
            package_bc.components = package.components

        build_config.inner_packages[package_name] = package_bc
        return True

    for unit in repo_context.units.values():
        if (unit.type_ in repounits.UnitTypeCategory.UOR_CAT and
                unit.type_ != repounits.UnitType.THIRD_PARTY_DIR):
            load_uor(unit)

    # Sometimes we want to override the default SONAME used for a shared
    # object.  This can be done by setting a environment variable.
    # E.g., we can set 'BDE_BSL_SONAME' to 'robo20150101bsl' to set the
    # SONAME of the shared object built for the package group 'bsl'.

    for name in uor_map:
        soname = os.environ.get('BDE_%s_SONAME' % name.upper())
        if soname:
            build_config.soname_overrides[name] = soname

    return build_config
def make_build_config(repo_context,
                      build_flags_parser,
                      uplid,
                      ufid,
                      default_rules,
                      debug_keys=[]):
    """Create a build configuration for repository.

    Args:
        repo_context (RepoContext): Repository structure and metadata.
        build_flags_parser (BuildFlagsParser): Parser for build flags.
        uplid (Uplid): Build platform id.
        ufid (Ufid): Build flags id.
        default_rules (list of OptionRule): Option rules that is the base of
            all UORs.
        debug_keys (list of str): Print some debug information for some
            option keys.
    """

    build_config = buildconfig.BuildConfig(repo_context.root_path, uplid, ufid)

    for unit in repo_context.units.values():
        if unit.type_ == repounits.UnitType.THIRD_PARTY_DIR:
            build_config.third_party_dirs[unit.name] = unit

    uor_dep_graph = repocontextutil.get_uor_digraph(repo_context)
    uor_map = repocontextutil.get_uor_map(repo_context)

    build_config.external_dep = graphutil.find_external_nodes(uor_dep_graph)

    # BDE_CXXINCLUDES is hard coded in bde_build
    initial_options = {'BDE_CXXINCLUDES': '$(BDE_CXXINCLUDE)'}

    # Waf already knows about the flags necessary for building shared objects,
    # so don't get the necessary flags from opts files.  We don't have to the
    # operation below once we remove the the option rules for 'shr' in the
    # default option files.

    effective_ufid = copy.deepcopy(build_config.ufid)
    effective_ufid.flags.discard('shr')
    def_oe = optionsevaluator.OptionsEvaluator(build_config.uplid,
                                               effective_ufid, initial_options)

    def_oe.store_option_rules(default_rules, debug_keys)

    def_oe_copy = copy.deepcopy(def_oe)
    def_oe_copy.evaluate()
    build_config.default_flags = get_build_flags_from_opts(
        build_flags_parser, def_oe_copy.results, def_oe_copy.results)

    # These custom environment variables comes from default_internal.opts and
    # needs to be set when building dpkg.
    env_variables = ('SET_TMPDIR', 'XLC_LIBPATH')
    setenv_re = re.compile(r'^([^=]+)=(.*)$')
    for e in env_variables:
        if e in def_oe_copy.results:
            m = setenv_re.match(def_oe_copy.results[e])
            if m:
                build_config.custom_envs[m.group(1)] = m.group(2)

    def set_unit_loc(oe, unit):
        oe.results['%s_LOCN' % unit.name.upper().replace('+', '_')] = unit.path

    def load_uor(uor):
        # Preserve the existing behavior of loading defs, opts and cap files as
        # bde_build:
        #
        # - Exported options of an UOR: read the defs files of its dependencies
        #   follow by itself. The files of the dependencies should be read in
        #   topological order, if the order of certain dependencies are
        #   ambiguous, order them first by dependency levels, and then by their
        #   name.
        #
        # - Internal options of an UOR: read the defs files in the same way,
        #   followed by its own opts file.

        dep_levels = graphutil.levelize(uor_dep_graph, uor_dep_graph[uor.name])

        oe = copy.deepcopy(def_oe)
        # We load options in levelized order instead of any topological order
        # to preserve the behavior with bde_build (older version of the build
        # tool).  Note that we cannot cache intermediate results because later
        # option rules may change the results from the preivous rule.
        for level in dep_levels:
            for dep_name in sorted(level):
                if dep_name not in build_config.external_dep and \
                   dep_name not in build_config.third_party_dirs:
                    dep_uor = uor_map[dep_name]
                    oe.store_option_rules(dep_uor.cap)
                    oe.store_option_rules(dep_uor.defs)

        if (build_config.uplid.os_type == 'windows'
                and build_config.uplid.comp_type == 'cl'):
            # By default, Visual Studio uses a single pdb file for all object
            # files compiled from a particular directory named
            # vc<vs_version>.pdb.  We want to use a separate pdb file for each
            # package group and standard alone package.
            #
            # BDE_CXXFLAGS and BDE_CFLAGS are defined by default.opts, so the
            # code below is a bit hackish.
            pdb_option = ' /Fd%s\\%s.pdb' % (os.path.relpath(
                uor.path, build_config.root_path), uor.name)
            oe.results['BDE_CXXFLAGS'] += pdb_option
            oe.results['BDE_CFLAGS'] += pdb_option

        if uor.type_ == repounits.UnitType.GROUP:
            uor_bc = buildconfig.PackageGroupBuildConfig()
        elif uor.type_ in repounits.UnitTypeCategory.PACKAGE_STAND_ALONE_CAT:
            uor_bc = buildconfig.StdalonePackageBuildConfig()
        else:
            assert (False)

        uor_bc.name = uor.name
        uor_bc.path = uor.path
        uor_bc.doc = uor.doc
        uor_bc.version = uor.version
        uor_bc.dep = uor.dep - build_config.external_dep
        uor_bc.external_dep = uor.dep & build_config.external_dep

        # Store options from dependencies, options for exports, and internal
        # options separately

        dep_oe = copy.deepcopy(oe)
        dep_oe.evaluate()
        oe.store_option_rules(uor.cap)
        oe.store_option_rules(uor.defs)
        set_unit_loc(oe, uor)
        export_oe = copy.deepcopy(oe)
        int_oe = copy.deepcopy(oe)
        export_oe.evaluate()
        if export_oe.results.get('CAPABILITY') == 'NEVER':
            logutil.warn('Skipped non-supported UOR %s' % uor.name)
            return

        int_oe.store_option_rules(uor.opts)

        # Copy unevaluted internal options to be used by packages within
        # package groups.
        int_oe_copy = copy.deepcopy(int_oe)
        if debug_keys:
            logutil.info('--Evaluating %s' % uor.name)
        int_oe.evaluate(debug_keys)

        # Remove export flags of an uor's dependencies from its own export
        # flags.  This implementation is not very optimal, but it's gets the
        # job done.
        dep_flags = get_build_flags_from_opts(build_flags_parser,
                                              dep_oe.results, dep_oe.results)

        uor_bc.flags = get_build_flags_from_opts(build_flags_parser,
                                                 int_oe.results,
                                                 export_oe.results,
                                                 dep_flags.export_flags,
                                                 dep_flags.export_libs)

        if uor.type_ == repounits.UnitType.GROUP:
            load_package_group(uor, uor_bc, int_oe_copy)
        elif uor.type_ in repounits.UnitTypeCategory.PACKAGE_STAND_ALONE_CAT:
            load_sa_package(uor, uor_bc)
        else:
            assert (False)

    def load_sa_package(package, package_bc):
        package_bc.components = package.components
        package_bc.type_ = package.type_
        package_bc.has_dums = package.has_dums
        package_bc.app_main = package.app_main
        build_config.stdalone_packages[package_bc.name] = package_bc

    def load_package_group(group, group_bc, oe):
        skipped_packages = set()
        for package_name in group.mem:
            is_skipped = not load_normal_package(package_name, oe)
            if is_skipped:
                skipped_packages.add(package_name)

        group_bc.mem = group.mem - skipped_packages
        build_config.package_groups[group_bc.name] = group_bc

    def load_normal_package(package_name, oe):
        package = repo_context.units[package_name]
        int_oe = copy.deepcopy(oe)
        int_oe.store_option_rules(package.opts)
        int_oe.store_option_rules(package.cap)
        set_unit_loc(int_oe, package)

        if debug_keys:
            logutil.info('--Evaluating %s' % package_name)
        int_oe.evaluate(debug_keys)

        if int_oe.results.get('CAPABILITY') == 'NEVER':
            logutil.warn('Skipped non-supported package %s' % package_name)
            return False

        if package.type_ == repounits.PackageType.PACKAGE_PLUS:
            package_bc = buildconfig.PlusPackageBuildConfig()
        else:
            package_bc = buildconfig.InnerPackageBuildConfig()

        package_bc.name = package.name
        package_bc.path = package.path
        package_bc.dep = package.dep
        package_bc.type_ = package.type_
        package_bc.flags = get_build_flags_from_opts(build_flags_parser,
                                                     int_oe.results)
        package_bc.has_dums = package.has_dums

        if package.type_ == repounits.PackageType.PACKAGE_PLUS:
            package_bc.headers = package.pt_extras.headers
            package_bc.cpp_sources = package.pt_extras.cpp_sources
            package_bc.cpp_tests = package.pt_extras.cpp_tests
            package_bc.c_tests = package.pt_extras.c_tests
        else:
            package_bc.components = package.components

        build_config.inner_packages[package_name] = package_bc
        return True

    for unit in repo_context.units.values():
        if (unit.type_ in repounits.UnitTypeCategory.UOR_CAT
                and unit.type_ != repounits.UnitType.THIRD_PARTY_DIR):
            load_uor(unit)

    # Sometimes we want to override the default SONAME used for a shared
    # object.  This can be done by setting a environment variable.
    # E.g., we can set 'BDE_BSL_SONAME' to 'robo20150101bsl' to set the
    # SONAME of the shared object built for the package group 'bsl'.

    for name in uor_map:
        soname = os.environ.get('BDE_%s_SONAME' % name.upper())
        if soname:
            build_config.soname_overrides[name] = soname

    return build_config
Exemple #3
0
 def test_find_external_nodes(self):
     external_nodes = graphutil.find_external_nodes(self.group_dep)
     exp_external_nodes = set(['bsl'])
     self.assertEqual(external_nodes, exp_external_nodes)
 def test_find_external_nodes(self):
     external_nodes = graphutil.find_external_nodes(self.group_dep)
     exp_external_nodes = set(['bsl'])
     self.assertEqual(external_nodes, exp_external_nodes)