From e1855f185bfe2c130d247d3413ee427121c17432 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Tue, 21 Oct 2003 05:47:39 +0000 Subject: [PATCH] Fix a bug which caused double loading of Jamfile in some cases. Also, simplify some things. * new/project.jam (load): Tweak (lookup): Remove. (find): Simplify. [SVN r20430] --- new/project.jam | 122 +++++++----------------- test/double_loading.py | 29 ++++++ test/project-test1.jam | 5 - test/project-test1/project-test1.jam | 4 +- test/test_all.py | 1 + v2/build/project.jam | 122 +++++++----------------- v2/test/double_loading.py | 29 ++++++ v2/test/project-test1.jam | 5 - v2/test/project-test1/project-test1.jam | 4 +- v2/test/test_all.py | 1 + 10 files changed, 134 insertions(+), 188 deletions(-) create mode 100644 test/double_loading.py create mode 100644 v2/test/double_loading.py diff --git a/new/project.jam b/new/project.jam index d473a8a87..33468c70a 100644 --- a/new/project.jam +++ b/new/project.jam @@ -60,11 +60,11 @@ rule load ( jamfile-location ) # Load project root, first. It might decide to act as Jamfile. project-roots.load $(jamfile-location) ; - local module-name = [ module-name $(jamfile-location) ] ; + local module-name = [ module-name $(jamfile-location) ] ; # If Jamfile is already loaded, don't try again. - if ! $(jamfile-location) in $(.project-locations) + if ! $(module-name) in $(.jamfile-modules) { - .project-locations += $(jamfile-location) ; + .jamfile-modules += $(module-name) ; load-jamfile $(jamfile-location) ; @@ -81,7 +81,7 @@ rule load ( jamfile-location ) # error. rule act-as-jamfile ( module : location ) { - if $(location) in $(.project-locations) + if [ module-name $(location) ] in $(.jamfile-modules) { errors.error "Jamfile was already loaded for '$(location)'" ; } @@ -90,102 +90,48 @@ rule act-as-jamfile ( module : location ) # Add the location to the list of project locations # so that we don't try to load Jamfile in future - .project-locations += $(location) ; + .jamfile-modules += [ module-name $(location) ] ; initialize $(module) : $(location) ; } -# Returns the project module, given its id. -# Projects can be referred using @project-id notation. -# Where is a path. When this path is not absolute, it's relative -# to the project in 'current-location'. -rule lookup ( id : current-location ) -{ - local split = [ MATCH ^(@)(.*) : $(id) ] ; - if ! $(split) - { - error "Project id '$(id)' is invalid" ; - } - - local project-id = $(split[2]) ; - - local location = $(current-location) ; - - if [ path.is-rooted $(project-id) ] - { - return $($(project-id).jamfile-module) ; - } - else - { - # Find the project module for this location - assert.in $(location) : $(.project-locations) ; - local module-name = [ module-name $(location) ] ; - - if ! $(project-id) - { - return $(module-name) ; - } - else - { - local base-id = [ attribute $(module-name) id ] ; - - if ! $(base-id) - { - error "Project in $(location) has no project id" ; - } - else - { - local rooted-id = $(base-id)/$(project-id) ; - return $($(rooted-id).jamfile-module) ; - } - } - } -} - # Given 'name' which can be project-id or plain directory name, # return project module corresponding to that id or directory. # Returns nothing of project is not found. rule find ( name : current-location ) { local project-module ; - if [ MATCH (@) : $(name) ] - { - project-module = [ lookup $(name) : $(current-location) ] ; - } - else - { - # Try interpreting name as project id which does not have '@' - # prefix. - if [ path.is-rooted $(name) ] - { - project-module = [ find @$(name) : $(current-location) ] ; - } + + # Try interpreting name as project id. + if [ path.is-rooted $(name) ] + { + project-module = $($(name).jamfile-module) ; + } - 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 ! $(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) ] ; - } - } + $(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) ; @@ -200,6 +146,10 @@ rule module-name ( jamfile-location ) { if ! $(.module.$(jamfile-location)) { + # Root the path, so that locations are always umbiguious. + # Without this, we can't decide if '../../exe/program1' and '.' + # are the same paths, or not. + jamfile-location = [ path.root $(jamfile-location) [ path.pwd ] ] ; .module.$(jamfile-location) = Jamfile<$(jamfile-location)> ; } return $(.module.$(jamfile-location)) ; diff --git a/test/double_loading.py b/test/double_loading.py new file mode 100644 index 000000000..3453bf8e2 --- /dev/null +++ b/test/double_loading.py @@ -0,0 +1,29 @@ +#!/usr/bin/python + +# Copyright (C) Vladimir Prus 2003. Permission to copy, use, modify, sell and +# distribute this software is granted provided this copyright notice appears in +# all copies. This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. + +# Regression test for double loading of the same Jamfile. +from BoostBuild import Tester, List +import string + +t = Tester() + +t.write("Jamfile", """ +build-project subdir ; +""") + +t.write("project-root.jam", """ +""") + +t.write("subdir/Jamfile", """ +ECHO "Loaded subdir" ; +""") + +t.run_build_system(subdir="subdir") +t.fail_test(string.count(t.stdout(), "Loaded subdir") != 1) + +t.cleanup() + diff --git a/test/project-test1.jam b/test/project-test1.jam index 80f93f5dd..9fe1ab988 100644 --- a/test/project-test1.jam +++ b/test/project-test1.jam @@ -7,11 +7,6 @@ import project-roots ; project-roots.print ; -assert.result Jamfile : project.lookup @/cool-library : "." ; -assert.result Jamfile : project.lookup @dir : "project-test1" ; -assert.result Jamfile : project.lookup @ : "project-test1" ; - - NOTFILE all ; diff --git a/test/project-test1/project-test1.jam b/test/project-test1/project-test1.jam index e6fcd5ae9..e09e6750c 100644 --- a/test/project-test1/project-test1.jam +++ b/test/project-test1/project-test1.jam @@ -9,9 +9,7 @@ import standalone-project ; project-roots.print ; -assert.result Jamfile : project.lookup @/cool-library : "." ; -assert.result Jamfile : project.lookup @dir : "." ; -assert.result standalone-project : project.lookup @/teeest : "." ; +assert.result standalone-project : project.find /teeest : "." ; NOTFILE all ; diff --git a/test/test_all.py b/test/test_all.py index ff08ccd33..c9441da5f 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -108,6 +108,7 @@ tests = [ "project_test1", "project_root", "glob", "project_root_constants", + "double_loading", ] if os.name == 'posix': diff --git a/v2/build/project.jam b/v2/build/project.jam index d473a8a87..33468c70a 100644 --- a/v2/build/project.jam +++ b/v2/build/project.jam @@ -60,11 +60,11 @@ rule load ( jamfile-location ) # Load project root, first. It might decide to act as Jamfile. project-roots.load $(jamfile-location) ; - local module-name = [ module-name $(jamfile-location) ] ; + local module-name = [ module-name $(jamfile-location) ] ; # If Jamfile is already loaded, don't try again. - if ! $(jamfile-location) in $(.project-locations) + if ! $(module-name) in $(.jamfile-modules) { - .project-locations += $(jamfile-location) ; + .jamfile-modules += $(module-name) ; load-jamfile $(jamfile-location) ; @@ -81,7 +81,7 @@ rule load ( jamfile-location ) # error. rule act-as-jamfile ( module : location ) { - if $(location) in $(.project-locations) + if [ module-name $(location) ] in $(.jamfile-modules) { errors.error "Jamfile was already loaded for '$(location)'" ; } @@ -90,102 +90,48 @@ rule act-as-jamfile ( module : location ) # Add the location to the list of project locations # so that we don't try to load Jamfile in future - .project-locations += $(location) ; + .jamfile-modules += [ module-name $(location) ] ; initialize $(module) : $(location) ; } -# Returns the project module, given its id. -# Projects can be referred using @project-id notation. -# Where is a path. When this path is not absolute, it's relative -# to the project in 'current-location'. -rule lookup ( id : current-location ) -{ - local split = [ MATCH ^(@)(.*) : $(id) ] ; - if ! $(split) - { - error "Project id '$(id)' is invalid" ; - } - - local project-id = $(split[2]) ; - - local location = $(current-location) ; - - if [ path.is-rooted $(project-id) ] - { - return $($(project-id).jamfile-module) ; - } - else - { - # Find the project module for this location - assert.in $(location) : $(.project-locations) ; - local module-name = [ module-name $(location) ] ; - - if ! $(project-id) - { - return $(module-name) ; - } - else - { - local base-id = [ attribute $(module-name) id ] ; - - if ! $(base-id) - { - error "Project in $(location) has no project id" ; - } - else - { - local rooted-id = $(base-id)/$(project-id) ; - return $($(rooted-id).jamfile-module) ; - } - } - } -} - # Given 'name' which can be project-id or plain directory name, # return project module corresponding to that id or directory. # Returns nothing of project is not found. rule find ( name : current-location ) { local project-module ; - if [ MATCH (@) : $(name) ] - { - project-module = [ lookup $(name) : $(current-location) ] ; - } - else - { - # Try interpreting name as project id which does not have '@' - # prefix. - if [ path.is-rooted $(name) ] - { - project-module = [ find @$(name) : $(current-location) ] ; - } + + # Try interpreting name as project id. + if [ path.is-rooted $(name) ] + { + project-module = $($(name).jamfile-module) ; + } - 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 ! $(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) ] ; - } - } + $(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) ; @@ -200,6 +146,10 @@ rule module-name ( jamfile-location ) { if ! $(.module.$(jamfile-location)) { + # Root the path, so that locations are always umbiguious. + # Without this, we can't decide if '../../exe/program1' and '.' + # are the same paths, or not. + jamfile-location = [ path.root $(jamfile-location) [ path.pwd ] ] ; .module.$(jamfile-location) = Jamfile<$(jamfile-location)> ; } return $(.module.$(jamfile-location)) ; diff --git a/v2/test/double_loading.py b/v2/test/double_loading.py new file mode 100644 index 000000000..3453bf8e2 --- /dev/null +++ b/v2/test/double_loading.py @@ -0,0 +1,29 @@ +#!/usr/bin/python + +# Copyright (C) Vladimir Prus 2003. Permission to copy, use, modify, sell and +# distribute this software is granted provided this copyright notice appears in +# all copies. This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. + +# Regression test for double loading of the same Jamfile. +from BoostBuild import Tester, List +import string + +t = Tester() + +t.write("Jamfile", """ +build-project subdir ; +""") + +t.write("project-root.jam", """ +""") + +t.write("subdir/Jamfile", """ +ECHO "Loaded subdir" ; +""") + +t.run_build_system(subdir="subdir") +t.fail_test(string.count(t.stdout(), "Loaded subdir") != 1) + +t.cleanup() + diff --git a/v2/test/project-test1.jam b/v2/test/project-test1.jam index 80f93f5dd..9fe1ab988 100644 --- a/v2/test/project-test1.jam +++ b/v2/test/project-test1.jam @@ -7,11 +7,6 @@ import project-roots ; project-roots.print ; -assert.result Jamfile : project.lookup @/cool-library : "." ; -assert.result Jamfile : project.lookup @dir : "project-test1" ; -assert.result Jamfile : project.lookup @ : "project-test1" ; - - NOTFILE all ; diff --git a/v2/test/project-test1/project-test1.jam b/v2/test/project-test1/project-test1.jam index e6fcd5ae9..e09e6750c 100644 --- a/v2/test/project-test1/project-test1.jam +++ b/v2/test/project-test1/project-test1.jam @@ -9,9 +9,7 @@ import standalone-project ; project-roots.print ; -assert.result Jamfile : project.lookup @/cool-library : "." ; -assert.result Jamfile : project.lookup @dir : "." ; -assert.result standalone-project : project.lookup @/teeest : "." ; +assert.result standalone-project : project.find /teeest : "." ; NOTFILE all ; diff --git a/v2/test/test_all.py b/v2/test/test_all.py index ff08ccd33..c9441da5f 100644 --- a/v2/test/test_all.py +++ b/v2/test/test_all.py @@ -108,6 +108,7 @@ tests = [ "project_test1", "project_root", "glob", "project_root_constants", + "double_loading", ] if os.name == 'posix':