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

📄 targets.jam

📁 boost库提供标准的C++ API 配合dev 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.


#   Supports 'abstract' targets, which are targets explicitly defined in Jamfile.
#
#   Abstract targets are represented by classes derived from 'abstract-target' class. 
#   The first abstract target is 'project-target', which is created for each
#   Jamfile, and can be obtained by the 'target' rule in the Jamfile's module.
#   (see project.jam). 
#
#   Project targets keep a list of 'main-target' instances.
#   A main target is what the user explicitly defines in a Jamfile. It is
#   possible to have several definitions for a main target, for example to have
#   different lists of sources for different platforms. So, main targets
#   keep a list of alternatives.
#
#   Each alternative is an instance of 'abstract-target'. When a main target
#   subvariant is defined by some rule, that rule will decide what class to
#   use, create an instance of that class and add it to the list of alternatives
#   for the main target.
#
#   Rules supplied by the build system will use only targets derived
#   from 'basic-target' class, which will provide some default behaviour.
#   There will be two classes derived from it, 'make-target', created by the
#   'make' rule, and 'typed-target', created by rules such as 'exe' and 'dll'.

#
#                         +------------------------+
#                         |abstract-target         |
#                         +========================+
#                         |name                    |
#                         |project                 |                                   
#                         |                        |                                   
#                         |generate(properties) = 0|                                   
#                         +-----------+------------+                                   
#                                     |                                                
#                                     ^                                                
#                                    / \                                               
#                                   +-+-+                                              
#                                     |                                                
#                                     |                                                
#            +------------------------+------+------------------------------+          
#            |                               |                              |          
#            |                               |                              |          
# +----------+-----------+            +------+------+                +------+-------+  
# | project-target       |            | main-target |                | basic-target |  
# +======================+ 1        * +=============+  alternatives  +==============+  
# | generate(properties) |o-----------+ generate    |<>------------->| generate     |  
# | main-target          |            +-------------+                | construct = 0|
# +----------------------+                                           +--------------+  
#                                                                           |          
#                                                                           ^          
#                                                                          / \         
#                                                                         +-+-+        
#                                                                           |          
#                                                                           |          
#                 ...--+----------------+------------------+----------------+---+      
#                      |                |                  |                    |      
#                      |                |                  |                    |      
#               ... ---+-----+   +------+-------+   +------+------+    +--------+-----+
#                            |   | typed-target |   | make-target |    | stage-target |
#                            .   +==============+   +=============+    +==============+
#                            .   | construct    |   | construct   |    | construct    |
#                                +--------------+   +-------------+    +--------------+

import "class" : new ;
import sequence ;
import regex ;
import property ;
import errors ;
import common ;
import property-set ;
import project ;
import feature ;
import virtual-target ;
import path ;
import set ;

# Base class for all abstract targets.
class abstract-target 
{
    import project ;    
    
    rule __init__ ( name      # name of the target in Jamfile
        : project # the project module where the target is declared
    )
    {        
        # Note: it might seem that we don't need either name or project at all.
        # However, there are places where we really need it. One example is error
        # messages which should name problematic targets. Another is setting correct
        # paths for sources and generated files.
        
        self.name = $(name) ;
        self.project = $(project) ;
    }    
    
    # Returns the name of this target.
    rule name ( )
    {
        return $(self.name) ;
    }
    
    # Returns the project for this target.
    rule project ( )
    {
        return $(self.project) ;
    }
        
    # Returns a user-readable name for this target.
    rule full-name ( )
    {
        local location = [ project.attribute $(self.project) location ] ;
        return $(location)/$(self.name) ;
    }
        
    # Takes properties in split form ("<feature1>foo <feature2>bar").
    # Generates virtual targets for this abstract target, using the specified properties,
    # unless a different value of some feature is required by the target. The properties
    # on returned virtual targets should be link-compatible with the requested ones.
    #
    # On success, returns: 
    # - a property-set with the usage requirements to be applied to dependents
    # - a list of produced virtual targets, which may be empty.
    #
    # If 'properties' are empty, performs default build of this target, in a way specific
    # to derived class.
    rule generate ( property-set )
    {
        errors.error "method should be defined in derived classes" ;
    }
    
    rule rename ( new-name )
    {
        self.name = $(new-name) ;
    }        
}

#  Project target class (derived from 'abstract-target')
#
#  This class these responsibilities:
#  - maintaining a list of main target in this project and
#    building it
#
#  Main targets are constructed in two stages:
#  - When Jamfile is read, a number of calls to 'add-alternative' is made.
#    At that time, alternatives can also be renamed to account for inline
#    targets.
#  - The first time 'main-target' or 'has-main-target' rule is called,
#    all alternatives are enumerated an main targets are created.
class project-target : abstract-target 
{
    import project targets ;
    import path ;
    import print ;
    import property-set ;
    import set : difference : set.difference ;
    import sequence ;
    import "class" : new ;
        
    rule __init__ ( name : project : requirements * : default-build * )
    {    
        abstract-target.__init__ $(name) : $(project) ;
        
        self.requirements = $(requirements) ;
        self.default-build = $(default-build) ;
    }
    
    # Generates all possible targets contained in this project.
    rule generate ( property-set * )
    {
        local usage-requirements = [ property-set.empty ] ;
        local targets ;
        
        for local t in [ targets-to-build ] 
        {
            local g = [ $(t).generate $(property-set) ] ;
            usage-requirements = [ $(usage-requirements).add $(g[1]) ] ;
            targets += $(g[2-]) ;
        }
        return $(usage-requirements) [ sequence.unique $(targets) ] ;        
    }
        
    # Computes and returns a list of abstract-target instances which
    # must be built when this project is built.
    rule targets-to-build ( )
    {
        local result ;
        
        if ! $(self.built-main-targets)
        {
            build-main-targets ;
        }
        
        # Collect all main targets here, except for "explicit" ones.
        for local t in $(self.main-targets)
        {
            if ! [ $(t).name ] in $(self.explicit-targets)
            {                    
                result += $(t) ;
            }
        }

        # Collect all projects referenced via "projects-to-build" attribute.
        local self-location = [ project.attribute $(self.project) location ] ;
        for local pn in [ project.attribute $(self.project) projects-to-build ]
        {
            local p = [ project.module-name [ path.join $(self-location) $(pn) ] ] ;
            result += [ project.target $(p) ] ;
        }
                        
        return $(result) ;
    }
    
    # Add 'target' to the list of targets in this project that should be build
    # only by explicit request
    rule mark-target-as-explicit ( target-name )
    {
        # Record the name of the target, not instance, since this
        # rule is called before main target instaces are created.
        self.explicit-targets += $(target-name) ;
    }
    
    # Add new target alternative
    rule add-alternative ( target-instance )
    {
        if $(self.built-main-targets)
        {
            errors.error "add-alternative called when main targets are already created." ;
        }        
        self.alternatives += $(target-instance) ;
    }
    
            
    # Returns a 'main-target' class instance corresponding to the 'name'.
    rule main-target ( name )
    {
        if ! $(self.built-main-targets)
        {
            build-main-targets ;
        }
                        
        return $(self.main-target.$(name)) ;
    }

    # Tells if a main target with the specified name exists.
    rule has-main-target ( name )
    {
        if ! $(self.built-main-targets)
        {
            build-main-targets ;
        }
        
        if $(self.main-target.$(name)) 
        {
            return true ;
        } 
    }
    
    rule build-main-targets ( )
    {
        self.built-main-targets = true ;
        for local a in $(self.alternatives)
        {
            local name = [ $(a).name ] ;
            local target = $(self.main-target.$(name)) ;
            if ! $(target)
            {
                local t = [ new main-target $(name) : $(self.project) ] ;
                self.main-target.$(name) = $(t) ;
                self.main-targets += $(t) ;
                target = $(self.main-target.$(name)) ;
            }
            
            $(target).add-alternative $(a) ;            
        }    
    }                            
}


# Helper rules to detect cycles in main target references
local rule start-building ( main-target-instance )
{
    if $(main-target-instance) in $(.targets-being-built)
    {
        local names ;
        for local t in $(.targets-being-built) $(main-target-instance)
        {
            names += [ $(t).full-name ] ;
        }
        
        errors.error "Recursion in main target references" 
          : "the following target are being built currently:"
          : $(names) ;
    }
    .targets-being-built += $(main-target-instance) ;    
}

local rule end-building ( main-target-instance )
{
    .targets-being-built = $(.targets-being-built[1--2]) ;
}


# A named top-level target in Jamfile
class main-target : abstract-target
{
    import errors : error ;
    import assert ;
    import sequence ;    
    import print ;
    import build-request feature property-set ;
    import targets : start-building end-building ;
    import "class" : is-a ;
        
    rule __init__ ( name : project )
    {
        abstract-target.__init__ $(name) : $(project) ;
    }
    
        
    # Add a new alternative for this target
    rule add-alternative ( target )
    {
        local d = [ $(target).default-build ] ;
        if $(self.alternatives) && ( $(self.default-build) != $(d) )
        {
            errors.error "default build must be identical in all alternatives"
              : "main target is" [ full-name ]
              : "with" [ $(d).raw ]
              : "differing from previous default build" [ $(self.default-build).raw ] ;
        }
        else
        {
            self.default-build = $(d) ;
        }        
        self.alternatives += $(target) ;
    }

    # Returns the best viable alternative for this property-set
    # See the documentation for selection rules.
    local rule select-alternatives ( property-set )
    {
        # The algorithm: we keep the current best viable alternative.
        # When we've got new best viable alternative, we compare it
        # with the current one. 
        
        local best ;
        local best-properties ;
                        
        if $(self.alternatives[2-])
        {
            local bad ;
            local worklist = $(self.alternatives) ;    
            while $(worklist) && ! $(bad)
            {
                local v = $(worklist[1]) ; 
                local properties = [ $(v).match $(property-set) ] ;
                           
                if $(properties) != no-match
                {                                    
                    if ! $(best)
                    {
                        best = $(v) ;
                        best-properties = $(properties) ;
                    }
                    else
                    {                                                   
                        if $(properties) = $(best-properties)
                        {
                            bad = true ;
                        }
                        else if $(properties) in $(best-properties) 
                        {
                            # Do nothing, this alternative is worse
                        }
                        else if $(best-properties) in $(properties)
                        {
                            best = $(v) ;
                            best-properties = $(properties) ;
                        }
                        else 
                        {
                            bad = true ;
                        }                                                
                    }
                }
                worklist = $(worklist[2-]) ;                
            }
            if ! $(bad)
            {
                return $(best) ;
            }                                    
        }
        else
        {
            return $(self.alternatives) ;

⌨️ 快捷键说明

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