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

📄 generators.jam

📁 C++的一个好库。。。现在很流行
💻 JAM
📖 第 1 页 / 共 3 页
字号:
    # 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 if foo.z, then created files would
    # be "foo.t1" and "foo_x.t2". The 'name' attribute actually determined the
    # basename of a file.
    #
    # Note that this pattern mechanism has nothing to do with implicit patterns
    # in make. It's a way to produce target which name is different for name of 
    # source.
    rule generated-targets ( sources + : property-set : project name ? )
    {
        if ! $(name)
        {
            # Determine the name of the produced target from the
            # names of the 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
            # - A type which suffix has a dot. Say, we can
            #   type 'host_cpp' with extension 'host.cpp'.
            # In the first case, we want to take the part till the last
            # dot. In the second case -- no sure, but for now take
            # the part till 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)
                {
                    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=) ;
        }
        
        # 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 'source' to the types that this generator can
    # handle. The intention is to produce the set of targets can should be
    # used when generator is run.
    rule convert-to-consumable-types ( project name ? : 
        property-set : sources +  
        : only-one ? # convert 'source' to only one of source types
                     # if there's more that one possibility, report an
                     # error 
        : consumed-var # name of variable which recieves all targets which 
                       # can be consumed. 
          bypassed-var # name variable which recieves all targets which 
                       # cannot be consumed  
    )
    {        
        # We're likely to be passed 'consumed' and 'bypassed'
        # var names. Use "_" to avoid name conflicts.
        local _consumed ;
        local _bypassed ;
        local missing-types ; 

        if $(sources[2])
        {
            # Don't 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 consuned/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's 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 don't 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' won't allow two different
        # instances. Therefore, it's OK to use 'set.difference'.
        
        _bypassed = [ set.difference $(_bypassed) : $(_consumed) ] ;
        
                
        $(consumed-var) += $(_consumed) ;
        $(bypassed-var) += $(_bypassed) ;
    }
    
    # Converts several files to consumable types.
    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.
        local failed ;
        while $(sources) && ! $(failed)
        {
            local _c ;
            local _b ;
            # TODO: need to check for failure on each source.
            convert-to-consumable-types $(project) : $(property-set)
              : $(sources[1]) : true : _c _b ;
            if ! $(_c)
            {
                generators.dout [ indent ] " failed to convert " $(sources[1]) ;
                # failed = true ;
            }
            $(consumed-var) += $(_c) ;            
            $(bypassed-var) += $(_b) ;
            sources = $(sources[2-]) ;
        }           
        if $(failed)
        {
            $(consumed-var) = ;
            $(bypassed-var) = ;
        }        
    }
        
    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 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" ;
    }        
}

import errors : error ;

.generators = ;

# Registers new generator instance 'g'.
rule register ( g )
{
    .generators += $(g) ;
                   
    for local t in [ $(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 the
    # normal $(id:S=) won't 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 module toolset
    local base = $(id) ;
    while $(base:S)
    {
        base = $(base:B) ;
    }
    .generators-for-toolset.$(base) += $(g) ;
}
    
# Creates new instance of the 'generator' class and registers it.
# Retursn the creates instance.
# Rationale: the instance is returned so that it's possible to first register
# a generator and then call 'run' method on that generator, bypassing all
# generator selection.
rule register-standard ( id : source-types * : target-types + : requirements * )

{
    local g = [ new generator $(id) : $(source-types) : $(target-types)
      : $(requirements) ] ;
    register $(g) ;   
    return $(g) ;
}

# Creates new instance of the 'composing-generator' class 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 which belong to 'toolset', i.e. which
# ids are $(toolset).<something>
rule generators-for-toolset ( toolset )
{
    return $(.generators-for-toolset.$(toolset)) ;
}

rule override ( overrider-id : overridee-id )
{
    .override.$(overrider-id) += $(overridee-id) ;    
}



    
# Set if results of the current generators search are going to be cached
# This means no futher attempts to cache generators search should be
# made.
.caching = ;

# 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 union of source types for those generators and result
# of calling itself recusrively on source types.
local rule viable-source-types-real ( target-type )
{
    local generators ;

    local t = [ type.all-bases $(target-type) ] ;
    
    local result ;
    # 't' is the list of types which are not yet processed    
    while $(t)
    {
        # Find all generators for current type. 
        # Unlike 'find-viable-generators' we don't care about 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 outer loop.
                t = ;
            }
              
            for local source-type in [ $(g).source-types ] 
            {
                if ! $(source-type) in $(result) 
                {
                    # If generator accepts 'source-type' it
                    # will happily accept any type derived from it
                    local all = [ type.all-derived $(source-type) ] ;
                    for local n in $(all)
                    {
                        if ! $(n) in $(result)
                        {   
                            t += $(n) ;
                            result += $(n) ;
                        }    
                    }                    
                }                
            }            
        }        
    }          
        
    result = [ sequence.unique $(result) ] ;
    
    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))
    {
        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 'generator', has some change of being eventually used

⌨️ 快捷键说明

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