diff --git a/v2/build/project.jam b/v2/build/project.jam index 4a3a2e96e..e27791380 100644 --- a/v2/build/project.jam +++ b/v2/build/project.jam @@ -774,6 +774,37 @@ rule extension ( id : options * : * ) } } +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) ] + : [ 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. + for local p in $(paths) + { + result += [ path.root $(p) [ path.pwd ] ] ; + } + } + 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. + result = $(paths:D="") ; + } + + return $(result) ; +} + + # This module defines rules common to all projects module project-rules { @@ -945,40 +976,23 @@ module project-rules rule glob ( wildcards + : excludes * ) { - import path ; import project ; - import sequence ; - - local current = [ project.current ] ; - - local location = [ $(current).get source-location ] ; - - local result ; - local paths = [ path.glob $(location) - : [ sequence.transform path.make : $(wildcards) ] - : [ sequence.transform path.make : $(excludes) ] ] ; - if $(wildcards:D) - { - # 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. - for local p in $(paths) - { - result += [ path.root $(p) [ path.pwd ] ] ; - } - } - 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. - result = $(paths:D="") ; - } - - return $(result) ; + 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 ] + : $(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: diff --git a/v2/test/project_glob.py b/v2/test/project_glob.py index a902ae1bc..39ec39305 100644 --- a/v2/test/project_glob.py +++ b/v2/test/project_glob.py @@ -103,6 +103,28 @@ exe a : [ glob foo/*.cpp bar/*.cpp : bar/bad* ] ../d2/d//l ; t.run_build_system(subdir="d1") t.expect_addition("d1/bin/$toolset/debug/a.exe") + + +# Test that 'glob-tree' works. +t.rm("d1/bin/$toolset/debug/a.exe") +t.write("d1/Jamfile", """ +project : source-location src ; +exe a : [ glob-tree *.cpp : bad* ] ../d2/d//l ; +""") +t.run_build_system(subdir="d1") +t.expect_addition("d1/bin/$toolset/debug/a.exe") + +# Test that directory names in patterns for +# 'glob-tree' are rejected. +t.write("d1/Jamfile", """ +project : source-location src ; +exe a : [ glob-tree foo/*.cpp bar/*.cpp : bad* ] ../d2/d//l ; +""") + +t.run_build_system(subdir="d1", status=1) +t.expect_output_line("error: The patterns * may not include directory") + + t.rm("d1/src/bar/bad.cpp") # Test that 'glob' works with absolute names