# Status: being ported by Vladimir Prus
# Base revision: 42507

# Copyright 2002, 2003 Dave Abrahams 
# Copyright 2002, 2005, 2006 Rene Rivera 
# Copyright 2002, 2003, 2004, 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) 

#  Implements project representation and loading.
#   Each project is represented by 
#   - a module where all the Jamfile content live. 
#   - an instance of 'project-attributes' class.
#     (given module name, can be obtained by 'attributes' rule)
#   - an instance of 'project-target' class (from targets.jam)
#     (given a module name, can be obtained by 'target' rule)
#
#  Typically, projects are created as result of loading Jamfile, which is
#  do by rules 'load' and 'initialize', below. First, module for Jamfile
#  is loaded and new project-attributes instance is created. Some rules
#  necessary for project are added to the module (see 'project-rules' module)
#  at the bottom of this file.
#  Default project attributes are set (inheriting attributes of parent project, if
#  it exists). After that, Jamfile is read. It can declare its own attributes,
#  via 'project' rule, which will be combined with already set attributes.
#
#
#  The 'project' rule can also declare project id, which will be associated with 
#  the project module.
#
#  There can also be 'standalone' projects. They are created by calling 'initialize'
#  on arbitrary module, and not specifying location. After the call, the module can
#  call 'project' rule, declare main target and behave as regular projects. However,
#  since it's not associated with any location, it's better declare only prebuilt 
#  targets.
#
#  The list of all loaded Jamfile is stored in variable .project-locations. It's possible
#  to obtain module name for a location using 'module-name' rule. The standalone projects
#  are not recorded, the only way to use them is by project id.

import b2.util.path
from b2.build import property_set, property
from b2.build.errors import ExceptionWithUserContext
import b2.build.targets

import bjam

import re
import sys
import os
import string
import imp
import traceback

class ProjectRegistry:

    def __init__(self, manager, global_build_dir):
        self.manager = manager
        self.global_build_dir = None
        self.project_rules_ = ProjectRules(self)

        # The target corresponding to the project being loaded now
        self.current_project = None
        
        # The set of names of loaded project modules
        self.jamfile_modules = {}

        # Mapping from location to module name
        self.location2module = {}

        # Mapping from project id to project module
        self.id2module = {}

        # Map from Jamfile directory to parent Jamfile/Jamroot
        # location.
        self.dir2parent_jamfile = {}

        # Map from directory to the name of Jamfile in
        # that directory (or None).
        self.dir2jamfile = {}

        # Map from project module to attributes object.
        self.module2attributes = {}

        # Map from project module to target for the project
        self.module2target = {}

        # Map from names to Python modules, for modules loaded
        # via 'using' and 'import' rules in Jamfiles.
        self.loaded_tool_modules_ = {}

        # Map from project target to the list of
        # (id,location) pairs corresponding to all 'use-project'
        # invocations.
        # TODO: should not have a global map, keep this
        # in ProjectTarget.
        self.used_projects = {}

        self.saved_current_project = []

        self.JAMROOT = self.manager.getenv("JAMROOT");

        # Note the use of character groups, as opposed to listing
        # 'Jamroot' and 'jamroot'. With the latter, we'd get duplicate
        # matches on windows and would have to eliminate duplicates.
        if not self.JAMROOT:
            self.JAMROOT = ["project-root.jam", "[Jj]amroot", "[Jj]amroot.jam"]

        # Default patterns to search for the Jamfiles to use for build
        # declarations.
        self.JAMFILE = self.manager.getenv("JAMFILE")

        if not self.JAMFILE:
            self.JAMFILE = ["[Bb]uild.jam", "[Jj]amfile.v2", "[Jj]amfile",
                            "[Jj]amfile.jam"]


    def load (self, jamfile_location):
        """Loads jamfile at the given location. After loading, project global
        file and jamfile needed by the loaded one will be loaded recursively.
        If the jamfile at that location is loaded already, does nothing.
        Returns the project module for the Jamfile."""

        absolute = os.path.join(os.getcwd(), jamfile_location)
        absolute = os.path.normpath(absolute)
        jamfile_location = b2.util.path.relpath(os.getcwd(), absolute)

        if "--debug-loading" in self.manager.argv():
            print "Loading Jamfile at '%s'" % jamfile_location

            
        mname = self.module_name(jamfile_location)
        # If Jamfile is already loaded, don't try again.
        if not mname in self.jamfile_modules:
        
            self.load_jamfile(jamfile_location)
                
            # We want to make sure that child project are loaded only
            # after parent projects. In particular, because parent projects
            # define attributes whch are inherited by children, and we don't
            # want children to be loaded before parents has defined everything.
            #
            # While "build-project" and "use-project" can potentially refer
            # to child projects from parent projects, we don't immediately
            # load child projects when seing those attributes. Instead,
            # we record the minimal information that will be used only later.
            
            self.load_used_projects(mname)
             
        return mname

    def load_used_projects(self, module_name):
        # local used = [ modules.peek $(module-name) : .used-projects ] ;
        used = self.used_projects[module_name]
    
        location = self.attribute(module_name, "location")
        for u in used:
            id = u[0]
            where = u[1]

            self.use(id, os.path.join(location, where))

    def load_parent(self, location):
        """Loads parent of Jamfile at 'location'.
        Issues an error if nothing is found."""

        found = b2.util.path.glob_in_parents(
            location, self.JAMROOT + self.JAMFILE) 

        if not found:
            print "error: Could not find parent for project at '%s'" % location
            print "error: Did not find Jamfile or project-root.jam in any parent directory."
            sys.exit(1)
    
        return self.load(os.path.dirname(found[0]))

    def act_as_jamfile(self, module, location):
        """Makes the specified 'module' act as if it were a regularly loaded Jamfile 
        at 'location'. If Jamfile is already located for that location, it's an 
        error."""

        if self.module_name(location) in self.jamfile_modules:
            self.manager.errors()(
                "Jamfile was already loaded for '%s'" % location)
    
        # Set up non-default mapping from location to module.
        self.location2module[location] = module
    
        # Add the location to the list of project locations
        # so that we don't try to load Jamfile in future
        self.jamfile_modules.append(location)
    
        self.initialize(module, location)

    def find(self, name, current_location):
        """Given 'name' which can be project-id or plain directory name,
        return project module corresponding to that id or directory.
        Returns nothing of project is not found."""

        project_module = None

        # Try interpreting name as project id.
        if name[0] == '/':
            project_module = self.id2module.get(name)

        if not project_module:
            location = os.path.join(current_location, name)
            # If no project is registered for the given location, try to
            # load it. First see if we have Jamfile. If not we might have project
            # root, willing to act as Jamfile. In that case, project-root
            # must be placed in the directory referred by id.
        
            project_module = self.module_name(location)
            if not project_module in self.jamfile_modules and \
               b2.util.path.glob([location], self.JAMROOT + self.JAMFILE):
                project_module = self.load(location)

        return project_module

    def module_name(self, jamfile_location):
        """Returns the name of module corresponding to 'jamfile-location'.
        If no module corresponds to location yet, associates default
        module name with that location."""
        module = self.location2module.get(jamfile_location)
        if not module:
            # Root the path, so that locations are always umbiguious.
            # Without this, we can't decide if '../../exe/program1' and '.'
            # are the same paths, or not.
            jamfile_location = os.path.realpath(
                os.path.join(os.getcwd(), jamfile_location))
            module = "Jamfile<%s>" % jamfile_location
            self.location2module[jamfile_location] = module
        return module

    def find_jamfile (self, dir, parent_root=0, no_errors=0):
        """Find the Jamfile at the given location. This returns the
        exact names of all the Jamfiles in the given directory. The optional
        parent-root argument causes this to search not the given directory
        but the ones above it up to the directory given in it."""
        
        # Glob for all the possible Jamfiles according to the match pattern.
        #
        jamfile_glob = None
        if parent_root:
            parent = self.dir2parent_jamfile.get(dir)
            if not parent:
                parent = b2.util.path.glob_in_parents(dir,
                                                               self.JAMFILE)
                self.dir2parent_jamfile[dir] = parent
            jamfile_glob = parent
        else:
            jamfile = self.dir2jamfile.get(dir)
            if not jamfile:
                jamfile = b2.util.path.glob([dir], self.JAMFILE)
                self.dir2jamfile[dir] = jamfile
            jamfile_glob = jamfile

        if len(jamfile_glob) > 1:
            # Multiple Jamfiles found in the same place. Warn about this.
            # And ensure we use only one of them.
            # As a temporary convenience measure, if there's Jamfile.v2 amount
            # found files, suppress the warning and use it.
            #
            pattern = "(.*[Jj]amfile\\.v2)|(.*[Bb]uild\\.jam)"
            v2_jamfiles = [x for x in jamfile_glob if re.match(pattern, x)]
            if len(v2_jamfiles) == 1:
                jamfile_glob = v2_jamfiles
            else:
                print """warning: Found multiple Jamfiles at '%s'!""" % (dir)
                for j in jamfile_glob:
                    print "    -", j
                print "Loading the first one"
    
        # Could not find it, error.
        if not no_errors and not jamfile_glob:
            self.manager.errors()(
                """Unable to load Jamfile.
Could not find a Jamfile in directory '%s'
Attempted to find it with pattern '%s'.
Please consult the documentation at 'http://boost.org/boost-build2'."""
                % (dir, string.join(self.JAMFILE)))

        return jamfile_glob[0]
    
    def load_jamfile(self, dir):
        """Load a Jamfile at the given directory. Returns nothing.
        Will attempt to load the file as indicated by the JAMFILE patterns.
        Effect of calling this rule twice with the same 'dir' is underfined."""
      
        # See if the Jamfile is where it should be.
        jamfile_to_load = b2.util.path.glob([dir], self.JAMROOT)
        if not jamfile_to_load:
            jamfile_to_load = self.find_jamfile(dir)
        else:
            jamfile_to_load = jamfile_to_load[0]
            
        # The module of the jamfile.
        dir = os.path.realpath(os.path.dirname(jamfile_to_load))
        
        jamfile_module = self.module_name (dir)

        # Initialize the jamfile module before loading.
        #    
        self.initialize(jamfile_module, dir, os.path.basename(jamfile_to_load))

        saved_project = self.current_project

        self.used_projects[jamfile_module] = []
        
        # Now load the Jamfile in it's own context.
        # Initialization might have load parent Jamfiles, which might have
        # loaded the current Jamfile with use-project. Do a final check to make
        # sure it's not loaded already.
        if not jamfile_module in self.jamfile_modules:
            self.jamfile_modules[jamfile_module] = True

            # FIXME:
            # mark-as-user $(jamfile-module) ;

            bjam.call("load", jamfile_module, jamfile_to_load)
            basename = os.path.basename(jamfile_to_load)
                        
        # Now do some checks
        if self.current_project != saved_project:
            self.manager.errors()(
"""The value of the .current-project variable
has magically changed after loading a Jamfile.
This means some of the targets might be defined a the wrong project.
after loading %s
expected value %s
actual value %s""" % (jamfile_module, saved_project, self.current_project))
          
        if self.global_build_dir:
            id = self.attribute(jamfile_module, "id")
            project_root = self.attribute(jamfile_module, "project-root")
            location = self.attribute(jamfile_module, "location")

            if location and project_root == dir:
                # This is Jamroot
                if not id:
                    # FIXME: go via errors module, so that contexts are
                    # shown?
                    print "warning: the --build-dir option was specified"
                    print "warning: but Jamroot at '%s'" % dir
                    print "warning: specified no project id"
                    print "warning: the --build-dir option will be ignored"


    def load_standalone(self, jamfile_module, file):
        """Loads 'file' as standalone project that has no location
        associated with it.  This is mostly useful for user-config.jam,
        which should be able to define targets, but although it has
        some location in filesystem, we don't want any build to
        happen in user's HOME, for example.

        The caller is required to never call this method twice on
        the same file.
        """

        self.initialize(jamfile_module)
        self.used_projects[jamfile_module] = []
        bjam.call("load", jamfile_module, file)
        self.load_used_projects(jamfile_module)
        
    def is_jamroot(self, basename):
        match = [ pat for pat in self.JAMROOT if re.match(pat, basename)]
        if match:
            return 1
        else:
            return 0

    def initialize(self, module_name, location=None, basename=None):
        """Initialize the module for a project.
        
        module-name is the name of the project module.
        location is the location (directory) of the project to initialize.
                 If not specified, stanalone project will be initialized
        """

        if "--debug-loading" in self.manager.argv():
            print "Initializing project '%s'" % module_name

        # TODO: need to consider if standalone projects can do anything but defining
        # prebuilt targets. If so, we need to give more sensible "location", so that
        # source paths are correct.
        if not location:
            location = ""
        else:
            location = b2.util.path.relpath(os.getcwd(), location)

        attributes = ProjectAttributes(self.manager, location, module_name)
        self.module2attributes[module_name] = attributes

        if location:
            attributes.set("source-location", [location], exact=1)
        else:
            attributes.set("source-location", "", exact=1)

        attributes.set("requirements", property_set.empty(), exact=True)
        attributes.set("usage-requirements", property_set.empty(), exact=True)
        attributes.set("default-build", [], exact=True)
        attributes.set("projects-to-build", [], exact=True)
        attributes.set("project-root", None, exact=True)
        attributes.set("build-dir", None, exact=True)
        
        self.project_rules_.init_project(module_name)

        jamroot = False

        parent_module = None;
        if module_name == "site-config":
            # No parent
            pass
        elif module_name == "user-config":
            parent_module = "site-config"
        elif location and not self.is_jamroot(basename):
            # We search for parent/project-root only if jamfile was specified 
            # --- i.e
            # if the project is not standalone.
            parent_module = self.load_parent(location)
        else:
            # It's either jamroot, or standalone project.
            # If it's jamroot, inherit from user-config.
            if location:
                parent_module = "user-config" ;                
                jamroot = True ;
                
        if parent_module:
            self.inherit_attributes(module_name, parent_module)
            attributes.set("parent-module", parent_module, exact=1)

        if jamroot:
            attributes.set("project-root", location, exact=1)
                                
        parent = None
        if parent_module:
            parent = self.target(parent_module)

        if not self.module2target.has_key(module_name):
            target = b2.build.targets.ProjectTarget(self.manager,
                module_name, module_name, parent,
                self.attribute(module_name,"requirements"),
                # FIXME: why we need to pass this? It's not
                # passed in jam code.
                self.attribute(module_name, "default-build"))
            self.module2target[module_name] = target

        self.current_project = self.target(module_name)

    def inherit_attributes(self, project_module, parent_module):
        """Make 'project-module' inherit attributes of project
        root and parent module."""

        attributes = self.module2attributes[project_module]
        pattributes = self.module2attributes[parent_module]
        
        # Parent module might be locationless user-config.
        # FIXME:
        #if [ modules.binding $(parent-module) ]
        #{        
        #    $(attributes).set parent : [ path.parent 
        #                                 [ path.make [ modules.binding $(parent-module) ] ] ] ;
        #    }
        
        attributes.set("project-root", pattributes.get("project-root"), exact=True)
        attributes.set("default-build", pattributes.get("default-build"), exact=True)
        attributes.set("requirements", pattributes.get("requirements"), exact=True)
        attributes.set("usage-requirements",
                       pattributes.get("usage-requirements"), exact=1)

        parent_build_dir = pattributes.get("build-dir")
        
        if parent_build_dir:
        # Have to compute relative path from parent dir to our dir
        # Convert both paths to absolute, since we cannot
        # find relative path from ".." to "."

             location = attributes.get("location")
             parent_location = pattributes.get("location")

             our_dir = os.path.join(os.getcwd(), location)
             parent_dir = os.path.join(os.getcwd(), parent_location)

             build_dir = os.path.join(parent_build_dir,
                                      b2.util.path.relpath(parent_dir,
                                                                    our_dir))

    def register_id(self, id, module):
        """Associate the given id with the given project module."""
        self.id2module[id] = module

    def current(self):
        """Returns the project which is currently being loaded."""
        return self.current_project

    def push_current(self, project):
        """Temporary changes the current project to 'project'. Should
        be followed by 'pop-current'."""
        self.saved_current_project.append(self.current_project)
        self.current_project = project

    def pop_current(self):
        self.current_project = self.saved_current_project[-1]
        del self.saved_current_project[-1]

    def attributes(self, project):
        """Returns the project-attribute instance for the
        specified jamfile module."""
        return self.module2attributes[project]

    def attribute(self, project, attribute):
        """Returns the value of the specified attribute in the
        specified jamfile module."""
        return self.module2attributes[project].get(attribute)
        try:    
            return self.module2attributes[project].get(attribute)
        except:
            print "Sucks", project, attribute
            raise "Sucks"

    def attributeDefault(self, project, attribute, default):
        """Returns the value of the specified attribute in the
        specified jamfile module."""
        return self.module2attributes[project].getDefault(attribute, default)

    def target(self, project_module):
        """Returns the project target corresponding to the 'project-module'."""
        if not self.module2target.has_key(project_module):
            self.module2target[project_module] = \
                b2.build.targets.ProjectTarget(project_module, project_module,
                              self.attribute(project_module, "requirements"))
        
        return self.module2target[project_module]

    def use(self, id, location):
        # Use/load a project.
        saved_project = self.current_project
        project_module = self.load(location)
        declared_id = self.attributeDefault(project_module, "id", "")

        if not declared_id or declared_id != id:
            # The project at 'location' either have no id or
            # that id is not equal to the 'id' parameter.
            if self.id2module.has_key(id) and self.id2module[id] != project_module:
                self.manager.errors()(
"""Attempt to redeclare already existing project id '%s'""" % id)
            self.id2module[id] = project_module

        self.current_module = saved_project

    def add_rule(self, name, callable):
        """Makes rule 'name' available to all subsequently loaded Jamfiles.

        Calling that rule wil relay to 'callable'."""
        self.project_rules_.add_rule(name, callable)

    def project_rules(self):
        return self.project_rules_

    def glob_internal(self, project, wildcards, excludes, rule_name):
        location = project.get("source-location")

        result = []
        callable = b2.util.path.__dict__[rule_name]
        
        paths = callable(location, wildcards, excludes)
        has_dir = 0
        for w in wildcards:
            if os.path.dirname(w):
                has_dir = 1
                break

        if has_dir or rule_name != "glob":
            # The paths we've found are relative to current directory,
            # but the names specified in sources list are assumed to
            # be relative to source directory of the corresponding
            # prject. So, just make the name absolute.
            result = [os.path.join(os.getcwd(), p) for p in paths]
        else:
            # There were not directory in wildcard, so the files are all
            # in the source directory of the project. Just drop the
            # directory, instead of making paths absolute.
            result = [os.path.basename(p) for p in paths]
            
        return result

    def load_module(self, name, extra_path=None):
        """Classic Boost.Build 'modules' are in fact global variables.
        Therefore, try to find an already loaded Python module called 'name' in sys.modules. 
        If the module ist not loaded, find it Boost.Build search
        path and load it.  The new module is not entered in sys.modules.
        The motivation here is to have disjoint namespace of modules
        loaded via 'import/using' in Jamfile, and ordinary Python
        modules. We don't want 'using foo' in Jamfile to load ordinary
        Python module 'foo' which is going to not work. And we
        also don't want 'import foo' in regular Python module to
        accidentally grab module named foo that is internal to
        Boost.Build and intended to provide interface to Jamfiles."""

        existing = self.loaded_tool_modules_.get(name)
        if existing:
            return existing

        modules = sys.modules
        for class_name in modules:
            if name is class_name:
                module = modules[class_name]
                self.loaded_tool_modules_[name] = module
                return module
        
        path = extra_path
        if not path:
            path = []
        path.extend(self.manager.boost_build_path())
        location = None
        for p in path:
            l = os.path.join(p, name + ".py")
            if os.path.exists(l):
                location = l
                break

        if not location:
            self.manager.errors()("Cannot find module '%s'" % name)

        mname = "__build_build_temporary__"
        file = open(location)
        try:
            # TODO: this means we'll never make use of .pyc module,
            # which might be a problem, or not.
            module = imp.load_module(mname, file, os.path.basename(location),
                                     (".py", "r", imp.PY_SOURCE))
            del sys.modules[mname]
            self.loaded_tool_modules_[name] = module
            return module
        finally:
            file.close()
        


# FIXME:
# Defines a Boost.Build extension project. Such extensions usually
# contain library targets and features that can be used by many people.
# Even though extensions are really projects, they can be initialize as
# a module would be with the "using" (project.project-rules.using)
# mechanism.
#rule extension ( id : options * : * )
#{
#    # The caller is a standalone module for the extension.
#    local mod = [ CALLER_MODULE ] ;
#    
#    # We need to do the rest within the extension module.
#    module $(mod)
#    {
#        import path ;
#        
#        # Find the root project.
#        local root-project = [ project.current ] ;
#        root-project = [ $(root-project).project-module ] ;
#        while
#            [ project.attribute $(root-project) parent-module ] &&
#            [ project.attribute $(root-project) parent-module ] != user-config
#        {
#            root-project = [ project.attribute $(root-project) parent-module ] ;
#        }
#        
#        # Create the project data, and bring in the project rules
#        # into the module.
#        project.initialize $(__name__) :
#            [ path.join [ project.attribute $(root-project) location ] ext $(1:L) ] ;
#        
#        # Create the project itself, i.e. the attributes.
#        # All extensions are created in the "/ext" project space.
#        project /ext/$(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
#        local attributes = [ project.attributes $(__name__) ] ;
#        
#        # Inherit from the root project of whomever is defining us.
#        project.inherit-attributes $(__name__) : $(root-project) ;
#        $(attributes).set parent-module : $(root-project) : exact ;
#    }
#}
        

class ProjectAttributes:
    """Class keeping all the attributes of a project.

    The standard attributes are 'id', "location", "project-root", "parent"
    "requirements", "default-build", "source-location" and "projects-to-build".
    """
        
    def __init__(self, manager, location, project_module):
        self.manager = manager
        self.location = location
        self.project_module = project_module
        self.attributes = {}
        self.usage_requirements = None
        
    def set(self, attribute, specification, exact):
        """Set the named attribute from the specification given by the user.
        The value actually set may be different."""

        if exact:
            self.__dict__[attribute] = specification
            
        elif attribute == "requirements":
            self.requirements = property_set.refine_from_user_input(
                self.requirements, specification,
                self.project_module, self.location)
            
        elif attribute == "usage-requirements":
            unconditional = []
            for p in specification:
                split = property.split_conditional(p)
                if split:
                    unconditional.append(split[1])
                else:
                    unconditional.append(p)

            non_free = property.remove("free", unconditional)
            if non_free:                
                pass
                # FIXME:
                #errors.error "usage-requirements" $(specification) "have non-free properties" $(non-free) ;

            t = property.translate_paths(specification, self.location)

            existing = self.__dict__.get("usage-requirements")
            if existing:
                new = property_set.create(existing.raw() +  t)
            else:
                new = property_set.create(t)
            self.__dict__["usage-requirements"] = new

                
        elif attribute == "default-build":
            self.__dict__["default-build"] = property_set.create(specification)
            
        elif attribute == "source-location":
            source_location = []
            for path in specification:
                source_location += os.path.join(self.location, path)
            self.__dict__["source-location"] = source_location
                
        elif attribute == "build-dir":
            self.__dict__["build-dir"] = os.path.join(self.location, specification)
                 
        elif not attribute in ["id", "default-build", "location",
                               "source-location", "parent",
                               "projects-to-build", "project-root"]:
            self.manager.errors()(
"""Invalid project attribute '%s' specified
for project at '%s'""" % (attribute, self.location))
        else:
            self.__dict__[attribute] = specification

    def get(self, attribute):
        return self.__dict__[attribute]

    def getDefault(self, attribute, default):
        return self.__dict__.get(attribute, default)

    def dump(self):
        """Prints the project attributes."""
        id = self.get("id")
        if not id:
            id = "(none)"
        else:
            id = id[0]

        parent = self.get("parent")
        if not parent:
            parent = "(none)"
        else:
            parent = parent[0]

        print "'%s'" % id
        print "Parent project:%s", parent
        print "Requirements:%s", self.get("requirements")
        print "Default build:%s", string.join(self.get("debuild-build"))
        print "Source location:%s", string.join(self.get("source-location"))
        print "Projects to build:%s", string.join(self.get("projects-to-build").sort());

class ProjectRules:
    """Class keeping all rules that are made available to Jamfile."""

    def __init__(self, registry):
        self.registry = registry
        self.manager_ = registry.manager
        self.rules = {}
        self.local_names = [x for x in self.__class__.__dict__
                            if x not in ["__init__", "init_project", "add_rule",
                                         "error_reporting_wrapper", "add_rule_for_type"]]
        self.all_names_ = [x for x in self.local_names]

    def add_rule_for_type(self, type):
        rule_name = type.lower();

        def xpto (name, sources, requirements = [], default_build = None, usage_requirements = []):
            return self.manager_.targets().create_typed_target(
                type, self.registry.current(), name[0], sources,
                requirements, default_build, usage_requirements) 

        self.add_rule(type.lower(), xpto)
    
    def add_rule(self, name, callable):
        self.rules[name] = callable
        self.all_names_.append(name)

    def all_names(self):
        return self.all_names_

    def call_and_report_errors(self, callable, *args):
        result = None
        try:
            self.manager_.errors().push_jamfile_context()
            result = callable(*args)
        except ExceptionWithUserContext, e:
            e.report()
        except Exception, e:
            try:
                self.manager_.errors().handle_stray_exception (e)
            except ExceptionWithUserContext, e:
                e.report()
        finally:                
            self.manager_.errors().pop_jamfile_context()
                                        
        return result

    def make_wrapper(self, callable):
        """Given a free-standing function 'callable', return a new
        callable that will call 'callable' and report all exceptins,
        using 'call_and_report_errors'."""
        def wrapper(*args):
            self.call_and_report_errors(callable, *args)
        return wrapper

    def init_project(self, project_module):

        for n in self.local_names:            
            # Using 'getattr' here gives us a bound method,
            # while using self.__dict__[r] would give unbound one.
            v = getattr(self, n)
            if callable(v):
                if n == "import_":
                    n = "import"
                else:
                    n = string.replace(n, "_", "-")
                    
                bjam.import_rule(project_module, n,
                                 self.make_wrapper(v))

        for n in self.rules:
            bjam.import_rule(project_module, n,
                             self.make_wrapper(self.rules[n]))

    def project(self, *args):

        jamfile_module = self.registry.current().project_module()
        attributes = self.registry.attributes(jamfile_module)
        
        id = None
        if args and args[0]:
            id = args[0][0]
            args = args[1:]

        if id:
            if id[0] != '/':
                id = '/' + id
            self.registry.register_id (id, jamfile_module)

        explicit_build_dir = None
        for a in args:
            if a:
                attributes.set(a[0], a[1:], exact=0)
                if a[0] == "build-dir":
                    explicit_build_dir = a[1]
        
        # If '--build-dir' is specified, change the build dir for the project.
        if self.registry.global_build_dir:

            location = attributes.get("location")
            # Project with empty location is 'standalone' project, like
            # user-config, or qt.  It has no build dir.
            # If we try to set build dir for user-config, we'll then
            # try to inherit it, with either weird, or wrong consequences.
            if location and location == attributes.get("project-root"):
                # This is Jamroot.
                if id:
                    if explicit_build_dir and os.path.isabs(explicit_build_dir):
                        self.register.manager.errors()(
"""Absolute directory specified via 'build-dir' project attribute
Don't know how to combine that with the --build-dir option.""")

                    rid = id
                    if rid[0] == '/':
                        rid = rid[1:]

                    p = os.path.join(self.registry.global_build_dir,
                                     rid, explicit_build_dir)
                    attributes.set("build-dir", p, exact=1)
            elif explicit_build_dir:
                self.registry.manager.errors()(
"""When --build-dir is specified, the 'build-dir'
attribute is allowed only for top-level 'project' invocations""")

    def constant(self, name, value):
        """Declare and set a project global constant.
        Project global constants are normal variables but should
        not be changed. They are applied to every child Jamfile."""
        m = "Jamfile</home/ghost/Work/Boost/boost-svn/tools/build/v2_python/python/tests/bjam/make>"
        self.registry.current().add_constant(name[0], value)

    def path_constant(self, name, value):
        """Declare and set a project global constant, whose value is a path. The
        path is adjusted to be relative to the invocation directory. The given
        value path is taken to be either absolute, or relative to this project
        root."""
        self.registry.current().add_constant(name[0], value, path=1)

    def use_project(self, id, where):
        # See comment in 'load' for explanation why we record the
        # parameters as opposed to loading the project now.
        m = self.registry.current().project_module();
        self.registry.used_projects[m].append((id[0], where[0]))
        
    def build_project(self, dir):
        assert(isinstance(dir, list))
        jamfile_module = self.registry.current().project_module()
        attributes = self.registry.attributes(jamfile_module)
        now = attributes.get("projects-to-build")
        attributes.set("projects-to-build", now + dir, exact=True)

    def explicit(self, target_names):
        t = self.registry.current()
        for n in target_names:
            t.mark_target_as_explicit(n)

    def glob(self, wildcards, excludes=None):
        return self.registry.glob_internal(self.registry.current(),
                                           wildcards, excludes, "glob")

    def glob_tree(self, wildcards, excludes=None):
        bad = 0
        for p in wildcards:
            if os.path.dirname(p):
                bad = 1

        if excludes:
            for p in excludes:
                if os.path.dirname(p):
                    bad = 1

        if bad:
            self.registry.manager().errors()(
"The patterns to 'glob-tree' may not include directory")
        return self.registry.glob_internal(self.registry.current(),
                                           wildcards, excludes, "glob_tree")
    

    def using(self, toolset, *args):
        # The module referred by 'using' can be placed in
        # the same directory as Jamfile, and the user
        # will expect the module to be found even though
        # the directory is not in BOOST_BUILD_PATH.
        # So temporary change the search path.
        jamfile_module = self.registry.current().project_module()
        attributes = self.registry.attributes(jamfile_module)
        location = attributes.get("location")

        m = self.registry.load_module(toolset[0], [location])
        if not m.__dict__.has_key("init"):
            self.registry.manager.errors()(
                "Tool module '%s' does not define the 'init' method" % toolset[0])
        m.init(*args)


    def import_(self, name, names_to_import=None, local_names=None):

        name = name[0]
        jamfile_module = self.registry.current().project_module()
        attributes = self.registry.attributes(jamfile_module)
        location = attributes.get("location")

        m = self.registry.load_module(name, [location])

        for f in m.__dict__:
            v = m.__dict__[f]
            if callable(v):
                bjam.import_rule(jamfile_module, name + "." + f, v)

        if names_to_import:
            if not local_names:
                local_names = names_to_import

            if len(names_to_import) != len(local_names):
                self.registry.manager.errors()(
"""The number of names to import and local names do not match.""")

            for n, l in zip(names_to_import, local_names):
                bjam.import_rule(jamfile_module, l, m.__dict__[n])
        
    def conditional(self, condition, requirements):
        """Calculates conditional requirements for multiple requirements
        at once. This is a shorthand to be reduce duplication and to
        keep an inline declarative syntax. For example:

            lib x : x.cpp : [ conditional <toolset>gcc <variant>debug :
                <define>DEBUG_EXCEPTION <define>DEBUG_TRACE ] ;
        """

        c = string.join(condition, ",")
        if c.find(":") != -1:
            return [c + r for r in requirements]
        else:
            return [c + ":" + r for r in requirements]
