diff --git a/new/build-request.jam b/new/build-request.jam index c188feada..df91518d3 100644 --- a/new/build-request.jam +++ b/new/build-request.jam @@ -139,11 +139,11 @@ rule from-command-line ( command-line * : feature-space ? ) { if ! [ MATCH "^(-).*" : $(e) ] { - # Build request spec either contains slashes, or has "=" in it, - # or is the name of an implicit property. + # Build request spec either has "=" in it, or completely + # consists of implicit feature values. local fs = feature-space ; - if [ MATCH "(.*/.*)" : $(e) ] || [ MATCH "(.*=.*)" : $(e) ] || - [ $(feature-space).is-implicit-value $(e) ] + if [ MATCH "(.*=.*)" : $(e) ] + || [ $(feature-space).is-implicit-value $(e:D=) ] { properties += [ convert-command-line-element $(e) : $(feature-space) ] ; } diff --git a/new/build-system.jam b/new/build-system.jam index 99378a50a..a41bb0060 100644 --- a/new/build-system.jam +++ b/new/build-system.jam @@ -22,7 +22,6 @@ if [ MATCH (--dump-projects) : [ modules.peek : ARGV ] ] build-request = [ build-request.from-command-line [ modules.peek : ARGV ] ] ; -targets = [ $(build-request).get-at 1 ] ; properties = [ $(build-request).get-at 2 ] ; # For the time being, just stick toolset to the build request. We'd need to # find a way to select default toolset collection and a method to override @@ -30,24 +29,67 @@ properties = [ $(build-request).get-at 2 ] ; expanded = [ build-request.expand $(properties) gcc ] ; -root-target = [ project.target "." ] ; +local target-ids = [ $(build-request).get-at 1 ] ; +local targets +local clean ; + +if "--clean" in [ modules.peek : ARGV ] +{ + clean = true ; +} + +for local id in $(target-ids) +{ + if $(id) = clean + { + clean = true ; + } + else + { + local t = [ project.find-target $(id) : "." ] ; + if ! $(t) + { + print.wrapped-text "error: target" $(id) "does not exist" ; + EXIT ; + } + else + { + targets += $(t) ; + } + } +} + +if ! $(targets) +{ + targets += [ project.target "." ] ; +} + virtual-targets = ; if $(expanded) { for local p in $(expanded) { - $(root-target).direct-build-request [ feature.split $(p) ] ; + for local t in $(targets) + { + $(t).direct-build-request [ feature.split $(p) ] ; + } } for local p in $(expanded) { - virtual-targets += [ $(root-target).generate [ feature.split $(p) ] ] ; + for local t in $(targets) + { + virtual-targets += [ $(t).generate [ feature.split $(p) ] ] ; + } } } else { - virtual-targets = [ $(root-target).generate ] ; + for local t in $(targets) + { + virtual-targets += [ $(t).generate ] ; + } } @@ -59,7 +101,14 @@ for t in $(virtual-targets) NOTFILE all ; DEPENDS all : $(actual-targets) ; -# If there are any targets in the command line, cause them to be updated -UPDATE $(targets) ; +if $(clean) +{ + UPDATE clean ; +} +else +{ + UPDATE all ; +} + diff --git a/new/project.jam b/new/project.jam index 12c500365..ac882f37f 100644 --- a/new/project.jam +++ b/new/project.jam @@ -107,6 +107,33 @@ rule lookup ( id : current-location ) } } +# Agressively tries to lookup target: if it's not found, loads +# project at location specified by target-id and tries again +rule lookup-with-load ( id : current-location ) +{ + local location = [ lookup $(id) : $(current-location) ] ; + if ! $(location) + { + # Try to load the project at the specified location + location = [ MATCH (.*)@(.*) : $(project-id) ] ; + location = [ path.root $(location[1]) $(current-location) ] ; + if [ find-jamfile $(location) ] + { + load $(location) ; + # If there's project-id relative to the 'location' the + # jamfile at 'location' should made those available somehow. + location = [ lookup $(id) : $(current-location) ] ; + } + else + { + location = ; + } + } + return $(location) ; +} + + + # Helper for 'find-target' local rule remove-trailing-slash ( string ) { @@ -120,8 +147,8 @@ local rule remove-trailing-slash ( string ) } } -# Given an 'id' for a target, return an instance of 'main-target' that -# corresponds to it. If there's no such main-target, returns empty string. +# Given an 'id' for a target, return an instance of 'abstract-target' that +# corresponds to it. If there's no such target, returns empty string. # The project referred to by id is loaded if it is not already loaded. rule find-target ( id : current-location ) { @@ -154,38 +181,46 @@ rule find-target ( id : current-location ) target-id = $(split[3]) ; } - local location = [ lookup $(project-id) : $(current-location) ] ; - if ! $(location) + # First check if there's a project with such id. In that case, we'll + # return project target for it. + + local location ; + if [ MATCH (@) : $(id) ] { - # Try to load the project at the specified location - location = [ MATCH (.*)@(.*) : $(project-id) ] ; - if [ find-jamfile $(location[1]) ] - { - load $(location[1]) ; - # If there's project-id relative to the 'location' the - # jamfile at 'location' should made those available somehow. - location = [ lookup $(project-id) : $(current-location) ] ; - } - else - { - location = ; - } + location = [ lookup-with-load $(id) + : $(current-location) ] ; + } + else + { + # When id has no "@" and we're looking for a project, treat id + # as path. + location = [ lookup-with-load $(id)@ : $(current-location) ] ; } - if $(location) { - local project-target = [ project.target $(location) ] ; - if [ $(project-target).has-main-target $(target-id) ] - { - return [ $(project-target).main-target $(target-id) ] ; - } - } - else if $(explicit) + if $(location) { - print.wrapped-text - "The target id" $(id) " specified by project at" $(current-location) - "is invalid" ; - EXIT ; + return [ project.target $(location) ] ; } + else + { + # Now treat 'id' as referring to a main target + location = [ lookup-with-load $(project-id) : $(current-location) ] ; + + if $(location) { + local project-target = [ project.target $(location) ] ; + if [ $(project-target).has-main-target $(target-id) ] + { + return [ $(project-target).main-target $(target-id) ] ; + } + } + else if $(explicit) + { + print.wrapped-text + "The target id" $(id) " specified by project at" $(current-location) + "is invalid" ; + EXIT ; + } + } } # diff --git a/test/BoostBuild.py b/test/BoostBuild.py index 40de83ee0..4d7b33048 100644 --- a/test/BoostBuild.py +++ b/test/BoostBuild.py @@ -179,6 +179,7 @@ class Tester(TestCmd.TestCmd): self.tree = build_tree(self.workdir) self.difference = trees_difference(self.previous_tree, self.tree) + self.difference.ignore_directories() self.unexpected_difference = copy.deepcopy(self.difference) self.last_build_time = time.time() diff --git a/test/project_test3.py b/test/project_test3.py index e5a99a66c..7231638d2 100644 --- a/test/project_test3.py +++ b/test/project_test3.py @@ -1,6 +1,6 @@ #!/usr/bin/python -from BoostBuild import Tester +from BoostBuild import Tester, List import os from string import strip @@ -101,4 +101,30 @@ t.expect_removal(["bin/gcc/debug/a.obj", "lib3/bin/gcc/debug/f.obj", ]) +# Now test target ids in command line +t.set_tree("project-test3") +t.run_build_system("lib/b.obj") +t.expect_addition("lib/bin/gcc/debug/b.obj") +t.expect_nothing_more() + +t.run_build_system("clean lib/b.obj") +t.expect_removal("lib/bin/gcc/debug/b.obj") +t.expect_nothing_more() + +t.run_build_system("release lib2@helper/e.obj @/lib3/f.obj") +t.expect_addition("lib2/helper/bin/gcc/release/e.obj") +t.expect_addition("lib3/bin/gcc/release/f.obj") +t.expect_nothing_more() + +# Test project ids in command line work as well +t.set_tree("project-test3") +t.run_build_system("@/lib2") +t.expect_addition("lib2/bin/gcc/debug/" * List("c.obj d.obj l.exe")) +t.expect_addition("bin/gcc/debug/a.obj") +t.expect_nothing_more() + +t.run_build_system("lib") +t.expect_addition("lib/bin/gcc/debug/" * List("b.obj m.exe")) +t.expect_nothing_more() + t.cleanup() diff --git a/test/tree.py b/test/tree.py index 4c05ab810..abe1dd5fb 100644 --- a/test/tree.py +++ b/test/tree.py @@ -21,6 +21,16 @@ class Trees_difference: self.removed_files.extend(other.removed_files) self.modified_files.extend(other.modified_files) self.touched_files.extend(other.touched_files) + + def ignore_directories(self): + "Removes directories for list of found differences" + + def not_dir(x): + return x[-1] != "/" + self.added_files = filter(not_dir, self.added_files) + self.removed_files = filter(not_dir, self.removed_files) + self.modified_files = filter(not_dir, self.modified_files) + self.touched_files = filter(not_dir, self.touched_files) def pprint(self): print "Added files :", self.added_files diff --git a/v2/build/build-request.jam b/v2/build/build-request.jam index c188feada..df91518d3 100644 --- a/v2/build/build-request.jam +++ b/v2/build/build-request.jam @@ -139,11 +139,11 @@ rule from-command-line ( command-line * : feature-space ? ) { if ! [ MATCH "^(-).*" : $(e) ] { - # Build request spec either contains slashes, or has "=" in it, - # or is the name of an implicit property. + # Build request spec either has "=" in it, or completely + # consists of implicit feature values. local fs = feature-space ; - if [ MATCH "(.*/.*)" : $(e) ] || [ MATCH "(.*=.*)" : $(e) ] || - [ $(feature-space).is-implicit-value $(e) ] + if [ MATCH "(.*=.*)" : $(e) ] + || [ $(feature-space).is-implicit-value $(e:D=) ] { properties += [ convert-command-line-element $(e) : $(feature-space) ] ; } diff --git a/v2/build/project.jam b/v2/build/project.jam index 12c500365..ac882f37f 100644 --- a/v2/build/project.jam +++ b/v2/build/project.jam @@ -107,6 +107,33 @@ rule lookup ( id : current-location ) } } +# Agressively tries to lookup target: if it's not found, loads +# project at location specified by target-id and tries again +rule lookup-with-load ( id : current-location ) +{ + local location = [ lookup $(id) : $(current-location) ] ; + if ! $(location) + { + # Try to load the project at the specified location + location = [ MATCH (.*)@(.*) : $(project-id) ] ; + location = [ path.root $(location[1]) $(current-location) ] ; + if [ find-jamfile $(location) ] + { + load $(location) ; + # If there's project-id relative to the 'location' the + # jamfile at 'location' should made those available somehow. + location = [ lookup $(id) : $(current-location) ] ; + } + else + { + location = ; + } + } + return $(location) ; +} + + + # Helper for 'find-target' local rule remove-trailing-slash ( string ) { @@ -120,8 +147,8 @@ local rule remove-trailing-slash ( string ) } } -# Given an 'id' for a target, return an instance of 'main-target' that -# corresponds to it. If there's no such main-target, returns empty string. +# Given an 'id' for a target, return an instance of 'abstract-target' that +# corresponds to it. If there's no such target, returns empty string. # The project referred to by id is loaded if it is not already loaded. rule find-target ( id : current-location ) { @@ -154,38 +181,46 @@ rule find-target ( id : current-location ) target-id = $(split[3]) ; } - local location = [ lookup $(project-id) : $(current-location) ] ; - if ! $(location) + # First check if there's a project with such id. In that case, we'll + # return project target for it. + + local location ; + if [ MATCH (@) : $(id) ] { - # Try to load the project at the specified location - location = [ MATCH (.*)@(.*) : $(project-id) ] ; - if [ find-jamfile $(location[1]) ] - { - load $(location[1]) ; - # If there's project-id relative to the 'location' the - # jamfile at 'location' should made those available somehow. - location = [ lookup $(project-id) : $(current-location) ] ; - } - else - { - location = ; - } + location = [ lookup-with-load $(id) + : $(current-location) ] ; + } + else + { + # When id has no "@" and we're looking for a project, treat id + # as path. + location = [ lookup-with-load $(id)@ : $(current-location) ] ; } - if $(location) { - local project-target = [ project.target $(location) ] ; - if [ $(project-target).has-main-target $(target-id) ] - { - return [ $(project-target).main-target $(target-id) ] ; - } - } - else if $(explicit) + if $(location) { - print.wrapped-text - "The target id" $(id) " specified by project at" $(current-location) - "is invalid" ; - EXIT ; + return [ project.target $(location) ] ; } + else + { + # Now treat 'id' as referring to a main target + location = [ lookup-with-load $(project-id) : $(current-location) ] ; + + if $(location) { + local project-target = [ project.target $(location) ] ; + if [ $(project-target).has-main-target $(target-id) ] + { + return [ $(project-target).main-target $(target-id) ] ; + } + } + else if $(explicit) + { + print.wrapped-text + "The target id" $(id) " specified by project at" $(current-location) + "is invalid" ; + EXIT ; + } + } } # diff --git a/v2/test/BoostBuild.py b/v2/test/BoostBuild.py index 40de83ee0..4d7b33048 100644 --- a/v2/test/BoostBuild.py +++ b/v2/test/BoostBuild.py @@ -179,6 +179,7 @@ class Tester(TestCmd.TestCmd): self.tree = build_tree(self.workdir) self.difference = trees_difference(self.previous_tree, self.tree) + self.difference.ignore_directories() self.unexpected_difference = copy.deepcopy(self.difference) self.last_build_time = time.time() diff --git a/v2/test/project_test3.py b/v2/test/project_test3.py index e5a99a66c..7231638d2 100644 --- a/v2/test/project_test3.py +++ b/v2/test/project_test3.py @@ -1,6 +1,6 @@ #!/usr/bin/python -from BoostBuild import Tester +from BoostBuild import Tester, List import os from string import strip @@ -101,4 +101,30 @@ t.expect_removal(["bin/gcc/debug/a.obj", "lib3/bin/gcc/debug/f.obj", ]) +# Now test target ids in command line +t.set_tree("project-test3") +t.run_build_system("lib/b.obj") +t.expect_addition("lib/bin/gcc/debug/b.obj") +t.expect_nothing_more() + +t.run_build_system("clean lib/b.obj") +t.expect_removal("lib/bin/gcc/debug/b.obj") +t.expect_nothing_more() + +t.run_build_system("release lib2@helper/e.obj @/lib3/f.obj") +t.expect_addition("lib2/helper/bin/gcc/release/e.obj") +t.expect_addition("lib3/bin/gcc/release/f.obj") +t.expect_nothing_more() + +# Test project ids in command line work as well +t.set_tree("project-test3") +t.run_build_system("@/lib2") +t.expect_addition("lib2/bin/gcc/debug/" * List("c.obj d.obj l.exe")) +t.expect_addition("bin/gcc/debug/a.obj") +t.expect_nothing_more() + +t.run_build_system("lib") +t.expect_addition("lib/bin/gcc/debug/" * List("b.obj m.exe")) +t.expect_nothing_more() + t.cleanup() diff --git a/v2/test/tree.py b/v2/test/tree.py index 4c05ab810..abe1dd5fb 100644 --- a/v2/test/tree.py +++ b/v2/test/tree.py @@ -21,6 +21,16 @@ class Trees_difference: self.removed_files.extend(other.removed_files) self.modified_files.extend(other.modified_files) self.touched_files.extend(other.touched_files) + + def ignore_directories(self): + "Removes directories for list of found differences" + + def not_dir(x): + return x[-1] != "/" + self.added_files = filter(not_dir, self.added_files) + self.removed_files = filter(not_dir, self.removed_files) + self.modified_files = filter(not_dir, self.modified_files) + self.touched_files = filter(not_dir, self.touched_files) def pprint(self): print "Added files :", self.added_files