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

📄 virtual-target.jam

📁 C++的一个好库。。。现在很流行
💻 JAM
📖 第 1 页 / 共 3 页
字号:
#  Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and
#  distribute this software is granted provided this copyright notice appears in
#  all copies. This software is provided "as is" without express or implied
#  warranty, and with no claim as to its suitability for any purpose.

#  Implements virtual targets, which correspond to actual files created during
#  build, but are not yet targets in Jam sense. They are needed, for example,
#  when searching for possible transormation sequences, when it's not known
#  if particular target should be created at all.

import "class" : new ;
import path property-set utility sequence errors set type os ;

#                       +--------------------------+
#                       | virtual-target           |
#                       +==========================+
#                       | actualize                |
#                       +--------------------------+
#                       | actualize-action() = 0   |
#                       | actualize-location() = 0 |
#                       +----------------+---------+
#                                        |
#                                        ^
#                                       / \
#                                      +-+-+
#                                        |
#    +---------------------+     +-------+--------------+
#    | action              |     | abstract-file-target |
#    +=====================|   * +======================+
#    | action-name         |  +--+ action               |
#    | properties          |  |  +----------------------+
#    +---------------------+--+  | actualize-action()   |
#    | actualize()         |0..1 +-----------+----------+
#    | path()              |                 |
#    | adjust-properties() | sources         |
#    | actualize-sources() | targets         |
#    +------+--------------+                 ^
#           |                               / \
#           ^                              +-+-+
#          / \                               |
#         +-+-+                +-------------+-------------+
#           |                  |                           |
#           |           +------+---------------+  +--------+-------------+
#           |           | file-target          |  | searched-lib-target  |
#           |           +======================+  +======================+
#           |           | actualize-location() |  | actualize-location() |
#           |           +----------------------+  +----------------------+
#           |
#         +-+------------------------------+
#         |                                |
#    +----+----------------+     +---------+-----------+
#    | compile-action      |     | link-action         |
#    +=====================+     +=====================+
#    | adjust-properties() |     | adjust-properties() |
#    +---------------------+     | actualize-sources() |
#                                +---------------------+
#
# The 'compile-action' and 'link-action' classes are defined not here,
# but in builtin.jam modules. They are shown in the diagram to give
# the big picture.

# Potential target. It can be converted into jam target and used in
# building, if needed. However, it can be also dropped, which allows
# to search for different transformation and select only one.
#
class virtual-target 
{
    import virtual-target utility scanner ;    
    
    rule __init__ ( name  # Name of this target -- specifies the name of
        : project # Project to which this target belongs
    )
    {    
        self.name = $(name) ;
        self.project = $(project) ;
        self.dependencies = ;
    }
    
    # Name of this target.
    rule name ( ) { return $(self.name) ; }

    # Project of this target.
    rule project ( ) { return $(self.project) ; }

    # Adds additional instances of 'virtual-target' that this
    # one depends on.
    rule depends ( d + )
    {
        self.dependencies = [ sequence.merge $(self.dependencies)
                               : [ sequence.insertion-sort $(d) ] ] ;
    }

    rule dependencies ( )
    {
        return $(self.dependencies) ;
    }

    # 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.
    rule actualize ( scanner ? )
    {
        local actual-name = [ actualize-no-scanner ] ;

        if ! $(scanner)
        {
            return $(actual-name) ;
        }
        else
        {
            # Add the scanner instance to the grist for name.
            local g = [ sequence.join
                [ utility.ungrist $(actual-name:G) ] $(scanner) : - ] ;
            local name = $(actual-name:G=$(g)) ;

            if ! $(self.made.$(name)) {
                self.made.$(name) = true ;

                DEPENDS $(name) : $(actual-name) ;

                actualize-location $(name) ;

                scanner.install $(scanner) : $(name) $(__name__) ;
            }
            return $(name) ;
        }

    }

# private: (overridables)

    # Sets up build actions for 'target'. Should call appropriate rules
    # and set target variables.
    rule actualize-action ( target )
    {
        errors.error "method should be defined in derived classes" ;
    }

    # Sets up variables on 'target' which specify its location.
    rule actualize-location ( target )
    {
        errors.error "method should be defined in derived classes" ;
    }
    
    # If the target is generated one, returns the path where it will be
    # generated. Otherwise, returns empty list.
    rule path ( )
    {
        errors.error "method should be defined in derived classes" ;        
    }
    
    # Return that actual target name that should be used
    # (for the case where no scanner is involved)
    rule actual-name ( )
    {
        errors.error "method should be defined in derived classes" ;
    }

# implementation
    rule actualize-no-scanner ( )
    {
        local name = [ actual-name ] ;

        # Do anything only on the first invocation
        if ! $(self.made.$(name)) {
            self.made.$(name) = true ;
            
            virtual-target.register-actual-name $(name) : $(__name__) ;            

            for local i in $(self.dependencies) {
                DEPENDS $(name) : [ $(i).actualize ] ;
            }

            actualize-location $(name) ;
            actualize-action $(name) ;
        }
        return $(name) ;
    }


}


# Target which correspond to a file. The exact mapping for file
# is not yet specified in this class. (TODO: Actually, the class name
# could be better...)
#
# May be a source file (when no action is specified), or
# derived file (otherwise).
#
# The target's grist is concatenation of project's location,
# properties of action (for derived files), and, optionally,
# value identifying the main target.
class abstract-file-target : virtual-target
{
    import project regex sequence path type ;
    import property-set ;
    import indirect ;
    
    rule __init__ ( 
         name     # Name for this target
        exact ?   # If non-empty, the name is exactly the name
                  # created file should have. Otherwise, the '__init__'
                  # method will add suffix obtained from 'type' by
                  # calling 'type.generated-target-suffix'.
        : type ?  # The type of this target.
        : project
        : action ?
    )
    {
        virtual-target.__init__ $(name) : $(project) ;
            
        self.type = $(type) ;
        self.action = $(action) ;
        if $(action)
        {         
            $(action).add-targets $(__name__) ;

            if $(self.type) && ! $(exact)              
            {                
                _adjust-name $(name) ;
            }            
        }        
    }
    
    rule type ( ) { return $(self.type) ; }

    # Sets the path. When generating target name, it will override any path
    # computation from properties.
    rule set-path ( path )
    {
        self.path = [ path.native $(path) ] ;
    }

    # If 'a' is supplied, sets action to 'a'.
    # Returns the action currently set.
    rule action ( )
    {
        return $(self.action) ;
    }

    # Sets/gets the 'root' flag. Target is root is it directly correspods to some
    # variant of a main target.
    rule root ( set ? )
    {
        if $(set)
        {
            self.root = true ;
        }
        return $(self.root) ;
    }
    
    # Gets or sets the subvariant which created this target. Subvariant
    # is set when target is brought into existance, and is never changed
    # after that. In particual, if target is shared by subvariant, only 
    # the first is stored.    
    rule creating-subvariant ( s ? # If specified, specified the value to set,
                                   # which should be instance of 'subvariant'
                                   # class.
                             )
    {
        if $(s) && ( ! $(self.creating-subvariant) && ! $(overwrite) )
        {
            if $(self.creating-subvariant)
            {
                errors.error "Attempt to change 'dg'" ;
            }
            else
            {                
                self.creatin-subvariant = $(s) ;
            }            
        }
        return $(self.creatin-subvariant) ;
    }

    rule actualize-action ( target )
    {
        if $(self.action)
        {
            $(self.action).actualize ;
        }
    }
          
    # Return a human-readable representation of this target
    #
    # If this target has an action, that's:
    #
    #    { <action-name>-<self.name>.<self.type> <action-sources>... }
    #
    # otherwise, it's:
    #
    #    { <self.name>.<self.type> }
    #
    rule str ( )
    {
        local action = [ action ] ;
        
        local name-dot-type = [ sequence.join $(self.name) "."  $(self.type) ] ;
        
        if $(action)
        {
            local sources = [ $(action).sources ] ;
            
            local action-name =  [ $(action).action-name ] ;            

            local ss ;            
            for local s in $(sources)
            {
                ss += [ $(s).str ] ;
            }
            
            return "{" $(action-name)-$(name-dot-type) $(ss) "}" ;
        }
        else
        {
            return "{" $(name-dot-type) "}" ;
        }
    }

    rule less ( a )
    {
        if [ str ] < [ $(a).str ]
        {
            return true ;
        }
    }

    rule equal ( a )
    {
        if [ str ] = [ $(a).str ]
        {
            return true ;
        }
    }

# private:
    rule actual-name ( )
    {
        if ! $(self.actual-name)
        {            
            local grist = [ grist ] ;

            local basename = [ path.native $(self.name) ] ;
            self.actual-name = <$(grist)>$(basename) ;
            
        }
        return $(self.actual-name) ;
    }
        
    # Helper to 'actual-name', above. Compute unique prefix used to distinguish
    # this target from other targets with the same name which create different
    # file.
    rule grist ( )
    {
        # Depending on target, there may be different approaches to generating
        # unique prefixes. We'll generate prefixes in the form 
        # <one letter approach code> <the actual prefix>
        local path = [ path ] ;
        if $(path)
        {
            # The target will be generated to a known path. Just use the path

⌨️ 快捷键说明

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