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
def verify_uors(self): logutil.start_msg('Verifying UORs') digraph = repocontextutil.get_uor_digraph(self.repo_context) self._verify_cycles_impl(digraph)