📄 project.jam
字号:
# 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 a module name, can be obtained using the 'attributes' rule)# - an instance of 'project-target' class (from targets.jam)# (given a module name, can be obtained using the 'target' rule)## Typically, projects are created as result of loading a Jamfile, which is done# 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 the Jamfile is read. It can declare its own# attributes using the 'project' rule which will be combined with any already# set attributes.## The 'project' rule can also declare a project id which will be associated with# the project module.## There can also be 'standalone' projects. They are created by calling# 'initialize' on an arbitrary module and not specifying their location. After# the call, the module can call the 'project' rule, declare main targets and# behave as a regular project except that, since it is not associated with any# location, it should not declare targets that are not prebuilt.## The list of all loaded Jamfile is stored in the .project-locations variable.# It is possible to obtain a module name for a location using the 'module-name'# rule. Standalone projects are not recorded and can only be referenced using# their project id.import "class" : new ;import errors ;import modules ;import path ;import print ;import property-set ;import sequence ;# Loads the Jamfile at the given location. After loading, project global file# and Jamfiles needed by the requested one will be loaded recursively. If the# Jamfile at that location is loaded already, does nothing. Returns the project# module for the Jamfile.#rule load ( jamfile-location ){ if --debug-loading in [ modules.peek : ARGV ] { ECHO "Loading Jamfile at" '$(jamfile-location)' ; } local module-name = [ module-name $(jamfile-location) ] ; # If Jamfile is already loaded, don't try again. if ! $(module-name) in $(.jamfile-modules) { 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 # which are inherited by children, and we don't want children to be # loaded before parent 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 seeing those attributes. Instead, we record the minimal # information to be used only later. load-used-projects $(module-name) ; } return $(module-name) ;}rule load-used-projects ( module-name ){ local used = [ modules.peek $(module-name) : .used-projects ] ; local location = [ attribute $(module-name) location ] ; import project ; while $(used) { local id = $(used[1]) ; local where = $(used[2]) ; project.use $(id) : [ path.root [ path.make $(where) ] $(location) ] ; used = $(used[3-]) ; }}# Note the use of character groups, as opposed to listing 'Jamroot' and# 'jamroot'. With the latter, we would get duplicate matches on Windows and# would have to eliminate duplicates.JAMROOT ?= [ modules.peek : JAMROOT ] ;JAMROOT ?= project-root.jam [Jj]amroot [Jj]amroot.jam ;# Loads parent of Jamfile at 'location'. Issues an error if nothing is found.#rule load-parent ( location ){ local found = [ path.glob-in-parents $(location) : $(JAMROOT) $(JAMFILE) ] ; if ! $(found) { ECHO error: Could not find parent for project at '$(location)' ; EXIT error: Did not find Jamfile.jam or Jamroot.jam in any parent directory. ; } return [ load $(found[1]:D) ] ;}# Makes the specified 'module' act as if it were a regularly loaded Jamfile at# 'location'. Reports an error if a Jamfile has already been loaded for that# location.#rule act-as-jamfile ( module : location ){ if [ module-name $(location) ] in $(.jamfile-modules) { errors.error "Jamfile was already loaded for '$(location)'" ; } # Set up non-default mapping from location to module. .module.$(location) = $(module) ; # Add the location to the list of project locations so that we don't try to # reload the same Jamfile in the future. .jamfile-modules += [ module-name $(location) ] ; initialize $(module) : $(location) ;}# Returns the project module corresponding to the given project-id or plain# directory name. Returns nothing if such a project can not be found.#rule find ( name : current-location ){ local project-module ; # Try interpreting name as project id. if [ path.is-rooted $(name) ] { project-module = $($(name).jamfile-module) ; } if ! $(project-module) { local location = [ path.root [ path.make $(name) ] $(current-location) ] ; # If no project is registered for the given location, try to load it. # First see if we have a Jamfile. If not, then see if we might have a # project root willing to act as a Jamfile. In that case, project root # must be placed in the directory referred by id. project-module = [ module-name $(location) ] ; if ! $(project-module) in $(.jamfile-modules) { if [ path.glob $(location) : $(JAMROOT) $(JAMFILE) ] { project-module = [ load $(location) ] ; } else { project-module = ; } } } return $(project-module) ;}# Returns the name of the module corresponding to 'jamfile-location'. If no# module corresponds to that location yet, associates the default module name# with that location.#rule module-name ( jamfile-location ){ if ! $(.module.$(jamfile-location)) { # Root the path, so that locations are always unambiguous. Without this, # we can't decide if '../../exe/program1' and '.' are the same paths. jamfile-location = [ path.root $(jamfile-location) [ path.pwd ] ] ; .module.$(jamfile-location) = Jamfile<$(jamfile-location)> ; } return $(.module.$(jamfile-location)) ;}# Default patterns to search for the Jamfiles to use for build declarations.#JAMFILE = [ modules.peek : JAMFILE ] ;JAMFILE ?= [Bb]uild.jam [Jj]amfile.v2 [Jj]amfile [Jj]amfile.jam ;# 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.#rule find-jamfile ( dir # The directory(s) to look for a Jamfile. parent-root ? # Optional flag indicating to search for the parent Jamfile. : no-errors ? ){ # Glob for all the possible Jamfiles according to the match pattern. # local jamfile-glob = ; if $(parent-root) { if ! $(.parent-jamfile.$(dir)) { .parent-jamfile.$(dir) = [ path.glob-in-parents $(dir) : $(JAMFILE) ] ; } jamfile-glob = $(.parent-jamfile.$(dir)) ; } else { if ! $(.jamfile.$(dir)) { .jamfile.$(dir) = [ path.glob $(dir) : $(JAMFILE) ] ; } jamfile-glob = $(.jamfile.$(dir)) ; } local jamfile-to-load = $(jamfile-glob) ; # 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 is # Jamfile.v2 among found files, suppress the warning and use it. # if $(jamfile-to-load[2-]) { local v2-jamfiles = [ MATCH (.*[Jj]amfile\\.v2)|(.*[Bb]uild\\.jam) : $(jamfile-to-load) ] ; if $(v2-jamfiles) && ! $(v2-jamfiles[2]) { jamfile-to-load = $(v2-jamfiles) ; } else { local jamfile = [ path.basename $(jamfile-to-load[1]) ] ; ECHO "warning: Found multiple Jamfiles at '"$(dir)"'!" "Loading the first one: '$(jamfile)'." ; } jamfile-to-load = $(jamfile-to-load[1]) ; } # Could not find it, error. # if ! $(no-errors) && ! $(jamfile-to-load) { errors.error Unable to load Jamfile. : Could not find a Jamfile in directory '$(dir)'. : Attempted to find it with pattern '"$(JAMFILE:J=" ")"'. : Please consult the documentation at 'http://www.boost.org'. ; } return $(jamfile-to-load) ;}# 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 undefined.#local rule load-jamfile ( dir # The directory of the project Jamfile. ){ # See if the Jamfile is where it should be. # local jamfile-to-load = [ path.glob $(dir) : $(JAMROOT) ] ; if ! $(jamfile-to-load) { jamfile-to-load = [ find-jamfile $(dir) ] ; } # The module of the Jamfile. # local jamfile-module = [ module-name [ path.parent $(jamfile-to-load) ] ] ; # Initialize the Jamfile module before loading. # initialize $(jamfile-module) : [ path.parent $(jamfile-to-load) ] : $(jamfile-to-load:BS) ; local saved-project = $(.current-project) ; # Now load the Jamfile in it's own context. Initialization might have loaded # 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 ! $(jamfile-module) in $(.jamfile-modules) { .jamfile-modules += $(jamfile-module) ; mark-as-user $(jamfile-module) ; modules.load $(jamfile-module) : [ path.native $(jamfile-to-load) ] : . ; if [ MATCH ($(JAMROOT)) : $(jamfile-to-load:BS) ] { jamfile = [ find-jamfile $(dir) : no-errors ] ; if $(jamfile) { load-aux $(jamfile-module) : [ path.native $(jamfile) ] ; } } } # Now do some checks. if $(.current-project) != $(saved-project) { errors.error "The value of the .current-project variable has magically" : "changed after loading a Jamfile. This means some of the targets" : "might be defined in the wrong project." : "after loading" $(jamfile-module) : "expected value" $(saved-project) : "actual value" $(.current-project) ; } if $(.global-build-dir) { local id = [ attribute $(jamfile-module) id ] ; local project-root = [ attribute $(jamfile-module) project-root ] ; local location = [ attribute $(jamfile-module) location ] ; if $(location) && $(project-root) = $(dir) { # This is Jamroot. if ! $(id) { ECHO "warning: the --build-dir option was specified" ; ECHO "warning: but Jamroot at '$(dir)'" ; ECHO "warning: specified no project id" ; ECHO "warning: the --build-dir option will be ignored" ; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -