From 0c58c9ae6bf3391270dadbf088bf09d043494a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jurko=20Gospodneti=C4=87?= Date: Sat, 5 Jan 2008 20:02:24 +0000 Subject: [PATCH] Minor stylistic changes such as: comment typo corrections, wrapping lines to 80 characters, indentations, removing trailing spaces, etc. [SVN r42494] --- src/build-system.jam | 181 ++++--- src/build/alias.jam | 52 +-- src/build/feature.jam | 867 +++++++++++++++++----------------- src/build/generators.jam | 342 +++++++------- src/build/project.jam | 659 +++++++++++++------------- src/build/property-set.jam | 300 ++++++------ src/build/property.jam | 420 ++++++++--------- src/build/targets.jam | 517 ++++++++++---------- src/build/type.jam | 47 +- src/engine/build.bat | 2 +- src/tools/builtin.jam | 931 ++++++++++++++++++------------------- src/tools/cast.jam | 54 +-- src/tools/common.jam | 461 +++++++++--------- src/tools/generate.jam | 74 ++- src/tools/gettext.jam | 87 ++-- src/tools/msvc.jam | 312 ++++++------- src/tools/notfile.jam | 46 +- src/tools/python.jam | 58 +-- src/tools/testing.jam | 415 +++++++++-------- src/util/indirect.jam | 65 +-- 20 files changed, 2892 insertions(+), 2998 deletions(-) diff --git a/src/build-system.jam b/src/build-system.jam index 18c0c0eeb..facab713d 100755 --- a/src/build-system.jam +++ b/src/build-system.jam @@ -1,8 +1,8 @@ -# Copyright 2003, 2005, 2007 Dave Abrahams -# Copyright 2006, 2007 Rene Rivera -# Copyright 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) +# Copyright 2003, 2005, 2007 Dave Abrahams +# Copyright 2006, 2007 Rene Rivera +# Copyright 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) # This file is part of Boost.Build version 2. You can think of it as # forming the main() routine. It is invoked by the bootstrapping code @@ -64,42 +64,42 @@ if $(test-config) { if $(debug-config) { - ECHO "notice: loading test-config.jam from" + ECHO "notice: loading test-config.jam from" [ NORMALIZE_PATH $(test-config[1]) ] ; ECHO "notice: user-config.jam and site-config.jam will be ignored" ; - } - - module test-config + } + + module test-config { import toolset : using : using ; } - import test-config ; + import test-config ; } local ignore-config ; -if $(test-config) || --ignore-config in [ modules.peek : ARGV ] -{ +if $(test-config) || --ignore-config in [ modules.peek : ARGV ] +{ ignore-config = true ; } local user-path = [ os.home-directories ] [ os.environ BOOST_BUILD_PATH ] ; - + # Unless ignore-config is set, load the configuration file in # $(path)/$(basename).jam local rule load-config ( basename : path + ) -{ - if ! $(ignore-config) +{ + if ! $(ignore-config) { if $(debug-config) { ECHO notice: searching \"$(path)\" for \"$(basename).jam\" ; local where = [ GLOB $(path) : $(basename).jam ] ; if $(where) - { + { ECHO notice: loading $(basename).jam from [ NORMALIZE_PATH $(where[1]) ] ; - } - } + } + } modules.load $(basename) : : $(path) ; project.load-used-projects $(basename) ; @@ -109,17 +109,17 @@ local rule load-config ( basename : path + ) # # Load site-config. # -module site-config +module site-config { import project : initialize ; - initialize site-config ; + initialize site-config ; } -local site-path = /etc $(user-path) ; +local site-path = /etc $(user-path) ; if [ os.name ] in NT CYGWIN -{ - site-path = [ modules.peek : SystemRoot ] $(user-path) ; +{ + site-path = [ modules.peek : SystemRoot ] $(user-path) ; } load-config site-config : $(site-path) ; @@ -127,30 +127,28 @@ load-config site-config : $(site-path) ; # # Load user-config. # -module user-config +module user-config { import project : initialize ; - initialize user-config ; + initialize user-config ; } local user-config-path = [ MATCH ^--user-config=(.*) : $(argv) ] ; - user-config-path ?= [ os.environ BOOST_BUILD_USER_CONFIG ] ; if $(user-config-path) { if $(debug-config) { - ECHO "Loading explicitly specifier user configuration file:" ; + ECHO "Loading explicitly specified user configuration file:" ; ECHO " $(user-config-path)" ; } - - + modules.load user-config : $(user-config-path:BS) : $(user-config-path:D) ; project.load-used-projects user-config ; } else -{ +{ load-config user-config : $(user-path) ; } @@ -164,7 +162,7 @@ local feature-toolsets = [ regex.split-list [ MATCH ^toolset=(.*) : $(argv) ] : # if the user specified --toolset=..., we need to add toolset=... to # the build request -local extra-build-request ; +local extra-build-request ; if ! $(ignore-config) { @@ -178,8 +176,8 @@ if ! $(ignore-config) if $(debug-config) { - ECHO notice: [cmdline-cfg] Detected command-line request for - $(toolset-version): toolset= \"$(toolset)\" "version= \""$(version)\" ; + ECHO notice: [cmdline-cfg] Detected command-line request for + $(toolset-version): toolset= \"$(toolset)\" "version= \""$(version)\" ; } local known ; @@ -190,8 +188,8 @@ if ! $(ignore-config) known = true ; } - if $(known) && $(version) - && ! [ feature.is-subvalue toolset : $(toolset) : version : $(version) ] + if $(known) && $(version) + && ! [ feature.is-subvalue toolset : $(toolset) : version : $(version) ] { known = ; } @@ -200,8 +198,8 @@ if ! $(ignore-config) { if $(debug-config) { - ECHO notice: [cmdline-cfg] toolset $(toolset-version) - not previously configured; configuring now ; + ECHO notice: [cmdline-cfg] toolset $(toolset-version) + not previously configured; configuring now ; } toolset.using $(toolset) : $(version) ; } @@ -216,7 +214,7 @@ if ! $(ignore-config) # make sure we get an appropriate property into the build request in # case the user used the "--toolset=..." form if ! $(t) in $(argv) - && ! $(t) in $(feature-toolsets) + && ! $(t) in $(feature-toolsets) { if $(debug-config) { @@ -226,14 +224,13 @@ if ! $(ignore-config) } } } - + if USER_MODULE in [ RULENAMES ] { USER_MODULE site-config user-config ; } - if --version in [ modules.peek : ARGV ] { version.print ; @@ -241,23 +238,22 @@ if --version in [ modules.peek : ARGV ] } - -# We always load project in "." so that 'use-project' directives has -# any chance of been seen. Otherwise, we won't be able to refer to -# subprojects using target ids. +# We always load project in "." so that 'use-project' directives has any chance +# of been seen. Otherwise, we won't be able to refer to subprojects using target +# ids. if [ project.find "." : "." ] -{ +{ current-project = [ project.target [ project.load "." ] ] ; -} +} -if ! [ feature.values ] +if ! [ feature.values ] { local default-toolset = gcc ; if [ os.name ] = NT { default-toolset = msvc ; } - + ECHO "warning: No toolsets are configured." ; ECHO "warning: Configuring default toolset" \"$(default-toolset)\". ; ECHO "warning: If the default is wrong, you may not be able to build C++ programs." ; @@ -265,30 +261,28 @@ if ! [ feature.values ] ECHO "warning: For more configuration options, please consult" ; ECHO "warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html" ; - if ! $(ignore-config) { toolset.using $(default-toolset) ; } } -build-request = [ - build-request.from-command-line [ - modules.peek : ARGV - ] $(extra-build-request) +build-request = [ + build-request.from-command-line [ modules.peek : ARGV ] + $(extra-build-request) ] ; properties = [ $(build-request).get-at 2 ] ; -if $(properties) -{ +if $(properties) +{ expanded = [ build-request.expand-no-defaults $(properties) ] ; local xexpanded ; for local e in $(expanded) { xexpanded += [ property-set.create [ feature.split $(e) ] ] ; } - expanded = $(xexpanded) ; + expanded = $(xexpanded) ; } else { @@ -321,8 +315,8 @@ local bjam-targets ; # that code without project-targets instance. rule find-target ( target-id ) { - local split = [ MATCH (.*)//(.*) : $(target-id) ] ; - + local split = [ MATCH (.*)//(.*) : $(target-id) ] ; + local pm ; if $(split) { @@ -332,27 +326,27 @@ rule find-target ( target-id ) { pm = [ project.find $(target-id) : "." ] ; } - - local result ; + + local result ; if $(pm) { result = [ project.target $(pm) ] ; } - + if $(split) { result = [ $(result).find $(split[2]) ] ; } - + return $(result) ; } -if ! $(current-project) +if ! $(current-project) { if ! $(target-ids) - { + { ECHO "error: no Jamfile in current directory found, and no target references specified." ; EXIT ; } @@ -364,7 +358,7 @@ for local id in $(target-ids) if $(id) = clean { clean = true ; - } + } else { local t ; @@ -376,7 +370,7 @@ for local id in $(target-ids) { t = [ find-target $(id) ] ; } - + if ! $(t) { ECHO "notice: could not find main target " $(id) ; @@ -386,13 +380,13 @@ for local id in $(target-ids) else { targets += $(t) ; - } - } + } + } } if ! $(targets) { - targets += [ project.target [ project.module-name "." ] ] ; + targets += [ project.target [ project.module-name "." ] ] ; } virtual-targets = ; @@ -410,18 +404,17 @@ for local p in $(expanded) { .command-line-free-features = [ property-set.create [ $(p).free ] ] ; for local t in $(targets) - { + { local g = [ $(t).generate $(p) ] ; if ! [ class.is-a $(t) : project-target ] { results-of-main-targets += $(g[2-]) ; - } + } virtual-targets += $(g[2-]) ; - } + } } -# The cleaning is tricky. Say, if -# user says: +# The cleaning is tricky. Say, if user says: # # bjam --clean foo # @@ -434,22 +427,22 @@ for local p in $(expanded) local projects-to-clean ; local targets-to-clean ; if $(clean) || $(clean-all) -{ +{ for local t in $(targets) { if [ class.is-a $(t) : project-target ] { projects-to-clean += [ $(t).project-module ] ; - } + } } - + local subvariants ; for local t in $(results-of-main-targets) { # Don't include roots or sources. targets-to-clean += [ virtual-target.traverse $(t) ] ; } - targets-to-clean = [ sequence.unique $(targets-to-clean) ] ; + targets-to-clean = [ sequence.unique $(targets-to-clean) ] ; } # Returns 'true' if 'project' is a child of 'current-project', @@ -461,22 +454,22 @@ rule is-child ( project ) { local r = false ; if $(project) in $(projects-to-clean) - { + { r = true ; } - else + else { local parent = [ project.attribute $(project) parent-module ] ; if $(parent) && $(parent) != user-config { r = [ is-child $(parent) ] ; - } - } - + } + } + .is-child.$(project) = $(r) ; } - - return $(.is-child.$(project)) ; + + return $(.is-child.$(project)) ; } @@ -500,7 +493,7 @@ if $(.out-xml) local project-path = [ $(project).get location ] ; return $(project-path)//$(name) ; } - + # Generate an XML file containing build statistics for each # constituent rule out-xml ( xml-file : constituents * ) @@ -559,7 +552,7 @@ if $(.out-xml) "$(nl) " "$(nl) " ; - } + } } .contents on $(xml-file) += "$(nl) " @@ -589,7 +582,7 @@ if $(.out-xml) # Nothing to do here; the *real* actions happen in # out-xml.generate-action actions quietly out-xml.generate { } - + # Define the out-xml file target, which depends on all the targets # so that it runs the collection after the targets have run. out-xml $(.out-xml) : $(actual-targets) ; @@ -607,7 +600,7 @@ if $(.out-xml) .contents on $(xml-file) += "$(nl) " ; - + # If we have an action object we can print out more detailed info. local action = [ on $(target) return $(.action) ] ; if $(action) @@ -615,12 +608,12 @@ if $(.out-xml) local action-name = [ $(action).action-name ] ; local action-sources = [ $(action).sources ] ; local action-props = [ $(action).properties ] ; - + # The qualified name of the action which we created the target. .contents on $(xml-file) += "$(nl) " ; - + # The sources that made up the target. .contents on $(xml-file) += "$(nl) " @@ -635,7 +628,7 @@ if $(.out-xml) .contents on $(xml-file) += "$(nl) " ; - + # The properties that define the conditions under which the # target was built. .contents on $(xml-file) += @@ -652,7 +645,7 @@ if $(.out-xml) "$(nl) " ; } - + local locate = [ on $(target) return $(LOCATE) ] ; locate ?= "" ; .contents on $(xml-file) += @@ -683,7 +676,7 @@ if $(bjam-targets) UPDATE $(bjam-targets:G=e) $(.out-xml) ; } else if $(cleanall) -{ +{ UPDATE clean-all ; } else if $(clean) diff --git a/src/build/alias.jam b/src/build/alias.jam index 14b938bdd..9b2b7b519 100644 --- a/src/build/alias.jam +++ b/src/build/alias.jam @@ -1,69 +1,69 @@ -# Copyright 2003, 2004, 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) +# Copyright 2003, 2004, 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) -# This module defines the 'alias' rule and associated class. +# This module defines the 'alias' rule and the associated target class. # -# Alias is just a main target which returns its source targets without any -# processing. For example:: +# Alias is just a main target which returns its source targets without any +# processing. For example: # # alias bin : hello test_hello ; # alias lib : helpers xml_parser ; # -# Another important use of 'alias' is to conveniently group source files:: +# Another important use of 'alias' is to conveniently group source files: # # alias platform-src : win.cpp : NT ; # alias platform-src : linux.cpp : LINUX ; # exe main : main.cpp platform-src ; -# +# # Lastly, it's possible to create local alias for some target, with different # properties:: # # alias big_lib : : @/external_project/big_lib/static ; # -import targets ; + import "class" : new ; -import errors : error ; import project ; import property-set ; +import targets ; -class alias-target-class : basic-target + +class alias-target-class : basic-target { - rule __init__ ( name : project : sources * : requirements * + rule __init__ ( name : project : sources * : requirements * : default-build * : usage-requirements * ) { - basic-target.__init__ $(name) : $(project) : $(sources) : $(requirements) - : $(default-build) : $(usage-requirements) ; + basic-target.__init__ $(name) : $(project) : $(sources) : $(requirements) + : $(default-build) : $(usage-requirements) ; } - + rule construct ( name : source-targets * : property-set ) { return [ property-set.empty ] $(source-targets) ; - } - - rule compute-usage-requirements ( subvariant ) + } + + rule compute-usage-requirements ( subvariant ) { local base = [ basic-target.compute-usage-requirements $(subvariant) ] ; # Add source's usage requirement. If we don't do this, "alias" does not # look like 100% alias. return [ $(base).add [ $(subvariant).sources-usage-requirements ] ] ; } - } # Declares the 'alias' target. It will build sources, and return them unaltered. rule alias ( name : sources * : requirements * : default-build * : usage-requirements * ) { local project = [ project.current ] ; - + targets.main-target-alternative - [ new alias-target-class $(name) : $(project) - : [ targets.main-target-sources $(sources) : $(name) : no-renaming ] - : [ targets.main-target-requirements $(requirements) : $(project) ] - : [ targets.main-target-default-build $(default-build) : $(project) ] - : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] - ] ; + [ new alias-target-class $(name) : $(project) + : [ targets.main-target-sources $(sources) : $(name) : no-renaming ] + : [ targets.main-target-requirements $(requirements) : $(project) ] + : [ targets.main-target-default-build $(default-build) : $(project) ] + : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] + ] ; } IMPORT $(__name__) : alias : : alias ; diff --git a/src/build/feature.jam b/src/build/feature.jam index 0e4e88830..66b317d4c 100644 --- a/src/build/feature.jam +++ b/src/build/feature.jam @@ -1,52 +1,53 @@ -# Copyright 2001, 2002, 2003 Dave Abrahams -# Copyright 2002, 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) +# Copyright 2001, 2002, 2003 Dave Abrahams +# Copyright 2002, 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) +import assert : * ; import "class" : * ; - -import errors : error lol->list ; -import sequence ; +import errors : lol->list ; +import indirect ; +import modules ; import regex ; +import sequence ; import set ; import utility ; -import modules indirect ; -import assert : * ; + local rule setup ( ) { .all-attributes = - - implicit - executed - composite - optional - symmetric - free - incidental - path - dependency - propagated - link-incompatible - subfeature - order-sensitive - ; + implicit + executed + composite + optional + symmetric + free + incidental + path + dependency + propagated + link-incompatible + subfeature + order-sensitive + ; .all-features = ; - .all-subfeatures = ; # non-subfeatures - .all-top-features = ; # non-subfeatures + .all-subfeatures = ; + .all-top-features = ; # non-subfeatures .all-implicit-values = ; } setup ; -# prepare a fresh space to test in by moving all global variable -# settings into the given temporary module and erasing them here. + +# Prepare a fresh space to test in by moving all global variable settings into +# the given temporary module and erasing them here. rule prepare-test ( temp-module ) { DELETE_MODULE $(temp-module) ; - - # transfer globals to temp-module + + # Transfer globals to temp-module. for local v in [ VARNAMES feature ] { if [ MATCH (\\.) : $(v) ] @@ -58,11 +59,12 @@ rule prepare-test ( temp-module ) setup ; } -# clear out all global variables and recover all variables from the -# given temporary module + +# Clear out all global variables and recover all variables from the given +# temporary module. rule finish-test ( temp-module ) { - # clear globals + # Clear globals. for local v in [ VARNAMES feature ] { if [ MATCH (\\.) : $(v) ] @@ -70,7 +72,7 @@ rule finish-test ( temp-module ) $(v) = ; } } - + for local v in [ VARNAMES $(temp-module) ] { $(v) = [ modules.peek $(temp-module) : $(v) ] ; @@ -79,33 +81,31 @@ rule finish-test ( temp-module ) } -# Transform features by bracketing any elements which aren't already -# bracketed by "<>" +# Transform features by bracketing any elements which aren't already bracketed +# by "<>". local rule grist ( features * ) { local empty = "" ; - local r = $(empty:G=$(features)) ; - return $(r) ; + return $(empty:G=$(features)) ; } -empty = "" ; -# declare a new feature with the given name, values, and attributes. -rule feature ( - name # feature name - : values * # the allowable values - may be extended later with feature.extend - : attributes * # The feature's attributes (e.g. implicit, free, propagated...) +# Declare a new feature with the given name, values, and attributes. +rule feature ( + name # Feature name. + : values * # Allowable values - may be extended later using feature.extend. + : attributes * # Feature attributes (e.g. implicit, free, propagated...). ) { name = [ grist $(name) ] ; local error ; - # if there are any unknown attributes... + # Check for any unknown attributes. if ! ( $(attributes) in $(.all-attributes) ) { error = unknown attributes: - [ set.difference $(attributes) : $(.all-attributes) ] ; + [ set.difference $(attributes) : $(.all-attributes) ] ; } else if $(name) in $(.all-features) { @@ -116,16 +116,15 @@ rule feature ( error = free features cannot also be implicit ; } else if free in $(attributes) && propagated in $(attributes) - { + { error = free features cannot be propagated ; - } - + } if $(error) { - error $(error) - : "in" feature declaration: - : feature [ lol->list $(1) : $(2) : $(3) ] ; + errors.error $(error) + : "in" feature declaration: + : feature [ lol->list $(1) : $(2) : $(3) ] ; } $(name).values ?= ; @@ -142,24 +141,24 @@ rule feature ( { .all-top-features += $(name) ; } - extend $(name) : $(values) ; + extend $(name) : $(values) ; } -# set default value of the given feature, overriding any previous -# default. + +# Sets the default value of the given feature, overriding any previous default. rule set-default ( feature : value ) { local f = [ grist $(feature) ] ; - if ! $(value) in $($(f).values) + if ! $(value) in $($(f).values) { - errors.error "The specified default value, '$(value)' is invalid" + errors.error "The specified default value, '$(value)' is invalid" : "allowed values are: " $($(f).values) ; - } + } $(f).default = $(value) ; } -# return the default property values for the given features. +# Returns the default property values for the given features. rule defaults ( features * ) { local result ; @@ -178,7 +177,8 @@ rule defaults ( features * ) return $(result) ; } -# returns true iff all elements of names are valid features. + +# Returns true iff all 'names' elements are valid features. rule valid ( names + ) { if $(names) in $(.all-features) @@ -187,31 +187,33 @@ rule valid ( names + ) } } -# return the attibutes of the given feature + +# Returns the attibutes of the given feature. rule attributes ( feature ) { return $($(:E=:G=$(feature)).attributes) ; } -# return the values of the given feature + +# Returns the values of the given feature. rule values ( feature ) { return $($(:E=:G=$(feature)).values) ; } -# returns true iff 'value-string' is a value-string of an implicit feature + +# Returns true iff 'value-string' is a value-string of an implicit feature. rule is-implicit-value ( value-string ) { local v = [ regex.split $(value-string) - ] ; local failed ; - if ! $(v[1]) in $(.all-implicit-values) + if ! $(v[1]) in $(.all-implicit-values) { failed = true ; } - else + else { local feature = $($(v[1]).implicit-feature) ; - for local subvalue in $(v[2-]) { if ! [ find-implied-subfeature $(feature) $(subvalue) : $(v[1]) ] @@ -220,82 +222,87 @@ rule is-implicit-value ( value-string ) } } } - - if ! $(failed) + + if ! $(failed) { return true ; } } -# return the implicit feature associated with the given implicit value. + +# Returns the implicit feature associated with the given implicit value. rule implied-feature ( implicit-value ) { local components = [ regex.split $(implicit-value) "-" ] ; - + local feature = $($(components[1]).implicit-feature) ; if ! $(feature) { - error \"$(implicit-value)\" is not a value of an implicit feature ; - feature = "" ; # keep testing happy; it expects a result. + errors.error \"$(implicit-value)\" is not a value of an implicit feature ; + feature = "" ; # Keep testing happy; it expects a result. } return $(feature) ; } + local rule find-implied-subfeature ( feature subvalue : value-string ? ) { - # feature should be of the form + # Feature should be of the form . if $(feature) != $(feature:G) { - error invalid feature $(feature) ; + errors.error invalid feature $(feature) ; } return $($(feature)$(value-string:E="")<>$(subvalue).subfeature) ; } -# Given a feature and a value of one of its subfeatures, find the name -# of the subfeature. If value-string is supplied, looks for implied -# subfeatures that are specific to that value of feature -rule implied-subfeature ( - feature # The main feature name - subvalue # The value of one of its subfeatures - : value-string ? # The value of the main feature + +# Given a feature and a value of one of its subfeatures, find the name of the +# subfeature. If value-string is supplied, looks for implied subfeatures that +# are specific to that value of feature +rule implied-subfeature ( + feature # The main feature name. + subvalue # The value of one of its subfeatures. + : value-string ? # The value of the main feature. ) { local subfeature = [ find-implied-subfeature $(feature) $(subvalue) - : $(value-string) ] ; - + : $(value-string) ] ; if ! $(subfeature) { value-string ?= "" ; - error \"$(subvalue)\" is not a known subfeature value of - $(feature)$(value-string) ; + errors.error \"$(subvalue)\" is not a known subfeature value of + $(feature)$(value-string) ; } - return $(subfeature) ; } -# generate an error if the feature is unknown + +# Generate an error if the feature is unknown. local rule validate-feature ( feature ) { if ! $(feature) in $(.all-features) { - error unknown feature \"$(feature)\" ; + errors.error unknown feature \"$(feature)\" ; } } -# Given a feature and value, or just a value corresponding to an -# implicit feature, returns a property set consisting of all component -# subfeatures and their values. For example: + +# Given a feature and its value or just a value corresponding to an implicit +# feature, returns a property set consisting of all component subfeatures and +# their values. For example all the following calls: # -# expand-subfeatures gcc-2.95.2-linux-x86 -# -> gcc 2.95.2 linux x86 +# expand-subfeatures-aux gcc-2.95.2-linux-x86 +# expand-subfeatures-aux gcc-2.95.2-linux-x86 # -# equivalent to: -# expand-subfeatures gcc-2.95.2-linux-x86 -local rule expand-subfeatures-aux ( - feature ? # The name of the feature, or empty if value corresponds to an implicit property - : value # The value of the feature. - : dont-validate ? # If set, no validation of value string will be done +# return: +# +# gcc 2.95.2 linux x86 +local rule expand-subfeatures-aux ( + feature ? # Feature name or empty if value corresponds to an + # implicit property. + : value # Feature value. + : dont-validate ? # If set, no value string validation will be done. ) { if $(feature) @@ -312,31 +319,31 @@ local rule expand-subfeatures-aux ( validate-feature $(feature) ; } if ! $(dont-validate) - { + { validate-value-string $(feature) $(value) ; } - + local components = [ regex.split $(value) "-" ] ; - - # get the top-level feature's value + + # Get the top-level feature's value. local value = $(components[1]:G=) ; local result = $(components[1]:G=$(feature)) ; - + local subvalues = $(components[2-]) ; while $(subvalues) { - local subvalue = $(subvalues[1]) ; # pop the head off of subvalues + local subvalue = $(subvalues[1]) ; # Pop the head off of subvalues. subvalues = $(subvalues[2-]) ; - + local subfeature = [ find-implied-subfeature $(feature) $(subvalue) : $(value) ] ; - - # If no subfeature was found, reconstitute the value string and use that + + # If no subfeature was found reconstitute the value string and use that. if ! $(subfeature) { result = $(components:J=-) ; result = $(result:G=$(feature)) ; - subvalues = ; # stop looping + subvalues = ; # Stop looping. } else { @@ -344,25 +351,27 @@ local rule expand-subfeatures-aux ( result += $(subvalue:G=$(f)-$(subfeature)) ; } } - + return $(result) ; } -# Make all elements of properties corresponding to implicit features -# explicit, and express all subfeature values as separate properties -# in their own right. For example, the property + +# Make all elements of properties corresponding to implicit features explicit, +# and express all subfeature values as separate properties in their own right. +# For example, all of the following properties # # gcc-2.95.2-linux-x86 +# gcc-2.95.2-linux-x86 # # might expand to # # gcc 2.95.2 linux x86 # -rule expand-subfeatures ( - properties * # property set with elements of the form - # value-string or just value-string in the - # case of implicit features. - : dont-validate ? +rule expand-subfeatures ( + properties * # Property set with elements of the form + # value-string or just value-string in the case + # of implicit features. + : dont-validate ? ) { local result ; @@ -370,17 +379,18 @@ rule expand-subfeatures ( { # Don't expand subfeatures in subfeatures if ! [ MATCH "(:)" : $(p:G) ] - { + { result += [ expand-subfeatures-aux $(p:G) : $(p:G=) : $(dont-validate) ] ; } else { result += $(p) ; - } + } } return $(result) ; } + # Helper for extend, below. Handles the feature case. local rule extend-feature ( feature : values * ) { @@ -392,7 +402,7 @@ local rule extend-feature ( feature : values * ) { if $($(v).implicit-feature) { - error $(v) is already associated with the \"$($(v).implicit-feature)\" feature ; + errors.error $(v) is already associated with the \"$($(v).implicit-feature)\" feature ; } $(v).implicit-feature = $(feature) ; } @@ -404,20 +414,21 @@ local rule extend-feature ( feature : values * ) # This is the first value specified for this feature, # take it as default value $(feature).default = $(values[1]) ; - } + } $(feature).values += $(values) ; } + # Checks that value-string is a valid value-string for the given feature. rule validate-value-string ( feature value-string ) -{ - if ! ( - free in $($(feature).attributes) - || ( $(value-string) in $(feature).values ) +{ + if ! ( + free in $($(feature).attributes) + || ( $(value-string) in $(feature).values ) ) { local values = $(value-string) ; - + if $($(feature).subfeatures) { values = [ regex.split $(value-string) - ] ; @@ -425,38 +436,33 @@ rule validate-value-string ( feature value-string ) if ! ( $(values[1]) in $($(feature).values) ) && - # An empty value is allowed for optional features - ( $(values[1]) || ! ( optional in $($(feature).attributes) ) ) + # An empty value is allowed for optional features. + ( $(values[1]) || ! ( optional in $($(feature).attributes) ) ) { - error \"$(values[1])\" is not a known value of feature $(feature) - : legal values: \"$($(feature).values)\" ; + errors.error \"$(values[1])\" is not a known value of feature $(feature) + : legal values: \"$($(feature).values)\" ; } for local v in $(values[2-]) { - # this will validate any subfeature values in value-string + # This will validate any subfeature values in value-string. implied-subfeature $(feature) $(v) : $(values[1]) ; } } } + # A helper that computes: -# * the name(s) of the module-local variable(s) used to record the -# correspondence between subvalue(s) and a subfeature -# -# * the value of that variable when such a subfeature/subvalue has -# been defined -# -# Returns a list consisting of the latter followed by the former -local rule subvalue-var ( - feature # Main feature name - - value-string ? # If supplied, specifies a specific value of the - # main feature for which the subfeature values - # are valid - - : subfeature # The name of the subfeature - : subvalues * # The subfeature values +# * name(s) of module-local variable(s) used to record the correspondence +# between subvalue(s) and a subfeature +# * value of that variable when such a subfeature/subvalue has been defined and +# returns a list consisting of the latter followed by the former. +local rule subvalue-var ( + feature # Main feature name. + value-string ? # If supplied, specifies a specific value of the main + # feature for which the subfeature values are valid. + : subfeature # Subfeature name. + : subvalues * # Subfeature values. ) { feature = [ grist $(feature) ] ; @@ -472,68 +478,68 @@ local rule subvalue-var ( $(feature)$(value-string:E="")<>$(subvalues).subfeature ; } -# Extends the given subfeature with the subvalues. If the optional -# value-string is provided, the subvalues are only valid for the given -# value of the feature. Thus, you could say that -# mingw is specifc to gcc-2.95.2 as follows: + +# Extends the given subfeature with the subvalues. If the optional value-string +# is provided, the subvalues are only valid for the given value of the feature. +# Thus, you could say that mingw is specific to +# gcc-2.95.2 as follows: # # extend-subfeature toolset gcc-2.95.2 : target-platform : mingw ; # -rule extend-subfeature ( - feature # The feature whose subfeature is being extended - - value-string ? # If supplied, specifies a specific value of the - # main feature for which the new subfeature values - # are valid - - : subfeature # The name of the subfeature - : subvalues * # The additional values of the subfeature being defined. +rule extend-subfeature ( + feature # The feature whose subfeature is being extended. + + value-string ? # If supplied, specifies a specific value of the main + # feature for which the new subfeature values are valid. + + : subfeature # Subfeature name. + : subvalues * # Additional subfeature values. ) { - local subfeature-vars = [ - subvalue-var $(feature) $(value-string) : $(subfeature) : $(subvalues) ] ; - + local subfeature-vars = [ subvalue-var $(feature) $(value-string) + : $(subfeature) : $(subvalues) ] ; + local f = [ utility.ungrist [ grist $(feature) ] ] ; extend $(f)-$(subfeature-vars[1]) : $(subvalues) ; - - # provide a way to get from the given feature or property and - # subfeature value to the subfeature name. + + # Provide a way to get from the given feature or property and subfeature + # value to the subfeature name. $(subfeature-vars[2-]) = $(subfeature-vars[1]) ; } -# Returns true iff the subvalues are valid for the feature. When the -# optional value-string is provided, returns true iff the subvalues -# are valid for the given value of the feature. + +# Returns true iff the subvalues are valid for the feature. When the optional +# value-string is provided, returns true iff the subvalues are valid for the +# given value of the feature. rule is-subvalue ( feature : value-string ? : subfeature : subvalue ) { - local subfeature-vars = [ - subvalue-var $(feature) $(value-string) : $(subfeature) : $(subvalue) ] ; - - if $($(subfeature-vars[2])) = $(subfeature-vars[1]) + local subfeature-vars = [ subvalue-var $(feature) $(value-string) + : $(subfeature) : $(subvalue) ] ; + + if $($(subfeature-vars[2])) = $(subfeature-vars[1]) { return true ; } } + # Can be called three ways: # # 1. extend feature : values * # 2. extend subfeature : values * # 3. extend value-string subfeature : values * # -# * Form 1 adds the given values to the given feature -# * Forms 2 and 3 add subfeature values to the given feature -# * Form 3 adds the subfeature values as specific to the given -# property value-string. +# * Form 1 adds the given values to the given feature. +# * Forms 2 and 3 add subfeature values to the given feature. +# * Form 3 adds the subfeature values as specific to the given property +# value-string. # rule extend ( feature-or-property subfeature ? : values * ) { - local - feature # If a property was specified this is its feature - value-string # E.G., the gcc-2.95-2 part of gcc-2.95.2 - ; + local feature ; # If a property was specified this is its feature. + local value-string ; # E.g., the gcc-2.95-2 part of gcc-2.95.2. - # if a property was specified + # If a property was specified. if $(feature-or-property:G) && $(feature-or-property:G=) { # Extract the feature and value-string, if any. @@ -545,140 +551,145 @@ rule extend ( feature-or-property subfeature ? : values * ) feature = [ grist $(feature-or-property) ] ; } - # Dispatch to the appropriate handler + # Dispatch to the appropriate handler. if $(subfeature) { - extend-subfeature $(feature) $(value-string) - : $(subfeature) : $(values) ; + extend-subfeature $(feature) $(value-string) : $(subfeature) + : $(values) ; } else { # If no subfeature was specified, we didn't expect to see a - # value-string + # value-string. if $(value-string) { - error can only be specify a property as the first argument - when extending a subfeature - : usage: - : " extend" feature ":" values... - : " | extend" value-string subfeature ":" values... - ; + errors.error can only specify a property as the first argument when + extending a subfeature + : usage: + : " extend" feature ":" values... + : " | extend" value-string subfeature ":" values... + ; } extend-feature $(feature) : $(values) ; } } + local rule get-subfeature-name ( subfeature value-string ? ) { local prefix = $(value-string): ; return $(prefix:E="")$(subfeature) ; } -# Declares a subfeature -rule subfeature ( - feature # Root feature that is not a subfeature - value-string ? # A value-string specifying which feature or - # subfeature values this subfeature is specific to, - # if any - - : subfeature # The name of the subfeature being declared - : subvalues * # The allowed values of this subfeature - : attributes * # The attributes of the subfeature + +# Declares a subfeature. +rule subfeature ( + feature # Root feature that is not a subfeature. + value-string ? # A value-string specifying which feature or subfeature + # values this subfeature is specific to, if any. + : subfeature # The name of the subfeature being declared. + : subvalues * # The allowed values of this subfeature. + : attributes * # The attributes of the subfeature. ) { feature = [ grist $(feature) ] ; validate-feature $(feature) ; - - # Add grist to the subfeature name if a value-string was supplied + + # Add grist to the subfeature name if a value-string was supplied. local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ; - + if $(subfeature-name) in $($(feature).subfeatures) { - error \"$(subfeature)\" already declared as a subfeature of \"$(feature)\" - "specific to "$(value-string) ; + errors.error \"$(subfeature)\" already declared as a subfeature of \"$(feature)\" + "specific to "$(value-string) ; } $(feature).subfeatures += $(subfeature-name) ; - - # First declare the subfeature as a feature in its own right + + # First declare the subfeature as a feature in its own right. local f = [ utility.ungrist $(feature) ] ; feature $(f)-$(subfeature-name) : $(subvalues) : $(attributes) subfeature ; - + # Now make sure the subfeature values are known. extend-subfeature $(feature) $(value-string) : $(subfeature) : $(subvalues) ; } -# Set the components of the given composite property + +# Set components of the given composite property. rule compose ( composite-property : component-properties * ) { local feature = $(composite-property:G) ; if ! ( composite in [ attributes $(feature) ] ) { - error "$(feature)" is not a composite feature ; + errors.error "$(feature)" is not a composite feature ; } $(composite-property).components ?= ; if $($(composite-property).components) { - error components of "$(composite-property)" already set: - $($(composite-property).components) ; + errors.error components of "$(composite-property)" already set: + $($(composite-property).components) ; } if $(composite-property) in $(component-properties) { - error composite property "$(composite-property)" cannot have itself as a component ; + errors.error composite property "$(composite-property)" cannot have itself as a component ; } $(composite-property).components = $(component-properties) ; } + local rule expand-composite ( property ) { return $(property) - [ sequence.transform expand-composite : $($(property).components) ] ; + [ sequence.transform expand-composite : $($(property).components) ] ; } -# return all values of the given feature specified by the given property set. + +# Return all values of the given feature specified by the given property set. rule get-values ( feature : properties * ) { local result ; - - feature = $(:E=:G=$(feature)) ; # add <> if necessary. + + feature = $(:E=:G=$(feature)) ; # Add <> if necessary. for local p in $(properties) { if $(p:G) = $(feature) { - #~ Use MATCH instead if :G= to get the value, in order to preserve - #~ the value intact instead of having bjam treat it as a decompossible - #~ path. + # Use MATCH instead of :G= to get the value, in order to preserve + # the value intact instead of having bjam treat it as a decomposable + # path. result += [ MATCH ">(.*)" : $(p) ] ; } } return $(result) ; } + rule free-features ( ) { return $(free.features) ; } -# Expand all composite properties in the set so that all components -# are explicitly expressed. + +# Expand all composite properties in the set so that all components are +# explicitly expressed. rule expand-composites ( properties * ) { local explicit-features = $(properties:G) ; - local result ; - # now expand composite features + + # Now expand composite features. for local p in $(properties) { local expanded = [ expand-composite $(p) ] ; - + for local x in $(expanded) { if ! $(x) in $(result) { local f = $(x:G) ; - + if $(f) in $(free.features) { result += $(x) ; @@ -689,21 +700,21 @@ rule expand-composites ( properties * ) { if $(f) in $(result:G) { - error expansions of composite features result in conflicting - values for $(f) - : values: [ get-values $(f) : $(result) ] $(x:G=) - : one contributing composite property was $(p) ; + errors.error expansions of composite features result + in conflicting values for $(f) + : values: [ get-values $(f) : $(result) ] $(x:G=) + : one contributing composite property was $(p) ; } else { result += $(x) ; } } - } + } else if $(f) in $(result:G) { - error explicitly-specified values of non-free feature - $(f) conflict : + errors.error explicitly-specified values of non-free feature + $(f) conflict : "existing values:" [ get-values $(f) : $(properties) ] : "value from expanding " $(p) ":" $(x:G=) ; } @@ -711,15 +722,16 @@ rule expand-composites ( properties * ) { result += $(x) ; } - } + } } } return $(result) ; } -# Return true iff f is an ordinary subfeature of the parent-property's -# feature, or if f is a subfeature fo the parent-property's feature -# specific to the parent-property's value + +# Return true iff f is an ordinary subfeature of the parent-property's feature, +# or if f is a subfeature of the parent-property's feature specific to the +# parent-property's value. local rule is-subfeature-of ( parent-property f ) { if subfeature in $($(f).attributes) @@ -727,9 +739,8 @@ local rule is-subfeature-of ( parent-property f ) local specific-subfeature = [ MATCH <(.*):(.*)> : $(f) ] ; if $(specific-subfeature) { - # The feature has the form - # , - # e.g. + # The feature has the form , e.g. + # . local feature-value = [ split-top-feature $(specific-subfeature[1]) ] ; if <$(feature-value[1])>$(feature-value[2]) = $(parent-property) { @@ -738,10 +749,9 @@ local rule is-subfeature-of ( parent-property f ) } else { - # The feature has the form , - # e.g. + # The feature has the form , e.g. + # local top-sub = [ split-top-feature [ utility.ungrist $(f) ] ] ; - if $(top-sub[2]) && <$(top-sub[1])> = $(parent-property:G) { return true ; @@ -750,46 +760,47 @@ local rule is-subfeature-of ( parent-property f ) } } -# as above, for subproperties + +# As for is-subfeature-of but for subproperties. local rule is-subproperty-of ( parent-property p ) { return [ is-subfeature-of $(parent-property) $(p:G) ] ; } -# Given a property, return the subset of features consisting of all -# ordinary subfeatures of the property's feature, and all specific -# subfeatures of the property's feature which are conditional on the -# property's value. + +# Given a property, return the subset of features consisting of all ordinary +# subfeatures of the property's feature, and all specific subfeatures of the +# property's feature which are conditional on the property's value. local rule select-subfeatures ( parent-property : features * ) { return [ sequence.filter is-subfeature-of $(parent-property) : $(features) ] ; } - -# as above, for subproperties + + +# As for select-subfeatures but for subproperties. local rule select-subproperties ( parent-property : properties * ) { return [ sequence.filter is-subproperty-of $(parent-property) : $(properties) ] ; } -# Given a property set which may consist of composite and implicit -# properties and combined subfeature values, returns an expanded, -# normalized property set with all implicit features expressed -# explicitly, all subfeature values individually expressed, and all -# components of composite properties expanded. Non-free features -# directly expressed in the input properties cause any values of -# those features due to composite feature expansion to be dropped. If -# two values of a given non-free feature are directly expressed in the -# input, an error is issued. + +# Given a property set which may consist of composite and implicit properties +# and combined subfeature values, returns an expanded, normalized property set +# with all implicit features expressed explicitly, all subfeature values +# individually expressed, and all components of composite properties expanded. +# Non-free features directly expressed in the input properties cause any values +# of those features due to composite feature expansion to be dropped. If two +# values of a given non-free feature are directly expressed in the input, an +# error is issued. rule expand ( properties * ) { local expanded = [ expand-subfeatures $(properties) ] ; - return [ expand-composites $(expanded) ] ; } -# Helper rule for minimize, below - return true iff property's feature -# is present in the contents of the variable named by feature-set-var. +# Helper rule for minimize. Returns true iff property's feature is present in +# the contents of the variable named by feature-set-var. local rule in-features ( feature-set-var property ) { if $(property:G) in $($(feature-set-var)) @@ -798,9 +809,9 @@ local rule in-features ( feature-set-var property ) } } -# Helper for minimize, below - returns the list with -# the same properties, but where all subfeatures -# are in the end of the list + +# Helper rule for minimize. Returns the list with the same properties, but with +# all subfeatures moved to the end of the list. local rule move-subfeatures-to-the-end ( properties * ) { local x1 ; @@ -814,53 +825,53 @@ local rule move-subfeatures-to-the-end ( properties * ) else { x1 += $(p) ; - } + } } - return $(x1) $(x2) ; + return $(x1) $(x2) ; } -# Given an expanded property set, eliminate all redundancy: properties -# which are elements of other (composite) properties in the set will -# be eliminated. Non-symmetric properties equal to default values will be -# eliminated, unless the override a value from some composite property. -# Implicit properties will be expressed without feature -# grist, and sub-property values will be expressed as elements joined -# to the corresponding main property. +# Given an expanded property set, eliminate all redundancy: properties that are +# elements of other (composite) properties in the set will be eliminated. +# Non-symmetric properties equal to default values will be eliminated unless +# they override a value from some composite property. Implicit properties will +# be expressed without feature grist, and sub-property values will be expressed +# as elements joined to the corresponding main property. rule minimize ( properties * ) { # Precondition checking local implicits = [ set.intersection $(p:G=) : $(p:G) ] ; if $(implicits) { - error minimize requires an expanded property set, but \"$(implicits[1])\" - appears to be the value of an un-expanded implicit feature ; + errors.error minimize requires an expanded property set, but + \"$(implicits[1])\" appears to be the value of an un-expanded + implicit feature ; } - - # remove properties implied by composite features + + # Remove properties implied by composite features. local components = $($(properties).components) ; local x = [ set.difference $(properties) : $(components) ] ; - - # handle subfeatures and implicit features - x = [ move-subfeatures-to-the-end $(x) ] ; + + # Handle subfeatures and implicit features. + x = [ move-subfeatures-to-the-end $(x) ] ; local result ; while $(x) { local p fullp = $(x[1]) ; local f = $(p:G) ; local v = $(p:G=) ; - - # eliminate features in implicit properties. + + # Eliminate features in implicit properties. if implicit in [ attributes $(f) ] { p = $(v) ; } - # locate all subproperties of $(x[1]) in the property set + # Locate all subproperties of $(x[1]) in the property set. local subproperties = [ select-subproperties $(fullp) : $(x) ] ; if $(subproperties) { - # reconstitute the joined property name + # Reconstitute the joined property name. local sorted = [ sequence.insertion-sort $(subproperties) ] ; result += $(p)-$(sorted:G="":J=-) ; @@ -868,16 +879,16 @@ rule minimize ( properties * ) } else { - # eliminate properties whose value is equal to feature's - # default and which are not symmetric and which do not - # contradict values implied by composite properties. - - # since all component properties of composites in the set - # have been eliminated, any remaining property whose - # feature is the same as a component of a composite in the - # set must have a non-redundant value. + # Eliminate properties whose value is equal to feature's default, + # which are not symmetric and which do not contradict values implied + # by composite properties. + + # Since all component properties of composites in the set have been + # eliminated, any remaining property whose feature is the same as a + # component of a composite in the set must have a non-redundant + # value. if $(fullp) != [ defaults $(f) ] - || symmetric in [ attributes $(f) ] + || symmetric in [ attributes $(f) ] || $(fullp:G) in $(components:G) { result += $(p) ; @@ -889,33 +900,33 @@ rule minimize ( properties * ) return $(result) ; } + # Combine all subproperties into their parent properties # -# Requires: for every subproperty, there is a parent property. All -# features are explicitly expressed. +# Requires: for every subproperty, there is a parent property. All features are +# explicitly expressed. # -# This rule probably shouldn't be needed, but -# build-request.expand-no-defaults is being abused for unintended -# purposes and it needs help +# This rule probably shouldn't be needed, but build-request.expand-no-defaults +# is being abused for unintended purposes and it needs help. rule compress-subproperties ( properties * ) { - local all-subs matched-subs result ; - + local all-subs ; + local matched-subs ; + local result ; + for local p in $(properties) { if ! $(p:G) { - assert.nonempty-variable p:G ; # expecting fully-gristed properties + # Expecting fully-gristed properties. + assert.nonempty-variable p:G ; } - - + if ! subfeature in $($(p:G).attributes) { - local subs = [ - sequence.insertion-sort - [ sequence.filter is-subproperty-of $(p) : $(properties) ] - ] ; - + local subs = [ sequence.insertion-sort + [ sequence.filter is-subproperty-of $(p) : $(properties) ] ] ; + matched-subs += $(subs) ; local subvalues = -$(subs:G=:J=-) ; @@ -930,17 +941,16 @@ rule compress-subproperties ( properties * ) assert.result true : set.equal $(all-subs) : $(matched-subs) ; return $(result) ; } - -# given an ungristed string, finds the longest prefix which is a -# top-level feature name followed by a dash, and return a pair -# consisting of the parts before and after that dash. More -# interesting than a simple split because feature names can contain -# dashes. + + +# Given an ungristed string, finds the longest prefix which is a top-level +# feature name followed by a dash, and return a pair consisting of the parts +# before and after that dash. More interesting than a simple split because +# feature names may contain dashes. local rule split-top-feature ( feature-plus ) { local e = [ regex.split $(feature-plus) - ] ; local f = $(e[1]) ; - local v ; while $(e) { @@ -953,22 +963,24 @@ local rule split-top-feature ( feature-plus ) } return $(v) ; } - -# Given a set of properties, add default values for features not -# represented in the set. -# Note: if there's there's ordinary feature F1 and composite feature -# F2, which includes some value for F1, and both feature have default values, -# then the default value of F1 will be added, not the value in F2. This might -# not be right idea: consider + + +# Given a set of properties, add default values for features not represented in +# the set. +# +# Note: if there's an ordinary feature F1 and a composite feature F2 which +# includes some value for F1 and both feature have default values then the +# default value of F1 will be added (as opposed to the value in F2). This might +# not be the right idea, e.g. consider: # # feature variant : debug ... ; # debug : .... on # feature : off on ; -# +# # Here, when adding default for an empty property set, we'll get # # debug off -# +# # and that's kind of strange. rule add-defaults ( properties * ) { @@ -976,22 +988,23 @@ rule add-defaults ( properties * ) { if $(v) in $(properties) { - error add-defaults requires explicitly specified features, - but \"$(v)\" appears to be the value of an un-expanded implicit feature ; + errors.error add-defaults requires explicitly specified features, + but \"$(v)\" appears to be the value of an un-expanded implicit + feature ; } } # We don't add default for elements with ":" inside. This catches: # 1. Conditional properties --- we don't want debug:DEBUG # to be takes as specified value for - # 2. Free properties with ":" in values. We don't care, since free properties - # don't have defaults. + # 2. Free properties with ":" in values. We don't care, since free + # properties don't have defaults. local xproperties = [ MATCH "^([^:]+)$" : $(properties) ] ; local missing-top = [ set.difference $(.all-top-features) : $(xproperties:G) ] ; local more = [ defaults $(missing-top) ] ; properties += $(more) ; xproperties += $(more) ; - - # Add defaults for subfeatures of features which are present + + # Add defaults for subfeatures of features which are present. for local p in $(xproperties) { local s = $($(p:G).subfeatures) ; @@ -999,19 +1012,20 @@ rule add-defaults ( properties * ) local missing-subs = [ set.difference <$(f)-$(s)> : $(properties:G) ] ; properties += [ defaults [ select-subfeatures $(p) : $(missing-subs) ] ] ; } - + return $(properties) ; } + # Given a property-set of the form # v1/v2/...vN-1/vN/vN+1/...vM # # Returns # v1 v2 ... vN-1 vN vN+1 ... vM # -# Note that vN...vM may contain slashes. This is resilient to the -# substitution of backslashes for slashes, since Jam, unbidden, -# sometimes swaps slash direction on NT. +# Note that vN...vM may contain slashes. This needs to be resilient to the +# substitution of backslashes for slashes, since Jam, unbidden, sometimes swaps +# slash direction on NT. rule split ( property-set ) { local pieces = [ regex.split $(property-set) [\\/] ] ; @@ -1032,18 +1046,19 @@ rule split ( property-set ) return $(result) ; } -# tests of module feature + +# Tests of module feature. local rule __test__ ( ) { - # use a fresh copy of the feature module + # Use a fresh copy of the feature module. prepare-test feature-test-temp ; - # These are local rules and so must be explicitly reimported into - # the testing module - import feature : extend-feature validate-feature select-subfeatures ; - - import errors : try catch ; import assert ; + import errors : try catch ; + + # These are local rules and so must be explicitly reimported into the + # testing module. + import feature : extend-feature validate-feature select-subfeatures ; feature toolset : gcc : implicit ; feature define : : free ; @@ -1063,84 +1078,74 @@ local rule __test__ ( ) { compose profile : profile ; } - catch composite property profile cannot have itself as a component ; + catch composite property profile cannot have itself as a component ; extend-feature toolset : msvc metrowerks ; - subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 - 3.0 3.0.1 3.0.2 ; - + subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 3.0 3.0.1 3.0.2 ; + assert.true is-subvalue toolset : gcc : version : 2.95.3 ; assert.false is-subvalue toolset : gcc : version : 1.1 ; assert.false is-subvalue toolset : msvc : version : 2.95.3 ; assert.false is-subvalue toolset : : version : yabba ; - + feature yabba ; subfeature yabba : version : dabba ; assert.true is-subvalue yabba : : version : dabba ; - - + subfeature toolset gcc : platform : linux cygwin : optional ; - + assert.result - : select-subfeatures gcc - : - - - - ; - + : select-subfeatures gcc + : + + + ; + subfeature stdlib : version : 3 4 : optional ; assert.result - : select-subfeatures native - : - - - - ; - + : select-subfeatures native + : + + + ; + assert.result gcc 3.0.1 - : expand-subfeatures gcc-3.0.1 ; - + : expand-subfeatures gcc-3.0.1 ; + assert.result gcc 3.0.1 linux - : expand-subfeatures gcc-3.0.1-linux ; + : expand-subfeatures gcc-3.0.1-linux ; - assert.result gcc 3.0.1 - : expand gcc 3.0.1 ; - + : expand gcc 3.0.1 ; + assert.result foo=x-y - : expand-subfeatures foo=x-y ; + : expand-subfeatures foo=x-y ; assert.result gcc 3.0.1 - : expand-subfeatures gcc-3.0.1 ; - + : expand-subfeatures gcc-3.0.1 ; + assert.result a c e - : get-values : a b c d e ; + : get-values : a b c d e ; assert.result gcc 3.0.1 - debug _DEBUG on - : expand gcc-3.0.1 debug on - ; - + debug _DEBUG on + : expand gcc-3.0.1 debug on ; + assert.result debug _DEBUG on - : expand debug on - ; + : expand debug on ; - assert.result on debug _DEBUG - : expand on debug - ; + assert.result on debug _DEBUG + : expand on debug ; assert.result dynamic on - : defaults - ; - - # make sure defaults is resilient to missing grist. + : defaults ; + + # Make sure defaults is resilient to missing grist. assert.result dynamic on - : defaults runtime-link define optimization - ; - + : defaults runtime-link define optimization ; + feature dummy : dummy1 dummy2 ; subfeature dummy : subdummy : x y z : optional ; @@ -1150,68 +1155,54 @@ local rule __test__ ( ) assert.result optional : attributes ; assert.result optional : attributes fu ; - - assert.result static foobar on gcc:FOO - gcc debug native dummy1 2.95.2 - : add-defaults static foobar - on gcc:FOO - ; - - assert.result static foobar on gcc:FOO - fu1 gcc debug native dummy1 q - 2.95.2 - - : add-defaults static foobar - on gcc:FOO fu1 - ; - + assert.result static foobar on + gcc:FOO gcc debug native + dummy1 2.95.2 + : add-defaults static foobar on + gcc:FOO ; + + assert.result static foobar on + gcc:FOO fu1 gcc debug + native dummy1 q 2.95.2 + : add-defaults static foobar on + gcc:FOO fu1 ; + set-default : static ; - assert.result static - : defaults - ; - + assert.result static : defaults ; + assert.result gcc-3.0.1 debug on - : minimize [ expand gcc-3.0.1 debug on native ] - ; + : minimize [ expand gcc-3.0.1 debug on native ] ; assert.result gcc-3.0.1 debug dynamic - : minimize [ expand gcc-3.0.1 debug off dynamic ] - ; + : minimize + [ expand gcc-3.0.1 debug off dynamic ] ; assert.result gcc-3.0.1 debug - : minimize [ expand gcc-3.0.1 debug off ] - ; + : minimize [ expand gcc-3.0.1 debug off ] ; assert.result debug on - : minimize [ expand debug on ] - ; + : minimize [ expand debug on ] ; assert.result gcc-3.0 - : minimize gcc 3.0 - ; + : minimize gcc 3.0 ; assert.result gcc-3.0 - : minimize 3.0 gcc - ; + : minimize 3.0 gcc ; assert.result y/z b/c e/f - : split y/z/b/c/e/f - ; + : split y/z/b/c/e/f ; assert.result y/z b/c e/f - : split y\\z\\b\\c\\e\\f - ; + : split y\\z\\b\\c\\e\\f ; assert.result a b c e/f/g i/j/k - : split a/b/c/e/f/g/i/j/k - ; + : split a/b/c/e/f/g/i/j/k ; assert.result a b c e/f/g i/j/k - : split a\\b\\c\\e\\f\\g\\i\\j\\k - ; + : split a\\b\\c\\e\\f\\g\\i\\j\\k ; - # test error checking + # Test error checking. try ; { @@ -1269,16 +1260,14 @@ local rule __test__ ( ) { implied-subfeature 3.0.1 ; } - catch \"3.0.1\" is not a known subfeature value of - ; + catch \"3.0.1\" is not a known subfeature value of ; try ; { implied-subfeature not-a-version : gcc ; } - catch \"not-a-version\" is not a known subfeature value of - gcc ; + catch \"not-a-version\" is not a known subfeature value of gcc ; - # leave a clean copy of the features module behind + # Leave a clean copy of the features module behind. finish-test feature-test-temp ; } diff --git a/src/build/generators.jam b/src/build/generators.jam index 14d96cc1a..bbf8d9831 100644 --- a/src/build/generators.jam +++ b/src/build/generators.jam @@ -10,55 +10,60 @@ # sources to targets. # # The main entry point to this module is generators.construct rule. It is given -# a list of source targets, desired target type and a set of properties. -# It starts by selecting 'viable generators', which have any chances of -# producing the desired target type with the required properties. Generators -# are ranked and a set of most specific ones is selected. +# a list of source targets, desired target type and a set of properties. It +# starts by selecting 'viable generators', which have any chances of producing +# the desired target type with the required properties. Generators are ranked +# and a set of the most specific ones is selected. # # The most specific generators have their 'run' methods called, with the -# properties and list of sources. Each one selects target which can be directly -# consumed, and tries to convert the remaining ones to the types it can -# consume. This is done by recursively calling 'construct' with all consumable -# types. +# properties and list of sources. Each one selects a target which can be +# directly consumed, and tries to convert the remaining ones to the types it +# can consume. This is done by recursively calling 'construct' with all +# consumable types. # # If the generator has collected all the targets it needs, it creates targets # corresponding to result, and returns it. When all generators have been run, -# results of one of them are selected and returned as result. +# results of one of them are selected and returned as a result. # -# It's quite possible that 'construct' returns more targets that it was asked for. -# For example, it was asked to target type EXE, but the only found generators produces -# both EXE and TDS (file with debug) information. The extra target will be returned. +# It's quite possible that 'construct' returns more targets that it was asked +# for. For example, it was asked to target type EXE, but the only found +# generators produces both EXE and TDS (file with debug) information. The extra +# target will be returned. # -# Likewise, when generator tries to convert sources to consumable types, it can get -# more targets that it was asked for. The question is what to do with extra targets. -# Boost.Build attempts to convert them to requested types, and attempts as early as -# possible. Specifically, this is done after invoking each generator. (Later I'll -# document the rationale for trying extra target conversion at that point). +# Likewise, when generator tries to convert sources to consumable types, it can +# get more targets that it was asked for. The question is what to do with extra +# targets. Boost.Build attempts to convert them to requested types, and +# attempts that as early as possible. Specifically, this is done after invoking +# each generator. (Later I'll document the rationale for trying extra target +# conversion at that point). # -# That early conversion is not always desirable. Suppose a generator got a source of -# type Y and must consume one target of type X_1 and one target of type X_2. -# When converting Y to X_1 extra target of type Y_2 is created. We should not try to -# convert it to type X_1, because if we do so, the generator will get two targets -# of type X_1, and will be at loss as to which one to use. Because of that, the -# 'construct' rule has a parameter, telling if multiple targets can be returned. If -# the parameter is false, conversion of extra targets is not performed. +# That early conversion is not always desirable. Suppose a generator got a +# source of type Y and must consume one target of type X_1 and one target of +# type X_2. When converting Y to X_1 extra target of type Y_2 is created. We +# should not try to convert it to type X_1, because if we do so, the generator +# will get two targets of type X_1, and will be at loss as to which one to use. +# Because of that, the 'construct' rule has a parameter, telling if multiple +# targets can be returned. If the parameter is false, conversion of extra +# targets is not performed. import "class" : new ; -import container ; -import utility : str equal ; -import set sequence ; -import assert ; -import virtual-target ; +import errors ; import property-set ; +import sequence ; +import set ; +import utility ; +import virtual-target ; + if "--debug-generators" in [ modules.peek : ARGV ] { .debug = true ; } -# Outputs a debug message if generators debugging is on. -# Each element of 'message' is checked to see if it's class instance. -# If so, instead of the value, the result of 'str' call is output. + +# Outputs a debug message if generators debugging is on. Each element of +# 'message' is checked to see if it's class instance. If so, instead of the +# value, the result of 'str' call is output. local rule generators.dout ( message * ) { if $(.debug) @@ -73,16 +78,19 @@ local rule indent ( ) return $(.indent:J="") ; } + local rule increase-indent ( ) { .indent += " " ; } + local rule decrease-indent ( ) { .indent = $(.indent[2-]) ; } + # Takes a vector of 'virtual-target' instances and makes a normalized # representation, which is the same for given set of targets, # regardless of their order. @@ -92,17 +100,15 @@ rule normalize-target-list ( targets ) $(targets).set $(v[1]) [ sequence.insertion-sort $(v[2-]) : utility.less ] ; } + # Creates a generator class generator { - import generators ; - import assert ; import generators : indent increase-indent decrease-indent generators.dout ; - import generators ; import set ; - import utility : equal ; + import utility ; import feature ; - import errors : error ; + import errors ; import sequence ; import type ; import virtual-target ; @@ -312,14 +318,12 @@ class generator if $(self.composing) { convert-multiple-sources-to-consumable-types $(project) - : $(property-set) : $(sources) : consumed bypassed ; + : $(property-set) : $(sources) : consumed bypassed ; } else { - convert-to-consumable-types $(project) $(name) : - $(property-set) : $(sources) - : - : consumed bypassed ; + convert-to-consumable-types $(project) $(name) : $(property-set) + : $(sources) : : consumed bypassed ; } local result ; @@ -329,10 +333,9 @@ class generator : $(property-set) ] ; } - if $(result) { - generators.dout [ indent ] " SUCCESS: " $(result) ; + generators.dout [ indent ] " SUCCESS: " $(result) ; } else { @@ -342,8 +345,7 @@ class generator return $(result) ; } - # Constructs the dependency graph that will be returned by this - # generator + # Constructs the dependency graph to be returned by this generator. rule construct-result ( consumed + # Already prepared list of consumable targets # If generator requires several source files will contain @@ -351,7 +353,7 @@ class generator # Otherwise, might contain several targets with the type of # $(self.source-types[1]) : project name ? - : property-set # Properties to be used for all actions create here + : property-set # Properties to be used for all actions create here. ) { local result ; @@ -374,8 +376,7 @@ class generator return $(result) ; } - # Determine the name of the produced target from the - # names of the sources. + # Determine the name of the produced target from the names of the sources. rule determine-output-name ( sources + ) { # The simple case if when a name @@ -394,7 +395,7 @@ class generator local n2 = [ utility.basename [ $(s).name ] ] ; if $(n2) != $(name) { - error "$(self.id): source targets have different names: cannot determine target name" ; + errors.error "$(self.id): source targets have different names: cannot determine target name" ; } } @@ -404,22 +405,22 @@ class generator return $(name) ; } - # Constructs targets that are created after consuming 'sources'. - # The result will be the list of virtual-target, which the same length - # as 'target-types' attribute and with corresponding types. + # Constructs targets that are created after consuming 'sources'. The result + # will be the list of virtual-target, which has the same length as the + # 'target-types' attribute and with corresponding types. # - # When 'name' is empty, all source targets must have the same value of - # the 'name' attribute, which will be used instead of the 'name' argument. + # When 'name' is empty, all source targets must have the same value of the + # 'name' attribute, which will be used instead of the 'name' argument. # # The value of 'name' attribute for each generated target will be equal to # the 'name' parameter if there's no name pattern for this type. Otherwise, - # the '%' symbol in the name pattern will be replaced with the 'name' parameter - # to obtain the 'name' attribute. + # the '%' symbol in the name pattern will be replaced with the 'name' + # parameter to obtain the 'name' attribute. # - # For example, if targets types are T1 and T2(with name pattern "%_x"), suffixes - # for T1 and T2 are .t1 and t2, and source if foo.z, then created files would - # be "foo.t1" and "foo_x.t2". The 'name' attribute actually determined the - # basename of a file. + # For example, if targets types are T1 and T2(with name pattern "%_x"), + # suffixes for T1 and T2 are .t1 and t2, and source if foo.z, then created + # files would be "foo.t1" and "foo_x.t2". The 'name' attribute actually + # determines the basename of a file. # # Note that this pattern mechanism has nothing to do with implicit patterns # in make. It's a way to produce target which name is different for name of @@ -458,12 +459,11 @@ class generator # used when generator is run. rule convert-to-consumable-types ( project name ? : property-set : sources + - : only-one ? # convert 'source' to only one of source types - # if there's more that one possibility, report an - # error - : consumed-var # name of variable which recieves all targets which + : only-one ? # Convert 'source' to only one of the source types. If + # there's more that one possibility, report an error. + : consumed-var # Name of the variable which recieves all targets which # can be consumed. - bypassed-var # name variable which recieves all targets which + bypassed-var # Name of the variable which recieves all targets which # cannot be consumed ) { @@ -600,11 +600,11 @@ class generator } } -import errors : error ; .generators = ; -# Registers new generator instance 'g'. + +# Registers a new generator instance 'g'. rule register ( g ) { .generators += $(g) ; @@ -642,64 +642,61 @@ rule register ( g ) .generators-for-toolset.$(base) += $(g) ; } -# Creates new instance of the 'generator' class and registers it. -# Retursn the creates instance. -# Rationale: the instance is returned so that it's possible to first register -# a generator and then call 'run' method on that generator, bypassing all -# generator selection. + +# Creates new instance of the 'generator' class and registers it. Returns the +# created instance. Rationale: the instance is returned so that it's possible to +# first register a generator and then call the 'run' method on that generator, +# bypassing all generator selection. rule register-standard ( id : source-types * : target-types + : requirements * ) { local g = [ new generator $(id) : $(source-types) : $(target-types) - : $(requirements) ] ; + : $(requirements) ] ; register $(g) ; return $(g) ; } -# Creates new instance of the 'composing-generator' class and -# registers it. + +# Creates new instance of the 'composing-generator' class and registers it. rule register-composing ( id : source-types * : target-types + : requirements * ) { - local g = [ new generator $(id) true : $(source-types) - : $(target-types) : $(requirements) ] ; + local g = [ new generator $(id) true : $(source-types) : $(target-types) + : $(requirements) ] ; register $(g) ; return $(g) ; } -# Returns all generators which belong to 'toolset', i.e. which -# ids are $(toolset). + +# Returns all generators which belong to 'toolset', i.e. whose ids are +# '$(toolset).'. rule generators-for-toolset ( toolset ) { return $(.generators-for-toolset.$(toolset)) ; } -# Make generator 'overrider-id' be preferred to -# 'overridee-id'. If, when searching for generators -# that could produce a target of certain type, -# both those generators are amoung viable generators, -# the overridden generator is immediately discarded. + +# Make generator 'overrider-id' be preferred to 'overridee-id'. If, when +# searching for generators that could produce a target of a certain type, both +# those generators are amoung viable generators, the overridden generator is +# immediately discarded. # -# The overridden generators are discarded immediately -# after computing the list of viable generators, before -# running any of them. +# The overridden generators are discarded immediately after computing the list +# of viable generators, before running any of them. rule override ( overrider-id : overridee-id ) { .override.$(overrider-id) += $(overridee-id) ; } - - -# Set if results of the current generators search are going to be cached -# This means no futher attempts to cache generators search should be -# made. +# Set if results of the current generators search are going to be cached. This +# means no futher attempts to cache generators search should be made. .caching = ; -# Returns a list of source type which can possibly be converted -# to 'target-type' by some chain of generator invocation. +# Returns a list of source type which can possibly be converted to 'target-type' +# by some chain of generator invocation. # -# More formally, takes all generators for 'target-type' and -# returns union of source types for those generators and result -# of calling itself recusrively on source types. +# More formally, takes all generators for 'target-type' and returns union of +# source types for those generators and result of calling itself recirsively on +# source types. local rule viable-source-types-real ( target-type ) { local generators ; @@ -707,7 +704,7 @@ local rule viable-source-types-real ( target-type ) local t = [ type.all-bases $(target-type) ] ; local result ; - # 't' is the list of types which are not yet processed + # 't' is the list of types which have not yet been processed. while $(t) { # Find all generators for current type. @@ -715,8 +712,6 @@ local rule viable-source-types-real ( target-type ) local generators = $(.generators.$(t[1])) ; t = $(t[2-]) ; - - while $(generators) { local g = $(generators[1]) ; @@ -752,11 +747,10 @@ local rule viable-source-types-real ( target-type ) } } - result = [ sequence.unique $(result) ] ; - - return $(result) ; + return [ sequence.unique $(result) ] ; } + # Helper rule, caches the result of 'viable-source-types-real'. rule viable-source-types ( target-type ) { @@ -777,19 +771,19 @@ rule viable-source-types ( target-type ) } } -# Returns the list of source types, which, when passed to 'run' -# method of 'generator', has some change of being eventually used -# (probably after conversion by other generators) + +# Returns the list of source types, which, when passed to 'run' method of +# 'generator', has some change of being eventually used (probably after +# conversion by other generators). rule viable-source-types-for-generator-real ( generator ) { local source-types = [ $(generator).source-types ] ; if ! $(source-types) { - # If generator does not specify any source types, - # it might be special generator like builtin.lib-generator - # which just relays to other generators. Return '*' to - # indicate that any source type is possibly OK, since we don't - # know for sure. + # If generator does not specify any source types, it might be special + # generator like builtin.lib-generator which just relays to other + # generators. Return '*' to indicate that any source type is possibly + # OK, since we don't know for sure. return * ; } else @@ -809,7 +803,8 @@ rule viable-source-types-for-generator-real ( generator ) } } -# Helper rule, caches the result of 'viable-source-types-for-genrator'. + +# Helper rule, caches the result of 'viable-source-types-for-generator'. local rule viable-source-types-for-generator ( generator ) { local key = .vstg.$(generator) ; @@ -830,16 +825,12 @@ local rule viable-source-types-for-generator ( generator ) } - -# Returns usage requirements + list of created targets -local rule try-one-generator-really ( project name ? : generator : - target-type : property-set : sources * ) +# Returns usage requirements + list of created targets. +local rule try-one-generator-really ( project name ? : generator : target-type + : property-set : sources * ) { local targets = - [ $(generator).run $(project) $(name) - : $(property-set) - : $(sources) - ] ; + [ $(generator).run $(project) $(name) : $(property-set) : $(sources) ] ; local usage-requirements ; local success ; @@ -874,11 +865,11 @@ local rule try-one-generator-really ( project name ? : generator : } } -# Checks if generator invocation can be pruned, because it's guaranteed -# to fail. If so, quickly returns empty list. Otherwise, calls -# try-one-generator-really. -local rule try-one-generator ( project name ? : generator : - target-type : property-set : sources * ) + +# Checks if generator invocation can be pruned, because it's guaranteed to fail. +# If so, quickly returns empty list. Otherwise, calls try-one-generator-really. +local rule try-one-generator ( project name ? : generator : target-type + : property-set : sources * ) { local source-types ; for local s in $(sources) @@ -903,8 +894,9 @@ local rule try-one-generator ( project name ? : generator : } } -rule construct-types ( project name ? : target-types + : - property-set : sources + ) + +rule construct-types ( project name ? : target-types + : property-set + : sources + ) { local result ; local matched-types ; @@ -920,14 +912,12 @@ rule construct-types ( project name ? : target-types + : matched-types += $(t) ; } } - # TODO: have to introduce parameter controlling if - # several types can be matches and add appropriate - # checks + # TODO: have to introduce parameter controlling if several types can be + # matched and add appropriate checks. - # TODO: need to review the documentation for - # 'construct' to see if it should return $(source) even - # if nothing can be done with it. Currents docs seem to - # imply that, contrary to the behaviour. + # TODO: need to review the documentation for 'construct' to see if it should + # return $(source) even if nothing can be done with it. Currents docs seem + # to imply that, contrary to the behaviour. if $(result) { return $(usage-requirements) $(result) ; @@ -938,8 +928,8 @@ rule construct-types ( project name ? : target-types + : } } -# Ensures all 'targets' have types. If this is not so, exists with -# error. + +# Ensures all 'targets' have types. If this is not so, exists with error. local rule ensure-type ( targets * ) { for local t in $(targets) @@ -951,16 +941,17 @@ local rule ensure-type ( targets * ) } } + # Returns generators which can be used to construct target of specified type # with specified properties. Uses the following algorithm: -# - iterates over requested target-type and all it's bases (in the order returned bt -# type.all-bases. -# - for each type find all generators that generate that type and which requirements -# are satisfied by properties. +# - iterates over requested target-type and all its bases (in the order returned +# by type.all-bases. +# - for each type find all generators that generate that type and whose +# requirements are satisfied by properties. # - if the set of generators is not empty, returns that set. # # Note: this algorithm explicitly ignores generators for base classes if there's -# at least one generator for requested target-type. +# at least one generator for the requested target-type. local rule find-viable-generators-aux ( target-type : property-set ) { # Select generators that can create the required target type. @@ -970,16 +961,15 @@ local rule find-viable-generators-aux ( target-type : property-set ) import type ; local t = [ type.all-bases $(target-type) ] ; - generators.dout [ indent ] find-viable-generators target-type= $(target-type) - property-set= [ $(property-set).as-path ] - ; + generators.dout [ indent ] find-viable-generators target-type= $(target-type) + property-set= [ $(property-set).as-path ] ; - # Get the lit of generators for the requested type. - # If no generator is registered, try base type, and so on. + # Get the list of generators for the requested type. If no generator is + # registered, try base type, and so on. local generators ; while $(t[1]) { - generators.dout [ indent ] "trying type" $(t[1]) ; + generators.dout [ indent ] "trying type" $(t[1]) ; if $(.generators.$(t[1])) { generators.dout [ indent ] "there are generators for this type" ; @@ -987,18 +977,19 @@ local rule find-viable-generators-aux ( target-type : property-set ) if $(t[1]) != $(target-type) { - # We're here, when no generators for target-type are found, - # but there are some generators for a base type. - # We'll try to use them, but they will produce targets of - # base type, not of 'target-type'. So, we clone the generators - # and modify the list of target types. + # We're here, when no generators for target-type are found, but + # there are some generators for a base type. We'll try to use + # them, but they will produce targets of base type, not of + # 'target-type'. So, we clone the generators and modify the list + # of target types. local generators2 ; for local g in $(generators) { - # generators.register adds generator to the list of generators - # for toolsets, which is a bit strange, but should work. - # That list is only used when inheriting toolset, which - # should have being done before generators are run. + # generators.register adds a generator to the list of + # generators for toolsets, which is a bit strange, but + # should work. That list is only used when inheriting a + # toolset, which should have been done before running + # generators. generators2 += [ $(g).clone-and-change-target-type $(t[1]) : $(target-type) ] ; generators.register $(generators2[-1]) ; @@ -1010,7 +1001,6 @@ local rule find-viable-generators-aux ( target-type : property-set ) t = $(t[2-]) ; } - for local g in $(generators) { generators.dout [ indent ] "trying generator" [ $(g).id ] "(" [ $(g).source-types ] -> [ $(g).target-types ] ")" ; @@ -1026,6 +1016,7 @@ local rule find-viable-generators-aux ( target-type : property-set ) return $(viable-generators) ; } + rule find-viable-generators ( target-type : property-set ) { local key = $(target-type).$(property-set) ; @@ -1085,17 +1076,19 @@ rule find-viable-generators ( target-type : property-set ) return $(result) ; } + .construct-stack = ; -# Attempts to construct target by finding viable generators, running them -# and selecting the dependency graph + +# Attempts to construct a target by finding viable generators, running them and +# selecting the dependency graph. local rule construct-really ( project name ? : target-type : property-set : sources * ) { viable-generators = [ find-viable-generators $(target-type) : $(property-set) ] ; generators.dout [ indent ] "*** " [ sequence.length $(viable-generators) ] - " viable generators" ; + " viable generators" ; local result ; local generators-that-succeeded ; @@ -1146,17 +1139,14 @@ local rule construct-really ( } -# Attempts to create target of 'target-type' with 'properties' -# from 'sources'. The 'sources' are treated as a collection of -# *possible* ingridients -- i.e. it is not required to consume -# them all. If 'multiple' is true, the rule is allowed to return -# several targets of 'target-type'. +# Attempts to create a target of 'target-type' with 'properties' from 'sources'. +# The 'sources' are treated as a collection of *possible* ingridients -- i.e. it +# is not required to consume them all. If 'multiple' is true, the rule is +# allowed to return several targets of 'target-type'. # -# -# Returns a list of target. When this invocation is first instance of +# Returns a list of targets. When this invocation is first instance of # 'construct' in stack, returns only targets of requested 'target-type', -# otherwise, returns also unused sources and additionally generated -# targets. +# otherwise, returns also unused sources and additionally generated targets. rule construct ( project name ? : target-type : property-set * : sources * ) { if (.construct-stack) @@ -1179,7 +1169,6 @@ rule construct ( project name ? : target-type : property-set * : sources * ) generators.dout [ indent ] " properties:" [ $(property-set).raw ] ; } - local result = [ construct-really $(project) $(name) : $(target-type) : $(property-set) : $(sources) ] ; @@ -1190,11 +1179,12 @@ rule construct ( project name ? : target-type : property-set * : sources * ) return $(result) ; } -# Given 'result', obtained from some generator or -# generators.construct, adds 'raw-properties' as usage requirements -# to it. If result already contains usage requirements -- that is -# the first element of result of an instance of the property-set class, -# the existing usage requirements and 'raw-properties' are combined. + +# Given 'result', obtained from some generator or generators.construct, adds +# 'raw-properties' as usage requirements to it. If result already contains usage +# requirements -- that is the first element of result of an instance of the +# property-set class, the existing usage requirements and 'raw-properties' are +# combined. rule add-usage-requirements ( result * : raw-properties * ) { if $(result) diff --git a/src/build/project.jam b/src/build/project.jam index bb6f95250..d0f6fd31b 100644 --- a/src/build/project.jam +++ b/src/build/project.jam @@ -1,12 +1,12 @@ -# 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) +# 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. +# 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) @@ -21,7 +21,7 @@ # 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' 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 @@ -43,25 +43,25 @@ import print ; import property-set ; import sequence ; -# -# 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. + +# 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) ] ; + } + + 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 @@ -69,11 +69,11 @@ rule load ( jamfile-location ) # # While "build-project" and "use-project" can potentially refer to child # projects from parent projects, we don't immediately loading child - # projects when seing those attributes. Instead, we record the minimal + # projects when seeing those attributes. Instead, we record the minimal # information that will be used only later. load-used-projects $(module-name) ; - } - return $(module-name) ; + } + return $(module-name) ; } rule load-used-projects ( module-name ) @@ -85,39 +85,41 @@ rule load-used-projects ( module-name ) { local id = $(used[1]) ; local where = $(used[2]) ; - - project.use $(id) : [ path.root + + 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'd get duplicate -# matches on windows and would have to eliminate duplicates. +# 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. 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) : + local found = [ path.glob-in-parents $(location) : $(JAMROOT) $(JAMFILE) ] ; - + if ! $(found) { ECHO "error: Could not find parent for project at '$(location)'" ; ECHO "error: Did not find Jamfile or project-root.jam in any parent directory." ; EXIT ; } - - return [ load $(found[1]:D) ] ; + + return [ load $(found[1]:D) ] ; } -# 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. + +# 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) @@ -125,83 +127,83 @@ rule act-as-jamfile ( module : location ) 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 load Jamfile in future + .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) ; } -# 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. +# 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) ; - } - + { + project-module = $($(name).jamfile-module) ; + } + if ! $(project-module) - { - local location = [ path.root + { + 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 Jamfile. If not we might have project - # root, willing to act as Jamfile. In that case, project-root + + # 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 ! $(project-module) in $(.jamfile-modules) { if [ path.glob $(location) : $(JAMROOT) $(JAMFILE) ] { - project-module = [ load $(location) ] ; - } + project-module = [ load $(location) ] ; + } else { project-module = ; } - } + } } - + return $(project-module) ; } -# -# Returns the name of module corresponding to 'jamfile-location'. -# If no module corresponds to location yet, associates default -# module name with that location. + +# 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 umbiguious. - # Without this, we can't decide if '../../exe/program1' and '.' - # are the same paths, or not. + # 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)> ; + .module.$(jamfile-location) = Jamfile<$(jamfile-location)> ; } return $(.module.$(jamfile-location)) ; } -# Default patterns to search for the Jamfiles to use for build -# declarations. + +# 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. + +# 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. @@ -215,27 +217,26 @@ rule find-jamfile ( if $(parent-root) { if ! $(.parent-jamfile.$(dir)) - { - .parent-jamfile.$(dir) = - [ path.glob-in-parents $(dir) : $(JAMFILE) ] ; - } - jamfile-glob = $(.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.$(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's Jamfile.v2 amount - # found files, suppress the warning and use it. + # 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 among found files, suppress the warning and use it. # if $(jamfile-to-load[2-]) { @@ -244,24 +245,24 @@ rule find-jamfile ( if $(v2-jamfiles) && ! $(v2-jamfiles[2]) { jamfile-to-load = $(v2-jamfiles) ; - } - else - { - ECHO - "warning: Found multiple Jamfiles at '"$(dir)"'!" - "Loading the first one: '" [ path.basename $(jamfile-to-load[1]) ] "'." ; } - + 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)'". : + "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'." ; } @@ -269,10 +270,11 @@ rule find-jamfile ( 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 underfined. +# 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. ) @@ -287,68 +289,68 @@ local rule load-jamfile ( # The module of the jamfile. # - local jamfile-module = [ module-name [ path.parent $(jamfile-to-load) ] ] ; + local jamfile-module = [ module-name [ path.parent $(jamfile-to-load) ] ] ; # Initialize the jamfile module before loading. - # - initialize $(jamfile-module) : [ path.parent $(jamfile-to-load) ] + # + 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 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. + # 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) ; + { + .jamfile-modules += $(jamfile-module) ; mark-as-user $(jamfile-module) ; - modules.load $(jamfile-module) : [ path.native $(jamfile-to-load) ] : . ; + 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 + # 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) + : "after loading" $(jamfile-module) + : "expected value" $(saved-project) + : "actual value" $(.current-project) ; } if $(.global-build-dir) - { - local id = [ attribute $(jamfile-module) id ] ; + { + local id = [ attribute $(jamfile-module) id ] ; local project-root = [ attribute $(jamfile-module) project-root ] ; - local location = [ attribute $(jamfile-module) location ] ; + local location = [ attribute $(jamfile-module) location ] ; if $(location) && $(project-root) = $(dir) { - # This is Jamroot + # 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" ; - } - } - } + } + } + } } + rule mark-as-user ( module-name ) { if USER_MODULE in [ RULENAMES ] - { + { USER_MODULE $(module-name) ; } } @@ -357,30 +359,31 @@ rule mark-as-user ( module-name ) rule load-aux ( module-name : file ) { mark-as-user $(module-name) ; - + module $(module-name) { include $(2) ; local rules = [ RULENAMES $(1) ] ; IMPORT $(1) : $(rules) : $(1) : $(1).$(rules) ; - } + } } + .global-build-dir = [ MATCH --build-dir=(.*) : [ modules.peek : ARGV ] ] ; if $(.global-build-dir) -{ - # If the option is specified several times, take the last value. +{ + # If the option is specified several times, take the last value. .global-build-dir = [ path.make $(.global-build-dir[-1]) ] ; } -# Initialize the module for a project. +# Initialize the module for a project. # rule initialize ( - module-name # The name of the project module. - : location ? # The location (directory) of the project to initialize. - # If not specified, stanalone project will be initialized. - : basename ? + module-name # The name of the project module. + : location ? # The location (directory) of the project to initialize. + # If not specified, a standalone project will be initialized. + : basename ? ) { if --debug-loading in [ modules.peek : ARGV ] @@ -392,73 +395,72 @@ rule initialize ( # prebuilt targets. If so, we need to give more sensible "location", so that # source paths are correct. location ?= "" ; - # Create the module for the Jamfile first. + # Create the module for the Jamfile first. module $(module-name) - { - } - $(module-name).attributes = [ new project-attributes $(location) - $(module-name) ] ; + { + } + $(module-name).attributes = [ new project-attributes $(location) + $(module-name) ] ; local attributes = $($(module-name).attributes) ; - + if $(location) - { - $(attributes).set source-location : [ path.make $(location) ] : exact ; + { + $(attributes).set source-location : [ path.make $(location) ] : exact ; } else { - $(attributes).set source-location : "" : exact ; + $(attributes).set source-location : "" : exact ; } - - $(attributes).set requirements : [ property-set.empty ] : exact ; - $(attributes).set usage-requirements : [ property-set.empty ] : exact ; + + $(attributes).set requirements : [ property-set.empty ] : exact ; + $(attributes).set usage-requirements : [ property-set.empty ] : exact ; # Import rules common to all project modules from project-rules module, # defined at the end of this file. modules.clone-rules project-rules $(module-name) ; - + local jamroot ; local parent-module ; if $(module-name) = site-config { # No parent. - } + } else if $(module-name) = user-config { parent-module = site-config ; } - else + else { - # We search for parent/project-root only if jamfile was specified - # --- i.e + # We search for parent/project-root only if jamfile was specified, i.e. # if the project is not standalone. - if $(location) && ! [ MATCH ($(JAMROOT)) : $(basename) ] + if $(location) && ! [ MATCH ($(JAMROOT)) : $(basename) ] { parent-module = [ load-parent $(location) ] ; - } + } else { - # It's either jamroot, or standalone project. - # If it's jamroot, inherit from user-config. + # It's either jamroot, or standalone project. If it's jamroot, + # inherit from user-config. if $(location) { - parent-module = user-config ; + parent-module = user-config ; jamroot = true ; - } - } + } + } } - + if $(parent-module) - { + { inherit-attributes $(module-name) : $(parent-module) ; $(attributes).set parent-module : $(parent-module) : exact ; } - + if $(jamroot) - { + { $(attributes).set project-root : $(location) : exact ; } - + local parent ; if $(parent-module) { @@ -467,70 +469,72 @@ rule initialize ( if ! $(.target.$(module-name)) { - .target.$(module-name) = [ new project-target $(module-name) - : $(module-name) $(parent) + .target.$(module-name) = [ new project-target $(module-name) + : $(module-name) $(parent) : [ attribute $(module-name) requirements ] ] ; - + if --debug-loading in [ modules.peek : ARGV ] { - ECHO "Assigned project target" $(.target.$(module-name)) - "to '$(module-name)'" ; + ECHO "Assigned project target" $(.target.$(module-name)) + "to '$(module-name)'" ; } - } - + } + .current-project = [ target $(module-name) ] ; } + # Make 'project-module' inherit attributes of project root and parent module. rule inherit-attributes ( project-module : parent-module ) { - local attributes = $($(project-module).attributes) ; + local attributes = $($(project-module).attributes) ; local pattributes = [ attributes $(parent-module) ] ; # Parent module might be locationless user-config. if [ modules.binding $(parent-module) ] - { - $(attributes).set parent : [ path.parent + { + $(attributes).set parent : [ path.parent [ path.make [ modules.binding $(parent-module) ] ] ] ; - } + } local v = [ $(pattributes).get project-root ] ; $(attributes).set project-root : $(v) : exact ; - $(attributes).set default-build - : [ $(pattributes).get default-build ] ; + $(attributes).set default-build + : [ $(pattributes).get default-build ] ; $(attributes).set requirements - : [ $(pattributes).get requirements ] : exact ; + : [ $(pattributes).get requirements ] : exact ; $(attributes).set usage-requirements - : [ $(pattributes).get usage-requirements ] : exact ; - + : [ $(pattributes).get usage-requirements ] : exact ; + local 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 "." - + { + # Have to compute relative path from parent dir to our dir. Convert both + # paths to absolute, since we cannot find relative path from ".." to + # ".". + local location = [ attribute $(project-module) location ] ; local parent-location = [ attribute $(parent-module) location ] ; - + local pwd = [ path.pwd ] ; local parent-dir = [ path.root $(parent-location) $(pwd) ] ; local our-dir = [ path.root $(location) $(pwd) ] ; - $(attributes).set build-dir : [ path.join $(parent-build-dir) - [ path.relative $(our-dir) $(parent-dir) ] ] : exact ; - } + $(attributes).set build-dir : [ path.join $(parent-build-dir) + [ path.relative $(our-dir) $(parent-dir) ] ] : exact ; + } } -# Associate the given id with the given project module +# Associate the given id with the given project module. rule register-id ( id : module ) { $(id).jamfile-module = $(module) ; } + # 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". -class project-attributes +class project-attributes { import property ; import property-set ; @@ -539,28 +543,28 @@ class project-attributes import print ; import sequence ; import project ; - + rule __init__ ( location project-module ) - { + { self.location = $(location) ; self.project-module = $(project-module) ; } - - # Set the named attribute from the specification given by the user. - # The value actually set may be different. - rule set ( attribute : specification * - : exact ? # Sets value from 'specification' without any processing - ) + + # Set the named attribute from the specification given by the user. The + # value actually set may be different. + rule set ( attribute : specification * + : exact ? # Sets value from 'specification' without any processing. + ) { if $(exact) { self.$(attribute) = $(specification) ; } - else if $(attribute) = "requirements" + else if $(attribute) = "requirements" { local result = [ property-set.refine-from-user-input $(self.requirements) : $(specification) - : $(self.project-module) : $(self.location) ] ; + : $(self.project-module) : $(self.location) ] ; if $(result[1]) = "@error" { @@ -583,28 +587,28 @@ class project-attributes split ?= nothing $(p) ; unconditional += $(split[2]) ; } - + local non-free = [ property.remove free : $(unconditional) ] ; if $(non-free) { errors.error "usage-requirements" $(specification) "have non-free properties" $(non-free) ; - } + } local t = [ property.translate-paths $(specification) : $(self.location) ] ; if $(self.usage-requirements) { - self.usage-requirements = [ property-set.create + self.usage-requirements = [ property-set.create [ $(self.usage-requirements).raw ] $(t) ] ; } - else + else { self.usage-requirements = [ property-set.create $(t) ] ; - } - } + } + } else if $(attribute) = "default-build" { self.default-build = [ property.make $(specification) ] ; - } + } else if $(attribute) = "source-location" { self.source-location = ; @@ -613,17 +617,17 @@ class project-attributes self.source-location += [ path.root [ path.make $(src-path) ] $(self.location) ] ; } - } + } else if $(attribute) = "build-dir" { - self.build-dir = [ path.root + self.build-dir = [ path.root [ path.make $(specification) ] $(self.location) ] ; - } - else if ! $(attribute) in "id" "default-build" "location" "source-location" - "parent" "projects-to-build" "project-root" + } + else if ! $(attribute) in "id" "default-build" "location" + "source-location" "parent" "projects-to-build" "project-root" { - errors.error "Invalid project attribute '$(attribute)' specified " - "for project at '$(self.location)'" ; + errors.error "Invalid project attribute '$(attribute)' specified" + "for project at '$(self.location)'" ; } else { @@ -648,27 +652,29 @@ class project-attributes print.list-item "Requirements:" [ $(self.requirements).raw ] ; print.list-item "Default build:" $(self.default-build) ; print.list-item "Source location:" $(self.source-location) ; - print.list-item "Projects to build:" - [ sequence.insertion-sort $(self.projects-to-build) ] ; + print.list-item "Projects to build:" + [ sequence.insertion-sort $(self.projects-to-build) ] ; print.list-end ; } - } -# Returns the project which is currently being loaded + +# Returns the project which is currently being loaded. rule current ( ) { return $(.current-project) ; } -# Temporary changes the current project to 'project'. Should -# be followed by 'pop-current'. + +# Temporarily changes the current project to 'project'. Should be followed by +# 'pop-current'. rule push-current ( project ) { .saved-current-project += $(.current-project) ; .current-project = $(project) ; } + rule pop-current ( ) { .current-project = $(.saved-current-project[-1]) ; @@ -676,68 +682,71 @@ rule pop-current ( ) } - # Returns the project-attribute instance for the specified jamfile module. rule attributes ( project ) { return $($(project).attributes) ; } + # Returns the value of the specified attribute in the specified jamfile module. rule attribute ( project attribute ) { - return [ $($(project).attributes).get $(attribute) ] ; + return [ $($(project).attributes).get $(attribute) ] ; } + # Returns the project target corresponding to the 'project-module'. rule target ( project-module ) { if ! $(.target.$(project-module)) { - .target.$(project-module) = [ new project-target $(project-module) - : $(project-module) - : [ attribute $(project-module) requirements ] ] ; + .target.$(project-module) = [ new project-target $(project-module) + : $(project-module) + : [ attribute $(project-module) requirements ] ] ; } - return $(.target.$(project-module)) ; + return $(.target.$(project-module)) ; } + # Use/load a project. rule use ( id : location ) { local saved-project = $(.current-project) ; local project-module = [ project.load $(location) ] ; local declared-id = [ project.attribute $(project-module) id ] ; - + if ! $(declared-id) || $(declared-id) != $(id) { # The project at 'location' either have no id or # that id is not equal to the 'id' parameter. - if $($(id).jamfile-module) - && $($(id).jamfile-module) != $(project-module) + if $($(id).jamfile-module) + && $($(id).jamfile-module) != $(project-module) { - errors.user-error - "Attempt to redeclare already existing project id '$(id)'" ; - } + errors.user-error + "Attempt to redeclare already existing project id '$(id)'" ; + } $(id).jamfile-module = $(project-module) ; } .current-project = $(saved-project) ; } -# 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. + +# 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 initialized 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 ] ; @@ -747,163 +756,162 @@ rule extension ( id : options * : * ) { root-project = [ project.attribute $(root-project) parent-module ] ; } - - # Create the project data, and bring in the project rules - # into the 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. + + # 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 ; } } + rule glob-internal ( project : wildcards + : excludes * : rule-name ) { local location = [ $(project).get source-location ] ; - + local result ; - local paths = [ path.$(rule-name) $(location) - : [ sequence.transform path.make : $(wildcards) ] + local paths = [ path.$(rule-name) $(location) + : [ sequence.transform path.make : $(wildcards) ] : [ sequence.transform path.make : $(excludes) ] ] ; if $(wildcards:D) || $(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. + # The paths we've found are relative to the current directory, but the + # names specified in the sources list are assumed to be relative to the + # source directory of the corresponding project. So, just make the names + # absolute. for local p in $(paths) { result += [ path.root $(p) [ path.pwd ] ] ; - } + } } - else + 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. + # There were no wildcards in the directory path, so the files are all in + # the source directory of the project. Just drop the directory, instead + # of making paths absolute. result = $(paths:D="") ; } - - return $(result) ; + + return $(result) ; } -# This module defines rules common to all projects +# This module defines rules common to all projects. module project-rules -{ +{ rule using ( toolset-module : * ) { import toolset ; import modules ; import project ; - - # 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. + + # Temporarily change the search path so the module referred to by + # 'using' can be placed in the same directory as Jamfile. User will + # expect the module to be found even though the directory is not in + # BOOST_BUILD_PATH. local x = [ modules.peek : BOOST_BUILD_PATH ] ; local caller = [ modules.binding $(__name__) ] ; modules.poke : BOOST_BUILD_PATH : $(caller:D) $(x) ; toolset.using $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; modules.poke : BOOST_BUILD_PATH : $(x) ; - - # The above might have clobbered .current-project - # Restore the the right value. - modules.poke project : .current-project - : [ project.target $(__name__) ] ; + + # The above might have clobbered .current-project. Restore the correct + # value. + modules.poke project : .current-project + : [ project.target $(__name__) ] ; } - + import modules ; - + rule import ( * : * : * ) { modules.import project ; - + local caller = [ CALLER_MODULE ] ; local saved = [ modules.peek project : .current-project ] ; module $(caller) { modules.import $(1) : $(2) : $(3) ; } - modules.poke project : .current-project : $(saved) ; + modules.poke project : .current-project : $(saved) ; } - rule project ( id ? : options * : * ) { - import project ; - import path ; import errors ; - + import path ; + import project ; + local attributes = [ project.attributes $(__name__) ] ; - if $(id) + if $(id) { id = [ path.root $(id) / ] ; project.register-id $(id) : $(__name__) ; $(attributes).set id : $(id) ; } - + local explicit-build-dir ; - + for n in 2 3 4 5 6 7 8 9 { local option = $($(n)) ; - if $(option) + if $(option) { $(attributes).set $(option[1]) : $(option[2-]) ; } if $(option[1]) = "build-dir" { explicit-build-dir = [ path.make $(option[2-]) ] ; - } + } } - + # If '--build-dir' is specified, change the build dir for the project. - local global-build-dir = - [ modules.peek project : .global-build-dir ] ; - + local global-build-dir = + [ modules.peek project : .global-build-dir ] ; + if $(global-build-dir) - { + { local location = [ $(attributes).get location ] ; # Project with an empty location is a 'standalone' project such as - # 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. + # 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) && $(location) = [ $(attributes).get project-root ] { # This is Jamroot. if $(id) - { - if $(explicit-build-dir) + { + if $(explicit-build-dir) && [ path.is-rooted $(explicit-build-dir) ] { - errors.user-error "Absolute directory specified via 'build-dir' project attribute" - : "Don't know how to combine that with the --build-dir option." - ; + errors.user-error "Absolute directory specified via 'build-dir' project attribute" + : "Don't know how to combine that with the --build-dir option." + ; } # Strip the leading slash from id. - local rid = [ MATCH /(.*) : $(id) ] ; - local p = [ path.join + local rid = [ MATCH /(.*) : $(id) ] ; + local p = [ path.join $(global-build-dir) $(rid) $(explicit-build-dir) ] ; $(attributes).set build-dir : $(p) : exact ; - } - } - else + } + } + else { # Not Jamroot if $(explicit-build-dir) { errors.user-error "When --build-dir is specified, the 'build-dir' project" - : "attribute is allowed only for top-level 'project' invocations" ; + : "attribute is allowed only for top-level 'project' invocations" ; } } } @@ -920,13 +928,12 @@ module project-rules { import project ; local p = [ project.target $(__name__) ] ; - $(p).add-constant $(name) : $(value) ; + $(p).add-constant $(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. + + # 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. rule path-constant ( name # Variable name of the constant. : value + # Value of the constant. @@ -937,7 +944,6 @@ module project-rules $(p).add-constant $(name) : $(value) : path ; } - rule use-project ( id : where ) { # See comment in 'load' for explanation. @@ -952,43 +958,42 @@ module project-rules local now = [ $(attributes).get projects-to-build ] ; $(attributes).set projects-to-build : $(now) $(dir) ; } - + rule explicit ( target-names * ) { import project ; - # If 'explicit' is used in a helper rule defined in Jamroot, - # and inherited by children, then most of the time - # we want 'explicit' to operate on the Jamfile where - # the helper rule is invoked. + # If 'explicit' is used in a helper rule defined in Jamroot and + # inherited by children, then most of the time we want 'explicit' to + # operate on the Jamfile where the helper rule is invoked. local t = [ project.current ] ; for local n in $(target-names) - { + { $(t).mark-target-as-explicit $(n) ; - } - } - + } + } + rule glob ( wildcards + : excludes * ) { import project ; - return [ project.glob-internal [ project.current ] + return [ project.glob-internal [ project.current ] : $(wildcards) : $(excludes) : glob ] ; } rule glob-tree ( wildcards + : excludes * ) { import project ; - + if $(wildcards:D) || $(excludes:D) { errors.user-error "The patterns to 'glob-tree' may not include directory" ; } - return [ project.glob-internal [ project.current ] + return [ project.glob-internal [ project.current ] : $(wildcards) : $(excludes) : glob-tree ] ; } - # 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: + # Calculates conditional requirements for multiple requirements at once. + # This is a shorthand to reduce duplication and to keep an inline + # declarative syntax. For example: # # lib x : x.cpp : [ conditional gcc debug : # DEBUG_EXCEPTION DEBUG_TRACE ] ; diff --git a/src/build/property-set.jam b/src/build/property-set.jam index 9ccf8677f..2ab25a3dd 100644 --- a/src/build/property-set.jam +++ b/src/build/property-set.jam @@ -1,7 +1,7 @@ -# Copyright 2003 Dave Abrahams -# Copyright 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) +# Copyright 2003 Dave Abrahams +# Copyright 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) import "class" : new ; import feature ; @@ -10,46 +10,45 @@ import sequence ; import set ; # Class for storing a set of properties. -# - there's 1<->1 correspondence between identity and value. No -# two instances of the class are equal. To maintain this property, -# the 'property-set.create' rule should be used to create new instances. -# Instances are immutable. -# -# - each property is classified with regard to it's effect on build -# results. Incidental properties have no effect on build results, from -# Boost.Build point of view. Others are either free, or non-free, which we -# call 'base'. Each property belong to exactly one of those categories and -# it's possible to get list of properties in each category. +# - there's 1<->1 correspondence between identity and value. No two instances of +# the class are equal. To maintain this property, the 'property-set.create' +# rule should be used to create new instances. Instances are immutable. # -# In addition, it's possible to get list of properties with specific +# - each property is classified with regard to it's effect on build results. +# Incidental properties have no effect on build results, from Boost.Build's +# point of view. Others are either free, or non-free, which we call 'base'. +# Each property belongs to exactly one of those categories and it's possible +# to get list of properties in each category. +# +# In addition, it's possible to get a list of properties with a specific # attribute. # # - several operations, like and refine and as-path are provided. They all use # caching whenever possible. # -class property-set +class property-set { - import feature ; - import property-set ; - import property ; - import set ; - import path ; import errors ; - + import feature ; + import path ; + import property ; + import property-set ; + import set ; + rule __init__ ( raw-properties * ) - { + { self.raw = $(raw-properties) ; - + for local p in $(raw-properties) { if ! $(p:G) { - errors.error "Invalid property: '$(p)'" ; + errors.error "Invalid property: '$(p)'" ; } - - local att = [ feature.attributes $(p:G) ] ; - # A feature can be both incidental and free, - # in which case we add it to incidental. + + local att = [ feature.attributes $(p:G) ] ; + # A feature can be both incidental and free, in which case we add it + # to incidental. if incidental in $(att) { self.incidental += $(p) ; @@ -58,11 +57,11 @@ class property-set { self.free += $(p) ; } - else + else { self.base += $(p) ; } - + if dependency in $(att) { self.dependency += $(p) ; @@ -71,8 +70,8 @@ class property-set { self.non-dependency += $(p) ; } - - if [ MATCH (:) : $(p:G=) ] + + if [ MATCH (:) : $(p:G=) ] { self.conditional += $(p) ; } @@ -80,80 +79,76 @@ class property-set { self.non-conditional += $(p) ; } - - + if propagated in $(att) { self.propagated += $(p) ; - } + } if link-incompatible in $(att) { self.link-incompatible += $(p) ; - } + } } - } - - - # Returns Jam list of stored properties + + # Returns Jam list of stored properties. rule raw ( ) { return $(self.raw) ; } - + rule str ( ) { return "[" $(self.raw) "]" ; } - - # Returns properties that are neither incidental nor free + + # Returns properties that are neither incidental nor free. rule base ( ) { return $(self.base) ; } - - - # Returns free properties which are not dependency properties + + # Returns free properties which are not dependency properties. rule free ( ) { return $(self.free) ; } - - # Returns dependency properties + + # Returns dependency properties. rule dependency ( ) { return $(self.dependency) ; } - + rule non-dependency ( ) { return $(self.non-dependency) ; } - + rule conditional ( ) { return $(self.conditional) ; } - + rule non-conditional ( ) { return $(self.non-conditional) ; } - - # Returns incidental properties + + # Returns incidental properties. rule incidental ( ) { return $(self.incidental) ; } - + rule refine ( ps ) { if ! $(self.refined.$(ps)) { - local r = [ property.refine $(self.raw) : [ $(ps).raw ] ] ; + local r = [ property.refine $(self.raw) : [ $(ps).raw ] ] ; if $(r[1]) != "@error" { - self.refined.$(ps) = [ property-set.create $(r) ] ; + self.refined.$(ps) = [ property-set.create $(r) ] ; } else { @@ -162,7 +157,7 @@ class property-set } return $(self.refined.$(ps)) ; } - + rule expand ( ) { if ! $(self.expanded) @@ -171,8 +166,7 @@ class property-set } return $(self.expanded) ; } - - + rule expand-composites ( ) { if ! $(self.composites) @@ -182,18 +176,18 @@ class property-set } return $(self.composites) ; } - + rule evaluate-conditionals ( context ? ) { context ?= $(__name__) ; if ! $(self.evaluated.$(context)) { - self.evaluated.$(context) = [ property-set.create + self.evaluated.$(context) = [ property-set.create [ property.evaluate-conditionals-in-context $(self.raw) : [ $(context).raw ] ] ] ; } - return $(self.evaluated.$(context)) ; + return $(self.evaluated.$(context)) ; } - + rule propagated ( ) { if ! $(self.propagated-ps) @@ -201,19 +195,18 @@ class property-set self.propagated-ps = [ property-set.create $(self.propagated) ] ; } return $(self.propagated-ps) ; - } - + } + rule link-incompatible ( ) { if ! $(self.link-incompatible-ps) { - self.link-incompatible-ps = + self.link-incompatible-ps = [ property-set.create $(self.link-incompatible) ] ; } return $(self.link-incompatible-ps) ; } - - + rule run-actions ( ) { if ! $(self.run) @@ -222,37 +215,34 @@ class property-set } return $(self.run) ; } - + rule add-defaults ( ) { if ! $(self.defaults) { - self.defaults = [ property-set.create + self.defaults = [ property-set.create [ feature.add-defaults $(self.raw) ] ] ; } return $(self.defaults) ; } - - + rule as-path ( ) { if ! $(self.as-path) { self.as-path = [ property.as-path $(self.base) ] ; - } + } return $(self.as-path) ; - } - - # Computes the target path that should be used for - # target with these properties. + } + + # Computes the path to be used for a target with the given properties. # Returns a list of # - the computed path - # - if the path is relative to build directory, a value of - # 'true'. + # - if the path is relative to the build directory, a value of 'true'. rule target-path ( ) { if ! $(self.target-path) - { + { # The feature can be used to explicitly # change the location of generated targetsv local l = [ get ] ; @@ -262,62 +252,61 @@ class property-set } else { - local p = [ as-path ] ; + local p = [ as-path ] ; # Really, an ugly hack. Boost regression test system requires # specific target paths, and it seems that changing it to handle - # other directory layout is really hard. For that reason, - # we teach V2 to do the things regression system requires. - # The value o '' is predended to the path. - local prefix = [ get ] ; + # other directory layout is really hard. For that reason, we + # teach V2 to do the things regression system requires. The + # value of '' is prepended to the path. + local prefix = [ get ] ; if $(prefix) { self.target-path = [ path.join $(prefix) $(p) ] ; - } + } else { self.target-path = $(p) ; - } + } if ! $(self.target-path) { self.target-path = . ; - } + } # The path is relative to build dir. self.target-path += true ; - } - } + } + } return $(self.target-path) ; } - - + rule add ( ps ) { - if ! $(self.added.$(ps)) + if ! $(self.added.$(ps)) { self.added.$(ps) = [ property-set.create $(self.raw) [ $(ps).raw ] ] ; } return $(self.added.$(ps)) ; - } - + } + rule add-raw ( properties * ) { return [ add [ property-set.create $(properties) ] ] ; - } - + } + rule link-incompatible-with ( ps ) { if ! $(.li.$(ps)) { local li1 = [ $(__name__).link-incompatible ] ; - local li2 = [ $(ps).link-incompatible ] ; - if [ set.equal $(li1) : $(li2) ] + local li2 = [ $(ps).link-incompatible ] ; + if [ set.equal $(li1) : $(li2) ] { .li.$(ps) = false ; } else { .li.$(ps) = true ; - } - } + } + } if $(.li.$(ps)) = true { return true ; @@ -325,85 +314,79 @@ class property-set else { return ; - } + } } - - # Returns all values of 'feature'. rule get ( feature ) { if ! $(self.map-built) { - # For each feature, create member var and assign all - # values to it. Since all regular member vars start with - # 'self', there will be no conflicts between names. + # For each feature, create a member var and assign all values to it. + # Since all regular member vars start with 'self', there will be no + # conflicts between names. self.map-built = true ; for local v in $(self.raw) { $(v:G) += $(v:G=) ; - } + } } - return $($(feature)) ; } - } -# Creates new 'property-set' instance for the given raw properties, -# or returns an already existing ones. + +# Creates a new 'property-set' instance for the given raw properties or returns +# an already existing ones. rule create ( raw-properties * ) { - raw-properties = [ sequence.unique + raw-properties = [ sequence.unique [ sequence.insertion-sort $(raw-properties) ] ] ; - + local key = $(raw-properties:J=-:E=) ; - - if ! $(.ps.$(key)) + + if ! $(.ps.$(key)) { .ps.$(key) = [ new property-set $(raw-properties) ] ; } - return $(.ps.$(key)) ; + return $(.ps.$(key)) ; } NATIVE_RULE property-set : create ; -# Creates new 'property-set' instances after checking -# that all properties are valid and converting incidental -# properties into gristed form. + +# Creates a new 'property-set' instance after checking that all properties are +# valid and converting incidental properties into gristed form. rule create-with-validation ( raw-properties * ) { property.validate $(raw-properties) ; - return [ create [ property.make $(raw-properties) ] ] ; } -# Creates a property-set from the input given by the user, in the -# context of 'jamfile-module' at 'location' + +# Creates a property-set from the input given by the user, in the context of +# 'jamfile-module' at 'location'. rule create-from-user-input ( raw-properties * : jamfile-module location ) { local specification = [ property.translate-paths $(raw-properties) - : $(location) ] ; + : $(location) ] ; specification = [ property.translate-indirect $(specification) - : $(jamfile-module) ] ; - specification = - [ property.expand-subfeatures-in-conditions $(specification) ] ; - specification = [ property.make $(specification) ] ; - result = [ property-set.create $(specification) ] ; - return $(result) ; + : $(jamfile-module) ] ; + specification = + [ property.expand-subfeatures-in-conditions $(specification) ] ; + specification = [ property.make $(specification) ] ; + return [ property-set.create $(specification) ] ; } -# Refines requirements with requirements provided by the user. -# Specially handles "-value" syntax in specification -# to remove given requirements. -# - parent-requirements -- property-set object with requirements -# to refine -# - specification -- string list of requirements provided by the use -# - project-module -- the module to which context indirect features -# will be bound. -# - location -- the path to which path features are relative. + +# Refines requirements with requirements provided by the user. Specially handles +# "-value" syntax in specification to remove given requirements. +# - parent-requirements -- property-set object with requirements to refine. +# - specification -- string list of requirements provided by the user. +# - project-module -- module to which context indirect features will be +# bound. +# - location -- path to which path features are relative. # -# -rule refine-from-user-input ( parent-requirements : specification * +rule refine-from-user-input ( parent-requirements : specification * : project-module : location ) { if ! $(specification) @@ -414,7 +397,7 @@ rule refine-from-user-input ( parent-requirements : specification * { local add-requirements ; local remove-requirements ; - + for local r in $(specification) { local m = [ MATCH "^-(.*)" : $(r) ] ; @@ -427,38 +410,35 @@ rule refine-from-user-input ( parent-requirements : specification * add-requirements += $(r) ; } } - + if $(remove-requirements) { - # Need to create property set, so that path features - # and indirect features are translated just like they - # are in project requirements. - local ps = [ property-set.create-from-user-input + # Need to create a property set, so that path features and indirect + # features are translated just like they are in project + # requirements. + local ps = [ property-set.create-from-user-input $(remove-requirements) : $(project-module) $(location) ] ; - - parent-requirements = [ property-set.create - [ set.difference [ $(parent-requirements).raw ] - : [ $(ps).raw ] ] ] ; + + parent-requirements = [ property-set.create + [ set.difference [ $(parent-requirements).raw ] + : [ $(ps).raw ] ] ] ; specification = $(add-requirements) ; } - local requirements = [ property-set.create-from-user-input + local requirements = [ property-set.create-from-user-input $(specification) : $(project-module) $(location) ] ; - - requirements = [ $(parent-requirements).refine $(requirements) ] ; - return $(requirements) ; + + return [ $(parent-requirements).refine $(requirements) ] ; } } - -# Returns property-set with empty set of properties. +# Returns a property-set with an empty set of properties. rule empty ( ) { if ! $(.empty) { - .empty = [ create ] ; + .empty = [ create ] ; } - return $(.empty) ; } diff --git a/src/build/property.jam b/src/build/property.jam index 734c55e3c..c39733b33 100644 --- a/src/build/property.jam +++ b/src/build/property.jam @@ -1,52 +1,50 @@ -# Copyright 2001, 2002, 2003 Dave Abrahams -# Copyright 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) +# Copyright 2001, 2002, 2003 Dave Abrahams +# Copyright 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) -import utility : ungrist ; -import sequence : unique ; -import errors : error ; +import errors ; import feature ; +import indirect ; +import path ; import regex ; import string ; import sequence ; import set ; -import path ; -import assert ; -import indirect ; +import utility ; -# Refines 'properties' by overriding any non-free properties -# for which a different value is specified in 'requirements'. -# Conditional requirements are just added without modification. -# Returns the resulting list of properties. + +# Refines 'properties' by overriding any non-free and non-conditional properties +# for which a different value is specified in 'requirements'. Returns the +# resulting list of properties. rule refine ( properties * : requirements * ) { local result ; local error ; - - # All the elements of requirements should be present in the result - # Record them so that we can handle 'properties'. + + # All the 'requirements' elements should be present in the result. Record + # them so that we can handle 'properties'. for local r in $(requirements) { # Don't consider conditional requirements. if ! [ MATCH (:) : $(r:G=) ] - { - # Note: cannot use local here, so take an ugly name + { + # Note: cannot use a local variable here, so use an ugly name. __require__$(r:G) = $(r:G=) ; - } + } } for local p in $(properties) - { - # No processing for free properties + { if [ MATCH (:) : $(p:G=) ] { - # Skip conditional properties + # Do not modify conditional properties. result += $(p) ; - } + } else if free in [ feature.attributes $(p:G) ] { + # Do not modify free properties. result += $(p) ; } else @@ -54,8 +52,7 @@ rule refine ( properties * : requirements * ) local required-value = $(__require__$(p:G)) ; if $(required-value) { - local value = $(p:G=) ; - if $(value) != $(required-value) + if $(p:G=) != $(required-value) { result += $(p:G)$(required-value) ; } @@ -71,23 +68,24 @@ rule refine ( properties * : requirements * ) } } - # Unset our ugly map. + # Unset our ugly map. for local r in $(requirements) { - __require__$(r:G) = ; + __require__$(r:G) = ; } - + if $(error) { return $(error) ; } else { - return [ unique $(result) $(requirements) ] ; + return [ sequence.unique $(result) $(requirements) ] ; } } -# Removes all conditional properties which conditions are not met. For those + +# Removes all conditional properties whose conditions are not met. For those # with met conditions, removes the condition. Properties in conditions are # looked up in 'context'. rule evaluate-conditionals-in-context ( properties * : context * ) @@ -103,31 +101,32 @@ rule evaluate-conditionals-in-context ( properties * : context * ) else { base += $(p) ; - } + } } local result = $(base) ; for local p in $(conditionals) { - # Separate condition and property + # Separate condition and property. local s = [ MATCH (.*):(<.*) : $(p) ] ; - # Split condition into individual properties + # Split condition into individual properties. local c = [ regex.split $(s[1]) "," ] ; - # Evaluate condition + # Evaluate condition. if $(c) in $(context) { result += $(s[2]) ; - } + } } - return $(result) ; + return $(result) ; } + rule expand-subfeatures-in-conditions ( properties * ) { local result ; for local p in $(properties) { - local s = [ MATCH (.*):(<.*) : $(p) ] ; + local s = [ MATCH (.*):(<.*) : $(p) ] ; if ! $(s) { result += $(p) ; @@ -135,20 +134,20 @@ rule expand-subfeatures-in-conditions ( properties * ) else { local condition = $(s[1]) ; - # Condition might include several elements + local value = $(s[2]) ; + # Condition might include several elements. condition = [ regex.split $(condition) "," ] ; - local value = $(s[2]) ; local e ; for local c in $(condition) - { - # It common that condition includes a toolset which - # was never defined, or mentiones subfeatures which - # were never defined. In that case, validation will - # only produce an spirious error, so prevent - # validation by passing 'true' as second parameter. + { + # It is common for a condition to include a toolset or + # subfeatures that have not been defined. In that case we want + # the condition to simply 'never be satisfied' and validation + # would only produce a spurious error so we prevent it by + # passing 'true' as the second parameter. e += [ feature.expand-subfeatures $(c) : true ] ; } - + if $(e) = $(condition) { result += $(p) ; @@ -157,17 +156,15 @@ rule expand-subfeatures-in-conditions ( properties * ) { local individual-subfeatures = [ set.difference $(e) : $(condition) ] ; result += $(individual-subfeatures:J=,):$(value) ; - } - } - } + } + } + } return $(result) ; } - -# Helper for as-path, below. Orders properties with the implicit ones -# first, and within the two sections in alphabetical order of feature -# name. +# Helper for as-path, below. Orders properties with the implicit ones first, and +# within the two sections in alphabetical order of feature name. local rule path-order ( x y ) { if $(y:G) && ! $(x:G) @@ -185,7 +182,7 @@ local rule path-order ( x y ) x = [ feature.expand-subfeatures $(x) ] ; y = [ feature.expand-subfeatures $(y) ] ; } - + if $(x[1]) < $(y[1]) { return true ; @@ -193,6 +190,7 @@ local rule path-order ( x y ) } } + local rule abbreviate-dashed ( string ) { local r ; @@ -203,11 +201,13 @@ local rule abbreviate-dashed ( string ) return $(r:J=-) ; } + local rule identity ( string ) { return $(string) ; } + if --abbreviate-paths in [ modules.peek : ARGV ] { .abbrev = abbreviate-dashed ; @@ -217,37 +217,38 @@ else .abbrev = identity ; } -# Returns a path which represents the given expanded property set. + +# Returns a path representing the given expanded property set. rule as-path ( properties * ) { local entry = .result.$(properties:J=-) ; - + if ! $($(entry)) { # trim redundancy properties = [ feature.minimize $(properties) ] ; - + # sort according to path-order properties = [ sequence.insertion-sort $(properties) : path-order ] ; - + local components ; for local p in $(properties) { if $(p:G) { - local f = [ ungrist $(p:G) ] ; + local f = [ utility.ungrist $(p:G) ] ; p = $(f)-$(p:G=) ; } - components += [ $(.abbrev) $(p) ] ; } - + $(entry) = $(components:J=/) ; - } - + } + return $($(entry)) ; } + # Exit with error if property is not valid. local rule validate1 ( property ) { @@ -259,17 +260,19 @@ local rule validate1 ( property ) if ! [ feature.valid $(feature) ] { - feature = [ ungrist $(property:G) ] ; # Ungrist for better error messages + # Ungrist for better error messages. + feature = [ utility.ungrist $(property:G) ] ; msg = "unknown feature '$(feature)'" ; } - else if $(value) && ! free in [ feature.attributes $(feature) ] + else if $(value) && ! free in [ feature.attributes $(feature) ] { feature.validate-value-string $(feature) $(value) ; - } + } else if ! ( $(value) || ( optional in [ feature.attributes $(feature) ] ) ) { - feature = [ ungrist $(property:G) ] ; # Ungrist for better error messages - msg = "No value specified for feature '$(feature)'" ; + # Ungrist for better error messages. + feature = [ utility.ungrist $(property:G) ] ; + msg = "No value specified for feature '$(feature)'" ; } } else @@ -277,12 +280,13 @@ local rule validate1 ( property ) local feature = [ feature.implied-feature $(property) ] ; feature.validate-value-string $(feature) $(property) ; } - if $(msg) + if $(msg) { - error "Invalid property "'$(property:J=" ")'": "$(msg:J=" "). ; + errors.error "Invalid property "'$(property:J=" ")'": "$(msg:J=" "). ; } } + rule validate ( properties * ) { for local p in $(properties) @@ -291,6 +295,7 @@ rule validate ( properties * ) } } + rule validate-property-sets ( property-sets * ) { for local s in $(property-sets) @@ -299,12 +304,13 @@ rule validate-property-sets ( property-sets * ) } } -# Makes a property set from 'specification', converting implicit values into -# full properties. + +# Expands any implicit property values in the given property 'specification' so +# they explicitly state their feature. rule make ( specification * ) { local result ; - for local e in $(specification) + for local e in $(specification) { if $(e:G) { @@ -313,18 +319,19 @@ rule make ( specification * ) else if [ feature.is-implicit-value $(e) ] { local feature = [ feature.implied-feature $(e) ] ; - result += $(feature)$(e) ; + result += $(feature)$(e) ; } else { - error "'$(e)' is not a valid for property specification" ; + errors.error "'$(e)' is not a valid property specification" ; } } return $(result) ; } -# Returns a property sets which include all the elements in 'properties' that -# do not have attributes listed in 'attributes'. + +# Returns a property set containing all the elements in 'properties' that do not +# have their attributes listed in 'attributes'. rule remove ( attributes + : properties * ) { local result ; @@ -338,8 +345,9 @@ rule remove ( attributes + : properties * ) return $(result) ; } -# Returns a property set which include all properties in 'properties' that have -# any of 'attributes'. + +# Returns a property set containig all the elements in 'properties' that have +# their attributes listed in 'attributes'. rule take ( attributes + : properties * ) { local result ; @@ -353,15 +361,16 @@ rule take ( attributes + : properties * ) return $(result) ; } -# Selects properties which correspond to any of the given features. + +# Selects properties corresponding to any of the given features. rule select ( features * : properties * ) { local result ; - - # add any missing angle brackets + + # Add any missing angle brackets. local empty = "" ; features = $(empty:G=$(features)) ; - + for local p in $(properties) { if $(p:G) in $(features) @@ -372,17 +381,17 @@ rule select ( features * : properties * ) return $(result) ; } -# Returns a modified version of properties with all values of the -# given feature replaced by the given value. -# If 'value' is empty the feature will be removed + +# Returns a modified version of properties with all values of the given feature +# replaced by the given value. If 'value' is empty the feature will be removed. rule change ( properties * : feature value ? ) { - local result ; + local result ; for local p in $(properties) { if $(p:G) = $(feature) { - result += $(value:G=$(feature)) ; + result += $(value:G=$(feature)) ; } else { @@ -392,61 +401,61 @@ rule change ( properties * : feature value ? ) return $(result) ; } -# If 'property' is conditional property, returns -# condition and the property, e.g -# debug,gcc:full will become -# debug,gcc full. -# Otherwise, returns empty string. + +# If 'property' is a conditional property, returns the condition and the +# property. E.g. debug,gcc:full will become +# debug,gcc full. Otherwise, returns an empty +# string. rule split-conditional ( property ) { local m = [ MATCH "(.+):<(.+)" : $(property) ] ; if $(m) { return $(m[1]) <$(m[2]) ; - } + } } -# Interpret all path properties in 'properties' as relative to 'path' -# The property values are assumed to be in system-specific form, and -# will be translated into normalized form. +# Interpret all path properties in 'properties' as relative to 'path'. The +# property values are assumed to be in system-specific form, and will be +# translated into normalized form. rule translate-paths ( properties * : path ) { local result ; for local p in $(properties) { local split = [ split-conditional $(p) ] ; - local condition = "" ; + local condition = "" ; if $(split) { condition = $(split[1]): ; p = $(split[2]) ; } - - if path in [ feature.attributes $(p:G) ] + + if path in [ feature.attributes $(p:G) ] { local values = [ regex.split $(p:TG=) "&&" ] ; local t ; for local v in $(values) { - t += [ path.root [ path.make $(v) ] $(path) ] ; + t += [ path.root [ path.make $(v) ] $(path) ] ; } - t = $(t:J="&&") ; + t = $(t:J="&&") ; result += $(condition)$(t:TG=$(p:G)) ; } else { result += $(condition)$(p) ; - } + } } return $(result) ; } -# Assumes that all feature values that start with '@' are -# names of rules, used in 'context-module'. Such rules -# can be either local to the module or global. Converts such -# values into 'indirect-rule' format (see indirect.jam), so -# that they can be called from other modules. + +# Assumes that all feature values that start with '@' are names of rules, used +# in 'context-module'. Such rules can be either local to the module or global. +# Converts such values into 'indirect-rule' format (see indirect.jam), so they +# can be called from other modules. rule translate-indirect ( specification * : context-module ) { local result ; @@ -458,23 +467,21 @@ rule translate-indirect ( specification * : context-module ) local v ; if [ MATCH "^([^%]*)%([^%]+)$" : $(m) ] { - # Rule is already in indirect format + # Rule is already in indirect format. v = $(m) ; } else { if ! [ MATCH ".*([.]).*" : $(m) ] { - # This is unqualified rule name. The user might want - # to set flags on this rule name, and toolset.flag - # auto-qualifies the rule name. Need to do the same - # here so set flag setting work. - # We can arrange for toolset.flag to *not* auto-qualify - # the argument, but then two rules defined in two Jamfiles - # will conflict. + # This is an unqualified rule name. The user might want to + # set flags on this rule name and toolset.flag + # auto-qualifies it. Need to do the same here so flag + # setting works. We can arrange for toolset.flag to *not* + # auto-qualify the argument but then two rules defined in + # two Jamfiles would conflict. m = $(context-module).$(m) ; } - v = [ indirect.make $(m) : $(context-module) ] ; } @@ -484,25 +491,24 @@ rule translate-indirect ( specification * : context-module ) else { result += $(p) ; - } + } } - return $(result) ; + return $(result) ; } -# Class which maintains a property set -> string -# mapping +# Class which maintains a property set -> string mapping. class property-map { + import errors ; import numbers ; import sequence ; - import errors : error ; - + rule __init__ ( ) - { + { self.next-flag = 1 ; } - + # Associate 'value' with 'properties' rule insert ( properties + : value ) { @@ -513,18 +519,16 @@ class property-map self.next-flag = [ numbers.increment $(self.next-flag) ] ; } - # Return the value associated with 'properties' - # or any subset of it. If more than one - # subset has value assigned to it, return the - # value for the longest subset, if it's unique. + # Returns the value associated with 'properties' or any subset of it. If + # more than one subset has a value assigned to it, returns the value for the + # longest subset, if it's unique. rule find ( properties + ) { return [ find-replace $(properties) ] ; } - - # Find the value associated with 'properties'. - # If 'value' parameter is given, replaces the found value - # Returns the value that were stored originally. + + # Returns the value associated with 'properties'. If 'value' parameter is + # given, replaces the found value. rule find-replace ( properties + : value ? ) { # First find all matches @@ -535,106 +539,95 @@ class property-map if $(self.properties.$(i)) in $(properties) { matches += $(i) ; - match-ranks += [ sequence.length - $(self.properties.$(i)) ] ; + match-ranks += [ sequence.length $(self.properties.$(i)) ] ; } } - local best = [ sequence.select-highest-ranked - $(matches) : $(match-ranks) ] ; + local best = [ sequence.select-highest-ranked $(matches) + : $(match-ranks) ] ; if $(best[2]) { - error "Ambiguous key" ; - } + errors.error "Ambiguous key" ; + } local original = $(self.value.$(best)) ; if $(value) { self.value.$(best) = $(value) ; - } + } return $(original) ; - } + } } + local rule __test__ ( ) { - import errors : try catch ; - import feature ; - import feature : feature subfeature compose ; - - # local rules must be explicitly re-imported - import property : path-order abbreviate-dashed ; - - feature.prepare-test property-test-temp ; - - feature toolset : gcc : implicit symmetric ; - subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 - 3.0 3.0.1 3.0.2 : optional ; - feature define : : free ; - feature runtime-link : dynamic static : symmetric link-incompatible ; - feature optimization : on off ; - feature variant : debug release : implicit composite symmetric ; - feature rtti : on off : link-incompatible ; - - compose debug : _DEBUG off ; - compose release : NDEBUG on ; - import assert ; import "class" : new ; - + import errors : try catch ; + import feature ; + + # Local rules must be explicitly re-imported. + import property : path-order abbreviate-dashed ; + + feature.prepare-test property-test-temp ; + + feature.feature toolset : gcc : implicit symmetric ; + feature.subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 3.0 3.0.1 + 3.0.2 : optional ; + feature.feature define : : free ; + feature.feature runtime-link : dynamic static : symmetric link-incompatible ; + feature.feature optimization : on off ; + feature.feature variant : debug release : implicit composite symmetric ; + feature.feature rtti : on off : link-incompatible ; + + feature.compose debug : _DEBUG off ; + feature.compose release : NDEBUG on ; + validate gcc gcc-3.0.1 : $(test-space) ; - + assert.true path-order $(test-space) debug foo ; assert.false path-order $(test-space) foo debug ; assert.true path-order $(test-space) gcc debug ; assert.false path-order $(test-space) debug gcc ; assert.true path-order $(test-space) on on ; assert.false path-order $(test-space) on on ; - + assert.result-equal gcc off FOO : refine gcc off : FOO - : $(test-space) - ; + : $(test-space) ; assert.result-equal gcc on : refine gcc off : on - : $(test-space) - ; + : $(test-space) ; assert.result-equal gcc off - : refine gcc : off : $(test-space) - ; + : refine gcc : off : $(test-space) ; assert.result-equal gcc off off:FOO - : refine gcc : off off:FOO - : $(test-space) - ; - - assert.result-equal gcc:foo gcc:bar - : refine gcc:foo : gcc:bar - : $(test-space) - ; + : refine gcc : off off:FOO + : $(test-space) ; + + assert.result-equal gcc:foo gcc:bar + : refine gcc:foo : gcc:bar + : $(test-space) ; assert.result MY_RELEASE - : evaluate-conditionals-in-context + : evaluate-conditionals-in-context release,off:MY_RELEASE - : gcc release off - - ; + : gcc release off ; assert.result debug - : as-path off debug - : $(test-space) - ; + : as-path off debug + : $(test-space) ; assert.result gcc/debug/rtti-off - : as-path gcc off off debug - : $(test-space) - ; + : as-path gcc off off debug + : $(test-space) ; assert.result optmz-off : abbreviate-dashed optimization-off ; assert.result rntm-lnk-sttc : abbreviate-dashed runtime-link-static ; - + try ; validate value : $(test-space) ; catch "Invalid property 'value': unknown feature 'feature'." ; @@ -642,7 +635,7 @@ local rule __test__ ( ) try ; validate default : $(test-space) ; catch \"default\" is not a known value of feature ; - + validate WHATEVER : $(test-space) ; try ; @@ -652,21 +645,20 @@ local rule __test__ ( ) try ; validate value : $(test-space) ; catch "value" is not a value of an implicit feature ; - - assert.result-equal on + assert.result-equal on : remove free implicit : gcc foo on : $(test-space) ; - assert.result-equal a + assert.result-equal a : select include : a gcc ; - assert.result-equal a + assert.result-equal a : select include bar : a gcc ; assert.result-equal a gcc : select include : a gcc ; - - assert.result-equal kylix a + + assert.result-equal kylix a : change gcc a : kylix ; pm = [ new property-map ] ; @@ -674,31 +666,23 @@ local rule __test__ ( ) $(pm).insert gcc NT : obj ; $(pm).insert gcc CYGWIN : obj ; - assert.equal o - : [ $(pm).find gcc ] ; + assert.equal o : [ $(pm).find gcc ] ; - assert.equal obj - : [ $(pm).find gcc NT ] ; + assert.equal obj : [ $(pm).find gcc NT ] ; try ; $(pm).find gcc NT CYGWIN ; catch "Ambiguous key" ; - # Test ordinary properties - assert.result - : split-conditional gcc - ; - - # Test properties with ":" - assert.result - : split-conditional FOO=A::B - ; - - # Test conditional feature + # Test ordinary properties. + assert.result : split-conditional gcc ; + + # Test properties with ":". + assert.result : split-conditional FOO=A::B ; + + # Test conditional feature. assert.result-equal gcc,3.0 FOO - : split-conditional gcc,3.0:FOO - ; - + : split-conditional gcc,3.0:FOO ; + feature.finish-test property-test-temp ; } - diff --git a/src/build/targets.jam b/src/build/targets.jam index f0596bc61..85a6a92b0 100644 --- a/src/build/targets.jam +++ b/src/build/targets.jam @@ -5,30 +5,29 @@ # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) - -# Supports 'abstract' targets, which are targets explicitly defined in Jamfile. +# Supports 'abstract' targets, which are targets explicitly defined in a +# Jamfile. # # Abstract targets are represented by classes derived from 'abstract-target' # class. The first abstract target is 'project-target', which is created for # each Jamfile, and can be obtained by the 'target' rule in the Jamfile's # module (see project.jam). # -# Project targets keep a list of 'main-target' instances. -# A main target is what the user explicitly defines in a Jamfile. It is -# possible to have several definitions for a main target, for example to have -# different lists of sources for different platforms. So, main targets -# keep a list of alternatives. +# Project targets keep a list of 'main-target' instances. A main target is +# what the user explicitly defines in a Jamfile. It is possible to have +# several definitions for a main target, for example to have different lists +# of sources for different platforms. So, main targets keep a list of +# alternatives. # # Each alternative is an instance of 'abstract-target'. When a main target -# subvariant is defined by some rule, that rule will decide what class to -# use, create an instance of that class and add it to the list of alternatives -# for the main target. +# subvariant is defined by some rule, that rule will decide what class to use, +# create an instance of that class and add it to the list of alternatives for +# the main target. # -# Rules supplied by the build system will use only targets derived -# from 'basic-target' class, which will provide some default behaviour. -# There will be different classes derived from it such as 'make-target', -# created by the 'make' rule, and 'typed-target', created by rules such as -# 'exe' and 'lib'. +# Rules supplied by the build system will use only targets derived from +# 'basic-target' class, which will provide some default behaviour. There will +# be different classes derived from it such as 'make-target', created by the +# 'make' rule, and 'typed-target', created by rules such as 'exe' and 'lib'. # # +------------------------+ @@ -147,6 +146,7 @@ class abstract-target } } + if --debug-building in [ modules.peek : ARGV ] { modules.poke : .debug-building : true ; @@ -171,17 +171,16 @@ rule decrease-indent ( ) } -# Project target class (derived from 'abstract-target') +# Project target class (derived from 'abstract-target'). # -# This class these responsibilities: -# - maintaining a list of main targets in this project and building them +# This class has the following responsibilities: +# - Maintaining a list of main targets in this project and building them. # # Main targets are constructed in two stages: -# - When Jamfile is read, a number of calls to 'add-alternative' is made. -# At that time, alternatives can also be renamed to account for inline -# targets. -# - The first time 'main-target' or 'has-main-target' rule is called, -# all alternatives are enumerated an main targets are created. +# - When Jamfile is read, a number of calls to 'add-alternative' is made. At +# that time, alternatives can also be renamed to account for inline targets. +# - The first time 'main-target' or 'has-main-target' rule is called, all +# alternatives are enumerated and main targets are created. class project-target : abstract-target { import project ; @@ -210,8 +209,8 @@ class project-target : abstract-target } } - # This is needed only by the 'make' rule. Need to find the - # way to make 'make' work without this method. + # This is needed only by the 'make' rule. Need to find the way to make + # 'make' work without this method. rule project-module ( ) { return $(self.project-module) ; @@ -260,8 +259,8 @@ class project-target : abstract-target return $(usage-requirements) [ sequence.unique $(targets) ] ; } - # Computes and returns a list of abstract-target instances which - # must be built when this project is built. + # Computes and returns a list of abstract-target instances which must be + # built when this project is built. rule targets-to-build ( ) { local result ; @@ -305,7 +304,7 @@ class project-target : abstract-target if $(self.built-main-targets) { errors.error "add-alternative called when main targets are already created." - : "in project" [ full-name ] ; + : "in project" [ full-name ] ; } self.alternatives += $(target-instance) ; } @@ -350,8 +349,8 @@ class project-target : abstract-target local extra-error-message ; if $(project-part) { - # There's explicit project part in id. Looks up the - # project and pass the request to it. + # There's explicit project part in id. Looks up the project and + # passes the request to it. local pm = [ project.find $(project-part) : $(current-location) ] ; if $(pm) { @@ -365,8 +364,8 @@ class project-target : abstract-target } else { - # Interpret target-name as name of main target - # Need to do this before checking for file. Consider this: + # Interpret target-name as name of main target. Need to do this + # before checking for file. Consider this: # # exe test : test.cpp ; # install s : test : . ; @@ -381,8 +380,8 @@ class project-target : abstract-target if ! [ $(result).exists ] { - # File actually does not exist. - # Reset 'target' so that an error is issued. + # File actually does not exist. Reset 'target' so that an + # error is issued. result = ; } } @@ -454,9 +453,9 @@ class project-target : abstract-target # Accessor, add a constant. rule add-constant ( - name # Variable name of the constant. - : value + # Value of the constant. - : type ? # Optional type of value. + name # Variable name of the constant. + : value + # Value of the constant. + : type ? # Optional type of value. ) { switch $(type) @@ -466,9 +465,9 @@ class project-target : abstract-target for local v in $(value) { v = [ path.root [ path.make $(v) ] $(self.location) ] ; - # Now make the value absolute path + # Now make the value absolute path. v = [ path.root $(v) [ path.pwd ] ] ; - # Constants should be in platform-native form + # Constants should be in platform-native form. v = [ path.native $(v) ] ; r += $(v) ; } @@ -479,7 +478,7 @@ class project-target : abstract-target self.constants += $(name) ; } self.constant.$(name) = $(value) ; - # Inject the constant in the scope of project-root module + # Inject the constant in the scope of project-root module. modules.poke $(self.project-module) : $(name) : $(value) ; } @@ -493,11 +492,11 @@ class project-target : abstract-target : [ modules.peek $(parent) : self.constant.$(c) ] ; } - # Import rules from parent + # Import rules from parent. local this-module = [ project-module ] ; local parent-module = [ $(parent).project-module ] ; - # Don't import rules which comes from 'project-rules', they - # must be imported localized. + # Don't import rules coming from 'project-rules' as they must be + # imported localized. local user-rules = [ set.difference [ RULENAMES $(parent-module) ] : [ RULENAMES project-rules ] ] ; @@ -532,16 +531,16 @@ local rule end-building ( main-target-instance ) } -# A named top-level target in Jamfile +# A named top-level target in Jamfile. class main-target : abstract-target { - import errors ; import assert ; - import sequence ; - import print ; import build-request ; + import errors ; import feature ; + import print ; import property-set ; + import sequence ; import targets : start-building end-building ; rule __init__ ( name : project ) @@ -567,20 +566,18 @@ class main-target : abstract-target self.alternatives += $(target) ; } - # Returns the best viable alternative for this property-set - # See the documentation for selection rules. + # Returns the best viable alternative for this property-set. See the + # documentation for selection rules. local rule select-alternatives ( property-set debug ? ) { - # When selecting alternatives we have to consider defaults, - # for example: + # When selecting alternatives we have to consider defaults, for example: # lib l : l.cpp : debug ; # lib l : l_opt.cpp : release ; # won't work unless we add default value debug. property-set = [ $(p).add-defaults ] ; - # The algorithm: we keep the current best viable alternative. - # When we've got new best viable alternative, we compare it - # with the current one. + # The algorithm: we keep the current best viable alternative. When we've + # got a new best viable alternative, we compare it with the current one. local best ; local best-properties ; @@ -635,11 +632,10 @@ class main-target : abstract-target } } - rule apply-default-build ( property-set ) { - # 1. First, see what properties from default-build - # are already present in property-set. + # 1. First, see what properties from default-build are already present + # in property-set. local raw = [ $(property-set).raw ] ; local specified-features = $(raw:G) ; @@ -653,18 +649,17 @@ class main-target : abstract-target } } - # 2. If there's any defaults to be applied, form the new - # build request. Pass it throw 'expand-no-defaults', since - # default-build might contain "release debug", which will - # result in two property-sets. + # 2. If there are any defaults to be applied, form a new build request. + # Pass it through to 'expand-no-defaults' since default-build might + # contain "release debug" resulting in two property-sets. local result ; if $(defaults-to-apply) { properties = [ build-request.expand-no-defaults - # We have to compress subproperties here to prevent - # property lists like: + # We have to compress subproperties here to prevent property + # lists like: # # msvc 7.1 multi # @@ -673,10 +668,9 @@ class main-target : abstract-target # 7.1/multi # msvc/7.1/multi # - # due to cross-product property combination. That may - # be an indication that - # build-request.expand-no-defaults is the wrong rule - # to use here. + # due to a cross-product property combination. That may be an + # indication that build-request.expand-no-defaults is the wrong + # rule to use here. [ feature.compress-subproperties $(raw) ] $(defaults-to-apply) ] ; @@ -693,7 +687,6 @@ class main-target : abstract-target { result = [ property-set.empty ] ; } - } else { @@ -704,14 +697,14 @@ class main-target : abstract-target # Select an alternative for this main target, by finding all alternatives # which requirements are satisfied by 'properties' and picking the one with - # longest requirements set. - # Returns the result of calling 'generate' on that alternative. + # longest requirements set. Returns the result of calling 'generate' on that + # alternative. rule generate ( property-set ) { start-building $(__name__) ; - # We want composite properties in build request act as if - # all the properties it expands too are explicitly specified. + # We want composite properties in build request act as if all the + # properties it expands too are explicitly specified. property-set = [ $(property-set).expand ] ; local all-property-sets = [ apply-default-build $(property-set) ] ; @@ -730,11 +723,10 @@ class main-target : abstract-target return $(usage-requirements) [ sequence.unique $(result) ] ; } - # Generates the main target with the given property set - # and returns a list which first element is property-set object - # containing usage-requirements of generated target and with - # generated virtual target in other elements. It's possible - # that no targets are generated. + # Generates the main target with the given property set and returns a list + # which first element is property-set object containing usage-requirements + # of generated target and with generated virtual target in other elements. + # It's possible that no targets are generated. local rule generate-really ( property-set ) { local best-alternatives = [ select-alternatives $(property-set) ] ; @@ -746,10 +738,8 @@ class main-target : abstract-target } else { - local result = [ $(best-alternatives).generate $(property-set) ] ; - - # Now return virtual targets for the only alternative - return $(result) ; + # Now return virtual targets for the only alternative. + return [ $(best-alternatives).generate $(property-set) ] ; } } @@ -760,13 +750,13 @@ class main-target : abstract-target { $(a).rename $(new-name) ; } - } } -# Abstract target which refers to a source file. -# This is artificial creature; it's usefull so that sources to -# a target can be represented as list of abstract target instances. + +# Abstract target which refers to a source file. This is an artificial entity +# allowing sources to a target to be represented using a list of abstract target +# instances. class file-reference : abstract-target { import virtual-target ; @@ -787,20 +777,19 @@ class file-reference : abstract-target : $(self.project) ] ; } - # Returns true if the referred file really exists; + # Returns true if the referred file really exists. rule exists ( ) { location ; return $(self.file-path) ; } - # Returns the location of target. Needed by 'testing.jam' + # Returns the location of target. Needed by 'testing.jam'. rule location ( ) { if ! $(self.file-location) { local source-location = [ $(self.project).get source-location ] ; - for local src-dir in $(source-location) { if ! $(self.file-location) @@ -818,9 +807,10 @@ class file-reference : abstract-target } } -# Given a target-reference, made in context of 'project', -# returns the abstract-target instance that is referred to, as well -# as properties explicitly specified for this reference. + +# Given a target-reference, made in context of 'project', returns the +# abstract-target instance that is referred to, as well as properties explicitly +# specified for this reference. rule resolve-reference ( target-reference : project ) { # Separate target name from properties override @@ -840,44 +830,42 @@ rule resolve-reference ( target-reference : project ) } - -# Attempts to generate the target given by target reference, which -# can refer both to a main target or to a file. -# Returns a list consisting of +# Attempts to generate the target given by target reference, which can refer +# both to a main target or to a file. Returns a list consisting of # - usage requirements # - generated virtual targets, if any -rule generate-from-reference - ( target-reference # Target reference - : project # Project where the reference is made - : property-set # Properties of the main target that - # makes the reference - ) +rule generate-from-reference ( + target-reference # Target reference. + : project # Project where the reference is made. + : property-set # Properties of the main target that makes the reference. +) { local r = [ resolve-reference $(target-reference) : $(project) ] ; local target = $(r[1]) ; local sproperties = $(r[2]) ; - # Take properties which should be propagated and refine them - # with source-specific requirements. + # Take properties which should be propagated and refine them with + # source-specific requirements. local propagated = [ $(property-set).propagated ] ; local rproperties = [ $(propagated).refine $(sproperties) ] ; if $(rproperties[1]) = "@error" { errors.error - "When building" [ full-name ] " with properties " $(properties) : + "When building" [ full-name ] " with properties " $(properties) : "Invalid properties specified for " $(source) ":" - $(rproperties[2-]) ; + $(rproperties[2-]) ; } return [ $(target).generate $(rproperties) ] ; } -# Given build request and requirements, return properties common to dependency + +# Given a build request and requirements, return properties common to dependency # build request and target build properties. rule common-properties ( build-request requirements ) { - # For optimization, we add free requirements directly, - # without using complex algorithsm. - # This gives the complex algorithm better chance of caching results. + # For optimization, we add free requirements directly, without using a + # complex algorithm. This gives the complex algorithm better chance of + # caching results. local free = [ $(requirements).free ] ; local non-free = [ property-set.create [ $(requirements).base ] [ $(requirements).incidental ] ] ; @@ -890,24 +878,24 @@ rule common-properties ( build-request requirements ) result = [ $($(key)).add-raw $(free) ] ; } + # Given 'context' -- a set of already present properties, and 'requirements', -# decide which extra properties should be applied to 'context'. -# For conditional requirements, this means evaluating condition. For -# indirect conditional requirements, this means calling a rule. Ordinary -# requirements are always applied. -# -# Handles situation where evaluating one conditional requirements affects -# condition of another conditional requirements, for example: +# decide which extra properties should be applied to 'context'. For conditional +# requirements, this means evaluating condition. For indirect conditional +# requirements, this means calling a rule. Ordinary requirements are always +# applied. # +# Handles the situation where evaluating one conditional requirement affects +# conditions of another conditional requirements, such as: # gcc:release release:RELEASE # -# If 'what' is 'refined' returns context refined with new requirements. -# If 'what' is 'added' returns just the requirements that must be applied. +# If 'what' is 'refined' returns context refined with new requirements. If +# 'what' is 'added' returns just the requirements to be applied. rule evaluate-requirements ( requirements : context : what ) { - # Apply non-conditional requirements. - # It's possible that further conditional requirement change a value set by - # non-conditional requirements. For example: + # Apply non-conditional requirements. It's possible that further conditional + # requirement change a value set by non-conditional requirements. For + # example: # # exe a : a.cpp : single foo:multi ; # @@ -923,17 +911,16 @@ rule evaluate-requirements ( requirements : context : what ) raw = [ property.refine $(raw) : $(unconditional) ] ; # We've collected properties that surely must be present in common - # properties. We now try to figure out what other properties - # should be added in order to satisfy rules (4)-(6) from the docs. + # properties. We now try to figure out what other properties should be added + # in order to satisfy rules (4)-(6) from the docs. local conditionals = [ $(requirements).conditional ] ; - # The 'count' variable has one element for each conditional feature - # and for each occurence of '' feature. - # It's used as a loop counter: for each iteration of the loop - # before we remove one element and the property set should - # stabilize before we've done. It's supposed to #conditionals iterations - # should be enough for properties to propagate along conditions in any - # direction. + # The 'count' variable has one element for each conditional feature and for + # each occurence of '' feature. It's used as a loop + # counter: for each iteration of the loop before we remove one element and + # the property set should stabilize before we're done. It's assumed that + # #conditionals iterations should be enough for properties to propagate + # along conditions in any direction. local count = $(conditionals) [ $(requirements).get ] and-once-more ; @@ -943,19 +930,18 @@ rule evaluate-requirements ( requirements : context : what ) local current = $(raw) ; # It's assumed that ordinary conditional requirements can't add - # properties, and that rules referred - # by properties can't add new - # properties. So the list of indirect conditionals - # does not change. + # properties, and that rules referred by + # properties can't add new + # properties. So the list of indirect conditionals does not change. local indirect = [ $(requirements).get ] ; indirect = [ MATCH @(.*) : $(indirect) ] ; local ok ; while $(count) { - # Evaluate conditionals in context of current properties + # Evaluate conditionals in context of current properties. local e = [ property.evaluate-conditionals-in-context $(conditionals) - : $(current) ] ; + : $(current) ] ; # Evaluate indirect conditionals. for local i in $(indirect) @@ -971,10 +957,9 @@ rule evaluate-requirements ( requirements : context : what ) } else { - # Oops, results of evaluation of conditionals has changed. - # Also 'current' contains leftover from previous evaluation. - # Recompute 'current' using initial properties and conditional - # requirements. + # Oops, results of evaluation of conditionals has changed. Also + # 'current' contains leftover from previous evaluation. Recompute + # 'current' using initial properties and conditional requirements. added-requirements = $(e) ; current = [ property.refine $(raw) : [ feature.expand $(e) ] ] ; } @@ -985,7 +970,6 @@ rule evaluate-requirements ( requirements : context : what ) errors.error "Can't evaluate conditional properties " $(conditionals) ; } - if $(what) = added { return [ property-set.create $(unconditional) $(added-requirements) ] ; @@ -1003,43 +987,42 @@ rule evaluate-requirements ( requirements : context : what ) rule common-properties2 ( build-request requirements ) { - # This guarantees that default properties are present - # in result, unless they are overrided by some requirement. - # FIXME: There is possibility that we've added bar, which is composite - # and expands to bar2, but default value of is not bar2, - # in which case it's not clear what to do. + # This guarantees that default properties are present in the result, unless + # they are overriden by some requirement. FIXME: There is possibility that + # we've added bar, which is composite and expands to bar2, but + # default value of is not bar2, in which case it's not clear what to + # do. # build-request = [ $(build-request).add-defaults ] ; - # Featured added by 'add-default' can be composite and expand - # to features without default values -- so they are not added yet. - # It could be clearer/faster to expand only newly added properties - # but that's not critical. + # Features added by 'add-default' can be composite and expand to features + # without default values -- so they are not added yet. It could be clearer/ + # /faster to expand only newly added properties but that's not critical. build-request = [ $(build-request).expand ] ; return [ evaluate-requirements $(requirements) : $(build-request) : refined ] ; } + # Implements the most standard way of constructing main target alternative from # sources. Allows sources to be either file or other main target and handles # generation of those dependency targets. class basic-target : abstract-target { import build-request ; - import virtual-target ; - import targets ; - import property-set ; - import set ; - import sequence ; - import errors ; - import "class" : new ; - import property ; - import feature ; import build-system ; + import "class" : new ; + import errors ; + import feature ; + import property ; + import property-set ; + import sequence ; + import set ; + import targets ; + import virtual-target ; - rule __init__ ( name : project - : sources * : requirements * : - default-build * : usage-requirements * ) + rule __init__ ( name : project : sources * : requirements * + : default-build * : usage-requirements * ) { abstract-target.__init__ $(name) : $(project) ; @@ -1065,10 +1048,9 @@ class basic-target : abstract-target } } - # Returns the list of abstract-targets which are used as sources. - # The extra properties specified for sources are not represented. - # The only user of this rule at the moment is the "--dump-tests" - # feature of the test system. + # Returns the list of abstract-targets which are used as sources. The extra + # properties specified for sources are not represented. The only user for + # this rule at the moment is the "--dump-tests" feature of the test system. rule sources ( ) { if ! $(self.source-targets) { @@ -1091,18 +1073,18 @@ class basic-target : abstract-target return $(self.default-build) ; } - # Returns the alternative condition for this alternative, if - # the condition is satisfied by 'property-set'. + # Returns the alternative condition for this alternative, if the condition + # is satisfied by 'property-set'. rule match ( property-set debug ? ) { - # The condition is composed of all base non-conditional properties. - # It's not clear if we should expand 'self.requirements' or not. - # For one thing, it would be nice to be able to put + # The condition is composed of all base non-conditional properties. It's + # not clear if we should expand 'self.requirements' or not. For one + # thing, it would be nice to be able to put # msvc-6.0 # in requirements. - # On the other hand, if we have release in condition it - # does not make sense to require full to be in - # build request just to select this variant. + # On the other hand, if we have release in condition it does + # not make sense to require full to be in build request + # just to select this variant. local bcondition = [ $(self.requirements).base ] ; local ccondition = [ $(self.requirements).conditional ] ; local condition = [ set.difference $(bcondition) : $(ccondition) ] ; @@ -1129,12 +1111,11 @@ class basic-target : abstract-target } } - # Takes a target reference, which might be either target id - # or a dependency property, and generates that target using - # 'property-set' as build request. + # Takes a target reference, which might be either target id or a dependency + # property, and generates that target using 'property-set' as build request. # - # The results are added to to variable called 'result-var'. - # Usage requirements are added variable called 'usage-requirements-var'. + # The results are added to the variable called 'result-var'. Usage + # requirements are added to the variable called 'usage-requirements-var'. rule generate-dependencies ( dependencies * : property-set : result-var usage-requirements-var ) { @@ -1144,7 +1125,7 @@ class basic-target : abstract-target local id = $(dependency:G=) ; local result = - [ targets.generate-from-reference $(id) : $(self.project) + [ targets.generate-from-reference $(id) : $(self.project) : $(property-set) ] ; $(result-var) += $(result[2-]:G=$(grist)) ; @@ -1152,10 +1133,8 @@ class basic-target : abstract-target } } - - # Determines final build properties, generates sources, - # and calls 'construct'. This method should not be - # overridden. + # Determines final build properties, generates sources, and calls + # 'construct'. This method should not be overridden. rule generate ( property-set ) { if [ modules.peek : .debug-building ] @@ -1166,21 +1145,19 @@ class basic-target : abstract-target targets.increase-indent ; ECHO [ targets.indent ] "Build request: " [ $(property-set).raw ] ; local cf = [ build-system.command-line-free-features ] ; - ECHO [ targets.indent ] "Command line free features: " - [ $(cf).raw ] ; + ECHO [ targets.indent ] "Command line free features: " [ $(cf).raw ] ; ECHO [ targets.indent ] "Target requirements: " [ $(self.requirements).raw ] ; } if ! $(self.generated.$(property-set)) { - # Apply free features form the command line. If user - # said + # Apply free features form the command line. If user said # define=FOO - # he most likely want this define to be set for all compiles. + # he most likely wants this define to be set for all compiles. property-set = [ $(property-set).refine - [ build-system.command-line-free-features ] ] ; + [ build-system.command-line-free-features ] ] ; local rproperties = [ targets.common-properties $(property-set) - $(self.requirements) ] ; + $(self.requirements) ] ; if [ modules.peek : .debug-building ] { @@ -1195,34 +1172,33 @@ class basic-target : abstract-target local usage-requirements ; generate-dependencies [ $(rproperties).dependency ] - : $(rproperties) - : properties usage-requirements ; + : $(rproperties) + : properties usage-requirements ; generate-dependencies $(self.sources) : $(rproperties) - : source-targets usage-requirements ; + : source-targets usage-requirements ; if [ modules.peek : .debug-building ] { ECHO ; ECHO [ targets.indent ] - "Usage requirements for $(self.name) are " $(usage-requirements) ; + "Usage requirements for $(self.name) are " $(usage-requirements) ; } rproperties = [ property-set.create $(properties) - $(usage-requirements) ] ; + $(usage-requirements) ] ; usage-requirements = [ property-set.create $(usage-requirements) ] ; if [ modules.peek : .debug-building ] { ECHO [ targets.indent ] - "Build properties: " [ $(rproperties).raw ] ; + "Build properties: " [ $(rproperties).raw ] ; } local extra = [ $(rproperties).get ] ; source-targets += $(extra:G=) ; - # We might get duplicate sources, for example if - # we link to two library which have the same in - # usage requirements. + # We might get duplicate sources, for example if we link to two + # libraries having the same usage requirement. source-targets = [ sequence.unique $(source-targets) ] ; local result = @@ -1234,11 +1210,10 @@ class basic-target : abstract-target local gur = $(result[1]) ; result = $(result[2-]) ; - local s = [ create-subvariant - $(result) : - [ virtual-target.recent-targets ] - : $(property-set) : $(source-targets) - : $(rproperties) : $(usage-requirements) ] ; + local s = [ create-subvariant $(result) + : [ virtual-target.recent-targets ] + : $(property-set) : $(source-targets) + : $(rproperties) : $(usage-requirements) ] ; virtual-target.clear-recent-targets ; local ur = [ compute-usage-requirements $(s) ] ; @@ -1259,12 +1234,12 @@ class basic-target : abstract-target if $(rproperties[1]) = "@error" { ECHO [ targets.indent ] - "Skipping build of: " [ full-name ] " cannot compute common properties" ; + "Skipping build of: " [ full-name ] " cannot compute common properties" ; } else if [ $(rproperties).get ] = no { ECHO [ targets.indent ] - "Skipping build of: " [ full-name ] " no in common properties" ; + "Skipping build of: " [ full-name ] " no in common properties" ; } else { @@ -1290,19 +1265,16 @@ class basic-target : abstract-target return $(self.generated.$(property-set)) ; } - # Given the set of generated targets, and refined build - # properties, determines and sets appripriate usage requirements - # on those targets. + # Given the set of generated targets, and refined build properties, + # determines and sets appripriate usage requirements on those targets. rule compute-usage-requirements ( subvariant ) { local rproperties = [ $(subvariant).build-properties ] ; xusage-requirements = [ targets.evaluate-requirements - $(self.usage-requirements) - : $(rproperties) - : added ] ; + $(self.usage-requirements) : $(rproperties) : added ] ; - # We generate all dependency properties and add them, - # as well as their usage requirements, to result. + # We generate all dependency properties and add them, as well as their + # usage requirements, to the result. local extra ; generate-dependencies [ $(xusage-requirements).dependency ] : $(rproperties) : extra extra ; @@ -1310,11 +1282,11 @@ class basic-target : abstract-target local result = [ property-set.create [ $(xusage-requirements).non-dependency ] $(extra) ] ; - # Propagate usage requirements we've got from sources, except - # for the and features. + # Propagate usage requirements we've got from sources, except for the + # and features. # - # That feature specifies which pch file to use, and should apply - # only to direct dependents. Consider: + # That feature specifies which pch file to use, and should apply only to + # direct dependents. Consider: # # pch pch1 : ... # lib lib1 : ..... pch1 ; @@ -1323,27 +1295,22 @@ class basic-target : abstract-target # # Here, lib2 should not get property from pch1. # - # Essentially, when those two features are in usage requirements, - # they are propagated only to direct dependents. We might need - # a more general mechanism, but for now, only those two - # features are special. + # Essentially, when those two features are in usage requirements, they + # are propagated only to direct dependents. We might need a more general + # mechanism, but for now, only those two features are special. local raw = [ $(subvariant).sources-usage-requirements ] ; raw = [ $(raw).raw ] ; raw = [ property.change $(raw) : ] ; raw = [ property.change $(raw) : ] ; - result = [ $(result).add [ property-set.create $(raw) ] ] ; - - return $(result) ; + return [ $(result).add [ property-set.create $(raw) ] ] ; } - # Creates a new subvariant-dg instances for 'targets' - # - 'root-targets' the virtual targets will be returned to dependents - # - 'all-targets' all virtual - # targets created while building this main target - # - 'build-request' is property-set instance with requested build properties + # Creates new subvariant instances for 'targets'. + # 'root-targets' - virtual targets to be returned to dependants + # 'all-targets' - virtual targets created while building this main target + # 'build-request' - property-set instance with requested build properties local rule create-subvariant ( root-targets * - : all-targets * : build-request : sources * : - rproperties + : all-targets * : build-request : sources * : rproperties : usage-requirements ) { for local e in $(root-targets) @@ -1351,10 +1318,10 @@ class basic-target : abstract-target $(e).root true ; } - # Process all vtargets that will be created if this main target + # Process all virtual targets that will be created if this main target # is created. local s = [ new subvariant $(__name__) : $(build-request) : $(sources) - : $(rproperties) : $(usage-requirements) : $(all-targets) ] ; + : $(rproperties) : $(usage-requirements) : $(all-targets) ] ; for local v in $(all-targets) { if ! [ $(v).creating-subvariant ] @@ -1365,9 +1332,9 @@ class basic-target : abstract-target return $(s) ; } - # Constructs the virtual targets for this abstract targets and - # the dependecy graph. Returns the list of virtual targets. - # Should be overrided in derived classes. + # Constructs virtual targets for this abstract target and the dependency + # graph. Returns the list of virtual targets. Should be overriden in derived + # classes. rule construct ( name : source-targets * : properties * ) { errors.error "method should be defined in derived classes" ; @@ -1379,11 +1346,11 @@ class typed-target : basic-target { import generators ; - rule __init__ ( name : project : type - : sources * : requirements * : default-build * : usage-requirements * ) + rule __init__ ( name : project : type : sources * : requirements * + : default-build * : usage-requirements * ) { - basic-target.__init__ $(name) : $(project) - : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ; + basic-target.__init__ $(name) : $(project) : $(sources) + : $(requirements) : $(default-build) : $(usage-requirements) ; self.type = $(type) ; } @@ -1404,8 +1371,8 @@ class typed-target : basic-target ECHO "warn: Unable to construct" [ full-name ] ; # Are there any top-level generators for this type/property set. - if ! [ generators.find-viable-generators - $(self.type) : $(property-set) ] + if ! [ generators.find-viable-generators $(self.type) + : $(property-set) ] { ECHO "error: no generators were found for type '$(self.type)'" ; ECHO "error: and the requested properties" ; @@ -1415,7 +1382,6 @@ class typed-target : basic-target EXIT ; } } - return $(r) ; } } @@ -1425,7 +1391,7 @@ class typed-target : basic-target # 'sources'. If there are any objects in 'sources', they are treated as main # target instances, and the name of such targets are adjusted to be # '__'. Such renaming is disabled if -# a non-empty value is passed for 'no-renaming' parameter. +# a non-empty value is passed as the 'no-renaming' parameter. # rule main-target-sources ( sources * : main-target-name : no-renaming ? ) { @@ -1454,13 +1420,12 @@ rule main-target-sources ( sources * : main-target-name : no-renaming ? ) } -# Returns the requirement to use when declaring a main target, which are -# obtained by -# - translating all specified property paths, and -# - refining project requirements with the one specified for the target +# Returns the requirements to use when declaring a main target, obtained by +# translating all specified property paths and refining project requirements +# with the ones specified for the target. rule main-target-requirements ( - specification * # Properties explicitly specified for a main target - : project # Project where the main target is to be declared + specification * # Properties explicitly specified for the main target. + : project # Project where the main target is to be declared. ) { specification += [ toolset.requirements ] ; @@ -1468,7 +1433,6 @@ rule main-target-requirements ( local requirements = [ property-set.refine-from-user-input [ $(project).get requirements ] : $(specification) : [ $(project).project-module ] : [ $(project).get location ] ] ; - if $(requirements[1]) = "@error" { errors.error "Conflicting requirements for target:" $(requirements) ; @@ -1477,25 +1441,23 @@ rule main-target-requirements ( } -# Returns the use requirement to use when declaring a main target, which are -# obtained by -# - translating all specified property paths, and -# - adding project's usage requirements +# Returns the usage requirements to use when declaring a main target, which are +# obtained by translating all specified property paths and adding project's +# usage requirements. rule main-target-usage-requirements ( - specification * # Use-properties explicitly specified for a main target - : project # Project where the main target is to be declared + specification * # Use-properties explicitly specified for a main target. + : project # Project where the main target is to be declared. ) { - local loc = [ $(project).get location ] ; local project-usage-requirements = [ $(project).get usage-requirements ] ; - # We don't use 'refine-from-user-input' because I'm not sure if: - # - removing of parent's usage requirements makes sense + # We don't use 'refine-from-user-input' because: + # - I'm not sure if removing of parent's usage requirements makes sense # - refining of usage requirements is not needed, since usage requirements # are always free. local usage-requirements = [ property-set.create-from-user-input $(specification) - : [ $(project).project-module ] [ $(project).get location ] ] ; + : [ $(project).project-module ] [ $(project).get location ] ] ; return [ $(project-usage-requirements).add $(usage-requirements) ] ; } @@ -1505,9 +1467,9 @@ rule main-target-usage-requirements ( # obtained by using the specified value if not empty and parent's default build # attribute otherwise. rule main-target-default-build ( - specification * # Default build explicitly specified for a main target - : project # Project where the main target is to be declared - ) + specification * # Default build explicitly specified for a main target. + : project # Project where the main target is to be declared. +) { local result ; if $(specification) @@ -1522,8 +1484,7 @@ rule main-target-default-build ( } -# Registers the specified target as a main target alternatives. -# Returns 'target'. +# Registers the specified target as a main target alternative and returns it. rule main-target-alternative ( target ) { local ptarget = [ $(target).project ] ; @@ -1535,17 +1496,15 @@ rule main-target-alternative ( target ) # Creates a typed-target with the specified properties. The 'name', 'sources', # 'requirements', 'default-build' and 'usage-requirements' are assumed to be in # the form specified by the user in Jamfile corresponding to 'project'. -rule create-typed-target ( type : project : - name : sources * : requirements * : default-build * - : usage-requirements * ) +rule create-typed-target ( type : project : name : sources * : requirements * + : default-build * : usage-requirements * ) { return [ - targets.main-target-alternative - [ new typed-target $(name) : $(project) : $(type) - : [ targets.main-target-sources $(sources) : $(name) ] - : [ targets.main-target-requirements $(requirements) : $(project) ] - : [ targets.main-target-default-build $(default-build) : $(project) ] - : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] - ] ] ; - + targets.main-target-alternative + [ new typed-target $(name) : $(project) : $(type) + : [ targets.main-target-sources $(sources) : $(name) ] + : [ targets.main-target-requirements $(requirements) : $(project) ] + : [ targets.main-target-default-build $(default-build) : $(project) ] + : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] + ] ] ; } diff --git a/src/build/type.jam b/src/build/type.jam index 8973effd8..a1184abfe 100644 --- a/src/build/type.jam +++ b/src/build/type.jam @@ -6,16 +6,16 @@ # Deals with target type declaration and defines target class which supports # typed targets. -import feature ; -import generators : * ; import "class" : new ; import errors ; +import feature ; +import generators : * ; +import project ; import property ; import scanner ; -import project ; -# This creates a circular dependency -# project-test1 -> project -> project-root -> builtin -> type -> targets -> project +# The follwing import would create a circular dependency: +# project -> project-root -> builtin -> type -> targets -> project # import targets ; # The feature is optional so it would never get added implicitly. It's used only @@ -25,6 +25,7 @@ feature.feature target-type : : composite optional ; feature.feature main-target-type : : optional incidental ; feature.feature base-target-type : : composite optional free ; + # Registers a target type, possible derived from a 'base-type'. Providing a list # of 'suffixes' here is a shortcut for separately calling the register-suffixes # rule with the given suffixes and the set-generated-target-suffix rule with the @@ -51,7 +52,7 @@ rule register ( type : suffixes * : base-type ? ) if $(suffixes)-is-not-empty { - # Specify mapping from suffixes to type + # Specify mapping from suffixes to type. register-suffixes $(suffixes) : $(type) ; # Generated targets of 'type' will use the first of 'suffixes'. This # may be overriden. @@ -82,7 +83,7 @@ rule register ( type : suffixes * : base-type ? ) # of that type. rule type-to-rule-name ( type ) { - # Lowercase everything. Convert underscores to dashes.ame. + # Lowercase everything. Convert underscores to dashes. import regex ; local n = [ regex.split $(type:L) "_" ] ; return $(n:J=-) ; @@ -110,7 +111,7 @@ rule register-suffixes ( suffixes + : type ) else if $(.type.$(s)) != type { errors.error Attempting to specify multiple types for suffix \"$(s)\" - : "Old type $(.type.$(s)), New type $(type)" ; + : "Old type $(.type.$(s)), New type $(type)" ; } } } @@ -150,13 +151,15 @@ rule set-scanner ( type : scanner ) # Returns a scanner instance appropriate to 'type' and 'properties'. rule get-scanner ( type : property-set ) { - if $(.scanner.$(type)) { + if $(.scanner.$(type)) + { return [ scanner.get $(.scanner.$(type)) : $(property-set) ] ; } } -# returns type and all of its bases in order of their distance from type. +# Returns the given type and all of its base types in order of their distance +# from type. rule all-bases ( type ) { local result = $(type) ; @@ -204,10 +207,10 @@ rule is-subtype ( type base ) } -# Store suffixes for generated targets +# Store suffixes for generated targets. .suffixes = [ new property-map ] ; -# Store prefixes for generated targets (e.g. "lib" for library) +# Store prefixes for generated targets (e.g. "lib" for library). .prefixes = [ new property-map ] ; @@ -272,7 +275,7 @@ rule generated-target-prefix ( type : property-set ) } -# Common rules for prefix/suffix provisioning follow +# Common rules for prefix/suffix provisioning follow. local rule set-generated-target-ps ( ps : type : properties * : psval ) { @@ -359,22 +362,22 @@ rule type ( filename ) # Rule used to construct all main targets. Note that this rule gets imported -# into the global namespace under different names and exactly what type of -# target it is supposed to construct is read from the name of the rule actually -# used to invoke it. +# into the global namespace under different alias names and exactly what type of +# target it is supposed to construct is read from the name of the alias rule +# actually used to invoke it. rule main-target-rule ( name : sources * : requirements * : default-build * - : usage-requirements * ) + : usage-requirements * ) { - # First find the required target type, which is equal to the rule name used - # to invoke us. + # First discover the required target type, which is equal to the rule name + # used to invoke us. local bt = [ BACKTRACE 1 ] ; local rulename = $(bt[4]) ; local project = [ project.current ] ; - # This is a circular module dependency, so it must be imported here + # This is a circular module dependency so it must be imported here. import targets ; return [ targets.create-typed-target $(.main-target-type.$(rulename)) - : $(project) : $(name) : $(sources) : $(requirements) - : $(default-build) : $(usage-requirements) ] ; + : $(project) : $(name) : $(sources) : $(requirements) + : $(default-build) : $(usage-requirements) ] ; } diff --git a/src/engine/build.bat b/src/engine/build.bat index 377db20c0..8335a0f01 100644 --- a/src/engine/build.bat +++ b/src/engine/build.bat @@ -40,7 +40,7 @@ goto :eof :Test_Option -REM Tests wether the given string is in the form of an option: "--*" +REM Tests whether the given string is in the form of an option: "--*" setlocal & endlocal setlocal set test=%1 diff --git a/src/tools/builtin.jam b/src/tools/builtin.jam index 52e726a68..678a18611 100644 --- a/src/tools/builtin.jam +++ b/src/tools/builtin.jam @@ -1,45 +1,46 @@ -# Copyright 2002, 2003, 2004, 2005 Dave Abrahams -# Copyright 2002, 2005, 2006, 2007 Rene Rivera -# Copyright 2006 Juergen Hunold -# Copyright 2005 Toon Knapen -# 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) +# Copyright 2002, 2003, 2004, 2005 Dave Abrahams +# Copyright 2002, 2005, 2006, 2007 Rene Rivera +# Copyright 2006 Juergen Hunold +# Copyright 2005 Toon Knapen +# 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) # Defines standard features and rules. +import alias ; import "class" : new ; - import feature : feature compose ; import toolset : flags ; import errors : error ; -import type ; -import scanner ; -import generators ; -import regex ; -import virtual-target ; -import os ; -import symlink ; -import alias ; -import property ; -import print ; -import utility ; -import project ; import generate ; +import generators ; +import os ; +import print ; +import project ; +import property ; +import regex ; +import scanner ; +import symlink ; +import type ; +import utility ; +import virtual-target ; +import types/register ; -# This feature is used to determine which OS we're on. -# In future, this may become and -# The future is now... + +.os-names = amiga aix bsd cygwin darwin dos emx freebsd hpux linux netbsd + openbsd osf qnx qnxnto sgi solaris sun sunos svr4 sysv ultrix unix unixware + vms windows ; + + +# Feature used to determine which OS we're on. New and +# features should be used instead. local os = [ modules.peek : OS ] ; -feature os : $(os) : propagated link-incompatible ; +feature.feature os : $(os) : propagated link-incompatible ; -.os-names = amiga aix bsd cygwin darwin dos emx freebsd hpux - linux netbsd openbsd osf qnx qnxnto sgi solaris sun sunos - svr4 sysv ultrix unix unixware vms windows ; -# Translates from bjam current OS to the os tags used -# in host-os and target-os. I.e. it returns the -# running host-os. +# Translates from bjam current OS to the os tags used in host-os and target-os, +# i.e. returns the running host-os. local rule default-host-os ( ) { local host-os ; @@ -51,238 +52,230 @@ local rule default-host-os ( ) { switch [ os.name ] { - case NT : host-os = windows ; - case AS400 : host-os = unix ; - case MINGW : host-os = windows ; - case BSDI : host-os = bsd ; - case COHERENT : host-os = unix ; - case DRAGONFLYBSD : host-os = bsd ; - case IRIX : host-os = sgi ; - case MACOSX : host-os = darwin ; - case KFREEBSD : host-os = freebsd ; - case LINUX : host-os = linux ; - case * : host-os = unix ; + case NT : host-os = windows ; + case AS400 : host-os = unix ; + case MINGW : host-os = windows ; + case BSDI : host-os = bsd ; + case COHERENT : host-os = unix ; + case DRAGONFLYBSD : host-os = bsd ; + case IRIX : host-os = sgi ; + case MACOSX : host-os = darwin ; + case KFREEBSD : host-os = freebsd ; + case LINUX : host-os = linux ; + case * : host-os = unix ; } } return $(host-os:L) ; } -# The two OS features define a known set of abstract OS -# names. The host-os is the OS under which bjam is running. -# Even though this should really be a fixed property we need -# to list all the values to prevent unkown value errors. -# Both set the default value to the current OS to account for -# the default use case of building on the target OS. -feature host-os : $(.os-names) ; + +# The two OS features define a known set of abstract OS names. The host-os is +# the OS under which bjam is running. Even though this should really be a fixed +# property we need to list all the values to prevent unknown value errors. Both +# set the default value to the current OS to account for the default use case of +# building on the target OS. +feature.feature host-os : $(.os-names) ; feature.set-default host-os : [ default-host-os ] ; -feature target-os - : $(.os-names) - : propagated link-incompatible ; +feature.feature target-os : $(.os-names) : propagated link-incompatible ; feature.set-default target-os : [ default-host-os ] ; -feature toolset : : implicit propagated symmetric ; +feature.feature toolset : : implicit propagated symmetric ; +feature.feature stdlib : native : propagated composite ; +feature.feature link : shared static : propagated ; +feature.feature runtime-link : shared static : propagated ; +feature.feature runtime-debugging : on off : propagated ; +feature.feature optimization : off speed space : propagated ; +feature.feature profiling : off on : propagated ; +feature.feature inlining : off on full : propagated ; +feature.feature threading : single multi : propagated ; +feature.feature rtti : on off : propagated ; +feature.feature exception-handling : on off : propagated ; -feature stdlib : native : propagated composite ; +# Whether there is support for asynchronous EH (e.g. catching SEGVs). +feature.feature asynch-exceptions : off on : propagated ; -feature link : shared static : propagated ; -feature runtime-link : shared static : propagated ; -feature runtime-debugging : on off : propagated ; +# Whether all extern "C" functions are considered nothrow by default. +feature.feature extern-c-nothrow : off on : propagated ; +feature.feature debug-symbols : on off : propagated ; +feature.feature define : : free ; +feature.feature undef : : free ; +feature.feature "include" : : free path ; #order-sensitive ; +feature.feature cflags : : free ; +feature.feature cxxflags : : free ; +feature.feature fflags : : free ; +feature.feature asmflags : : free ; +feature.feature linkflags : : free ; +feature.feature archiveflags : : free ; +feature.feature version : : free ; -feature optimization : off speed space : propagated ; -feature profiling : off on : propagated ; -feature inlining : off on full : propagated ; - -feature threading : single multi : propagated ; -feature rtti : on off : propagated ; -feature exception-handling : on off : propagated ; -# Whether there is support for asynchronous EH (e.g. catching SEGVs) -feature asynch-exceptions : off on : propagated ; -# Whether all extern "C" functions are considered nothrow by default -feature extern-c-nothrow : off on : propagated ; -feature debug-symbols : on off : propagated ; -feature define : : free ; -feature undef : : free ; -feature "include" : : free path ; #order-sensitive ; -feature cflags : : free ; -feature cxxflags : : free ; -feature fflags : : free ; -feature asmflags : : free ; -feature linkflags : : free ; -feature archiveflags : : free ; -feature version : : free ; - -# Generic, i.e. non-lanugage specific, flags for tools. -feature flags : : free ; - +# Generic, i.e. non-language specific, flags for tools. +feature.feature flags : : free ; feature.feature location-prefix : : free ; -# The following features are incidental, since -# in themself they have no effect on build products. -# Not making them incidental will result in problems in corner -# cases, for example: -# +# The following features are incidental since they have no effect on built +# products. Not making them incidental will result in problems in corner cases, +# e.g.: +# # unit-test a : a.cpp : b ; # lib b : a.cpp b ; -# -# Here, if is not incidental, we'll decide we have two -# targets for a.obj with different properties, and will complain. # -# Note that making feature incidental does not mean it's ignored. It may -# be ignored when creating the virtual target, but the rest of build process -# will use them. -feature use : : free dependency incidental ; -feature dependency : : free dependency incidental ; -feature implicit-dependency : : free dependency incidental ; +# Here, if is not incidental, we'll decide we have two targets for a.obj +# with different properties, and will complain. +# +# Note that making feature incidental does not mean it's ignored. It may be +# ignored when creating the virtual target, but the rest of build process will +# use them. +feature.feature use : : free dependency incidental ; +feature.feature dependency : : free dependency incidental ; +feature.feature implicit-dependency : : free dependency incidental ; -feature warnings : - on # enable default/"reasonable" warning level for the tool - all # enable all possible warnings issued by the tool - off # disable all warnings issued by the tool +feature.feature warnings : + on # Enable default/"reasonable" warning level for the tool. + all # Enable all possible warnings issued by the tool. + off # Disable all warnings issued by the tool. : incidental propagated ; -feature warnings-as-errors : - off # do not fail the compilation if there are warnings - on # fail the compilation if there are warnings +feature.feature warnings-as-errors : + off # Do not fail the compilation if there are warnings. + on # Fail the compilation if there are warnings. : incidental propagated ; -feature source : : free dependency incidental ; -feature library : : free dependency incidental ; -feature file : : free dependency incidental ; -feature find-shared-library : : free ; #order-sensitive ; -feature find-static-library : : free ; #order-sensitive ; -feature library-path : : free path ; #order-sensitive ; +feature.feature source : : free dependency incidental ; +feature.feature library : : free dependency incidental ; +feature.feature file : : free dependency incidental ; +feature.feature find-shared-library : : free ; #order-sensitive ; +feature.feature find-static-library : : free ; #order-sensitive ; +feature.feature library-path : : free path ; #order-sensitive ; + # Internal feature. -feature library-file : : free dependency ; +feature.feature library-file : : free dependency ; -feature name : : free ; -feature tag : : free ; -feature search : : free path ; #order-sensitive ; -feature location : : free path ; - -feature dll-path : : free path ; -feature hardcode-dll-paths : true false : incidental ; +feature.feature name : : free ; +feature.feature tag : : free ; +feature.feature search : : free path ; #order-sensitive ; +feature.feature location : : free path ; +feature.feature dll-path : : free path ; +feature.feature hardcode-dll-paths : true false : incidental ; -# An internal feature that holds the paths of all dependency -# dynamic libraries. On Windows, it's needed so that we can all -# those paths to PATH when running applications. -# On Linux, it's needed to add proper -rpath-link command line options. -feature xdll-path : : free path ; +# An internal feature that holds the paths of all dependency shared libraries. +# On Windows, it's needed so that we can add all those paths to PATH when +# running applications. On Linux, it's needed to add proper -rpath-link command +# line options. +feature.feature xdll-path : : free path ; -#provides means to specify def-file for windows dlls. -feature def-file : : free dependency ; +# Provides means to specify def-file for windows DLLs. +feature.feature def-file : : free dependency ; -feature.feature suppress-import-lib : false true : incidental ; +feature.feature suppress-import-lib : false true : incidental ; -# This is internal feature which is used to store the name of -# bjam action to call when building a target. +# Internal feature used to store the name of a bjam action to call when building +# a target. feature.feature action : : free ; -# This feature is used to allow specific generators to run. -# For example, QT tools can only be invoked when QT library -# is used. In that case, qt will be in usage requirement -# of the library. -feature allow : : free ; +# This feature is used to allow specific generators to run. For example, QT +# tools can only be invoked when QT library is used. In that case, qt +# will be in usage requirement of the library. +feature.feature allow : : free ; -# The addressing model to generate code for. -# Currently a limited set only specifying the bit size of pointers. -feature address-model : 16 32 64 - : propagated optional ; +# The addressing model to generate code for. Currently a limited set only +# specifying the bit size of pointers. +feature.feature address-model : 16 32 64 : propagated optional ; # Type of CPU architecture to compile for. -feature architecture : +feature.feature architecture : # x86 and x86-64 x86 + # ia64 ia64 + # Sparc sparc + # RS/6000 & PowerPC power + # MIPS/SGI mips1 mips2 mips3 mips4 mips32 mips32r2 mips64 + # HP/PA-RISC parisc - # Combined architectures for platforms/toolsets that support - # building for multiple architectures at once. "combined" - # would be the default multi-arch for the toolset. - combined - combined-x86-power - # + + # Combined architectures for platforms/toolsets that support building for + # multiple architectures at once. "combined" would be the default multi-arch + # for the toolset. + combined + combined-x86-power + : propagated optional ; # The specific instruction set in an architecture to compile. -feature instruction-set : +feature.feature instruction-set : # x86 and x86-64 - i386 i486 i586 i686 - pentium pentium-mmx pentiumpro pentium2 pentium3 pentium3m pentium-m pentium4 pentium4m - prescott nocona - conroe conroe-xe conroe-l allendale mermon mermon-xe kentsfield kentsfield-xe - penryn wolfdale yorksfield nehalem - k6 k6-2 k6-3 athlon athlon-tbird athlon-4 athlon-xp athlon-mp - k8 opteron athlon64 athlon-fx - winchip-c6 winchip2 - c3 c3-2 + i386 i486 i586 i686 pentium pentium-mmx pentiumpro pentium2 pentium3 + pentium3m pentium-m pentium4 pentium4m prescott nocona conroe conroe-xe + conroe-l allendale mermon mermon-xe kentsfield kentsfield-xe penryn wolfdale + yorksfield nehalem k6 k6-2 k6-3 athlon athlon-tbird athlon-4 athlon-xp + athlon-mp k8 opteron athlon64 athlon-fx winchip-c6 winchip2 c3 c3-2 + # ia64 itanium itanium1 merced itanium2 mckinley + # Sparc - v7 cypress v8 supersparc sparclite hypersparc sparclite86x - f930 f934 sparclet tsc701 v9 ultrasparc ultrasparc3 + v7 cypress v8 supersparc sparclite hypersparc sparclite86x f930 f934 + sparclet tsc701 v9 ultrasparc ultrasparc3 + # RS/6000 & PowerPC - 401 403 405 405fp 440 440fp 505 - 601 602 603 603e 604 604e 620 630 740 7400 7450 750 - 801 821 823 860 970 8540 - power-common ec603e g3 g4 g5 - power power2 power3 power4 power5 powerpc powerpc64 - rios rios1 rsc rios2 rs64a + 401 403 405 405fp 440 440fp 505 601 602 603 603e 604 604e 620 630 740 7400 + 7450 750 801 821 823 860 970 8540 power-common ec603e g3 g4 g5 power power2 + power3 power4 power5 powerpc powerpc64 rios rios1 rsc rios2 rs64a + # MIPS - 4kc 4kp 5kc 20kc m4k - r2000 r3000 r3900 r4000 r4100 r4300 r4400 r4600 r4650 r6000 r8000 - rm7000 rm9000 orion sb1 - vr4100 vr4111 vr4120 vr4130 vr4300 vr5000 vr5400 vr5500 + 4kc 4kp 5kc 20kc m4k r2000 r3000 r3900 r4000 r4100 r4300 r4400 r4600 r4650 + r6000 r8000 rm7000 rm9000 orion sb1 vr4100 vr4111 vr4120 vr4130 vr4300 + vr5000 vr5400 vr5500 + # HP/PA-RISC 700 7100 7100lc 7200 7300 8000 - # + : propagated optional ; - - -# Used to select specific variant of C++ ABI is the compiler -# supports several. -feature c++abi : : propagated optional ; - - -feature conditional : : incidental free ; + +# Used to select a specific variant of C++ ABI if the compiler supports several. +feature.feature c++abi : : propagated optional ; + +feature.feature conditional : : incidental free ; # The value of 'no' prevents building of a target. -feature build : yes no : optional ; +feature.feature build : yes no : optional ; # Windows-specific features -feature user-interface : console gui wince native auto ; +feature.feature user-interface : console gui wince native auto ; + +feature.feature variant : : implicit composite propagated symmetric ; -feature variant : : implicit composite propagated symmetric ; # Declares a new variant. -# First determines explicit properties for this variant, by -# refining parents' explicit properties with the passed explicit -# properties. The result is remembered and will be used if -# this variant is used as parent. # -# Second, determines the full property set for this variant by -# adding to the explicit properties default values for all properties -# which neither present nor are symmetric. +# First determines explicit properties for this variant, by refining parents' +# explicit properties with the passed explicit properties. The result is +# remembered and will be used if this variant is used as parent. # -# Lastly, makes appropriate value of 'variant' property expand -# to the full property set. -rule variant ( name # Name of the variant - : parents-or-properties * # Specifies parent variants, if - # 'explicit-properties' are given, - # and explicit-properties otherwise. - : explicit-properties * # Explicit properties. +# Second, determines the full property set for this variant by adding to the +# explicit properties default values for all missing non-symmetric properties. +# +# Lastly, makes appropriate value of 'variant' property expand to the full +# property set. +rule variant ( name # Name of the variant + : parents-or-properties * # Specifies parent variants, if + # 'explicit-properties' are given, and + # explicit-properties or parents otherwise. + : explicit-properties * # Explicit properties. ) { local parents ; @@ -302,97 +295,102 @@ rule variant ( name # Name of the variant parents = $(parents-or-properties) ; } - # The problem is that we have to check for conflicts - # between base variants. + # The problem is that we have to check for conflicts between base variants. if $(parents[2]) { - error "multiple base variants are not yet supported" ; + errors.error "multiple base variants are not yet supported" ; } - + local inherited ; - # Add explicitly specified properties for parents + # Add explicitly specified properties for parents. for local p in $(parents) { - # TODO: the check may be sticter + # TODO: This check may be made stricter. if ! [ feature.is-implicit-value $(p) ] { - error "Invalid base varaint" $(p) ; + errors.error "Invalid base variant" $(p) ; } - + inherited += $(.explicit-properties.$(p)) ; } property.validate $(explicit-properties) ; - explicit-properties = [ property.refine $(inherited) : $(explicit-properties) ] ; - - # Record explicitly specified properties for this variant - # We do this after inheriting parents' properties, so that - # they affect other variants, derived from this one. + explicit-properties = [ property.refine $(inherited) + : $(explicit-properties) ] ; + + # Record explicitly specified properties for this variant. We do this after + # inheriting parents' properties so they affect other variants derived from + # this one. .explicit-properties.$(name) = $(explicit-properties) ; - + feature.extend variant : $(name) ; - feature.compose $(name) : $(explicit-properties) ; + feature.compose $(name) : $(explicit-properties) ; } IMPORT $(__name__) : variant : : variant ; -variant debug : off on off on ; -variant release : speed off full + +variant debug : off on off + on ; +variant release : speed off full off NDEBUG ; variant profile : release : on on ; + class searched-lib-target : abstract-file-target { - rule __init__ ( name - : project - : shared ? + rule __init__ ( name + : project + : shared ? : search * : action ) { - abstract-file-target.__init__ $(name) : SEARCHED_LIB : $(project) + abstract-file-target.__init__ $(name) : SEARCHED_LIB : $(project) : $(action) : ; - + self.shared = $(shared) ; self.search = $(search) ; } - + rule shared ( ) { return $(self.shared) ; } - + rule search ( ) { return $(self.search) ; } - + rule actualize-location ( target ) { NOTFILE $(target) ; - } - + } + rule path ( ) { } -} +} + -import types/register ; import stage ; -class c-scanner : scanner +class c-scanner : scanner { - import regex virtual-target path scanner ; - + import path ; + import regex ; + import scanner ; + import virtual-target ; + rule __init__ ( includes * ) { scanner.__init__ ; - + for local i in $(includes) - { + { self.includes += [ path.native $(i:G=) ] ; } - - } + } rule pattern ( ) { @@ -401,72 +399,70 @@ class c-scanner : scanner rule process ( target : matches * : binding ) { - local angle = [ regex.transform $(matches) : "<(.*)>" ] ; + local angle = [ regex.transform $(matches) : "<(.*)>" ] ; local quoted = [ regex.transform $(matches) : "\"(.*)\"" ] ; # CONSIDER: the new scoping rule seem to defeat "on target" variables. - local g = [ on $(target) return $(HDRGRIST) ] ; + local g = [ on $(target) return $(HDRGRIST) ] ; local b = [ NORMALIZE_PATH $(binding:D) ] ; - # Attach binding of including file to included targets. - # When target is directly created from virtual target - # this extra information is unnecessary. But in other - # cases, it allows to distinguish between two headers of the - # same name included from different places. - # We don't need this extra information for angle includes, - # since they should not depend on including file (we can't - # get literal "." in include path). + # Attach binding of including file to included targets. When a target is + # directly created from virtual target this extra information is + # unnecessary. But in other cases, it allows us to distinguish between + # two headers of the same name included from different places. We don't + # need this extra information for angle includes, since they should not + # depend on including file (we can't get literal "." in include path). local g2 = $(g)"#"$(b) ; - + angle = $(angle:G=$(g)) ; quoted = $(quoted:G=$(g2)) ; - + local all = $(angle) $(quoted) ; INCLUDES $(target) : $(all) ; NOCARE $(all) ; SEARCH on $(angle) = $(self.includes:G=) ; SEARCH on $(quoted) = $(b) $(self.includes:G=) ; - - # Just propagate current scanner to includes, in a hope - # that includes do not change scanners. + + # Just propagate the current scanner to includes in hope that includes + # do not change scanners. scanner.propagate $(__name__) : $(angle) $(quoted) : $(target) ; - + ISFILE $(angle) $(quoted) ; - } + } } + +type.register H : h ; +type.register HPP : hpp : H ; +type.register C : c ; + scanner.register c-scanner : include ; type.set-scanner CPP : c-scanner ; +type.set-scanner C : c-scanner ; -type.register H : h ; -type.register HPP : hpp : H ; -type.register C : c ; - -type.set-scanner C : c-scanner ; - -# The generator class for libraries (target type LIB). Depending on properties it will -# request building of the approapriate specific type -- SHARED_LIB, STATIC_LIB or -# SHARED_LIB. +# The generator class for libraries (target type LIB). Depending on properties +# it will request building of the appropriate specific library type -- +# -- SHARED_LIB, STATIC_LIB or SHARED_LIB. class lib-generator : generator { rule __init__ ( * : * ) { generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; } - + rule run ( project name ? : property-set : sources * ) { - # The lib generator is composing, and can be only invoked with + # The lib generator is composing, and can be only invoked with an # explicit name. This check is present in generator.run (and so in - # builtin.linking-generator), but duplicate it here to avoid doing - # extra work. + # builtin.linking-generator) but duplicated here to avoid doing extra + # work. if $(name) - { + { local properties = [ $(property-set).raw ] ; - # Determine the needed target type + # Determine the needed target type. local actual-type ; # files can be generated by @rule feature # in which case we don't consider it a SEARCHED_LIB type. @@ -477,129 +473,129 @@ class lib-generator : generator } else if in $(properties:G) { - # The generator for actual-type = LIB ; - } + } else if shared in $(properties) { actual-type = SHARED_LIB ; } - else + else { actual-type = STATIC_LIB ; } property-set = [ $(property-set).add-raw LIB ] ; # Construct the target. - return [ generators.construct $(project) $(name) : $(actual-type) - : $(property-set) : $(sources) ] ; - } - } - + return [ generators.construct $(project) $(name) : $(actual-type) + : $(property-set) : $(sources) ] ; + } + } + rule viable-source-types ( ) { return * ; - } + } } + generators.register [ new lib-generator builtin.lib-generator : : LIB ] ; + # The implementation of the 'lib' rule. Beyond standard syntax that rule allows -# simplified: -# lib a b c ; -# so we need to write code to handle that syntax. -rule lib ( names + : sources * : requirements * : default-build * +# simplified: "lib a b c ;". +rule lib ( names + : sources * : requirements * : default-build * : usage-requirements * ) { - local result ; - local project = [ project.current ] ; - - # This is a circular module dependency, so it must be imported here - import targets ; - if $(names[2]) { if in $(requirements:G) { errors.user-error "When several names are given to the 'lib' rule" : - "it's not allowed to specify the feature. " ; - } + "it's not allowed to specify the feature." ; + } if $(sources) { errors.user-error "When several names are given to the 'lib' rule" : - "it's not allowed to specify sources. " ; - } + "it's not allowed to specify sources." ; + } } - + + # This is a circular module dependency so it must be imported here. + import targets ; + + local project = [ project.current ] ; + local result ; + for local name in $(names) - { + { local r = $(requirements) ; - # Support " lib a ; " and " lib a b c ; " syntaxes. + # Support " lib a ; " and " lib a b c ; " syntax. if ! $(sources) && ! in $(requirements:G) && ! in $(requirements:G) { r += $(name) ; - } + } result += [ targets.main-target-alternative - [ new typed-target $(name) : $(project) : LIB - : [ targets.main-target-sources $(sources) : $(name) ] - : [ targets.main-target-requirements $(r) : $(project) ] - : [ targets.main-target-default-build $(default-build) : $(project) ] - : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] - ] ] ; - } + [ new typed-target $(name) : $(project) : LIB + : [ targets.main-target-sources $(sources) : $(name) ] + : [ targets.main-target-requirements $(r) : $(project) ] + : [ targets.main-target-default-build $(default-build) : $(project) ] + : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] + ] ] ; + } return $(result) ; } IMPORT $(__name__) : lib : : lib ; + class searched-lib-generator : generator { import property-set ; - + rule __init__ ( ) { - # The requirements cause the generators to be tried *only* when we're building - # lib target and there's 'search' feature. This seems ugly --- all we want - # is make sure searched-lib-generator is not invoced deep in transformation - # search. + # The requirements cause the generators to be tried *only* when we're + # building a lib target with a 'search' feature. This seems ugly --- all + # we want is to make sure searched-lib-generator is not invoked deep + # inside transformation search to produce intermediate targets. generator.__init__ searched-lib-generator : : SEARCHED_LIB ; } - + rule run ( project name ? : property-set : sources * ) { if $(name) { - # If name is empty, it means we're called not from top-level. - # In this case, we just fail immediately, because searched-lib-generator - # cannot be used to produce intermediate targets. - - local properties = [ $(property-set).raw ] ; + # If 'name' is empty, it means we have not been called to build a + # top-level target. In this case, we just fail immediately, because + # searched-lib-generator cannot be used to produce intermediate + # targets. + + local properties = [ $(property-set).raw ] ; local shared ; if shared in $(properties) { shared = true ; - } - + } + local search = [ feature.get-values : $(properties) ] ; - a = [ new null-action $(property-set) ] ; + local a = [ new null-action $(property-set) ] ; local lib-name = [ feature.get-values : $(properties) ] ; lib-name ?= $(name) ; - local t = [ new searched-lib-target $(lib-name) : $(project) : $(shared) - : $(search) - : $(a) - ] ; + local t = [ new searched-lib-target $(lib-name) : $(project) + : $(shared) : $(search) : $(a) ] ; # We return sources for a simple reason. If there's - # lib png : z : png ; - # the 'z' target should be returned, so that apps linking to - # 'png' will link to 'z', too. + # lib png : z : png ; + # the 'z' target should be returned, so that apps linking to 'png' + # will link to 'z', too. return [ property-set.create $(search) ] [ virtual-target.register $(t) ] $(sources) ; } - } + } } generators.register [ new searched-lib-generator ] ; + class prebuilt-lib-generator : generator { rule __init__ ( * : * ) @@ -611,94 +607,95 @@ class prebuilt-lib-generator : generator { local f = [ $(property-set).get ] ; return $(f) $(sources) ; - } + } } -generators.register +generators.register [ new prebuilt-lib-generator builtin.prebuilt : : LIB : ] ; generators.override builtin.prebuilt : builtin.lib-generator ; - -class compile-action : action + +class compile-action : action { import sequence ; - + rule __init__ ( targets * : sources * : action-name : properties * ) { action.__init__ $(targets) : $(sources) : $(action-name) : $(properties) ; } - - - # For all virtual targets for the same dependency graph as self, - # i.e. which belong to the same main target, add their directories - # to include path. + + # For all virtual targets for the same dependency graph as self, i.e. which + # belong to the same main target, add their directories to the include path. rule adjust-properties ( property-set ) - { + { local s = [ $(self.targets[1]).creating-subvariant ] ; - return [ $(property-set).add-raw + return [ $(property-set).add-raw [ $(s).implicit-includes "include" : H ] ] ; - } + } } -# Declare a special compiler generator. -# The only thing it does is changing the type used to represent -# 'action' in the constructed dependency graph to 'compile-action'. -# That class in turn adds additional include paths to handle a case -# when a source file includes headers which are generated themselfs. + +# Declare a special compiler generator. The only thing it does is changing the +# type used to represent 'action' in the constructed dependency graph to +# 'compile-action'. That class in turn adds additional include paths to handle +# cases when a source file includes headers which are generated themselves. class C-compiling-generator : generator { - rule __init__ ( id : source-types + : target-types + : - requirements * : optional-properties * ) + rule __init__ ( id : source-types + : target-types + : requirements * + : optional-properties * ) { generator.__init__ $(id) : $(source-types) : $(target-types) : - $(requirements) : $(optional-properties) ; + $(requirements) : $(optional-properties) ; } - + rule action-class ( ) { return compile-action ; } } -rule register-c-compiler ( id : source-types + : target-types + : - requirements * : optional-properties * ) + +rule register-c-compiler ( id : source-types + : target-types + : requirements * + : optional-properties * ) { - local g = [ new C-compiling-generator $(id) : $(source-types) - : $(target-types) : $(requirements) : $(optional-properties) ] ; - generators.register $(g) ; + generators.register [ new C-compiling-generator $(id) : $(source-types) + : $(target-types) : $(requirements) : $(optional-properties) ] ; } -# FIXME: this is ugly, should find a better way (we'd want client code to -# register all generators as "generator.some-rule", not with "some-module.some-rule".) +# FIXME: this is ugly, should find a better way (we'd like client code to +# register all generators as "generators.some-rule" instead of +# "some-module.some-rule".) IMPORT $(__name__) : register-c-compiler : : generators.register-c-compiler ; + # The generator class for handling EXE and SHARED_LIB creation. class linking-generator : generator { - import property-set ; - import type ; import path ; import project ; - - rule __init__ ( id - composing ? : # Specify if generator is composing. The generator will be - # composing if non-empty string is passed, or parameter is - # not given. To make generator non-composing, pass empty - # string ("") - source-types + : target-types + : + import property-set ; + import type ; + + rule __init__ ( id + composing ? : # The generator will be composing if a non-empty + # string is passed or the parameter is not given. To + # make the generator non-composing, pass an empty + # string (""). + source-types + : + target-types + : requirements * ) { composing ?= true ; - generator.__init__ $(id) $(composing) : $(source-types) : $(target-types) : - $(requirements) ; + generator.__init__ $(id) $(composing) : $(source-types) + : $(target-types) : $(requirements) ; } - + rule run ( project name ? : property-set : sources + ) - { - sources += [ $(property-set).get ] ; - - # Add properties for all searched libraries + { + sources += [ $(property-set).get ] ; + + # Add properties for all searched libraries. local extra ; for local s in $(sources) { @@ -708,62 +705,60 @@ class linking-generator : generator extra += $(search) ; } } - - # It's possible that sources include shared libraries that - # did not came from 'lib' targets. For example, .so files - # specified as sources. - # In this case we have - # - add extra dll-path properties - # - propagate extra xdll-path properties so that application - # linking to use will get xdll-path to those libraries. + + # It's possible that sources include shared libraries that did not came + # from 'lib' targets, e.g. .so files specified as sources. In this case + # we have to add extra dll-path properties and propagate extra xdll-path + # properties so that application linking to use will get xdll-path to + # those libraries. local extra-xdll-paths ; for local s in $(sources) { - if [ type.is-derived [ $(s).type ] SHARED_LIB ] && ! [ $(s).action ] + if [ type.is-derived [ $(s).type ] SHARED_LIB ] && ! [ $(s).action ] { - # Unfortunately, we don't have a good way to find the path - # to a file, so use this nasty approach. + # Unfortunately, we don't have a good way to find the path to a + # file, so use this nasty approach. local p = [ $(s).project ] ; local location = [ path.root [ $(s).name ] - [ $(p).get source-location ] ] ; + [ $(p).get source-location ] ] ; extra-xdll-paths += [ path.parent $(location) ] ; - } + } } - - # Hardcode dll paths only when linking executables. + + # Hardcode DLL paths only when linking executables. # Pros: don't need to relink libraries when installing. - # Cons: "standalone" libraries (plugins, python extensions) - # can't hardcode paths to dependent libraries. + # Cons: "standalone" libraries (plugins, python extensions) can't + # hardcode paths to dependent libraries. if [ $(property-set).get ] = true - && [ type.is-derived $(self.target-types[1]) EXE ] + && [ type.is-derived $(self.target-types[1]) EXE ] { local xdll-path = [ $(property-set).get ] ; extra += $(xdll-path) $(extra-xdll-paths) ; } - + if $(extra) { property-set = [ $(property-set).add-raw $(extra) ] ; - } - + } + local result = [ generator.run $(project) $(name) : $(property-set) - : $(sources) ] ; - + : $(sources) ] ; + local ur ; if $(result) - { - ur = [ extra-usage-requirements $(result) : $(property-set) ] ; - ur = [ $(ur).add - [ property-set.create $(extra-xdll-paths) ] ] ; - } + { + ur = [ extra-usage-requirements $(result) : $(property-set) ] ; + ur = [ $(ur).add + [ property-set.create $(extra-xdll-paths) ] ] ; + } return $(ur) $(result) ; } - + rule extra-usage-requirements ( created-targets * : property-set ) - { - local result = [ property-set.empty ] ; + { + local result = [ property-set.empty ] ; local extra ; - + # Add appropricate usage requirements. local raw = [ $(property-set).raw ] ; if shared in $(raw) @@ -772,41 +767,40 @@ class linking-generator : generator local pwd = [ path.pwd ] ; for local t in $(created-targets) { - if [ type.is-derived [ $(t).type ] SHARED_LIB ] + if [ type.is-derived [ $(t).type ] SHARED_LIB ] { paths += [ path.root [ path.make [ $(t).path ] ] $(pwd) ] ; - } - } + } + } extra += $(paths:G=) ; } - + # We need to pass features that we've got from sources, - # because if shared library is built, exe which uses it must know paths - # to other shared libraries this one depends on, to be able to find them - # all at runtime. - - # Just pass all features in property-set, it's theorically possible - # that we'll propagate features explicitly specified by - # the user, but then the user's to blaim for using internal feature. + # because if a shared library is built, exe using it needs to know paths + # to other shared libraries this one depends on in order to be able to + # find them all at runtime. + + # Just pass all features in property-set, it's theorically possible that + # we'll propagate features explicitly specified by the user, + # but then the user's to blaim for using an internal feature. local values = [ $(property-set).get ] ; extra += $(values:G=) ; - + if $(extra) { result = [ property-set.create $(extra) ] ; } return $(result) ; } - + rule generated-targets ( sources + : property-set : project name ? ) { - local sources2 ; # sources to pass to inherited rule - local properties2 ; # properties to pass to inherited rule - local libraries ; # sources which are libraries - - # Searched libraries are not passed as argument to linker - # but via some option. So, we pass them to the action - # via property. + local sources2 ; # Sources to pass to inherited rule. + local properties2 ; # Properties to pass to inherited rule. + local libraries ; # Library sources. + + # Searched libraries are not passed as arguments to the linker but via + # some option. So, we pass them to the action using a property. properties2 = [ $(property-set).raw ] ; local fsa ; local fst ; @@ -815,75 +809,73 @@ class linking-generator : generator if [ type.is-derived [ $(s).type ] SEARCHED_LIB ] { local name = [ $(s).name ] ; - if [ $(s).shared ] - { - fsa += $(name) ; + if [ $(s).shared ] + { + fsa += $(name) ; } else { fst += $(name) ; - } + } } else { sources2 += $(s) ; } } - properties2 += $(fsa:J=&&) + properties2 += $(fsa:J=&&) $(fst:J=&&) ; - - local spawn = [ generator.generated-targets $(sources2) - : [ property-set.create $(properties2) ] : $(project) $(name) ] ; - - return $(spawn) ; - } -} -rule register-linker ( id composing ? : source-types + : target-types + : - requirements * ) -{ - local g = [ new linking-generator $(id) $(composing) : $(source-types) - : $(target-types) : $(requirements) ] ; - generators.register $(g) ; + return [ generator.generated-targets $(sources2) + : [ property-set.create $(properties2) ] : $(project) $(name) ] ; + } } + +rule register-linker ( id composing ? : source-types + : target-types + + : requirements * ) +{ + generators.register [ new linking-generator $(id) $(composing) + : $(source-types) : $(target-types) : $(requirements) ] ; +} + + # The generator class for handling STATIC_LIB creation. class archive-generator : generator { - import property-set ; + import property-set ; - rule __init__ ( id composing ? : source-types + : target-types + : - requirements * ) + rule __init__ ( id composing ? : source-types + : target-types + + : requirements * ) { composing ?= true ; - generator.__init__ $(id) $(composing) : $(source-types) : $(target-types) : - $(requirements) ; + generator.__init__ $(id) $(composing) : $(source-types) + : $(target-types) : $(requirements) ; } - + rule run ( project name ? : property-set : sources + ) - { - sources += [ $(property-set).get ] ; - + { + sources += [ $(property-set).get ] ; + local result = [ generator.run $(project) $(name) : $(property-set) - : $(sources) ] ; - - # For static linking, if we get a library in source, we can't - # directly link to it. So, we need to cause our dependencies - # to link to that library. There are two approaches: + : $(sources) ] ; + + # For static linking, if we get a library in source, we can't directly + # link to it so we need to cause our dependencies to link to that + # library. There are two approaches: # - adding the library to the list of returned targets. # - using the usage requirements. # The problem with the first is: - # + # # lib a1 : : liba1.a ; # lib a2 : a2.cpp a1 : static ; # install dist : a2 ; # - # here we'll try to install 'a1', even though it's not necessary in - # the general case. - # With the second approaches, even indirect dependents will link to - # the library, but it should not cause any harm. - # So, return all LIB sources together with created targets, - # so that dependents link to them. + # here we'll try to install 'a1', even though it's not necessary in the + # general case. With the second approach, even indirect dependants will + # link to the library, but it should not cause any harm. So, return all + # LIB sources together with created targets, so that dependants link to + # them. local usage-requirements ; if [ $(property-set).get ] = static { @@ -892,41 +884,36 @@ class archive-generator : generator if [ type.is-derived [ $(t).type ] LIB ] { usage-requirements += $(t) ; - } - } + } + } } - + usage-requirements = [ property-set.create $(usage-requirements) ] ; - + return $(usage-requirements) $(result) ; - } + } } -rule register-archiver ( id composing ? : source-types + : target-types + : - requirements * ) + +rule register-archiver ( id composing ? : source-types + : target-types + + : requirements * ) { - local g = [ new archive-generator $(id) $(composing) : $(source-types) - : $(target-types) : $(requirements) ] ; - generators.register $(g) ; + generators.register [ new archive-generator $(id) $(composing) + : $(source-types) : $(target-types) : $(requirements) ] ; } -# Generators that accepts everything, and produces nothing. -# Usefull as general fallback for toolset-specific actions, like -# PCH generation. + +# Generator that accepts everything and produces nothing. Useful as a general +# fallback for toolset-specific actions like PCH generation. class dummy-generator : generator { import property-set ; - + rule run ( project name ? : property-set : sources + ) { return [ property-set.empty ] ; } } - - -IMPORT $(__name__) : register-linker register-archiver - : : generators.register-linker generators.register-archiver ; - - - +IMPORT $(__name__) : register-linker register-archiver + : : generators.register-linker generators.register-archiver ; diff --git a/src/tools/cast.jam b/src/tools/cast.jam index 086d2f93c..407980686 100644 --- a/src/tools/cast.jam +++ b/src/tools/cast.jam @@ -10,7 +10,7 @@ # This is done with: # # exe main : main.cpp [ cast _ moccable-cpp : widget.cpp ] ; -# +# # Boost.Build will assing target type CPP to both main.cpp and widget.cpp. # Then, the cast rule will change target type of widget.cpp to # MOCCABLE-CPP, and Qt support will run MOC tool as part of build process. @@ -22,22 +22,25 @@ # cast, as defining new target type + generator for that type is somewhat # simpler then defining main target rule. -import project type targets ; import "class" : new ; import errors ; +import project ; import property-set ; +import targets ; +import type ; + class cast-target-class : typed-target { import type ; - - rule __init__ ( name : project : type - : sources * : requirements * : default-build * : usage-requirements * ) + + rule __init__ ( name : project : type : sources * : requirements * + : default-build * : usage-requirements * ) { - typed-target.__init__ $(name) : $(project) : $(type) - : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ; + typed-target.__init__ $(name) : $(project) : $(type) : $(sources) + : $(requirements) : $(default-build) : $(usage-requirements) ; } - + rule construct ( name : source-targets * : property-set ) { local result ; @@ -47,43 +50,42 @@ class cast-target-class : typed-target { ECHO "error: source to the 'cast' rule is not a file!" ; EXIT ; - } + } if [ $(s).action ] { ECHO "error: only non-derived target are allowed for 'cast'." ; ECHO "error: when building " [ full-name ] ; EXIT ; - } + } local r = [ $(s).clone-with-different-type $(self.type) ] ; result += [ virtual-target.register $(r) ] ; } - return [ property-set.empty ] $(result) ; - } - + } } -rule cast ( name type : sources * : requirements * : default-build * + +rule cast ( name type : sources * : requirements * : default-build * : usage-requirements * ) { local project = [ project.current ] ; - + local real-type = [ type.type-from-rule-name $(type) ] ; if ! $(real-type) { - errors.user-error "No type corresponds to main target rule nam '$(type)'" - : "Hint: try lowercase name" ; + errors.user-error "No type corresponds to main target rule name '$(type)'" + : "Hint: try lowercase name" ; } - - - # This is a circular module dependency, so it must be imported here + + # This is a circular module dependency so it must be imported here. import targets ; targets.main-target-alternative - [ new cast-target-class $(name) : $(project) : $(real-type) - : [ targets.main-target-sources $(sources) : $(name) ] - : [ targets.main-target-requirements $(requirements) : $(project) ] - : [ targets.main-target-default-build $(default-build) : $(project) ] - : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] - ] ; + [ new cast-target-class $(name) : $(project) : $(real-type) + : [ targets.main-target-sources $(sources) : $(name) ] + : [ targets.main-target-requirements $(requirements) : $(project) ] + : [ targets.main-target-default-build $(default-build) : $(project) ] + : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] + ] ; } + IMPORT $(__name__) : cast : : cast ; diff --git a/src/tools/common.jam b/src/tools/common.jam index bd063954b..9ef8b22f9 100644 --- a/src/tools/common.jam +++ b/src/tools/common.jam @@ -1,9 +1,9 @@ -# Copyright 2003, 2005 Dave Abrahams -# Copyright 2005, 2006 Rene Rivera -# Copyright 2005 Toon Knapen -# 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) +# Copyright 2003, 2005 Dave Abrahams +# Copyright 2005, 2006 Rene Rivera +# Copyright 2005 Toon Knapen +# 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) # Provides actions common to all toolsets, for as making directoies and # removing files. @@ -31,41 +31,43 @@ if [ MATCH (--show-configuration) : [ modules.peek : ARGV ] ] # Configurations # -# The following class helps to manage toolset configurations. Each configuration -# has unique ID and one or more parameters. A typical example of unique ID is -# a condition generated by 'common.check-init-parameters' rule. Other kinds of -# ID can be used. Parameters may include any details about the configuration like -# 'command', 'path', etc. +# The following class helps to manage toolset configurations. Each configuration +# has a unique ID and one or more parameters. A typical example of a unique ID +# is a condition generated by 'common.check-init-parameters' rule. Other kinds +# of IDs can be used. Parameters may include any details about the configuration +# like 'command', 'path', etc. # -# A configuration may be in one of two states: -# -# - registered - a toolset configuration is registered (by autodetection code -# for instance) but is not used. I.e. 'toolset.using' wasn't yet been called -# for this configuration. -# - used - once called 'toolset.using' marks the configuration as 'used'. +# A toolset configuration may be in one of the following states: # -# The main difference between the states is that while a configuration is -# 'registered' its options can be freely changed. This is useful in particular -# for autodetection code - all detected configurations may be safely overwritten -# by a user. +# - registered +# Configuration has been registered (e.g. by autodetection code) but has +# not yet been marked as used, i.e. 'toolset.using' rule has not yet been +# called for it. +# - used +# Once called 'toolset.using' rule marks the configuration as 'used'. +# +# The main difference between the states above is that while a configuration is +# 'registered' its options can be freely changed. This is useful in particular +# for autodetection code - all detected configurations may be safely overwritten +# by user code. class configurations { - import errors : error ; + import errors ; rule __init__ ( ) { } - - # Registers a configuration. + + # Registers a configuration. # - # Returns 'true' if the configuration has been added and an empty value if + # Returns 'true' if the configuration has been added and an empty value if # it already exists. Reports an error if the configuration is 'used'. rule register ( id ) { - if $(id) in $(self.used) + if $(id) in $(self.used) { - error "common: the configuration '$(id)' is in use" ; + errors.error "common: the configuration '$(id)' is in use" ; } local retval ; @@ -74,28 +76,28 @@ class configurations { self.all += $(id) ; - # indicate that a new configuration has been added + # Indicate that a new configuration has been added. retval = true ; } return $(retval) ; } - # Mark a configuration as 'used'. + # Mark a configuration as 'used'. # - # Returns 'true' if the state of the configuration has been changed to + # Returns 'true' if the state of the configuration has been changed to # 'used' and an empty value if it the state wasn't changed. Reports an error # if the configuration isn't known. rule use ( id ) { if ! $(id) in $(self.all) { - error "common: the configuration '$(id)' is not known" ; + errors.error "common: the configuration '$(id)' is not known" ; } local retval ; - if ! $(id) in $(self.used) + if ! $(id) in $(self.used) { self.used += $(id) ; @@ -117,31 +119,30 @@ class configurations { return $(self.used) ; } - + # Returns the value of a configuration parameter. rule get ( id : param ) { - return $(self.$(param).$(id)) ; + return $(self.$(param).$(id)) ; } # Sets the value of a configuration parameter. rule set ( id : param : value * ) { - self.$(param).$(id) = $(value) ; + self.$(param).$(id) = $(value) ; } } -# The rule checks toolset parameters. Each trailing parameter -# should be a pair of parameter name and parameter value. -# The rule will check that each parameter either has value in -# each invocation, or has no value in each invocation. Also, -# the rule will check that the combination of all parameter values is -# unique in all invocations. +# The rule for checking toolset parameters. Trailing parameters should all be +# parameter name/value pairs. The rule will check that each parameter either has +# a value in each invocation or has no value in each invocation. Also, the rule +# will check that the combination of all parameter values is unique in all +# invocations. # -# Each parameter name corresponds to subfeature. This rule will declare subfeature -# the first time non-empty parameter value is passed, and will extend it with -# all the values. +# Each parameter name corresponds to a subfeature. This rule will declare +# a subfeature the first time a non-empty parameter value is passed and will +# extend it with all the values. # # The return value from this rule is a condition to be used for flags settings. rule check-init-parameters ( toolset : * ) @@ -152,8 +153,8 @@ rule check-init-parameters ( toolset : * ) { local name = $($(index)[1]) ; local value = $($(index)[2]) ; - - if $(value)-is-specified + + if $(value)-is-not-empty { condition = $(condition)-$(value) ; if $(.had-unspecified-value.$(toolset).$(name)) @@ -163,37 +164,36 @@ rule check-init-parameters ( toolset : * ) "no value was specified in earlier initialization" : "an explicit value is specified now" ; } - # The below logic is for intel compiler. It calls this rule - # with 'intel-linux' and 'intel-win' as toolset, so we need to - # get the base part of toolset name. - # We can't pass 'intel' as toolset, because it that case it will - # be impossible to register versionles intel-linux and - # intel-win of specific version. + # The below logic is for intel compiler. It calls this rule with + # 'intel-linux' and 'intel-win' as toolset, so we need to get the + # base part of toolset name. We can't pass 'intel' as toolset + # because in that case it will be impossible to register versionless + # intel-linux and intel-win toolsets of a specific version. local t = $(toolset) ; local m = [ MATCH ([^-]*)- : $(toolset) ] ; if $(m) { t = $(m[1]) ; - } - if ! $(.had-value.$(toolset).$(name)) + } + if ! $(.had-value.$(toolset).$(name)) { if ! $(.declared-subfeature.$(t).$(name)) { feature.subfeature toolset $(t) : $(name) : : propagated ; .declared-subfeature.$(t).$(name) = true ; - } + } .had-value.$(toolset).$(name) = true ; } feature.extend-subfeature toolset $(t) : $(name) : $(value) ; } else { - if $(.had-value.$(toolset).$(name)) + if $(.had-value.$(toolset).$(name)) { - errors.user-error + errors.user-error "$(toolset) initialization: parameter '$(name)' inconsistent" : "an explicit value was specified in an earlier initialization" : - "no value is specified now" ; + "no value is specified now" ; } .had-unspecified-value.$(toolset).$(name) = true ; } @@ -201,23 +201,24 @@ rule check-init-parameters ( toolset : * ) } if $(sig) in $(.all-signatures) { - local message = - "duplicate initialization of $(toolset) with the following parameters: " ; + local message = + "duplicate initialization of $(toolset) with the following parameters: " ; for local index in 2 3 4 5 6 7 8 9 { local p = $($(index)) ; if $(p) { message += "$(p[1]) = $(p[2]:E=)" ; - } + } } message += "previous initialization at $(.init-loc.$(sig))" ; - errors.user-error $(message[1]) : $(message[2]) : $(message[3]) : $(message[4]) - : $(message[5]) : $(message[6]) : $(message[7]) : $(message[8]) ; - } + errors.user-error + $(message[1]) : $(message[2]) : $(message[3]) : $(message[4]) : + $(message[5]) : $(message[6]) : $(message[7]) : $(message[8]) ; + } .all-signatures += $(sig) ; .init-loc.$(sig) = [ errors.nearest-user-location ] ; - + if $(.show-configuration) { ECHO notice: $(condition) ; @@ -225,18 +226,16 @@ rule check-init-parameters ( toolset : * ) return $(condition) ; } -# A helper rule to get the command to invoke some tool. -# In 'user-provided-command' is not given, tries to find binary -# named 'tool' in PATH and in the passed 'additional-path'. Otherwise, -# verified that the first element of 'user-provided-command' is an -# existing program. -# + +# A helper rule to get the command to invoke some tool. If +# 'user-provided-command' is not given, tries to find binary named 'tool' in +# PATH and in the passed 'additional-path'. Otherwise, verifies that the first +# element of 'user-provided-command' is an existing program. # # This rule returns the command to be used when invoking the tool. If we can't -# find the tool, a warning is issued. -# If 'path-last' is specified, PATH is checked after 'additional-paths' when -# searching to 'tool'. -rule get-invocation-command-nodefault ( +# find the tool, a warning is issued. If 'path-last' is specified, PATH is +# checked after 'additional-paths' when searching for 'tool'. +rule get-invocation-command-nodefault ( toolset : tool : user-provided-command * : additional-paths * : path-last ? ) { local command ; @@ -251,7 +250,7 @@ rule get-invocation-command-nodefault ( } else { - command = [ common.check-tool $(user-provided-command) ] ; + command = [ common.check-tool $(user-provided-command) ] ; if ! $(command) && $(.debug-configuration) { ECHO "warning: toolset $(toolset) initialization: " ; @@ -263,15 +262,15 @@ rule get-invocation-command-nodefault ( return $(command) ; } -# Same as get-invocation-command-nodefault, except that if no tool -# if found, returns either the user-provided-command, if present, -# or the 'tool' parameter. -rule get-invocation-command ( + +# Same as get-invocation-command-nodefault, except that if no tool is found, +# returns either the user-provided-command, if present, or the 'tool' parameter. +rule get-invocation-command ( toolset : tool : user-provided-command * : additional-paths * : path-last ? ) { local result = [ get-invocation-command-nodefault $(toolset) : $(tool) - : $(user-provided-command) : $(additional-paths) : $(path-last) ] ; - + : $(user-provided-command) : $(additional-paths) : $(path-last) ] ; + if ! $(result) { if $(user-provided-command) @@ -281,14 +280,14 @@ rule get-invocation-command ( else { result = $(tool) ; - } + } } - return $(result) ; + return $(result) ; } - -# Given an invocation command, -# return the absolute path to the command. This works even if commnad -# has not path element and is present in PATH. + + +# Given an invocation command return the absolute path to the command. This +# works even if command has no path element and was found on the PATH. rule get-absolute-tool-path ( command ) { if $(command:D) @@ -299,22 +298,20 @@ rule get-absolute-tool-path ( command ) { local m = [ GLOB [ modules.peek : PATH Path path ] : $(command) $(command).exe ] ; return $(m[1]:D) ; - } + } } - # Attempts to find tool (binary) named 'name' in PATH and in 'additional-paths'. -# If found in PATH, returns 'name'. -# If found in additional paths, returns absolute name. If the tool is found -# in several directories, return all paths. -# Otherwise, returns empty string. -# If 'path-last' is specified, PATH is searched after 'additional-paths'. +# If found in PATH, returns 'name' and if found in additional paths, returns +# absolute name. If the tool is found in several directories, returns all paths. +# Otherwise, returns an empty string. If 'path-last' is specified, PATH is +# searched after 'additional-paths'. rule find-tool ( name : additional-paths * : path-last ? ) { local path = [ path.programs-path ] ; local match = [ path.glob $(path) : $(name) $(name).exe ] ; - local additional-match = [ path.glob $(additional-paths) : $(name) $(name).exe ] ; + local additional-match = [ path.glob $(additional-paths) : $(name) $(name).exe ] ; local result ; if $(path-last) @@ -337,65 +334,65 @@ rule find-tool ( name : additional-paths * : path-last ? ) } } if $(result) - { + { return [ path.native $(result[1]) ] ; - } + } } -# Checks if 'command' can be found either in path -# or is a full name to an existing file. + +# Checks if 'command' can be found either in path or is a full name to an +# existing file. rule check-tool-aux ( command ) { if $(command:D) { if [ path.exists $(command) ] - # Both NT and Cygwin will run .exe files by their unqualified names - || [ os.on-windows ] && [ path.exists $(command).exe ] - # Only NT will run .bat files by their unqualified names + # Both NT and Cygwin will run .exe files by their unqualified names. + || [ os.on-windows ] && [ path.exists $(command).exe ] + # Only NT will run .bat files by their unqualified names. || [ os.name ] = NT && [ path.exists $(command).bat ] { return $(command) ; - } + } } else { if [ GLOB [ modules.peek : PATH Path path ] : $(command) ] { return $(command) ; - } - } + } + } } -# Checks that a tool can be invoked by 'command'. -# If command is not an absolute path, checks if it can be found in 'path'. -# If comand is absolute path, check that it exists. Returns 'command' -# if ok and empty string otherwise. +# Checks that a tool can be invoked by 'command'. If command is not an absolute +# path, checks if it can be found in 'path'. If comand is an absolute path, +# check that it exists. Returns 'command' if ok or empty string otherwise. rule check-tool ( xcommand + ) { - if [ check-tool-aux $(xcommand[1]) ] - || [ check-tool-aux $(xcommand[-1]) ] + if [ check-tool-aux $(xcommand[1]) ] || + [ check-tool-aux $(xcommand[-1]) ] { return $(xcommand) ; } } -# Handle common options for toolset, specifically sets the following -# flag variables: + +# Handle common options for toolset, specifically sets the following flag +# variables: # - CONFIG_COMMAND to 'command' -# - OPTIONS for compile.c to the value of in options -# - OPTIONS for compile.c++ to the value of in options -# - OPTIOns for compile to the value of in options -# - OPTIONs for link to the value of in options +# - OPTIONS for compile.c to the value of in options +# - OPTIONS for compile.c++ to the value of in options +# - OPTIOns for compile to the value of in options +# - OPTIONs for link to the value of in options rule handle-options ( toolset : condition * : command * : options * ) { if $(.debug-configuration) { ECHO "notice: will use '$(command)' for $(toolset), condition $(condition:E=(empty))" ; } - - # The last parameter ('true') says it's OK to set flags for another - # module, + + # The last parameter ('true') says it's OK to set flags for another module. toolset.flags $(toolset) CONFIG_COMMAND $(condition) : $(command) : unchecked ; toolset.flags $(toolset).compile OPTIONS $(condition) : [ feature.get-values : $(options) ] : unchecked ; @@ -406,12 +403,11 @@ rule handle-options ( toolset : condition * : command * : options * ) toolset.flags $(toolset).compile.fortran OPTIONS $(condition) : [ feature.get-values : $(options) ] : unchecked ; toolset.flags $(toolset).link OPTIONS $(condition) : - [ feature.get-values : $(options) ] : unchecked ; + [ feature.get-values : $(options) ] : unchecked ; } -# returns the location of the "program files" directory on a windows -# platform +# Returns the location of the "program files" directory on a windows platform. rule get-program-files-dir ( ) { local ProgramFiles = [ modules.peek : ProgramFiles ] ; @@ -426,12 +422,13 @@ rule get-program-files-dir ( ) return $(ProgramFiles) ; } + if [ os.name ] = NT { RM = del /f /q ; CP = copy ; IGNORE = "2>nul >nul & setlocal" ; - LN ?= $(CP) ; + LN ?= $(CP) ; } else { @@ -440,28 +437,29 @@ else LN = ln ; } -nl = " -" ; -rule rm-command ( ) +rule rm-command ( ) { - return $(RM) ; + return $(RM) ; } + rule copy-command ( ) { return $(CP) ; } -# Returns the command needed to set the environment variable on the -# current platform. The variable setting persists through all -# following commands and is visible in the environment seen by -# subsequently executed commands. In other words, on Unix systems, -# the variable is exported, which is consistent with the only possible -# behavior on Windows systems. +# Returns the command needed to set an environment variable on the current +# platform. The variable setting persists through all following commands and is +# visible in the environment seen by subsequently executed commands. In other +# words, on Unix systems, the variable is exported, which is consistent with the +# only possible behavior on Windows systems. rule variable-setting-command ( variable : value ) -{ +{ + local nl = " +" ; + if [ os.name ] = NT { return "set $(variable)=$(value)$(nl)" ; @@ -472,30 +470,28 @@ rule variable-setting-command ( variable : value ) } } -# Returns a command that sets the named shell path variable to the -# given NATIVE paths to on the current platform. + +# Returns a command to sets a named shell path variable to the given NATIVE +# paths on the current platform. rule path-variable-setting-command ( variable : paths * ) -{ +{ local sep = [ os.path-separator ] ; return [ variable-setting-command $(variable) : $(paths:J=$(sep)) ] ; } -# Returns a command that prepends the given paths to the named path -# variable on the current platform. + +# Returns a command that prepends the given paths to the named path variable on +# the current platform. rule prepend-path-variable-command ( variable : paths * ) -{ - return [ - path-variable-setting-command $(variable) - : $(paths) [ os.expand-variable $(variable) ] - ] ; +{ + return [ path-variable-setting-command $(variable) + : $(paths) [ os.expand-variable $(variable) ] ] ; } -# Return a command which can create a file. If 'r' is result of invocation, -# then -# r foobar -# will create foobar with unspecified content. What happens if file already -# exists is unspecified. +# Return a command which can create a file. If 'r' is result of invocation, then +# 'r foobar' will create foobar with unspecified content. What happens if file +# already exists is unspecified. rule file-creation-command ( ) { if [ modules.peek : NT ] @@ -508,10 +504,10 @@ rule file-creation-command ( ) } } - -# Returns a command that may be used for 'touching' files. -# It is not a real 'touch' command on NT because it adds an empty line at -# the end of file but it works with source files + +# Returns a command that may be used for 'touching' files. It is not a real +# 'touch' command on NT because it adds an empty line at the end of file but it +# works with source files. rule file-touch-command ( ) { if [ os.name ] in NT @@ -527,18 +523,14 @@ rule file-touch-command ( ) rule MkDir { - # If dir exists, don't update it - # Do this even for $(DOT). - + # If dir exists, don't update it. Do this even for $(DOT). NOUPDATE $(<) ; if $(<) != $(DOT) && ! $($(<)-mkdir) { - local s ; - - # Cheesy gate to prevent multiple invocations on same dir - # MkDir1 has the actions - # Arrange for jam dirs + # Cheesy gate to prevent multiple invocations on same dir. + # MkDir1 has the actions. + # Arrange for jam dirs. $(<)-mkdir = true ; MkDir1 $(<) ; @@ -547,7 +539,7 @@ rule MkDir # Recursively make parent directories. # $(<:P) = $(<)'s parent, & we recurse until root - s = $(<:P) ; + local s = $(<:P) ; if $(NT) { @@ -557,7 +549,7 @@ rule MkDir case *:\\ : s = ; } } - + if $(s) && $(s) != $(<) { Depends $(<) : $(s) ; @@ -570,18 +562,21 @@ rule MkDir } } + actions MkDir1 { mkdir "$(<)" } + actions piecemeal together existing Clean { $(RM) "$(>)" } -rule copy -{ + +rule copy +{ } @@ -590,28 +585,32 @@ actions copy $(CP) "$(>)" "$(<)" } + rule RmTemps { } + + actions quietly updated piecemeal together RmTemps { $(RM) "$(>)" $(IGNORE) } + actions hard-link { $(RM) "$(<)" 2$(NULL_OUT) $(NULL_OUT) - $(LN) "$(>)" "$(<)" $(NULL_OUT) + $(LN) "$(>)" "$(<)" $(NULL_OUT) } # Given a target, as given to a custom tag rule, returns a string formatted # according to the passed format. Format is a list of properties that is -# represented in the result. For each element of format the corresponding -# target information is obtained and added to the result string. -# For all, but the literal, the format value is taken as the as string to -# prepend to the output to join the item to the rest of the result. If not -# given "-" is used as a joiner. +# represented in the result. For each element of format the corresponding target +# information is obtained and added to the result string. For all, but the +# literal, the format value is taken as the as string to prepend to the output +# to join the item to the rest of the result. If not given "-" is used as a +# joiner. # # The format options can be: # @@ -642,8 +641,8 @@ actions hard-link # boost_thread-vc80-mt-gd-1_33.dll, or # boost_regex-vc80-gd-1_33.dll # -# The returned name also has the target type specific prefix and suffix -# which puts it in a ready form to use as the value from a custom tag rule. +# The returned name also has the target type specific prefix and suffix which +# puts it in a ready form to use as the value from a custom tag rule. # rule format-name ( format * : name : type ? : property-set ) { @@ -656,19 +655,19 @@ rule format-name ( format * : name : type ? : property-set ) { case : result += $(name:B) ; - + case : result += [ join-tag $(f:G=) : [ toolset-tag $(name) : $(type) : $(property-set) ] ] ; - + case : result += [ join-tag $(f:G=) : [ threading-tag $(name) : $(type) : $(property-set) ] ] ; - + case : result += [ join-tag $(f:G=) : [ runtime-tag $(name) : $(type) : $(property-set) ] ] ; - + case : local key = [ MATCH : $(f:G) ] ; local version = [ $(property-set).get <$(key)> ] ; @@ -676,7 +675,7 @@ rule format-name ( format * : name : type ? : property-set ) version = [ MATCH "^([^.]+)[.]([^.]+)[.]?([^.]*)" : $(version) ] ; result += [ join-tag $(f:G=) : $(version[1])_$(version[2]) ] ; - + case : local key = [ MATCH : $(f:G) ] ; local p = [ $(property-set).get [ MATCH : $(f:G) ] ] ; @@ -684,7 +683,7 @@ rule format-name ( format * : name : type ? : property-set ) { result += [ join-tag $(f:G=) : $(p) ] ; } - + case * : result += $(f:G=) ; } @@ -695,16 +694,18 @@ rule format-name ( format * : name : type ? : property-set ) } } + local rule join-tag ( joiner ? : tag ? ) { if ! $(joinder) { joiner = - ; } return $(joiner)$(tag) ; } + local rule toolset-tag ( name : type ? : property-set ) { local tag = ; - + local properties = [ $(property-set).raw ] ; switch [ $(property-set).get ] { @@ -721,7 +722,7 @@ local rule toolset-tag ( name : type ? : property-set ) case * : tag += gcc ; } } - case intel : + case intel : if [ $(property-set).get ] = win { tag += iw ; @@ -742,8 +743,7 @@ local rule toolset-tag ( name : type ? : property-set ) } local version = [ MATCH "([0123456789]+)[.]([0123456789]*)" : $(properties) ] ; - # For historical reasons, vc6.0 and vc7.0 use different - # naming. + # For historical reasons, vc6.0 and vc7.0 use different naming. if $(tag) = vc { if $(version[1]) = 6 @@ -756,88 +756,87 @@ local rule toolset-tag ( name : type ? : property-set ) version = 7 ; } } - # On intel, version is not added, because it does not - # matter and it's the version of vc used as backend - # that matters. Ideally, we'd encode the backend - # version but that will break compatibility with - # V1. + # On intel, version is not added, because it does not matter and it's the + # version of vc used as backend that matters. Ideally, we'd encode the + # backend version but that would break compatibility with V1. if $(tag) = iw { version = ; } - - # On borland, version is not added for compatibility - # with V1. + + # On borland, version is not added for compatibility with V1. if $(tag) = bcb { version = ; } - + tag += $(version) ; - + return $(tag:J=) ; } + local rule threading-tag ( name : type ? : property-set ) { local tag = ; local properties = [ $(property-set).raw ] ; if multi in $(properties) { tag = mt ; } - + return $(tag:J=) ; } + local rule runtime-tag ( name : type ? : property-set ) { local tag = ; - + local properties = [ $(property-set).raw ] ; if static in $(properties) { tag += s ; } - - # This is ugly thing. In V1, there's a code to automatically - # detect which properties affect a target. So, if - # does not affect gcc toolset, the - # tag rules won't even see . - # Similar functionality in V2 is not implemented yet, so we just - # check for toolsets which are know to care about runtime debug - if msvc in $(properties) - || stlport in $(properties) + + # This is an ugly thing. In V1, there's a code to automatically detect which + # properties affect a target. So, if does not affect gcc + # toolset, the tag rules won't even see . Similar + # functionality in V2 is not implemented yet, so we just check for toolsets + # which are known to care about runtime debug. + if msvc in $(properties) || + stlport in $(properties) { - if on in $(properties) { tag += g ; } + if on in $(properties) { tag += g ; } } - + if on in $(properties) { tag += y ; } if debug in $(properties) { tag += d ; } if stlport in $(properties) { tag += p ; } if hostios in $(properties) { tag += n ; } - + return $(tag:J=) ; } -rule __test__ ( ) { +rule __test__ ( ) +{ import assert ; - - local save-os = [ modules.peek os : name ] ; - - modules.poke os : .name : LINUX ; - + local nl = " " ; - - assert.result "PATH=foo:bar:baz$(nl)export PATH$(nl)" - : path-variable-setting-command PATH : foo bar baz ; - - assert.result "PATH=foo:bar:$PATH$(nl)export PATH$(nl)" - : prepend-path-variable-command PATH : foo bar ; - - modules.poke os : .name : NT ; - - assert.result "set PATH=foo;bar;baz$(nl)" - : path-variable-setting-command PATH : foo bar baz ; - - assert.result "set PATH=foo;bar;%PATH%$(nl)" - : prepend-path-variable-command PATH : foo bar ; - modules.poke os : .name : $(save-os) ; -} + local save-os = [ modules.peek os : name ] ; + + modules.poke os : .name : LINUX ; + + assert.result "PATH=foo:bar:baz$(nl)export PATH$(nl)" + : path-variable-setting-command PATH : foo bar baz ; + + assert.result "PATH=foo:bar:$PATH$(nl)export PATH$(nl)" + : prepend-path-variable-command PATH : foo bar ; + + modules.poke os : .name : NT ; + + assert.result "set PATH=foo;bar;baz$(nl)" + : path-variable-setting-command PATH : foo bar baz ; + + assert.result "set PATH=foo;bar;%PATH%$(nl)" + : prepend-path-variable-command PATH : foo bar ; + + modules.poke os : .name : $(save-os) ; +} diff --git a/src/tools/generate.jam b/src/tools/generate.jam index 2bbce8062..588077348 100644 --- a/src/tools/generate.jam +++ b/src/tools/generate.jam @@ -1,6 +1,6 @@ -# Copyright 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) +# Copyright 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) # Declares main target 'generate' that can be used to produce targets # by calling a user-provides rule, that takes virtual target and produces @@ -9,13 +9,13 @@ import targets ; import "class" : new ; import property ; -import errors : error ; -import type : type ; +import errors ; import regex ; import property-set ; import project ; import feature ; + feature.feature generating-rule : : free ; @@ -24,28 +24,28 @@ class generated-target-class : basic-target import errors ; import indirect ; import virtual-target ; - + rule __init__ ( name : project : sources * : requirements * : default-build * : usage-requirements * ) - { - basic-target.__init__ $(name) : $(project) : $(sources) - : $(requirements) : $(default-build) : $(usage-requirements) ; - + { + basic-target.__init__ $(name) : $(project) : $(sources) + : $(requirements) : $(default-build) : $(usage-requirements) ; + local r = [ $(self.requirements).get ] ; if ! $(r) { - errors.user-error - "The generate rule requires property to be set" ; - } + errors.user-error + "The generate rule requires property to be set" ; + } } - + rule construct ( name : sources * : property-set ) { local result ; local gr = [ $(property-set).get ] ; - + # FIXME: this is copy-paste from virtual-target.jam. Must - # have an utilty rule to call a rule like this. + # have n utilty rule to call a rule like this. local rule-name = [ MATCH ^@(.*) : $(gr) ] ; if $(rule-name) { @@ -53,22 +53,21 @@ class generated-target-class : basic-target { errors.error "@rulename is present but is not the only feature" ; } - - - result = [ indirect.call $(rule-name) $(self.project) $(name) - : $(property-set) : $(sources) ] ; - + + result = [ indirect.call $(rule-name) $(self.project) $(name) + : $(property-set) : $(sources) ] ; + if ! $(result) { ECHO "warning: Unable to construct" [ full-name ] ; - } - } - + } + } + local ur ; local targets ; if $(result) - { + { if [ class.is-a $(result[1]) : property-set ] { ur = $(result[1]) ; @@ -78,31 +77,30 @@ class generated-target-class : basic-target { ur = [ property-set.empty ] ; targets = $(result) ; - } - } + } + } local rt ; for t in $(targets) { rt += [ virtual-target.register $(t) ] ; } return $(ur) $(rt) ; - } + } } -rule generate ( name : sources * : requirements * : default-build * + +rule generate ( name : sources * : requirements * : default-build * : usage-requirements * ) { local project = [ project.current ] ; - + targets.main-target-alternative - [ new generated-target-class $(name) : $(project) - : [ targets.main-target-sources $(sources) : $(name) ] - : [ targets.main-target-requirements $(requirements) : $(project) ] - : [ targets.main-target-default-build $(default-build) : $(project) ] - : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] - ] ; + [ new generated-target-class $(name) : $(project) + : [ targets.main-target-sources $(sources) : $(name) ] + : [ targets.main-target-requirements $(requirements) : $(project) ] + : [ targets.main-target-default-build $(default-build) : $(project) ] + : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] + ] ; } IMPORT $(__name__) : generate : : generate ; - - diff --git a/src/tools/gettext.jam b/src/tools/gettext.jam index 2fbfbe02d..99a43ffe9 100644 --- a/src/tools/gettext.jam +++ b/src/tools/gettext.jam @@ -1,47 +1,47 @@ -# Copyright 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) +# Copyright 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) # This module support GNU gettext internationalization utilities. -# +# # It provides two main target rules: 'gettext.catalog', used for # creating machine-readable catalogs from translations files, and # 'gettext.update', used for update translation files from modified # sources. -# +# # To add i18n support to your application you should follow these # steps. -# +# # - Decide on a file name which will contain translations and # what main target name will be used to update it. For example:: -# +# # gettext.update update-russian : russian.po a.cpp my_app ; -# +# # - Create the initial translation file by running:: # # bjam update-russian # # - Edit russian.po. For example, you might change fields like LastTranslator. -# +# # - Create a main target for final message catalog:: # # gettext.catalog russian : russian.po ; # -# The machine-readable catalog will be updated whenever you update +# The machine-readable catalog will be updated whenever you update # "russian.po". The "russian.po" file will be updated only on explicit # request. When you're ready to update translations, you should -# +# # - Run:: -# +# # bjam update-russian # # - Edit "russian.po" in appropriate editor. -# +# # The next bjam run will convert "russian.po" into machine-readable form. # # By default, translations are marked by 'i18n' call. The 'gettext.keyword' # feature can be used to alter this. - + import targets ; import property-set ; @@ -59,7 +59,7 @@ import regex ; # Initializes the gettext module. rule init ( path ? # Path where all tools are located. If not specified, - # they should be in PATH. + # they should be in PATH. ) { if $(.initialized) && $(.path) != $(path) @@ -68,9 +68,9 @@ rule init ( path ? # Path where all tools are located. If not specified, } .initialized = true ; if $(path) - { + { .path = $(path)/ ; - } + } } # Creates a main target 'name', which, when updated, will cause @@ -80,36 +80,36 @@ rule init ( path ? # Path where all tools are located. If not specified, # of those main targets will be scanned, provided they are of # appropricate type. The 'gettext.types' feature can be used to # control the types. -# +# # The target will be updated only if explicitly requested on the # command line. rule update ( name : existing-translation sources + : requirements * ) { local project = [ project.current ] ; - + targets.main-target-alternative [ new typed-target $(name) : $(project) : gettext.UPDATE : $(existing-translation) $(sources) - : [ targets.main-target-requirements $(requirements) : $(project) ] + : [ targets.main-target-requirements $(requirements) : $(project) ] ] ; $(project).mark-target-as-explicit $(name) ; } # The human editable source, containing translation. -type.register gettext.PO : po ; +type.register gettext.PO : po ; # The machine readable message catalog. type.register gettext.catalog : mo ; # Intermediate type produce by extracting translations from # sources. -type.register gettext.POT : pot ; +type.register gettext.POT : pot ; # Pseudo type used to invoke update-translations generator type.register gettext.UPDATE ; # Identifies the keyword that should be used when scanning sources. # Default: i18n feature gettext.keyword : : free ; -# Contains space-separated list of sources types which should be scanned. +# Contains space-separated list of sources types which should be scanned. # Default: "C CPP" feature gettext.types : : free ; @@ -119,7 +119,7 @@ class update-translations-generator : generator { import regex : split ; import property-set ; - + rule __init__ ( * : * ) { generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; @@ -135,11 +135,11 @@ class update-translations-generator : generator local types = [ $(property-set).get ] ; types ?= "C CPP" ; types = [ regex.split $(types) " " ] ; - + local keywords = [ $(property-set).get ] ; property-set = [ property-set.create $(keywords:G=) ] ; - # First deterime the list of sources that must be scanned for + # First deterime the list of sources that must be scanned for # messages. local all-sources ; # CONSIDER: I'm not sure if the logic should be the same as for 'stage': @@ -154,22 +154,22 @@ class update-translations-generator : generator if [ $(s).type ] in $(types) { right-sources += $(s) ; - } + } } - + local .constructed ; if $(right-sources) - { + { # Create the POT file, which will contain list of messages extracted # from the sources. - local extract = + local extract = [ new action $(right-sources) : gettext.extract : $(property-set) ] ; - local new-messages = [ new file-target $(name) : gettext.POT + local new-messages = [ new file-target $(name) : gettext.POT : $(project) : $(extract) ] ; - + # Create a notfile target which will update the existing translation file - # with new messages. - local a = [ new action $(sources[1]) $(new-messages) + # with new messages. + local a = [ new action $(sources[1]) $(new-messages) : gettext.update-po-dispatch ] ; local r = [ new notfile-target $(name) : $(project) : $(a) ] ; .constructed = [ virtual-target.register $(r) ] ; @@ -177,9 +177,9 @@ class update-translations-generator : generator else { errors.error "No source could be scanned by gettext tools" ; - } - return $(.constructed) ; - } + } + return $(.constructed) ; + } } generators.register [ new update-translations-generator gettext.update : : gettext.UPDATE ] ; @@ -199,11 +199,11 @@ actions extract # first run), we need to copy the file created from sources. # In all other cases, we need to update the file. rule update-po-dispatch -{ +{ NOCARE $(>[1]) ; gettext.create-po $(<) : $(>) ; gettext.update-po $(<) : $(>) ; - _ on $(<) = " " ; + _ on $(<) = " " ; ok on $(<) = "" ; EXISTING_PO on $(<) = $(>[1]) ; } @@ -214,7 +214,7 @@ rule update-po-dispatch # to have "missing" action modifier. actions quietly existing updated create-po bind EXISTING_PO { - cp$(_)"$(>[1])"$(_)"$(EXISTING_PO)"$($(>[2]:E=ok)) + cp$(_)"$(>[1])"$(_)"$(EXISTING_PO)"$($(>[2]:E=ok)) } actions updated update-po bind EXISTING_PO @@ -222,12 +222,9 @@ actions updated update-po bind EXISTING_PO $(.path)msgmerge$(_)-U$(_)"$(EXISTING_PO)"$(_)"$(>[1])" } -actions gettext.compile +actions gettext.compile { - $(.path)msgfmt -o $(<) $(>) + $(.path)msgfmt -o $(<) $(>) } IMPORT $(__name__) : update : : gettext.update ; - - - diff --git a/src/tools/msvc.jam b/src/tools/msvc.jam index 6d8bb8380..0ceb565ab 100644 --- a/src/tools/msvc.jam +++ b/src/tools/msvc.jam @@ -51,15 +51,14 @@ toolset.inherit-flags msvc : mc ; # Dynamic runtime comes only in MT flavour. toolset.add-requirements msvc,shared:multi ; - -RM = [ common.rm-command ] ; +RM = [ common.rm-command ] ; nl = " " ; -# Initialize the toolset for a specific version. As the result, path to -# compiler and, possible, program names are set up, and will be used when -# that version of compiler is requested. For example, you might have: +# Initialize the toolset for a specific version. As the result, path to compiler +# and, possible, program names are set up, and will be used when that version of +# compiler is requested. For example, you might have: # # using msvc : 6.5 : cl.exe ; # using msvc : 7.0 : Y:/foo/bar/cl.exe ; @@ -72,36 +71,36 @@ nl = " # - all - all detected versions will be registered; # - default - this is an equivalent to an empty version. # -# Depending on a supplied version, detected configurations and presence -# 'cl.exe' in the path different results may be achieved. The following -# table describes all possible cases: +# Depending on a supplied version, detected configurations and presence 'cl.exe' +# in the path different results may be achieved. The following table describes +# all possible cases: # # Nothing "x.y" # Passed Nothing "x.y" detected, detected, # version detected detected cl.exe in path cl.exe in path -# +# # default Error Use "x.y" Create "default" Use "x.y" # all None Use all None Use all # x.y - Use "x.y" - Use "x.y" # a.b Error Error Create "a.b" Create "a.b" -# +# # "x.y" - refers to a detected version; # "a.b" - refers to an undetected version. # # Note: for free VC7.1 tools, we don't correctly find vcvars32.bar when user # explicitly provides a path. -rule init ( +rule init ( version ? # the msvc version which is being configured. When omitted # the tools invoked when no explicit version is given will be configured. - : command * + : command * # the command to invoke the compiler. If not specified: # - if version is given, default location for that version will be searched - # - # - if version is not given, default locations for 7.1, 7.0 and 6.* will - # be searched - # - # - if compiler is not found in default locations, PATH will be searched. - : options * + # + # - if version is not given, default locations for 7.1, 7.0 and 6.* will + # be searched + # + # - if compiler is not found in default locations, PATH will be searched. + : options * # options can include , , , and # # @@ -118,12 +117,9 @@ rule init ( } -# 'configure' is a newer version of 'init'. The parameter 'command' is passed as +# 'configure' is a newer version of 'init'. The parameter 'command' is passed as # a part of the 'options' list. -rule configure ( - version ? : - options * - ) +rule configure ( version ? : options * ) { switch $(version) { @@ -149,27 +145,24 @@ rule configure ( # Supported CPU architectures -cpu-arch-i386 = +cpu-arch-i386 = / /32 - x86/ + x86/ x86/32 ; -cpu-arch-amd64 = - /64 +cpu-arch-amd64 = + /64 x86/64 ; cpu-arch-ia64 = - ia64/ + ia64/ ia64/64 ; -local rule configure-really ( - version ? : - options * - ) +local rule configure-really ( version ? : options * ) { - # If no version supplied use the default configuration. Note that condition + # If no version supplied use the default configuration. Note that condition # remains versionless. local v = $(version) ; if ! $(v) @@ -179,7 +172,7 @@ local rule configure-really ( version = $(version[1]) ; v = $(version) ; - # Note: 'version' can still be empty at this point if no versions were + # Note: 'version' can still be empty at this point if no versions were # detected. version ?= "default" ; } @@ -194,7 +187,7 @@ local rule configure-really ( if $(version) in [ $(.versions).used ] { # Allow multiple 'toolset.usage' calls for the same configuration - # if the identical sets of options are used + # if the identical sets of options are used if $(options) && ( $(options) != [ $(.versions).get $(version) : options ] ) { error "msvc: the toolset version '$(version)' is configured already" ; @@ -202,7 +195,7 @@ local rule configure-really ( } else { - # Register a new configuration + # Register a new configuration $(.versions).register $(version) ; # Add user-supplied to auto-detected options @@ -212,26 +205,23 @@ local rule configure-really ( $(.versions).use $(version) ; # Generate condition and save it - local condition = [ common.check-init-parameters msvc : - version $(v) ] ; + local condition = [ common.check-init-parameters msvc : version $(v) ] ; $(.versions).set $(version) : condition : $(condition) ; - local command = [ get-values : $(options) ] ; - # If version is specified, we try to search first in default paths, - # and only then in PATH. + # If version is specified, we try to search first in default paths, and + # only then in PATH. command = [ common.get-invocation-command msvc : cl.exe : $(command) : [ default-paths $(version) ] : $(version) ] ; common.handle-options msvc : $(condition) : $(command) : $(options) ; - - if ! $(version) + if ! $(version) { - # Even if version is not explicitly specified, try to detect the version - # from the path. + # Even if version is not explicitly specified, try to detect the + # version from the path. if [ MATCH "(Microsoft Visual Studio 9)" : $(command) ] { version = 9.0 ; @@ -239,7 +229,7 @@ local rule configure-really ( if [ MATCH "(Microsoft Visual Studio 8)" : $(command) ] { version = 8.0 ; - } + } else if [ MATCH "(NET 2003[\/\\]VC7)" : $(command) ] { version = 7.1 ; @@ -255,11 +245,10 @@ local rule configure-really ( else { version = 6.0 ; - } + } } - - # Generate and register setup command + # Generate and register setup command. local below-8.0 = [ MATCH ^([67]\\.) : $(version) ] ; @@ -276,8 +265,8 @@ local rule configure-really ( parent = [ path.parent $(parent) ] ; parent = [ path.native $(parent) ] ; - # setup will be used if the script name has been specified. - # If setup is not specified, a default script will be used instead. + # setup will be used if the script name has been specified. If setup + # is not specified, a default script will be used instead. setup = [ get-values : $(options) ] ; if ! $(setup) @@ -291,14 +280,14 @@ local rule configure-really ( setup ?= vcvarsall.bat ; } - # The vccars32.bat is actually in "bin" directory. - # (except for free VC7.1 tools) + # The vccars32.bat is actually in "bin" directory except for + # free VC7.1 tools. setup = [ GLOB $(command) $(parent) : $(setup) ] ; } if $(setup) { - # Note Cygwin to Windows translation + # Note Cygwin to Windows translation. setup = "\""$(setup[1]:W)"\"" ; if ! $(below-8.0) @@ -309,16 +298,14 @@ local rule configure-really ( # say about x86_IPF, that seem to be doc bug, # and x86_ia64 is right one. setup-option = x86 x86_amd64 x86_ia64 ; - - # When using 64-bit Windows, and targeting 64-bit, - # it's possible to use native 64-bit compiler, which is - # selected by the "amd64" parameter to vcvarsall.bat. - # There are two variables we can use -- - # PROCESSOR_ARCHITECTURE and PROCESSOR_IDENTIFIER. - # The first is 'x86' when running 32-bit windows, - # no matter what processor is, and 'AMD64' on 64-bit - # windows on x86 (either AMD64 or EM64T). - # windows. + + # When using 64-bit Windows, and targeting 64-bit, it's + # possible to use native 64-bit compiler, which is selected + # by the "amd64" parameter to vcvarsall.bat. There are two + # variables we can use -- PROCESSOR_ARCHITECTURE and + # PROCESSOR_IDENTIFIER. The first is 'x86' when running + # 32-bit windows, no matter what processor is, and 'AMD64' + # on 64-bit windows on x86 (either AMD64 or EM64T) windows. if [ MATCH ^(AMD64) : [ os.environ PROCESSOR_ARCHITECTURE ] ] { setup-option = x86 amd64 x86_ia64 ; @@ -341,7 +328,7 @@ local rule configure-really ( # Setup script is not required in some configurations command ?= "" ; - # Get tool names (if any) and finish setup + # Get tool names (if any) and finish setup. compiler = [ get-values : $(options) ] ; compiler ?= cl ; @@ -362,7 +349,7 @@ local rule configure-really ( mc-compiler ?= mc ; manifest-tool = mt ; - + local cc-filter = [ get-values : $(options) ] ; for local i in 1 2 3 @@ -378,7 +365,7 @@ local rule configure-really ( ECHO "msvc: condition: '$(cond)', " "command: '$(command[$(i)])'" ; } - + flags msvc.compile .CC $(cond) : $(command[$(i)])$(compiler) /Zm800 -nologo ; flags msvc.compile .RC $(cond) : $(command[$(i)])$(resource-compiler) ; flags msvc.compile .ASM $(cond) : $(command[$(i)])$(assembler) ; @@ -395,7 +382,7 @@ local rule configure-really ( { flags msvc.link .MT $(cond) : $(manifest-tool) -nologo ; } - + if $(cc-filter) { flags msvc .CC.FILTER $(cond) : "|" $(cc-filter) ; @@ -411,37 +398,36 @@ local rule configure-really ( # Supported CPU types (only Itanium optimization options are supported from # VC++ 2005 on). See http://msdn2.microsoft.com/en-us/library/h66s5s0e(vs.90).aspx cpu-type-g5 = i586 pentium pentium-mmx ; -cpu-type-g6 = - i686 pentiumpro pentium2 pentium3 pentium3m pentium-m k6 k6-2 k6-3 +cpu-type-g6 = + i686 pentiumpro pentium2 pentium3 pentium3m pentium-m k6 k6-2 k6-3 winchip-c6 winchip2 c3 c3-2 ; -cpu-type-em64t = prescott nocona +cpu-type-em64t = prescott nocona conroe conroe-xe conroe-l allendale mermon mermon-xe kentsfield kentsfield-xe penryn wolfdale yorksfield nehalem ; cpu-type-amd64 = k8 opteron athlon64 athlon-fx ; -cpu-type-g7 = - pentium4 pentium4m athlon athlon-tbird athlon-4 athlon-xp athlon-mp +cpu-type-g7 = + pentium4 pentium4m athlon athlon-tbird athlon-4 athlon-xp athlon-mp $(cpu-type-em64t) $(cpu-type-amd64) ; cpu-type-itanium = itanium itanium1 merced ; cpu-type-itanium2 = itanium2 mckinley ; -# Sets up flag definitions that are dependent on the version ot -# compiler. + +# Sets up flag definitions dependent on the compiler version used. # - 'version' is the version of compiler in N.M format. -# - 'condition' is the property set to be used as condition for flag -# - 'toolset' is the toolset for which flag settings are to be defined +# - 'condition' is the property set to be used as condition for flag. +# - 'toolset' is the toolset for which flag settings are to be defined. # This makes the rule reusable for other msvc-option-compatible compilers. rule configure-version-specific ( toolset : version : condition ) { toolset.push-checking-for-flags-module unchecked ; - # Starting with versions 7.0, the msvc compiler have the /Zc:forScope - # and /Zc:wchar_t options that improve C++ standard conformance, but - # those options are off by default. - # If we're sure that msvc version is at 7.*, add those options explicitly. - # We can be sure either if user specified version 7.* explicitly, - # or if the installation path contain 7.* (this is checked above). + # Starting with versions 7.0, the msvc compiler have the /Zc:forScope and + # /Zc:wchar_t options that improve C++ standard conformance, but those + # options are off by default. If we're sure that msvc version is at 7.*, add + # those options explicitly. We can be sure either if user specified version + # 7.* explicitly, or if the installation path contain 7.* (checked above). if ! [ MATCH ^(6\\.) : $(version) ] { flags $(toolset).compile CFLAGS $(condition) : /Zc:forScope /Zc:wchar_t ; @@ -449,18 +435,18 @@ rule configure-version-specific ( toolset : version : condition ) # disable the function is deprecated warning # Some version of msvc have a bug, that cause deprecation # warning to be emitted even with /W0 - flags $(toolset).compile CFLAGS $(condition)/off : /wd4996 ; + flags $(toolset).compile CFLAGS $(condition)/off : /wd4996 ; # 64-bit compatibility warning - flags $(toolset).compile CFLAGS $(condition)/all : /Wp64 ; + flags $(toolset).compile CFLAGS $(condition)/all : /Wp64 ; } - + # # Processor-specific optimization # if [ MATCH ^([67]) : $(version) ] { - # 8.0 deprecates some of the options + # 8.0 deprecates some of the options. flags $(toolset).compile CFLAGS $(condition)/speed $(condition)/space : /Ogiy /Gs ; flags $(toolset).compile CFLAGS $(condition)/speed : /Ot ; flags $(toolset).compile CFLAGS $(condition)/space : /Os ; @@ -471,23 +457,23 @@ rule configure-version-specific ( toolset : version : condition ) flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-i386)/$(cpu-type-g5) : /G5 ; flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-i386)/$(cpu-type-g6) : /G6 ; flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-i386)/$(cpu-type-g7) : /G7 ; - - # Improve floating-point accuracy. Otherwise, some of C++ Boost's - # "math" tests will fail. + + # Improve floating-point accuracy. Otherwise, some of C++ Boost's "math" + # tests will fail. flags $(toolset).compile CFLAGS $(condition) : /Op ; - # 7.1 and below have single-threaded static RTL + # 7.1 and below have single-threaded static RTL. flags $(toolset).compile CFLAGS $(condition)/off/static/single : /ML ; flags $(toolset).compile CFLAGS $(condition)/on/static/single : /MLd ; } else { - # 8.0 and above adds some more options + # 8.0 and above adds some more options. flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-amd64)/ : /favor:blend ; flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-amd64)/$(cpu-type-em64t) : /favor:EM64T ; flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-amd64)/$(cpu-type-amd64) : /favor:AMD64 ; - # 8.0 and above only has multi-threaded static RTL + # 8.0 and above only has multi-threaded static RTL. flags $(toolset).compile CFLAGS $(condition)/off/static/single : /MT ; flags $(toolset).compile CFLAGS $(condition)/on/static/single : /MTd ; } @@ -495,11 +481,11 @@ rule configure-version-specific ( toolset : version : condition ) } -# Returns the default installation path for the given version. +# Returns the default installation path for the given version. local rule default-path ( version ) { - # Use auto-detected path if possible - local path = [ get-values : + # Use auto-detected path if possible + local path = [ get-values : [ $(.versions).get $(version) : options ] ] ; if $(path) @@ -532,12 +518,13 @@ local rule default-path ( version ) return $(path) ; } -# Returns either the default installation path (if 'version' is not empty) or list of all -# known default paths (if no version is given) + +# Returns either the default installation path (if 'version' is not empty) or +# list of all known default paths (if no version is given) rule default-paths ( version ? ) { local possible-paths ; - + if $(version) { possible-paths += [ default-path $(version) ] ; @@ -554,14 +541,13 @@ rule default-paths ( version ? ) } -# Declare generators +# Declare generators. -# is it possible to combine these? -# make the generators non-composing, so that they don't convert each source -# into separate rsp file. +# Is it possible to combine these? Make the generators non-composing so that +# they don't convert each source into a separate rsp file. generators.register-linker msvc.link : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE : msvc ; generators.register-linker msvc.link.dll : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB : msvc ; - + generators.register-archiver msvc.archive : OBJ : STATIC_LIB : msvc ; generators.register-c-compiler msvc.compile.c++ : CPP : OBJ : msvc ; generators.register-c-compiler msvc.compile.c : C : OBJ : msvc ; @@ -586,7 +572,7 @@ class msvc-pch-generator : pch-generator import property-set ; rule run-pch ( project name ? : property-set : sources * ) - { + { # searching header and source file in the sources local pch-header ; local pch-source ; @@ -603,7 +589,7 @@ class msvc-pch-generator : pch-generator pch-source = $(s) ; } } - + if ! $(pch-header) { errors.user-error "can't build pch without pch-header" ; @@ -638,7 +624,7 @@ class msvc-pch-generator : pch-generator } return - [ + [ property-set.create $(pch-header) $(pch-file) @@ -648,18 +634,19 @@ class msvc-pch-generator : pch-generator } } -# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The latter -# have HPP type, but HPP type is derived from H. The type of compilation is determined -# entirely by the destination type. + +# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The +# latter have HPP type, but HPP type is derived from H. The type of compilation +# is determined entirely by the destination type. generators.register [ new msvc-pch-generator msvc.compile.c.pch : H : C_PCH OBJ : on msvc ] ; generators.register [ new msvc-pch-generator msvc.compile.c++.pch : H : CPP_PCH OBJ : on msvc ] ; generators.override msvc.compile.c.pch : pch.default-c-pch-generator ; generators.override msvc.compile.c++.pch : pch.default-cpp-pch-generator ; -flags msvc.compile PCH_FILE on : ; -flags msvc.compile PCH_SOURCE on : ; -flags msvc.compile PCH_HEADER on : ; +flags msvc.compile PCH_FILE on : ; +flags msvc.compile PCH_SOURCE on : ; +flags msvc.compile PCH_HEADER on : ; # # Declare flags and action for compilation @@ -705,22 +692,26 @@ flags msvc.compile DEFINES ; flags msvc.compile UNDEFS ; flags msvc.compile INCLUDES ; + rule get-rspline ( target : lang-opt ) { CC_RSPLINE on $(target) = [ on $(target) return $(lang-opt) -U$(UNDEFS) $(CFLAGS) $(C++FLAGS) $(OPTIONS) -c $(nl)-D$(DEFINES) $(nl)\"-I$(INCLUDES)\" ] ; } + rule compile-c-c++ ( targets + : sources * ) { DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ; DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ; } + actions compile-c-c++ { $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" $(.CC.FILTER) } + rule compile.c ( targets + : sources * : properties * ) { C++FLAGS on $(targets[1]) = ; @@ -728,19 +719,22 @@ rule compile.c ( targets + : sources * : properties * ) compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ; } + rule compile.c++ ( targets + : sources * : properties * ) { get-rspline $(targets) : -TP ; compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ; } + actions compile-c-c++-pch-s { $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" -Yl"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" $(.CC.FILTER) } -# Needed only to avoid messing up Emacs syntax highlighting in -# the messing N-quoted code below. + +# Needed only to avoid messing up Emacs syntax highlighting in the messy +# N-quoted code below. quote = "\"" ; actions compile-c-c++-pch @@ -748,6 +742,7 @@ actions compile-c-c++-pch $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" -Yl"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" "@($(<[1]:W).cpp:E=#include $(quote)$(>[1]:D=)$(quote))" $(.CC.FILTER) } + rule compile.c.pch ( targets + : sources * : properties * ) { C++FLAGS on $(targets[1]) = ; @@ -755,47 +750,52 @@ rule compile.c.pch ( targets + : sources * : properties * ) get-rspline $(targets[2]) : -TC ; local pch-source = [ on $(<) return $(PCH_SOURCE) ] ; if $(pch-source) - { + { DEPENDS $(<) : $(pch-source) ; compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ; } else { compile-c-c++-pch $(targets) : $(sources) ; - } + } } + rule compile.c++.pch ( targets + : sources * : properties * ) { get-rspline $(targets[1]) : -TP ; get-rspline $(targets[2]) : -TP ; local pch-source = [ on $(<) return $(PCH_SOURCE) ] ; if $(pch-source) - { + { DEPENDS $(<) : $(pch-source) ; compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ; } else { compile-c-c++-pch $(targets) : $(sources) ; - } + } } + actions compile.rc { $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES)" -fo "$(<:W)" "$(>:W)" } + # See midl.jam for details TOUCH_FILE = [ common.file-touch-command ] ; + actions compile.idl { $(.IDL) /nologo @"@($(<[1]:W).rsp:E=$(nl)"$(>:W)" $(nl)-D$(DEFINES) $(nl)"-I$(INCLUDES)" $(nl)-U$(UNDEFS) $(nl)$(MIDLFLAGS) $(nl)/tlb "$(<[1]:W)" $(nl)/h "$(<[2]:W)" $(nl)/iid "$(<[3]:W)" $(nl)/proxy "$(<[4]:W)" $(nl)/dlldata "$(<[5]:W)")" - $(TOUCH_FILE) "$(<[4]:W)" - $(TOUCH_FILE) "$(<[5]:W)" + $(TOUCH_FILE) "$(<[4]:W)" + $(TOUCH_FILE) "$(<[5]:W)" } + # Declare flags and action for the assembler flags msvc.compile.asm USER_ASMFLAGS : ; @@ -813,12 +813,13 @@ actions compile.asm $(.ASM) -nologo -c -coff -Zp4 -Cp -Cx $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)" } + # Declare flags and action for linking -flags msvc.link PDB_LINKFLAG on/database : /PDB: ; # not used yet +flags msvc.link PDB_LINKFLAG on/database : /PDB: ; # not used yet flags msvc.link LINKFLAGS on : /DEBUG ; flags msvc.link DEF_FILE ; -# The linker disables the default optimizations when using /DEBUG. Whe have -# to enable them manually for release builds with debug symbols. +# The linker disables the default optimizations when using /DEBUG. Whe have to +# enable them manually for release builds with debug symbols. flags msvc LINKFLAGS on/off : /OPT:REF,ICF ; flags msvc LINKFLAGS console : /subsystem:console ; @@ -830,7 +831,6 @@ flags msvc LINKFLAGS auto : /subsystem:posix ; flags msvc.link OPTIONS ; flags msvc.link LINKPATH ; - flags msvc.link FINDLIBS_ST ; flags msvc.link FINDLIBS_SA ; flags msvc.link LIBRARY_OPTION msvc : "" : unchecked ; @@ -844,40 +844,38 @@ rule link.dll ( targets + : sources * : properties * ) DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ; } -# Declare action for creating static libraries -# If library exists, remove it before adding files. See -# http://article.gmane.org/gmane.comp.lib.boost.build/4241 -# for rationale. +# Declare action for creating static libraries. If library exists, remove it +# before adding files. See +# http://article.gmane.org/gmane.comp.lib.boost.build/4241 for rationale. if [ os.name ] in NT -{ - # The 'DEL' command would issue a message to stdout - # if the file does not exist, so need a check. +{ + # The 'DEL' command would issue a message to stdout if the file does not + # exist, so need a check. actions archive - { - if exist "$(<[1])" DEL "$(<[1])" + { + if exist "$(<[1])" DEL "$(<[1])" $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES_MENTIONED_BY_FILE) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" } } else { actions archive - { + { $(RM) "$(<[1])" $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES_MENTIONED_BY_FILE) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" } } - -# incremental linking a DLL causes no end of problems: if the -# actual exports don't change, the import .lib file is never -# updated. Therefore, the .lib is always out-of-date and gets -# rebuilt every time. I'm not sure that incremental linking is -# such a great idea in general, but in this case I'm sure we -# don't want it. -# Windows Manifests is a new way to specify dependencies -# on managed DotNet assemblies and Windows native DLLs. The -# manifests are embedded as resources and are useful in -# any PE targets (both DLL and EXE) + +# Incremental linking a DLL causes no end of problems: if the actual exports +# don't change, the import .lib file is never updated. Therefore, the .lib is +# always out-of-date and gets rebuilt every time. I'm not sure that incremental +# linking is such a great idea in general, but in this case I'm sure we don't +# want it. + +# Windows manifest is a new way to specify dependencies on managed DotNet +# assemblies and Windows native DLLs. The manifests are embedded as resources +# and are useful in any PE target (both DLL and EXE). if [ os.name ] in NT { @@ -927,7 +925,7 @@ actions compile.mc # # Autodetection code -# detects versions listed as '.known-versions' using registry, environment +# detects versions listed as '.known-versions' using registry, environment # and checking default paths. Supports both native Windows and Cygwin. # @@ -941,7 +939,7 @@ actions compile.mc .version-alias-7 = 7.0 ; .version-alias-8 = 8.0 ; .version-alias-9 = 9.0 ; - + # Name of the registry key that contains Visual C++ installation path # (relative to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft" .version-6.0-reg = "VisualStudio\\6.0\\Setup\\Microsoft Visual C++" ; @@ -953,18 +951,18 @@ actions compile.mc .version-9.0express-reg = "VCExpress\\9.0\\Setup\\VC" ; # Visual C++ Toolkit 2003 do not store its installation path in the registry. -# The environment variable 'VCToolkitInstallDir' and the default installation +# The environment variable 'VCToolkitInstallDir' and the default installation # path will be checked instead. .version-7.1toolkit-path = "Microsoft Visual C++ Toolkit 2003" "bin" ; .version-7.1toolkit-env = VCToolkitInstallDir ; -# Path to the folder containing "cl.exe" relative to the value of the corresponding -# environment variable +# Path to the folder containing "cl.exe" relative to the value of the +# corresponding environment variable. .version-7.1toolkit-envpath = "bin" ; -# Validates given path, registers found configuration and prints debug information -# about it. +# Validates given path, registers found configuration and prints debug +# information about it. local rule register-configuration ( version : path ? ) { if $(path) @@ -986,8 +984,7 @@ local rule register-configuration ( version : path ? ) if [ os.name ] in NT CYGWIN { - # Get installation paths from the registry - + # Get installation paths from the registry. for local i in $(.known-versions) { if $(.version-$(i)-reg) @@ -999,7 +996,7 @@ if [ os.name ] in NT CYGWIN "HKEY_LOCAL_MACHINE\\SOFTWARE\\"$(x)"\\Microsoft\\"$(.version-$(i)-reg) : "ProductDir" ] ; } - + if $(vc-path) { vc-path = [ path.native [ path.join [ path.make-NT $(vc-path[1]) ] "bin" ] ] ; @@ -1010,7 +1007,7 @@ if [ os.name ] in NT CYGWIN } -# Check environment and default installation paths +# Check environment and default installation paths. for local i in $(.known-versions) { @@ -1019,4 +1016,3 @@ for local i in $(.known-versions) register-configuration $(i) : [ default-path $(i) ] ; } } - diff --git a/src/tools/notfile.jam b/src/tools/notfile.jam index ab907de57..48d00f2de 100644 --- a/src/tools/notfile.jam +++ b/src/tools/notfile.jam @@ -4,47 +4,52 @@ # License Version 1.0. (See accompanying file LICENSE_1_0.txt or # http://www.boost.org/LICENSE_1_0.txt) +import "class" : new ; import generators ; -import type ; -import feature ; import project ; import targets ; import toolset ; -import "class" : new ; +import type ; + type.register NOTFILE_MAIN ; + class notfile-generator : generator { rule __init__ ( * : * ) { generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; } - + rule run ( project name ? : property-set : sources * : multiple ? ) { local action ; local action-name = [ $(property-set).get ] ; - + local m = [ MATCH ^@(.*) : $(action-name) ] ; - - if $(m) + + if $(m) { - action = [ new action $(sources) : $(m[1]) - : $(property-set) ] ; + action = [ new action $(sources) : $(m[1]) + : $(property-set) ] ; } else { - action = [ new action $(sources) : notfile.run - : $(property-set) ] ; - } + action = [ new action $(sources) : notfile.run + : $(property-set) ] ; + } return [ new notfile-target $(name) : $(project) : $(action) ] ; - } + } } + generators.register [ new notfile-generator notfile.main : : NOTFILE_MAIN ] ; + toolset.flags notfile.run ACTION : ; + + actions run { $(ACTION) @@ -52,20 +57,17 @@ actions run rule notfile ( target-name : action + : sources * : requirements * : default-build * ) -{ +{ local project = [ project.current ] ; - + requirements += $(action) ; - - targets.main-target-alternative + targets.main-target-alternative [ new typed-target $(target-name) : $(project) : NOTFILE_MAIN - : [ targets.main-target-sources $(sources) : $(target-name) ] - : [ targets.main-target-requirements $(requirements) : $(project) ] - : [ targets.main-target-default-build $(default-build) : $(project) ] + : [ targets.main-target-sources $(sources) : $(target-name) ] + : [ targets.main-target-requirements $(requirements) : $(project) ] + : [ targets.main-target-default-build $(default-build) : $(project) ] ] ; } IMPORT $(__name__) : notfile : : notfile ; - - diff --git a/src/tools/python.jam b/src/tools/python.jam index b21441159..d9829a2ab 100644 --- a/src/tools/python.jam +++ b/src/tools/python.jam @@ -94,8 +94,8 @@ lib rt ; # # using python 2.3 ; # using python 2.3 : /usr/local/bin/python ; -# -rule init ( version ? : cmd-or-prefix ? : includes * : libraries ? +# +rule init ( version ? : cmd-or-prefix ? : includes * : libraries ? : condition * : extension-suffix ? ) { project.push-current $(.project) ; @@ -108,7 +108,7 @@ rule init ( version ? : cmd-or-prefix ? : includes * : libraries ? debug-message " user-specified "$(v): \"$($(v))\" ; } } - + configure $(version) : $(cmd-or-prefix) : $(includes) : $(libraries) : $(condition) : $(extension-suffix) ; project.pop-current ; @@ -617,7 +617,7 @@ local rule system-library-dependencies ( target-os ) # For example, on my installation, adding -ldl causes at # least one test to fail because the library can't be # found and removing it causes no failures. - + # Apparently, though, we need to add -lrt for gcc. return gcc:rt ; @@ -664,7 +664,7 @@ local rule declare-libpython-target ( version ? : requirements * ) } # implementation of init -local rule configure ( +local rule configure ( version ? : cmd-or-prefix ? : includes * : libraries ? : condition * : extension-suffix ? ) { local prefix ; @@ -675,13 +675,13 @@ local rule configure ( local target-os = [ feature.get-values target-os : $(condition) ] ; target-os ?= [ feature.defaults target-os ] ; target-os = $(target-os:G=) ; - - if $(target-os) = windows && on in $(condition) + + if $(target-os) = windows && on in $(condition) { extension-suffix ?= _d ; } extension-suffix ?= "" ; - + # Normalize and dissect any version number local major-minor ; if $(version) @@ -715,7 +715,7 @@ local rule configure ( # Values to use in case we can't really find anything in the system. local fallback-cmd = $(cmds-to-try[1]) ; local fallback-version ; - + # Anything left to find or check? if ! ( $(interpreter-cmd) && $(includes) && $(libraries) ) { @@ -734,7 +734,7 @@ local rule configure ( case windows : platform = win32 ; case cygwin : platform = cygwin ; } - + while $(cmds-to-try) { # pop top command @@ -780,7 +780,7 @@ local rule configure ( } } } - + # Anything left to compute? if $(includes) && $(libraries) { @@ -858,13 +858,13 @@ local rule configure ( } local dll-path = $(libraries) ; - + # Make sure that we can find the Python DLL on windows if $(target-os) = windows && $(exec-prefix) { dll-path += $(exec-prefix) ; } - + # # prepare usage requirements # @@ -884,9 +884,9 @@ local rule configure ( } } - # Register the right suffix for extensions + # Register the right suffix for extensions. register-extension-suffix $(extension-suffix) : $(target-requirements) ; - + # # Declare the "python" target. This should really be called # python_for_embedding @@ -911,7 +911,7 @@ local rule configure ( # (http://article.gmane.org/gmane.comp.python.general/544986). The # evil here, aside from the workaround necessitated by # Python's bug, is that: - # + # # a. we're guessing the location of the python standard # library from the location of pythonXX.lib # @@ -924,7 +924,7 @@ local rule configure ( set-PYTHONPATH = [ common.prepend-path-variable-command PYTHONPATH : $(libraries:D)/Lib ] ; } - + alias python : : $(target-requirements) @@ -933,8 +933,8 @@ local rule configure ( # the system libs is a mystery, but if we don't do it, on # cygwin, -lpythonX.Y never appears in the command line # (although it does on linux). - : $(usage-requirements) - $(set-PYTHONPATH) + : $(usage-requirements) + $(set-PYTHONPATH) $(libraries) $(dll-path) python.lib ; } @@ -987,12 +987,12 @@ type.register PYTHON_EXTENSION : : SHARED_LIB ; local rule register-extension-suffix ( root : condition * ) { local suffix ; - + switch [ feature.get-values target-os : $(condition) ] { case windows : suffix = pyd ; case cygwin : suffix = dll ; - case hpux : + case hpux : { if [ feature.get-values python : $(condition) ] in 1.5 1.6 2.0 2.1 2.2 2.3 2.4 { @@ -1005,7 +1005,7 @@ local rule register-extension-suffix ( root : condition * ) } case * : suffix = so ; } - + type.set-generated-target-suffix PYTHON_EXTENSION : $(condition) : <$(root).$(suffix)> ; } @@ -1023,23 +1023,23 @@ rule python-extension ( name : sources * : requirements * : default-build * : local project = [ project.current ] ; - targets.main-target-alternative - [ new typed-target $(name) : $(project) : PYTHON_EXTENSION - : [ targets.main-target-sources $(sources) : $(name) ] - : [ targets.main-target-requirements $(requirements) : $(project) ] - : [ targets.main-target-default-build $(default-build) : $(project) ] - ] ; + [ new typed-target $(name) : $(project) : PYTHON_EXTENSION + : [ targets.main-target-sources $(sources) : $(name) ] + : [ targets.main-target-requirements $(requirements) : $(project) ] + : [ targets.main-target-default-build $(default-build) : $(project) ] + ] ; } IMPORT python : python-extension : : python-extension ; + # Support for testing type.register PY : py ; type.register RUN_PYD_OUTPUT ; -#type.set-generated-target-suffix RUN_PYD : : run ; type.register RUN_PYD : : TEST ; + class python-test-generator : generator { import set ; diff --git a/src/tools/testing.jam b/src/tools/testing.jam index fe57c2e9b..0193b8ed1 100644 --- a/src/tools/testing.jam +++ b/src/tools/testing.jam @@ -1,36 +1,36 @@ -# Copyright 2005 Dave Abrahams -# 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) +# Copyright 2005 Dave Abrahams +# 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) -# This module implements regression testing framework. It declares a number of -# main target rules, which perform some action, and if the results are ok, +# This module implements regression testing framework. It declares a number of +# main target rules which perform some action and, if the results are ok, # creates an output file. -# +# # The exact list of rules is: -# 'compile' -- creates .test file if compilation of sources was successfull -# 'compile-fail' -- creates .test file if compilation of sources failed +# 'compile' -- creates .test file if compilation of sources was +# successful. +# 'compile-fail' -- creates .test file if compilation of sources failed. # 'run' -- creates .test file is running of executable produced from -# sources was successfull. Also leaves behing .output file +# sources was successful. Also leaves behind .output file # with the output from program run. # 'run-fail' -- same as above, but .test file is created if running fails. # -# In all cases, presense of .test file is an incication that -# the test passed. For more convenient reporting, you might want to use C++ Boost -# regression testing utilities, see -# http://www.boost.org/more/regression.html +# In all cases, presence of .test file is an indication that the test passed. +# For more convenient reporting, you might want to use C++ Boost regression +# testing utilities, see http://www.boost.org/more/regression.html # -# For historical reason, a 'unit-test' rule is available which -# has the same syntax as 'exe' and behaves just like 'run'. +# For historical reason, a 'unit-test' rule is available which has the same +# syntax as 'exe' and behaves just like 'run'. # Things to do: # - Teach compiler_status handle Jamfile.v2. # Notes: -# - is not implemented, since in Como-specific, and it's not clear how -# to implement it -# - std::locale-support is not impelemted (it's used in one test). +# - is not implemented, since in Como-specific, and it's not clear +# how to implement it +# - std::locale-support is not implemented (it's used in one test). + - import targets ; import "class" : new ; import property ; @@ -48,77 +48,83 @@ import common ; import sequence ; import errors ; -rule init ( ) { } -# The feature which controls the name of program used to -# lanch test programs. -feature.feature testing.launcher : : optional free ; -feature.feature test-info : : free incidental ; -feature.feature testing.arg : : free incidental ; +rule init ( ) +{ +} + + +# Feature controling the command used to lanch test programs. +feature.feature testing.launcher : : free optional ; + +feature.feature test-info : : free incidental ; +feature.feature testing.arg : : free incidental ; feature.feature testing.input-file : : free dependency ; + # Register target types. -type.register TEST : test ; -type.register COMPILE : : TEST ; -type.register COMPILE_FAIL : : TEST ; -type.register RUN_OUTPUT : run ; -type.register RUN : : TEST ; -type.register RUN_FAIL : : TEST ; -type.register LINK_FAIL : : TEST ; -type.register LINK : : TEST ; -type.register UNIT_TEST : passed : TEST ; +type.register TEST : test ; +type.register COMPILE : : TEST ; +type.register COMPILE_FAIL : : TEST ; +type.register RUN_OUTPUT : run ; +type.register RUN : : TEST ; +type.register RUN_FAIL : : TEST ; +type.register LINK_FAIL : : TEST ; +type.register LINK : : TEST ; +type.register UNIT_TEST : passed : TEST ; -# Declare the rules which create main targets. -# While the 'type' module already creates rules with the same names for us, -# we need extra convenience: default name of main target, so write -# our own versions. -# Helper rule. Create a test target, using basename of first source if no -# target name is explicitly passed. Remembers the created target in -# a global variable. +# Declare the rules which create main targets. While the 'type' module already +# creates rules with the same names for us, we need extra convenience: default +# name of main target, so write our own versions. + +# Helper rule. Create a test target, using basename of first source if no target +# name is explicitly passed. Remembers the created target in a global variable. rule make-test ( target-type : sources + : requirements * : target-name ? ) { target-name ?= $(sources[1]:D=:S=) ; local project = [ project.current ] ; - # The forces the build system for generate paths in the form - # $build_dir/array1.test/gcc/debug - # This is necessary to allow post-processing tools to work. - local t = - [ targets.create-typed-target + # The forces the build system for generate paths in the + # form '$build_dir/array1.test/gcc/debug'. This is necessary to allow + # post-processing tools to work. + local t = + [ targets.create-typed-target [ type.type-from-rule-name $(target-type) ] : $(project) - : $(target-name) : $(sources) + : $(target-name) : $(sources) : $(requirements) $(target-name).test ] ; - - # Remember the test (for --dump-tests). - # A good way would be to collect all given a project. - # This has some technical problems: e.g. we can't call this dump from - # Jamfile since projects referred by 'build-project' are not available until - # whole Jamfile is loaded. + + # Remember the test (for --dump-tests). A good way would be to collect all + # given a project. This has some technical problems: e.g. we can't call this + # dump from Jamfile since projects referred by 'build-project' are not + # available until the whole Jamfile is loaded. .all-tests += $(t) ; - return $(t) ; + return $(t) ; } -# Note: passing more that one cpp file here is know to -# fail. Passing a cpp file and a library target works. + +# Note: passing more that one cpp file here is known to fail. Passing a cpp file +# and a library target works. rule compile ( sources + : requirements * : target-name ? ) -{ +{ return [ make-test compile : $(sources) : $(requirements) : $(target-name) ] ; } + rule compile-fail ( sources + : requirements * : target-name ? ) -{ +{ return [ make-test compile-fail : $(sources) : $(requirements) : $(target-name) ] ; } + rule link ( sources + : requirements * : target-name ? ) -{ +{ return [ make-test link : $(sources) : $(requirements) : $(target-name) ] ; } rule link-fail ( sources + : requirements * : target-name ? ) -{ +{ return [ make-test link-fail : $(sources) : $(requirements) : $(target-name) ] ; } @@ -127,56 +133,55 @@ rule handle-input-files ( input-files * ) { if $(input-files[2]) { - # Check that sorting made when creating property-set instance - # won't change the ordering. + # Check that sorting made when creating property-set instance won't + # change the ordering. if [ sequence.insertion-sort $(input-files) ] != $(input-files) { errors.user-error "Names of input files must be sorted alphabetically" - : "due to internal limitations" ; - } + : "due to internal limitations" ; + } } return $(input-files) ; } -rule run ( sources + : args * : input-files * : requirements * : target-name ? +rule run ( sources + : args * : input-files * : requirements * : target-name ? : default-build * ) -{ +{ requirements += $(args:J=" ") ; requirements += [ handle-input-files $(input-files) ] ; return [ make-test run : $(sources) : $(requirements) : $(target-name) ] ; } -rule run-fail ( sources + : args * : input-files * : requirements * : target-name ? - : default-build * ) -{ - requirements += $(args:J=" ") ; + +rule run-fail ( sources + : args * : input-files * : requirements * + : target-name ? : default-build * ) +{ + requirements += $(args:J=" ") ; requirements += [ handle-input-files $(input-files) ] ; return [ make-test run-fail : $(sources) : $(requirements) : $(target-name) ] ; } - -# Use 'test-suite' as synonym for 'alias', for backward compatibility. +# Use 'test-suite' as a synonym for 'alias', for backward compatibility. IMPORT : alias : : test-suite ; - -# For all main target in 'project-module', -# which are typed target with type derived from 'TEST', -# produce some interesting information. +# For all main targets in 'project-module', which are typed targets with type +# derived from 'TEST', produce some interesting information. rule dump-tests # ( project-module ) { for local t in $(.all-tests) { dump-test $(t) ; - } + } } -# Given a project location, compute the name of Boost library + +# Given a project location in normalized form (slashes are forward), compute the +# name of the Boost library. local rule get-library-name ( path ) { # Path is in normalized form, so all slashes are forward. - local match1 = [ MATCH /libs/(.*)/(test|example) : $(path) ] ; local match2 = [ MATCH /libs/(.*)$ : $(path) ] ; local match3 = [ MATCH (/status$) : $(path) ] ; @@ -184,19 +189,20 @@ local rule get-library-name ( path ) if $(match1) { return $(match1[0]) ; } else if $(match2) { return $(match2[0]) ; } else if $(match3) { return "" ; } - else if --dump-tests in [ modules.peek : ARGV ] - { - # The 'run' rule and others might be used outside - # boost. In that case, just return the path, - # since the 'library name' makes no sense. + else if --dump-tests in [ modules.peek : ARGV ] + { + # The 'run' rule and others might be used outside boost. In that case, + # just return the path, since the 'library name' makes no sense. return $(path) ; } } + # Was an XML dump requested? .out-xml = [ MATCH --out-xml=(.*) : [ modules.peek : ARGV ] ] ; -# Take a target (instance of 'basic-target') and prints + +# Takes a target (instance of 'basic-target') and prints # - its type # - its name # - comments specified via the property @@ -206,44 +212,44 @@ rule dump-test ( target ) local type = [ $(target).type ] ; local name = [ $(target).name ] ; local project = [ $(target).project ] ; - + local project-root = [ $(project).get project-root ] ; - local library = [ get-library-name + local library = [ get-library-name [ path.root [ $(project).get location ] [ path.pwd ] ] ] ; if $(library) { name = $(library)/$(name) ; } - + local sources = [ $(target).sources ] ; local source-files ; for local s in $(sources) { - if [ class.is-a $(s) : file-reference ] + if [ class.is-a $(s) : file-reference ] { - local location = - [ path.root + local location = + [ path.root [ path.root [ $(s).name ] [ $(s).location ] ] - [ path.pwd ] ] ; - - source-files += - [ path.relative + [ path.pwd ] ] ; + + source-files += + [ path.relative $(location) [ path.root $(project-root) [ path.pwd ] ] ] ; - } + } } - + local r = [ $(target).requirements ] ; - # Extract values of the feature + # Extract values of the feature. local test-info = [ $(r).get ] ; - - # If the user requested XML output on the command-line, add the - # test info to that XML file rather than dumping them to stdout. + + # If the user requested XML output on the command-line, add the test info to + # that XML file rather than dumping them to stdout. if $(.out-xml) { local nl = " " ; - .contents on $(.out-xml) += + .contents on $(.out-xml) += "$(nl) " "$(nl) " "$(nl) " @@ -252,123 +258,123 @@ rule dump-test ( target ) } else { - # Format them into a single string of quoted strings + # Format them into a single string of quoted strings. test-info = \"$(test-info:J=\"\ \")\" ; - - ECHO boost-test($(type)) \"$(name)\" - [$(test-info)] - ":" \"$(source-files)\" - ; + + ECHO boost-test($(type)) \"$(name)\" + [$(test-info)] + ":" \"$(source-files)\" ; } } -# Register generators. Depending on target type, either -# 'expect-success' or 'expect-failure' rule will be used. -generators.register-standard testing.expect-success : OBJ : COMPILE ; -generators.register-standard testing.expect-failure : OBJ : COMPILE_FAIL ; -generators.register-standard testing.expect-success : RUN_OUTPUT : RUN ; -generators.register-standard testing.expect-failure : RUN_OUTPUT : RUN_FAIL ; -generators.register-standard testing.expect-failure : EXE : LINK_FAIL ; -generators.register-standard testing.expect-success : EXE : LINK ; + +# Register generators. Depending on target type, either 'expect-success' or +# 'expect-failure' rule will be used. +generators.register-standard testing.expect-success : OBJ : COMPILE ; +generators.register-standard testing.expect-failure : OBJ : COMPILE_FAIL ; +generators.register-standard testing.expect-success : RUN_OUTPUT : RUN ; +generators.register-standard testing.expect-failure : RUN_OUTPUT : RUN_FAIL ; +generators.register-standard testing.expect-failure : EXE : LINK_FAIL ; +generators.register-standard testing.expect-success : EXE : LINK ; # Generator which runs an EXE and captures output. generators.register-standard testing.capture-output : EXE : RUN_OUTPUT ; -# Generator which creates target if sources runs successfully. -# Differers from RUN in that run output is not captured. -# The reason why it exists is that the 'run' rule is much better for -# automated testing, but is not user-friendly. See +# Generator which creates a target if sources runs successfully. Differs from +# RUN in that run output is not captured. The reason why it exists is that the +# 'run' rule is much better for automated testing, but is not user-friendly. See # http://article.gmane.org/gmane.comp.lib.boost.build/6353/ generators.register-standard testing.unit-test : EXE : UNIT_TEST ; # The action rules called by generators. -# Causes the 'target' to exist after bjam invocation if and only if all the +# Causes the 'target' to exist after bjam invocation if and only if all the # dependencies were successfully built. rule expect-success ( target : dependency + : requirements * ) { - **passed** $(target) : $(sources) ; + **passed** $(target) : $(sources) ; } -# Causes the 'target' to exist after bjam invocation if and only if all some -# of the dependencies were not successfully built. +# Causes the 'target' to exist after bjam invocation if and only if all some of +# the dependencies were not successfully built. rule expect-failure ( target : dependency + : properties * ) { local grist = [ MATCH ^<(.*)> : $(dependency:G) ] ; local marker = $(dependency:G=$(grist)*fail) ; (failed-as-expected) $(marker) ; - FAIL_EXPECTED $(dependency) ; + FAIL_EXPECTED $(dependency) ; LOCATE on $(marker) = [ on $(dependency) return $(LOCATE) ] ; RMOLD $(marker) ; DEPENDS $(marker) : $(dependency) ; - DEPENDS $(target) : $(marker) ; **passed** $(target) : $(marker) ; } -# The rule/action combination used to report successfull passing -# of a test. + +# The rule/action combination used to report successfull passing of a test. rule **passed** { - # Dump all the tests, if needed. - # We do it here, since dump should happen after all Jamfiles are read, - # and there's no such place currently defined (but should). - if ! $(.dumped-tests) && --dump-tests in [ modules.peek : ARGV ] + # Dump all the tests, if needed. We do it here, since dump should happen + # only after all Jamfiles have been read, and there's no such place + # currently defined (but there should be). + if ! $(.dumped-tests) && --dump-tests in [ modules.peek : ARGV ] { .dumped-tests = true ; dump-tests ; } - - # Force deletion of the target, in case any dependencies failed - # to build. + + # Force deletion of the target, in case any dependencies failed to build. RMOLD $(<) ; } + actions **passed** { echo passed > $(<) } + actions (failed-as-expected) { echo failed as expected > $(<) } + rule run-path-setup ( target : source : properties * ) { - # For testing, we need to make sure that all dynamic libraries needed by - # the test are found. So, we collect all paths from dependency libraries - # (via xdll-path property) and add whatever explicit dll-path user has - # specified. The resulting paths are added to environment on each test - # invocation. + # For testing, we need to make sure that all dynamic libraries needed by the + # test are found. So, we collect all paths from dependency libraries (via + # xdll-path property) and add whatever explicit dll-path user has specified. + # The resulting paths are added to the environment on each test invocation. local dll-paths = [ feature.get-values : $(properties) ] ; dll-paths += [ feature.get-values : $(properties) ] ; dll-paths += [ on $(source) return $(RUN_PATH) ] ; dll-paths = [ sequence.unique $(dll-paths) ] ; if $(dll-paths) - { + { dll-paths = [ sequence.transform path.native : $(dll-paths) ] ; - - PATH_SETUP on $(target) = - [ common.prepend-path-variable-command - [ os.shared-library-path-variable ] : $(dll-paths) ] ; - } + PATH_SETUP on $(target) = [ common.prepend-path-variable-command + [ os.shared-library-path-variable ] : $(dll-paths) ] ; + } } + local argv = [ modules.peek : ARGV ] ; if --preserve-test-targets in $(argv) { preserve-test-targets = true ; } + toolset.flags testing.capture-output ARGS ; toolset.flags testing.capture-output INPUT_FILES ; toolset.flags testing.capture-output LAUNCHER ; -# Runs executable 'sources' and stores stdout in file 'target'. -# If --preserve-test-targets command line option, removes the executable. -# The 'target-to-remove' parameter controls what should be removed: + +# Runs executable 'sources' and stores stdout in file 'target'. Unless +# --preserve-test-targets command line option has been specified, removes the +# executable. The 'target-to-remove' parameter controls what should be removed: # - if 'none', does not remove anything, ever # - if empty, removes 'source' # - if non-empty and not 'none', contains a list of sources to remove. @@ -376,19 +382,20 @@ rule capture-output ( target : source : properties * : targets-to-remove * ) { output-file on $(target) = $(target:S=.output) ; LOCATE on $(target:S=.output) = [ on $(target) return $(LOCATE) ] ; - + # The INCLUDES kill a warning about independent target... INCLUDES $(target) : $(target:S=.output) ; - # but it also puts .output into dependency graph, so we must tell jam - # it's OK if it cannot find the target or updating rule. - NOCARE $(target:S=.output) ; - + # but it also puts .output into dependency graph, so we must tell jam it's + # OK if it cannot find the target or updating rule. + NOCARE $(target:S=.output) ; + # This has two-fold effect. First it adds input files to the dependendency # graph, preventing a warning. Second, it causes input files to be bound - # before target is created. Therefore, they are bound using SEARCH setting - # on them and not LOCATE setting of $(target), as in other case (due to jam bug). + # before target is created. Therefore, they are bound using SEARCH setting + # on them and not LOCATE setting of $(target), as in other case (due to jam + # bug). DEPENDS $(target) : [ on $(target) return $(INPUT_FILES) ] ; - + if $(targets-to-remove) = none { targets-to-remove = ; @@ -397,23 +404,19 @@ rule capture-output ( target : source : properties * : targets-to-remove * ) { targets-to-remove = $(source) ; } - + run-path-setup $(target) : $(source) : $(properties) ; - + if ! $(preserve-test-targets) { TEMPORARY $(targets-to-remove) ; - # Set a second action on target that will - # be executed after capture output action. - # The 'RmTemps' rule has the 'ignore' modifier - # so it's always considered succeeded. - # This is needed for 'run-fail' test. For that - # test the target will be marked with FAIL_EXPECTED, - # and without 'ingore' successfull execution - # will be negated and be reported as failure. - # With 'ignore' we don't detect a case where - # removing files, but it's not likely to - # happen. + # Set a second action on target that will be executed after capture + # output action. The 'RmTemps' rule has the 'ignore' modifier so it's + # always considered succeeded. This is needed for 'run-fail' test. For + # that test the target will be marked with FAIL_EXPECTED, and without + # 'ignore' successful execution will be negated and be reported as + # failure. With 'ignore' we don't detect a case where removing files + # fails, but it's not likely to happen. RmTemps $(target) : $(targets-to-remove) ; } } @@ -421,34 +424,32 @@ rule capture-output ( target : source : properties * : targets-to-remove * ) if [ os.name ] = NT { - STATUS = %status% ; - SET_STATUS = "set status=%ERRORLEVEL%" ; + STATUS = %status% ; + SET_STATUS = "set status=%ERRORLEVEL%" ; RUN_OUTPUT_NL = "echo." ; - STATUS_0 = "%status% EQU 0 (" ; - STATUS_NOT_0 = "%status% NEQ 0 (" ; - VERBOSE = "%verbose% EQU 1 (" ; - ENDIF = ")" ; - SHELL_SET = "set " ; - - CATENATE = type ; - CP = copy ; + STATUS_0 = "%status% EQU 0 (" ; + STATUS_NOT_0 = "%status% NEQ 0 (" ; + VERBOSE = "%verbose% EQU 1 (" ; + ENDIF = ")" ; + SHELL_SET = "set " ; + CATENATE = type ; + CP = copy ; } else { - STATUS = "$status" ; - SET_STATUS = "status=$?" ; + STATUS = "$status" ; + SET_STATUS = "status=$?" ; RUN_OUTPUT_NL = "echo" ; - STATUS_0 = "test $status -eq 0 ; then" ; - STATUS_NOT_0 = "test $status -ne 0 ; then" ; - VERBOSE = "test $verbose -eq 1 ; then" ; - ENDIF = "fi" ; - SHELL_SET = "" ; - - CATENATE = cat ; - CP = cp ; + STATUS_0 = "test $status -eq 0 ; then" ; + STATUS_NOT_0 = "test $status -ne 0 ; then" ; + VERBOSE = "test $verbose -eq 1 ; then" ; + ENDIF = "fi" ; + SHELL_SET = "" ; + CATENATE = cat ; + CP = cp ; } -if --verbose-test in [ modules.peek : ARGV ] +if --verbose-test in [ modules.peek : ARGV ] { VERBOSE_TEST = 1 ; } @@ -460,10 +461,11 @@ else RM = [ common.rm-command ] ; + actions capture-output bind INPUT_FILES output-file { $(PATH_SETUP) - $(LAUNCHER) "$(>)" $(ARGS) "$(INPUT_FILES)" > "$(output-file)" 2>&1 + $(LAUNCHER) "$(>)" $(ARGS) "$(INPUT_FILES)" > "$(output-file)" 2>&1 $(SET_STATUS) $(RUN_OUTPUT_NL) >> "$(output-file)" echo EXIT STATUS: $(STATUS) >> "$(output-file)" @@ -478,15 +480,17 @@ actions capture-output bind INPUT_FILES output-file echo ====== BEGIN OUTPUT ====== $(CATENATE) "$(output-file)" echo ====== END OUTPUT ====== - $(ENDIF) - exit $(STATUS) + $(ENDIF) + exit $(STATUS) } + actions quietly updated ignore piecemeal together RmTemps { $(RM) "$(>)" } + MAKE_FILE = [ common.file-creation-command ] ; toolset.flags testing.unit-test LAUNCHER ; @@ -496,19 +500,21 @@ rule unit-test ( target : source : properties * ) run-path-setup $(target) : $(source) : $(properties) ; } -actions unit-test + +actions unit-test { $(PATH_SETUP) $(LAUNCHER) $(>) $(ARGS) && $(MAKE_FILE) $(<) } -IMPORT $(__name__) : compile compile-fail run run-fail link link-fail - : : compile compile-fail run run-fail link link-fail ; +IMPORT $(__name__) : compile compile-fail run run-fail link link-fail + : : compile compile-fail run run-fail link link-fail ; type.register TIME : time ; generators.register-standard testing.time : : TIME ; + rule record-time ( target : source : start end user system ) { local src-string = [$(source:G=:J=",")"] " ; @@ -517,21 +523,24 @@ rule record-time ( target : source : start end user system ) } IMPORT testing : record-time : : testing.record-time ; + + rule time ( target : source : properties * ) { - # Set up rule for recording timing information + # Set up rule for recording timing information. __TIMING_RULE__ on $(source) = testing.record-time $(target) ; - - # Make sure that the source is rebuilt any time we need to - # retrieve that information + + # Make sure that the source is rebuilt any time we need to retrieve that + # information. REBUILDS $(target) : $(source) ; } + actions time { echo user: $(USER_TIME) echo system: $(SYSTEM_TIME) - + echo user: $(USER_TIME)" seconds" > $(<) echo system: $(SYSTEM_TIME)" seconds" > $(<) } diff --git a/src/util/indirect.jam b/src/util/indirect.jam index 41fda47d1..749b9479e 100755 --- a/src/util/indirect.jam +++ b/src/util/indirect.jam @@ -1,14 +1,16 @@ -# Copyright 2003 Dave Abrahams -# Copyright 2003 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) +# Copyright 2003 Dave Abrahams +# Copyright 2003 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) import modules ; import numbers ; -# The pattern that indirect rules must match: module$rule + +# The pattern that indirect rules must match: module%rule .pattern = ^([^%]*)%([^%]+)$ ; - + + # # Type checking rules. # @@ -16,14 +18,15 @@ local rule indirect-rule ( x ) { if ! [ MATCH $(.pattern) : $(x) ] { - return "expected a string of the form module$rule, but got \""$(x)"\" for argument" ; + return "expected a string of the form module%rule, but got \""$(x)"\" for argument" ; } } -# make an indirect rule which calls the given rule; if context is -# supplied it is expected to be the module in which to invoke the rule -# by the 'call' rule below. Otherwise, the rule will be invoked in -# the module of this rule's caller. + +# Make an indirect rule which calls the given rule. If context is supplied it is +# expected to be the module in which to invoke the rule by the 'call' rule +# below. Otherwise, the rule will be invoked in the module of this rule's +# caller. rule make ( rulename bound-args * : context ? ) { context ?= [ CALLER_MODULE ] ; @@ -31,12 +34,12 @@ rule make ( rulename bound-args * : context ? ) return $(context)%$(rulename) $(bound-args) ; } -# make an indirect rule which calls the given rule. rulename may be a -# qualified rule; if so it is returned unchanged. Otherwise, if -# frames is not supplied, the result will be invoked (by 'call', -# below) in the module of the caller. Otherwise, frames > 1 -# specifies additional call frames to back up in order to find the -# module context. + +# Make an indirect rule which calls the given rule. 'rulename' may be a +# qualified rule; if so it is returned unchanged. Otherwise, if frames is not +# supplied, the result will be invoked (by 'call', below) in the module of the +# caller. Otherwise, frames > 1 specifies additional call frames to back up in +# order to find the module context. rule make-qualified ( rulename bound-args * : frames ? ) { if [ MATCH $(.pattern) : $(rulename) ] @@ -46,17 +49,16 @@ rule make-qualified ( rulename bound-args * : frames ? ) else { frames ?= 1 ; - # Take the first dot-separated element as module name. - # This disallows module names with dots, but allows rule names - # with dots. + # Take the first dot-separated element as module name. This disallows + # module names with dots, but allows rule names with dots. local module-context = [ MATCH ^([^.]*)\\..* : $(rulename) ] ; module-context ?= [ CALLER_MODULE $(frames) ] ; return [ make $(rulename) $(bound-args) : $(module-context) ] ; } } -# return the module name in which the given indirect rule will be -# invoked. + +# Returns the module name in which the given indirect rule will be invoked. rule get-module ( [indirect-rule] x ) { local m = [ MATCH $(.pattern) : $(x) ] ; @@ -67,37 +69,36 @@ rule get-module ( [indirect-rule] x ) return $(m[1]) ; } -# return the rulename that will be called when x is invoked + +# Returns the rulename that will be called when x is invoked. rule get-rule ( [indirect-rule] x ) { local m = [ MATCH $(.pattern) : $(x) ] ; return $(m[2]) ; } + # Invoke the given indirect-rule. rule call ( [indirect-rule] r args * : * ) { - return [ - modules.call-in [ get-module $(r) ] - : [ get-rule $(r) ] $(args) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) - ] ; + return [ modules.call-in [ get-module $(r) ] : [ get-rule $(r) ] $(args) + : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ; } + rule __test__ { import assert ; - + rule foo-barr! ( x ) { assert.equal $(x) : x ; } - + assert.equal [ get-rule [ make foo-barr! ] ] : foo-barr! ; assert.equal [ get-module [ make foo-barr! ] ] : [ CALLER_MODULE ] ; - + call [ make foo-barr! ] x ; call [ make foo-barr! x ] ; - - call [ make foo-barr! : [ CALLER_MODULE ] ] x ; }