mirror of
https://github.com/boostorg/build.git
synced 2026-02-17 13:42:14 +00:00
445 lines
12 KiB
Plaintext
445 lines
12 KiB
Plaintext
# Copyright (C) Vladimir Prus and Rene Rivera 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.
|
|
|
|
# Each (sub)project is represented by a module with name Jamfile@jamfile-path.
|
|
# The module interface is:
|
|
#
|
|
# rule location ( )
|
|
# rule id ( )
|
|
# rule project-root ( )
|
|
# rule parent ( )
|
|
# rule requirements ( )
|
|
# rule default-build ( )
|
|
# rule source-location ( )
|
|
|
|
# rule subprojects ( ) XXX currently 'subincludes' -- should rename.
|
|
#
|
|
# Targets defined in Jamfile, as well as target representing the entire
|
|
# Jamfile will be available using facilities in the 'targets' module.
|
|
#
|
|
|
|
import modules : poke ;
|
|
import numbers ;
|
|
import os.path ;
|
|
import sequence ;
|
|
import targets ;
|
|
import errors : error ;
|
|
import project-root ;
|
|
|
|
|
|
#
|
|
# Loads jamfile at the given location. After loading, project global
|
|
# file and jamfile needed by the loaded one will be loaded recursively.
|
|
#
|
|
rule load ( jamfile-location )
|
|
{
|
|
local loaded = ;
|
|
local module-name = [ load-jamfile $(jamfile-location) loaded ] ;
|
|
|
|
if $(loaded)
|
|
{
|
|
.projects += $(jamfile-location) ;
|
|
|
|
for local subinclude in [ $(module-name).subincludes ]
|
|
{
|
|
load [ os.path.join $(jamfile-location) $(subinclude) ] ;
|
|
}
|
|
}
|
|
return $(module-name) ;
|
|
}
|
|
|
|
#
|
|
# Returns the name of project module given its id.
|
|
# Projects can be referred using path@project-id notation. In it, 'path'
|
|
# selects jamfile location relatively to 'current-location' and 'project-id'
|
|
# names project relatively to the selected jamfile.
|
|
# Rooted 'project-id' is possible:
|
|
# "@/boost" will refer to the top-level project called "boost".
|
|
#
|
|
rule lookup ( id : current-location )
|
|
{
|
|
local split = [ MATCH (.*)@(.*) : $(id) ] ;
|
|
local location = $(split[1]) ;
|
|
# A jam quirk: if there's no part before "@", 'location' will be empty
|
|
# string, and ?= won't change it.
|
|
if $(location)
|
|
{
|
|
location =
|
|
[ os.path.root-relative-path $(location) $(current-location) ] ;
|
|
}
|
|
else
|
|
{
|
|
location = $(current-location) ;
|
|
}
|
|
|
|
local project-id = $(split[2]) ;
|
|
|
|
if [ os.path.is-rooted $(project-id) ]
|
|
{
|
|
return $($(project-id).jamfile-location) ;
|
|
}
|
|
else
|
|
{
|
|
if ! $(location)
|
|
{
|
|
error Jamfile location must be specified for relative project-id $(id) ;
|
|
}
|
|
|
|
local module-name = [ module-name $(location) ] ;
|
|
local base-id = [ $(module-name).id ] ;
|
|
|
|
if ! $(base-id)
|
|
{
|
|
error "Project in $(location) has no project id" ;
|
|
}
|
|
|
|
if $(project-id)
|
|
{
|
|
local rooted-id = $(base-id)/$(project-id) ;
|
|
return $($(rooted-id).jamfile-location) ;
|
|
}
|
|
else
|
|
{
|
|
return $($(base-id).jamfile-location) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
rule project ( id ? : option1 * : option2 * : option3 * )
|
|
{
|
|
# ECHO "Declared project '$(id)'" ;
|
|
|
|
local caller = [ CALLER_MODULE ] ;
|
|
$(id).jamfile-location = [ $(caller).location ] ;
|
|
|
|
poke $(caller) : __id__ : $(id) ;
|
|
|
|
module [ CALLER_MODULE ]
|
|
{
|
|
import targets ;
|
|
targets.create-abstract-project-target [ location ] ;
|
|
}
|
|
|
|
if $(option1) {
|
|
assign-option [ CALLER_MODULE ] : $(option1) ;
|
|
}
|
|
if $(option2) {
|
|
assign-option [ CALLER_MODULE ] : $(option2) ;
|
|
}
|
|
if $(option3) {
|
|
assign-option [ CALLER_MODULE ] : $(option3) ;
|
|
}
|
|
}
|
|
|
|
rule assign-option ( module : option + )
|
|
{
|
|
local first = $(option[1]) ;
|
|
local tail = $(option[2-]) ;
|
|
|
|
switch $(first) {
|
|
case "requirements" :
|
|
poke $(module) : __requirements__ : $(tail) ;
|
|
case "default-build" :
|
|
poke $(module) : __default-build__ : $(tail) ;
|
|
case "source-location" :
|
|
poke $(module) : __source-location__
|
|
: [ os.path.join [ $(module).location ] $(tail) ] ;
|
|
case * :
|
|
error "Invalid project option" ;
|
|
}
|
|
}
|
|
|
|
|
|
#
|
|
# Returns the name of module corresponding to 'jamfile-location'.
|
|
#
|
|
rule module-name ( jamfile-location )
|
|
{
|
|
return Jamfile<$(jamfile-location)> ;
|
|
}
|
|
|
|
#
|
|
# Output a human readable description of the project structure.
|
|
#
|
|
rule dump ( )
|
|
{
|
|
# Sort projects so that output is independent of order. It is
|
|
# needed to allow tests to works despite possible change in
|
|
# project inclusion order.
|
|
local projects = [ sequence.insertion-sort $(.projects) ] ;
|
|
|
|
ECHO "Projects structure dump" ;
|
|
ECHO "" ;
|
|
for local i in $(projects) {
|
|
ECHO " Location: $(i)" ;
|
|
local module-name = [ module-name $(i) ] ;
|
|
local id = [ $(module-name).id ] ;
|
|
id ?= "(none)" ;
|
|
ECHO " Project id: $(id)" ;
|
|
ECHO "" ;
|
|
|
|
local project-root = [ $(module-name).project-root ] ;
|
|
local parent = [ $(module-name).parent ] ;
|
|
parent ?= none ;
|
|
local requirements = [ $(module-name).requirements ] ;
|
|
local default-build = [ $(module-name).default-build ] ;
|
|
local source-location = [ $(module-name).source-location ] ;
|
|
local subincludes = [ $(module-name).subincludes ] ;
|
|
subincludes = [ sequence.insertion-sort $(subincludes) ] ;
|
|
ECHO " Project root: $(project-root)" ;
|
|
ECHO " Parent project: $(parent)" ;
|
|
ECHO " Requirements:" $(requirements) ;
|
|
ECHO " Default build:" $(default-build) ;
|
|
ECHO " Source location:" $(source-location) ;
|
|
ECHO " Subincludes:" $(subincludes) ;
|
|
|
|
ECHO "" ;
|
|
}
|
|
}
|
|
|
|
# Default patterns to search for the Jamfiles to use for build
|
|
# declarations.
|
|
#
|
|
JAMFILE = [ modules.peek : JAMFILE ] ;
|
|
JAMFILE ?= [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.
|
|
#
|
|
local rule find-jamfile (
|
|
dir # The directory(s) to look for a Jamfile.
|
|
parent-root ? # Optional flag indicating to search for the parent Jamfile.
|
|
)
|
|
{
|
|
# Glob for all the possible Jamfiles according to the match pattern.
|
|
#
|
|
local jamfile-glob = ;
|
|
if $(parent-root)
|
|
{
|
|
jamfile-glob = [ os.path.make
|
|
[ find-to-root [ os.path.native $(dir:P) ] : $(JAMFILE) ] ] ;
|
|
}
|
|
else
|
|
{
|
|
jamfile-glob = [ os.path.glob $(dir) : $(JAMFILE) ] ;
|
|
}
|
|
|
|
# Normalize the paths of each file found.
|
|
#
|
|
local jamfile-found = ;
|
|
if $(parent-root)
|
|
{
|
|
parent-root = [ os.path.make $(parent-root) ] ;
|
|
}
|
|
for local jamfile in $(jamfile-glob)
|
|
{
|
|
# Filter out if the found file is above the target parent root.
|
|
if $(parent-root)
|
|
{
|
|
if ! [ MATCH "$(parent-root)\\/(.*)" : $(jamfile) ]
|
|
{
|
|
jamfile = ;
|
|
}
|
|
}
|
|
|
|
if $(jamfile)
|
|
{
|
|
jamfile-found += $(jamfile) ;
|
|
}
|
|
}
|
|
|
|
return $(jamfile-found) ;
|
|
}
|
|
|
|
# Load a Jamfile at the given directory. Will attempt to load
|
|
# the file as indicated by the JAMFILE patterns. We return the
|
|
# module for the Jamfile.
|
|
#
|
|
local rule load-jamfile (
|
|
dir # The directory of the project Jamfile.
|
|
loaded-var ? # Name of variable to indicated we loaded the Jamfile.
|
|
)
|
|
{
|
|
# See if the Jamfile is where it should be.
|
|
#
|
|
local jamfile-to-load = [ find-jamfile $(dir) ] ;
|
|
|
|
# Could not find it, error.
|
|
#
|
|
if ! $(jamfile-to-load)
|
|
{
|
|
EXIT
|
|
"Unable to load Jamfile. Could not find a Jamfile in"
|
|
"this directory:" $(dir)"." "Attempted to find it with"
|
|
"this pattern:" $(JAMFILE)"."
|
|
"Please consult the documentation at 'http://www.boost.org'." ;
|
|
}
|
|
|
|
# The module of the jamfile.
|
|
#
|
|
local jamfile-module = [ module-name [ os.path.parent $(jamfile-to-load[1]) ] ] ;
|
|
|
|
# Don't even bother with the rest if we know the file is already loaded.
|
|
#
|
|
if ! [ modules.binding $(jamfile-module) ]
|
|
{
|
|
# Multiple Jamfiles found in the same place. Warn about this.
|
|
# And ensure we use only one of them.
|
|
#
|
|
if $(jamfile-to-load[2-])
|
|
{
|
|
ECHO
|
|
"WARNING: Found multiple Jamfiles at this '"$(dir)"' location!"
|
|
"Loading the first one: '" [ os.path.basename $(jamfile-to-load[1]) ] "'." ;
|
|
}
|
|
|
|
jamfile-to-load = $(jamfile-to-load[1]) ;
|
|
|
|
# Initialize the jamfile module before loading.
|
|
#
|
|
initialize $(jamfile-module) : $(jamfile-to-load) ;
|
|
|
|
# Setup, by coordinating with project-root.
|
|
#
|
|
local project-root-module = [ $(jamfile-module).project-root-module ] ;
|
|
$(project-root-module).register-project $(jamfile-module) ;
|
|
|
|
# Now load the Jamfile in it's own context.
|
|
#
|
|
modules.load $(jamfile-module) : [ os.path.native $(jamfile-to-load) ] : . ;
|
|
|
|
# Indicate we loaded the Jamfile.
|
|
#
|
|
if $(loaded-var)
|
|
{
|
|
$(loaded-var) = true ;
|
|
}
|
|
}
|
|
|
|
# Return the Jamfile's filename/module.
|
|
#
|
|
return $(jamfile-module) ;
|
|
}
|
|
|
|
# Initialize the module for a Jamfile.
|
|
#
|
|
local rule initialize (
|
|
module-name # The name of the Jamfile module.
|
|
: jamfile # The location (binding) of the jamfile for the project to initialize.
|
|
)
|
|
{
|
|
# Make sure we've loaded the project-root corresponding to this
|
|
# Jamfile.
|
|
#
|
|
local project-root-module = [ project-root.load [ os.path.parent $(jamfile) ] ] ;
|
|
local project-root = [ $(project-root-module).location ] ;
|
|
|
|
local parent = [ find-jamfile [ os.path.parent $(jamfile) ] $(project-root) ] ;
|
|
local parent-module = ;
|
|
if $(parent)
|
|
{
|
|
parent-module = [ load [ os.path.parent $(parent[1]) ] ] ;
|
|
}
|
|
|
|
module $(module-name)
|
|
{
|
|
import project : project ;
|
|
}
|
|
|
|
# Import rules common to all project modules from project-rules module,
|
|
# define at the end of this file.
|
|
modules.clone-rules project-rules $(module-name) ;
|
|
|
|
modules.poke $(module-name) : __jamfile-location__ : $(jamfile-location) ;
|
|
modules.poke $(module-name) : __source-location__ : $(jamfile-location) ;
|
|
modules.poke $(module-name) : __project-root__ : $(project-root) ;
|
|
modules.poke $(module-name) : __project-root-module__ : $(project-root-module) ;
|
|
if $(parent-module)
|
|
{
|
|
modules.poke $(module-name) : __parent__ : [ os.path.parent $(parent) ] ;
|
|
modules.poke $(module-name) : __default-build__ : [ $(parent-module).default-build ] ;
|
|
modules.poke $(module-name) : __requirements__ : [ $(parent-module).requirements ] ;
|
|
}
|
|
else
|
|
{
|
|
modules.poke $(module-name) : __default-build__ : debug ;
|
|
}
|
|
}
|
|
|
|
# This module defines rules common to all projects
|
|
module project-rules {
|
|
|
|
rule location ( )
|
|
{
|
|
return $(__jamfile-location__) ;
|
|
}
|
|
|
|
rule id ( )
|
|
{
|
|
return $(__id__) ;
|
|
}
|
|
|
|
rule project-root ( )
|
|
{
|
|
return $(__project-root__) ;
|
|
}
|
|
|
|
rule project-root-module ( )
|
|
{
|
|
return $(__project-root-module__) ;
|
|
}
|
|
|
|
rule parent ( )
|
|
{
|
|
return $(__parent__) ;
|
|
}
|
|
|
|
rule requirements ( )
|
|
{
|
|
return $(__requirements__) ;
|
|
}
|
|
|
|
rule default-build ( )
|
|
{
|
|
return $(__default-build__) ;
|
|
}
|
|
|
|
rule source-location ( )
|
|
{
|
|
return $(__source-location__) ;
|
|
}
|
|
|
|
rule subinclude ( jamfile-location )
|
|
{
|
|
__subincludes__ += $(jamfile-location) ;
|
|
}
|
|
|
|
rule subincludes ( )
|
|
{
|
|
return $(__subincludes__) ;
|
|
}
|
|
|
|
rule print ( )
|
|
{
|
|
import sequence ;
|
|
import print ;
|
|
|
|
print.section "'"$(__id__)"'" ;
|
|
print.list-start ;
|
|
print.list-item "Project root:" [ project-root ] ;
|
|
print.list-item "Parent project:" [ parent ] ;
|
|
print.list-item "Requirements:" [ requirements ] ;
|
|
print.list-item "Default build:" [ default-build ] ;
|
|
print.list-item "Source location:" [ source-location ] ;
|
|
print.list-item "Subincludes:" [ sequence.insertion-sort [ subincludes ] ] ;
|
|
print.list-end ;
|
|
}
|
|
}
|
|
|
|
|