def _configure_options(self, uplid): self.uplid = uplid self.option_mask = OptionMask(self.uplid, self.ufid) # Get the path of default.opts. Assume the directory containing this # script is <repo_root>/bin/tools/waf/bde and default.opts is located # in the directory <repo_root>/etc. upd = os.path.dirname bde_root = os.environ.get('BDE_ROOT') repo_root = upd(upd(upd(upd(upd(os.path.realpath(__file__)))))) default_opts_path = os.path.join(repo_root, 'etc', 'default.opts') default_opts_flag = os.path.isfile(default_opts_path) if not default_opts_flag and bde_root: default_opts_path = os.path.join(bde_root, 'etc', 'default.opts') default_opts_flag = os.path.isfile(default_opts_path) if not default_opts_flag: self.ctx.fatal("Can not find default.opts from the /etc directory " "of the waf executable, nor the BDE_ROOT " "environment variable.") raw_options = RawOptions() raw_options.read(default_opts_path) # At BB, default_internal.opts contains some variables that is required # for building bde-bb. if bde_root: default_internal_opts_path = os.path.join(bde_root, 'etc', 'default_internal.opts') raw_options.read(default_internal_opts_path) debug_opt_keys = self.ctx.options.debug_opt_keys if debug_opt_keys: debug_opt_keys = debug_opt_keys.split(',') self.default_opts = Options(self.option_mask) self.default_opts.read(raw_options.options, self.ctx, debug_opt_keys=debug_opt_keys) for g in self.group_dep: self.ctx.start_msg("Evaluating options for '%s'" % g) status_msg = self._evaluate_group_options(g) self.ctx.end_msg(status_msg) tmp_opts = copy.deepcopy(self.default_opts) tmp_opts.evaluate() env_variables = ('SET_TMPDIR', 'XLC_LIBPATH') setenv_re = re.compile(r'^([^=]+)=(.*)$') for e in env_variables: if e in tmp_opts.options: m = setenv_re.match(tmp_opts.options[e]) self.custom_envs[m.group(1)] = m.group(2)
def configure_options(self, uplid): self.uplid = uplid self.option_mask = OptionMask(self.uplid, self.ufid) default_opts_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'default.opts') raw_options = RawOptions() raw_options.read(default_opts_path) # At BB, default_internal.opts contains some variables that is required for building bde-bb. bde_root = os.environ.get('BDE_ROOT') if bde_root: default_internal_opts_path = os.path.join(bde_root, 'etc', 'default_internal.opts') raw_options.read(default_internal_opts_path) debug_opt_keys = self.ctx.options.debug_opt_keys if debug_opt_keys: debug_opt_keys = debug_opt_keys.split(',') self.default_opts = Options(self.option_mask) self.default_opts.read(raw_options.options, self.ctx, debug_opt_keys=debug_opt_keys) for g in self.group_dep: self.ctx.start_msg("Evaluating options for '%s'" % g) status_msg = self._evaluate_group_options(g) self.ctx.end_msg(status_msg) tmp_opts = copy.deepcopy(self.default_opts) tmp_opts.evaluate() env_variables = ('SET_TMPDIR', 'XLC_LIBPATH') setenv_re = re.compile(r'^([^=]+)=(.*)$') for e in env_variables: if e in tmp_opts.options: m = setenv_re.match(tmp_opts.options[e]) self.custom_envs[m.group(1)] = m.group(2)
def configure_options(self, uplid): self.uplid = uplid self.option_mask = OptionMask(self.uplid, self.ufid) default_opts_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'default.opts') raw_options = RawOptions() raw_options.read(default_opts_path) debug_opt_keys = self.ctx.options.debug_opt_keys if debug_opt_keys: debug_opt_keys = debug_opt_keys.split(',') self.default_opts = Options(self.option_mask) self.default_opts.read(raw_options.options, self.ctx, debug_opt_keys=debug_opt_keys) for g in self.group_dep: self.ctx.start_msg("Evaluating options for '%s'" % g) self._evaluate_group_options(g) self.ctx.end_msg('ok')
class BdeWafConfigure(object): def __init__(self, ctx): self.ctx = ctx self.external_libs = set() self.export_groups = [] self.group_dep = {} self.group_mem = {} self.group_defs = {} self.group_opts = {} self.group_doc = {} self.package_dep = {} self.package_mem = {} self.package_pub = {} self.package_opts = {} self.sl_package_deps = {} self.sl_package_locations = {} self.group_options = {} self.group_export_options = {} self.package_options = {} REMOVE_COMMENT_RE = re.compile(r'^([^#]*)(#.*)?$') @staticmethod def _get_meta(node, metadir, metatype): metafile = node.make_node([metadir, node.name + '.' + metatype]) entries = [] txt = metafile.read() for line in txt.splitlines(): entries.extend(BdeWafConfigure.REMOVE_COMMENT_RE.match(line).group(1).split()) return entries def _get_raw_options(self, node, metadir, metatype): metafile = node.make_node([metadir, node.name + '.' + metatype]) raw_options = RawOptions() raw_options.read(metafile.abspath()) return raw_options.options def _parse_group_doc(self, group_node): ''' parse the doc of a package group and return (name, description) to be used in the .pc file ''' name = group_node.name doc_node = group_node.make_node(['doc', name + '.txt']) try: doc = Utils.readf(doc_node.abspath()) purpose = None mnemonic = None for line in doc.split('\n'): if line.startswith('@PURPOSE'): purpose = line.split(':')[1].strip() elif line.startswith('@MNEMONIC'): mnemonic = line.split(':')[1].strip() if purpose and mnemonic: return (mnemonic, purpose) except: pass return (name, 'N/A') def _load_metadata(self): group_nodes = [x.parent.parent for x in self.ctx.path.ant_glob('groups/*/group/*.mem')] for g in group_nodes: self.group_dep[g.name] = self._get_meta(g, 'group', 'dep') self.group_mem[g.name] = self._get_meta(g, 'group', 'mem') self.group_defs[g.name] = self._get_raw_options(g, 'group', 'defs') self.group_opts[g.name] = self._get_raw_options(g, 'group', 'opts') self.group_doc[g.name] = self._parse_group_doc(g) if g.name + 'scm' in g.listdir(): self.export_groups.append(g.name) for g in self.group_dep: for dep in self.group_dep[g]: if dep not in self.group_dep: self.external_libs.add(dep) for group_node in group_nodes: for package_name in self.group_mem[group_node.name]: package_node = group_node.make_node(package_name) self.package_dep[package_name] = self._get_meta(package_node, 'package', 'dep') self.package_mem[package_name] = self._get_meta(package_node, 'package', 'mem') self.package_opts[package_name] = self._get_raw_options(package_node, 'package', 'opts') # only header-only packages typically have 'pub' files try: self.package_pub[package_name] = self._get_meta(package_node, 'package', 'pub') except: pass def _levelize_group_dependencies(self, group): from collections import defaultdict level_map = defaultdict(set) def _levelize_groups_impl(group): if not group in self.group_dep or not self.group_dep[group]: level_map[1].add(group) return 1 children = self.group_dep[group] level = 1 + max(_levelize_groups_impl(child) for child in self.group_dep[group]) level_map[level].add(group) return level map(lambda x: _levelize_groups_impl(x), self.group_dep[group]) levels = [] for level in sorted(level_map.keys()): levels.append(level_map[level]) return levels def _evaluate_group_options(self, group): # %s_LOCN and BDE_CXXINCLUDES are hard coded in bde_build.pl defs = copy.deepcopy(self.default_opts) group_node = self.ctx.path.make_node(['groups', group]) defs.options['%s_LOCN' % group.upper()] = group_node.abspath() levels = self._levelize_group_dependencies(group) for level in levels: for group_dependency in sorted(level): if not group_dependency in self.external_libs: defs.read(self.group_defs[group_dependency], self.ctx) defs.read(self.group_defs[group], self.ctx) opts = copy.deepcopy(defs) opts.read(self.group_opts[group], self.ctx) defs.evaluate() self.group_export_options[group] = defs.options for package in self.group_mem[group]: p_opts = copy.deepcopy(opts) package_node = group_node.make_node(package) # hacks to make bst+apache work. bst+apache's opts file references the _LOCN variable. p_opts.options['%s_LOCN' % package.upper()] = package_node.abspath() # from bde_build.pl 'BDE_CXXINCLUDES = $(SWITCHCHAR)I. $(BDE_CXXINCLUDE) $(PKG_INCLUDES) $(GRP_INCLUDES)' p_opts.options['BDE_CXXINCLUDES'] = '$(BDE_CXXINCLUDE)' p_opts.read(self.package_opts[package], self.ctx) p_opts.evaluate() self.package_options[package] = p_opts.options opts.evaluate() self.group_options[group] = opts.options def load_metadata(self): self.ctx.start_msg('Loading BDE metadata') self._load_metadata() self.ctx.end_msg('ok') def configure_external_libs(self, ufid): self.ufid = copy.deepcopy(ufid) pkgconfig_args = [ '--libs', '--cflags' ] shared_flag = 'shr' in self.ufid.ufid if shared_flag: self.ufid.ufid.remove('shr') self.libtype_features = ['cxxshlib'] else: pkgconfig_args.append('--static') self.libtype_features = ['cxxstlib'] # If the static build is chosen (the default), waf assumes that all libraries queried from pkg-config are to be # built statically, which is not true for some libraries. We work around this issue by manually changing the # affected libraries to be linked dynamically instead. dl_overrides = set(['pthread', 'rt']) for lib in self.external_libs: self.ctx.check_cfg(package = lib, args = pkgconfig_args, errmsg = "Make sure the path indicated by environment variable 'PKG_CONFIG_PATH' contains '%s.pc'" % lib) sl_key = ('stlib_' + lib).upper() dl_key = ('lib_' + lib).upper() sl_set = set(self.ctx.env[sl_key]) self.ctx.env[sl_key] = list(sl_set - dl_overrides) # dl_set = set(self.ctx.env[dl_key]) self.ctx.env[dl_key] = list(sl_set & dl_overrides) # check_cfg always stores the libpath as dynamic library path instead of static even if the configuration # option is set to static. if not shared_flag: slp_key = ('stlibpath_' + lib).upper() dlp_key = ('libpath_' + lib).upper() if dlp_key in self.ctx.env: self.ctx.env[slp_key] = self.ctx.env[dlp_key] del self.ctx.env[dlp_key] def configure_options(self, uplid): self.uplid = uplid self.option_mask = OptionMask(self.uplid, self.ufid) default_opts_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'default.opts') raw_options = RawOptions() raw_options.read(default_opts_path) debug_opt_keys = self.ctx.options.debug_opt_keys if debug_opt_keys: debug_opt_keys = debug_opt_keys.split(',') self.default_opts = Options(self.option_mask) self.default_opts.read(raw_options.options, self.ctx, debug_opt_keys=debug_opt_keys) for g in self.group_dep: self.ctx.start_msg("Evaluating options for '%s'" % g) self._evaluate_group_options(g) self.ctx.end_msg('ok') def _get_libs(self, ldflags): libs = [] flags = [] expression = re.compile(self.ctx.env['LIB_ST'].replace('%s', r'([^ =]+)')) # import pdb; pdb.set_trace() for flag in ldflags: m = expression.match(flag) if m: lib = m.group(1) if not lib in libs: libs.append(m.group(1)) else: flags.append(flag) return (libs, flags) def _get_export_cxxflags(self, cxxflags): "only defines is required to be in export flags" export_flags = [] for flag in cxxflags: st = flag[:2] if st == '-D' or (self.ctx.env.CXX_NAME == 'msvc' and st == '/D'): export_flags.append(flag) return export_flags def _save_group_options(self, group): export_options = self.group_export_options[group] options = self.group_options[group] # First value in the list is the compiler, and so we ignore it to just take the parameters. linkflags = options['CXXLINK'].split()[1:] (libs, flags) = self._get_libs(options['COMPONENT_BDEBUILD_LDFLAGS'].split()) linkflags.extend(flags) self.ctx.env[group + '_export_libs'] = libs self.ctx.env[group + '_export_cxxflags'] = self._get_export_cxxflags(export_options['COMPONENT_BDEBUILD_CXXFLAGS'].split()) self.ctx.env[group + '_libs'] = libs self.ctx.env[group + '_linkflags'] = linkflags def _save_package_options(self, package): options = self.package_options[package] # First value in the list is the compiler, and so we ignore it to just take the parameters. cxxflags = options['CXX'].split()[1:] cflags = options['CC'].split()[1:] linkflags = options['CXXLINK'].split()[1:] (libs, flags) = self._get_libs(options['COMPONENT_BDEBUILD_LDFLAGS'].split()) linkflags.extend(flags) self.ctx.env[package + '_cxxflags'] = cxxflags + options['COMPONENT_BDEBUILD_CXXFLAGS'].split() self.ctx.env[package + '_cflags'] = cflags + options['COMPONENT_BDEBUILD_CFLAGS'].split() self.ctx.env[package + '_libs'] = libs self.ctx.env[package + '_linkflags'] = linkflags def save(self): self.ctx.start_msg('Saving configuration') self.ctx.env['ufid'] = self.option_mask.ufid.ufid self.ctx.env['external_libs'] = self.external_libs self.ctx.env['export_groups'] = self.export_groups self.ctx.env['group_dep'] = self.group_dep self.ctx.env['group_mem'] = self.group_mem self.ctx.env['group_doc'] = self.group_doc self.ctx.env['package_dep'] = self.package_dep self.ctx.env['package_mem'] = self.package_mem self.ctx.env['package_pub'] = self.package_pub self.ctx.env['libtype_features'] = self.libtype_features self.ctx.env['prefix'] = self.ctx.options.prefix for g in self.group_dep: self._save_group_options(g) for p in self.package_dep: self._save_package_options(p) self.ctx.end_msg('ok')
class BdeWafConfigure(object): def __init__(self, ctx): self.ctx = ctx self.external_libs = set() self.export_groups = [] self.group_dep = {} self.group_mem = {} self.group_defs = {} self.group_opts = {} self.group_doc = {} self.group_cap = {} # Stores the subdirectory under which the stand-alone package is stored # e.g. { 'a_comdb2': 'adapters' } = package 'a_comdb2' is stored under 'adapters' # meta-data of stand-alone packages are stored with package groups self.sa_package_locs = {} # Stores the subdirectory under which the package group is stored. Almost all package groups currently reside # under 'groups', except for 'e_ipc', which resides under 'enterprise'. self.group_locs = {} self.package_dep = {} self.package_mem = {} self.package_pub = {} self.package_opts = {} self.package_cap = {} self.package_dums = [] self.unsupported_groups = set() self.unsupported_packages = set() self.group_options = {} self.group_export_options = {} self.package_options = {} self.custom_envs = {} REMOVE_COMMENT_RE = re.compile(r'^([^#]*)(#.*)?$') @staticmethod def _get_meta(node, metadir, metatype): metafile = node.make_node([metadir, node.name + '.' + metatype]) entries = [] txt = metafile.read() for line in txt.splitlines(): entries.extend(BdeWafConfigure.REMOVE_COMMENT_RE.match(line).group(1).split()) return entries def _get_raw_options(self, node, metadir, metatype): metafile = node.make_node([metadir, node.name + '.' + metatype]) raw_options = RawOptions() raw_options.read(metafile.abspath()) return raw_options.options def _parse_group_doc(self, group_node): ''' parse the doc of a package group and return (name, description) to be used in the .pc file ''' name = group_node.name doc_node = group_node.make_node(['doc', name + '.txt']) try: doc = Utils.readf(doc_node.abspath()) purpose = None mnemonic = None for line in doc.split('\n'): if line.startswith('@PURPOSE'): purpose = line.split(':')[1].strip() elif line.startswith('@MNEMONIC'): mnemonic = line.split(':')[1].strip() if purpose and mnemonic: return (mnemonic, purpose) except: pass return (name, 'N/A') def _load_metadata(self): groups_nodes = [x.parent.parent for x in self.ctx.path.ant_glob('groups/*/group/*.mem')] enterprise_nodes = [x.parent.parent for x in self.ctx.path.ant_glob('enterprise/*/group/*.mem')] group_nodes = groups_nodes + enterprise_nodes for g in group_nodes: self.group_dep[g.name] = self._get_meta(g, 'group', 'dep') self.group_mem[g.name] = self._get_meta(g, 'group', 'mem') self.group_defs[g.name] = self._get_raw_options(g, 'group', 'defs') self.group_opts[g.name] = self._get_raw_options(g, 'group', 'opts') self.group_cap[g.name] = self._get_raw_options(g, 'group', 'cap') self.group_doc[g.name] = self._parse_group_doc(g) if g.name + 'scm' in g.listdir(): self.export_groups.append(g.name) self.group_locs[g.name] = g.parent.name # stand-alone packages behaves like pakcage groups with a single package adapter_nodes = [x.parent.parent for x in self.ctx.path.ant_glob('adapters/*/package/*.mem')] sa_package_nodes = adapter_nodes for s in sa_package_nodes: self.group_dep[s.name] = self._get_meta(s, 'package', 'dep') self.group_mem[s.name] = self._get_meta(s, 'package', 'mem') self.group_defs[s.name] = self._get_raw_options(s, 'package', 'defs') self.group_opts[s.name] = self._get_raw_options(s, 'package', 'opts') self.group_cap[s.name] = self._get_raw_options(s, 'package', 'cap') self.group_doc[s.name] = self._parse_group_doc(s) dums_file = s.make_node('package').find_node(s.name + '.dums') if dums_file: self.package_dums.append(s.name) self.export_groups.append(s.name) self.sa_package_locs[s.name] = s.parent.name # assume that std-alone packages are not headers only and do not have 'pub' files. for g in self.group_dep: for dep in self.group_dep[g]: if dep not in self.group_dep: self.external_libs.add(dep) for group_node in group_nodes: for package_name in self.group_mem[group_node.name]: package_node = group_node.make_node(package_name) self.package_dep[package_name] = self._get_meta(package_node, 'package', 'dep') self.package_mem[package_name] = self._get_meta(package_node, 'package', 'mem') self.package_opts[package_name] = self._get_raw_options(package_node, 'package', 'opts') self.package_cap[package_name] = self._get_raw_options(package_node, 'package', 'cap') # only header-only packages typically have 'pub' files try: self.package_pub[package_name] = self._get_meta(package_node, 'package', 'pub') except: pass dums_file = package_node.make_node('package').find_node(package_node.name + '.dums') if dums_file: self.package_dums.append(package_node.name) def configure(self, uplid, ufid): self.ctx.msg('os_type', uplid.uplid['os_type']) self.ctx.msg('os_name', uplid.uplid['os_name']) self.ctx.msg('cpu_type', uplid.uplid['cpu_type']) self.ctx.msg('os_ver', uplid.uplid['os_ver']) self.ctx.msg('comp_type', uplid.uplid['comp_type']) self.ctx.msg('comp_ver', uplid.uplid['comp_ver']) self.ctx.msg('uplid', uplid) self.ctx.msg('ufid', '_'.join(sorted(list(ufid.ufid)))) self.ctx.msg('prefix', self.ctx.options.prefix) self.load_metadata() self.configure_external_libs(ufid) self.configure_options(uplid) self.save() def _levelize_group_dependencies(self, group): from collections import defaultdict level_map = defaultdict(set) def _levelize_groups_impl(group): if not group in self.group_dep or not self.group_dep[group]: level_map[1].add(group) return 1 children = self.group_dep[group] level = 1 + max(_levelize_groups_impl(child) for child in self.group_dep[group]) level_map[level].add(group) return level map(lambda x: _levelize_groups_impl(x), self.group_dep[group]) levels = [] for level in sorted(level_map.keys()): levels.append(level_map[level]) return levels def _evaluate_group_options(self, group): # %s_LOCN and BDE_CXXINCLUDES are hard coded in bde_build.pl defs = copy.deepcopy(self.default_opts) group_node = self.ctx.path.make_node(['groups', group]) defs.options['%s_LOCN' % group.upper()] = group_node.abspath() levels = self._levelize_group_dependencies(group) for level in levels: for group_dependency in sorted(level): if not group_dependency in self.external_libs: defs.read(self.group_defs[group_dependency], self.ctx) defs.read(self.group_cap[group_dependency], self.ctx) defs.read(self.group_defs[group], self.ctx) defs.read(self.group_cap[group], self.ctx) opts = copy.deepcopy(defs) opts.read(self.group_opts[group], self.ctx) defs.evaluate() if defs.options.get('CAPABILITY') == 'NEVER': self.unsupported_groups.add(group) if not group in self.sa_package_locs: self.unsupported_packages |= set(self.group_mem[group]) return 'skipped (unsupported)' self.group_export_options[group] = defs.options unsupported_packages = set() if not group in self.sa_package_locs: for package in self.group_mem[group]: p_opts = copy.deepcopy(opts) package_node = group_node.make_node(package) # hacks to make bst+apache work. bst+apache's opts file references the _LOCN variable. p_opts.options['%s_LOCN' % package.upper().replace('+', '_')] = package_node.abspath() # from bde_build.pl 'BDE_CXXINCLUDES = $(SWITCHCHAR)I. $(BDE_CXXINCLUDE) $(PKG_INCLUDES) $(GRP_INCLUDES)' p_opts.options['BDE_CXXINCLUDES'] = '$(BDE_CXXINCLUDE)' p_opts.read(self.package_opts[package], self.ctx) # Ideally, we should also read the capability files of the packages on which this depends, but since # bde_build.pl doesn't do this, we don't need to do it for now. p_opts.read(self.package_cap[package], self.ctx) p_opts.evaluate() if p_opts.options.get('CAPABILITY') == 'NEVER': unsupported_packages.add(package) else: self.package_options[package] = p_opts.options # from bde_build.pl 'BDE_CXXINCLUDES = $(SWITCHCHAR)I. $(BDE_CXXINCLUDE) $(PKG_INCLUDES) $(GRP_INCLUDES)' opts.options['BDE_CXXINCLUDES'] = '$(BDE_CXXINCLUDE)' opts.evaluate() self.group_options[group] = opts.options if unsupported_packages: self.unsupported_packages |= unsupported_packages return 'ok, with some skipped (%s)' % ','.join(unsupported_packages) return 'ok' def load_metadata(self): self.ctx.start_msg('Loading BDE metadata') self._load_metadata() self.ctx.end_msg('ok') def configure_external_libs(self, ufid): self.ufid = copy.deepcopy(ufid) pkgconfig_args = [ '--libs', '--cflags' ] shared_flag = 'shr' in self.ufid.ufid if shared_flag: self.ufid.ufid.remove('shr') self.libtype_features = ['cxxshlib'] else: pkgconfig_args.append('--static') self.libtype_features = ['cxxstlib'] # If the static build is chosen (the default), waf assumes that all libraries queried from pkg-config are to be # built statically, which is not true for some libraries. We work around this issue by manually changing the # affected libraries to be linked dynamically instead. dl_overrides = ['pthread', 'rt', 'nsl', 'socket'] for lib in self.external_libs: self.ctx.check_cfg(package = lib, args = pkgconfig_args, errmsg = "Make sure the path indicated by environment variable 'PKG_CONFIG_PATH' contains '%s.pc'" % lib) sl_key = ('stlib_' + lib).upper() dl_key = ('lib_' + lib).upper() # preserve the order of libraries for l in dl_overrides: if l in self.ctx.env[sl_key]: if dl_key not in self.ctx.env: self.ctx.env[dl_key] = [] self.ctx.env[sl_key].remove(l) self.ctx.env[dl_key].append(l) # check_cfg always stores the libpath as dynamic library path instead of static even if the configuration # option is set to static. if not shared_flag: slp_key = ('stlibpath_' + lib).upper() dlp_key = ('libpath_' + lib).upper() if dlp_key in self.ctx.env: self.ctx.env[slp_key] = self.ctx.env[dlp_key] del self.ctx.env[dlp_key] def configure_options(self, uplid): self.uplid = uplid self.option_mask = OptionMask(self.uplid, self.ufid) default_opts_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'default.opts') raw_options = RawOptions() raw_options.read(default_opts_path) # At BB, default_internal.opts contains some variables that is required for building bde-bb. bde_root = os.environ.get('BDE_ROOT') if bde_root: default_internal_opts_path = os.path.join(bde_root, 'etc', 'default_internal.opts') raw_options.read(default_internal_opts_path) debug_opt_keys = self.ctx.options.debug_opt_keys if debug_opt_keys: debug_opt_keys = debug_opt_keys.split(',') self.default_opts = Options(self.option_mask) self.default_opts.read(raw_options.options, self.ctx, debug_opt_keys=debug_opt_keys) for g in self.group_dep: self.ctx.start_msg("Evaluating options for '%s'" % g) status_msg = self._evaluate_group_options(g) self.ctx.end_msg(status_msg) tmp_opts = copy.deepcopy(self.default_opts) tmp_opts.evaluate() env_variables = ('SET_TMPDIR', 'XLC_LIBPATH') setenv_re = re.compile(r'^([^=]+)=(.*)$') for e in env_variables: if e in tmp_opts.options: m = setenv_re.match(tmp_opts.options[e]) self.custom_envs[m.group(1)] = m.group(2) def _parse_ldflags(self, ldflags): """ parse the linker flags into the following components: stlib, libs, libpaths, flags """ stlibs = [] libs = [] libpaths = [] flags = [] shlib_marker = self.ctx.env['SHLIB_MARKER'] stlib_marker = self.ctx.env['STLIB_MARKER'] libs_exp = re.compile(self.ctx.env['LIB_ST'].replace('%s', r'([^ =]+)')) libpath_exp = re.compile(self.ctx.env['LIBPATH_ST'].replace('%s', r'([^ =]+)')) # default to shlibs isshlib_flag = True for flag in ldflags: if flag == shlib_marker: isshlib_flag = True continue if flag == stlib_marker: isshlib_flag = False continue m = libpath_exp.match(flag) if m: libpaths.append(m.group(1)) continue m = libs_exp.match(flag) if m: lib = m.group(1) if isshlib_flag: libs.append(lib) else: stlibs.append(lib) continue flags.append(flag) return (stlibs, libs, libpaths, flags) def _parse_cflags(self, cflags): includes = [] flags = [] inc_exp = re.compile(self.ctx.env['CPPPATH_ST'].replace('%s', r'([^ =]+)')) for flag in cflags: m = inc_exp.match(flag) if m: lib = m.group(1) includes.append(m.group(1)) continue flags.append(flag) return (includes, flags) def _get_export_cxxflags(self, cxxflags): "only defines is required to be in export flags" export_flags = [] for flag in cxxflags: st = flag[:2] if st == '-D' or (self.ctx.env.CXX_NAME == 'msvc' and st == '/D'): export_flags.append(flag) return export_flags def _save_group_options(self, group): export_options = self.group_export_options[group] options = self.group_options[group] # First value in the list is the compiler or linker, and so we ignore it to just take the parameters. (stlibs, libs, libpaths, linkflags) = self._parse_ldflags(options['CXXLINK'].split()[1:] + options['COMPONENT_BDEBUILD_LDFLAGS'].split()) self.ctx.env[group + '_export_libs'] = libs self.ctx.env[group + '_export_cxxflags'] = self._get_export_cxxflags(export_options['COMPONENT_BDEBUILD_CXXFLAGS'].split()) self.ctx.env[group + '_libs'] = libs self.ctx.env[group + '_stlibs'] = stlibs self.ctx.env[group + '_libpaths'] = libpaths self.ctx.env[group + '_linkflags'] = linkflags if group in self.sa_package_locs: (cxxincludes, cxxflags) = self._parse_cflags(options['CXX'].split()[1:] + options['COMPONENT_BDEBUILD_CXXFLAGS'].split()) (cincludes, cflags) = self._parse_cflags(options['CC'].split()[1:] + options['COMPONENT_BDEBUILD_CXXFLAGS'].split()) self.ctx.env[group + '_cxxflags'] = cxxflags self.ctx.env[group + '_cxxincludes'] = cxxincludes self.ctx.env[group + '_cflags'] = cflags self.ctx.env[group + '_cincludes'] = cincludes def _save_package_options(self, package): options = self.package_options[package] (stlibs, libs, libpaths, linkflags) = self._parse_ldflags(options['CXXLINK'].split()[1:] + options['COMPONENT_BDEBUILD_LDFLAGS'].split()) (cxxincludes, cxxflags) = self._parse_cflags(options['CXX'].split()[1:] + options['COMPONENT_BDEBUILD_CXXFLAGS'].split()) (cincludes, cflags) = self._parse_cflags(options['CC'].split()[1:] + options['COMPONENT_BDEBUILD_CFLAGS'].split()) self.ctx.env[package + '_cxxflags'] = cxxflags self.ctx.env[package + '_cxxincludes'] = cxxincludes self.ctx.env[package + '_cflags'] = cflags self.ctx.env[package + '_cincludes'] = cincludes self.ctx.env[package + '_libs'] = libs self.ctx.env[package + '_stlibs'] = stlibs self.ctx.env[package + '_libpaths'] = libpaths self.ctx.env[package + '_linkflags'] = linkflags def save(self): self.ctx.start_msg('Saving configuration') self.ctx.env['ufid'] = self.option_mask.ufid.ufid # For visual studio, waf explicitly includes the system header files by setting the 'INCLUD' # variable. BSL_OVERRIDE_STD mode requires that the system header files, which contains the standard library, be # overridden with custom versions in bsl, so we workaround the issue by moving the system includes to # 'INCLUDE_BSL' if it exists. This solution is not perfect, because it doesn't support package groups that # doesn't depend on bsl -- this is not a problem for BDE libraries. if self.option_mask.uplid.uplid['os_type'] == 'windows' and 'INCLUDES_BSL' in self.ctx.env: self.ctx.env['INCLUDES_BSL'].extend(self.ctx.env['INCLUDES']) # assuming that 'INCLUDES' containly system # headers only del self.ctx.env['INCLUDES'] # ar on aix only processes 32-bit object files by default if '64' in self.option_mask.ufid.ufid and self.option_mask.uplid.uplid['comp_type'] == 'xlc': self.ctx.env['ARFLAGS'] = ['-rcs', '-X64'] # Remove unsupported package groups and packages. We don't need to do dependency analysis because the # unsupported sets already contain all transitively unsupported nodes. for g in self.unsupported_groups: if g in self.export_groups: self.export_groups.remove(g) self.group_dep.pop(g, None) self.group_mem.pop(g, None) self.group_doc.pop(g, None) self.sa_package_locs.pop(g, None) self.group_locs.pop(g, None) for p in self.unsupported_packages: self.package_dep.pop(p, None) self.package_mem.pop(p, None) self.package_pub.pop(p, None) for g in self.group_mem: self.group_mem[g] = list(set(self.group_mem[g]) - self.unsupported_packages) self.ctx.env['external_libs'] = self.external_libs self.ctx.env['export_groups'] = self.export_groups self.ctx.env['group_dep'] = self.group_dep self.ctx.env['group_mem'] = self.group_mem self.ctx.env['group_doc'] = self.group_doc self.ctx.env['sa_package_locs'] = self.sa_package_locs self.ctx.env['group_locs'] = self.group_locs self.ctx.env['package_dep'] = self.package_dep self.ctx.env['package_mem'] = self.package_mem self.ctx.env['package_pub'] = self.package_pub self.ctx.env['package_dums'] = self.package_dums self.ctx.env['libtype_features'] = self.libtype_features self.ctx.env['prefix'] = self.ctx.options.prefix self.ctx.env['custom_envs'] = self.custom_envs for g in self.group_dep: self._save_group_options(g) for p in self.package_dep: self._save_package_options(p) self.ctx.end_msg('ok')
class BdeWafConfigure(object): def __init__(self, ctx): self.ctx = ctx self.external_libs = set() self.export_groups = [] self.group_dep = {} self.group_mem = {} self.group_defs = {} self.group_opts = {} self.group_doc = {} self.group_cap = {} self.group_ver = {} # Stores the subdirectory under which the stand-alone package is stored # e.g. { 'a_comdb2': 'adapters' } = package 'a_comdb2' is stored under # 'adapters' meta-data of stand-alone packages are stored with package # groups self.sa_package_locs = {} self.soname_override = {} # Stores the subdirectory under which the package group is stored. # Almost all package groups currently reside under the 'groups' # directory, with a few exceptions such as 'e_ipc', which resides under # the 'enterprise' directory. self.group_locs = {} self.package_dep = {} self.package_mem = {} self.package_pub = {} self.package_opts = {} self.package_cap = {} self.package_dums = [] self.component_type = {} # c or cpp self.package_type = {} # c or cpp self.unsupported_groups = set() self.unsupported_packages = set() self.group_options = {} self.group_export_options = {} self.package_options = {} self.custom_envs = {} self.lib_suffix = self.ctx.options.lib_suffix self.pc_extra_include_dirs = [] def configure(self, uplid, ufid): self.ctx.msg('os_type', uplid.uplid['os_type']) self.ctx.msg('os_name', uplid.uplid['os_name']) self.ctx.msg('cpu_type', uplid.uplid['cpu_type']) self.ctx.msg('os_ver', uplid.uplid['os_ver']) self.ctx.msg('comp_type', uplid.uplid['comp_type']) self.ctx.msg('comp_ver', uplid.uplid['comp_ver']) self.ctx.msg('uplid', uplid) self.ctx.msg('ufid', ufid) self.ctx.msg('prefix', self.ctx.options.prefix) self._load_metadata() self._configure_external_libs(ufid) self._configure_options(uplid) self._save() REMOVE_COMMENT_RE = re.compile(r'^([^#]*)(#.*)?$') @staticmethod def _get_meta(node, metadir, metatype): metafile = node.make_node([metadir, node.name + '.' + metatype]) entries = [] txt = metafile.read() for line in txt.splitlines(): entries.extend( BdeWafConfigure.REMOVE_COMMENT_RE.match(line).group(1).split()) return entries def _get_raw_options(self, node, metadir, metatype): metafile = node.make_node([metadir, node.name + '.' + metatype]) raw_options = RawOptions() raw_options.read(metafile.abspath()) return raw_options.options def _parse_group_doc(self, group_node): ''' parse the doc of a package group and return (name, description) to be used in the .pc file ''' name = group_node.name doc_node = group_node.make_node(['doc', name + '.txt']) try: doc = Utils.readf(doc_node.abspath()) purpose = None mnemonic = None for line in doc.split('\n'): if line.startswith('@PURPOSE'): purpose = line.split(':')[1].strip() elif line.startswith('@MNEMONIC'): mnemonic = line.split(':')[1].strip() if purpose and mnemonic: return (mnemonic, purpose) except: pass return (name, 'N/A') def _load_metadata(self): self.ctx.start_msg('Loading BDE metadata') groups_nodes = [x.parent.parent for x in self.ctx.path.ant_glob('groups/*/group/*.mem')] enterprise_nodes = [x.parent.parent for x in self.ctx.path.ant_glob('enterprise/*/group/*.mem')] wrapper_group_nodes = [x.parent.parent for x in self.ctx.path.ant_glob( 'wrappers/*/group/*.mem')] group_nodes = groups_nodes + enterprise_nodes + wrapper_group_nodes for g in group_nodes: self.group_dep[g.name] = self._get_meta(g, 'group', 'dep') self.group_mem[g.name] = self._get_meta(g, 'group', 'mem') self.group_defs[g.name] = self._get_raw_options(g, 'group', 'defs') self.group_opts[g.name] = self._get_raw_options(g, 'group', 'opts') self.group_cap[g.name] = self._get_raw_options(g, 'group', 'cap') self.group_doc[g.name] = self._parse_group_doc(g) if g.name + 'scm' in g.listdir(): self.export_groups.append(g.name) self.group_locs[g.name] = g.parent.name # stand-alone packages behaves like pakcage groups with a single # package adapter_nodes = [x.parent.parent for x in self.ctx.path.ant_glob('adapters/*/package/*.mem')] wrapper_package_nodes = [x.parent.parent for x in self.ctx.path.ant_glob( 'wrappers/*/package/*.mem')] sa_package_nodes = adapter_nodes + wrapper_package_nodes for s in sa_package_nodes: self.group_dep[s.name] = self._get_meta(s, 'package', 'dep') self.group_mem[s.name] = self._get_meta(s, 'package', 'mem') self.group_defs[s.name] = self._get_raw_options(s, 'package', 'defs') self.group_opts[s.name] = self._get_raw_options(s, 'package', 'opts') self.group_cap[s.name] = self._get_raw_options(s, 'package', 'cap') self.group_doc[s.name] = self._parse_group_doc(s) dums_file = s.make_node('package').find_node(s.name + '.dums') if dums_file: self.package_dums.append(s.name) self.export_groups.append(s.name) self.sa_package_locs[s.name] = s.parent.name # assume that std-alone packages are not headers only and do not # have 'pub' files. for g in self.group_dep: for dep in self.group_dep[g]: if dep not in self.group_dep: self.external_libs.add(dep) for group_node in group_nodes: for package_name in self.group_mem[group_node.name]: package_node = group_node.make_node(package_name) self.package_dep[package_name] = \ self._get_meta(package_node, 'package', 'dep') self.package_mem[package_name] = \ self._get_meta(package_node, 'package', 'mem') self.package_opts[package_name] = \ self._get_raw_options(package_node, 'package', 'opts') self.package_cap[package_name] = \ self._get_raw_options(package_node, 'package', 'cap') # only header-only packages typically have 'pub' files try: self.package_pub[package_name] = \ self._get_meta(package_node, 'package', 'pub') except: pass dums_file = \ package_node.make_node('package').find_node( package_node.name + '.dums') if dums_file: self.package_dums.append(package_node.name) self._load_package_and_component_types() self._load_group_vers() self._load_soname_override() self._load_pc_extra_include_dirs() self.ctx.end_msg('ok') def _load_package_and_component_types(self): def load_package_types(package_name, component_names, package_node): if 0 == len(component_names): cpp_nodes = package_node.ant_glob('*.cpp') self.package_type[package_name] = ('cpp' if 0 < len(cpp_nodes) else 'c') return cpp_count = 0 c_count = 0 for c in component_names: if package_node.find_node('%s.cpp' % c): self.component_type[c] = 'cpp' cpp_count += 1 else: # assume that only c or cpp components exist self.component_type[c] = 'c' c_count += 1 self.package_type[package_name] = ('cpp' if c_count <= cpp_count else 'c') for g in self.group_mem: if g not in self.sa_package_locs: group_node = self.ctx.path.make_node( self.group_locs[g]).make_node(g) for p in self.group_mem[g]: package_node = group_node.make_node(p) load_package_types(p, self.package_mem[p], package_node) else: package_node = self.ctx.path.make_node( self.sa_package_locs[g]).make_node(g) load_package_types(g, self.group_mem[g], package_node) def _levelize_group_dependencies(self, group): from collections import defaultdict level_map = defaultdict(set) def _levelize_groups_impl(group): if group not in self.group_dep or not self.group_dep[group]: level_map[1].add(group) return 1 level = 1 + max(_levelize_groups_impl(child) for child in self.group_dep[group]) level_map[level].add(group) return level map(lambda x: _levelize_groups_impl(x), self.group_dep[group]) levels = [] for level in sorted(level_map.keys()): levels.append(level_map[level]) return levels def _evaluate_group_options(self, group): def patch_options_common(options): ''' patch options to mimic hardcoded behaviors in bde_build common to packages and package groups ''' # 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. if (self.option_mask.uplid.uplid['os_type'] == 'windows' and self.option_mask.uplid.uplid['comp_type'] == 'cl'): loc = self.group_locs[group] if group in self.group_locs else \ self.sa_package_locs[group] options['BDE_CXXFLAGS'] += " /Fd%s\\%s\\%s.pdb" % ( loc, group, group) options['BDE_CFLAGS'] += " /Fd%s\\%s\\%s.pdb" % ( loc, group, group) defs = copy.deepcopy(self.default_opts) # %s_LOCN is hard coded in bde_build group_node = self.ctx.path.make_node( [(self.group_locs[group] if group in self.group_locs else self.sa_package_locs[group]), group]) defs.options['%s_LOCN' % group.upper()] = group_node.abspath() levels = self._levelize_group_dependencies(group) for level in levels: for group_dependency in sorted(level): if group_dependency not in self.external_libs: defs.read(self.group_defs[group_dependency], self.ctx) defs.read(self.group_cap[group_dependency], self.ctx) defs.read(self.group_defs[group], self.ctx) defs.read(self.group_cap[group], self.ctx) opts = copy.deepcopy(defs) opts.read(self.group_opts[group], self.ctx) defs.evaluate() if defs.options.get('CAPABILITY') == 'NEVER': self.unsupported_groups.add(group) if group not in self.sa_package_locs: self.unsupported_packages |= set(self.group_mem[group]) return 'skipped (unsupported)' self.group_export_options[group] = defs.options unsupported_packages = set() if group not in self.sa_package_locs: for package in self.group_mem[group]: p_opts = copy.deepcopy(opts) package_node = group_node.make_node(package) p_opts.read(self.package_opts[package], self.ctx) # Ideally, we should also read the capability files of the # packages on which this depends, but since bde_build.pl # doesn't do this, we don't need to do it for now. p_opts.read(self.package_cap[package], self.ctx) # '%s_LOCN' and 'BDE_CXXINCLUDES' are hard coded in bde_build p_opts.options['%s_LOCN' % package.upper().replace('+', '_')] = \ package_node.abspath() p_opts.options['BDE_CXXINCLUDES'] = '$(BDE_CXXINCLUDE)' patch_options_common(p_opts.options) p_opts.evaluate() if p_opts.options.get('CAPABILITY') == 'NEVER': unsupported_packages.add(package) else: self.package_options[package] = p_opts.options # BDE_CXXINCLUDES is hard coded in bde_build opts.options['BDE_CXXINCLUDES'] = '$(BDE_CXXINCLUDE)' opts.evaluate() self.group_options[group] = opts.options patch_options_common(opts.options) if unsupported_packages: self.unsupported_packages |= unsupported_packages return ('ok, with some skipped (%s)' % ','.join(unsupported_packages)) return 'ok' def _configure_external_libs(self, ufid): self.ufid = copy.deepcopy(ufid) pkgconfig_args = ['--libs', '--cflags'] shared_flag = 'shr' in self.ufid.ufid if shared_flag: self.ufid.ufid.remove('shr') self.libtype_features = ['cxxshlib'] else: pkgconfig_args.append('--static') self.libtype_features = ['cxxstlib'] # If the static build is chosen (the default), waf assumes that all # libraries queried from pkg-config are to be built statically, which # is not true for some libraries. We work around this issue by manually # changing the affected libraries to be linked dynamically instead. dl_overrides = ['pthread', 'rt', 'nsl', 'socket'] # If lib_suffix is set, we expect the pkgconfig files being depended on # to have the same suffix as well. Since the .dep files will not have # the suffix, we will remove the suffix from the names of the options # loaded into the waf environment. rename_keys = ['defines', 'includes', 'libpath', 'stlib', 'lib'] for lib in self.external_libs: actual_lib = lib + str(self.lib_suffix or '') self.ctx.check_cfg(package=actual_lib, args=pkgconfig_args, errmsg="Make sure the path indicated by " "environment variable 'PKG_CONFIG_PATH' " "contains '%s.pc'" % actual_lib) if self.lib_suffix: for k in rename_keys: key_old = (k + '_' + actual_lib).upper() key_new = (k + '_' + lib).upper() self.ctx.env[key_new] = self.ctx.env[key_old] del self.ctx.env[key_old] sl_key = ('stlib_' + lib).upper() dl_key = ('lib_' + lib).upper() # preserve the order of libraries for l in dl_overrides: if l in self.ctx.env[sl_key]: if dl_key not in self.ctx.env: self.ctx.env[dl_key] = [] self.ctx.env[sl_key].remove(l) self.ctx.env[dl_key].append(l) # check_cfg always stores the libpath as dynamic library path # instead of static even if the configuration option is set to # static. if not shared_flag: slp_key = ('stlibpath_' + lib).upper() dlp_key = ('libpath_' + lib).upper() if dlp_key in self.ctx.env: self.ctx.env[slp_key] = self.ctx.env[dlp_key] del self.ctx.env[dlp_key] if self.lib_suffix: defines_old = self.ctx.env['DEFINES'] defines_new = [] for d in defines_old: index = d.find('%s=1' % self.lib_suffix.upper()) if index >= 0: defines_new.append('%s=1' % d[0:index]) else: defines_new.append(d) self.ctx.env['DEFINES'] = defines_new def _configure_options(self, uplid): self.uplid = uplid self.option_mask = OptionMask(self.uplid, self.ufid) # Get the path of default.opts. Assume the directory containing this # script is <repo_root>/bin/tools/waf/bde and default.opts is located # in the directory <repo_root>/etc. upd = os.path.dirname bde_root = os.environ.get('BDE_ROOT') repo_root = upd(upd(upd(upd(upd(os.path.realpath(__file__)))))) default_opts_path = os.path.join(repo_root, 'etc', 'default.opts') default_opts_flag = os.path.isfile(default_opts_path) if not default_opts_flag and bde_root: default_opts_path = os.path.join(bde_root, 'etc', 'default.opts') default_opts_flag = os.path.isfile(default_opts_path) if not default_opts_flag: self.ctx.fatal("Can not find default.opts from the /etc directory " "of the waf executable, nor the BDE_ROOT " "environment variable.") raw_options = RawOptions() raw_options.read(default_opts_path) # At BB, default_internal.opts contains some variables that is required # for building bde-bb. if bde_root: default_internal_opts_path = os.path.join(bde_root, 'etc', 'default_internal.opts') raw_options.read(default_internal_opts_path) debug_opt_keys = self.ctx.options.debug_opt_keys if debug_opt_keys: debug_opt_keys = debug_opt_keys.split(',') self.default_opts = Options(self.option_mask) self.default_opts.read(raw_options.options, self.ctx, debug_opt_keys=debug_opt_keys) for g in self.group_dep: self.ctx.start_msg("Evaluating options for '%s'" % g) status_msg = self._evaluate_group_options(g) self.ctx.end_msg(status_msg) tmp_opts = copy.deepcopy(self.default_opts) tmp_opts.evaluate() env_variables = ('SET_TMPDIR', 'XLC_LIBPATH') setenv_re = re.compile(r'^([^=]+)=(.*)$') for e in env_variables: if e in tmp_opts.options: m = setenv_re.match(tmp_opts.options[e]) self.custom_envs[m.group(1)] = m.group(2) def _parse_ldflags(self, ldflags): """ parse the linker flags into the following components: stlib, libs, libpaths, flags """ stlibs = [] libs = [] libpaths = [] flags = [] shlib_marker = self.ctx.env['SHLIB_MARKER'] stlib_marker = self.ctx.env['STLIB_MARKER'] libs_exp = re.compile( self.ctx.env['LIB_ST'].replace('%s', r'([^ =]+)')) libpath_exp = re.compile( self.ctx.env['LIBPATH_ST'].replace('%s', r'([^ =]+)')) # default to shlibs isshlib_flag = True for flag in ldflags: if flag == shlib_marker: isshlib_flag = True continue if flag == stlib_marker: isshlib_flag = False continue m = libpath_exp.match(flag) if m: libpaths.append(m.group(1)) continue m = libs_exp.match(flag) if m: lib = m.group(1) if isshlib_flag: libs.append(lib) else: stlibs.append(lib) continue flags.append(flag) return (stlibs, libs, libpaths, flags) def _parse_cflags(self, cflags): includes = [] flags = [] inc_exp = re.compile( self.ctx.env['CPPPATH_ST'].replace('%s', r'([^ =]+)')) for flag in cflags: m = inc_exp.match(flag) if m: includes.append(m.group(1)) continue flags.append(flag) return (includes, flags) def _get_export_cxxflags(self, cxxflags): "only defines is required to be in export flags" export_flags = [] for flag in cxxflags: st = flag[:2] if st == '-D' or (self.ctx.env.CXX_NAME == 'msvc' and st == '/D'): export_flags.append(flag) return export_flags def _save_group_options(self, group): export_options = self.group_export_options[group] options = self.group_options[group] # First value in the list is the compiler or linker, and so we ignore # it to just take the parameters. (stlibs, libs, libpaths, linkflags) = self._parse_ldflags( options['CXXLINK'].split()[1:] + options['COMPONENT_BDEBUILD_LDFLAGS'].split()) self.ctx.env[group + '_export_libs'] = libs self.ctx.env[group + '_export_cxxflags'] = self._get_export_cxxflags( export_options['COMPONENT_BDEBUILD_CXXFLAGS'].split()) self.ctx.env[group + '_libs'] = libs self.ctx.env[group + '_stlibs'] = stlibs self.ctx.env[group + '_libpaths'] = libpaths self.ctx.env[group + '_linkflags'] = linkflags if group in self.sa_package_locs: (cxxincludes, cxxflags) = self._parse_cflags( options['CXX'].split()[1:] + options['COMPONENT_BDEBUILD_CXXFLAGS'].split()) (cincludes, cflags) = self._parse_cflags( options['CC'].split()[1:] + options['COMPONENT_BDEBUILD_CXXFLAGS'].split()) self.ctx.env[group + '_cxxflags'] = cxxflags self.ctx.env[group + '_cxxincludes'] = cxxincludes self.ctx.env[group + '_cflags'] = cflags self.ctx.env[group + '_cincludes'] = cincludes def _save_package_options(self, package): options = self.package_options[package] (stlibs, libs, libpaths, linkflags) = self._parse_ldflags( options['CXXLINK'].split()[1:] + options['COMPONENT_BDEBUILD_LDFLAGS'].split()) (cxxincludes, cxxflags) = self._parse_cflags( options['CXX'].split()[1:] + options['COMPONENT_BDEBUILD_CXXFLAGS'].split()) (cincludes, cflags) = self._parse_cflags( options['CC'].split()[1:] + options['COMPONENT_BDEBUILD_CFLAGS'].split()) self.ctx.env[package + '_cxxflags'] = cxxflags self.ctx.env[package + '_cxxincludes'] = cxxincludes self.ctx.env[package + '_cflags'] = cflags self.ctx.env[package + '_cincludes'] = cincludes self.ctx.env[package + '_libs'] = libs self.ctx.env[package + '_stlibs'] = stlibs self.ctx.env[package + '_libpaths'] = libpaths self.ctx.env[package + '_linkflags'] = linkflags def _load_group_vers(self): # This is a big hack to get the version numbers for package groups and # sa-packages for group_name in self.export_groups: try: self.group_ver[group_name] = self._get_group_ver(group_name) except BaseException: Logs.warn("Could not identify the version number for %s." % group_name) self.group_ver[group_name] = ("-1", "-1", "-1") for group_name in self.export_groups: if self.group_ver[group_name][0] == 'BDE_VERSION_MAJOR': if 'bde' in self.group_ver: self.group_ver[group_name] = self.group_ver['bde'] else: self.group_ver[group_name] = self.group_ver['bsi'] def _get_group_ver(self, group_name): if group_name in ('a_bdema',): version = ('BDE_VERSION_MAJOR', 'BDE_VERSION_MINOR', 'BDE_VERSION_PATCH') elif group_name in ('bap', 'zde', 'e_ipc'): version = self._get_group_ver2(group_name) elif (group_name.startswith('a_') and group_name not in ('a_xercesc', 'a_bteso')): version = self._get_group_ver3(group_name) else: version = self._get_group_ver1(group_name) if (version[0] is None or version[1] is None or version[2] is None): raise Exception return version def _get_group_ver1(self, group_name): if group_name not in self.sa_package_locs: group_node = self.ctx.path.make_node( [self.group_locs[group_name], group_name]) versiontag_node = group_node.find_node( '%sscm/%sscm_versiontag.h' % (group_name, group_name)) if group_name == 'bde': version_node = group_node.find_node( '%sscm/%sscm_patchversion.h' % (group_name, group_name)) else: version_node = group_node.find_node( '%sscm/%sscm_version.cpp' % (group_name, group_name)) else: package_node = self.ctx.path.make_node( [self.sa_package_locs[group_name], group_name]) versiontag_node = package_node.find_node( '%s_versiontag.h' % group_name) version_node = package_node.find_node( '%s_version.cpp' % group_name) versiontag_source = versiontag_node.read() version_source = version_node.read() major_ver_re = re.compile( r'''^\s*#define\s+%s_VERSION_MAJOR\s+(\S+)\s*$''' % group_name.upper(), re.MULTILINE) minor_ver_re = \ re.compile(r'''^\s*#define\s+%s_VERSION_MINOR\s+(\S+)\s*$''' % group_name.upper(), re.MULTILINE) if group_name == 'bde': patch_ver_re = re.compile( r'''^\s*#define\s+%sSCM_PATCHVERSION_PATCH\s+(\S+)\s*$''' % group_name.upper(), re.MULTILINE) else: patch_ver_re = re.compile( r'''^\s*#define\s+%s_VERSION_PATCH\s+(\S+)\s*$''' % group_name.upper(), re.MULTILINE) (major_ver, minor_ver, patch_ver) = (None, None, None) m = major_ver_re.search(versiontag_source) if m: major_ver = m.group(1) m = minor_ver_re.search(versiontag_source) if m: minor_ver = m.group(1) m = patch_ver_re.search(version_source) if m: patch_ver = m.group(1) return (major_ver, minor_ver, patch_ver) def _get_group_ver2(self, group_name): if group_name not in self.sa_package_locs: group_node = self.ctx.path.make_node( [self.group_locs[group_name], group_name]) version_node = group_node.find_node( '%sscm/%sscm_version.cpp' % (group_name, group_name)) if not version_node: version_node = group_node.find_node( '%sscm/%sscm_version.c' % (group_name, group_name)) else: package_node = self.ctx.path.make_node( [self.sa_package_locs[group_name], group_name]) version_node = package_node.find_node( '%s_version.cpp' % group_name) source = version_node.read() if group_name.startswith('e_'): type_name = 'ENT' lib_name = group_name[2:].upper() else: type_name = 'LIB' lib_name = group_name.upper() exp = ( r'''BLP_%s_BDE_%s_(?P<major>\d+)\.(?P<minor>\d+).(?P<patch>\d+)''' % (type_name, lib_name) ) version_re = re.compile(exp) (major_ver, minor_ver, patch_ver) = (None, None, None) m = version_re.search(source) if m: major_ver = m.group('major') minor_ver = m.group('minor') patch_ver = m.group('patch') return (major_ver, minor_ver, patch_ver) def _get_group_ver3(self, group_name): package_node = self.ctx.path.make_node( [self.sa_package_locs[group_name], group_name]) version_node = package_node.find_node('%s_version.cpp' % group_name) source = version_node.read() exp = r'''(?P<major>\d+)\.(?P<minor>\d+).(?P<patch>\d+)''' version_re = re.compile(exp, re.MULTILINE) (major_ver, minor_ver, patch_ver) = (None, None, None) m = version_re.search(source) if m: major_ver = m.group('major') minor_ver = m.group('minor') patch_ver = m.group('patch') return (major_ver, minor_ver, patch_ver) def _load_soname_override(self): for group_name in self.export_groups: soname = os.environ.get('BDE_%s_SONAME' % group_name.upper()) if soname: self.soname_override[group_name] = soname def _load_pc_extra_include_dirs(self): include_dirs = os.environ.get('PC_EXTRA_INCLUDE_DIRS') if include_dirs: self.pc_extra_include_dirs = include_dirs.split(':') def _save(self): self.ctx.start_msg('Saving configuration') self.ctx.env['ufid'] = self.option_mask.ufid.ufid # For visual studio, waf explicitly includes the system header files by # setting the 'INCLUDES' variable. BSL_OVERRIDE_STD mode requires that # the system header files, which contains the standard library, be # overridden with custom versions in bsl, so we workaround the issue by # moving the system includes to 'INCLUDE_BSL' if it exists. This # solution is not perfect, because it doesn't support package groups # that doesn't depend on bsl -- this is not a problem for BDE # libraries. if (self.option_mask.uplid.uplid['os_type'] == 'windows' and 'INCLUDES_BSL' in self.ctx.env): # Assume that 'INCLUDES' containly system header only. self.ctx.env['INCLUDES_BSL'].extend(self.ctx.env['INCLUDES']) del self.ctx.env['INCLUDES'] if self.option_mask.uplid.uplid['comp_type'] == 'xlc': # The default xlc linker options for linking shared objects for waf # are '-brtl' and '-bexpfull', bde_build does not use '-bexpfull', # change the options to preserve binary compatibility. self.ctx.env['LINKFLAGS_cxxshlib'] = ['-G', '-brtl'] self.ctx.env['LINKFLAGS_cshlib'] = ['-G', '-brtl'] # The envrionment variables SHLIB_MARKER and STLIB_MARKERS are used # by the '_parse_ldflags' function to determine wheter a library is # to be linked staticcally or dyanmically. These are not set by # waf xlc plugin. self.ctx.env['SHLIB_MARKER'] = '-bdynamic' self.ctx.env['STLIB_MARKER'] = '-bstatic' # ar on aix only processes 32-bit object files by default if '64' in self.option_mask.ufid.ufid: self.ctx.env['ARFLAGS'] = ['-rcs', '-X64'] if (self.option_mask.uplid.uplid['os_name'] == 'sunos' and self.option_mask.uplid.uplid['comp_type'] == 'cc'): # Work around bug in waf's sun CC plugin to allow for properly # adding SONAMES. TODO: submit patch self.ctx.env['SONAME_ST'] = '-h %s' self.ctx.env['DEST_BINFMT'] = 'elf' # Sun C++ linker doesn't link in the Std library by default if 'cxxshlib' in self.libtype_features: if 'LINKFLAGS' not in self.ctx.env: self.ctx.env['LINKFLAGS'] = [] self.ctx.env['LINKFLAGS'].extend(['-zdefs', '-lCstd', '-lCrun', '-lc', '-lm', '-lsunmath', '-lpthread']) # Remove unsupported package groups and packages. We don't need to do # dependency analysis because the unsupported sets already contain all # transitively unsupported nodes. for g in self.unsupported_groups: if g in self.export_groups: self.export_groups.remove(g) self.group_dep.pop(g, None) self.group_mem.pop(g, None) self.group_doc.pop(g, None) self.sa_package_locs.pop(g, None) self.group_locs.pop(g, None) for p in self.unsupported_packages: self.package_dep.pop(p, None) self.package_mem.pop(p, None) self.package_pub.pop(p, None) for g in self.group_mem: self.group_mem[g] = list(set(self.group_mem[g]) - self.unsupported_packages) self.ctx.env['external_libs'] = self.external_libs self.ctx.env['export_groups'] = self.export_groups self.ctx.env['group_dep'] = self.group_dep self.ctx.env['group_mem'] = self.group_mem self.ctx.env['group_doc'] = self.group_doc self.ctx.env['group_ver'] = self.group_ver self.ctx.env['sa_package_locs'] = self.sa_package_locs self.ctx.env['soname_override'] = self.soname_override self.ctx.env['group_locs'] = self.group_locs self.ctx.env['package_dep'] = self.package_dep self.ctx.env['package_mem'] = self.package_mem self.ctx.env['package_pub'] = self.package_pub self.ctx.env['package_dums'] = self.package_dums self.ctx.env['libtype_features'] = self.libtype_features self.ctx.env['prefix'] = self.ctx.options.prefix self.ctx.env['custom_envs'] = self.custom_envs self.ctx.env['package_type'] = self.package_type self.ctx.env['component_type'] = self.component_type self.ctx.env['lib_suffix'] = self.lib_suffix self.ctx.env['install_flat_include'] = \ self.ctx.options.install_flat_include self.ctx.env['install_lib_dir'] = self.ctx.options.install_lib_dir self.ctx.env['pc_extra_include_dirs'] = self.pc_extra_include_dirs for g in self.group_dep: self._save_group_options(g) for p in self.package_dep: self._save_package_options(p) self.ctx.end_msg('ok')