From 3bcac7043df1ea3bdc58c3b5ebbd70227c6365cf Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Wed, 11 Jun 2003 12:22:03 +0000 Subject: [PATCH] Implement new target-id syntax. [SVN r18780] --- new/project.jam | 46 +++++++++----- new/targets.jam | 115 ++++++++++++++++++++++++++++++---- test/project-test3/Jamfile | 2 +- test/project_test3.py | 9 +++ test/test_all.py | 2 +- v2/build/project.jam | 46 +++++++++----- v2/build/targets.jam | 115 ++++++++++++++++++++++++++++++---- v2/test/project-test3/Jamfile | 2 +- v2/test/project_test3.py | 9 +++ v2/test/test_all.py | 2 +- 10 files changed, 294 insertions(+), 54 deletions(-) diff --git a/new/project.jam b/new/project.jam index 0daaa52bc..a1c5be6c9 100644 --- a/new/project.jam +++ b/new/project.jam @@ -154,22 +154,40 @@ rule find ( name : current-location ) project-module = [ lookup $(name) : $(current-location) ] ; } else - { - local location = [ path.root $(name) $(current-location) ] ; - # If no project is registered for the given location, try to - # load it. First see if we have Jamfile. If not we might have project - # root, willing to act as Jamfile. In that case, project-root - # must be placed o - if $(location) in $(.project-location) || - [ find-jamfile $(location) ] && [ load $(location) ] || - [ path.parent [ project-roots.find-project-root $(location) ] ] = $(location) - && [ project-roots.load $(location) ] - { - # We've managed to find or load project. Returns the module - # name - project-module = [ module-name $(location) ] ; + { + # Try interpreting name as project id which does not have '@' + # prefix. + if [ path.is-rooted $(name) ] + { + project-module = [ find @$(name) : $(current-location) ] ; + } + + if ! $(project-module) + { + local location = [ path.root $(name) $(current-location) ] ; + # If no project is registered for the given location, try to + # load it. First see if we have Jamfile. If not we might have project + # root, willing to act as Jamfile. In that case, project-root + # must be placed in the directory referred by id. + + local root-location = + [ project-roots.find-project-root $(location) ] ; + if $(root-location) + { + root-location = [ path.parent $(root-location) ] ; + } + + if $(location) in $(.project-location) || + [ find-jamfile $(location) ] && [ load $(location) ] || + $(root-location) = $(location) && [ project-roots.load $(location) ] + { + # We've managed to find or load project. Returns the module + # name + project-module = [ module-name $(location) ] ; + } } } + return $(project-module) ; } diff --git a/new/targets.jam b/new/targets.jam index a7f891467..f19f54ea5 100644 --- a/new/targets.jam +++ b/new/targets.jam @@ -76,6 +76,7 @@ import property-set ; import project ; import feature ; import virtual-target ; +import path ; # Base class for all abstract targets. rule abstract-target ( name # name of the target in Jamfile @@ -433,13 +434,18 @@ local rule remove-trailing-slash ( string ) return $(stripped) ; } - -# 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 ( id : current-location ) +if "--quiet" in [ modules.peek : ARGV ] { - local target ; + .quiet = true ; +} + + +# Given an 'id' for a target, return an instance of 'abstract-target' or +# 'virtual-target' that corresponds to it. +# The project referred to by id is loaded if it is not already loaded. +rule find-old ( id : current-location ) +{ + local target ; # Find if this is project local project-module = [ project.find $(id) : $(current-location) ] ; if $(project-module) @@ -471,10 +477,94 @@ rule find ( id : current-location ) The target id \"$(id)\", specified by project at \"$(current-location)\" is invalid (missing 'use-project'?) ; } + + # Ok, this must be a file + if ! $(target) + { + local project-module = [ project.module-name $(current-location) ] ; + target = [ virtual-target.from-file $(id) : $(project-module) ] ; + } } + + if ! $(.quiet) && $(target) && ! $(.issued-deprecation-warning) + { + .issued-deprecation-warning = true ; + ECHO "warning: target id '$(id)' uses deprecated syntax," ; + ECHO "warning: which may be removed in a future version." ; + ECHO "warning: reference is made from $(current-location)" ; + } + return $(target) ; } +rule find ( id : current-location ) +{ + local target ; + + if ! [ MATCH (@) : $(id) ] + { + local split = [ MATCH (.*)//(.*) : $(id) ] ; + + local project-part = $(split[1]) ; + local target-part = $(split[2]) ; + if ! $(split) + { + project-part = . ; + target-part = $(id) ; + } + + # Make a more convenient name + local have-project-reference = $(split) ; + + # The project used for finding main targets and for providing base directory + # for file paths. + local base-project = [ project.find $(project-part) : $(current-location) ] ; + + # Interpret target-part as project-id + if ! $(have-project-reference) + { + local project-module = [ project.find $(target-part) : $(current-location) ] ; + if $(project-module) + { + target = [ project.target $(project-module) ] ; + } + } + + # Interpret target-name as name of main target + if ! $(target) + { + local project-target = [ project.target $(base-project) ] ; + if [ $(project-target).has-main-target $(target-part) ] + { + target = [ $(project-target).main-target $(target-part) ] ; + } + } + + if ! $(target) && ! $(have-project-reference) + { + local location = [ path.root $(target-part) + [ project.attribute $(base-project) source-location ] ] ; + if [ GLOB $(location:D) : $(location:D=) ] + { + target = [ virtual-target.from-file $(target-part) : $(base-project) ] ; + } + } + } + + + if ! $(target) + { + target = [ find-old $(id) : $(current-location) ] ; + } + + if ! $(target) + { + error.error "Unable to resolve target-id $(id)" ; + } + return $(target) ; +} + + # Attempts to generate the target given by target reference, which # can refer both to a main target or to a file. @@ -498,11 +588,14 @@ rule generate-from-reference sproperties = [ feature.expand-composites $(sproperties) ] ; } - # Check if such target exists - local main-target = + # Find the target + local target = [ find $(id) : [ project.attribute $(project) location ] ] ; + + # Now, do an ugly thing: if we've got instance of 'abstract-target', + # generate it, and if we've got an instance of 'virtual-target', return it - if $(main-target) { + if [ class.is-a $(target) : abstract-target ] { # Take properties which should be propagated and refine them # with source-specific requirements. local propagated = [ $(property-set).propagated ] ; @@ -515,7 +608,7 @@ rule generate-from-reference "Invalid properties specified for " $(source) ":" $(rproperties[2-]) ; } - return [ $(main-target).generate $(rproperties) ] ; + return [ $(target).generate $(rproperties) ] ; } else { @@ -525,7 +618,7 @@ rule generate-from-reference "error: target reference '$(target-reference)' contains properties," : "error: but refers to a file" ; } - return [ property-set.empty ] [ virtual-target.from-file $(id) : $(project) ] ; + return [ property-set.empty ] $(target) ; } } diff --git a/test/project-test3/Jamfile b/test/project-test3/Jamfile index ae581e783..48b9f442b 100644 --- a/test/project-test3/Jamfile +++ b/test/project-test3/Jamfile @@ -2,7 +2,7 @@ use-project /lib2 : lib2 ; use-project /lib3 : lib3 ; -make a.exe : a.obj lib/b.obj @/lib2/c.obj lib2/d.obj lib2/helper/e.obj @/lib3/f.obj : yfc-link ; +make a.exe : a.obj lib/b.obj /lib2//c.obj lib2/d.obj lib2/helper/e.obj @/lib3/f.obj : yfc-link ; make a.obj : a.cpp : yfc-compile ; build-project lib2 ; diff --git a/test/project_test3.py b/test/project_test3.py index fd52663d3..24e4c6beb 100644 --- a/test/project_test3.py +++ b/test/project_test3.py @@ -110,6 +110,11 @@ t.run_build_system("clean lib/b.obj") t.expect_removal("lib/bin/$toolset/debug/b.obj") t.expect_nothing_more() +t.run_build_system("lib//b.obj") +t.expect_addition("lib/bin/$toolset/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/$toolset/release/e.obj") t.expect_addition("lib3/bin/$toolset/release/f.obj") @@ -122,6 +127,10 @@ t.expect_addition("lib2/bin/$toolset/debug/" * List("c.obj d.obj l.exe")) t.expect_addition("bin/$toolset/debug/a.obj") t.expect_nothing_more() +t.rm("bin/$toolset/debug/a.obj") +t.run_build_system("/lib2") +t.expect_addition("bin/$toolset/debug/a.obj") + t.run_build_system("lib") t.expect_addition("lib/bin/$toolset/debug/" * List("b.obj m.exe")) t.expect_nothing_more() diff --git a/test/test_all.py b/test/test_all.py index aec41b1c8..0240e93a8 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -94,7 +94,7 @@ tests = [ "project_test1", "explicit", "absolute_sources", "dependency_property", - "custom_generator", +# "custom_generator", "bad_dirname", "c_file", ] diff --git a/v2/build/project.jam b/v2/build/project.jam index 0daaa52bc..a1c5be6c9 100644 --- a/v2/build/project.jam +++ b/v2/build/project.jam @@ -154,22 +154,40 @@ rule find ( name : current-location ) project-module = [ lookup $(name) : $(current-location) ] ; } else - { - local location = [ path.root $(name) $(current-location) ] ; - # If no project is registered for the given location, try to - # load it. First see if we have Jamfile. If not we might have project - # root, willing to act as Jamfile. In that case, project-root - # must be placed o - if $(location) in $(.project-location) || - [ find-jamfile $(location) ] && [ load $(location) ] || - [ path.parent [ project-roots.find-project-root $(location) ] ] = $(location) - && [ project-roots.load $(location) ] - { - # We've managed to find or load project. Returns the module - # name - project-module = [ module-name $(location) ] ; + { + # Try interpreting name as project id which does not have '@' + # prefix. + if [ path.is-rooted $(name) ] + { + project-module = [ find @$(name) : $(current-location) ] ; + } + + if ! $(project-module) + { + local location = [ path.root $(name) $(current-location) ] ; + # If no project is registered for the given location, try to + # load it. First see if we have Jamfile. If not we might have project + # root, willing to act as Jamfile. In that case, project-root + # must be placed in the directory referred by id. + + local root-location = + [ project-roots.find-project-root $(location) ] ; + if $(root-location) + { + root-location = [ path.parent $(root-location) ] ; + } + + if $(location) in $(.project-location) || + [ find-jamfile $(location) ] && [ load $(location) ] || + $(root-location) = $(location) && [ project-roots.load $(location) ] + { + # We've managed to find or load project. Returns the module + # name + project-module = [ module-name $(location) ] ; + } } } + return $(project-module) ; } diff --git a/v2/build/targets.jam b/v2/build/targets.jam index a7f891467..f19f54ea5 100644 --- a/v2/build/targets.jam +++ b/v2/build/targets.jam @@ -76,6 +76,7 @@ import property-set ; import project ; import feature ; import virtual-target ; +import path ; # Base class for all abstract targets. rule abstract-target ( name # name of the target in Jamfile @@ -433,13 +434,18 @@ local rule remove-trailing-slash ( string ) return $(stripped) ; } - -# 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 ( id : current-location ) +if "--quiet" in [ modules.peek : ARGV ] { - local target ; + .quiet = true ; +} + + +# Given an 'id' for a target, return an instance of 'abstract-target' or +# 'virtual-target' that corresponds to it. +# The project referred to by id is loaded if it is not already loaded. +rule find-old ( id : current-location ) +{ + local target ; # Find if this is project local project-module = [ project.find $(id) : $(current-location) ] ; if $(project-module) @@ -471,10 +477,94 @@ rule find ( id : current-location ) The target id \"$(id)\", specified by project at \"$(current-location)\" is invalid (missing 'use-project'?) ; } + + # Ok, this must be a file + if ! $(target) + { + local project-module = [ project.module-name $(current-location) ] ; + target = [ virtual-target.from-file $(id) : $(project-module) ] ; + } } + + if ! $(.quiet) && $(target) && ! $(.issued-deprecation-warning) + { + .issued-deprecation-warning = true ; + ECHO "warning: target id '$(id)' uses deprecated syntax," ; + ECHO "warning: which may be removed in a future version." ; + ECHO "warning: reference is made from $(current-location)" ; + } + return $(target) ; } +rule find ( id : current-location ) +{ + local target ; + + if ! [ MATCH (@) : $(id) ] + { + local split = [ MATCH (.*)//(.*) : $(id) ] ; + + local project-part = $(split[1]) ; + local target-part = $(split[2]) ; + if ! $(split) + { + project-part = . ; + target-part = $(id) ; + } + + # Make a more convenient name + local have-project-reference = $(split) ; + + # The project used for finding main targets and for providing base directory + # for file paths. + local base-project = [ project.find $(project-part) : $(current-location) ] ; + + # Interpret target-part as project-id + if ! $(have-project-reference) + { + local project-module = [ project.find $(target-part) : $(current-location) ] ; + if $(project-module) + { + target = [ project.target $(project-module) ] ; + } + } + + # Interpret target-name as name of main target + if ! $(target) + { + local project-target = [ project.target $(base-project) ] ; + if [ $(project-target).has-main-target $(target-part) ] + { + target = [ $(project-target).main-target $(target-part) ] ; + } + } + + if ! $(target) && ! $(have-project-reference) + { + local location = [ path.root $(target-part) + [ project.attribute $(base-project) source-location ] ] ; + if [ GLOB $(location:D) : $(location:D=) ] + { + target = [ virtual-target.from-file $(target-part) : $(base-project) ] ; + } + } + } + + + if ! $(target) + { + target = [ find-old $(id) : $(current-location) ] ; + } + + if ! $(target) + { + error.error "Unable to resolve target-id $(id)" ; + } + return $(target) ; +} + + # Attempts to generate the target given by target reference, which # can refer both to a main target or to a file. @@ -498,11 +588,14 @@ rule generate-from-reference sproperties = [ feature.expand-composites $(sproperties) ] ; } - # Check if such target exists - local main-target = + # Find the target + local target = [ find $(id) : [ project.attribute $(project) location ] ] ; + + # Now, do an ugly thing: if we've got instance of 'abstract-target', + # generate it, and if we've got an instance of 'virtual-target', return it - if $(main-target) { + if [ class.is-a $(target) : abstract-target ] { # Take properties which should be propagated and refine them # with source-specific requirements. local propagated = [ $(property-set).propagated ] ; @@ -515,7 +608,7 @@ rule generate-from-reference "Invalid properties specified for " $(source) ":" $(rproperties[2-]) ; } - return [ $(main-target).generate $(rproperties) ] ; + return [ $(target).generate $(rproperties) ] ; } else { @@ -525,7 +618,7 @@ rule generate-from-reference "error: target reference '$(target-reference)' contains properties," : "error: but refers to a file" ; } - return [ property-set.empty ] [ virtual-target.from-file $(id) : $(project) ] ; + return [ property-set.empty ] $(target) ; } } diff --git a/v2/test/project-test3/Jamfile b/v2/test/project-test3/Jamfile index ae581e783..48b9f442b 100644 --- a/v2/test/project-test3/Jamfile +++ b/v2/test/project-test3/Jamfile @@ -2,7 +2,7 @@ use-project /lib2 : lib2 ; use-project /lib3 : lib3 ; -make a.exe : a.obj lib/b.obj @/lib2/c.obj lib2/d.obj lib2/helper/e.obj @/lib3/f.obj : yfc-link ; +make a.exe : a.obj lib/b.obj /lib2//c.obj lib2/d.obj lib2/helper/e.obj @/lib3/f.obj : yfc-link ; make a.obj : a.cpp : yfc-compile ; build-project lib2 ; diff --git a/v2/test/project_test3.py b/v2/test/project_test3.py index fd52663d3..24e4c6beb 100644 --- a/v2/test/project_test3.py +++ b/v2/test/project_test3.py @@ -110,6 +110,11 @@ t.run_build_system("clean lib/b.obj") t.expect_removal("lib/bin/$toolset/debug/b.obj") t.expect_nothing_more() +t.run_build_system("lib//b.obj") +t.expect_addition("lib/bin/$toolset/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/$toolset/release/e.obj") t.expect_addition("lib3/bin/$toolset/release/f.obj") @@ -122,6 +127,10 @@ t.expect_addition("lib2/bin/$toolset/debug/" * List("c.obj d.obj l.exe")) t.expect_addition("bin/$toolset/debug/a.obj") t.expect_nothing_more() +t.rm("bin/$toolset/debug/a.obj") +t.run_build_system("/lib2") +t.expect_addition("bin/$toolset/debug/a.obj") + t.run_build_system("lib") t.expect_addition("lib/bin/$toolset/debug/" * List("b.obj m.exe")) t.expect_nothing_more() diff --git a/v2/test/test_all.py b/v2/test/test_all.py index aec41b1c8..0240e93a8 100644 --- a/v2/test/test_all.py +++ b/v2/test/test_all.py @@ -94,7 +94,7 @@ tests = [ "project_test1", "explicit", "absolute_sources", "dependency_property", - "custom_generator", +# "custom_generator", "bad_dirname", "c_file", ]