⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 generators.jam

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 JAM
📖 第 1 页 / 共 3 页
字号:
        }        return $(result) ;    }    # Determine the name of the produced target from the names of the sources.    #    rule determine-output-name ( sources + )    {        # The simple case if when a name of source has single dot. Then, we take        # the part before dot. Several dots can be caused by:        #   - using source file like a.host.cpp, or        #   - a type whose suffix has a dot. Say, we can type 'host_cpp' with        #     extension 'host.cpp'.        # In the first case, we want to take the part up to the last dot. In the        # second case -- not sure, but for now take the part up to the last dot        # too.        name = [ utility.basename [ $(sources[1]).name ] ] ;        for local s in $(sources[2])        {            local n2 = [ utility.basename [ $(s).name ] ] ;            if $(n2) != $(name)            {                errors.error "$(self.id): source targets have different names: cannot determine target name" ;            }        }        # Names of sources might include directory. We should strip it.        name = $(name:D=) ;        return $(name) ;    }    # Constructs targets that are created after consuming 'sources'. The result    # will be the list of virtual-target, which has the same length as the    # 'target-types' attribute and with corresponding types.    #    # When 'name' is empty, all source targets must have the same 'name'    # attribute value, which will be used instead of the 'name' argument.    #    # The 'name' attribute value for each generated target will be equal to    # the 'name' parameter if there is no name pattern for this type. Otherwise,    # the '%' symbol in the name pattern will be replaced with the 'name'    # parameter to obtain the 'name' attribute.    #    # For example, if targets types are T1 and T2 (with name pattern "%_x"),    # suffixes for T1 and T2 are .t1 and .t2, and source is foo.z, then created    # files would be "foo.t1" and "foo_x.t2". The 'name' attribute actually    # determines the basename of a file.    #    # Note that this pattern mechanism has nothing to do with implicit patterns    # in make. It is a way to produce a target whose name is different than the    # name of its source.    #    rule generated-targets ( sources + : property-set : project name ? )    {        if ! $(name)        {            name = [ determine-output-name $(sources) ] ;        }        # Assign an action for each target.        local action = [ action-class ] ;        local a = [ class.new $(action) $(sources) : $(self.id) :                    $(property-set) ] ;        # Create generated target for each target type.        local targets ;        local pre = $(self.name-prefix) ;        local post = $(self.name-postfix) ;        for local t in $(self.target-types)        {            local generated-name = $(pre[1])$(name)$(post[1]) ;            pre = $(pre[2-]) ;            post = $(post[2-]) ;            targets += [ class.new file-target $(generated-name) : $(t) :                $(project) : $(a) ] ;        }        return [ sequence.transform virtual-target.register : $(targets) ] ;    }    # Attempts to convert 'sources' to targets of types that this generator can    # handle. The intention is to produce the set of targets that can be used    # when the generator is run.    #    rule convert-to-consumable-types    (        project name ?        : property-set        : sources +        : only-one ?    # Convert 'source' to only one of the source types. If                        # there is more that one possibility, report an error.        : consumed-var  # Name of the variable which receives all targets which                        # can be consumed.          bypassed-var  # Name of the variable which receives all targets which                        # can not be consumed.    )    {        # We are likely to be passed 'consumed' and 'bypassed' var names. Use        # '_' to avoid name conflicts.        local _consumed ;        local _bypassed ;        local missing-types ;        if $(sources[2])        {            # Do not know how to handle several sources yet. Just try to pass            # the request to other generator.            missing-types = $(self.source-types) ;        }        else        {            consume-directly $(sources) : _consumed : missing-types ;        }        # No need to search for transformation if some source type has consumed        # source and no more source types are needed.        if $(only-one) && $(_consumed)        {            missing-types = ;        }        # TODO: we should check that only one source type if create of        # 'only-one' is true.        # TODO: consider if consumed/bypassed separation should be done by        # 'construct-types'.        if $(missing-types)        {            local transformed = [ generators.construct-types $(project) $(name)                : $(missing-types) : $(property-set) : $(sources) ] ;            # Add targets of right type to 'consumed'. Add others to 'bypassed'.            # The 'generators.construct' rule has done its best to convert            # everything to the required type. There is no need to rerun it on            # targets of different types.            # NOTE: ignoring usage requirements.            for local t in $(transformed[2-])            {                if [ $(t).type ] in $(missing-types)                {                    _consumed += $(t) ;                }                else                {                    _bypassed += $(t) ;                }            }        }        _consumed = [ sequence.unique $(_consumed) ] ;        _bypassed = [ sequence.unique $(_bypassed) ] ;        # Remove elements of '_bypassed' that are in '_consumed'.        # Suppose the target type of current generator, X is produced from X_1        # and X_2, which are produced from Y by one generator. When creating X_1        # from Y, X_2 will be added to 'bypassed'. Likewise, when creating X_2        # from Y, X_1 will be added to 'bypassed', but they are also in        # 'consumed'. We have to remove them from bypassed, so that generators        # up the call stack do not try to convert them.        # In this particular case, X_1 instance in 'consumed' and X_1 instance        # in 'bypassed' will be the same: because they have the same source and        # action name, and 'virtual-target.register' will not allow two        # different instances. Therefore, it is OK to use 'set.difference'.        _bypassed = [ set.difference $(_bypassed) : $(_consumed) ] ;        $(consumed-var) += $(_consumed) ;        $(bypassed-var) += $(_bypassed) ;    }    # Converts several files to consumable types. Called for composing    # generators only.    #    rule convert-multiple-sources-to-consumable-types ( project : property-set :        sources * : consumed-var bypassed-var )    {        # We process each source one-by-one, trying to convert it to a usable        # type.        for local source in $(sources)        {            local _c ;            local _b ;            # TODO: need to check for failure on each source.            convert-to-consumable-types $(project) : $(property-set) : $(source)                : true : _c _b ;            if ! $(_c)            {                generators.dout [ indent ] " failed to convert " $(source) ;            }            $(consumed-var) += $(_c) ;            $(bypassed-var) += $(_b) ;        }    }    rule consume-directly ( source : consumed-var : missing-types-var )    {        local real-source-type = [ $(source).type ] ;        # If there are no source types, we can consume anything.        local source-types = $(self.source-types) ;        source-types ?= $(real-source-type) ;        for local st in $(source-types)        {            # The 'source' if of the right type already.            if $(real-source-type) = $(st) || [ type.is-derived                $(real-source-type) $(st) ]            {                $(consumed-var) += $(source) ;            }            else            {                $(missing-types-var) += $(st) ;            }        }    }    # Returns the class to be used to actions. Default implementation returns    # "action".    #    rule action-class ( )    {        return "action" ;    }}# Registers a new generator instance 'g'.#rule register ( g ){    # A generator can produce several targets of the same type. We want unique    # occurrence of that generator in .generators.$(t) in that case, otherwise,    # it will be tried twice and we will get a false ambiguity.    for local t in [ sequence.unique [ $(g).target-types ] ]    {        .generators.$(t) += $(g) ;    }    # Update the set of generators for toolset.    # TODO: should we check that generator with this id is not already    # registered. For example, the fop.jam module intentionally declared two    # generators with the same id, so such check will break it.    local id = [ $(g).id ] ;    # Some generators have multiple periods in their name, so a simple $(id:S=)    # will not generate the right toolset name. E.g. if id = gcc.compile.c++,    # then .generators-for-toolset.$(id:S=) will append to    # .generators-for-toolset.gcc.compile, which is a separate value from    # .generators-for-toolset.gcc. Correcting this makes generator inheritance    # work properly. See also inherit-generators in the toolset module.    local base = $(id) ;    while $(base:S)    {        base = $(base:B) ;    }    .generators-for-toolset.$(base) += $(g) ;    # After adding a new generator that can construct new target types, we need    # to clear the related cached viable source target type information for    # constructing a specific target type or using a specific generator. Cached    # viable source target type lists affected by this are those containing any    # of the target types constructed by the new generator or any of their base    # target types.    #    # A more advanced alternative to clearing that cached viable source target    # type information would be to expand it with additional source types or    # even better - mark it as needing to be expanded on next use.    #    # Also see the http://thread.gmane.org/gmane.comp.lib.boost.build/19077    # mailing list thread for an even more advanced idea of how we could convert    # Boost Build's Jamfile processing, target selection and generator selection    # into separate steps which would prevent these caches from ever being    # invalidated.    #    # For now we just clear all the cached viable source target type information    # that does not simply state 'all types' and may implement a more detailed    # algorithm later on if it becomes needed.    invalidate-extendable-viable-source-target-type-cache ;}# Creates a new non-composing 'generator' class instance and registers it.# Returns the created instance. Rationale: the instance is returned so that it# is possible to first register a generator and then call its 'run' method,# bypassing the whole generator selection process.#rule register-standard ( id : source-types * : target-types + : requirements * ){    local g = [ new generator $(id) : $(source-types) : $(target-types) :        $(requirements) ] ;    register $(g) ;    return $(g) ;}# Creates a new composing 'generator' class instance and registers it.#rule register-composing ( id : source-types * : target-types + : requirements *    ){    local g = [ new generator $(id) true : $(source-types) : $(target-types) :        $(requirements) ] ;    register $(g) ;    return $(g) ;}# Returns all generators belonging to the given 'toolset', i.e. whose ids are# '$(toolset).<something>'.#rule generators-for-toolset ( toolset ){    return $(.generators-for-toolset.$(toolset)) ;}# Make generator 'overrider-id' be preferred to 'overridee-id'. If, when# searching for generators that could produce a target of a certain type, both# those generators are among viable generators, the overridden generator is# immediately discarded.## The overridden generators are discarded immediately after computing the list# of viable generators but before running any of them.#rule override ( overrider-id : overridee-id ){    .override.$(overrider-id) += $(overridee-id) ;}# Returns a list of source type which can possibly be converted to 'target-type'# by some chain of generator invocation.## More formally, takes all generators for 'target-type' and returns a union of# source types for those generators and result of calling itself recursively on# source types.## Returns '*' in case any type should be considered a viable source type for the# given type.#local rule viable-source-types-real ( target-type ){    local result ;    # 't0' is the initial list of target types we need to process to get a list    # of their viable source target types. New target types will not be added to    # this list.    local t0 = [ type.all-bases $(target-type) ] ;    # 't' is the list of target types which have not yet been processed to get a    # list of their viable source target types. This list will get expanded as    # we locate more target types to process.    local t = $(t0) ;    while $(t)    {        # Find all generators for the current type. Unlike        # 'find-viable-generators' we do not care about the property-set.        local generators = $(.generators.$(t[1])) ;        t = $(t[2-]) ;        while $(generators)        {            local g = $(generators[1]) ;            generators = $(generators[2-]) ;            if ! [ $(g).source-types ]            {                # Empty source types -- everything can be accepted.                result = * ;                # This will terminate this loop.                generators = ;                # This will terminate the outer loop.                t = ;            }            for local source-type in [ $(g).source-types ]            {                if ! $(source-type) in $(result)                {                    # If a generator accepts a 'source-type' it will also                    # happily accept any type derived from it.                    for local n in [ type.all-derived $(source-type) ]                    {                        if ! $(n) in $(result)                        {                            # Here there is no point in adding target types to                            # the list of types to process in case they are or                            # have already been on that list. We optimize this                            # check by realizing that we only need to avoid the                            # original target type's base types. Other target                            # types that are or have been on the list of target                            # types to process have been added to the 'result'                            # list as well and have thus already been eliminated                            # by the previous if.                            if ! $(n) in $(t0)                            {                                t += $(n) ;                            }                            result += $(n) ;                        }                    }                }            }        }    }    return $(result) ;}# Helper rule, caches the result of 'viable-source-types-real'.#rule viable-source-types ( target-type ){    local key = .vst.$(target-type) ;    if ! $($(key))    {        .vst-cached-types += $(target-type) ;        local v = [ viable-source-types-real $(target-type) ] ;        if ! $(v)        {            v = none ;        }        $(key) = $(v) ;    }    if $($(key)) != none    {        return $($(key)) ;    }}# Returns the list of source types, which, when passed to 'run' method of

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -