# Copyright 2003 Dave Abrahams 
# Copyright 2003, 2005, 2006 Rene Rivera 
# Copyright 2003, 2005, 2006 Vladimir Prus 
# Distributed under the Boost Software License, Version 1.0. 
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) 

# First of all, check the jam version

if $(JAM_VERSION:J="") < 030112
{
    ECHO "error: Boost.Jam version 3.1.12 or later required" ;
    EXIT ;
}

local required-rules = GLOB-RECURSIVELY HAS_NATIVE_RULE ;

for local r in $(required-rules)
{
    if ! $(r) in [ RULENAMES ]
    {
        ECHO "error: builtin rule '$(r)' is not present" ;
        ECHO "error: your version of bjam is likely out of date" ;
        ECHO "error: please get a fresh version from SVN." ;
        EXIT ;
    }
}

local native =
    regex transform 2
    ;
while $(native)
{
    if ! [ HAS_NATIVE_RULE $(native[1]) :
                           $(native[2]) :
               $(native[3]) ]
    {
        ECHO "error: missing native rule '$(native[1]).$(native[2])'" ;
        ECHO "error: or interface version of that rule is too low" ;
        ECHO "error: your version of bjam is likely out of date" ;
        ECHO "error: please get a fresh version from SVN." ;
        EXIT ;
    }
    native = $(native[4-]) ;
}

# Check that the builtin .ENVIRON module is present. We don't have a
# builtin to check that a module is present, so we assume that the PATH
# environment variable is always set and verify that the .ENVIRON module
# has non-empty value of that variable.
module .ENVIRON
{
    local p = $(PATH) $(Path) $(path) ;
    if ! $(p)
    {
        ECHO "error: no builtin module .ENVIRON is found" ;
        ECHO "error: your version of bjam is likely out of date" ;
        ECHO "error: please get a fresh version from SVN." ;
        EXIT ;
    }
}

# Check that @() functionality is present. Similarly to modules,
# we don't have a way to test that directly. Instead we check that
# $(TMPNAME) functionality is present which was added at roughly
# the same time (more precisely it was added just before).
{
    if ! $(TMPNAME)
    {
        ECHO "error: no @() functionality found" ;
        ECHO "error: your version of bjam is likely out of date" ;
        ECHO "error: please get a fresh version from SVN." ;
        EXIT ;
    }
}

# Make sure that \n escape is avaiable.
if "\n" = "n"
{
    if $(OS) = CYGWIN 
    {        
        ECHO "warning: escape sequences are not supported" ;
        ECHO "warning: this will cause major misbehaviour on cygwin" ;
        ECHO "warning: your version of bjam is likely out of date" ;
        ECHO "warning: please get a fresh version from SVN." ;
    }    
}

# Bootstrap the module system. Then bring the import rule into the global module.
#
SEARCH on <module@>modules.jam = $(.bootstrap-file:D) ;
module modules { include <module@>modules.jam ; }
IMPORT modules : import : : import ;

{
    # Add module subdirectories to the BOOST_BUILD_PATH, which allows
    # us to make an incremental refactoring step by moving modules to
    # the appropriate subdirectories, thereby achieving some physical
    # separation of different layers without changing all of our code
    # to specify subdirectories in import statements or use an extra
    # level of qualification on imported names.

    local subdirs =
      kernel        # only the most-intrinsic modules: modules, errors
      util          # low-level substrate: string/number handling, etc.
      build         # essential elements of the build system architecture
      tools         # toolsets for handling specific build jobs and targets.
      contrib       # user contributed (unreviewed) modules
      .             # build-system.jam lives here
      ;
    local whereami = [ NORMALIZE_PATH $(.bootstrap-file:DT) ] ;
    BOOST_BUILD_PATH += $(whereami:D)/$(subdirs) ;

    modules.poke .ENVIRON : BOOST_BUILD_PATH : $(BOOST_BUILD_PATH) ;
    
    modules.poke : EXTRA_PYTHONPATH : $(whereami) ;
}

# Reload the modules, to clean up things. The modules module can tolerate
# being included twice.
#
import modules ;

# Process option plugins first to alow them to prevent loading
# the rest of the build system.
#
import option ;
local dont-build = [ option.process ] ;

# Should we skip building, i.e. loading the build system, according
# to the options processed?
#
if ! $(dont-build)
{
    if ! --python in $(ARGV)
    {
        # Allow users to override the build system file from the
        # command-line (mostly for testing)
        local build-system = [ MATCH --build-system=(.*) : $(ARGV) ] ;
        build-system ?= build-system ;

        # Use last element in case of multiple command-line options
        import $(build-system[-1]) ;
    }
    else
    {
        ECHO "Boost.Build V2 Python port (experimental)" ;
                
        # Define additional interface that is exposed to Python code. Python code will
        # also have access to select bjam builtins in the 'bjam' module, but some
        # things are easier to define outside C.
        module python_interface
        {
            rule load ( module-name : location )
            {        
                USER_MODULE $(module-name) ;
	        # Make all rules in the loaded module available in
	        # the global namespace, so that we don't have
	        # to bother specifying "right" module when calling
	        # from Python.
                module $(module-name)
                {
                    __name__ = $(1) ;
                    include $(2) ;
                    local rules = [ RULENAMES $(1) ] ;
                    IMPORT $(1) : $(rules) : $(1) : $(1).$(rules) ;
                }
            }    
            
            rule peek ( module-name ? : variables + )
            {
                module $(<)
                {
                    return $($(>)) ;
                }
            }
            
            rule set-variable ( module-name : name : value * )
            {
                module $(<)
                {
                    $(>) = $(3) ;
                }        
            }
            
            rule set-top-level-targets ( targets * )
            {
                DEPENDS all : $(targets) ;
            }
            
            rule call-in-module ( m : rulename : * )
            {
                module $(m)
                {
                    return [ $(2) $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
                }                
            }

            
            rule set-update-action ( action : targets * : sources * : properties * )
            {
                $(action) $(targets) : $(sources) : $(properties) ;
            }
            
            rule set-update-action-in-module ( m : action : targets * : sources * : properties * )
            {
                module $(m)
                {
                    $(2) $(3) : $(4) : $(5) ;
                }                
            }
                        
            rule set-target-variable ( targets + : variable : value * : append ? )
            {
                if $(append)
                {            
	            $(variable) on $(targets) += $(value) ;
                }
                else
                {
	            $(variable) on $(targets) = $(value) ;            
                }        
            }        

            rule get-target-variable ( targets + : variable )
            {
                return [ on $(targets) return $($(variable)) ] ;
            }

            rule import-rules-from-parent ( parent-module : this-module : user-rules * )
            {
                IMPORT $(parent-module) : $(user-rules) : $(this-module) : $(user-rules) ;
                EXPORT $(this-module) : $(user-rules) ;
            }

            rule mark-included ( targets * : includes * ) {
                NOCARE $(includes) ;
                INCLUDES $(targets) : $(includes) ;
                ISFILE $(includes) ;
            }
        }

        PYTHON_IMPORT_RULE bootstrap : bootstrap : PyBB : bootstrap ;
        modules.poke PyBB : root : [ NORMALIZE_PATH $(.bootstrap-file:DT)/.. ] ;
        
        module PyBB
        {
            local ok = [ bootstrap $(root) ] ;
            if ! $(ok)
            {
                EXIT ;
            }            
        }
        
        
        #PYTHON_IMPORT_RULE boost.build.build_system : main : PyBB : main ;

        #module PyBB
        #{    
        #    main ;
        #}

    }
}
