Index: test/test_all.py =================================================================== --- test/test_all.py (revision 47828) +++ test/test_all.py (working copy) @@ -169,7 +169,8 @@ "free_features_request", "file_name_handling", "sort_rule", - "ordered_include" + "ordered_include", + "inherited_dependency" ] if os.name == 'posix': Index: test/inherited_dependency.py =================================================================== --- test/inherited_dependency.py (revision 0) +++ test/inherited_dependency.py (revision 0) @@ -0,0 +1,239 @@ +#!/usr/bin/python +# +# Copyright (c) 2008 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt) or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +from BoostBuild import Tester + +tester = Tester() + + +############################################################################### +# +# Test without giving the project an explicit id. +# +############################################################################### + +tester.write("Jamroot", """ + lib test : test.cpp ; + project : requirements test ; + build-project a ; +""") + +tester.write("test.cpp", """ + #ifdef _WIN32 + __declspec(dllexport) + #endif + void foo() {} +""") + +tester.write("a/test1.cpp", """ + int main() {} +""") + +tester.write("a/Jamfile", """ + exe test1 : test1.cpp ; +""") + +tester.run_build_system() + +tester.expect_addition("bin/$toolset/debug/test.obj") +tester.expect_addition("a/bin/$toolset/debug/test1.exe") + +tester.rm("bin") +tester.rm("a/bin") + + +############################################################################### +# +# Run the same test from the "a" directory. +# +############################################################################### + +tester.run_build_system(subdir="a") + +tester.expect_addition("bin/$toolset/debug/test.obj") +tester.expect_addition("a/bin/$toolset/debug/test1.exe") + +tester.rm("bin") +tester.rm("a/bin") + + +############################################################################### +# +# This time, do give the project an id. +# +############################################################################### + +tester.write("Jamroot", """ + lib test : test.cpp ; + project test_project : requirements test ; + build-project a ; +""") + +tester.run_build_system() + +tester.expect_addition("bin/$toolset/debug/test.obj") +tester.expect_addition("a/bin/$toolset/debug/test1.exe") + +tester.rm("bin") +tester.rm("a/bin") + + +############################################################################### +# +# Now, give the project an id in its attributes. +# +############################################################################### + +tester.write("Jamroot", """ + lib test : test.cpp ; + project : id test_project : requirements test ; + build-project a ; +""") + +tester.run_build_system() + +tester.expect_addition("bin/$toolset/debug/test.obj") +tester.expect_addition("a/bin/$toolset/debug/test1.exe") + +tester.rm("bin") +tester.rm("a/bin") + + +############################################################################### +# +# Give the project an id in both ways at once. +# +############################################################################### + +tester.write("Jamroot", """ + lib test : test.cpp ; + project test_project1 : id test_project : requirements test ; + build-project a ; +""") + +tester.run_build_system() + +tester.expect_addition("bin/$toolset/debug/test.obj") +tester.expect_addition("a/bin/$toolset/debug/test1.exe") + +tester.rm("bin") +tester.rm("a/bin") + + +############################################################################### +# +# Test an absolute path in native format. +# +############################################################################### + +tester.write("Jamroot", """ + import path ; + path-constant here : . ; + current-location = + [ path.native [ path.root [ path.make $(here) ] [ path.pwd ] ] ] ; + project test : requirements $(current-location)/a/test1.cpp ; + exe test : test.cpp ; +""") + +tester.run_build_system() +tester.expect_addition("bin/$toolset/debug/test.exe") + +tester.rm("bin") +tester.rm("a/bin") + + +############################################################################### +# +# Test an absolute path in canonical format. +# +############################################################################### + +tester.write("Jamroot", """ + import path ; + path-constant here : . ; + current-location = [ path.root [ path.make $(here) ] [ path.pwd ] ] ; + project test : requirements $(current-location)/a/test1.cpp ; + exe test : test.cpp ; +""") + +tester.run_build_system() +tester.expect_addition("bin/$toolset/debug/test.exe") + +tester.rm("bin") +tester.rm("a/bin") + + +############################################################################### +# +# Test dependency properties (e.g. +# ) whose targets are specified using a relative path. +# +############################################################################### + + +# Use Jamroot rather than Jamfile to avoid inheriting +# the from the parent as that would would make +# test3 a source of itself. +tester.write("b/Jamroot", """ + obj test3 : test3.cpp ; +""") + +tester.write("b/test3.cpp", """ + void bar() {} +""") + +tester.write("Jamroot", """ + project test : requirements b//test3 ; + build-project a ; +""") + +tester.write("a/Jamfile", """ + exe test : test1.cpp ; +""") + +tester.write("a/test1.cpp", """ + void bar(); + int main() { bar(); } +""") + +tester.run_build_system() +tester.expect_addition("b/bin/$toolset/debug/test3.obj") +tester.expect_addition("a/bin/$toolset/debug/test.exe") + +tester.rm("bin") +tester.rm("a") +tester.rm("Jamroot") +tester.rm("test.cpp") + + +############################################################################### +# +# Test that source-location is respected +# +############################################################################### + +tester.write("build/Jamroot", """ + project : requirements test.cpp : source-location ../src ; +""") + +tester.write("src/test.cpp", """ + int main() {} +""") + +tester.write("build/a/Jamfile", """ + project : source-location ../../a_src ; + exe test : test1.cpp ; +""") + +tester.write("a_src/test1.cpp", """ +""") + +tester.run_build_system(subdir="build/a") +tester.expect_addition("build/a/bin/$toolset/debug/test.exe") + +tester.cleanup() Property changes on: test\inherited_dependency.py ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/x-python Name: svn:eol-style + native Index: build/property-set.jam =================================================================== --- build/property-set.jam (revision 47828) +++ build/property-set.jam (working copy) @@ -384,6 +384,10 @@ : $(location) ] ; specification = [ property.translate-indirect $(specification) : $(jamfile-module) ] ; + local project-id = [ project.attribute $(jamfile-module) id ] ; + project-id ?= [ path.root $(location) [ path.pwd ] ] ; + specification = [ property.translate-dependencies + $(specification) : $(project-id) : $(location) ] ; specification = [ property.expand-subfeatures-in-conditions $(specification) ] ; specification = [ property.make $(specification) ] ; Index: build/property.jam =================================================================== --- build/property.jam (revision 47828) +++ build/property.jam (working copy) @@ -512,6 +512,49 @@ return $(result) ; } +# Binds all dependency properties in a list relative to +# the given project. Targets with absolute paths will +# be left unchanged and targets which have a project specified +# will have the path to the project interpreted relative +# to location. +# +rule translate-dependencies ( specification * : project-id : location ) +{ + local result ; + for local p in $(specification) + { + local split = [ split-conditional $(p) ] ; + local condition = "" ; + if $(split) + { + condition = $(split[1]): ; + p = $(split[2]) ; + } + if dependency in [ feature.attributes $(p:G) ] + { + local split-target = [ regex.match (.*)//(.*) : $(p:G=) ] ; + if $(split-target) + { + local rooted = [ path.root [ path.make $(split-target[1]) ] + [ path.root $(location) [ path.pwd ] ] ] ; + result += $(condition)$(p:G)$(rooted)//$(split-target[2]) ; + } + else if [ path.is-rooted $(p:G=) ] + { + result += $(condition)$(p) ; + } + else + { + result += $(condition)$(p:G)$(project-id)//$(p:G=) ; + } + } + else + { + result += $(condition)$(p) ; + } + } + return $(result) ; +} # Class maintaining a property set -> string mapping. # Index: build/project.jam =================================================================== --- build/project.jam (revision 47828) +++ build/project.jam (working copy) @@ -633,9 +633,15 @@ self.build-dir = [ path.root [ path.make $(specification) ] $(self.location) ] ; } - else if ! $(attribute) in "id" "default-build" "location" - "source-location" "parent" "projects-to-build" "project-root" + else if $(attribute) = "id" { + id = [ path.root $(specification) / ] ; + project.register-id $(id) : $(self.project-module) ; + self.id = $(id) ; + } + else if ! $(attribute) in "default-build" "location" "parent" + "projects-to-build" "project-root" "source-location" + { errors.error "Invalid project attribute '$(attribute)' specified" "for project at '$(self.location)'" ; } @@ -873,8 +879,6 @@ local attributes = [ project.attributes $(__name__) ] ; if $(id) { - id = [ path.root $(id) / ] ; - project.register-id $(id) : $(__name__) ; $(attributes).set id : $(id) ; } @@ -906,6 +910,9 @@ # or wrong consequences. if $(location) && $(location) = [ $(attributes).get project-root ] { + # Re-read the project id, since it might have been changed in + # the project's attributes. + id = [ $(attributes).get id ] ; # This is Jamroot. if $(id) {