diff --git a/src/build/targets.jam b/src/build/targets.jam index d9abed230..3e46c81a1 100644 --- a/src/build/targets.jam +++ b/src/build/targets.jam @@ -4,12 +4,7 @@ # warranty, and with no claim as to its suitability for any purpose. -# There are three kinds of targets: "abstract", which correspond to -# targets explicitly defined in Jamfile; "virtual", which correspond -# to possible build product with defined properties and "actual", which -# are targets in Jam sense. The "virtual" targets are generated during -# search for the best transformation sequence, and some of them can be -# later 'actualized'. +# Supports 'abstact' targets, which are targets explicitly defined in Jamfile. # # Abstract targets are represented by classes derived from 'abstract-target' class. # The first abstract target is 'project-target', which is created for each @@ -252,6 +247,7 @@ rule basic-target ( name : project : sources * : requirements * : default-build * ) { import build-request ; + import virtual-target ; abstract-target.__init__ $(name) : $(project) ; @@ -309,9 +305,7 @@ rule basic-target ( name : project else { # Just a source file - # FIXME: break an import cycle in a rude way - import type ; - source-targets += [ type.from-file $(s) : $(self.project) ] ; + source-targets += [ virtual-target.from-file $(s) : $(self.project) ] ; } } self.generated.$(property-path) = @@ -426,231 +420,22 @@ rule main-target-alternative ( target-name project class-name : $(a4) : $(a5) : $(a6) : $(a7) : $(a8) : $(a9) ] ; } -# Class which represents a virtual target -rule virtual-target ( name : type ? : project - : subvariant * # Property sets which define this subvariant - ) + +rule typed-target ( name : project : type + : sources * : requirements * : default-build * ) { - self.name = $(name) ; + ECHO "Typed target: type is " $(type) ; + basic-target.__init__ $(name) : $(project) + : $(sources) : $(requirements) : $(defailt-build) ; + self.type = $(type) ; - self.subvariant = $(subvariant) ; - self.project = $(project) ; - - self.includes = ; - self.dependencies = ; - self.action = ; - - self.actual-name = ; - - - # Name of the target - rule name ( ) { return $(self.name) ; } - rule type ( ) { return $(self.type) ; } - - - # Property set that distinguished different variants of a target. - # May be a subset of the property set that is used for building. - # Determines the location of target, in an unspecified way. - rule subvariant ( ) { return $(self.subvariant) ; } - - # Project where this target was declared - rule project ( ) { return $(self.project) ; } - - rule includes ( ) { return $(self.includes) ; } - rule add_includes ( i + ) + rule construct ( source-targets * : properties * ) { - self.includes = [ sequence.merge $(self.includes) - : [ sequence.insertion-sort $(i) ] ] ; - } - - rule dependencies ( ) { return $(self.dependencies) ; } - rule depends ( d + ) - { - self.dependencies = [ sequence.merge $(self.dependencies) - : [ sequence.insertion-sort $(d) ] ] ; - } - - # If 'a' is supplied, sets action to 'a'. - # Returns the action currently set. - rule action ( a ? ) - { - if $(a) { - self.action = $(a) ; - } - return $(self.action) ; - } - - # Specified an extra element to be added to the target path. - rule extra-path ( p ) - { - self.extra-path = $(p) ; - } - - # Generates all the actual targets and build instructions needed to build - # this target. Returns the actual target name. Can be called several times. - # Does no processing for other targets that 'action' will generate. - # Rationale: we might need only one file from the set created by an - # action, and there's no need to run the action if the file is up-to-date, - # only because some other file in set is out-of-date. - rule actualize ( ) - { - if ! $(self.actual-name) { - - self.actual-name = [ actual-name ] ; - for local i in $(dependencies) { - DEPENDS $(name) : [ $(i).actualize ] ; - } - for local i in $(includes) { - INCLUDES $(name) : [ $(i).actualize ] ; - } - local a = [ action ] ; - if $(a) { - $(a).actualize ; - local path = [ path.join [ project.attribute $(self.project) location ] - "bin" [ property.as-path [ subvariant ] ] - $(self.extra-path) ] ; - path = [ path.native $(path) ] ; - LOCATE on $(self.actual-name) = $(path) ; - DEPENDS $(self.actual-name) : $(path) ; - common.MkDir $(path) ; - common.Clean clean : $(self.actual-name) ; - } else { - SEARCH on $(self.actual-name) = - [ path.native [ project.attribute $(self.project) source-location ] ] ; - } - } - return $(self.actual-name) ; - } - - rule str ( ) - { - local action = [ action ] ; - local filename = [ sequence.join $(self.name) "." $(self.type) ] ; - if $(action) - { - local sources = [ $(action).sources ] ; - - local ss ; - for local s in $(sources) - { - ss += [ $(s).str ] ; - } - - local name = [ $(action).action_name ] ; - return "{" $(name)-$(filename) $(ss) "}" ; - } - else - { - return "{" $(filename) "}" ; - } - } - - rule less ( a ) - { - if [ str ] < [ $(a).str ] - { - return true ; - } - } - - rule equal ( a ) - { - if [ str ] = [ $(a).str ] - { - return true ; - } - } - -# private: - rule actual-name ( ) - { - if ! $(self.actual-name) - { - local project-location = [ project.attribute $(self.project) location ] ; - local location-grist = - [ sequence.join [ regex.split $(project-location) "/" ] : "!" ] ; - local property-grist = - [ property.as-path $(self.subvariant) ] ; - # Set empty value to avoid eating adjacent text - local grist = $(location-grist)/$(property-grist) ; - if ! $(self.subvariant) { - grist = $(location-grist) ; - } - if $(self.type) - { - self.actual-name = [ sequence.join <$(grist)>$(self.name) [ type.suffix $(self.type) ] : "." ] ; - } - else - { - self.actual-name = <$(grist)>$(self.name) ; - } - } - return $(self.actual-name) ; - } + local r = [ generators.construct-dbg $(self.project) $(self.name) : $(self.type) + : $(properties) $(self.type) : $(source-targets) ] ; + return [ $(r).get-at 1 ] [ $(r).get-at 2 ] ; + } } -class virtual-target ; - -# Class which represents an action. -# Both 'targets' and 'sources' should list instances of 'virtual-target'. -# Action name should name a rule with this prototype -# rule action_name ( targets + : sources * : properties * ) -# Targets and sources are passed as actual jam targets. The rule may -# not establish dependency relationship, but should do everything else. -rule action ( targets + : sources * : action_name : properties * ) -{ - self.targets = $(targets) ; - self.sources = $(sources) ; - self.action_name = $(action_name) ; - self.properties = $(properties) ; - - rule targets ( ) - { - return $(self.targets) ; - } - - rule sources ( ) - { - return $(self.sources) ; - } - - rule action_name ( ) - { - return $(self.action_name) ; - } - - rule properties ( ) - { - return $(self.properties) ; - } - - # Generates actual build instructions. - rule actualize ( ) - { - if ! $(self.actualized) - { - self.actualized = true ; - - local actual_targets ; - for local i in [ targets ] - { - actual_targets += [ $(i).actualize ] ; - } - - local actual_sources ; - for local i in [ sources ] - { - actual_sources += [ $(i).actualize ] ; - } - - DEPENDS $(actual_targets) : $(actual_sources) ; - - $(self.action_name) - $(actual_targets) : $(actual_sources) : [ properties ] ; - } - } -} -class action ; - - - + +class typed-target : basic-target ; diff --git a/src/build/type.jam b/src/build/type.jam index ec5e62c29..55c98cd8a 100644 --- a/src/build/type.jam +++ b/src/build/type.jam @@ -7,7 +7,6 @@ # typed targets. import feature ; -import targets ; import generators : * ; import class : class new ; @@ -17,12 +16,14 @@ feature.feature base-target-type : : composite optional ; feature.feature main-target-type : : optional incidental ; # Registers a target type, possible derived from a 'base-type'. -# If 'suffix' is provided, it is associated with this target type. +# If 'suffixes' are provided, they given all the suffixes that mean a file is of 'type'. +# Also, the first element gives the suffix to be used when constructing and object of +# 'type'. # If 'main' is given, a rule with the same name as the target type # and signature # rule target-type ( name : sources * : requirements * : default-build ) # will be added to the global scope. -rule register ( type : suffix ? : base-type ? : main ? ) +rule register ( type : suffixes * : base-type ? : main ? ) { if $(type) in $(.types) { @@ -31,8 +32,8 @@ rule register ( type : suffix ? : base-type ? : main ? ) else { .types += $(type) ; - .suffix.$(type) = $(suffix) ; - .type.$(suffix) = $(type) ; + .suffix.$(type) = $(suffixes[1]) ; + .type.$(suffixes) = $(type) ; feature.extend target-type : $(type) ; feature.compose $(type) : $(base-type:G=) ; feature.compose $(type) : $(base-type:G=) ; @@ -44,49 +45,19 @@ rule register ( type : suffix ? : base-type ? : main ? ) } } -# Returns suffix to the 'type'. -rule suffix ( type ) +# Returns suffix that should be used when generating target of 'type'. +rule generated-target-suffix ( type ) { return $(.suffix.$(type)) ; } -# Creates a virtual target with approariate name and type from 'file'. -# TODO: passing project with all virtual targets starts to be annoying. -rule from-file ( file : project ) +# Returns file type given its suffix. +rule type ( suffix ) { - local name = $(file:S=) ; - local type = $(.type$(file:S)) ; - if ! $(type) - { - # warning "cannot determine type for file $(file)" ; - return [ new virtual-target $(file) : : $(project) ] ; - } - else - { - return [ new virtual-target $(name) : $(type) : $(project) ] ; - } + return $(.type$(suffix)) ; } -rule typed-target ( name : project : type - : sources * : requirements * : default-build * ) -{ - ECHO "Typed target: type is " $(type) ; - basic-target.__init__ $(name) : $(project) - : $(sources) : $(requirements) : $(defailt-build) ; - - self.type = $(type) ; - - rule construct ( source-targets * : properties * ) - { - local r = [ generators.construct-dbg $(self.project) $(self.name) : $(self.type) - : $(properties) $(self.type) : $(source-targets) ] ; - return [ $(r).get-at 1 ] [ $(r).get-at 2 ] ; - } -} - -class typed-target : basic-target ; - rule main-target-rule ( name : sources * : requirements * : default-build ? ) { # First find requuired target type, which is equal to the name used to @@ -99,13 +70,3 @@ rule main-target-rule ( name : sources * : requirements * : default-build ? ) ; } -rule construct-dbg-x ( target-types + : properties * : source-files + ) -{ - local sources ; - for local s in $(source-files) - { - sources += [ from-file $(s) : "some project" ] ; - } - return [ construct-dbg "result" : $(target-types) : $(properties) : - $(sources) ] ; -} diff --git a/test/generators-test/Jamfile b/test/generators-test/Jamfile index f6aff8a7e..6cb8b65c8 100644 --- a/test/generators-test/Jamfile +++ b/test/generators-test/Jamfile @@ -1,5 +1,5 @@ -exe a : a.cpp b.cpp c.ui d.wd x.l y.x_pro lib/aux ; +exe a : a.cpp b.cxx c.ui d.wd x.l y.x_pro lib/aux ; #exe a : a.cpp b.cpp c.ui d.wd x.l y.x_pro ; nm_exe e : e.cpp ; diff --git a/test/generators-test/b.cpp b/test/generators-test/b.cxx similarity index 100% rename from test/generators-test/b.cpp rename to test/generators-test/b.cxx diff --git a/test/generators-test/project-root.jam b/test/generators-test/project-root.jam index 2a9196a69..96643aef5 100644 --- a/test/generators-test/project-root.jam +++ b/test/generators-test/project-root.jam @@ -10,7 +10,7 @@ import type ; type.register EXE : : : main ; type.register LIB : : : main ; -type.register CPP : cpp ; +type.register CPP : cpp cxx ; type.register C : c ; type.register OBJ : o ; type.register LEX : l ;