From 0a5e4a45812aeb70cf1476264d6b87188474ae9b Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Thu, 23 Nov 2006 09:30:09 +0000 Subject: [PATCH] Merge glob/glob-tree changes from HEAD [SVN r36162] --- src/build/project.jam | 79 +++++++++++++++++++++++++------------------ src/util/path.jam | 17 +++++++--- test/project_glob.py | 32 ++++++++++++++++-- 3 files changed, 90 insertions(+), 38 deletions(-) diff --git a/src/build/project.jam b/src/build/project.jam index f37161f88..e27791380 100644 --- a/src/build/project.jam +++ b/src/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 { @@ -943,41 +974,25 @@ module project-rules } } - rule glob ( wildcards + ) + 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) ] ] ; - 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/src/util/path.jam b/src/util/path.jam index 33403887b..dbf153aec 100644 --- a/src/util/path.jam +++ b/src/util/path.jam @@ -222,10 +222,11 @@ rule pwd ( ) # For example: # [ glob . : *.cpp ] # [ glob . : */build/Jamfile ] -rule glob ( dirs * : patterns + ) +rule glob ( dirs * : patterns + : exclude-patterns * ) { local result ; local real-patterns ; + local real-exclude-patterns ; for local d in $(dirs) { for local p in $(patterns) @@ -233,11 +234,19 @@ rule glob ( dirs * : patterns + ) local pattern = [ path.root $(p) $(d) ] ; real-patterns += [ path.native $(pattern) ] ; } + + for local p in $(exclude-patterns) + { + local pattern = [ path.root $(p) $(d) ] ; + real-exclude-patterns += [ path.native $(pattern) ] ; + } } + + local inc = [ GLOB-RECURSIVELY $(real-patterns) ] ; + local exc = [ GLOB-RECURSIVELY $(real-exclude-patterns) ] ; return [ sequence.transform path.make : - [ GLOB-RECURSIVELY $(real-patterns) ] ] ; - + [ set.difference $(inc) : $(exc) ] ] ; } # Recursive version of GLOB. Builds the glob of files while @@ -273,7 +282,7 @@ local rule .glob-tree ( roots * : patterns * : exclude-patterns * ) } if $(subdirs) { - result += [ .glob-tree $(subdirs) : $(patterns) ] ; + result += [ .glob-tree $(subdirs) : $(patterns) : $(exclude-patterns) ] ; } return $(result) ; } diff --git a/test/project_glob.py b/test/project_glob.py index 412bf77db..39ec39305 100644 --- a/test/project_glob.py +++ b/test/project_glob.py @@ -76,7 +76,8 @@ exe a : [ glob *.cpp ] ../d2/d//l ; t.run_build_system(subdir="d1") t.expect_addition("d1/bin/$toolset/debug/a.exe") -# Test that wildcards can include directories +# Test that wildcards can include directories. Also +# test exclusion patterns. t.rm("d1") t.write("d1/src/foo/a.cpp", """ @@ -90,15 +91,42 @@ void bar() {} """) +t.write("d1/src/bar/bad.cpp", """ +very bad non-compilable file +""") + t.write("d1/Jamfile", """ project : source-location src ; -exe a : [ glob foo/*.cpp bar/*.cpp ] ../d2/d//l ; +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 t.rm("d1/bin")