# Copyright (c) 2010 Vladimir Prus.
#
# Use, modification and distribution is subject to the Boost Software
# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
# http://www.boost.org/LICENSE_1_0.txt)

# This module defines function to help with two main tasks:
#
# - Discovering build-time configuration for the purposes of adjusting
#   build process.  
# - Reporting what is built, and how it is configured.

import targets ; 
import errors ;
import targets ;
import sequence ;
import property ;
import property-set ;
import "class" : new ;

rule log-summary ( )
{
    
}

.width = 30 ;

rule set-width ( width )
{
    .width = $(width) ;
}

# Declare that the components specified by the parameter exist.
rule register-components ( components * )
{
    .components += $(components) ;
}

# Declare that the components specified by the parameters will
# be build.
rule components-building ( components * )
{
    .built-components += $(components) ;
}

# Report something about component configuration that the
# user should better know.
rule log-component-configuration ( component : message )
{
    # FIXME: implement per-property-set logs
    .component-logs.$(component) += $(message) ;
}



rule log-check-result ( result )
{
    if ! $(.announced-checks)
    {
        ECHO "Performing configuration checks\n" ;
        .announced-checks = 1 ;
    }
    
    ECHO $(result) ;    
    #.check-results += $(result) ;
}

rule log-library-search-result ( library : result )
{
    local x = [ PAD "    - $(library) : $(result)" : $(.width) ] ;
    log-check-result "$(x)" ;
}

rule print-component-configuration ( )
{
    local c = [ sequence.unique $(.components) ] ;
    
    ECHO "\nComponent configuration:\n" ;
    for c in $(.components)
    {
        local s ;
        if $(c) in $(.built-components)
        {
            s = "building" ;
        }
        else
        {
            s = "not building" ;
        }
        ECHO [ PAD "    - $(c)" : $(.width) ] ": $(s)" ;
        for local m in $(.component-logs.$(c))
        {
            ECHO "        -" $(m) ;
        }        
    }
    ECHO ;
}

rule print-configure-checks-summary ( )
{
    # FIXME: the problem with that approach is tha
    # the user sees checks summary when all checks are
    # done, and has no progress reporting while the
    # checks are being executed.    
    if $(.check-results)
    {        
        ECHO "Configuration checks summary\n" ;
    
        for local r in $(.check-results)
        {
            ECHO $(r) ;
        }
        ECHO ;
    }    
}

# Attempt to build a metatarget named by 'metatarget-reference'
# in context of 'project' with properties 'ps'.
# Returns non-empty value if build is OK.
rule builds-raw ( metatarget-reference : project : ps : what : retry ? )
{   
    local result ;
           
    if ! $(retry) && ! $(.$(what)-tested.$(ps))
    {        
        .$(what)-tested.$(ps) = true ;
        
        local targets = [ targets.generate-from-reference 
            $(metatarget-reference) : $(project) : $(ps) ] ;
        
        local jam-targets ;
        for local t in $(targets[2-])
        {
            jam-targets += [ $(t).actualize ] ;
        }
                    
        if ! UPDATE_NOW in [ RULENAMES ]
        {
            # Cannot determine. Assume existance.
        }
        else 
        {           
            local x = [ PAD "    - $(what)" : $(.width) ] ;            
            if [ UPDATE_NOW $(jam-targets) :
                 $(.log-fd) : ignore-minus-n : ignore-minus-q ] 
            {
                .$(what)-supported.$(ps) = yes ;
                result = true ;
                log-check-result "$(x) : yes" ;
            }        
            else
            {
                log-check-result "$(x) : no" ;
            }
        }        
        return $(result) ;
    }    
    else
    {
        return $(.$(what)-supported.$(ps)) ;
    }
}

rule builds ( metatarget-reference : properties * : what ? : retry ? )
{
    what ?= "$(metatarget-reference) builds" ;
    
    # FIXME: this should not be hardcoded. Other checks might
    # want to consider different set of features as relevant.
    local toolset = [ property.select <toolset> : $(properties) ] ;
    local toolset-version-property = "<toolset-$(toolset:G=):version>" ;
    local relevant = [ property.select <target-os> <toolset> $(toolset-version-property)
      <address-model> <architecture>
      : $(properties) ] ;
    local ps = [ property-set.create $(relevant) ] ;        
    local t = [ targets.current ] ;
    local p = [ $(t).project ] ;

    return [ builds-raw $(metatarget-reference) : $(p) : $(ps) : $(what) : $(retry) ] ;
}


# Called by Boost.Build startup code to specify name of a file
# that will receive results of configure checks.  This
# should never be called by users.
rule set-log-file ( log-file )
{
    # FIXME: remove this check as soon as Boost regression tests
    # start using trunk bjam
    if FILE_OPEN in [ RULENAMES ]
    {        
        .log-fd = [ FILE_OPEN $(log-file) : "w" ] ;
    }    
}

# Frontend rules

class check-target-builds-worker
{
    import configure ;
    import property-set ;
    import targets ;
    import property ; 
    
    rule __init__ ( target message ? : true-properties * : false-properties * )    
    {
        self.target = $(target) ;
        self.message = $(message) ;     
        self.true-properties = $(true-properties) ;
        self.false-properties = $(false-properties) ;
    }
        
    rule check ( properties * )
    {
        local choosen ;
        if [ configure.builds $(self.target) : $(properties) : $(self.message) ]
        {
            choosen = $(self.true-properties) ;
        }        
        else
        {
            choosen = $(self.false-properties) ;
        }        
        return [ property.evaluate-conditionals-in-context $(choosen) : $(properties) ] ;
    }    
}


rule check-target-builds ( target message ? : true-properties * : false-properties * )
{
    local instance = [ new check-target-builds-worker $(target) $(message) : $(true-properties)
      : $(false-properties) ] ;
    return <conditional>@$(instance).check ;
}

IMPORT $(__name__) : check-target-builds :  : check-target-builds ;


