Example #1
0
def subfeature(feature_name,
               value_string,
               subfeature,
               subvalues,
               attributes=[]):
    """ Declares a subfeature.
        feature_name:   Root feature that is not a subfeature.
        value_string:   An optional value-string specifying which feature or
                        subfeature values this subfeature is specific to,
                        if any.                
        subfeature:     The name of the subfeature being declared.
        subvalues:      The allowed values of this subfeature.
        attributes:     The attributes of the subfeature.
    """
    feature_name = add_grist(feature_name)
    validate_feature(feature_name)

    # Add grist to the subfeature name if a value-string was supplied
    subfeature_name = __get_subfeature_name(subfeature, value_string)

    if subfeature_name in __all_features[feature_name]['subfeatures']:
        message = "'%s' already declared as a subfeature of '%s'" % (
            subfeature, feature_name)
        message += " specific to '%s'" % value_string
        raise BaseException(message)

    __all_features[feature_name]['subfeatures'].append(subfeature_name)

    # First declare the subfeature as a feature in its own right
    f = ungrist(feature_name)
    feature(f + '-' + subfeature_name, subvalues, attributes + ['subfeature'])

    # Now make sure the subfeature values are known.
    extend_subfeature(feature_name, value_string, subfeature, subvalues)
Example #2
0
def is_subfeature_of(parent_property, f):
    """ Return true iff f is an ordinary subfeature of the parent_property's
        feature, or if f is a subfeature of the parent_property's feature
        specific to the parent_property's value.
    """
    if not valid(f) or not 'subfeature' in __all_features[f]['attributes']:
        return False

    specific_subfeature = __re_split_subfeatures.match(f)

    if specific_subfeature:
        # The feature has the form
        # <topfeature-topvalue:subfeature>,
        # e.g. <toolset-msvc:version>
        feature_value = split_top_feature(specific_subfeature.group(1))
        if replace_grist(feature_value[1],
                         '<' + feature_value[0] + '>') == parent_property:
            return True
    else:
        # The feature has the form <topfeature-subfeature>,
        # e.g. <toolset-version>
        top_sub = split_top_feature(ungrist(f))

        if top_sub[1] and add_grist(top_sub[0]) == get_grist(parent_property):
            return True

    return False
Example #3
0
def add_prefix_and_suffix(specified_name, type, property_set):
    """Appends the suffix appropriate to 'type/property-set' combination
    to the specified name and returns the result."""

    property_set = b2.util.jam_to_value_maybe(property_set)

    suffix = ""
    if type:
        suffix = b2.build.type.generated_target_suffix(type, property_set)

    # Handle suffixes for which no leading dot is desired.  Those are
    # specified by enclosing them in <...>.  Needed by python so it
    # can create "_d.so" extensions, for example.
    if get_grist(suffix):
        suffix = ungrist(suffix)
    elif suffix:
        suffix = "." + suffix

    prefix = ""
    if type:
        prefix = b2.build.type.generated_target_prefix(type, property_set)

    if specified_name.startswith(prefix):
        prefix = ""

    if not prefix:
        prefix = ""
    if not suffix:
        suffix = ""
    return prefix + specified_name + suffix
Example #4
0
def subfeature (feature_name, value_string, subfeature, subvalues, attributes = []):
    """ Declares a subfeature.
        feature_name:   Root feature that is not a subfeature.
        value_string:   An optional value-string specifying which feature or
                        subfeature values this subfeature is specific to,
                        if any.                
        subfeature:     The name of the subfeature being declared.
        subvalues:      The allowed values of this subfeature.
        attributes:     The attributes of the subfeature.
    """
    feature_name = add_grist (feature_name)
    validate_feature (feature_name)
    
    # Add grist to the subfeature name if a value-string was supplied
    subfeature_name = __get_subfeature_name (subfeature, value_string)
    
    if subfeature_name in __all_features [feature_name]['subfeatures']:
        message = "'%s' already declared as a subfeature of '%s'" % (subfeature, feature_name)
        message += " specific to '%s'" % value_string
        raise BaseException (message)

    __all_features [feature_name]['subfeatures'].append (subfeature_name)

    # First declare the subfeature as a feature in its own right
    f = ungrist (feature_name)
    feature (f + '-' + subfeature_name, subvalues, attributes + ['subfeature'])
    
    # Now make sure the subfeature values are known.
    extend_subfeature (feature_name, value_string, subfeature, subvalues)
Example #5
0
    def actualize (self, scanner = None):
        """ Generates all the actual targets and sets up build actions for
            this target.
            
            If 'scanner' is specified, creates an additional target
            with the same location as actual target, which will depend on the
            actual target and be associated with 'scanner'. That additional
            target is returned. See the docs (#dependency_scanning) for rationale.
            Target must correspond to a file if 'scanner' is specified.
            
            If scanner is not specified, then actual target is returned.
        """
        actual_name = self.actualize_no_scanner ()

        if not scanner:
            return actual_name

        else:
            # Add the scanner instance to the grist for name.
            g = '-'.join ([ungrist(get_grist(actual_name)), str(id(scanner))])

            name = replace_grist (actual_name, '<' + g + '>')

            if not self.made_.has_key (name):
                self.made_ [name] = True

                self.project_.manager ().engine ().add_dependency (name, actual_name)

                self.actualize_location (name)

                self.project_.manager ().scanners ().install (scanner, name, str (self))

            return name
Example #6
0
def is_subfeature_of (parent_property, f):
    """ Return true iff f is an ordinary subfeature of the parent_property's
        feature, or if f is a subfeature of the parent_property's feature
        specific to the parent_property's value.
    """
    if not valid (f) or not 'subfeature' in __all_features [f]['attributes']:
        return False

    specific_subfeature = __re_split_subfeatures.match (f)

    if specific_subfeature:
        # The feature has the form
        # <topfeature-topvalue:subfeature>,
        # e.g. <toolset-msvc:version>
        feature_value = split_top_feature(specific_subfeature.group(1))
        if replace_grist (feature_value [1], '<' + feature_value [0] + '>') == parent_property:
            return True
    else:
        # The feature has the form <topfeature-subfeature>,
        # e.g. <toolset-version>
        top_sub = split_top_feature (ungrist (f))

        if top_sub [1] and add_grist (top_sub [0]) == get_grist (parent_property):
            return True

    return False
Example #7
0
    def actualize (self, scanner = None):
        """ Generates all the actual targets and sets up build actions for
            this target.
            
            If 'scanner' is specified, creates an additional target
            with the same location as actual target, which will depend on the
            actual target and be associated with 'scanner'. That additional
            target is returned. See the docs (#dependency_scanning) for rationale.
            Target must correspond to a file if 'scanner' is specified.
            
            If scanner is not specified, then actual target is returned.
        """
        actual_name = self.actualize_no_scanner ()

        if not scanner:
            return actual_name

        else:
            # Add the scanner instance to the grist for name.
            g = '-'.join ([ungrist(get_grist(actual_name)), str(id(scanner))])

            name = replace_grist (actual_name, '<' + g + '>')

            if not self.made_.has_key (name):
                self.made_ [name] = True

                self.project_.manager ().engine ().add_dependency (name, actual_name)

                self.actualize_location (name)

                self.project_.manager ().scanners ().install (scanner, name, str (self))

            return name
Example #8
0
def add_defaults(properties):
    """ Given a set of properties, add default values for features not
        represented in the set. 
        Note: if there's there's ordinary feature F1 and composite feature
        F2, which includes some value for F1, and both feature have default values,
        then the default value of F1 will be added, not the value in F2. This might
        not be right idea: consider
        
          feature variant : debug ... ;
               <variant>debug : .... <runtime-debugging>on
          feature <runtime-debugging> : off on ;
          
          Here, when adding default for an empty property set, we'll get
        
            <variant>debug <runtime_debugging>off
         
          and that's kind of strange.        
    """
    result = [x for x in properties]

    for v in replace_grist(properties, ''):
        if v in properties:
            raise BaseException(
                "'add_defaults' requires explicitly specified features, but '%s' appears to be the value of an un-expanded implicit feature"
                % v)

    # We don't add default for elements with ":" inside. This catches:
    # 1. Conditional properties --- we don't want <variant>debug:<define>DEBUG
    #    to be takes as specified value for <variant>
    # 2. Free properties with ":" in values. We don't care, since free properties
    #    don't have defaults.
    xproperties = [
        property for property in properties if __re_no_hyphen.match(property)
    ]
    missing_top = set.difference(__all_top_features, get_grist(xproperties))
    more = defaults(missing_top)
    result += more
    xproperties += more

    # Add defaults for subfeatures of features which are present
    for p in xproperties:
        gp = get_grist(p)
        s = []
        if __all_features.has_key(gp):
            s = __all_features[gp]['subfeatures']
        f = ungrist(gp)

        xbase = ['<%s-%s>' % (f, xs) for xs in s]

        missing_subs = set.difference(xbase, get_grist(result))
        result += defaults(__select_subfeatures(p, missing_subs))

    return result
Example #9
0
def extend_subfeature (feature, value_string, subfeature, subvalues):
    feature = add_grist (feature)
    validate_feature (feature)

    if value_string:
        validate_value_string (feature, value_string)

    subfeature_name = __get_subfeature_name (subfeature, value_string)
    
    f = ungrist (feature)
    extend (f + '-' + subfeature_name, subvalues) ;
    
    __add_to_subfeature_value_to_name_map (feature, value_string, subfeature_name, subvalues)
Example #10
0
def __expand_subfeatures_aux(feature, value, dont_validate=False):
    """ Helper for expand_subfeatures.
        Given a feature and value, or just a value corresponding to an
        implicit feature, returns a property set consisting of all component
        subfeatures and their values. For example:
        
          expand_subfeatures <toolset>gcc-2.95.2-linux-x86
              -> <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
          equivalent to:
              expand_subfeatures gcc-2.95.2-linux-x86

        feature:        The name of the feature, or empty if value corresponds to an implicit property
        value:          The value of the feature.
        dont_validate:  If True, no validation of value string will be done.
    """
    if not feature:
        feature = implied_feature(value)
    else:
        validate_feature(feature)

    if not dont_validate:
        validate_value_string(feature, value)

    components = value.split("-")

    # get the top-level feature's value
    value = replace_grist(components[0], '')

    result = [replace_grist(components[0], feature)]

    subvalues = components[1:]

    while len(subvalues) > 0:
        subvalue = subvalues[0]  # pop the head off of subvalues
        subvalues = subvalues[1:]

        subfeature = __find_implied_subfeature(feature, subvalue, value)

        # If no subfeature was found, reconstitute the value string and use that
        if not subfeature:
            result = '-'.join(components)
            result = replace_grist(result, feature)
            return [result]

        f = ungrist(feature)
        # FIXME: why grist includes '<>'?
        result.append(replace_grist(subvalue,
                                    '<' + f + '-' + subfeature + '>'))

    return result
Example #11
0
def add_defaults (properties):
    """ Given a set of properties, add default values for features not
        represented in the set. 
        Note: if there's there's ordinary feature F1 and composite feature
        F2, which includes some value for F1, and both feature have default values,
        then the default value of F1 will be added, not the value in F2. This might
        not be right idea: consider
        
          feature variant : debug ... ;
               <variant>debug : .... <runtime-debugging>on
          feature <runtime-debugging> : off on ;
          
          Here, when adding default for an empty property set, we'll get
        
            <variant>debug <runtime_debugging>off
         
          and that's kind of strange.        
    """
    result = [ x for x in properties ]
    
    for v in replace_grist (properties, ''):
        if v in properties:
            raise BaseException ("'add_defaults' requires explicitly specified features, but '%s' appears to be the value of an un-expanded implicit feature" % v)

    # We don't add default for elements with ":" inside. This catches:
    # 1. Conditional properties --- we don't want <variant>debug:<define>DEBUG
    #    to be takes as specified value for <variant>
    # 2. Free properties with ":" in values. We don't care, since free properties
    #    don't have defaults.
    xproperties = [ property for property in properties if __re_no_hyphen.match (property) ]
    missing_top = set.difference (__all_top_features, get_grist (xproperties))
    more =  defaults (missing_top)
    result += more
    xproperties += more
    
    # Add defaults for subfeatures of features which are present
    for p in xproperties:
        gp = get_grist (p)
        s = []
        if __all_features.has_key (gp):
            s = __all_features [gp]['subfeatures']
        f = ungrist (gp)
        
        xbase = ['<%s-%s>' % (f, xs) for xs in s]
            
        missing_subs = set.difference (xbase, get_grist (result))
        result += defaults (__select_subfeatures (p, missing_subs))
    
    return result
Example #12
0
def __expand_subfeatures_aux (feature, value, dont_validate = False):
    """ Helper for expand_subfeatures.
        Given a feature and value, or just a value corresponding to an
        implicit feature, returns a property set consisting of all component
        subfeatures and their values. For example:
        
          expand_subfeatures <toolset>gcc-2.95.2-linux-x86
              -> <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
          equivalent to:
              expand_subfeatures gcc-2.95.2-linux-x86

        feature:        The name of the feature, or empty if value corresponds to an implicit property
        value:          The value of the feature.
        dont_validate:  If True, no validation of value string will be done.
    """
    if not feature:
        feature = implied_feature(value)
    else:
        validate_feature(feature)

    if not dont_validate:
        validate_value_string(feature, value)
    
    components = value.split ("-")
    
    # get the top-level feature's value
    value = replace_grist(components[0], '')

    result = [ replace_grist(components[0], feature) ]
    
    subvalues = components[1:]

    while len(subvalues) > 0:
        subvalue = subvalues [0]    # pop the head off of subvalues
        subvalues = subvalues [1:]
        
        subfeature = __find_implied_subfeature (feature, subvalue, value)
        
        # If no subfeature was found, reconstitute the value string and use that
        if not subfeature:
            result = '-'.join(components)
            result = replace_grist (result, feature)
            return [result]
            
        f = ungrist (feature)
        # FIXME: why grist includes '<>'?
        result.append (replace_grist (subvalue, '<' + f + '-' + subfeature + '>'))
    
    return result
Example #13
0
def get_prefix(package_name, requirements):

    specified = property.select("install-default-prefix", requirements)
    if specified:
        specified = ungrist(specified[0])
    prefix = option.get("prefix", specified)
    requirements = property.change(requirements, "install-default-prefix", None)    
    # Or some likely defaults if neither is given.
    if not prefix:
        if os.name == "nt":
            prefix = "C:\\" + package_name
        elif os.name == "posix":
            prefix = "/usr/local"

    return prefix
def get_prefix(package_name, requirements):
    specified = property.select("install-default-prefix", requirements)
    if specified:
        specified = ungrist(specified[0])
    prefix = option.get("prefix", specified)
    requirements = property.change(requirements, "install-default-prefix",
                                   None)
    # Or some likely defaults if neither is given.
    if not prefix:
        if os.name == "nt":
            prefix = "C:\\" + package_name
        elif os.name == "posix":
            prefix = "/usr/local"

    return prefix
Example #15
0
def install(name, package_name=None, requirements=[], binaries=[], libraries=[], headers=[]):

    requirements = requirements[:]
    binaries = binaries[:]
    libraries

    if not package_name:
        package_name = name

    if option.get("prefix"):
        # If --prefix is explicitly specified on the command line,
        # then we need wipe away any settings of libdir/includir that
        # is specified via options in config files.
        option.set("bindir", None)
        option.set("libdir", None)
        option.set("includedir", None)
            
    # If <install-source-root> is not specified, all headers are installed to
    # prefix/include, no matter what their relative path is. Sometimes that is
    # what is needed.
    install_source_root = property.select('install-source-root', requirements)
    if install_source_root:
        requirements = property.change(requirements, 'install-source-root', None)
            
    install_header_subdir = property.select('install-header-subdir', requirements)
    if install_header_subdir:
        install_header_subdir = ungrist(install_header_subdir[0])
        requirements = property.change(requirements, 'install-header-subdir', None)

    # First, figure out all locations. Use the default if no prefix option
    # given.
    prefix = get_prefix(name, requirements)

    # Architecture dependent files.
    exec_locate = option.get("exec-prefix", prefix)

    # Binaries.
    bin_locate = option.get("bindir", os.path.join(prefix, "bin"))

    # Object code libraries.
    lib_locate = option.get("libdir", os.path.join(prefix, "lib"))

    # Source header files.
    include_locate = option.get("includedir", os.path.join(prefix, "include"))

    stage.install(name + "-bin", binaries, requirements + ["<location>" + bin_locate])
    
    alias(name + "-lib", [name + "-lib-shared", name + "-lib-static"])
    
    # Since the install location of shared libraries differs on universe
    # and cygwin, use target alternatives to make different targets.
    # We should have used indirection conditioanl requirements, but it's
    # awkward to pass bin-locate and lib-locate from there to another rule.
    alias(name + "-lib-shared", [name + "-lib-shared-universe"])
    alias(name + "-lib-shared", [name + "-lib-shared-cygwin"], ["<target-os>cygwin"])
    
    # For shared libraries, we install both explicitly specified one and the
    # shared libraries that the installed executables depend on.
    stage.install(name + "-lib-shared-universe", binaries + libraries,
                  requirements + ["<location>" + lib_locate, "<install-dependencies>on",
                                  "<install-type>SHARED_LIB"])
    stage.install(name + "-lib-shared-cygwin", binaries + libraries,
                  requirements + ["<location>" + bin_locate, "<install-dependencies>on",
                                  "<install-type>SHARED_LIB"])

    # For static libraries, we do not care about executable dependencies, since
    # static libraries are already incorporated into them.
    stage.install(name + "-lib-static", libraries, requirements +
                  ["<location>" + lib_locate, "<install-dependencies>on", "<install-type>STATIC_LIB"])
    stage.install(name + "-headers", headers, requirements \
                  + ["<location>" + os.path.join(include_locate, s) for s in install_header_subdir]
                  + install_source_root)

    alias(name, [name + "-bin", name + "-lib", name + "-headers"])

    pt = get_manager().projects().current()

    for subname in ["bin", "lib", "headers", "lib-shared", "lib-static", "lib-shared-universe", "lib-shared-cygwin"]:
        pt.mark_targets_as_explicit([name + "-" + subname])
Example #16
0
def install(name,
            package_name=None,
            requirements=[],
            binaries=[],
            libraries=[],
            headers=[]):

    requirements = requirements[:]
    binaries = binaries[:]
    libraries

    if not package_name:
        package_name = name

    if option.get("prefix"):
        # If --prefix is explicitly specified on the command line,
        # then we need wipe away any settings of libdir/includir that
        # is specified via options in config files.
        option.set("bindir", None)
        option.set("libdir", None)
        option.set("includedir", None)

    # If <install-source-root> is not specified, all headers are installed to
    # prefix/include, no matter what their relative path is. Sometimes that is
    # what is needed.
    install_source_root = property.select('install-source-root', requirements)
    if install_source_root:
        requirements = property.change(requirements, 'install-source-root',
                                       None)

    install_header_subdir = property.select('install-header-subdir',
                                            requirements)
    if install_header_subdir:
        install_header_subdir = ungrist(install_header_subdir[0])
        requirements = property.change(requirements, 'install-header-subdir',
                                       None)

    # First, figure out all locations. Use the default if no prefix option
    # given.
    prefix = get_prefix(name, requirements)

    # Architecture dependent files.
    exec_locate = option.get("exec-prefix", prefix)

    # Binaries.
    bin_locate = option.get("bindir", os.path.join(prefix, "bin"))

    # Object code libraries.
    lib_locate = option.get("libdir", os.path.join(prefix, "lib"))

    # Source header files.
    include_locate = option.get("includedir", os.path.join(prefix, "include"))

    stage.install(name + "-bin", binaries,
                  requirements + ["<location>" + bin_locate])

    alias(name + "-lib", [name + "-lib-shared", name + "-lib-static"])

    # Since the install location of shared libraries differs on universe
    # and cygwin, use target alternatives to make different targets.
    # We should have used indirection conditioanl requirements, but it's
    # awkward to pass bin-locate and lib-locate from there to another rule.
    alias(name + "-lib-shared", [name + "-lib-shared-universe"])
    alias(name + "-lib-shared", [name + "-lib-shared-cygwin"],
          ["<target-os>cygwin"])

    # For shared libraries, we install both explicitly specified one and the
    # shared libraries that the installed executables depend on.
    stage.install(
        name + "-lib-shared-universe", binaries + libraries, requirements + [
            "<location>" + lib_locate, "<install-dependencies>on",
            "<install-type>SHARED_LIB"
        ])
    stage.install(
        name + "-lib-shared-cygwin", binaries + libraries, requirements + [
            "<location>" + bin_locate, "<install-dependencies>on",
            "<install-type>SHARED_LIB"
        ])

    # For static libraries, we do not care about executable dependencies, since
    # static libraries are already incorporated into them.
    stage.install(
        name + "-lib-static", libraries, requirements + [
            "<location>" + lib_locate, "<install-dependencies>on",
            "<install-type>STATIC_LIB"
        ])
    stage.install(name + "-headers", headers, requirements \
                  + ["<location>" + os.path.join(include_locate, s) for s in install_header_subdir]
                  + install_source_root)

    alias(name, [name + "-bin", name + "-lib", name + "-headers"])

    pt = get_manager().projects().current()

    for subname in [
            "bin", "lib", "headers", "lib-shared", "lib-static",
            "lib-shared-universe", "lib-shared-cygwin"
    ]:
        pt.mark_targets_as_explicit([name + "-" + subname])