From bfca88c2619c779ca8580a0229498cc21bfef1d7 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Mon, 18 Sep 2006 08:58:37 +0000 Subject: [PATCH] Merge:\n * build/property-set.jam (refine-from-user-input): New, extracted from main-target-requirements, with extra code to handle "-value" syntax. * build/targets.jam (main-target-requirements): Use the above. * build/project.jam (project-attributes.set): Likewise. [SVN r35160] --- src/build/project.jam | 50 +++++++++++++++++++++++++++-------- src/build/property-set.jam | 53 ++++++++++++++++++++++++++++++++++++++ src/build/targets.jam | 9 +++---- 3 files changed, 95 insertions(+), 17 deletions(-) diff --git a/src/build/project.jam b/src/build/project.jam index feecab007..08565be90 100644 --- a/src/build/project.jam +++ b/src/build/project.jam @@ -568,16 +568,9 @@ class project-attributes } else if $(attribute) = "requirements" { - local result = [ property-set.create-from-user-input - $(specification) : $(self.project-module) $(self.location) ] ; - - # If we have inherited properties, need to refine them with the - # specified. - local current = $(self.requirements) ; - if $(current) - { - result = [ $(current).refine $(result) ] ; - } + local result = [ property-set.refine-from-user-input + $(self.requirements) : $(specification) + : $(self.project-module) : $(self.location) ] ; if $(result[1]) = "@error" { @@ -740,6 +733,29 @@ rule use ( id : location ) .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. +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) + { + # Create the project data, and bring in the project rules + # into the module. + project.initialize $(__name__) ; + + # 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) ; + } +} + # This module defines rules common to all projects module project-rules { @@ -942,7 +958,19 @@ module project-rules } return $(result) ; - } + } + + # Calculates conditional requirements for multiple requirements + # at once. This is a shorthand to be reduce duplication and to + # keep an inline declarative syntax. For example: + # + # lib x : x.cpp : [ gcc debug : + # DEBUG_EXCEPTION DEBUG_TRACE ] ; + # + rule conditional ( condition + : requirements * ) + { + return $(condition:J=,):$(requirements) ; + } } diff --git a/src/build/property-set.jam b/src/build/property-set.jam index 3fda5e8f7..00e8383e6 100644 --- a/src/build/property-set.jam +++ b/src/build/property-set.jam @@ -7,6 +7,7 @@ import "class" : new ; import feature ; import property ; import sequence ; +import set ; # Class for storing a set of properties. # - there's 1<->1 correspondence between identity and value. No @@ -386,6 +387,58 @@ rule create-from-user-input ( raw-properties * : jamfile-module location ) return $(result) ; } +# 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. +# +# +rule refine-from-user-input ( parent-requirements : specification * + : project-module : location ) +{ + if ! $(specification) + { + return $(parent-requirements) ; + } + else + { + local add-requirements ; + local remove-requirements ; + + for local r in $(specification) + { + local m = [ MATCH "^-(.*)" : $(r) ] ; + if $(m) + { + remove-requirements += $(m) ; + } + else + { + add-requirements += $(r) ; + } + } + + if $(remove-requirements) + { + parent-requirements = [ property-set.create + [ set.difference [ $(parent-requirements).raw ] + : $(remove-requirements) ] ] ; + specification = $(add-requirements) ; + } + + local requirements = [ property-set.create-from-user-input + $(specification) : $(project-module) $(location) ] ; + + requirements = [ $(parent-requirements).refine $(requirements) ] ; + return $(requirements) ; + } +} + # Returns property-set with empty set of properties. diff --git a/src/build/targets.jam b/src/build/targets.jam index 2c8689ec0..94bfc6b28 100644 --- a/src/build/targets.jam +++ b/src/build/targets.jam @@ -1400,13 +1400,10 @@ rule main-target-requirements ( : project # Project where the main target is to be declared ) { - local loc = [ $(project).get location ] ; - local jamfile-module = [ $(project).project-module ] ; - local requirements = [ property-set.create-from-user-input $(specification) - : $(jamfile-module) $(loc) ] ; + local requirements = [ property-set.refine-from-user-input + [ $(project).get requirements ] : $(specification) : + [ $(project).project-module ] : [ $(project).get location ] ] ; - local project-requirements = [ $(project).get requirements ] ; - requirements = [ $(project-requirements).refine $(requirements) ] ; if $(requirements[1]) = "@error" { errors.error "Conflicting requirements for target:" $(requirements) ;