[pkg-boost-commits] r13935 - in boost-jam: . boost-build
boost-build/branches boost-build/branches/upstream
boost-build/branches/upstream/current
boost-build/branches/upstream/current/build
boost-build/branches/upstream/current/debian
boost-build/branches/upstream/current/doc
boost-build/branches/upstream/current/doc/html
boost-build/branches/upstream/current/doc/html/bbv2
boost-build/branches/upstream/current/doc/html/bbv2/advanced
boost-build/branches/upstream/current/doc/html/bbv2/advanced/builtins
boost-build/branches/upstream/current/doc/html/bbv2/arch
boost-build/branches/upstream/current/doc/html/bbv2/extending
boost-build/branches/upstream/current/doc/html/bbv2/faq
boost-build/branches/upstream/current/doc/html/bbv2/recipies
boost-build/branches/upstream/current/doc/html/bbv2/reference
boost-build/branches/upstream/current/doc/html/bbv2/tutorial
boost-build/branches/upstream/current/doc/html/images
boost-build/branches/upstream/current/doc/src
boost-build/branches/upstream/current/example
boost-build/branches/upstream/current/example/customization
boost-build/branches/upstream/current/example/gettext
boost-build/branches/upstream/current/example/hello
boost-build/branches/upstream/current/example/libraries
boost-build/branches/upstream/current/example/libraries/app
boost-build/branches/upstream/current/example/libraries/lib1
boost-build/branches/upstream/current/example/libraries/lib1/include
boost-build/branches/upstream/current/example/qt
boost-build/branches/upstream/current/example/qt-ui
boost-build/branches/upstream/current/example/variant
boost-build/branches/upstream/current/example/variant/libs
boost-build/branches/upstream/current/jam_src
boost-build/branches/upstream/current/jam_src/debian
boost-build/branches/upstream/current/jam_src/modules
boost-build/branches/upstream/current/kernel
boost-build/branches/upstream/current/options
boost-build/branches/upstream/current/test
boost-build/branches/upstream/current/test/dependency-test
boost-build/branches/upstream/current/test/dependency-test/src1
boost-build/branches/upstream/current/test/dependency-test/src2
boost-build/branches/upstream/current/test/direct-request-test
boost-build/branches/upstream/current/test/generators-test
boost-build/branches/upstream/current/test/generators-test/lib
boost-build/branches/upstream/current/test/module-actions
boost-build/branches/upstream/current/test/prebuilt
boost-build/branches/upstream/current/test/prebuilt/ext
boost-build/branches/upstream/current/test/prebuilt/ext/debug
boost-build/branches/upstream/current/test/prebuilt/ext/release
boost-build/branches/upstream/current/test/project-test1
boost-build/branches/upstream/current/test/project-test1/dir
boost-build/branches/upstream/current/test/project-test1/dir2
boost-build/branches/upstream/current/test/project-test3
boost-build/branches/upstream/current/test/project-test3/lib
boost-build/branches/upstream/current/test/project-test3/lib2
boost-build/branches/upstream/current/test/project-test3/lib2/helper
boost-build/branches/upstream/current/test/project-test3/lib3
boost-build/branches/upstream/current/test/project-test4
boost-build/branches/upstream/current/test/project-test4/lib
boost-build/branches/upstream/current/test/project-test4/lib2
boost-build/branches/upstream/current/test/railsys
boost-build/branches/upstream/current/test/railsys/libx
boost-build/branches/upstream/current/test/railsys/libx/include
boost-build/branches/upstream/current/test/railsys/libx/src
boost-build/branches/upstream/current/test/railsys/program
boost-build/branches/upstream/current/test/railsys/program/include
boost-build/branches/upstream/current/test/railsys/program/liba
boost-build/branches/upstream/current/test/railsys/program/main
boost-build/branches/upstream/current/test/startup
boost-build/branches/upstream/current/test/startup/boost-root
boost-build/branches/upstream/current/test/startup/boost-root/build
boost-build/branches/upstream/current/test/startup/bootstrap-env
boost-build/branches/upstream/current/test/startup/bootstrap-explicit
boost-build/branches/upstream/current/test/startup/bootstrap-implicit
boost-build/branches/upstream/current/test/startup/no-bootstrap1
boost-build/branches/upstream/current/test/startup/no-bootstrap1/subdir
boost-build/branches/upstream/current/test/startup/no-bootstrap2
boost-build/branches/upstream/current/test/startup/no-bootstrap3
boost-build/branches/upstream/current/test/subdir1
boost-build/branches/upstream/current/test/test2
boost-build/branches/upstream/current/test/testing-primitives
boost-build/branches/upstream/current/test/unused
boost-build/branches/upstream/current/test/v1-testing
boost-build/branches/upstream/current/test/v1_testing
boost-build/branches/upstream/current/tools
boost-build/branches/upstream/current/util
Domenico Andreoli
cavok at costa.debian.org
Thu Dec 22 14:00:20 UTC 2005
Author: cavok
Date: 2005-12-22 14:00:13 +0000 (Thu, 22 Dec 2005)
New Revision: 13935
Added:
boost-jam/boost-build/
boost-jam/boost-build/branches/
boost-jam/boost-build/branches/upstream/
boost-jam/boost-build/branches/upstream/current/
boost-jam/boost-build/branches/upstream/current/boost-build.jam
boost-jam/boost-build/branches/upstream/current/boost.png
boost-jam/boost-build/branches/upstream/current/bootstrap.jam
boost-jam/boost-build/branches/upstream/current/build-system.jam
boost-jam/boost-build/branches/upstream/current/build/
boost-jam/boost-build/branches/upstream/current/build/alias.jam
boost-jam/boost-build/branches/upstream/current/build/build-request.jam
boost-jam/boost-build/branches/upstream/current/build/feature.jam
boost-jam/boost-build/branches/upstream/current/build/generators.jam
boost-jam/boost-build/branches/upstream/current/build/modifiers.jam
boost-jam/boost-build/branches/upstream/current/build/project-roots.jam
boost-jam/boost-build/branches/upstream/current/build/project.jam
boost-jam/boost-build/branches/upstream/current/build/property-set.jam
boost-jam/boost-build/branches/upstream/current/build/property.jam
boost-jam/boost-build/branches/upstream/current/build/readme.txt
boost-jam/boost-build/branches/upstream/current/build/scanner.jam
boost-jam/boost-build/branches/upstream/current/build/targets.jam
boost-jam/boost-build/branches/upstream/current/build/toolset.jam
boost-jam/boost-build/branches/upstream/current/build/type.jam
boost-jam/boost-build/branches/upstream/current/build/version.jam
boost-jam/boost-build/branches/upstream/current/build/virtual-target.jam
boost-jam/boost-build/branches/upstream/current/debian/
boost-jam/boost-build/branches/upstream/current/debian/boost-build.docs
boost-jam/boost-build/branches/upstream/current/debian/boost-build.examples
boost-jam/boost-build/branches/upstream/current/debian/changelog
boost-jam/boost-build/branches/upstream/current/debian/conffiles
boost-jam/boost-build/branches/upstream/current/debian/control
boost-jam/boost-build/branches/upstream/current/debian/copyright
boost-jam/boost-build/branches/upstream/current/debian/excludes
boost-jam/boost-build/branches/upstream/current/debian/rules
boost-jam/boost-build/branches/upstream/current/doc/
boost-jam/boost-build/branches/upstream/current/doc/Jamfile.v2
boost-jam/boost-build/branches/upstream/current/doc/catalog.xml
boost-jam/boost-build/branches/upstream/current/doc/development_plan.html
boost-jam/boost-build/branches/upstream/current/doc/html/
boost-jam/boost-build/branches/upstream/current/doc/html/HTML.manifest
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/build_process.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/builtins/
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/builtins/features.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/builtins/targets.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/differences_to_v1.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/jamfiles.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/build.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/targets.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/tools.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extender.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/features.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/rules.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/targets.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/tools.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/toolset_modules.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/dll-path.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/external.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s02.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s03.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s04.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s06.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s07.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/howto.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/installation.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/recipies/
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/recipies/site-config.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/buildprocess.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/definitions.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/generators.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/jamfiles.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/conditions.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/depends.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/hierarchy.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/libs.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/linkage.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/prebuilt.html
boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/properties.html
boost-jam/boost-build/branches/upstream/current/doc/html/boostbook.css
boost-jam/boost-build/branches/upstream/current/doc/html/images/
boost-jam/boost-build/branches/upstream/current/doc/html/images/blank.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/caution.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/draft.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/home.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/important.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/next.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/note.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/prev.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/tip.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/toc-blank.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/toc-minus.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/toc-plus.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/up.png
boost-jam/boost-build/branches/upstream/current/doc/html/images/warning.png
boost-jam/boost-build/branches/upstream/current/doc/html/index.html
boost-jam/boost-build/branches/upstream/current/doc/project-root.jam
boost-jam/boost-build/branches/upstream/current/doc/src/
boost-jam/boost-build/branches/upstream/current/doc/src/advanced.xml
boost-jam/boost-build/branches/upstream/current/doc/src/architecture.xml
boost-jam/boost-build/branches/upstream/current/doc/src/catalog.xml
boost-jam/boost-build/branches/upstream/current/doc/src/extending.xml
boost-jam/boost-build/branches/upstream/current/doc/src/faq.xml
boost-jam/boost-build/branches/upstream/current/doc/src/howto.xml
boost-jam/boost-build/branches/upstream/current/doc/src/install.xml
boost-jam/boost-build/branches/upstream/current/doc/src/recipes.xml
boost-jam/boost-build/branches/upstream/current/doc/src/reference.xml
boost-jam/boost-build/branches/upstream/current/doc/src/tutorial.xml
boost-jam/boost-build/branches/upstream/current/doc/src/userman.xml
boost-jam/boost-build/branches/upstream/current/doc/tools.html
boost-jam/boost-build/branches/upstream/current/doc/tracker.html
boost-jam/boost-build/branches/upstream/current/example/
boost-jam/boost-build/branches/upstream/current/example/boost-build.jam
boost-jam/boost-build/branches/upstream/current/example/customization/
boost-jam/boost-build/branches/upstream/current/example/customization/Jamfile
boost-jam/boost-build/branches/upstream/current/example/customization/class.verbatim
boost-jam/boost-build/branches/upstream/current/example/customization/codegen.cpp
boost-jam/boost-build/branches/upstream/current/example/customization/inline_file.py
boost-jam/boost-build/branches/upstream/current/example/customization/project-root.jam
boost-jam/boost-build/branches/upstream/current/example/customization/readme.txt
boost-jam/boost-build/branches/upstream/current/example/customization/t1.verbatim
boost-jam/boost-build/branches/upstream/current/example/customization/t2.verbatim
boost-jam/boost-build/branches/upstream/current/example/customization/usage.verbatim
boost-jam/boost-build/branches/upstream/current/example/customization/verbatim.jam
boost-jam/boost-build/branches/upstream/current/example/gettext/
boost-jam/boost-build/branches/upstream/current/example/gettext/Jamfile
boost-jam/boost-build/branches/upstream/current/example/gettext/main.cpp
boost-jam/boost-build/branches/upstream/current/example/gettext/project-root.jam
boost-jam/boost-build/branches/upstream/current/example/gettext/readme.txt
boost-jam/boost-build/branches/upstream/current/example/gettext/russian.po
boost-jam/boost-build/branches/upstream/current/example/hello/
boost-jam/boost-build/branches/upstream/current/example/hello/Jamfile
boost-jam/boost-build/branches/upstream/current/example/hello/hello.cpp
boost-jam/boost-build/branches/upstream/current/example/hello/project-root.jam
boost-jam/boost-build/branches/upstream/current/example/libraries/
boost-jam/boost-build/branches/upstream/current/example/libraries/Jamfile
boost-jam/boost-build/branches/upstream/current/example/libraries/app/
boost-jam/boost-build/branches/upstream/current/example/libraries/app/Jamfile
boost-jam/boost-build/branches/upstream/current/example/libraries/app/app.cpp
boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/
boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/Jamfile
boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/include/
boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/include/lib1.h
boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/lib1.cpp
boost-jam/boost-build/branches/upstream/current/example/libraries/project-root.jam
boost-jam/boost-build/branches/upstream/current/example/qt-ui/
boost-jam/boost-build/branches/upstream/current/example/qt-ui/Jamfile
boost-jam/boost-build/branches/upstream/current/example/qt-ui/hello_world_widget.ui
boost-jam/boost-build/branches/upstream/current/example/qt-ui/main.cpp
boost-jam/boost-build/branches/upstream/current/example/qt-ui/project-root.jam
boost-jam/boost-build/branches/upstream/current/example/qt/
boost-jam/boost-build/branches/upstream/current/example/qt/Jamfile
boost-jam/boost-build/branches/upstream/current/example/qt/canvas.cpp
boost-jam/boost-build/branches/upstream/current/example/qt/canvas.h
boost-jam/boost-build/branches/upstream/current/example/qt/main.cpp
boost-jam/boost-build/branches/upstream/current/example/qt/project-root.jam
boost-jam/boost-build/branches/upstream/current/example/variant/
boost-jam/boost-build/branches/upstream/current/example/variant/Jamfile
boost-jam/boost-build/branches/upstream/current/example/variant/a.cpp
boost-jam/boost-build/branches/upstream/current/example/variant/libs/
boost-jam/boost-build/branches/upstream/current/example/variant/libs/Jamfile
boost-jam/boost-build/branches/upstream/current/example/variant/libs/l.cpp
boost-jam/boost-build/branches/upstream/current/example/variant/project-root.jam
boost-jam/boost-build/branches/upstream/current/example/variant/readme.txt
boost-jam/boost-build/branches/upstream/current/hacking.txt
boost-jam/boost-build/branches/upstream/current/index.html
boost-jam/boost-build/branches/upstream/current/jam_src/
boost-jam/boost-build/branches/upstream/current/jam_src/Jam.html
boost-jam/boost-build/branches/upstream/current/jam_src/Jambase
boost-jam/boost-build/branches/upstream/current/jam_src/Jambase.html
boost-jam/boost-build/branches/upstream/current/jam_src/Jamfile.html
boost-jam/boost-build/branches/upstream/current/jam_src/Porting
boost-jam/boost-build/branches/upstream/current/jam_src/README
boost-jam/boost-build/branches/upstream/current/jam_src/RELNOTES
boost-jam/boost-build/branches/upstream/current/jam_src/boost-jam.spec
boost-jam/boost-build/branches/upstream/current/jam_src/build.bat
boost-jam/boost-build/branches/upstream/current/jam_src/build.jam
boost-jam/boost-build/branches/upstream/current/jam_src/build.sh
boost-jam/boost-build/branches/upstream/current/jam_src/build_vms.com
boost-jam/boost-build/branches/upstream/current/jam_src/builtins.c
boost-jam/boost-build/branches/upstream/current/jam_src/builtins.h
boost-jam/boost-build/branches/upstream/current/jam_src/bump_version.py
boost-jam/boost-build/branches/upstream/current/jam_src/class.c
boost-jam/boost-build/branches/upstream/current/jam_src/class.h
boost-jam/boost-build/branches/upstream/current/jam_src/command.c
boost-jam/boost-build/branches/upstream/current/jam_src/command.h
boost-jam/boost-build/branches/upstream/current/jam_src/compile.c
boost-jam/boost-build/branches/upstream/current/jam_src/compile.h
boost-jam/boost-build/branches/upstream/current/jam_src/debian/
boost-jam/boost-build/branches/upstream/current/jam_src/debian/changelog
boost-jam/boost-build/branches/upstream/current/jam_src/debian/control
boost-jam/boost-build/branches/upstream/current/jam_src/debian/copyright
boost-jam/boost-build/branches/upstream/current/jam_src/debian/jam.man.sgml
boost-jam/boost-build/branches/upstream/current/jam_src/debian/rules
boost-jam/boost-build/branches/upstream/current/jam_src/execcmd.h
boost-jam/boost-build/branches/upstream/current/jam_src/execmac.c
boost-jam/boost-build/branches/upstream/current/jam_src/execnt.c
boost-jam/boost-build/branches/upstream/current/jam_src/execunix.c
boost-jam/boost-build/branches/upstream/current/jam_src/execvms.c
boost-jam/boost-build/branches/upstream/current/jam_src/expand.c
boost-jam/boost-build/branches/upstream/current/jam_src/expand.h
boost-jam/boost-build/branches/upstream/current/jam_src/filemac.c
boost-jam/boost-build/branches/upstream/current/jam_src/filent.c
boost-jam/boost-build/branches/upstream/current/jam_src/fileos2.c
boost-jam/boost-build/branches/upstream/current/jam_src/filesys.c
boost-jam/boost-build/branches/upstream/current/jam_src/filesys.h
boost-jam/boost-build/branches/upstream/current/jam_src/fileunix.c
boost-jam/boost-build/branches/upstream/current/jam_src/filevms.c
boost-jam/boost-build/branches/upstream/current/jam_src/frames.c
boost-jam/boost-build/branches/upstream/current/jam_src/frames.h
boost-jam/boost-build/branches/upstream/current/jam_src/glob.c
boost-jam/boost-build/branches/upstream/current/jam_src/hash.c
boost-jam/boost-build/branches/upstream/current/jam_src/hash.h
boost-jam/boost-build/branches/upstream/current/jam_src/hcache.c
boost-jam/boost-build/branches/upstream/current/jam_src/hcache.h
boost-jam/boost-build/branches/upstream/current/jam_src/hdrmacro.c
boost-jam/boost-build/branches/upstream/current/jam_src/hdrmacro.h
boost-jam/boost-build/branches/upstream/current/jam_src/headers.c
boost-jam/boost-build/branches/upstream/current/jam_src/headers.h
boost-jam/boost-build/branches/upstream/current/jam_src/index.html
boost-jam/boost-build/branches/upstream/current/jam_src/jam.c
boost-jam/boost-build/branches/upstream/current/jam_src/jam.h
boost-jam/boost-build/branches/upstream/current/jam_src/jambase.c
boost-jam/boost-build/branches/upstream/current/jam_src/jambase.h
boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.c
boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.h
boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.y
boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.yy
boost-jam/boost-build/branches/upstream/current/jam_src/jamgramtab.h
boost-jam/boost-build/branches/upstream/current/jam_src/lists.c
boost-jam/boost-build/branches/upstream/current/jam_src/lists.h
boost-jam/boost-build/branches/upstream/current/jam_src/make.c
boost-jam/boost-build/branches/upstream/current/jam_src/make.h
boost-jam/boost-build/branches/upstream/current/jam_src/make1.c
boost-jam/boost-build/branches/upstream/current/jam_src/mkjambase.c
boost-jam/boost-build/branches/upstream/current/jam_src/modules.c
boost-jam/boost-build/branches/upstream/current/jam_src/modules.h
boost-jam/boost-build/branches/upstream/current/jam_src/modules/
boost-jam/boost-build/branches/upstream/current/jam_src/modules/order.c
boost-jam/boost-build/branches/upstream/current/jam_src/modules/path.c
boost-jam/boost-build/branches/upstream/current/jam_src/modules/property-set.c
boost-jam/boost-build/branches/upstream/current/jam_src/modules/readme.txt
boost-jam/boost-build/branches/upstream/current/jam_src/modules/regex.c
boost-jam/boost-build/branches/upstream/current/jam_src/modules/sequence.c
boost-jam/boost-build/branches/upstream/current/jam_src/modules/set.c
boost-jam/boost-build/branches/upstream/current/jam_src/native.c
boost-jam/boost-build/branches/upstream/current/jam_src/native.h
boost-jam/boost-build/branches/upstream/current/jam_src/newstr.c
boost-jam/boost-build/branches/upstream/current/jam_src/newstr.h
boost-jam/boost-build/branches/upstream/current/jam_src/option.c
boost-jam/boost-build/branches/upstream/current/jam_src/option.h
boost-jam/boost-build/branches/upstream/current/jam_src/parse.c
boost-jam/boost-build/branches/upstream/current/jam_src/parse.h
boost-jam/boost-build/branches/upstream/current/jam_src/patchlevel.h
boost-jam/boost-build/branches/upstream/current/jam_src/pathmac.c
boost-jam/boost-build/branches/upstream/current/jam_src/pathsys.h
boost-jam/boost-build/branches/upstream/current/jam_src/pathunix.c
boost-jam/boost-build/branches/upstream/current/jam_src/pathvms.c
boost-jam/boost-build/branches/upstream/current/jam_src/pwd.c
boost-jam/boost-build/branches/upstream/current/jam_src/pwd.h
boost-jam/boost-build/branches/upstream/current/jam_src/regexp.c
boost-jam/boost-build/branches/upstream/current/jam_src/regexp.h
boost-jam/boost-build/branches/upstream/current/jam_src/rules.c
boost-jam/boost-build/branches/upstream/current/jam_src/rules.h
boost-jam/boost-build/branches/upstream/current/jam_src/scan.c
boost-jam/boost-build/branches/upstream/current/jam_src/scan.h
boost-jam/boost-build/branches/upstream/current/jam_src/search.c
boost-jam/boost-build/branches/upstream/current/jam_src/search.h
boost-jam/boost-build/branches/upstream/current/jam_src/strings.c
boost-jam/boost-build/branches/upstream/current/jam_src/strings.h
boost-jam/boost-build/branches/upstream/current/jam_src/subst.c
boost-jam/boost-build/branches/upstream/current/jam_src/timestamp.c
boost-jam/boost-build/branches/upstream/current/jam_src/timestamp.h
boost-jam/boost-build/branches/upstream/current/jam_src/variable.c
boost-jam/boost-build/branches/upstream/current/jam_src/variable.h
boost-jam/boost-build/branches/upstream/current/jam_src/w32_getreg.c
boost-jam/boost-build/branches/upstream/current/jam_src/yyacc.c
boost-jam/boost-build/branches/upstream/current/kernel/
boost-jam/boost-build/branches/upstream/current/kernel/boost-build.jam
boost-jam/boost-build/branches/upstream/current/kernel/bootstrap.jam
boost-jam/boost-build/branches/upstream/current/kernel/class.jam
boost-jam/boost-build/branches/upstream/current/kernel/errors.jam
boost-jam/boost-build/branches/upstream/current/kernel/modules.jam
boost-jam/boost-build/branches/upstream/current/options/
boost-jam/boost-build/branches/upstream/current/options/help.jam
boost-jam/boost-build/branches/upstream/current/site-config.jam
boost-jam/boost-build/branches/upstream/current/test/
boost-jam/boost-build/branches/upstream/current/test/BoostBuild.py
boost-jam/boost-build/branches/upstream/current/test/Jamfile
boost-jam/boost-build/branches/upstream/current/test/Jamrules
boost-jam/boost-build/branches/upstream/current/test/TestCmd.py
boost-jam/boost-build/branches/upstream/current/test/absolute_sources.py
boost-jam/boost-build/branches/upstream/current/test/alias.py
boost-jam/boost-build/branches/upstream/current/test/alternatives.py
boost-jam/boost-build/branches/upstream/current/test/assert-equal.jam
boost-jam/boost-build/branches/upstream/current/test/bad_dirname.py
boost-jam/boost-build/branches/upstream/current/test/boost-build.jam
boost-jam/boost-build/branches/upstream/current/test/build_dir.py
boost-jam/boost-build/branches/upstream/current/test/c_file.py
boost-jam/boost-build/branches/upstream/current/test/chain.py
boost-jam/boost-build/branches/upstream/current/test/check-arguments.jam
boost-jam/boost-build/branches/upstream/current/test/check-bindrule.jam
boost-jam/boost-build/branches/upstream/current/test/check-jam-patches.jam
boost-jam/boost-build/branches/upstream/current/test/check-test-tools.jam
boost-jam/boost-build/branches/upstream/current/test/composite.py
boost-jam/boost-build/branches/upstream/current/test/conditionals.py
boost-jam/boost-build/branches/upstream/current/test/conditionals2.py
boost-jam/boost-build/branches/upstream/current/test/conditionals3.py
boost-jam/boost-build/branches/upstream/current/test/core_d12.py
boost-jam/boost-build/branches/upstream/current/test/core_delete_module.py
boost-jam/boost-build/branches/upstream/current/test/core_dependencies.py
boost-jam/boost-build/branches/upstream/current/test/core_import_module.py
boost-jam/boost-build/branches/upstream/current/test/core_modifiers.py
boost-jam/boost-build/branches/upstream/current/test/core_typecheck.py
boost-jam/boost-build/branches/upstream/current/test/core_varnames.py
boost-jam/boost-build/branches/upstream/current/test/custom_generator.py
boost-jam/boost-build/branches/upstream/current/test/default_build.py
boost-jam/boost-build/branches/upstream/current/test/default_features.py
boost-jam/boost-build/branches/upstream/current/test/dependency-test/
boost-jam/boost-build/branches/upstream/current/test/dependency-test/Jamfile
boost-jam/boost-build/branches/upstream/current/test/dependency-test/a.cpp
boost-jam/boost-build/branches/upstream/current/test/dependency-test/a.h
boost-jam/boost-build/branches/upstream/current/test/dependency-test/b.cpp
boost-jam/boost-build/branches/upstream/current/test/dependency-test/b.h
boost-jam/boost-build/branches/upstream/current/test/dependency-test/c.cpp
boost-jam/boost-build/branches/upstream/current/test/dependency-test/e.cpp
boost-jam/boost-build/branches/upstream/current/test/dependency-test/foo.jam
boost-jam/boost-build/branches/upstream/current/test/dependency-test/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/
boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/a.h
boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/b.h
boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/c.h
boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/z.h
boost-jam/boost-build/branches/upstream/current/test/dependency-test/src2/
boost-jam/boost-build/branches/upstream/current/test/dependency-test/src2/b.h
boost-jam/boost-build/branches/upstream/current/test/dependency-test/x.foo
boost-jam/boost-build/branches/upstream/current/test/dependency-test/y.foo
boost-jam/boost-build/branches/upstream/current/test/dependency_property.py
boost-jam/boost-build/branches/upstream/current/test/dependency_test.py
boost-jam/boost-build/branches/upstream/current/test/direct-request-test/
boost-jam/boost-build/branches/upstream/current/test/direct-request-test/Jamfile
boost-jam/boost-build/branches/upstream/current/test/direct-request-test/Jamfile2
boost-jam/boost-build/branches/upstream/current/test/direct-request-test/a.cpp
boost-jam/boost-build/branches/upstream/current/test/direct-request-test/b.cpp
boost-jam/boost-build/branches/upstream/current/test/direct-request-test/b_inverse.cpp
boost-jam/boost-build/branches/upstream/current/test/direct-request-test/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/direct_request_test.py
boost-jam/boost-build/branches/upstream/current/test/dll_path.py
boost-jam/boost-build/branches/upstream/current/test/double_loading.py
boost-jam/boost-build/branches/upstream/current/test/duplicate.py
boost-jam/boost-build/branches/upstream/current/test/echo_args.jam
boost-jam/boost-build/branches/upstream/current/test/empty.jam
boost-jam/boost-build/branches/upstream/current/test/expansion.py
boost-jam/boost-build/branches/upstream/current/test/explicit.py
boost-jam/boost-build/branches/upstream/current/test/gcc_runtime.py
boost-jam/boost-build/branches/upstream/current/test/generators-test/
boost-jam/boost-build/branches/upstream/current/test/generators-test/Jamfile
boost-jam/boost-build/branches/upstream/current/test/generators-test/a.cpp
boost-jam/boost-build/branches/upstream/current/test/generators-test/b.cxx
boost-jam/boost-build/branches/upstream/current/test/generators-test/c.ui
boost-jam/boost-build/branches/upstream/current/test/generators-test/d.wd
boost-jam/boost-build/branches/upstream/current/test/generators-test/e.cpp
boost-jam/boost-build/branches/upstream/current/test/generators-test/extra.jam
boost-jam/boost-build/branches/upstream/current/test/generators-test/lex.jam
boost-jam/boost-build/branches/upstream/current/test/generators-test/lib/
boost-jam/boost-build/branches/upstream/current/test/generators-test/lib/Jamfile
boost-jam/boost-build/branches/upstream/current/test/generators-test/lib/c.cpp
boost-jam/boost-build/branches/upstream/current/test/generators-test/nm.jam
boost-jam/boost-build/branches/upstream/current/test/generators-test/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/generators-test/qt.jam
boost-jam/boost-build/branches/upstream/current/test/generators-test/x.l
boost-jam/boost-build/branches/upstream/current/test/generators-test/y.x_pro
boost-jam/boost-build/branches/upstream/current/test/generators-test/z.cpp
boost-jam/boost-build/branches/upstream/current/test/generators_test.py
boost-jam/boost-build/branches/upstream/current/test/glob.py
boost-jam/boost-build/branches/upstream/current/test/inherit_toolset.py
boost-jam/boost-build/branches/upstream/current/test/inline.py
boost-jam/boost-build/branches/upstream/current/test/library_chain.py
boost-jam/boost-build/branches/upstream/current/test/library_order.py
boost-jam/boost-build/branches/upstream/current/test/library_property.py
boost-jam/boost-build/branches/upstream/current/test/load_dir.py
boost-jam/boost-build/branches/upstream/current/test/loop.py
boost-jam/boost-build/branches/upstream/current/test/m1-01.py
boost-jam/boost-build/branches/upstream/current/test/m1-02.py
boost-jam/boost-build/branches/upstream/current/test/m1-03.py
boost-jam/boost-build/branches/upstream/current/test/make_rule.py
boost-jam/boost-build/branches/upstream/current/test/module-actions/
boost-jam/boost-build/branches/upstream/current/test/module-actions/boost-build.jam
boost-jam/boost-build/branches/upstream/current/test/module-actions/bootstrap.jam
boost-jam/boost-build/branches/upstream/current/test/module_actions.py
boost-jam/boost-build/branches/upstream/current/test/ndebug.py
boost-jam/boost-build/branches/upstream/current/test/no_type.py
boost-jam/boost-build/branches/upstream/current/test/ordered_properties.py
boost-jam/boost-build/branches/upstream/current/test/path_features.py
boost-jam/boost-build/branches/upstream/current/test/prebuilt.py
boost-jam/boost-build/branches/upstream/current/test/prebuilt/
boost-jam/boost-build/branches/upstream/current/test/prebuilt/Jamfile
boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/
boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/Jamfile
boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/Jamfile2
boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/Jamfile3
boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/a.cpp
boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/debug/
boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/debug/a.h
boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/release/
boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/release/a.h
boost-jam/boost-build/branches/upstream/current/test/prebuilt/hello.cpp
boost-jam/boost-build/branches/upstream/current/test/prebuilt/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/print.py
boost-jam/boost-build/branches/upstream/current/test/project-test1.jam
boost-jam/boost-build/branches/upstream/current/test/project-test1/
boost-jam/boost-build/branches/upstream/current/test/project-test1/Jamfile
boost-jam/boost-build/branches/upstream/current/test/project-test1/dir/
boost-jam/boost-build/branches/upstream/current/test/project-test1/dir/Jamfile
boost-jam/boost-build/branches/upstream/current/test/project-test1/dir2/
boost-jam/boost-build/branches/upstream/current/test/project-test1/dir2/Jamfile
boost-jam/boost-build/branches/upstream/current/test/project-test1/dir2/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/project-test1/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/project-test1/project-test1.jam
boost-jam/boost-build/branches/upstream/current/test/project-test1/readme.txt
boost-jam/boost-build/branches/upstream/current/test/project-test1/standalone-project.jam
boost-jam/boost-build/branches/upstream/current/test/project-test3/
boost-jam/boost-build/branches/upstream/current/test/project-test3/Jamfile
boost-jam/boost-build/branches/upstream/current/test/project-test3/a.cpp
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib/
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib/Jamfile
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib/b.cpp
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/Jamfile
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/c.cpp
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/d.cpp
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/helper/
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/helper/Jamfile
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/helper/e.cpp
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib3/
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib3/Jamfile
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib3/f.cpp
boost-jam/boost-build/branches/upstream/current/test/project-test3/lib3/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/project-test3/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/project-test3/readme.txt
boost-jam/boost-build/branches/upstream/current/test/project-test4/
boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile
boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile3
boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile4
boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile5
boost-jam/boost-build/branches/upstream/current/test/project-test4/a.cpp
boost-jam/boost-build/branches/upstream/current/test/project-test4/a_gcc.cpp
boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/
boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile
boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile1
boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile2
boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile3
boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/b.cpp
boost-jam/boost-build/branches/upstream/current/test/project-test4/lib2/
boost-jam/boost-build/branches/upstream/current/test/project-test4/lib2/Jamfile
boost-jam/boost-build/branches/upstream/current/test/project-test4/lib2/Jamfile2
boost-jam/boost-build/branches/upstream/current/test/project-test4/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/project-test4/readme.txt
boost-jam/boost-build/branches/upstream/current/test/project_dependencies.py
boost-jam/boost-build/branches/upstream/current/test/project_root.py
boost-jam/boost-build/branches/upstream/current/test/project_root_constants.py
boost-jam/boost-build/branches/upstream/current/test/project_test1.py
boost-jam/boost-build/branches/upstream/current/test/project_test3.py
boost-jam/boost-build/branches/upstream/current/test/project_test4.py
boost-jam/boost-build/branches/upstream/current/test/property_expansion.py
boost-jam/boost-build/branches/upstream/current/test/railsys.py
boost-jam/boost-build/branches/upstream/current/test/railsys/
boost-jam/boost-build/branches/upstream/current/test/railsys/libx/
boost-jam/boost-build/branches/upstream/current/test/railsys/libx/include/
boost-jam/boost-build/branches/upstream/current/test/railsys/libx/include/test_libx.h
boost-jam/boost-build/branches/upstream/current/test/railsys/libx/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/railsys/libx/src/
boost-jam/boost-build/branches/upstream/current/test/railsys/libx/src/Jamfile
boost-jam/boost-build/branches/upstream/current/test/railsys/libx/src/test_libx.cpp
boost-jam/boost-build/branches/upstream/current/test/railsys/program/
boost-jam/boost-build/branches/upstream/current/test/railsys/program/Jamfile
boost-jam/boost-build/branches/upstream/current/test/railsys/program/include/
boost-jam/boost-build/branches/upstream/current/test/railsys/program/include/test_a.h
boost-jam/boost-build/branches/upstream/current/test/railsys/program/liba/
boost-jam/boost-build/branches/upstream/current/test/railsys/program/liba/Jamfile
boost-jam/boost-build/branches/upstream/current/test/railsys/program/liba/test_a.cpp
boost-jam/boost-build/branches/upstream/current/test/railsys/program/main/
boost-jam/boost-build/branches/upstream/current/test/railsys/program/main/Jamfile
boost-jam/boost-build/branches/upstream/current/test/railsys/program/main/main.cpp
boost-jam/boost-build/branches/upstream/current/test/railsys/program/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/readme.txt
boost-jam/boost-build/branches/upstream/current/test/recursive.jam
boost-jam/boost-build/branches/upstream/current/test/regression.py
boost-jam/boost-build/branches/upstream/current/test/relative_sources.py
boost-jam/boost-build/branches/upstream/current/test/searched_lib.py
boost-jam/boost-build/branches/upstream/current/test/skipping.py
boost-jam/boost-build/branches/upstream/current/test/stage.py
boost-jam/boost-build/branches/upstream/current/test/standalone.py
boost-jam/boost-build/branches/upstream/current/test/startup/
boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/
boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/boost-build.jam
boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/build/
boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/build/boost-build.jam
boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/build/bootstrap.jam
boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-env/
boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-env/boost-build.jam
boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-explicit/
boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-explicit/boost-build.jam
boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-implicit/
boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-implicit/readme.txt
boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap1/
boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap1/boost-build.jam
boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap1/subdir/
boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap1/subdir/readme.txt
boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap2/
boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap2/boost-build.jam
boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap3/
boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap3/boost-build.jam
boost-jam/boost-build/branches/upstream/current/test/startup_v1.py
boost-jam/boost-build/branches/upstream/current/test/startup_v2.py
boost-jam/boost-build/branches/upstream/current/test/subdir1/
boost-jam/boost-build/branches/upstream/current/test/subdir1/file-to-bind
boost-jam/boost-build/branches/upstream/current/test/suffix.py
boost-jam/boost-build/branches/upstream/current/test/svn_tree.py
boost-jam/boost-build/branches/upstream/current/test/symlink.py
boost-jam/boost-build/branches/upstream/current/test/tag.py
boost-jam/boost-build/branches/upstream/current/test/template.py
boost-jam/boost-build/branches/upstream/current/test/test-config-example.jam
boost-jam/boost-build/branches/upstream/current/test/test.jam
boost-jam/boost-build/branches/upstream/current/test/test1.py
boost-jam/boost-build/branches/upstream/current/test/test2.py
boost-jam/boost-build/branches/upstream/current/test/test2/
boost-jam/boost-build/branches/upstream/current/test/test2/Jamfile
boost-jam/boost-build/branches/upstream/current/test/test2/Jamrules
boost-jam/boost-build/branches/upstream/current/test/test2/foo.cpp
boost-jam/boost-build/branches/upstream/current/test/test_all.py
boost-jam/boost-build/branches/upstream/current/test/test_nt_line_length.jam
boost-jam/boost-build/branches/upstream/current/test/test_system.html
boost-jam/boost-build/branches/upstream/current/test/testing-primitives/
boost-jam/boost-build/branches/upstream/current/test/testing-primitives/boost-build.jam
boost-jam/boost-build/branches/upstream/current/test/testing-primitives/bootstrap.jam
boost-jam/boost-build/branches/upstream/current/test/testing_primitives.py
boost-jam/boost-build/branches/upstream/current/test/tree.py
boost-jam/boost-build/branches/upstream/current/test/unit-tests.jam
boost-jam/boost-build/branches/upstream/current/test/unit_test.py
boost-jam/boost-build/branches/upstream/current/test/unit_tests.py
boost-jam/boost-build/branches/upstream/current/test/unused.py
boost-jam/boost-build/branches/upstream/current/test/unused/
boost-jam/boost-build/branches/upstream/current/test/unused/Jamfile
boost-jam/boost-build/branches/upstream/current/test/unused/a.cpp
boost-jam/boost-build/branches/upstream/current/test/unused/b.cpp
boost-jam/boost-build/branches/upstream/current/test/unused/b.x
boost-jam/boost-build/branches/upstream/current/test/unused/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/use_requirements.py
boost-jam/boost-build/branches/upstream/current/test/v1-testing/
boost-jam/boost-build/branches/upstream/current/test/v1-testing/Jamfile
boost-jam/boost-build/branches/upstream/current/test/v1-testing/a.cpp
boost-jam/boost-build/branches/upstream/current/test/v1-testing/b.cpp
boost-jam/boost-build/branches/upstream/current/test/v1-testing/boost-build.jam
boost-jam/boost-build/branches/upstream/current/test/v1-testing/c.cpp
boost-jam/boost-build/branches/upstream/current/test/v1_testing.py
boost-jam/boost-build/branches/upstream/current/test/v1_testing/
boost-jam/boost-build/branches/upstream/current/test/v1_testing/Jamfile
boost-jam/boost-build/branches/upstream/current/test/v1_testing/Jamrules
boost-jam/boost-build/branches/upstream/current/test/v1_testing/boost-build.jam
boost-jam/boost-build/branches/upstream/current/test/v1_testing/foo.cpp
boost-jam/boost-build/branches/upstream/current/test/v1_testing/lib-err.cpp
boost-jam/boost-build/branches/upstream/current/test/v1_testing/lib.cpp
boost-jam/boost-build/branches/upstream/current/test/v1_testing/project-root.jam
boost-jam/boost-build/branches/upstream/current/test/wrapper.py
boost-jam/boost-build/branches/upstream/current/tools/
boost-jam/boost-build/branches/upstream/current/tools/bison.jam
boost-jam/boost-build/branches/upstream/current/tools/boostbook.jam
boost-jam/boost-build/branches/upstream/current/tools/borland.jam
boost-jam/boost-build/branches/upstream/current/tools/builtin.jam
boost-jam/boost-build/branches/upstream/current/tools/common.jam
boost-jam/boost-build/branches/upstream/current/tools/como-linux.jam
boost-jam/boost-build/branches/upstream/current/tools/como-win.jam
boost-jam/boost-build/branches/upstream/current/tools/como.jam
boost-jam/boost-build/branches/upstream/current/tools/cw.jam
boost-jam/boost-build/branches/upstream/current/tools/darwin.jam
boost-jam/boost-build/branches/upstream/current/tools/doxygen.jam
boost-jam/boost-build/branches/upstream/current/tools/fop.jam
boost-jam/boost-build/branches/upstream/current/tools/gcc.jam
boost-jam/boost-build/branches/upstream/current/tools/gettext.jam
boost-jam/boost-build/branches/upstream/current/tools/intel-linux.jam
boost-jam/boost-build/branches/upstream/current/tools/intel-win.jam
boost-jam/boost-build/branches/upstream/current/tools/intel.jam
boost-jam/boost-build/branches/upstream/current/tools/kylix.jam
boost-jam/boost-build/branches/upstream/current/tools/lex.jam
boost-jam/boost-build/branches/upstream/current/tools/make.jam
boost-jam/boost-build/branches/upstream/current/tools/msvc.jam
boost-jam/boost-build/branches/upstream/current/tools/qt.jam
boost-jam/boost-build/branches/upstream/current/tools/rc.jam
boost-jam/boost-build/branches/upstream/current/tools/stage.jam
boost-jam/boost-build/branches/upstream/current/tools/stlport.jam
boost-jam/boost-build/branches/upstream/current/tools/sun.jam
boost-jam/boost-build/branches/upstream/current/tools/symlink.jam
boost-jam/boost-build/branches/upstream/current/tools/testing.jam
boost-jam/boost-build/branches/upstream/current/tools/unix.jam
boost-jam/boost-build/branches/upstream/current/tools/vacpp.jam
boost-jam/boost-build/branches/upstream/current/tools/xsltproc.jam
boost-jam/boost-build/branches/upstream/current/user-config.jam
boost-jam/boost-build/branches/upstream/current/util/
boost-jam/boost-build/branches/upstream/current/util/assert.jam
boost-jam/boost-build/branches/upstream/current/util/container.jam
boost-jam/boost-build/branches/upstream/current/util/doc.jam
boost-jam/boost-build/branches/upstream/current/util/indirect.jam
boost-jam/boost-build/branches/upstream/current/util/numbers.jam
boost-jam/boost-build/branches/upstream/current/util/order.jam
boost-jam/boost-build/branches/upstream/current/util/os.jam
boost-jam/boost-build/branches/upstream/current/util/path.jam
boost-jam/boost-build/branches/upstream/current/util/print.jam
boost-jam/boost-build/branches/upstream/current/util/regex.jam
boost-jam/boost-build/branches/upstream/current/util/sequence.jam
boost-jam/boost-build/branches/upstream/current/util/set.jam
boost-jam/boost-build/branches/upstream/current/util/string.jam
boost-jam/boost-build/branches/upstream/current/util/utility.jam
boost-jam/boost-build/tags/
Log:
[svn-inject] Installing original source of boost-build
Added: boost-jam/boost-build/branches/upstream/current/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+boost-build kernel ;
+
Added: boost-jam/boost-build/branches/upstream/current/boost.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/boost.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/bootstrap.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/bootstrap.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/bootstrap.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,18 @@
+# Copyright (c) 2003 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# This file handles initial phase of Boost.Build loading.
+# Boost.Jam has already figured out where Boost.Build is
+# and loads this file, which is responsible for initialization
+# of basic facilities such a module system and loading the
+# main Boost.Build module, build-system.jam.
+#
+# Exact operation of this module is not interesting, it makes
+# sense to look at build-system.jam right away.
+
+# Load the kernel/bootstrap.jam, which does all the work.
+.bootstrap-file = $(.bootstrap-file:D)/kernel/bootstrap.jam ;
+include $(.bootstrap-file) ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/build/alias.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/alias.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/alias.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,81 @@
+# 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.
+
+# This module defines the 'alias' rule and associated class.
+#
+# Alias is just a main target which returns its source targets without any
+# processing. For example::
+#
+# alias bin : hello test_hello ;
+# alias lib : helpers xml_parser ;
+#
+# Another important use of 'alias' is to conveniently group source files::
+#
+# alias platform-src : win.cpp : <os>NT ;
+# alias platform-src : linux.cpp : <os>LINUX ;
+# exe main : main.cpp platform-src ;
+#
+# Lastly, it's possible to create local alias for some target, with different
+# properties::
+#
+# alias big_lib : : @/external_project/big_lib/<link>static ;
+#
+
+import targets ;
+import "class" : new ;
+import property ;
+import errors : error ;
+import type : type ;
+import regex ;
+import project ;
+
+class alias-target-class : basic-target
+{
+ rule __init__ ( name : project : sources * : requirements *
+ : default-build * : usage-requirements * )
+ {
+ basic-target.__init__ $(name) : $(project) : $(sources) : $(requirements)
+ : $(default-build) : $(usage-requirements) ;
+ }
+
+ rule construct ( source-targets * : property-set )
+ {
+ return $(source-targets) ;
+ }
+
+ # This check makes no sense for 'alias', so just
+ # disable it.
+ rule check-for-link-compatibility ( * : * )
+ {
+ }
+
+ rule compute-usage-requirements ( subvariant )
+ {
+ local base = [ basic-target.compute-usage-requirements $(subvariant) ] ;
+ # Add source's usage requirement. If we don't do this, "alias" does not
+ # look like 100% alias.
+ return [ $(base).add [ $(subvariant).sources-usage-requirements ] ] ;
+ }
+
+}
+
+# Declares the 'alias' target. It will build sources, and return them unaltered.
+rule alias ( name : sources * : requirements * : default-build * : usage-requirements * )
+{
+ local project = [ project.current ] ;
+
+ targets.main-target-alternative
+ [ new alias-target-class $(name) : $(project)
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
+ ] ;
+}
+
+IMPORT $(__name__) : alias : : alias ;
+
+
+
Added: boost-jam/boost-build/branches/upstream/current/build/build-request.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/build-request.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/build-request.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,292 @@
+# (C) Copyright David Abrahams 2002. 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.
+
+import sequence ;
+import set ;
+import regex ;
+import feature ;
+import property ;
+import numbers ;
+import container ;
+import "class" : new ;
+import string ;
+
+# Transform property-set by applying f to each component property.
+local rule apply-to-property-set ( f property-set )
+{
+ local properties = [ feature.split $(property-set) ] ;
+ return [ string.join [ $(f) $(properties) ] : / ] ;
+}
+
+# expand the given build request by combining all property-sets which don't
+# specify conflicting non-free features.
+rule expand-no-defaults ( property-sets * )
+{
+ # First make all features and subfeatures explicit
+ local expanded-property-sets = [
+ sequence.transform apply-to-property-set feature.expand-subfeatures
+ : $(property-sets) ] ;
+
+ # Now combine all of the expanded property-sets
+ local product = [ x-product $(expanded-property-sets) : $(feature-space) ] ;
+
+ return $(product) ;
+}
+
+# implementaiton of x-product, below
+local rule x-product-aux ( property-sets + )
+{
+ local result ;
+ local p = [ feature.split $(property-sets[1]) ] ;
+ local f = [ set.difference $(p:G) : [ feature.free-features ] ] ;
+ local seen ;
+ # No conflict with things used at a higher level?
+ if ! [ set.intersection $(f) : $(x-product-used) ]
+ {
+ local x-product-seen ;
+ {
+ # don't mix in any conflicting features
+ local x-product-used = $(x-product-used) $(f) ;
+
+ if $(property-sets[2])
+ {
+ local rest = [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ;
+ result = $(property-sets[1])/$(rest) ;
+ }
+
+ result ?= $(property-sets[1]) ;
+ }
+
+ # If we didn't encounter a conflicting feature lower down,
+ # don't recurse again.
+ if ! [ set.intersection $(f) : $(x-product-seen) ]
+ {
+ property-sets = ;
+ }
+
+ seen = $(x-product-seen) ;
+ }
+
+ if $(property-sets[2])
+ {
+ result += [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ;
+ }
+
+ # Note that we've seen these features so that higher levels will
+ # recurse again without them set.
+ x-product-seen += $(f) $(seen) ;
+ return $(result) ;
+}
+
+# Return the cross-product of all elements of property-sets, less any
+# that would contain conflicting values for single-valued features.
+local rule x-product ( property-sets * )
+{
+ if $(property-sets).non-empty
+ {
+ # prepare some "scoped globals" that can be used by the
+ # implementation function, x-product-aux.
+ local x-product-seen x-product-used ;
+ return [ x-product-aux $(property-sets) : $(feature-space) ] ;
+ }
+ # otherwise return empty
+}
+
+# Returns true if 'v' is either implicit value, or
+# the part before the first '-' symbol is implicit value
+local rule looks-like-implicit-value ( v )
+{
+
+ if [ feature.is-implicit-value $(v) ]
+ {
+ return true ;
+ }
+ else
+ {
+ local split = [ regex.split $(v) - ] ;
+ if [ feature.is-implicit-value $(split[1]) ]
+ {
+ return true ;
+ }
+ }
+}
+
+
+# Takes the command line tokens (such as taken from ARGV rule) and constructs
+# build request from it.
+# Returns a vector of two vectors (where "vector" means container.jam's "vector").
+# First is the set of targets specified in the command line, and second is
+# the set of requested build properties.
+rule from-command-line ( command-line * )
+{
+ local targets ;
+ local properties ;
+
+ command-line = $(command-line[2-]) ;
+ for local e in $(command-line)
+ {
+ if ! [ MATCH "^(-).*" : $(e) ]
+ {
+ # Build request spec either has "=" in it, or completely
+ # consists of implicit feature values.
+ local fs = feature-space ;
+ if [ MATCH "(.*=.*)" : $(e) ]
+ || [ looks-like-implicit-value $(e:D=) : $(feature-space) ]
+ {
+ properties += [ convert-command-line-element $(e) : $(feature-space) ] ;
+ }
+ else
+ {
+ targets += $(e) ;
+ }
+ }
+ }
+ return [ new vector [ new vector $(targets) ] [ new vector $(properties) ] ] ;
+}
+
+# Converts one element of command line build request specification into
+# internal form.
+local rule convert-command-line-element ( e )
+{
+ local result ;
+ local parts = [ regex.split $(e) "/" ] ;
+ for local p in $(parts)
+ {
+ local m = [ MATCH "([^=]*)=(.*)" : $(p) ] ;
+ local lresult ;
+ if $(m)
+ {
+ local feature = $(m[1]) ;
+ local values = [ regex.split $(m[2]) "," ] ;
+ lresult = <$(feature)>$(values) ;
+ }
+ else
+ {
+ lresult = [ regex.split $(p) "," ] ;
+ }
+
+ if ! [ MATCH (.*-.*) : $(p) ]
+ {
+ # property.validate cannot handle subfeatures,
+ # so we avoid the check here.
+ for local p in $(lresult)
+ {
+ property.validate $(p) : $(feature-space) ;
+ }
+ }
+
+
+ if ! $(result)
+ {
+ result = $(lresult) ;
+ }
+ else
+ {
+ result = $(result)/$(lresult) ;
+ }
+ }
+
+ return $(result) ;
+}
+
+rule __test__ ( )
+{
+ import assert feature ;
+
+ feature.prepare-test build-request-test-temp ;
+
+ import build-request ;
+ import build-request : expand-no-defaults : build-request.expand-no-defaults ;
+ import errors : try catch ;
+ import feature : feature subfeature ;
+
+ feature toolset : gcc msvc borland : implicit ;
+ subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4
+ 3.0 3.0.1 3.0.2 : optional ;
+
+ feature variant : debug release : implicit composite ;
+ feature inlining : on off ;
+ feature "include" : : free ;
+
+ feature stdlib : native stlport : implicit ;
+
+ feature runtime-link : dynamic static : symmetric ;
+
+ # empty build requests should expand to empty.
+ assert.result
+ : build-request.expand-no-defaults
+ ;
+
+ assert.result
+ <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug
+ <toolset>msvc/<stdlib>stlport/<variant>debug
+ <toolset>msvc/<variant>debug
+
+ : build-request.expand-no-defaults gcc-3.0.1/stlport msvc/stlport msvc debug
+ ;
+
+ assert.result
+ <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug
+ <toolset>msvc/<variant>debug
+ <variant>debug/<toolset>msvc/<stdlib>stlport
+
+ : build-request.expand-no-defaults gcc-3.0.1/stlport msvc debug msvc/stlport
+ ;
+
+ assert.result
+ <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug/<inlining>off
+ <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>release/<inlining>off
+
+ : build-request.expand-no-defaults gcc-3.0.1/stlport debug release <inlining>off
+ ;
+
+ assert.result
+ <include>a/b/c/<toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug/<include>x/y/z
+ <include>a/b/c/<toolset>msvc/<stdlib>stlport/<variant>debug/<include>x/y/z
+ <include>a/b/c/<toolset>msvc/<variant>debug/<include>x/y/z
+
+ : build-request.expand-no-defaults <include>a/b/c gcc-3.0.1/stlport msvc/stlport msvc debug <include>x/y/z
+ ;
+
+ local r ;
+
+ r = [ build-request.from-command-line bjam debug runtime-link=dynamic ] ;
+ assert.equal [ $(r).get-at 1 ] : ;
+ assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic ;
+
+ try ;
+ {
+
+ build-request.from-command-line bjam gcc/debug runtime-link=dynamic/static ;
+ }
+ catch \"static\" is not a value of an implicit feature ;
+
+
+ r = [ build-request.from-command-line bjam -d2 --debug debug target runtime-link=dynamic ] ;
+ assert.equal [ $(r).get-at 1 ] : target ;
+ assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic ;
+
+ r = [ build-request.from-command-line bjam debug runtime-link=dynamic,static ] ;
+ assert.equal [ $(r).get-at 1 ] : ;
+ assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic <runtime-link>static ;
+
+ r = [ build-request.from-command-line bjam debug gcc/runtime-link=dynamic,static ] ;
+ assert.equal [ $(r).get-at 1 ] : ;
+ assert.equal [ $(r).get-at 2 ] : debug gcc/<runtime-link>dynamic
+ gcc/<runtime-link>static ;
+
+ r = [ build-request.from-command-line bjam msvc gcc,borland/runtime-link=static ] ;
+ assert.equal [ $(r).get-at 1 ] : ;
+ assert.equal [ $(r).get-at 2 ] : msvc gcc/<runtime-link>static
+ borland/<runtime-link>static ;
+
+ r = [ build-request.from-command-line bjam gcc-3.0 ] ;
+ assert.equal [ $(r).get-at 1 ] : ;
+ assert.equal [ $(r).get-at 2 ] : gcc-3.0 ;
+
+ feature.finish-test build-request-test-temp ;
+}
+
+
Added: boost-jam/boost-build/branches/upstream/current/build/feature.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/feature.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/feature.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1218 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+import "class" : * ;
+
+import errors : error lol->list ;
+import sequence ;
+import regex ;
+import set ;
+import utility ;
+import modules indirect ;
+import assert : * ;
+
+local rule setup ( )
+{
+ .all-attributes =
+
+ implicit
+ executed
+ composite
+ optional
+ symmetric
+ free
+ incidental
+ path
+ dependency
+ propagated
+ link-incompatible
+ subfeature
+ order-sensitive
+ ;
+
+ .all-features = ;
+ .all-subfeatures = ; # non-subfeatures
+ .all-top-features = ; # non-subfeatures
+ .all-implicit-values = ;
+}
+setup ;
+
+# prepare a fresh space to test in by moving all global variable
+# settings into the given temporary module and erasing them here.
+rule prepare-test ( temp-module )
+{
+ DELETE_MODULE $(temp-module) ;
+
+ # transfer globals to temp-module
+ for local v in [ VARNAMES feature ]
+ {
+ if [ MATCH (\\.) : $(v) ]
+ {
+ modules.poke $(temp-module) : $(v) : $($(v)) ;
+ $(v) = ;
+ }
+ }
+ setup ;
+}
+
+# clear out all global variables and recover all variables from the
+# given temporary module
+rule finish-test ( temp-module )
+{
+ # clear globals
+ for local v in [ VARNAMES feature ]
+ {
+ if [ MATCH (\\.) : $(v) ]
+ {
+ $(v) = ;
+ }
+ }
+
+ for local v in [ VARNAMES $(temp-module) ]
+ {
+ $(v) = [ modules.peek $(temp-module) : $(v) ] ;
+ }
+ DELETE_MODULE $(temp-module) ;
+}
+
+
+# Transform features by bracketing any elements which aren't already
+# bracketed by "<>"
+local rule grist ( features * )
+{
+ local empty = "" ;
+ local r = $(empty:G=$(features)) ;
+ return $(r) ;
+}
+
+empty = "" ;
+
+# declare a new feature with the given name, values, and attributes.
+rule feature (
+ name # feature name
+ : values * # the allowable values - may be extended later with feature.extend
+ : attributes * # The feature's attributes (e.g. implicit, free, propagated...)
+)
+{
+ name = [ grist $(name) ] ;
+
+ local error ;
+
+ # if there are any unknown attributes...
+ if ! ( $(attributes) in $(.all-attributes) )
+ {
+ error = unknown attributes:
+ [ set.difference $(attributes) : $(.all-attributes) ] ;
+ }
+ else if $(name) in $(.all-features)
+ {
+ error = feature already defined: ;
+ }
+ else if implicit in $(attributes) && free in $(attributes)
+ {
+ error = free features cannot also be implicit ;
+ }
+ else if free in $(attributes) && propagated in $(attributes)
+ {
+ error = free features cannot be propagated ;
+ }
+
+
+ if $(error)
+ {
+ error $(error)
+ : "in" feature declaration:
+ : feature [ lol->list $(1) : $(2) : $(3) ] ;
+ }
+
+ $(name).values ?= ;
+ $(name).attributes = $(attributes) ;
+ $(name).subfeatures ?= ;
+ $(attributes).features += $(name) ;
+
+ .all-features += $(name) ;
+ if subfeature in $(attributes)
+ {
+ .all-subfeatures += $(name) ;
+ }
+ else
+ {
+ .all-top-features += $(name) ;
+ }
+ extend $(name) : $(values) ;
+}
+
+# set default value of the given feature, overriding any previous
+# default.
+rule set-default ( feature : value )
+{
+ local f = [ grist $(feature) ] ;
+ if ! $(value) in $($(f).values)
+ {
+ errors.error "The specified default value, '$(value)' is invalid"
+ : "allowed values are: " $($(f).values) ;
+ }
+ $(f).default = $(value) ;
+}
+
+
+# return the default property values for the given features.
+rule defaults ( features * )
+{
+ local result ;
+ for local f in $(features)
+ {
+ local a = $($(f).attributes) ;
+ if ( free in $(a) ) || ( optional in $(a) )
+ {
+ }
+ else
+ {
+ result += $(f)$($(f).default) ;
+ }
+ }
+ return $(result) ;
+}
+
+# returns true iff all elements of names are valid features.
+rule valid ( names + )
+{
+ if $(names) in $(.all-features)
+ {
+ return true ;
+ }
+}
+
+# return the attibutes of the given feature
+rule attributes ( feature )
+{
+ if ! [ valid $(feature) ]
+ {
+ error \"$(feature)\" is not a valid feature name ;
+ }
+ return $($(feature).attributes) ;
+}
+
+# return the values of the given feature
+rule values ( feature )
+{
+ return $($(feature).values) ;
+}
+
+# returns true iff 'value-string' is a value-string of an implicit feature
+rule is-implicit-value ( value-string )
+{
+ local v = [ regex.split $(value-string) - ] ;
+ local failed ;
+ if ! $(v[1]) in $(.all-implicit-values)
+ {
+ failed = true ;
+ }
+ else
+ {
+ local feature = $($(v[1]).implicit-feature) ;
+
+ for local subvalue in $(v[2-])
+ {
+ if ! [ find-implied-subfeature $(feature) $(subvalue) : $(v[1]) ]
+ {
+ failed = true ;
+ }
+ }
+ }
+
+ if ! $(failed)
+ {
+ return true ;
+ }
+}
+
+# return the implicit feature associated with the given implicit value.
+rule implied-feature ( implicit-value )
+{
+ local components = [ regex.split $(implicit-value) "-" ] ;
+
+ local feature = $($(components[1]).implicit-feature) ;
+ if ! $(feature)
+ {
+ error \"$(implicit-value)\" is not a value of an implicit feature ;
+ feature = "" ; # keep testing happy; it expects a result.
+ }
+ return $(feature) ;
+}
+
+local rule find-implied-subfeature ( feature subvalue : value-string ? )
+{
+ # feature should be of the form <feature-name>
+ if $(feature) != $(feature:G)
+ {
+ error invalid feature $(feature) ;
+ }
+
+ return $($(feature)$(value-string:E="")<>$(subvalue).subfeature) ;
+}
+
+# Given a feature and a value of one of its subfeatures, find the name
+# of the subfeature. If value-string is supplied, looks for implied
+# subfeatures that are specific to that value of feature
+rule implied-subfeature (
+ feature # The main feature name
+ subvalue # The value of one of its subfeatures
+ : value-string ? # The value of the main feature
+)
+{
+ local subfeature = [ find-implied-subfeature $(feature) $(subvalue)
+ : $(value-string) ] ;
+
+ if ! $(subfeature)
+ {
+ value-string ?= "" ;
+ error \"$(subvalue)\" is not a known subfeature value of
+ $(feature)$(value-string) ;
+ }
+
+ return $(subfeature) ;
+}
+
+# generate an error if the feature is unknown
+local rule validate-feature ( feature )
+{
+ if ! $(feature) in $(.all-features)
+ {
+ error unknown feature \"$(feature)\" ;
+ }
+}
+
+# Given a feature and value, or just a value corresponding to an
+# implicit feature, returns a property set consisting of all component
+# subfeatures and their values. For example:
+#
+# expand-subfeatures <toolset>gcc-2.95.2-linux-x86
+# -> <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
+#
+# equivalent to:
+# expand-subfeatures gcc-2.95.2-linux-x86
+local rule expand-subfeatures-aux (
+ feature ? # The name of the feature, or empty if value corresponds to an implicit property
+ : value # The value of the feature.
+ : dont-validate ? # If set, no validation of value string will be done
+)
+{
+ if $(feature)
+ {
+ feature = $(feature) ;
+ }
+
+ if ! $(feature)
+ {
+ feature = [ implied-feature $(value) ] ;
+ }
+ else
+ {
+ validate-feature $(feature) ;
+ }
+ if ! $(dont-validate)
+ {
+ validate-value-string $(feature) $(value) ;
+ }
+
+ local components = [ regex.split $(value) "-" ] ;
+
+ # get the top-level feature's value
+ local value = $(components[1]:G=) ;
+
+ local result = $(components[1]:G=$(feature)) ;
+
+ local subvalues = $(components[2-]) ;
+ while $(subvalues)
+ {
+ local subvalue = $(subvalues[1]) ; # pop the head off of subvalues
+ subvalues = $(subvalues[2-]) ;
+
+ local subfeature = [ find-implied-subfeature $(feature) $(subvalue) : $(value) ] ;
+
+ # If no subfeature was found, reconstitute the value string and use that
+ if ! $(subfeature)
+ {
+ result = $(components:J=-) ;
+ result = $(result:G=$(feature)) ;
+ subvalues = ; # stop looping
+ }
+ else
+ {
+ local f = [ MATCH ^<(.*)>$ : $(feature) ] ;
+ result += $(subvalue:G=$(f)-$(subfeature)) ;
+ }
+ }
+
+ return $(result) ;
+}
+
+# Make all elements of properties corresponding to implicit features
+# explicit, and express all subfeature values as separate properties
+# in their own right. For example, the property
+#
+# gcc-2.95.2-linux-x86
+#
+# might expand to
+#
+# <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
+#
+rule expand-subfeatures (
+ properties * # property set with elements of the form
+ # <feature>value-string or just value-string in the
+ # case of implicit features.
+ : dont-validate ?
+)
+{
+ local result ;
+ for local p in $(properties)
+ {
+ # Don't expand subfeatures in subfeatures
+ if ! [ MATCH "(:)" : $(p:G) ]
+ {
+ result += [ expand-subfeatures-aux $(p:G) : $(p:G=) : $(dont-validate) ] ;
+ }
+ else
+ {
+ result += $(p) ;
+ }
+ }
+ return $(result) ;
+}
+
+# Helper for extend, below. Handles the feature case.
+local rule extend-feature ( feature : values * )
+{
+ feature = [ grist $(feature) ] ;
+ validate-feature $(feature) ;
+ if implicit in $($(feature).attributes)
+ {
+ for local v in $(values)
+ {
+ if $($(v).implicit-feature)
+ {
+ error $(v) is already associated with the \"$($(v).implicit-feature)\" feature ;
+ }
+ $(v).implicit-feature = $(feature) ;
+ }
+
+ .all-implicit-values += $(values) ;
+ }
+ if ! $($(feature).values)
+ {
+ # This is the first value specified for this feature,
+ # take it as default value
+ $(feature).default = $(values[1]) ;
+ }
+ $(feature).values += $(values) ;
+}
+
+# Checks that value-string is a valid value-string for the given feature.
+rule validate-value-string ( feature value-string )
+{
+ if ! (
+ free in $($(feature).attributes)
+ || ( $(value-string) in $(feature).values )
+ )
+ {
+ local values = $(value-string) ;
+
+ if $($(feature).subfeatures)
+ {
+ values = [ regex.split $(value-string) - ] ;
+ }
+
+ if ! ( $(values[1]) in $($(feature).values) )
+ {
+ error \"$(values[1])\" is not a known value of feature $(feature)
+ : legal values: \"$($(feature).values)\" ;
+ }
+
+ for local v in $(values[2-])
+ {
+ # this will validate any subfeature values in value-string
+ implied-subfeature $(feature) $(v) : $(values[1]) ;
+ }
+ }
+}
+
+# Extends the given subfeature with the subvalues. If the optional
+# value-string is provided, the subvalues are only valid for the given
+# value of the feature. Thus, you could say that
+# <target-platform>mingw is specifc to <toolset>gcc-2.95.2 as follows:
+#
+# extend-subfeature toolset gcc-2.95.2 : target-platform : mingw ;
+#
+rule extend-subfeature (
+ feature # The feature whose subfeature is being extended
+
+ value-string ? # If supplied, specifies a specific value of the
+ # main feature for which the new subfeature values
+ # are valid
+
+ : subfeature # The name of the subfeature
+ : subvalues * # The additional values of the subfeature being defined.
+)
+{
+ feature = [ grist $(feature) ] ;
+ validate-feature $(feature) ;
+ if $(value-string)
+ {
+ validate-value-string $(feature) $(value-string) ;
+ }
+
+ local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ;
+
+ local f = [ utility.ungrist $(feature) ] ;
+ extend $(f)-$(subfeature-name) : $(subvalues) ;
+
+ # provide a way to get from the given feature or property and
+ # subfeature value to the subfeature name.
+ $(feature)$(value-string:E="")<>$(subvalues).subfeature = $(subfeature-name) ;
+}
+
+# Can be called three ways:
+#
+# 1. extend feature : values *
+# 2. extend <feature> subfeature : values *
+# 3. extend <feature>value-string subfeature : values *
+#
+# * Form 1 adds the given values to the given feature
+# * Forms 2 and 3 add subfeature values to the given feature
+# * Form 3 adds the subfeature values as specific to the given
+# property value-string.
+#
+rule extend ( feature-or-property subfeature ? : values * )
+{
+ local
+ feature # If a property was specified this is its feature
+ value-string # E.G., the gcc-2.95-2 part of <toolset>gcc-2.95.2
+ ;
+
+ # if a property was specified
+ if $(feature-or-property:G) && $(feature-or-property:G=)
+ {
+ # Extract the feature and value-string, if any.
+ feature = $(feature-or-property:G) ;
+ value-string = $(feature-or-property:G=) ;
+ }
+ else
+ {
+ feature = [ grist $(feature-or-property) ] ;
+ }
+
+ # Dispatch to the appropriate handler
+ if $(subfeature)
+ {
+ extend-subfeature $(feature) $(value-string)
+ : $(subfeature) : $(values) ;
+ }
+ else
+ {
+ # If no subfeature was specified, we didn't expect to see a
+ # value-string
+ if $(value-string)
+ {
+ error can only be specify a property as the first argument
+ when extending a subfeature
+ : usage:
+ : " extend" feature ":" values...
+ : " | extend" <feature>value-string subfeature ":" values...
+ ;
+ }
+
+ extend-feature $(feature) : $(values) ;
+ }
+}
+
+local rule get-subfeature-name ( subfeature value-string ? )
+{
+ local prefix = $(value-string): ;
+ return $(prefix:E="")$(subfeature) ;
+}
+
+# Declares a subfeature
+rule subfeature (
+ feature # Root feature that is not a subfeature
+ value-string ? # A value-string specifying which feature or
+ # subfeature values this subfeature is specific to,
+ # if any
+
+ : subfeature # The name of the subfeature being declared
+ : subvalues * # The allowed values of this subfeature
+ : attributes * # The attributes of the subfeature
+)
+{
+ feature = [ grist $(feature) ] ;
+ validate-feature $(feature) ;
+
+ # Add grist to the subfeature name if a value-string was supplied
+ local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ;
+
+ if $(subfeature-name) in $($(feature).subfeatures)
+ {
+ error \"$(subfeature)\" already declared as a subfeature of \"$(feature)\"
+ "specific to "$(value-string) ;
+ }
+ $(feature).subfeatures += $(subfeature-name) ;
+
+ # First declare the subfeature as a feature in its own right
+ local f = [ utility.ungrist $(feature) ] ;
+ feature $(f)-$(subfeature-name) : $(subvalues) : $(attributes) subfeature ;
+
+ # Now make sure the subfeature values are known.
+ extend-subfeature $(feature) $(value-string) : $(subfeature) : $(subvalues) ;
+}
+
+# Set the components of the given composite property
+rule compose ( composite-property : component-properties * )
+{
+ local feature = $(composite-property:G) ;
+ if ! ( composite in [ attributes $(feature) ] )
+ {
+ error "$(feature)" is not a composite feature ;
+ }
+
+ $(composite-property).components ?= ;
+ if $($(composite-property).components)
+ {
+ error components of "$(composite-property)" already set:
+ $($(composite-property).components) ;
+ }
+
+ if $(composite-property) in $(components)
+ {
+ errror composite property "$(composite-property)" cannot have itself as a component ;
+ }
+ $(composite-property).components = $(component-properties) ;
+}
+
+local rule has-attribute ( attribute property )
+{
+ if $(attribute) in [ attributes [ get-feature $(property) ] ]
+ {
+ return true ;
+ }
+}
+
+local rule expand-composite ( property )
+{
+ return $(property)
+ [ sequence.transform expand-composite : $($(property).components) ] ;
+}
+
+# return all values of the given feature specified by the given property set.
+rule get-values ( feature : properties * )
+{
+ local result ;
+ for local p in $(properties)
+ {
+ if $(p:G) = $(feature)
+ {
+ result += $(p:G=) ;
+ }
+ }
+ return $(result) ;
+}
+
+rule free-features ( )
+{
+ return $(free.features) ;
+}
+
+# Expand all composite properties in the set so that all components
+# are explicitly expressed.
+rule expand-composites ( properties * )
+{
+ local explicit-features = $(properties:G) ;
+
+ local result ;
+ # now expand composite features
+ for local p in $(properties)
+ {
+ local expanded = [ expand-composite $(p) ] ;
+
+ for local x in $(expanded)
+ {
+ if ! $(x) in $(result)
+ {
+ local f = $(x:G) ;
+
+ if $(f) in $(free.features)
+ {
+ result += $(x) ;
+ }
+ else if ! $(x) in $(properties) # x is the result of expansion
+ {
+ if ! $(f) in $(explicit-features) # not explicitly-specified
+ {
+ if $(f) in $(result:G)
+ {
+ error expansions of composite features result in conflicting
+ values for $(f)
+ : values: [ get-values $(f) : $(result) ] $(x:G=)
+ : one contributing composite property was $(p) ;
+ }
+ else
+ {
+ result += $(x) ;
+ }
+ }
+ }
+ else if $(f) in $(result:G)
+ {
+ error explicitly-specified values of non-free feature
+ $(f) conflict :
+ "existing values:" [ get-values $(f) : $(properties) ] :
+ "value from expanding " $(p) ":" (x:G=) ;
+ }
+ else
+ {
+ result += $(x) ;
+ }
+ }
+ }
+ }
+ return $(result) ;
+}
+
+# Return true iff f is an ordinary subfeature of the parent-property's
+# feature, or if f is a subfeature fo the parent-property's feature
+# specific to the parent-property's value
+local rule is-subfeature-of ( parent-property f )
+{
+ if subfeature in $($(f).attributes)
+ {
+ local specific-subfeature = [ MATCH <(.*):(.*)> : $(f) ] ;
+ if $(specific-subfeature)
+ {
+ # The feature has the form
+ # <topfeature-topvalue:subfeature>,
+ # e.g. <toolset-msvc:version>
+ local feature-value = [ split-top-feature $(specific-subfeature[1]) ] ;
+ if <$(feature-value[1])>$(feature-value[2]) = $(parent-property)
+ {
+ return true ;
+ }
+ }
+ else
+ {
+ # The feature has the form <topfeature-subfeature>,
+ # e.g. <toolset-version>
+ local top-sub = [ split-top-feature [ utility.ungrist $(f) ] ] ;
+
+ if $(top-sub[2]) && <$(top-sub[1])> = $(parent-property:G)
+ {
+ return true ;
+ }
+ }
+ }
+}
+
+# as above, for subproperties
+local rule is-subproperty-of ( parent-property p )
+{
+ return [ is-subfeature-of $(parent-property) $(p:G) ] ;
+}
+
+# Given a property, return the subset of features consisting of all
+# ordinary subfeatures of the property's feature, and all specific
+# subfeatures of the property's feature which are conditional on the
+# property's value.
+local rule select-subfeatures ( parent-property : features * )
+{
+ return [ sequence.filter is-subfeature-of $(parent-property) : $(features) ] ;
+}
+
+# as above, for subproperties
+local rule select-subproperties ( parent-property : properties * )
+{
+ return [ sequence.filter is-subproperty-of $(parent-property) : $(properties) ] ;
+}
+
+# Given a property set which may consist of composite and implicit
+# properties and combined subfeature values, returns an expanded,
+# normalized property set with all implicit features expressed
+# explicitly, all subfeature values individually expressed, and all
+# components of composite properties expanded. Non-free features
+# directly expressed in the input properties cause any values of
+# those features due to composite feature expansion to be dropped. If
+# two values of a given non-free feature are directly expressed in the
+# input, an error is issued.
+rule expand ( properties * )
+{
+ local expanded = [ expand-subfeatures $(properties) ] ;
+
+ return [ expand-composites $(expanded) ] ;
+}
+
+
+# Helper rule for minimize, below - return true iff property's feature
+# is present in the contents of the variable named by feature-set-var.
+local rule in-features ( feature-set-var property )
+{
+ if $(property:G) in $($(feature-set-var))
+ {
+ return true ;
+ }
+}
+
+# Helper for minimize, below - returns the list with
+# the same properties, but where all subfeatures
+# are in the end of the list
+local rule move-subfeatures-to-the-end ( properties * )
+{
+ local x1 ;
+ local x2 ;
+ for local p in $(properties)
+ {
+ if subfeature in $($(p:G).attributes)
+ {
+ x2 += $(p) ;
+ }
+ else
+ {
+ x1 += $(p) ;
+ }
+ }
+ return $(x1) $(x2) ;
+}
+
+
+# Given an expanded property set, eliminate all redundancy: properties
+# which are elements of other (composite) properties in the set will
+# be eliminated. Non-symmetric properties equal to default values will be
+# eliminated, unless the override a value from some composite property.
+# Implicit properties will be expressed without feature
+# grist, and sub-property values will be expressed as elements joined
+# to the corresponding main property.
+rule minimize ( properties * )
+{
+ # Precondition checking
+ local implicits = [ set.intersection $(p:G=) : $(p:G) ] ;
+ if $(implicits)
+ {
+ error minimize requires an expanded property set, but \"$(implicits[1])\"
+ appears to be the value of an un-expanded implicit feature ;
+ }
+
+ # remove properties implied by composite features
+ local components = $($(properties).components) ;
+ local x = [ set.difference $(properties) : $(components) ] ;
+
+ # handle subfeatures and implicit features
+ x = [ move-subfeatures-to-the-end $(x) ] ;
+ local result ;
+ while $(x)
+ {
+ local p fullp = $(x[1]) ;
+ local f = $(p:G) ;
+ local v = $(p:G=) ;
+
+ # eliminate features in implicit properties.
+ if implicit in [ attributes $(f) ]
+ {
+ p = $(v) ;
+ }
+
+ # locate all subproperties of $(x[1]) in the property set
+ local subproperties = [ select-subproperties $(fullp) : $(x) ] ;
+ if $(subproperties)
+ {
+ # reconstitute the joined property name
+ local sorted = [ sequence.insertion-sort $(subproperties) ] ;
+ result += $(p)-$(sorted:G="":J=-) ;
+
+ x = [ set.difference $(x[2-]) : $(subproperties) ] ;
+ }
+ else
+ {
+ # eliminate properties whose value is equal to feature's
+ # default and which are not symmetric and which do not
+ # contradict values implied by composite properties.
+
+ # since all component properties of composites in the set
+ # have been eliminated, any remaining property whose
+ # feature is the same as a component of a composite in the
+ # set must have a non-redundant value.
+ if $(fullp) != [ defaults $(f) ]
+ || symmetric in [ attributes $(f) ]
+ || $(fullp:G) in $(components:G)
+ {
+ result += $(p) ;
+ }
+
+ x = $(x[2-]) ;
+ }
+ }
+ return $(result) ;
+}
+
+# Combine all subproperties into their parent properties
+#
+# Requires: for every subproperty, there is a parent property. All
+# features are explicitly expressed.
+#
+# This rule probably shouldn't be needed, but
+# build-request.expand-no-defaults is being abused for unintended
+# purposes and it needs help
+rule compress-subproperties ( properties * )
+{
+ local all-subs matched-subs result ;
+
+ for local p in $(properties)
+ {
+ if ! $(p:G)
+ {
+ assert.nonempty-variable p:G ; # expecting fully-gristed properties
+ }
+
+
+ if ! subfeature in $($(p:G).attributes)
+ {
+ local subs = [
+ sequence.insertion-sort
+ [ sequence.filter is-subproperty-of $(p) : $(properties) ]
+ ] ;
+
+ matched-subs += $(subs) ;
+
+ local subvalues = -$(subs:G=:J=-) ;
+ subvalues ?= "" ;
+ result += $(p)$(subvalues) ;
+ }
+ else
+ {
+ all-subs += $(p) ;
+ }
+ }
+ assert.result true : set.equal $(all-subs) : $(matched-subs) ;
+ return $(result) ;
+}
+
+# given an ungristed string, finds the longest prefix which is a
+# top-level feature name followed by a dash, and return a pair
+# consisting of the parts before and after that dash. More
+# interesting than a simple split because feature names can contain
+# dashes.
+local rule split-top-feature ( feature-plus )
+{
+ local e = [ regex.split $(feature-plus) - ] ;
+ local f = $(e[1]) ;
+
+ local v ;
+ while $(e)
+ {
+ if <$(f)> in $(.all-top-features)
+ {
+ v = $(f) $(e[2-]:J=-) ;
+ }
+ e = $(e[2-]) ;
+ f = $(f)-$(e[1]) ;
+ }
+ return $(v) ;
+}
+
+# Given a set of properties, add default values for features not
+# represented in the set.
+# Note: if there's there's ordinary feature F1 and composite feature
+# F2, which includes some value for F1, and both feature have default values,
+# then the default value of F1 will be added, not the value in F2. This might
+# not be right idea: consider
+#
+# feature variant : debug ... ;
+# <variant>debug : .... <runtime-debugging>on
+# feature <runtime-debugging> : off on ;
+#
+# Here, when adding default for an empty property set, we'll get
+#
+# <variant>debug <runtime_debugging>off
+#
+# and that's kind of strange.
+rule add-defaults ( properties * )
+{
+ for local v in $(properties:G=)
+ {
+ if $(v) in $(properties)
+ {
+ error add-defaults requires explicitly specified features,
+ but \"$(v)\" appears to be the value of an un-expanded implicit feature ;
+ }
+ }
+ # We don't add default for elements with ":" inside. This catches:
+ # 1. Conditional properties --- we don't want <variant>debug:<define>DEBUG
+ # to be takes as specified value for <variant>
+ # 2. Free properties with ":" in values. We don't care, since free properties
+ # don't have defaults.
+ local xproperties = [ MATCH "^([^:]+)$" : $(properties) ] ;
+ local missing-top = [ set.difference $(.all-top-features) : $(xproperties:G) ] ;
+ local more = [ defaults $(missing-top) ] ;
+ properties += $(more) ;
+ xproperties += $(more) ;
+
+ # Add defaults for subfeatures of features which are present
+ for local p in $(xproperties)
+ {
+ local s = $($(p:G).subfeatures) ;
+ local f = [ utility.ungrist $(p:G) ] ;
+ local missing-subs = [ set.difference <$(f)-$(s)> : $(properties:G) ] ;
+ properties += [ defaults [ select-subfeatures $(p) : $(missing-subs) ] ] ;
+ }
+
+ return $(properties) ;
+}
+
+# Given a property-set of the form
+# v1/v2/...vN-1/<fN>vN/<fN+1>vN+1/...<fM>vM
+#
+# Returns
+# v1 v2 ... vN-1 <fN>vN <fN+1>vN+1 ... <fM>vM
+#
+# Note that vN...vM may contain slashes. This is resilient to the
+# substitution of backslashes for slashes, since Jam, unbidden,
+# sometimes swaps slash direction on NT.
+rule split ( property-set )
+{
+ local pieces = [ regex.split $(property-set) [\\/] ] ;
+ local result ;
+
+ for local x in $(pieces)
+ {
+ if ( ! $(x:G) ) && $(result[-1]:G)
+ {
+ result = $(result[1--2]) $(result[-1])/$(x) ;
+ }
+ else
+ {
+ result += $(x) ;
+ }
+ }
+
+ return $(result) ;
+}
+
+# tests of module feature
+local rule __test__ ( )
+{
+ # use a fresh copy of the feature module
+ prepare-test feature-test-temp ;
+
+ # These are local rules and so must be explicitly reimported into
+ # the testing module
+ import feature : extend-feature validate-feature select-subfeatures ;
+
+ import errors : try catch ;
+ import assert ;
+
+ feature toolset : gcc : implicit ;
+ feature define : : free ;
+ feature runtime-link : dynamic static : symmetric ;
+ feature optimization : on off ;
+ feature variant : debug release : implicit composite symmetric ;
+ feature stdlib : native stlport ;
+ feature magic : : free ;
+
+ compose <variant>debug : <define>_DEBUG <optimization>off ;
+ compose <variant>release : <define>NDEBUG <optimization>on ;
+
+ extend-feature toolset : msvc metrowerks ;
+ subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4
+ 3.0 3.0.1 3.0.2 ;
+
+ subfeature toolset gcc : platform : linux cygwin : optional ;
+
+ assert.result <toolset-gcc:version>
+ : select-subfeatures <toolset>gcc
+ : <toolset-gcc:version>
+ <toolset-msvc:version>
+ <toolset-version>
+ <stdlib>
+ ;
+
+ subfeature stdlib : version : 3 4 : optional ;
+
+ assert.result <stdlib-version>
+ : select-subfeatures <stdlib>native
+ : <toolset-gcc:version>
+ <toolset-msvc:version>
+ <toolset-version>
+ <stdlib-version>
+ ;
+
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1
+ : expand-subfeatures <toolset>gcc-3.0.1 ;
+
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1 <toolset-gcc:platform>linux
+ : expand-subfeatures <toolset>gcc-3.0.1-linux ;
+
+
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1
+ : expand <toolset>gcc <toolset-gcc:version>3.0.1 ;
+
+ assert.result <define>foo=x-y
+ : expand-subfeatures <define>foo=x-y ;
+
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1
+ : expand-subfeatures gcc-3.0.1 ;
+
+ assert.result a c e
+ : get-values <x> : <x>a <y>b <x>c <y>d <x>e ;
+
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1
+ <variant>debug <define>_DEBUG <optimization>on
+ : expand gcc-3.0.1 debug <optimization>on
+ ;
+
+ assert.result <variant>debug <define>_DEBUG <optimization>on
+ : expand debug <optimization>on
+ ;
+
+ assert.result <optimization>on <variant>debug <define>_DEBUG
+ : expand <optimization>on debug
+ ;
+
+ assert.result <runtime-link>dynamic <optimization>on
+ : defaults <runtime-link> <define> <optimization>
+ ;
+
+ feature dummy : dummy1 dummy2 ;
+ subfeature dummy : subdummy : x y z : optional ;
+
+ feature fu : fu1 fu2 : optional ;
+ subfeature fu : subfu : x y z : optional ;
+ subfeature fu : subfu2 : q r s ;
+
+ assert.result <runtime-link>static <define>foobar <optimization>on <toolset>gcc:<define>FOO
+ <toolset>gcc <variant>debug <stdlib>native <dummy>dummy1 <toolset-gcc:version>2.95.2
+
+ : add-defaults <runtime-link>static <define>foobar
+ <optimization>on <toolset>gcc:<define>FOO
+ ;
+
+ assert.result <runtime-link>static <define>foobar <optimization>on <toolset>gcc:<define>FOO
+ <fu>fu1 <toolset>gcc <variant>debug <stdlib>native <dummy>dummy1 <fu-subfu2>q
+ <toolset-gcc:version>2.95.2
+
+ : add-defaults <runtime-link>static <define>foobar
+ <optimization>on <toolset>gcc:<define>FOO <fu>fu1
+ ;
+
+ set-default <runtime-link> : static ;
+ assert.result <runtime-link>static
+ : defaults <runtime-link>
+ ;
+
+ assert.result gcc-3.0.1 debug <optimization>on
+ : minimize [ expand gcc-3.0.1 debug <optimization>on <stdlib>native ]
+ ;
+
+ assert.result gcc-3.0.1 debug <runtime-link>dynamic
+ : minimize [ expand gcc-3.0.1 debug <optimization>off <runtime-link>dynamic ]
+ ;
+
+ assert.result gcc-3.0.1 debug
+ : minimize [ expand gcc-3.0.1 debug <optimization>off ]
+ ;
+
+ assert.result debug <optimization>on
+ : minimize [ expand debug <optimization>on ]
+ ;
+
+ assert.result gcc-3.0
+ : minimize <toolset>gcc <toolset-gcc:version>3.0
+ ;
+
+ assert.result gcc-3.0
+ : minimize <toolset-gcc:version>3.0 <toolset>gcc
+ ;
+
+ assert.result <x>y/z <a>b/c <d>e/f
+ : split <x>y/z/<a>b/c/<d>e/f
+ ;
+
+ assert.result <x>y/z <a>b/c <d>e/f
+ : split <x>y\\z\\<a>b\\c\\<d>e\\f
+ ;
+
+ assert.result a b c <d>e/f/g <h>i/j/k
+ : split a/b/c/<d>e/f/g/<h>i/j/k
+ ;
+
+ assert.result a b c <d>e/f/g <h>i/j/k
+ : split a\\b\\c\\<d>e\\f\\g\\<h>i\\j\\k
+ ;
+
+ # test error checking
+
+ try ;
+ {
+ expand release <optimization>off <optimization>on ;
+ }
+ catch explicitly-specified values of non-free feature <optimization> conflict ;
+
+ try ;
+ {
+ validate-feature <foobar> ;
+ }
+ catch unknown feature ;
+
+ validate-value-string <toolset> gcc ;
+ validate-value-string <toolset> gcc-3.0.1 ;
+
+ try ;
+ {
+ validate-value-string <toolset> digital_mars ;
+ }
+ catch \"digital_mars\" is not a known value of <toolset> ;
+
+ try ;
+ {
+ feature foobar : : baz ;
+ }
+ catch unknown attributes: baz ;
+
+ feature feature1 ;
+ try ;
+ {
+ feature feature1 ;
+ }
+ catch feature already defined: ;
+
+ try ;
+ {
+ feature feature2 : : free implicit ;
+ }
+ catch free features cannot also be implicit ;
+
+ try ;
+ {
+ feature feature3 : : free propagated ;
+ }
+ catch free features cannot be propagated ;
+
+ try ;
+ {
+ implied-feature lackluster ;
+ }
+ catch \"lackluster\" is not a value of an implicit feature ;
+
+ try ;
+ {
+ implied-subfeature <toolset> 3.0.1 ;
+ }
+ catch \"3.0.1\" is not a known subfeature value of
+ <toolset> ;
+
+ try ;
+ {
+ implied-subfeature <toolset> not-a-version : gcc ;
+ }
+ catch \"not-a-version\" is not a known subfeature value of
+ <toolset>gcc ;
+
+ # leave a clean copy of the features module behind
+ finish-test feature-test-temp ;
+}
Added: boost-jam/boost-build/branches/upstream/current/build/generators.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/generators.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/generators.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1102 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+# Manages 'generators' --- objects which can do transformation between different
+# target types and contain algorithm for finding transformation from sources
+# to targets.
+#
+# The main entry point to this module is generators.construct rule. It is given
+# a list of source targets, desired target type and a set of properties.
+# It starts by selecting 'viable generators', which have any chances of producing
+# the desired target type with the required properties. Generators are ranked and
+# a set of most specific ones is selected.
+#
+# The most specific generators have their 'run' methods called, with the properties
+# and list of sources. Each one selects target which can be directly consumed, and
+# tries to convert the remaining ones to the types it can consume. This is done
+# by recursively calling 'construct' with all consumable types.
+#
+# If the generator has collected all the targets it needs, it creates targets
+# corresponding to result, and returns it. When all generators have been run,
+# results of one of them are selected and returned as result.
+#
+# It's quite possible that 'construct' returns more targets that it was asked for.
+# For example, it was asked to target type EXE, but the only found generators produces
+# both EXE and TDS (file with debug) information. The extra target will be returned.
+#
+# Likewise, when generator tries to convert sources to consumable types, it can get
+# more targets that it was asked for. The question is what to do with extra targets.
+# Boost.Build attempts to convert them to requested types, and attempts as early as
+# possible. Specifically, this is done after invoking each generator. (Later I'll
+# document the rationale for trying extra target conversion at that point).
+#
+# That early conversion is not always desirable. Suppose a generator got a source of
+# type Y and must consume one target of type X_1 and one target of type X_2.
+# When converting Y to X_1 extra target of type Y_2 is created. We should not try to
+# convert it to type X_1, because if we do so, the generator will get two targets
+# of type X_1, and will be at loss as to which one to use. Because of that, the
+# 'construct' rule has a parameter, telling if multiple targets can be returned. If
+# the parameter is false, conversion of extra targets is not performed.
+
+import "class" : is-a new ;
+import container ;
+import utility : str equal ;
+import set sequence ;
+import assert ;
+import virtual-target ;
+
+if "--debug-generators" in [ modules.peek : ARGV ]
+{
+ .debug = true ;
+}
+
+# Outputs a debug message if generators debugging is on.
+# Each element of 'message' is checked to see if it's class instance.
+# If so, instead of the value, the result of 'str' call is output.
+local rule generators.dout ( message * )
+{
+ if $(.debug)
+ {
+ ECHO [ sequence.transform utility.str : $(message) ] ;
+ }
+}
+
+
+local rule indent ( )
+{
+ return $(.indent:J="") ;
+}
+
+local rule increase-indent ( )
+{
+ .indent += " " ;
+}
+
+local rule decrease-indent ( )
+{
+ .indent = $(.indent[2-]) ;
+}
+
+# Takes a vector of 'virtual-target' instances and makes a normalized
+# representation, which is the same for given set of targets,
+# regardless of their order.
+rule normalize-target-list ( targets )
+{
+ $(targets).sort ;
+}
+
+# Creates a generator
+class generator
+{
+ import generators ;
+ import assert ;
+ import generators : indent increase-indent decrease-indent generators.dout ;
+ import set ;
+ import utility : equal ;
+ import feature ;
+ import errors : error ;
+ import sequence ;
+ import type ;
+ import virtual-target ;
+ import "class" : new ;
+ import property ;
+
+ EXPORT class at generator : indent increase-indent decrease-indent generators.dout ;
+
+ rule __init__ (
+ id # identifies the generator - should be name of the rule which
+ # sets up build actions
+ composing ? # whether generator processes each source target in
+ # turn, converting it to required types.
+ # Ordinary generators pass all sources together to
+ # recusrive generators.construct-types call.
+
+ : source-types * # types that this generator can handle
+
+ : target-types-and-names +
+ # types the generator will create and, optionally, names for
+ # created targets. Each element should have the form
+ # type["(" name-pattern ")"]
+ # for example, obj(%_x). Name of generated target will be found
+ # by replacing % with the name of source, provided explicit name
+ # was not specified.
+
+ : requirements *
+ )
+ {
+ self.id = $(id) ;
+ self.composing = $(composing) ;
+ self.source-types = $(source-types) ;
+ self.target-types-and-names = $(target-types-and-names) ;
+ self.requirements = $(requirements) ;
+
+ for local e in $(target-types-and-names)
+ {
+ # Create three parallel lists: one with the list of target types,
+ # and two other with prefixes and postfixes to be added to target
+ # name. We use parallel lists for prefix and postfix (as opposed
+ # to mapping), because given target type might occur several times,
+ # for example "H H(%_symbols)".
+ local m = [ MATCH ([^\\(]*)(\\((.*)%(.*)\\))? : $(e) ] ;
+ self.target-types += $(m[1]) ;
+ self.name-prefix += $(m[3]:E="") ;
+ self.name-postfix += $(m[4]:E="") ;
+ }
+
+ # Note that 'transform' here, is the same as 'for_each'.
+ sequence.transform type.validate : $(self.source-types) ;
+ if $(self.target-types) != *
+ {
+ sequence.transform type.validate : $(self.target-types) ;
+ }
+ }
+
+ ############## End of constructor #################
+
+ rule id ( )
+ {
+ return $(self.id) ;
+ }
+
+ # Returns the list of target type the generator accepts.
+ rule source-types ( )
+ {
+ return $(self.source-types) ;
+ }
+
+ # Returns the list of target types that this generator produces.
+ # It is assumed to be always the same -- i.e. it cannot change depending
+ # list of sources.
+ rule target-types ( )
+ {
+ return $(self.target-types) ;
+ }
+
+ # Returns the required properties for this generator. Properties
+ # in returned set must be present in build properties if this
+ # generator is to be used. If result has grist-only element,
+ # that build properties must include some value of that feature.
+ # XXX: remove this method?
+ rule requirements ( )
+ {
+ return $(self.requirements) ;
+ }
+
+ # Returns a true value if the generator can be run with the specified
+ # properties.
+ rule match-rank ( property-set-to-match )
+ {
+ # See if generator's requirements are satisfied by
+ # 'properties'. Treat a feature name in requirements
+ # (i.e. grist-only element), as matching any value of the
+ # feature.
+ local all-requirements = [ requirements ] ;
+
+ local property-requirements feature-requirements ;
+ for local r in $(all-requirements)
+ {
+ if $(r:G=)
+ {
+ property-requirements += $(r) ;
+ }
+ else
+ {
+ feature-requirements += $(r) ;
+ }
+ }
+
+ local properties-to-match = [ $(property-set-to-match).raw ] ;
+ if $(property-requirements) in $(properties-to-match)
+ && $(feature-requirements) in $(properties-to-match:G)
+ {
+ return true ;
+ }
+ else
+ {
+ return ;
+ }
+ }
+
+ # Returns another generator which differers from $(self) in
+ # - id
+ # - value to <toolset> feature in properties
+ rule clone ( new-id : new-toolset-properties + )
+ {
+ return [ new $(__class__) $(new-id) $(self.composing)
+ : $(self.source-types)
+ : $(self.target-types-and-names)
+ # Note: this does not remove any subfeatures of <toolset>
+ # which might cause problems
+ : [ property.change $(self.requirements) : <toolset> ]
+ $(new-toolset-properties)
+ ] ;
+ }
+
+ # Tries to invoke this generator on the given sources. Returns a
+ # list of generated targets (instances of 'virtual-target').
+ rule run ( project # Project for which the targets are generated
+ name ? # Determines the name of 'name' attribute for
+ # all generated targets. See 'generated-targets' method.
+ : property-set # Desired properties for generated targets.
+ : sources + # Source targets.
+ : multiple ? # Allows the rule to run generator several times and return
+ # multiple targets of the same type. When this argument is not
+ # given, 'run' will return the list of targets, which is equal
+ # in size to the list of target types, and where type of
+ # each target is the same as the corresponding element of
+ # target type list. Non-empty value allows to return several
+ # such target lists, joined together.
+ )
+ {
+ # multiple = true ; # The tests seem to tolerate this; will
+ # remove the parameter altogether in the
+ # next revision to see what I learn -- DWA 2003/5/6
+
+ generators.dout [ indent ] " generator" $(self.id) ;
+ generators.dout [ indent ] " multiple:" $(mutliple) ;
+ generators.dout [ indent ] " composing:" $(self.composing) ;
+
+ if ! $(self.composing) && $(sources[2]) && $(self.source-types[2])
+ {
+ errors.error "Unsupported source/source-type combination" ;
+ }
+
+ if $(self.source-types[2])
+ {
+ multiple = ;
+ }
+
+ # We don't run composing generators if no name is specified. The reason
+ # is that composing generator combines several targets, which can have
+ # different names, and it cannot decide which name to give for produced
+ # target. Therefore, the name must be passed.
+ #
+ # This in effect, means that composing generators are runnable only
+ # at top-level of transofrmation graph, or if name is passed explicitly.
+ # Thus, we dissallow composing generators in the middle. For example, the
+ # transofrmation CPP -> OBJ -> STATIC_LIB -> RSP -> EXE won't be allowed
+ # (the OBJ -> STATIC_LIB generator is composing)
+ if ! $(self.composing) || $(name)
+ {
+ run-really $(project) $(name) : $(property-set) : $(sources) : $(multiple) ;
+ }
+ }
+
+
+ rule run-really ( project name ? : property-set : sources + : multiple ? )
+ {
+
+ # Targets that this generator will consume directly.
+ local consumed = ;
+ # Targets that can't be consumed and will be returned as-is.
+ local bypassed = ;
+
+ if $(self.composing)
+ {
+ convert-multiple-sources-to-consumable-types $(project)
+ : $(property-set) : $(sources) : consumed bypassed ;
+ }
+ else
+ {
+ convert-to-consumable-types $(project) $(name) :
+ $(property-set) : $(sources) : $(multiple)
+ :
+ : consumed bypassed ;
+ }
+
+ local result ;
+ if $(consumed)
+ {
+ result = [ construct-result $(consumed) : $(project) $(name)
+ : $(property-set) ] ;
+ result += $(bypassed) ;
+ }
+
+
+ if $(result)
+ {
+ generators.dout [ indent ] " SUCCESS: " $(result) ;
+ }
+ else
+ {
+ generators.dout [ indent ] " FAILURE" ;
+ }
+ generators.dout ;
+ return $(result) ;
+ }
+
+ # Constructs the dependency graph that will be returned by this
+ # generator
+ rule construct-result (
+ consumed + # Already prepared list of consumable targets
+ # If generator requires several source files will contain
+ # exactly len $(self.source-types) targets with matching types
+ # Otherwise, might contain several targets with the type of
+ # $(self.source-types[1])
+ : project name ?
+ : property-set # Properties to be used for all actions create here
+ )
+ {
+ local result ;
+ # If this is 1->1 transformation, apply it to all consumed targets in order.
+ if ! $(self.source-types[2]) && ! $(self.composing)
+ {
+ generators.dout [ indent ] "alt1" ;
+ for local r in $(consumed)
+ {
+ result += [ generated-targets $(r) : $(property-set) : $(project) $(name) ] ; #(targets) ;
+ }
+ }
+ else
+ {
+ generators.dout [ indent ] "alt2 : consumed is" $(consumed) ;
+ if $(consumed)
+ {
+ result += [ generated-targets $(consumed) : $(property-set)
+ : $(project) $(name) ] ;
+ }
+ }
+ return $(result) ;
+ }
+
+ # Constructs targets that are created after consuming 'sources'.
+ # The result will be the list of virtual-target, which the same length
+ # as 'target-types' attribute and with corresponding types.
+ #
+ # When 'name' is empty, all source targets must have the same value of
+ # the 'name' attribute, which will be used instead of the 'name' argument.
+ #
+ # The value of 'name' attribute for each generated target will be equal to
+ # the 'name' parameter if there's no name pattern for this type. Otherwise,
+ # the '%' symbol in the name pattern will be replaced with the 'name' parameter
+ # to obtain the 'name' attribute.
+ #
+ # For example, if targets types are T1 and T2(with name pattern "%_x"), suffixes
+ # for T1 and T2 are .t1 and t2, and source if foo.z, then created files would
+ # be "foo.t1" and "foo_x.t2". The 'name' attribute actually determined the
+ # basename of a file.
+ #
+ # Note that this pattern mechanism has nothing to do with implicit patterns
+ # in make. It's a way to produce target which name is different for name of
+ # source.
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ if ! $(name)
+ {
+ name = [ $(sources[1]).name ] ;
+
+ for local s in $(sources[2])
+ {
+ if [ $(s).name ] != $(name)
+ {
+ error "$(self.id): source targets have different names: cannot determine target name" ;
+ }
+ }
+
+ # Names of sources might include directory. We should strip it.
+ name = $(name:D=) ;
+ }
+
+ # Create generated target for each target type.
+ local targets ;
+ local pre = $(self.name-prefix) ;
+ local post = $(self.name-postfix) ;
+ for local t in $(self.target-types)
+ {
+ local generated-name = $(pre[1])$(name)$(post[1]) ;
+ pre = $(pre[2-]) ;
+ post = $(post[2-]) ;
+
+ targets += [ class.new file-target $(generated-name) : $(t) : $(project) ] ;
+ }
+ # Assign an action for each target
+ local action = [ action-class ] ;
+ local a = [ class.new $(action) $(targets) : $(sources) : $(self.id) :
+ $(property-set) ] ;
+ for local t in $(targets)
+ {
+ $(t).action $(a) ;
+ $(t).set-intermediate true ;
+ }
+
+ return [ sequence.transform virtual-target.register : $(targets) ] ;
+ }
+
+ # Attempts to convert 'source' to the types that this generator can
+ # handle. The intention is to produce the set of targets can should be
+ # used when generator is run.
+ rule convert-to-consumable-types ( project name ? :
+ property-set : sources + : multiple ?
+ : only-one ? # convert 'source' to only one of source types
+ # if there's more that one possibility, report an
+ # error
+ : consumed-var # name of variable which recieves all targets which
+ # can be consumed.
+ bypassed-var # name variable which recieves all targets which
+ # cannot be consumed
+ )
+ {
+ # We're likely to be passed 'consumed' and 'bypassed'
+ # var names. Use "_" to avoid name conflicts.
+ local _consumed ;
+ local _bypassed ;
+ local missing-types ;
+
+ if $(sources[2])
+ {
+ # Don't know how to handle several sources yet. Just try
+ # to pass the request to other generator
+ missing-types = $(self.source-types) ;
+ }
+ else
+ {
+ consume-directly $(sources) : _consumed : missing-types ;
+ }
+
+ # No need to search for transformation if
+ # some source type has consumed source and
+ # no more source types are needed.
+ if $(only-one) && $(_consumed)
+ {
+ missing-types = ;
+ }
+
+ #TODO: we should check that only one source type
+ #if create of 'only-one' is true.
+ # TODO: consider if consuned/bypassed separation should
+ # be done by 'construct-types'.
+
+ if $(missing-types)
+ {
+ local transformed = [ generators.construct-types $(project) $(name)
+ : $(missing-types) : $(multiple) : $(property-set) : $(sources) ] ;
+
+ # Add targets of right type to 'consumed'. Add others to
+ # 'bypassed'. The 'generators.construct' rule has done
+ # its best to convert everything to the required type.
+ # There's no need to rerun it on targets of different types.
+
+ for local t in $(transformed)
+ {
+ if [ $(t).type ] in $(missing-types)
+ {
+ _consumed += $(t) ;
+ }
+ else
+ {
+ _bypassed += $(t) ;
+ }
+ }
+ }
+
+ _consumed = [ sequence.unique $(_consumed) ] ;
+ _bypassed = [ sequence.unique $(_bypassed) ] ;
+
+ # remove elements of '_bypassed' that are in '_consumed'
+
+ # Suppose the target type of current generator, X is produced from
+ # X_1 and X_2, which are produced from Y by one generator.
+ # When creating X_1 from Y, X_2 will be added to 'bypassed'
+ # Likewise, when creating X_2 from Y, X_1 will be added to 'bypassed'
+ # But they are also in 'consumed'. We have to remove them from
+ # bypassed, so that generators up the call stack don't try to convert
+ # them.
+
+ # In this particular case, X_1 instance in 'consumed' and X_1 instance
+ # in 'bypassed' will be the same: because they have the same source and
+ # action name, and 'virtual-target.register' won't allow two different
+ # instances. Therefore, it's OK to use 'set.difference'.
+
+ _bypassed = [ set.difference $(_bypassed) : $(_consumed) ] ;
+
+
+ $(consumed-var) += $(_consumed) ;
+ $(bypassed-var) += $(_bypassed) ;
+ }
+
+ # Converts several files to consumable types.
+ rule convert-multiple-sources-to-consumable-types
+ ( project : property-set : sources * : consumed-var bypassed-var : multiple ? )
+ {
+ multiple ?= * ;
+ # We process each source one-by-one, trying to convert it to
+ # a usable type.
+ local failed ;
+ while $(sources) && ! $(failed)
+ {
+ local _c ;
+ local _b ;
+ # TODO: need to check for failure on each source.
+ convert-to-consumable-types $(project) : $(property-set)
+ : $(sources[1]) : $(multiple) : true : _c _b ;
+ if ! $(_c)
+ {
+ generators.dout [ indent ] " failed to convert " [ $(sources[1]).str ] ;
+ # failed = true ;
+ }
+ $(consumed-var) += $(_c) ;
+ $(bypassed-var) += $(_b) ;
+ sources = $(sources[2-]) ;
+ }
+ if $(failed)
+ {
+ $(consumed-var) = ;
+ $(bypassed-var) = ;
+ }
+ }
+
+ rule consume-directly ( source : consumed-var : missing-types-var )
+ {
+ local real-source-type = [ $(source).type ] ;
+
+ for local st in $(self.source-types)
+ {
+ # The 'source' if of right type already)
+ if $(real-source-type) = $(st) ||
+ [ type.is-derived $(real-source-type) $(st) ]
+ {
+ $(consumed-var) += $(source) ;
+ }
+ else
+ {
+ $(missing-types-var) += $(st) ;
+ }
+ }
+ }
+
+
+ # Returns the class to be used to actions. Default implementation
+ # returns "action".
+ rule action-class ( )
+ {
+ return "action" ;
+ }
+}
+
+import errors : error ;
+
+.generators = ;
+
+# Registers new generator instance 'g'.
+rule register ( g )
+{
+ .generators += $(g) ;
+
+ for local t in [ $(g).target-types ]
+ {
+ .generators.$(t) += $(g) ;
+ }
+
+ # Update the set of generators for toolset
+
+ # TODO: should we check that generator with this id
+ # is not already registered. For example, the fop.jam
+ # module intentionally declared two generators with the
+ # same id, so such check will break it.
+ local id = [ $(g).id ] ;
+
+ # Some generators have multiple periods in their name, so the
+ # normal $(id:S=) won't generate the right toolset name.
+ # e.g. if id = gcc.compile.c++, then
+ # .generators-for-toolset.$(id:S=) will append to
+ # .generators-for-toolset.gcc.compile, which is a separate
+ # value from .generators-for-toolset.gcc. Correcting this
+ # makes generator inheritance work properly.
+ # See also inherit-generators in module toolset
+ local base = $(id) ;
+ while $(base:S)
+ {
+ base = $(base:B) ;
+ }
+ .generators-for-toolset.$(base) += $(g) ;
+}
+
+# Creates new instance of the 'generator' class and registers it.
+# Retursn the creates instance.
+# Rationale: the instance is returned so that it's possible to first register
+# a generator and then call 'run' method on that generator, bypassing all
+# generator selection.
+rule register-standard ( id : source-types + : target-types + : requirements * )
+
+{
+ local g = [ new generator $(id) : $(source-types) : $(target-types)
+ : $(requirements) ] ;
+ register $(g) ;
+ return $(g) ;
+}
+
+# Creates new instance of the 'composing-generator' class and
+# registers it.
+rule register-composing ( id : source-types + : target-types + : requirements * )
+{
+ local g = [ new generator $(id) true : $(source-types)
+ : $(target-types) : $(requirements) ] ;
+ register $(g) ;
+ return $(g) ;
+}
+
+# Returns all generators which belong to 'toolset', i.e. which
+# ids are $(toolset).<something>
+rule generators-for-toolset ( toolset )
+{
+ return $(.generators-for-toolset.$(toolset)) ;
+}
+
+rule override ( overrider-id : overridee-id )
+{
+ .override.$(overrider-id) += $(overridee-id) ;
+}
+
+
+
+
+# Set if results of the current generators search are going to be cached
+# This means no futher attempts to cache generators search should be
+# made.
+.caching = ;
+
+# For all t in 'targets':
+# if [ $(t).type ] in $(target-types), add 't' to result
+# if [ $(t).type ] in base type for any of 'target-types', add 't' to result
+# otherwise, add 't' to extra.
+rule base-to-derived-type-conversion ( targets * : target-types +
+ : result-var extra-var )
+{
+ for local t in $(targets)
+ {
+ if [ $(t).type ] in $(target-types)
+ {
+ $(result-var) += $(t) ;
+ }
+ else
+ {
+ # We might have asked for a type 'D', but found only generator for
+ # a type 'B', where 'D' is derived from 'B'. In this case, the
+ # generation succeeds, but we should change type of the generated target.
+
+ local at = [ $(t).type ] ;
+ local found ;
+ for local tt in $(target-types)
+ {
+ if ! $(found) && [ type.is-derived $(tt) $(at) ]
+ {
+ $(t).set-type $(tt) ;
+ $(result-var) += $(t) ;
+ found = 1 ;
+ }
+ }
+ if ! $(found)
+ {
+ $(extra-var) += $(t) ;
+ }
+ }
+ }
+}
+
+
+
+local rule try-one-generator ( project name ? : generator multiple ? :
+ target-type : property-set : sources * )
+{
+ local targets =
+ [ $(generator).run $(project) $(name)
+ : $(property-set)
+ : $(sources)
+ : $(multiple)
+ ] ;
+
+ # Generated targets that are of required types
+ local result ;
+ # Generated target of other types.
+ local extra ;
+
+ base-to-derived-type-conversion $(targets) : $(target-type)
+ : result extra ;
+
+ # Now try to convert extra targets
+ # 'construct' will to its best to return only requested
+ # target types, so if we receive any extra from that call,
+ # we don't try to do anything about them.
+ local extra2 ;
+ if $(multiple)
+ {
+ for local e in $(extra)
+ {
+ local try2 = [ construct-types $(project) $(name)
+ : $(target-type)
+ :
+ : $(property-set)
+ : $(e) ] ;
+
+ result += $(try2) ;
+ }
+ }
+ else
+ {
+ extra2 = $(extra) ;
+ }
+ generators.dout [ indent ] " generator" [ $(generator).id ] " spawned " ;
+ generators.dout [ indent ] " " $(result) -- $(extra2) ;
+ return $(result) $(extra2) ;
+}
+
+rule construct-types ( project name ? : target-types + : multiple ? :
+ property-set : sources + )
+{
+ local result ;
+ local matched-types ;
+ for local t in $(target-types)
+ {
+ local r = [ construct $(project) $(name) : $(t) $(multiple) : $(property-set) :
+ $(sources) ] ;
+ if $(r)
+ {
+ result += $(r) ;
+ matched-types += $(t) ;
+ }
+ }
+ # TODO: have to introduce parameter controlling if
+ # several types can be matches and add appropriate
+ # checks
+
+ # TODO: need to review the documentation for
+ # 'construct' to see if it should return $(source) even
+ # if nothing can be done with it. Currents docs seem to
+ # imply that, contrary to the behaviour.
+ if $(result)
+ {
+ return $(result) ;
+ }
+ else
+ {
+ return $(sources) ;
+ }
+}
+
+# Ensures all 'targets' have types. If this is not so, exists with
+# error.
+local rule ensure-type ( targets * )
+{
+ for local t in $(targets)
+ {
+ if ! [ $(t).type ]
+ {
+ errors.error "target" [ $(t).str ] "has no type" ;
+ }
+ }
+}
+
+
+# Returns generators which can be used to construct target of specified type
+# with specified properties. Uses the following algorithm:
+# - iterates over requested target-type and all it's bases (in the order returned bt
+# type.all-bases.
+# - for each type find all generators that generate that type and which requirements
+# are satisfied by properties.
+# - if the set of generators is not empty, returns that set.
+#
+# Note: this algorithm explicitly ignores generators for base classes if there's
+# at least one generator for requested target-type.
+local rule find-viable-generators ( target-type : property-set )
+{
+ # Select generators that can create the required target type.
+ local viable-generators = ;
+ local generator-rank = ;
+
+ import type ;
+ # Try all-type generators first. Assume they have
+ # quite specific requirements.
+ local t = * [ type.all-bases $(target-type) ] ;
+
+ generators.dout [ indent ] find-viable-generators target-type= $(target-type)
+ property-set= [ $(property-set).as-path ]
+ ;
+
+ while $(t[1])
+ {
+ generators.dout [ indent ] "trying type" $(t[1]) ;
+ for local g in $(.generators.$(t[1]))
+ {
+ generators.dout [ indent ] "trying generator" [ $(g).id ] "(" [ $(g).source-types ] -> [ $(g).target-types ] ")" ;
+
+ # Avoid trying the same generator twice on different levels.
+ if ! $(g) in $(.active-generators)
+ {
+ local m = [ $(g).match-rank $(property-set) ] ;
+ if $(m)
+ {
+ generators.dout [ indent ] " is viable" ;
+ viable-generators += $(g) ;
+ t = ;
+ }
+ }
+ }
+ t = $(t[2-]) ;
+ }
+
+ # Generators which override 'all'.
+ local all-overrides ;
+ # Generators which are overriden
+ local overriden-ids ;
+ for local g in $(viable-generators)
+ {
+ local id = [ $(g).id ] ;
+ local this-overrides = $(.override.$(id)) ;
+ overriden-ids += $(this-overrides) ;
+ if all in $(this-overrides)
+ {
+ all-overrides += $(g) ;
+ }
+ }
+ if $(all-overrides)
+ {
+ viable-generators = $(all-overrides) ;
+ }
+ local result ;
+ for local g in $(viable-generators)
+ {
+ if ! [ $(g).id ] in $(overriden-ids)
+ {
+ result += $(g) ;
+ }
+ }
+
+ return $(result) ;
+}
+
+# Given a vector of vectors, of of them represents results of running some
+# generator, returns the 'best' result, it it exists. Otherwise, exit with
+# and error. Result is returned as plain jam list.
+local rule select-dependency-graph ( options )
+{
+ if [ $(options).size ] = 0
+ {
+ return ;
+ }
+ else if [ $(options).size ] = 1
+ {
+ return [ $(options).get-at 1 ] ;
+ }
+ else
+ {
+ # We have several alternatives and need to check if they
+ # are the same.
+
+ for local r in [ $(options).get ]
+ {
+ normalize-target-list $(r) ;
+ generators.dout $(r) ;
+ }
+
+ # One note why we can compare object names directly,
+ # without using deep copy. All the targets here are
+ # produced by some generators, and generators should
+ # pass the targets they've returned via 'virtual-target.register'.
+ # So, two elements can only be equivalent, if they are just
+ # the same object.
+ local f = [ $(options).at 1 ] ;
+ local mismatch ;
+ for local r in [ $(results).get ]
+ {
+ if [ $(r).get ] != [ $(f).get ]
+ {
+ mismatch = true ;
+ }
+ }
+
+ if ! $(mismatch)
+ {
+ return [ $(f).get ] ;
+ }
+ else
+ {
+ error [ $(options).size ] "possible generations for "
+ $(target-types) "Can't handle this now." ;
+ }
+ }
+}
+
+.construct-stack = ;
+
+# Attempt to construct the target by looking at transformation cache.
+local rule construct-with-caching (
+ project name ? : target-type multiple ? : property-set : sources * )
+{
+ local result ;
+ # Caching is only possible when we're not computing cacheable transformation
+ # already, when there's only one source which has no action -- i.e. source file,
+ # and name of target is not specified.
+ if ! $(.caching) && ! $(sources[2]) && $(sources[1]) && ! $(name)
+ && ! [ $(sources[1]).action ]
+ {
+ local .caching = true ;
+
+ local t = $(sources[1]) ;
+
+ local signature = [ sequence.join [ $(t).type ] $(target-type) $(property-set) : - ] ;
+
+ # Get a transformation template from cache or create it.
+ local cresult ;
+ if $(.transformation.cache.$(signature))
+ {
+ cresult = $(.transformation.cache.$(signature)) ;
+ }
+ else
+ {
+ local ut = [ new file-target % : [ $(t).type ] : "no project" ] ;
+ cresult = [ construct $(project) : $(target-type) $(multiple)
+ : $(property-set) : $(ut) ] ;
+ .transformation.cache.$(signature) = $(cresult) ;
+ }
+
+ # Substitute the real source name in the transformation template.
+ if $(cresult)
+ {
+ generators.dout [ indent ] "*** putting to cache?" ;
+ for local c in $(cresult)
+ {
+ generators.dout [ indent ] "*** cloning " $(c) ;
+ local cc = [ virtual-target.clone-template $(c) : $(t) : $(project) ] ;
+ generators.dout [ indent ] "*** cloned" $(cc) --- $(cc) ;
+ result += $(cc) ;
+ }
+ }
+ }
+ return $(result) ;
+}
+
+# Attempts to construct target by finding viable generators, running them
+# and selecting the dependency graph
+local rule construct-without-caching (
+ project name ? : target-type multiple ? : property-set : sources * )
+{
+ viable-generators = [ find-viable-generators $(target-type) : $(property-set) ] ;
+
+ local results = [ new vector ] ;
+
+ generators.dout [ indent ] "*** " [ sequence.length $(viable-generators) ]
+ " viable generators" ;
+
+ for local g in $(viable-generators)
+ {
+ # This variable will be restored on exit from this scope.
+ local .active-generators = $(g) $(.active-generators) ;
+
+ local r = [ try-one-generator $(project) $(name) : $(g) $(multiple) : $(target-type) :
+ $(property-set) : $(sources) ] ;
+
+ if $(r)
+ {
+ $(results).push-back [ new vector $(r) ] ;
+ }
+ }
+
+ return [ select-dependency-graph $(results) ] ;
+}
+
+
+# Attempts to create target of 'target-type' with 'properties'
+# from 'sources'. The 'sources' are treated as a collection of
+# *possible* ingridients -- i.e. it is not required to consume
+# them all. If 'multiple' is true, the rule is allowed to return
+# several targets of 'target-type'.
+#
+#
+# Returns a list of target. When this invocation is first instance of
+# 'construct' in stack, returns only targets of requested 'target-type',
+# otherwise, returns also unused sources and additionally generated
+# targets.
+#
+# Does not return target which are not of 'allowed-type' or of type derived from
+# it. If 'allowed-type' is not specified, it's defaulted to 'target-type'.
+# See lib-target-class for use case of this.
+rule construct ( project name ? : target-type multiple ? : property-set * : sources *
+ : allowed-type * )
+{
+ allowed-type ?= $(target-type) ;
+ if (.construct-stack)
+ {
+ ensure-type $(sources) ;
+ }
+
+ # Intermediate targets are not passed to generators
+ # and just returned unmodified.
+ local intermediate ;
+ if ! $(.construct-stack)
+ {
+ local sources2 ;
+ for local s in $(sources)
+ {
+ if ! [ $(s).intermediate ]
+ {
+ sources2 += $(s) ;
+ }
+ else
+ {
+ intermediate += $(s) ;
+ }
+ }
+ sources = $(sources2) ;
+ }
+
+ .construct-stack += 1 ;
+
+ increase-indent ;
+
+ local m ;
+ if $(multiple)
+ {
+ m = "(may return multiple targets)" ;
+ }
+ generators.dout [ indent ] "*** construct" $(target-type) $(m) ;
+
+ for local s in $(sources)
+ {
+ generators.dout [ indent ] " from" $(s) ;
+ }
+ generators.dout [ indent ] " properties:" [ $(property-set).raw ] ;
+
+ local result = [ construct-with-caching $(project) $(name)
+ : $(target-type) $(multiple) : $(property-set) : $(sources) ] ;
+
+ if ! $(result) {
+ result = [ construct-without-caching $(project) $(name)
+ : $(target-type) $(multiple) : $(property-set) : $(sources) ] ;
+ }
+
+ decrease-indent ;
+
+ .construct-stack = $(.construct-stack[2-]) ;
+
+ if ! $(.construct-stack)
+ {
+ result += $(intermediate) ;
+ }
+
+ # For all targets of 'allowed-type', reset the 'intermediate' attribute.
+ if ! $(.construct-stack) && $(allowed-type) != * # This is first invocation in stack
+ {
+ local result2 ;
+ for local t in $(result)
+ {
+ local type = [ $(t).type ] ;
+ assert.nonempty-variable type ;
+ assert.nonempty-variable target-type ;
+
+ # Return only targets of the requested type, unless 'return-all'
+ # is specified. If we don't do this, then all targets calling
+ # 'construct' will get unused target returned, which will break
+ # checking for unused sources a bit harder.
+ if $(type) = $(target-type) || [ type.is-derived $(type) $(allowed-type) ]
+ {
+ $(t).set-intermediate ;
+ }
+ }
+ }
+
+
+ return $(result) ;
+}
+
Added: boost-jam/boost-build/branches/upstream/current/build/modifiers.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/modifiers.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/modifiers.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,223 @@
+# (C) Copyright Rene Rivera, 2003.
+#
+# See accompanying license for terms and conditions of use.
+#
+
+# Modifiers are generalized generators that mutate targets in specific ways.
+# This structure allows for grouping a variety of functionality in an
+# orthogonal way to the functionality in toolsets, and without specifying
+# more target variations. In turn the modifiers can be used as building
+# blocks to implement simple requests, like the <version> feature.
+
+import modules ;
+import feature ;
+import errors ;
+import type ;
+import "class" : new ;
+import generators : generator ;
+import property ;
+import virtual-target ;
+import numbers ;
+import sequence ;
+import symlink ;
+import property-set ;
+
+# Base generator for creating targets that are modifications of existing
+# targets.
+#
+rule modifier (
+ id
+ composing ?
+ : source-types *
+ : target-types-and-names +
+ : requirements *
+ )
+{
+ generator.__init__ $(id) $(composing) : $(source-types) : $(target-types-and-names) : $(requirements) ;
+
+ self.targets-in-progress = ;
+
+ # Wraps the generation of the target to call before and after rules to
+ # affect the real target.
+ #
+ rule run ( project name ? : property-set : sources + : multiple ? )
+ {
+ local result ;
+ local current-target = $(project)^$(name) ;
+ if ! $(current-target) in $(self.targets-in-progress)
+ {
+ # Before modifications...
+ local project_ = [ modify-project-before
+ $(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
+ local name_ = [ modify-name-before
+ $(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
+ local property-set_ = [ modify-properties-before
+ $(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
+ local sources_ = [ modify-sources-before
+ $(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
+ local multiple_ = [ modify-multiple-before
+ $(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
+ project = $(project_) ;
+ name = $(name_) ;
+ property-set = $(property-set_) ;
+ sources = $(sources_) ;
+ multiple = $(multiple_) ;
+
+ # Generate the real target...
+ local target-type-p = [ property.select <main-target-type> : [ $(property-set).raw ] ] ;
+ self.targets-in-progress += $(current-target) ;
+ result =
+ [ generators.construct $(project) $(name) : $(target-type-p:G=) $(multiple) :
+ $(property-set) : $(sources) ] ;
+ self.targets-in-progress = $(self.targets-in-progress[1--2]) ;
+
+ # After modifications...
+ result = [ modify-target-after $(result) :
+ $(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
+ }
+ return $(result) ;
+ }
+
+ rule modify-project-before ( project name ? : property-set : sources + : multiple ? )
+ {
+ return $(project) ;
+ }
+
+ rule modify-name-before ( project name ? : property-set : sources + : multiple ? )
+ {
+ return $(name) ;
+ }
+
+ rule modify-properties-before ( project name ? : property-set : sources + : multiple ? )
+ {
+ return $(property-set) ;
+ }
+
+ rule modify-sources-before ( project name ? : property-set : sources + : multiple ? )
+ {
+ return $(sources) ;
+ }
+
+ rule modify-multiple-before ( project name ? : property-set : sources + : multiple ? )
+ {
+ return $(multiple) ;
+ }
+
+ rule modify-target-after ( target : project name ? : property-set : sources + : multiple ? )
+ {
+ return $(target) ;
+ }
+
+ # Utility, clones a file-target with optional changes to the name, type, and project
+ # of the target.
+ # NOTE: This functionality should be moved, and generalized, to virtual-targets.
+ #
+ rule clone-file-target ( target : new-name ? : new-type ? : new-project ? )
+ {
+ # Need a MUTCH better way to clone a target...
+ new-name ?= [ $(target).name ] ;
+ new-type ?= [ $(target).type ] ;
+ new-project ?= [ $(target).project ] ;
+ local result = [ new file-target $(new-name) : $(new-type) : $(new-project) ] ;
+
+ if [ $(target).dependencies ] { $(result).depends [ $(target).dependencies ] ; }
+ $(result).suffix [ $(target).suffix ] ;
+ $(result).root [ $(target).root ] ;
+ $(result).set-usage-requirements [ $(target).usage-requirements ] ;
+
+ local action = [ $(target).action ] ;
+ local action-class = [ modules.peek $(action) : __class__ ] ;
+
+ local ps = [ $(action).properties ] ;
+ local cloned-action = [ new $(action-class) $(result) :
+ [ $(action).sources ] : [ $(action).action-name ] : $(ps) ] ;
+ $(result).action $(cloned-action) ;
+
+ return $(result) ;
+ }
+}
+class modifier : generator ;
+
+# A modifier that changes the name of a target, after it's generated, given
+# a regular expression to slpit the name, and a set of token to insert
+# between the split tokens of the name. This also exposes the target for other
+# uses with a symlink to the original name (optionally).
+#
+rule name-modifier ( )
+{
+ # Apply ourselves to EXE targets, for now.
+ modifier.__init__ name.modifier : : EXE LIB : <name-modify>yes ;
+
+ # Modifies the name, by cloning the target with the new name.
+ #
+ rule modify-target-after ( target : project name ? : property-set : sources + : multiple ? )
+ {
+ local result = $(target) ;
+
+ local name-mod-p = [ property.select <name-modifier> : [ $(property-set).raw ] ] ;
+ if $(name-mod-p)
+ {
+ local new-name = [ modify-name [ $(target).name ] : $(name-mod-p:G=) ] ;
+ if $(new-name) != [ $(target).name ]
+ {
+ result = [ clone-file-target $(target) : $(new-name) ] ;
+ }
+ local expose-original-as-symlink = [ MATCH "<symlink>(.*)" : $(name-mod-p) ] ;
+ if $(expose-original-as-symlink)
+ {
+ local symlink-t = [ new symlink-targets $(project) : $(name) : [ $(result).name ] ] ;
+ result = [ $(symlink-t).construct $(result)
+ : [ property-set.create [ $(property-set).raw ] <symlink-location>build-relative ] ] ;
+ }
+ }
+
+ return $(result) ;
+ }
+
+ # Do the transformation of the name.
+ #
+ rule modify-name ( name : modifier-spec + )
+ {
+ local match = [ MATCH "<match>(.*)" : $(modifier-spec) ] ;
+ local name-parts = [ MATCH $(match) : $(name) ] ;
+ local insertions = [ sequence.insertion-sort [ MATCH "(<[0123456789]+>.*)" : $(modifier-spec) ] ] ;
+ local new-name-parts ;
+ local insert-position = 1 ;
+ while $(insertions)
+ {
+ local insertion = [ MATCH "<$(insert-position)>(.*)" : $(insertions[1]) ] ;
+ if $(insertion)
+ {
+ new-name-parts += $(insertion) ;
+ insertions = $(insertions[2-]) ;
+ }
+ new-name-parts += $(name-parts[1]) ;
+ name-parts = $(name-parts[2-]) ;
+ insert-position = [ numbers.increment $(insert-position) ] ;
+ }
+ new-name-parts += $(name-parts) ;
+ return [ sequence.join $(new-name-parts) ] ;
+ }
+
+ rule optional-properties ( )
+ {
+ return <name-modify>yes ;
+ }
+}
+class name-modifier : modifier ;
+feature.feature name-modifier : : free ;
+feature.feature name-modify : no yes : incidental optional ;
+generators.register [ new name-modifier ] ;
+
+# Translates <version> property to a set of modification properties
+# that are applied by the name-modifier, and symlink-modifier.
+#
+rule version-to-modifier ( property : properties * )
+{
+ return
+ <name-modify>yes
+ <name-modifier><match>"^([^.]*)(.*)" <name-modifier><2>.$(property:G=)
+ <name-modifier><symlink>yes
+ ;
+}
+feature.action <version> : version-to-modifier ;
Added: boost-jam/boost-build/branches/upstream/current/build/project-roots.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/project-roots.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/project-roots.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,370 @@
+# (C) Copyright Rene Rivera, 2002.
+#
+# See accompanying license for terms and conditions of use.
+#
+
+# Represents the projet-root of a collection of projects. This maintains
+# information about the root, and pointers to the project defined within
+# the root. Each project-root gets it's own module to put things into. For
+# instance declared constants which also get interned into each loaded project.
+
+import modules ;
+import path ;
+import "class" ;
+import set ;
+import regex ;
+
+# Load the project-root file for the given directory. The directory can
+# be either the project-root itself, or any subdirectory. Fails if it can't
+# find the project-root. We return the project-root module.
+#
+rule load (
+ dir # The directory to obtain the project-root for.
+ )
+{
+ local location = [ find-project-root $(dir) ] ;
+
+ # No project-root file found.
+ #
+ if ! $(location)
+ {
+ ECHO "Failed to find the project root for directory '$(dir)'." ;
+ ECHO "Did not find a project-root.jam file there or in any of its parent"
+ "directories." ;
+ EXIT "Please consult the documentation at 'http://www.boost.org'." ;
+ }
+ location = [ path.parent [ path.make $(location) ] ] ;
+
+ local module-name = project-root<$(location)> ;
+
+ local root ;
+ # Only bother with the rest if the project-root isn't loaded yet.
+ #
+ if ! [ modules.peek $(module-name) : .project-root ]
+ {
+ # Create the project-root, and remember it.
+ #
+ root = [ class.new project-root-object $(location) ] ;
+ modules.poke $(module-name) : .project-root : $(root) ;
+ .roots += $(root) ;
+
+ # Let the project root initialize and load the contents.
+ #
+ $(root).initialize ;
+ }
+ else
+ {
+ root = [ modules.peek $(module-name) : .project-root ] ;
+ }
+
+
+ # Return the module for the project.
+ #
+ return $(root) ;
+}
+
+# Finds the location of project root for a directory.
+# Returns the path to 'project-root.jam'.
+rule find-project-root ( dir )
+{
+ # Find the project-root.jam corresponding to this directory.
+ #
+ local location = [ path.glob $(dir) : project-root.jam ] ;
+ if ! $(location)
+ {
+ location = [ path.glob-in-parents $(dir) : project-root.jam ] ;
+ }
+ return $(location) ;
+}
+
+
+# Print out all the project-roots.
+#
+rule print ( )
+{
+ import sequence ;
+ import print ;
+
+ local rule compare-project-roots ( r1 r2 )
+ {
+ if [ $(r1).get-module ] < [ $(r2).get-module ]
+ {
+ return true ;
+ }
+ }
+
+ print.section "Project Roots" ;
+ local roots = [ sequence.insertion-sort $(.roots) : compare-project-roots ] ;
+ for local root in $(roots)
+ {
+ $(root).print ;
+ }
+}
+
+# Class encapsulating settings for a single project root.
+#
+class project-root-object
+{
+ import path ;
+ import set ;
+ import sequence ;
+ import print ;
+ import project ;
+
+ rule __init__ (
+ location # The root location.
+ )
+ {
+ # The module name of the project-root.
+ self.module = project-root<$(location)> ;
+
+ # The location of the project-root, as a path.
+ self.location = $(location) ;
+
+ # The set of projects registered in this project-root.
+ self.projects = ;
+
+ # The set of interned constants for this project-root.
+ self.constants = ;
+ }
+
+ # Accessor, the module of the project root.
+ rule get-module ( )
+ {
+ return $(self.module) ;
+ }
+
+ # Accessor, the location of the porject root.
+ rule get-location ( )
+ {
+ return $(self.location) ;
+ }
+
+ # Accessor, the project modules under this project root.
+ rule get-projects ( )
+ {
+ return $(self.projects) ;
+ }
+
+ # Accessor, the constants to intern into the project root.
+ rule get-constants ( )
+ {
+ return $(self.constants) ;
+ }
+
+ # Initialize the project root, also loads the project root file.
+ rule initialize ( )
+ {
+ # Give the new module all the rules from project-root-context
+ #
+ modules.clone-rules project-root-context $(self.module) ;
+
+ # Load it within a module specifically for the project root.
+ # The module system handles checking for multiple includes.
+ #
+ modules.load $(self.module)
+ : project-root.jam : [ path.native $(self.location) ] ;
+ }
+
+ # Accessor, add a constant.
+ rule add-constant (
+ name # Variable name of the constant.
+ : value # Value of the constant.
+ : type ? # Optional type of value.
+ )
+ {
+ switch $(type)
+ {
+ case path :
+ value = [ path.root [ path.make $(value) ] $(self.location) ] ;
+ # Now make the value absolute path
+ value = [ path.root $(value) [ path.pwd ] ] ;
+ # Constants should be in platform-native form
+ value = [ path.native $(value) ] ;
+ }
+ if ! $(name) in $(self.constants)
+ {
+ self.constants += $(name) ;
+ }
+ self.constant.$(name) = $(value) ;
+ # Inject the constant in the scope of project-root module
+ modules.poke $(self.module) : $(name) : $(value) ;
+ }
+
+ # Register a project under this project-root. This does any setup
+ # in the module of the project, including interning the project-root
+ # constants. Multiple calls on the same project are allowed and will
+ # not disturb the previous calls.
+ #
+ rule register-project (
+ project-module # The module of the project to register.
+ )
+ {
+ if ! $(project-module) in $(self.projects)
+ {
+ self.projects += $(project-module) ;
+ intern-constants $(project-module) ;
+ modules.clone-rules project-context $(project-module) ;
+
+ # Import project-root rules declared by teh user into each project.
+ #
+ local user-rules = [ set.difference
+ [ RULENAMES $(self.module) ] :
+ [ RULENAMES project-root-context ] ] ;
+ IMPORT $(self.module) : $(user-rules) : $(project-module) : $(user-rules) ;
+ }
+ }
+
+ # Intern the constants from this project-root into the calling context.
+ #
+ rule intern-constants (
+ context ? # The module to intern into the current module.
+ )
+ {
+ local intern-module = $(context) ;
+ intern-module ?= [ CALLER_MODULE ] ;
+ for local c in $(self.constants)
+ {
+ modules.poke $(intern-module) : $(c) : $(self.constant.$(c)) ;
+ }
+ }
+
+ # Needed to get deterministic order of output, which makes testing simpler
+ local rule compare-projects ( p1 p2 )
+ {
+ local id1 = [ project.attribute $(p1) id ] ;
+ local id2 = [ project.attribute $(p2) id ] ;
+ if $(id1) < $(id2)
+ {
+ return true ;
+ }
+ else
+ {
+ if $(id1) = $(id2) && $(p1) < $(p2)
+ {
+ return true ;
+ }
+ }
+ }
+
+
+ # Print out info about this project root. Calls print on the
+ # individual projects in this project-root.
+ #
+ rule print ( )
+ {
+ print.section "'"$(self.location)"'" Module for project-root is "'"$(self.module)"'" ;
+ if $(self.constants)
+ {
+ print.section Constants ;
+ print.list-start ;
+ local constants = [ sequence.insertion-sort $(self.constants) ] ;
+ for local c in $(constants)
+ {
+ print.list-item $(c) "=" $(self.constant.$(c)) ;
+ }
+ print.list-end ;
+ }
+ if $(self.projects)
+ {
+ print.section Projects ;
+ local projects = [ sequence.insertion-sort $(self.projects) : compare-projects ] ;
+ for local p in $(projects)
+ {
+ local attributes = [ project.attributes $(p) ] ;
+ $(attributes).print ;
+ }
+ }
+ }
+}
+
+# Rules callable by the user in the context of the project-root.jam of a project.
+#
+module project-root-context
+{
+ # Make toolset.using accessible in project-root.
+ import toolset : using ;
+ EXPORT project-root-context : using ;
+
+ # Access to project root object and shortcut for it's methods. The
+ # optional argument is a shortcut to execute the given method on the
+ # object. This saves the hasle of creating local vars to call on the
+ # singleton.
+ #
+ rule project-root (
+ method ? # The optional method.
+ args * # The arguments.
+ : * # The rest.
+ )
+ {
+ if $(method)
+ {
+ return [ $(.project-root).$(method) $(args) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+ else
+ {
+ return $(.project-root) ;
+ }
+ }
+
+ # Declare and set a project global constant. Project global constants are
+ # normal variables but should not be changed. They are applied to each
+ # Jamfile that is loaded under it's corresponding project-root.
+ #
+ rule constant (
+ name # Variable name of the constant.
+ : value # Value of the constant.
+ )
+ {
+ project-root add-constant $(name) : $(value) ;
+ }
+
+ # Declare and set a project global constant, whose value is a path. The
+ # path is adjusted to be relative to the invocation directory. The given
+ # value path is taken to be either absolute, or relative to this project root.
+ #
+ rule path-constant (
+ name # Variable name of the constant.
+ : value # Value of the constant.
+ )
+ {
+ project-root add-constant $(name) : $(value) : path ;
+ }
+
+ # Load and use a project in this project root.
+ #
+ rule use-project (
+ id # The ID of the project.
+ : location # The location of the project.
+ )
+ {
+ import project ;
+ import path ;
+ project.use $(id) : [ path.root
+ [ path.make $(location) ] [ project-root get-location ] ] ;
+ }
+}
+
+# Project root specific rules callable in the context of a project file. These
+# get imported into each project.
+#
+module project-context
+{
+ # Access to project root object and shortcut for it's methods. The
+ # optional argument is a shortcut to execute the given method on the
+ # object. This saves the hasle of creating local vars to call on the
+ # singleton.
+ #
+ rule project-root (
+ method ? # The optional method.
+ args * # The arguments.
+ : * # The rest.
+ )
+ {
+ import project ;
+ local attributes = [ project.attributes $(__name__) ] ;
+ local project-root = [ $(attributes).get project-root ] ;
+ return [ $(project-root).$(method)
+ $(args) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+}
Property changes on: boost-jam/boost-build/branches/upstream/current/build/project-roots.jam
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/build/project.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/project.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/project.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,644 @@
+# Copyright (C) Vladimir Prus and Rene Rivera 2002.
+# 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.
+
+# Implements project representation and loading.
+# Each project is represented by
+# - a module where all the Jamfile content live.
+# - an instance of 'project-attributes' class.
+# (given module name, can be obtained by 'attributes' rule)
+# - an instance of 'project-target' class (from targets.jam)
+# (given a module name, can be obtained by 'target' rule)
+#
+# Typically, projects are created as result of loading Jamfile, which is
+# do by rules 'load' and 'initialize', below. First, module for Jamfile
+# is loaded and new project-attributes instance is created. Some rules
+# necessary for project are added to the module (see 'project-rules' module)
+# at the bottom of this file.
+# Default project attributes are set (inheriting attributes of parent project, if
+# it exists). After that, Jamfile is read. It can declare its own attributes,
+# via 'project' rule, which will be combined with already set attributes.
+#
+#
+# The 'project' rule can also declare project id, which will be associated with
+# the project module.
+#
+# There can also be 'standalone' projects. They are created by calling 'initialize'
+# on arbitrary module, and not specifying location. After the call, the module can
+# call 'project' rule, declare main target and behave as regular projects. However,
+# since it's not associated with any location, it's better declare only prebuilt
+# targets.
+#
+# The list of all loaded Jamfile is stored in variable .project-locations. It's possible
+# to obtain module name for a location using 'module-name' rule. The standalone projects
+# are not recorded, the only way to use them is by project id.
+
+
+import modules : peek poke ;
+import numbers ;
+import path ;
+import sequence ;
+import errors : error ;
+import project-roots ;
+
+import print ;
+import "class" : new ;
+import errors ;
+import assert ;
+import property-set ;
+
+#
+# Loads jamfile at the given location. After loading, project global
+# file and jamfile needed by the loaded one will be loaded recursively.
+# If the jamfile at that location is loaded already, does nothing.
+# Returns the project module for the Jamfile.
+#
+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) ] ;
+ # If Jamfile is already loaded, don't try again.
+ if ! $(module-name) in $(.jamfile-modules)
+ {
+ load-jamfile $(jamfile-location) ;
+
+ for local p in [ attribute $(module-name) projects-to-build ]
+ {
+ load [ path.join $(jamfile-location) $(p) ] ;
+ }
+ }
+ return $(module-name) ;
+}
+
+# Makes the specified 'module' act as if it were a regularly loaded Jamfile
+# at 'location'. If Jamfile is already located for that location, it's an
+# error.
+rule act-as-jamfile ( module : location )
+{
+ if [ module-name $(location) ] in $(.jamfile-modules)
+ {
+ errors.error "Jamfile was already loaded for '$(location)'" ;
+ }
+ # Set up non-default mapping from location to module.
+ .module.$(location) = $(module) ;
+
+ # Add the location to the list of project locations
+ # so that we don't try to load Jamfile in future
+ .jamfile-modules += [ module-name $(location) ] ;
+
+ initialize $(module) : $(location) ;
+}
+
+
+# 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 ;
+
+ # 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.
+
+ project-module = [ module-name $(location) ] ;
+ if ! $(project-module) in $(.jamfile-modules)
+ {
+ if [ find-jamfile $(location) ]
+ {
+ project-module = [ load $(location) ] ;
+ }
+ else
+ {
+ project-module = ;
+ }
+ }
+ }
+
+ return $(project-module) ;
+}
+
+#
+# Returns the name of module corresponding to 'jamfile-location'.
+# If no module corresponds to location yet, associates default
+# module name with that location.
+#
+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)) ;
+}
+
+# Default patterns to search for the Jamfiles to use for build
+# declarations.
+#
+JAMFILE = [ modules.peek : JAMFILE ] ;
+JAMFILE ?= [Jj]amfile.v2 [Jj]amfile [Jj]amfile.jam ;
+
+# Find the Jamfile at the given location. This returns the exact names of
+# all the Jamfiles in the given directory. The optional parent-root argument
+# causes this to search not the given directory but the ones above it up
+# to the directory given in it.
+#
+local rule find-jamfile (
+ dir # The directory(s) to look for a Jamfile.
+ parent-root ? # Optional flag indicating to search for the parent Jamfile.
+ )
+{
+ # Glob for all the possible Jamfiles according to the match pattern.
+ #
+ local jamfile-glob = ;
+ if $(parent-root)
+ {
+ if ! $(.parent-jamfile.$(dir))
+ {
+ .parent-jamfile.$(dir) =
+ [ path.glob-in-parents $(dir) : $(JAMFILE) : $(parent-root) ] ;
+ }
+ jamfile-glob = $(.parent-jamfile.$(dir)) ;
+ }
+ else
+ {
+ if ! $(.jamfile.$(dir))
+ {
+ .jamfile.$(dir) = [ path.glob $(dir) : $(JAMFILE) ] ;
+ }
+ jamfile-glob = $(.jamfile.$(dir)) ;
+
+ }
+
+ return $(jamfile-glob) ;
+}
+
+# Load a Jamfile at the given directory. Returns nothing.
+# Will attempt to load the file as indicated by the JAMFILE patterns.
+# Effect of calling this rule twice with the same 'dir' is underfined.
+
+local rule load-jamfile (
+ dir # The directory of the project Jamfile.
+ )
+{
+ # See if the Jamfile is where it should be.
+ #
+ local jamfile-to-load = [ find-jamfile $(dir) ] ;
+
+ # Could not find it, error.
+ #
+ if ! $(jamfile-to-load)
+ {
+ errors.error
+ "Unable to load Jamfile." :
+ "Could not find a Jamfile in directory '$(dir)'". :
+ "Attempted to find it with pattern '"$(JAMFILE:J=" ")"'." :
+ "Please consult the documentation at 'http://www.boost.org'." ;
+ }
+
+ # Multiple Jamfiles found in the same place. Warn about this.
+ # And ensure we use only one of them.
+ # As a temporary convenience measure, if there's Jamfile.v2 amount
+ # found files, suppress the warning and use it.
+ #
+ if $(jamfile-to-load[2-])
+ {
+ local v2-jamfiles = [ MATCH (.*[Jj]amfile\\.v2) : $(jamfile-to-load) ] ;
+
+ if $(v2-jamfiles) && ! $(v2-jamfiles[2])
+ {
+ jamfile-to-load = $(v2-jamfiles) ;
+ }
+ else
+ {
+ ECHO
+ "WARNING: Found multiple Jamfiles at this '"$(dir)"' location!"
+ "Loading the first one: '" [ path.basename $(jamfile-to-load[1]) ] "'." ;
+ }
+
+ jamfile-to-load = $(jamfile-to-load[1]) ;
+ }
+
+ # The module of the jamfile.
+ #
+ local jamfile-module = [ module-name [ path.parent $(jamfile-to-load) ] ] ;
+
+ # Initialize the jamfile module before loading.
+ #
+ initialize $(jamfile-module) : [ path.parent $(jamfile-to-load) ] ;
+
+ # Now load the Jamfile in it's own context.
+ # Initialization might have load parent Jamfiles, which might have
+ # loaded the current Jamfile with use-project. Do a final check to make
+ # sure it's not loaded already.
+ if ! $(jamfile-module) in $(.jamfile-modules)
+ {
+ .jamfile-modules += $(jamfile-module) ;
+ modules.load $(jamfile-module) : [ path.native $(jamfile-to-load) ] : . ;
+ }
+ .current-project = $(.current-project[2-]) ;
+}
+
+# Initialize the module for a project.
+#
+rule initialize (
+ module-name # The name of the project module.
+ : location ? # The location (directory) of the project to initialize.
+ # If not specified, stanalone project will be initialized.
+ )
+{
+ # TODO: need to consider if standalone projects can do anything but defining
+ # prebuilt targets. If so, we need to give more sensible "location", so that
+ # source paths are correct.
+ location ?= "" ;
+ # Create the module for the Jamfile first.
+ module $(module-name)
+ {
+ }
+ $(module-name).attributes = [ new project-attributes $(location) ] ;
+ local attributes = $($(module-name).attributes) ;
+
+ if $(location)
+ {
+ $(attributes).set source-location : [ path.make $(location) ] : exact ;
+ }
+ else
+ {
+ $(attributes).set source-location : "" : exact ;
+ }
+
+ $(attributes).set requirements : [ property-set.empty ] : exact ;
+ $(attributes).set usage-requirements : [ property-set.empty ] : exact ;
+
+ # Import rules common to all project modules from project-rules module,
+ # defined at the end of this file.
+ modules.clone-rules project-rules $(module-name) ;
+
+ # We search for parent/project-root only if jamfile was specified --- i.e
+ # if the project is not standalone.
+ if $(location)
+ {
+ # Make sure we've loaded the project-root corresponding to this
+ # Jamfile.
+ #
+ local project-root-object = [ project-roots.load $(location) ] ;
+ local project-root = [ $(project-root-object).get-location ] ;
+
+ $(attributes).set project-root : $(project-root-object) : exact ;
+
+ local parent = [ find-jamfile $(location) $(project-root) ] ;
+ local parent-module = ;
+ if $(parent)
+ {
+ parent-module = [ load [ path.parent $(parent[1]) ] ] ;
+ }
+
+ inherit-attributes $(module-name) : $(project-root-object) : $(parent-module) ;
+ }
+
+ .current-project = [ target $(module-name) ] $(.current-project) ;
+}
+
+# Make 'project-module' inherit attributes of project root and parent module.
+rule inherit-attributes ( project-module : project-root : parent-module ? )
+{
+ # Register with the project root. This will inject project-root
+ # constants and do some other initialization.
+ $(project-root).register-project $(project-module) ;
+
+ if $(parent-module)
+ {
+ local attributes = $($(project-module).attributes) ;
+ local pattributes = [ attributes $(parent-module) ] ;
+ $(attributes).set parent : [ path.parent
+ [ path.make [ modules.binding $(parent-module) ] ] ] ;
+ $(attributes).set default-build
+ : [ $(pattributes).get default-build ] ;
+ $(attributes).set requirements
+ : [ $(pattributes).get requirements ] : exact ;
+ $(attributes).set usage-requirements
+ : [ $(pattributes).get usage-requirements ] : exact ;
+ local parent-build-dir = [ $(pattributes).get build-dir ] ;
+ if $(parent-build-dir)
+ {
+ # Have to compute relative path from parent dir to our dir
+ # Convert both paths to absolute, since we cannot
+ # find relative path from ".." to "."
+
+ local location = [ attribute $(project-module) location ] ;
+ local parent-location = [ attribute $(parent-module) location ] ;
+
+ local pwd = [ path.pwd ] ;
+ local parent-dir = [ path.root $(parent-location) $(pwd) ] ;
+ local our-dir = [ path.root $(location) $(pwd) ] ;
+ $(attributes).set build-dir : [ path.join $(parent-build-dir)
+ [ path.relative $(our-dir) $(parent-dir) ] ] : exact ;
+ }
+ }
+}
+
+
+# Associate the given id with the given project module
+rule register-id ( id : module )
+{
+ $(id).jamfile-module = $(module) ;
+}
+
+# Class keeping all the attributes of a project.
+#
+# The standard attributes are "id", "location", "project-root", "parent"
+# "requirements", "default-build", "source-location" and "projects-to-build".
+class project-attributes
+{
+ import property ;
+ import property-set ;
+ import errors ;
+ import path ;
+ import print ;
+ import sequence ;
+
+ rule __init__ ( location )
+ {
+ self.location = $(location) ;
+ }
+
+ # Set the named attribute from the specification given by the user.
+ # The value actually set may be different.
+ rule set ( attribute : specification *
+ : exact ? # Sets value from 'specification' without any processing
+ )
+ {
+ if $(exact)
+ {
+ self.$(attribute) = $(specification) ;
+ }
+ else if $(attribute) = "requirements"
+ {
+ specification = [ property.translate-paths $(specification)
+ : $(self.location) ] ;
+ specification =
+ [ property.expand-subfeatures-in-conditions $(specification) ] ;
+ specification = [ property.make $(specification) ] ;
+ result = [ property-set.create $(specification) ] ;
+
+ # If we have inherited properties, need to refine them with the
+ # specified.
+ local current = $(self.requirements) ;
+ if $(current)
+ {
+ result = [ $(current).refine $(result) ] ;
+ }
+
+ if $(result[1]) = "@error"
+ {
+ errors.error
+ "Requirements for project at '$(self.location)'"
+ "conflict with parent's." :
+ "Explanation: " $(result[2-]) ;
+ }
+ else
+ {
+ self.requirements = $(result) ;
+ }
+ }
+ else if $(attribute) = "usage-requirements"
+ {
+ local unconditional ;
+ for local p in $(specification)
+ {
+ local split = [ property.split-conditional $(p) ] ;
+ split ?= nothing $(p) ;
+ unconditional += $(split[2]) ;
+ }
+
+ local non-free = [ property.remove free : $(unconditional) ] ;
+ if $(non-free)
+ {
+ errors.error "usage-requirements" $(specification) "have non-free properties" $(non-free) ;
+ }
+ local t = [ property.translate-paths $(specification)
+ : $(self.location) ] ;
+ if $(self.usage-requirements)
+ {
+ self.usage-requirements = [ property-set.create
+ [ $(self.usage-requirements).raw ] $(t) ] ;
+ }
+ else
+ {
+ self.usage-requirements = [ property-set.create $(t) ] ;
+ }
+ }
+ else if $(attribute) = "default-build"
+ {
+ self.default-build = [ property.make $(specification) ] ;
+ }
+ else if $(attribute) = "source-location"
+ {
+ self.source-location = [ path.root
+ [ path.make $(specification) ] $(self.location) ] ;
+ }
+ else if $(attribute) = "build-dir"
+ {
+ self.build-dir = [ path.root $(specification) $(self.location) ] ;
+ }
+ else if ! $(attribute) in "id" "default-build" "location" "source-location"
+ "parent" "projects-to-build"
+ {
+ errors.error "Invalid project attribute '$(attribute)' specified "
+ "for project at '$(self.location)'" ;
+ }
+ else
+ {
+ self.$(attribute) = $(specification) ;
+ }
+ }
+
+ # Returns the value of the given attribute.
+ rule get ( attribute )
+ {
+ return $(self.$(attribute)) ;
+ }
+
+ # Prints the project attributes.
+ rule print ( )
+ {
+ local id = $(self.id) ; id ?= (none) ;
+ local parent = $(self.parent) ; parent ?= (none) ;
+ print.section "'"$(id)"'" ;
+ print.list-start ;
+ print.list-item "Parent project:" $(parent) ;
+ print.list-item "Requirements:" [ $(self.requirements).raw ] ;
+ print.list-item "Default build:" $(self.default-build) ;
+ print.list-item "Source location:" $(self.source-location) ;
+ print.list-item "Projects to build:"
+ [ sequence.insertion-sort $(self.projects-to-build) ] ;
+ print.list-end ;
+ }
+
+}
+
+# Returns the project which is currently being loaded
+rule current ( )
+{
+ return $(.current-project[1]) ;
+}
+
+# Returns the project-attribute instance for the specified jamfile module.
+rule attributes ( project )
+{
+ return $($(project).attributes) ;
+}
+
+# Returns the value of the specified attribute in the specified jamfile module.
+rule attribute ( project attribute )
+{
+ return [ $($(project).attributes).get $(attribute) ] ;
+}
+
+# Returns the project target corresponding to the 'project-module'.
+rule target ( project-module )
+{
+ if ! $(.target.$(project-module))
+ {
+ .target.$(project-module) = [ new project-target $(project-module)
+ : $(project-module)
+ : [ attribute $(project-module) requirements ] ] ;
+ }
+ return $(.target.$(project-module)) ;
+}
+
+# Use/load a project.
+rule use ( id : location )
+{
+ local saved-project = $(.current-project) ;
+ local project-module = [ project.load $(location) ] ;
+ local declared-id = [ project.attribute $(project-module) id ] ;
+
+ if ! $(declared-id)
+ {
+ error "project loaded by 'use-project' has no project-id." ;
+ }
+ if $(declared-id) != $(id)
+ {
+ error project \"$(declared-id)\" at \"$(location)\" redeclared with id \"$(id)\". ;
+ }
+ .current-project = $(saved-project) ;
+}
+
+# This module defines rules common to all projects
+module project-rules
+{
+ rule project ( id ? : options * : * )
+ {
+ import project ;
+ import path ;
+
+ local attributes = [ project.attributes $(__name__) ] ;
+ if $(id)
+ {
+ id = [ path.root $(id) / ] ;
+ project.register-id $(id) : $(__name__) ;
+ $(attributes).set id : $(id) ;
+ }
+
+ for n in 2 3 4 5 6 7 8 9
+ {
+ local option = $($(n)) ;
+ if $(option)
+ {
+ $(attributes).set $(option[1]) : $(option[2-]) ;
+ }
+ }
+ }
+
+ rule use-project ( id : where )
+ {
+ import project ;
+ import path ;
+ local attributes = [ project.attributes $(__name__) ] ;
+ project.use $(id) : [ path.root
+ [ path.make $(where) ] [ $(attributes).get location ] ] ;
+ }
+
+ rule build-project ( dir )
+ {
+ import project ;
+ local attributes = [ project.attributes $(__name__) ] ;
+
+ local now = [ $(attributes).get projects-to-build ] ;
+ $(attributes).set projects-to-build : $(now) $(dir) ;
+ }
+
+ rule explicit ( target-names * )
+ {
+ import project ;
+ local t = [ project.target $(__name__) ] ;
+ for local n in $(target-names)
+ {
+ $(t).mark-target-as-explicit $(n) ;
+ }
+ }
+
+ rule glob ( wildcards + )
+ {
+ import path ;
+ import project ;
+
+ local location = [ project.attribute $(__name__) source-location ] ;
+
+ local all-paths ;
+ if ! $(wildcards:D)
+ {
+ # No directory in any wildcard -- the simplest case.
+ all-paths = [ path.glob $(location) : $(wildcards) ] ;
+ all-paths = $(all-paths:D="") ;
+ }
+ else
+ {
+ for local w in $(wildcards)
+ {
+ local l = [ path.join $(location) $(w:D) ] ;
+ local paths = [ path.glob $(l) : $(w: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)
+ {
+ all-paths += [ path.root $(p) [ path.pwd ] ] ;
+ }
+ }
+
+ }
+
+ return $(all-paths) ;
+ }
+}
+
+
+local rule __test__ ( )
+{
+ import assert ;
+ assert.result foo/bar : remove-trailing-slash foo/bar/ ;
+ assert.result foo/bar : remove-trailing-slash foo/bar ;
+ assert.result foo : remove-trailing-slash foo/ ;
+ assert.result foo : remove-trailing-slash foo ;
+}
Added: boost-jam/boost-build/branches/upstream/current/build/property-set.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/property-set.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/property-set.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,319 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+import "class" : new ;
+import feature ;
+import property ;
+import sequence ;
+
+# Class for storing a set of properties.
+# - there's 1<->1 correspondence between identity and value. No
+# two instances of the class are equal. To maintain this property,
+# the 'property-set.create' rule should be used to create new instances.
+# Instances are immutable.
+#
+# - each property is classified with regard to it's effect on build
+# results. Incidental properties have no effect on build results, from
+# Boost.Build point of view. Others are either free, or non-free, which we
+# call 'base'. Each property belong to exactly one of those categories and
+# it's possible to get list of properties in each category.
+#
+# In addition, it's possible to get list of properties with specific
+# attribute.
+#
+# - several operations, like and refine and as-path are provided. They all use
+# caching whenever possible.
+#
+class property-set
+{
+ import feature ;
+ import property-set ;
+ import property ;
+ import set ;
+
+ rule __init__ ( raw-properties * )
+ {
+ self.raw = $(raw-properties) ;
+
+ for local p in $(raw-properties)
+ {
+ local att = [ feature.attributes $(p:G) ] ;
+ # A feature can be both incidental and free,
+ # in which case we add it to incidental.
+ if incidental in $(att)
+ {
+ self.incidental += $(p) ;
+ }
+ else if free in $(att)
+ {
+ self.free += $(p) ;
+ }
+ else
+ {
+ self.base += $(p) ;
+ }
+
+ if dependency in $(att)
+ {
+ self.dependency += $(p) ;
+ }
+ else
+ {
+ self.non-dependency += $(p) ;
+ }
+
+ if [ MATCH (:) : $(p:G=) ]
+ {
+ self.conditional += $(p) ;
+ }
+ else
+ {
+ self.non-conditional += $(p) ;
+ }
+
+
+ if propagated in $(att)
+ {
+ self.propagated += $(p) ;
+ }
+ if link-incompatible in $(att)
+ {
+ self.link-incompatible += $(p) ;
+ }
+ }
+
+ }
+
+
+ # Returns Jam list of stored properties
+ rule raw ( )
+ {
+ return $(self.raw) ;
+ }
+
+ # Returns properties that are neither incidental nor free
+ rule base ( )
+ {
+ return $(self.base) ;
+ }
+
+
+ # Returns free properties which are not dependency properties
+ rule free ( )
+ {
+ return $(self.free) ;
+ }
+
+ # Returns dependency properties
+ rule dependency ( )
+ {
+ return $(self.dependency) ;
+ }
+
+ rule non-dependency ( )
+ {
+ return $(self.non-dependency) ;
+ }
+
+ rule conditional ( )
+ {
+ return $(self.conditional) ;
+ }
+
+ rule non-conditional ( )
+ {
+ return $(self.non-conditional) ;
+ }
+
+ # Returns incidental properties
+ rule incidental ( )
+ {
+ return $(self.incidental) ;
+ }
+
+ rule refine ( ps )
+ {
+ if ! $(self.refined.$(ps))
+ {
+ local r = [ property.refine $(self.raw) : [ $(ps).raw ] ] ;
+ if $(r[1]) != "@error"
+ {
+ self.refined.$(ps) = [ property-set.create $(r) ] ;
+ }
+ else
+ {
+ self.refined.$(ps) = $(r) ;
+ }
+ }
+ return $(self.refined.$(ps)) ;
+ }
+
+ rule expand ( )
+ {
+ if ! $(self.expanded)
+ {
+ self.expanded = [ property-set.create [ feature.expand $(self.raw) ] ] ;
+ }
+ return $(self.expanded) ;
+ }
+
+
+ rule expand-composites ( )
+ {
+ if ! $(self.composites)
+ {
+ self.composites = [ property-set.create
+ [ feature.expand-composites $(self.raw) ] ] ;
+ }
+ return $(self.composites) ;
+ }
+
+ rule evaluate-conditionals ( context ? )
+ {
+ context ?= $(__name__) ;
+ if ! $(self.evaluated.$(context))
+ {
+ self.evaluated.$(context) = [ property-set.create
+ [ property.evaluate-conditionals-in-context $(self.raw) : [ $(context).raw ] ] ] ;
+ }
+ return $(self.evaluated.$(context)) ;
+ }
+
+ rule propagated ( )
+ {
+ if ! $(self.propagated-ps)
+ {
+ self.propagated-ps = [ property-set.create $(self.propagated) ] ;
+ }
+ return $(self.propagated-ps) ;
+ }
+
+ rule link-incompatible ( )
+ {
+ if ! $(self.link-incompatible-ps)
+ {
+ self.link-incompatible-ps =
+ [ property-set.create $(self.link-incompatible) ] ;
+ }
+ return $(self.link-incompatible-ps) ;
+ }
+
+
+ rule run-actions ( )
+ {
+ if ! $(self.run)
+ {
+ self.run = [ property-set.create [ feature.run-actions $(self.raw) ] ] ;
+ }
+ return $(self.run) ;
+ }
+
+ rule add-defaults ( )
+ {
+ if ! $(self.defaults)
+ {
+ self.defaults = [ property-set.create
+ [ feature.add-defaults $(self.raw) ] ] ;
+ }
+ return $(self.defaults) ;
+ }
+
+
+ rule as-path ( )
+ {
+ if ! $(self.as-path)
+ {
+ self.as-path = [ property.as-path $(self.base) ] ;
+ }
+ return $(self.as-path) ;
+ }
+
+ rule add ( ps )
+ {
+ if ! $(self.added.$(ps))
+ {
+ self.added.$(ps) = [ property-set.create $(self.raw) [ $(ps).raw ] ] ;
+ }
+ return $(self.added.$(ps)) ;
+ }
+
+ rule add-raw ( properties * )
+ {
+ return [ add [ property-set.create $(properties) ] ] ;
+ }
+
+ rule link-incompatible-with ( ps )
+ {
+ if ! $(.li.$(ps))
+ {
+ local li1 = [ $(__name__).link-incompatible ] ;
+ local li2 = [ $(ps).link-incompatible ] ;
+ if [ set.equal $(li1) : $(li2) ]
+ {
+ .li.$(ps) = false ;
+ }
+ else
+ {
+ .li.$(ps) = true ;
+ }
+ }
+ if $(.li.$(ps)) = true
+ {
+ return true ;
+ }
+ else
+ {
+ return ;
+ }
+ }
+
+
+
+ # Returns all values of 'feature'.
+ rule get ( feature )
+ {
+ return [ feature.get-values $(feature) : $(self.raw) ] ;
+ }
+
+}
+
+# Creates new 'property-set' instance for the given raw properties,
+# or returns an already existing ones.
+rule create ( raw-properties * )
+{
+ raw-properties = [ sequence.unique
+ [ sequence.insertion-sort $(raw-properties) ] ] ;
+
+ local key = $(raw-properties:J=-:E=) ;
+
+ if ! $(.ps.$(key))
+ {
+ .ps.$(key) = [ new property-set $(raw-properties) ] ;
+ }
+ return $(.ps.$(key)) ;
+}
+NATIVE_RULE property-set : create ;
+
+# Creates new 'property-set' instances after checking
+# that all properties are valid and converting incidental
+# properties into gristed form.
+rule create-with-validation ( raw-properties * )
+{
+ property.validate $(raw-properties) ;
+
+ return [ create [ property.make $(raw-properties) ] ] ;
+}
+
+
+# Returns property-set with empty set of properties.
+rule empty ( )
+{
+ if ! $(.empty)
+ {
+ .empty = [ create ] ;
+ }
+
+ return $(.empty) ;
+}
Added: boost-jam/boost-build/branches/upstream/current/build/property.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/property.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/property.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,639 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+import utility : ungrist ;
+import sequence : unique ;
+import errors : error ;
+import feature ;
+import regex ;
+import sequence ;
+import set ;
+import path ;
+import assert ;
+
+# Refines 'properties' by overriding any non-free properties
+# for which a different value is specified in 'requirements'.
+# Conditional requirements are just added without modification.
+# Returns the resulting list of properties.
+rule refine ( properties * : requirements * )
+{
+ local result ;
+ local error ;
+
+ # All the elements of requirements should be present in the result
+ # Record them so that we can handle 'properties'.
+ for local r in $(requirements)
+ {
+ # Don't consider conditional requirements.
+ if ! [ MATCH (:) : $(r:G=) ]
+ {
+ # Note: cannot use local here, so take an ugly name
+ __require__$(r:G) = $(r:G=) ;
+ }
+ }
+
+ for local p in $(properties)
+ {
+ # No processing for free properties
+ if [ MATCH (:) : $(p:G=) ]
+ {
+ # Skip conditional properties
+ result += $(p) ;
+ }
+ else if free in [ feature.attributes $(p:G) ]
+ {
+ result += $(p) ;
+ }
+ else
+ {
+ local required-value = $(__require__$(p:G)) ;
+ if $(required-value)
+ {
+ local value = $(p:G=) ;
+ if $(value) != $(required-value)
+ {
+ result += $(p:G)$(required-value) ;
+ }
+ else
+ {
+ result += $(p) ;
+ }
+ }
+ else
+ {
+ result += $(p) ;
+ }
+ }
+ }
+
+ # Unset our ugly map.
+ for local r in $(requirements)
+ {
+ __require__$(r:G) = ;
+ }
+
+ if $(error)
+ {
+ return $(error) ;
+ }
+ else
+ {
+ return [ unique $(result) $(requirements) ] ;
+ }
+}
+
+# Removes all conditional properties which conditions are not met
+# For those with met conditions, removes the condition. Properies
+# in conditions are looked up in 'context'
+rule evaluate-conditionals-in-context ( properties * : context * )
+{
+ local base ;
+ local conditionals ;
+ for local p in $(properties)
+ {
+ if [ MATCH (:<) : $(p) ]
+ {
+ conditionals += $(p) ;
+ }
+ else
+ {
+ base += $(p) ;
+ }
+ }
+
+ local result = $(base) ;
+ for local p in $(conditionals)
+ {
+ # Separate condition and property
+ local s = [ MATCH (.*):(<.*) : $(p) ] ;
+ # Split condition into individual properties
+ local c = [ regex.split $(s[1]) "," ] ;
+ # Evaluate condition
+ if $(c) in $(context)
+ {
+ result += $(s[2]) ;
+ }
+ }
+ return $(result) ;
+}
+
+rule expand-subfeatures-in-conditions ( properties * )
+{
+ local result ;
+ for local p in $(properties)
+ {
+ local s = [ MATCH (.*):(<.*) : $(p) ] ;
+ if ! $(s)
+ {
+ result += $(p) ;
+ }
+ else
+ {
+ local condition = $(s[1]) ;
+ # Condition might include several elements
+ condition = [ regex.split $(condition) "," ] ;
+ local value = $(s[2]) ;
+ local e ;
+ for local c in $(condition)
+ {
+ if [ MATCH "^(<toolset>|<toolset->)" : $(c:G) ] ||
+ [ MATCH "^(<os>)" : $(c:G) ]
+ {
+ # It common that condition includes a toolset which
+ # was never defined, or mentiones subfeatures which
+ # were never defined. In that case, validation will
+ # only produce an spirious error, so don't validate.
+ e += [ feature.expand-subfeatures $(c) : true ] ;
+ }
+ else
+ {
+ e += [ feature.expand-subfeatures $(c) ] ;
+ }
+ }
+
+ if $(e) = $(condition)
+ {
+ result += $(p) ;
+ }
+ else
+ {
+ local individual-subfeatures = [ set.difference $(e) : $(condition) ] ;
+ result += $(individual-subfeatures:J=,):$(value) ;
+ }
+ }
+ }
+ return $(result) ;
+}
+
+
+
+# Helper for as-path, below. Orders properties with the implicit ones
+# first, and within the two sections in alphabetical order of feature
+# name.
+local rule path-order ( x y )
+{
+ if $(y:G) && ! $(x:G)
+ {
+ return true ;
+ }
+ else if $(x:G) && ! $(y:G)
+ {
+ return ;
+ }
+ else
+ {
+ if ! $(x:G)
+ {
+ x = [ feature.expand-subfeatures $(x) ] ;
+ y = [ feature.expand-subfeatures $(y) ] ;
+ }
+
+ if $(x[1]) < $(y[1])
+ {
+ return true ;
+ }
+ }
+}
+
+# Returns a path which represents the given expanded property set.
+rule as-path ( properties * )
+{
+ local entry = .result.$(properties:J=-) ;
+
+ if ! $($(entry))
+ {
+ # trim redundancy
+ properties = [ feature.minimize $(properties) ] ;
+
+ # sort according to path-order
+ properties = [ sequence.insertion-sort $(properties) : path-order ] ;
+
+ local components ;
+ for local p in $(properties)
+ {
+ if $(p:G)
+ {
+ local f = [ ungrist $(p:G) ] ;
+ components += $(f)-$(p:G=) ;
+ }
+ else
+ {
+ components += $(p) ;
+ }
+ }
+
+ $(entry) = $(components:J=/) ;
+ }
+
+ return $($(entry)) ;
+}
+
+# Exit with error if property is not valid.
+local rule validate1 ( property )
+{
+ local msg ;
+ if $(property:G)
+ {
+ local feature = $(property:G) ;
+ local value = $(property:G=) ;
+
+ if ! [ feature.valid $(feature) ]
+ {
+ feature = [ ungrist $(property:G) ] ; # Ungrist for better error messages
+ msg = "unknown feature '$(feature)'" ;
+ }
+ else if $(value) && ! free in [ feature.attributes $(feature) ]
+ {
+ feature.validate-value-string $(feature) $(value) ;
+ }
+ else if ! $(value)
+ {
+ feature = [ ungrist $(property:G) ] ; # Ungrist for better error messages
+ msg = "No value specified for feature '$(feature)'" ;
+ }
+ }
+ else
+ {
+ local feature = [ feature.implied-feature $(property) ] ;
+ feature.validate-value-string $(feature) $(property) ;
+ }
+ if $(msg)
+ {
+ error "Invalid property "'$(property:J=" ")'": "$(msg:J=" "). ;
+ }
+}
+
+rule validate ( properties * )
+{
+ for local p in $(properties)
+ {
+ validate1 $(p) ;
+ }
+}
+
+rule validate-property-sets ( property-sets * )
+{
+ for local s in $(property-sets)
+ {
+ validate [ feature.split $(s) ] ;
+ }
+}
+
+# Makes a property set from 'specification', converting implicit values into
+# full properties.
+rule make ( specification * )
+{
+ local result ;
+ for local e in $(specification)
+ {
+ if $(e:G)
+ {
+ result += $(e) ;
+ }
+ else if [ feature.is-implicit-value $(e) ]
+ {
+ local feature = [ feature.implied-feature $(e) ] ;
+ result += $(feature)$(e) ;
+ }
+ else
+ {
+ error "'$(e)' is not a valid for property specification" ;
+ }
+ }
+ return $(result) ;
+}
+
+# Returns a property sets which include all the elements in 'properties' that
+# do not have attributes listed in 'attributes'.
+rule remove ( attributes + : properties * )
+{
+ local result ;
+ for local e in $(properties)
+ {
+ if ! [ set.intersection $(attributes) : [ feature.attributes $(e:G) ] ]
+ {
+ result += $(e) ;
+ }
+ }
+ return $(result) ;
+}
+
+# Returns a property set which include all properties in 'properties' that have
+# any of 'attributes'.
+rule take ( attributes + : properties * )
+{
+ local result ;
+ for local e in $(properties)
+ {
+ if [ set.intersection $(attributes) : [ feature.attributes $(e:G) ] ]
+ {
+ result += $(e) ;
+ }
+ }
+ return $(result) ;
+}
+
+# Selects properties which correspond to any of the given features.
+rule select ( features * : properties * )
+{
+ local result ;
+
+ # add any missing angle brackets
+ local empty = "" ;
+ features = $(empty:G=$(features)) ;
+
+ for local p in $(properties)
+ {
+ if $(p:G) in $(features)
+ {
+ result += $(p) ;
+ }
+ }
+ return $(result) ;
+}
+
+# Returns a modified version of properties with all values of the
+# given feature replaced by the given value.
+# If 'value' is empty the feature will be removed
+rule change ( properties * : feature value ? )
+{
+ local result ;
+ for local p in $(properties)
+ {
+ if $(p:G) = $(feature)
+ {
+ result += $(value:G=$(feature)) ;
+ }
+ else
+ {
+ result += $(p) ;
+ }
+ }
+ return $(result) ;
+}
+
+# If 'property' is conditional property, returns
+# condition and the property, e.g
+# <variant>debug,<toolset>gcc:<inlining>full will become
+# <variant>debug,<toolset>gcc <inlining>full.
+# Otherwise, returns empty string.
+rule split-conditional ( property )
+{
+ local m = [ MATCH "(.+):<(.+)" : $(property) ] ;
+ if $(m)
+ {
+ return $(m[1]) <$(m[2]) ;
+ }
+}
+
+
+# Interpret all path properties in 'properties' as relative to 'path'
+# The property values are assumed to be in system-specific form, and
+# will be translated into normalized form.
+rule translate-paths ( properties * : path )
+{
+ local result ;
+ for local p in $(properties)
+ {
+ local split = [ split-conditional $(p) ] ;
+ local condition = "" ;
+ if $(split)
+ {
+ condition = $(split[1]): ;
+ p = $(split[2]) ;
+ }
+
+ # need to do this here to get reasonable error messages for
+ # unrecognized implicit features.
+ validate $(p) ;
+
+ if path in [ feature.attributes $(p:G) ]
+ {
+ local values = [ regex.split $(p:TG=) "&&" ] ;
+ local t ;
+ for local v in $(values)
+ {
+ t += [ path.root [ path.make $(v) ] $(path) ] ;
+ }
+ t = $(t:J="&&") ;
+ result += $(condition)$(t:TG=$(p:G)) ;
+ }
+ else
+ {
+ result += $(condition)$(p) ;
+ }
+ }
+ return $(result) ;
+}
+
+# Class which maintains a property set -> string
+# mapping
+class property-map
+{
+ import numbers ;
+ import sequence ;
+ import errors : error ;
+
+ rule __init__ ( )
+ {
+ self.next-flag = 1 ;
+ }
+
+ # Associate 'value' with 'properties'
+ rule insert ( properties + : value )
+ {
+ self.all-flags += $(self.next-flag) ;
+ self.properties.$(self.next-flag) = $(properties) ;
+ self.value.$(self.next-flag) = $(value) ;
+
+ self.next-flag = [ numbers.increment $(self.next-flag) ] ;
+ }
+
+ # Return the value associated with 'properties'
+ # or any subset of it. If more than one
+ # subset has value assigned to it, return the
+ # value for the longest subset, if it's unique.
+ rule find ( properties + )
+ {
+ return [ find-replace $(properties) ] ;
+ }
+
+ # Find the value associated with 'properties'.
+ # If 'value' parameter is given, replaces the found value
+ # Returns the value that were stored originally.
+ rule find-replace ( properties + : value ? )
+ {
+ # First find all matches
+ local matches ;
+ local match-ranks ;
+ for local i in $(self.all-flags)
+ {
+ if $(self.properties.$(i)) in $(properties)
+ {
+ matches += $(i) ;
+ match-ranks += [ sequence.length
+ $(self.properties.$(i)) ] ;
+ }
+ }
+ local best = [ sequence.select-highest-ranked
+ $(matches) : $(match-ranks) ] ;
+ if $(best[2])
+ {
+ error "Ambiguous key" ;
+ }
+ local original = $(self.value.$(best)) ;
+ if $(value)
+ {
+ self.value.$(best) = $(value) ;
+ }
+ return $(original) ;
+ }
+}
+
+local rule __test__ ( )
+{
+ import errors : try catch ;
+ import feature ;
+ import feature : feature subfeature compose ;
+
+ # local rules must be explicitly re-imported
+ import property : path-order ;
+
+ feature.prepare-test property-test-temp ;
+
+ feature toolset : gcc : implicit symmetric ;
+ subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4
+ 3.0 3.0.1 3.0.2 : optional ;
+ feature define : : free ;
+ feature runtime-link : dynamic static : symmetric link-incompatible ;
+ feature optimization : on off ;
+ feature variant : debug release : implicit composite symmetric ;
+ feature rtti : on off : link-incompatible ;
+
+ compose <variant>debug : <define>_DEBUG <optimization>off ;
+ compose <variant>release : <define>NDEBUG <optimization>on ;
+
+ import assert ;
+ import "class" : new ;
+
+ validate <toolset>gcc <toolset>gcc-3.0.1 : $(test-space) ;
+
+ assert.true path-order $(test-space) debug <define>foo ;
+ assert.false path-order $(test-space) <define>foo debug ;
+ assert.true path-order $(test-space) gcc debug ;
+ assert.false path-order $(test-space) debug gcc ;
+ assert.true path-order $(test-space) <optimization>on <rtti>on ;
+ assert.false path-order $(test-space) <rtti>on <optimization>on ;
+
+ assert.result <toolset>gcc <rtti>off <define>FOO
+ : refine <toolset>gcc <rtti>off
+ : <define>FOO
+ : $(test-space)
+ ;
+
+ assert.result <toolset>gcc <optimization>on
+ : refine <toolset>gcc <optimization>off
+ : <optimization>on
+ : $(test-space)
+ ;
+
+ assert.result <toolset>gcc <rtti>off
+ : refine <toolset>gcc : <rtti>off : $(test-space)
+ ;
+
+ assert.result <toolset>gcc <rtti>off <rtti>off:<define>FOO
+ : refine <toolset>gcc : <rtti>off <rtti>off:<define>FOO
+ : $(test-space)
+ ;
+
+ assert.result <toolset>gcc:<define>foo <toolset>gcc:<define>bar
+ : refine <toolset>gcc:<define>foo : <toolset>gcc:<define>bar
+ : $(test-space)
+ ;
+
+ assert.result <define>MY_RELEASE
+ : evaluate-conditionals-in-context
+ <variant>release,<rtti>off:<define>MY_RELEASE
+ : <toolset>gcc <variant>release <rtti>off
+
+ ;
+
+ assert.result debug
+ : as-path <optimization>off <variant>debug
+ : $(test-space)
+ ;
+
+ assert.result gcc/debug/rtti-off
+ : as-path <toolset>gcc <optimization>off <rtti>off <variant>debug
+ : $(test-space)
+ ;
+
+ try ;
+ validate <feature>value : $(test-space) ;
+ catch "Invalid property '<feature>value': unknown feature 'feature'." ;
+
+ try ;
+ validate <rtti>default : $(test-space) ;
+ catch \"default\" is not a known value of feature <rtti> ;
+
+ validate <define>WHATEVER : $(test-space) ;
+
+ try ;
+ validate <rtti> : $(test-space) ;
+ catch "Invalid property '<rtti>': No value specified for feature 'rtti'." ;
+
+ try ;
+ validate value : $(test-space) ;
+ catch "value" is not a value of an implicit feature ;
+
+
+ assert.result <rtti>on
+ : remove free implicit : <toolset>gcc <define>foo <rtti>on : $(test-space) ;
+
+ assert.result <include>a
+ : select include : <include>a <toolset>gcc ;
+
+ assert.result <include>a
+ : select include bar : <include>a <toolset>gcc ;
+
+ assert.result <include>a <toolset>gcc
+ : select include <bar> <toolset> : <include>a <toolset>gcc ;
+
+ assert.result <toolset>kylix <include>a
+ : change <toolset>gcc <include>a : <toolset> kylix ;
+
+ pm = [ new property-map ] ;
+ $(pm).insert <toolset>gcc : o ;
+ $(pm).insert <toolset>gcc <os>NT : obj ;
+ $(pm).insert <toolset>gcc <os>CYGWIN : obj ;
+
+ assert.equal o
+ : [ $(pm).find <toolset>gcc ] ;
+
+ assert.equal obj
+ : [ $(pm).find <toolset>gcc <os>NT ] ;
+
+ try ;
+ $(pm).find <toolset>gcc <os>NT <os>CYGWIN ;
+ catch "Ambiguous key" ;
+
+ # Test ordinary properties
+ assert.result
+ : split-conditional <toolset>gcc
+ ;
+
+ # Test properties with ":"
+ assert.result
+ : split-conditional <define>FOO=A::B
+ ;
+
+ # Test conditional feature
+ assert.result <toolset>gcc,<toolset-gcc:version>3.0 <define>FOO
+ : split-conditional <toolset>gcc,<toolset-gcc:version>3.0:<define>FOO
+ ;
+
+ feature.finish-test property-test-temp ;
+}
+
Added: boost-jam/boost-build/branches/upstream/current/build/readme.txt
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/readme.txt 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/readme.txt 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+Development code for new build system. To run unit tests for jam code, execute:
+
+ bjam --debug --build-system=test
+
+Comprehensive tests require Python. See ../test/readme.txt
+
+
+
Added: boost-jam/boost-build/branches/upstream/current/build/scanner.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/scanner.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/scanner.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,147 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+# Implements scanners: objects that compute implicit dependencies for
+# files, such as includes in C++.
+#
+# Scanner has a regular expression used to find dependencies, some
+# data needed to interpret those dependencies (for example, include
+# paths), and a code which actually established needed relationship
+# between actual jam targets.
+#
+# Scanner objects are created by actions, when they try to actualize
+# virtual targets, passed to 'virtual-target.actualize' method and are
+# then associated with actual targets. It is possible to use
+# several scanners for a virtual-target. For example, a single source
+# might be used by to compile actions, with different include paths.
+# In this case, two different actual targets will be created, each
+# having scanner of its own.
+#
+# Typically, scanners are created from target type and action's
+# properties, using the rule 'get' in this module. Directly creating
+# scanners is not recommended, because it might create many equvivalent
+# but different instances, and lead in unneeded duplication of
+# actual targets. However, actions can also create scanners in a special
+# way, instead of relying on just target type.
+
+import "class" : new ;
+import property virtual-target ;
+
+# Base scanner class.
+class scanner
+{
+ rule __init__ ( )
+ {
+ }
+
+ # Returns a pattern to use for scanning
+ rule pattern ( )
+ {
+ error "method must be overriden" ;
+ }
+
+ # Establish necessary relationship between targets,
+ # given actual target beeing scanned, and a list of
+ # pattern matches in that file.
+ rule process ( target : matches * )
+ {
+ error "method must be overriden" ;
+ }
+}
+
+# Registers a new generator class, specifying a set of
+# properties relevant to this scanner. Ctor for that class
+# should have one parameter: list of properties.
+rule register ( scanner-class : relevant-properties * )
+{
+ .registered += $(scanner-class) ;
+ .relevant-properties.$(scanner-class) = $(relevant-properties) ;
+}
+
+# Common scanner class, which can be used when there's only one
+# kind of includes (unlike C, where "" and <> includes have different
+# search paths).
+class common-scanner : scanner
+{
+ import scanner ;
+ rule __init__ ( includes * )
+ {
+ scanner.__init__ ;
+ self.includes = $(includes) ;
+ }
+
+ rule process ( target : matches * : binding )
+ {
+ local target_path = [ NORMALIZE_PATH $(binding:D) ] ;
+
+ NOCARE $(matches) ;
+ INCLUDES $(target) : $(matches) ;
+ SEARCH on $(matches) = $(target_path) $(self.includes:G=) ;
+
+ scanner.propagate $(__name__) : $(matches) : $(target) ;
+ }
+}
+
+
+# Returns an instance of previously registered scanner,
+# with the specified properties.
+rule get ( scanner-class : properties * )
+{
+ if ! $(scanner-class) in $(.registered)
+ {
+ error "attempt to get unregisted scanner" ;
+ }
+ local r = [ property.select $(.relevant-properties.$(scanner-class)) :
+ $(properties) ] ;
+ if ! $(r)
+ {
+ r = "" ;
+ }
+ if ! $(scanner.$(scanner-class).$(r:J=-))
+ {
+ scanner.$(scanner-class).$(r:J=-) = [ new $(scanner-class) $(r) ] ;
+ }
+ return $(scanner.$(scanner-class).$(r:J=-)) ;
+}
+
+
+# Installs the specified scanner on actual target 'target'.
+rule install ( scanner : target
+ vtarget # virtual target from which 'target' was actualized
+)
+{
+ HDRSCAN on $(target) = [ $(scanner).pattern ] ;
+ SCANNER on $(target) = $(scanner) ;
+ HDRRULE on $(target) = scanner.hdrrule ;
+
+ # scanner reflects difference in properties affecting
+ # binding of 'target', which will be known when processing
+ # includes for it, will give information on how to
+ # interpret quoted includes.
+ HDRGRIST on $(target) = $(scanner) ;
+}
+
+# Propagate scanner setting from 'including-target' to 'targets'.
+rule propagate ( scanner : targets * : including-target )
+{
+ HDRSCAN on $(targets) = [ on $(including-target) return $(HDRSCAN) ] ;
+ SCANNER on $(targets) = $(scanner) ;
+ HDRRULE on $(targets) = scanner.hdrrule ;
+ HDRGRIST on $(targets) = [ on $(including-target) return $(HDRGRIST) ] ;
+}
+
+
+rule hdrrule ( target : matches * : binding )
+{
+ local scanner = [ on $(target) return $(SCANNER) ] ;
+ $(scanner).process $(target) : $(matches) : $(binding) ;
+}
+# hdrrule must be available at global scope so that it can be invoked
+# by header scanning
+IMPORT scanner : hdrrule : : scanner.hdrrule ;
+
+
+
+
Added: boost-jam/boost-build/branches/upstream/current/build/targets.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/targets.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/targets.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1280 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+
+# Supports 'abstract' targets, which are targets explicitly defined in Jamfile.
+#
+# Abstract targets are represented by classes derived from 'abstract-target' class.
+# The first abstract target is 'project-target', which is created for each
+# Jamfile, and can be obtained by the 'target' rule in the Jamfile's module.
+# (see project.jam).
+#
+# Project targets keep a list of 'main-target' instances.
+# A main target is what the user explicitly defines in a Jamfile. It is
+# possible to have several definitions for a main target, for example to have
+# different lists of sources for different platforms. So, main targets
+# keep a list of alternatives.
+#
+# Each alternative is an instance of 'abstract-target'. When a main target
+# subvariant is defined by some rule, that rule will decide what class to
+# use, create an instance of that class and add it to the list of alternatives
+# for the main target.
+#
+# Rules supplied by the build system will use only targets derived
+# from 'basic-target' class, which will provide some default behaviour.
+# There will be two classes derived from it, 'make-target', created by the
+# 'make' rule, and 'typed-target', created by rules such as 'exe' and 'dll'.
+
+#
+# +------------------------+
+# |abstract-target |
+# +========================+
+# |name |
+# |project |
+# | |
+# |generate(properties) = 0|
+# +-----------+------------+
+# |
+# ^
+# / \
+# +-+-+
+# |
+# |
+# +------------------------+------+------------------------------+
+# | | |
+# | | |
+# +----------+-----------+ +------+------+ +------+-------+
+# | project-target | | main-target | | basic-target |
+# +======================+ 1 * +=============+ alternatives +==============+
+# | generate(properties) |o-----------+ generate |<>------------->| generate |
+# | main-target | +-------------+ | construct = 0|
+# +----------------------+ +--------------+
+# |
+# ^
+# / \
+# +-+-+
+# |
+# |
+# ...--+----------------+------------------+----------------+---+
+# | | | |
+# | | | |
+# ... ---+-----+ +------+-------+ +------+------+ +--------+-----+
+# | | typed-target | | make-target | | stage-target |
+# . +==============+ +=============+ +==============+
+# . | construct | | construct | | construct |
+# +--------------+ +-------------+ +--------------+
+
+import "class" : new ;
+import sequence ;
+import regex ;
+import property ;
+import errors ;
+import common ;
+import property-set ;
+import project ;
+import feature ;
+import virtual-target ;
+import path ;
+import set ;
+import assert ;
+
+# Base class for all abstract targets.
+class abstract-target
+{
+ import project assert "class" errors ;
+
+ rule __init__ ( name # name of the target in Jamfile
+ : project-target # the project target to which this one belongs
+ )
+ {
+ assert.true class.is-a $(project-target) : project-target ;
+ # Note: it might seem that we don't need either name or project at all.
+ # However, there are places where we really need it. One example is error
+ # messages which should name problematic targets. Another is setting correct
+ # paths for sources and generated files.
+
+ self.name = $(name) ;
+ self.project = $(project-target) ;
+ self.location = [ errors.nearest-user-location ] ;
+ }
+
+ # Returns the name of this target.
+ rule name ( )
+ {
+ return $(self.name) ;
+ }
+
+ # Returns the project for this target.
+ rule project ( )
+ {
+ return $(self.project) ;
+ }
+
+ # Return the location where the target was declared
+ rule location ( )
+ {
+ return $(self.location) ;
+ }
+
+ # Returns a user-readable name for this target.
+ rule full-name ( )
+ {
+ local location = [ $(self.project).get location ] ;
+ return $(location)/$(self.name) ;
+ }
+
+ # Takes properties in split form ("<feature1>foo <feature2>bar").
+ # Generates virtual targets for this abstract target, using the specified properties,
+ # unless a different value of some feature is required by the target. The properties
+ # on returned virtual targets should be link-compatible with the requested ones.
+ #
+ # On success, returns:
+ # - a property-set with the usage requirements to be applied to dependents
+ # - a list of produced virtual targets, which may be empty.
+ #
+ # If 'properties' are empty, performs default build of this target, in a way specific
+ # to derived class.
+ rule generate ( property-set )
+ {
+ errors.error "method should be defined in derived classes" ;
+ }
+
+ rule rename ( new-name )
+ {
+ self.name = $(new-name) ;
+ }
+}
+
+# Project target class (derived from 'abstract-target')
+#
+# This class these responsibilities:
+# - maintaining a list of main target in this project and
+# building it
+#
+# Main targets are constructed in two stages:
+# - When Jamfile is read, a number of calls to 'add-alternative' is made.
+# At that time, alternatives can also be renamed to account for inline
+# targets.
+# - The first time 'main-target' or 'has-main-target' rule is called,
+# all alternatives are enumerated an main targets are created.
+class project-target : abstract-target
+{
+ import project targets ;
+ import path ;
+ import print ;
+ import property-set ;
+ import set : difference : set.difference ;
+ import sequence ;
+ import "class" : new ;
+ import errors ;
+
+ rule __init__ ( name : project-module : requirements * : default-build * )
+ {
+ abstract-target.__init__ $(name) : $(__name__) ;
+
+ self.project-module = $(project-module) ;
+ self.requirements = $(requirements) ;
+ self.default-build = $(default-build) ;
+ }
+
+ # This is needed only by the 'make' rule. Need to find the
+ # way to make 'make' work without this method.
+ rule project-module ( )
+ {
+ return $(self.project-module) ;
+ }
+
+ rule get ( attribute )
+ {
+ return [ project.attribute $(self.project-module) $(attribute) ] ;
+ }
+
+
+ # Generates all possible targets contained in this project.
+ rule generate ( property-set * )
+ {
+ local usage-requirements = [ property-set.empty ] ;
+ local targets ;
+
+ for local t in [ targets-to-build ]
+ {
+ local g = [ $(t).generate $(property-set) ] ;
+ usage-requirements = [ $(usage-requirements).add $(g[1]) ] ;
+ targets += $(g[2-]) ;
+ }
+ return $(usage-requirements) [ sequence.unique $(targets) ] ;
+ }
+
+ # Computes and returns a list of abstract-target instances which
+ # must be built when this project is built.
+ rule targets-to-build ( )
+ {
+ local result ;
+
+ if ! $(self.built-main-targets)
+ {
+ build-main-targets ;
+ }
+
+ # Collect all main targets here, except for "explicit" ones.
+ for local t in $(self.main-targets)
+ {
+ if ! [ $(t).name ] in $(self.explicit-targets)
+ {
+ result += $(t) ;
+ }
+ }
+
+ # Collect all projects referenced via "projects-to-build" attribute.
+ local self-location = [ get location ] ;
+ for local pn in [ get projects-to-build ]
+ {
+ local p = [ project.module-name [ path.join $(self-location) $(pn) ] ] ;
+ result += [ project.target $(p) ] ;
+ }
+
+ return $(result) ;
+ }
+
+ # Add 'target' to the list of targets in this project that should be build
+ # only by explicit request
+ rule mark-target-as-explicit ( target-name )
+ {
+ # Record the name of the target, not instance, since this
+ # rule is called before main target instaces are created.
+ self.explicit-targets += $(target-name) ;
+ }
+
+ # Add new target alternative
+ rule add-alternative ( target-instance )
+ {
+ if $(self.built-main-targets)
+ {
+ errors.error "add-alternative called when main targets are already created."
+ : "in project" [ full-name ] ;
+ }
+ self.alternatives += $(target-instance) ;
+ }
+
+
+ # Returns a 'main-target' class instance corresponding to the 'name'.
+ rule main-target ( name )
+ {
+ if ! $(self.built-main-targets)
+ {
+ build-main-targets ;
+ }
+
+ return $(self.main-target.$(name)) ;
+ }
+
+ # Tells if a main target with the specified name exists.
+ rule has-main-target ( name )
+ {
+ if ! $(self.built-main-targets)
+ {
+ build-main-targets ;
+ }
+
+ if $(self.main-target.$(name))
+ {
+ return true ;
+ }
+ }
+
+ rule build-main-targets ( )
+ {
+ self.built-main-targets = true ;
+ for local a in $(self.alternatives)
+ {
+ local name = [ $(a).name ] ;
+ local target = $(self.main-target.$(name)) ;
+ if ! $(target)
+ {
+ local t = [ new main-target $(name) : $(self.project) ] ;
+ self.main-target.$(name) = $(t) ;
+ self.main-targets += $(t) ;
+ target = $(self.main-target.$(name)) ;
+ }
+
+ $(target).add-alternative $(a) ;
+ }
+ }
+}
+
+
+# Helper rules to detect cycles in main target references
+local rule start-building ( main-target-instance )
+{
+ if $(main-target-instance) in $(.targets-being-built)
+ {
+ local names ;
+ for local t in $(.targets-being-built) $(main-target-instance)
+ {
+ names += [ $(t).full-name ] ;
+ }
+
+ errors.error "Recursion in main target references"
+ : "the following target are being built currently:"
+ : $(names) ;
+ }
+ .targets-being-built += $(main-target-instance) ;
+}
+
+local rule end-building ( main-target-instance )
+{
+ .targets-being-built = $(.targets-being-built[1--2]) ;
+}
+
+
+# A named top-level target in Jamfile
+class main-target : abstract-target
+{
+ import errors : error ;
+ import assert ;
+ import sequence ;
+ import print ;
+ import build-request feature property-set ;
+ import targets : start-building end-building ;
+ import "class" : is-a ;
+
+ rule __init__ ( name : project )
+ {
+ abstract-target.__init__ $(name) : $(project) ;
+ }
+
+
+ # Add a new alternative for this target
+ rule add-alternative ( target )
+ {
+ local d = [ $(target).default-build ] ;
+ if $(self.alternatives) && ( $(self.default-build) != $(d) )
+ {
+ errors.error "default build must be identical in all alternatives"
+ : "main target is" [ full-name ]
+ : "with" [ $(d).raw ]
+ : "differing from previous default build" [ $(self.default-build).raw ] ;
+ }
+ else
+ {
+ self.default-build = $(d) ;
+ }
+ self.alternatives += $(target) ;
+ }
+
+ # Returns the best viable alternative for this property-set
+ # See the documentation for selection rules.
+ local rule select-alternatives ( property-set )
+ {
+ # When selecting alternatives we have to consider defaults,
+ # for example:
+ # lib l : l.cpp : <variant>debug ;
+ # lib l : l_opt.cpp : <variant>release ;
+ # won't work unless we add default value <variant>debug.
+ property-set = [ $(p).add-defaults ] ;
+
+ # The algorithm: we keep the current best viable alternative.
+ # When we've got new best viable alternative, we compare it
+ # with the current one.
+
+ local best ;
+ local best-properties ;
+
+ if $(self.alternatives[2-])
+ {
+ local bad ;
+ local worklist = $(self.alternatives) ;
+ while $(worklist) && ! $(bad)
+ {
+ local v = $(worklist[1]) ;
+ local properties = [ $(v).match $(property-set) ] ;
+
+ if $(properties) != no-match
+ {
+ if ! $(best)
+ {
+ best = $(v) ;
+ best-properties = $(properties) ;
+ }
+ else
+ {
+ if $(properties) = $(best-properties)
+ {
+ bad = true ;
+ }
+ else if $(properties) in $(best-properties)
+ {
+ # Do nothing, this alternative is worse
+ }
+ else if $(best-properties) in $(properties)
+ {
+ best = $(v) ;
+ best-properties = $(properties) ;
+ }
+ else
+ {
+ bad = true ;
+ }
+ }
+ }
+ worklist = $(worklist[2-]) ;
+ }
+ if ! $(bad)
+ {
+ return $(best) ;
+ }
+ }
+ else
+ {
+ return $(self.alternatives) ;
+ }
+ }
+
+
+ rule apply-default-build ( property-set )
+ {
+ # 1. First, see what properties from default-build
+ # are already present in property-set.
+
+ local raw = [ $(property-set).raw ] ;
+ local specified-features = $(raw:G) ;
+
+ local defaults-to-apply ;
+ for local d in [ $(self.default-build).raw ]
+ {
+ if ! $(d:G) in $(specified-features)
+ {
+ defaults-to-apply += $(d) ;
+ }
+ }
+
+ # 2. If there's any defaults to be applied, form the new
+ # build request. Pass it throw 'expand-no-defaults', since
+ # default-build might contain "release debug", which will
+ # result in two property-sets.
+ local result ;
+ if $(defaults-to-apply)
+ {
+ properties = [
+ build-request.expand-no-defaults
+
+ # We have to compress subproperties here to prevent
+ # property lists like:
+ #
+ # <toolset>msvc <toolset-msvc:version>7.1 <threading>multi
+ #
+ # from being expanded into:
+ #
+ # <toolset-msvc:version>7.1/<threading>multi
+ # <toolset>msvc/<toolset-msvc:version>7.1/<threading>multi
+ #
+ # due to cross-product property combination. That may
+ # be an indication that
+ # build-request.expand-no-defaults is the wrong rule
+ # to use here.
+ [ feature.compress-subproperties $(raw) ]
+ $(defaults-to-apply)
+ ] ;
+
+ if $(properties)
+ {
+ for local p in $(properties)
+ {
+ result += [ property-set.create
+ [ feature.expand [ feature.split $(p) ] ] ] ;
+ }
+ }
+ else
+ {
+ result = [ property-set.empty ] ;
+ }
+
+ }
+ else
+ {
+ result = $(property-set) ;
+ }
+ return $(result) ;
+ }
+
+ # Select an alternative for this main target, by finding all alternatives
+ # which requirements are satisfied by 'properties' and picking the one with
+ # longest requirements set.
+ # Returns the result of calling 'generate' on that alternative.
+ rule generate ( property-set )
+ {
+ start-building $(__name__) ;
+
+ # We want composite properties in build request act as if
+ # all the properties it expands too are explicitly specified.
+ property-set = [ $(property-set).expand ] ;
+
+ local all-property-sets = [ apply-default-build $(property-set) ] ;
+ local usage-requirements = [ property-set.empty ] ;
+ local result ;
+ for local p in $(all-property-sets)
+ {
+ local r = [ generate-really $(p) ] ;
+ usage-requirements = [ $(usage-requirements).add $(r[1]) ] ;
+ result += $(r[2-]) ;
+ }
+ end-building $(__name__) ;
+ return $(usage-requirements) [ sequence.unique $(result) ] ;
+ }
+
+ # Generates the main target with the given property set
+ # and returns a list which first element is property-set object
+ # containing usage-requirements of generated target and with
+ # generated virtual target in other elements. It's possible
+ # that no targets are generated.
+ local rule generate-really ( property-set )
+ {
+ local best-alternatives = [ select-alternatives $(property-set) ] ;
+ if ! $(best-alternatives)
+ {
+ errors.error
+ "failed to build" [ full-name ]
+ "with properties" [ $(property-set).raw ]
+ "because no best-matching alternative could be found"
+ ;
+ return [ property-set.empty ] ;
+ }
+ else
+ {
+ local result = [ $(best-alternatives).generate $(property-set) ] ;
+
+ # Now return virtual targets for the only alternative
+ return $(result) ;
+ }
+ }
+
+ rule rename ( new-name )
+ {
+ abstract-target.rename $(new-name) ;
+ for local a in $(self.alternatives)
+ {
+ $(a).rename $(new-name) ;
+ }
+
+ }
+
+}
+
+# Abstract target which refers to a source file.
+# This is artificial creature; it's usefull so that sources to
+# a target can be represented as list of abstract target instances.
+class file-reference : abstract-target
+{
+ import virtual-target ;
+ import property-set ;
+ import path ;
+
+ rule __init__ ( file : project )
+ {
+ abstract-target.__init__ $(file) : $(project) ;
+ }
+
+ rule generate ( properties )
+ {
+ return [ property-set.empty ]
+ [ virtual-target.from-file $(self.name) : $(self.project) ] ;
+ }
+
+ # Returns true if the referred file really exists;
+ rule exists ( )
+ {
+ local location = [ path.root $(self.name)
+ [ $(self.project).get source-location ] ] ;
+ return [ path.exists [ path.native $(location) ] ] ;
+ }
+
+ # Returns the location of target. Needed by 'testing.jam'
+ rule location ( )
+ {
+ return [ path.root $(self.name)
+ [ $(self.project).get source-location ] ] ;
+ }
+}
+
+
+if "--quiet" in [ modules.peek : ARGV ]
+{
+ .quiet = true ;
+}
+
+
+rule find ( id : project )
+{
+ local current-location = [ $(project).get location ] ;
+ local target ;
+
+ local split = [ MATCH (.*)//(.*) : $(id) ] ;
+
+ local project-part = $(split[1]) ;
+ local target-part = $(split[2]) ;
+ if ! $(split)
+ {
+ 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 ;
+ if $(project-part)
+ {
+ local pm = [ project.find $(project-part) : $(current-location) ] ;
+ # If we can't find a project, it means project part is invalid.
+ # Don't assign any value to base-project, the below code will eventually
+ # return empty result.
+ if $(pm)
+ {
+ base-project = [ project.target $(pm) ] ;
+ }
+ }
+ else
+ {
+ # No project part in id. Resolve references relatively to the referring
+ # project.
+ base-project = $(project) ;
+ }
+
+
+ # 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) && $(base-project)
+ {
+ if [ $(base-project).has-main-target $(target-part) ]
+ {
+ target = [ $(base-project).main-target $(target-part) ] ;
+ }
+ }
+
+ if ! $(target) && ! $(have-project-reference)
+ {
+ target = [ new file-reference [ path.make $(target-part) ] : $(project) ] ;
+ if ! [ $(target).exists ]
+ {
+ # File actually does not exist.
+ # Reset 'target' so that an error is issued.
+ target = ;
+ }
+ }
+
+ if ! $(target)
+ {
+ ECHO "error: Unable to find file or target named" ;
+ ECHO "error: '$(id)'" ;
+ ECHO "error: referred from project at" ;
+ ECHO "error: '$(current-location)'" ;
+ EXIT ;
+
+
+ errors.error "Unable to resolve target-id $(id)" :
+ "Reference was made from project at '$(current-location)'" ;
+ }
+ return $(target) ;
+}
+
+# Given a target-reference, made in context of 'project',
+# returns the abstract-target instance that is referred to, as well
+# as properties explicitly specified for this reference.
+rule resolve-reference ( target-reference : project )
+{
+ # Separate target name from properties override
+ local split = [ MATCH "^([^<]*)(/(<.*))?$" : $(target-reference) ] ;
+ local id = $(split[1]) ;
+ local sproperties = ;
+ if $(split[3])
+ {
+ sproperties = [ property.make [ feature.split $(split[3]) ] ] ;
+ sproperties = [ feature.expand-composites $(sproperties) ] ;
+ }
+
+ # Find the target
+ local target =
+ [ find $(id) : $(project) ] ;
+
+ # Do a sanity check
+ if $(sproperties) && [ class.is-a $(target) : file-reference ]
+ {
+ errors.error
+ "error: target reference '$(target-reference)' contains properties," :
+ "error: but refers to a file" ;
+ }
+ return $(target) [ property-set.create $(sproperties) ] ;
+}
+
+
+
+# Attempts to generate the target given by target reference, which
+# can refer both to a main target or to a file.
+# Returns a list consisting of
+# - usage requirements
+# - generated virtual targets, if any
+rule generate-from-reference
+ ( target-reference # Target reference
+ : project # Project where the reference is made
+ : property-set # Properties of the main target that
+ # makes the reference
+ )
+{
+ local r = [ resolve-reference $(target-reference) : $(project) ] ;
+ local target = $(r[1]) ;
+ local sproperties = $(r[2]) ;
+
+ # Take properties which should be propagated and refine them
+ # with source-specific requirements.
+ local propagated = [ $(property-set).propagated ] ;
+ local rproperties = [ $(propagated).refine $(sproperties) ] ;
+ if $(rproperties[1]) = "@error"
+ {
+ errors.error
+ "When building" [ full-name ] " with properties " $(properties) :
+ "Invalid properties specified for " $(source) ":"
+ $(rproperties[2-]) ;
+ }
+ return [ $(target).generate $(rproperties) ] ;
+}
+
+# Given build request and requirements, return properties
+# common to dependency build request and target build
+# properties
+rule common-properties ( build-request requirements )
+{
+ # For optimization, we add free requirements directly,
+ # without using complex algorithsm.
+ # This gives the complex algorithm better chance of caching results.
+ local free = [ $(requirements).free ] ;
+ local non-free = [ property-set.create
+ [ $(requirements).base ] [ $(requirements).incidental ] ] ;
+
+ local key = .rp.$(build-request)-$(non-free) ;
+ if ! $($(key))
+ {
+ $(key) = [ common-properties2 $(build-request) $(non-free) ] ;
+ }
+ result = [ $($(key)).add-raw $(free) ] ;
+}
+
+rule common-properties2 ( build-request requirements )
+{
+ # This guarantees that default properties are present
+ # in result, unless they are overrided by some requirement.
+ # FIXME: There is possibility that we've added <foo>bar, which is composite
+ # and expands to <foo2>bar2, but default value of <foo2> is not bar2,
+ # in which case it's not clear what to do.
+ #
+ build-request = [ $(build-request).add-defaults ] ;
+ # Featured added by 'add-default' can be composite and expand
+ # to features without default values -- so they are not added yet.
+ # It could be clearer/faster to expand only newly added properties
+ # but that's not critical.
+ build-request = [ $(build-request).expand ] ;
+
+ # Apply non-conditional requirements.
+ # There's a slight bug here: it's possible that conditional
+ # requirement change a value set by non-conditional requirements. This
+ # should be error, but we don't detect it yet.
+ local raw = [ $(build-request).raw ] ;
+ raw = [ property.refine $(raw) :
+ [ feature.expand [ $(requirements).non-conditional ] ] ] ;
+
+ # We've collected properties that surely must be present in common
+ # properties. We now try to figure out what other properties
+ # should be added in order to satisfy rules (4)-(6) from the docs.
+
+ local conditionals = [ $(requirements).conditional ] ;
+ local count = $(conditionals) and-once-more ;
+ local prev ;
+
+ local current = $(raw) ;
+
+ local ok ;
+ while $(count)
+ {
+ # Evaluate conditionals in context of current properties
+ local e = [ property.evaluate-conditionals-in-context $(conditionals)
+ : $(current) ] ;
+ if $(e) = $(prev)
+ {
+ # If we got the same result, we've found final properties.
+ count = ;
+ ok = true ;
+ }
+ else
+ {
+ # Oops, results of evaluation of conditionals has changes
+ # Also 'current' contains leftover from previous evaluation.
+ # Recompute 'current' using initial properties and conditional
+ # requirements.
+ prev = $(e) ;
+ current = [ property.refine $(raw) : [ feature.expand $(e) ] ] ;
+ }
+ count = $(count[2-]) ;
+ }
+ if ! $(ok)
+ {
+ errors.error "Can't evaluate conditional properties " $(conditionals) ;
+ }
+
+
+ return [ property-set.create $(current) ] ;
+}
+
+# Implements the most standard way of constructing main target
+# alternative from sources. Allows sources to be either file or
+# other main target and handles generation of those dependency
+# targets.
+class basic-target : abstract-target
+{
+ import build-request ;
+ import virtual-target targets ;
+ import property-set ;
+ import set sequence errors ;
+ import "class" : new ;
+ import property feature ;
+
+ rule __init__ ( name : project
+ : sources * : requirements * :
+ default-build * : usage-requirements * )
+ {
+ abstract-target.__init__ $(name) : $(project) ;
+
+ self.sources = $(sources) ;
+ if ! $(requirements) {
+ requirements = [ property-set.empty ] ;
+ }
+ self.requirements = $(requirements) ;
+ if ! $(default-build)
+ {
+ default-build = [ property-set.empty ] ;
+ }
+ self.default-build = $(default-build) ;
+ if ! $(usage-requirements)
+ {
+ usage-requirements = [ property-set.empty ] ;
+ }
+ self.usage-requirements = $(usage-requirements) ;
+
+ if $(sources:G)
+ {
+ errors.error "gristed element in sources for" [ full-name ] ;
+ }
+ }
+
+ # Returns the list of abstract-targets which are used as sources.
+ # The extra properties specified for sources are not represented.
+ rule sources ( )
+ {
+ if ! $(self.source-targets) {
+ for local s in $(self.sources)
+ {
+ self.source-targets +=
+ [ targets.resolve-reference $(s) : $(self.project) ] ;
+ }
+ }
+ return $(self.source-targets) ;
+ }
+
+ rule requirements ( )
+ {
+ return $(self.requirements) ;
+ }
+
+ rule default-build ( )
+ {
+ return $(self.default-build) ;
+ }
+
+ # Returns the alternative condition for this alternative, if
+ # the condition is satisfied by 'property-set'.
+ rule match ( property-set )
+ {
+ # The condition is composed of all base non-conditional properties.
+ # It's not clear if we should expand 'self.requirements' or not.
+ # For one thing, it would be nice to be able to put
+ # <toolset>msvc-6.0
+ # in requirements.
+ # On the other hand, if we have <variant>release in condition it
+ # does not make sense to require <optimization>full to be in
+ # build request just to select this variant.
+ local bcondition = [ $(self.requirements).base ] ;
+ local ccondition = [ $(self.requirements).conditional ] ;
+ local condition = [ set.difference $(bcondition) : $(ccondition) ] ;
+ if $(condition) in [ $(property-set).raw ]
+ {
+ return $(condition) ;
+ }
+ else
+ {
+ return no-match ;
+ }
+ }
+
+ #
+ # Allows the user to tag the name of the target, according to properties.
+ #
+ rule tag-name ( name : property-set )
+ {
+ local properties = [ $(property-set).raw ] ;
+
+ local tagged-name = $(name) ;
+
+ if <tag> in $(properties:G)
+ {
+ local tags = [ $(property-set).get <tag> ] ;
+ for local tag in $(tags)
+ {
+ tagged-name = $(tagged-name)$(tag) ;
+ }
+ }
+
+ return $(tagged-name) ;
+ }
+
+ # Takes a target reference, which might be either target id
+ # or a dependency property, and generates that target using
+ # 'property-set' as build request.
+ #
+ # The results are added to to variable called 'result-var'.
+ # Usage requirements are added variable called 'usage-requirements-var'.
+ rule generate-dependencies ( dependencies * : property-set
+ : result-var usage-requirements-var )
+ {
+ for local dependency in $(dependencies)
+ {
+ local grist = $(dependency:G) ;
+ local id = $(dependency:G=) ;
+
+ local result =
+ [ targets.generate-from-reference $(id) : $(self.project)
+ : $(property-set) ] ;
+ check-for-link-compatibility $(result[2-]) : $(property-set) ;
+
+ $(result-var) += $(result[2-]:G=$(grist)) ;
+ $(usage-requirements-var) += [ $(result[1]).raw ] ;
+ }
+ }
+
+
+ # Determines final build properties, generates sources,
+ # and calls 'construct'. This method should not be
+ # overridden.
+ rule generate ( property-set )
+ {
+ if --debug-targets in [ modules.peek : ARGV ]
+ {
+ ECHO "Building $(self.name) with" [ $(property-set).raw ] ;
+ }
+
+ if ! $(self.generated.$(property-set))
+ {
+ local rproperties = [ targets.common-properties $(property-set)
+ $(self.requirements) ] ;
+
+ if $(rproperties[1]) != "@error"
+ {
+ local source-targets ;
+ local properties = [ $(rproperties).non-dependency ] ;
+ local usage-requirements ;
+
+ generate-dependencies [ $(rproperties).dependency ]
+ : $(rproperties)
+ : properties usage-requirements ;
+
+ generate-dependencies $(self.sources) : $(rproperties)
+ : source-targets usage-requirements ;
+
+ if --debug-targets in [ modules.peek : ARGV ]
+ {
+ ECHO "Usage requirements for $(self.name) are $(usage-requirements)" ;
+ }
+
+ rproperties = [ property-set.create $(properties)
+ $(usage-requirements) ] ;
+ usage-requirements = [ property-set.create $(usage-requirements) ] ;
+
+ local extra = [ $(rproperties).get <source> ] ;
+ source-targets += $(extra:G=) ;
+ # We might get duplicate sources, for example if
+ # we link to two library which have the same <library> in
+ # usage requirements.
+ source-targets = [ sequence.unique $(source-targets) ] ;
+
+ local tagged-name = [ tag-name $(self.name) : $(rproperties) ] ;
+
+ local original-name = $(self.name) ;
+ self.name = $(tagged-name) ;
+
+ local result =
+ [ construct $(source-targets) : $(rproperties) ] ;
+
+ local s = [ create-subvariant $(result) : $(property-set) : $(source-targets)
+ : $(rproperties) : $(usage-requirements) ] ;
+
+ local ur = [ compute-usage-requirements $(s) ] ;
+ $(s).set-usage-requirements $(ur) ;
+ self.generated.$(property-set) = $(ur) $(result) ;
+
+ self.name = $(original-name) ;
+ }
+ else
+ {
+ self.generated.$(property-set) = $(rproperties) ;
+ }
+ }
+ return $(self.generated.$(property-set)) ;
+ }
+
+ # Given the set of generated targets, and refined build
+ # properties, determines and sets appripriate usage requirements
+ # on those targets.
+ rule compute-usage-requirements ( subvariant )
+ {
+ local rproperties = [ $(subvariant).build-properties ] ;
+ xusage-requirements = [ $(self.usage-requirements).evaluate-conditionals
+ $(rproperties) ] ;
+
+ # We generate all dependency properties and add them,
+ # as well as their usage requirements, to result.
+ local extra ;
+ generate-dependencies [ $(xusage-requirements).dependency ] :
+ $(rproperties) : extra extra ;
+
+ local result = [ property-set.create
+ [ $(xusage-requirements).non-dependency ] $(extra) ] ;
+
+ return $(result) ;
+ }
+
+ # Creates a new subvariant-dg instances for 'targets'
+ local rule create-subvariant ( targets * : build-request : sources * :
+ rproperties
+ : usage-requirements )
+ {
+ for local e in $(targets)
+ {
+ $(e).root true ;
+ }
+
+ # Process all vtargets that will be created if this main target
+ # is created.
+ local all-targets =
+ [ sequence.transform virtual-target.traverse : $(targets) ] ;
+ local s = [ new subvariant $(__name__) : $(build-request) : $(sources)
+ : $(rproperties) : $(usage-requirements) : $(all-targets) ] ;
+ for local v in $(all-targets)
+ {
+ if ! [ $(v).creating-subvariant ]
+ {
+ $(v).creating-subvariant $(s) ;
+ }
+ }
+ return $(s) ;
+ }
+
+ # Checks if 'targets' are link-compatible with 'build-request' and
+ # issues a warning if that's not the case.
+ local rule check-for-link-compatibility ( targets * : build-request )
+ {
+ local checked ;
+ for local t in $(targets)
+ {
+ local a = [ $(t).action ] ;
+ if $(a)
+ {
+ local p = [ $(a).properties ] ;
+ if ! $(p) in $(cheched)
+ {
+ if [ $(p).link-incompatible-with $(build-request) ]
+ {
+ local s = [ $(t).creating-subvariant ] ;
+ local other-mt = [ $(s).main-target ] ;
+ ECHO "warning: targets produced from" [ $(other-mt).name ]
+ "are link incompatible" ;
+ ECHO "warning: with main target" [ name ] ;
+ }
+ }
+ checked += $(p) ;
+ }
+ }
+
+ }
+
+
+
+ # Constructs the virtual targets for this abstract targets and
+ # the dependecy graph. Returns the list of virtual targets.
+ # Should be overrided in derived classes.
+ rule construct ( source-targets * : properties * )
+ {
+ errors.error "method should be defined in derived classes" ;
+ }
+}
+
+class typed-target : basic-target
+{
+ import generators ;
+
+ rule __init__ ( name : project : type
+ : sources * : requirements * : default-build * : usage-requirements * )
+ {
+ basic-target.__init__ $(name) : $(project)
+ : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ;
+
+ self.type = $(type) ;
+ }
+
+ rule type ( )
+ {
+ return $(self.type) ;
+ }
+
+ rule construct ( source-targets * : property-set )
+ {
+ local r = [ generators.construct $(self.project) $(self.name) : $(self.type)
+ : [ property-set.create [ $(property-set).raw ] # [ feature.expand
+ <main-target-type>$(self.type) ]
+ # ]
+ : $(source-targets) ] ;
+ if ! $(r)
+ {
+ errors.error "unable to construct" [ full-name ] ;
+ }
+
+ return $(r) ;
+ }
+}
+
+# Return the list of sources to use, if main target rule is invoked
+# with 'sources'. If there are any objects in 'sources', they are treated
+# as main target instances, and WRITEME.
+rule main-target-sources ( sources * : main-target-name )
+{
+ local result ;
+ for local t in $(sources)
+ {
+ if [ class.is-instance $(t) ]
+ {
+ local name = [ $(t).name ] ;
+ # NOTE: on windows, this won't work if 'main-target-name'
+ # if single letter. But other alternatives are even worse.
+ local new-name = $(main-target-name)..$(name) ;
+ $(t).rename $(new-name) ;
+ #local p = [ $(t).project ] ;
+ #local pt = [ project.target $(p) ] ;
+ #$(pt).rename-main-target $(name) : $(new-name) ;
+ result += $(new-name) ;
+ }
+ else
+ {
+ result += $(t) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+# Returns the requirement to use when declaring a main target,
+# which are obtained by
+# - translating all specified property paths, and
+# - refining project requirements with the one specified for the target
+rule main-target-requirements (
+ specification * # Properties explicitly specified for a main target
+ : project # Project where the main target is to be declared
+ )
+{
+ local loc = [ $(project).get location ] ;
+ local requirements = [ property.translate-paths $(specification) : $(loc) ] ;
+ local requirements =
+ [ property.expand-subfeatures-in-conditions $(requirements) ] ;
+ local requirements = [ property-set.create $(requirements) ] ;
+ local project-requirements = [ $(project).get requirements ] ;
+ requirements = [ $(project-requirements).refine $(requirements) ] ;
+ if $(requirements[1]) = "@error"
+ {
+ errors.error "Conflicting requirements for target:" $(requirements) ;
+ }
+ return $(requirements) ;
+}
+
+# Returns the use requirement to use when declaraing a main target,
+# which are obtained by
+# - translating all specified property paths, and
+# - adding project's usage requirements
+rule main-target-usage-requirements (
+ specification * # Use-properties explicitly specified for a main target
+ : project # Project where the main target is to be declared
+ )
+{
+ local loc = [ $(project).get location ] ;
+ local project-usage-requirements = [ $(project).get usage-requirements ] ;
+
+ local usage-requirements = [ property-set.create
+ [ property.translate-paths $(specification) : $(loc) ] ] ;
+
+ return [ $(project-usage-requirements).add $(usage-requirements) ] ;
+}
+
+# Return the default build value to use when declaring a main target,
+# which is obtained by using specified value if not empty and parent's
+# default build attribute otherwise.
+rule main-target-default-build (
+ specification * # Default build explicitly specified for a main target
+ : project # Project where the main target is to be declared
+ )
+{
+ local result ;
+ if $(specification)
+ {
+ result = $(specification) ;
+ }
+ else
+ {
+ result = [ $(project).get default-build ] ;
+ }
+ return [ property-set.create-with-validation $(result) ] ;
+}
+
+# Registers the specified target as a main target alternatives.
+# Returns 'target'.
+rule main-target-alternative ( target )
+{
+ local ptarget = [ $(target).project ] ;
+
+ $(ptarget).add-alternative $(target) ;
+ return $(target) ;
+}
+
+# Creates a typed-target with the specified properties.
+# The 'name', 'sources', 'requirements', 'default-build' and
+# 'usage-requirements' are assumed to be in the form specified
+# by the user in Jamfile corresponding to 'project'.
+rule create-typed-target ( type : project :
+ name : sources * : requirements * : default-build *
+ : usage-requirements * )
+{
+ return [
+ targets.main-target-alternative
+ [ new typed-target $(name) : $(project) : $(type)
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
+ ] ] ;
+
+}
Added: boost-jam/boost-build/branches/upstream/current/build/toolset.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/toolset.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/toolset.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,349 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+# Support for toolset definition.
+
+import feature ;
+import numbers ;
+import errors : error ;
+import property ;
+import path ;
+import generators ;
+import set : difference ;
+import regex ;
+import sequence ;
+
+.flag-no = 1 ;
+
+# Initializes an additional toolset-like module.
+# First load 'toolset-module' and then calls its 'init'
+# rule with trailing arguments
+rule using ( toolset-module : * )
+{
+ import $(toolset-module) ;
+ if ! $(.$(toolset-module)-init-callled)
+ {
+ $(toolset-module)-init-callled = true ;
+ $(toolset-module).init $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+}
+
+# Expands subfeatures in each property sets.
+# e.g
+# <toolset>gcc-3.2
+# will be converted to
+# <toolset>gcc/<toolset-version>3.2
+local rule normalize-condition ( property-sets * )
+{
+ local result ;
+ for local p in $(property-sets)
+ {
+ local split = [ feature.split $(p) ] ;
+ local expanded = [ feature.expand-subfeatures [ feature.split $(p) ] ] ;
+ result += $(expanded:J=/) ;
+ }
+ return $(result) ;
+}
+
+
+# Specifies the flags (variables) that must be set on targets under certain
+# conditions, described by arguments.
+rule flags ( rule-or-module # If contains dot, should be a rule name.
+ # The flags will be applied when that rule is
+ # used to set up build actions.
+ #
+ # If does not contain dot, should be a module name.
+ # The flags will be applied for all rules in that
+ # module.
+ # If module for rule is different from the calling
+ # module, an error is issued.
+
+ variable-name # Variable that should be set on target
+ condition * : # A condition when this flag should be applied.
+ # Should be set of property sets. If one of
+ # those property sets is contained in build
+ # properties, the flag will be used.
+ # Implied values are not allowed:
+ # "<toolset>gcc" should be used, not just
+ # "gcc". Subfeatures, like in "<toolset>gcc-3.2"
+ # are allowed. If left empty, the flag will
+ # always used.
+
+
+ values * : # The value to add to variable. If <feature>
+ # is specified, then the value of 'feature'
+ # will be added.
+ unchecked ? # If value 'unchecked' is passed, will not test
+ # that flags are set for the calling module.
+ )
+{
+ local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ;
+ local caller = [ CALLER_MODULE ] ;
+ if $(unchecked) != unchecked && $(module_) != $(caller)
+ {
+ errors.error "Module $(caller) attempted to set flags for module $(module_)" ;
+ }
+
+ if $(condition) && ! $(condition:G=)
+ {
+ # We have condition in the form '<feature>', that is, without
+ # value. That's a previous syntax:
+ #
+ # flags gcc.link RPATH <dll-path> ;
+ # for compatibility, convert it to
+ # flags gcc.link RPATH : <dll-path> ;
+ values = $(condition) ;
+ condition = ;
+ }
+
+ if $(condition)
+ {
+ property.validate-property-sets $(condition) ;
+ condition = [ normalize-condition $(condition) ] ;
+ }
+
+ add-flag $(rule-or-module) : $(variable-name)
+ : $(condition) : $(values) ;
+}
+
+# Adds new flag setting with the specified values
+# Does no checking
+local rule add-flag ( rule-or-module :
+ variable-name : condition * : values * )
+{
+ .$(rule-or-module).flags += $(.flag-no) ;
+
+ # Store all flags for a module
+ local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ;
+ .module-flags.$(module_) += $(.flag-no) ;
+ # Store flag-no -> rule-or-module mapping
+ .rule-or-module.$(.flag-no) = $(rule-or-module) ;
+
+ .$(rule-or-module).variable.$(.flag-no) += $(variable-name) ;
+ .$(rule-or-module).values.$(.flag-no) += $(values) ;
+ .$(rule-or-module).condition.$(.flag-no) += $(condition) ;
+
+ .flag-no = [ numbers.increment $(.flag-no) ] ;
+}
+
+
+# Returns the first element of 'property-sets' which is a subset of
+# 'properties', or an empty list if no such element exists.
+local rule find-property-subset ( property-sets * : properties * )
+{
+ local result ;
+ for local s in $(property-sets)
+ {
+ if ! $(result)
+ {
+ if [ feature.split $(s) ] in $(properties)
+ {
+ result = $(s) ;
+ }
+ }
+ }
+ return $(result) ;
+}
+
+rule handle-flag-value ( value * : properties * )
+{
+ local result ;
+ if $(value:G)
+ {
+ local matches = [ property.select $(value) : $(properties) ] ;
+ for local p in $(matches)
+ {
+ local att = [ feature.attributes $(p:G) ] ;
+ if dependency in $(att)
+ {
+ # the value of a dependency feature is a target
+ # and must be actualized
+ result += [ $(p:G=).actualize ] ;
+ }
+ else if path in $(att) || free in $(att)
+ {
+ local values ;
+ # Treat features with && in the value
+ # specially -- each &&-separated element is considered
+ # separate value. This is needed to handle searched
+ # libraries, which must be in specific order.
+ if ! [ MATCH (&&) : $(p:G=) ]
+ {
+ values = $(p:G=) ;
+ }
+ else
+ {
+ values = [ regex.split $(p:G=) "&&" ] ;
+ }
+ if path in $(att)
+ {
+ result += [ sequence.transform path.native : $(values) ] ;
+ }
+ else
+ {
+ result += $(values) ;
+ }
+ }
+ else
+ {
+ result += $(p:G=) ;
+ }
+ }
+ }
+ else
+ {
+ result += $(values) ;
+ }
+ return $(result) ;
+}
+
+
+rule set-target-variables ( rule-or-module targets + : properties * )
+{
+ for local f in $(.$(rule-or-module).flags)
+ {
+ local variable = $(.$(rule-or-module).variable.$(f)) ;
+ local condition = $(.$(rule-or-module).condition.$(f)) ;
+ local values = $(.$(rule-or-module).values.$(f)) ;
+ local result ;
+
+ if ! $(condition) ||
+ [ find-property-subset $(condition) : $(properties) ]
+ {
+ result += [ handle-flag-value $(values) : $(properties) ] ;
+ }
+
+ # Without this test, the assignment below would create a
+ # target variable even if $(result) is empty. That is
+ # undesirable because the empty target variable would mask
+ # module globals intended to be used as defaults.
+ if $(result)-is-nonempty
+ {
+ $(variable) on $(targets) += $(result) ;
+ }
+ }
+
+ # strip away last dot separated part and recurse.
+ local next = [ MATCH ^(.+)\\.([^\\.])* : $(rule-or-module) ] ;
+ if $(next)
+ {
+ set-target-variables $(next) $(targets) : $(properties) ;
+ }
+}
+
+.toolsets += $(toolset) ;
+
+# Registers a new toolset
+rule register ( toolset )
+{
+ feature.extend toolset : $(toolset) ;
+ .toolsets += $(toolset) ;
+}
+
+# Make toolset 'toolset', defined in a module of the same name,
+# inherit from 'base'
+# 1. The 'init' rule from 'base' is imported into 'toolset' with full
+# name. Another 'init' is called, which forwards to the base one.
+# 2. All generators from 'base' are cloned. The ids are adjusted and
+# <toolset> property in requires is adjusted too
+# 3. All flags are inherited
+# 4. All rules are imported.
+rule inherit ( toolset : base )
+{
+ import $(base) ;
+
+ inherit-generators $(toolset) : $(base) ;
+ inherit-flags $(toolset) : $(base) ;
+ inherit-rules $(toolset) : $(base) ;
+}
+
+rule inherit-generators ( toolset properties * : base : generators-to-ignore * )
+{
+ properties ?= <toolset>$(toolset) ;
+ local base-generators = [ generators.generators-for-toolset $(base) ] ;
+ for local g in $(base-generators)
+ {
+ local id = [ $(g).id ] ;
+
+ if ! $(id) in $(generators-to-ignore)
+ {
+ # Some generator names have multiple periods in their name, so
+ # $(id:B=$(toolset)) doesn't generate the right new-id name.
+ # e.g. if id = gcc.compile.c++, $(id:B=darwin) = darwin.c++,
+ # which is not what we want. Manually parse the base and suffix
+ # (if there's a better way to do this, I'd love to see it.)
+ # See also register in module generators.
+ local base = $(id) ;
+ local suffix = "" ;
+ while $(base:S)
+ {
+ suffix = $(base:S)$(suffix) ;
+ base = $(base:B) ;
+ }
+ local new-id = $(toolset)$(suffix) ;
+
+ generators.register [ $(g).clone $(new-id) : $(properties) ] ;
+ }
+ }
+}
+
+# properties listed in prohibited-properties won't
+# be inherited. Note that <debug-symbols>on and
+# <debug-symbols>off are two different properties
+rule inherit-flags ( toolset : base : prohibited-properties * )
+{
+ for local f in $(.module-flags.$(base))
+ {
+ local rule-or-module = $(.rule-or-module.$(f)) ;
+ if [ set.difference
+ $(.$(rule-or-module).condition.$(f)) :
+ $(prohibited-properties)
+ ] || ! $(.$(rule-or-module).condition.$(f))
+ {
+ local rule_ = [ MATCH "[^.]*\.(.*)" : $(rule-or-module) ] ;
+ local new-rule-or-module ;
+ if $(rule_)
+ {
+ new-rule-or-module = $(toolset).$(rule_) ;
+ }
+ else
+ {
+ new-rule-or-module = $(toolset) ;
+ }
+
+ add-flag
+ $(new-rule-or-module)
+ : $(.$(rule-or-module).variable.$(f))
+ : $(.$(rule-or-module).condition.$(f))
+ : $(.$(rule-or-module).values.$(f))
+ ;
+ }
+ }
+}
+
+rule inherit-rules ( toolset : base )
+{
+ # It appears that "action" creates local rule...
+ local base-generators = [ generators.generators-for-toolset $(base) ] ;
+ local rules ;
+ for local g in $(base-generators)
+ {
+ local id = [ MATCH "[^.]*\.(.*)" : [ $(g).id ] ] ;
+ rules += $(id) ;
+ }
+ IMPORT $(base) : $(rules) : $(toolset) : $(rules) : localized ;
+ # Import the rules to the global scope
+ IMPORT $(toolset) : $(rules) : : $(toolset).$(rules) ;
+}
+
+
+
+local rule __test__ ( )
+{
+ import assert ;
+ local p = <b>0 <c>1 <d>2 <e>3 <f>4 ;
+ assert.result <c>1/<d>2/<e>3 : find-property-subset <c>1/<d>2/<e>3 <a>0/<b>0/<c>1 <d>2/<e>5 <a>9 : $(p) ;
+ assert.result : find-property-subset <a>0/<b>0/<c>9/<d>9/<e>5 <a>9 : $(p) ;
+}
Added: boost-jam/boost-build/branches/upstream/current/build/type.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/type.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/type.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,294 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+# Deals with target type declaration and defines target class which supports
+# typed targets.
+
+import feature ;
+import generators : * ;
+import "class" : new ;
+import errors ;
+import property ;
+import scanner ;
+import project ;
+
+# This creates a circular dependency
+# project-test1 -> project -> project-root -> builtin -> type -> targets -> project
+# import targets ;
+
+# The feature is optional so that it never implicitly added.
+# It's used only for internal purposes, and in all cases we
+# want to explicitly use it.
+feature.feature target-type : : composite optional ;
+
+# feature.feature base-target-type : : composite optional ;
+feature.feature main-target-type : : optional incidental ;
+feature.feature base-target-type : : composite optional free ;
+# feature.feature main-target-type : : composite optional incidental ;
+
+# Store suffixes for generated targets
+.suffixes = [ new property-map ] ;
+
+# Registers a target type, possible derived from a 'base-type'.
+# If 'suffixes' are provided, they given all the suffixes that mean a file is of 'type'.
+# Also, the first element gives the suffix to be used when constructing and object of
+# 'type'.
+# If 'main' is given, a rule with the same name as the target type
+# and signature
+# rule target-type ( name : sources * : requirements * : default-build )
+# will be added to the global scope.
+rule register ( type : suffixes * : base-type ? : main ? )
+{
+ # Type names cannot contain hyphens, because when used as
+ # feature-values they will be interpreted as composite features
+ # which need to be decomposed.
+ switch $(type)
+ {
+ case *-* : errors.error "type name \"$(type)\" contains a hyphen" ;
+ }
+
+ if $(type) in $(.types)
+ {
+ errors.error "Type $(type) is already registered." ;
+ }
+ else
+ {
+ .types += $(type) ;
+ .bases.$(type) = $(base-type) ;
+
+ if $(suffixes)-not-empty
+ {
+ # Generated targets of 'type' will use the first of 'suffixes'
+ # (this may be overriden)
+ $(.suffixes).insert <target-type>$(type) : $(suffixes[1]) ;
+ # Specify mapping from suffixes to type
+ register-suffixes $(suffixes) : $(type) ;
+ }
+
+ feature.extend target-type : $(type) ;
+ feature.extend main-target-type : $(type) ;
+
+ feature.compose <target-type>$(type) : $(base-type:G=<base-target-type>) ;
+ feature.extend base-target-type : $(type) ;
+# feature.compose <target-type>$(type) : <base-target-type>$(type) ;
+ feature.compose <base-target-type>$(type) : <base-target-type>$(base-type) ;
+
+ if $(main)
+ {
+ main-rule-name = [ type-to-rule-name $(type) ] ;
+ .main-target-type.$(main-rule-name) = $(type) ;
+
+ IMPORT $(__name__) : main-target-rule : : $(main-rule-name) ;
+# feature.compose <main-target-type>$(type) : <base-target-type>$(type) ;
+ }
+ }
+}
+
+# Given type, returns name of main target rule which creates
+# targets of that type.
+rule type-to-rule-name ( type )
+{
+ # Lowercase everything. Convert underscores to dashes.ame.
+ import regex ;
+ local n = [ regex.split $(type:L) "_" ] ;
+ n = $(n:J=-) ;
+ return $(n) ;
+}
+
+# Returns a type, given the name of a main rule.
+rule type-from-rule-name ( main-target-name )
+{
+ return $(.main-target-type.$(main-target-name)) ;
+}
+
+
+
+# Specifies that targets with suffix from 'suffixes' has the type 'type'.
+# If different type is already specified for any of syffixes,
+# issues an error.
+rule register-suffixes ( suffixes + : type )
+{
+ for local s in $(suffixes)
+ {
+ if ! $(.type.$(s))
+ {
+ .type.$(s) = $(type) ;
+ }
+ else if $(.type.$(s)) != type
+ {
+ errors.error Attempting to specify type for suffix \"$(s)\"
+ : "Old type $(.type.$(s)), New type $(type)" ;
+ }
+ }
+}
+
+
+# Returns true iff type has been registered.
+rule registered ( type )
+{
+ if $(type) in $(.types)
+ {
+ return true ;
+ }
+}
+
+# Issues an error if 'type' is unknown.
+rule validate ( type )
+{
+ if ! $(type) in $(.types)
+ {
+ errors.error "Unknown target type $(type)" ;
+ }
+}
+
+
+# Sets a scanner class that will be used for this 'type'.
+rule set-scanner ( type : scanner )
+{
+ if ! $(type) in $(.types)
+ {
+ error "Type" $(type) "is not declared" ;
+ }
+ .scanner.$(type) = $(scanner) ;
+}
+
+# Returns a scanner instance appropriate to 'type' and 'properties'.
+rule get-scanner ( type : properties * )
+{
+ if $(.scanner.$(type)) {
+ return [ scanner.get $(.scanner.$(type)) : $(properties) ] ;
+ }
+}
+
+# returns type and all of its bases in order of their distance from type.
+rule all-bases ( type )
+{
+ local result = $(type) ;
+ while $(type)
+ {
+ type = $(.bases.$(type)) ;
+ result += $(type) ;
+ }
+ return $(result) ;
+}
+
+# Returns true if 'type' has 'base' as its direct or
+# indirect base.
+rule is-derived ( type base )
+{
+ if $(base) in [ all-bases $(type) ]
+ {
+ return true ;
+ }
+}
+
+# Returns true if 'type' is either derived from 'base',
+# or 'type' is equal to 'base'.
+rule is-subtype ( type base )
+{
+ if $(type) = $(base)
+ {
+ return true ;
+ }
+ else
+ {
+ return [ is-derived $(type) $(base) ] ;
+ }
+}
+
+
+# Sets a target suffix that should be used when generating target
+# of 'type' with the specified properties. Can be called with
+# empty properties if no suffix for 'type' was specified yet.
+# This does not automatically specify that files 'suffix' have
+# 'type' --- two different types can use the same suffix for
+# generating, but only one type should be auto-detected for
+# a file with that suffix. User should explicitly specify which
+# one.
+#
+# The 'suffix' parameter can be empty string ("") to indicate that
+# no suffix should be used.
+rule set-generated-target-suffix ( type : properties * : suffix )
+{
+ properties = <target-type>$(type) $(properties) ;
+ $(.suffixes).insert $(properties) : $(suffix) ;
+}
+
+# Change the suffix previously registered for this type/properties
+# combination. If suffix is not yet specified, sets it.
+rule change-generated-target-suffix ( type : properties * : suffix )
+{
+ properties = <target-type>$(type) $(properties) ;
+ local prev = [ $(.suffixes).find-replace $(properties) : $(suffix) ] ;
+ if ! $(prev)
+ {
+ set-generated-target-suffix $(type) : $(properties) : $(suffix) ;
+ }
+}
+
+
+# Returns suffix that should be used when generating target of 'type',
+# with the specified properties. If not suffix were specified for
+# 'type', returns suffix for base type, if any.
+rule generated-target-suffix ( type : properties * )
+{
+ local result ;
+ local found ;
+ while $(type) && ! $(found)
+ {
+ result = [ $(.suffixes).find <target-type>$(type) $(properties) ] ;
+ # If the suffix is explicitly set to empty string, we consider suffix
+ # to be found. If we did not compare with "", there would be no
+ # way for user to set empty suffix.
+ if $(result)-is-not-empty
+ {
+ found = true ;
+ }
+ type = $(.bases.$(type)) ;
+ }
+ if $(result) = ""
+ {
+ result = ;
+ }
+ return $(result) ;
+}
+
+# Returns file type given it's name. If there are several dots in filename,
+# tries each suffix. E.g. for name of "file.so.1.2" suffixes "2", "1", and
+# "so" will be tried.
+rule type ( filename )
+{
+ local type ;
+ while ! $(type) && $(filename:S)
+ {
+ local suffix = $(filename:S) ;
+ type = $(.type$(suffix)) ;
+ filename = $(filename:S=) ;
+ }
+ return $(type) ;
+}
+
+
+
+rule main-target-rule ( name : sources * : requirements * : default-build *
+ : usage-requirements * )
+{
+ # First find required target type, which is equal to the name used
+ # to invoke us.
+ local bt = [ BACKTRACE 1 ] ;
+ local rulename = $(bt[4]) ;
+
+ # This rule may be only called from Jamfile, and therefore,
+ # CALLER_MODULE is Jamfile module, which is used to denote
+ # a project.
+ local project = [ project.current ] ;
+
+ # This is a circular module dependency, so it must be imported here
+ import targets ;
+ return [ targets.create-typed-target $(.main-target-type.$(rulename)) : $(project)
+ : $(name) : $(sources) : $(requirements)
+ : $(default-build) : $(usage-requirements) ] ;
+}
+
Added: boost-jam/boost-build/branches/upstream/current/build/version.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/version.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/version.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,21 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+rule boost-build ( )
+{
+ return "V2 (Milestone 10)" ;
+}
+rule jam ( )
+{
+ local v = [ modules.peek : JAM_VERSION ] ;
+ return $(v:J=.) ;
+}
+
+
+rule print ( )
+{
+ ECHO "Boost.Build" [ boost-build ] ;
+ ECHO "Boost.Jam" [ jam ] ;
+}
Added: boost-jam/boost-build/branches/upstream/current/build/virtual-target.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build/virtual-target.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build/virtual-target.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1177 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+# Implements virtual targets, which correspond to actual files created during
+# build, but are not yet targets in Jam sense. They are needed, for example,
+# when searching for possible transormation sequences, when it's not known
+# if particular target should be created at all.
+
+import "class" : new ;
+import path property-set utility sequence errors set ;
+
+# +--------------------------+
+# | virtual-target |
+# +==========================+
+# | actualize |
+# +--------------------------+
+# | actualize-action() = 0 |
+# | actualize-location() = 0 |
+# +----------------+---------+
+# |
+# ^
+# / \
+# +-+-+
+# |
+# +---------------------+ +-------+--------------+
+# | action | | abstract-file-target |
+# +=====================| * +======================+
+# | action-name | +--+ action |
+# | properties | | +----------------------+
+# +---------------------+--+ | actualize-action() |
+# | actualize() |0..1 +-----------+----------+
+# | path() | |
+# | adjust-properties() | sources |
+# | actualize-sources() | targets |
+# +------+--------------+ ^
+# | / \
+# ^ +-+-+
+# / \ |
+# +-+-+ +-------------+-------------+
+# | | |
+# | +------+---------------+ +--------+-------------+
+# | | file-target | | searched-lib-target |
+# | +======================+ +======================+
+# | | actualize-location() | | actualize-location() |
+# | +----------------------+ +----------------------+
+# |
+# +-+------------------------------+
+# | |
+# +----+----------------+ +---------+-----------+
+# | compile-action | | link-action |
+# +=====================+ +=====================+
+# | adjust-properties() | | adjust-properties() |
+# +---------------------+ | actualize-sources() |
+# +---------------------+
+#
+# The 'compile-action' and 'link-action' classes are defined not here,
+# but in builtin.jam modules. They are shown in the diagram to give
+# the big picture.
+
+# Potential target. It can be converted into jam target and used in
+# building, if needed. However, it can be also dropped, which allows
+# to search for different transformation and select only one.
+#
+class virtual-target
+{
+ import virtual-target utility scanner ;
+
+ rule __init__ ( name # Name of this target -- specifies the name of
+ : project # Project to which this target belongs
+ )
+ {
+ self.name = $(name) ;
+ self.project = $(project) ;
+ self.dependencies = ;
+ }
+
+ # Name of this target.
+ rule name ( ) { return $(self.name) ; }
+
+ # Project of this target.
+ rule project ( ) { return $(self.project) ; }
+
+ # Adds additional instances of 'virtual-target' that this
+ # one depends on.
+ rule depends ( d + )
+ {
+ self.dependencies = [ sequence.merge $(self.dependencies)
+ : [ sequence.insertion-sort $(d) ] ] ;
+ }
+
+ rule dependencies ( )
+ {
+ return $(self.dependencies) ;
+ }
+
+ # Generates all the actual targets and sets up build actions for
+ # this target.
+ #
+ # If 'scanner' is specified, creates an additional target
+ # with the same location as actual target, which will depend on the
+ # actual target and be associated with 'scanner'. That additional
+ # target is returned. See the docs (#dependency_scanning) for rationale.
+ # Target must correspond to a file if 'scanner' is specified.
+ #
+ # If scanner is not specified, then actual target is returned.
+ rule actualize ( scanner ? )
+ {
+ local actual-name = [ actualize-no-scanner ] ;
+
+ if ! $(scanner)
+ {
+ return $(actual-name) ;
+ }
+ else
+ {
+ # Add the scanner instance to the grist for name.
+ local g = [ sequence.join
+ [ utility.ungrist $(actual-name:G) ] $(scanner) : - ] ;
+ local name = $(actual-name:G=$(g)) ;
+
+ if ! $(self.made.$(name)) {
+ self.made.$(name) = true ;
+
+ DEPENDS $(name) : $(actual-name) ;
+
+ actualize-location $(name) ;
+
+ scanner.install $(scanner) : $(name) $(__name__) ;
+ }
+ return $(name) ;
+ }
+
+ }
+
+# private: (overridables)
+
+ # Sets up build actions for 'target'. Should call appropriate rules
+ # and set target variables.
+ rule actualize-action ( target )
+ {
+ errors.error "method should be defined in derived classes" ;
+ }
+
+ # Sets up variables on 'target' which specify its location.
+ rule actualize-location ( target )
+ {
+ errors.error "method should be defined in derived classes" ;
+ }
+
+ # If the target is generated one, returns the path where it will be
+ # generated. Otherwise, returns empty list.
+ rule path ( )
+ {
+ errors.error "method should be defined in derived classes" ;
+ }
+
+ # Return that actual target name that should be used
+ # (for the case where no scanner is involved)
+ rule actual-name ( )
+ {
+ errors.error "method should be defined in derived classes" ;
+ }
+
+# implementation
+ rule actualize-no-scanner ( )
+ {
+ local name = [ actual-name ] ;
+
+ # Do anything only on the first invocation
+ if ! $(self.made.$(name)) {
+ self.made.$(name) = true ;
+
+ virtual-target.register-actual-name $(name) : $(__name__) ;
+
+ for local i in $(self.dependencies) {
+ DEPENDS $(name) : [ $(i).actualize ] ;
+ }
+
+ actualize-location $(name) ;
+ actualize-action $(name) ;
+ }
+ return $(name) ;
+ }
+
+
+}
+
+
+# Target which correspond to a file. The exact mapping for file
+# is not yet specified in this class. (TODO: Actually, the class name
+# could be better...)
+#
+# May be a source file (when no action is specified), or
+# derived file (otherwise).
+#
+# The target's grist is concatenation of project's location,
+# properties of action (for derived files), and, optionally,
+# value identifying the main target.
+class abstract-file-target : virtual-target
+{
+ import project regex sequence path type ;
+
+ rule __init__ ( name
+ : type ? # Optional type for this target
+ : project
+ )
+ {
+ virtual-target.__init__ $(name) : $(project) ;
+
+ self.type = $(type) ;
+ self.action = ;
+ }
+
+ rule type ( ) { return $(self.type) ; }
+ rule set-type ( type )
+ {
+ self.type = $(type) ;
+ }
+
+ # Sets the suffix. When generating target name, it will be used in preference to
+ # the suffix that is associated with 'type'
+ rule suffix ( suffix ? )
+ {
+ if $(suffix)
+ {
+ self.suffix = $(suffix) ;
+ }
+ return $(self.suffix) ;
+ }
+
+ # Sets the path. When generating target name, it will override any path
+ # computation from properties.
+ rule set-path ( path )
+ {
+ self.path = [ path.native $(path) ] ;
+ }
+
+ # If 'a' is supplied, sets action to 'a'.
+ # Returns the action currently set.
+ rule action ( a ? )
+ {
+ if $(a)
+ {
+ self.action = $(a) ;
+ }
+ return $(self.action) ;
+ }
+
+ # Sets/gets the 'root' flag. Target is root is it directly correspods to some
+ # variant of a main target.
+ rule root ( set ? )
+ {
+ if $(set)
+ {
+ self.root = true ;
+ }
+ return $(self.root) ;
+ }
+
+ rule set-intermediate ( value ? )
+ {
+ self.intermediate = $(value) ;
+ }
+
+ rule intermediate ( )
+ {
+ return $(self.intermediate) ;
+ }
+
+
+
+ # Gets or sets the subvariant which created this target. Subvariant
+ # is set when target is brought into existance, and is never changed
+ # after that. In particual, if target is shared by subvariant, only
+ # the first is stored.
+ rule creating-subvariant ( s ? # If specified, specified the value to set,
+ # which should be instance of 'subvariant'
+ # class.
+ )
+ {
+ if $(s) && ( ! $(self.creating-subvariant) && ! $(overwrite) )
+ {
+ if $(self.creating-subvariant)
+ {
+ errors.error "Attempt to change 'dg'" ;
+ }
+ else
+ {
+ self.creatin-subvariant = $(s) ;
+ }
+ }
+ return $(self.creatin-subvariant) ;
+ }
+
+ rule actualize-action ( target )
+ {
+ if $(self.action)
+ {
+ $(self.action).actualize ;
+ }
+ }
+
+ # Return a human-readable representation of this target
+ #
+ # If this target has an action, that's:
+ #
+ # { <action-name>-<self.name>.<self.type> <action-sources>... }
+ #
+ # otherwise, it's:
+ #
+ # { <self.name>.<self.type> }
+ #
+ rule str ( )
+ {
+ local action = [ action ] ;
+
+ local name-dot-type = [ sequence.join $(self.name) "." $(self.type) ] ;
+
+ if $(action)
+ {
+ local sources = [ $(action).sources ] ;
+
+ local action-name = [ $(action).action-name ] ;
+
+ local ss ;
+ for local s in $(sources)
+ {
+ ss += [ $(s).str ] ;
+ }
+
+ return "{" $(action-name)-$(name-dot-type) $(ss) "}" ;
+ }
+ else
+ {
+ return "{" $(name-dot-type) "}" ;
+ }
+ }
+
+ rule less ( a )
+ {
+ if [ str ] < [ $(a).str ]
+ {
+ return true ;
+ }
+ }
+
+ rule equal ( a )
+ {
+ if [ str ] = [ $(a).str ]
+ {
+ return true ;
+ }
+ }
+
+# private:
+ rule actual-name ( )
+ {
+ if ! $(self.actual-name)
+ {
+ local grist = [ grist ] ;
+
+ local basename = [ actual-basename ] ;
+ self.actual-name = <$(grist)>$(basename) ;
+
+ }
+ return $(self.actual-name) ;
+ }
+
+ # Helper to 'actual-name', above. Compute unique prefix used to distinguish
+ # this target from other targets with the same name which create different
+ # file.
+ rule grist ( )
+ {
+ # Depending on target, there may be different approaches to generating
+ # unique prefixes. We'll generate prefixes in the form
+ # <one letter approach code> <the actual prefix>
+ local path = [ path ] ;
+ if $(path)
+ {
+ # The target will be generated to a know path. Just use the path
+ # for identification, since path is as unique as it can get.
+ return p$(path) ;
+ }
+ else
+ {
+ # File is either source, which will be searched for, or is not a file at
+ # all. Use the location of project for distinguishing.
+ local project-location = [ $(self.project).get location ] ;
+ local location-grist =
+ [ sequence.join [ regex.split $(project-location) "/" ] : "!" ] ;
+
+ if $(self.action)
+ {
+ local ps = [ $(self.action).properties ] ;
+ local property-grist = [ $(ps).as-path ] ;
+ location-grist = $(location-grist)/$(property-grist) ;
+ }
+
+ return l$(location-grist) ;
+ }
+ }
+
+ # Helper to actual-name, above. Compute the 'basename' of the filename
+ # of the actual created file.
+ rule actual-basename ( )
+ {
+ local name = [ path.native $(self.name) ] ;
+ if $(self.suffix)
+ {
+ name = $(name).$(self.suffix) ;
+ }
+ else if $(self.type)
+ {
+ local properties ;
+ if $(self.action)
+ {
+ local ps = [ $(self.action).properties ] ;
+ properties = [ $(ps).raw ] ;
+ }
+ local suffix = [ type.generated-target-suffix $(self.type) :
+ $(properties) ] ;
+ if $(suffix)
+ {
+ name = $(name).$(suffix) ;
+ }
+ }
+ return $(name) ;
+ }
+
+
+}
+
+# File target with explicitly known location.
+#
+# The file path is determined as
+# - value passed to the 'set-path' method, if any
+# - for derived files, project's build dir, joined with components
+# that describe action's properties. If the free properties
+# are not equal to the project's reference properties
+# an element with name of main target is added.
+# - for source files, project's source dir
+#
+# The file suffix is
+# - the value passed to the 'suffix' method, if any, or
+# - the suffix which correspond to the target's type.
+#
+class file-target : abstract-file-target
+{
+ import common ;
+ import errors ;
+
+ rule __init__ (
+ name
+ : type ? # Optional type for this target
+ : project
+ )
+ {
+ abstract-file-target.__init__ $(name) : $(type) : $(project) ;
+ }
+
+ rule actualize-location ( target )
+ {
+ if $(self.action)
+ {
+ # This is a derived file.
+ local path = [ path ] ;
+ LOCATE on $(target) = $(path) ;
+
+ # Make sure the path exists.
+ DEPENDS $(target) : $(path) ;
+ common.MkDir $(path) ;
+ }
+ else
+ {
+ # This is a source file.
+ SEARCH on $(target) =
+ [ path.native [ $(self.project).get source-location ] ] ;
+ }
+ }
+
+ # Returns the directory for this target
+ rule path ( )
+ {
+ if ! $(self.path)
+ {
+ if $(self.action)
+ {
+ local build-dir = [ $(self.project).get build-dir ] ;
+ if ! $(build-dir)
+ {
+ build-dir = [ path.join
+ [ $(self.project).get location ]
+ bin
+ ] ;
+ }
+
+ local path = [ path.join
+ $(build-dir)
+ [ $(self.action).path ]
+ ] ;
+
+ # Store the computed path, so that it's not recomputed
+ # any more
+ self.path = [ path.native $(path) ] ;
+ }
+ }
+ return $(self.path) ;
+ }
+
+}
+
+class notfile-target : abstract-file-target
+{
+ rule __init__ ( name : project )
+ {
+ abstract-file-target.__init__ $(name) : : $(project) ;
+ }
+
+
+ rule actualize-location ( target )
+ {
+ NOTFILE $(target) ;
+ ALWAYS $(target) ;
+ }
+}
+
+# Class which represents an action.
+# Both 'targets' and 'sources' should list instances of 'virtual-target'.
+# Action name should name a rule with this prototype
+# rule action-name ( targets + : sources * : properties * )
+# Targets and sources are passed as actual jam targets. The rule may
+# not establish dependency relationship, but should do everything else.
+class action
+{
+ import type toolset property-set indirect class path ;
+
+ rule __init__ ( targets + : sources * : action-name + : property-set ? )
+ {
+ self.targets = $(targets) ;
+ self.sources = $(sources) ;
+
+ self.action-name = [ indirect.make-qualified $(action-name) ] ;
+
+ if ! $(property-set)
+ {
+ property-set = [ property-set.empty ] ;
+ }
+
+ if ! [ class.is-instance $(property-set) ]
+ {
+ errors.error "Property set instance required" ;
+ }
+
+ self.properties = $(property-set) ;
+ }
+
+ rule targets ( )
+ {
+ return $(self.targets) ;
+ }
+
+ rule sources ( )
+ {
+ return $(self.sources) ;
+ }
+
+ rule action-name ( )
+ {
+ return $(self.action-name) ;
+ }
+
+ rule properties ( )
+ {
+ return $(self.properties) ;
+ }
+
+ # Generates actual build instructions.
+ rule actualize ( )
+ {
+ if ! $(self.actualized)
+ {
+ self.actualized = true ;
+
+ local ps = [ properties ] ;
+ local properties = [ adjust-properties [ $(ps).raw ] ] ;
+
+
+ local actual-targets ;
+ for local i in [ targets ]
+ {
+ actual-targets += [ $(i).actualize ] ;
+ }
+
+ actualize-sources [ sources ] ;
+
+ DEPENDS $(actual-targets) : $(self.actual-sources) $(self.dependency-only-sources) ;
+
+ # Action name can include additional argument to rule, which should not
+ # be passed to 'set-target-variables'
+ toolset.set-target-variables
+ [ indirect.get-rule $(self.action-name[1]) ] $(actual-targets)
+ : $(properties) ;
+
+ indirect.call $(self.action-name)
+ $(actual-targets) : $(self.actual-sources) : $(properties)
+ ;
+
+ # Since we set up creating action here, we also set up
+ # action for cleaning up
+ common.Clean clean : $(actual-targets) ;
+ }
+ }
+
+ # Helper for 'actualize-sources'.
+ # For each passed source, actualizes it with the appropriate scanner.
+ # Returns the actualized virtual targets.
+ rule actualize-source-type ( sources * )
+ {
+ local result = ;
+ for local i in $(sources)
+ {
+ local scanner ;
+ if [ $(i).type ]
+ {
+ scanner =
+ [ type.get-scanner [ $(i).type ] : $(properties) ] ;
+ }
+ result += [ $(i).actualize $(scanner) ] ;
+ }
+
+ return $(result) ;
+ }
+
+ # Creates actual jam targets for sources. Initialized two member
+ # variables:.
+ # 'self.actual-sources' -- sources which are passed to updating action
+ # 'self.dependency-only-sources' -- sources which are made dependencies, but
+ # are not used otherwise.
+ #
+ # New values will be *appended* to the variables. They may be non-empty,
+ # if caller wants it.
+ rule actualize-sources ( sources * )
+ {
+ local dependencies = [ $(self.properties).get <dependency> ] ;
+
+ self.dependency-only-sources += [ actualize-source-type $(dependencies) ] ;
+ self.actual-sources += [ actualize-source-type $(sources) ] ;
+ }
+
+ rule path ( )
+ {
+ local p = [ $(self.properties).as-path ] ;
+ # Really, an ugly hack. Boost regression test system requires
+ # specific target paths, and it seems that changing it to handle
+ # other directory layout is really hard. For that reason,
+ # we teach V2 to do the things regression system requires.
+ # The value o '<location-prefix>' is predended to the path.
+ local prefix = [ $(self.properties).get <location-prefix> ] ;
+ if $(prefix)
+ {
+ p = [ path.join $(prefix) $(p) ] ;
+ }
+ return $(p) ;
+ }
+
+ # Determined real properties when trying building with 'properties'.
+ # This is last chance to fix properties, for example to adjust includes
+ # to get generated headers correctly. Default implementation returns
+ # its argument.
+ rule adjust-properties ( properties * )
+ {
+ return $(properties) ;
+ }
+
+
+ rule set-targets ( targets * )
+ {
+ self.targets = $(targets) ;
+ }
+}
+
+# Action class which does nothing --- it produces the targets with
+# specific properties out of nowhere. It's needed to distinguish virtual
+# targets with different properties that are known to exist, and have no
+# actions which create them.
+class null-action : action
+{
+ rule __init__ ( targets + : property-set ? )
+ {
+ action.__init__ $(targets) : : .no-action : $(property-set) ;
+ }
+
+ rule actualize ( )
+ {
+ if ! $(self.actualized)
+ {
+ self.actualized = true ;
+
+ for local i in [ targets ]
+ {
+ $(i).actualize ;
+ }
+ }
+ }
+}
+
+
+# Creates a virtual target with approariate name and type from 'file'.
+# If a target with that name in that project was already created, returns that already
+# created target.
+# FIXME: more correct way would be to compute path to the file, based on name and source location
+# for the project, and use that path to determine if the target was already created.
+# TODO: passing project with all virtual targets starts to be annoying.
+rule from-file ( file : project )
+{
+ import type ; # had to do this here to break a circular dependency
+
+ # Check if we've created a target corresponding to this file.
+ local source-location = [ $(project).get source-location ] ;
+ local path = [ path.root [ path.root [ path.make $(file) ] $(source-location) ]
+ [ path.pwd ] ] ;
+
+ if $(.files.$(path))
+ {
+ return $(.files.$(path)) ;
+ }
+ else
+ {
+ local name = [ path.make $(file:S=) ] ;
+ local type = [ type.type $(file) ] ;
+ local result ;
+ if ! $(type)
+ {
+ # warning "cannot determine type for file $(file)" ;
+ result = [ new file-target $(file) : : $(project) ] ;
+ }
+ else
+ {
+ local v = [ new file-target $(name) : $(type) : $(project) ] ;
+ $(v).suffix [ MATCH ^.(.*)$ : $(file:S) ] ;
+ result = $(v) ;
+ }
+ .files.$(path) = $(result) ;
+ return $(result) ;
+ }
+}
+
+# Registers a new virtual target. Checks if there's already registered target, with the same
+# name, type, project and subvariant properties, and also with the same sources
+# and equal action. If such target is found it is retured and 'target' is not registers.
+# Otherwise, 'target' is registered and returned.
+rule register ( target )
+{
+ local signature = [ sequence.join
+ [ $(target).actual-name ] : - ] ;
+
+ local result ;
+ for local t in $(.cache.$(signature))
+ {
+ local a1 = [ $(t).action ] ;
+ local a2 = [ $(target).action ] ;
+
+ if ! $(result)
+ {
+ if ! $(a1) && ! $(a2)
+ {
+ result = $(t) ;
+ }
+ else
+ {
+ if $(a1) && $(a2) && [ $(a1).action-name ] = [ $(a2).action-name ] &&
+ [ $(a1).sources ] = [ $(a2).sources ]
+ {
+ local ps1 = [ $(a1).properties ] ;
+ local ps2 = [ $(a2).properties ] ;
+ local p1 = [ $(ps1).base ] [ $(ps1).free ] [ $(ps1).dependency ] ;
+ local p2 = [ $(ps2).base ] [ $(ps2).free ] [ $(ps2).dependency ] ;
+ if $(p1) = $(p2)
+ {
+ result = $(t) ;
+ }
+ }
+ }
+ }
+ }
+
+ if ! $(result)
+ {
+ .cache.$(signature) += $(target) ;
+ result = $(target) ;
+ }
+
+ return $(result) ;
+}
+
+rule register-actual-name ( actual-name : virtual-target )
+{
+ if $(.actual.$(actual-name))
+ {
+ local cs1 = [ $(.actual.$(actual-name)).creating-subvariant ] ;
+ local cs2 = [ $(virtual-target).creating-subvariant ] ;
+ local cmt1 = [ $(cs1).main-target ] ;
+ local cmt2 = [ $(cs2).main-target ] ;
+
+
+ local action1 = [ $(.actual.$(actual-name)).action ] ;
+ local action2 = [ $(virtual-target).action ] ;
+ local properties-added ;
+ local properties-removed ;
+ if $(action1) && $(action2)
+ {
+ local p1 = [ $(action1).properties ] ;
+ p1 = [ $(p1).raw ] ;
+ local p2 = [ $(action2).properties ] ;
+ p2 = [ $(p2).raw ] ;
+ properties-removed = [ set.difference $(p1) : $(p2) ] ;
+ properties-removed ?= "none" ;
+ properties-added = [ set.difference $(p2) : $(p1) ] ;
+ properties-added ?= "none" ;
+ }
+ errors.error "Duplicate name of actual target:" $(actual-name)
+ : "previous virtual target" [ $(.actual.$(actual-name)).str ]
+ : "created from" [ $(cmt1).location ]
+ : "another virtual target" [ $(virtual-target).str ]
+ : "created from" [ $(cmt2).location ]
+ : "added properties: " $(properties-added)
+ : "removed properties: " $(properties-removed) ;
+ }
+ else
+ {
+ .actual.$(actual-name) = $(virtual-target) ;
+ }
+}
+
+
+# Traverses the dependency graph of 'target' and return all targets that will
+# be created before this one is created. If root of some dependency graph is
+# found during traversal, it's either included or not, dependencing of the
+# value of 'include-roots'. In either case, sources of root are not traversed.
+rule traverse ( target : include-roots ? : include-sources ? )
+{
+ local result ;
+ if [ $(target).action ]
+ {
+ local action = [ $(target).action ] ;
+ # This includes 'target' as well
+ result += [ $(action).targets ] ;
+
+ for local t in [ $(action).sources ]
+ {
+ if ! [ $(t).root ]
+ {
+ result += [ traverse $(t) : $(include-roots) : $(include-sources) ] ;
+ }
+ else if $(include-roots)
+ {
+ result += $(t) ;
+ }
+ }
+ }
+ else if $(include-sources)
+ {
+ result = $(target) ;
+ }
+ return $(result) ;
+}
+
+# Takes an 'action' instances and creates new instance of it
+# and all produced target. The rule-name and properties are set
+# to 'new-rule-name' and 'new-properties', if those are specified.
+# Returns the cloned action.
+rule clone-action ( action : new-project : new-action-name ? : new-properties ? )
+{
+ if ! $(new-action-name)
+ {
+ new-action-name = [ $(action).action-name ] ;
+ }
+ if ! $(new-properties)
+ {
+ new-properties = [ $(action).properties ] ;
+ }
+
+ local cloned-targets ;
+ for local target in [ $(action).targets ]
+ {
+ local n = [ $(target).name ] ;
+ local cloned-target = [ class.new file-target $(n:D=) : [ $(target).type ]
+ : $(new-project) ] ;
+ local d = [ $(target).dependencies ] ;
+ if $(d)
+ {
+ $(cloned-target).depends $(d) ;
+ }
+ $(cloned-target).root [ $(target).root ] ;
+ $(cloned-target).creating-subvariant [ $(target).creating-subvariant ] ;
+
+ cloned-targets += $(cloned-target) ;
+ }
+
+ local action-class = [ modules.peek $(action) : __class__ ] ;
+
+ local cloned-action = [ class.new $(action-class) $(cloned-targets) :
+ [ $(action).sources ] : $(new-action-name) : $(new-properties) ] ;
+
+ for local cloned-target in $(cloned-targets)
+ {
+ $(cloned-target).action $(cloned-action) ;
+ }
+
+
+ return $(cloned-action) ;
+}
+
+
+
+
+# Clones a dependency graph template, given one of its root,
+# and a new source target to instantinate the template with.
+#
+# If 'target's name is "%" and type is equal to 'new-source's
+# return 'new-source', otherwise created a new target:
+# - if there "%" in target's name, its replaced with 'new-target's
+# - project for new target is the same as for 'new-target'
+# - other attributes are copied
+#
+# If 'dont-recurse' is not set, clones action, which results in
+# cloning of other targets, and, ultimately, cloning of the
+# entire dependency graph.
+#
+# The 'new-project' parameter tells what project should be assigned
+# for newly created non-source targets.
+rule clone-template ( target dont-recurse ? : new-source : new-project : dont-register ? )
+{
+ local name = [ $(new-source).name ] ;
+ local old-name = [ $(target).name ] ;
+ local new-name = $(old-name) ;
+ local m = [ MATCH (.*)(%)(.*) : $(old-name) ] ;
+ if $(m)
+ {
+ if [ $(target).action ]
+ {
+ new-name = [ sequence.join $(m[1]) $(name:D=) $(m[3]) ] ;
+ }
+ else
+ {
+ new-name = [ sequence.join $(m[1]) $(name) $(m[3]) ] ;
+ }
+ }
+
+ if $(old-name) = % && [ $(target).type ] = [ $(new-source).type ]
+ {
+ return $(new-source) ;
+ }
+ else
+ {
+ local cloned = [ new file-target $(new-name) : [ $(target).type ] :
+ $(new-project) ] ;
+ $(cloned).set-intermediate [ $(target).intermediate ] ;
+
+ if ! $(dont-recurse) && [ $(target).action ]
+ {
+ local cloned-action = [ clone-action-template
+ [ $(target).action ] $(target) $(cloned) : $(new-source) : $(new-project) ] ;
+
+ cloned-targets = $(cloned) ;
+ for t in [ $(cloned-action).targets ]
+ {
+ if $(t) != $(target)
+ {
+ cloned-targets +=
+ [ clone-template $(t) dont-recurse : $(new-source) : $(new-project)
+ # We don't want to pass new targets vis 'register' util we've
+ # finished building them -- i.e. until we assign the action.
+ # It might seem registering this not-yet ready target is
+ # harmless, but in fact the 'register' logic expects than
+ # registered target is never changed later.
+ : dont-register ] ;
+ }
+ }
+ local cloned-targets2 ;
+ for local t in $(cloned-targets)
+ {
+ $(t).action $(cloned-action) ;
+
+ cloned-targets2 += [ register $(t) ] ;
+
+ }
+
+ $(cloned-action).set-targets $(cloned-targets2) ;
+ cloned = $(cloned-targets2[1]) ;
+ }
+ else
+ {
+ if ! $(dont-register)
+ {
+ cloned = [ register $(cloned) ] ;
+ }
+ }
+ return $(cloned) ;
+ }
+}
+
+# Clones an action template: helper for clone-template above.
+local rule clone-action-template ( action from cloned-from : new-source : new-project )
+{
+ local targets ;
+ local sources ;
+
+ for local t in [ $(action).sources ]
+ {
+ sources += [ clone-template $(t) : $(new-source) : $(new-project) ] ;
+ }
+
+ local action-class = [ modules.peek $(action) : __class__ ] ;
+
+ local ps = [ $(action).properties ] ;
+ local cloned = [ new $(action-class) [ $(action).targets ] : $(sources)
+ : [ $(action).action-name ] : $(ps) ] ;
+
+ return $(cloned) ;
+}
+
+class subvariant
+{
+ import sequence ;
+ import type ;
+
+ rule __init__ ( main-target # The instance of main-target class
+ : property-set # Properties requested for this target
+ : sources *
+ : build-properties # Actually used properties
+ : sources-usage-requirements # Properties propagated from sources
+ : created-targets * ) # Top-level created targets
+ {
+ self.main-target = $(main-target) ;
+ self.properties = $(property-set) ;
+ self.sources = $(sources) ;
+ self.build-properties = $(build-properties) ;
+ self.sources-usage-requirements = $(sources-usage-requirements) ;
+ self.created-targets = $(created-targets) ;
+
+ # Pre-compose the list of other dependency graphs, on which this one
+ # depends
+ local deps = [ $(build-properties).get <implicit-dependency> ] ;
+ for local d in $(deps)
+ {
+ self.other-dg += [ $(d:G=).creating-subvariant ] ;
+ }
+
+ self.other-dg = [ sequence.unique $(self.other-dg) ] ;
+ }
+
+
+ rule main-target ( )
+ {
+ return $(self.main-target) ;
+ }
+
+ rule created-targets ( )
+ {
+ return $(self.created-targets) ;
+ }
+
+ rule requested-properties ( )
+ {
+ return $(self.properties) ;
+ }
+
+ rule build-properties ( )
+ {
+ return $(self.build-properties) ;
+ }
+
+ rule sources-usage-requirements ( )
+ {
+ return $(self.sources-usage-requirements) ;
+ }
+
+ rule set-usage-requirements ( usage-requirements )
+ {
+ self.usage-requirements = $(usage-requirements) ;
+ }
+
+ rule usage-requirements ( )
+ {
+ return $(self.usage-requirements) ;
+ }
+
+ # Returns all targets referenced by this subvariant,
+ # either directly or indirectly, and
+ # either as sources, or as dependency properties.
+ rule all-referenced-targets ( )
+ {
+ # Find directly referenced targets.
+ local deps = [ $(self.build-properties).dependency ] ;
+ local all-targets = $(self.sources) $(deps:G=) ;
+
+ # Find other subvariants.
+ local r ;
+ for local t in $(all-targets)
+ {
+ r += [ $(t).creating-subvariant ] ;
+ }
+ r = [ sequence.unique $(r) ] ;
+ for local s in $(r)
+ {
+ if $(s) != $(__name__)
+ {
+ all-targets += [ $(s).all-referenced-targets ] ;
+ }
+ }
+ return $(all-targets) ;
+ }
+
+ # Returns the properties which specify implicit include paths to
+ # generated headers. This traverses all targets in this subvariant,
+ # and subvariants referred by <implcit-dependecy>properties.
+ # For all targets which are of type 'target-type' (or for all targets,
+ # if 'target-type' is not specified), the result will contain
+ # <$(feature)>path-to-that-target.
+ rule implicit-includes ( feature : target-type ? )
+ {
+ local key = ii$(feature)-$(target-type:E="") ;
+ if ! $($(key))-is-nonempty
+ {
+ local target-paths = [ all-target-directories $(target-type) ] ;
+ target-paths = [ sequence.unique $(target-paths) ] ;
+ local result = $(target-paths:G=$(feature)) ;
+ if ! $(result)
+ {
+ result = "" ;
+ }
+ $(key) = $(result) ;
+ }
+ if $($(key)) = ""
+ {
+ return ;
+ }
+ else
+ {
+ return $($(key)) ;
+ }
+ }
+
+ rule all-target-directories ( target-type ? )
+ {
+ if ! $(self.target-directories)
+ {
+ compute-target-directories $(target-type) ;
+ }
+ return $(self.target-directories) ;
+ }
+
+ rule compute-target-directories ( target-type ? )
+ {
+ local result ;
+ for local t in $(self.created-targets)
+ {
+ if $(target-type) && ! [ type.is-derived [ $(t).type ] $(target-type) ]
+ {
+ # Skip target which is of wrong type.
+ }
+ else
+ {
+ result = [ sequence.merge $(result) : [ $(t).path ] ] ;
+ }
+ }
+ for local d in $(self.other-dg)
+ {
+ result += [ $(d).all-target-directories $(target-type) ] ;
+ }
+ self.target-directories = $(result) ;
+ }
+}
+
Added: boost-jam/boost-build/branches/upstream/current/build-system.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/build-system.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/build-system.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,184 @@
+# (C) Copyright David Abrahams 2001-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.
+
+# This file is part of Boost.Build version 2. You can think of it as
+# forming the main() routine. It is invoked by the bootstrapping code
+# in bootstrap.jam.
+#
+# The version of bootstrap.jam invoking this lives in
+# tools/build/kernel until BBv1 is retired, so that BBv1 can have its
+# bootstrap.jam in this directory.
+
+import project ;
+import targets ;
+import sequence ;
+import modules ;
+import feature ;
+import property-set ;
+import build-request ;
+import errors : error ;
+import project-roots ;
+import "class" : new ;
+
+import builtin ;
+import make ;
+import os ;
+
+import version ;
+
+# Check if we can load 'test-config.jam'. If we can, load it and
+# ignore user configs.
+local test-config = [ GLOB [ modules.peek : BOOST_BUILD_PATH ] : test-config.jam ] ;
+if $(test-config)
+{
+ import test-config ;
+}
+
+if ! $(test-config) && ! --ignore-config in [ modules.peek : ARGV ]
+{
+ module site-config
+ {
+ import toolset : using ;
+ }
+
+ module user-config
+ {
+ import toolset : using ;
+ }
+
+ local user-path = [ modules.peek : HOME ] [ modules.peek : BOOST_BUILD_PATH ] ;
+ if [ os.name ] in NT CYGWIN
+ {
+ modules.load site-config : : [ modules.peek : SystemRoot ] $(user-path) ;
+ modules.load user-config : : $(user-path) ;
+ }
+ else
+ {
+ modules.load site-config : : /etc $(user-path) ;
+ modules.load user-config : : $(user-path) ;
+ }
+}
+
+
+if --version in [ modules.peek : ARGV ]
+{
+ version.print ;
+ EXIT ;
+}
+
+# We always load project in "." so that 'use-project' directives has
+# any chance of been seen. Otherwise, we won't be able to refer to
+# subprojects using target ids.
+current-project = [ project.target [ project.load "." ] ] ;
+
+if [ MATCH (--dump-projects) : [ modules.peek : ARGV ] ]
+{
+ project-roots.print ;
+}
+
+if ! [ feature.values <toolset> ]
+{
+ ECHO "warning: no toolsets are configured." ;
+ ECHO "warning: you won't be able to build C++ programs." ;
+ ECHO "warning: please consult the documentation." ;
+ ECHO ;
+}
+
+
+
+build-request = [ build-request.from-command-line [ modules.peek : ARGV ] ] ;
+
+properties = [ $(build-request).get-at 2 ] ;
+
+if $(properties)
+{
+ expanded = [ build-request.expand-no-defaults $(properties) ] ;
+ local xexpanded ;
+ for local e in $(expanded)
+ {
+ xexpanded += [ property-set.create [ feature.split $(e) ] ] ;
+ }
+ expanded = $(xexpanded) ;
+}
+
+
+local target-ids = [ $(build-request).get-at 1 ] ;
+local targets
+local clean ;
+
+
+if "--clean" in [ modules.peek : ARGV ]
+{
+ clean = true ;
+}
+
+for local id in $(target-ids)
+{
+ if $(id) = clean
+ {
+ clean = true ;
+ }
+ else
+ {
+ local t = [ targets.find $(id) : $(current-project) ] ;
+ if ! $(t)
+ {
+ error target $(id) does not exist ;
+ }
+ else
+ {
+ targets += $(t) ;
+ }
+ }
+}
+
+if ! $(targets)
+{
+ targets += [ project.target [ project.module-name "." ] ] ;
+}
+
+virtual-targets = ;
+
+if $(expanded)
+{
+ for local p in $(expanded)
+ {
+ for local t in $(targets)
+ {
+ local g = [ $(t).generate $(p) ] ;
+ virtual-targets += $(g[2-]) ;
+ }
+ }
+}
+else
+{
+ for local t in $(targets)
+ {
+ local g = [ $(t).generate [ property-set.empty ] ] ;
+ virtual-targets += $(g[2-]) ;
+ }
+}
+
+
+actual-targets = ;
+for t in $(virtual-targets)
+{
+ actual-targets += [ $(t).actualize ] ;
+}
+NOTFILE all ;
+DEPENDS all : $(actual-targets) ;
+
+if $(clean)
+{
+ UPDATE clean ;
+}
+else
+{
+ UPDATE all ;
+}
+
+
+
Property changes on: boost-jam/boost-build/branches/upstream/current/build-system.jam
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/debian/boost-build.docs
===================================================================
--- boost-jam/boost-build/branches/upstream/current/debian/boost-build.docs 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/debian/boost-build.docs 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,4 @@
+boost_build_v2.html
+index_v2.html
+boost.png
+doc
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/debian/boost-build.examples
===================================================================
--- boost-jam/boost-build/branches/upstream/current/debian/boost-build.examples 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/debian/boost-build.examples 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+example/*
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/debian/changelog
===================================================================
--- boost-jam/boost-build/branches/upstream/current/debian/changelog 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/debian/changelog 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,6 @@
+boost-build (2.0.m10-1) unstable; urgency=low
+
+ * Initial Release.
+
+ -- Vladimir Prus <ghost at cs.msu.su> Wed, 14 Aug 2002 14:08:00 +0400
+
Added: boost-jam/boost-build/branches/upstream/current/debian/conffiles
===================================================================
--- boost-jam/boost-build/branches/upstream/current/debian/conffiles 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/debian/conffiles 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+/etc/site-config.jam
Added: boost-jam/boost-build/branches/upstream/current/debian/control
===================================================================
--- boost-jam/boost-build/branches/upstream/current/debian/control 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/debian/control 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,13 @@
+Source: boost-build
+Section: devel
+Priority: optional
+Maintainer: Vladimir Prus <ghost at cs.msu.su>
+Build-Depends: debhelper (>> 3.0.0), docbook-to-man, bison
+Standards-Version: 3.5.2
+
+Package: boost-build
+Architecture: all
+Depends: ${shlibs:Depends}, bjam (>> 3.1.9-1)
+Description: Build system
+ Boost.Build is a build system with a simple and high-level language.
+ It supports build variants, and several different compilers and tools.
Added: boost-jam/boost-build/branches/upstream/current/debian/copyright
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/debian/excludes
===================================================================
--- boost-jam/boost-build/branches/upstream/current/debian/excludes 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/debian/excludes 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,14 @@
+boost.css
+boost_build_v2.html
+index_v2.html
+boost.png
+generators_prototype.py
+hacking.txt
+release_procedure.txt
+site-config.jam
+roll.sh
+debian
+doc
+example
+test
+CVS
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/debian/rules
===================================================================
--- boost-jam/boost-build/branches/upstream/current/debian/rules 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/debian/rules 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,56 @@
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# This file is public domain software, originally written by Joey Hess.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+build:
+clean:
+binary-arch:
+
+binary-indep:
+ dh_testdir
+ dh_testroot
+
+ dh_clean -k
+ dh_installdirs usr/share/boost-build etc
+
+ # Add here commands to install the package into debian/<packagename>
+ (tar --exclude-from debian/excludes -cpf - * ) | (cd `pwd`/debian/tmp/usr/share/boost-build && tar xpf - )
+ chmod a-x -R `pwd`/debian/tmp/usr/share/boost-build
+
+ dh_installchangelogs
+ dh_installdocs -XCVS
+ mv `pwd`/debian/tmp/usr/share/doc/boost-build/index_v2.html `pwd`/debian/tmp/usr/share/doc/boost-build/index.html
+
+ (tar --exclude make --exclude CVS -cpf - example/* ) | ( cd `pwd`/debian/tmp/usr/share/doc/boost-build && tar xpf - )
+
+ sed 's/# using gcc/using gcc/' user-config.jam > `pwd`/debian/tmp/etc/site-config.jam
+
+# dh_install
+# dh_installmenu
+# dh_installdebconf
+# dh_installlogrotate
+# dh_installemacsen
+# dh_installcatalogs
+# dh_installpam
+# dh_installmime
+# dh_installinit
+# dh_installcron
+# dh_installinfo
+# dh_undocumented
+ dh_installman
+ dh_link
+ dh_compress
+ dh_fixperms
+# dh_perl
+# dh_python
+# dh_makeshlibs
+ dh_installdeb
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
Property changes on: boost-jam/boost-build/branches/upstream/current/debian/rules
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/doc/Jamfile.v2
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/Jamfile.v2 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/Jamfile.v2 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,19 @@
+
+project tools/build/v2/doc
+ ;
+
+boostbook userman : src/userman.xml
+ : <xsl:param>toc.section.depth=1
+ <xsl:param>doc.standalone=true
+ <xsl:param>nav.layout=none
+ ;
+
+if ! $(BOOST_ROOT)
+{
+ BOOST_ROOT = [ modules.peek : BOOST_ROOT ] ;
+}
+
+# Copy stylesheet and images from 'official' docs location
+stage html : $(BOOST_ROOT)/doc/html/boostbook.css ;
+stage html/images
+ : [ path.glob $(BOOST_ROOT)/doc/html/images : *.png ] ;
Added: boost-jam/boost-build/branches/upstream/current/doc/catalog.xml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/catalog.xml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/catalog.xml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalog
+ PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
+ "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <rewriteURI uriStartString="http://www.boost.org/tools/boostbook/dtd/" rewritePrefix="file:///home/ghost/Work/boost/tools/boostbook/dtd//"/>
+ <rewriteURI uriStartString="http://docbook.sourceforge.net/release/xsl/current/" rewritePrefix="file:///home/ghost/build/docbook/xsl/"/>
+ <rewriteURI uriStartString="http://www.oasis-open.org/docbook/xml/4.2/" rewritePrefix="file:///home/ghost/build/docbook/dtd/"/>
+</catalog>
Added: boost-jam/boost-build/branches/upstream/current/doc/development_plan.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/development_plan.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/development_plan.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,125 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+ <head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st April 2002), see www.w3.org">
+ <meta name="generator" content="Microsoft FrontPage 5.0">
+ <meta http-equiv="Content-Type" content=
+ "text/html; charset=windows-1252">
+ <!-- tidy options: ‐‐tidy-mark false -i -wrap 78 !-->
+
+ <title>Boost Build System V2</title>
+ </head>
+
+ <body bgcolor="#FFFFFF" text="#000000">
+ <img src="../../../../boost.png" alt="boost.png (6897 bytes)" align="center"
+ width="277" height="86"> <!-- sf logo -->
+
+
+ <h1>Boost Build Development Plan</h1>
+
+ <ul>
+ <li>
+ <b>Milestone 2</b> (October 25, 2002)
+
+ <p>Boost buildable with gcc and also usable as part of another
+ project.</p>
+ </li>
+
+ <li>
+ <b>Milestone 3</b> (May 21, 2003)
+
+ <p>Two gcc versions and two other compilers are supported. Some other
+ tools (e.g. lex and BoostBook) are implemented.</p>
+ </li>
+
+ <li>
+ <b>Milestone 4</b> (June 18, 2003)
+
+ <p>More tools implemented.</p>
+ </li>
+
+ <li>
+ <b>Milestone 5</b> (Jule 2, 2003)
+
+ <p>Improvements and bugfixes with dependency scanning. Support for
+ i18n tools. Testing framework for Boost.</p>
+ </li>
+
+ <li>
+ <b>Milestone 6</b> (Jule 22, 2003)
+
+ <p>Bugfixes.</p>
+ </li>
+
+ <li>
+ <b>Milestone 7</b> (Aug 1, 2003)
+
+ <p>Optimizations.</p>
+ </li>
+
+ <li>
+ <b>Milestone 8</b> (Oct 15, 2003)
+
+ <p>Implementation of regression testing framework was
+ implemented. Handling of dependencies to generated headers was
+ optimized. Algorithms for link-compatibility checking and selecting
+ main target alternatives were improved.</p>
+ </li>
+
+ <li>
+ <b>Milestone 9.1</b> (Nov 06, 2003)
+
+ <p>Performance was considerably improved. The syntax for linking a
+ library into a library was simplified. The 'stage' rule can traverse
+ dependencies of the targets it installs. Regression testing support
+ now works on Windows. Some toolsets were improved. Bugs in project
+ loading and suffix determination were fixed.
+ </li>
+
+ <li>
+ <b>Milestone 10</b> (TBD)
+
+ <p>Remaining features for <a href="http://boost.org">C++ Boost</a>:
+ improved installation, Python support. Uniform toolset initialization
+ scheme. Many bugfixes</p>
+ </li>
+
+
+ <li>
+ <b>Alpha</b> (TBD)
+
+ <p>Optimization. Using buildable tools: consider using bison, which
+ is itself built with Boost.Build.</p>
+ </li>
+
+ <li>
+ <b>Beta</b> (TBD)
+
+ <p>Feature-complete milestone.</p>
+ </li>
+
+ <li>
+ <b>2.0 Release</b> (TBD)
+
+ <p>Bugfixes</p>
+ </li>
+ </ul>
+ <hr>
+
+ <p>© Copyright Vladimir Prus 2002-2003. Permission to copy, use,
+ modify, sell and distribute this document is granted provided this
+ copyright notice appears in all copies. This document is provided "as is"
+ without express or implied warranty, and with no claim as to its
+ suitability for any purpose.</p>
+
+ <p>Revised
+ <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
+ -->23 Aug, 2004
+ <!--webbot bot="Timestamp" endspan i-checksum="13972"
+ -->
+ </p>
+ </body>
+</html>
+
Added: boost-jam/boost-build/branches/upstream/current/doc/html/HTML.manifest
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/HTML.manifest 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/HTML.manifest 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,41 @@
+index.html
+bbv2/howto.html
+bbv2/installation.html
+bbv2/tutorial.html
+bbv2/tutorial/properties.html
+bbv2/tutorial/hierarchy.html
+bbv2/tutorial/libs.html
+bbv2/tutorial/depends.html
+bbv2/tutorial/linkage.html
+bbv2/tutorial/conditions.html
+bbv2/tutorial/prebuilt.html
+bbv2/advanced.html
+bbv2/advanced/jamfiles.html
+bbv2/advanced/build_process.html
+bbv2/advanced/builtins/targets.html
+bbv2/advanced/builtins/features.html
+bbv2/advanced/differences_to_v1.html
+bbv2/extender.html
+bbv2/extending/targets.html
+bbv2/extending/tools.html
+bbv2/extending/features.html
+bbv2/extending/rules.html
+bbv2/extending/toolset_modules.html
+bbv2/reference.html
+bbv2/reference/jamfiles.html
+bbv2/reference/buildprocess.html
+bbv2/reference/definitions.html
+bbv2/reference/generators.html
+bbv2/faq.html
+bbv2/faq/s02.html
+bbv2/faq/s03.html
+bbv2/faq/s04.html
+bbv2/faq/external.html
+bbv2/faq/s06.html
+bbv2/faq/s07.html
+bbv2/faq/dll-path.html
+bbv2/recipies/site-config.html
+bbv2/arch.html
+bbv2/arch/build.html
+bbv2/arch/tools.html
+bbv2/arch/targets.html
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/build_process.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/build_process.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/build_process.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,168 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Build process</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../advanced.html" title="Chapter 4. User documentation">
+<link rel="previous" href="jamfiles.html" title="Writing Jamfiles">
+<link rel="next" href="builtins/targets.html" title="Builtin target types">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="jamfiles.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../advanced.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="builtins/targets.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.advanced.build_process"></a>Build process</h2></div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="build_process.html#id2536467">Build request</a></dt>
+<dt><a href="build_process.html#id2536509">Building a main target</a></dt>
+<dt><a href="build_process.html#id2536623">Building a project</a></dt>
+</dl></div>
+<p>When you've described your targets, you want Boost.Build to run the
+ right tools and create the needed targets. This section will describe
+ two things: how you specify what to build, and how the main targets are
+ actually constructed.
+ </p>
+<p>The most important thing to note is that in Boost.Build, unlike
+ other build tools, the targets you declare do not correspond to specific
+ files. What you declare in Jamfiles is more like "metatarget". Depending
+ on the properties that you specify on the command line, each
+ "metatarget" will produce a set of real targets corresponding to the
+ requested properties. It is quite possible that the same metatarget is
+ build several times with different properties, and will, of course,
+ produce different files.
+ </p>
+<div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Tip</h3>
+<p>
+ This means that for Boost.Build, you cannot directly obtain build
+ variant from Jamfile. There could be several variants requested by the
+ user, and each target can be build with different properties.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="id2536467"></a>Build request</h3></div></div>
+<div></div>
+</div>
+<p>
+ The command line specifies which targets to build and with what
+ properties. For example:
+</p>
+<pre class="programlisting">
+bjam app1 lib1//lib1 toolset=gcc variant=debug optimization=full
+</pre>
+<p>
+ would build two targets, "app1" and "lib1//lib1" with the specified
+ properties. You can refer to any targets, using
+ <a href="../reference/definitions.html#bbv2.reference.ids" title="Target identifiers and references">target id</a> and specify arbitrary
+ properties. Some of the properties are very common, and for them the name
+ of the property can be omitted. For example, the above can be written as:
+</p>
+<pre class="programlisting">
+bjam app1 lib1//lib1 gcc debug optimization=full
+</pre>
+<p>
+ The complete syntax which has some additional shortcuts if described <a href="../reference.html#bbv2.reference.commandline" title="Command line">here</a>.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="id2536509"></a>Building a main target</h3></div></div>
+<div></div>
+</div>
+<p>When you request, directly or indirectly, a build of a main target
+ with specific requirements, the following steps are made. Some brief
+ explanation is provided, and more detailes are given in the <a href="../reference/buildprocess.html" title="Build process">reference</a>.
+ </p>
+<div class="orderedlist"><ol type="1">
+<li><p>Applying default build. If the default-build
+ property of a target specifies a value of a feature which is not
+ present in the build request, that value is added.</p></li>
+<li><p>Selecting the main target alternative to use. For
+ each alternative we look how many properties are present both in
+ alternative's requirements, and in build request. The
+ alternative with large number of matching properties is selected.
+ </p></li>
+<li><p>Determining "common" properties. The build request
+ is <a href="../reference/definitions.html#bbv2.reference.variants.proprefine" title="Property refinement">refined</a>
+ with target's requirements. The conditional properties in
+ requirements are handled as well. Finally, default values of
+ features are added.
+ </p></li>
+<li><p>Building targets referred by the sources list and
+ dependency properties. The list of sources and the properties
+ can refer to other target using <a href="../reference/definitions.html#bbv2.reference.ids" title="Target identifiers and references">target references</a>. For each
+ reference, we take all <a href="../reference/definitions.html#bbv2.reference.features.attributes.propagated">propagated</a>
+ properties, refine them by explicit properties specified in the
+ target reference, and pass the resulting properties as build
+ request to the other target.
+ </p></li>
+<li><p>Adding the usage requirements produces when building
+ dependencies to the "common" properties. When dependencies are
+ built in the previous step, they return both the set of created
+ "real" targets, and usage requirements. The usage requirements
+ are added to the common properties and the resulting property
+ set will be used for building the current target.
+ </p></li>
+<li><p>Building the target using generators. To convert the
+ sources to the desired type, Boost.Build uses "generators" ---
+ objects which correspond to tools like compilers and
+ linkers. Each generator declares what type of targets in can
+ produce and what type of sources it requires. Using this
+ information, Boost.Build determines which generators must be run
+ to produce a specific target from specific sources. When
+ generators are run, they return the "real" targets.
+ </p></li>
+<li><p>Computing the usage requirements to be returned. The
+ conditional properties in usage requirements are expanded and the
+ result is returned.</p></li>
+</ol></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="id2536623"></a>Building a project</h3></div></div>
+<div></div>
+</div>
+<p>Often, user request a build of a complete project, not just one
+ main target. In fact, invoking <b class="command">bjam</b> without
+ parameters builds the project defined in the current directory.</p>
+<p>When a project is build, the build request is passed without
+ modification to all main targets in that project. It's is possible to
+ prevent implicit building of a target in a project with the
+ <tt class="computeroutput">explicit</tt> rule:
+</p>
+<pre class="programlisting">
+explicit hello_test ;
+</pre>
+<p>
+ would cause the <tt class="computeroutput">hello_test</tt> target to be built only if
+ explicitly requested by the user or by some other target.
+ </p>
+<p>The Jamfile for a project can include a number of
+ <tt class="computeroutput">build-project</tt> rule calls, that specify additional projects
+ to be built.
+ </p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="jamfiles.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../advanced.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="builtins/targets.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/builtins/features.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/builtins/features.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/builtins/features.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,119 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Builtin features</title>
+<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../../advanced.html" title="Chapter 4. User documentation">
+<link rel="previous" href="targets.html" title="Builtin target types">
+<link rel="next" href="../differences_to_v1.html" title="Differences to Boost.Build V1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="targets.html"><img src="../../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../../advanced.html"><img src="../../../images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="../differences_to_v1.html"><img src="../../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.advanced.builtins.features"></a>Builtin features</h2></div></div>
+<div></div>
+</div>
+<div class="variablelist"><dl>
+<dt><span class="term"><tt class="literal">variant</tt></span></dt>
+<dd>
+<p>
+ The feature which combines several low-level features in
+ order to make building most common variants simple.
+ </p>
+<p><span class="bold"><b>Allowed values:</b></span><tt class="literal">debug</tt>, <tt class="literal">release</tt>,
+ <tt class="literal">profile</tt></p>
+<p>The value <tt class="literal">debug</tt> expands to</p>
+<pre class="programlisting">
+ <optimization>off <debug-symbols>on <inlining>off <runtime-debugging>on
+ </pre>
+<p>The value <tt class="literal">release</tt> expands to</p>
+<pre class="programlisting">
+ <optimization>speed <debug-symbols>off <inlining>full <runtime-debugging>off
+ </pre>
+<p>The value <tt class="literal">profile</tt> expands to the same as
+ <tt class="literal">release</tt>, plus:</p>
+<pre class="programlisting">
+ <profiling>on <debug-symbols>on
+ </pre>
+<p><span class="bold"><b>Rationale:</b></span> Runtime debugging is on in debug build
+ to suit expectations of people used various IDEs. It's
+ assumed other folks don't have any specific expectation in
+ this point.</p>
+</dd>
+<dt>
+<a name="bbv2.advanced.builtins.features.link"></a><span class="term"><tt class="literal">link</tt></span>
+</dt>
+<dd>
+<p>
+ Feature which controls how libraries are built.
+ </p>
+<p><span class="bold"><b>Allowed values:</b></span><tt class="literal">shared</tt>,
+ <tt class="literal">static</tt></p>
+</dd>
+<dt><span class="term"><tt class="literal">source</tt></span></dt>
+<dd>
+ Tthe <source>X feature has the same effect on building a target
+ as putting X in the list of sources. The feature
+ is sometimes more convenient: you can put <source>X in
+ the requirements for a project and it will be linked to all
+ executables.
+ </dd>
+<dt><span class="term"><tt class="literal">library</tt></span></dt>
+<dd>
+ This feature is equivalent to the <source> feature, and exists
+ for backward compatibility reasons.
+ </dd>
+<dt><span class="term"><tt class="literal">use</tt></span></dt>
+<dd>
+ Causes the target referenced by the value of this feature
+ to be constructed and adds it's usage requirements to build
+ properties. The constructed targets are not used in any other
+ way. The primary use case is when you use some library and want
+ it's usage requirements (such as include paths) to be applied,
+ but don't want to link to the library.
+ </dd>
+<dt><span class="term"><tt class="literal">dll-path</tt></span></dt>
+<dd>
+ Specify an additional path where shared libraries should be
+ searched where the executable or shared library is run. This
+ feature only affect Unix compilers. Plase see the <a href="../../faq/dll-path.html" title="Why are the dll-path and
+ hardcode-dll-paths properties useful?
+ ">FAQ entry</a> for details.
+ </dd>
+<dt><span class="term"><tt class="literal">hardcode-dll-paths</tt></span></dt>
+<dd>
+<p>
+ Controls automatic generation of dll-path properties.
+ </p>
+<p><span class="bold"><b>Allowed values:</b></span><tt class="literal">true</tt>, <tt class="literal">false</tt>. This property
+ is specific to Unix systems. If an executable is build with
+ <tt class="computeroutput"><hardcode-dll-paths>true</tt>, the generated binary
+ will contain the list of all the paths to the used shared
+ libraries. As the result, the executable can be run without
+ changing system paths to shared libraries, or installing the
+ libraries to system paths. This is very convenient during
+ development. Plase see the <a href="../../faq/dll-path.html" title="Why are the dll-path and
+ hardcode-dll-paths properties useful?
+ ">FAQ entry</a> for details.
+ </p>
+</dd>
+</dl></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="targets.html"><img src="../../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../../advanced.html"><img src="../../../images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="../differences_to_v1.html"><img src="../../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/builtins/targets.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/builtins/targets.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/builtins/targets.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,321 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Builtin target types</title>
+<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../../advanced.html" title="Chapter 4. User documentation">
+<link rel="previous" href="../build_process.html" title="Build process">
+<link rel="next" href="features.html" title="Builtin features">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../build_process.html"><img src="../../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../../advanced.html"><img src="../../../images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="features.html"><img src="../../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.advanced.builtins.targets"></a>Builtin target types</h2></div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="targets.html#id2536681">Programs</a></dt>
+<dt><a href="targets.html#id2536744">Libraries</a></dt>
+<dt><a href="targets.html#bbv2.builtins.alias">Alias</a></dt>
+<dt><a href="targets.html#bbv2.builtins.stage">Installing</a></dt>
+<dt><a href="targets.html#bbv2.builtins.testing">Testing</a></dt>
+</dl></div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="id2536681"></a>Programs</h3></div></div>
+<div></div>
+</div>
+<p>Programs are created using the <tt class="computeroutput">exe</tt> rule, which
+ follows the <a href="../jamfiles.html#bbv2.main-target-rule-syntax">common
+ syntax</a>. For example:
+</p>
+<pre class="programlisting">
+exe hello : hello.cpp some_library.lib /some_project//library
+ : <threading>multi
+ ;
+</pre>
+<p>
+ This will create an executable file from the sources -- in this case,
+ one C++ file, one library file present in the same directory, and
+ another library which is created by Boost.Build. Generally, sources
+ can include C and C++ files, object files and libraries. Boost.Build
+ will automatically try to convert targets of other types.
+ </p>
+<div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Tip</h3>
+<p>
+ On Windows, if an application uses dynamic libraries, and both
+ the application and the libraries are built by Boost.Build, its not
+ possible to immediately run the application, because the
+ <tt class="literal">PATH</tt> environment variable should include the path
+ to the libraries. It means you have to either add the paths
+ manually, or place the application and the libraries to the same
+ directory, for example using the <a href="targets.html#bbv2.builtins.stage" title="Installing">
+ stage</a> rule.
+ </p>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="id2536744"></a>Libraries</h3></div></div>
+<div></div>
+</div>
+<p>Libraries are created using the <tt class="computeroutput">lib</tt> rule, which
+ follows the <a href="../jamfiles.html#bbv2.main-target-rule-syntax">common
+ syntax</a>. For example:
+</p>
+<pre class="programlisting">
+lib helpers : helpers.cpp : <include>boost : : <include>. ;
+</pre>
+<p>In the most common case, the <tt class="computeroutput">lib</tt> creates a library
+ from the specified sources. Depending on the value of
+ <link> feature the library will be either static or
+ shared. There are two other cases. First is when the library is
+ installed somewhere in compiler's search paths, and should be
+ searched by the compiler (typically, using the <tt class="option">-l</tt>
+ option). The second case is where the library is available as a
+ prebuilt file and the full path is known.
+ </p>
+<p>
+ The syntax for these case is given below:
+</p>
+<pre class="programlisting">
+lib z : : <name>z <search>/home/ghost ;
+lib compress : : <file>/opt/libs/compress.a ;
+</pre>
+<p>
+ The <tt class="computeroutput">name</tt> property specifies the name which should be
+ passed to the <tt class="option">-l</tt> option, and the <tt class="computeroutput">file</tt>
+ property specifies the file location. The <tt class="computeroutput">search</tt> feature
+ specifies paths where the library should be searched. That feature can
+ be specified several time, or can be omitted -- in which case only
+ default compiler paths will be searched.
+ </p>
+<p>The difference between using the <tt class="computeroutput">file</tt> feature as
+ opposed to the <tt class="computeroutput">name</tt> name feature together with the
+ <tt class="computeroutput">search</tt> feature is that <tt class="computeroutput">file</tt> is more
+ precise. A specific file will be used. On the other hand, the
+ <tt class="computeroutput">search</tt> feature only adds a library path, and the
+ <tt class="computeroutput">name</tt> feature gives the basic name of the library. The
+ search rules are specific to the linker. For example, given these
+ definition:
+</p>
+<pre class="programlisting">
+lib a : : <variant>release <file>/pool/release/a.so ;
+lib a : : <variant>debug <file>/pool/debug/a.so ;
+lib b : : <variant>release <file>/pool/release/b.so ;
+lib b : : <variant>debug <file>/pool/debug/b.so ;
+</pre>
+<p>
+ It's possible to use release version of <tt class="computeroutput">a</tt> and debug
+ version of <tt class="computeroutput">b</tt>. Had we used the <tt class="computeroutput">name</tt> and
+ <tt class="computeroutput">search</tt> features, the linker would always pick either
+ release or debug versions.
+ </p>
+<p>
+ For convenience, the following syntax is allowed:
+</p>
+<pre class="programlisting">
+lib z ;
+lib gui db aux ;
+</pre>
+<p>
+ and is does exactly the same as:
+</p>
+<pre class="programlisting">
+lib z : : <name>z ;
+lib giu : : <name>gui ;
+lib db : : <name>db ;
+lib aux : : <name>aux ;
+</pre>
+<p>When a library uses another library you should put that another
+ library in the list of sources. This will do the right thing in all
+ cases. For portability, you should specify library dependencies even
+ for searched and prebuilt libraries, othewise, static linking on
+ Unix won't work. For example:
+</p>
+<pre class="programlisting">
+lib z ;
+lib png : z : <name>png ;
+</pre>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>When a library (say, <tt class="computeroutput">a</tt>), which has another
+ library, (say, <tt class="computeroutput">b</tt>) is linked dynamically, the <tt class="computeroutput">b</tt>
+ library will be incorporated in <tt class="computeroutput">a</tt>. (If <tt class="computeroutput">b</tt>
+ is dynamic library as well, then <tt class="computeroutput">a</tt> will only refer to
+ it, and not include any extra code.) When the <tt class="computeroutput">a</tt>
+ library is linked statically, Boost.Build will assure that all
+ executables which link to <tt class="computeroutput">a</tt> will also link to
+ <tt class="computeroutput">b</tt>.
+ </p>
+</div>
+<p>One feature of Boost.Build which is very important for libraries
+ is usage requirements. For example, if you write:
+</p>
+<pre class="programlisting">
+lib helpers : helpers.cpp : : : <include>. ;
+</pre>
+<p>
+ then compiler include path for all targets which use
+ <tt class="computeroutput">helpers</tt> will contain the directory where the target is
+ defined.path to "helpers.cpp". So, the user need only to add
+ <tt class="computeroutput">helpers</tt> to the list of sources, and don't bother about
+ other requirements. This allows to greatly simplify Jamfiles.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>If you don't want shared libraries to include all libraries
+ which are specified in sources (especially statically linked ones),
+ you'd need to use the following:
+</p>
+<pre class="programlisting">
+lib b : a.cpp ;
+lib a : a.cpp : <use>b : : <library>b ;
+</pre>
+<p>
+ This specifies that <tt class="computeroutput">a</tt> uses <tt class="computeroutput">b</tt>, and causes
+ all executables which link to <tt class="computeroutput">a</tt> also link to
+ <tt class="computeroutput">b</tt>. In this case, even for shared linking, the
+ <tt class="computeroutput">a</tt> library won't even refer to <tt class="computeroutput">b</tt>.
+ </p>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.builtins.alias"></a>Alias</h3></div></div>
+<div></div>
+</div>
+<p>The <tt class="computeroutput">alias</tt> rule follows the <a href="../jamfiles.html#bbv2.main-target-rule-syntax">common syntax</a>. For
+ example:
+</p>
+<pre class="programlisting">
+alias core : im reader writer ;
+</pre>
+<p>
+ will build the sources and return the generated source targets
+ without modification.
+ </p>
+<p>
+ The <tt class="computeroutput">alias</tt> rule is a convenience tool. If you often build
+ the same group of targets at the same time, you can define the alias
+ to save typing.
+ </p>
+<p>
+ Another use of the <tt class="computeroutput">alias</tt> rule is to change build
+ properties. For example, if you always want static linking for a
+ specific C++ Boost library, you can write the following:
+</p>
+<pre class="programlisting">
+alias boost_thread : /boost/thread//boost_thread : <link>static ;
+</pre>
+<p>
+ and use only the <tt class="computeroutput">boost_thread</tt> alias in your Jamfiles.
+ </p>
+<p>
+ It is also allowed to specify usage requirements for the
+ <tt class="computeroutput">alias</tt> target. If you write the following:
+</p>
+<pre class="programlisting">
+alias header_only_library : : : : <include>/usr/include/header_only_library ;
+</pre>
+<p>
+ then using <tt class="computeroutput">header_only_library</tt> in sources will only add an
+ include path. Also note that when there are some sources, their usage
+ requirements are propagated, too. For example:
+</p>
+<pre class="programlisting">
+lib lib : lib.cpp : : : <include>. ;
+alias lib_alias ;
+exe main : main.cpp lib_alias ;
+</pre>
+<p>
+ will compile <tt class="filename">main.cpp</tt> with the additional include.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.builtins.stage"></a>Installing</h3></div></div>
+<div></div>
+</div>
+<p>For installing the built target you should use the
+ <tt class="computeroutput">stage</tt> rule follows the <a href="../jamfiles.html#bbv2.main-target-rule-syntax">common syntax</a>. For
+ example:
+</p>
+<pre class="programlisting">
+stage dist : hello helpers ;
+</pre>
+<p>
+ will cause the targets <tt class="computeroutput">hello</tt> and <tt class="computeroutput">helpers</tt> to
+ be moved to the <tt class="filename">dist</tt> directory. The directory can
+ be changed with the <tt class="computeroutput">location</tt> property:
+</p>
+<pre class="programlisting">
+stage dist : hello helpers : <location>/usr/bin ;
+</pre>
+<p>
+ Specifying the names of all libraries to install can be boring. The
+ <tt class="computeroutput">stage</tt> allows to specify only the top-level executable
+ targets to install, and automatically install all dependencies:
+</p>
+<pre class="programlisting">
+stage dist : hello
+ : <traverse-dependencies>on <include-type>EXE
+ <include-type>LIB
+ ;
+</pre>
+<p>
+ will find all targets that <tt class="computeroutput">hello</tt> depends on, and install
+ all of the which are either executables or libraries.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.builtins.testing"></a>Testing</h3></div></div>
+<div></div>
+</div>
+<p>Boost.Build has convenient support for running unit tests. The
+ simplest way is the <tt class="computeroutput">unit-test</tt> rule, which follows the
+ <a href="../jamfiles.html#bbv2.main-target-rule-syntax">common syntax</a>. For
+ example:
+</p>
+<pre class="programlisting">
+unit-test helpers_test : helpers_test.cpp helpers ;
+</pre>
+<p>The <tt class="computeroutput">unit-test</tt> rule behaves like the
+ <tt class="computeroutput">exe</tt> rule, but after the executable is created it is
+ run. If the executable returns error, the build system will also
+ return error and will try running the executable on the next
+ invocation until it runs successfully. This behaviour ensures that you
+ can't miss a unit test failure.
+ </p>
+<p>There are rules for more elaborate testing: <tt class="computeroutput">compile</tt>,
+ <tt class="computeroutput">compile-fail</tt>, <tt class="computeroutput">run</tt> and
+ <tt class="computeroutput">run-fail</tt>. They are more suitable for automated testing, and
+ are not covered here yet.
+ </p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../build_process.html"><img src="../../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../../advanced.html"><img src="../../../images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="features.html"><img src="../../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/differences_to_v1.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/differences_to_v1.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/differences_to_v1.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,129 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Differences to Boost.Build V1</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../advanced.html" title="Chapter 4. User documentation">
+<link rel="previous" href="builtins/features.html" title="Builtin features">
+<link rel="next" href="../extender.html" title="Chapter 5. Extender Manual">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="builtins/features.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../advanced.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="../extender.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.advanced.differences_to_v1"></a>Differences to Boost.Build V1</h2></div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="differences_to_v1.html#bbv2.advanced.differences_to_v1.configuration">Configuration</a></dt>
+<dt><a href="differences_to_v1.html#bbv2.advanced.differences_to_v1.jamfiles">Writing Jamfiles</a></dt>
+<dt><a href="differences_to_v1.html#bbv2.advanced.differences_to_v1.build_process">Build process</a></dt>
+</dl></div>
+<p>While Boost.Build V2 is based on the same ideas as Boost.Build V1,
+ some of the syntax was changed, and some new important features were
+ added. This chapter describes most of the changes.</p>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.advanced.differences_to_v1.configuration"></a>Configuration</h3></div></div>
+<div></div>
+</div>
+<p>In V1, there were two methods to configure a toolset. One is to
+ set some environment variable, or use "-s" command line option to set
+ variable inside BJam. Another method was creating new toolset module,
+ which would set the variables and then invoke basic toolset. Neither
+ method is necessary now, the "using" rule provides a consistent way to
+ initialize toolset, including several versions. See <a href="../advanced.html#bbv2.advanced.configuration" title="Configuration">section on configuraton</a> for
+ details.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.advanced.differences_to_v1.jamfiles"></a>Writing Jamfiles</h3></div></div>
+<div></div>
+</div>
+<p>Probably one of the most important differences in V2 Jamfiles is
+ the project requirements. In V1, if several targets have the same
+ requirements (for example, common include path), it was necessary to
+ manually write that requirements, or use a helper rule. In V2, the
+ common properties can be specified with the "requirements" project
+ attribute, as documented <a href="jamfiles.html#bbv2.advanced.projects" title="Projects">here</a>.
+ </p>
+<p>The <a href="../tutorial/libs.html" title="Libraries and Dependent Targets">usage requirements</a>
+ is also important mechanism to simplify Jamfile. If a library requires
+ all clients to use specific includes, or macros when compiling the
+ code which depends on the library, this information can be cleanly
+ represented.</p>
+<p>The difference between "lib" and "dll" targets in V1 is completely
+ eliminated in V2. There's only one target -- "lib", which can create
+ either static or shared library depending on the value of the
+ <a href="builtins/features.html#bbv2.advanced.builtins.features.link"><link>
+ feature</a>. If your target should be only build in one variant, you
+ can add <link>shared or <link>static to requirements.
+ </p>
+<p>The syntax for referring to other targets was changed a bit. While
+ in V1 one would use:
+</p>
+<pre class="programlisting">
+exe a : a.cpp <lib>../foo/bar ;
+</pre>
+<p>
+ the V2 syntax is:
+</p>
+<pre class="programlisting">
+exe a : a.cpp ../foo//bar ;
+</pre>
+<p>
+ Note that you don't need to specify the type of other target, but the
+ last element should be separated to double slash, to indicate that
+ you're referring to target "bar" in project "../foo", and not to
+ project "../foo/bar".
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.advanced.differences_to_v1.build_process"></a>Build process</h3></div></div>
+<div></div>
+</div>
+<p>The command line syntax in V2 is completely different. For example
+</p>
+<pre class="programlisting">
+bjam -sTOOLS=msvc -sBUILD=release some_target
+</pre>
+<p>
+ now becomes:
+</p>
+<pre class="programlisting">
+bjam toolset=msvc variant=release some_target
+</pre>
+<p>
+ or, using shortcuts, just:
+</p>
+<pre class="programlisting">
+bjam msvc release some_target
+</pre>
+<p>
+ See <a href="../reference.html#bbv2.reference.commandline" title="Command line">the reference</a> for
+ complete description of the syntax.
+ </p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="builtins/features.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../advanced.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="../extender.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/jamfiles.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/jamfiles.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced/jamfiles.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,428 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Writing Jamfiles</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../advanced.html" title="Chapter 4. User documentation">
+<link rel="previous" href="../advanced.html" title="Chapter 4. User documentation">
+<link rel="next" href="build_process.html" title="Build process">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../advanced.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../advanced.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="build_process.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.advanced.jamfiles"></a>Writing Jamfiles</h2></div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="jamfiles.html#bbv2.advanced.overview">Overview</a></dt>
+<dt><a href="jamfiles.html#bbv2.advanced.targets">Main targets</a></dt>
+<dt><a href="jamfiles.html#bbv2.advanced.projects">Projects</a></dt>
+<dt><a href="jamfiles.html#bbv2.advanced.other-rules">Additional Jamfile rules</a></dt>
+<dt><a href="jamfiles.html#bbv2.advanced.project-root">Project root</a></dt>
+</dl></div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.advanced.overview"></a>Overview</h3></div></div>
+<div></div>
+</div>
+<p>Jamfiles are the thing which is most important to the user,
+ bacause they declare the targets which should be build. Jamfiles are
+ also used for organizing targets -- each Jamfile is a separate project,
+ which can be build independently from the other projects.</p>
+<p>Jamfile mostly contain calls to Boost.Build functions, which do
+ all the work, specifically:
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li><p><a href="jamfiles.html#bbv2.advanced.targets" title="Main targets">declare main
+ targets</a></p></li>
+<li><p><a href="jamfiles.html#bbv2.advanced.projects" title="Projects">define
+ project properties</a></p></li>
+<li><p><a href="jamfiles.html#bbv2.advanced.other-rules" title="Additional Jamfile rules">do various other
+ things</a></p></li>
+</ul></div>
+<p>In addition to Jamfiles, Boost.Build has another user-editable
+ file, project-root.jam, which is mostly useful to declare constants
+ global to all the projects. It is described in more detail <a href="jamfiles.html#bbv2.advanced.project-root" title="Project root">below</a>.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.advanced.targets"></a>Main targets</h3></div></div>
+<div></div>
+</div>
+<p><a name="bbv2.advanced.targets.main"></a><span class="emphasis"><em>Main target</em></span> is a user-defined named
+ entity which can be build, for example a named executable file.
+ Declaring a main target is usually done using one of <a href="builtins/targets.html" title="Builtin target types">main target functions</a>.
+ The user can also declare <a href="doc/extending.html#main_target_rules" target="_top">custom main target
+ function</a>.</p>
+<p>Most main targets rules in Boost.Build use similiar
+ syntax:</p>
+<a name="bbv2.main-target-rule-syntax"></a><pre class="programlisting">
+function-name main-target-name
+ : sources
+ : requirements
+ : default-build
+ : usage-requirements
+ ;
+</pre>
+<div class="itemizedlist"><ul type="disc">
+<li>
+ "main-target-name" is the name used to request the target
+ on command line and to use it from other main targets. Main
+ target name may contain alphanumeric characters and symbols '-'
+ and '_';
+ </li>
+<li>
+ "sources" is the list of source files and other main
+ targets that must be combined.
+ </li>
+<li>
+ "requirements" is the list of properties that must always
+ be present when this main target is built.
+ </li>
+<li>
+ "default-build" is the list of properties that will be used
+ unless some other value of the same feature is already
+ specified.
+ </li>
+<li>
+ "usage-requirements" is the list of properties that will be
+ propagated to all main targets that use this one, i.e. to all
+ dependents.
+ </li>
+</ul></div>
+<p>Note that the actual requirements, default-build and
+ usage-requirements attributes for a target are obtained by combining
+ the explicitly specified one with those specified for the project
+ where a target is declared.
+ </p>
+<p>
+ Some main target rules have shorter list of parameters, and
+ you should consult their documentation for details.
+ </p>
+<p>The list of sources specifies what should be processed to get
+ the resulting targets. Most of the time, it's just a list of
+ files. Sometimes, you'd want to use all files with the same
+ extension as sources, in which case you can use the "glob"
+ rule. Here are two examples:
+</p>
+<pre class="programlisting">
+exe a : a.cpp ;
+exe b : [ glob *.cpp ] ;
+</pre>
+<p>
+ Unless you specify a files with absolute path, the name is
+ considered relative to the source directory -- which is typically
+ the same as directory when Jamfile is located, but can be changed as
+ described <a href="jamfiles.html#bbv2.advanced.projects.attributes.projectrule">here</a></p>
+<p>
+ The list of sources can also reference other main targets. The
+ targets in the same project can be referred by using the name, and
+ targets in other project need to specify directory or a symbolic
+ name of the other project. For example:
+</p>
+<pre class="programlisting">
+lib helper : helper.cpp ;
+exe a : a.cpp helper ;
+exe b : b.cpp ..//utils ;
+exe c : c.cpp /boost/program_options//program_opions ;
+</pre>
+<p>
+ The first exe uses the library defined in the same project. The
+ second one uses some target (most likely library) defined by Jamfile
+ one level higher. Finally, the third target uses some <a href="http://boost.org" target="_top">C++ Boost</a> library, using the
+ symbolic name to refer to it. More information about it can be found
+ in <a href="../tutorial/libs.html" title="Libraries and Dependent Targets">tutorial</a> and in
+ <a href="../reference/definitions.html#bbv2.reference.ids" title="Target identifiers and references">target id reference</a>.
+ </p>
+<p>Requirements are the properties that should always be present when
+ building a target. Typically, they are includes and defines:
+</p>
+<pre class="programlisting">
+exe hello : hello.cpp : <include>/opt/boost <define>MY_DEBUG ;
+</pre>
+<p>
+ In special circumstances, other properties can be used, for example if
+ a library does not work if it's shared, or a file can't be compiled
+ with optimization due to a compiler bug, one can use
+</p>
+<pre class="programlisting">
+lib util : util.cpp : <link>static ;
+obj main : main.cpp : <optimization>off ;
+</pre>
+<p>Sometimes, requirements are necessary only for a specific
+ compiler, or build variant. The
+ <a href="../../">conditional
+ properties</a> can be used in that case:
+</p>
+<pre class="programlisting">
+lib util : util.cpp : <toolset>msvc:<link>static ;
+</pre>
+<p>
+ In means when whenever <tt class="computeroutput"><toolset>msvc</tt> property is
+ in build properties, the <tt class="computeroutput"><link>static</tt> property will
+ be included as well. The conditional requirements can be "chained":
+</p>
+<pre class="programlisting">
+lib util : util.cpp : <toolset>msvc:<link>static
+ <link>static:<define>STATIC_LINK ;
+</pre>
+<p>
+ will set of static link and the <tt class="computeroutput">STATIC_LINK</tt> define on the
+ <tt class="computeroutput">msvc</tt> toolset.
+ </p>
+<p>The default-build attribute is
+ a set of properties which should be used if build request does not
+ specify a value. For example:
+</p>
+<pre class="programlisting">
+exe hello : hello.cpp : : <threading>multi ;
+</pre>
+<p>
+ would build the target in multi-threaded mode, unless the user
+ explicitly requests single-threaded version. The difference between
+ requirements and default-build is that requirements cannot be
+ overriden in any way.
+ </p>
+<p>A target of the same name can be declared several times. In that
+ case is declaration is called an
+ <i class="firstterm">alternative</i>. When the target is build, one of
+ the alternatives will be selected and use. Alternatives need not be
+ defined by the same main target rule. The following is OK:
+</p>
+<pre class="programlisting">
+lib helpers : helpers.hpp ;
+alias helpers : helpers.lib : <toolset>msvc ;
+</pre>
+<p>Building of the same main target can differ greatly from
+ platform to platform. For example, you might have different list
+ of sources for different compilers, or different options for those
+ compilers. Two approaches to this are explained in the
+ <a href="../tutorial/conditions.html" title="Conditions and alternatives">tutorial</a>.
+ </p>
+<p>Sometimes a main target is really needed only by some other main
+ target. For example, a rule that declares a test-suite uses a main
+ target that represent test, but those main targets are rarely needed
+ by themself.</p>
+<p>It is possible to declare target inline, i.e. the "sources"
+ parameter may include call to other main rules. For example:</p>
+<pre class="programlisting">
+exe hello : hello.cpp
+ [ obj helpers : helpers.cpp : <optimization>off ] ;
+</pre>
+<p>
+ Will cause "helpers.cpp" to be always compiled without
+ optimization. It's possible to request main targets declared
+ inline, but since they are considered local, they are renamed to
+ "parent-main-target_name..main-target-name". In the example above,
+ to build only helpers, one should run "bjam hello..helpers".
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.advanced.projects"></a>Projects</h3></div></div>
+<div></div>
+</div>
+<p>As mentioned before, targets are grouped into project, and each
+ Jamfile is a separate project. Projects are useful because it allows
+ to group related targets together, define properties common to all
+ those targets, and assign a symbolic name to the project, allowing to
+ easily refer to the targets in the project. Two last goals are
+ accompished with the "project" rule.
+ </p>
+<p>The rule has this syntax
+</p>
+<pre class="programlisting">
+project id : <attributes> ;
+</pre>
+<p>
+ Here, attributes is a sequence of (attribute-name,
+ attribute-value) pairs. The list of attribute names along with its
+ handling is also shown in the table below. For example, it is
+ possible to write:
+</p>
+<pre class="programlisting">
+project tennis
+ : requirements <threading>multi
+ : default-build release
+ ;
+</pre>
+<p>The possible attributes are listed below.</p>
+<p><span class="emphasis"><em>Project id</em></span> is a short way to denote a project, as
+ opposed to the Jamfile's pathname. It is a hierarchical path,
+ unrelated to filesystem, such as "boost/thread". <a href="../reference/definitions.html#bbv2.reference.ids" title="Target identifiers and references">Target references</a> make use of project ids to
+ specify a target.</p>
+<p><span class="emphasis"><em>Source location</em></span> specifies the directory where sources
+ for the project are located.</p>
+<p><span class="emphasis"><em>Project requirements</em></span> are requirements that apply to
+ all the targets in the projects as well as all subprojects.</p>
+<p><span class="emphasis"><em>Default build</em></span> is the build request that should be
+ used when no build request is specified explicitly.</p>
+<p><a name="bbv2.advanced.projects.attributes.projectrule"></a>
+ The default values for those attributes are
+ given in the table below.
+
+ </p>
+<div class="table">
+<a name="id2536169"></a><p class="title"><b>Table 4.1. </b></p>
+<table class="table" summary="">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Attribute</th>
+<th>Name for the 'project' rule</th>
+<th>Default value</th>
+<th>Handling by the 'project' rule</th>
+</tr></thead>
+<tbody>
+<tr>
+<td>Project id</td>
+<td>none</td>
+<td>none</td>
+<td>Assigned from the first parameter of the 'project' rule.
+ It is assumed to denote absolute project id.</td>
+</tr>
+<tr>
+<td>Source location</td>
+<td><tt class="literal">source-location</tt></td>
+<td>The location of jamfile for the project</td>
+<td>Sets to the passed value</td>
+</tr>
+<tr>
+<td>Requirements</td>
+<td><tt class="literal">requirements</tt></td>
+<td>The parent's requirements</td>
+<td>The parent's requirements are refined with the passed
+ requirement and the result is used as the project
+ requirements.</td>
+</tr>
+<tr>
+<td>Default build</td>
+<td><tt class="literal">default-build</tt></td>
+<td>none</td>
+<td>Sets to the passed value</td>
+</tr>
+<tr>
+<td>Build directory</td>
+<td><tt class="literal">build-dir</tt></td>
+<td>If parent has a build dir set, the value of it, joined
+ with the relative path from parent to the current project.
+ Otherwise, empty</td>
+<td>Sets to the passed value, interpreted as relative to the
+ project's location.</td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.advanced.other-rules"></a>Additional Jamfile rules</h3></div></div>
+<div></div>
+</div>
+<p>There's a number of other helper rules which can be used in
+ Jamfile, described in the following table.</p>
+<div class="table">
+<a name="id2536280"></a><p class="title"><b>Table 4.2. </b></p>
+<table class="table" summary="">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Rule</th>
+<th>Semantic</th>
+</tr></thead>
+<tbody>
+<tr>
+<td><a href="jamfiles.html#bbv2.advanced.projects.attributes.projectrule">project</a></td>
+<td>Define project attributes.</td>
+</tr>
+<tr>
+<td><a href="../../">use-project</a></td>
+<td>Make another project known.</td>
+</tr>
+<tr>
+<td><a href="../../">build-project</a></td>
+<td>Build another project when this one is built.</td>
+</tr>
+<tr>
+<td><a href="../../">explicit</a></td>
+<td>States that the target should be built only by explicit
+ request.</td>
+</tr>
+<tr>
+<td>glob</td>
+<td>Takes a list of wildcards, and returns the list of files
+ which match any of the wildcards.</td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.advanced.project-root"></a>Project root</h3></div></div>
+<div></div>
+</div>
+<p>Each project is also associated with <span class="emphasis"><em>project root</em></span>.
+ That's a root for a tree of projects, which specifies some global
+ properties.</p>
+<p>
+ Project root for a projects is the nearest parent directory
+ which contains a file called
+ <tt class="filename">project-root.jam</tt>. That file defines
+ certain properties which apply to all projects under project
+ root. It can:
+
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+ configure toolsets, via call to <tt class="literal">toolset.using</tt>
+</li>
+<li>
+ refer to other projects, via the <tt class="literal">use-project</tt>
+ rule
+ </li>
+<li>
+ declare constants, via the <tt class="literal">constant</tt> and
+ <tt class="literal">path-constant</tt> rules.
+ </li>
+</ul></div>
+<p>To facilitate declaration of simple projects, Jamfile and
+ project-root can be merged together. To achieve this effect, the
+ project root file should call the <tt class="literal">project</tt> rule. The
+ semantic is precisely the same as if the call was made in
+ Jamfile, except that project-root.jam will start to serve as
+ Jamfile. The Jamfile in the directory of project-root.jam will be
+ ignored, and project-root.jam will be able to declare main
+ targets as usual.</p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../advanced.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../advanced.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="build_process.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/advanced.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,168 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 4. User documentation</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="previous" href="tutorial/prebuilt.html" title="Prebuilt targets">
+<link rel="next" href="advanced/jamfiles.html" title="Writing Jamfiles">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="tutorial/prebuilt.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="advanced/jamfiles.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title">
+<a name="bbv2.advanced"></a>Chapter 4. User documentation</h2></div></div>
+<div></div>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><a href="advanced.html#bbv2.advanced.configuration">Configuration</a></dt>
+<dt><a href="advanced/jamfiles.html">Writing Jamfiles</a></dt>
+<dt><a href="advanced/build_process.html">Build process</a></dt>
+<dt><a href="advanced/builtins/targets.html">Builtin target types</a></dt>
+<dt><a href="advanced/builtins/features.html">Builtin features</a></dt>
+<dt><a href="advanced/differences_to_v1.html">Differences to Boost.Build V1</a></dt>
+</dl>
+</div>
+<p>This section will provide the information necessary to create your own
+ projects using Boost.Build. The information provided here is relatively
+ high-level, and <a href="reference.html" title="Chapter 6. Detailed reference">detailed reference</a> as
+ well as the on-line help system must be used to obtain
+ low-level documentation (see the <a href="reference.html#bbv2.reference.init.options.help">help option</a>).</p>
+<p>The Boost.Build actually consists of two parts - Boost.Jam, which is a
+ build engine with its own interpreted language, and Boost.Build itself,
+ implemented in Boost.Jam's language. The chain of event which happen when
+ you type "bjam" on the command is:
+ </p>
+<div class="orderedlist"><ol type="1">
+<li><p>Boost.Jam tries to find Boost.Build and loads the top-level
+ module. The exact process is described in the <a href="reference.html#bbv2.reference.init" title="Initialization">section on
+ initialization</a></p></li>
+<li><p>Boost.Build top-level module loads user-defined configuration
+ files, "user-config.jam" and "site-config.jam", which define
+ available toolsets.</p></li>
+<li><p>The Jamfile in the current directory is read. That in turn
+ might cause reading of further Jamfiles. As a result, a tree of
+ projects is created, with targets inside projects.</p></li>
+<li><p>Finally, using build request specified on the command line,
+ Boost.Build decides which targets should be built, and how. That
+ information is passed back to Boost.Jam, which takes care of
+ actually running commands.</p></li>
+</ol></div>
+<p>So, to be able to successfully use Boost.Build, you'd need to know only
+ three things:
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li><p><a href="advanced.html#bbv2.advanced.configuration" title="Configuration">
+ How to configure Boost.Build</a></p></li>
+<li><p><a href="advanced/jamfiles.html" title="Writing Jamfiles">
+ How to write Jamfiles</a></p></li>
+<li><p><a href="advanced/build_process.html" title="Build process">
+ How the build process works</a></p></li>
+</ul></div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.advanced.configuration"></a>Configuration</h2></div></div>
+<div></div>
+</div>
+<p>The Boost.Build configuration is specified in the file
+ "user-config.jam". You can edit the one which comes with Boost.Build, or
+ create a copy in your home directory and edit that. (See the <a href="reference.html#bbv2.reference.init.config" title="Table 6.1. Search paths for configuration files">reference</a> for the exact search
+ paths.) The primary function of that file is to declarate which compilers
+ and other tools are available. The simplest syntax to configure a tool is:
+</p>
+<pre class="programlisting">
+using <tool-name> ;
+</pre>
+<p>
+ The "using" rule is given a name of tool, and will make that tool
+ available to Boost.Build. For example, "using gcc ;" will make available
+ the gcc compiler.
+ </p>
+<p>
+ Since nothing but tool name is specified, Boost.Build will pick some
+ default settings -- for example will use gcc found in path, or look in
+ some known installation locations. For ordinary users, this is quite
+ fine. In case you have several version of a compiler, or it's located in
+ some unusual location, or you need to tweak the configuration, you'd
+ need to pass additional parameters to the "using" rule. Generally,
+ for every tool module, the parameters differ, and you can obtain the documentaiton
+ by running
+</p>
+<pre class="programlisting">
+bjam --help <tool-name>.init
+</pre>
+<p>
+ on the command line. However, for all compilers the meaning of the first
+ three parameters is the same: version, invocation command and options.
+ </p>
+<p>The "version" parameter identifies the compiler, in case you have
+ several. It can have any form you like, but it's recommended that you use
+ a numeric identifier, like "7.1". The "invocation command"
+ parameter is the command which must be executed to run the compiler. This
+ might be just compiler name, or a name with a path in it. Here are some
+ examples.
+ </p>
+<p>To configure a compiler installed in non-standard location and not
+ present in path, you can do the following:
+</p>
+<pre class="programlisting">
+using msvc : : Z:/Programs/Microsoft Visual Studio/vc98/bin/cl.exe ;
+</pre>
+<p>To configure several versions of a compiler, the following can be used.
+</p>
+<pre class="programlisting">
+using gcc : 3.3 ;
+using gcc : 3.4 : g++-3.4 ;
+using gcc : 3.2 : g++-3.2 ;
+</pre>
+<p>
+ Note that in the first call to "using", the compiler found in path
+ will be used, and there's no need to explicitly specify the command.
+ </p>
+<p>As shown above, both "version" and "invocation command" parameters
+ are optional, but there's an important restriction: if you configure the
+ same compiler more then once, you must pass the "version" parameter
+ every time. For example, the following is not allowed:
+</p>
+<pre class="programlisting">
+using gcc ;
+using gcc : 3.4 : g++-3.4 ;
+</pre>
+<p>
+ because the first "using" does not specify the version.
+ </p>
+<p>The <tt class="computeroutput">options</tt> parameter is used to fine-tune the
+ configuration. All compilers allow to pass four option, intentionally
+ similiar in spelling to builtin features: <tt class="computeroutput">cflags</tt>,
+ <tt class="computeroutput">cxxflags</tt>, <tt class="computeroutput">compileflags</tt> and
+ <tt class="computeroutput">linkflags</tt>. They specify additional options which will be
+ always passed to the corresponding tools. The <tt class="computeroutput">cflags</tt> option
+ applies only to the C compiler, the <tt class="computeroutput">cxxflags</tt> option applies
+ only to the C++ compiler and the <tt class="computeroutput">compileflags</tt> options
+ applies to both. For example, to use 64 bit mode with gcc you can use:
+</p>
+<pre class="programlisting">
+using gcc : 3.4 : : <compileflags>-m64 <linkflags>-m64 ;
+</pre>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="tutorial/prebuilt.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="advanced/jamfiles.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/build.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/build.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/build.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,116 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>The build layer</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../arch.html" title="Appendix A. Boost.Build v2 architecture">
+<link rel="previous" href="../arch.html" title="Appendix A. Boost.Build v2 architecture">
+<link rel="next" href="tools.html" title="The tools layer">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../arch.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../arch.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="tools.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.arch.build"></a>The build layer</h2></div></div>
+<div></div>
+</div>
+<p>The build layer has just four main parts -- abstract targets,
+ virtual targets, generators and properties. The abstract targets,
+ represented by the "abstract-target" class, correspond to main targets
+ -- which, as you recall, can produce different files depending on
+ properties. Virtual targets, represented by the 'virtual-target' class
+ correspond to real files. The abstract-target class has a method
+ 'generate', which is given a set of properties and produces virtual
+ targets for those properties.
+ </p>
+<p>There are several classes derived from "abstract-target". The
+ "main-target" class represents top-level main target, the "project-target"
+ acts like container for all main targets, and "basic-target" class is a
+ base class for all further target types.
+ </p>
+<p>Since each main target can have several alternatives, all top-level
+ target objects are just containers, referring to "real" main target
+ classes. The type is that container is "main-target". For example, given:
+</p>
+<pre class="programlisting">
+alias a ;
+lib a : a.cpp : <toolset>gcc ;
+</pre>
+<p>
+ we would have one-top level instance of "main-target-class", which will
+ contain one instance of "alias-target-class" and one instance of
+ "lib-target-class". The "generate" method of "main-target" decides
+ which of the alternative should be used, and call "generate" on the
+ corresponding instance.
+</p>
+<p>Each alternative is a instance of a class derived from
+ "basic-target". The "basic-target.generate" does several things that are
+ always should be done:
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li><p>Determines what properties should be used for building the
+ target. This includes looking at requested properties, requirements,
+ and usage requirements of all sources.</p></li>
+<li><p>Builds all sources</p></li>
+<li><p>Computes the usage requirements which should be passes back.</p></li>
+</ul></div>
+<p>
+ For the real work of constructing virtual target, a new method
+ "construct" is called.
+ </p>
+<p>The "construct" method can be implemented in any way by classes
+ derived from "basic-target", but one specific derived class plays the
+ central role -- "typed-target". That class holds the desired type of file
+ to be produces, and calls the generators modules to do the job.
+ </p>
+<p>Generators are Boost.Build abstractions for a tool. For example, one
+ can register a generator which converts target of type CPP into target of
+ type OBJ. When run with on a virtual target with CPP type, the generator
+ will construct the virtual target of type OBJ. The "generators" module
+ implements an algorithm, which given a list of sources, the desired type
+ and a list of properties, find all the generators which can perform the conversion.
+ </p>
+<p>The virtual targets which are produces by the main targets form a
+ graph. Targets which are produces from other ones refer to an instance of
+ "action" class, which in turn refers to action's sources, which can
+ further refer to actions. The sources, which are not produces from
+ anything, don't refer to any actions.
+ </p>
+<p>When all virtual targets are produced, they are "actualized". This
+ means that the real file names are computed, and the commands that should
+ be run are generated. This is done by "virtual-target.actualize" and
+ "action.actualize" methods. The first is conceptually simple, while the
+ second need additional explanation. The commands in bjam are generated in
+ two-stage process. First, a rule with the appropriate name (for example
+ "gcc.compile") is called and is given the names of targets. The rule sets
+ some variables, like "OPTIONS". After that, the command string is taken,
+ and variable are substitutes, so use of OPTIONS inside the command string
+ become the real compile options.
+ </p>
+<p>Boost.Build added a third stage to simplify things. It's now
+ possible to automatically convert properties to appropriate assignments to
+ variables. For example, <debug-symbols>on would add "-g" to the
+ OPTIONS variable, without requiring to manually add this logic to
+ gcc.compile. This functionality is part of the "toolset" module.
+ </p>
+<p>When target paths are computed and the commands are set, Boost.Build
+ just gives control to bjam, which controls the execution of
+ commands.</p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../arch.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../arch.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="tools.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/targets.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/targets.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/targets.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,406 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Targets</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../arch.html" title="Appendix A. Boost.Build v2 architecture">
+<link rel="previous" href="tools.html" title="The tools layer">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="tools.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../arch.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.arch.targets"></a>Targets</h2></div></div>
+<div></div>
+</div>
+<div class="toc"><dl><dt><a href="targets.html#bbv2.arch.depends">Dependency scanning</a></dt></dl></div>
+<p>NOTE: THIS SECTION IS NOT EXPECTED TO BE READ!
+ There are two user-visible kinds of targets in Boost.Build.
+ First are "abstract" — they correspond to things declared
+ by user, for example, projects and executable files. The primary
+ thing about abstract target is that it's possible to request them
+ to be build with a particular values of some properties. Each
+ combination of properties may possible yield different set of
+ real file, so abstract target do not have a direct correspondence
+ with files.</p>
+<p>File targets, on the contary, are associated with concrete
+ files. Dependency graphs for abstract targets with specific
+ properties are constructed from file targets. User has no was to
+ create file targets, however it can specify rules that detect
+ file type for sources, and also rules for transforming between
+ file targets of different types. That information is used in
+ constructing dependency graph, as desribed in the "next section".
+ [ link? ] <span class="bold"><b>Note:</b></span>File targets are not
+ the same as targets in Jam sense; the latter are created from
+ file targets at the latest possible moment. <span class="bold"><b>Note:</b></span>"File
+ target" is a proposed name for what we call virtual targets. It
+ it more understandable by users, but has one problem: virtual
+ targets can potentially be "phony", and not correspond to any
+ file.</p>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.arch.depends"></a>Dependency scanning</h3></div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="targets.html#id2541586">Support for different scanning algorithms</a></dt>
+<dt><a href="targets.html#id2541595">Ability to scan the same file several times</a></dt>
+<dt><a href="targets.html#id2541654">Proper detection of dependencies on generated files.</a></dt>
+<dt><a href="targets.html#id2541833">Proper detection of dependencies from generated files</a></dt>
+</dl></div>
+<p>Dependency scanning is the process of finding implicit
+ dependencies, like "#include" statements in C++. The requirements
+ for right dependency scanning mechanism are:</p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+ Support for different scanning algorithms. C++ and XML have
+ quite different syntax for includes and rules for looking up
+ included files.
+ </li>
+<li>
+ Ability to scan the same file several times. For example,
+ single C++ file can be compiled with different include
+ paths.
+ </li>
+<li>
+ Proper detection of dependencies on generated files.
+ </li>
+<li>
+ Proper detection of dependencies from generated file.
+ </li>
+</ul></div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h4 class="title">
+<a name="id2541586"></a>Support for different scanning algorithms</h4></div></div>
+<div></div>
+</div>
+<p>Different scanning algorithm are encapsulated by objects
+ called "scanners". Please see the documentation for "scanner"
+ module for more details.</p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h4 class="title">
+<a name="id2541595"></a>Ability to scan the same file several times</h4></div></div>
+<div></div>
+</div>
+<p>As said above, it's possible to compile a C++ file twice, with
+ different include paths. Therefore, include dependencies for
+ those compilations can be different. The problem is that bjam
+ does not allow several scans of the same target.</p>
+<p>The solution in Boost.Build is straigtforward. When a virtual
+ target is converted to bjam target (via
+ <tt class="literal">virtual-target.actualize</tt> method), we specify the scanner
+ object to be used. The actualize method will create different
+ bjam targets for different scanners.</p>
+<p>All targets with specific scanner are made dependent on target
+ without scanner, which target is always created. This is done in
+ case the target is updated. The updating action will be
+ associated with target without scanner, but if sources for that
+ action are touched, all targets — with scanner and without
+ should be considered outdated.</p>
+<p>For example, assume that "a.cpp" is compiled by two compilers
+ with different include path. It's also copied into some install
+ location. In turn, it's produced from "a.verbatim". The
+ dependency graph will look like:</p>
+<pre class="programlisting">
+a.o (<toolset>gcc) <--(compile)-- a.cpp (scanner1) ----+
+a.o (<toolset>msvc) <--(compile)-- a.cpp (scanner2) ----|
+a.cpp (installed copy) <--(copy) ----------------------- a.cpp (no scanner)
+ ^
+ |
+ a.verbose --------------------------------+
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h4 class="title">
+<a name="id2541654"></a>Proper detection of dependencies on generated files.</h4></div></div>
+<div></div>
+</div>
+<p>This requirement breaks down to the following ones.</p>
+<div class="orderedlist"><ol type="1">
+<li>
+ If when compiling "a.cpp" there's include of "a.h", the
+ "dir" directory is in include path, and a target called "a.h"
+ will be generated to "dir", then bjam should discover the
+ include, and create "a.h" before compiling "a.cpp".
+ </li>
+<li>
+ Since almost always Boost.Build generates targets to a
+ "bin" directory, it should be supported as well. I.e. in the
+ scanario above, Jamfile in "dir" might create a main target,
+ which generates "a.h". The file will be generated to "dir/bin"
+ directory, but we still have to recornize the dependency.
+ </li>
+</ol></div>
+<p>The first requirement means that when determining what "a.h"
+ means, when found in "a.cpp", we have to iterate over all
+ directories in include paths, checking for each one:</p>
+<div class="orderedlist"><ol type="1">
+<li>
+ If there's file "a.h" in that directory, or
+ </li>
+<li>
+ If there's a target called "a.h", which will be generated
+ to that directory.
+ </li>
+</ol></div>
+<p>Classic Jam has built-in facilities for point (1) above, but
+ that's not enough. It's hard to implement the right semantic
+ without builtin support. For example, we could try to check if
+ there's targer called "a.h" somewhere in dependency graph, and
+ add a dependency to it. The problem is that without search in
+ include path, the semantic may be incorrect. For example, one can
+ have an action which generated some "dummy" header, for system
+ which don't have the native one. Naturally, we don't want to
+ depend on that generated header on platforms where native one is
+ included.</p>
+<p>There are two design choices for builtin support. Suppose we
+ have files a.cpp and b.cpp, and each one includes header.h,
+ generated by some action. Dependency graph created by classic jam
+ would look like:</p>
+<pre class="programlisting">
+a.cpp -----> <scanner1>header.h [search path: d1, d2, d3]
+
+
+ <d2>header.h --------> header.y
+ [generated in d2]
+
+b.cpp -----> <scanner2>header.h [ search path: d1, d2, d4]
+</pre>
+<p>
+In this case, Jam thinks all header.h target are not
+realated. The right dependency graph might be:
+
+</p>
+<pre class="programlisting">
+a.cpp ----
+ \
+ \
+ >----> <d2>header.h --------> header.y
+ / [generated in d2]
+ /
+b.cpp ----
+</pre>
+<p>
+
+or
+
+</p>
+<pre class="programlisting">
+a.cpp -----> <scanner1>header.h [search path: d1, d2, d3]
+ |
+ (includes)
+ V
+ <d2>header.h --------> header.y
+ [generated in d2]
+ ^
+ (includes)
+ |
+b.cpp -----> <scanner2>header.h [ search path: d1, d2, d4]
+</pre>
+<p>
+The first alternative was used for some time. The problem
+however is: what include paths should be used when scanning
+header.h? The second alternative was suggested by Matt Armstrong.
+It has similiar effect: add targets which depend on
+<scanner1>header.h will also depend on <d2>header.h.
+But now we have two different target with two different scanners,
+and those targets can be scanned independently. The problem of
+first alternative is avoided, so the second alternative is
+implemented now.
+ </p>
+<p>The second sub-requirements is that targets generated to "bin"
+ directory are handled as well. Boost.Build implements
+ semi-automatic approach. When compiling C++ files the process
+ is:</p>
+<div class="orderedlist"><ol type="1">
+<li>
+ The main target to which compiled file belongs is found.
+ </li>
+<li>
+ All other main targets that the found one depends on are
+ found. Those include main target which are used as sources, or
+ present as values of "dependency" features.
+ </li>
+<li>
+ All directories where files belonging to those main target
+ will be generated are added to the include path.
+ </li>
+</ol></div>
+<p>After this is done, dependencies are found by the approach
+ explained previously.</p>
+<p>Note that if a target uses generated headers from other main
+ target, that main target should be explicitly specified as
+ dependency property. It would be better to lift this requirement,
+ but it seems not very problematic in practice.</p>
+<p>For target types other than C++, adding of include paths must
+ be implemented anew.</p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h4 class="title">
+<a name="id2541833"></a>Proper detection of dependencies from generated files</h4></div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="targets.html#id2541934">File targets</a></dt>
+<dt><a href="targets.html#id2541969">Target paths</a></dt>
+</dl></div>
+<p>Suppose file "a.cpp" includes "a.h" and both are generated by
+ some action. Note that classic jam has two stages. In first stage
+ dependency graph graph is build and actions which should be run
+ are determined. In second stage the actions are executed.
+ Initially, neither file exists, so the include is not found. As
+ the result, jam might attempt to compile a.cpp before creating
+ a.h, and compilation will fail.</p>
+<p>The solution in Boost.Jam is to perform additional dependency
+ scans after targets are updated. This break separation between
+ build stages in jam — which some people consider a good
+ thing — but I'm not aware of any better solution.</p>
+<p>In order to understand the rest of this section, you better
+ read some details about jam dependency scanning, available
+ <a href="http://public.perforce.com:8080/@md=d&cd=//public/jam/src/&ra=s&c=kVu@//2614?ac=10" target="_top">
+ at this link</a>.</p>
+<p>Whenever a target is updated, Boost.Jam rescans it for
+ includes. Consider this graph, created before any actions are
+ run.</p>
+<pre class="programlisting">
+A -------> C ----> C.pro
+ /
+B --/ C-includes ---> D
+</pre>
+<p>
+Both A and B have dependency on C and C-includes (the latter
+dependency is not shown). Say during building we've tried to create
+A, then tried to create C and successfully created C.
+ </p>
+<p>In that case, the set of includes in C might well have
+ changed. We do not bother to detect precisely which includes were
+ added or removed. Instead we create another internal node
+ C-includes-2. Then we determine what actions should be run to
+ update the target. In fact this mean that we perform logic of
+ first stage while already executing stage.</p>
+<p>After actions for C-includes-2 are determined, we add
+ C-includes-2 to the list of A's dependents, and stage 2 proceeds
+ as usual. Unfortunately, we can't do the same with target B,
+ since when it's not visited, C target does not know B depends on
+ it. So, we add a flag to C which tells and it was rescanned. When
+ visiting B target, the flag is notices and C-includes-2 will be
+ added to the list of B's dependencies.</p>
+<p>Note also that internal nodes are sometimes updated too.
+ Consider this dependency graph:</p>
+<pre class="programlisting">
+a.o ---> a.cpp
+ a.cpp-includes --> a.h (scanned)
+ a.h-includes ------> a.h (generated)
+ |
+ |
+ a.pro <-------------------------------------------+
+</pre>
+<p>Here, out handling of generated headers come into play. Say
+ that a.h exists but is out of date with respect to "a.pro", then
+ "a.h (generated)" and "a.h-includes" will be marking for
+ updating, but "a.h (scanned)" won't be marked. We have to rescan
+ "a.h" file after it's created, but since "a.h (generated)" has no
+ scanner associated with it, it's only possible to rescan "a.h"
+ after "a.h-includes" target was updated.</p>
+<p>Tbe above consideration lead to decision that we'll rescan a
+ target whenever it's updated, no matter if this target is
+ internal or not.</p>
+<div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+<p>
+ The remainder of this document is not indended to be read at
+ all. This will be rearranged in future.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h5 class="title">
+<a name="id2541934"></a>File targets</h5></div></div>
+<div></div>
+</div>
+<p>
+ As described above, file targets corresponds
+ to files that Boost.Build manages. User's may be concerned about
+ file targets in three ways: when declaring file target types,
+ when declaring transformations between types, and when
+ determining where file target will be placed. File targets can
+ also be connected with actions, that determine how the target is
+ created. Both file targets and actions are implemented in the
+ <tt class="literal">virtual-target</tt> module.
+ </p>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h6 class="title">
+<a name="id2541953"></a>Types</h6></div></div>
+<div></div>
+</div>
+<p>A file target can be given a file, which determines
+ what transformations can be applied to the file. The
+ <tt class="literal">type.register</tt> rule declares new types. File type can
+ also be assigned a scanner, which is used to find implicit
+ dependencies. See "dependency scanning" [ link? ] below.</p>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h5 class="title">
+<a name="id2541969"></a>Target paths</h5></div></div>
+<div></div>
+</div>
+<p>To distinguish targets build with different properties, they
+ are put in different directories. Rules for determining target
+ paths are given below:</p>
+<div class="orderedlist"><ol type="1">
+<li>
+ All targets are placed under directory corresponding to the
+ project where they are defined.
+ </li>
+<li>
+ Each non free, non incidental property cause an additional
+ element to be added to the target path. That element has the
+ form <tt class="literal"><feature-name>-<feature-value></tt> for
+ ordinary features and <tt class="literal"><feature-value></tt> for
+ implicit ones. [Note about composite features].
+ </li>
+<li>
+ If the set of free, non incidental properties is different
+ from the set of free, non incidental properties for the project
+ in which the main target that uses the target is defined, a
+ part of the form <tt class="literal">main_target-<name></tt> is added to
+ the target path. <span class="bold"><b>Note:</b></span>It would be nice to completely
+ track free features also, but this appears to be complex and
+ not extremely needed.
+ </li>
+</ol></div>
+<p>For example, we might have these paths:</p>
+<pre class="programlisting">
+debug/optimization-off
+debug/main-target-a
+</pre>
+</div>
+</div>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="tools.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../arch.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/tools.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/tools.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch/tools.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,35 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>The tools layer</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../arch.html" title="Appendix A. Boost.Build v2 architecture">
+<link rel="previous" href="build.html" title="The build layer">
+<link rel="next" href="targets.html" title="Targets">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="build.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../arch.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="targets.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.arch.tools"></a>The tools layer</h2></div></div>
+<div></div>
+</div>
+<p>Write me!</p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="build.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../arch.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="targets.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/arch.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,61 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Appendix A. Boost.Build v2 architecture</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="previous" href="recipies/site-config.html" title="Targets in site-config.jam">
+<link rel="next" href="arch/build.html" title="The build layer">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="recipies/site-config.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="arch/build.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="appendix" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title">
+<a name="bbv2.arch"></a>Appendix A. Boost.Build v2 architecture</h2></div></div>
+<div></div>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><a href="arch.html#bbv2.arch.overview">Overview</a></dt>
+<dt><a href="arch/build.html">The build layer</a></dt>
+<dt><a href="arch/tools.html">The tools layer</a></dt>
+<dt><a href="arch/targets.html">Targets</a></dt>
+</dl>
+</div>
+<div class="sidebar"><p>This document is work-in progress. Don't expect much from it
+ yet.</p></div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.arch.overview"></a>Overview</h2></div></div>
+<div></div>
+</div>
+<p>The Boost.Build code is structured in four different components:
+ "kernel", "util", "build" and "tools". The first two are relatively
+ uninteresting, so we'll focus on the remaining pair. The "build" component
+ provides classes necessary to declare targets, determine which properties
+ should be used for their building, and for creating the dependency
+ graph. The "tools" component provides user-visible functionality. It
+ mostly allows to declare specific kind of main targets, and declare
+ avaiable tools, which are then used when creating the dependency graph.
+ </p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="recipies/site-config.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="arch/build.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extender.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extender.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extender.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,122 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 5. Extender Manual</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="previous" href="advanced/differences_to_v1.html" title="Differences to Boost.Build V1">
+<link rel="next" href="extending/targets.html" title="Target types">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="advanced/differences_to_v1.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="extending/targets.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title">
+<a name="bbv2.extender"></a>Chapter 5. Extender Manual</h2></div></div>
+<div></div>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><a href="extender.html#bbv2.extender.intro">Introduction</a></dt>
+<dt><a href="extending/targets.html">Target types</a></dt>
+<dt><a href="extending/tools.html">Tools and generators</a></dt>
+<dt><a href="extending/features.html">Features</a></dt>
+<dt><a href="extending/rules.html">Main target rules</a></dt>
+<dt><a href="extending/toolset_modules.html">Toolset modules</a></dt>
+</dl>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.extender.intro"></a>Introduction</h2></div></div>
+<div></div>
+</div>
+<p>This document explains how to extend Boost.Build to accomodate
+ your local requirements. Let's start with quite simple, but
+ realistic example.</p>
+<p>Say you're writing an application which generates C++ code. If
+ you ever did this, you know that it's not nice. Embedding large
+ portions of C++ code in string literals is very awkward. A much
+ better solution is:</p>
+<div class="orderedlist"><ol type="1">
+<li>
+ Write the template of the code to be generated, leaving
+ placeholders at the points which will change
+ </li>
+<li>
+ Access the template in your application and replace
+ placeholders with appropriate text.
+ </li>
+<li>Write the result.</li>
+</ol></div>
+<p>It's quite easy to achieve. You write special verbatim files,
+ which are just C++, except that the very first line of the file
+ gives a name of variable that should be generated. A simple tool
+ is created which takes verbatim file and creates a cpp file with
+ a single char* variable, which name is taken from the first line
+ of verbatim file, and which value is properly quoted content of
+ the verbatim file.</p>
+<p>Let's see what Boost.Build can do.</p>
+<p>First off, Boost.Build has no idea about "verbatim files". So,
+ you must register a new type. The following code does it:</p>
+<pre class="programlisting">
+import type ;
+type.register VERBATIM : verbatim ;
+</pre>
+<p>The first parameter to 'type.register' gives the name of
+ declared type. By convention, it's uppercase. The second
+ parameter is suffix for this type. So, if Boost.Build sees
+ "code.verbatim" in the list of sources, it knows that it's of
+ type <tt class="literal">VERBATIM</tt>.</p>
+<p>Lastly, you need a tool to convert verbatim files to C++. Say
+ you've sketched such a tool in Python. Then, you have to inform
+ Boost.Build about the tool. The Boost.Build concept which
+ represents a tool is <span class="emphasis"><em>generator</em></span>.</p>
+<p>First, you say that generator 'inline-file' is able to convert
+ VERBATIM type into C++:</p>
+<pre class="programlisting">
+import generators ;
+generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
+</pre>
+<p>Second, you must specify the commands to be run to actually
+ perform convertion:</p>
+<pre class="programlisting">
+actions inline-file
+{
+ "./inline-file.py" $(<) $(>)
+}
+</pre>
+<p>Now, we're ready to tie it all together. Put all the code
+ above in file "verbatim.jam", add "import verbatim ;" to
+ "project-root.jam", and it's possible to write the following in
+ Jamfile:</p>
+<pre class="programlisting">
+exe codegen : codegen.cpp class_template.verbatim usage.verbatim ;
+</pre>
+<p>
+The verbatim files will be automatically converted into C++
+and linked it.
+ </p>
+<p>In the subsequent sections, we will extend this example, and review
+ all the mechanisms in detail. The complete code is available in <a href="../../example/customization" target="_top">example/customization</a>
+ directory.
+ </p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="advanced/differences_to_v1.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="extending/targets.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/features.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/features.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/features.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,235 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Features</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../extender.html" title="Chapter 5. Extender Manual">
+<link rel="previous" href="tools.html" title="Tools and generators">
+<link rel="next" href="rules.html" title="Main target rules">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="tools.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../extender.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="rules.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.extending.features"></a>Features</h2></div></div>
+<div></div>
+</div>
+<p>
+ Often, we need to control the options passed the invoked tools. This
+ is done with features. Consider an example:
+</p>
+<pre class="programlisting">
+# Declare a new feature
+import feature : feature ;
+feature verbatim-options : : free ;
+
+# Cause the value of the 'verbatim-options' feature to be
+# available as 'OPTIONS' variable inside verbatim.inline-file
+import toolset : flags ;
+flags verbatim.inline-file OPTIONS <verbatim-options> ;
+
+# Use the "OPTIONS" variable
+actions inline-file
+{
+ "./inline-file.py" $(OPTIONS) $(<) $(>)
+}
+</pre>
+<p>
+ We first define a new feature. Then, the <tt class="computeroutput">flags</tt> invocation
+ says that whenever verbatin.inline-file action is run, the value of
+ the <tt class="computeroutput">verbatim-options</tt> feature will be added to the
+ <tt class="computeroutput">OPTIONS</tt> variable, an can be used inside the action body.
+ You'd need to consult online help (--help) to find all the features of
+ the <tt class="computeroutput">toolset.flags</tt> rule.
+ </p>
+<p>
+ Although you can define any set of features and interpret their values
+ in any way, Boost.Build suggests the following coding standard for
+ designing features.
+ </p>
+<p>Most features should have a fixed set of values, which is portable
+ (tool neutral) across the class of tools they are designed to work
+ with. The user does not have to adjust the values for a exact tool. For
+ example, <tt class="computeroutput"><optimization>speed</tt> has the same meaning for
+ all C++ compilers and the user does not have to worry about the exact
+ options which are passed to the compiler's command line.
+ </p>
+<p>
+ Besides such portable features there are special 'raw' features which
+ allow the user to pass any value to the command line parameters for a
+ particular tool, if so desired. For example, the
+ <tt class="computeroutput"><cxxflags></tt> feature allows to pass any command line
+ options to a C++ compiler. The <tt class="computeroutput"><include></tt> feature
+ allows to pass any value to the <tt class="computeroutput">-I</tt> and the interpretation
+ is tool-specific. (There an <a href="../faq/external.html" title="Can I get output of external program as a variable in a Jamfile?
+ ">example</a> of very smart usage of that
+ feature). Of course one should always strive to use the portable
+ features but these should still be provided as a backdoor just to make
+ sure Boost.Build does not take away any control from the user.
+ </p>
+<p>
+ Some of the reasons why portable features are better are:
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li><p>Since a portable feature have a fixed set of value, you will
+ be able to build your project with two different settings of the
+ feature. Boost.Build will automatically use two different
+ directories for produced files. If you pass raw compiler options,
+ Boost.Build assumes you know what you are doing, and would not
+ care about what options are passed.
+ </p></li>
+<li><p>Unlike "raw" features, you don't need to use specific
+ compiler flags in Jamfile, and it will more likely work on other systems.
+ </p></li>
+</ul></div>
+<h3>
+<a name="id2538586"></a>Steps for adding a feauture</h3>
+<p>Adding a feature requires three steps:
+
+ </p>
+<div class="orderedlist"><ol type="1">
+<li>
+<p>Declaring a feature. For that, the "feature.feature"
+ rule is used. You should have to decide on the set of <a href="../reference/definitions.html#bbv2.reference.features.attributes" title="Feature Attributes">feature
+ attributes</a>:
+
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li><p>if feature has several values, and
+ significally affects build, make it "propagated", so that
+ whole project is build with the same value by
+ default</p></li>
+<li><p>if a feature does not have a fixed list of
+ values, it must be "free".</p></li>
+<li><p>if feature is used to refer to a path, it must
+ be "path".</p></li>
+<li><p>if feature is used to refer to some target, it
+ must be "dependency".</p></li>
+</ul></div>
+</li>
+<li><p>Converting the feature value into variable. To use
+ feature in build action, it must be converted into a variable,
+ accessible in build action. This is accomplished by
+ "toolset.flags" rule.</p></li>
+<li><p>Using the variable. The variable set in step 2 can
+ be used in build action to form command parameters or
+ files.</p></li>
+</ol></div>
+<h3>
+<a name="id2538645"></a>Another example</h3>
+<p>Here's an another example.
+ Let's see how we can make a feature which refers to a target. For example,
+ when linking dynamic libraries on windows, one sometimes needs to specify
+ "DEF file", telling what functions should be exported. It would be nice to
+ use this file like this:
+</p>
+<pre class="programlisting">
+ lib a : a.cpp : <def-file>a.def ;
+</pre>
+<p>
+ Actually, this feature is already supported, but anyway...
+ </p>
+<div class="orderedlist"><ol type="1">
+<li>
+<p>Since the feature refers to a target, it must be "dependency".
+</p>
+<pre class="programlisting">
+feature def-file : : free dependency ;
+</pre>
+</li>
+<li>
+<p>One of the toolsets which cares about DEF files is
+msvc. The following line should be added to it.
+
+</p>
+<pre class="programlisting">
+flags msvc.link DEF_FILE <def-file> ;
+</pre>
+</li>
+<li>
+<p>Since the DEF_FILE variable is not used by the
+msvc.link action, we need to modify it to be:
+
+</p>
+<pre class="programlisting">
+actions link bind DEF_FILE
+{
+ $(.LD) .... /DEF:$(DEF_FILE) ....
+}
+</pre>
+<p> Note the "bind DEF_FILE" part. It tells bjam that DEF_FILE
+ refers to a file, otherwise the variable will contain internal
+ target name, which is not likely to make sense for the linker.
+ </p>
+<p>
+ We've almost done, but should stop for a small workaround. Add the following
+ code to msvc.jam
+
+</p>
+<pre class="programlisting">
+rule link
+{
+ DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
+}
+</pre>
+<p>
+
+ This is needed to accomodate some bug in bjam, which hopefully
+ will be fixed one day.</p>
+</li>
+</ol></div>
+<h3>
+<a name="id2538721"></a>Variants and composite features.</h3>
+<p>Sometimes you want to create a shorcut for some set of
+ features. For example, <tt class="computeroutput">release</tt> is a value of the
+ <tt class="computeroutput">variant</tt> and is a shortcut for a set of features.
+ </p>.
+
+ <p>It is possible to define your build variants. For example:
+</p>
+<pre class="programlisting">
+variant crazy : <optimization>speed <inlining>off
+ <debug-symbols>on <profiling>on ;
+</pre>
+<p>
+ will define a new variant with the specified set of properties. You
+ can also extend an existing variant:
+</p>
+<pre class="programlisting">
+variant super_release : release : <define>USE_ASM ;
+</pre>
+<p>
+ In this case, <tt class="computeroutput">super_release</tt> will expand to all properties
+ specified by <tt class="computeroutput">release</tt>, and the additional one you've specified.
+ </p>
+<p>You are not restricted to using the <tt class="computeroutput">variant</tt> feature
+ only. Here's example which defines a brand new feature:
+</p>
+<pre class="programlisting">
+feature parallelism : mpi fake none : composite link-incompatible ;
+feature.compose <parallelism>mpi : <library>/mpi//mpi/<parallelism>none ;
+feature.compose <parallelism>fake : <library>/mpi//fake/<parallelism>none ;
+</pre>
+<p>
+ This will allow you to specify value of feature
+ <tt class="computeroutput">parallelism</tt>, which will expand to link to the necessary
+ library.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="tools.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../extender.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="rules.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/rules.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/rules.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/rules.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,89 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Main target rules</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../extender.html" title="Chapter 5. Extender Manual">
+<link rel="previous" href="features.html" title="Features">
+<link rel="next" href="toolset_modules.html" title="Toolset modules">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="features.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../extender.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="toolset_modules.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.extending.rules"></a>Main target rules</h2></div></div>
+<div></div>
+</div>
+<p>
+ The main target rule is what creates a top-level target, for example "exe" or
+ "lib". It's quite likely that you'll want to declare your own and
+ there are as many as three ways to do that.
+ </p>
+<p>The first is the simplest, but is sufficient in a number of
+ cases. Just write a wrapper rule, which will redirect to any of the
+ existing rules. For example, you have only one library per directory and
+ want all cpp files in the directory to be compiled. You can achieve this
+ effect with:
+</p>
+<pre class="programlisting">
+lib codegen : [ glob *.cpp ] ;
+</pre>
+<p>
+ but what if you want to make it even simple. Then, you add the following
+ definition to the project-root.jam file:
+</p>
+<pre class="programlisting">
+rule glib ( name : extra-sources * : requirements * )
+{
+ lib $(name) : [ glob *.cpp ] $(extra-sources) : $(requirements) ;
+}
+</pre>
+<p>
+which would allow to reduce Jamfile to
+</p>
+<pre class="programlisting">
+glib codegen ;
+</pre>
+<p>The second approach is suitable when your target rule should just
+ produce a target of specific type. Then, when declaring a type you
+ should tell Boost.Build that a main target rule should be created.
+ For example, if you create a module "obfuscate.jam" containing:
+
+</p>
+<pre class="programlisting">
+import type ;
+type.register OBFUSCATED_CPP : ocpp : : main ;
+
+import generators ;
+generators.register-standard obfuscate.file : CPP : OBFUSCATED_CPP ;
+</pre>
+<p>
+ and import that module, you'll be able to use the rule "obfuscated-cpp"
+ in Jamfiles, which will convert source to the OBFUSCATED_CPP type.
+ </p>
+<p>
+ The remaining method is to declare your own main target class. The
+ simplest example of this can be found in "build/alias.jam" file. The
+ current V2 uses this method when transformations are relatively
+ complex. However, we might deprecate this approach. If you find that you
+ need to use it (that is, the first two approaches are not sufficient),
+ please let us know by posting to the mailing list.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="features.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../extender.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="toolset_modules.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/targets.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/targets.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/targets.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,112 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Target types</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../extender.html" title="Chapter 5. Extender Manual">
+<link rel="previous" href="../extender.html" title="Chapter 5. Extender Manual">
+<link rel="next" href="tools.html" title="Tools and generators">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../extender.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../extender.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="tools.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.extending.targets"></a>Target types</h2></div></div>
+<div></div>
+</div>
+<div class="toc"><dl><dt><a href="targets.html#bbv2.extending.scanners">Scanners</a></dt></dl></div>
+<p>The first thing we did in the <a href="../extender.html#bbv2.extender.intro" title="Introduction">intruduction</a> was declaring a
+ new target type:
+</p>
+<pre class="programlisting">
+import type ;
+type.register VERBATIM : verbatim ;
+</pre>
+<p>
+ The type is the most important property of a target. Boost.Build can
+ automatically generate necessary build actions only because you
+ specify the desired type (using the different main target rules), and
+ because Boost.Build can guess the type of sources from their
+ extensions.
+ </p>
+<p>The first two parameters for the <tt class="computeroutput">type.register</tt> rule
+ are the name of new type and the list of extensions associated with
+ it. A file with an extension from the list will have the given target
+ type. In the case where a target of the declared type is generated
+ from other sources, the first specified extension will be used. This
+ behaviour can be changed using the
+ <tt class="computeroutput">type.set-generated-target-suffix</tt> rule.
+ </p>
+<p>
+ Something about 'main' types.
+ </p>
+<p>Something about base types.
+ </p>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.extending.scanners"></a>Scanners</h3></div></div>
+<div></div>
+</div>
+<p>
+ Sometimes, a file can refer to other files via some include
+ mechanism. To make Boost.Build track dependencies to the included
+ files, you need to provide a scanner. The primary limitation is that
+ only one scanner can be assigned to a target type.
+ </p>
+<p>First, we need to declare a new class for the scanner:
+</p>
+<pre class="programlisting">
+class verbatim-scanner : common-scanner
+{
+ rule pattern ( )
+ {
+ return "//###include[ ]*\"([^\"]*)\"" ;
+ }
+}
+</pre>
+<p>
+ All the complex logic is in the <tt class="computeroutput">common-scanner</tt> class,
+ and you only need to override the method which returns the regular
+ expression to be used for scanning. The paranthethis in the regular
+ expression indicate which part of the string is the name of the
+ included file.
+ </p>
+<p>After that, we need to register our scanner class:
+</p>
+<pre class="programlisting">
+scanner.register verbatim-scanner : include ;
+</pre>
+<p>
+ The value of the second parameter, in this case
+ <tt class="computeroutput">include</tt>, specifies which properties contain the list
+ of paths which should be searched for the included files.
+ </p>
+<p>Finally, we assign the new scaner to the <tt class="computeroutput">VERBATIM</tt>
+ target type:
+</p>
+<pre class="programlisting">
+type.set-scanner VERBATIM : verbatim-scanner ;
+</pre>
+<p>
+ That's enough for scanning include dependencies.
+ </p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../extender.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../extender.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="tools.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/tools.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/tools.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/tools.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,228 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Tools and generators</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../extender.html" title="Chapter 5. Extender Manual">
+<link rel="previous" href="targets.html" title="Target types">
+<link rel="next" href="features.html" title="Features">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="targets.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../extender.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="features.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.extending.tools"></a>Tools and generators</h2></div></div>
+<div></div>
+</div>
+<p>
+ This section will describe how Boost.Build can be extended to support
+ new tools.
+ </p>
+<p>For each additional tool, a Boost.Build object called generator
+ must be created. That object has specific types of targets which it
+ accepts an produces. Using that information, Boost.Build is able
+ to automatically invoke the generator. For example, if you declare a
+ generator which takes a target of the type <tt class="literal">D</tt> and
+ produces a target of the type <tt class="literal">OBJ</tt>, when placing a
+ file with extention <tt class="literal">.d</tt> in a list of sources will
+ cause Boost.Build to invoke your generator, and then to link the
+ resulting object file into an application. (Of course, this requires
+ that you specify that the <tt class="literal">.d</tt> extension corresponds
+ to the <tt class="literal">D</tt> type.)
+ </p>
+<p>Each generator should be an instance of a class derived from the
+ <tt class="computeroutput">generator</tt> class. In the simplest case, you don't need to
+ create a derived class, but simply create an instance of the
+ <tt class="computeroutput">generator</tt> class. Let's review the example we've seen in the
+ <a href="../extender.html#bbv2.extender.intro" title="Introduction">introduction</a>.
+</p>
+<pre class="programlisting">
+import generators ;
+generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
+actions inline-file
+{
+ "./inline-file.py" $(<) $(>)
+}
+</pre>
+<p>We declare a standard generator, specifying its id, the source type
+ and the target type. When invoked, the generator will create a target
+ of type <tt class="literal">CPP</tt> which will have the source target of
+ type <tt class="literal">VERBATIM</tt> as the only source. But what command
+ will be used to actually generate the file? In bjam, actions are
+ specified using named "actions" blocks and the name of the action
+ block should be specified when creating targets. By convention,
+ generators use the same name of the action block as their own id. So,
+ in above example, the "inline-file" actions block will be use to
+ convert the source into the target.
+ </p>
+<p>
+ There are two primary kinds of generators: standard and composing,
+ which are registered with the
+ <tt class="computeroutput">generators.register-standard</tt> and the
+ <tt class="computeroutput">generators.register-composing</tt> rules, respectively. For
+ example:
+</p>
+<pre class="programlisting">
+generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
+generators.register-composing mex.mex : CPP LIB : MEX ;
+</pre>
+<p>
+ The first generators takes a <span class="emphasis"><em>single</em></span> source of type
+ <tt class="computeroutput">VERBATIM</tt> and produces a result. The second generator
+ takes any number of sources, which can have either the
+ <tt class="computeroutput">CPP</tt> or the <tt class="computeroutput">LIB</tt> type. Composing generators
+ are typically used for generating top-level target type. For example,
+ the first generator invoked when building an <tt class="computeroutput">exe</tt> target
+ is a composing generator corresponding to the proper linker.
+ </p>
+<p>You should also know about two specific function for registering
+ generators: <tt class="computeroutput">generators.register-c-compiler</tt> and
+ <tt class="computeroutput">generators.register-linker</tt>. The first sets up header
+ dependecy scanning for C files, and the seconds handles various
+ complexities like searched libraries. For that reason, you should always
+ use those functions when adding support for compilers and linkers.
+ </p>
+<p>(Need a note about UNIX)</p>
+<h3>
+<a name="id2538271"></a>Custom generator classes</h3>
+<p>The standard generators allows you to specify source and target
+ types, action, and a set of flags. If you need anything more complex,
+ you need to create a new generator class with your own logic. Then,
+ you have to create an instance of that class and register it. Here's
+ an example how you can create your own generator class:
+</p>
+<pre class="programlisting">
+class custom-generator : generator
+{
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+}
+
+generators.register
+ [ new custom-generator verbatim.inline-file : VERBATIM : CPP ] ;
+</pre>
+<p>
+ This generator will work exactly like the
+ <tt class="computeroutput">verbatim.inline-file</tt> generator we've defined above, but
+ it's possible to customize the behaviour by overriding methods of the
+ <tt class="computeroutput">generator</tt> class.
+ </p>
+<p>There are two methods of interest. The <tt class="computeroutput">run</tt> methods is
+ responsible for overall process - it takes a number of source targets,
+ converts them the the right types, and creates the result. The
+ <tt class="computeroutput">generated-targets</tt> method is called when all sources are
+ converted to the right types to actually create the result.
+ </p>
+<p>The <tt class="computeroutput">generated-target</tt> method can be overridden when you
+ want to add additional properties to the generated targets or use
+ additional sources. For example (which is real), you have a tool for
+ analysing programs, which should be given a name of executable and the
+ list of all sources. Naturally, you don't want to list all source
+ files manually. Here's how the <tt class="computeroutput">generated-target</tt> method
+ can find the list of sources automatically:
+</p>
+<pre class="programlisting">
+class itrace-generator : generator {
+....
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ local leafs ;
+ local temp = [ virtual-target.traverse $(sources[1]) : : include-sources ] ;
+ for local t in $(temp)
+ {
+ if ! [ $(t).action ]
+ {
+ leafs += $(t) ;
+ }
+ }
+ return [ generator.generated-targets $(sources) $(leafs)
+ : $(property-set) : $(project) $(name) ] ;
+ }
+}
+generators.register [ new itrace-generator nm.itrace : EXE : ITRACE ] ;
+</pre>
+<p>
+ The <tt class="computeroutput">generated-targets</tt> rule will be called with a single
+ source target of type <tt class="literal">EXE</tt>. The call to the
+ <tt class="computeroutput">virtual-target.traverse</tt> will return all targets the
+ executable depends on, and we further find files which are not
+ produced from anything. The found targets are added to the sources.
+ </p>
+<p>The <tt class="computeroutput">run</tt> method can be overriden to completely
+ customize the way generator works. In particular, the conversion of
+ sources to the desired types can be completely customized. Here's
+ another real example. Tests for the Boost Python library usually
+ consist of two parts: a Python program and a C++ file. The C++ file is
+ compiled to Python extension which is loaded by the Python
+ program. But in the likely case that both files have the same name,
+ the created Python extension must be renamed. Otherwise, Python
+ program will import itself, not the extension. Here's how it can be
+ done:
+</p>
+<pre class="programlisting">
+rule run ( project name ? : property-set : sources * : multiple ? )
+{
+ local python ;
+ for local s in $(sources)
+ {
+ if [ $(s).type ] = PY
+ {
+ python = $(s) ;
+ }
+ }
+
+ local libs ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] LIB ]
+ {
+ libs += $(s) ;
+ }
+ }
+
+ local new-sources ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] CPP ]
+ {
+ local name = [ $(s).name ] ;
+ if $(name) = [ $(python).name ]
+ {
+ name = $(name)_ext ;
+ }
+ new-sources += [ generators.construct $(project) $(name) :
+ PYTHON_EXTENSION : $(property-set) : $(s) $(libs) ] ;
+ }
+ }
+
+ result = [ construct-result $(python) $(new-sources) : $(project) $(name)
+ : $(property-set) ] ;
+}
+</pre>
+<p>
+ First, we separate all source into python files, libraries and C++
+ sources. For each C++ source we create a separate Python extension by
+ calling <tt class="computeroutput">generators.construct</tt> and passing the C++ source
+ and the libraries. At this point, we also change the extension's name,
+ if necessary.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="targets.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../extender.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="features.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/toolset_modules.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/toolset_modules.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/extending/toolset_modules.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,107 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Toolset modules</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../extender.html" title="Chapter 5. Extender Manual">
+<link rel="previous" href="rules.html" title="Main target rules">
+<link rel="next" href="../reference.html" title="Chapter 6. Detailed reference">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="rules.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../extender.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="../reference.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.extending.toolset_modules"></a>Toolset modules</h2></div></div>
+<div></div>
+</div>
+<p>If your extensions will be used only on one project, they can be
+ placed in a separate <tt class="filename">.jam</tt> file which will be
+ imported by your <tt class="filename">project-root.jam</tt>. If the
+ extensions will be used on many projects, the users will thank you for
+ a finishing touch.
+ </p>
+<p>The standard way to use a tool in Boost.Build is the
+ <tt class="computeroutput">using</tt> rule. To make it work, you module should provide an
+ <tt class="computeroutput">init</tt> rule. The rule will be called with the same parameters
+ which were passed to the <tt class="computeroutput">using</tt> rule. The set of allowed
+ parameters is determined by you. For example, you can allow the user to
+ specify paths, tool version, or tool options.
+ </p>
+<p>Here are some guidelines which help to make Boost.Build more
+ consistent:
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li><p>The <tt class="computeroutput">init</tt> rule should never fail. Even if
+ user provided a wrong path, you should emit a warning and go
+ on. Configuration may be shared between different machines, and
+ wrong values on one machine can be OK on another.
+ </p></li>
+<li>
+<p>Prefer specifying command to be executed to specifying
+ path. First of all, this gives more control: it's possible to
+ specify
+</p>
+<pre class="programlisting">
+/usr/bin/g++-snapshot
+time g++
+</pre>
+<p>
+ as the command. Second, while some tools have a logical
+ "installation root", it better if user don't have to remember if
+ a specific tool requires a full command or a path.
+ </p>
+</li>
+<li>
+<p>Check for multiple initialization. A user can try to
+ initialize the module several times. You need to check for this
+ and decide what to do. Typically, unless you support several
+ versions of a tool, duplicate initialization is a user error. If
+ tool version can be specified during initialization, make sure the
+ version is either always specified, or never specified (in which
+ case the tool is initialied only once). For example, if you allow:
+</p>
+<pre class="programlisting">
+using yfc ;
+using yfc : 3.3 ;
+using yfc : 3.4 ;
+</pre>
+<p>
+ Then it's not clear if the first initialization corresponds to
+ version 3.3 of the tool, version 3.4 of the tool, or some other
+ version. This can lead to building twice with the same version.
+ </p>
+</li>
+<li>
+<p>If possible, the <tt class="computeroutput">init</tt> must be callable
+ with no parameters. In which case, it should try to autodetect all
+ the necessary information, for example, by looking for a tool in
+ <tt class="envar">PATH</tt> or in common installation locations. Often this
+ is possible and allows the user to simply write:
+</p>
+<pre class="programlisting">
+using yfc ;
+</pre>
+</li>
+<li><p>Consider using facilities in the
+ <tt class="computeroutput">tools/common</tt> module. You can take a look at how
+ <tt class="computeroutput">tools/gcc.jam</tt> uses that module in the <tt class="computeroutput">init</tt> rule.
+ </p></li>
+</ul></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="rules.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../extender.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="../reference.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/dll-path.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/dll-path.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/dll-path.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,97 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Why are the dll-path and
+ hardcode-dll-paths properties useful?
+ </title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../faq.html" title="Chapter 7. Frequently Asked Questions">
+<link rel="previous" href="s07.html" title="How to change compilation flags for one file?
+ ">
+<link rel="next" href="../recipies/site-config.html" title="Targets in site-config.jam">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="s07.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="../recipies/site-config.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.faq.dll-path"></a>Why are the <tt class="computeroutput">dll-path</tt> and
+ <tt class="computeroutput">hardcode-dll-paths</tt> properties useful?
+ </h2></div></div>
+<div></div>
+</div>
+<p>(This entry is specific to Unix system.)Before answering the
+ questions, let's recall a few points about shared libraries. Shared
+ libraries can be used by several applications, or other libraries,
+ without phisycally including the library in the application. This can
+ greatly decrease the total size of applications. It's also possible to
+ upgrade a shared library when the application is already
+ installed. Finally, shared linking can be faster.
+ </p>
+<p>However, the shared library must be found when the application is
+ started. The dynamic linker will search in a system-defined list of
+ paths, load the library and resolve the symbols. Which means that you
+ should either change the system-defined list, given by the
+ <tt class="envar">LD_LIBRARY_PATH</tt> environment variable, or install the
+ libraries to a system location. This can be inconvenient when
+ developing, since the libraries are not yet ready to be installed, and
+ cluttering system paths is undesirable. Luckily, on Unix there's another
+ way.
+ </p>
+<p>An executable can include a list of additional library paths, which
+ will be searched before system paths. This is excellent for development,
+ because the build system knows the paths to all libraries and can include
+ them in executables. That's done when the <tt class="computeroutput">hardcode-dll-paths</tt>
+ feature has the <tt class="literal">true</tt> value, which is the
+ default. When the executables should be installed, the story is
+ different.
+ </p>
+<p>
+ Obviously, installed executable should not hardcode paths to your
+ development tree. (The <tt class="computeroutput">stage</tt> rule explicitly disables the
+ <tt class="computeroutput">hardcode-dll-paths</tt> feature for that reason.) However, you
+ can use the <tt class="computeroutput">dll-path</tt> feature to add explicit paths
+ manually. For example:
+</p>
+<pre class="programlisting">
+stage installed : application : <dll-path>/usr/lib/snake
+ <location>/usr/bin ;
+</pre>
+<p>
+ will allow the application to find libraries placed to
+ <tt class="filename">/usr/lib/snake</tt>.
+ </p>
+<p>If you install libraries to a nonstandard location and add an
+ explicit path, you get more control over libraries which will be used. A
+ library of the same name in a system location will not be inadvertently
+ used. If you install libraries to a system location and do not add any
+ paths, the system administrator will have more control. Each library can
+ be individually upgraded, and all applications will use the new library.
+ </p>
+<p>Which approach is best depends on your situation. If the libraries
+ are relatively standalone and can be used by third party applications,
+ they should be installed in the system location. If you have lots of
+ libraries which can be used only by our application, it makes sense to
+ install it to a nonstandard directory and add an explicit path, like the
+ example above shows. Please also note that guidelines for different
+ systems differ in this respect. The Debian guidelines prohibit any
+ additional search paths, and Solaris guidelines suggest that they should
+ always be used.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="s07.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="../recipies/site-config.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/external.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/external.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/external.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,64 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Can I get output of external program as a variable in a Jamfile?
+ </title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../faq.html" title="Chapter 7. Frequently Asked Questions">
+<link rel="previous" href="s04.html" title="
+ How to control the library order on Unix?
+ ">
+<link rel="next" href="s06.html" title="How to get the project-root location?
+ ">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="s04.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="s06.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.faq.external"></a>Can I get output of external program as a variable in a Jamfile?
+ </h2></div></div>
+<div></div>
+</div>
+<p>From time to time users ask how to run an external program and save
+ the result in Jamfile variable, something like:
+</p>
+<pre class="programlisting">
+local gtk_includes = [ RUN_COMMAND gtk-config ] ;
+</pre>
+<p>
+ Unfortunately, this is not possible at the moment. However, if the
+ result of command invocation is to be used in a command to some tool,
+ and you're working on Unix, the following workaround is possible.
+</p>
+<pre class="programlisting">
+ alias gtk+-2.0 : : : :
+ <cflags>"`pkg-config --cflags gtk+-2.0`"
+ <inkflags>"`pkg-config --libs gtk+-2.0`"
+ ;
+</pre>
+<p>
+ If you use the "gtk+-2.0" target in sources, then the properties
+ specified above will be added to the build properties and eventually
+ will appear in the command line. Unix command line shell processes
+ the backticks quoting by running the tool and using its output --
+ which is what's desired in that case. Thanks to Daniel James for
+ sharing this approach.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="s04.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="s06.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s02.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s02.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s02.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,59 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>
+ Accessing environment variables
+ </title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../faq.html" title="Chapter 7. Frequently Asked Questions">
+<link rel="previous" href="../faq.html" title="Chapter 7. Frequently Asked Questions">
+<link rel="next" href="s03.html" title="
+ How to control properties order?
+ ">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../faq.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="s03.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="id2540896"></a>
+ Accessing environment variables
+ </h2></div></div>
+<div></div>
+</div>
+<p>
+ Many users would like to use environment variables in Jamfiles, for
+ example, to control location of external libraries. In many cases you
+ better declare those external libraries in the site-config.jam file, as
+ documented in the <a href="../recipies/site-config.html" title="Targets in site-config.jam">recipes
+ section</a>. However, if the users already have the environment variables set
+ up, it's not convenient to ask them to set up site-config.jam files as
+ well, and using environment variables might be reasonable.
+ </p>
+<p>In Boost.Build V2, each Jamfile is a separate namespace, and the
+ variables defined in environment is imported into the global
+ namespace. Therefore, to access environment variable from Jamfile, you'd
+ need the following code:
+</p>
+<pre class="programlisting">
+import modules ;
+local SOME_LIBRARY_PATH = [ modules.peek : SOME_LIBRARY_PATH ] ;
+exe a : a.cpp : <include>$(SOME_LIBRARY_PATH) ;
+</pre>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../faq.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="s03.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s03.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s03.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s03.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>
+ How to control properties order?
+ </title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../faq.html" title="Chapter 7. Frequently Asked Questions">
+<link rel="previous" href="s02.html" title="
+ Accessing environment variables
+ ">
+<link rel="next" href="s04.html" title="
+ How to control the library order on Unix?
+ ">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="s02.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="s04.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="id2540933"></a>
+ How to control properties order?
+ </h2></div></div>
+<div></div>
+</div>
+<p>For internal reasons, Boost.Build sorts all the properties
+ alphabetically. This means that if you write:
+</p>
+<pre class="programlisting">
+exe a : a.cpp : <include>b <include>a ;
+</pre>
+<p>
+ then the command line with first mention the "a" include directory, and
+ then "b", even though they are specified in the opposite order. In most
+ cases, the user doesn't care. But sometimes the order of includes, or
+ other properties, is important. For example, if one uses both the C++
+ Boost library and the "boost-sandbox" (libraries in development), then
+ include path for boost-sandbox must come first, because some headers may
+ override ones in C++ Boost. For such cases, a special syntax is
+ provided:
+</p>
+<pre class="programlisting">
+exe a : a.cpp : <include>a&&b ;
+</pre>
+<p>The <tt class="computeroutput">&&</tt> symbols separate values of an
+ property, and specify that the order of the values should be preserved. You
+ are advised to use this feature only when the order of properties really
+ matters, and not as a convenient shortcut. Using it everywhere might
+ negatively affect performance.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="s02.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="s04.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s04.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s04.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s04.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,69 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>
+ How to control the library order on Unix?
+ </title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../faq.html" title="Chapter 7. Frequently Asked Questions">
+<link rel="previous" href="s03.html" title="
+ How to control properties order?
+ ">
+<link rel="next" href="external.html" title="Can I get output of external program as a variable in a Jamfile?
+ ">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="s03.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="external.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="id2540977"></a>
+ How to control the library order on Unix?
+ </h2></div></div>
+<div></div>
+</div>
+<p>On the Unix-like operating systems, the order in which static
+ libraries are specified when invoking the linker is important, because by
+ default, the linker uses one pass though the libraries list. Passing the
+ libraries in the incorrect order will lead to a link error. Further, this
+ behaviour is often used to make one library override symbols from
+ another. So, sometimes it's necessary to force specific order of
+ libraries.
+ </p>
+<p>Boost.Build tries to automatically compute the right order. The
+ primary rule is that if library a "uses" library b, then library a will
+ appear on the command line before library b. Library a is considered to
+ use b is b is present either in the sources of a or in its
+ requirements. To explicitly specify the use relationship one can use the
+ <use> feature. For example, both of the following lines will cause
+ a to appear before b on the command line:
+</p>
+<pre class="programlisting">
+lib a : a.cpp b ;
+lib a : a.cpp : <use>b ;
+</pre>
+<p>
+ The same approach works for searched libraries, too:
+</p>
+<pre class="programlisting">
+lib z ;
+lib png : : <use>z ;
+exe viewer : viewer png z ;
+</pre>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="s03.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="external.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s06.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s06.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s06.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,48 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>How to get the project-root location?
+ </title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../faq.html" title="Chapter 7. Frequently Asked Questions">
+<link rel="previous" href="external.html" title="Can I get output of external program as a variable in a Jamfile?
+ ">
+<link rel="next" href="s07.html" title="How to change compilation flags for one file?
+ ">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="external.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="s07.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="id2541063"></a>How to get the project-root location?
+ </h2></div></div>
+<div></div>
+</div>
+<p>You might want to use the location of the project-root in your
+ Jamfiles. To do it, you'd need to declare path constant in your
+ project-root.jam:
+</p>
+<pre class="programlisting">
+path-constant TOP : . ;
+</pre>
+<p>
+ After that, the <tt class="computeroutput">TOP</tt> variable can be used in every Jamfile.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="external.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="s07.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s07.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s07.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq/s07.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,63 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>How to change compilation flags for one file?
+ </title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../faq.html" title="Chapter 7. Frequently Asked Questions">
+<link rel="previous" href="s06.html" title="How to get the project-root location?
+ ">
+<link rel="next" href="dll-path.html" title="Why are the dll-path and
+ hardcode-dll-paths properties useful?
+ ">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="s06.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="dll-path.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="id2541085"></a>How to change compilation flags for one file?
+ </h2></div></div>
+<div></div>
+</div>
+<p>If one file must be compiled with special options, you need to
+ explicitly declare an <tt class="computeroutput">obj</tt> target for that file and then use
+ that target in your <tt class="computeroutput">exe</tt> or <tt class="computeroutput">lib</tt> target:
+</p>
+<pre class="programlisting">
+exe a : a.cpp b ;
+obj b : b.cpp : <optimization>off ;
+</pre>
+<p>
+ Of course you can use other properties, for example to specify specific
+ compiler options:
+</p>
+<pre class="programlisting">
+exe a : a.cpp b ;
+obj b : b.cpp : <cflags>-g ;
+</pre>
+<p>
+ You can also use <a href="../tutorial/conditions.html" title="Conditions and alternatives">conditional
+ properties</a> for finer control:
+</p>
+<pre class="programlisting">
+exe a : a.cpp b ;
+obj b : b.cpp : <variant>release:<optimization>off ;
+</pre>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="s06.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="dll-path.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/faq.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,139 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 7. Frequently Asked Questions</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="previous" href="reference/generators.html" title="Generators">
+<link rel="next" href="faq/s02.html" title="
+ Accessing environment variables
+ ">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="reference/generators.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="faq/s02.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title">
+<a name="bbv2.faq"></a>Chapter 7. Frequently Asked Questions</h2></div></div>
+<div></div>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><a href="faq.html#id2540813">
+ I'm getting "Duplicate name of actual target" error. What
+ does it mean?
+ </a></dt>
+<dt><a href="faq/s02.html">
+ Accessing environment variables
+ </a></dt>
+<dt><a href="faq/s03.html">
+ How to control properties order?
+ </a></dt>
+<dt><a href="faq/s04.html">
+ How to control the library order on Unix?
+ </a></dt>
+<dt><a href="faq/external.html">Can I get output of external program as a variable in a Jamfile?
+ </a></dt>
+<dt><a href="faq/s06.html">How to get the project-root location?
+ </a></dt>
+<dt><a href="faq/s07.html">How to change compilation flags for one file?
+ </a></dt>
+<dt><a href="faq/dll-path.html">Why are the dll-path and
+ hardcode-dll-paths properties useful?
+ </a></dt>
+<dt><a href="recipies/site-config.html">Targets in site-config.jam</a></dt>
+</dl>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="id2540813"></a>
+ I'm getting "Duplicate name of actual target" error. What
+ does it mean?
+ </h2></div></div>
+<div></div>
+</div>
+<p>
+ The most likely case is that you're trying to
+ compile the same file twice, with almost the same,
+ but differing properties. For example:
+
+</p>
+<pre class="programlisting">
+exe a : a.cpp : <include>/usr/local/include ;
+exe b : a.cpp ;
+</pre>
+<p>
+ The above snippet requires two different compilations
+ of 'a.cpp', which differ only in 'include' property.
+ Since the 'include' property is free, Boost.Build
+ can't generate two objects files into different directories.
+ On the other hand, it's dangerous to compile the file only
+ once -- maybe you really want to compile with different
+ includes.
+ </p>
+<p>
+ To solve this issue, you need to decide if file should
+ be compiled once or twice.</p>
+<div class="orderedlist"><ol type="1">
+<li>
+<p>Two compile file only once, make sure that properties
+ are the same:
+
+</p>
+<pre class="programlisting">
+exe a : a.cpp : <include>/usr/local/include ;
+exe b : a.cpp : <include>/usr/local/include ;
+</pre>
+</li>
+<li>
+<p>
+ If changing the properties is not desirable, for example
+ if 'a' and 'b' target have other sources which need
+ specific properties, separate 'a.cpp' into it's own target:
+
+</p>
+<pre class="programlisting">
+obj a_obj : a.cpp : <include>/usr/local/include ;
+exe a : a_obj ;
+</pre>
+</li>
+<li>
+<p>
+ To compile file twice, you can make the object file local
+ to the main target:
+
+</p>
+<pre class="programlisting">
+ exe a : [ obj a_obj : a.cpp ] : <include>/usr/local/include ;
+ exe b : [ obj a_obj : a.cpp ] ;
+</pre>
+</li>
+</ol></div>
+<p>
+ A good question is why Boost.Build can't use some of the above
+ approaches automatically. The problem is that such magic would
+ require additional implementation complexities and would only
+ help in half of the cases, while in other half we'd be silently
+ doing the wrong thing. It's simpler and safe to ask user to
+ clarify his intention in such cases.
+ </p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="reference/generators.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="faq/s02.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/howto.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/howto.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/howto.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,53 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 1. How to use this document</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="previous" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="next" href="installation.html" title="Chapter 2. Installation">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="installation.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title">
+<a name="bbv2.howto"></a>Chapter 1. How to use this document</h2></div></div>
+<div></div>
+</div>
+<p>
+ If you've just found out about Boost.Build V2 and want to know
+ if it will work for you, start with <a href="tutorial.html" title="Chapter 3. Tutorial">Chapter 3, <i>Tutorial</i></a>. You can continue with the <a href="advanced.html" title="Chapter 4. User documentation">Chapter 4, <i>User documentation</i></a>. When you're ready to try Boost.Build
+ in practice, go to <a href="installation.html" title="Chapter 2. Installation">Chapter 2, <i>Installation</i></a>.
+ </p>
+<p>
+ If you are about to use Boost.Build on your project, or already
+ using it and have a problem, look at <a href="advanced.html" title="Chapter 4. User documentation">Chapter 4, <i>User documentation</i></a>.
+ </p>
+<p>
+ If you're trying to build a project which uses Boost.Build,
+ look at <a href="installation.html" title="Chapter 2. Installation">Chapter 2, <i>Installation</i></a> and then read about
+ <a href="reference.html#bbv2.reference.commandline" title="Command line">the section called “Command line”</a>.
+ </p>
+<p>
+ If you have questions, please post them to our <a href="../../../../more/mailing_lists.htm#jamboost" target="_top">mailing
+ list</a>, and be sure to indicate in the subject line that
+ you're asking about Boost.Build <span class="bold"><b>V2</b></span>.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="installation.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/installation.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/installation.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/installation.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,131 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 2. Installation</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="previous" href="howto.html" title="Chapter 1. How to use this document">
+<link rel="next" href="tutorial.html" title="Chapter 3. Tutorial">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="howto.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="tutorial.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title">
+<a name="bbv2.installation"></a>Chapter 2. Installation</h2></div></div>
+<div></div>
+</div>
+<p>
+ This section describes how to install Boost.Build from a
+ released source distribution. All paths are given relative to
+ the <i class="firstterm">Boost.Build v2 root directory</i>, which is
+
+
+
+ located in the <tt class="filename">tools/build/v2</tt> subdirectory
+ of a full <a href="http://www.boost.org" target="_top">Boost</a>
+ distribution.
+ </p>
+<div class="orderedlist"><ol type="1">
+<li>
+ Boost.Build uses <a href="../jam_src/index.html" target="_top">Boost.Jam</a>, an
+ extension of the <a href="http://www.perforce.com/jam/jam.html" target="_top">Perforce
+ Jam</a> portable <b class="command">make</b> replacement. The
+ recommended way to get Boost.Jam is to <span class="bold"><b><a href="http://sourceforge.net/project/showfiles.php?group_id=7586&package_id=72941" target="_top">download
+ a prebuilt executable</a></b></span> from SourceForge.
+ If a prebuilt executable is not provided for your platform
+ or you are using Boost's sources in an unreleased state, it
+ may be neccessary to <a href="../../jam_src/index.html#building_bjam" target="_top">build <b class="command">bjam</b>
+ from sources</a> included in the Boost source tree.
+ </li>
+<li>
+<p>
+
+ To install Boost.Jam, copy the executable,
+ called <b class="command">bjam</b>
+ or <b class="command">bjam.exe</b> to a location accessible in
+ your <tt class="envar">PATH</tt>. Go to the Boost.Build root
+ directory and
+ run <b class="command">bjam <tt class="option">--version</tt></b>. You
+ should see:
+
+ </p>
+<pre class="screen">
+ Boost.Build V2 (Milestone N)
+ Boost.Jam xx.xx.xx
+ </pre>
+<p>
+
+ where N is the version of Boost.Build you're using.
+ </p>
+</li>
+<li>
+ Configure Boost.Build to recognize the build resources (such
+ as compilers and libraries) you have installed on your
+ system. Open the
+ <tt class="filename">user-config.jam</tt> file in the Boost.Build
+ root directory and follow the instructions there to describe
+ your toolsets and libraries, and, if neccessary, where they
+ are located.
+ </li>
+<li>
+ You should now be able to go to the
+ <tt class="filename">example/hello/</tt> directory and run
+ <b class="command">bjam</b> there. A simple application will be
+ built. You can also play with other projects in the
+ <tt class="filename">example/</tt> directory.
+ </li>
+</ol></div>
+<p>
+ If you are using Boost's CVS state, be sure to
+ rebuild <b class="command">bjam</b> even if you have a previous
+ version. The CVS version of Boost.Build requires the CVS
+ version of Boost.Jam.
+ </p>
+<p>
+ When <b class="command">bjam</b> is invoked, it always needs to be
+ able to find the Boost.Build root directory, where the
+ interpreted source code of Boost.Build is located. There are
+ two ways to tell <b class="command">bjam</b> about the root directory:
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+ Set the environment variable <tt class="envar">BOOST_BUILD_PATH</tt>
+ to the absolute path of the Boost.Build root directory.
+ </li>
+<li>
+<p>
+ At the root directory of your project or in any of its
+ parent directories, create a file called
+ <tt class="filename">boost-build.jam</tt>, with a single line:
+
+</p>
+<pre class="programlisting">
+boost-build <i class="replaceable"><tt>/path/to/boost.build</tt></i> ;
+</pre>
+</li>
+</ul></div>
+<p><span class="bold"><b>N.B.</b></span>
+ When <b class="command">bjam</b> is invoked from anywhere in the Boost
+ directory tree <span class="emphasis"><em>other than</em></span> the Boost.Build root
+ and its subdirectories, <a href="../../tools/build" target="_top">Boost.Build
+ v1</a> is used by default. To override the default and use
+ Boost.Build v2, you have to add the <tt class="option">--v2</tt> command
+ line option to all <b class="command">bjam</b> invocations.</p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="howto.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="tutorial.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/recipies/site-config.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/recipies/site-config.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/recipies/site-config.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,56 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Targets in site-config.jam</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../faq.html" title="Chapter 7. Frequently Asked Questions">
+<link rel="previous" href="../faq/dll-path.html" title="Why are the dll-path and
+ hardcode-dll-paths properties useful?
+ ">
+<link rel="next" href="../arch.html" title="Appendix A. Boost.Build v2 architecture">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../faq/dll-path.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="../arch.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.recipies.site-config"></a>Targets in site-config.jam</h2></div></div>
+<div></div>
+</div>
+<p>It is desirable to declare standard libraries available on a
+ given system. Putting target declaration in Jamfile is not really
+ good, since locations of the libraries can vary. The solution is
+ to put the following to site-config.jam.</p>
+<pre class="programlisting">
+import project ;
+project.initialize $(__name__) ;
+project site-config ;
+lib zlib : : <name>z ;
+</pre>
+<p>The second line allows this module to act as project. The
+ third line gives id to this project — it really has no location
+ and cannot be used otherwise. The fourth line just declares a
+ target. Now, one can write:
+</p>
+<pre class="programlisting">
+exe hello : hello.cpp /site-config//zlib ;
+</pre>
+<p>
+ in any Jamfile.</p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../faq/dll-path.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../faq.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="../arch.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/buildprocess.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/buildprocess.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/buildprocess.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,134 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Build process</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../reference.html" title="Chapter 6. Detailed reference">
+<link rel="previous" href="jamfiles.html" title="Writing Jamfiles">
+<link rel="next" href="definitions.html" title="">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="jamfiles.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../reference.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="definitions.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.reference.buildprocess"></a>Build process</h2></div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="buildprocess.html#bbv2.reference.buildprocess.alternatives">Alternative selection</a></dt>
+<dt><a href="buildprocess.html#bbv2.reference.buildprocess.common">Determining common properties</a></dt>
+</dl></div>
+<p>The general overview of the build process was given in the
+ <a href="../advanced/build_process.html" title="Build process">user documentation</a>.
+ This section provides additional details, and some specific rules.
+ </p>
+<p>To recap, building a target with specific properties includes the
+ following steps:
+ </p>
+<div class="orderedlist"><ol type="1">
+<li><p>applying default build,</p></li>
+<li><p>selecting the main target alternative to use,
+ </p></li>
+<li><p>determining "common" properties</p></li>
+<li><p>building targets referred by the sources list and
+ dependency properties</p></li>
+<li><p>adding the usage requirements produces when building
+ dependencies to the "common" properties</p></li>
+<li><p>building the target using generators</p></li>
+<li><p>computing the usage requirements to be returned</p></li>
+</ol></div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.reference.buildprocess.alternatives"></a>Alternative selection</h3></div></div>
+<div></div>
+</div>
+<p>When there are several alternatives, one of them must be
+ selected. The process is as follows:</p>
+<div class="orderedlist"><ol type="1">
+<li>
+ For each alternative <span class="emphasis"><em>condition</em></span> is defined
+ as the set of base properies in requirements. [Note: it might be
+ better to specify the condition explicitly, as in
+ conditional requirements].
+ </li>
+<li>
+ An alternative is viable only if all properties in condition
+ are present in build request.
+ </li>
+<li>
+ If there's one viable alternative, it's choosen. Otherwise,
+ an attempt is made to find one best alternative. An alternative
+ a is better than another alternative b, iff set of properties
+ in b's condition is strict subset of the set of properities of
+ 'a's condition. If there's one viable alternative, which is
+ better than all other, it's selected. Otherwise, an error is
+ reported.
+ </li>
+</ol></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.reference.buildprocess.common"></a>Determining common properties</h3></div></div>
+<div></div>
+</div>
+<p>The "common" properties is a somewhat artificial term. Those are
+ the intermediate property set from which both the build request for
+ dependencies and properties for building the target are derived.
+ </p>
+<p>Since default build and alternatives are already handled, we have
+ only two inputs: build requests and requirements. Here are the rules
+ about common properties.
+ </p>
+<div class="orderedlist"><ol type="1">
+<li><p>Non-free feature can have only one
+ value</p></li>
+<li><p>A non-conditional property in requirement in always
+ present in common properties.</p></li>
+<li><p>A property in build request is present in
+ common properties, unless (2) tells otherwise.</p></li>
+<li><p>If either build request, or requirements (non-conditional
+ or conditional) include an expandable property (either composite,
+ or property with specified subfeature value), the behaviour is
+ equivalent to explicitly adding all expanded properties to build
+ request or requirements.</p></li>
+<li><p>If requirements include a conditional property, and
+ condiiton of this property is true in context of common
+ properties, then the conditional property should be in common
+ properties as well.</p></li>
+<li><p>If no value for a feature is given by other rules
+ here, it has default value in common properties.</p></li>
+</ol></div>
+<p>Those rules are declarative, they don't specify how to compute the
+ common properties. However, they provide enough information for the
+ user. The important point is the handling of conditional
+ requirements. The condition can be satisfied either by property in
+ build request, by non-conditional requirements, or even by another
+ conditional property. For example, the following example works as
+ expected:
+</p>
+<pre class="programlisting">
+exe a : a.cpp
+ : <toolset>gcc:<variant>release
+ <variant>release:<define>FOO ;
+</pre>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="jamfiles.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../reference.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="definitions.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/definitions.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/definitions.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/definitions.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,391 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title></title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../reference.html" title="Chapter 6. Detailed reference">
+<link rel="previous" href="buildprocess.html" title="Build process">
+<link rel="next" href="generators.html" title="Generators">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="buildprocess.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../reference.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="generators.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="definitions.html#bbv2.reference.features">Features and properties</a></dt>
+<dt><a href="definitions.html#bbv2.reference.variants">Build Variants</a></dt>
+<dt><a href="definitions.html#bbv2.reference.variants.proprefine">Property refinement</a></dt>
+<dt><a href="definitions.html#bbv2.reference.variants.propcond">Conditional properties</a></dt>
+<dt><a href="definitions.html#bbv2.reference.ids">Target identifiers and references</a></dt>
+</dl></div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.reference.features"></a>Features and properties</h3></div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="definitions.html#bbv2.reference.features.validity">Property Validity</a></dt>
+<dt><a href="definitions.html#bbv2.reference.features.attributes">Feature Attributes</a></dt>
+<dt><a href="definitions.html#bbv2.reference.features.declaration">Feature Declaration</a></dt>
+</dl></div>
+<p>A <span class="emphasis"><em>feature</em></span> is a normalized (toolset-independent)
+ aspect of a build configuration, such as whether inlining is
+ enabled. Feature names may not contain the '<tt class="literal">></tt>'
+ character.</p>
+<p>Each feature in a build configuration has one or more
+ associated <span class="emphasis"><em>value</em></span>s. Feature values for non-free features
+ may not contain the '<tt class="literal"><</tt>', '<tt class="literal">:</tt>', or
+ '<tt class="literal">=</tt>' characters. Feature values for free features may not
+ contain the '<tt class="literal"><</tt>' character.</p>
+<p>A <span class="emphasis"><em>property</em></span> is a (feature,value) pair, expressed as
+ <feature>value.</p>
+<p>A <span class="emphasis"><em>subfeature</em></span> is a feature which only exists in the
+ presence of its parent feature, and whose identity can be derived
+ (in the context of its parent) from its value. A subfeature's
+ parent can never be another subfeature. Thus, features and their
+ subfeatures form a two-level hierarchy.</p>
+<p>A <span class="emphasis"><em>value-string</em></span> for a feature <span class="bold"><b>F</b></span> is a string of
+ the form
+ <tt class="literal">value-subvalue1-subvalue2</tt>...<tt class="literal">-subvalueN</tt>, where
+ <tt class="literal">value</tt> is a legal value for <span class="bold"><b>F</b></span> and
+ <tt class="literal">subvalue1</tt>...<tt class="literal">subvalueN</tt> are legal values of some
+ of <span class="bold"><b>F</b></span>'s subfeatures. For example, the properties
+ <tt class="literal"><toolset>gcc <toolset-version>3.0.1</tt> can be
+ expressed more conscisely using a value-string, as
+ <tt class="literal"><toolset>gcc-3.0.1</tt>.</p>
+<p>A <span class="emphasis"><em>property set</em></span> is a set of properties (i.e. a
+ collection without duplicates), for instance:
+ <tt class="literal"><toolset>gcc <runtime-link>static</tt>.</p>
+<p>A <span class="emphasis"><em>property path</em></span> is a property set whose elements have
+ been joined into a single string separated by slashes. A property
+ path representation of the previous example would be
+ <tt class="literal"><toolset>gcc/<runtime-link>static</tt>.</p>
+<p>A <span class="emphasis"><em>build specification</em></span> is a property set which fully
+ describes the set of features used to build a target.</p>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h4 class="title">
+<a name="bbv2.reference.features.validity"></a>Property Validity</h4></div></div>
+<div></div>
+</div>
+<p>
+ For <a href="definitions.html#bbv2.reference.features.attributes.free">free</a>
+ features, all values are valid. For all other features,
+ the valid values are explicitly specified, and the build
+ system will report an error for the use of an invalid
+ feature-value. Subproperty validity may be restricted so
+ that certain values are valid only in the presence of
+ certain other subproperties. For example, it is possible
+ to specify that the <tt class="computeroutput"><gcc-target>mingw</tt>
+ property is only valid in the presence of
+ <tt class="computeroutput"><gcc-version>2.95.2</tt>.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h4 class="title">
+<a name="bbv2.reference.features.attributes"></a>Feature Attributes</h4></div></div>
+<div></div>
+</div>
+<p>Each feature has a collection of zero or more of the following
+ attributes. Feature attributes are low-level descriptions of how the
+ build system should interpret a feature's values when they appear in
+ a build request. We also refer to the attributes of properties, so
+ that an <span class="emphasis"><em>incidental</em></span> property, for example, is
+ one whose feature has the <span class="emphasis"><em>incidental</em></span>
+ attribute.</p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<p><span class="emphasis"><em>incidental</em></span></p>
+<p>Incidental features are assumed not to affect build
+ products at all. As a consequence, the build system may use
+ the same file for targets whose build specification differs
+ only in incidental features. A feature which controls a
+ compiler's warning level is one example of a likely
+ incidental feature.</p>
+<p>Non-incidental features are assumed to affect build
+ products, so the files for targets whose build specification
+ differs in non-incidental features are placed in different
+ directories as described in "target paths" below. [ where? ]
+ </p>
+</li>
+<li>
+<p><a name="bbv2.reference.features.attributes.propagated"></a><span class="emphasis"><em>propagated</em></span></p>
+<p>Features of this kind are
+ propagated to dependencies. That is, if a <a href="../advanced/jamfiles.html#bbv2.advanced.targets.main">main target</a> is built using a
+ propagated
+ property, the build systems attempts to use the same property
+ when building any of its dependencies as part of that main
+ target. For instance, when an optimized exectuable is
+ requested, one usually wants it to be linked with optimized
+ libraries. Thus, the <tt class="literal"><optimization></tt> feature is
+ propagated.</p>
+</li>
+<li>
+<p><a name="bbv2.reference.features.attributes.free"></a><span class="emphasis"><em>free</em></span></p>
+<p>Most features have a finite set of allowed values, and can
+ only take on a single value from that set in a given build
+ specification. Free features, on the other hand, can have
+ several values at a time and each value can be an arbitrary
+ string. For example, it is possible to have several
+ preprocessor symbols defined simultaneously:</p>
+<pre class="programlisting">
+<define>NDEBUG=1 <define>HAS_CONFIG_H=1
+</pre>
+</li>
+<li>
+<p><span class="emphasis"><em>optional</em></span></p>
+<p>An optional feature is a feature which is not required to
+ appear in a build specification. Every non-optional non-free
+ feature has a default value which is used when a value for
+ the feature is not otherwise specified, either in a target's
+ requirements or in the user's build request. [A feature's
+ default value is given by the first value listed in the
+ feature's declaration. -- move this elsewhere - dwa]</p>
+</li>
+<li>
+<p><span class="emphasis"><em>symmetric</em></span></p>
+<p>A symmetric feature's default value is not automatically
+ included in <a href="definitions.html#bbv2.reference.variants" title="Build Variants">build variants</a>. Normally
+ a feature only generates a subvariant directory when its
+ value differs from the value specified by the build variant,
+ leading to an assymmetric subvariant directory structure for
+ certain values of the feature. A symmetric feature, when
+ relevant to the toolset, always generates a corresponding
+ subvariant directory.</p>
+</li>
+<li>
+<p><span class="emphasis"><em>path</em></span></p>
+<p>The value of a path feature specifies a path. The path is
+ treated as relative to the directory of Jamfile where path
+ feature is used and is translated appropriately by the build
+ system when the build is invoked from a different
+ directory</p>
+</li>
+<li>
+<p><span class="emphasis"><em>implicit</em></span></p>
+<p>Values of implicit features alone identify the feature.
+ For example, a user is not required to write
+ "<toolset>gcc", but can simply write "gcc". Implicit
+ feature names also don't appear in variant paths, although
+ the values do. Thus: bin/gcc/... as opposed to
+ bin/toolset-gcc/.... There should typically be only a few
+ such features, to avoid possible name clashes.</p>
+</li>
+<li>
+<p><span class="emphasis"><em>composite</em></span></p>
+<p>Composite features actually correspond to groups of
+ properties. For example, a build variant is a composite
+ feature. When generating targets from a set of build
+ properties, composite features are recursively expanded and
+ <span class="emphasis"><em>added</em></span> to the build property set, so rules can find
+ them if neccessary. Non-composite non-free features override
+ components of composite features in a build property set.</p>
+</li>
+<li>
+<p><span class="emphasis"><em>link-incompatible</em></span></p>
+<p>See <a href="../../">below</a>.</p>
+</li>
+<li>
+<p><span class="emphasis"><em>dependency</em></span></p>
+<p>The value of dependency feature if a target reference.
+ When used for building of a main target, the value of
+ dependency feature is treated as additional dependency.</p>
+<p>For example, dependency features allow to state that
+ library A depends on library B. As the result, whenever an
+ application will link to A, it will also link to B.
+ Specifying B as dependency of A is different from adding B to
+ the sources of A. </p>
+</li>
+</ul></div>
+<p>Features which are neither free nor incidental are called
+ <span class="emphasis"><em>base</em></span> features.</p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h4 class="title">
+<a name="bbv2.reference.features.declaration"></a>Feature Declaration</h4></div></div>
+<div></div>
+</div>
+<p>The low-level feature declaration interface is the
+ <tt class="literal">feature</tt> rule from the
+ <tt class="literal">feature</tt> module:
+
+</p>
+<pre class="programlisting">
+rule feature ( name : allowed-values * : attributes * )
+</pre>
+<p>
+
+ A feature's allowed-values may be extended with the
+ <tt class="computeroutput">feature.extend</tt> rule.
+ </p>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.reference.variants"></a>Build Variants</h3></div></div>
+<div></div>
+</div>
+<p>
+ A build variant, or (simply variant) is a special kind of composite
+ feature which automatically incorporates the default values of
+ features that . Typically you'll want at least two separate
+ variants: one for debugging, and one for your release code. [
+ Volodya says: "Yea, we'd need to mention that it's a composite
+ feature and describe how they are declared, in pacticular that
+ default values of non-optional features are incorporated into
+ build variant automagically. Also, do we wan't some variant
+ inheritance/extension/templates. I don't remember how it works in
+ V1, so can't document this for V2.". Will clean up soon -DWA ]
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.reference.variants.proprefine"></a>Property refinement</h3></div></div>
+<div></div>
+</div>
+<p>When a target with certain properties is requested, and that
+ target requires some set of properties, it is needed to find the
+ set of properties to use for building. This process is called
+ <span class="emphasis"><em>property refinement</em></span> and is performed by these rules</p>
+<div class="orderedlist"><ol type="1">
+<li>
+ If original properties and required properties are not
+ link-compatible, refinement fails.
+ </li>
+<li>
+ Each property in the required set is added to the original
+ property set
+ </li>
+<li>
+ If the original property set includes property with a different
+ value of non free feature, that property is removed.
+ </li>
+</ol></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.reference.variants.propcond"></a>Conditional properties</h3></div></div>
+<div></div>
+</div>
+<p>Sometime it's desirable to apply certain requirements only for
+ a specific combination of other properties. For example, one of
+ compilers that you use issues a pointless warning that you want to
+ suppress by passing a command line option to it. You would not
+ want to pass that option to other compilers. Conditional
+ properties allow you to do just that. Their syntax is:</p>
+<pre class="programlisting">
+ property ( "," property ) * ":" property
+ </pre>
+<p>
+ For example, the problem above would be solved by:
+
+</p>
+<pre class="programlisting">
+exe hello : hello.cpp : <toolset>yfc:<cxxflags>-disable-pointless-warning ;
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.reference.ids"></a>Target identifiers and references</h3></div></div>
+<div></div>
+</div>
+<p><span class="emphasis"><em>Target identifier</em></span> is used to denote a
+ target. The syntax is:</p>
+<pre class="programlisting">
+target-id -> (project-id | target-name | file-name )
+ | (project-id | directory-name) "//" target-name
+project-id -> path
+target-name -> path
+file-name -> path
+directory-name -> path
+</pre>
+<p>
+ This grammar allows some elements to be recognized as either
+
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+ project id (at this point, all project ids start with slash).
+ </li>
+<li>
+ name of target declared in current Jamfile (note that target
+ names may include slash).
+ </li>
+<li>
+ a regular file, denoted by absolute name or name relative to
+ project's sources location.
+ </li>
+</ul></div>
+<p>
+
+ To determine the real meaning a check is made if project-id
+ by the specified name exists, and then if main target of that
+ name exists. For example, valid target ids might be:
+
+</p>
+<pre class="screen">
+a -- target in current project
+lib/b.cpp -- regular file
+/boost/thread -- project "/boost/thread"
+/home/ghost/build/lr_library//parser -- target in specific project
+</pre>
+<p><span class="bold"><b>Rationale:</b></span>Target is separated from project by special
+ separator (not just slash), because:</p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+ It emphasises that projects and targets are different things.
+ </li>
+<li>
+ It allows to have main target names with slashes.
+
+ </li>
+</ul></div>
+<p><a name="bbv2.reference.targets.references"></a><span class="emphasis"><em>Target reference</em></span> is used to
+ specify a source target, and may additionally specify desired
+ properties for that target. It has this syntax:</p>
+<pre class="programlisting">
+target-reference -> target-id [ "/" requested-properties ]
+requested-properties -> property-path
+</pre>
+<p>
+ For example,
+
+ </p>
+<pre class="programlisting">
+ exe compiler : compiler.cpp libs/cmdline/<optimization>space ;
+ </pre>
+<p>
+
+ would cause the version of <tt class="literal">cmdline</tt> library,
+ optimized for space, to be linked in even if the
+ <tt class="literal">compiler</tt> executable is build with optimization for
+ speed.
+ </p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="buildprocess.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../reference.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="generators.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/generators.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/generators.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/generators.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,198 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Generators</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../reference.html" title="Chapter 6. Detailed reference">
+<link rel="previous" href="definitions.html" title="">
+<link rel="next" href="../faq.html" title="Chapter 7. Frequently Asked Questions">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="definitions.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../reference.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="../faq.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.reference.generators"></a>Generators</h2></div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="generators.html#id2540607">Selecting and ranking viable generators</a></dt>
+<dt><a href="generators.html#id2540667">Running generators</a></dt>
+<dt><a href="generators.html#id2540706">Selecting dependency graph</a></dt>
+<dt><a href="generators.html#id2540717">Property adjustment</a></dt>
+<dt><a href="generators.html#id2540792">Transformations cache</a></dt>
+</dl></div>
+<div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+<p>The information is this section is likely to be outdated
+ and misleading.
+ </p>
+</div>
+<p>To construct a main target with given properties from sources,
+ it is required to create a dependency graph for that main target,
+ which will also include actions to be run. The algorithm for
+ creating the dependency graph is described here.</p>
+<p>The fundamental concept is <span class="emphasis"><em>generator</em></span>. If encapsulates
+ the notion of build tool and is capable to converting a set of
+ input targets into a set of output targets, with some properties.
+ Generator matches a build tool as closely as possible: it works
+ only when the tool can work with requested properties (for
+ example, msvc compiler can't work when requested toolset is gcc),
+ and should produce exactly the same targets as the tool (for
+ example, if Borland's linker produces additional files with debug
+ information, generator should also).</p>
+<p>Given a set of generators, the fundamental operation is to
+ construct a target of a given type, with given properties, from a
+ set of targets. That operation is performed by rule
+ <tt class="literal">generators.construct</tt> and the used algorithm is described
+ below.</p>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="id2540607"></a>Selecting and ranking viable generators</h3></div></div>
+<div></div>
+</div>
+<p>Each generator, in addition to target types that it can
+ produce, have attribute that affects its applicability in
+ particular sitiation. Those attributes are:</p>
+<div class="orderedlist"><ol type="1">
+<li>
+ Required properties, which are properties absolutely
+ necessary for the generator to work. For example, generator
+ encapsulating the gcc compiler would have <toolset>gcc as
+ required property.
+ </li>
+<li>
+ Optional properties, which increase the generators
+ suitability for a particual build.
+ </li>
+</ol></div>
+<p>
+ Generator's required and optional properties may not include
+ either free or incidental properties. (Allowing this would
+ greatly complicate caching targets).
+ </p>
+<p>When trying to construct a target, the first step is to select
+ all possible generators for the requested target type, which
+ required properties are a subset of requested properties.
+ Generators which were already selected up the call stack are
+ excluded. In addition, if any composing generators were selected
+ up the call stack, all other composing generators are ignored
+ (TODO: define composing generators). The found generators
+ are assigned a rank, which is the number of optional properties
+ present in requested properties. Finally, generators with highest
+ rank are selected for futher processing.</p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="id2540667"></a>Running generators</h3></div></div>
+<div></div>
+</div>
+<p>When generators are selected, each is run to produce a list of
+ created targets. This list might include targets which are not of
+ requested types, because generators create the same targets as
+ some tool, and tool's behaviour is fixed. (Note: should specify
+ that in some cases we actually want extra targets). If generator
+ fails, it returns an empty list. Generator is free to call
+ 'construct' again, to convert sources to the types it can handle.
+ It also can pass modified properties to 'construct'. However, a
+ generator is not allowed to modify any propagated properties,
+ otherwise when actually consuming properties we might discover
+ that the set of propagated properties is different from what was
+ used for building sources.</p>
+<p>For all targets which are not of requested types, we try to
+ convert them to requested type, using a second call to
+ <tt class="literal">construct</tt>. This is done in order to support
+ transformation sequences where single source file expands to
+ several later. See <a href="http://groups.yahoo.com/group/jamboost/message/1667" target="_top">this
+ message</a> for details.</p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="id2540706"></a>Selecting dependency graph</h3></div></div>
+<div></div>
+</div>
+<p>
+ After all generators are run,
+ it is necessary to decide which of successfull invocation will be
+ taken as final result. At the moment, this is not done. Instead,
+ it is checked whether all successfull generator invocation
+ returned the same target list. Error is issued otherwise.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="id2540717"></a>Property adjustment</h3></div></div>
+<div></div>
+</div>
+<p>Because target location is determined by the build system, it
+ is sometimes necessary to adjust properties, in order to not
+ break actions. For example, if there's an action which generates
+ a header, say "a_parser.h", and a source file "a.cpp" which
+ includes that file, we must make everything work as if a_parser.h
+ is generated in the same directory where it would be generated
+ without any subvariants.</p>
+<p>Correct property adjustment can be done only after all targets
+ are created, so the approach taken is:</p>
+<div class="orderedlist"><ol type="1">
+<li><p>
+ When dependency graph is constructed, each action can be
+ assigned a rule for property adjustment.
+ </p></li>
+<li><p>
+ When virtual target is actualized, that rule is run and
+ return the final set of properties. At this stage it can use
+ information of all created virtual targets.
+ </p></li>
+</ol></div>
+<p>In case of quoted includes, no adjustment can give 100% correct
+ results. If target dirs are not changed by build system, quoted
+ includes are searched in "." and then in include path, while angle
+ includes are searched only in include path. When target dirs are
+ changed, we'd want to make quoted includes to be search in "." then in
+ additional dirs and then in the include path and make angle includes
+ be searched in include path, probably with additional paths added at
+ some position. Unless, include path already has "." as the first
+ element, this is not possible. So, either generated headers should not
+ be included with quotes, or first element of include path should be
+ ".", which essentially erases the difference between quoted and angle
+ includes. <span class="bold"><b>Note:</b></span> the only way to get
+ "." as include path into compiler command line is via verbatim
+ compiler option. In all other case, Boost.Build will convert "." into
+ directory where it occurs.</p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="id2540792"></a>Transformations cache</h3></div></div>
+<div></div>
+</div>
+<p>
+ Under certain conditions, an
+ attempt is made to cache results of transformation search. First,
+ the sources are replaced with targets with special name and the
+ found target list is stored. Later, when properties, requested
+ type, and source type are the same, the store target list is
+ retrieved and cloned, with appropriate change in names.
+ </p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="definitions.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../reference.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="../faq.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/jamfiles.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/jamfiles.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference/jamfiles.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,69 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Writing Jamfiles</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../reference.html" title="Chapter 6. Detailed reference">
+<link rel="previous" href="../reference.html" title="Chapter 6. Detailed reference">
+<link rel="next" href="buildprocess.html" title="Build process">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../reference.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../reference.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="buildprocess.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.reference.jamfiles"></a>Writing Jamfiles</h2></div></div>
+<div></div>
+</div>
+<div class="toc"><dl><dt><a href="jamfiles.html#bbv2.reference.headers">Generated headers</a></dt></dl></div>
+<p>This section describes specific information about writing Jamfiles.</p>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.reference.headers"></a>Generated headers</h3></div></div>
+<div></div>
+</div>
+<p>Usually, Boost.Build handles implicit dependendies completely
+ automatically. For example, for C++ files, all <tt class="literal">#include</tt>
+ statements are found and handled. The only aspect where user help
+ might be needed is implicit dependency on generated files.</p>
+<p>By default, Boost.Build handles such dependencies within one
+ main target. For example, assume that main target "app" has two
+ sources, "app.cpp" and "parser.y". The latter source is converted
+ into "parser.c" and "parser.h". Then, if "app.cpp" includes
+ "parser.h", Boost.Build will detect this dependency. Moreover,
+ since "parser.h" will be generated into a build directory, the
+ path to that directory will automatically added to include
+ path.</p>
+<p>Making this mechanism work across main target boundaries is
+ possible, but imposes certain overhead. For that reason, if
+ there's implicit dependency on files from other main targets, the
+ <tt class="literal"><implicit-dependency></tt> [ link ] feature must
+ be used, for example:</p>
+<pre class="programlisting">
+lib parser : parser.y ;
+exe app : app.cpp : <implicit-dependency>parser ;
+</pre>
+<p>
+ The above example tells the build system that when scanning
+ all sources of "app" for implicit-dependencies, it should consider
+ targets from "parser" as potential dependencies.
+ </p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../reference.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../reference.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="buildprocess.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/reference.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,310 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 6. Detailed reference</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="previous" href="extending/toolset_modules.html" title="Toolset modules">
+<link rel="next" href="reference/jamfiles.html" title="Writing Jamfiles">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="extending/toolset_modules.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="reference/jamfiles.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title">
+<a name="bbv2.reference"></a>Chapter 6. Detailed reference</h2></div></div>
+<div></div>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><a href="reference.html#bbv2.reference.general">General information</a></dt>
+<dt><a href="reference/jamfiles.html">Writing Jamfiles</a></dt>
+<dt><a href="reference/buildprocess.html">Build process</a></dt>
+<dt><a href="reference/definitions.html"></a></dt>
+<dt><a href="reference/generators.html">Generators</a></dt>
+</dl>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.reference.general"></a>General information</h2></div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="reference.html#bbv2.reference.init">Initialization</a></dt>
+<dt><a href="reference.html#bbv2.reference.commandline">Command line</a></dt>
+</dl></div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.reference.init"></a>Initialization</h3></div></div>
+<div></div>
+</div>
+<p>bjam's first job upon startup is to load the Jam code which
+ implements the build system. To do this, it searches for a file
+ called "boost-build.jam", first in the invocation directory, then
+ in its parent and so forth up to the filesystem root, and finally
+ in the directories specified by the environment variable
+ BOOST_BUILD_PATH. When found, the file is interpreted, and should
+ specify the build system location by calling the boost-build
+ rule:</p>
+<pre class="programlisting">
+rule boost-build ( location ? )
+</pre>
+<p>
+ If location is a relative path, it is treated as relative to
+ the directory of boost-build.jam. The directory specified by
+ location and directories in BOOST_BUILD_PATH are then searched for
+ a file called bootstrap.jam which is interpreted and is expected to
+ bootstrap the build system. This arrangement allows the build
+ system to work without any command-line or environment variable
+ settings. For example, if the build system files were located in a
+ directory "build-system/" at your project root, you might place a
+ boost-build.jam at the project root containing:
+
+</p>
+<pre class="programlisting">
+boost-build build-system ;
+</pre>
+<p>
+
+ In this case, running bjam anywhere in the project tree will
+ automatically find the build system.</p>
+<p>The default "bootstrap.jam", after loading some standard
+ definitions, loads two files, which can be provided/customised by
+ user: "site-config.jam" and "user-config.jam".</p>
+<p>Locations where those files a search are summarized below:</p>
+<div class="table">
+<a name="bbv2.reference.init.config"></a><p class="title"><b>Table 6.1. Search paths for configuration files</b></p>
+<table class="table" summary="Search paths for configuration files">
+<colgroup>
+<col>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th> </th>
+<th>site-config.jam</th>
+<th>user-config.jam</th>
+</tr></thead>
+<tbody>
+<tr>
+<td>Linux</td>
+<td>
+<p>/etc</p>
+<p>$HOME</p>
+<p>$BOOST_BUILD_PATH</p>
+</td>
+<td>
+<p>$HOME</p>
+<p>$BOOST_BUILD_PATH</p>
+</td>
+</tr>
+<tr>
+<td>Windows</td>
+<td>
+<p>$SystemRoot</p>
+<p>$HOME</p>
+<p>$BOOST_BUILD_PATH</p>
+</td>
+<td>
+<p>$HOME</p>
+<p>$BOOST_BUILD_PATH</p>
+</td>
+</tr>
+</tbody>
+</table>
+</div>
+<p>
+ Boost.Build comes with default versions of those files,
+ which can serve as templates for customized versions.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.reference.commandline"></a>Command line</h3></div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="reference.html#bbv2.reference.init.args">Command line arguments</a></dt>
+<dt><a href="reference.html#bbv2.reference.init.options">Command line options</a></dt>
+</dl></div>
+<p>The command line may contain:</p>
+<div class="itemizedlist"><ul type="disc">
+<li>Jam options,</li>
+<li>Boost.Build <a href="reference.html#bbv2.reference.init.options" title="Command line options">options</a>,</li>
+<li>Command line arguments</li>
+</ul></div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h4 class="title">
+<a name="bbv2.reference.init.args"></a>Command line arguments</h4></div></div>
+<div></div>
+</div>
+<p>
+ Command line arguments specify targets and build
+ request using the following rules.
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+ An argument which does not contain slashes or the "="
+ symbol is either a value of an implicit feature, or target to
+ be built. It is taken to be value of a feature if appropriate
+ feature exists. Otherwise, it is considered a <a href="reference/definitions.html#bbv2.reference.ids" title="Target identifiers and references">target id</a>. Special target name "clean"
+ has the same effect as "--clean" option.
+ </li>
+<li>
+<p>
+ An argument with either slashes or the "=" symbol specifies
+ a number of <a href="../">build
+ request</a>
+ elements. In the simplest form, it's just a set of properties,
+ separated by slashes, which become a single build request
+ element, for example:
+
+</p>
+<pre class="programlisting">
+borland/<runtime-link>static
+</pre>
+<p>
+
+ More complex form is used to save typing. For example,
+ instead of
+
+</p>
+<pre class="programlisting">
+borland/runtime-link=static borland/runtime-link=dynamic
+</pre>
+<p>
+
+ one can use
+
+</p>
+<pre class="programlisting">
+borland/runtime-link=static,dynamic
+</pre>
+<p>
+
+ Exactly, the conversion from argument to build request
+ elements is performed by (1) splitting the argument at each slash,
+ (2) converting each split part into a set of properties and (3)
+ taking all possible combination of the property sets. Each split
+ part should have the either the form
+
+</p>
+<pre class="programlisting"><span class="emphasis"><em>feature-name</em></span>=<span class="emphasis"><em>feature-value1</em></span>[","<span class="emphasis"><em>feature-valueN</em></span>]*
+</pre>
+<p>
+
+ or, in case of implicit feature
+
+</p>
+<pre class="programlisting"><span class="emphasis"><em>feature-value1</em></span>[","<span class="emphasis"><em>feature-valueN</em></span>;]*
+</pre>
+<p>
+
+ and will be converted into property set
+
+</p>
+<pre class="programlisting">
+<feature-name>feature-value1 .... <feature-name>feature-valueN
+</pre>
+</li>
+</ul></div>
+<p>
+ For example, the command line
+
+</p>
+<pre class="programlisting">
+target1 debug gcc/runtime-link=dynamic,static
+</pre>
+<p>
+
+ would cause target called <tt class="literal">target1</tt> to be rebuilt in
+ debug mode, except that for gcc, both dynamically and statically
+ linked binaries would be created.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h4 class="title">
+<a name="bbv2.reference.init.options"></a>Command line options</h4></div></div>
+<div></div>
+</div>
+<p>All of the Boost.Build options start with the "--" prefix.
+ They are described in the following table.</p>
+<div class="table">
+<a name="id2539335"></a><p class="title"><b>Table 6.2. Command line options</b></p>
+<table class="table" summary="Command line options">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Option</th>
+<th>Description</th>
+</tr></thead>
+<tbody>
+<tr>
+<td><tt class="literal">--version</tt></td>
+<td>Prints information on Boost.Build and Boost.Jam
+ versions.</td>
+</tr>
+<tr>
+<td>
+<a name="bbv2.reference.init.options.help"></a><tt class="literal">--help</tt>
+</td>
+<td>Access to the online help system. This prints general
+ information on how to use the help system with additional
+ --help* options.</td>
+</tr>
+<tr>
+<td><tt class="literal">--clean</tt></td>
+<td>Removes everything instead of building. Unlike
+ <tt class="literal">clean</tt> target in make, it is possible to clean only
+ some targets.</td>
+</tr>
+<tr>
+<td><tt class="literal">--debug</tt></td>
+<td>Enables internal checks.</td>
+</tr>
+<tr>
+<td><tt class="literal">--dump-projects</tt></td>
+<td>Cause the project structure to be output.</td>
+</tr>
+<tr>
+<td><tt class="literal">--no-error-backtrace</tt></td>
+<td>Don't print backtrace on errors. Primary useful for
+ testing.</td>
+</tr>
+<tr>
+<td><tt class="literal">--ignore-config</tt></td>
+<td>Do not load <tt class="literal">site-config.jam</tt> and
+ <tt class="literal">user-config.jam</tt>
+</td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+</div>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="extending/toolset_modules.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="reference/jamfiles.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/conditions.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/conditions.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/conditions.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,80 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Conditions and alternatives</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<style type="text/css">
+body { background-image: url('http://docbook.sourceforge.net/release/images/draft.png');
+ background-repeat: no-repeat;
+ background-position: top left;
+ /* The following properties make the watermark "fixed" on the page. */
+ /* I think that's just a bit too distracting for the reader... */
+ /* background-attachment: fixed; */
+ /* background-position: center center; */
+ }</style>
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../tutorial.html" title="Chapter 3. Tutorial">
+<link rel="previous" href="linkage.html" title="Static and shared libaries">
+<link rel="next" href="prebuilt.html" title="Prebuilt targets">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="linkage.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="prebuilt.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.tutorial.conditions"></a>Conditions and alternatives</h2></div></div>
+<div></div>
+</div>
+<p>As we've just figured out, properties can significally affect the
+ way targets are built. The processing of the <link> feature is
+ built in the build system, and is quite complex. But there is a couple
+ of mechanisms which allow ordinary users to do different things
+ depending on properties.
+ </p>
+<p>The first mechanism is called <i class="firstterm">conditinal
+ requirement</i>. For example, you might want to set specific
+ defines when the library is build as shared, or you have your own define
+ to be used in release mode. Here's a piece of Jamfile.
+</p>
+<pre class="programlisting">
+lib network : network.cpp
+ : <link>shared:<define>NEWORK_LIB_SHARED
+ <variant>release:<define>EXTRA_FAST
+ ;
+</pre>
+<p>
+ This will have exactly the effect we wanted: whenever <link>shared
+ is in properties, <define>NEWORK_LIB_SHARED will be in properties
+ as well.
+ </p>
+<p>
+ Sometimes different variant of a target are so different, that
+ describing them using conditional requirements would be hard. Imagine
+ that a library has different sources on two supported toolsets, and
+ dummy implementation for all the other toolset. We can express this
+ situation using <i class="firstterm">target alternatives</i>:
+</p>
+<pre class="programlisting">
+lib demangler : dummy_demangler.cpp ;
+lib demangler : demangler_gcc.cpp : <toolset>gcc ;
+lib demangler : demangler_msvc.cpp : <toolset>msvc ;
+</pre>
+<p>
+ The proper alternative will be automatically selected.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="linkage.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="prebuilt.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/depends.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/depends.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/depends.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,77 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Library dependencies</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<style type="text/css">
+body { background-image: url('http://docbook.sourceforge.net/release/images/draft.png');
+ background-repeat: no-repeat;
+ background-position: top left;
+ /* The following properties make the watermark "fixed" on the page. */
+ /* I think that's just a bit too distracting for the reader... */
+ /* background-attachment: fixed; */
+ /* background-position: center center; */
+ }</style>
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../tutorial.html" title="Chapter 3. Tutorial">
+<link rel="previous" href="libs.html" title="Libraries and Dependent Targets">
+<link rel="next" href="linkage.html" title="Static and shared libaries">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="libs.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="linkage.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.tutorial.depends"></a>Library dependencies</h2></div></div>
+<div></div>
+</div>
+<p>The previous example was simple. Often, there are long chains
+ of dependencies between libraries. The main application is a thin
+ wrapper on top of library with core logic, which uses library of
+ utility functions, which uses boost filesystem library.
+ Expressing these dependencies is straightforward:</p>
+<pre class="programlisting">
+lib utils : utils.cpp /boost/filesystem//fs ;
+lib core : core.cpp utils ;
+exe app : app.cpp core ;
+</pre>
+<p>So, what's the reason to even mention this case? First,
+ because it's a bit more complex that it seems. When using shared
+ linking, libraries are build just as written, and everything will
+ work. However, what happens with static linking? It's not
+ possible to include another library in static library.
+ Boost.Build solves this problem by returning back library targets
+ which appear as sources for static libraries. In this case, if
+ everything is built statically, the "app" target will link not
+ only "core" library, but also "utils" and
+ "/boost/filesystem//fs".</p>
+<p>So, the net result is that the above code will work for both
+ static linking and for shared linking.</p>
+<p>Sometimes, you want all applications in some project to link
+ to a certain library. Putting the library in sources of all
+ targets is possible, but verbose. You can do better by using the
+ <source> property. For example, if "/boost/filesystem//fs"
+ should be linked to all applications in your project, you can add
+ <source>/boost/filesystem//fs to requirements of the
+ project, like this:</p>
+<pre class="programlisting">
+project
+ : requirements <source>/boost/filesystem//fs
+ ;
+</pre>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="libs.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="linkage.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/hierarchy.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/hierarchy.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/hierarchy.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,124 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Project Hierarchies</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<style type="text/css">
+body { background-image: url('http://docbook.sourceforge.net/release/images/draft.png');
+ background-repeat: no-repeat;
+ background-position: top left;
+ /* The following properties make the watermark "fixed" on the page. */
+ /* I think that's just a bit too distracting for the reader... */
+ /* background-attachment: fixed; */
+ /* background-position: center center; */
+ }</style>
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../tutorial.html" title="Chapter 3. Tutorial">
+<link rel="previous" href="properties.html" title="Properties">
+<link rel="next" href="libs.html" title="Libraries and Dependent Targets">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="properties.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="libs.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.tutorial.hierarchy"></a>Project Hierarchies</h2></div></div>
+<div></div>
+</div>
+<p>So far we've only considered examples with one project
+ (i.e. with one <tt class="filename">Jamfile</tt>). A typical large
+ software project would be composed of sub-projects organized
+ into a tree. The top of the tree is called the
+ <i class="firstterm">project root</i>. Besides a
+ <tt class="filename">Jamfile</tt>, the project root directory
+ contains a file called <tt class="filename">project-root.jam</tt>. Every other
+ <tt class="filename">Jamfile</tt> in the project has a single parent
+ project, rooted in the nearest parent directory containing a
+ <tt class="filename">Jamfile</tt>. For example, in the following
+ directory layout:
+
+</p>
+<pre class="screen">
+top/
+ |
+ +-- Jamfile
+ +-- project-root.jam
+ |
+ +-- src/
+ | |
+ | +-- Jamfile
+ | `-- app.cpp
+ |
+ `-- util/
+ |
+ +-- foo/
+ . |
+ . +-- Jamfile
+ . `-- bar.cpp
+</pre>
+<p>
+
+ the project root is <tt class="filename">top/</tt>. Because there is
+ no <tt class="filename">Jamfile</tt> in
+ <tt class="filename">top/util/</tt>, the projects in
+ <tt class="filename">top/src/</tt> and
+ <tt class="filename">top/util/foo/</tt> are immediate children of the
+ root project.
+ </p>
+<p>
+ Projects inherit all attributes (such as requirements)
+ from their parents. Inherited requirements are combined with
+ any requirements specified by the sub-project.
+ For example, if <tt class="filename">top/Jamfile</tt> has
+
+</p>
+<pre class="programlisting">
+<include>/home/ghost/local
+</pre>
+<p>
+
+ in its requirements, then all of its sub-projects will have it
+ in their requirements, too. Of course, any project can add
+ additional includes. <sup>[<a name="id2534693" href="#ftn.id2534693">2</a>]</sup> More details can be found in the section
+ on <a href="../advanced/jamfiles.html#bbv2.advanced.projects" title="Projects">projects</a>.
+ </p>
+<p>
+ Invoking <b class="command">bjam</b> without explicitly specifying
+ any targets on the command-line builds the project rooted in the
+ current directory. Building a project does not automatically
+ cause its sub-projects to be built unless the parent project's
+ <tt class="filename">Jamfile</tt> explicitly requests it. In our
+ example, <tt class="filename">top/Jamfile</tt> might contain:
+
+</p>
+<pre class="programlisting">
+build-project src ;
+</pre>
+<p>
+
+ which would cause the project in <tt class="filename">top/src/</tt>
+ to be built whenever the project in <tt class="filename">top/</tt> is
+ built. However, targets in <tt class="filename">top/util/foo/</tt>
+ will be built only if they are needed by targets in
+ <tt class="filename">top/</tt> or <tt class="filename">top/src/</tt>.
+ </p>
+<div class="footnotes">
+<br><hr width="100" align="left">
+<div class="footnote"><a href="../reference/definitions.html#bbv2.reference.features.attributes" title="Feature Attributes"><sup>[<a name="ftn.id2534693" href="#id2534693">2</a>] </sup>the section called “Feature Attributes”</a></div>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="properties.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="libs.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/libs.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/libs.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/libs.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,157 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Libraries and Dependent Targets</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<style type="text/css">
+body { background-image: url('http://docbook.sourceforge.net/release/images/draft.png');
+ background-repeat: no-repeat;
+ background-position: top left;
+ /* The following properties make the watermark "fixed" on the page. */
+ /* I think that's just a bit too distracting for the reader... */
+ /* background-attachment: fixed; */
+ /* background-position: center center; */
+ }</style>
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../tutorial.html" title="Chapter 3. Tutorial">
+<link rel="previous" href="hierarchy.html" title="Project Hierarchies">
+<link rel="next" href="depends.html" title="Library dependencies">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="hierarchy.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="depends.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.tutorial.libs"></a>Libraries and Dependent Targets</h2></div></div>
+<div></div>
+</div>
+<i><span class="comment">TODO: need to make this
+ section consistent with "examples-v2/libraries".</span></i><p>
+ Targets that are "needed" by other targets are called
+ <i class="firstterm">dependencies</i> of those other targets. The
+ targets that need the other targets are called
+ <i class="firstterm">dependent</i> targets.
+ </p>
+<p>To get a feeling of target dependencies, let's continue the
+ above example and see how <tt class="filename">src/Jamfile</tt> can
+ use libraries from <tt class="filename">util/foo</tt>. Assume
+ util/foo/Jamfile contains:
+
+</p>
+<pre class="programlisting">
+lib bar : bar.cpp ;
+</pre>
+<p>
+
+ Then, to use this library in <tt class="filename">src/Jamfile</tt>, we can write:
+
+</p>
+<pre class="programlisting">
+exe app : app.cpp ../util/foo//bar ;
+</pre>
+<p>
+
+ While <tt class="computeroutput">app.cpp</tt> refers to a regular source file,
+ <tt class="computeroutput">../util/foo//bar</tt> is a reference to another target:
+ a library "bar" declared in the <tt class="filename">Jamfile</tt> at
+ <tt class="filename">../util/foo</tt>. When linking the
+ <b class="command">app</b> executable, the appropriate version of
+ <tt class="computeroutput">bar</tt> will be built and linked in. What do we mean by
+ "appropriate"? For example, suppose we build "app" with:
+
+</p>
+<pre class="screen">
+bjam app optimization=full cxxflags=-w-8080
+</pre>
+<p>
+
+ Which properties must be used to build <tt class="computeroutput">foo</tt>? The
+ answer is that some properties are
+ <i class="firstterm">propagated</i> — Boost.Build attempts to
+ use dependencies with the same value of propagated features. The
+ <optimization> feature is propagated, so both "app" and
+ "foo" will be compiled with full optimization. But
+ <cxxflags> feature is not propagated: its value will be
+ added as-is to compiler flags for "a.cpp", but won't affect
+ "foo". There is still a couple of problems. First, the library
+ probably has some headers which must be used when compiling
+ "app.cpp". We could use requirements on "app" to add those
+ includes, but then this work will be repeated for all programs
+ which use "foo". A better solution is to modify
+ util/foo/Jamfilie in this way:
+
+</p>
+<pre class="programlisting">
+project
+ : usage-requirements <include>.
+ ;
+
+lib foo : foo.cpp ;
+</pre>
+<p>
+
+ Usage requirements are requirements which are applied to
+ dependents. In this case, <include> will be applied to all
+ targets which use "foo" — i.e. targets which have "foo"
+ either in sources or in dependency properties. You'd need to
+ specify usage requirements only once, and programs which use "foo"
+ don't have to care about include paths any longer. Or course, the
+ path will be interpreted relatively to "util/foo" and will be
+ adjusted according to the <b class="command">bjam</b>s invocation
+ directory. For
+ example, if building from project root, the final compiler's
+ command line will contain <tt class="option">-Ilib/foo</tt>.
+ </p>
+<p>The second problem is that we hardcode the path to library's
+ Jamfile. Imagine it's hardcoded in 20 different places and we
+ change the directory layout. The solution is to use project ids
+ — symbolic names, not tied to directory layout. First, we
+ assign a project id to Jamfile in util/foo:</p>
+<pre class="programlisting">
+project foo
+ : usage-requirements <include>.
+ ;
+</pre>
+<p>
+ Second, we use the project id to refer to the library in
+ src/Jamfile:
+
+</p>
+<pre class="programlisting">
+exe app : app.cpp /foo//bar ;
+</pre>
+<p>
+
+ The "/foo//bar" syntax is used to refer to target "foo" in
+ project with global id "/foo" (the slash is used to specify global
+ id). This way, users of "foo" do not depend on its location, only
+ on id, which is supposedly stable. The only thing left, it to make
+ sure that src/Jamfile knows the project id that it uses. We add to
+ top/Jamfile the following line:
+
+</p>
+<pre class="programlisting">
+use-project /foo : util/foo ;
+</pre>
+<p>
+
+ Now, all projects can refer to "foo" using the symbolic
+ name. If the library is moved somewhere, only a single line in the
+ top-level Jamfile should be changed.
+ </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="hierarchy.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="depends.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/linkage.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/linkage.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/linkage.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,134 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Static and shared libaries</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<style type="text/css">
+body { background-image: url('http://docbook.sourceforge.net/release/images/draft.png');
+ background-repeat: no-repeat;
+ background-position: top left;
+ /* The following properties make the watermark "fixed" on the page. */
+ /* I think that's just a bit too distracting for the reader... */
+ /* background-attachment: fixed; */
+ /* background-position: center center; */
+ }</style>
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../tutorial.html" title="Chapter 3. Tutorial">
+<link rel="previous" href="depends.html" title="Library dependencies">
+<link rel="next" href="conditions.html" title="Conditions and alternatives">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="depends.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="conditions.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.tutorial.linkage"></a>Static and shared libaries</h2></div></div>
+<div></div>
+</div>
+<p>While the
+ previous section explained how to create and use libraries, it
+ omitted one important detail. Libraries can be either
+ <span class="emphasis"><em>static</em></span>, which means they are included in executable
+ files which use them, or <span class="emphasis"><em>shared</em></span> (a.k.a.
+ <span class="emphasis"><em>dynamic</em></span>), which are only referred to from executables,
+ and must be available at run time. Boost.Build can work with both
+ types. By default, all libraries are shared. This is much more
+ efficient in build time and space. But the need to install all
+ libraries to some location is not always convenient, especially
+ for debug builds. Also, if the installed shared library changes,
+ all application which use it might start to behave differently.
+ </p>
+<p>Static libraries do not suffer from these problems, but
+ considerably increase the size of application. Before describing
+ static libraries, it's reasonable to give another, quite simple
+ approach. If your project is built with
+ <hardcode-dll-paths>true property, then the application
+ will include the full paths for all shared libraries, eliminating
+ the above problems. Unfortunately, you no longer can move shared
+ library to a different location, which makes this option suitable
+ only for debug builds. Further, only gcc compiler supports this
+ option.</p>
+<p>Building a library statically is easy. You'd need to change
+ the value of <link> feature from it's deafault value
+ <tt class="literal">shared</tt>, to <tt class="literal">static</tt>. So, to build everything as
+ static libraries, you'd say</p>
+<pre class="screen">
+bjam link=static
+</pre>
+<p>
+ on the command line. The linking mode can be fine-tuned on
+ per-target basis.
+
+ </p>
+<div class="orderedlist"><ol type="1">
+<li>
+<p>
+ Suppose your library can be only build statically. This is
+ easily achieved using requirements:
+
+</p>
+<pre class="programlisting">
+lib l : l.cpp : <link>static ;
+</pre>
+</li>
+<li>
+<p>
+ What if library can be both static and shared, but when
+ using it in specific executable, you want it static?
+ <a href="../../">Target
+ references</a> are here to help:
+
+</p>
+<pre class="programlisting">
+exe important : main.cpp helpers/<link>static ;
+</pre>
+</li>
+<li>
+<p>
+ What if the library is defined in some other project, which
+ you cannot change. But still, you want static linking to that
+ library in all cases. You can use target references everywhere:
+
+</p>
+<pre class="programlisting">
+exe e1 : e1.cpp /other_project//bar/<link>static ;
+exe e10 : e10.cpp /other_project//bar/<link>static ;
+</pre>
+<p>
+
+ but that's far from being convenient. Another way is to
+ introduce a level of indirection: create a local target, which will
+ refer to static version of <tt class="filename">foo</tt>. Here's the
+ solution:
+
+</p>
+<pre class="programlisting">
+alias foo : /other_project//bar/<link>static ;
+exe e1 : e1.cpp foo ;
+exe e10 : e10.cpp foo ;
+</pre>
+<p>
+
+ Note that the <a href="../advanced/builtins/targets.html#bbv2.builtins.alias" title="Alias">alias</a>
+ rule is specifically used for rename a reference to a target and possibly
+ change the properties.
+
+ </p>
+</li>
+</ol></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="depends.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="conditions.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/prebuilt.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/prebuilt.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/prebuilt.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,114 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Prebuilt targets</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<style type="text/css">
+body { background-image: url('http://docbook.sourceforge.net/release/images/draft.png');
+ background-repeat: no-repeat;
+ background-position: top left;
+ /* The following properties make the watermark "fixed" on the page. */
+ /* I think that's just a bit too distracting for the reader... */
+ /* background-attachment: fixed; */
+ /* background-position: center center; */
+ }</style>
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../tutorial.html" title="Chapter 3. Tutorial">
+<link rel="previous" href="conditions.html" title="Conditions and alternatives">
+<link rel="next" href="../advanced.html" title="Chapter 4. User documentation">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="conditions.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="../advanced.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.tutorial.prebuilt"></a>Prebuilt targets</h2></div></div>
+<div></div>
+</div>
+<p>
+ We've just learned how to use libraries which are created by
+ Boost.Build. But some libraries are not. At the same time, those
+ libraries can have different versions (release and debug, for
+ example), that we
+ should select depending on build properties. Prebuilt targets
+ provide a mechanism for that. Jamfile in util/lib2 can contain:
+
+</p>
+<pre class="programlisting">
+lib lib2
+ :
+ : <file>lib2_release.a <variant>release
+ ;
+
+lib lib2
+ :
+ : <file>lib2_debug.a <variant>debug
+ ;
+</pre>
+<p>
+
+ This defines two alternatives for target "lib2", and for each
+ one names a prebuilt file. Naturally, there are no sources.
+ Instead, the <file> feature is used to specify the file name.
+ Which alternative is selected depends on properties of dependents.
+ If "app" binary should use "lib2", we can write:
+
+</p>
+<pre class="programlisting">
+exe app : app.cpp ../util/lib2//lib2 ;
+</pre>
+<p>
+
+ If we build release version of "app", then it will be linked
+ with "lib2_release.a", and debug version will use "lib2_debug.a".
+ Another important kind of prebuilt targets are system libraries
+ — more specifically, libraries which are automatically found
+ by the compiler. E.g. gcc uses "-l" switch for that. Such libraries
+ should be declared almost like regular ones:
+
+</p>
+<pre class="programlisting">
+lib zlib : : <name>z ;
+</pre>
+<p>
+
+ We again don't specify any sources, but give a name which
+ should be passed to the compiler. In this example, and for gcc
+ compiler, the "-lz" option will be added. Paths where library
+ should be searched can also be specified:
+
+</p>
+<pre class="programlisting">
+lib zlib : : <name>z <search>/opt/lib ;
+</pre>
+<p>
+
+ And, of course, two variants can be used:
+
+</p>
+<pre class="programlisting">
+lib zlib : : <name>z <variant>release ;
+lib zlib : : <name>z_d <variant>debug ;
+</pre>
+<p>
+
+ Of course, you'll probably never in your life need debug
+ version of zlib, but for other libraries this is quite reasonable.
+ </p>
+<p>More advanced use of prebuilt target is described in <a href="doc/recipes.html#site_config_targets" target="_top">recipes</a>.</p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="conditions.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="../advanced.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/properties.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/properties.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial/properties.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,167 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Properties</title>
+<link rel="stylesheet" href="../../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<style type="text/css">
+body { background-image: url('http://docbook.sourceforge.net/release/images/draft.png');
+ background-repeat: no-repeat;
+ background-position: top left;
+ /* The following properties make the watermark "fixed" on the page. */
+ /* I think that's just a bit too distracting for the reader... */
+ /* background-attachment: fixed; */
+ /* background-position: center center; */
+ }</style>
+<link rel="home" href="../../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../tutorial.html" title="Chapter 3. Tutorial">
+<link rel="previous" href="../tutorial.html" title="Chapter 3. Tutorial">
+<link rel="next" href="hierarchy.html" title="Project Hierarchies">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../tutorial.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="hierarchy.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.tutorial.properties"></a>Properties</h2></div></div>
+<div></div>
+</div>
+<div class="toc"><dl>
+<dt><a href="properties.html#bbv2.tutorial.properties.requirements">Build Requests and Target Requirements</a></dt>
+<dt><a href="properties.html#bbv2.tutorial.properties.project_attributes">Project Attributes</a></dt>
+</dl></div>
+<p>
+ To portably represent aspects of target configuration such as
+ debug and release variants, or single- and multi-threaded
+ builds, Boost.Build uses <i class="firstterm">features</i> with
+ associated <i class="firstterm">values</i>. For
+ example, the "debug-symbols" feature can have a value of "on" or
+ "off". A <i class="firstterm">property</i> is just a (feature,
+ value) pair. When a user initiates a build, Boost.Build
+ automatically translates the requested properties into appropriate
+ command-line flags for invoking toolset components like compilers
+ and linkers.</p>
+<p>There are many built-in features that can be combined to
+ produce arbitrary build configurations. The following command
+ builds the project's "release" variant with inlining
+ disabled and debug symbols enabled:
+
+</p>
+<pre class="screen">
+bjam release inlining=off debug-symbols=on
+</pre>
+<p>Properties on the command-line are specified with the syntax:
+
+</p>
+<pre class="screen"><i class="replaceable"><tt>feature-name</tt></i>=<i class="replaceable"><tt>feature-value</tt></i></pre>
+<p>The "release" and "debug" that we've seen
+ in <b class="command">bjam</b> invocations are just a shorthand way to
+ specify values of the "variant" feature. For example, the command
+ above could also have been written this way:
+
+ </p>
+<pre class="screen">
+bjam variant=release inlining=off debug-symbols=on
+ </pre>
+<p> "variant" is so commonly-used that it has been given
+ special status as an <i class="firstterm">implicit</i> feature
+ — Boost.Build will deduce the its identity just from the name
+ of one of its values.
+ </p>
+<p>
+ A complete description of features can be found
+ <a href="../reference/definitions.html#bbv2.reference.features" title="Features and properties">here</a>.
+ </p>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.tutorial.properties.requirements"></a>Build Requests and Target Requirements</h3></div></div>
+<div></div>
+</div>
+<p>
+ The set of properties specified in the command line constitute a
+ <i class="firstterm">build request</i> — a description of
+ the desired properties for building the requested targets (or,
+ if no targets were explicitly requested, the project in the
+ current directory). The <span class="emphasis"><em>actual</em></span> properties
+ used for building targets is typically a combination of the
+ build request and properties derived from the
+ project's <tt class="filename">Jamfile</tt>s. For example, the
+ locations of <tt class="computeroutput">#include</tt>d header files are normally
+ not specified on the command-line, but described
+ in <tt class="filename">Jamfile</tt>s as <i class="firstterm">target
+ requirements</i> and automatically combined with the
+ build request for those targets. Multithread-enabled
+ compilation is another example of a typical target requirement.
+ The <tt class="filename">Jamfile</tt> fragment below illustrates how
+ these requirements might be specified.
+ </p>
+<pre class="programlisting">
+exe hello
+ : hello.cpp
+ : <include>/home/ghost/Work/boost <threading>multi
+ ;
+</pre>
+<p>
+ When <tt class="filename">hello</tt> is built, the two
+ requirements specified above will normally always be present.
+ If the build request given on the <b class="command">bjam</b>
+ command-line explictly contradicts a target's requirements,
+ the command-line usually overrides (or, in the case of
+ "free" feautures like <tt class="computeroutput"><include></tt><sup>[<a name="id2473668" href="#ftn.id2473668">1</a>]</sup>,
+ augments) the target requirements. However, when a
+ contradiction of a target's requrements involves certain
+ <i class="firstterm">link-incompatible</i> features, the target
+ will be skipped. See ??? for more information.
+ </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h3 class="title">
+<a name="bbv2.tutorial.properties.project_attributes"></a>Project Attributes</h3></div></div>
+<div></div>
+</div>
+<p>
+ If we want the same requirements for our other
+ target, <tt class="filename">hello2</tt>, we could simply duplicate
+ them. However, as projects grow, that approach leads to a great
+ deal of repeated boilerplate in Jamfiles.
+
+ Fortunately, there's a better way. Each project (i.e. each
+ <tt class="filename">Jamfile</tt>), can specify a set of <i class="firstterm">attributes</i>,
+ including requirements:
+
+</p>
+<pre class="programlisting">
+project
+ : requirements <include>/home/ghost/Work/boost <threading>multi
+ ;
+
+exe hello : hello.cpp ;
+exe hello2 : hello.cpp ;
+</pre>
+<p>
+
+ The effect would be as if we specified the same requirement for
+ both <b class="command">hello</b> and <b class="command">hello2</b>.
+ </p>
+</div>
+<div class="footnotes">
+<br><hr width="100" align="left">
+<div class="footnote"><a href="../reference/definitions.html#bbv2.reference.features.attributes" title="Feature Attributes"><sup>[<a name="ftn.id2473668" href="#id2473668">1</a>] </sup>the section called “Feature Attributes”</a></div>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../tutorial.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="hierarchy.html"><img src="../../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/bbv2/tutorial.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,130 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 3. Tutorial</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<style type="text/css">
+body { background-image: url('http://docbook.sourceforge.net/release/images/draft.png');
+ background-repeat: no-repeat;
+ background-position: top left;
+ /* The following properties make the watermark "fixed" on the page. */
+ /* I think that's just a bit too distracting for the reader... */
+ /* background-attachment: fixed; */
+ /* background-position: center center; */
+ }</style>
+<link rel="home" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="up" href="../index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="previous" href="installation.html" title="Chapter 2. Installation">
+<link rel="next" href="tutorial/properties.html" title="Properties">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="installation.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="tutorial/properties.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title">
+<a name="bbv2.tutorial"></a>Chapter 3. Tutorial</h2></div></div>
+<div></div>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><a href="tutorial.html#bbv2.tutorial.hello">Hello, world</a></dt>
+<dt><a href="tutorial/properties.html">Properties</a></dt>
+<dt><a href="tutorial/hierarchy.html">Project Hierarchies</a></dt>
+<dt><a href="tutorial/libs.html">Libraries and Dependent Targets</a></dt>
+<dt><a href="tutorial/depends.html">Library dependencies</a></dt>
+<dt><a href="tutorial/linkage.html">Static and shared libaries</a></dt>
+<dt><a href="tutorial/conditions.html">Conditions and alternatives</a></dt>
+<dt><a href="tutorial/prebuilt.html">Prebuilt targets</a></dt>
+</dl>
+</div>
+<div class="section" lang="en">
+<div class="titlepage">
+<div><div><h2 class="title" style="clear: both">
+<a name="bbv2.tutorial.hello"></a>Hello, world</h2></div></div>
+<div></div>
+</div>
+<p>The simplest project that Boost.Build can construct is
+ stored in <tt class="filename">example/hello/</tt> directory. The
+ project is described by a file
+ called <tt class="filename">Jamfile</tt> that contains:
+
+</p>
+<pre class="programlisting">
+exe hello : hello.cpp ;
+</pre>
+<p>
+
+ Even with this simple setup, you can do some interesting
+ things. First of all, just invoking <b class="command">bjam</b> will
+ build the debug variant of the <b class="command">hello</b>
+ executable by compiling and
+ linking <tt class="filename">hello.cpp</tt>. Now, to build the
+ release variant of <b class="command">hello</b>, invoke
+
+</p>
+<pre class="screen">
+bjam release
+</pre>
+<p>
+
+ Note that debug and release variants are created in different
+ directories, so you can switch between variants or even build
+ multiple variants at once, without any unneccessary
+ recompilation. Let's extend the example by adding another line
+ to our project's <tt class="filename">Jamfile</tt>:
+
+</p>
+<pre class="programlisting">
+exe hello2 : hello.cpp ;
+</pre>
+<p>
+
+ Now we can build both the debug and release variants of our
+ project:
+
+</p>
+<pre class="screen">
+bjam debug release
+</pre>
+<p>
+
+ Note that two variants of <b class="command">hello2</b> are linked.
+ Since we have already built both variants
+ of <b class="command">hello</b>, hello.cpp won't be recompiled;
+ instead the existing object files will just be linked into the
+ corresponding variants of <b class="command">hello2</b>. Now
+ let's remove all the built products:
+
+</p>
+<pre class="screen">
+bjam --clean debug release
+</pre>
+<p>
+
+ It's also possible to build or clean specific targets. The
+ following two commands, respectively, build or clean only the
+ debug version of <b class="command">hello2</b>.
+
+</p>
+<pre class="screen">
+bjam hello2
+bjam --clean hello2
+</pre>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="installation.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="tutorial/properties.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/html/boostbook.css
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/boostbook.css 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/boostbook.css 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,331 @@
+/*=============================================================================
+ Copyright (c) 2002 2004 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Use, modification and distribution is subject to 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)
+=============================================================================*/
+
+/* CSS based on w3c documentation which I like a lot, and the classic Spirit
+documentation. */
+
+/* Body defaults */
+body
+{
+ padding: 2em 1em 2em 1em;
+ margin: 1em 1em 1em 1em;
+ font-family: sans-serif;
+}
+
+/* Paragraphs */
+p
+{
+ text-align: justify;
+}
+
+pre.synopsis
+{
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+}
+
+/* Headings */
+h1, h2, h3, h4, h5, h6 { text-align: left; margin-top: 2pc; }
+h1 { font: 170% sans-serif }
+h2 { font: bold 140% sans-serif }
+h3 { font: 120% sans-serif }
+h4 { font: bold 100% sans-serif }
+h5 { font: italic 100% sans-serif }
+h6 { font: italic 100% sans-serif }
+
+/* Unordered lists */
+ul
+{
+ text-align: justify;
+}
+
+/* Links */
+a
+{
+ text-decoration: none; /* no underline */
+}
+
+a:hover
+{
+ text-decoration: underline;
+}
+
+/* Top page title */
+title, h1.title, h2.title, h3.title,
+ h4.title, h5.title, h6.title,
+ .refentrytitle
+{
+ font-weight: bold;
+ font-size: 2pc;
+ margin-bottom: 1pc;
+}
+
+/* Spirit style navigation */
+.spirit-nav
+{
+ text-align: right;
+}
+
+.spirit-nav a
+{
+ color: white;
+ padding-left: 0.5em;
+}
+
+.spirit-nav img
+{
+ border-width: 0px;
+}
+
+/* Program listing box */
+.programlisting, .screen
+{
+ display: block;
+ margin-left: 4%;
+ margin-right: 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+}
+
+/* Table of contents */
+.toc
+{
+ margin: 1pc 4% 0pc 4%;
+ padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+}
+
+.boost-toc
+{
+ float: right;
+ padding: 0.5pc;
+}
+
+/* Tables */
+.table-title, div.table p.title
+{
+ margin-left: 4%;
+ padding-right: 0.5em;
+ padding-left: 0.5em;
+ font-size: 120%;
+}
+
+.informaltable table, .table table
+{
+ width: 92%;
+ margin-left: 4%;
+ margin-right: 4%;
+}
+
+div.informaltable table, div.table table
+{
+ padding: 4px 4px 4px 4px;
+}
+
+div.informaltable table tr td, div.table table tr td
+{
+ padding: 0.5em 0.5em 0.5em 0.5em;
+ text-align: justify;
+}
+
+div.informaltable table tr th, div.table table tr th
+{
+ padding: 0.5em 0.5em 0.5em 0.5em;
+ border: 1pt solid white;
+}
+
+/* inlined images */
+.inlinemediaobject
+{
+ padding: 0.5em 0.5em 0.5em 0.5em;
+}
+
+/* tone down the title of Parameter lists */
+div.variablelist p.title
+{
+ font-weight: bold;
+ font-size: 100%;
+ text-align: left;
+}
+
+/* tabularize parameter lists */
+div.variablelist dl dt
+{
+ float: left;
+ clear: left;
+ display: block;
+ font-style: italic;
+}
+
+div.variablelist dl dd
+{
+ display: block;
+ clear: right;
+ padding-left: 8pc;
+}
+
+/* title of books and articles in bibliographies */
+span.title
+{
+ font-style: italic;
+}
+
+div.tip, div.note, div.warning
+{
+ padding: 0.5em 0.5em 0.5em 0.5em;
+ border: 1pt solid white;
+}
+
+div.tip .title, div.note .title, div.warning .title
+{
+ font: bold 100% sans-serif;
+ margin-top: 0pc;
+}
+
+div.tip .title:before
+{
+ content: url(images/tip.png) " ";
+}
+
+div.note .title:before
+{
+ content: url(images/note.png) " ";
+}
+
+div.warning .title:before
+{
+ content: url(images/caution.png) " ";
+}
+
+ at media screen
+{
+ a
+ {
+ color: #005a9c;
+ }
+
+ a:visited
+ {
+ color: #9c5a9c;
+ }
+
+ /* Syntax Highlighting */
+ .keyword { color: #0000AA; font-weight: bold; }
+ .identifier {}
+ .special { color: #707070; }
+ .preprocessor { color: #402080; font-weight: bold; }
+ .char { color: teal; }
+ .comment { color: #800000; }
+ .string { color: teal; }
+ .number { color: teal; }
+ .copyright { color: #666666; font-size: small; }
+ .white_bkd { background-color: #FFFFFF; }
+ .dk_grey_bkd { background-color: #999999; }
+
+ pre.synopsis
+ {
+ background-color: #f3f3f3;
+ }
+
+ .programlisting, .screen
+ {
+ background-color: #f3f3f3;
+ }
+
+ /* Table of contents */
+ .toc
+ {
+ background-color: #f3f3f3;
+ }
+
+ div.informaltable table tr td, div.table table tr td
+ {
+ background-color: #F3F3F3;
+ border: 1pt solid white;
+ }
+
+ div.informaltable table tr th, div.table table tr th
+ {
+ background-color: #e4e4e4;
+ }
+
+ div.tip, div.note, div.warning
+ {
+ background-color: #F3F3F3;
+ }
+
+ span.highlight
+ {
+ color: #00A000;
+ }
+}
+
+ at media print
+{
+ a
+ {
+ color: black;
+ }
+
+ a:visited
+ {
+ color: black;
+ }
+
+ .spirit-nav
+ {
+ display: none;
+ }
+
+ /* Syntax Highlighting */
+ .keyword
+ {
+ font-weight: bold;
+ }
+
+ pre.synopsis
+ {
+ border: 1px solid gray;
+ }
+
+ .programlisting, .screen
+ {
+ border: 1px solid gray;
+ }
+
+ /* Table of contents */
+ .toc
+ {
+ border: 1px solid gray;
+ }
+
+ .informaltable table, .table table
+ {
+ border: 1px solid gray;
+ border-collapse: collapse;
+ }
+
+ div.informaltable table tr td, div.table table tr td
+ {
+ border: 1px solid gray;
+ }
+
+ div.informaltable table tr th, div.table table tr th
+ {
+ border: 1px solid gray;
+ }
+
+ div.tip, div.note, div.warning
+ {
+ border: 1px solid gray;
+ }
+
+ span.highlight
+ {
+ font-weight: bold;
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/blank.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/caution.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/caution.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/draft.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/draft.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/home.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/home.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/important.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/important.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/next.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/next.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/note.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/note.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/prev.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/prev.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/tip.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/tip.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/toc-blank.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/toc-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/toc-minus.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/toc-minus.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/toc-plus.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/toc-plus.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/up.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/up.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/images/warning.png
===================================================================
(Binary files differ)
Property changes on: boost-jam/boost-build/branches/upstream/current/doc/html/images/warning.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: boost-jam/boost-build/branches/upstream/current/doc/html/index.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/html/index.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/html/index.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,113 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Part I. Boost.Build v2 User Manual</title>
+<link rel="stylesheet" href="boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.61.3">
+<link rel="home" href="index.html" title="Part I. Boost.Build v2 User Manual">
+<link rel="next" href="bbv2/howto.html" title="Chapter 1. How to use this document">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../boost.png"></td></table>
+<hr>
+<div class="spirit-nav"><a accesskey="n" href="bbv2/howto.html"><img src="images/next.png" alt="Next"></a></div>
+<div class="part" lang="en">
+<div class="titlepage">
+<div><div><h1 class="title">
+<a name="bbv2"></a>Boost.Build v2 User Manual</h1></div></div>
+<div></div>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt>1. <a href="bbv2/howto.html">How to use this document</a>
+</dt>
+<dt>2. <a href="bbv2/installation.html">Installation</a>
+</dt>
+<dt>3. <a href="bbv2/tutorial.html">Tutorial</a>
+</dt>
+<dd><dl>
+<dt><a href="bbv2/tutorial.html#bbv2.tutorial.hello">Hello, world</a></dt>
+<dt><a href="bbv2/tutorial/properties.html">Properties</a></dt>
+<dt><a href="bbv2/tutorial/hierarchy.html">Project Hierarchies</a></dt>
+<dt><a href="bbv2/tutorial/libs.html">Libraries and Dependent Targets</a></dt>
+<dt><a href="bbv2/tutorial/depends.html">Library dependencies</a></dt>
+<dt><a href="bbv2/tutorial/linkage.html">Static and shared libaries</a></dt>
+<dt><a href="bbv2/tutorial/conditions.html">Conditions and alternatives</a></dt>
+<dt><a href="bbv2/tutorial/prebuilt.html">Prebuilt targets</a></dt>
+</dl></dd>
+<dt>4. <a href="bbv2/advanced.html">User documentation</a>
+</dt>
+<dd><dl>
+<dt><a href="bbv2/advanced.html#bbv2.advanced.configuration">Configuration</a></dt>
+<dt><a href="bbv2/advanced/jamfiles.html">Writing Jamfiles</a></dt>
+<dt><a href="bbv2/advanced/build_process.html">Build process</a></dt>
+<dt><a href="bbv2/advanced/builtins/targets.html">Builtin target types</a></dt>
+<dt><a href="bbv2/advanced/builtins/features.html">Builtin features</a></dt>
+<dt><a href="bbv2/advanced/differences_to_v1.html">Differences to Boost.Build V1</a></dt>
+</dl></dd>
+<dt>5. <a href="bbv2/extender.html">Extender Manual</a>
+</dt>
+<dd><dl>
+<dt><a href="bbv2/extender.html#bbv2.extender.intro">Introduction</a></dt>
+<dt><a href="bbv2/extending/targets.html">Target types</a></dt>
+<dt><a href="bbv2/extending/tools.html">Tools and generators</a></dt>
+<dt><a href="bbv2/extending/features.html">Features</a></dt>
+<dt><a href="bbv2/extending/rules.html">Main target rules</a></dt>
+<dt><a href="bbv2/extending/toolset_modules.html">Toolset modules</a></dt>
+</dl></dd>
+<dt>6. <a href="bbv2/reference.html">Detailed reference</a>
+</dt>
+<dd><dl>
+<dt><a href="bbv2/reference.html#bbv2.reference.general">General information</a></dt>
+<dt><a href="bbv2/reference/jamfiles.html">Writing Jamfiles</a></dt>
+<dt><a href="bbv2/reference/buildprocess.html">Build process</a></dt>
+<dt><a href="bbv2/reference/definitions.html"></a></dt>
+<dt><a href="bbv2/reference/generators.html">Generators</a></dt>
+</dl></dd>
+<dt>7. <a href="bbv2/faq.html">Frequently Asked Questions</a>
+</dt>
+<dd><dl>
+<dt><a href="bbv2/faq.html#id2540813">
+ I'm getting "Duplicate name of actual target" error. What
+ does it mean?
+ </a></dt>
+<dt><a href="bbv2/faq/s02.html">
+ Accessing environment variables
+ </a></dt>
+<dt><a href="bbv2/faq/s03.html">
+ How to control properties order?
+ </a></dt>
+<dt><a href="bbv2/faq/s04.html">
+ How to control the library order on Unix?
+ </a></dt>
+<dt><a href="bbv2/faq/external.html">Can I get output of external program as a variable in a Jamfile?
+ </a></dt>
+<dt><a href="bbv2/faq/s06.html">How to get the project-root location?
+ </a></dt>
+<dt><a href="bbv2/faq/s07.html">How to change compilation flags for one file?
+ </a></dt>
+<dt><a href="bbv2/faq/dll-path.html">Why are the dll-path and
+ hardcode-dll-paths properties useful?
+ </a></dt>
+<dt><a href="bbv2/recipies/site-config.html">Targets in site-config.jam</a></dt>
+</dl></dd>
+<dt>A. <a href="bbv2/arch.html">Boost.Build v2 architecture</a>
+</dt>
+<dd><dl>
+<dt><a href="bbv2/arch.html#bbv2.arch.overview">Overview</a></dt>
+<dt><a href="bbv2/arch/build.html">The build layer</a></dt>
+<dt><a href="bbv2/arch/tools.html">The tools layer</a></dt>
+<dt><a href="bbv2/arch/targets.html">Targets</a></dt>
+</dl></dd>
+</dl>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"><small><p>Last revised: October 21, 2004 at 10:05:15 GMT</p></small></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav"><a accesskey="n" href="bbv2/howto.html"><img src="images/next.png" alt="Next"></a></div>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/doc/project-root.jam
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/doc/src/advanced.xml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/src/advanced.xml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/src/advanced.xml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1408 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <chapter id="bbv2.advanced">
+ <title>User documentation</title>
+
+ <para>This section will provide the information necessary to create your own
+ projects using Boost.Build. The information provided here is relatively
+ high-level, and <link linkend="bbv2.reference">detailed reference</link> as
+ well as the on-line help system must be used to obtain
+ low-level documentation (see the <link linkend=
+ "bbv2.reference.init.options.help">help option</link>).</para>
+
+ <para>The Boost.Build actually consists of two parts - Boost.Jam, which is a
+ build engine with its own interpreted language, and Boost.Build itself,
+ implemented in Boost.Jam's language. The chain of event which happen when
+ you type "bjam" on the command is:
+ <orderedlist>
+ <listitem>
+ <para>Boost.Jam tries to find Boost.Build and loads the top-level
+ module. The exact process is described in the <link
+ linkend="bbv2.reference.init">section on
+ initialization</link></para>
+ </listitem>
+ <listitem>
+ <para>Boost.Build top-level module loads user-defined configuration
+ files, "user-config.jam" and "site-config.jam", which define
+ available toolsets.</para>
+ </listitem>
+ <listitem>
+ <para>The Jamfile in the current directory is read. That in turn
+ might cause reading of further Jamfiles. As a result, a tree of
+ projects is created, with targets inside projects.</para>
+ </listitem>
+ <listitem>
+ <para>Finally, using build request specified on the command line,
+ Boost.Build decides which targets should be built, and how. That
+ information is passed back to Boost.Jam, which takes care of
+ actually running commands.</para>
+ </listitem>
+ </orderedlist>
+ </para>
+
+ <para>So, to be able to successfully use Boost.Build, you'd need to know only
+ three things:
+ <itemizedlist>
+ <listitem>
+ <para><link linkend="bbv2.advanced.configuration">
+ How to configure Boost.Build</link></para>
+ </listitem>
+ <listitem>
+ <para><link linkend="bbv2.advanced.jamfiles">
+ How to write Jamfiles</link></para>
+ </listitem>
+ <listitem>
+ <para><link linkend="bbv2.advanced.build_process">
+ How the build process works</link></para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+
+ <section id="bbv2.advanced.configuration">
+ <title>Configuration</title>
+
+ <para>The Boost.Build configuration is specified in the file
+ "user-config.jam". You can edit the one which comes with Boost.Build, or
+ create a copy in your home directory and edit that. (See the <link
+ linkend="bbv2.reference.init.config">reference</link> for the exact search
+ paths.) The primary function of that file is to declarate which compilers
+ and other tools are available. The simplest syntax to configure a tool is:
+<programlisting>
+using <tool-name> ;
+</programlisting>
+ The "using" rule is given a name of tool, and will make that tool
+ available to Boost.Build. For example, "using gcc ;" will make available
+ the gcc compiler.
+ </para>
+
+ <para>
+ Since nothing but tool name is specified, Boost.Build will pick some
+ default settings -- for example will use gcc found in path, or look in
+ some known installation locations. For ordinary users, this is quite
+ fine. In case you have several version of a compiler, or it's located in
+ some unusual location, or you need to tweak the configuration, you'd
+ need to pass additional parameters to the "using" rule. Generally,
+ for every tool module, the parameters differ, and you can obtain the documentaiton
+ by running
+<programlisting>
+bjam --help <tool-name>.init
+</programlisting>
+ on the command line. However, for all compilers the meaning of the first
+ three parameters is the same: version, invocation command and options.
+ </para>
+
+ <para>The "version" parameter identifies the compiler, in case you have
+ several. It can have any form you like, but it's recommended that you use
+ a numeric identifier, like "7.1". The "invocation command"
+ parameter is the command which must be executed to run the compiler. This
+ might be just compiler name, or a name with a path in it. Here are some
+ examples.
+ </para>
+
+ <para>To configure a compiler installed in non-standard location and not
+ present in path, you can do the following:
+<programlisting>
+using msvc : : Z:/Programs/Microsoft Visual Studio/vc98/bin/cl.exe ;
+</programlisting>
+ </para>
+
+ <para>To configure several versions of a compiler, the following can be used.
+<programlisting>
+using gcc : 3.3 ;
+using gcc : 3.4 : g++-3.4 ;
+using gcc : 3.2 : g++-3.2 ;
+</programlisting>
+ Note that in the first call to "using", the compiler found in path
+ will be used, and there's no need to explicitly specify the command.
+ </para>
+
+ <para>As shown above, both "version" and "invocation command" parameters
+ are optional, but there's an important restriction: if you configure the
+ same compiler more then once, you must pass the "version" parameter
+ every time. For example, the following is not allowed:
+<programlisting>
+using gcc ;
+using gcc : 3.4 : g++-3.4 ;
+</programlisting>
+ because the first "using" does not specify the version.
+ </para>
+
+ <para>The <code>options</code> parameter is used to fine-tune the
+ configuration. All compilers allow to pass four option, intentionally
+ similiar in spelling to builtin features: <code>cflags</code>,
+ <code>cxxflags</code>, <code>compileflags</code> and
+ <code>linkflags</code>. They specify additional options which will be
+ always passed to the corresponding tools. The <code>cflags</code> option
+ applies only to the C compiler, the <code>cxxflags</code> option applies
+ only to the C++ compiler and the <code>compileflags</code> options
+ applies to both. For example, to use 64 bit mode with gcc you can use:
+<programlisting>
+using gcc : 3.4 : : <compileflags>-m64 <linkflags>-m64 ;
+</programlisting>
+ </para>
+
+ </section>
+
+ <section id="bbv2.advanced.jamfiles">
+ <title>Writing Jamfiles</title>
+
+ <section id="bbv2.advanced.overview">
+ <title>Overview</title>
+
+ <para>Jamfiles are the thing which is most important to the user,
+ bacause they declare the targets which should be build. Jamfiles are
+ also used for organizing targets -- each Jamfile is a separate project,
+ which can be build independently from the other projects.</para>
+
+ <para>Jamfile mostly contain calls to Boost.Build functions, which do
+ all the work, specifically:
+ <itemizedlist>
+ <listitem>
+ <para><link linkend="bbv2.advanced.targets">declare main
+ targets</link></para>
+ </listitem>
+ <listitem>
+ <para><link
+ linkend="bbv2.advanced.projects">define
+ project properties</link></para>
+ </listitem>
+ <listitem>
+ <para><link linkend="bbv2.advanced.other-rules">do various other
+ things</link></para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>In addition to Jamfiles, Boost.Build has another user-editable
+ file, project-root.jam, which is mostly useful to declare constants
+ global to all the projects. It is described in more detail <link
+ linkend="bbv2.advanced.project-root">below</link>.
+ </para>
+
+<!--
+ <para>The most fundemental entity in Boost.Build is <emphasis>main
+ target</emphasis>. This is object that user want to construct from
+ sources and keep up to date with regard to those sources. Typical
+ examples of main targets are executable files and libraries.</para>
+
+ <para>Main targets are grouped in <emphasis>projects</emphasis>. Their main
+ purpose is organization: related targets placed in one project,
+ can then be built together, or share some definitions.</para>
+
+ <para>Main targets and projects are created as the result of reading
+ one or several Jamfiles. Each Jamfile is a file written in
+ Boost.Jam interpreted language, and typically contains calls to
+ functions provided by Boost.Build, which create main targets of
+ needed type, declare project attributes and access other
+ projects. The full list of functions provided by Boost.Build is
+ described <link linkend="bbv2.advanced.builtins">below</link>.
+ Of course, user can create his own functions, or it can directly
+ access Boost.Build internals from Jamfile, if builtin facilities are
+ not sufficient.</para>
+
+ <para>Each main target, or project can be built in a number of ways,
+ say with optimization or without. We'll call such entities
+ "metatargets". To make Boost.Build produce any real targets, user
+ issues <link linkend="bbv2.reference.buildreq">build request</link>,
+ which specifies metatargets to be built, and properties to be
+ used.</para>
+
+ <para>The <emphasis>properties</emphasis> are just (name,value) pairs that
+ describe various aspects of constructed objects, for example:</para>
+ <programlisting>
+<optimization>full <inlining>off
+</programlisting>
+
+ <para>Given the built request, Boost.Build figures out the targets
+ needed for requested metatargets with requested properties, how
+ they can be created, and whether exising files can be reused. It
+ finally issues command to create needed files, automatically
+ converting properties into appropricate command line options.</para>
+-->
+ </section>
+
+<!--
+ <section id="bbv2.advanced.roadmap">
+ <title>Your first project and roadmap</title>
+
+
+ <para>Creating your first project requires three steps:</para>
+
+ <orderedlist>
+ <listitem><simpara>Create an empty file called "Jamfile"</simpara></listitem>
+
+ <listitem>
+ <simpara>
+ Create an empty file called "project-root.jam"
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <para>Either set your <envar>BOOST_BUILD_PATH</envar> environment
+ variant to Boost.Build root, or create a "boost-build.jam" file
+ with the following content:
+
+<programlisting>
+boost-build /path/to/boost.build ;
+</programlisting>
+
+ </para>
+ </listitem>
+ </orderedlist>
+
+ <para>After that, you can run the "bjam" command in the directory
+ where you've created the files. Surely, it won't do anything, but
+ it will run without error, at least. Your next steps might
+ be:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Adding new main targets to the "Jamfile" file. The basic
+ syntax for declaring a main target is described <link linkend=
+ "bbv2.advanced.targets">below</link>, and all builtin functions for
+ declaring main targets are <link linkend=
+ "bbv2.advanced.builtins.targets">listed</link>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Creating subprojects. Create a directory, put new Jamfile
+ there, and move some main targets to that Jamfile, or declare
+ new ones. The <link linkend="bbv2.advanced.projects">projects
+ reference</link> will help with this part.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Customizing Boost.Build for your needs. You might have
+ additional tools you want to run, or just want different
+ extension for some file. The <link linkend="bbv2.extending">extender manual</ulink> is waiting for
+ you.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ </section>
+-->
+ <section id="bbv2.advanced.targets">
+ <title>Main targets</title>
+
+ <para id="bbv2.advanced.targets.main">
+ <emphasis>Main target</emphasis> is a user-defined named
+ entity which can be build, for example a named executable file.
+ Declaring a main target is usually done using one of <link linkend=
+ "bbv2.advanced.builtins.targets">main target functions</link>.
+ The user can also declare <ulink url=
+ "doc/extending.html#main_target_rules">custom main target
+ function</ulink>.</para>
+
+ <para>Most main targets rules in Boost.Build use similiar
+ syntax:</para>
+
+<anchor id="bbv2.main-target-rule-syntax"/>
+<programlisting>
+function-name main-target-name
+ : sources
+ : requirements
+ : default-build
+ : usage-requirements
+ ;
+</programlisting>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ "main-target-name" is the name used to request the target
+ on command line and to use it from other main targets. Main
+ target name may contain alphanumeric characters and symbols '-'
+ and '_';
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ "sources" is the list of source files and other main
+ targets that must be combined.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ "requirements" is the list of properties that must always
+ be present when this main target is built.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ "default-build" is the list of properties that will be used
+ unless some other value of the same feature is already
+ specified.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ "usage-requirements" is the list of properties that will be
+ propagated to all main targets that use this one, i.e. to all
+ dependents.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>Note that the actual requirements, default-build and
+ usage-requirements attributes for a target are obtained by combining
+ the explicitly specified one with those specified for the project
+ where a target is declared.
+ </para>
+ <para>
+ Some main target rules have shorter list of parameters, and
+ you should consult their documentation for details.
+ </para>
+
+ <para>The list of sources specifies what should be processed to get
+ the resulting targets. Most of the time, it's just a list of
+ files. Sometimes, you'd want to use all files with the same
+ extension as sources, in which case you can use the "glob"
+ rule. Here are two examples:
+<programlisting>
+exe a : a.cpp ;
+exe b : [ glob *.cpp ] ;
+</programlisting>
+ Unless you specify a files with absolute path, the name is
+ considered relative to the source directory -- which is typically
+ the same as directory when Jamfile is located, but can be changed as
+ described <link linkend=
+ "bbv2.advanced.projects.attributes.projectrule">here</link>
+ </para>
+
+ <para>
+ The list of sources can also reference other main targets. The
+ targets in the same project can be referred by using the name, and
+ targets in other project need to specify directory or a symbolic
+ name of the other project. For example:
+<programlisting>
+lib helper : helper.cpp ;
+exe a : a.cpp helper ;
+exe b : b.cpp ..//utils ;
+exe c : c.cpp /boost/program_options//program_opions ;
+</programlisting>
+ The first exe uses the library defined in the same project. The
+ second one uses some target (most likely library) defined by Jamfile
+ one level higher. Finally, the third target uses some <ulink
+ url="http://boost.org">C++ Boost</ulink> library, using the
+ symbolic name to refer to it. More information about it can be found
+ in <link linkend="bbv2.tutorial.libs">tutorial</link> and in
+ <link linkend="bbv2.reference.ids">target id reference</link>.
+ </para>
+
+<!--
+ <section id="bbv2.advanced.targets.requirements">
+ <title>Requirements and usage-requirements</title>
+
+ <para>The requirements argument specify what properties are absolutely
+ necessary for this main target.
+ </section>
+-->
+ <para>Requirements are the properties that should always be present when
+ building a target. Typically, they are includes and defines:
+<programlisting>
+exe hello : hello.cpp : <include>/opt/boost <define>MY_DEBUG ;
+</programlisting>
+ In special circumstances, other properties can be used, for example if
+ a library does not work if it's shared, or a file can't be compiled
+ with optimization due to a compiler bug, one can use
+<programlisting>
+lib util : util.cpp : <link>static ;
+obj main : main.cpp : <optimization>off ;
+</programlisting>
+ </para>
+
+ <para>Sometimes, requirements are necessary only for a specific
+ compiler, or build variant. The
+ <link linkend="v2.reference.variants.propcond">conditional
+ properties</link> can be used in that case:
+<programlisting>
+lib util : util.cpp : <toolset>msvc:<link>static ;
+</programlisting>
+ In means when whenever <code><toolset>msvc</code> property is
+ in build properties, the <code><link>static</code> property will
+ be included as well. The conditional requirements can be "chained":
+<programlisting>
+lib util : util.cpp : <toolset>msvc:<link>static
+ <link>static:<define>STATIC_LINK ;
+</programlisting>
+ will set of static link and the <code>STATIC_LINK</code> define on the
+ <code>msvc</code> toolset.
+ </para>
+
+ <para>The default-build attribute is
+ a set of properties which should be used if build request does not
+ specify a value. For example:
+<programlisting>
+exe hello : hello.cpp : : <threading>multi ;
+</programlisting>
+ would build the target in multi-threaded mode, unless the user
+ explicitly requests single-threaded version. The difference between
+ requirements and default-build is that requirements cannot be
+ overriden in any way.
+ </para>
+
+ <para>A target of the same name can be declared several times. In that
+ case is declaration is called an
+ <firstterm>alternative</firstterm>. When the target is build, one of
+ the alternatives will be selected and use. Alternatives need not be
+ defined by the same main target rule. The following is OK:
+<programlisting>
+lib helpers : helpers.hpp ;
+alias helpers : helpers.lib : <toolset>msvc ;
+</programlisting>
+ </para>
+
+ <para>Building of the same main target can differ greatly from
+ platform to platform. For example, you might have different list
+ of sources for different compilers, or different options for those
+ compilers. Two approaches to this are explained in the
+ <link linkend="bbv2.tutorial.conditions">tutorial</link>.
+ </para>
+
+ <para>Sometimes a main target is really needed only by some other main
+ target. For example, a rule that declares a test-suite uses a main
+ target that represent test, but those main targets are rarely needed
+ by themself.</para>
+
+ <para>It is possible to declare target inline, i.e. the "sources"
+ parameter may include call to other main rules. For example:</para>
+
+<programlisting>
+exe hello : hello.cpp
+ [ obj helpers : helpers.cpp : <optimization>off ] ;
+</programlisting>
+
+ <para>
+ Will cause "helpers.cpp" to be always compiled without
+ optimization. It's possible to request main targets declared
+ inline, but since they are considered local, they are renamed to
+ "parent-main-target_name..main-target-name". In the example above,
+ to build only helpers, one should run "bjam hello..helpers".
+ </para>
+
+ </section>
+
+ <section id="bbv2.advanced.projects">
+ <title>Projects</title>
+
+ <para>As mentioned before, targets are grouped into project, and each
+ Jamfile is a separate project. Projects are useful because it allows
+ to group related targets together, define properties common to all
+ those targets, and assign a symbolic name to the project, allowing to
+ easily refer to the targets in the project. Two last goals are
+ accompished with the "project" rule.
+ </para>
+
+ <para>The rule has this syntax
+<programlisting>
+project id : <attributes> ;
+</programlisting>
+ Here, attributes is a sequence of (attribute-name,
+ attribute-value) pairs. The list of attribute names along with its
+ handling is also shown in the table below. For example, it is
+ possible to write:
+<programlisting>
+project tennis
+ : requirements <threading>multi
+ : default-build release
+ ;
+</programlisting>
+ </para>
+
+ <para>The possible attributes are listed below.</para>
+
+ <para><emphasis>Project id</emphasis> is a short way to denote a project, as
+ opposed to the Jamfile's pathname. It is a hierarchical path,
+ unrelated to filesystem, such as "boost/thread". <link linkend=
+ "bbv2.reference.ids">Target references</link> make use of project ids to
+ specify a target.</para>
+
+ <para><emphasis>Source location</emphasis> specifies the directory where sources
+ for the project are located.</para>
+
+ <para><emphasis>Project requirements</emphasis> are requirements that apply to
+ all the targets in the projects as well as all subprojects.</para>
+
+ <para><emphasis>Default build</emphasis> is the build request that should be
+ used when no build request is specified explicitly.</para>
+
+ <para id="bbv2.advanced.projects.attributes.projectrule">
+ The default values for those attributes are
+ given in the table below.
+
+ <table>
+ <title/>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+
+ <entry>Name for the 'project' rule</entry>
+
+ <entry>Default value</entry>
+
+ <entry>Handling by the 'project' rule</entry>
+ </row>
+ </thead>
+
+ <tbody>
+
+ <row>
+ <entry>Project id</entry>
+
+ <entry>none</entry>
+
+ <entry>none</entry>
+
+ <entry>Assigned from the first parameter of the 'project' rule.
+ It is assumed to denote absolute project id.</entry>
+ </row>
+
+ <row>
+ <entry>Source location</entry>
+
+ <entry><literal>source-location</literal></entry>
+
+ <entry>The location of jamfile for the project</entry>
+
+ <entry>Sets to the passed value</entry>
+ </row>
+
+ <row>
+ <entry>Requirements</entry>
+
+ <entry><literal>requirements</literal></entry>
+
+ <entry>The parent's requirements</entry>
+
+ <entry>The parent's requirements are refined with the passed
+ requirement and the result is used as the project
+ requirements.</entry>
+ </row>
+
+ <row>
+ <entry>Default build</entry>
+
+ <entry><literal>default-build</literal></entry>
+
+ <entry>none</entry>
+
+ <entry>Sets to the passed value</entry>
+ </row>
+
+ <row>
+ <entry>Build directory</entry>
+
+ <entry><literal>build-dir</literal></entry>
+
+ <entry>If parent has a build dir set, the value of it, joined
+ with the relative path from parent to the current project.
+ Otherwise, empty</entry>
+
+ <entry>Sets to the passed value, interpreted as relative to the
+ project's location.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </para>
+ </section>
+
+ <section id="bbv2.advanced.other-rules">
+ <title>Additional Jamfile rules</title>
+
+ <para>There's a number of other helper rules which can be used in
+ Jamfile, described in the following table.</para>
+
+ <table>
+ <title/>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Rule</entry>
+
+ <entry>Semantic</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><link linkend=
+ "bbv2.advanced.projects.attributes.projectrule">project</link>
+ </entry>
+
+ <entry>Define project attributes.</entry>
+ </row>
+
+ <row>
+ <entry><link linkend=
+ "bbv2.advanced.projects.relationships.useprojectrule">use-project</link></entry>
+
+ <entry>Make another project known.</entry>
+ </row>
+
+ <row>
+ <entry><link linkend=
+ "bbv2.advanced.projects.relationships.buildprojectrule">build-project</link></entry>
+
+ <entry>Build another project when this one is built.</entry>
+ </row>
+
+ <row>
+ <entry><link linkend=
+ "bbv2.reference.buildprocess.explict">explicit</link></entry>
+
+ <entry>States that the target should be built only by explicit
+ request.</entry>
+ </row>
+
+ <row>
+ <entry>glob</entry>
+
+ <entry>Takes a list of wildcards, and returns the list of files
+ which match any of the wildcards.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <section id="bbv2.advanced.project-root">
+ <para>Each project is also associated with <emphasis>project root</emphasis>.
+ That's a root for a tree of projects, which specifies some global
+ properties.</para>
+
+ <title>Project root</title>
+
+ <para>
+ Project root for a projects is the nearest parent directory
+ which contains a file called
+ <filename>project-root.jam</filename>. That file defines
+ certain properties which apply to all projects under project
+ root. It can:
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ configure toolsets, via call to <literal>toolset.using</literal>
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ refer to other projects, via the <literal>use-project</literal>
+ rule
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ declare constants, via the <literal>constant</literal> and
+ <literal>path-constant</literal> rules.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ </para>
+
+ <para>To facilitate declaration of simple projects, Jamfile and
+ project-root can be merged together. To achieve this effect, the
+ project root file should call the <literal>project</literal> rule. The
+ semantic is precisely the same as if the call was made in
+ Jamfile, except that project-root.jam will start to serve as
+ Jamfile. The Jamfile in the directory of project-root.jam will be
+ ignored, and project-root.jam will be able to declare main
+ targets as usual.</para>
+
+ </section>
+
+<!--
+ <section id="bbv2.advanced.projects.relationships">
+ <title>Project relationship</title>
+
+ <para>There are three kinds of project relationships.</para>
+
+ <para>First is parent-child. This relationship is established
+ implicitly: parent directories of a project are searched, and the
+ first found Jamfile is assumed to define the parent project. The
+ parent-child relationship affects only attribute values for the
+ child project.</para>
+
+ <para id="bbv2.advanced.projects.relationships.buildprojectrule">
+ Second is build relationship. Some
+ project may request to recursively build other projects. Those
+ project need not be child projects. The <literal>build-project</literal>
+ rule is used for that:</para>
+ <programlisting>
+ build-project src ;
+</programlisting>
+
+ <para id="bbv2.advanced.projects.relationships.useprojectrule">
+ The third kind is the 'use'
+ relationship. In means that one project uses targets from
+ another. It is possible to just refer to target in other projects
+ using target id. However, if target id uses project id, it is
+ required that the project id is known. The
+ <literal>use-project</literal>
+ rule is employed to guarantee that.
+ </para>
+
+<programlisting>
+use-project ( id : location )
+</programlisting>
+
+ <para>
+It loads the project at the specified location, which makes
+its project id available in the project which invokes the rule. It
+is required that the <literal>id</literal> parameter passed to the
+<literal>use-project</literal> rule be equal to the id that the loaded
+project declared. At this moment, the <literal>id</literal> paremeter
+should be absolute project id.
+ </para>
+ </section>
+ </section>
+
+-->
+
+ </section>
+
+ <section id="bbv2.advanced.build_process">
+ <title>Build process</title>
+
+ <para>When you've described your targets, you want Boost.Build to run the
+ right tools and create the needed targets. This section will describe
+ two things: how you specify what to build, and how the main targets are
+ actually constructed.
+ </para>
+
+ <para>The most important thing to note is that in Boost.Build, unlike
+ other build tools, the targets you declare do not correspond to specific
+ files. What you declare in Jamfiles is more like "metatarget". Depending
+ on the properties that you specify on the command line, each
+ "metatarget" will produce a set of real targets corresponding to the
+ requested properties. It is quite possible that the same metatarget is
+ build several times with different properties, and will, of course,
+ produce different files.
+ </para>
+ <tip>
+ <para>
+ This means that for Boost.Build, you cannot directly obtain build
+ variant from Jamfile. There could be several variants requested by the
+ user, and each target can be build with different properties.
+ </para>
+ </tip>
+
+ <section>
+ <title>Build request</title>
+
+ <para>
+ The command line specifies which targets to build and with what
+ properties. For example:
+<programlisting>
+bjam app1 lib1//lib1 toolset=gcc variant=debug optimization=full
+</programlisting>
+ would build two targets, "app1" and "lib1//lib1" with the specified
+ properties. You can refer to any targets, using
+ <link linkend="bbv2.reference.ids">target id</link> and specify arbitrary
+ properties. Some of the properties are very common, and for them the name
+ of the property can be omitted. For example, the above can be written as:
+<programlisting>
+bjam app1 lib1//lib1 gcc debug optimization=full
+</programlisting>
+ The complete syntax which has some additional shortcuts if described <link
+ linkend="bbv2.reference.commandline">here</link>.
+ </para>
+ </section>
+
+ <section><title>Building a main target</title>
+
+ <para>When you request, directly or indirectly, a build of a main target
+ with specific requirements, the following steps are made. Some brief
+ explanation is provided, and more detailes are given in the <link
+ linkend="bbv2.reference.buildprocess">reference</link>.
+ <orderedlist>
+
+ <listitem><para>Applying default build. If the default-build
+ property of a target specifies a value of a feature which is not
+ present in the build request, that value is added.</para></listitem>
+
+ <listitem><para>Selecting the main target alternative to use. For
+ each alternative we look how many properties are present both in
+ alternative's requirements, and in build request. The
+ alternative with large number of matching properties is selected.
+ </para></listitem>
+
+ <listitem><para>Determining "common" properties. The build request
+ is <link linkend="bbv2.reference.variants.proprefine">refined</link>
+ with target's requirements. The conditional properties in
+ requirements are handled as well. Finally, default values of
+ features are added.
+ </para></listitem>
+
+ <listitem><para>Building targets referred by the sources list and
+ dependency properties. The list of sources and the properties
+ can refer to other target using <link
+ linkend="bbv2.reference.ids">target references</link>. For each
+ reference, we take all <link
+ linkend="bbv2.reference.features.attributes.propagated">propagated</link>
+ properties, refine them by explicit properties specified in the
+ target reference, and pass the resulting properties as build
+ request to the other target.
+ </para></listitem>
+
+ <listitem><para>Adding the usage requirements produces when building
+ dependencies to the "common" properties. When dependencies are
+ built in the previous step, they return both the set of created
+ "real" targets, and usage requirements. The usage requirements
+ are added to the common properties and the resulting property
+ set will be used for building the current target.
+ </para></listitem>
+
+ <listitem><para>Building the target using generators. To convert the
+ sources to the desired type, Boost.Build uses "generators" ---
+ objects which correspond to tools like compilers and
+ linkers. Each generator declares what type of targets in can
+ produce and what type of sources it requires. Using this
+ information, Boost.Build determines which generators must be run
+ to produce a specific target from specific sources. When
+ generators are run, they return the "real" targets.
+ </para></listitem>
+
+ <listitem><para>Computing the usage requirements to be returned. The
+ conditional properties in usage requirements are expanded and the
+ result is returned.</para></listitem>
+ </orderedlist>
+ </para>
+ </section>
+
+ <section><title>Building a project</title>
+
+ <para>Often, user request a build of a complete project, not just one
+ main target. In fact, invoking <command>bjam</command> without
+ parameters builds the project defined in the current directory.</para>
+
+ <para>When a project is build, the build request is passed without
+ modification to all main targets in that project. It's is possible to
+ prevent implicit building of a target in a project with the
+ <code>explicit</code> rule:
+<programlisting>
+explicit hello_test ;
+</programlisting>
+ would cause the <code>hello_test</code> target to be built only if
+ explicitly requested by the user or by some other target.
+ </para>
+
+ <para>The Jamfile for a project can include a number of
+ <code>build-project</code> rule calls, that specify additional projects
+ to be built.
+ </para>
+
+ </section>
+
+ </section>
+
+ <section id="bbv2.advanced.builtins.targets">
+ <title>Builtin target types</title>
+
+ <section>
+ <title>Programs</title>
+
+ <para>Programs are created using the <code>exe</code> rule, which
+ follows the <link linkend="bbv2.main-target-rule-syntax">common
+ syntax</link>. For example:
+<programlisting>
+exe hello : hello.cpp some_library.lib /some_project//library
+ : <threading>multi
+ ;
+</programlisting>
+ This will create an executable file from the sources -- in this case,
+ one C++ file, one library file present in the same directory, and
+ another library which is created by Boost.Build. Generally, sources
+ can include C and C++ files, object files and libraries. Boost.Build
+ will automatically try to convert targets of other types.
+ </para>
+
+ <tip>
+ <para>
+ On Windows, if an application uses dynamic libraries, and both
+ the application and the libraries are built by Boost.Build, its not
+ possible to immediately run the application, because the
+ <literal>PATH</literal> environment variable should include the path
+ to the libraries. It means you have to either add the paths
+ manually, or place the application and the libraries to the same
+ directory, for example using the <link linkend="bbv2.builtins.stage">
+ stage</link> rule.
+ </para>
+ </tip>
+ </section>
+
+ <section>
+ <title>Libraries</title>
+
+ <para>Libraries are created using the <code>lib</code> rule, which
+ follows the <link linkend="bbv2.main-target-rule-syntax">common
+ syntax</link>. For example:
+<programlisting>
+lib helpers : helpers.cpp : <include>boost : : <include>. ;
+</programlisting>
+ </para>
+
+ <para>In the most common case, the <code>lib</code> creates a library
+ from the specified sources. Depending on the value of
+ <link> feature the library will be either static or
+ shared. There are two other cases. First is when the library is
+ installed somewhere in compiler's search paths, and should be
+ searched by the compiler (typically, using the <option>-l</option>
+ option). The second case is where the library is available as a
+ prebuilt file and the full path is known.
+ </para>
+
+ <para>
+ The syntax for these case is given below:
+<programlisting>
+lib z : : <name>z <search>/home/ghost ;
+lib compress : : <file>/opt/libs/compress.a ;
+</programlisting>
+ The <code>name</code> property specifies the name which should be
+ passed to the <option>-l</option> option, and the <code>file</code>
+ property specifies the file location. The <code>search</code> feature
+ specifies paths where the library should be searched. That feature can
+ be specified several time, or can be omitted -- in which case only
+ default compiler paths will be searched.
+ </para>
+
+ <para>The difference between using the <code>file</code> feature as
+ opposed to the <code>name</code> name feature together with the
+ <code>search</code> feature is that <code>file</code> is more
+ precise. A specific file will be used. On the other hand, the
+ <code>search</code> feature only adds a library path, and the
+ <code>name</code> feature gives the basic name of the library. The
+ search rules are specific to the linker. For example, given these
+ definition:
+<programlisting>
+lib a : : <variant>release <file>/pool/release/a.so ;
+lib a : : <variant>debug <file>/pool/debug/a.so ;
+lib b : : <variant>release <file>/pool/release/b.so ;
+lib b : : <variant>debug <file>/pool/debug/b.so ;
+</programlisting>
+ It's possible to use release version of <code>a</code> and debug
+ version of <code>b</code>. Had we used the <code>name</code> and
+ <code>search</code> features, the linker would always pick either
+ release or debug versions.
+ </para>
+
+ <para>
+ For convenience, the following syntax is allowed:
+<programlisting>
+lib z ;
+lib gui db aux ;
+</programlisting>
+ and is does exactly the same as:
+<programlisting>
+lib z : : <name>z ;
+lib giu : : <name>gui ;
+lib db : : <name>db ;
+lib aux : : <name>aux ;
+</programlisting>
+ </para>
+
+ <para>When a library uses another library you should put that another
+ library in the list of sources. This will do the right thing in all
+ cases. For portability, you should specify library dependencies even
+ for searched and prebuilt libraries, othewise, static linking on
+ Unix won't work. For example:
+<programlisting>
+lib z ;
+lib png : z : <name>png ;
+</programlisting>
+ </para>
+
+ <note>
+ <para>When a library (say, <code>a</code>), which has another
+ library, (say, <code>b</code>) is linked dynamically, the <code>b</code>
+ library will be incorporated in <code>a</code>. (If <code>b</code>
+ is dynamic library as well, then <code>a</code> will only refer to
+ it, and not include any extra code.) When the <code>a</code>
+ library is linked statically, Boost.Build will assure that all
+ executables which link to <code>a</code> will also link to
+ <code>b</code>.
+ </para>
+ </note>
+
+ <para>One feature of Boost.Build which is very important for libraries
+ is usage requirements. For example, if you write:
+<programlisting>
+lib helpers : helpers.cpp : : : <include>. ;
+</programlisting>
+ then compiler include path for all targets which use
+ <code>helpers</code> will contain the directory where the target is
+ defined.path to "helpers.cpp". So, the user need only to add
+ <code>helpers</code> to the list of sources, and don't bother about
+ other requirements. This allows to greatly simplify Jamfiles.
+ </para>
+
+ <note>
+ <para>If you don't want shared libraries to include all libraries
+ which are specified in sources (especially statically linked ones),
+ you'd need to use the following:
+<programlisting>
+lib b : a.cpp ;
+lib a : a.cpp : <use>b : : <library>b ;
+</programlisting>
+ This specifies that <code>a</code> uses <code>b</code>, and causes
+ all executables which link to <code>a</code> also link to
+ <code>b</code>. In this case, even for shared linking, the
+ <code>a</code> library won't even refer to <code>b</code>.
+ </para>
+ </note>
+
+ </section>
+
+ <section id="bbv2.builtins.alias">
+ <title>Alias</title>
+
+ <para>The <code>alias</code> rule follows the <link
+ linkend="bbv2.main-target-rule-syntax">common syntax</link>. For
+ example:
+<programlisting>
+alias core : im reader writer ;
+</programlisting>
+ will build the sources and return the generated source targets
+ without modification.
+ </para>
+
+ <para>
+ The <code>alias</code> rule is a convenience tool. If you often build
+ the same group of targets at the same time, you can define the alias
+ to save typing.
+ </para>
+
+ <para>
+ Another use of the <code>alias</code> rule is to change build
+ properties. For example, if you always want static linking for a
+ specific C++ Boost library, you can write the following:
+<programlisting>
+alias boost_thread : /boost/thread//boost_thread : <link>static ;
+</programlisting>
+ and use only the <code>boost_thread</code> alias in your Jamfiles.
+ </para>
+
+ <para>
+ It is also allowed to specify usage requirements for the
+ <code>alias</code> target. If you write the following:
+<programlisting>
+alias header_only_library : : : : <include>/usr/include/header_only_library ;
+</programlisting>
+ then using <code>header_only_library</code> in sources will only add an
+ include path. Also note that when there are some sources, their usage
+ requirements are propagated, too. For example:
+<programlisting>
+lib lib : lib.cpp : : : <include>. ;
+alias lib_alias ;
+exe main : main.cpp lib_alias ;
+</programlisting>
+ will compile <filename>main.cpp</filename> with the additional include.
+ </para>
+
+ </section>
+
+ <section id="bbv2.builtins.stage">
+ <title>Installing</title>
+
+ <para>For installing the built target you should use the
+ <code>stage</code> rule follows the <link
+ linkend="bbv2.main-target-rule-syntax">common syntax</link>. For
+ example:
+<programlisting>
+stage dist : hello helpers ;
+</programlisting>
+ will cause the targets <code>hello</code> and <code>helpers</code> to
+ be moved to the <filename>dist</filename> directory. The directory can
+ be changed with the <code>location</code> property:
+<programlisting>
+stage dist : hello helpers : <location>/usr/bin ;
+</programlisting>
+ </para>
+
+ <para>
+ Specifying the names of all libraries to install can be boring. The
+ <code>stage</code> allows to specify only the top-level executable
+ targets to install, and automatically install all dependencies:
+<programlisting>
+stage dist : hello
+ : <traverse-dependencies>on <include-type>EXE
+ <include-type>LIB
+ ;
+</programlisting>
+ will find all targets that <code>hello</code> depends on, and install
+ all of the which are either executables or libraries.
+ </para>
+
+ </section>
+
+ <section id="bbv2.builtins.testing">
+
+ <title>Testing</title>
+
+ <para>Boost.Build has convenient support for running unit tests. The
+ simplest way is the <code>unit-test</code> rule, which follows the
+ <link linkend="bbv2.main-target-rule-syntax">common syntax</link>. For
+ example:
+<programlisting>
+unit-test helpers_test : helpers_test.cpp helpers ;
+</programlisting>
+ </para>
+
+ <para>The <code>unit-test</code> rule behaves like the
+ <code>exe</code> rule, but after the executable is created it is
+ run. If the executable returns error, the build system will also
+ return error and will try running the executable on the next
+ invocation until it runs successfully. This behaviour ensures that you
+ can't miss a unit test failure.
+ </para>
+
+ <para>There are rules for more elaborate testing: <code>compile</code>,
+ <code>compile-fail</code>, <code>run</code> and
+ <code>run-fail</code>. They are more suitable for automated testing, and
+ are not covered here yet.
+ </para>
+ </section>
+
+ </section>
+
+ <section id="bbv2.advanced.builtins.features">
+ <title>Builtin features</title>
+
+ <variablelist>
+ <varlistentry><term><literal>variant</literal></term>
+
+ <listitem>
+ <simpara>
+ The feature which combines several low-level features in
+ order to make building most common variants simple.
+ </simpara>
+
+ <para><emphasis role="bold">Allowed values:</emphasis> <literal>debug</literal>, <literal>release</literal>,
+ <literal>profile</literal></para>
+
+ <para>The value <literal>debug</literal> expands to</para>
+
+ <programlisting>
+ <optimization>off <debug-symbols>on <inlining>off <runtime-debugging>on
+ </programlisting>
+
+ <para>The value <literal>release</literal> expands to</para>
+
+ <programlisting>
+ <optimization>speed <debug-symbols>off <inlining>full <runtime-debugging>off
+ </programlisting>
+
+ <para>The value <literal>profile</literal> expands to the same as
+ <literal>release</literal>, plus:</para>
+
+ <programlisting>
+ <profiling>on <debug-symbols>on
+ </programlisting>
+
+ <para><emphasis role="bold">Rationale:</emphasis> Runtime debugging is on in debug build
+ to suit expectations of people used various IDEs. It's
+ assumed other folks don't have any specific expectation in
+ this point.</para>
+ </listitem></varlistentry>
+
+ <varlistentry id="bbv2.advanced.builtins.features.link">
+ <term><literal>link</literal></term>
+
+ <listitem>
+ <simpara>
+ Feature which controls how libraries are built.
+ </simpara>
+
+ <para><emphasis role="bold">Allowed values:</emphasis> <literal>shared</literal>,
+ <literal>static</literal></para>
+ </listitem></varlistentry>
+
+ <varlistentry><term><literal>source</literal></term>
+
+ <listitem>
+ <simpara>
+ Tthe <source>X feature has the same effect on building a target
+ as putting X in the list of sources. The feature
+ is sometimes more convenient: you can put <source>X in
+ the requirements for a project and it will be linked to all
+ executables.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term><literal>library</literal></term>
+
+ <listitem>
+ <simpara>
+ This feature is equivalent to the <source> feature, and exists
+ for backward compatibility reasons.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry><term><literal>use</literal></term>
+
+ <listitem>
+ <simpara>
+ Causes the target referenced by the value of this feature
+ to be constructed and adds it's usage requirements to build
+ properties. The constructed targets are not used in any other
+ way. The primary use case is when you use some library and want
+ it's usage requirements (such as include paths) to be applied,
+ but don't want to link to the library.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term><literal>dll-path</literal></term>
+
+ <listitem>
+ <simpara>
+ Specify an additional path where shared libraries should be
+ searched where the executable or shared library is run. This
+ feature only affect Unix compilers. Plase see the <link
+ linkend="bbv2.faq.dll-path">FAQ entry</link> for details.
+ </simpara>
+ </listitem></varlistentry>
+
+ <varlistentry><term><literal>hardcode-dll-paths</literal></term>
+
+ <listitem>
+ <simpara>
+ Controls automatic generation of dll-path properties.
+ </simpara>
+
+ <para><emphasis role="bold">Allowed values:</emphasis>
+ <literal>true</literal>, <literal>false</literal>. This property
+ is specific to Unix systems. If an executable is build with
+ <code><hardcode-dll-paths>true</code>, the generated binary
+ will contain the list of all the paths to the used shared
+ libraries. As the result, the executable can be run without
+ changing system paths to shared libraries, or installing the
+ libraries to system paths. This is very convenient during
+ development. Plase see the <link
+ linkend="bbv2.faq.dll-path">FAQ entry</link> for details.
+ </para>
+ </listitem></varlistentry>
+ </variablelist>
+ </section>
+
+ <section id="bbv2.advanced.differences_to_v1">
+ <title>Differences to Boost.Build V1</title>
+
+ <para>While Boost.Build V2 is based on the same ideas as Boost.Build V1,
+ some of the syntax was changed, and some new important features were
+ added. This chapter describes most of the changes.</para>
+
+ <section id="bbv2.advanced.differences_to_v1.configuration">
+ <title>Configuration</title>
+
+ <para>In V1, there were two methods to configure a toolset. One is to
+ set some environment variable, or use "-s" command line option to set
+ variable inside BJam. Another method was creating new toolset module,
+ which would set the variables and then invoke basic toolset. Neither
+ method is necessary now, the "using" rule provides a consistent way to
+ initialize toolset, including several versions. See <link
+ linkend="bbv2.advanced.configuration">section on configuraton</link> for
+ details.
+ </para>
+
+ </section>
+
+ <section id="bbv2.advanced.differences_to_v1.jamfiles">
+ <title>Writing Jamfiles</title>
+
+ <para>Probably one of the most important differences in V2 Jamfiles is
+ the project requirements. In V1, if several targets have the same
+ requirements (for example, common include path), it was necessary to
+ manually write that requirements, or use a helper rule. In V2, the
+ common properties can be specified with the "requirements" project
+ attribute, as documented <link linkend="bbv2.advanced.projects">here</link>.
+ </para>
+
+ <para>The <link linkend="bbv2.tutorial.libs">usage requirements</link>
+ is also important mechanism to simplify Jamfile. If a library requires
+ all clients to use specific includes, or macros when compiling the
+ code which depends on the library, this information can be cleanly
+ represented.</para>
+
+ <para>The difference between "lib" and "dll" targets in V1 is completely
+ eliminated in V2. There's only one target -- "lib", which can create
+ either static or shared library depending on the value of the
+ <link linkend="bbv2.advanced.builtins.features.link"><link>
+ feature</link>. If your target should be only build in one variant, you
+ can add <link>shared or <link>static to requirements.
+ </para>
+
+ <para>The syntax for referring to other targets was changed a bit. While
+ in V1 one would use:
+<programlisting>
+exe a : a.cpp <lib>../foo/bar ;
+</programlisting>
+ the V2 syntax is:
+<programlisting>
+exe a : a.cpp ../foo//bar ;
+</programlisting>
+ Note that you don't need to specify the type of other target, but the
+ last element should be separated to double slash, to indicate that
+ you're referring to target "bar" in project "../foo", and not to
+ project "../foo/bar".
+ </para>
+
+
+ </section>
+
+ <section id="bbv2.advanced.differences_to_v1.build_process">
+ <title>Build process</title>
+
+ <para>The command line syntax in V2 is completely different. For example
+<programlisting>
+bjam -sTOOLS=msvc -sBUILD=release some_target
+</programlisting>
+ now becomes:
+<programlisting>
+bjam toolset=msvc variant=release some_target
+</programlisting>
+ or, using shortcuts, just:
+<programlisting>
+bjam msvc release some_target
+</programlisting>
+ See <link linkend="bbv2.reference.commandline">the reference</link> for
+ complete description of the syntax.
+ </para>
+
+
+ </section>
+
+ </section>
+
+
+ </chapter>
+
+<!--
+ Local Variables:
+ mode: xml
+ sgml-indent-data: t
+ sgml-parent-document: ("userman.xml" "chapter")
+ sgml-set-face: t
+ End:
+-->
Added: boost-jam/boost-build/branches/upstream/current/doc/src/architecture.xml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/src/architecture.xml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/src/architecture.xml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,564 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE appendix PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <appendix id="bbv2.arch">
+ <title>Boost.Build v2 architecture</title>
+
+ <sidebar>
+ <para>This document is work-in progress. Don't expect much from it
+ yet.</para>
+ </sidebar>
+
+ <section id="bbv2.arch.overview">
+ <title>Overview</title>
+
+ <para>The Boost.Build code is structured in four different components:
+ "kernel", "util", "build" and "tools". The first two are relatively
+ uninteresting, so we'll focus on the remaining pair. The "build" component
+ provides classes necessary to declare targets, determine which properties
+ should be used for their building, and for creating the dependency
+ graph. The "tools" component provides user-visible functionality. It
+ mostly allows to declare specific kind of main targets, and declare
+ avaiable tools, which are then used when creating the dependency graph.
+ </para>
+
+ </section>
+
+ <section id="bbv2.arch.build">
+ <title>The build layer</title>
+
+ <para>The build layer has just four main parts -- abstract targets,
+ virtual targets, generators and properties. The abstract targets,
+ represented by the "abstract-target" class, correspond to main targets
+ -- which, as you recall, can produce different files depending on
+ properties. Virtual targets, represented by the 'virtual-target' class
+ correspond to real files. The abstract-target class has a method
+ 'generate', which is given a set of properties and produces virtual
+ targets for those properties.
+ </para>
+
+ <para>There are several classes derived from "abstract-target". The
+ "main-target" class represents top-level main target, the "project-target"
+ acts like container for all main targets, and "basic-target" class is a
+ base class for all further target types.
+ </para>
+
+ <para>Since each main target can have several alternatives, all top-level
+ target objects are just containers, referring to "real" main target
+ classes. The type is that container is "main-target". For example, given:
+<programlisting>
+alias a ;
+lib a : a.cpp : <toolset>gcc ;
+</programlisting>
+ we would have one-top level instance of "main-target-class", which will
+ contain one instance of "alias-target-class" and one instance of
+ "lib-target-class". The "generate" method of "main-target" decides
+ which of the alternative should be used, and call "generate" on the
+ corresponding instance.
+</para>
+
+ <para>Each alternative is a instance of a class derived from
+ "basic-target". The "basic-target.generate" does several things that are
+ always should be done:
+ <itemizedlist>
+ <listitem>
+ <para>Determines what properties should be used for building the
+ target. This includes looking at requested properties, requirements,
+ and usage requirements of all sources.</para>
+ </listitem>
+ <listitem>
+ <para>Builds all sources</para>
+ </listitem>
+ <listitem>
+ <para>Computes the usage requirements which should be passes back.</para>
+ </listitem>
+ </itemizedlist>
+ For the real work of constructing virtual target, a new method
+ "construct" is called.
+ </para>
+
+ <para>The "construct" method can be implemented in any way by classes
+ derived from "basic-target", but one specific derived class plays the
+ central role -- "typed-target". That class holds the desired type of file
+ to be produces, and calls the generators modules to do the job.
+ </para>
+
+ <para>Generators are Boost.Build abstractions for a tool. For example, one
+ can register a generator which converts target of type CPP into target of
+ type OBJ. When run with on a virtual target with CPP type, the generator
+ will construct the virtual target of type OBJ. The "generators" module
+ implements an algorithm, which given a list of sources, the desired type
+ and a list of properties, find all the generators which can perform the conversion.
+ </para>
+
+ <para>The virtual targets which are produces by the main targets form a
+ graph. Targets which are produces from other ones refer to an instance of
+ "action" class, which in turn refers to action's sources, which can
+ further refer to actions. The sources, which are not produces from
+ anything, don't refer to any actions.
+ </para>
+
+ <para>When all virtual targets are produced, they are "actualized". This
+ means that the real file names are computed, and the commands that should
+ be run are generated. This is done by "virtual-target.actualize" and
+ "action.actualize" methods. The first is conceptually simple, while the
+ second need additional explanation. The commands in bjam are generated in
+ two-stage process. First, a rule with the appropriate name (for example
+ "gcc.compile") is called and is given the names of targets. The rule sets
+ some variables, like "OPTIONS". After that, the command string is taken,
+ and variable are substitutes, so use of OPTIONS inside the command string
+ become the real compile options.
+ </para>
+
+ <para>Boost.Build added a third stage to simplify things. It's now
+ possible to automatically convert properties to appropriate assignments to
+ variables. For example, <debug-symbols>on would add "-g" to the
+ OPTIONS variable, without requiring to manually add this logic to
+ gcc.compile. This functionality is part of the "toolset" module.
+ </para>
+
+ <para>When target paths are computed and the commands are set, Boost.Build
+ just gives control to bjam, which controls the execution of
+ commands.</para>
+
+ </section>
+
+ <section id="bbv2.arch.tools">
+ <title>The tools layer</title>
+
+ <para>Write me!</para>
+
+ </section>
+
+ <section id="bbv2.arch.targets">
+ <title>Targets</title>
+
+ <para>NOTE: THIS SECTION IS NOT EXPECTED TO BE READ!
+ There are two user-visible kinds of targets in Boost.Build.
+ First are "abstract" — they correspond to things declared
+ by user, for example, projects and executable files. The primary
+ thing about abstract target is that it's possible to request them
+ to be build with a particular values of some properties. Each
+ combination of properties may possible yield different set of
+ real file, so abstract target do not have a direct correspondence
+ with files.</para>
+
+ <para>File targets, on the contary, are associated with concrete
+ files. Dependency graphs for abstract targets with specific
+ properties are constructed from file targets. User has no was to
+ create file targets, however it can specify rules that detect
+ file type for sources, and also rules for transforming between
+ file targets of different types. That information is used in
+ constructing dependency graph, as desribed in the "next section".
+ [ link? ] <emphasis role="bold">Note:</emphasis>File targets are not
+ the same as targets in Jam sense; the latter are created from
+ file targets at the latest possible moment. <emphasis role="bold">Note:</emphasis>"File
+ target" is a proposed name for what we call virtual targets. It
+ it more understandable by users, but has one problem: virtual
+ targets can potentially be "phony", and not correspond to any
+ file.</para>
+
+ <section id="bbv2.arch.depends">
+ <title>Dependency scanning</title>
+
+ <para>Dependency scanning is the process of finding implicit
+ dependencies, like "#include" statements in C++. The requirements
+ for right dependency scanning mechanism are:</para>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Support for different scanning algorithms. C++ and XML have
+ quite different syntax for includes and rules for looking up
+ included files.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Ability to scan the same file several times. For example,
+ single C++ file can be compiled with different include
+ paths.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Proper detection of dependencies on generated files.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Proper detection of dependencies from generated file.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <section>
+ <title>Support for different scanning algorithms</title>
+
+ <para>Different scanning algorithm are encapsulated by objects
+ called "scanners". Please see the documentation for "scanner"
+ module for more details.</para>
+
+ </section>
+
+ <section>
+ <title>Ability to scan the same file several times</title>
+
+ <para>As said above, it's possible to compile a C++ file twice, with
+ different include paths. Therefore, include dependencies for
+ those compilations can be different. The problem is that bjam
+ does not allow several scans of the same target.</para>
+
+ <para>The solution in Boost.Build is straigtforward. When a virtual
+ target is converted to bjam target (via
+ <literal>virtual-target.actualize</literal> method), we specify the scanner
+ object to be used. The actualize method will create different
+ bjam targets for different scanners.</para>
+
+ <para>All targets with specific scanner are made dependent on target
+ without scanner, which target is always created. This is done in
+ case the target is updated. The updating action will be
+ associated with target without scanner, but if sources for that
+ action are touched, all targets — with scanner and without
+ should be considered outdated.</para>
+
+ <para>For example, assume that "a.cpp" is compiled by two compilers
+ with different include path. It's also copied into some install
+ location. In turn, it's produced from "a.verbatim". The
+ dependency graph will look like:</para>
+
+<programlisting>
+a.o (<toolset>gcc) <--(compile)-- a.cpp (scanner1) ----+
+a.o (<toolset>msvc) <--(compile)-- a.cpp (scanner2) ----|
+a.cpp (installed copy) <--(copy) ----------------------- a.cpp (no scanner)
+ ^
+ |
+ a.verbose --------------------------------+
+</programlisting>
+
+ </section>
+ <section>
+ <title>Proper detection of dependencies on generated files.</title>
+
+ <para>This requirement breaks down to the following ones.</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ If when compiling "a.cpp" there's include of "a.h", the
+ "dir" directory is in include path, and a target called "a.h"
+ will be generated to "dir", then bjam should discover the
+ include, and create "a.h" before compiling "a.cpp".
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Since almost always Boost.Build generates targets to a
+ "bin" directory, it should be supported as well. I.e. in the
+ scanario above, Jamfile in "dir" might create a main target,
+ which generates "a.h". The file will be generated to "dir/bin"
+ directory, but we still have to recornize the dependency.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>The first requirement means that when determining what "a.h"
+ means, when found in "a.cpp", we have to iterate over all
+ directories in include paths, checking for each one:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ If there's file "a.h" in that directory, or
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there's a target called "a.h", which will be generated
+ to that directory.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>Classic Jam has built-in facilities for point (1) above, but
+ that's not enough. It's hard to implement the right semantic
+ without builtin support. For example, we could try to check if
+ there's targer called "a.h" somewhere in dependency graph, and
+ add a dependency to it. The problem is that without search in
+ include path, the semantic may be incorrect. For example, one can
+ have an action which generated some "dummy" header, for system
+ which don't have the native one. Naturally, we don't want to
+ depend on that generated header on platforms where native one is
+ included.</para>
+
+ <para>There are two design choices for builtin support. Suppose we
+ have files a.cpp and b.cpp, and each one includes header.h,
+ generated by some action. Dependency graph created by classic jam
+ would look like:</para>
+
+<programlisting>
+a.cpp -----> <scanner1>header.h [search path: d1, d2, d3]
+
+
+ <d2>header.h --------> header.y
+ [generated in d2]
+
+b.cpp -----> <scanner2>header.h [ search path: d1, d2, d4]
+</programlisting>
+
+ <para>
+In this case, Jam thinks all header.h target are not
+realated. The right dependency graph might be:
+
+<programlisting>
+a.cpp ----
+ \
+ \
+ >----> <d2>header.h --------> header.y
+ / [generated in d2]
+ /
+b.cpp ----
+</programlisting>
+
+or
+
+<programlisting>
+a.cpp -----> <scanner1>header.h [search path: d1, d2, d3]
+ |
+ (includes)
+ V
+ <d2>header.h --------> header.y
+ [generated in d2]
+ ^
+ (includes)
+ |
+b.cpp -----> <scanner2>header.h [ search path: d1, d2, d4]
+</programlisting>
+ </para>
+
+ <para>
+The first alternative was used for some time. The problem
+however is: what include paths should be used when scanning
+header.h? The second alternative was suggested by Matt Armstrong.
+It has similiar effect: add targets which depend on
+<scanner1>header.h will also depend on <d2>header.h.
+But now we have two different target with two different scanners,
+and those targets can be scanned independently. The problem of
+first alternative is avoided, so the second alternative is
+implemented now.
+ </para>
+
+ <para>The second sub-requirements is that targets generated to "bin"
+ directory are handled as well. Boost.Build implements
+ semi-automatic approach. When compiling C++ files the process
+ is:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ The main target to which compiled file belongs is found.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ All other main targets that the found one depends on are
+ found. Those include main target which are used as sources, or
+ present as values of "dependency" features.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ All directories where files belonging to those main target
+ will be generated are added to the include path.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>After this is done, dependencies are found by the approach
+ explained previously.</para>
+
+ <para>Note that if a target uses generated headers from other main
+ target, that main target should be explicitly specified as
+ dependency property. It would be better to lift this requirement,
+ but it seems not very problematic in practice.</para>
+
+ <para>For target types other than C++, adding of include paths must
+ be implemented anew.</para>
+
+ </section>
+ <section>
+ <title>Proper detection of dependencies from generated files</title>
+
+ <para>Suppose file "a.cpp" includes "a.h" and both are generated by
+ some action. Note that classic jam has two stages. In first stage
+ dependency graph graph is build and actions which should be run
+ are determined. In second stage the actions are executed.
+ Initially, neither file exists, so the include is not found. As
+ the result, jam might attempt to compile a.cpp before creating
+ a.h, and compilation will fail.</para>
+
+ <para>The solution in Boost.Jam is to perform additional dependency
+ scans after targets are updated. This break separation between
+ build stages in jam — which some people consider a good
+ thing — but I'm not aware of any better solution.</para>
+
+ <para>In order to understand the rest of this section, you better
+ read some details about jam dependency scanning, available
+ <ulink url=
+ "http://public.perforce.com:8080/@md=d&cd=//public/jam/src/&ra=s&c=kVu@//2614?ac=10">
+ at this link</ulink>.</para>
+
+ <para>Whenever a target is updated, Boost.Jam rescans it for
+ includes. Consider this graph, created before any actions are
+ run.</para>
+
+<programlisting>
+A -------> C ----> C.pro
+ /
+B --/ C-includes ---> D
+</programlisting>
+
+ <para>
+Both A and B have dependency on C and C-includes (the latter
+dependency is not shown). Say during building we've tried to create
+A, then tried to create C and successfully created C.
+ </para>
+
+ <para>In that case, the set of includes in C might well have
+ changed. We do not bother to detect precisely which includes were
+ added or removed. Instead we create another internal node
+ C-includes-2. Then we determine what actions should be run to
+ update the target. In fact this mean that we perform logic of
+ first stage while already executing stage.</para>
+
+ <para>After actions for C-includes-2 are determined, we add
+ C-includes-2 to the list of A's dependents, and stage 2 proceeds
+ as usual. Unfortunately, we can't do the same with target B,
+ since when it's not visited, C target does not know B depends on
+ it. So, we add a flag to C which tells and it was rescanned. When
+ visiting B target, the flag is notices and C-includes-2 will be
+ added to the list of B's dependencies.</para>
+
+ <para>Note also that internal nodes are sometimes updated too.
+ Consider this dependency graph:</para>
+
+<programlisting>
+a.o ---> a.cpp
+ a.cpp-includes --> a.h (scanned)
+ a.h-includes ------> a.h (generated)
+ |
+ |
+ a.pro <-------------------------------------------+
+</programlisting>
+
+ <para>Here, out handling of generated headers come into play. Say
+ that a.h exists but is out of date with respect to "a.pro", then
+ "a.h (generated)" and "a.h-includes" will be marking for
+ updating, but "a.h (scanned)" won't be marked. We have to rescan
+ "a.h" file after it's created, but since "a.h (generated)" has no
+ scanner associated with it, it's only possible to rescan "a.h"
+ after "a.h-includes" target was updated.</para>
+
+ <para>Tbe above consideration lead to decision that we'll rescan a
+ target whenever it's updated, no matter if this target is
+ internal or not.</para>
+
+ <warning>
+ <para>
+ The remainder of this document is not indended to be read at
+ all. This will be rearranged in future.
+ </para>
+ </warning>
+
+ <section>
+ <title>File targets</title>
+
+ <para>
+ As described above, file targets corresponds
+ to files that Boost.Build manages. User's may be concerned about
+ file targets in three ways: when declaring file target types,
+ when declaring transformations between types, and when
+ determining where file target will be placed. File targets can
+ also be connected with actions, that determine how the target is
+ created. Both file targets and actions are implemented in the
+ <literal>virtual-target</literal> module.
+ </para>
+
+ <section>
+ <title>Types</title>
+
+ <para>A file target can be given a file, which determines
+ what transformations can be applied to the file. The
+ <literal>type.register</literal> rule declares new types. File type can
+ also be assigned a scanner, which is used to find implicit
+ dependencies. See "dependency scanning" [ link? ] below.</para>
+ </section>
+ </section>
+
+ <section>
+ <title>Target paths</title>
+
+ <para>To distinguish targets build with different properties, they
+ are put in different directories. Rules for determining target
+ paths are given below:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ All targets are placed under directory corresponding to the
+ project where they are defined.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Each non free, non incidental property cause an additional
+ element to be added to the target path. That element has the
+ form <literal><feature-name>-<feature-value></literal> for
+ ordinary features and <literal><feature-value></literal> for
+ implicit ones. [Note about composite features].
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If the set of free, non incidental properties is different
+ from the set of free, non incidental properties for the project
+ in which the main target that uses the target is defined, a
+ part of the form <literal>main_target-<name></literal> is added to
+ the target path. <emphasis role="bold">Note:</emphasis>It would be nice to completely
+ track free features also, but this appears to be complex and
+ not extremely needed.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>For example, we might have these paths:</para>
+
+<programlisting>
+debug/optimization-off
+debug/main-target-a
+</programlisting>
+
+ </section>
+ </section>
+ </section>
+ </section>
+ </appendix>
+
+<!--
+ Local Variables:
+ mode: xml
+ sgml-indent-data: t
+ sgml-parent-document: ("userman.xml" "chapter")
+ sgml-set-face: t
+ End:
+-->
Added: boost-jam/boost-build/branches/upstream/current/doc/src/catalog.xml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/src/catalog.xml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/src/catalog.xml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalog
+ PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
+ "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <rewriteURI uriStartString="http://www.boost.org/tools/boostbook/dtd/" rewritePrefix="file:///home/ccurrie/src/boost/tools/boostbook/dtd//"/>
+ <rewriteURI uriStartString="http://docbook.sourceforge.net/release/xsl/current/" rewritePrefix="file:///shared/ccurrie/share/sgml/docbook/docbook-xsl-1.64.1/"/>
+ <rewriteURI uriStartString="http://www.oasis-open.org/docbook/xml/4.2/" rewritePrefix="file:///shared/ccurrie/share/sgml/docbook/docbook-dtd-4.2/"/>
+</catalog>
Added: boost-jam/boost-build/branches/upstream/current/doc/src/extending.xml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/src/extending.xml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/src/extending.xml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,756 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE appendix PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <chapter id="bbv2.extender">
+ <title>Extender Manual</title>
+
+ <section id="bbv2.extender.intro">
+ <title>Introduction</title>
+
+ <para>This document explains how to extend Boost.Build to accomodate
+ your local requirements. Let's start with quite simple, but
+ realistic example.</para>
+
+ <para>Say you're writing an application which generates C++ code. If
+ you ever did this, you know that it's not nice. Embedding large
+ portions of C++ code in string literals is very awkward. A much
+ better solution is:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Write the template of the code to be generated, leaving
+ placeholders at the points which will change
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Access the template in your application and replace
+ placeholders with appropriate text.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>Write the result.</simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>It's quite easy to achieve. You write special verbatim files,
+ which are just C++, except that the very first line of the file
+ gives a name of variable that should be generated. A simple tool
+ is created which takes verbatim file and creates a cpp file with
+ a single char* variable, which name is taken from the first line
+ of verbatim file, and which value is properly quoted content of
+ the verbatim file.</para>
+
+ <para>Let's see what Boost.Build can do.</para>
+
+ <para>First off, Boost.Build has no idea about "verbatim files". So,
+ you must register a new type. The following code does it:</para>
+
+<programlisting>
+import type ;
+type.register VERBATIM : verbatim ;
+</programlisting>
+
+ <para>The first parameter to 'type.register' gives the name of
+ declared type. By convention, it's uppercase. The second
+ parameter is suffix for this type. So, if Boost.Build sees
+ "code.verbatim" in the list of sources, it knows that it's of
+ type <literal>VERBATIM</literal>.</para>
+
+ <para>Lastly, you need a tool to convert verbatim files to C++. Say
+ you've sketched such a tool in Python. Then, you have to inform
+ Boost.Build about the tool. The Boost.Build concept which
+ represents a tool is <emphasis>generator</emphasis>.</para>
+
+ <para>First, you say that generator 'inline-file' is able to convert
+ VERBATIM type into C++:</para>
+
+<programlisting>
+import generators ;
+generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
+</programlisting>
+
+ <para>Second, you must specify the commands to be run to actually
+ perform convertion:</para>
+
+<programlisting>
+actions inline-file
+{
+ "./inline-file.py" $(<) $(>)
+}
+</programlisting>
+<!-- We use verbatim.inline-file in one place and just inline-file in
+ another. Is this confusing for user?
+ -->
+
+ <para>Now, we're ready to tie it all together. Put all the code
+ above in file "verbatim.jam", add "import verbatim ;" to
+ "project-root.jam", and it's possible to write the following in
+ Jamfile:</para>
+
+<programlisting>
+exe codegen : codegen.cpp class_template.verbatim usage.verbatim ;
+</programlisting>
+
+ <para>
+The verbatim files will be automatically converted into C++
+and linked it.
+ </para>
+
+ <para>In the subsequent sections, we will extend this example, and review
+ all the mechanisms in detail. The complete code is available in <ulink url=
+ "../../example/customization">example/customization</ulink>
+ directory.
+ </para>
+
+ </section>
+ <section id="bbv2.extending.targets">
+ <title>Target types</title>
+ <para>The first thing we did in the <link
+ linkend="bbv2.extender.intro">intruduction</link> was declaring a
+ new target type:
+<programlisting>
+import type ;
+type.register VERBATIM : verbatim ;
+</programlisting>
+ The type is the most important property of a target. Boost.Build can
+ automatically generate necessary build actions only because you
+ specify the desired type (using the different main target rules), and
+ because Boost.Build can guess the type of sources from their
+ extensions.
+ </para>
+
+ <para>The first two parameters for the <code>type.register</code> rule
+ are the name of new type and the list of extensions associated with
+ it. A file with an extension from the list will have the given target
+ type. In the case where a target of the declared type is generated
+ from other sources, the first specified extension will be used. This
+ behaviour can be changed using the
+ <code>type.set-generated-target-suffix</code> rule.
+ </para>
+
+ <para>
+ Something about 'main' types.
+ </para>
+
+ <para>Something about base types.
+ </para>
+
+ <section id="bbv2.extending.scanners">
+ <title>Scanners</title>
+ <para>
+ Sometimes, a file can refer to other files via some include
+ mechanism. To make Boost.Build track dependencies to the included
+ files, you need to provide a scanner. The primary limitation is that
+ only one scanner can be assigned to a target type.
+ </para>
+
+ <para>First, we need to declare a new class for the scanner:
+<programlisting>
+class verbatim-scanner : common-scanner
+{
+ rule pattern ( )
+ {
+ return "//###include[ ]*\"([^\"]*)\"" ;
+ }
+}
+</programlisting>
+ All the complex logic is in the <code>common-scanner</code> class,
+ and you only need to override the method which returns the regular
+ expression to be used for scanning. The paranthethis in the regular
+ expression indicate which part of the string is the name of the
+ included file.
+ </para>
+
+ <para>After that, we need to register our scanner class:
+<programlisting>
+scanner.register verbatim-scanner : include ;
+</programlisting>
+ The value of the second parameter, in this case
+ <code>include</code>, specifies which properties contain the list
+ of paths which should be searched for the included files.
+ </para>
+
+ <para>Finally, we assign the new scaner to the <code>VERBATIM</code>
+ target type:
+<programlisting>
+type.set-scanner VERBATIM : verbatim-scanner ;
+</programlisting>
+ That's enough for scanning include dependencies.
+ </para>
+
+ </section>
+
+
+ </section>
+
+ <section id="bbv2.extending.tools">
+ <title>Tools and generators</title>
+ <para>
+ This section will describe how Boost.Build can be extended to support
+ new tools.
+ </para>
+
+ <para>For each additional tool, a Boost.Build object called generator
+ must be created. That object has specific types of targets which it
+ accepts an produces. Using that information, Boost.Build is able
+ to automatically invoke the generator. For example, if you declare a
+ generator which takes a target of the type <literal>D</literal> and
+ produces a target of the type <literal>OBJ</literal>, when placing a
+ file with extention <literal>.d</literal> in a list of sources will
+ cause Boost.Build to invoke your generator, and then to link the
+ resulting object file into an application. (Of course, this requires
+ that you specify that the <literal>.d</literal> extension corresponds
+ to the <literal>D</literal> type.)
+ </para>
+
+ <para>Each generator should be an instance of a class derived from the
+ <code>generator</code> class. In the simplest case, you don't need to
+ create a derived class, but simply create an instance of the
+ <code>generator</code> class. Let's review the example we've seen in the
+ <link linkend="bbv2.extender.intro">introduction</link>.
+<programlisting>
+import generators ;
+generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
+actions inline-file
+{
+ "./inline-file.py" $(<) $(>)
+}
+</programlisting>
+ </para>
+
+ <para>We declare a standard generator, specifying its id, the source type
+ and the target type. When invoked, the generator will create a target
+ of type <literal>CPP</literal> which will have the source target of
+ type <literal>VERBATIM</literal> as the only source. But what command
+ will be used to actually generate the file? In bjam, actions are
+ specified using named "actions" blocks and the name of the action
+ block should be specified when creating targets. By convention,
+ generators use the same name of the action block as their own id. So,
+ in above example, the "inline-file" actions block will be use to
+ convert the source into the target.
+ </para>
+
+ <para>
+ There are two primary kinds of generators: standard and composing,
+ which are registered with the
+ <code>generators.register-standard</code> and the
+ <code>generators.register-composing</code> rules, respectively. For
+ example:
+<programlisting>
+generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
+generators.register-composing mex.mex : CPP LIB : MEX ;
+</programlisting>
+ The first generators takes a <emphasis>single</emphasis> source of type
+ <code>VERBATIM</code> and produces a result. The second generator
+ takes any number of sources, which can have either the
+ <code>CPP</code> or the <code>LIB</code> type. Composing generators
+ are typically used for generating top-level target type. For example,
+ the first generator invoked when building an <code>exe</code> target
+ is a composing generator corresponding to the proper linker.
+ </para>
+
+ <para>You should also know about two specific function for registering
+ generators: <code>generators.register-c-compiler</code> and
+ <code>generators.register-linker</code>. The first sets up header
+ dependecy scanning for C files, and the seconds handles various
+ complexities like searched libraries. For that reason, you should always
+ use those functions when adding support for compilers and linkers.
+ </para>
+
+ <para>(Need a note about UNIX)</para>
+
+ <bridgehead>Custom generator classes</bridgehead>
+
+ <para>The standard generators allows you to specify source and target
+ types, action, and a set of flags. If you need anything more complex,
+ you need to create a new generator class with your own logic. Then,
+ you have to create an instance of that class and register it. Here's
+ an example how you can create your own generator class:
+<programlisting>
+class custom-generator : generator
+{
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+}
+
+generators.register
+ [ new custom-generator verbatim.inline-file : VERBATIM : CPP ] ;
+</programlisting>
+ This generator will work exactly like the
+ <code>verbatim.inline-file</code> generator we've defined above, but
+ it's possible to customize the behaviour by overriding methods of the
+ <code>generator</code> class.
+ </para>
+
+ <para>There are two methods of interest. The <code>run</code> methods is
+ responsible for overall process - it takes a number of source targets,
+ converts them the the right types, and creates the result. The
+ <code>generated-targets</code> method is called when all sources are
+ converted to the right types to actually create the result.
+ </para>
+
+ <para>The <code>generated-target</code> method can be overridden when you
+ want to add additional properties to the generated targets or use
+ additional sources. For example (which is real), you have a tool for
+ analysing programs, which should be given a name of executable and the
+ list of all sources. Naturally, you don't want to list all source
+ files manually. Here's how the <code>generated-target</code> method
+ can find the list of sources automatically:
+<programlisting>
+class itrace-generator : generator {
+....
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ local leafs ;
+ local temp = [ virtual-target.traverse $(sources[1]) : : include-sources ] ;
+ for local t in $(temp)
+ {
+ if ! [ $(t).action ]
+ {
+ leafs += $(t) ;
+ }
+ }
+ return [ generator.generated-targets $(sources) $(leafs)
+ : $(property-set) : $(project) $(name) ] ;
+ }
+}
+generators.register [ new itrace-generator nm.itrace : EXE : ITRACE ] ;
+</programlisting>
+ The <code>generated-targets</code> rule will be called with a single
+ source target of type <literal>EXE</literal>. The call to the
+ <code>virtual-target.traverse</code> will return all targets the
+ executable depends on, and we further find files which are not
+ produced from anything. The found targets are added to the sources.
+ </para>
+
+ <para>The <code>run</code> method can be overriden to completely
+ customize the way generator works. In particular, the conversion of
+ sources to the desired types can be completely customized. Here's
+ another real example. Tests for the Boost Python library usually
+ consist of two parts: a Python program and a C++ file. The C++ file is
+ compiled to Python extension which is loaded by the Python
+ program. But in the likely case that both files have the same name,
+ the created Python extension must be renamed. Otherwise, Python
+ program will import itself, not the extension. Here's how it can be
+ done:
+<programlisting>
+rule run ( project name ? : property-set : sources * : multiple ? )
+{
+ local python ;
+ for local s in $(sources)
+ {
+ if [ $(s).type ] = PY
+ {
+ python = $(s) ;
+ }
+ }
+
+ local libs ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] LIB ]
+ {
+ libs += $(s) ;
+ }
+ }
+
+ local new-sources ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] CPP ]
+ {
+ local name = [ $(s).name ] ;
+ if $(name) = [ $(python).name ]
+ {
+ name = $(name)_ext ;
+ }
+ new-sources += [ generators.construct $(project) $(name) :
+ PYTHON_EXTENSION : $(property-set) : $(s) $(libs) ] ;
+ }
+ }
+
+ result = [ construct-result $(python) $(new-sources) : $(project) $(name)
+ : $(property-set) ] ;
+}
+</programlisting>
+ First, we separate all source into python files, libraries and C++
+ sources. For each C++ source we create a separate Python extension by
+ calling <code>generators.construct</code> and passing the C++ source
+ and the libraries. At this point, we also change the extension's name,
+ if necessary.
+ </para>
+
+
+ </section>
+
+ <section id="bbv2.extending.features">
+ <title>Features</title>
+ <para>
+ Often, we need to control the options passed the invoked tools. This
+ is done with features. Consider an example:
+<programlisting>
+# Declare a new feature
+import feature : feature ;
+feature verbatim-options : : free ;
+
+# Cause the value of the 'verbatim-options' feature to be
+# available as 'OPTIONS' variable inside verbatim.inline-file
+import toolset : flags ;
+flags verbatim.inline-file OPTIONS <verbatim-options> ;
+
+# Use the "OPTIONS" variable
+actions inline-file
+{
+ "./inline-file.py" $(OPTIONS) $(<) $(>)
+}
+</programlisting>
+ We first define a new feature. Then, the <code>flags</code> invocation
+ says that whenever verbatin.inline-file action is run, the value of
+ the <code>verbatim-options</code> feature will be added to the
+ <code>OPTIONS</code> variable, an can be used inside the action body.
+ You'd need to consult online help (--help) to find all the features of
+ the <code>toolset.flags</code> rule.
+ </para>
+
+ <para>
+ Although you can define any set of features and interpret their values
+ in any way, Boost.Build suggests the following coding standard for
+ designing features.
+ </para>
+
+ <para>Most features should have a fixed set of values, which is portable
+ (tool neutral) across the class of tools they are designed to work
+ with. The user does not have to adjust the values for a exact tool. For
+ example, <code><optimization>speed</code> has the same meaning for
+ all C++ compilers and the user does not have to worry about the exact
+ options which are passed to the compiler's command line.
+ </para>
+
+ <para>
+ Besides such portable features there are special 'raw' features which
+ allow the user to pass any value to the command line parameters for a
+ particular tool, if so desired. For example, the
+ <code><cxxflags></code> feature allows to pass any command line
+ options to a C++ compiler. The <code><include></code> feature
+ allows to pass any value to the <code>-I</code> and the interpretation
+ is tool-specific. (There an <link
+ linkend="bbv2.faq.external">example</link> of very smart usage of that
+ feature). Of course one should always strive to use the portable
+ features but these should still be provided as a backdoor just to make
+ sure Boost.Build does not take away any control from the user.
+ </para>
+
+ <para>
+ Some of the reasons why portable features are better are:
+ <itemizedlist>
+ <listitem>
+ <para>Since a portable feature have a fixed set of value, you will
+ be able to build your project with two different settings of the
+ feature. Boost.Build will automatically use two different
+ directories for produced files. If you pass raw compiler options,
+ Boost.Build assumes you know what you are doing, and would not
+ care about what options are passed.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>Unlike "raw" features, you don't need to use specific
+ compiler flags in Jamfile, and it will more likely work on other systems.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead>Steps for adding a feauture</bridgehead>
+ <para>Adding a feature requires three steps:
+
+ <orderedlist>
+ <listitem><para>Declaring a feature. For that, the "feature.feature"
+ rule is used. You should have to decide on the set of <link
+ linkend="bbv2.reference.features.attributes">feature
+ attributes</link>:
+
+ <itemizedlist>
+ <listitem><para>if feature has several values, and
+ significally affects build, make it "propagated", so that
+ whole project is build with the same value by
+ default</para></listitem>
+
+ <listitem><para>if a feature does not have a fixed list of
+ values, it must be "free".</para></listitem>
+
+ <listitem><para>if feature is used to refer to a path, it must
+ be "path".</para></listitem>
+
+ <listitem><para>if feature is used to refer to some target, it
+ must be "dependency".</para></listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+
+
+ <listitem><para>Converting the feature value into variable. To use
+ feature in build action, it must be converted into a variable,
+ accessible in build action. This is accomplished by
+ "toolset.flags" rule.</para></listitem>
+
+
+ <listitem><para>Using the variable. The variable set in step 2 can
+ be used in build action to form command parameters or
+ files.</para></listitem>
+
+ </orderedlist>
+ </para>
+
+ <bridgehead>Another example</bridgehead>
+
+ <para>Here's an another example.
+ Let's see how we can make a feature which refers to a target. For example,
+ when linking dynamic libraries on windows, one sometimes needs to specify
+ "DEF file", telling what functions should be exported. It would be nice to
+ use this file like this:
+<programlisting>
+ lib a : a.cpp : <def-file>a.def ;
+</programlisting>
+ Actually, this feature is already supported, but anyway...
+ </para>
+
+ <orderedlist>
+ <listitem>
+ <para>Since the feature refers to a target, it must be "dependency".
+<programlisting>
+feature def-file : : free dependency ;
+</programlisting>
+ </para></listitem>
+
+ <listitem><para>One of the toolsets which cares about DEF files is
+msvc. The following line should be added to it.
+
+<programlisting>
+flags msvc.link DEF_FILE <def-file> ;
+</programlisting>
+ </para></listitem>
+
+ <listitem><para>Since the DEF_FILE variable is not used by the
+msvc.link action, we need to modify it to be:
+
+<programlisting>
+actions link bind DEF_FILE
+{
+ $(.LD) .... /DEF:$(DEF_FILE) ....
+}
+</programlisting>
+ </para>
+
+
+ <para> Note the "bind DEF_FILE" part. It tells bjam that DEF_FILE
+ refers to a file, otherwise the variable will contain internal
+ target name, which is not likely to make sense for the linker.
+ </para>
+
+ <para>
+ We've almost done, but should stop for a small workaround. Add the following
+ code to msvc.jam
+
+<programlisting>
+rule link
+{
+ DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
+}
+</programlisting>
+
+ This is needed to accomodate some bug in bjam, which hopefully
+ will be fixed one day.</para></listitem>
+
+ </orderedlist>
+
+ <bridgehead>Variants and composite features.</bridgehead>
+
+ <para>Sometimes you want to create a shorcut for some set of
+ features. For example, <code>release</code> is a value of the
+ <code>variant</code> and is a shortcut for a set of features.
+ </para>.
+
+ <para>It is possible to define your build variants. For example:
+<programlisting>
+variant crazy : <optimization>speed <inlining>off
+ <debug-symbols>on <profiling>on ;
+</programlisting>
+ will define a new variant with the specified set of properties. You
+ can also extend an existing variant:
+<programlisting>
+variant super_release : release : <define>USE_ASM ;
+</programlisting>
+ In this case, <code>super_release</code> will expand to all properties
+ specified by <code>release</code>, and the additional one you've specified.
+ </para>
+
+ <para>You are not restricted to using the <code>variant</code> feature
+ only. Here's example which defines a brand new feature:
+<programlisting>
+feature parallelism : mpi fake none : composite link-incompatible ;
+feature.compose <parallelism>mpi : <library>/mpi//mpi/<parallelism>none ;
+feature.compose <parallelism>fake : <library>/mpi//fake/<parallelism>none ;
+</programlisting>
+ This will allow you to specify value of feature
+ <code>parallelism</code>, which will expand to link to the necessary
+ library.
+ </para>
+
+ </section>
+
+ <section id="bbv2.extending.rules">
+ <title>Main target rules</title>
+ <para>
+ The main target rule is what creates a top-level target, for example "exe" or
+ "lib". It's quite likely that you'll want to declare your own and
+ there are as many as three ways to do that.
+ </para>
+
+ <para>The first is the simplest, but is sufficient in a number of
+ cases. Just write a wrapper rule, which will redirect to any of the
+ existing rules. For example, you have only one library per directory and
+ want all cpp files in the directory to be compiled. You can achieve this
+ effect with:
+<programlisting>
+lib codegen : [ glob *.cpp ] ;
+</programlisting>
+ but what if you want to make it even simple. Then, you add the following
+ definition to the project-root.jam file:
+<programlisting>
+rule glib ( name : extra-sources * : requirements * )
+{
+ lib $(name) : [ glob *.cpp ] $(extra-sources) : $(requirements) ;
+}
+</programlisting>
+which would allow to reduce Jamfile to
+<programlisting>
+glib codegen ;
+</programlisting>
+ </para>
+
+ <para>The second approach is suitable when your target rule should just
+ produce a target of specific type. Then, when declaring a type you
+ should tell Boost.Build that a main target rule should be created.
+ For example, if you create a module "obfuscate.jam" containing:
+
+<programlisting>
+import type ;
+type.register OBFUSCATED_CPP : ocpp : : main ;
+
+import generators ;
+generators.register-standard obfuscate.file : CPP : OBFUSCATED_CPP ;
+</programlisting>
+ and import that module, you'll be able to use the rule "obfuscated-cpp"
+ in Jamfiles, which will convert source to the OBFUSCATED_CPP type.
+ </para>
+
+ <para>
+ The remaining method is to declare your own main target class. The
+ simplest example of this can be found in "build/alias.jam" file. The
+ current V2 uses this method when transformations are relatively
+ complex. However, we might deprecate this approach. If you find that you
+ need to use it (that is, the first two approaches are not sufficient),
+ please let us know by posting to the mailing list.
+ </para>
+
+
+ </section>
+
+ <section id="bbv2.extending.toolset_modules">
+
+ <title>Toolset modules</title>
+
+ <para>If your extensions will be used only on one project, they can be
+ placed in a separate <filename>.jam</filename> file which will be
+ imported by your <filename>project-root.jam</filename>. If the
+ extensions will be used on many projects, the users will thank you for
+ a finishing touch.
+ </para>
+
+ <para>The standard way to use a tool in Boost.Build is the
+ <code>using</code> rule. To make it work, you module should provide an
+ <code>init</code> rule. The rule will be called with the same parameters
+ which were passed to the <code>using</code> rule. The set of allowed
+ parameters is determined by you. For example, you can allow the user to
+ specify paths, tool version, or tool options.
+ </para>
+
+ <para>Here are some guidelines which help to make Boost.Build more
+ consistent:
+ <itemizedlist>
+ <listitem><para>The <code>init</code> rule should never fail. Even if
+ user provided a wrong path, you should emit a warning and go
+ on. Configuration may be shared between different machines, and
+ wrong values on one machine can be OK on another.
+ </para></listitem>
+
+ <listitem><para>Prefer specifying command to be executed to specifying
+ path. First of all, this gives more control: it's possible to
+ specify
+<programlisting>
+/usr/bin/g++-snapshot
+time g++
+</programlisting>
+ as the command. Second, while some tools have a logical
+ "installation root", it better if user don't have to remember if
+ a specific tool requires a full command or a path.
+ </para></listitem>
+
+ <listitem><para>Check for multiple initialization. A user can try to
+ initialize the module several times. You need to check for this
+ and decide what to do. Typically, unless you support several
+ versions of a tool, duplicate initialization is a user error. If
+ tool version can be specified during initialization, make sure the
+ version is either always specified, or never specified (in which
+ case the tool is initialied only once). For example, if you allow:
+<programlisting>
+using yfc ;
+using yfc : 3.3 ;
+using yfc : 3.4 ;
+</programlisting>
+ Then it's not clear if the first initialization corresponds to
+ version 3.3 of the tool, version 3.4 of the tool, or some other
+ version. This can lead to building twice with the same version.
+ </para></listitem>
+
+ <listitem><para>If possible, the <code>init</code> must be callable
+ with no parameters. In which case, it should try to autodetect all
+ the necessary information, for example, by looking for a tool in
+ <envar>PATH</envar> or in common installation locations. Often this
+ is possible and allows the user to simply write:
+<programlisting>
+using yfc ;
+</programlisting>
+ </para></listitem>
+
+ <listitem><para>Consider using facilities in the
+ <code>tools/common</code> module. You can take a look at how
+ <code>tools/gcc.jam</code> uses that module in the <code>init</code> rule.
+ </para></listitem>
+
+ </itemizedlist>
+ </para>
+
+
+
+
+ </section>
+
+ </chapter>
+
+<!--
+ Local Variables:
+ mode: xml
+ sgml-indent-data: t
+ sgml-parent-document: ("userman.xml" "chapter")
+ sgml-set-face: t
+ End:
+-->
Added: boost-jam/boost-build/branches/upstream/current/doc/src/faq.xml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/src/faq.xml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/src/faq.xml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,350 @@
+<?xml version="1.0" standalone="yes"?>
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <chapter id="bbv2.faq">
+ <title>Frequently Asked Questions</title>
+
+ <section>
+ <title>
+ I'm getting "Duplicate name of actual target" error. What
+ does it mean?
+ </title>
+
+ <para>
+ The most likely case is that you're trying to
+ compile the same file twice, with almost the same,
+ but differing properties. For example:
+
+<programlisting>
+exe a : a.cpp : <include>/usr/local/include ;
+exe b : a.cpp ;
+</programlisting>
+
+ </para>
+
+ <para>
+ The above snippet requires two different compilations
+ of 'a.cpp', which differ only in 'include' property.
+ Since the 'include' property is free, Boost.Build
+ can't generate two objects files into different directories.
+ On the other hand, it's dangerous to compile the file only
+ once -- maybe you really want to compile with different
+ includes.
+ </para>
+
+ <para>
+ To solve this issue, you need to decide if file should
+ be compiled once or twice.</para>
+
+ <orderedlist>
+ <listitem>
+ <para>Two compile file only once, make sure that properties
+ are the same:
+
+<programlisting>
+exe a : a.cpp : <include>/usr/local/include ;
+exe b : a.cpp : <include>/usr/local/include ;
+</programlisting></para></listitem>
+
+ <listitem><para>
+ If changing the properties is not desirable, for example
+ if 'a' and 'b' target have other sources which need
+ specific properties, separate 'a.cpp' into it's own target:
+
+<programlisting>
+obj a_obj : a.cpp : <include>/usr/local/include ;
+exe a : a_obj ;
+</programlisting></para></listitem>
+
+ <listitem><para>
+ To compile file twice, you can make the object file local
+ to the main target:
+
+<programlisting>
+ exe a : [ obj a_obj : a.cpp ] : <include>/usr/local/include ;
+ exe b : [ obj a_obj : a.cpp ] ;
+</programlisting></para></listitem>
+
+ </orderedlist>
+
+ <para>
+ A good question is why Boost.Build can't use some of the above
+ approaches automatically. The problem is that such magic would
+ require additional implementation complexities and would only
+ help in half of the cases, while in other half we'd be silently
+ doing the wrong thing. It's simpler and safe to ask user to
+ clarify his intention in such cases.
+ </para>
+
+ </section>
+
+ <section>
+ <title>
+ Accessing environment variables
+ </title>
+
+ <para>
+ Many users would like to use environment variables in Jamfiles, for
+ example, to control location of external libraries. In many cases you
+ better declare those external libraries in the site-config.jam file, as
+ documented in the <link linkend="bbv2.recipies.site-config">recipes
+ section</link>. However, if the users already have the environment variables set
+ up, it's not convenient to ask them to set up site-config.jam files as
+ well, and using environment variables might be reasonable.
+ </para>
+
+ <para>In Boost.Build V2, each Jamfile is a separate namespace, and the
+ variables defined in environment is imported into the global
+ namespace. Therefore, to access environment variable from Jamfile, you'd
+ need the following code:
+<programlisting>
+import modules ;
+local SOME_LIBRARY_PATH = [ modules.peek : SOME_LIBRARY_PATH ] ;
+exe a : a.cpp : <include>$(SOME_LIBRARY_PATH) ;
+</programlisting>
+ </para>
+</section>
+
+ <section>
+ <title>
+ How to control properties order?
+ </title>
+
+ <para>For internal reasons, Boost.Build sorts all the properties
+ alphabetically. This means that if you write:
+<programlisting>
+exe a : a.cpp : <include>b <include>a ;
+</programlisting>
+ then the command line with first mention the "a" include directory, and
+ then "b", even though they are specified in the opposite order. In most
+ cases, the user doesn't care. But sometimes the order of includes, or
+ other properties, is important. For example, if one uses both the C++
+ Boost library and the "boost-sandbox" (libraries in development), then
+ include path for boost-sandbox must come first, because some headers may
+ override ones in C++ Boost. For such cases, a special syntax is
+ provided:
+<programlisting>
+exe a : a.cpp : <include>a&&b ;
+</programlisting>
+ </para>
+
+ <para>The <code>&&</code> symbols separate values of an
+ property, and specify that the order of the values should be preserved. You
+ are advised to use this feature only when the order of properties really
+ matters, and not as a convenient shortcut. Using it everywhere might
+ negatively affect performance.
+ </para>
+
+ </section>
+
+ <section>
+ <title>
+ How to control the library order on Unix?
+ </title>
+
+ <para>On the Unix-like operating systems, the order in which static
+ libraries are specified when invoking the linker is important, because by
+ default, the linker uses one pass though the libraries list. Passing the
+ libraries in the incorrect order will lead to a link error. Further, this
+ behaviour is often used to make one library override symbols from
+ another. So, sometimes it's necessary to force specific order of
+ libraries.
+ </para>
+
+ <para>Boost.Build tries to automatically compute the right order. The
+ primary rule is that if library a "uses" library b, then library a will
+ appear on the command line before library b. Library a is considered to
+ use b is b is present either in the sources of a or in its
+ requirements. To explicitly specify the use relationship one can use the
+ <use> feature. For example, both of the following lines will cause
+ a to appear before b on the command line:
+<programlisting>
+lib a : a.cpp b ;
+lib a : a.cpp : <use>b ;
+</programlisting>
+ </para>
+
+ <para>
+ The same approach works for searched libraries, too:
+<programlisting>
+lib z ;
+lib png : : <use>z ;
+exe viewer : viewer png z ;
+</programlisting>
+ </para>
+
+ </section>
+
+ <section id="bbv2.faq.external">
+ <title>Can I get output of external program as a variable in a Jamfile?
+ </title>
+
+ <para>From time to time users ask how to run an external program and save
+ the result in Jamfile variable, something like:
+<programlisting>
+local gtk_includes = [ RUN_COMMAND gtk-config ] ;
+</programlisting>
+ Unfortunately, this is not possible at the moment. However, if the
+ result of command invocation is to be used in a command to some tool,
+ and you're working on Unix, the following workaround is possible.
+<programlisting>
+ alias gtk+-2.0 : : : :
+ <cflags>"`pkg-config --cflags gtk+-2.0`"
+ <inkflags>"`pkg-config --libs gtk+-2.0`"
+ ;
+</programlisting>
+ If you use the "gtk+-2.0" target in sources, then the properties
+ specified above will be added to the build properties and eventually
+ will appear in the command line. Unix command line shell processes
+ the backticks quoting by running the tool and using its output --
+ which is what's desired in that case. Thanks to Daniel James for
+ sharing this approach.
+ </para>
+
+ </section>
+
+ <section>
+ <title>How to get the project-root location?
+ </title>
+
+ <para>You might want to use the location of the project-root in your
+ Jamfiles. To do it, you'd need to declare path constant in your
+ project-root.jam:
+<programlisting>
+path-constant TOP : . ;
+</programlisting>
+ After that, the <code>TOP</code> variable can be used in every Jamfile.
+ </para>
+ </section>
+
+ <section>
+ <title>How to change compilation flags for one file?
+ </title>
+
+ <para>If one file must be compiled with special options, you need to
+ explicitly declare an <code>obj</code> target for that file and then use
+ that target in your <code>exe</code> or <code>lib</code> target:
+<programlisting>
+exe a : a.cpp b ;
+obj b : b.cpp : <optimization>off ;
+</programlisting>
+ Of course you can use other properties, for example to specify specific
+ compiler options:
+<programlisting>
+exe a : a.cpp b ;
+obj b : b.cpp : <cflags>-g ;
+</programlisting>
+ You can also use <link linkend="bbv2.tutorial.conditions">conditional
+ properties</link> for finer control:
+<programlisting>
+exe a : a.cpp b ;
+obj b : b.cpp : <variant>release:<optimization>off ;
+</programlisting>
+
+ </para>
+ </section>
+
+ <section id="bbv2.faq.dll-path">
+ <title>Why are the <code>dll-path</code> and
+ <code>hardcode-dll-paths</code> properties useful?
+ </title>
+
+ <para>(This entry is specific to Unix system.)Before answering the
+ questions, let's recall a few points about shared libraries. Shared
+ libraries can be used by several applications, or other libraries,
+ without phisycally including the library in the application. This can
+ greatly decrease the total size of applications. It's also possible to
+ upgrade a shared library when the application is already
+ installed. Finally, shared linking can be faster.
+ </para>
+
+ <para>However, the shared library must be found when the application is
+ started. The dynamic linker will search in a system-defined list of
+ paths, load the library and resolve the symbols. Which means that you
+ should either change the system-defined list, given by the
+ <envar>LD_LIBRARY_PATH</envar> environment variable, or install the
+ libraries to a system location. This can be inconvenient when
+ developing, since the libraries are not yet ready to be installed, and
+ cluttering system paths is undesirable. Luckily, on Unix there's another
+ way.
+ </para>
+
+ <para>An executable can include a list of additional library paths, which
+ will be searched before system paths. This is excellent for development,
+ because the build system knows the paths to all libraries and can include
+ them in executables. That's done when the <code>hardcode-dll-paths</code>
+ feature has the <literal>true</literal> value, which is the
+ default. When the executables should be installed, the story is
+ different.
+ </para>
+
+ <para>
+ Obviously, installed executable should not hardcode paths to your
+ development tree. (The <code>stage</code> rule explicitly disables the
+ <code>hardcode-dll-paths</code> feature for that reason.) However, you
+ can use the <code>dll-path</code> feature to add explicit paths
+ manually. For example:
+<programlisting>
+stage installed : application : <dll-path>/usr/lib/snake
+ <location>/usr/bin ;
+</programlisting>
+ will allow the application to find libraries placed to
+ <filename>/usr/lib/snake</filename>.
+ </para>
+
+ <para>If you install libraries to a nonstandard location and add an
+ explicit path, you get more control over libraries which will be used. A
+ library of the same name in a system location will not be inadvertently
+ used. If you install libraries to a system location and do not add any
+ paths, the system administrator will have more control. Each library can
+ be individually upgraded, and all applications will use the new library.
+ </para>
+
+ <para>Which approach is best depends on your situation. If the libraries
+ are relatively standalone and can be used by third party applications,
+ they should be installed in the system location. If you have lots of
+ libraries which can be used only by our application, it makes sense to
+ install it to a nonstandard directory and add an explicit path, like the
+ example above shows. Please also note that guidelines for different
+ systems differ in this respect. The Debian guidelines prohibit any
+ additional search paths, and Solaris guidelines suggest that they should
+ always be used.
+ </para>
+
+ </section>
+
+ <section id="bbv2.recipies.site-config">
+ <title>Targets in site-config.jam</title>
+
+ <para>It is desirable to declare standard libraries available on a
+ given system. Putting target declaration in Jamfile is not really
+ good, since locations of the libraries can vary. The solution is
+ to put the following to site-config.jam.</para>
+<programlisting>
+import project ;
+project.initialize $(__name__) ;
+project site-config ;
+lib zlib : : <name>z ;
+</programlisting>
+
+ <para>The second line allows this module to act as project. The
+ third line gives id to this project — it really has no location
+ and cannot be used otherwise. The fourth line just declares a
+ target. Now, one can write:
+<programlisting>
+exe hello : hello.cpp /site-config//zlib ;
+</programlisting>
+ in any Jamfile.</para>
+
+ </section>
+
+ </chapter>
+<!--
+ Local Variables:
+ mode: xml
+ sgml-indent-data: t
+ sgml-parent-document: ("userman.xml" "chapter")
+ sgml-set-face: t
+ End:
+-->
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/doc/src/howto.xml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/src/howto.xml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/src/howto.xml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <chapter id="bbv2.howto">
+ <title>How to use this document</title>
+
+ <para>
+ If you've just found out about Boost.Build V2 and want to know
+ if it will work for you, start with <xref linkend=
+ "bbv2.tutorial" />. You can continue with the <xref
+ linkend="bbv2.advanced" />. When you're ready to try Boost.Build
+ in practice, go to <xref linkend="bbv2.installation"/>.
+ </para>
+
+ <para>
+ If you are about to use Boost.Build on your project, or already
+ using it and have a problem, look at <xref linkend=
+ "bbv2.advanced"/>.
+ </para>
+
+ <para>
+ If you're trying to build a project which uses Boost.Build,
+ look at <xref linkend="bbv2.installation"/> and then read about
+ <xref linkend="bbv2.reference.commandline"/>.
+ </para>
+
+ <para>
+ If you have questions, please post them to our <ulink
+ url="../../../../more/mailing_lists.htm#jamboost">mailing
+ list</ulink>, and be sure to indicate in the subject line that
+ you're asking about Boost.Build <emphasis
+ role="bold">V2</emphasis>.
+ </para>
+
+ </chapter>
Added: boost-jam/boost-build/branches/upstream/current/doc/src/install.xml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/src/install.xml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/src/install.xml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <chapter id="bbv2.installation">
+ <title>Installation</title>
+
+ <para>
+ This section describes how to install Boost.Build from a
+ released source distribution. All paths are given relative to
+ the <firstterm>Boost.Build v2 root directory</firstterm>, which is
+
+ <!-- the normal location of the document you are reading.
+ Boost.Build is -->
+
+ <!-- That is a lie AFAICT, at least in a Boost distro. You need
+ to say something that will be true if you want to cover BBv2 as
+ distributed separately -->
+
+ located in the <filename>tools/build/v2</filename> subdirectory
+ of a full <ulink url="http://www.boost.org">Boost</ulink>
+ distribution.
+ </para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Boost.Build uses <ulink
+ url= "../jam_src/index.html">Boost.Jam</ulink>, an
+ extension of the <ulink
+ url="http://www.perforce.com/jam/jam.html">Perforce
+ Jam</ulink> portable <command>make</command> replacement. The
+ recommended way to get Boost.Jam is to <emphasis
+ role="bold"><ulink
+ url= "http://sourceforge.net/project/showfiles.php?group_id=7586&package_id=72941">download
+ a prebuilt executable</ulink></emphasis> from SourceForge.
+ If a prebuilt executable is not provided for your platform
+ or you are using Boost's sources in an unreleased state, it
+ may be neccessary to <ulink
+ url= "../../jam_src/index.html#building_bjam">build <command>bjam</command>
+ from sources</ulink> included in the Boost source tree.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <para>
+
+ To install Boost.Jam, copy the executable,
+ called <command>bjam</command>
+ or <command>bjam.exe</command> to a location accessible in
+ your <envar>PATH</envar>. Go to the Boost.Build root
+ directory and
+ run <command>bjam <option>--version</option></command>. You
+ should see:
+
+ <screen>
+ Boost.Build V2 (Milestone N)
+ Boost.Jam xx.xx.xx
+ </screen>
+
+ where N is the version of Boost.Build you're using.
+ </para>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Configure Boost.Build to recognize the build resources (such
+ as compilers and libraries) you have installed on your
+ system. Open the
+ <filename>user-config.jam</filename> file in the Boost.Build
+ root directory and follow the instructions there to describe
+ your toolsets and libraries, and, if neccessary, where they
+ are located.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ You should now be able to go to the
+ <filename>example/hello/</filename> directory and run
+ <command>bjam</command> there. A simple application will be
+ built. You can also play with other projects in the
+ <filename>example/</filename> directory.
+ <!-- This part should not go into intoduction docs, but we need to
+ place it somewhere.
+
+ <para>It is slighly better way is to copy
+ <filename>new/user-config.jam</filename> into one of the locations
+ where it can be found (given in <link linkend=
+ "bbv2.reference.init.config">this table</link>). This prevent you
+ from accidentally overwriting your config when updating.</para>
+
+ -->
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ If you are using Boost's CVS state, be sure to
+ rebuild <command>bjam</command> even if you have a previous
+ version. The CVS version of Boost.Build requires the CVS
+ version of Boost.Jam.
+ </para>
+
+ <para>
+ When <command>bjam</command> is invoked, it always needs to be
+ able to find the Boost.Build root directory, where the
+ interpreted source code of Boost.Build is located. There are
+ two ways to tell <command>bjam</command> about the root directory:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Set the environment variable <envar>BOOST_BUILD_PATH</envar>
+ to the absolute path of the Boost.Build root directory.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <para>
+ At the root directory of your project or in any of its
+ parent directories, create a file called
+ <filename>boost-build.jam</filename>, with a single line:
+
+<programlisting>
+boost-build <replaceable>/path/to/boost.build</replaceable> ;
+</programlisting>
+
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para><emphasis role="bold">N.B.</emphasis>
+ When <command>bjam</command> is invoked from anywhere in the Boost
+ directory tree <emphasis>other than</emphasis> the Boost.Build root
+ and its subdirectories, <ulink url="../../tools/build">Boost.Build
+ v1</ulink> is used by default. To override the default and use
+ Boost.Build v2, you have to add the <option>--v2</option> command
+ line option to all <command>bjam</command> invocations.</para>
+
+ </chapter>
Added: boost-jam/boost-build/branches/upstream/current/doc/src/recipes.xml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/src/recipes.xml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/src/recipes.xml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE appendix PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+ <!-- The file is empty. It's not clear if it will be needed in
+ future or FAQ completely supercedes it. -->
+
+ <appendix id="bbv2.recipies">
+ <title>Boost Build System V2 recipes</title>
+
+ </appendix>
Added: boost-jam/boost-build/branches/upstream/current/doc/src/reference.xml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/src/reference.xml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/src/reference.xml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+<chapter id="bbv2.reference">
+ <title>Detailed reference</title>
+
+ <section id="bbv2.reference.general">
+ <title>General information</title>
+
+ <section id="bbv2.reference.init">
+ <title>Initialization</title>
+
+ <para>bjam's first job upon startup is to load the Jam code which
+ implements the build system. To do this, it searches for a file
+ called "boost-build.jam", first in the invocation directory, then
+ in its parent and so forth up to the filesystem root, and finally
+ in the directories specified by the environment variable
+ BOOST_BUILD_PATH. When found, the file is interpreted, and should
+ specify the build system location by calling the boost-build
+ rule:</para>
+
+<programlisting>
+rule boost-build ( location ? )
+</programlisting>
+
+ <para>
+ If location is a relative path, it is treated as relative to
+ the directory of boost-build.jam. The directory specified by
+ location and directories in BOOST_BUILD_PATH are then searched for
+ a file called bootstrap.jam which is interpreted and is expected to
+ bootstrap the build system. This arrangement allows the build
+ system to work without any command-line or environment variable
+ settings. For example, if the build system files were located in a
+ directory "build-system/" at your project root, you might place a
+ boost-build.jam at the project root containing:
+
+<programlisting>
+boost-build build-system ;
+</programlisting>
+
+ In this case, running bjam anywhere in the project tree will
+ automatically find the build system.</para>
+
+ <para>The default "bootstrap.jam", after loading some standard
+ definitions, loads two files, which can be provided/customised by
+ user: "site-config.jam" and "user-config.jam".</para>
+
+ <para>Locations where those files a search are summarized below:</para>
+
+ <table id="bbv2.reference.init.config">
+ <title>Search paths for configuration files</title>
+
+ <tgroup cols="3">
+ <thead>
+
+ <row>
+ <entry></entry>
+
+ <entry>site-config.jam</entry>
+
+ <entry>user-config.jam</entry>
+ </row>
+
+ </thead>
+ <tbody>
+
+ <row>
+ <entry>Linux</entry>
+
+ <entry>
+ <simpara>/etc</simpara>
+ <simpara>$HOME</simpara>
+ <simpara>$BOOST_BUILD_PATH</simpara>
+ </entry>
+
+ <entry>
+ <simpara>$HOME</simpara>
+ <simpara>$BOOST_BUILD_PATH</simpara>
+ </entry>
+ </row>
+
+ <row>
+ <entry>Windows</entry>
+
+ <entry>
+ <simpara>$SystemRoot</simpara>
+ <simpara>$HOME</simpara>
+ <simpara>$BOOST_BUILD_PATH</simpara>
+ </entry>
+
+ <entry>
+ <simpara>$HOME</simpara>
+ <simpara>$BOOST_BUILD_PATH</simpara>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ Boost.Build comes with default versions of those files,
+ which can serve as templates for customized versions.
+ </para>
+
+ </section>
+ <section id="bbv2.reference.commandline">
+ <title>Command line</title>
+
+ <para>The command line may contain:</para>
+
+ <itemizedlist>
+ <listitem><simpara>Jam options,</simpara></listitem>
+
+ <listitem><simpara>Boost.Build <link linkend=
+ "bbv2.reference.init.options">options</link>,</simpara></listitem>
+
+ <listitem><simpara>Command line arguments</simpara></listitem>
+ </itemizedlist>
+
+ <section id="bbv2.reference.init.args">
+ <title>Command line arguments</title>
+
+ <para>
+ Command line arguments specify targets and build
+ request using the following rules.
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ An argument which does not contain slashes or the "="
+ symbol is either a value of an implicit feature, or target to
+ be built. It is taken to be value of a feature if appropriate
+ feature exists. Otherwise, it is considered a <link linkend=
+ "bbv2.reference.ids">target id</link>. Special target name "clean"
+ has the same effect as "--clean" option.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <para>
+ An argument with either slashes or the "=" symbol specifies
+ a number of <link linkend="bbv2.reference.buildreq">build
+ request</link>
+ elements. In the simplest form, it's just a set of properties,
+ separated by slashes, which become a single build request
+ element, for example:
+
+<programlisting>
+borland/<runtime-link>static
+</programlisting>
+
+ More complex form is used to save typing. For example,
+ instead of
+
+<programlisting>
+borland/runtime-link=static borland/runtime-link=dynamic
+</programlisting>
+
+ one can use
+
+<programlisting>
+borland/runtime-link=static,dynamic
+</programlisting>
+
+ Exactly, the conversion from argument to build request
+ elements is performed by (1) splitting the argument at each slash,
+ (2) converting each split part into a set of properties and (3)
+ taking all possible combination of the property sets. Each split
+ part should have the either the form
+
+<programlisting>
+<emphasis>feature-name</emphasis>=<emphasis>feature-value1</emphasis>[","<emphasis>feature-valueN</emphasis>]*
+</programlisting>
+
+ or, in case of implicit feature
+
+<programlisting>
+<emphasis>feature-value1</emphasis>[","<emphasis>feature-valueN</emphasis>;]*
+</programlisting>
+
+ and will be converted into property set
+
+<programlisting>
+<feature-name>feature-value1 .... <feature-name>feature-valueN
+</programlisting>
+
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ For example, the command line
+
+<programlisting>
+target1 debug gcc/runtime-link=dynamic,static
+</programlisting>
+
+ would cause target called <literal>target1</literal> to be rebuilt in
+ debug mode, except that for gcc, both dynamically and statically
+ linked binaries would be created.
+ </para>
+
+ </section>
+ <section id="bbv2.reference.init.options">
+ <title>Command line options</title>
+
+ <para>All of the Boost.Build options start with the "--" prefix.
+ They are described in the following table.</para>
+
+ <table>
+ <title>Command line options</title>
+ <tgroup cols="2">
+
+ <thead>
+ <row>
+ <entry>Option</entry>
+
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><literal>--version</literal></entry>
+
+ <entry>Prints information on Boost.Build and Boost.Jam
+ versions.</entry>
+ </row>
+
+ <row id="bbv2.reference.init.options.help">
+ <entry><literal>--help</literal></entry>
+
+ <entry>Access to the online help system. This prints general
+ information on how to use the help system with additional
+ --help* options.</entry>
+ </row>
+
+ <row>
+ <entry><literal>--clean</literal></entry>
+
+ <entry>Removes everything instead of building. Unlike
+ <literal>clean</literal> target in make, it is possible to clean only
+ some targets.</entry>
+ </row>
+
+ <row>
+ <entry><literal>--debug</literal></entry>
+
+ <entry>Enables internal checks.</entry>
+ </row>
+
+ <row>
+ <entry><literal>--dump-projects</literal></entry>
+
+ <entry>Cause the project structure to be output.</entry>
+ </row>
+
+ <row>
+ <entry><literal>--no-error-backtrace</literal></entry>
+
+ <entry>Don't print backtrace on errors. Primary useful for
+ testing.</entry>
+ </row>
+
+ <row>
+ <entry><literal>--ignore-config</literal></entry>
+
+ <entry>Do not load <literal>site-config.jam</literal> and
+ <literal>user-config.jam</literal></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </section>
+ </section>
+
+
+ </section>
+
+ <section id="bbv2.reference.jamfiles">
+ <title>Writing Jamfiles</title>
+
+ <para>This section describes specific information about writing Jamfiles.</para>
+
+ <section id="bbv2.reference.headers">
+ <title>Generated headers</title>
+
+ <para>Usually, Boost.Build handles implicit dependendies completely
+ automatically. For example, for C++ files, all <literal>#include</literal>
+ statements are found and handled. The only aspect where user help
+ might be needed is implicit dependency on generated files.</para>
+
+ <para>By default, Boost.Build handles such dependencies within one
+ main target. For example, assume that main target "app" has two
+ sources, "app.cpp" and "parser.y". The latter source is converted
+ into "parser.c" and "parser.h". Then, if "app.cpp" includes
+ "parser.h", Boost.Build will detect this dependency. Moreover,
+ since "parser.h" will be generated into a build directory, the
+ path to that directory will automatically added to include
+ path.</para>
+
+ <para>Making this mechanism work across main target boundaries is
+ possible, but imposes certain overhead. For that reason, if
+ there's implicit dependency on files from other main targets, the
+ <literal><implicit-dependency></literal> [ link ] feature must
+ be used, for example:</para>
+
+<programlisting>
+lib parser : parser.y ;
+exe app : app.cpp : <implicit-dependency>parser ;
+</programlisting>
+
+ <para>
+ The above example tells the build system that when scanning
+ all sources of "app" for implicit-dependencies, it should consider
+ targets from "parser" as potential dependencies.
+ </para>
+ </section>
+
+
+ </section>
+
+ <section id="bbv2.reference.buildprocess">
+ <title>Build process</title>
+
+ <para>The general overview of the build process was given in the
+ <link linkend="bbv2.advanced.build_process">user documentation</link>.
+ This section provides additional details, and some specific rules.
+ </para>
+
+ <para>To recap, building a target with specific properties includes the
+ following steps:
+ <orderedlist>
+
+ <listitem><para>applying default build,</para></listitem>
+
+ <listitem><para>selecting the main target alternative to use,
+ </para></listitem>
+
+ <listitem><para>determining "common" properties</para></listitem>
+
+ <listitem><para>building targets referred by the sources list and
+ dependency properties</para></listitem>
+
+ <listitem><para>adding the usage requirements produces when building
+ dependencies to the "common" properties</para></listitem>
+
+ <listitem><para>building the target using generators</para></listitem>
+
+ <listitem><para>computing the usage requirements to be returned</para></listitem>
+
+ </orderedlist>
+ </para>
+
+ <section id="bbv2.reference.buildprocess.alternatives">
+ <title>Alternative selection</title>
+
+ <para>When there are several alternatives, one of them must be
+ selected. The process is as follows:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ For each alternative <emphasis>condition</emphasis> is defined
+ as the set of base properies in requirements. [Note: it might be
+ better to specify the condition explicitly, as in
+ conditional requirements].
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ An alternative is viable only if all properties in condition
+ are present in build request.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there's one viable alternative, it's choosen. Otherwise,
+ an attempt is made to find one best alternative. An alternative
+ a is better than another alternative b, iff set of properties
+ in b's condition is strict subset of the set of properities of
+ 'a's condition. If there's one viable alternative, which is
+ better than all other, it's selected. Otherwise, an error is
+ reported.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ </section>
+
+ <section id="bbv2.reference.buildprocess.common">
+ <title>Determining common properties</title>
+
+ <para>The "common" properties is a somewhat artificial term. Those are
+ the intermediate property set from which both the build request for
+ dependencies and properties for building the target are derived.
+ </para>
+
+ <para>Since default build and alternatives are already handled, we have
+ only two inputs: build requests and requirements. Here are the rules
+ about common properties.
+ </para>
+
+ <orderedlist>
+ <listitem><para>Non-free feature can have only one
+ value</para></listitem>
+
+ <listitem><para>A non-conditional property in requirement in always
+ present in common properties.</para></listitem>
+
+ <listitem><para>A property in build request is present in
+ common properties, unless (2) tells otherwise.</para></listitem>
+
+ <listitem><para>If either build request, or requirements (non-conditional
+ or conditional) include an expandable property (either composite,
+ or property with specified subfeature value), the behaviour is
+ equivalent to explicitly adding all expanded properties to build
+ request or requirements.</para></listitem>
+
+ <listitem><para>If requirements include a conditional property, and
+ condiiton of this property is true in context of common
+ properties, then the conditional property should be in common
+ properties as well.</para></listitem>
+
+ <listitem><para>If no value for a feature is given by other rules
+ here, it has default value in common properties.</para></listitem>
+ </orderedlist>
+
+ <para>Those rules are declarative, they don't specify how to compute the
+ common properties. However, they provide enough information for the
+ user. The important point is the handling of conditional
+ requirements. The condition can be satisfied either by property in
+ build request, by non-conditional requirements, or even by another
+ conditional property. For example, the following example works as
+ expected:
+<programlisting>
+exe a : a.cpp
+ : <toolset>gcc:<variant>release
+ <variant>release:<define>FOO ;
+</programlisting>
+ </para>
+
+ </section>
+
+
+<!--
+
+ <para>Construction of each main target begins with finding
+ properties for <emphasis>this</emphasis> main target. They are found by
+ processing both build request, and <emphasis>target requirements</emphasis>,
+ which give properties needed for the target to build. For
+ example, a given main target might require certian defines, or
+ will not work unless compiled in multithreaded mode. The process
+ of finding properties for main target is described in <link linkend=
+ "bbv2.reference.variants.proprefine">property refinement</link>.
+ </para>
+
+ <para>After that, dependencies (i.e. other main targets) are built
+ recursively. Build request for dependencies is not always equal
+ to those of dependent — certain properties are dropped and
+ user can explicitly specify desired properties for dependencies.
+ See <link linkend="bbv2.reference.features.attributes.propagated">
+ propagated features</link> and <xref linkend=
+ "bbv2.advanced.targets.references"/> for details.</para>
+
+ <para>When dependencies are constructed, the dependency graph for
+ this main target and for this property set is created, which
+ describes which files need to be created, on which other files
+ they depend and what actions are needed to construct those files.
+ There's more that one method, and user can define new ones, but
+ usually, this involves <emphasis>generators</emphasis> and <emphasis>target
+ types</emphasis>.</para>
+
+ <para>Target type is just a way to classify targets. For example,
+ there are builtin types <literal>EXE</literal>, <literal>OBJ</literal> and
+ <literal>CPP</literal>. <link linkend=
+ "bbv2.reference.generators">Generators</link> are objects
+ that know how to convert between different target type. When a
+ target of a given type must be created, all generators for that
+ type, which can handle needed properties, are found. Each is
+ passed the list of sources, and either fails, or returns a
+ dependency graph. If a generator cannot produce desired type from
+ given sources, it may try to recursively construct types that it
+ can handle from the types is was passed. This allows to try all
+ possible transformations. When all generators are tried, a
+ dependency graph is selected.</para>
+
+ <para>Finally, the dependency graph is passed to underlying
+ Boost.Jam program, which runs all actions needed to bring all
+ main targets up-to date. At this step, implicit dependencies are
+ also scanned and accounted for, as described "here." [ link? ]</para>
+
+ <para>Given a list of targets ids and a build request, building goes
+ this way. First, for each id we obtain the abstract targets
+ corresponding to it. This also loads all necessary projects. If
+ no target id is given, project in the current directory is used.
+ Build request is expanded, and for each resulting property set,
+ the <literal>generate</literal> method of all targets is called, which
+ yields a list of virtual targets. After that all virtual targets
+ are actualized, and target "all" is set to depend on all created
+ actual targets. Lastly, depending on whether <literal>- XXXXXX -clean</literal>
+ option was given, either target "all" or target "clean" is
+ updated. Generation of virtual target from abstract one is
+ performed as follows:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>For project targets, all of main targets are generated
+ with the same properties. Then all projects referred via
+ "build-project" are generated as well. If it's not possible
+ to refine requested properties with project requirements, the
+ project is skipped.</para>
+
+ <para id="bbv2.reference.buildprocess.explict">
+ It is possible to disable building of certain target using the
+ <literal>explicit</literal> rule, available in all project
+ modules. The syntax is
+
+<programlisting>
+rule explicit ( target-name )
+</programlisting>
+
+ If this rule is invoked on a target, it will be built only
+ when it's explicitly requested on the command line.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ For main target, with several alternatives, one of them is
+ selected as described <link linkend=
+ "bbv2.reference.buildprocess.alternatives">below</link>.
+ If there's only one
+ alternative, it's used unconditionally.
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ All main target alternatives which requirements are
+ satisfied by the build request are enumerated.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there are several such alternatives, the one which
+ longer requirements list is selected.
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ For the selected alternative
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Each target reference in the source list are
+ recursively constructed.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Properties are refined with alternative's requirements,
+ and active features in the resulting set are executed.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Conditional properties are evaluated.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The dependency graph for the target is constructed in a
+ way which depends on the kind of main target, typically
+ using generators.
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </para>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If, when building sources, the properties on recursively
+ created targets are not link-compatibile with build properties,
+ a warning is issued.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+-->
+
+ </section>
+
+
+
+ <section id="bbv2.reference.definitions">
+
+ <section id="bbv2.reference.features">
+ <title>Features and properties</title>
+
+ <para>A <emphasis>feature</emphasis> is a normalized (toolset-independent)
+ aspect of a build configuration, such as whether inlining is
+ enabled. Feature names may not contain the '<literal>></literal>'
+ character.</para>
+
+ <!--
+ And what about dash?
+ -->
+
+ <para>Each feature in a build configuration has one or more
+ associated <emphasis>value</emphasis>s. Feature values for non-free features
+ may not contain the '<literal><</literal>', '<literal>:</literal>', or
+ '<literal>=</literal>' characters. Feature values for free features may not
+ contain the '<literal><</literal>' character.</para>
+
+ <para>A <emphasis>property</emphasis> is a (feature,value) pair, expressed as
+ <feature>value.</para>
+
+ <para>A <emphasis>subfeature</emphasis> is a feature which only exists in the
+ presence of its parent feature, and whose identity can be derived
+ (in the context of its parent) from its value. A subfeature's
+ parent can never be another subfeature. Thus, features and their
+ subfeatures form a two-level hierarchy.</para>
+
+ <para>A <emphasis>value-string</emphasis> for a feature <emphasis role="bold">F</emphasis> is a string of
+ the form
+ <literal>value-subvalue1-subvalue2</literal>...<literal>-subvalueN</literal>, where
+ <literal>value</literal> is a legal value for <emphasis role="bold">F</emphasis> and
+ <literal>subvalue1</literal>...<literal>subvalueN</literal> are legal values of some
+ of <emphasis role="bold">F</emphasis>'s subfeatures. For example, the properties
+ <literal><toolset>gcc <toolset-version>3.0.1</literal> can be
+ expressed more conscisely using a value-string, as
+ <literal><toolset>gcc-3.0.1</literal>.</para>
+
+ <para>A <emphasis>property set</emphasis> is a set of properties (i.e. a
+ collection without duplicates), for instance:
+ <literal><toolset>gcc <runtime-link>static</literal>.</para>
+
+ <para>A <emphasis>property path</emphasis> is a property set whose elements have
+ been joined into a single string separated by slashes. A property
+ path representation of the previous example would be
+ <literal><toolset>gcc/<runtime-link>static</literal>.</para>
+
+ <para>A <emphasis>build specification</emphasis> is a property set which fully
+ describes the set of features used to build a target.</para>
+
+ <section id="bbv2.reference.features.validity">
+ <title>Property Validity</title>
+
+ <para>
+ For <link linkend=
+ "bbv2.reference.features.attributes.free">free</link>
+ features, all values are valid. For all other features,
+ the valid values are explicitly specified, and the build
+ system will report an error for the use of an invalid
+ feature-value. Subproperty validity may be restricted so
+ that certain values are valid only in the presence of
+ certain other subproperties. For example, it is possible
+ to specify that the <code><gcc-target>mingw</code>
+ property is only valid in the presence of
+ <code><gcc-version>2.95.2</code>.
+ </para>
+
+ </section>
+ <section id="bbv2.reference.features.attributes">
+ <title>Feature Attributes</title>
+
+ <para>Each feature has a collection of zero or more of the following
+ attributes. Feature attributes are low-level descriptions of how the
+ build system should interpret a feature's values when they appear in
+ a build request. We also refer to the attributes of properties, so
+ that an <emphasis>incidental</emphasis> property, for example, is
+ one whose feature has the <emphasis>incidental</emphasis>
+ attribute.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>incidental</emphasis></para>
+
+ <para>Incidental features are assumed not to affect build
+ products at all. As a consequence, the build system may use
+ the same file for targets whose build specification differs
+ only in incidental features. A feature which controls a
+ compiler's warning level is one example of a likely
+ incidental feature.</para>
+
+ <para>Non-incidental features are assumed to affect build
+ products, so the files for targets whose build specification
+ differs in non-incidental features are placed in different
+ directories as described in "target paths" below. [ where? ]
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <anchor id="bbv2.reference.features.attributes.propagated"/>
+ <emphasis>propagated</emphasis>
+ </para>
+
+ <para>Features of this kind are
+ propagated to dependencies. That is, if a <link linkend=
+ "bbv2.advanced.targets.main">main target</link> is built using a
+ propagated
+ property, the build systems attempts to use the same property
+ when building any of its dependencies as part of that main
+ target. For instance, when an optimized exectuable is
+ requested, one usually wants it to be linked with optimized
+ libraries. Thus, the <literal><optimization></literal> feature is
+ propagated.</para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <anchor id="bbv2.reference.features.attributes.free"/>
+ <emphasis>free</emphasis>
+ </para>
+
+ <para>Most features have a finite set of allowed values, and can
+ only take on a single value from that set in a given build
+ specification. Free features, on the other hand, can have
+ several values at a time and each value can be an arbitrary
+ string. For example, it is possible to have several
+ preprocessor symbols defined simultaneously:</para>
+
+<programlisting>
+<define>NDEBUG=1 <define>HAS_CONFIG_H=1
+</programlisting>
+
+ </listitem>
+
+ <listitem>
+ <para><emphasis>optional</emphasis></para>
+
+ <para>An optional feature is a feature which is not required to
+ appear in a build specification. Every non-optional non-free
+ feature has a default value which is used when a value for
+ the feature is not otherwise specified, either in a target's
+ requirements or in the user's build request. [A feature's
+ default value is given by the first value listed in the
+ feature's declaration. -- move this elsewhere - dwa]</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>symmetric</emphasis></para>
+
+ <para>A symmetric feature's default value is not automatically
+ included in <link linkend=
+ "bbv2.reference.variants">build variants</link>. Normally
+ a feature only generates a subvariant directory when its
+ value differs from the value specified by the build variant,
+ leading to an assymmetric subvariant directory structure for
+ certain values of the feature. A symmetric feature, when
+ relevant to the toolset, always generates a corresponding
+ subvariant directory.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>path</emphasis></para>
+
+ <para>The value of a path feature specifies a path. The path is
+ treated as relative to the directory of Jamfile where path
+ feature is used and is translated appropriately by the build
+ system when the build is invoked from a different
+ directory</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>implicit</emphasis></para>
+
+ <para>Values of implicit features alone identify the feature.
+ For example, a user is not required to write
+ "<toolset>gcc", but can simply write "gcc". Implicit
+ feature names also don't appear in variant paths, although
+ the values do. Thus: bin/gcc/... as opposed to
+ bin/toolset-gcc/.... There should typically be only a few
+ such features, to avoid possible name clashes.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>composite</emphasis></para>
+
+ <para>Composite features actually correspond to groups of
+ properties. For example, a build variant is a composite
+ feature. When generating targets from a set of build
+ properties, composite features are recursively expanded and
+ <emphasis>added</emphasis> to the build property set, so rules can find
+ them if neccessary. Non-composite non-free features override
+ components of composite features in a build property set.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>link-incompatible</emphasis></para>
+
+ <para>See <link linkend=
+ "bbv2.reference.variants.compat">below</link>.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>dependency</emphasis></para>
+
+ <para>The value of dependency feature if a target reference.
+ When used for building of a main target, the value of
+ dependency feature is treated as additional dependency.</para>
+
+ <para>For example, dependency features allow to state that
+ library A depends on library B. As the result, whenever an
+ application will link to A, it will also link to B.
+ Specifying B as dependency of A is different from adding B to
+ the sources of A. <!-- Need to clarify this. --></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Features which are neither free nor incidental are called
+ <emphasis>base</emphasis> features.</para>
+
+
+ </section>
+ <section id="bbv2.reference.features.declaration">
+ <title>Feature Declaration</title>
+
+ <para>The low-level feature declaration interface is the
+ <literal>feature</literal> rule from the
+ <literal>feature</literal> module:
+
+<programlisting>
+rule feature ( name : allowed-values * : attributes * )
+</programlisting>
+
+ A feature's allowed-values may be extended with the
+ <code>feature.extend</code> rule.
+ </para>
+
+ </section>
+ </section>
+
+ <section id="bbv2.reference.variants">
+ <title>Build Variants</title>
+
+ <para>
+ A build variant, or (simply variant) is a special kind of composite
+ feature which automatically incorporates the default values of
+ features that . Typically you'll want at least two separate
+ variants: one for debugging, and one for your release code. [
+ Volodya says: "Yea, we'd need to mention that it's a composite
+ feature and describe how they are declared, in pacticular that
+ default values of non-optional features are incorporated into
+ build variant automagically. Also, do we wan't some variant
+ inheritance/extension/templates. I don't remember how it works in
+ V1, so can't document this for V2.". Will clean up soon -DWA ]
+ </para>
+
+<!-- I no longer think link compatibility is a great idea, so comment out
+ this part of docs.
+
+ <section id="bbv2.reference.variants.compat">
+ <title>Link compatible and incompatible properties</title>
+
+ <para>When the build system tries to generate a target (such as
+ library dependency) matching a given build request, it may find
+ that an exact match isn't possible — for example, the
+ target may impose additonal build requirements. We need to
+ determine whether a buildable version of that target can actually
+ be used.</para>
+
+ <para>The build request can originate in many ways: it may come
+ directly from the user's command-line, from a dependency of a
+ main target upon a library, or from a dependency of a target upon
+ an executable used to build that target, for example. For each
+ way, there are different rules whether we can use a given
+ subvariant or not. The current rules are described below.</para>
+
+ <para>Two property sets are called <emphasis>link-compatible</emphasis> when
+ targets with those property sets can be used interchangably. In
+ turn, two property sets are link compatible when there's no
+ link-incompatible feature which has different values in those
+ property sets.</para>
+
+ <para>When building of a main target is requested from a command
+ line or some project, link-compatibility is not considered. When
+ building is requested by other main target, via sources or
+ dependency properties, the requested and actual property sets
+ must be link-compatible, otherwise a warning is produced.</para>
+
+ <para><emphasis role="bold">Rationale:</emphasis>Link-compatibility is not considered when
+ main target is requested by a project, because it causes problems
+ in practice. For example, some parts of a project might be
+ single-threaded, while others — multi-threaded. They are
+ not link-compatible, but they are not linked, either. So, there's
+ no need to issue error or warning. The errors used to be
+ generated, and only caused problems.</para> -->
+
+ </section>
+
+ <section id="bbv2.reference.variants.proprefine">
+ <title>Property refinement</title>
+
+ <para>When a target with certain properties is requested, and that
+ target requires some set of properties, it is needed to find the
+ set of properties to use for building. This process is called
+ <emphasis>property refinement</emphasis> and is performed by these rules</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ If original properties and required properties are not
+ link-compatible, refinement fails.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Each property in the required set is added to the original
+ property set
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If the original property set includes property with a different
+ value of non free feature, that property is removed.
+ </simpara>
+ </listitem>
+ </orderedlist>
+ </section>
+
+ <section id="bbv2.reference.variants.propcond">
+ <title>Conditional properties</title>
+
+ <para>Sometime it's desirable to apply certain requirements only for
+ a specific combination of other properties. For example, one of
+ compilers that you use issues a pointless warning that you want to
+ suppress by passing a command line option to it. You would not
+ want to pass that option to other compilers. Conditional
+ properties allow you to do just that. Their syntax is:</para>
+
+ <programlisting>
+ property ( "," property ) * ":" property
+ </programlisting>
+
+ <para>
+ For example, the problem above would be solved by:
+
+<programlisting>
+exe hello : hello.cpp : <toolset>yfc:<cxxflags>-disable-pointless-warning ;
+</programlisting>
+ </para>
+
+ </section>
+
+ <section id="bbv2.reference.ids">
+ <title>Target identifiers and references</title>
+
+ <para><emphasis>Target identifier</emphasis> is used to denote a
+ target. The syntax is:</para>
+
+<programlisting>
+target-id -> (project-id | target-name | file-name )
+ | (project-id | directory-name) "//" target-name
+project-id -> path
+target-name -> path
+file-name -> path
+directory-name -> path
+</programlisting>
+
+ <para>
+ This grammar allows some elements to be recognized as either
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ project id (at this point, all project ids start with slash).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ name of target declared in current Jamfile (note that target
+ names may include slash).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ a regular file, denoted by absolute name or name relative to
+ project's sources location.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ To determine the real meaning a check is made if project-id
+ by the specified name exists, and then if main target of that
+ name exists. For example, valid target ids might be:
+
+<screen>
+a -- target in current project
+lib/b.cpp -- regular file
+/boost/thread -- project "/boost/thread"
+/home/ghost/build/lr_library//parser -- target in specific project
+</screen>
+
+ </para>
+
+ <para><emphasis role="bold">Rationale:</emphasis>Target is separated from project by special
+ separator (not just slash), because:</para>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ It emphasises that projects and targets are different things.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ It allows to have main target names with slashes.
+
+ <!-- The motivation for which is:
+
+ So, to summarize:
+
+ 1. The project which extract tarfile may extract all possible kinds
+ of targets, and it's reasonable to use them directly from other
+ project.
+
+ 2. The rule for unpacking tar is inplemented in terms of
+ "patch-file", for maintainability, and therefore, must use main
+ target name which contains slashes?
+
+ 3. Using sub-Jamfile in "foo" to declare extracted file "foo/b" is
+ not an option, because you should not change existing tree
+
+ That makes good rationale for why main target must contain names.
+ -->
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para id="bbv2.reference.targets.references">
+ <emphasis>Target reference</emphasis> is used to
+ specify a source target, and may additionally specify desired
+ properties for that target. It has this syntax:</para>
+
+<programlisting>
+target-reference -> target-id [ "/" requested-properties ]
+requested-properties -> property-path
+</programlisting>
+
+ <para>
+ For example,
+
+ <programlisting>
+ exe compiler : compiler.cpp libs/cmdline/<optimization>space ;
+ </programlisting>
+
+ would cause the version of <literal>cmdline</literal> library,
+ optimized for space, to be linked in even if the
+ <literal>compiler</literal> executable is build with optimization for
+ speed.
+ </para>
+ </section>
+
+ </section>
+
+ <section id="bbv2.reference.generators">
+ <title>Generators</title>
+
+ <warning><para>The information is this section is likely to be outdated
+ and misleading.
+ </para></warning>
+
+ <para>To construct a main target with given properties from sources,
+ it is required to create a dependency graph for that main target,
+ which will also include actions to be run. The algorithm for
+ creating the dependency graph is described here.</para>
+
+ <para>The fundamental concept is <emphasis>generator</emphasis>. If encapsulates
+ the notion of build tool and is capable to converting a set of
+ input targets into a set of output targets, with some properties.
+ Generator matches a build tool as closely as possible: it works
+ only when the tool can work with requested properties (for
+ example, msvc compiler can't work when requested toolset is gcc),
+ and should produce exactly the same targets as the tool (for
+ example, if Borland's linker produces additional files with debug
+ information, generator should also).</para>
+
+ <para>Given a set of generators, the fundamental operation is to
+ construct a target of a given type, with given properties, from a
+ set of targets. That operation is performed by rule
+ <literal>generators.construct</literal> and the used algorithm is described
+ below.</para>
+
+ <section>
+ <title>Selecting and ranking viable generators</title>
+
+ <para>Each generator, in addition to target types that it can
+ produce, have attribute that affects its applicability in
+ particular sitiation. Those attributes are:</para>
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ Required properties, which are properties absolutely
+ necessary for the generator to work. For example, generator
+ encapsulating the gcc compiler would have <toolset>gcc as
+ required property.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Optional properties, which increase the generators
+ suitability for a particual build.
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ Generator's required and optional properties may not include
+ either free or incidental properties. (Allowing this would
+ greatly complicate caching targets).
+ </para>
+
+ <para>When trying to construct a target, the first step is to select
+ all possible generators for the requested target type, which
+ required properties are a subset of requested properties.
+ Generators which were already selected up the call stack are
+ excluded. In addition, if any composing generators were selected
+ up the call stack, all other composing generators are ignored
+ (TODO: define composing generators). The found generators
+ are assigned a rank, which is the number of optional properties
+ present in requested properties. Finally, generators with highest
+ rank are selected for futher processing.</para>
+
+ </section>
+ <section>
+ <title>Running generators</title>
+
+ <para>When generators are selected, each is run to produce a list of
+ created targets. This list might include targets which are not of
+ requested types, because generators create the same targets as
+ some tool, and tool's behaviour is fixed. (Note: should specify
+ that in some cases we actually want extra targets). If generator
+ fails, it returns an empty list. Generator is free to call
+ 'construct' again, to convert sources to the types it can handle.
+ It also can pass modified properties to 'construct'. However, a
+ generator is not allowed to modify any propagated properties,
+ otherwise when actually consuming properties we might discover
+ that the set of propagated properties is different from what was
+ used for building sources.</para>
+
+ <para>For all targets which are not of requested types, we try to
+ convert them to requested type, using a second call to
+ <literal>construct</literal>. This is done in order to support
+ transformation sequences where single source file expands to
+ several later. See <ulink url=
+ "http://groups.yahoo.com/group/jamboost/message/1667">this
+ message</ulink> for details.</para>
+
+ </section>
+
+ <section>
+ <title>Selecting dependency graph</title>
+
+ <para>
+ After all generators are run,
+ it is necessary to decide which of successfull invocation will be
+ taken as final result. At the moment, this is not done. Instead,
+ it is checked whether all successfull generator invocation
+ returned the same target list. Error is issued otherwise.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Property adjustment</title>
+
+ <para>Because target location is determined by the build system, it
+ is sometimes necessary to adjust properties, in order to not
+ break actions. For example, if there's an action which generates
+ a header, say "a_parser.h", and a source file "a.cpp" which
+ includes that file, we must make everything work as if a_parser.h
+ is generated in the same directory where it would be generated
+ without any subvariants.</para>
+
+ <para>Correct property adjustment can be done only after all targets
+ are created, so the approach taken is:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>
+ When dependency graph is constructed, each action can be
+ assigned a rule for property adjustment.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ When virtual target is actualized, that rule is run and
+ return the final set of properties. At this stage it can use
+ information of all created virtual targets.
+ </para>
+ </listitem>
+ </orderedlist>
+
+ <para>In case of quoted includes, no adjustment can give 100% correct
+ results. If target dirs are not changed by build system, quoted
+ includes are searched in "." and then in include path, while angle
+ includes are searched only in include path. When target dirs are
+ changed, we'd want to make quoted includes to be search in "." then in
+ additional dirs and then in the include path and make angle includes
+ be searched in include path, probably with additional paths added at
+ some position. Unless, include path already has "." as the first
+ element, this is not possible. So, either generated headers should not
+ be included with quotes, or first element of include path should be
+ ".", which essentially erases the difference between quoted and angle
+ includes. <emphasis role="bold">Note:</emphasis> the only way to get
+ "." as include path into compiler command line is via verbatim
+ compiler option. In all other case, Boost.Build will convert "." into
+ directory where it occurs.</para>
+
+ </section>
+
+ <section>
+ <title>Transformations cache</title>
+
+ <para>
+ Under certain conditions, an
+ attempt is made to cache results of transformation search. First,
+ the sources are replaced with targets with special name and the
+ found target list is stored. Later, when properties, requested
+ type, and source type are the same, the store target list is
+ retrieved and cloned, with appropriate change in names.
+ </para>
+
+ </section>
+ </section>
+
+</chapter>
+
+<!--
+ Local Variables:
+ mode: xml
+ sgml-indent-data: t
+ sgml-parent-document: ("userman.xml" "chapter")
+ sgml-set-face: t
+ End:
+-->
Added: boost-jam/boost-build/branches/upstream/current/doc/src/tutorial.xml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/src/tutorial.xml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/src/tutorial.xml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,670 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+<?psgml nofill screen programlisting literallayout?>
+
+<chapter id="bbv2.tutorial" status="draft">
+ <title>Tutorial</title>
+
+ <section id="bbv2.tutorial.hello">
+ <title>Hello, world</title>
+
+ <para>The simplest project that Boost.Build can construct is
+ stored in <filename>example/hello/</filename> directory. The
+ project is described by a file
+ called <filename>Jamfile</filename> that contains:
+
+<programlisting>
+exe hello : hello.cpp ;
+</programlisting>
+
+ Even with this simple setup, you can do some interesting
+ things. First of all, just invoking <command>bjam</command> will
+ build the debug variant of the <command>hello</command>
+ executable by compiling and
+ linking <filename>hello.cpp</filename>. Now, to build the
+ release variant of <command>hello</command>, invoke
+
+<screen>
+bjam release
+</screen>
+
+ Note that debug and release variants are created in different
+ directories, so you can switch between variants or even build
+ multiple variants at once, without any unneccessary
+ recompilation. Let's extend the example by adding another line
+ to our project's <filename>Jamfile</filename>:
+
+<programlisting>
+exe hello2 : hello.cpp ;
+</programlisting>
+
+ Now we can build both the debug and release variants of our
+ project:
+
+<screen>
+bjam debug release
+</screen>
+
+ Note that two variants of <command>hello2</command> are linked.
+ Since we have already built both variants
+ of <command>hello</command>, hello.cpp won't be recompiled;
+ instead the existing object files will just be linked into the
+ corresponding variants of <command>hello2</command>. Now
+ let's remove all the built products:
+
+<screen>
+bjam --clean debug release
+</screen>
+
+ It's also possible to build or clean specific targets. The
+ following two commands, respectively, build or clean only the
+ debug version of <command>hello2</command>.
+
+<screen>
+bjam hello2
+bjam --clean hello2
+</screen>
+ </para>
+
+ </section>
+ <section id="bbv2.tutorial.properties">
+ <title>Properties</title>
+
+ <para>
+ To portably represent aspects of target configuration such as
+ debug and release variants, or single- and multi-threaded
+ builds, Boost.Build uses <firstterm>features</firstterm> with
+ associated <firstterm>values</firstterm>. For
+ example, the "debug-symbols" feature can have a value of "on" or
+ "off". A <firstterm>property</firstterm> is just a (feature,
+ value) pair. When a user initiates a build, Boost.Build
+ automatically translates the requested properties into appropriate
+ command-line flags for invoking toolset components like compilers
+ and linkers.</para>
+
+ <para>There are many built-in features that can be combined to
+ produce arbitrary build configurations. The following command
+ builds the project's "release" variant with inlining
+ disabled and debug symbols enabled:
+
+<screen>
+bjam release inlining=off debug-symbols=on
+</screen>
+</para>
+
+ <para>Properties on the command-line are specified with the syntax:
+
+<screen>
+<replaceable>feature-name</replaceable>=<replaceable>feature-value</replaceable>
+</screen>
+</para>
+
+ <para>The "release" and "debug" that we've seen
+ in <command>bjam</command> invocations are just a shorthand way to
+ specify values of the "variant" feature. For example, the command
+ above could also have been written this way:
+
+ <screen>
+bjam variant=release inlining=off debug-symbols=on
+ </screen>
+ </para>
+
+ <para> "variant" is so commonly-used that it has been given
+ special status as an <firstterm>implicit</firstterm> feature
+ — Boost.Build will deduce the its identity just from the name
+ of one of its values.
+ </para>
+
+ <para>
+ A complete description of features can be found
+ <link linkend="bbv2.reference.features">here</link>.
+ </para>
+
+
+ <section id="bbv2.tutorial.properties.requirements">
+ <title>Build Requests and Target Requirements</title>
+
+ <para>
+ The set of properties specified in the command line constitute a
+ <firstterm>build request</firstterm> — a description of
+ the desired properties for building the requested targets (or,
+ if no targets were explicitly requested, the project in the
+ current directory). The <emphasis>actual</emphasis> properties
+ used for building targets is typically a combination of the
+ build request and properties derived from the
+ project's <filename>Jamfile</filename>s. For example, the
+ locations of <code>#include</code>d header files are normally
+ not specified on the command-line, but described
+ in <filename>Jamfile</filename>s as <firstterm>target
+ requirements</firstterm> and automatically combined with the
+ build request for those targets. Multithread-enabled
+ compilation is another example of a typical target requirement.
+ The <filename>Jamfile</filename> fragment below illustrates how
+ these requirements might be specified.
+ </para>
+
+<programlisting>
+exe hello
+ : hello.cpp
+ : <include>/home/ghost/Work/boost <threading>multi
+ ;
+</programlisting>
+
+ <para>
+ When <filename>hello</filename> is built, the two
+ requirements specified above will normally always be present.
+ If the build request given on the <command>bjam</command>
+ command-line explictly contradicts a target's requirements,
+ the command-line usually overrides (or, in the case of
+ "free" feautures like <code><include></code>
+ <footnote>See <xref
+ linkend="bbv2.reference.features.attributes"/></footnote>,
+ augments) the target requirements. However, when a
+ contradiction of a target's requrements involves certain
+ <firstterm>link-incompatible</firstterm> features, the target
+ will be skipped. See <xref linkend=
+ "bbv2.reference.variants.compat"/> for more information.
+ </para>
+
+ </section>
+ <section id="bbv2.tutorial.properties.project_attributes">
+ <title>Project Attributes</title>
+
+ <para>
+ If we want the same requirements for our other
+ target, <filename>hello2</filename>, we could simply duplicate
+ them. However, as projects grow, that approach leads to a great
+ deal of repeated boilerplate in Jamfiles.
+
+ Fortunately, there's a better way. Each project (i.e. each
+ <filename>Jamfile</filename>), can specify a set of <firstterm>attributes</firstterm>,
+ including requirements:
+
+<programlisting>
+project
+ : requirements <include>/home/ghost/Work/boost <threading>multi
+ ;
+
+exe hello : hello.cpp ;
+exe hello2 : hello.cpp ;
+</programlisting>
+
+ The effect would be as if we specified the same requirement for
+ both <command>hello</command> and <command>hello2</command>.
+ </para>
+ </section>
+ </section>
+
+ <section id="bbv2.tutorial.hierarchy">
+ <title>Project Hierarchies</title>
+
+ <para>So far we've only considered examples with one project
+ (i.e. with one <filename>Jamfile</filename>). A typical large
+ software project would be composed of sub-projects organized
+ into a tree. The top of the tree is called the
+ <firstterm>project root</firstterm>. Besides a
+ <filename>Jamfile</filename>, the project root directory
+ contains a file called <filename>project-root.jam</filename>. Every other
+ <filename>Jamfile</filename> in the project has a single parent
+ project, rooted in the nearest parent directory containing a
+ <filename>Jamfile</filename>. For example, in the following
+ directory layout:
+
+<screen>
+top/
+ |
+ +-- Jamfile
+ +-- project-root.jam
+ |
+ +-- src/
+ | |
+ | +-- Jamfile
+ | `-- app.cpp
+ |
+ `-- util/
+ |
+ +-- foo/
+ . |
+ . +-- Jamfile
+ . `-- bar.cpp
+</screen>
+
+ <!-- "lib/lib1/lib1" changed to "util/foo/bar" to avoid confusion -->
+
+ the project root is <filename>top/</filename>. Because there is
+ no <filename>Jamfile</filename> in
+ <filename>top/util/</filename>, the projects in
+ <filename>top/src/</filename> and
+ <filename>top/util/foo/</filename> are immediate children of the
+ root project.
+ </para>
+
+ <para>
+ Projects inherit all attributes (such as requirements)
+ from their parents. Inherited requirements are combined with
+ any requirements specified by the sub-project.
+ For example, if <filename>top/Jamfile</filename> has
+
+<programlisting>
+<include>/home/ghost/local
+</programlisting>
+
+ in its requirements, then all of its sub-projects will have it
+ in their requirements, too. Of course, any project can add
+ additional includes. <footnote>Many features will be overridden,
+ rather than added-to, in sub-projects. See <xref
+ linkend="bbv2.reference.features.attributes"/> for more
+ information</footnote> More details can be found in the section
+ on <link linkend= "bbv2.advanced.projects">projects</link>.
+ </para>
+
+ <para>
+ Invoking <command>bjam</command> without explicitly specifying
+ any targets on the command-line builds the project rooted in the
+ current directory. Building a project does not automatically
+ cause its sub-projects to be built unless the parent project's
+ <filename>Jamfile</filename> explicitly requests it. In our
+ example, <filename>top/Jamfile</filename> might contain:
+
+<programlisting>
+build-project src ;
+</programlisting>
+
+ which would cause the project in <filename>top/src/</filename>
+ to be built whenever the project in <filename>top/</filename> is
+ built. However, targets in <filename>top/util/foo/</filename>
+ will be built only if they are needed by targets in
+ <filename>top/</filename> or <filename>top/src/</filename>.
+ </para>
+ </section>
+
+ <section id="bbv2.tutorial.libs">
+ <title>Libraries and Dependent Targets</title>
+
+ <comment>TODO: need to make this
+ section consistent with "examples-v2/libraries".</comment>
+
+ <para>
+ Targets that are "needed" by other targets are called
+ <firstterm>dependencies</firstterm> of those other targets. The
+ targets that need the other targets are called
+ <firstterm>dependent</firstterm> targets.
+ </para>
+
+ <para>To get a feeling of target dependencies, let's continue the
+ above example and see how <filename>src/Jamfile</filename> can
+ use libraries from <filename>util/foo</filename>. Assume
+ util/foo/Jamfile contains:
+
+<programlisting>
+lib bar : bar.cpp ;
+</programlisting>
+
+ Then, to use this library in <filename>src/Jamfile</filename>, we can write:
+
+<programlisting>
+exe app : app.cpp ../util/foo//bar ;
+</programlisting>
+
+ While <code>app.cpp</code> refers to a regular source file,
+ <code>../util/foo//bar</code> is a reference to another target:
+ a library "bar" declared in the <filename>Jamfile</filename> at
+ <filename>../util/foo</filename>. When linking the
+ <command>app</command> executable, the appropriate version of
+ <code>bar</code> will be built and linked in. What do we mean by
+ "appropriate"? For example, suppose we build "app" with:
+
+<screen>
+bjam app optimization=full cxxflags=-w-8080
+</screen>
+
+ Which properties must be used to build <code>foo</code>? The
+ answer is that some properties are
+ <firstterm>propagated</firstterm> — Boost.Build attempts to
+ use dependencies with the same value of propagated features. The
+ <optimization> feature is propagated, so both "app" and
+ "foo" will be compiled with full optimization. But
+ <cxxflags> feature is not propagated: its value will be
+ added as-is to compiler flags for "a.cpp", but won't affect
+ "foo". There is still a couple of problems. First, the library
+ probably has some headers which must be used when compiling
+ "app.cpp". We could use requirements on "app" to add those
+ includes, but then this work will be repeated for all programs
+ which use "foo". A better solution is to modify
+ util/foo/Jamfilie in this way:
+
+<programlisting>
+project
+ : usage-requirements <include>.
+ ;
+
+lib foo : foo.cpp ;
+</programlisting>
+
+ Usage requirements are requirements which are applied to
+ dependents. In this case, <include> will be applied to all
+ targets which use "foo" — i.e. targets which have "foo"
+ either in sources or in dependency properties. You'd need to
+ specify usage requirements only once, and programs which use "foo"
+ don't have to care about include paths any longer. Or course, the
+ path will be interpreted relatively to "util/foo" and will be
+ adjusted according to the <command>bjam</command>s invocation
+ directory. For
+ example, if building from project root, the final compiler's
+ command line will contain <option>-Ilib/foo</option>.
+ </para>
+
+ <para>The second problem is that we hardcode the path to library's
+ Jamfile. Imagine it's hardcoded in 20 different places and we
+ change the directory layout. The solution is to use project ids
+ — symbolic names, not tied to directory layout. First, we
+ assign a project id to Jamfile in util/foo:</para>
+
+<programlisting>
+project foo
+ : usage-requirements <include>.
+ ;
+</programlisting>
+
+ <para>
+ Second, we use the project id to refer to the library in
+ src/Jamfile:
+
+<programlisting>
+exe app : app.cpp /foo//bar ;
+</programlisting>
+
+ The "/foo//bar" syntax is used to refer to target "foo" in
+ project with global id "/foo" (the slash is used to specify global
+ id). This way, users of "foo" do not depend on its location, only
+ on id, which is supposedly stable. The only thing left, it to make
+ sure that src/Jamfile knows the project id that it uses. We add to
+ top/Jamfile the following line:
+
+<programlisting>
+use-project /foo : util/foo ;
+</programlisting>
+
+ Now, all projects can refer to "foo" using the symbolic
+ name. If the library is moved somewhere, only a single line in the
+ top-level Jamfile should be changed.
+ </para>
+ </section>
+
+ <section id="bbv2.tutorial.depends">
+ <title>Library dependencies</title>
+
+ <para>The previous example was simple. Often, there are long chains
+ of dependencies between libraries. The main application is a thin
+ wrapper on top of library with core logic, which uses library of
+ utility functions, which uses boost filesystem library.
+ Expressing these dependencies is straightforward:</para>
+
+<programlisting>
+lib utils : utils.cpp /boost/filesystem//fs ;
+lib core : core.cpp utils ;
+exe app : app.cpp core ;
+</programlisting>
+
+ <para>So, what's the reason to even mention this case? First,
+ because it's a bit more complex that it seems. When using shared
+ linking, libraries are build just as written, and everything will
+ work. However, what happens with static linking? It's not
+ possible to include another library in static library.
+ Boost.Build solves this problem by returning back library targets
+ which appear as sources for static libraries. In this case, if
+ everything is built statically, the "app" target will link not
+ only "core" library, but also "utils" and
+ "/boost/filesystem//fs".</para>
+
+ <para>So, the net result is that the above code will work for both
+ static linking and for shared linking.</para>
+
+ <para>Sometimes, you want all applications in some project to link
+ to a certain library. Putting the library in sources of all
+ targets is possible, but verbose. You can do better by using the
+ <source> property. For example, if "/boost/filesystem//fs"
+ should be linked to all applications in your project, you can add
+ <source>/boost/filesystem//fs to requirements of the
+ project, like this:</para>
+
+<programlisting>
+project
+ : requirements <source>/boost/filesystem//fs
+ ;
+</programlisting>
+ </section>
+
+ <section id="bbv2.tutorial.linkage">
+ <title>Static and shared libaries</title>
+
+ <para>While the
+ previous section explained how to create and use libraries, it
+ omitted one important detail. Libraries can be either
+ <emphasis>static</emphasis>, which means they are included in executable
+ files which use them, or <emphasis>shared</emphasis> (a.k.a.
+ <emphasis>dynamic</emphasis>), which are only referred to from executables,
+ and must be available at run time. Boost.Build can work with both
+ types. By default, all libraries are shared. This is much more
+ efficient in build time and space. But the need to install all
+ libraries to some location is not always convenient, especially
+ for debug builds. Also, if the installed shared library changes,
+ all application which use it might start to behave differently.
+ </para>
+
+ <para>Static libraries do not suffer from these problems, but
+ considerably increase the size of application. Before describing
+ static libraries, it's reasonable to give another, quite simple
+ approach. If your project is built with
+ <hardcode-dll-paths>true property, then the application
+ will include the full paths for all shared libraries, eliminating
+ the above problems. Unfortunately, you no longer can move shared
+ library to a different location, which makes this option suitable
+ only for debug builds. Further, only gcc compiler supports this
+ option.</para>
+
+ <para>Building a library statically is easy. You'd need to change
+ the value of <link> feature from it's deafault value
+ <literal>shared</literal>, to <literal>static</literal>. So, to build everything as
+ static libraries, you'd say</para>
+
+<screen>
+bjam link=static
+</screen>
+
+ <para>
+ on the command line. The linking mode can be fine-tuned on
+ per-target basis.
+
+ <orderedlist>
+ <listitem>
+ <para>
+ Suppose your library can be only build statically. This is
+ easily achieved using requirements:
+
+<programlisting>
+lib l : l.cpp : <link>static ;
+</programlisting>
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ What if library can be both static and shared, but when
+ using it in specific executable, you want it static?
+ <link linkend="bbv2.advanced.targets.references">Target
+ references</link> are here to help:
+
+<programlisting>
+exe important : main.cpp helpers/<link>static ;
+</programlisting>
+
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ What if the library is defined in some other project, which
+ you cannot change. But still, you want static linking to that
+ library in all cases. You can use target references everywhere:
+
+<programlisting>
+exe e1 : e1.cpp /other_project//bar/<link>static ;
+exe e10 : e10.cpp /other_project//bar/<link>static ;
+</programlisting>
+
+ but that's far from being convenient. Another way is to
+ introduce a level of indirection: create a local target, which will
+ refer to static version of <filename>foo</filename>. Here's the
+ solution:
+
+<programlisting>
+alias foo : /other_project//bar/<link>static ;
+exe e1 : e1.cpp foo ;
+exe e10 : e10.cpp foo ;
+</programlisting>
+
+ Note that the <link linkend="bbv2.builtins.alias">alias</link>
+ rule is specifically used for rename a reference to a target and possibly
+ change the properties.
+
+ </para>
+ </listitem>
+ </orderedlist>
+ </para>
+ </section>
+
+ <section id="bbv2.tutorial.conditions">
+ <title>Conditions and alternatives</title>
+
+ <para>As we've just figured out, properties can significally affect the
+ way targets are built. The processing of the <link> feature is
+ built in the build system, and is quite complex. But there is a couple
+ of mechanisms which allow ordinary users to do different things
+ depending on properties.
+ </para>
+
+ <para>The first mechanism is called <firstterm>conditinal
+ requirement</firstterm>. For example, you might want to set specific
+ defines when the library is build as shared, or you have your own define
+ to be used in release mode. Here's a piece of Jamfile.
+<programlisting>
+lib network : network.cpp
+ : <link>shared:<define>NEWORK_LIB_SHARED
+ <variant>release:<define>EXTRA_FAST
+ ;
+</programlisting>
+ This will have exactly the effect we wanted: whenever <link>shared
+ is in properties, <define>NEWORK_LIB_SHARED will be in properties
+ as well.
+ </para>
+
+ <para>
+ Sometimes different variant of a target are so different, that
+ describing them using conditional requirements would be hard. Imagine
+ that a library has different sources on two supported toolsets, and
+ dummy implementation for all the other toolset. We can express this
+ situation using <firstterm>target alternatives</firstterm>:
+<programlisting>
+lib demangler : dummy_demangler.cpp ;
+lib demangler : demangler_gcc.cpp : <toolset>gcc ;
+lib demangler : demangler_msvc.cpp : <toolset>msvc ;
+</programlisting>
+ The proper alternative will be automatically selected.
+ </para>
+
+ </section>
+
+
+ <section id="bbv2.tutorial.prebuilt">
+ <title>Prebuilt targets</title>
+
+ <para>
+ We've just learned how to use libraries which are created by
+ Boost.Build. But some libraries are not. At the same time, those
+ libraries can have different versions (release and debug, for
+ example), that we
+ should select depending on build properties. Prebuilt targets
+ provide a mechanism for that. Jamfile in util/lib2 can contain:
+
+<programlisting>
+lib lib2
+ :
+ : <file>lib2_release.a <variant>release
+ ;
+
+lib lib2
+ :
+ : <file>lib2_debug.a <variant>debug
+ ;
+</programlisting>
+
+ This defines two alternatives for target "lib2", and for each
+ one names a prebuilt file. Naturally, there are no sources.
+ Instead, the <file> feature is used to specify the file name.
+ Which alternative is selected depends on properties of dependents.
+ If "app" binary should use "lib2", we can write:
+
+<programlisting>
+exe app : app.cpp ../util/lib2//lib2 ;
+</programlisting>
+
+ If we build release version of "app", then it will be linked
+ with "lib2_release.a", and debug version will use "lib2_debug.a".
+ Another important kind of prebuilt targets are system libraries
+ — more specifically, libraries which are automatically found
+ by the compiler. E.g. gcc uses "-l" switch for that. Such libraries
+ should be declared almost like regular ones:
+
+<programlisting>
+lib zlib : : <name>z ;
+</programlisting>
+
+ We again don't specify any sources, but give a name which
+ should be passed to the compiler. In this example, and for gcc
+ compiler, the "-lz" option will be added. Paths where library
+ should be searched can also be specified:
+
+<programlisting>
+lib zlib : : <name>z <search>/opt/lib ;
+</programlisting>
+
+ And, of course, two variants can be used:
+
+<programlisting>
+lib zlib : : <name>z <variant>release ;
+lib zlib : : <name>z_d <variant>debug ;
+</programlisting>
+
+ Of course, you'll probably never in your life need debug
+ version of zlib, but for other libraries this is quite reasonable.
+ </para>
+
+ <para>More advanced use of prebuilt target is described in <ulink
+ url="doc/recipes.html#site_config_targets">recipes</ulink>.</para>
+
+ </section>
+
+</chapter>
+
+<!--
+ Local Variables:
+ mode: xml
+ sgml-indent-data:t
+ sgml-parent-document:("userman.xml" "chapter")
+ sgml-set-face: t
+ sgml-omittag:nil
+ sgml-shorttag:nil
+ sgml-namecase-general:t
+ sgml-general-insert-case:lower
+ sgml-minimize-attributes:nil
+ sgml-always-quote-attributes:t
+ sgml-indent-step:2
+ sgml-exposed-tags:nil
+ sgml-local-catalogs:nil
+ sgml-local-ecat-files:nil
+ End:
+-->
Added: boost-jam/boost-build/branches/upstream/current/doc/src/userman.xml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/src/userman.xml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/src/userman.xml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE part PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+ "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+
+<part xmlns:xi="http://www.w3.org/2001/XInclude"
+ id="bbv2" last-revision="$Date: 2004/10/21 10:05:15 $">
+
+ <title>Boost.Build v2 User Manual</title>
+
+ <!-- Chapters -->
+ <xi:include href="howto.xml"/>
+ <xi:include href="install.xml"/>
+ <xi:include href="tutorial.xml"/>
+ <xi:include href="advanced.xml"/>
+ <xi:include href="extending.xml"/>
+ <xi:include href="reference.xml"/>
+ <xi:include href="faq.xml"/>
+
+ <!-- Appendicies -->
+ <xi:include href="architecture.xml"/>
+
+</part>
Added: boost-jam/boost-build/branches/upstream/current/doc/tools.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/tools.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/tools.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,87 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+ <head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st April 2002), see www.w3.org">
+ <meta name="generator" content="Microsoft FrontPage 5.0">
+ <meta http-equiv="Content-Type" content=
+ "text/html; charset=windows-1252">
+ <!-- tidy options: ‐‐tidy-mark false -i -wrap 78 !-->
+
+ <title>Boost Build System V2 — supported tools</title>
+ </head>
+
+ <body bgcolor="#FFFFFF" text="#000000">
+ <img src="../../../../boost.png" alt="boost.png (6897 bytes)" align="center"
+ width="277" height="86"> <a href="http://sourceforge.net"><img src=
+ "http://sourceforge.net/sflogo.php?group_id=7586&type=1" width="88"
+ height="31" border="0" alt="SourceForge.net Logo" align="right"></a>
+
+ <h1>Boost Build System V2 — supported tools</h1>
+
+ <h2>Compilers</h2>
+
+ <p>The following compilers are supported:</p>
+
+ <ul>
+ <li>GNU gcc (various versions), on Linux, NT, Cygwin and Darwin.</li>
+
+ <li>Microsoft VC++ compiler (various version), on NT and Cygwin.</li>
+
+ <li>Borland's compiler, on NT and Cygwin.</li>
+
+ <li>Metrowerks Code Warrior, on NT.</li>
+
+ <li>Intel C++ Compiler, on Linux and NT.</li>
+
+ <li>Sun's C++ Compiler.</li>
+
+ </ul>
+
+ <h2>Libraries</h2>
+
+ <p>Some important libraries have special support in Boost.Build:</p>
+
+ <ul>
+ <li><a href="http://stlport.org">STLport</a> — on gcc and
+ msvc.</li>
+
+ <li><a href="http://www.trolltech.com/products/qt/index.html">QT</a>,
+ including the <tt>moc</tt> and <tt>uic</tt> tools — on gcc and msvc.</li>
+ </ul>
+
+ <h2>Other tools</h2>
+
+ <ul>
+ <li>Parser/lexer generators <tt>bison</tt> and <tt>lex</tt>.</li>
+
+ <li>XSLT processor <a href=
+ "http://xmlsoft.org/XSLT/">xsltproc</a>.</li>
+
+ <li>The Apache <a href="http://xml.apache.org/fop/index.html">FOP</a>
+ tool.</li>
+
+ <li>BoostBook documentation format.</li>
+
+ <li>GNU <a href=
+ "http://www.gnu.org/software/gettext/gettext.html">gettext</a>
+ internationalization tools.</li>
+ </ul>
+ <hr>
+
+ <p>© Copyright Vladimir Prus 2003. Permission to copy, use, modify,
+ sell and distribute this document is granted provided this copyright
+ notice appears in all copies. This document is provided "as is" without
+ express or implied warranty, and with no claim as to its suitability for
+ any purpose.</p>
+
+ <p>Revised
+ <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
+ -->Jule 3, 2003
+ <!--webbot bot="Timestamp" endspan i-checksum="13972"
+ -->
+ </p>
+ </body>
+</html>
+
Added: boost-jam/boost-build/branches/upstream/current/doc/tracker.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/doc/tracker.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/doc/tracker.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,69 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+ <head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st April 2002), see www.w3.org">
+ <meta name="generator" content="Microsoft FrontPage 5.0">
+ <meta http-equiv="Content-Type" content=
+ "text/html; charset=windows-1252">
+ <!-- tidy options: ‐‐tidy-mark false -i -wrap 78 !-->
+
+ <title>Boost Build System V2 tracker</title>
+ </head>
+
+ <body bgcolor="#FFFFFF" text="#000000">
+ <img src="../../../../boost.png" alt="boost.png (6897 bytes)" align="center"
+ width="277" height="86"> <a href="http://sourceforge.net"><img src=
+ "http://sourceforge.net/sflogo.php?group_id=7586&type=1" width="88"
+ height="31" border="0" alt="SourceForge.net Logo" align="right"></a>
+
+ <h1>Boost Build System V2 tracker</h1>
+
+ <p>All bugs, planned features and enhancements for Boost.Build V2 are
+ kept in a online tracker, awailable at <a href=
+ "http://zigzag.cs.msu.su:7814/">http://zigzag.cs.msu.su:7814/</a></p>
+
+ <p>For read only access, please do the following:</p>
+
+ <ol>
+ <li>Point your browser to the above URL.</li>
+
+ <li>Type "anonymous" as username and password.</li>
+
+ <li>To see all issues, go to "Select query" menu, and choose
+ "Active"</li>
+
+ <li>To see issues planned for the next milestone, choose "Next
+ Milestone".</li>
+ </ol>
+
+ <p>If you want to create new issues and add comments, you'd need
+ read-write access. To obtain it, please do the following:</p>
+
+ <ol>
+ <li>Point your browser to the above URL.</li>
+
+ <li>Click on the "create an account" link and follow the
+ instructions.</li>
+
+ <li>Once you've registered and logged in, click "request roles" link
+ and request "Observe" role in "Boost->Build" module.</li>
+ </ol>
+ <hr>
+
+ <p>© Copyright Vladimir Prus 2003. Permission to copy, use, modify,
+ sell and distribute this document is granted provided this copyright
+ notice appears in all copies. This document is provided "as is" without
+ express or implied warranty, and with no claim as to its suitability for
+ any purpose.</p>
+
+ <p>Revised
+ <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
+ -->Jule 8, 2003
+ <!--webbot bot="Timestamp" endspan i-checksum="13972"
+ -->
+ </p>
+ </body>
+</html>
+
Added: boost-jam/boost-build/branches/upstream/current/example/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+boost-build ../kernel ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/customization/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/customization/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/customization/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,3 @@
+
+exe codegen : codegen.cpp class.verbatim usage.verbatim
+ t1.verbatim ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/customization/class.verbatim
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/customization/class.verbatim 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/customization/class.verbatim 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,7 @@
+class_template
+
+class %class_name% {
+public:
+ %class_name%() {}
+ ~%class_name%() {}
+};
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/customization/codegen.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/customization/codegen.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/customization/codegen.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,36 @@
+// (C) Copyright Vladimir Prus, 2003
+// 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)
+
+// Please see 'usage.verbatim' file for usage notes.
+
+#include <iostream>
+#include <string>
+#include <cstring>
+using std::cout;
+using std::string;
+using std::strlen;
+
+extern const char class_template[];
+extern const char usage[];
+
+int main(int ac, char* av[])
+{
+ if (av[1]) {
+
+ string class_name = av[1];
+ string s = class_template;
+
+ string::size_type n;
+ while((n = s.find("%class_name%")) != string::npos) {
+ s.replace(n, strlen("%class_name%"), class_name);
+ }
+ std::cout << "Output is:\n";
+ std::cout << s << "\n";
+ return 0;
+ } else {
+ std::cout << usage << "\n";
+ return 1;
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/example/customization/inline_file.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/customization/inline_file.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/customization/inline_file.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,45 @@
+#!/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.
+
+import sys
+from string import strip
+
+def quote_line(line):
+
+ result = ""
+
+ for i in line:
+ if (i == '\\'):
+ result = result + '\\\\'
+ elif (i == '\"'):
+ result = result + '\\\"'
+ elif (i != '\r' and i != '\n'):
+ result = result + i;
+
+ return '\"' + result + '\\n\"'
+
+def quote_file(file):
+ result = ""
+
+ for i in file.readlines():
+ result = result + quote_line(i) + "\n"
+
+ return result
+
+if len(sys.argv) < 3:
+ print "Usage: inline_file.py output_c_file file_to_include"
+else:
+ output_c_file = sys.argv[1]
+ out_file = open(output_c_file, "w");
+
+ file_to_include = sys.argv[2]
+
+ in_file = open(file_to_include, "r");
+ variable_name = strip(in_file.readline())
+ out_file.write("extern const char %s[] = {\n%s};\n\n" % (variable_name, quote_file(in_file)))
+ in_file.close()
+ out_file.close()
Property changes on: boost-jam/boost-build/branches/upstream/current/example/customization/inline_file.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/example/customization/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/customization/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/customization/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+import verbatim ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/customization/readme.txt
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/customization/readme.txt 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/customization/readme.txt 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,7 @@
+
+This example show how to add a new target type and a new tool
+support to Boost.Build. Please refer to extender manual for
+complete description of this example.
+
+Note that this example requires Python. If cygwin Python on Windows is
+to be used, please go to "verbatim.jam" and follow instructions there.
Added: boost-jam/boost-build/branches/upstream/current/example/customization/t1.verbatim
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/customization/t1.verbatim 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/customization/t1.verbatim 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+t1
+//###include "t2.verbatim"
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/customization/t2.verbatim
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/example/customization/usage.verbatim
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/customization/usage.verbatim 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/customization/usage.verbatim 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,6 @@
+usage
+Usage: codegen class_name
+
+This program takes a template of C++ code and replaces of
+occurences of %class_name% with the passed 'class_name'
+parameter.
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/customization/verbatim.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/customization/verbatim.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/customization/verbatim.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,53 @@
+# Copyright (C) Vladimir Prus 2003-2004. 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.
+
+#
+# This file shows some of the primary customization mechanisms in Boost.Build V2
+# and should serve as a basic for your own customization.
+# Each part has a comment describing its purpose, and you can pick the parts
+# which are relevant to your case, remove everything else, and then change names
+# and actions to taste.
+
+# Declare a new target type. This allows Boost.Build to do something sensible
+# when targets with the .verbatim extension are found in sources.
+import type ;
+type.register VERBATIM : verbatim ;
+
+# Declare a dependency scanner for the new target type. The
+# 'inline-file.py' script does not handle includes, so this is
+# only for illustraction.
+import scanner ;
+# First, define a new class, derived from 'common-scanner',
+# that class has all the interesting logic, and we only need
+# to override the 'pattern' method which return regular
+# expression to use when scanning.
+class verbatim-scanner : common-scanner
+{
+ rule pattern ( )
+ {
+ return "//###include[ ]*\"([^\"]*)\"" ;
+ }
+}
+
+# Register the scanner class. The 'include' is
+# the property which specifies the search path
+# for includes.
+scanner.register verbatim-scanner : include ;
+# Assign the scanner class to the target type.
+# Now, all .verbatim sources will be scanned.
+# To test this, build the project, touch the
+# t2.verbatim file and build again.
+type.set-scanner VERBATIM : verbatim-scanner ;
+
+import generators ;
+generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
+
+# Note: To use Cygwin Python on Windows change the following line
+# to "python inline_file.py $(<) $(>)"
+# Also, make sure that "python" in in PATH.
+actions inline-file
+{
+ "./inline_file.py" $(<) $(>)
+}
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/gettext/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/gettext/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/gettext/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,22 @@
+
+# Declare a main target.
+exe main : main.cpp ;
+
+# Declare an action for updating translations
+# After changing main.cpp, invocation of
+#
+# bjam update-russian
+#
+# will update translations in russian.po
+gettext.update update-russian : russian.po main ;
+
+# Compiled message catalog.
+gettext.catalog russian : russian.po ;
+
+# A stage rule which installs message catalog to the
+# location gettext expects.
+stage messages-russian : russian
+ : <location>messages/ru_RU.KOI8-R/LC_MESSAGES
+ <name>main
+ ;
+
Added: boost-jam/boost-build/branches/upstream/current/example/gettext/main.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/gettext/main.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/gettext/main.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,28 @@
+// Copyright Vladimir Prus 2003.
+// 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)
+
+
+#include <locale.h>
+#include <libintl.h>
+#define i18n(s) gettext(s)
+
+#include <iostream>
+using namespace std;
+
+int main()
+{
+ // Specify that translations are stored in directory
+ // "messages".
+ bindtextdomain("main", "messages");
+ textdomain("main");
+
+ // Switch to russian locale.
+ setlocale(LC_MESSAGES, "ru_RU.KOI8-R");
+
+ // Output localized message.
+ std::cout << i18n("hello") << "\n";
+
+ return 0;
+}
Added: boost-jam/boost-build/branches/upstream/current/example/gettext/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/gettext/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/gettext/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+using gettext ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/gettext/readme.txt
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/gettext/readme.txt 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/gettext/readme.txt 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,21 @@
+
+This example shows how it's possible to used GNU gettext utilities with
+Boost.Build.
+
+A simple translation file is compiled and installed as message catalog for
+russian. The main application explicitly switches to russian locale and
+output the translation of "hello".
+
+To test:
+
+ bjam
+ bin/gcc/debug/main
+
+To test even more:
+
+ - add more localized strings to "main.cpp"
+ - run "bjam update-russian"
+ - edit "russian.po"
+ - run bjam
+ - run "main"
+
Added: boost-jam/boost-build/branches/upstream/current/example/gettext/russian.po
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/gettext/russian.po 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/gettext/russian.po 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,21 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-07-01 15:45+0400\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: main.cpp:16
+msgid "hello"
+msgstr "international hello"
Added: boost-jam/boost-build/branches/upstream/current/example/hello/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/hello/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/hello/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+exe hello : hello.cpp ;
Added: boost-jam/boost-build/branches/upstream/current/example/hello/hello.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/hello/hello.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/hello/hello.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,16 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#include <iostream>
+
+int main()
+{
+ std::cout << "Hello!\n";
+ return 1;
+}
Added: boost-jam/boost-build/branches/upstream/current/example/hello/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/hello/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/hello/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+
Added: boost-jam/boost-build/branches/upstream/current/example/libraries/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/libraries/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/libraries/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+build-project app ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/libraries/app/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/libraries/app/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/libraries/app/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,5 @@
+
+# Declare a executable file, which uses a library. Note that
+# includes that for library will be automatically used
+# when compiling 'app.cpp'
+exe app : app.cpp ../lib1//lib1 ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/libraries/app/app.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/libraries/app/app.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/libraries/app/app.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,15 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#include <lib1.h>
+
+int main()
+{
+ foo();
+}
Added: boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,5 @@
+
+project lib1
+ : usage-requirements <include>include ;
+
+lib lib1 : lib1.cpp ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/include/lib1.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/include/lib1.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/include/lib1.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,10 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+void foo();
Added: boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/lib1.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/lib1.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/libraries/lib1/lib1.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,13 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {};
Added: boost-jam/boost-build/branches/upstream/current/example/libraries/project-root.jam
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/example/qt/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/qt/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/qt/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,11 @@
+# Copyright Vladimir Prus 2004.
+# 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)
+
+project
+ # built MT version, unless asked otherwise.
+ : default-build <threading>multi
+ ;
+
+exe canvas : main.cpp canvas.cpp canvas.h : <library>/qt//qt ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/qt/canvas.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/qt/canvas.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/qt/canvas.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,73 @@
+// Copyright Vladimir Prus 2004.
+// 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)
+
+#include "canvas.h"
+
+#include <qlabel.h>
+#include <qcanvas.h>
+#include <qlayout.h>
+
+Canvas::Canvas(QWidget* parent)
+: QWidget(parent)
+{
+ m_pen = QPen(QColor(255, 128, 128));
+ m_brushes = new QBrush[2];
+ m_brushes[0] = QBrush(QColor(255, 0, 0));
+ m_brushes[1] = QBrush(QColor(0, 255, 0));
+ m_current_brush = 0;
+
+ m_canvas = new QCanvas(this);
+ m_canvas->resize(4*1600, 600);
+
+ redraw();
+
+ QVBoxLayout* l = new QVBoxLayout(this);
+
+ m_canvas_view = new QCanvasView(m_canvas, this);
+ l->addWidget(m_canvas_view);
+ m_canvas_view->resize(rect().size());
+ m_canvas_view->show();
+}
+
+Canvas::~Canvas()
+{
+ delete m_brushes;
+}
+
+void Canvas::redraw()
+{
+ QCanvasItemList l = m_canvas->allItems();
+ for(QCanvasItemList::iterator i = l.begin(),
+ e = l.end(); i != e; ++i)
+ {
+ delete *i;
+ }
+
+ unsigned count = 0;
+ for (unsigned x = 10; x < 4*1600; x += 20)
+ for (unsigned y = 10; y < 600; y += 20) {
+ QCanvasRectangle* r = new QCanvasRectangle(x, y, 10, 10, m_canvas);
+ r->setPen(m_pen);
+ r->setBrush(m_brushes[m_current_brush]);
+ r->show();
+ ++count;
+ QCanvasText* t = new QCanvasText("D", m_canvas);
+ t->move(x, y);
+ t->show();
+ ++count;
+ }
+
+ (new QCanvasText(QString::number(count), m_canvas))->show();
+ m_canvas->setAllChanged();
+
+}
+
+void Canvas::change_color()
+{
+ m_current_brush = (m_current_brush + 1)%2;
+ redraw();
+ m_canvas->update();
+}
+
Added: boost-jam/boost-build/branches/upstream/current/example/qt/canvas.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/qt/canvas.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/qt/canvas.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,35 @@
+// Copyright Vladimir Prus 2004.
+// 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)
+
+
+#ifndef CANVAS_VP_2004_08_31
+#define CANVAS_VP_2004_08_31
+
+#include <qmainwindow.h>
+#include <qpen.h>
+#include <qbrush.h>
+
+class Canvas : public QWidget
+{
+ Q_OBJECT
+public:
+ Canvas(QWidget* parent);
+
+ virtual ~Canvas();
+
+public slots:
+ void change_color();
+
+private:
+ void redraw();
+ class QCanvas* m_canvas;
+ class QCanvasView* m_canvas_view;
+ class QPen m_pen;
+ class QBrush* m_brushes;
+ int m_current_brush;
+};
+
+#endif
+
Added: boost-jam/boost-build/branches/upstream/current/example/qt/main.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/qt/main.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/qt/main.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,36 @@
+// Copyright Vladimir Prus 2004.
+// 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)
+
+#include "canvas.h"
+#include <qapplication.h>
+#include <qvbox.h>
+#include <qpushbutton.h>
+
+class Window : public QMainWindow
+{
+public:
+ Window()
+ {
+ setCaption("QCanvas test");
+ QVBox* vb = new QVBox(this);
+ setCentralWidget(vb);
+
+ Canvas* c = new Canvas(vb);
+ QPushButton* b = new QPushButton("Change color", vb);
+ connect(b, SIGNAL(clicked()), c, SLOT(change_color()));
+ }
+};
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ Window *w = new Window();
+
+ app.setMainWidget(w);
+ w->show();
+
+ return app.exec();
+}
+
Added: boost-jam/boost-build/branches/upstream/current/example/qt/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/qt/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/qt/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,9 @@
+
+import toolset ;
+
+# Tell that QT should be used. QTDIR will give installation
+# prefix.
+toolset.using qt ;
+
+#Alternatively, the prefix can be given as second argument
+#toolset.using qt : /usr/share/qt ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/qt-ui/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/qt-ui/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/qt-ui/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,10 @@
+# Copyright Felix E. Klee, 2003
+# 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)
+
+project
+ : default-build <threading>multi
+ ;
+
+exe hello : main.cpp hello_world_widget.ui : <library>/qt//qt ;
Added: boost-jam/boost-build/branches/upstream/current/example/qt-ui/hello_world_widget.ui
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/qt-ui/hello_world_widget.ui 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/qt-ui/hello_world_widget.ui 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,58 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>HelloWorldWidget</class>
+<comment>
+<!--
+ Copyright Felix E. Klee, 2003
+ 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)
+-->
+</comment>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>HelloWorldWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>124</width>
+ <height>63</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Hello World!</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Hello World!</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>OkButton</cstring>
+ </property>
+ <property name="text">
+ <string>OK</string>
+ </property>
+ </widget>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
Added: boost-jam/boost-build/branches/upstream/current/example/qt-ui/main.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/qt-ui/main.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/qt-ui/main.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,18 @@
+// Copyright Felix E. Klee, 2003
+// 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)
+
+#include "hello_world_widget.h"
+#include <qapplication.h>
+
+#include <qpushbutton.h>
+
+int main(int argc, char **argv) {
+ QApplication a(argc, argv);
+ HelloWorldWidget w;
+ QObject::connect(static_cast<QObject*>(w.OkButton), SIGNAL(clicked()), &w, SLOT(close()));
+ a.setMainWidget(&w);
+ w.show();
+ return a.exec();
+}
Added: boost-jam/boost-build/branches/upstream/current/example/qt-ui/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/qt-ui/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/qt-ui/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,11 @@
+# Copyright Felix E. Klee, 2003
+# 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)
+
+import gcc ;
+import toolset ;
+
+# Tell that QT should be used. QTDIR will give installation
+# prefix.
+toolset.using qt ;
Added: boost-jam/boost-build/branches/upstream/current/example/variant/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/variant/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/variant/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,9 @@
+
+# By default, build the project with two variants
+# we've defined in project-root.jam
+project
+ : default-build crazy super_release
+ ;
+
+exe a : a.cpp libs//l ;
+
Added: boost-jam/boost-build/branches/upstream/current/example/variant/a.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/variant/a.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/variant/a.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,7 @@
+// Copyright Vladimir Prus 2004.
+// 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)
+
+void l();
+int main() { l(); return 0; }
Added: boost-jam/boost-build/branches/upstream/current/example/variant/libs/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/variant/libs/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/variant/libs/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+lib l : l.cpp ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/variant/libs/l.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/variant/libs/l.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/variant/libs/l.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,9 @@
+// Copyright Vladimir Prus 2002-2004.
+// 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)
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void l() {}
Added: boost-jam/boost-build/branches/upstream/current/example/variant/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/variant/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/variant/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,10 @@
+
+# Define a build variant which is just combination
+# of four properties.
+variant crazy : <optimization>speed <inlining>off
+ <debug-symbols>on <profiling>on ;
+
+# Define a built variant inherited from 'release'.
+# It defines one new property and get all properties
+# from parent variant.
+variant super_release : release : <define>USE_ASM ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/example/variant/readme.txt
===================================================================
--- boost-jam/boost-build/branches/upstream/current/example/variant/readme.txt 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/example/variant/readme.txt 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,7 @@
+
+This example shows how user can create his own build variants.
+Two variants are defined: "crazy", which is just random combination
+of properties, and "super-release", which is inherited from "release",
+and differs by a single define.
+
+See the project-root.jam for the definitions.
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/hacking.txt
===================================================================
--- boost-jam/boost-build/branches/upstream/current/hacking.txt 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/hacking.txt 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,153 @@
+
+ ----------------------------------
+ Boost.Build contributor guidelines
+ ----------------------------------
+
+Boost.Build is an open-source project. This means that we welcome and
+appreciate all contributions --- be it ideas, bug reports, or patches.
+This document contains guidelines which helps to assure that development
+goes on smoothly, and changes are made quickly.
+
+The guidelines are not mandatory, and you can decide for yourself which one
+to follow. But note, that 10 mins that you spare writing a comment, for
+example, might lead to significally longer delay for everyone.
+
+Before contributing, make sure you are subscribed to our mailing list
+
+ jamboost at yahoogroups.com
+
+Additional resources include
+
+ - brief issues list
+ http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost.Build/Issues
+
+ - the issue tracker
+ http://zigzag.cs.msu.su:7814
+
+ - commits mailing list:
+ boost-build at lists.sourceforge.net
+ http://sourceforge.net/mailarchive/forum.php?forum_id=9097
+
+
+BUGS and PATCHES
+
+Both bugs and patches can be send to our mailing list.
+
+When reporting a bug, please try to provide the following information.
+
+ - What you did. A minimal reproducible testcase is very much appreciated.
+ Shell script with some annotations is much better than verbose description of
+ the problem. A regression test is the best (see test/test_system.html).
+ - What you got.
+ - What you expected.
+ - What version of Boost.Build and Boost.Jam did you use. If possible,
+ please try to test with the CVS HEAD state.
+
+When submitting a patch, please:
+
+ - make a single patch for a single logical change
+ - follow the policies and coding conventions below,
+ - send patches in unified diff format,
+ (using either "cvs diff -u" or "diff -u")
+ - provide a log message together with the patch
+ - put the patch and the log message as attachment to your email.
+
+The purpose of log message serves to communicate what was changed, and
+*why*. Without a good log message, you might spend a lot of time later,
+wondering where a strange piece of code came from and why it was necessary.
+
+The good log message mentions each changed file and each rule/method, saying
+what happend to it, and why. Consider, the following log message
+
+ Better direct request handling.
+
+ * new/build-request.jam
+ (directly-requested-properties-adjuster): Redo.
+
+ * new/targets.jam
+ (main-target.generate-really): Adjust properties here.
+
+ * new/virtual-target.jam
+ (register-actual-name): New rule.
+ (virtual-target.actualize-no-scanner): Call the above, to detected bugs,
+ where two virtual target correspond to one Jam target name.
+
+The log messages for the last two files are good. They tell what was
+changed. The change to the first file is clearly undercommented.
+
+It's OK to use terse log messages for uninteresting changes, like
+ones induces by interface changes elsewhere.
+
+
+POLICIES.
+
+1. Testing.
+
+All serious changes must be tested. New rules must be tested by the module
+where they are declared. Test system (test/test_system.html) should be used
+to verify user-observable behaviour.
+
+2. Documentation.
+
+It turns out that it's hard to have too much comments, but it's easy to have
+too little. Please predend each rule with a comment saying what the rule does
+and what arguments means. Stop for a minute and consider if the comment makes
+sense for anybody else, and completely describes what the rules does. Generic
+phrases like "adjusts properties" are really not enough.
+
+When applicable, make changes to the user documentation as well.
+
+
+CODING CONVENTIONS.
+
+ 1. All names of rules and variables are lowercase with "-" to separate
+ words.
+
+ rule call-me-ishmael ( ) ...
+
+ 2. Names with dots in them are "intended globals". Ordinary globals use
+ a dot prefix:
+
+ .foobar
+ $(.foobar)
+
+ 3. Pseudofunctions or associations are <parameter>.<property>:
+
+ $(argument).name = hello ;
+ $($(argument).name)
+
+ 4. Class attribute names are prefixed with "self.":
+
+ self.x
+ $(self.x)
+
+ 5. Builtin rules are called via their ALL_UPPERCASE_NAMES:
+
+ DEPENDS $(target) : $(sources) ;
+
+ 6. Opening and closing braces go on separate lines:
+
+ if $(a)
+ {
+ #
+ }
+ else
+ {
+ #
+ }
+
+HTML DOCUMENTATION.
+
+ Please pass HTML files though HTML Tidy (http://tidy.sf.net) before
+ comitting. This has to important purposes:
+ - detecting bad HTML
+ - converting files to uniform indentation style, which inverses effect
+ of different editors and makes differences between revisions much
+ smaller and easy for review.
+
+ Alas, the way Tidy indents HTML differs between version. Please use
+ the version awailable at
+
+ http://tidy.sourceforge.net/src/old/tidy_src_020411.tgz
+
+ and "-i -wrap 78" command line parameters.
Added: boost-jam/boost-build/branches/upstream/current/index.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/index.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/index.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,164 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+ <head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st April 2002), see www.w3.org">
+ <meta name="generator" content="Microsoft FrontPage 5.0">
+ <meta http-equiv="Content-Type" content=
+ "text/html; charset=windows-1252">
+ <!-- tidy options: ‐‐tidy-mark false -i -wrap 78 !-->
+<style type="text/css">
+div.sidebar {
+ margin-left: 1em ;
+ border: medium outset ;
+ padding: 0em 1em ;
+ background-color: #ffffee ;
+ width: 40% ;
+ float: right ;
+ clear: right }
+
+div.sidebar p.rubric {
+ font-family: sans-serif ;
+ font-size: medium }
+</style>
+
+ <title>Boost Build System V2</title>
+ </head>
+
+ <body bgcolor="#FFFFFF" text="#000000">
+ <img src="boost.png" alt="boost.png (6897 bytes)" align="center"
+ width="277" height="86"> <!-- sf logo -->
+
+
+ <div class="contents sidebar topic" id="index">
+ <p>
+ <b>Quick access</b>
+ <ul>
+ <li>Download: <a href=
+ "http://prdownloads.sourceforge.net/boost/boost-build-2.0-m10.zip">[zip]
+ </a>, <a href=
+ "http://prdownloads.sourceforge.net/boost/boost-build-2.0-m10.tar.bz2">[tar.bz2]
+ </a>
+ <li>Nightly build: <a href="http://boost.org/boost-build2/boost-build.zip">[zip]</a>,
+ <a href="http://boost.org/boost-build2/boost-build.tar.bz2">[tar.bz2]</a>
+ <li><a href="doc/html/index.html">Documentation</a>
+ (<a href="userman.pdf">PDF</a>)
+ <li><a
+ href="http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost.Build_V2">Wiki
+ (User-contibuted documentation)</a>
+ <li>Feedback: <a
+ href="http://groups.yahoo.com/group/jamboost/">[mailing list]</a>,
+ <a
+ href="news://news.gmane.org/gmane.comp.lib.boost.build">[newsgroup]</a>
+ <ul>
+ <li>Before posting, <a href="mailto:jamboost-subscribe at yahoogroups.com">subscribe</a>
+ </ul>
+<!-- <li>Rate Boost.Build: <a href="http://freshmeat.net/rate/38012/">Freshmeat</a> -->
+ </ul>
+ </p>
+ </div>
+
+
+ <h1>Boost Build System V2</h1>
+
+
+ <h2><a name="synopsis">Synopsis</a></h2>
+
+ <p>Boost.Build is a system for large project software construction, which
+ is simple to use and powerfull. Boost.Build V2 is an onging project to
+ rewrite Boost.Build, improving design and making it more extensible. The
+ distinguishing features are:</p>
+
+ <ul>
+ <li><b>Simple and high level target description language</b>. In most
+ cases name of target and list of sources is enough.</li>
+
+ <li><b>Variant builds</b>. You can build with your choice of basic
+ variants (e.g. debug, release, profile...), toolsets (e.g. gcc and
+ msvc) and specific properties (e.g. inlining off) from a single command
+ invocation.</li>
+
+ <li><b>Portability</b>. ``Feature Normalization'' allows to fine-tune
+ targets independently from the toolset used, and modular toolset
+ descriptions are employed to generate actual build instructions.</li>
+
+ <li><b>Multi-project builds</b>. Several projects can be combined and
+ built together, with dependencies correctly tracked. Typically, the
+ setting (like include paths and defines) needed to use other project
+ will be handled automatically.</li>
+
+ <li><b>Extensibility</b>. New file types and tools can be easily
+ added</li>
+ </ul>
+
+ <h2>Documentation</h2>
+
+ <p>The user manual, which includes installation instructions, tuturial
+ and initial reference is available <a href=
+ "doc/html/index.html">here</a>.</p>
+
+ <h2><a name="status">Status</a></h2>
+
+<!--
+ <p><font size=4 color=blue>Boost.Build V2 is project in development, and for building
+ C++ Boost you should use V1, see the
+ <a href="http://boost.org/more/getting_started.html">instructions</a>.
+ </font></p>
+-->
+
+ <p>Enough of the core functionality is implemented to allow practical use
+ on medium-size projects. Several compilers and tools are supported, the
+ full list is available <a href="doc/tools.html">here</a>.
+ The list of features
+ still to be implemented is outlined in the <a href=
+ "doc/development_plan.html">develepment plan</a>.</p>
+
+ <h2 id="download">Downloading</h2>
+
+ <p>The most up-to-date sources are available in <tt>tools/build</tt>
+ directory of Boost CVS. Please use "Boost CVS Repository" section in the
+ <a href="http://www.boost.org/more/download.html">download
+ instructions</a>.</p>
+
+ <p>Boost.Build releases are also available. There's <a href=
+ "http://prdownloads.sourceforge.net/boost/boost-build-2.0-m9.1.zip">zip
+ archive</a>, and <a href=
+ "http://prdownloads.sourceforge.net/boost/boost-build-2.0-m9.1.tar.bz2">tar.bz2
+ archive</a> of the current release. Older releases are available from the
+ <a href=
+ "http://sourceforge.net/project/showfiles.php?group_id=7586">SourceForce
+ download page</a>.</p>
+
+ <p>The installation is described in the
+ <a href="doc/html/bbv2.installation.html">user
+ manual</a>.</p>
+
+ <h2>Feedback</h2>
+
+ <p>Should you have any questions or comments, we'd be glad to hear them.
+ Post everything to the <a href=
+ "http://groups.yahoo.com/group/jamboost">jamboost</a> mailing list.</p>
+
+ <p>We have an online tracker for all Boost.Build bugs and features. Usage
+ instructions are available <a href="doc/tracker.html">here</a>.</p>
+
+ <p>If you'd like to help with development, there's a separate <a href=
+ "hacking.txt">guidelines document</a>.</p>
+ <hr>
+
+ <p>© Copyright David Abrahams and Vladimir Prus 2002-2003.
+ Permission to copy, use, modify, sell and distribute this document is
+ granted provided this copyright notice appears in all copies. This
+ document is provided "as is" without express or implied warranty, and
+ with no claim as to its suitability for any purpose.</p>
+
+ <p>Revised
+ <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
+ -->Oct 29, 2004
+ <!--webbot bot="Timestamp" endspan i-checksum="13972"
+ -->
+ </p>
+ </body>
+</html>
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/Jam.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/Jam.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/Jam.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1356 @@
+<HTML>
+
+<TITLE> Jam/MR - Make(1) Redux </TITLE>
+
+<BODY>
+
+<CENTER>
+
+<H1> Jam/MR - Make(1) Redux </H1>
+
+<P> The <a href=http://www.perforce.com/jam/jam.html>Jam/MR</a> Executable
+
+</CENTER>
+
+<DL>
+
+<DT> <P> <H2> USAGE </H2> <DD>
+
+<PRE>
+jam [ -a ] [ -n ] [ -v ] [ -q ]
+ [ -d <I>debug</I> ]
+ [ -f <I>jambase</I> ]
+ [ -j <I>jobs</I> ]
+ [ -o <I>actionsfile</I> ]
+ [ -s <I>var</I>=<I>value</I> ]
+ [ -t <I>target</I> ]
+ [ <I>target</I> ... ]
+</PRE>
+
+<DT> <P> <H2> DESCRIPTION </H2> <DD>
+
+ <P>
+
+ <B>Jam</B> is a program construction tool, like <B>make</B>(1).
+
+ <P>
+
+ <B>Jam</B> recursively builds target files from source files,
+ using dependency information and updating actions expressed in
+ the Jambase file, which is written in <B>jam</B>'s own interpreted
+ language. The default Jambase is compiled into <B>jam</B> and
+ provides a boilerplate for common use, relying on a user-provide
+ file "Jamfile" to enumerate actual targets and sources.
+
+ <P>
+
+ The Jambase is described in the <a href="Jambase.html">Jambase
+ Reference</a> and the document <a href="Jamfile.html">Using
+ Jamfiles and Jambase</A>.
+
+<DT> <P> <H2> OPTIONS </H2> <DD>
+
+ <P>
+
+ If <I>target</I> is provided on the command line, <B>jam</B>
+ builds <I>target;</I> otherwise <B>jam</B> builds the target
+ 'all'.
+
+ <P>
+
+ <B>Jam</b> may be invoked with the following options:
+
+ <P> <TABLE WIDTH=75% ALIGN=CENTER>
+
+ <TR><TD VALIGN=TOP><CODE> -a </CODE>
+ <TD> Build all targets anyway, even if they are up-to-date.
+
+ <TR><TD VALIGN=TOP><CODE> -d <I>n</I> </CODE>
+ <TD> Enable cummulative debugging levels from 1 to <I>n</I>.
+ Interesting values are:
+
+ <DL COMPACT>
+ <DT> 1 <DD> Show actions (the default)
+ <DT> 2 <DD> Show "quiet" actions and display all action text
+ <DT> 3 <DD> Show dependency analysis, and target/source
+ timestamps/paths
+ <DT> 4 <DD> Show shell arguments
+ <DT> 5 <DD> Show rule invocations and variable expansions
+ <DT> 6 <DD> Show directory/header file/archive scans
+ <DT> 7 <DD> Show variable settings
+ <DT> 8 <DD> Show variable fetches
+ <DT> 9 <DD> Show variable manipulation, scanner tokens
+ </DL>
+
+ <TR><TD VALIGN=TOP><CODE> -d +<I>n</I> </CODE>
+ <TD> Enable debugging level <I>n</I>.
+
+ <TR><TD VALIGN=TOP><CODE> -d 0 </CODE>
+ <TD> Turn off all debugging levels. Only errors are not suppressed.
+
+ <TR><TD VALIGN=TOP><CODE> -f <I>jambase</I></CODE>
+ <TD>Read <I>jambase</I> instead of using the built-in Jambase.
+ Only one -f flag is permitted, but the <i>jambase</i> may
+ explicitly include other files.
+
+ <TR><TD VALIGN=TOP><CODE> -j <I>n</I></CODE>
+ <TD> Run up to <I>n</I> shell commands concurrently (UNIX
+ and NT only). The default is 1.
+
+ <TR><TD VALIGN=TOP><CODE> -n</CODE>
+ <TD> Don't actually execute the updating actions, but do
+ everything else. This changes the debug level default to -d2.
+
+ <TR><TD VALIGN=TOP><CODE> -o <I>file</I></CODE>
+ <TD> Write the updating actions to the specified file instead
+ of running them (or outputting them, as on the Mac).
+
+ <TR><TD VALIGN=TOP><CODE> -q </CODE>
+ <TD> Quit quickly (as if an interrupt was received)
+ as soon as any target fails.
+
+ <TR><TD VALIGN=TOP><CODE> -s <I>var</I>=<I>value</I></CODE>
+ <TD> Set the variable <I>var</I> to <I>value</I>, overriding
+ both internal variables and variables imported from the
+ environment.
+
+ <TR><TD VALIGN=TOP><CODE> -t <I>target</I></CODE>
+ <TD> Rebuild <I>target</I> and everything that depends on it,
+ even if it is up-to-date.
+
+ <TR><TD VALIGN=TOP><CODE> -v</CODE>
+ <TD> Print the version of <B>jam</B> and exit.
+
+ </TABLE>
+
+<DT> <P> <H2> OPERATION </H2> <DD>
+
+ <P>
+
+ <b>Jam</b> has four phases of operation: start-up, parsing,
+ binding, and updating.
+
+<DT> <P> <H3> Start-up </H3> <DD>
+
+ <P>
+
+ Upon start-up, <b>jam</b> imports environment variable settings
+ into <b>jam</b> variables. Environment variables are split at
+ blanks with each word becoming an element in the variable's list
+ of values. Environment variables whose names end in PATH are
+ split at $(SPLITPATH) characters (e.g., ":" for Unix).
+
+ <P>
+
+ To set a variable's value on the command line, overriding the
+ variable's environment value, use the -s option. To see variable
+ assignments made during <b>jam</b>'s execution, use the -d+7
+ option.
+
+<DT> <P> <H3> Parsing </H3> <DD>
+
+ <P>
+
+ In the parsing phase, <b>jam</b> reads and parses the Jambase
+ file, by default the built-in one. It is written in the <b>jam</b>
+ language. See <a href="#language"> Language</a> below. The
+ last action of the Jambase is to read (via the "include" rule)
+ a user-provided file called "Jamfile".
+
+ <P>
+
+ Collectively, the purpose of the Jambase and the Jamfile is to
+ name built target and source files, construct the dependency
+ graph among them, and associate build actions with targets.
+ The Jambase defines boilerplate rules and variable assignments,
+ and the Jamfile uses these to specify the actual relationship
+ among the target and source files. See the <a
+ href="Jambase.html">Jambase Reference</a> and the document <a
+ href="Jamfile.html">Using Jamfiles and Jambase</A> for information.
+
+<A NAME="binding">
+<DT> <P> <H3> Binding </H3> <DD>
+</A>
+
+ <P>
+
+ <P> <H5> Binding </H5>
+
+ After parsing, <B>jam</B> recursively descends the dependency
+ graph and binds every file target with a location in the
+ filesystem. If <B>jam</B> detects a circular dependency in the
+ graph, it issues a warning.
+
+ <P>
+
+ File target names are given as absolute or relative path names
+ in the filesystem. If the path name is absolute, it is bound
+ as is. If the path name is relative, it is normally bound as
+ is, and thus relative to the current directory. This can be
+ modified by the settings of the $(SEARCH) and $(LOCATE) variables,
+ which enable <b>jam</b> to find and build targets spread across
+ a directory tree. See <A HREF="#search">SEARCH and LOCATE
+ Variables</a> below.
+
+ <P> <H5> Update Determination </H5>
+
+ After binding each target, <B>jam</B> determines whether the
+ target needs updating, and if so marks the target for the updating
+ phase. A target is normally so marked if it is missing, it is
+ older than any of its sources, or any of its sources are marked
+ for updating. This behavior can be modified by the application
+ of special built-in rules, ALWAYS, LEAVES, NOCARE, NOTFILE,
+ NOUPDATE, and TEMPORARY. See <A HREF="#bindingmods">Modifying
+ Binding</A> below.
+
+ <P> <H5> Header File Scanning </H5>
+
+ <P>
+
+ During the binding phase, <b>jam</b> also performs header file
+ scanning, where it looks inside source files for the implicit
+ dependencies on other files caused by C's #include syntax. This
+ is controlled by the special variables $(HDRSCAN) and $(HDRRULE).
+ The result of the scan is formed into a rule invocation, with
+ the scanned file as the target and the found included file names
+ as the sources. Note that this is the only case where rules
+ are invoked outside the parsing phase. See <A
+ HREF="#hdrscan">HDRSCAN and HDRRULE Variables</A> below.
+
+<DT> <P> <H3> Updating </H3> <DD>
+
+ <P>
+
+ After binding, <B>jam</B> again recursively descends the dependency
+ graph, this time executing the update actions for each target
+ marked for update during the binding phase. If a target's
+ updating actions fail, then all other targets which depend on
+ that target are skipped.
+
+ <P>
+
+ The -j flag instructs <B>jam</B> to build more than one target
+ at a time. If there are multiple actions on a single target,
+ they are run sequentially.
+
+<A NAME="language">
+<DT> <P> <H2> LANGUAGE </H2> <DD>
+</A>
+
+<DT> <P> <H3> Overview </H3> <DD>
+
+ <B>Jam</b> has an interpreted, procedural language. Statements
+ in <b>jam</b> are rule (procedure) definitions, rule invocations,
+ flow-of-control structures, variable assignments, and sundry
+ language support.
+
+<DT> <P> <H3> Lexical Features </H3> <DD>
+
+ <P>
+
+ <B>Jam</b> treats its input files as whitespace-separated tokens,
+ with two exceptions: double quotes (") can enclose whitespace
+ to embed it into a token, and everything between the matching
+ curly braces ({}) in the definition of a rule action is treated
+ as a single string. A backslash (\) can escape a double quote,
+ or any single whitespace character.
+
+ <P>
+
+ <B>Jam</b> requires whitespace (blanks, tabs, or newlines) to
+ surround all tokens, <i>including the colon (:) and semicolon
+ (;) tokens</i>.
+
+ <P>
+
+ <B>Jam</b> keywords (an mentioned in this document) are reserved
+ and generally must be quoted with double quotes (") to be used
+ as arbitrary tokens, such as variable or target names.
+
+<DT> <P> <H3> Targets </H3> <DD>
+
+ <P>
+
+ The essential <b>jam</b> data entity is a target. Built targets
+ are files to be updated. Source targets are the files used in
+ updating built targets. Built targets and source targets are
+ collectively referred to as file targets, and frequently built
+ targets are source targets for other built targets. Pseudotargets
+ are symbols which represent dependencies on other targets, but
+ which are not themselves associated with any real file.
+
+ <P>
+
+ A file target's identifier is generally the file's name, which
+ can be absolutely rooted, relative to the directory of <b>jam</b>'s
+ invocation, or simply local (no directory). Most often it is
+ the last case, and the actual file path is bound using the
+ $(SEARCH) and $(LOCATE) special variables. See <A HREF="#search">
+ SEARCH and LOCATE Variables</A> below. A local filename is
+ optionally qualified with grist, a string value used to assure
+ uniqueness. A file target with an identifier of the form
+ <I>file(member)</I> is a library member (usually an ar(1) archive
+ on UNIX).
+
+<DT> <P> <H3> Rules </H3> <DD>
+
+ <P>
+
+ The basic <B>jam</b> language entity is called a rule. A rule
+ is defined in two parts: the procedure and the actions. The
+ procedure is a body of <b>jam</b> statements to be run when the
+ rule is invoked; the actions are the OS shell commands to execute
+ when updating the built targets of the rule.
+
+ <P>
+
+ Rules can return values, which can be expanded into a list with
+ "[ <i>rule</i> <i>args</i> ... ]". A rule's value is the value
+ of its last statement, though only the following statements
+ have values: 'if' (value of the leg chosen), 'switch' (value of the case
+ chosen), set (value of the resulting variable), and 'return' (value
+ of its arguments). Note that 'return' doesn't actually cause a
+ return, i.e., is a no-op unless it is the last statement
+ of the last block executed within rule body.
+
+ <P>
+
+ The <b>jam</b> statements for defining and invoking rules are
+ as follows:
+
+ <P><TABLE WIDTH=75% ALIGN=CENTER><TR><TD><DL>
+
+ <P> <DT> <CODE>
+ rule <I>rulename</I> { <I>statements</I> }
+ </CODE>
+
+ <DD> Define a rule's procedure, replacing any previous
+ definition.
+
+ <P> <DT> <CODE>
+ actions [ <I>modifiers</I> ] <I>rulename</I> { <I>commands</I> }
+ </CODE>
+
+ <DD> Define a rule's updating actions, replacing any
+ previous definition.
+
+ <P> <DT> <CODE>
+ <I>rulename field1</I> : <I>field2</I> : <I>...</I>
+ : <I>fieldN</I> ;
+ </CODE>
+
+ <DD> Invoke a rule.
+
+ <P> <DT> <CODE>
+ on <I>target</I> <I>rulename field1</I> : <I>field2</I> : <I>...</I>
+ : <I>fieldN</I> ;
+ </CODE>
+
+ <DD> Invoke a rule under the influence of <I>target</I>'s specific
+ variables..
+
+ <P> <DT> <CODE>
+ [ <I>rulename field1</I> : <I>field2</I> : <I>...</I>
+ : <I>fieldN</I> ] <br>
+ [ on <I>target</I> <I>rulename field1</I> : <I>field2</I> : <I>...</I>
+ : <I>fieldN</I> ] <br>
+
+ </CODE>
+
+ <DD> Used as an argument, expands to the return value of the rule invoked.
+
+ </DL></TABLE>
+
+ <P>
+
+ A rule is invoked with values in <I>field1</I> through
+ <I>fieldN</I>. They may be referenced in the procedure's
+ <I>statements</I> as $(1) through $(<I>N</I>) (9 max), and the
+ first two only may be referenced in the action's <I>commands</I>
+ as $(1) and $(2). $(<) and $(>) are synonymous with $(1)
+ and $(2).
+
+ <P>
+
+ Rules fall into two categories: updating rules (with actions),
+ and pure procedure rules (without actions). Updating rules
+ treat arguments $(1) and $(2) as built targets and sources,
+ respectively, while pure procedure rules can take arbitrary
+ arguments.
+
+ <P>
+
+ When an updating rule is invoked, its updating actions are added
+ to those associated with its built targets ($(1)) before the
+ rule's procedure is run. Later, to build the targets in the
+ updating phase, <I>commands</I> are passed to the OS command
+ shell, with $(1) and $(2) replaced by bound versions of the
+ target names. See <A HREF="#binding"> Binding</A> above.
+
+ <P>
+
+ Rule invokation may be indirected through a variable:
+
+ <P><TABLE WIDTH=75% ALIGN=CENTER><TR><TD><DL>
+
+ <P> <DT> <CODE>
+ $(<I>var</I>) <I>field1</I> : <I>field2</I> : <I>...</I>
+ : <I>fieldN</I> ;
+ </CODE>
+
+ <P> <DT> <CODE>
+ on <I>target</I> $(<I>var</I>) <I>field1</I> : <I>field2</I> : <I>...</I>
+ : <I>fieldN</I> ;
+ </CODE>
+
+ <P> <DT> <CODE>
+ [ $(<I>var</I>) <I>field1</I> : <I>field2</I> : <I>...</I>
+
+ : <I>fieldN</I> ] <br>
+ [ on <I>target</I> $(<I>var</I>) <I>field1</I> : <I>field2</I> : <I>...</I>
+ : <I>fieldN</I> ] <br>
+
+ </CODE>
+
+ </DL></TABLE>
+
+ The variable's value names the rule (or rules) to be invoked.
+ A rule is invoked for each element in the list of
+ <TT>$(<I>var</I>)</TT>'s values. The fields
+ <I>field1</I> : <I>field2</I> : <I>...</I> are passed as
+ arguments for each invokation. For the <TT> [ ... ] </TT> forms,
+ the return value is the concatenation of the return values for
+ all of the invokations.
+
+ <A NAME="actionmods">
+ <P> <H4> Action Modifiers </H4>
+ </A>
+
+ <P>
+
+ The following action <i>modifiers</i> are understood:
+
+ <P><TABLE WIDTH=75% ALIGN=CENTER><TR><TD><DL>
+
+ <P><DT><CODE> actions bind <I>vars</I> </CODE>
+ <DD> $(vars) will be replaced with bound values.
+
+ <P><DT><CODE> actions existing </CODE>
+ <DD> $(>) includes only source targets currently existing.
+
+ <P><DT><CODE> actions ignore </CODE>
+ <DD> The return status of the <I>commands</I> is ignored.
+
+ <P><DT><CODE> actions piecemeal </CODE>
+ <DD> <I>commands</I> are repeatedly invoked with a subset
+ of $(>) small enough to fit in the command buffer on this
+ OS.
+
+ <P><DT><CODE> actions quietly </CODE>
+ <DD> The action is not echoed to the standard output.
+
+ <P><DT><CODE> actions together </CODE>
+ <DD> The $(>) from multiple invocations of the same action
+ on the same built target are glommed together.
+
+ <P><DT><CODE> actions updated </CODE>
+ <DD> $(>) includes only source targets themselves marked
+ for updating.
+
+ </DL></TABLE>
+
+
+<DT> <P> <H3> Built-in Rules </H3> <DD>
+
+ <P>
+ <B>Jam</b> has eleven built-in rules, all of which are pure
+ procedure rules without updating actions. They are in
+ three groups: the first builds the dependency graph;
+ the second modifies it; and the third are just utility
+ rules.
+
+ <P>
+
+ <P> <H5> Dependency Building </H5>
+
+ <P><TABLE WIDTH=75% ALIGN=CENTER><TR><TD><DL>
+
+ <P><DT><CODE>
+ DEPENDS <I>targets1</I> : <I>targets2</I> ;
+ </CODE>
+
+ <DD> Builds a direct dependency: makes each of <I>targets1</I>
+ depend on each of <I>targets2</I>. Generally, <I>targets1</I>
+ will be rebuilt if <I>targets2</I> are themselves rebuilt are
+ or are newer than <I>targets1</I>.
+
+ <P><DT><CODE>
+ INCLUDES <I>targets1</I> : <I>targets2</I> ;
+ </CODE>
+
+ <DD> Builds a sibling dependency: makes any target that depends
+ on any of <I>targets1</I> also depend on each of <I>targets2</I>.
+ This reflects the dependencies that arise when one source file
+ includes another: the object built from the source file depends
+ both on the original and included source file, but the two
+ sources files don't depend on each other. For example:
+
+ <CODE>
+ <P>DEPENDS foo.o : foo.c ;
+ <BR>INCLUDES foo.c : foo.h ;
+ </CODE>
+
+ <P>
+
+ "foo.o" depends on "foo.c" and "foo.h" in this example.
+
+ </DL></TABLE>
+
+ <A NAME="bindingmods">
+ <P> <H5> Modifying Binding </H5>
+ </A>
+
+ <P>
+
+ The six rules ALWAYS, LEAVES, NOCARE, NOTFILE, NOUPDATE, and
+ TEMPORARY modify the dependency graph so that <b>jam</b> treats
+ the targets differently during its target binding phase. See
+ <A HREF="#binding">Binding</A> above. Normally, <b>jam</b>
+ updates a target if it is missing, if its filesystem modification
+ time is older than any of its dependencies (recursively), or if
+ any of its dependencies are being updated. This basic behavior
+ can be changed by invoking the following rules:
+
+ <P><TABLE WIDTH=75% ALIGN=CENTER><TR><TD><DL>
+
+ <P><DT><CODE>
+ ALWAYS <I>targets</I> ;
+ </CODE>
+
+ <DD> Causes <I>targets</I> to be rebuilt regardless of whether
+ they are up-to-date (they must still be in the dependency graph).
+ This is used for the clean and uninstall targets, as they have
+ no dependencies and would otherwise appear never to need building.
+ It is best applied to targets that are also NOTFILE targets,
+ but it can also be used to force a real file to be updated as
+ well.
+
+ <P><DT><CODE>
+ LEAVES <I>targets</I> ;
+ </CODE>
+
+ <DD> Makes each of <I>targets</I> depend only on its leaf sources,
+ and not on any intermediate targets. This makes it immune to
+ its dependencies being updated, as the "leaf" dependencies are
+ those without their own dependencies and without updating actions.
+ This allows a target to be updated only if original source files
+ change.
+
+ <P><DT><CODE>
+ NOCARE <I>targets</I> ;
+ </CODE>
+
+ <DD> Causes <b>jam</b> to ignore <I>targets</I> that neither
+ can be found nor have updating actions to build them. Normally
+ for such targets <B>jam</B> issues a warning and then skips
+ other targets that depend on these missing targets. The HdrRule
+ in Jambase uses NOCARE on the header file names found during
+ header file scanning, to let <b>jam</b> know that the included
+ files may not exist. For example, if a #include is within an
+ #ifdef, the included file may not actually be around.
+
+ <P><DT><CODE>
+ NOTFILE <I>targets</I> ;
+ </CODE>
+
+ <DD> Marks <I>targets</I> as pseudotargets and not real files.
+ No timestamp is checked, and so the actions on such a target
+ are only executed if the target's dependencies are updated, or
+ if the target is also marked with ALWAYS. The default <b>jam</b>
+ target "all" is a pseudotarget. In Jambase, NOTFILE is used to
+ define several addition convenient pseudotargets.
+
+ <P><DT><CODE>
+ NOUPDATE <I>targets</I> ;
+ </CODE>
+
+ <DD> Causes the timestamps on <I>targets</I> to be ignored.
+ This has two effects: first, once the target has been created
+ it will never be updated; second, manually updating target will
+ not cause other targets to be updated. In Jambase, for example,
+ this rule is applied to directories by the MkDir rule, because
+ MkDir only cares that the target directory exists, not when it
+ has last been updated.
+
+ <P><DT><CODE>
+ TEMPORARY <I>targets</I> ;
+ </CODE>
+
+ <DD> Marks <I>targets</I> as temporary, allowing them to be
+ removed after other targets that depend upon them have been
+ updated. If a TEMPORARY target is missing, <b>jam</b> uses the
+ timestamp of the target's parent. Jambase uses TEMPORARY to
+ mark object files that are archived in a library after they are
+ built, so that they can be deleted after they are archived.
+
+ </DL></TABLE>
+
+ <P> <H5> Utility Rules </H5>
+
+ <P>
+
+ The two rules ECHO and EXIT are utility rules, used only in
+ <b>jam</b>'s parsing phase.
+
+ <P><TABLE WIDTH=75% ALIGN=CENTER><TR><TD><DL>
+
+ <P><DT><CODE>
+ ECHO <i>args</I> ;
+ </CODE>
+
+ <DD> Blurts out the message <i>args</I> to stdout.
+
+ <P><DT><CODE>
+ EXIT <i>args</I> ;
+ </CODE>
+
+ <DD> Blurts out the message <i>args</I> to stdout and then exits
+ with a failure status.
+
+ <P>
+
+ "Echo", "echo", "Exit", and "exit" are accepted as aliases for ECHO
+ and EXIT, since it is hard to tell that these are built-in
+ rules and not part of the language, like "include".
+
+ </DL></TABLE>
+
+ <P>
+
+ The GLOB rule does filename globbing.
+
+ <P><TABLE WIDTH=75% ALIGN=CENTER><TR><TD><DL>
+
+ <P><DT><CODE>
+ GLOB <i>directories</I> : <I>patterns</I> : <I>downcase-opt</I>
+ </CODE>
+
+ <DD> Using the same wildcards as for the patterns in the <A
+ HREF="#switch">switch</A> statement). It is invoked by being
+ used as an argument to a rule invocation inside of `[ ]`. For
+ example: "<TT>FILES = [ GLOB dir1 dir2 : *.c *.h ]</TT>" sets
+ A to the list of C source and header files in dir1 or dir2.
+ The resulting filenames are the full pathnames, including the
+ directory, but the pattern is applied only to the file name
+ without the directory.
+
+ <p>If <I>downcase-opt</I> is supplied, filenames are converted to
+ all-lowercase before matching against the pattern; you can use
+ this to do case-insensitive matching using lowercase patterns.
+ The paths returned will still have mixed case if the OS supplies
+ them. On Windows NT and Cygwin, filenames are always downcased
+ before matching.
+
+ </DL></TABLE>
+
+ <P>
+
+ The MATCH rule does pattern matching.
+
+ <P><TABLE WIDTH=75% ALIGN=CENTER><TR><TD><DL>
+
+ <P><DT><CODE>
+ MATCH <i>regexps</I> : <I>list</I>
+ </CODE>
+
+ <DD> Matches the <b>egrep</b>(1) style regular expressions
+ <I>regexps</I> against the strings in <I>list</I>. The result
+ is the concatenation of matching <tt>()</tt> subexpressions for
+ each string in <I>list</I>, and for each regular expression in
+ <I>regexps</I>. Only useful within the <tt>[ ]</tt> construct,
+ to change the result into a list.
+
+ </DL></TABLE>
+
+<DT> <P> <H3> Flow-of-Control </H3> <DD>
+
+ <P>
+
+ Jam has several simple flow-of-control statements:
+
+ <P><TABLE WIDTH=75% ALIGN=CENTER><TR><TD><DL>
+
+ <P><DT><CODE>
+
+ for <I>var</I> in <I>list</I> { <I>statements</I> }
+
+ </CODE>
+
+ <P><DD> Executes <i>statements</i> for each element in
+ <i>list</i>, setting the variable <i>var</i> to the element
+ value.
+
+ <A name=if>
+ <P><DT><CODE>
+ </A>
+
+ if <I>cond</I> { <I>statements</I> }
+ <BR> [ else <I>statements</I> ]
+
+ </CODE>
+
+ <P><DD> Does the obvious; the else clause is optional.
+ <i>cond</i> is built of:
+
+ <TABLE>
+
+ <TR><TD> <CODE><I>a</I></CODE></TD>
+ <TD> true if any <I>a</I> element is a non-zero-length
+ string</TD>
+ <TR><TD> <CODE><I>a</I> = <I>b</I></CODE> </TD>
+ <TD> list <I>a</I> matches list <I>b</I>
+ string-for-string</TD>
+ <TR><TD> <CODE><I>a</I> != <I>b</I> </CODE></TD>
+ <TD> list <I>a</I> does not match list <I>b</I></TD>
+ <TR><TD> <CODE><I>a</I> < <I>b</I> </CODE></TD>
+ <TD> <I>a[i]</I> string is less than <I>b[i]</I>
+ string, where <i>i</i> is first mismatched element
+ in lists <I>a</I> and <I>b</I></TD>
+ <TR><TD> <CODE><I>a</I> <= <I>b</I> </CODE></TD>
+ <TD> every <I>a</I> string is less than or equal to
+ its <I>b</I> counterpart</TD>
+ <TR><TD> <CODE><I>a</I> > <I>b</I> </CODE></TD>
+ <TD> <I>a[i]</I> string is greater than <I>b[i]</I>
+ string, where <i>i</i> is first mismatched element</TD>
+ <TR><TD> <CODE><I>a</I> >= <I>b</I> </CODE></TD>
+ <TD> every <I>a</I> string is greater than or equal to
+ its <I>b</I> counterpart</TD>
+ <TR><TD> <CODE><I>a</I> in <I>b</I> </CODE></TD>
+ <TD> true if all elements of <I>a</I> can be found
+ in <I>b</I>, or if <I>a</I> has no elements</TD>
+ <TR><TD> <CODE>! <I>cond</I> </CODE></TD>
+ <TD> condition not true</TD>
+ <TR><TD> <CODE><I>cond</I> && <I>cond</I> </CODE></TD>
+ <TD> conjunction</TD>
+ <TR><TD> <CODE><I>cond</I> || <I>cond</I> </CODE></TD>
+ <TD> disjunction</TD>
+ <TR><TD> <CODE>( <I>cond</I> ) </CODE></TD>
+ <TD> precedence grouping</TD>
+
+ </TABLE>
+
+ <P><DT> <CODE>
+
+ include <I>file</I> ;
+
+ </CODE>
+
+ <P><DD> Causes <b>jam</b> to read the named <i>file</i>.
+ The file is bound like a regular target (see <A
+ HREF="#binding"> Binding</A> above) but unlike a regular
+ target the include file cannot be built.
+
+ <P>
+
+ The include file is inserted into the input stream during
+ the parsing phase. The primary input file and all the included
+ file(s) are treated as a single file; that is, <b>jam</b>
+ infers no scope boundaries from included files.
+
+ <P><DT> <CODE>
+
+ local <i>vars</I> [ = <i>values</i> ] ;
+
+ </CODE>
+
+ <P><DD> Creates new <i>vars</i> inside to the enclosing {}
+ block, obscuring any previous values they might have. The
+ previous values for <i>vars</i> are restored when the current
+ block ends. Any rule called or file included will see the
+ local and not the previous value (this is sometimes called
+ Dynamic Scoping). The local statement may appear anywhere,
+ even outside of a block (in which case the previous value
+ is restored when the input ends). The <i>vars</i> are
+ initialized to <i>values</i> if present, or left uninitialized
+ otherwise.
+
+ <P><DT> <CODE>
+
+ return <I>values</I> ;
+
+ </CODE>
+
+ <P><DD> Within a rule body, the return statement sets the return
+ value for an invocation of the rule. It does <i>not</i> cause the
+ rule to return; a rule's value is actually the value of the
+ last statement executed, so a return should be the
+ last statement executed before the rule "naturally" returns.
+
+ <P><DT> <CODE>
+
+ <A NAME="switch">
+ switch <I>value</I>
+ </A>
+ <BR> {
+ <BR> case <I>pattern1</I> : <I>statements</I> ;
+ <BR> case <I>pattern2</I> : <I>statements</I> ;
+ <BR> ...
+ <BR> }
+
+ </CODE>
+
+ <P><DD> The switch statement executes zero or one of the
+ enclosed <i>statements</i>, depending on which, if any, is
+ the first case whose <i>pattern</I> matches <i>value</i>.
+ The <i>pattern</I> values are not variable-expanded. The
+ <i>pattern</I> values may include the following wildcards:
+
+ <TABLE>
+
+ <TR><TD><CODE> ? </CODE></TD>
+ <TD> match any single character </TD>
+ <TR><TD><CODE> * </CODE></TD>
+ <TD> match zero or more characters </TD>
+ <TR><TD><CODE> [<i>chars</i>] </CODE></TD>
+ <TD> match any single character in <i>chars</i> </TD>
+ <TR><TD><CODE> [^<i>chars</i>] </CODE></TD>
+ <TD> match any single character not in <i>chars</i> </TD>
+ <TR><TD><CODE> \<i>x</i> </CODE></TD>
+ <TD> match <i>x</i> (escapes the other wildcards)</i> </TD>
+
+ </TABLE>
+
+ <P><DT> <CODE>
+
+ while <I>cond</I> { <I>statements</I> }
+
+ </CODE>
+
+ <P><DD> Repeatedly execute <I>statements</I> while <I>cond</I>
+ remains true upon entry. (See the description of <I>cond</I>
+ expression syntax under <a href="#if">if</a>, above).
+ </DL></TABLE>
+
+<DT> <P> <H3> Variables </H3> <DD>
+
+ <P>
+
+ <B>Jam</b> variables are lists of zero or more elements, with
+ each element being a string value. An undefined variable is
+ indistinguishable from a variable with an empty list, however,
+ a defined variable may have one more elements which are null
+ strings. All variables are referenced as $(<I>variable</I>).
+
+ <P>
+
+ Variables are either global or target-specific. In the latter
+ case, the variable takes on the given value only during the
+ updating of the specific target.
+
+ <P>
+
+ A variable is defined with:
+
+ <P> <TABLE WIDTH=75% ALIGN=CENTER> <TR><TD> <DL>
+
+ <DT><CODE>
+ <I>variable</I> = <I>elements</I> ; </CODE>
+ <DT><CODE>
+ <I>variable</I> += <I>elements</I> ; </CODE>
+ <DT><CODE>
+ <I>variable</I> on <I>targets</I> = <I>elements</I> ; </CODE>
+ <DT><CODE>
+ <I>variable</I> on <I>targets</I> += <I>elements</I> ; </CODE>
+ <DT><CODE>
+ <I>variable</I> default = <I>elements</I> ; </CODE>
+ <DT><CODE>
+ <I>variable</I> ?= <I>elements</I> ; </CODE>
+
+ </DL></TABLE>
+
+ <P>
+
+ The first two forms set <I>variable</I> globally. The third
+ and forth forms set a target-specific variable. The = operator
+ replaces any previous elements of <I>variable</I> with
+ <I>elements</I>; the += operation adds <I>elements</I> to
+ <I>variable</I>'s list of elements. The final two forms are
+ synonymous: they set <I>variable</I> globally, but only if it
+ was previously unset.
+
+ <P>
+
+ Variables referenced in updating commands will be replaced with
+ their values; target-specific values take precedence over global
+ values. Variables passed as arguments ($(1) and $(2)) to actions
+ are replaced with their bound values; the "bind" modifier can
+ be used on actions to cause other variables to be replaced with
+ bound values. See <A HREF="#actionmods">Action Modifiers</A>
+ above.
+
+ <P>
+
+ <B>Jam</b> variables are not re-exported to the environment of
+ the shell that executes the updating actions, but the updating
+ actions can reference <b>jam</b> variables with $(<I>variable</I>).
+
+ <P> <H4> Variable Expansion </H4>
+
+ <P>
+
+ During parsing, <b>jam</b> performs variable expansion on each
+ token that is not a keyword or rule name. Such tokens with
+ embedded variable references are replaced with zero or more
+ tokens. Variable references are of the form $(<I>v</I>) or
+ $(<I>vm</I>), where <i>v</i> is the variable name, and <I>m</I>
+ are optional modifiers.
+
+ <P>
+
+ Variable expansion in a rule's actions is similar to variable
+ expansion in statements, except that the action string is
+ tokenized at whitespace regardless of quoting.
+
+ <P>
+
+ The result of a token after variable expansion is the
+ <i>product</i> of the components of the token, where each
+ component is a literal substring or a list substituting a variable
+ reference. For example:
+
+ <P> <TABLE WIDTH=75% ALIGN=CENTER><TR><TD><CODE>
+
+ <BR>$(X) -> a b c
+ <BR>t$(X) -> ta tb tc
+ <BR>$(X)z -> az bz cz
+ <BR>$(X)-$(X) -> a-a a-b a-c b-a b-b b-c c-a c-b c-c
+
+ </CODE></TABLE>
+
+ <P>
+
+ The variable name and modifiers can themselves contain
+ a variable reference, and this partakes of the product
+ as well:
+
+ <P> <TABLE WIDTH=75% ALIGN=CENTER><TR><TD><CODE>
+
+ <BR>$(X) -> a b c
+ <BR>$(Y) -> 1 2
+ <BR>$(Z) -> X Y
+ <BR>$($(Z)) -> a b c 1 2
+
+ </CODE></TABLE>
+
+ <P>
+
+ Because of this product expansion, if any variable reference in
+ a token is undefined, the result of the expansion is an empty
+ list. If any variable element is a null string, the result
+ propagates the non-null elements:
+
+ <P> <TABLE WIDTH=75% ALIGN=CENTER><TR><TD><CODE>
+
+ <BR>$(X) -> a ""
+ <BR>$(Y) -> "" 1
+ <BR>$(Z) ->
+ <BR>*$(X)$(Y)* -> *a* *a1* ** *1*
+ <BR>*$(X)$(Z)* ->
+
+ </CODE></TABLE>
+
+ <P>
+
+ A variable element's string value can be parsed into grist and
+ filename-related components. Modifiers to a variable are used
+ to select elements, select components, and replace components.
+ The modifiers are:
+
+ <P> <TABLE WIDTH=75% ALIGN=CENTER>
+
+ <TR><TD><CODE> [<I>n</I>] </CODE>
+ <TD>Select element number <I>n</I> (starting at 1). If
+ the variable contains fewer than <I>n</I> elements,
+ the result is a zero-element list.
+
+ <TR><TD><CODE> [<I>n</I>-<I>m</I>] </CODE>
+ <TD>Select elements number <I>n</I> through <I>m</I>.
+
+ <TR><TD><CODE> [<I>n</I>-] </CODE>
+ <TD>Select elements number <I>n</I> through the last.
+
+ <TR><TD><CODE> :B </CODE>
+ <TD>Select filename base.
+
+ <TR><TD><CODE> :S </CODE>
+ <TD>Select (last) filename suffix.
+
+ <TR><TD><CODE> :M </CODE>
+ <TD>Select archive member name.
+
+ <TR><TD><CODE> :D </CODE>
+ <TD>Select directory path.
+
+ <TR><TD><CODE> :P </CODE>
+ <TD>Select parent directory.
+
+ <TR><TD><CODE> :G </CODE>
+ <TD>Select grist.
+
+ <TR><TD><CODE> :U </CODE>
+ <TD>Replace lowercase characters with uppercase.
+
+ <TR><TD><CODE> :L </CODE>
+ <TD>Replace uppercase characters with lowercase.
+
+ <TR><TD><CODE> :<i>chars</I> </CODE>
+ <TD>Select the components listed in <i>chars</i>.
+
+ <TR><TD><CODE> :G=<I>grist</I> </CODE>
+ <TD>Replace grist with <I>grist</I>.
+
+ <TR><TD><CODE> :D=<I>path</I> </CODE>
+ <TD>Replace directory with <I>path</I>.
+
+ <TR><TD><CODE> :B=<I>base</I> </CODE>
+ <TD>Replace the base part of file name with <I>base</I>.
+
+ <TR><TD><CODE> :S=<I>suf</I> </CODE>
+ <TD>Replace the suffix of file name with <I>suf</I>.
+
+ <TR><TD><CODE> :M=<I>mem</I> </CODE>
+ <TD>Replace the archive member name with <I>mem</I>.
+
+ <TR><TD><CODE> :R=<I>root</I> </CODE>
+ <TD>Prepend <I>root</I> to the whole file name, if not
+ already rooted.
+
+ <TR><TD><CODE> :E=<I>value</I> </CODE>
+ <TD>Assign <I>value</I> to the variable if it is unset.
+
+ <TR><TD><CODE> :J=<I>joinval</I> </CODE>
+ <TD>Concatentate list elements into single
+ element, separated by <I>joinval</I>.
+
+ </TABLE>
+
+ <P>
+
+ On VMS, $(var:P) is the parent directory of $(var:D).
+
+<DT> <P> <H3> Built-in Variables </H3> <DD>
+
+ <P>
+
+ This section discusses variables that have special meaning to
+ <b>jam</b>.
+
+ <A NAME="search">
+ <P> <H4> SEARCH and LOCATE Variables </H4>
+ </A>
+
+ <P>
+
+ These two variables control the binding of file target names to
+ locations in the file system. Generally, $(SEARCH) is used to
+ find existing sources while $(LOCATE) is used to fix the location
+ for built targets.
+
+ <P>
+
+ Rooted (absolute path) file targets are bound as is. Unrooted
+ file target names are also normally bound as is, and thus relative
+ to the current directory, but the settings of $(LOCATE) and
+ $(SEARCH) alter this:
+
+ <P>
+
+ <UL>
+
+ <LI> If $(LOCATE) is set then the target is bound relative to
+ the first directory in $(LOCATE). Only the first element is
+ used for binding.
+
+ <LI> If $(SEARCH) is set then the target is bound to the first
+ directory in $(SEARCH) where the target file already exists.
+
+ <LI> If the $(SEARCH) search fails, the target is bound relative
+ to the current directory anyhow.
+
+ </UL>
+
+ <P>
+
+ Both $(SEARCH) and $(LOCATE) should be set target-specific and
+ not globally. If they were set globally, <b>jam</b> would use
+ the same paths for all file binding, which is not likely to
+ produce sane results. When writing your own rules, especially
+ ones not built upon those in Jambase, you may need to set
+ $(SEARCH) or $(LOCATE) directly. Almost all of the rules defined
+ in Jambase set $(SEARCH) and $(LOCATE) to sensible values for
+ sources they are looking for and targets they create, respectively.
+
+ <A NAME="hdrscan">
+ <P> <H4> HDRSCAN and HDRRULE Variables </H4>
+ </A>
+
+ <P>
+
+ These two variable control header file scanning. $(HDRSCAN) is
+ an <b>egrep</b>(1) pattern, with ()'s surrounding the file name,
+ used to find file inclusion statements in source files. Jambase
+ uses $(HDRPATTERN) as the pattern for $(HDRSCAN). $(HDRRULE)
+ is the name of a rule to invoke with the results of the scan:
+ the scanned file is the target, the found files are the sources.
+ This is the only place where <b>jam</b> invokes a rule through
+ a variable setting.
+
+ <P>
+
+ Both $(HDRSCAN) and $(HDRRULE) must be set for header file
+ scanning to take place, and they should be set target-specific
+ and not globally. If they were set globally, all files, including
+ executables and libraries, would be scanned for header file
+ include statements.
+
+ <P>
+
+ The scanning for header file inclusions is not exact, but it is
+ at least dynamic, so there is no need to run something like
+ <b>makedepend</b>(GNU) to create a static dependency file. The
+ scanning mechanism errs on the side of inclusion (i.e., it is
+ more likely to return filenames that are not actually used by
+ the compiler than to miss include files) because it can't tell
+ if #include lines are inside #ifdefs or other conditional logic.
+ In Jambase, HdrRule applies the NOCARE rule to each header file
+ found during scanning so that if the file isn't present yet
+ doesn't cause the compilation to fail, <b>jam</b> won't care.
+
+ <P>
+
+ Also, scanning for regular expressions only works where the
+ included file name is literally in the source file. It can't
+ handle languages that allow including files using variable names
+ (as the Jam language itself does).
+
+ <P> <H4> Platform Identifier Variables </H4>
+
+ <P>
+
+ A number of Jam built-in variables can be used to identify
+ runtime platform:
+
+ <P>
+
+ <TABLE WIDTH=75% ALIGN=CENTER>
+
+ <TR><TD>OS<TD>OS identifier string
+ <TR><TD>OSPLAT<TD>Underlying architecture, when applicable
+ <TR><TD>MAC<TD>true on MAC platform
+ <TR><TD>NT<TD>true on NT platform
+ <TR><TD>OS2<TD>true on OS2 platform
+ <TR><TD>UNIX<TD>true on Unix platforms
+ <TR><TD>VMS<TD>true on VMS platform
+
+ </TABLE>
+
+ <P> <H4> Jam Version Variables </H4>
+
+ <P>
+
+ <TABLE WIDTH=75% ALIGN=CENTER>
+
+ <TR><TD>JAMDATE<TD>Time and date at <b>jam</b> start-up.
+ <TR><TD>JAMUNAME<TD>Ouput of <b>uname</b>(1) command (Unix only)
+ <TR><TD>JAMVERSION<TD><b>jam</b> version, currently "2.3"
+
+ </TABLE>
+
+ <P> <H4> JAMSHELL Variable </H4>
+
+ <P>
+
+ When <b>jam</b> executes a rule's action block, it forks and
+ execs a shell, passing the action block as an argument to the
+ shell. The invocation of the shell can be controlled by
+ $(JAMSHELL). The default on Unix is, for example:
+
+ <P>
+
+ <CODE>JAMSHELL = /bin/sh -c % ;</CODE>
+
+ <P>
+
+ The % is replaced with the text of the action block.
+
+ <P>
+
+ <B>Jam</b> does not directly support building in parallel across
+ multiple hosts, since that is heavily dependent on the local
+ environment. To build in parallel across multiple hosts, you
+ need to write your own shell that provides access to the multiple
+ hosts. You then reset $(JAMSHELL) to reference it.
+
+ <P>
+
+ Just as <b>jam</b> expands a % to be the text of the rule's
+ action block, it expands a ! to be the multi-process slot number.
+ The slot number varies between 1 and the number of concurrent
+ jobs permitted by the -j flag given on the command line. Armed
+ with this, it is possible to write a multiple host shell. For
+ example:
+
+ <P>
+
+ <TABLE WIDTH=75% ALIGN=CENTER><TR><TD><CODE>
+
+ <BR>#!/bin/sh
+ <BR>
+ <BR># This sample JAMSHELL uses the SunOS on(1) command to execute a
+ <BR># command string with an identical environment on another host.
+ <BR>
+ <BR># Set JAMSHELL = jamshell ! %
+ <BR>#
+ <BR># where jamshell is the name of this shell file.
+ <BR>#
+ <BR># This version handles up to -j6; after that they get executed
+ <BR># locally.
+ <BR>
+ <BR>case $1 in
+ <BR>1|4) on winken sh -c "$2";;
+ <BR>2|5) on blinken sh -c "$2";;
+ <BR>3|6) on nod sh -c "$2";;
+ <BR>*) eval "$2";;
+ <BR>esac
+
+ </CODE></TABLE>
+
+
+<DT> <P> <H2> DIAGNOSTICS </H2> <DD>
+
+ <P>
+
+ In addition to generic error messages, <B>jam</B> may emit one of
+ the following:
+
+ <P><TABLE WIDTH=75% ALIGN=CENTER><TR><TD><DL>
+
+ <P><DT><CODE> warning: unknown rule X </CODE> <DD>
+
+ A rule was invoked that has not been defined with
+ an "actions" or "rule" statement.
+
+ <P><DT><CODE> using N temp target(s) </CODE> <DD>
+
+ Targets marked as being temporary (but nonetheless
+ present) have been found.
+
+ <P><DT><CODE> updating N target(s) </CODE> <DD>
+
+ Targets are out-of-date and will be updated.
+
+ <P><DT><CODE> can't find N target(s) </CODE> <DD>
+
+ Source files can't be found and there are no
+ actions to create them.
+
+ <P><DT><CODE> can't make N target(s) </CODE> <DD>
+
+ Due to sources not being found, other targets cannot be made.
+
+ <P><DT><CODE> warning: X depends on itself </CODE> <DD>
+
+ A target depends on itself either directly or
+ through its sources.
+
+ <P><DT><CODE> don't know how to make X </CODE> <DD>
+
+ A target is not present and no actions have been
+ defined to create it.
+
+ <P><DT><CODE> X skipped for lack of Y </CODE> <DD>
+
+ A source failed to build, and thus a target cannot
+ be built.
+
+ <P><DT><CODE> warning: using independent target X </CODE> <DD>
+
+ A target that is not a dependency of any other
+ target is being referenced with $(<) or $(>).
+
+ <P><DT><CODE> X removed </CODE> <DD>
+
+ <b>Jam</b> removed a partially built target after being
+ interrupted.
+
+ </DL></TABLE>
+
+<DT> <P> <H2> BUGS, LIMITATIONS </H2> <DD>
+
+ <P>
+
+ The -j flag can cause <B>jam</B> to get confused when single
+ actions update more than one target at a time. <B>jam</B> may
+ proceed as if the targets were built even though they are still
+ under construction.
+
+ <P>
+
+ For parallel building to be successful, the dependencies among
+ files must be properly spelled out, as targets tend to get built
+ in a quickest-first ordering. Also, beware of un-parallelizable
+ commands that drop fixed-named files into the current directory,
+ like <b>yacc</b>(1) does.
+
+ <P>
+
+ With the -j flag, errors from failed commands can get staggeringly
+ mixed up.
+
+ <P>
+
+ A poorly set $(JAMSHELL) is likely to result in silent failure.
+
+<DT> <P> <H2> SEE ALSO </H2> <DD>
+
+ <P>
+
+ <UL>
+
+ <LI> <a href="Jambase.html">Jambase Reference</a>
+
+ <LI> <a href="Jamfile.html">Using Jamfiles and Jambase</a>
+
+ </UL>
+
+ <P>
+
+ Jam documentation and source are available from the <A
+ HREF="http://public.perforce.com/public/index.html">Perforce
+ Public Depot</a>.
+
+<DT> <P> <H2> AUTHOR </H2> <DD>
+
+ <P>
+ Jam's author is Christopher Seiwald (<a
+ href="mailto:seiwald at perforce.com">seiwald at perforce.com</A>).
+ Documentation is provided by
+ <A HREF="http://www.perforce.com">Perforce Software, Inc.</A>
+
+</DL>
+
+<P> <HR>
+
+ <P>
+
+ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ <BR>
+ Comments to <A HREF="mailto:info at perforce.com">info at perforce.com</A>
+ <BR>
+ Last updated: April 1, 2002
+ <BR>
+ $Id: Jam.html,v 1.6 2003/09/01 08:04:33 vladimir_prus Exp $
+
+</BODY>
+</HTML>
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/Jambase
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/Jambase 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/Jambase 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2461 @@
+#
+# /+\
+# +\ Copyright 1993, 2000 Christopher Seiwald.
+# \+/
+#
+# This file is part of Jam - see jam.c for Copyright information.
+#
+
+# This file is ALSO:
+# Copyright 2001-2004 David Abrahams.
+# Copyright 2002-2004 Rene Rivera.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+if $(NT)
+{
+ SLASH ?= \\ ;
+}
+SLASH ?= / ;
+
+# Glob for patterns in the directories starting from the given
+# start directory, up to and including the root of the file-system.
+# We stop globbing as soon as we find at least one match.
+#
+rule find-to-root ( dir : patterns + )
+{
+ local globs = [ GLOB $(dir) : $(patterns) ] ;
+ while ! $(globs) && $(dir:P) != $(dir)
+ {
+ dir = $(dir:P) ;
+ globs = [ GLOB $(dir) : $(patterns) ] ;
+ }
+ return $(globs) ;
+}
+
+# This global will hold the location of the user's boost-build.jam file.
+.boost-build-file = ;
+
+# This global will hold the location of the build system bootstrap file.
+.bootstrap-file = ;
+
+# Remember the value of $(BOOST_BUILD_PATH) supplied to us by the user.
+BOOST_BUILD_PATH.user-value = $(BOOST_BUILD_PATH) ;
+
+# On Unix only, when BOOST_BUILD_PATH is not supplied by user, put
+# sensible default value. This allowes Boost.Build to work without
+# any environment variables, which is good in itself and also
+# required by Debian Policy.
+if ! $(BOOST_BUILD_PATH) && $(UNIX)
+{
+ BOOST_BUILD_PATH = /usr/share/boost-build ;
+}
+
+
+
+# This rule can be invoked from an optional user's boost-build.jam
+# file to both indicate where to find the build system files, and to
+# load them. The path indicated is relative to the location of the
+# boost-build.jam file.
+#
+rule boost-build ( dir ? )
+{
+ if $(.bootstrap-file)
+ {
+ EXIT "Error: Illegal attempt to re-bootstrap the build system by invoking" ;
+ ECHO ;
+ ECHO " 'boost-build" $(dir) ";'" ;
+ ECHO ;
+ EXIT "Please consult the documentation at 'http://www.boost.org'." ;
+ }
+
+ # Add the given directory to the path so we can find the build
+ # system. If dir is empty, has no effect.
+ #
+ BOOST_BUILD_PATH = $(dir:R=$(.boost-build-file:D)) $(BOOST_BUILD_PATH) ;
+
+ # Try to find the build system bootstrap file 'bootstrap.jam'.
+ #
+ local bootstrap-file =
+ [ GLOB $(BOOST_BUILD_PATH) : bootstrap.jam ] ;
+ .bootstrap-file = $(bootstrap-file[1]) ;
+
+ # There is no boost-build.jam we can find, exit with an error
+ #
+ if ! $(.bootstrap-file)
+ {
+ ECHO "Unable to load Boost.Build: could not find build system." ;
+ ECHO --------------------------------------------------------- ;
+ ECHO "$(.boost-build-file) attempted to load the build system by invoking" ;
+ ECHO ;
+ ECHO " 'boost-build" $(dir) ";'" ;
+ ECHO ;
+ ECHO "but we were unable to find \"bootstrap.jam\" in the specified directory" ;
+ ECHO "or in BOOST_BUILD_PATH (searching "$(BOOST_BUILD_PATH:J=", ")")." ;
+ ECHO ;
+ EXIT "Please consult the documentation at 'http://www.boost.org'." ;
+ }
+
+ if [ MATCH .*(--debug-configuration).* : $(ARGV) ]
+ {
+ ECHO "notice: loading Boost.Build from"
+ [ NORMALIZE_PATH $(.bootstrap-file:D) ] ;
+ }
+
+
+ # Load the build system, now that we know where to start from.
+ #
+ include $(.bootstrap-file) ;
+}
+
+
+if [ MATCH .*(bjam).* : $(ARGV[1]:BL) ]
+ || $(BOOST_ROOT) # A temporary measure so Jam works with Boost.Build v1
+{
+ # We attempt to load "boost-build.jam" by searching from the current invocation directory
+ # up to the root of the file-system.
+ #
+ # boost-build.jam is expected to invoke the "boost-build" rule to
+ # load the Boost.Build files.
+
+ local search-path = $(BOOST_BUILD_PATH) $(BOOST_ROOT) ;
+
+ local boost-build-files =
+ [ find-to-root [ PWD ] : boost-build.jam ]
+ # Another temporary measure so Jam works with Boost.Build v1
+ [ GLOB $(search-path) : boost-build.jam ] ;
+
+ .boost-build-file = $(boost-build-files[1]) ;
+
+ if [ MATCH .*(--debug-configuration).* : $(ARGV) ]
+ {
+ ECHO "notice: found boost-build.jam at"
+ [ NORMALIZE_PATH $(.boost-build-file) ] ;
+ }
+
+ # There is no boost-build.jam we can find, exit with an error, and information.
+ #
+ if ! $(.boost-build-file)
+ {
+ ECHO "Unable to load Boost.Build: could not find \"boost-build.jam\"" ;
+ ECHO --------------------------------------------------------------- ;
+
+ if ! [ MATCH .*(bjam).* : $(ARGV[1]:BL) ]
+ {
+ ECHO "BOOST_ROOT must be set, either in the environment, or " ;
+ ECHO "on the command-line with -sBOOST_ROOT=..., to the root" ;
+ ECHO "of the boost installation." ;
+ ECHO ;
+ }
+
+ ECHO "Attempted search from" [ PWD ] "up to the root" ;
+ ECHO "and in these directories from BOOST_BUILD_PATH and BOOST_ROOT: "$(search-path:J=", ")"." ;
+ EXIT "Please consult the documentation at 'http://www.boost.org'." ;
+ }
+
+ # Now load the boost-build.jam to get the build system loaded. This
+ # incidentaly loads the users jamfile and attempts to build targets.
+ #
+ # We also set it up so we can tell wether we are loading the new V2
+ # system or the the old V1 system.
+ #
+ include $(.boost-build-file) ;
+
+ # Check that, at minimum, the bootstrap file was found.
+ #
+ if ! $(.bootstrap-file)
+ {
+ ECHO "Unable to load Boost.Build" ;
+ ECHO -------------------------- ;
+ ECHO "\"$(.boost-build-file)\" was found by searching from" [ PWD ] "up to the root" ;
+ ECHO "and in these directories from BOOST_BUILD_PATH and BOOST_ROOT: "$(search-path:J=", ")"." ;
+ ECHO ;
+ ECHO "However, it failed to call the \"boost-build\" rule to indicate" ;
+ ECHO "the location of the build system." ;
+ ECHO ;
+ EXIT "Please consult the documentation at 'http://www.boost.org'." ;
+ }
+}
+else
+{
+
+#
+# JAMBASE - jam 2.3 ruleset providing make(1)-like functionality
+#
+# Supports UNIX, NT, and VMS.
+#
+# 12/27/93 (seiwald) - purturb library sources with SOURCE_GRIST
+# 04/18/94 (seiwald) - use '?=' when setting OS specific vars
+# 04/21/94 (seiwald) - do RmTemps together
+# 05/05/94 (seiwald) - all supported C compilers support -o: relegate
+# RELOCATE as an option; set Ranlib to "" to disable it
+# 06/01/94 (seiwald) - new 'actions existing' to do existing sources
+# 08/25/94 (seiwald) - new ObjectCcFlags rule to append to per-target CCFLAGS
+# 08/29/94 (seiwald) - new ObjectHdrs rule to append to per-target HDRS
+# 09/19/94 (seiwald) - LinkLibraries and Undefs now append
+# - Rule names downshifted.
+# 10/06/94 (seiwald) - Dumb yyacc stuff moved into Jamfile.
+# 10/14/94 (seiwald) - (Crude) support for .s, .C, .cc, .cpp, and .f files.
+# 01/08/95 (seiwald) - Shell now handled with awk, not sed
+# 01/09/95 (seiwald) - Install* now take dest directory as target
+# 01/10/95 (seiwald) - All entries sorted.
+# 01/10/95 (seiwald) - NT support moved in, with LauraW's help.
+# 01/10/95 (seiwald) - VMS support moved in.
+# 02/06/95 (seiwald) - ObjectC++Flags and SubDirC++Flags added.
+# 02/07/95 (seiwald) - Iron out when HDRSEARCH uses "" or SEARCH_SOURCE.
+# 02/08/95 (seiwald) - SubDir works on VMS.
+# 02/14/95 (seiwald) - MkDir and entourage.
+# 04/30/95 (seiwald) - Use install -c flag so that it copies, not moves.
+# 07/10/95 (taylor) - Support for Microsoft C++.
+# 11/21/96 (peterk) - Support for BeOS
+# 07/19/99 (sickel) - Support for Mac OS X Server (and maybe client)
+# 02/18/00 (belmonte)- Support for Cygwin.
+
+# Special targets defined in this file:
+#
+# all - parent of first, shell, files, lib, exe
+# first - first dependent of 'all', for potential initialization
+# shell - parent of all Shell targets
+# files - parent of all File targets
+# lib - parent of all Library targets
+# exe - parent of all Main targets
+# dirs - parent of all MkDir targets
+# clean - removes all Shell, File, Library, and Main targets
+# uninstall - removes all Install targets
+#
+
+# Rules defined by this file:
+#
+# as obj.o : source.s ; .s -> .o
+# Bulk dir : files ; populate directory with many files
+# Cc obj.o : source.c ; .c -> .o
+# C++ obj.o : source.cc ; .cc -> .o
+# Clean clean : sources ; remove sources with 'jam clean'
+# File dest : source ; copy file
+# Fortran obj.o : source.f ; .f -> .o
+# GenFile source.c : program args ; make custom file
+# Hardlink target : source ; make link from source to target
+# HdrRule source : headers ; handle #includes
+# InstallInto dir : sources ; install any files
+# InstallBin dir : sources ; install binaries
+# InstallLib dir : sources ; install files
+# InstallFile dir : sources ; install files
+# InstallMan dir : sources ; install man pages
+# InstallShell dir : sources ; install shell scripts
+# Lex source.c : source.l ; .l -> .c
+# Library lib : source ; archive library from compiled sources
+# LibraryFromObjects lib : objects ; archive library from objects
+# LinkLibraries images : libraries ; bag libraries onto Mains
+# Main image : source ; link executable from compiled sources
+# MainFromObjects image : objects ; link executable from objects
+# MkDir dir ; make a directory, if not there
+# Object object : source ; compile object from source
+# ObjectCcFlags source : flags ; add compiler flags for object
+# ObjectC++Flags source : flags ; add compiler flags for object
+# ObjectHdrs source : dirs ; add include directories for object
+# Objects sources ; compile sources
+# RmTemps target : sources ; remove temp sources after target made
+# Setuid images ; mark executables Setuid
+# SubDir TOP d1 d2 ... ; start a subdirectory Jamfile
+# SubDirCcFlags flags ; add compiler flags until next SubDir
+# SubDirC++Flags flags ; add compiler flags until next SubDir
+# SubDirHdrs dirs ; add include dirs until next SubDir
+# SubInclude TOP d1 d2 ... ; include a subdirectory Jamfile
+# Shell exe : source ; make a shell executable
+# Undefines images : symbols ; save undef's for linking
+# UserObject object : source ; handle unknown suffixes for Object
+# Yacc source.c : source.y ; .y -> .c
+#
+# Utility rules that have no side effects (not supported):
+#
+# FAppendSuffix f1 f2 ... : $(SUF) ; return $(<) with suffixes
+# FConcat value ... ; return contatenated values
+# FDirName d1 d2 ... ; return path from root to dir
+# FGrist d1 d2 ... ; return d1!d2!...
+# FGristFiles value ; return $(value:G=$(SOURCE_GRIST))
+# FGristSourceFiles value ; return $(value:G=$(SOURCE_GRIST))
+# FRelPath d1 : d2 ; return rel path from d1 to d2
+# FSubDir d1 d2 ... ; return path to root
+#
+
+
+# Brief review of the jam language:
+#
+# Statements:
+# rule RULE - statements to process a rule
+# actions RULE - system commands to carry out target update
+#
+# Modifiers on actions:
+# together - multiple instances of same rule on target get executed
+# once with their sources ($(>)) concatenated
+# updated - refers to updated sources ($(>)) only
+# ignore - ignore return status of command
+# quietly - don't trace its execution unless verbose
+# piecemeal - iterate command each time with a small subset of $(>)
+# existing - refers to currently existing sources ($(>)) only
+# bind vars - subject to binding before expanding in actions
+#
+# Special rules:
+# ALWAYS - always build a target
+# DEPENDS - builds the dependency graph
+# ECHO - blurt out targets on stdout
+# EXIT - blurt out targets and exit
+# INCLUDES - marks sources as headers for target (a codependency)
+# NOCARE - don't panic if the target can't be built
+# NOUPDATE - create the target if needed but never update it
+# NOTFILE - ignore the timestamp of the target (it's not a file)
+# TEMPORARY - target need not be present if sources haven't changed
+#
+# Special variables set by jam:
+# $(<) - targets of a rule (to the left of the :)
+# $(>) - sources of a rule (to the right of the :)
+# $(xxx) - true on xxx (UNIX, VMS, NT, OS2, MAC)
+# $(OS) - name of OS - varies wildly
+# $(JAMVERSION) - version number (2.3)
+#
+# Special variables used by jam:
+# SEARCH - where to find something (used during binding and actions)
+# LOCATE - where to plop something not found with SEARCH
+# HDRRULE - rule to call to handle include files
+# HDRSCAN - egrep regex to extract include files
+#
+# Special targets:
+# all - default if none given on command line
+#
+
+# Initialize variables
+#
+
+#
+# OS specific variable settings
+#
+if $(NT)
+{
+ # the list of supported toolsets on Windows NT and Windows 95/98
+ #
+ local SUPPORTED_TOOLSETS = "BORLANDC" "VC7" "VISUALC" "VISUALC16" "INTELC" "WATCOM"
+ "MINGW" "LCC" ;
+
+ # this variable holds the current toolset
+ #
+ TOOLSET = "" ;
+
+ # if the JAM_TOOLSET environment variable is defined, check that it is
+ # one of our supported values
+ #
+ if $(JAM_TOOLSET)
+ {
+ local t ;
+
+ for t in $(SUPPORTED_TOOLSETS)
+ {
+ $(t) = $($(t):J=" ") ; # reconstitute paths with spaces in them
+ if $(t) = $(JAM_TOOLSET) { TOOLSET = $(t) ; }
+ }
+
+ if ! $(TOOLSET)
+ {
+ ECHO "The JAM_TOOLSET environment variable is defined but its value" ;
+ ECHO "is invalid, please use one of the following:" ;
+ ECHO ;
+
+ for t in $(SUPPORTED_TOOLSETS) { ECHO " " $(t) ; }
+ EXIT ;
+ }
+ }
+
+ # if TOOLSET is empty, we'll try to detect the toolset from other
+ # environment variables to remain backwards compatible with Jam 2.3
+ #
+ if ! $(TOOLSET)
+ {
+ if $(BCCROOT)
+ {
+ TOOLSET = BORLANDC ;
+ BORLANDC = $(BCCROOT:J=" ") ;
+ }
+ else if $(MSVC)
+ {
+ TOOLSET = VISUALC16 ;
+ VISUALC16 = $(MSVC:J=" ") ;
+ }
+ else if $(MSVCNT)
+ {
+ TOOLSET = VISUALC ;
+ VISUALC = $(MSVCNT:J=" ") ;
+ }
+ else if $(MSVCDir)
+ {
+ TOOLSET = VISUALC ;
+ VISUALC = $(MSVCDir:J=" ") ;
+ }
+ else if $(MINGW)
+ {
+ TOOLSET = MINGW ;
+ }
+ else
+ {
+ ECHO "Jam cannot be run because, either:" ;
+ ECHO " a. You didn't set BOOST_ROOT to indicate the root of your" ;
+ ECHO " Boost installation." ;
+ ECHO " b. You are trying to use stock Jam but didn't indicate which" ;
+ ECHO " compilation toolset to use. To do so, follow these simple" ;
+ ECHO " instructions:" ;
+ ECHO ;
+ ECHO " - define one of the following environment variable, with the" ;
+ ECHO " appropriate value according to this list:" ;
+ ECHO ;
+ ECHO " Variable Toolset Description" ;
+ ECHO ;
+ ECHO " BORLANDC Borland C++ BC++ install path" ;
+ ECHO " VISUALC Microsoft Visual C++ VC++ install path" ;
+ ECHO " VISUALC16 Microsoft Visual C++ 16 bit VC++ 16 bit install" ;
+ ECHO " INTELC Intel C/C++ IC++ install path" ;
+ ECHO " WATCOM Watcom C/C++ Watcom install path" ;
+ ECHO " MINGW MinGW (gcc) MinGW install path" ;
+ ECHO " LCC Win32-LCC LCC-Win32 install path" ;
+ ECHO ;
+ ECHO " - define the JAM_TOOLSET environment variable with the *name*" ;
+ ECHO " of the toolset variable you want to use." ;
+ ECHO ;
+ ECHO " e.g.: set VISUALC=C:\\Visual6" ;
+ ECHO " set JAM_TOOLSET=VISUALC" ;
+ EXIT ;
+ }
+ }
+
+ CP ?= copy ;
+ RM ?= del /f/q ;
+ SLASH ?= \\ ;
+ SUFLIB ?= .lib ;
+ SUFOBJ ?= .obj ;
+ SUFEXE ?= .exe ;
+
+ if $(TOOLSET) = BORLANDC
+ {
+ ECHO "Compiler is Borland C++" ;
+
+ AR ?= tlib /C /P64 ;
+ CC ?= bcc32 ;
+ CCFLAGS ?= -q -y -d -v -w-par -w-ccc -w-rch -w-pro -w-aus ;
+ C++ ?= bcc32 ;
+ C++FLAGS ?= -q -y -d -v -w-par -w-ccc -w-rch -w-pro -w-aus -P ;
+ LINK ?= $(CC) ;
+ LINKFLAGS ?= $(CCFLAGS) ;
+ STDLIBPATH ?= $(BORLANDC)\\lib ;
+ STDHDRS ?= $(BORLANDC)\\include ;
+ NOARSCAN ?= true ;
+ }
+ else if $(TOOLSET) = VISUALC16
+ {
+ ECHO "Compiler is Microsoft Visual C++ 16 bit" ;
+
+ AR ?= lib /nologo ;
+ CC ?= cl /nologo ;
+ CCFLAGS ?= /D \"WIN\" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= $(CC) ;
+ LINKFLAGS ?= $(CCFLAGS) ;
+ LINKLIBS ?=
+ \"$(VISUALC16)\\lib\\mlibce.lib\"
+ \"$(VISUALC16)\\lib\\oldnames.lib\"
+ ;
+ LINKLIBS ?= ;
+ NOARSCAN ?= true ;
+ OPTIM ?= "" ;
+ STDHDRS ?= $(VISUALC16)\\include ;
+ UNDEFFLAG ?= "/u _" ;
+ }
+ else if $(TOOLSET) = VISUALC
+ {
+ ECHO "Compiler is Microsoft Visual C++" ;
+
+ AR ?= lib ;
+ AS ?= masm386 ;
+ CC ?= cl /nologo ;
+ CCFLAGS ?= "" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= link /nologo ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= \"$(VISUALC)\\lib\\advapi32.lib\"
+ # $(VISUALC)\\lib\\libc.lib
+ # $(VISUALC)\\lib\\oldnames.lib
+ \"$(VISUALC)\\lib\\gdi32.lib\"
+ \"$(VISUALC)\\lib\\user32.lib\"
+ \"$(VISUALC)\\lib\\kernel32.lib\" ;
+ OPTIM ?= "" ;
+ STDHDRS ?= $(VISUALC)\\include ;
+ UNDEFFLAG ?= "/u _" ;
+ }
+ else if $(TOOLSET) = VC7
+ {
+ ECHO "Compiler is Microsoft Visual C++ .NET" ;
+
+ AR ?= lib ;
+ AS ?= masm386 ;
+ CC ?= cl /nologo ;
+ CCFLAGS ?= "" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= link /nologo ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= \"$(VISUALC)\\PlatformSDK\\lib\\advapi32.lib\"
+ # $(VISUALC)\\lib\\libc.lib
+ # $(VISUALC)\\lib\\oldnames.lib
+ \"$(VISUALC)\\PlatformSDK\\lib\\gdi32.lib\"
+ \"$(VISUALC)\\PlatformSDK\\lib\\user32.lib\"
+ \"$(VISUALC)\\PlatformSDK\\lib\\kernel32.lib\" ;
+ OPTIM ?= "" ;
+ STDHDRS ?= \"$(VISUALC)\\include\"
+ \"$(VISUALC)\\PlatformSDK\\include\" ;
+ UNDEFFLAG ?= "/u _" ;
+ }
+ else if $(TOOLSET) = INTELC
+ {
+ ECHO "Compiler is Intel C/C++" ;
+
+ if ! $(VISUALC)
+ {
+ ECHO "As a special exception, when using the Intel C++ compiler, you need" ;
+ ECHO "to define the VISUALC environment variable to indicate the location" ;
+ ECHO "of your Visual C++ installation. Aborting.." ;
+ EXIT ;
+ }
+
+ AR ?= lib ;
+ AS ?= masm386 ;
+ CC ?= icl /nologo ;
+ CCFLAGS ?= "" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= link /nologo ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= $(VISUALC)\\lib\\advapi32.lib
+ # $(VISUALC)\\lib\\libc.lib
+ # $(VISUALC)\\lib\\oldnames.lib
+ $(VISUALC)\\lib\\kernel32.lib
+ ;
+ OPTIM ?= "" ;
+ STDHDRS ?= $(INTELC)\include $(VISUALC)\\include ;
+ UNDEFFLAG ?= "/u _" ;
+ }
+ else if $(TOOLSET) = WATCOM
+ {
+ ECHO "Compiler is Watcom C/C++" ;
+
+ AR ?= wlib ;
+ CC ?= wcc386 ;
+ CCFLAGS ?= /zq /DWIN32 /I$(WATCOM)\\h ; # zq=quiet
+ C++ ?= wpp386 ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ CP ?= copy ;
+ DOT ?= . ;
+ DOTDOT ?= .. ;
+ LINK ?= wcl386 ;
+ LINKFLAGS ?= /zq ; # zq=quiet
+ LINKLIBS ?= ;
+ MV ?= move ;
+ NOARSCAN ?= true ;
+ OPTIM ?= ;
+ RM ?= del /f ;
+ SLASH ?= \\ ;
+ STDHDRS ?= $(WATCOM)\\h $(WATCOM)\\h\\nt ;
+ SUFEXE ?= .exe ;
+ SUFLIB ?= .lib ;
+ SUFOBJ ?= .obj ;
+ UNDEFFLAG ?= "/u _" ;
+ }
+ else if $(TOOLSET) = MINGW
+ {
+ ECHO "Compiler is GCC with Mingw" ;
+
+ AR ?= ar -ru ;
+ CC ?= gcc ;
+ CCFLAGS ?= "" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= $(CC) ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= "" ;
+ OPTIM ?= ;
+ SUFOBJ = .o ;
+ SUFLIB = .a ;
+ SLASH = / ;
+# NOARSCAN ?= true ;
+ }
+ else if $(TOOLSET) = LCC
+ {
+ ECHO "Compiler is Win32-LCC" ;
+
+ AR ?= lcclib ;
+ CC ?= lcc ;
+ CCFLAGS ?= "" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= lcclnk ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= "" ;
+ OPTIM ?= ;
+ NOARSCAN = true ;
+ }
+ else
+ {
+#
+# XXX: We need better comments here !!
+#
+ EXIT On NT, set BCCROOT, MSVCNT, MINGW or MSVC to the root of the
+ Borland or Microsoft directories. ;
+ }
+
+}
+else if $(OS2)
+{
+ # the list of supported toolsets on Windows NT and Windows 95/98
+ #
+ local SUPPORTED_TOOLSETS = "EMX" "WATCOM" ;
+
+ # this variable holds the current toolset
+ #
+ TOOLSET = "" ;
+
+ # if the JAM_TOOLSET environment variable is defined, check that it is
+ # one of our supported values
+ #
+ if $(JAM_TOOLSET)
+ {
+ local t ;
+
+ for t in $(SUPPORTED_TOOLSETS)
+ {
+ $(t) = $($(t):J=" ") ; # reconstitute paths with spaces in them
+ if $(t) = $(JAM_TOOLSET) { TOOLSET = $(t) ; }
+ }
+
+ if ! $(TOOLSET)
+ {
+ ECHO "The JAM_TOOLSET environment variable is defined but its value" ;
+ ECHO "is invalid, please use one of the following:" ;
+ ECHO ;
+
+ for t in $(SUPPORTED_TOOLSETS) { ECHO " " $(t) ; }
+ EXIT ;
+ }
+ }
+
+ # if TOOLSET is empty, we'll try to detect the toolset from other
+ # environment variables to remain backwards compatible with Jam 2.3
+ #
+ if ! $(TOOLSET)
+ {
+ if $(watcom)
+ {
+ WATCOM = $(watcom:J=" ") ;
+ TOOLSET = WATCOM ;
+ }
+ else
+ {
+ ECHO "Jam cannot be run because you didn't indicate which compilation toolset" ;
+ ECHO "to use. To do so, follow these simple instructions:" ;
+ ECHO ;
+ ECHO " - define one of the following environment variable, with the" ;
+ ECHO " appropriate value according to this list:" ;
+ ECHO ;
+ ECHO " Variable Toolset Description" ;
+ ECHO ;
+ ECHO " WATCOM Watcom C/C++ Watcom install path" ;
+ ECHO " EMX EMX (gcc) EMX install path" ;
+ ECHO " VISUALAGE IBM Visual Age C/C++ VisualAge install path" ;
+ ECHO ;
+ ECHO " - define the JAM_TOOLSET environment variable with the *name*" ;
+ ECHO " of the toolset variable you want to use." ;
+ ECHO ;
+ ECHO " e.g.: set WATCOM=C:\WATCOM" ;
+ ECHO " set JAM_TOOLSET=WATCOM" ;
+ ECHO ;
+ EXIT ;
+ }
+ }
+
+ RM = del /f ;
+ CP = copy ;
+ MV ?= move ;
+ DOT ?= . ;
+ DOTDOT ?= .. ;
+ SUFLIB ?= .lib ;
+ SUFOBJ ?= .obj ;
+ SUFEXE ?= .exe ;
+
+ if $(TOOLSET) = WATCOM
+ {
+ AR ?= wlib ;
+ BINDIR ?= \\os2\\apps ;
+ CC ?= wcc386 ;
+ CCFLAGS ?= /zq /DOS2 /I$(WATCOM)\\h ; # zq=quiet
+ C++ ?= wpp386 ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= wcl386 ;
+ LINKFLAGS ?= /zq ; # zq=quiet
+ LINKLIBS ?= ;
+ NOARSCAN ?= true ;
+ OPTIM ?= ;
+ SLASH ?= \\ ;
+ STDHDRS ?= $(WATCOM)\\h ;
+ UNDEFFLAG ?= "/u _" ;
+ }
+ else if $(TOOLSET) = EMX
+ {
+ ECHO "Compiler is GCC-EMX" ;
+ AR ?= ar -ru ;
+ CC ?= gcc ;
+ CCFLAGS ?= "" ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ LINK ?= $(CC) ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= "" ;
+ OPTIM ?= ;
+ SUFOBJ = .o ;
+ SUFLIB = .a ;
+ UNDEFFLAG ?= "-U" ;
+ SLASH = / ;
+# NOARSCAN ?= true ;
+ }
+ else
+ {
+ # should never happen
+ EXIT "Sorry, but the $(JAM_TOOLSET) toolset isn't supported for now" ;
+ }
+}
+else if $(VMS)
+{
+ C++ ?= cxx ;
+ C++FLAGS ?= ;
+ CC ?= cc ;
+ CCFLAGS ?= ;
+ CHMOD ?= set file/prot= ;
+ CP ?= copy/replace ;
+ CRELIB ?= true ;
+ DOT ?= [] ;
+ DOTDOT ?= [-] ;
+ EXEMODE ?= (w:e) ;
+ FILEMODE ?= (w:r) ;
+ HDRS ?= ;
+ LINK ?= link ;
+ LINKFLAGS ?= "" ;
+ LINKLIBS ?= ;
+ MKDIR ?= create/dir ;
+ MV ?= rename ;
+ OPTIM ?= "" ;
+ RM ?= delete ;
+ RUNVMS ?= mcr ;
+ SHELLMODE ?= (w:er) ;
+ SLASH ?= . ;
+ STDHDRS ?= decc$library_include ;
+ SUFEXE ?= .exe ;
+ SUFLIB ?= .olb ;
+ SUFOBJ ?= .obj ;
+
+ switch $(OS)
+ {
+ case OPENVMS : CCFLAGS ?= /stand=vaxc ;
+ case VMS : LINKLIBS ?= sys$library:vaxcrtl.olb/lib ;
+ }
+}
+else if $(MAC)
+{
+ local OPT ;
+
+ CW ?= "{CW}" ;
+
+ MACHDRS ?=
+ "$(UMACHDRS):Universal:Interfaces:CIncludes"
+ "$(CW):MSL:MSL_C:MSL_Common:Include"
+ "$(CW):MSL:MSL_C:MSL_MacOS:Include" ;
+
+ MACLIBS ?=
+ "$(CW):MacOS Support:Universal:Libraries:StubLibraries:Interfacelib"
+ "$(CW):MacOS Support:Universal:Libraries:StubLibraries:Mathlib" ;
+
+ MPWLIBS ?=
+ "$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib"
+ "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW.Lib" ;
+
+ MPWNLLIBS ?=
+ "$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib"
+ "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW(NL).Lib" ;
+
+ SIOUXHDRS ?= ;
+
+ SIOUXLIBS ?=
+ "$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL RuntimePPC.lib"
+ "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL SIOUX.PPC.Lib"
+ "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC.Lib" ;
+
+ C++ ?= mwcppc ;
+ C++FLAGS ?= -w off -nomapcr ;
+ CC ?= mwcppc ;
+ CCFLAGS ?= -w off -nomapcr ;
+ CP ?= duplicate -y ;
+ DOT ?= ":" ;
+ DOTDOT ?= "::" ;
+ HDRS ?= $(MACHDRS) $(MPWHDRS) ;
+ LINK ?= mwlinkppc ;
+ LINKFLAGS ?= -mpwtool -warn ;
+ LINKLIBS ?= $(MACLIBS) $(MPWLIBS) ;
+ MKDIR ?= newfolder ;
+ MV ?= rename -y ;
+ NOARSCAN ?= true ;
+ OPTIM ?= ;
+ RM ?= delete -y ;
+ SLASH ?= ":" ;
+ STDHDRS ?= ;
+ SUFLIB ?= .lib ;
+ SUFOBJ ?= .o ;
+}
+else if $(OS) = BEOS && $(METROWERKS)
+{
+ AR ?= mwld -xml -o ;
+ BINDIR ?= /boot/apps ;
+ CC ?= mwcc ;
+ CCFLAGS ?= -nosyspath ;
+ C++ ?= $(CC) ;
+ C++FLAGS ?= -nosyspath ;
+ FORTRAN ?= "" ;
+ LIBDIR ?= /boot/develop/libraries ;
+ LINK ?= mwld ;
+ LINKFLAGS ?= "" ;
+ MANDIR ?= /boot/documentation/"Shell Tools"/HTML ;
+ NOARSCAN ?= true ;
+ STDHDRS ?= /boot/develop/headers/posix ;
+}
+else if $(OS) = BEOS
+{
+ BINDIR ?= /boot/apps ;
+ CC ?= gcc ;
+ C++ ?= $(CC) ;
+ FORTRAN ?= "" ;
+ LIBDIR ?= /boot/develop/libraries ;
+ LINK ?= gcc ;
+ LINKLIBS ?= -lnet ;
+ NOARSCAN ?= true ;
+ STDHDRS ?= /boot/develop/headers/posix ;
+}
+else if $(UNIX)
+{
+ switch $(OS)
+ {
+ case AIX :
+ LINKLIBS ?= -lbsd ;
+
+ case AMIGA :
+ CC ?= gcc ;
+ YACC ?= "bison -y" ;
+
+ case CYGWIN :
+ CC ?= gcc ;
+ CCFLAGS += -D__cygwin__ ;
+ LEX ?= flex ;
+ RANLIB ?= "" ;
+ SUFEXE ?= .exe ;
+ YACC ?= "bison -y" ;
+
+ case DGUX :
+ RANLIB ?= "" ;
+ RELOCATE ?= true ;
+
+ case HPUX :
+ YACC = ;
+ CFLAGS += -Ae ;
+ CCFLAGS += -Ae ;
+ RANLIB ?= "" ;
+
+ case INTERIX :
+ CC ?= gcc ;
+ RANLIB ?= "" ;
+
+ case IRIX :
+ RANLIB ?= "" ;
+
+ case MPEIX :
+ CC ?= gcc ;
+ C++ ?= gcc ;
+ CCFLAGS += -D_POSIX_SOURCE ;
+ HDRS += /usr/include ;
+ RANLIB ?= "" ;
+ NOARSCAN ?= true ;
+ NOARUPDATE ?= true ;
+
+ case MVS :
+ RANLIB ?= "" ;
+
+ case NEXT :
+ AR ?= libtool -o ;
+ RANLIB ?= "" ;
+
+ case MACOSX :
+ AR ?= libtool -o ;
+ C++ ?= c++ ;
+ MANDIR ?= /usr/local/share/man ;
+ RANLIB ?= "" ;
+
+ case NCR :
+ RANLIB ?= "" ;
+
+ case PTX :
+ RANLIB ?= "" ;
+
+ case QNX :
+ AR ?= wlib ;
+ CC ?= cc ;
+ CCFLAGS ?= -Q ; # quiet
+ C++ ?= $(CC) ;
+ C++FLAGS ?= -Q ; # quiet
+ LINK ?= $(CC) ;
+ LINKFLAGS ?= -Q ; # quiet
+ NOARSCAN ?= true ;
+ RANLIB ?= "" ;
+
+ case SCO :
+ RANLIB ?= "" ;
+ RELOCATE ?= true ;
+
+ case SINIX :
+ RANLIB ?= "" ;
+
+ case SOLARIS :
+ RANLIB ?= "" ;
+ AR ?= "/usr/ccs/bin/ar ru" ;
+
+ case UNICOS :
+ NOARSCAN ?= true ;
+ OPTIM ?= -O0 ;
+
+ case UNIXWARE :
+ RANLIB ?= "" ;
+ RELOCATE ?= true ;
+ }
+
+ # UNIX defaults
+
+ CCFLAGS ?= ;
+ C++FLAGS ?= $(CCFLAGS) ;
+ CHMOD ?= chmod ;
+ CHGRP ?= chgrp ;
+ CHOWN ?= chown ;
+ LEX ?= lex ;
+ LINKFLAGS ?= $(CCFLAGS) ;
+ LINKLIBS ?= ;
+ OPTIM ?= -O ;
+ RANLIB ?= ranlib ;
+ YACC ?= yacc ;
+ YACCFILES ?= y.tab ;
+ YACCFLAGS ?= -d ;
+}
+
+#
+# General defaults; a lot like UNIX
+#
+
+ AR ?= ar ru ;
+ AS ?= as ;
+ ASFLAGS ?= ;
+ AWK ?= awk ;
+ BINDIR ?= /usr/local/bin ;
+ C++ ?= cc ;
+ C++FLAGS ?= ;
+ CC ?= cc ;
+ CCFLAGS ?= ;
+ CP ?= cp -f ;
+ CRELIB ?= ;
+ DOT ?= . ;
+ DOTDOT ?= .. ;
+ EXEMODE ?= 711 ;
+ FILEMODE ?= 644 ;
+ FORTRAN ?= f77 ;
+ FORTRANFLAGS ?= ;
+ HDRS ?= ;
+ INSTALLGRIST ?= installed ;
+ JAMFILE ?= Jamfile ;
+ JAMRULES ?= Jamrules ;
+ LEX ?= ;
+ LIBDIR ?= /usr/local/lib ;
+ LINK ?= $(CC) ;
+ LINKFLAGS ?= ;
+ LINKLIBS ?= ;
+ LN ?= ln ;
+ MANDIR ?= /usr/local/man ;
+ MKDIR ?= mkdir ;
+ MV ?= mv -f ;
+ OPTIM ?= ;
+ RCP ?= rcp ;
+ RM ?= rm -f ;
+ RSH ?= rsh ;
+ SED ?= sed ;
+ SHELLHEADER ?= "#!/bin/sh" ;
+ SHELLMODE ?= 755 ;
+ SLASH ?= / ;
+ STDHDRS ?= /usr/include ;
+ SUFEXE ?= "" ;
+ SUFLIB ?= .a ;
+ SUFOBJ ?= .o ;
+ UNDEFFLAG ?= "-u _" ;
+ YACC ?= ;
+ YACCFILES ?= ;
+ YACCFLAGS ?= ;
+
+ HDRPATTERN =
+ "^[ ]*#[ ]*include[ ]*[<\"]([^\">]*)[\">].*$" ;
+
+ OSFULL = $(OS)$(OSVER)$(OSPLAT) $(OS)$(OSPLAT) $(OS)$(OSVER) $(OS) ;
+
+
+#
+# Base dependencies - first for "bootstrap" kinds of rules
+#
+
+DEPENDS all : shell files lib exe obj ;
+DEPENDS all shell files lib exe obj : first ;
+NOTFILE all first shell files lib exe obj dirs clean uninstall ;
+ALWAYS clean uninstall ;
+
+#
+# Rules
+#
+
+rule As
+{
+ DEPENDS $(<) : $(>) ;
+ ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
+}
+
+rule Bulk
+{
+ local i ;
+
+ for i in $(>)
+ {
+ File $(i:D=$(<)) : $(i) ;
+ }
+}
+
+rule Cc
+{
+ local _h ;
+
+ DEPENDS $(<) : $(>) ;
+
+ # Just to clarify here: this sets the per-target CCFLAGS to
+ # be the current value of (global) CCFLAGS and SUBDIRCCFLAGS.
+
+ CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) ;
+
+ # If the compiler's -o flag doesn't work, relocate the .o
+
+ if $(RELOCATE)
+ {
+ CcMv $(<) : $(>) ;
+ }
+
+ _h = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;
+
+ if $(VMS) && $(_h)
+ {
+ SLASHINC on $(<) = "/inc=(" $(_h[1]) ,$(_h[2-]) ")" ;
+ }
+ else if $(MAC) && $(_h)
+ {
+ local _i _j ;
+ _j = $(_h[1]) ;
+ for _i in $(_h[2-])
+ {
+ _j = $(_j),$(_i) ;
+ }
+ MACINC on $(<) = \"$(_j)\" ;
+ }
+}
+
+rule C++
+{
+ local _h ;
+
+ DEPENDS $(<) : $(>) ;
+ C++FLAGS on $(<) += $(C++FLAGS) $(SUBDIRC++FLAGS) ;
+
+ if $(RELOCATE)
+ {
+ CcMv $(<) : $(>) ;
+ }
+
+ _h = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;
+
+ if $(VMS) && $(_h)
+ {
+ SLASHINC on $(<) = "/inc=(" $(_h[1]) ,$(_h[2-]) ")" ;
+ }
+ else if $(MAC) && $(_h)
+ {
+ local _i _j ;
+ _j = $(_h[1]) ;
+ for _i in $(_h[2-])
+ {
+ _j = $(_j),$(_i) ;
+ }
+ MACINC on $(<) = \"$(_j)\" ;
+ }
+}
+
+rule Chmod
+{
+ if $(CHMOD) { Chmod1 $(<) ; }
+}
+
+rule File
+{
+ DEPENDS files : $(<) ;
+ DEPENDS $(<) : $(>) ;
+ SEARCH on $(>) = $(SEARCH_SOURCE) ;
+ MODE on $(<) = $(FILEMODE) ;
+ Chmod $(<) ;
+}
+
+rule Fortran
+{
+ DEPENDS $(<) : $(>) ;
+}
+
+rule GenFile
+{
+ local _t = [ FGristSourceFiles $(<) ] ;
+ local _s = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;
+ Depends $(_t) : $(_s) $(>[2-]) ;
+ GenFile1 $(_t) : $(_s) $(>[2-]) ;
+ Clean clean : $(_t) ;
+}
+
+rule GenFile1
+{
+ MakeLocate $(<) : $(LOCATE_SOURCE) ;
+ SEARCH on $(>) = $(SEARCH_SOURCE) ;
+}
+
+rule HardLink
+{
+ DEPENDS files : $(<) ;
+ DEPENDS $(<) : $(>) ;
+ SEARCH on $(>) = $(SEARCH_SOURCE) ;
+}
+
+rule HdrMacroFile
+{
+ # HdrMacroFile file ;
+ #
+ # this rule is used to indicate that a given file contains definitions
+ # for filename macros (e.g. "#define MYFILE_H <myfile.h>") that can
+ # later be used in #include statements in the rest of the source
+ #
+ # theses files must be parsed before any make is tried..
+ #
+ HDRMACRO $(<) ;
+}
+
+rule HdrRule
+{
+ # HdrRule source : headers ;
+
+ # N.B. This rule is called during binding, potentially after
+ # the fate of many targets has been determined, and must be
+ # used with caution: don't add dependencies to unrelated
+ # targets, and don't set variables on $(<).
+
+ # Tell Jam that anything depending on $(<) also depends on $(>),
+ # set SEARCH so Jam can find the headers, but then say we don't
+ # care if we can't actually find the headers (they may have been
+ # within ifdefs),
+
+ local s ;
+
+ if $(HDRGRIST)
+ {
+ s = $(>:G=$(HDRGRIST)) ;
+ } else {
+ s = $(>) ;
+ }
+
+ INCLUDES $(<) : $(s) ;
+ SEARCH on $(s) = $(HDRSEARCH) ;
+ NOCARE $(s) ;
+
+ # Propagate on $(<) to $(>)
+
+ HDRSEARCH on $(s) = $(HDRSEARCH) ;
+ HDRSCAN on $(s) = $(HDRSCAN) ;
+ HDRRULE on $(s) = $(HDRRULE) ;
+ HDRGRIST on $(s) = $(HDRGRIST) ;
+}
+
+rule InstallInto
+{
+ # InstallInto dir : sources ;
+
+ local i t ;
+
+ t = $(>:G=$(INSTALLGRIST)) ;
+
+ # Arrange for jam install
+ # Arrange for jam uninstall
+ # sources are in SEARCH_SOURCE
+ # targets are in dir
+
+ Depends install : $(t) ;
+ Clean uninstall : $(t) ;
+ SEARCH on $(>) = $(SEARCH_SOURCE) ;
+ MakeLocate $(t) : $(<) ;
+
+ # For each source, make gristed target name
+ # and Install, Chmod, Chown, and Chgrp
+
+ for i in $(>)
+ {
+ local tt = $(i:G=$(INSTALLGRIST)) ;
+
+ Depends $(tt) : $(i) ;
+ Install $(tt) : $(i) ;
+ Chmod $(tt) ;
+
+ if $(OWNER) && $(CHOWN)
+ {
+ Chown $(tt) ;
+ OWNER on $(tt) = $(OWNER) ;
+ }
+
+ if $(GROUP) && $(CHGRP)
+ {
+ Chgrp $(tt) ;
+ GROUP on $(tt) = $(GROUP) ;
+ }
+ }
+}
+
+rule InstallBin
+{
+ local _t = [ FAppendSuffix $(>) : $(SUFEXE) ] ;
+
+ InstallInto $(<) : $(_t) ;
+ MODE on $(_t:G=installed) = $(EXEMODE) ;
+}
+
+rule InstallFile
+{
+ InstallInto $(<) : $(>) ;
+ MODE on $(>:G=installed) = $(FILEMODE) ;
+}
+
+rule InstallLib
+{
+ InstallInto $(<) : $(>) ;
+ MODE on $(>:G=installed) = $(FILEMODE) ;
+}
+
+rule InstallMan
+{
+ # Really this just strips the . from the suffix
+
+ local i s d ;
+
+ for i in $(>)
+ {
+ switch $(i:S)
+ {
+ case .1 : s = 1 ; case .2 : s = 2 ; case .3 : s = 3 ;
+ case .4 : s = 4 ; case .5 : s = 5 ; case .6 : s = 6 ;
+ case .7 : s = 7 ; case .8 : s = 8 ; case .l : s = l ;
+ case .n : s = n ; case .man : s = 1 ;
+ }
+
+ d = man$(s) ;
+
+ InstallInto $(d:R=$(<)) : $(i) ;
+ }
+
+ MODE on $(>:G=installed) = $(FILEMODE) ;
+}
+
+rule InstallShell
+{
+ InstallInto $(<) : $(>) ;
+ MODE on $(>:G=installed) = $(SHELLMODE) ;
+}
+
+rule Lex
+{
+ LexMv $(<) : $(>) ;
+ DEPENDS $(<) : $(>) ;
+ MakeLocate $(<) : $(LOCATE_SOURCE) ;
+ Clean clean : $(<) ;
+}
+
+rule Library
+{
+ LibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
+ Objects $(>) ;
+}
+
+rule LibraryFromObjects
+{
+ local _i _l _s ;
+
+ # Add grist to file names
+
+ _s = [ FGristFiles $(>) ] ;
+ _l = $(<:S=$(SUFLIB)) ;
+
+ # library depends on its member objects
+
+ if $(KEEPOBJS)
+ {
+ DEPENDS obj : $(_s) ;
+ }
+ else
+ {
+ DEPENDS lib : $(_l) ;
+ }
+
+ # Set LOCATE for the library and its contents. The bound
+ # value shows up as $(NEEDLIBS) on the Link actions.
+ # For compatibility, we only do this if the library doesn't
+ # already have a path.
+
+ if ! $(_l:D)
+ {
+ MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ;
+ }
+
+ if $(NOARSCAN)
+ {
+ # If we can't scan the library to timestamp its contents,
+ # we have to just make the library depend directly on the
+ # on-disk object files.
+
+ DEPENDS $(_l) : $(_s) ;
+ }
+ else
+ {
+ # If we can scan the library, we make the library depend
+ # on its members and each member depend on the on-disk
+ # object file.
+
+ DEPENDS $(_l) : $(_l)($(_s:BS)) ;
+
+ for _i in $(_s)
+ {
+ DEPENDS $(_l)($(_i:BS)) : $(_i) ;
+ }
+ }
+
+ Clean clean : $(_l) ;
+
+ if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; }
+
+ Archive $(_l) : $(_s) ;
+
+ if $(RANLIB) { Ranlib $(_l) ; }
+
+ # If we can't scan the library, we have to leave the .o's around.
+
+ if ! ( $(NOARSCAN) || $(KEEPOBJS) ) { RmTemps $(_l) : $(_s) ; }
+}
+
+rule Link
+{
+ MODE on $(<) = $(EXEMODE) ;
+ Chmod $(<) ;
+}
+
+rule LinkLibraries
+{
+ # make library dependencies of target
+ # set NEEDLIBS variable used by 'actions Main'
+
+ local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
+
+ DEPENDS $(_t) : $(>:S=$(SUFLIB)) ;
+ NEEDLIBS on $(_t) += $(>:S=$(SUFLIB)) ;
+}
+
+rule Main
+{
+ MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
+ Objects $(>) ;
+}
+
+rule MainFromObjects
+{
+ local _s _t ;
+
+ # Add grist to file names
+ # Add suffix to exe
+
+ _s = [ FGristFiles $(>) ] ;
+ _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
+
+ if $(_t) != $(<)
+ {
+ DEPENDS $(<) : $(_t) ;
+ NOTFILE $(<) ;
+ }
+
+ # make compiled sources a dependency of target
+
+ DEPENDS exe : $(_t) ;
+ DEPENDS $(_t) : $(_s) ;
+ MakeLocate $(_t) : $(LOCATE_TARGET) ;
+
+ Clean clean : $(_t) ;
+
+ Link $(_t) : $(_s) ;
+}
+
+rule MakeLocate
+{
+ if $(>)
+ {
+ LOCATE on $(<) = $(>) ;
+ Depends $(<) : $(>[1]) ;
+ MkDir $(>[1]) ;
+ }
+}
+
+rule MkDir
+{
+ # If dir exists, don't update it
+ # Do this even for $(DOT).
+
+ NOUPDATE $(<) ;
+
+ if $(<) != $(DOT) && ! $($(<)-mkdir)
+ {
+ local s ;
+
+ # Cheesy gate to prevent multiple invocations on same dir
+ # MkDir1 has the actions
+ # Arrange for jam dirs
+
+ $(<)-mkdir = true ;
+ MkDir1 $(<) ;
+ Depends dirs : $(<) ;
+
+ # Recursively make parent directories.
+ # $(<:P) = $(<)'s parent, & we recurse until root
+
+ s = $(<:P) ;
+
+ if $(NT)
+ {
+ switch $(s)
+ {
+ case *: : s = ;
+ case *:\\ : s = ;
+ }
+ }
+
+ if $(s) && $(s) != $(<)
+ {
+ Depends $(<) : $(s) ;
+ MkDir $(s) ;
+ }
+ else if $(s)
+ {
+ NOTFILE $(s) ;
+ }
+
+ }
+}
+
+rule Object
+{
+ local h ;
+
+ # locate object and search for source, if wanted
+
+ Clean clean : $(<) ;
+
+ MakeLocate $(<) : $(LOCATE_TARGET) ;
+ SEARCH on $(>) = $(SEARCH_SOURCE) ;
+
+ # Save HDRS for -I$(HDRS) on compile.
+ # We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers
+ # in the .c file's directory, but generated .c files (from
+ # yacc, lex, etc) are located in $(LOCATE_TARGET), possibly
+ # different from $(SEARCH_SOURCE).
+
+ HDRS on $(<) = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;
+
+ # handle #includes for source: Jam scans for headers with
+ # the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE)
+ # with the scanned file as the target and the found headers
+ # as the sources. HDRSEARCH is the value of SEARCH used for
+ # the found header files. Finally, if jam must deal with
+ # header files of the same name in different directories,
+ # they can be distinguished with HDRGRIST.
+
+ # $(h) is where cc first looks for #include "foo.h" files.
+ # If the source file is in a distant directory, look there.
+ # Else, look in "" (the current directory).
+
+ if $(SEARCH_SOURCE)
+ {
+ h = $(SEARCH_SOURCE) ;
+ }
+ else
+ {
+ h = "" ;
+ }
+
+ HDRRULE on $(>) = HdrRule ;
+ HDRSCAN on $(>) = $(HDRPATTERN) ;
+ HDRSEARCH on $(>) = $(HDRS) $(SUBDIRHDRS) $(h) $(STDHDRS) ;
+ HDRGRIST on $(>) = $(HDRGRIST) ;
+
+ # if source is not .c, generate .c with specific rule
+
+ switch $(>:S)
+ {
+ case .asm : As $(<) : $(>) ;
+ case .c : Cc $(<) : $(>) ;
+ case .C : C++ $(<) : $(>) ;
+ case .cc : C++ $(<) : $(>) ;
+ case .cpp : C++ $(<) : $(>) ;
+ case .f : Fortran $(<) : $(>) ;
+ case .l : Cc $(<) : $(<:S=.c) ;
+ Lex $(<:S=.c) : $(>) ;
+ case .s : As $(<) : $(>) ;
+ case .y : Cc $(<) : $(<:S=.c) ;
+ Yacc $(<:S=.c) : $(>) ;
+ case * : UserObject $(<) : $(>) ;
+ }
+}
+
+
+rule ObjectCcFlags
+{
+ CCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
+}
+
+rule ObjectC++Flags
+{
+ C++FLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
+}
+
+rule ObjectHdrs
+{
+ HDRS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
+}
+
+rule Objects
+{
+ local _i ;
+
+ for _i in [ FGristFiles $(<) ]
+ {
+ Object $(_i:S=$(SUFOBJ)) : $(_i) ;
+ DEPENDS obj : $(_i:S=$(SUFOBJ)) ;
+ }
+}
+
+rule RmTemps
+{
+ TEMPORARY $(>) ;
+}
+
+rule Setuid
+{
+ MODE on [ FAppendSuffix $(<) : $(SUFEXE) ] = 4711 ;
+}
+
+rule Shell
+{
+ DEPENDS shell : $(<) ;
+ DEPENDS $(<) : $(>) ;
+ SEARCH on $(>) = $(SEARCH_SOURCE) ;
+ MODE on $(<) = $(SHELLMODE) ;
+ Clean clean : $(<) ;
+ Chmod $(<) ;
+}
+
+rule SubDir
+{
+ local _r _s ;
+
+ #
+ # SubDir TOP d1 [ ... ]
+ #
+ # This introduces a Jamfile that is part of a project tree
+ # rooted at $(TOP). It (only once) includes the project-specific
+ # rules file $(TOP)/Jamrules and then sets search & locate stuff.
+ #
+ # If the variable $(TOPRULES) is set (where TOP is the first arg
+ # to SubDir), that file is included instead of $(TOP)/Jamrules.
+ #
+ # d1 ... are the directory elements that lead to this directory
+ # from $(TOP). We construct the system dependent path from these
+ # directory elements in order to set search&locate stuff.
+ #
+
+ if ! $($(<[1]))
+ {
+ if ! $(<[1])
+ {
+ EXIT SubDir syntax error ;
+ }
+
+ $(<[1]) = [ FSubDir $(<[2-]) ] ;
+ }
+
+ #
+ # If $(TOP)/Jamrules hasn't been included, do so.
+ #
+
+ if ! $($(<[1])-included)
+ {
+ # Gated entry.
+
+ $(<[1])-included = TRUE ;
+
+ # File is $(TOPRULES) or $(TOP)/Jamrules.
+
+ _r = $($(<[1])RULES) ;
+
+ if ! $(_r)
+ {
+ _r = $(JAMRULES:R=$($(<[1]))) ;
+ }
+
+ # Include it.
+
+ include $(_r) ;
+ }
+
+ # Get path to current directory from root using SubDir.
+ # Save dir tokens for other potential uses.
+
+ _s = [ FDirName $(<[2-]) ] ;
+ SUBDIR = $(_s:R=$($(<[1]))) ;
+ SUBDIR_TOKENS = $(<[2-]) ;
+
+ # Now set up SEARCH_SOURCE, LOCATE_TARGET, SOURCE_GRIST
+ # These can be reset if needed. For example, if the source
+ # directory should not hold object files, LOCATE_TARGET can
+ # subsequently be redefined.
+
+ SEARCH_SOURCE = $(SUBDIR) ;
+ LOCATE_SOURCE = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
+ LOCATE_TARGET = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
+ SOURCE_GRIST = [ FGrist $(<[2-]) ] ;
+
+ # Reset per-directory ccflags, hdrs
+
+ SUBDIRCCFLAGS = ;
+ SUBDIRC++FLAGS = ;
+ SUBDIRHDRS = ;
+}
+
+rule SubDirCcFlags
+{
+ SUBDIRCCFLAGS += $(<) ;
+}
+
+rule SubDirC++Flags
+{
+ SUBDIRC++FLAGS += $(<) ;
+}
+
+rule SubDirHdrs
+{
+ SUBDIRHDRS += $(<) ;
+}
+
+rule SubInclude
+{
+ local _s ;
+
+ # That's
+ # SubInclude TOP d1 [ d2 [ d3 [ d4 ] ] ]
+ #
+ # to include a subdirectory's Jamfile.
+
+ if ! $($(<[1]))
+ {
+ EXIT Top level of source tree has not been set with $(<[1]) ;
+ }
+
+ _s = [ FDirName $(<[2-]) ] ;
+
+ include $(JAMFILE:D=$(_s):R=$($(<[1]))) ;
+}
+
+rule Undefines
+{
+ UNDEFS on [ FAppendSuffix $(<) : $(SUFEXE) ] += $(UNDEFFLAG)$(>) ;
+}
+
+rule UserObject
+{
+ EXIT "Unknown suffix on" $(>) "- see UserObject rule in Jamfile(5)." ;
+}
+
+rule Yacc
+{
+ local _h ;
+
+ _h = $(<:BS=.h) ;
+
+ # Some places don't have a yacc.
+
+ MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ;
+
+ if $(YACC)
+ {
+ DEPENDS $(<) $(_h) : $(>) ;
+ Yacc1 $(<) $(_h) : $(>) ;
+ YaccMv $(<) $(_h) : $(>) ;
+ Clean clean : $(<) $(_h) ;
+ }
+
+ # make sure someone includes $(_h) else it will be
+ # a deadly independent target
+
+ INCLUDES $(<) : $(_h) ;
+}
+
+#
+# Utility rules; no side effects on these
+#
+
+rule FGrist
+{
+ # Turn individual elements in $(<) into grist.
+
+ local _g _i ;
+
+ _g = $(<[1]) ;
+
+ for _i in $(<[2-])
+ {
+ _g = $(_g)!$(_i) ;
+ }
+
+ return $(_g) ;
+}
+
+rule FGristFiles
+{
+ if ! $(SOURCE_GRIST)
+ {
+ return $(<) ;
+ }
+ else
+ {
+ return $(<:G=$(SOURCE_GRIST)) ;
+ }
+}
+
+rule FGristSourceFiles
+{
+ # Produce source file name name with grist in it,
+ # if SOURCE_GRIST is set.
+
+ # Leave header files alone, because they have a global
+ # visibility.
+
+ if ! $(SOURCE_GRIST)
+ {
+ return $(<) ;
+ }
+ else
+ {
+ local _i _o ;
+
+ for _i in $(<)
+ {
+ switch $(_i)
+ {
+ case *.h : _o += $(_i) ;
+ case * : _o += $(_i:G=$(SOURCE_GRIST)) ;
+ }
+ }
+
+ return $(_o) ;
+ }
+}
+
+rule FConcat
+{
+ # Puts the variables together, removing spaces.
+
+ local _t _r ;
+
+ $(_r) = $(<[1]) ;
+
+ for _t in $(<[2-])
+ {
+ $(_r) = $(_r)$(_t) ;
+ }
+
+ return $(_r) ;
+}
+
+rule FSubDir
+{
+ local _i _d ;
+
+ # If $(>) is the path to the current directory, compute the
+ # path (using ../../ etc) back to that root directory.
+ # Sets result in $(<)
+
+ if ! $(<[1])
+ {
+ _d = $(DOT) ;
+ }
+ else
+ {
+ _d = $(DOTDOT) ;
+
+ for _i in $(<[2-])
+ {
+ _d = $(_d:R=$(DOTDOT)) ;
+ }
+ }
+
+ return $(_d) ;
+}
+
+rule FDirName
+{
+ local _s _i ;
+
+ # Turn individual elements in $(<) into a usable path.
+
+ if ! $(<)
+ {
+ _s = $(DOT) ;
+ }
+ else if $(VMS)
+ {
+ # This handles the following cases:
+ # a -> [.a]
+ # a b c -> [.a.b.c]
+ # x: -> x:
+ # x: a -> x:[a]
+ # x:[a] b -> x:[a.b]
+
+ switch $(<[1])
+ {
+ case *:* : _s = $(<[1]) ;
+ case \\[*\\] : _s = $(<[1]) ;
+ case * : _s = [.$(<[1])] ;
+ }
+
+ for _i in [.$(<[2-])]
+ {
+ _s = $(_i:R=$(_s)) ;
+ }
+ }
+ else if $(MAC)
+ {
+ _s = $(DOT) ;
+
+ for _i in $(<)
+ {
+ _s = $(_i:R=$(_s)) ;
+ }
+ }
+ else
+ {
+ _s = $(<[1]) ;
+
+ for _i in $(<[2-])
+ {
+ _s = $(_i:R=$(_s)) ;
+ }
+ }
+
+ return $(_s) ;
+}
+
+
+rule _makeCommon
+{
+ # strip common initial elements
+
+ if $($(<)[1]) && $($(<)[1]) = $($(>)[1])
+ {
+ $(<) = $($(<)[2-]) ;
+ $(>) = $($(>)[2-]) ;
+ _makeCommon $(<) : $(>) ;
+ }
+}
+
+
+rule FRelPath
+{
+ local _l _r ;
+
+ # first strip off common parts
+
+ _l = $(<) ;
+ _r = $(>) ;
+
+ _makeCommon _l : _r ;
+
+ # now make path to root and path down
+
+ _l = [ FSubDir $(_l) ] ;
+ _r = [ FDirName $(_r) ] ;
+
+ # Concatenate and save
+
+ # XXX This should be better
+
+ if $(_r) = $(DOT) {
+ return $(_l) ;
+ } else {
+ return $(_r:R=$(_l)) ;
+ }
+}
+
+rule FAppendSuffix
+{
+ # E.g., "FAppendSuffix yacc lex foo.bat : $(SUFEXE) ;"
+ # returns (yacc,lex,foo.bat) on Unix and
+ # (yacc.exe,lex.exe,foo.bat) on NT.
+
+ if $(>)
+ {
+ local _i _o ;
+
+ for _i in $(<)
+ {
+ if $(_i:S)
+ {
+ _o += $(_i) ;
+ }
+ else
+ {
+ _o += $(_i:S=$(>)) ;
+ }
+ }
+ return $(_o) ;
+ }
+ else
+ {
+ return $(<) ;
+ }
+}
+
+rule unmakeDir
+{
+ if $(>[1]:D) && $(>[1]:D) != $(>[1]) && $(>[1]:D) != \\\\
+ {
+ unmakeDir $(<) : $(>[1]:D) $(>[1]:BS) $(>[2-]) ;
+ }
+ else
+ {
+ $(<) = $(>) ;
+ }
+}
+
+
+rule FConvertToSlashes
+{
+ local _d, _s, _i ;
+
+ unmakeDir _d : $(<) ;
+
+ _s = $(_d[1]) ;
+ for _i in $(_d[2-])
+ {
+ _s = $(_s)/$(_i) ;
+ }
+ return $(_s) ;
+}
+
+
+#
+# Actions
+#
+
+#
+# First the defaults
+#
+
+actions updated together piecemeal Archive
+{
+ $(AR) $(<) $(>)
+}
+
+actions As
+{
+ $(AS) $(ASFLAGS) -I$(HDRS) -o $(<) $(>)
+}
+
+actions C++
+{
+ $(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o $(<) $(>)
+}
+
+actions Cc
+{
+ $(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o $(<) $(>)
+}
+
+actions Chgrp
+{
+ $(CHGRP) $(GROUP) $(<)
+}
+
+actions Chmod1
+{
+ $(CHMOD) $(MODE) $(<)
+}
+
+actions Chown
+{
+ $(CHOWN) $(OWNER) $(<)
+}
+
+actions piecemeal together existing Clean
+{
+ $(RM) $(>)
+}
+
+actions File
+{
+ $(CP) $(>) $(<)
+}
+
+actions GenFile1
+{
+ $(>[1]) $(<) $(>[2-])
+}
+
+actions Fortran
+{
+ $(FORTRAN) $(FORTRANFLAGS) -o $(<) $(>)
+}
+
+actions HardLink
+{
+ $(RM) $(<) && $(LN) $(>) $(<)
+}
+
+actions Install
+{
+ $(CP) $(>) $(<)
+}
+
+actions Lex
+{
+ $(LEX) $(>)
+}
+
+actions LexMv
+{
+ $(MV) lex.yy.c $(<)
+}
+
+actions Link bind NEEDLIBS
+{
+ $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
+}
+
+actions MkDir1
+{
+ $(MKDIR) $(<)
+}
+
+actions together Ranlib
+{
+ $(RANLIB) $(<)
+}
+
+actions quietly updated piecemeal together RmTemps
+{
+ $(RM) $(>)
+}
+
+actions Shell
+{
+ $(AWK) '
+ NR == 1 { print "$(SHELLHEADER)" }
+ NR == 1 && /^[#:]/ { next }
+ /^##/ { next }
+ { print }
+ ' < $(>) > $(<)
+}
+
+actions Yacc1
+{
+ $(YACC) $(YACCFLAGS) $(>)
+}
+
+actions YaccMv
+{
+ $(MV) $(YACCFILES).c $(<[1])
+ $(MV) $(YACCFILES).h $(<[2])
+}
+
+#
+# RELOCATE - for compilers with broken -o flags
+#
+
+if $(RELOCATE)
+{
+ actions C++
+ {
+ $(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) $(>)
+ }
+
+ actions Cc
+ {
+ $(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) $(>)
+ }
+
+ actions ignore CcMv
+ {
+ [ $(<) != $(>:BS=$(SUFOBJ)) ] && $(MV) $(>:BS=$(SUFOBJ)) $(<)
+ }
+}
+
+#
+# NOARUPDATE - can't update an archive
+#
+
+if $(NOARUPDATE)
+{
+ actions Archive
+ {
+ $(AR) $(<) $(>)
+ }
+}
+
+#
+# NT specific actions
+#
+
+if $(NT)
+{
+ if $(TOOLSET) = VISUALC || $(TOOLSET) = VC7 || $(TOOLSET) = INTELC
+ {
+ actions updated together piecemeal Archive
+ {
+ if exist $(<) set _$(<:B)_=$(<)
+ $(AR) /out:$(<) %_$(<:B)_% $(>)
+ }
+
+ actions As
+ {
+ $(AS) /Ml /p /v /w2 $(>) $(<) ,nul,nul;
+ }
+
+ actions Cc
+ {
+ $(CC) /c $(CCFLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /I$(STDHDRS) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) /c $(C++FLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /I$(STDHDRS) /Tp$(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
+ }
+ }
+ else if $(TOOLSET) = VISUALC16
+ {
+ actions updated together piecemeal Archive
+ {
+ $(AR) $(<) -+$(>)
+ }
+
+ actions Cc
+ {
+ $(CC) /c $(CCFLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) /c $(C++FLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /Tp$(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
+ }
+ }
+ else if $(TOOLSET) = BORLANDC
+ {
+ actions updated together piecemeal Archive
+ {
+ $(AR) $(<) -+$(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) -e$(<) $(LINKFLAGS) $(UNDEFS) -L$(LINKLIBS) $(NEEDLIBS) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
+ }
+
+ actions Cc
+ {
+ $(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
+ }
+
+ }
+ else if $(TOOLSET) = MINGW
+ {
+ actions together piecemeal Archive
+ {
+ $(AR) $(<) $(>:T)
+ }
+
+ actions Cc
+ {
+ $(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
+ }
+ }
+ else if $(TOOLSET) = WATCOM
+ {
+ actions together piecemeal Archive
+ {
+ $(AR) $(<) +-$(>)
+ }
+
+ actions Cc
+ {
+ $(CC) $(CCFLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) $(C++FLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
+ }
+
+ actions Shell
+ {
+ $(CP) $(>) $(<)
+ }
+ }
+ else if $(TOOLSET) = LCC
+ {
+ actions together piecemeal Archive
+ {
+ $(AR) /out:$(<) $(>)
+ }
+
+ actions Cc
+ {
+ $(CC) $(CCFLAGS) $(OPTIM) -Fo$(<) -I$(HDRS) $(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
+ }
+
+ actions Shell
+ {
+ $(CP) $(>) $(<)
+ }
+ }
+}
+
+#
+# OS2 specific actions
+#
+
+else if $(OS2)
+{
+ if $(TOOLSET) = WATCOM
+ {
+ actions together piecemeal Archive
+ {
+ $(AR) $(<) +-$(>)
+ }
+
+ actions Cc
+ {
+ $(CC) $(CCFLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) $(C++FLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
+ }
+
+ actions Shell
+ {
+ $(CP) $(>) $(<)
+ }
+ }
+ else if $(TOOLSET) = EMX
+ {
+ actions together piecemeal Archive
+ {
+ $(AR) $(<) $(>:T)
+ }
+
+ actions Cc
+ {
+ $(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
+ }
+
+ actions C++
+ {
+ $(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
+ }
+ }
+}
+
+#
+# VMS specific actions
+#
+
+else if $(VMS)
+{
+ actions updated together piecemeal Archive
+ {
+ lib/replace $(<) $(>[1]) ,$(>[2-])
+ }
+
+ actions Cc
+ {
+ $(CC)/obj=$(<) $(CCFLAGS) $(OPTIM) $(SLASHINC) $(>)
+ }
+
+ actions C++
+ {
+ $(C++)/obj=$(<) $(C++FLAGS) $(OPTIM) $(SLASHINC) $(>)
+ }
+
+ actions piecemeal together existing Clean
+ {
+ $(RM) $(>[1]);* ,$(>[2-]);*
+ }
+
+ actions together quietly CreLib
+ {
+ if f$search("$(<)") .eqs. "" then lib/create $(<)
+ }
+
+ actions GenFile1
+ {
+ mcr $(>[1]) $(<) $(>[2-])
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK)/exe=$(<) $(LINKFLAGS) $(>[1]) ,$(>[2-]) ,$(NEEDLIBS)/lib ,$(LINKLIBS)
+ }
+
+ actions quietly updated piecemeal together RmTemps
+ {
+ $(RM) $(>[1]);* ,$(>[2-]);*
+ }
+
+ actions Shell
+ {
+ $(CP) $(>) $(<)
+ }
+}
+
+#
+# Mac specifc actions
+#
+
+else if $(MAC)
+{
+ actions together Archive
+ {
+ $(LINK) -library -o $(<) $(>)
+ }
+
+ actions Cc
+ {
+ set -e MWCincludes $(MACINC)
+ $(CC) -o $(<) $(CCFLAGS) $(OPTIM) $(>)
+ }
+
+ actions C++
+ {
+ set -e MWCincludes $(MACINC)
+ $(CC) -o $(<) $(C++FLAGS) $(OPTIM) $(>)
+ }
+
+ actions Link bind NEEDLIBS
+ {
+ $(LINK) -o $(<) $(LINKFLAGS) $(>) $(NEEDLIBS) "$(LINKLIBS)"
+ }
+}
+
+#
+# Backwards compatibility with jam 1, where rules were uppercased.
+#
+
+rule BULK { Bulk $(<) : $(>) ; }
+rule FILE { File $(<) : $(>) ; }
+rule HDRRULE { HdrRule $(<) : $(>) ; }
+rule INSTALL { Install $(<) : $(>) ; }
+rule LIBRARY { Library $(<) : $(>) ; }
+rule LIBS { LinkLibraries $(<) : $(>) ; }
+rule LINK { Link $(<) : $(>) ; }
+rule MAIN { Main $(<) : $(>) ; }
+rule SETUID { Setuid $(<) ; }
+rule SHELL { Shell $(<) : $(>) ; }
+rule UNDEFINES { Undefines $(<) : $(>) ; }
+
+# Old INSTALL* didn't take dest directory.
+
+rule INSTALLBIN { InstallBin $(BINDIR) : $(<) ; }
+rule INSTALLLIB { InstallLib $(LIBDIR) : $(<) ; }
+rule INSTALLMAN { InstallMan $(MANDIR) : $(<) ; }
+
+# Compatibility with jam 2.2.
+
+rule addDirName { $(<) += [ FDirName $(>) ] ; }
+rule makeDirName { $(<) = [ FDirName $(>) ] ; }
+rule makeGristedName { $(<) = [ FGristSourceFiles $(>) ] ; }
+rule makeRelPath { $(<[1]) = [ FRelPath $(<[2-]) : $(>) ] ; }
+rule makeSuffixed { $(<[1]) = [ FAppendSuffix $(>) : $(<[2]) ] ; }
+
+#
+# Now include the user's Jamfile.
+#
+
+{
+ if $(JAMFILE) { include $(JAMFILE) ; }
+}
+
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/Jambase.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/Jambase.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/Jambase.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,931 @@
+<HTML>
+<TITLE>
+Jambase Reference
+</TITLE>
+<BODY>
+<CENTER>
+<a href=http://www.perforce.com/jam/jam.html>
+Jam/MR
+</a>
+<H1>
+<A NAME="TOP">
+Jambase Reference
+</A>
+</H1>
+</CENTER>
+<P>
+ Jambase is a base set of Jam/MR rules which
+ provide roughly make(1)-like functionality for
+ <a href="Jam.html"><b>jam</b></A>, the Jam/MR executable program.
+ This document, which started out as the Jambase(5) man page,
+ is a reference guide to the
+ <A href="#RULES">rules</A>,
+ <A href="#PSEUDOTARGETS">pseudotargets</A>,
+ and <A href="#VARS">variables</A>
+ defined in Jambase for use in Jamfiles.
+<P>
+ For further information see:
+<UL>
+<LI>
+ <a href="Jamfile.html">Using Jamfiles and Jambase</A>
+<LI>
+ <a href="Jam.html">The Jam/MR Executable Program</A>
+</UL>
+<P>
+Jam/MR documentation and source are available from the
+<A HREF=http://public.perforce.com/public/index.html>Perforce Public Depot</a>.
+For detailed information about any of the rules summarized below,
+see the
+<A HREF=http://public.perforce.com/public/jam/src/Jambase>Jambase</a>
+file itself.
+<HR>
+<H2>
+<A NAME="RULES">
+Jambase Rules
+</A>
+</H2>
+<P>
+ <B>As</B> <I>obj.o</I> : <I>source.s</I> ;
+<BLOCKQUOTE>
+ Assemble the file <I>source.s.</I> Called by the Object
+ rule.
+</BLOCKQUOTE>
+ <B>Bulk</B> <I>directory</I> : <I>sources</I> ;
+<BLOCKQUOTE>
+ Copies <I>sources</I> into <I>directory.</I>
+</BLOCKQUOTE>
+ <B>Cc</B> <I>object</I> : <I>source</I> ;
+<BLOCKQUOTE>
+ Compile the file <I>source</I> into <I>object,</I> using the C
+ compiler $(CC), its flags $(CCFLAGS) and $(OPTIM),
+ and the header file directories $(HDRS). Called by
+ the Object rule.
+</BLOCKQUOTE>
+ <B>C++</B> <I>obj.o</I> : <I>source.cc</I> ;
+<BLOCKQUOTE>
+ Compile the C++ source file <I>source.cc.</I> Called by
+ the Object rule.
+</BLOCKQUOTE>
+ <B>Chmod</B> <I>target</I> ;
+<BLOCKQUOTE>
+ <I>(Unix and VMS only.)</I>
+ Change file permissions on <I>target</I> to
+ target-specific $(MODE) value set by Link, File,
+ Install*, and Shell rules.
+</BLOCKQUOTE>
+
+ <B>Clean</B> <I>clean</I> : <I>targets</I> ;
+<BLOCKQUOTE>
+ Removes existing <I>targets</I> when <I>clean</I> is built.
+ clean is not a dependency of all, and must be built
+ explicitly for targets to be removed.
+</BLOCKQUOTE>
+ <B>FDefines</B> <I>defines</I> ; <BLOCKQUOTE>
+ Expands a list of definitions into a list of compiler
+ (or preprocessor) switches (such as
+ -D<I>symbol</I>=<I>val</I> on Unix)
+ to pass the definitions.
+</BLOCKQUOTE>
+ <B>File</B> <I>target</I> : <I>source</I> ;
+<BLOCKQUOTE>
+ Copies <I>source</I> into <I>target.</I>
+</BLOCKQUOTE>
+ <B>FIncludes</B> <I>dirs</I> ; <BLOCKQUOTE>
+ Expands a list of directories into a list of compiler
+ (or preprocessor) switches (such as -I<I>dir</I> on Unix)
+ to add the directories to the header inclusion search path.
+</BLOCKQUOTE>
+ <B>Fortran</B> <I>obj.o</I> : <I>source.f</I> ;
+<BLOCKQUOTE>
+ Compile the Fortran source file <I>source.f.</I> Called
+ by the Object rule.
+</BLOCKQUOTE>
+ <B>FQuote</B> <I>files</I> ; <BLOCKQUOTE>
+ Returns each of <I>files</I> suitably quoted so as to hide shell
+ metacharacters (such as whitespace and filename matching wildcards)
+ from the shell.
+</BLOCKQUOTE>
+<P>
+ <B>GenFile</B> <I>target</I> : <I>image</I> <I>sources</I> ;
+<BLOCKQUOTE>
+ Runs the command "<I>image</I> <I>target</I> <I>sources</I>"
+ to create <I>target</I> from <I>sources</I> and
+ <I>image</I>. (where <I>image</I> is an
+ executable built by the Main rule.)
+</BLOCKQUOTE>
+ <B>HardLink</B> <I>target</I> : <I>source</I> ;
+<BLOCKQUOTE>
+ Makes <I>target</I> a hard link to <I>source,</I> if it isn't one
+ already. (Unix only.)
+</BLOCKQUOTE>
+ <B>HdrRule</B> <I>source</I> : <I>headers</I> ;
+<BLOCKQUOTE>
+ Arranges the proper dependencies when the file
+ <I>source</I> includes the files <I>headers</I> through the
+ "#include" C preprocessor directive.
+ <P>
+ This rule is not intended to be called explicitly.
+ It is called automatically during header scanning on
+ sources handled by the Object rule (e.g., sources in
+ Main or Library rules).
+</BLOCKQUOTE>
+ <B>InstallBin</B> <I>dir</I> : <I>sources</I> ; <BLOCKQUOTE>
+ Copy <I>sources</I> into <I>dir</I> with mode
+ $(EXEMODE).
+</BLOCKQUOTE>
+ <B>InstallLib</B> <I>dir</I> : <I>sources</I> ; <BLOCKQUOTE>
+ Copy <I>sources</I> into <I>dir</I> with mode
+ $(FILEMODE).
+</BLOCKQUOTE>
+ <B>InstallMan</B> <I>dir</I> : <I>sources</I> ; <BLOCKQUOTE>
+ Copy <I>sources</I> into the appropriate subdirectory
+ of <I>dir</I> with mode $(FILEMODE). The subdirectory
+ is man<I>s,</I> where <I>s</I> is the suffix of
+ each of sources.
+</BLOCKQUOTE>
+ <B>InstallShell</B> <I>dir</I> : <I>sources</I> ; <BLOCKQUOTE>
+ Copy <I>sources</I> into <I>dir</I> with mode
+ $(SHELLMODE).
+</BLOCKQUOTE>
+ <B>Lex</B> <I>source.c</I> : <I>source.l</I> ; <BLOCKQUOTE>
+ Process the lex(1) source file <I>source.l</I> and
+ rename the lex.yy.c to <I>source.c.</I> Called by
+ the Object rule.
+</BLOCKQUOTE>
+ <B>Library</B> <I>library</I> : <I>sources</I> ; <BLOCKQUOTE>
+ Compiles <I>sources</I> and archives them into
+ <I>library.</I> The intermediate <I>objects</I>
+ are deleted. Calls Objects and LibraryFromObjects.
+ <P>
+ If Library is invoked with no suffix on <I>library</I>,
+ the $(SUFLIB) suffix is used.
+</BLOCKQUOTE>
+ <B>LibraryFromObjects</B> <I>library</I> : <I>objects</I> ;
+<BLOCKQUOTE>
+ Archives <I>objects</I> into <I>library.</I> The
+ <I>objects</I> are then deleted.
+ <P>
+ If <I>library</I> has no suffix, the $(SUFLIB) suffix is used.
+</BLOCKQUOTE>
+ <B>Link</B> <I>image</I> : <I>objects</I> ;
+<BLOCKQUOTE>
+ Links <I>image</I> from <I>objects</I> and sets
+ permissions on <I>image</I> to $(EXEMODE).
+ <I>Image</I> must be actual filename; suffix is not
+ supplied.
+ Called by Main.
+
+</BLOCKQUOTE>
+ <B>LinkLibraries</B> <I>image</I> : <I>libraries</I> ;
+<BLOCKQUOTE>
+ Makes <I>image</I> depend on <I>libraries</I> and
+ includes them during the linking.
+ <P>
+ <I>Image</I> may be referenced without a suffix in this
+ rule invocation; LinkLibraries supplies the suffix.
+</BLOCKQUOTE>
+ <B>Main</B> <I>image</I> : <I>sources</I> ;
+<BLOCKQUOTE>
+ Compiles <I>sources</I> and links them into <I>image.</I>
+ Calls Objects and MainFromObjects.
+ <P>
+ <I>Image</I> may be referenced without a suffix in this
+ rule invocation; Main supplies the suffix.
+</BLOCKQUOTE>
+ <B>MainFromObjects</B> <I>image</I> : <I>objects</I> ;
+<BLOCKQUOTE>
+ Links <I>objects</I> into <I>image.</I> Dependency
+ of exe. MainFromObjects supplies the suffix on <I>image</I>
+ filename.
+</BLOCKQUOTE>
+ <B>MakeLocate</B> <I>target</I> : <I>dir</I> ;
+<BLOCKQUOTE>
+ Creates <I>dir</I> and causes <I>target</I> to be built
+ into <I>dir</I>.
+</BLOCKQUOTE>
+ <B>MkDir</B> <I>dir</I> ;
+<BLOCKQUOTE>
+ Creates <I>dir</I> and its parent directories.
+</BLOCKQUOTE>
+ <B>Object</B> <I>object</I> : <I>source</I> ;
+<BLOCKQUOTE>
+ Compiles a <I>single</I> source file source into
+ <I>object.</I> The Main and Library rules use
+ this rule to compile source files.
+ <P>
+ Causes <I>source</I> to be scanned for "#include"
+ directives and calls HdrRule to make all included
+ files dependedencies of <I>object</I>.
+<P>
+ Calls one of the following rules to do the actual
+ compiling, depending on the suffix of source:
+<PRE>
+ *.c: Cc
+ *.cc: C++
+ *.cpp: C++
+ *.C: C++
+ *.l: Lex
+ *.y: Yacc
+ *.*: UserObject
+</PRE>
+</BLOCKQUOTE>
+ <B>ObjectC++Flags</B> <I>source</I> : <I>flags</I> ;
+ <BR>
+ <B>ObjectCcFlags</B> <I>source</I> : <I>flags</I> ;
+<BLOCKQUOTE>
+ Add <I>flags</I> to the source-specific
+ value of $(CCFLAGS) or $(C++FLAGS) when compiling <I>source.</I>
+ Any file suffix on <I>source</I> is ignored.
+</BLOCKQUOTE>
+ <B>ObjectDefines</B> <I>object</I> : <I>defines</I> ; <BLOCKQUOTE>
+ Adds preprocessor symbol definitions to the (gristed)
+ target-specific $(CCDEFS) for the <I>object</i>.
+</BLOCKQUOTE>
+ <B>ObjectHdrs</B> <I>source</I> : <I>dirs</I> ; <BLOCKQUOTE>
+ Add <I>dirs</I> to the source-specific value of
+ $(HDRS) when scanning and compiling <I>source.</I>
+ Any file suffix on <I>source</I> is ignored.
+</BLOCKQUOTE>
+ <B>Objects</B> <I>sources</I> ; <BLOCKQUOTE>
+ For each source file in <I>sources,</I> calls
+ Object to compile the source file into a similarly
+ named object file.
+</BLOCKQUOTE>
+ <B>RmTemps</B> <I>targets</I> : <I>sources</I> ; <BLOCKQUOTE>
+ Marks <I>sources</I> as temporary with the TEMPORARY
+ rule, and deletes <I>sources</I> once <I>targets</I>
+ are built. Must be the last rule invoked on
+ <I>targets.</I> Used internally by LibraryFromObjects rule.
+</BLOCKQUOTE>
+ <B>Setuid</B> <I>images</I> ; <BLOCKQUOTE>
+ Sets the setuid bit on each of <I>images</I> after
+ linking. (Unix only.)
+
+</BLOCKQUOTE>
+ <B>SoftLink</B> <I>target</I> : <I>source</I> ;
+<BLOCKQUOTE>
+ Makes <I>target</I> a symbolic link to <I>source,</I> if it isn't one
+ already. (Unix only.)
+</BLOCKQUOTE>
+ <B>SubDir</B> <I>VAR d1 ... dn</I> ;
+<BLOCKQUOTE>
+ Sets up housekeeping for the source files located
+ in <I><CODE>$(VAR)/d1/.../dn</CODE></I>:
+ <UL>
+ <LI>Reads in rules file associated with <I>VAR</I>,
+ if it hasn't already been read.
+ <LI>Initializes variables for search paths,
+ output directories, compiler
+ flags, and grist, using <I>d1 ... dn</I> tokens.
+ </UL>
+ <P>
+ <I>VAR</I> is the name of a variable;
+ <I>d1</I> thru <I>dn</I> are elements
+ of a directory path.
+</BLOCKQUOTE>
+ <B>SubDirC++Flags</B> <I>flags</I> ;
+ <BR>
+ <B>SubDirCcFlags</B> <I>flags</I> ;
+<BLOCKQUOTE>
+ Adds <I>flags</I> to the compiler flags for source files
+ in SubDir's directory.
+</BLOCKQUOTE>
+ <B>SubDirHdrs</B> <I>d1 ... dn</I> ;
+<BLOCKQUOTE>
+ Adds the path <I>d1/.../dn/</I> to the header search paths for
+ source files in SubDir's directory. <I>d1</I> through <I>dn</I>
+ are elements of a directory path.
+</BLOCKQUOTE>
+ <B>SubInclude</B> <I>VAR d1 ... dn</I> ;
+<BLOCKQUOTE>
+ Reads the Jamfile in <I><CODE>$(VAR)/d1/.../dn/</CODE></I>.
+</BLOCKQUOTE>
+ <B>Shell</B> <I>image</I> : <I>source</I> ; <BLOCKQUOTE>
+ Copies <I>source</I> into the executable sh(1)
+ script <I>image.</I> Ensures that the first line of
+ the script is $(SHELLHEADER) (default #!/bin/sh).
+</BLOCKQUOTE>
+ <B>Undefines</B> <I>images</I> : <I>symbols</I> ; <BLOCKQUOTE>
+ Adds flags to mark <I>symbols</I> as undefined
+ on link command for <I>images</I>.
+ <I>Images</I> may be referenced unsuffixed; the
+ Undefines rule supplies the suffix.
+</BLOCKQUOTE>
+ <B>UserObject</B> <I>object</I> : <I>source</I> ; <BLOCKQUOTE>
+ This rule is called by Object for source
+ files with unknown suffixes, and should be defined
+ in Jamrules
+ with a user-provided rule to handle the source file
+ types not handled by the Object rule.
+ The Jambase UserObject rule merely issues a
+ complaint when it encounters <I>source</I> with
+ files suffixes it does not recognize.
+</BLOCKQUOTE>
+ <B>Yacc</B> <I>source.c</I> : <I>source.y</I> ; <BLOCKQUOTE>
+ Process the yacc(1) file <I>source.y</I> and renamed
+ the resulting y.tab.c and y.tab.h to <I>source.c.</I>
+ Produces a y.tab.h and renames it to <I>source.h.</I>
+ Called by the <B>Object</B> rule.
+</BLOCKQUOTE>
+<P>
+<HR>
+<A NAME="PSEUDOTARGETS">
+<H3>
+Jambase Pseudotargets
+</H3>
+</A>
+<P>
+There are two kinds of Jam targets: file targets and pseudotargets.
+File targets are objects that can be found in the filesystem.
+Pseudotargets are symbolic, and usually represent other targets.
+Most Jambase rules that define file targets also define pseudotargets
+which are dependent on types of file targets. The Jambase pseudotargets
+are:
+<CENTER>
+<TABLE CELLPADDING=5%>
+<TR><TD>exe
+ <TD>Executables linked by the Main or MainFromObjects rules
+
+<TR><TD>lib
+ <TD>Libraries created by the Library or LibraryFromObjects rules
+
+<TR><TD>obj
+ <TD>Compiled objects used to create Main or Library targets
+
+<TR><TD>dirs
+ <TD>Directories where target files are written
+
+<TR><TD>file
+ <TD>Files copied by File and Bulk rules
+
+<TR><TD>shell
+ <TD>Files copied by Shell rule
+
+<TR><TD>clean
+ <TD>Removal of built targets (except files copied by Install* rules)
+
+<TR><TD>install
+ <TD>Files copied by Install* rules
+
+<TR><TD>uninstall
+ <TD>Removal of targets copied by Install* rules
+
+</TABLE>
+</CENTER>
+<P>
+In addition, Jambase makes the <b>jam</b> default target "all"
+depend on "exe", "lib", "obj", "files", and "shell".
+<P>
+
+<HR>
+<A NAME="VARS">
+<H3>
+Jambase Variables
+</H3>
+</A>
+<P>
+ Most of the following variables have default values for
+ each platform; refer to the Jambase file to see what those
+ defaults are.
+<P>
+ ALL_LOCATE_TARGET
+<BLOCKQUOTE>
+ Alternative location of built targets. By default,
+ Jambase rules locate built targets in the source
+ tree. By setting $(ALL_LOCATE_TARGET)
+ in Jamrules, you can cause <b>jam</b>
+ to write built targets to a location outside
+ the source tree.
+</BLOCKQUOTE>
+
+ AR
+
+<BLOCKQUOTE>
+ The archive command used to update Library
+ and LibraryFromObjects targets.
+</BLOCKQUOTE>
+ AS
+<BLOCKQUOTE>
+ The assembler for As rule targets.
+</BLOCKQUOTE>
+
+ ASFLAGS
+
+<BLOCKQUOTE>
+ Flags handed to the assembler for As.
+</BLOCKQUOTE>
+
+ AWK
+
+<BLOCKQUOTE>
+ The name of awk interpreter, used when copying a
+ shell script for the Shell rule.
+</BLOCKQUOTE>
+
+ BCCROOT
+<BLOCKQUOTE>
+ Selects Borland compile and link actions on NT.
+</BLOCKQUOTE>
+
+
+ BINDIR
+
+<BLOCKQUOTE>
+ Not longer used.
+ (I.e., used only for backward compatibility with the
+ obsolete INSTALLBIN rule.)
+</BLOCKQUOTE>
+
+ CC
+
+<BLOCKQUOTE>
+ C compiler used for Cc rule targets.
+</BLOCKQUOTE>
+
+ CCFLAGS
+
+<BLOCKQUOTE>
+ Compile flags for Cc rule targets.
+ The Cc rule sets target-specific $(CCFLAGS)
+ values on its targets.
+</BLOCKQUOTE>
+
+ C++
+
+<BLOCKQUOTE>
+ C++ compiler used for C++ rule targets.
+</BLOCKQUOTE>
+
+ C++FLAGS
+
+<BLOCKQUOTE>
+ Compile flags for C++ rule targets.
+ The C++ rule sets target-specific $(C++FLAGS)
+ values on its targets.
+</BLOCKQUOTE>
+
+ CHMOD
+
+<BLOCKQUOTE>
+ Program (usually chmod(1)) used to set file
+ permissions for Chmod rule.
+</BLOCKQUOTE>
+
+ CP
+
+<BLOCKQUOTE>
+ The file copy program, used by File and Install* rules.
+</BLOCKQUOTE>
+
+ CRELIB
+
+<BLOCKQUOTE>
+ If set, causes the Library rule to invoke the CreLib
+ rule on the target library before attempting to archive
+ any members, so that the library can be created if
+ needed.
+</BLOCKQUOTE>
+
+ CW
+
+<BLOCKQUOTE>
+ On Macintosh, the root of the Code Warrior Pro 5 directory.
+</BLOCKQUOTE>
+
+ DEFINES
+
+<BLOCKQUOTE>
+ Preprocessor symbol definitions for Cc and C++ rule targets.
+ The Cc and C++ rules set target-specific $(CCDEFS)
+ values on their targets, based on $(DEFINES). (The
+ "indirection" here is required to support compilers,
+ like VMS, with baroque command line syntax for
+ setting symbols).
+</BLOCKQUOTE>
+
+ DOT
+
+<BLOCKQUOTE>
+ The operating system-specific name for the current directory.
+</BLOCKQUOTE>
+
+ DOTDOT
+
+<BLOCKQUOTE>
+ The operating system-specific name for the parent directory.
+</BLOCKQUOTE>
+
+ EXEMODE
+
+<BLOCKQUOTE>
+ Permissions for executables linked with Link, Main,
+ and MainFromObjects, on platforms with a Chmod action.
+</BLOCKQUOTE>
+
+ FILEMODE
+
+<BLOCKQUOTE>
+ Permissions for files copied by File or Bulk,
+ on platforms with a Chmod action.
+</BLOCKQUOTE>
+
+ FORTRAN
+
+<BLOCKQUOTE>
+ The Fortran compiler used by Fortran rule.
+</BLOCKQUOTE>
+
+ FORTRANFLAGS
+
+<BLOCKQUOTE>
+ Fortran compiler flags for Fortran rule targets.
+</BLOCKQUOTE>
+
+ GROUP
+
+<BLOCKQUOTE>
+ <I>(Unix only.)</I>
+ The group owner for Install* rule targets.
+</BLOCKQUOTE>
+
+ HDRGRIST
+
+<BLOCKQUOTE>
+ If set, used by the HdrRule to distinguish header files
+ with the same name in diffrent directories.
+</BLOCKQUOTE>
+
+ HDRPATTERN
+
+<BLOCKQUOTE>
+ A regular expression pattern that matches
+ C preprocessor "#include" directives in source files
+ and returns the name of the included file.
+</BLOCKQUOTE>
+
+ HDRRULE
+
+<BLOCKQUOTE>
+ Name of the rule to invoke with the results of header file
+ scanning. Default is "HdrRule".
+ <P>
+ This is a jam-special variable. If both HDRRULE and HDRSCAN
+ are set on a target,
+ that target will be scanned for lines
+ matching $(HDRSCAN), and $(HDDRULE) will be
+ invoked on included files found in the matching $(HDRSCAN) lines.
+</BLOCKQUOTE>
+
+ HDRS
+
+<BLOCKQUOTE>
+ Directories to be searched for header files.
+ This is used by the Object rule to:
+ <UL>
+ <LI>set up search paths for finding files returned
+ by header scans
+ <LI>add -I flags on compile commands
+ </UL>
+ (See STDHDRS.)
+</BLOCKQUOTE>
+
+ HDRSCAN
+
+<BLOCKQUOTE>
+ Regular expression pattern to use for header file
+ scanning. The Object rule sets this to $(HDRPATTERN).
+ This is a jam-special variable; see HDRRULE.
+</BLOCKQUOTE>
+
+ HDRSEARCH
+
+<BLOCKQUOTE>
+ Used by the HdrRule to fix the list of directories where
+ header files can be found for a given source file.
+</BLOCKQUOTE>
+
+ INSTALLGRIST
+
+<BLOCKQUOTE>
+ Used by the Install* rules to grist paths to installed
+ files; defaults to "installed".
+</BLOCKQUOTE>
+
+ JAMFILE
+
+<BLOCKQUOTE>
+ Default is "Jamfile"; the name of the user-written
+ rules file found in each source directory.
+</BLOCKQUOTE>
+
+ JAMRULES
+
+<BLOCKQUOTE>
+ Default is "Jamrules"; the name of a rule definition
+ file to be read in at the first SubDir rule invocation.
+</BLOCKQUOTE>
+
+ KEEPOBJS
+
+<BLOCKQUOTE>
+ If set, tells the LibraryFromObjects rule not to delete
+ object files once they are archived.
+</BLOCKQUOTE>
+
+ LEX
+
+<BLOCKQUOTE>
+ The lex(1) command and flags.
+</BLOCKQUOTE>
+
+ LIBDIR
+
+<BLOCKQUOTE>
+ Not longer used.
+ (I.e., used only for backward compatibility with the
+ obsolete INSTALLLIB rule.)
+</BLOCKQUOTE>
+
+ LINK
+
+<BLOCKQUOTE>
+ The linker. Defaults to $(CC).
+</BLOCKQUOTE>
+
+ LINKFLAGS
+
+<BLOCKQUOTE>
+ Flags handed to the linker. Defaults to $(CCFLAGS).
+</BLOCKQUOTE>
+
+ LINKLIBS
+
+<BLOCKQUOTE>
+ List of external libraries to link with. The target image
+ does not depend on these libraries.
+</BLOCKQUOTE>
+
+ LN
+
+<BLOCKQUOTE>
+ The hard link command for HardLink rule.
+</BLOCKQUOTE>
+
+ LOCATE_SOURCE
+<BLOCKQUOTE>
+ Used to set the location of generated source files.
+ The Yacc, Lex, and GenFile rules set LOCATE on
+ their targets to $(LOCATE_SOURCE).
+ $(LOCATE_SOURCE) is initialized by the SubDir rule
+ to the source directory itself.
+ (Also, see ALL_LOCATE_TARGET.)
+</BLOCKQUOTE>
+
+ LOCATE_TARGET
+<BLOCKQUOTE>
+ Used to set the location of built binary targets.
+ The Object rule, and hence the Main and Library rules,
+ set LOCATE on their targets to $(LOCATE_TARGET).
+ $(LOCATE_TARGET) is initialized by the
+ SubDir rule to the source directory itself.
+ (See ALL_LOCATE_TARGET.)
+</BLOCKQUOTE>
+
+
+ MANDIR
+
+<BLOCKQUOTE>
+ Not longer used.
+ (I.e., used only for backward compatibility with the
+ obsolete INSTALLMAN rule.)
+</BLOCKQUOTE>
+
+ MKDIR
+
+<BLOCKQUOTE>
+ The 'create directory' command used for the MkDir
+ rule.
+</BLOCKQUOTE>
+
+ MODE
+
+<BLOCKQUOTE>
+ The target-specific file mode (permissions) for targets
+ of the Shell, Setuid, Link, and Install* rules.
+ Used by the Chmod action; hence relevant to NT and VMS
+ only.
+</BLOCKQUOTE>
+
+ MSVC
+<BLOCKQUOTE>
+ Selects Microsoft Visual C 16-bit compile & link
+ actions on NT.
+</BLOCKQUOTE>
+
+ MSVCNT
+<BLOCKQUOTE>
+ Selects Microsoft Visual C NT compile & link
+ actions on NT.
+</BLOCKQUOTE>
+
+
+ MV
+
+<BLOCKQUOTE>
+ The file rename command and options.
+</BLOCKQUOTE>
+
+ NEEDLIBS
+
+<BLOCKQUOTE>
+ The list of libraries used when linking an executable.
+ Used by the Link rule.
+</BLOCKQUOTE>
+
+ NOARSCAN
+
+<BLOCKQUOTE>
+ If set, indicates that library members' timestamps can't
+ be found, and prevents the individual objects from being
+ deleted, so that their timestamps can be used instead.
+</BLOCKQUOTE>
+
+ NOARUPDATE
+
+<BLOCKQUOTE>
+ If set, indicates that libraries can't be updated, but only
+ created whole.
+</BLOCKQUOTE>
+
+ OPTIM
+
+<BLOCKQUOTE>
+ The C compiler flag for optimization, used by Cc and C++
+ rules.
+</BLOCKQUOTE>
+
+ OSFULL
+
+<BLOCKQUOTE>
+ The concatenation of $(OS)$(OSVER)$(OSPLAT), used when jam
+ builds itself to determine the target binary directory.
+ $(OS) and $(OSPLAT) are determined by jam at its compile
+ time (in jam.h). $(OSVER) can optionally be set by the user.
+
+</BLOCKQUOTE>
+
+ OWNER
+
+<BLOCKQUOTE>
+ The owner of installed files. Used by Install* rules.
+</BLOCKQUOTE>
+
+ RANLIB
+
+<BLOCKQUOTE>
+ The name of the ranlib command. If set, causes
+ the Ranlib action to be applied after the
+ Archive action to targets of the Library rule.
+</BLOCKQUOTE>
+
+ RELOCATE
+
+<BLOCKQUOTE>
+ If set, tells the Cc rule to move the output object
+ file to its target directory because the cc command
+ has a broken -o option.
+</BLOCKQUOTE>
+
+ RM
+
+<BLOCKQUOTE>
+ The command and options to remove a file.
+</BLOCKQUOTE>
+
+ SEARCH_SOURCE
+
+<BLOCKQUOTE>
+ The directory to find sources listed with Main,
+ Library, Object, Bulk, File, Shell, InstallBin,
+ InstallLib, and InstallMan rules. This works by
+ setting the jam-special variable SEARCH to the
+ value of $(SEARCH_SOURCE) for each of the rules'
+ sources. The SubDir rule initializes SEARCH_SOURCE
+ for each directory.
+</BLOCKQUOTE>
+
+ SHELLHEADER
+
+<BLOCKQUOTE>
+ A string inserted to the first line of every file
+ created by the Shell rule.
+</BLOCKQUOTE>
+
+ SHELLMODE
+
+<BLOCKQUOTE>
+ Permissions for files installed by Shell rule.
+</BLOCKQUOTE>
+
+ SOURCE_GRIST
+
+<BLOCKQUOTE>
+ Set by the SubDir to a value derived from the
+ directory name, and used by Objects and related
+ rules as 'grist' to perturb file names.
+</BLOCKQUOTE>
+
+ STDHDRS
+
+<BLOCKQUOTE>
+ Directories where headers can be found without
+ resorting to using the flag to the C compiler.
+ The $(STDHDRS) directories are used to find
+ headers during scanning, but are not passed to the
+ compiler commands as -I paths.
+</BLOCKQUOTE>
+
+ SUBDIR
+
+<BLOCKQUOTE>
+ The path from the current directory to the directory
+ last named by the SubDir rule.
+</BLOCKQUOTE>
+
+ TOP
+
+<BLOCKQUOTE>
+ The path from the current directory to the directory
+ that has the Jamrules file. Used by the SubDir rule.
+</BLOCKQUOTE>
+
+ SUFEXE
+
+<BLOCKQUOTE>
+ The suffix for executable files, if none provided.
+ Used by the Main rule.
+</BLOCKQUOTE>
+
+ SUFLIB
+
+<BLOCKQUOTE>
+ The suffix for libraries. Used by the Library and
+ related rules.
+</BLOCKQUOTE>
+
+ SUFOBJ
+
+<BLOCKQUOTE>
+ The suffix for object files. Used by the Objects
+ and related rules.
+</BLOCKQUOTE>
+
+ UNDEFFLAG
+
+<BLOCKQUOTE>
+ The flag prefixed to each symbol for the Undefines
+ rule (i.e., the compiler flag for undefined symbols).
+</BLOCKQUOTE>
+
+ WATCOM
+<BLOCKQUOTE>
+ Selects Watcom compile and link actions on OS2.
+</BLOCKQUOTE>
+
+ YACC
+
+<BLOCKQUOTE>
+ The yacc(1) command.
+</BLOCKQUOTE>
+
+ YACCFILES
+
+<BLOCKQUOTE>
+ The base filename generated by yacc(1).
+</BLOCKQUOTE>
+
+ YACCFLAGS
+
+<BLOCKQUOTE>
+ The yacc(1) command flags.
+</BLOCKQUOTE>
+
+ YACCGEN
+
+<BLOCKQUOTE>
+ The suffix used on generated yacc(1) output.
+</BLOCKQUOTE>
+
+<P>
+<HR>
+<A HREF="#TOP">Back to top.</A>
+<P>
+ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ <BR>
+ Comments to <A HREF="mailto:info at perforce.com">info at perforce.com</A>
+ <BR>
+ Last updated: Dec 31, 2000
+ <BR>
+ $Id: Jambase.html,v 1.4 2002/04/07 00:22:45 david_abrahams Exp $
+</BODY>
+</HTML>
Added: boost-jam/boost-build/branches/upstream/current/jam_src/Jamfile.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/Jamfile.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/Jamfile.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1450 @@
+<HTML>
+<TITLE>
+Jamfiles and Jambase
+</TITLE>
+<BODY>
+<CENTER>
+<A HREF=http://www.perforce.com/jam/jam.html>
+Jam/MR
+</a>
+<A NAME="TOP">
+<H2>
+Using Jamfiles and Jambase
+</H2>
+</A>
+</CENTER>
+<P>
+This document describes how to write Jamfiles using the Jam/MR Jambase
+rules to build software products.
+Related documents of interest are:
+<UL>
+<LI>
+ <a href="Jam.html">The Jam/MR Executable Program</A>,
+ which describes using the <b>jam</b> command and the
+ langauge used in Jambase
+<LI>
+ <A href="Jambase.html">Jambase Reference</A>,
+ which summarizes the Jambase rules and variables
+</UL>
+<P>
+Jam/MR documentation and source are available from the
+<A HREF=http://public.perforce.com/public/index.html>Perforce Public Depot</a>.
+<HR>
+<P>
+<H2>
+Overview
+</H2>
+<P>
+ <B>jam,</B> the Jam executable program,
+ recursively builds target files from source files
+ using dependency and build specifications defined
+ in Jam rules files.
+ <B>jam</B> parses the rules files to identify targets
+ and sources,
+ examines the filesystem to determine which
+ targets need updating, and issues OS commands to update
+ targets.
+<P>
+ A base rules file called "Jambase" is provided with the
+ Jam distribution.
+ The Jambase file defines rules and variables which support
+ standard software build operations, like compiling, linking,
+ etc.
+<P>
+ When the Jambase rules are used,
+ <B>jam</B> reads Jambase, then reads a file called
+ "Jamfile" in the current directory.
+ The Jamfile describes what to do with the source files in
+ its directory. It may also cause
+ Jamfiles in other directories to be read.
+ <P>
+ Under certain circumstances, the first Jamfile read
+ also causes a site-specific "Jamrules" file to be read.
+ The Jamrules file is an optional set of rule and variable
+ definitions used to define site-specific processing.
+<P>
+<H4>
+The Basic Jamfile
+</H4>
+<P>
+Jamfiles contain rule invocations, which usually look like:
+<PRE>
+ <I>RuleName</I> <I>targets</I> : <I>targets</I> ;
+</PRE>
+The target(s) to the left of the colon usually indicate
+what gets built, and the target(s) to the right of the
+colon usually indicate what it is built from.
+<P>
+<P>
+A Jamfile can be as simple as this:
+<PRE>
+ Main myprog : main.c util.c ;
+</PRE>
+This specifies that there is a main.c and util.c file in the same
+directory as the Jamfile, and that those source files should be
+compiled and linked into an executable called myprog.
+If you cd to the directory where this Jamfile lives,
+you can see the exactly how <b>jam</b> would
+build myprog with:
+<PRE>
+ jam -n
+</PRE>
+Or, you can actually build myprog with the command:
+<PRE>
+ jam
+</PRE>
+
+<P>
+<H4>
+Whitespace
+</H4>
+Jamfile elements are delimited by whitespace (blanks, tabs, or
+newlines). Elements to be delimited include rule names, targets,
+colons, and semicolons. A common mistake users make is to forget the
+whitespace, e.g.,
+<PRE>
+ Main myprog: main.c util.c ; #<I>WRONG!</I>
+</PRE>
+Jam doesn't distinguish between a typo and a target called "myprog:",
+so if you get strange results, the first thing
+you should check for in your Jamfile is missing whitespace.
+<P>
+<H4>
+Filenames, Target Identifiers, and Buildable Targets
+</H4>
+<P>
+Consider this Jamfile:
+<PRE>
+ Main myprog : main.c util.c ;
+ LinkLibraries myprog : libtree ;
+ Library libtree : treemake.c treetrav.c ;
+</PRE>
+<P>
+The Main rule specifies that an executable called myprog will be built.
+The compiled main.c and util.c objects will be linked to produce
+myprog.
+The LinkLibraries rule specifies that libtree will
+be linked into myprog as well.
+The Library rule specifies which source files will be compiled and
+archived into the libtree library.
+<P>
+The Jamfile above refers to targets like "myprog" and "libtree".
+However, depending on the platform you're building on, the actual
+filenames of those targets could be "myprog.exe" and "libtree.lib".
+Most Jambase rules supply the actual filenames of targets,
+so that Jamfiles themselves need not make any
+platform-specific filename references.
+<P>
+The <b>jam</b> program builds up a list of unique target identifiers.
+Unless you are using the SubDir rules (described later),
+the default identifier for a file target is its filename. In the above
+example, the target identifiers are the filenames: myprog.exe,
+libtree.lib, main.obj, etc.
+<P>
+While all Jambase rules refer to "targets",
+not all targets are buildable.
+There are two kinds of buildable targets:
+file targets and pseudotargets.
+File targets are objects that can be found in the filesystem.
+Pseudotargets are symbolic, and represent other targets.
+<P>
+You can use any buildable target on the <b>jam</b> command line to
+build a subset of defined targets. For example:
+<PRE>
+ jam libtree.a
+</PRE>
+on Unix builds the libtree library and all the compiled objects
+that go in it.
+<P>
+<H4>
+Pseudotargets
+</H4>
+<P>
+Most Jambase rules that define file targets also define pseudotargets
+which are dependent on types of file targets.
+For example, Jambase defines a pseudotarget called "lib", which
+is dependent on file targets created by the Library rule. So
+the command:
+<PRE>
+ jam lib
+</PRE>
+used with the above example would cause the libtree library to be built.
+Also, there is one pseudotarget built into <b>jam</b> itself, called
+"all". Jambase sets "all" dependent on (almost) all other targets.
+<P>
+In the unfortunate case where you have a buildable target whose name
+is the same as one of the Jambase pseudotargets, you'll have problems
+with the conflicting target name.
+Your workaround choices are:
+<P>
+<ol>
+<lI>Change the name of your buildable file or directory that conflicts.
+<p>
+<li>Modify your Jambase and change the name of the conflicting pseudotarget.
+(Pseudotargets are defined in Jambase using the NOTFILE rule.)
+<p>
+<li>Use grist on the conflicting target name in your Jamfile. E.g., instead
+ of
+ <PRE>
+ File lib : libfoo.a ;
+ </PRE>
+ try
+ <PRE>
+ File <dir>lib : libfoo.a ;
+ </PRE>
+</ol>
+<P>
+
+<H4>
+Dependencies
+</H4>
+<P>
+Jambase rules set dependencies on targets, so that if you update a
+source file, all the file targets that depend on that source
+file, and only the ones that depend on that source file,
+will be updated (rebuilt) the next time you run <b>jam</b>.
+<P>
+Here are some of the dependencies
+that get set when <b>jam</b> runs on NT using the example Jamfile above:
+<CENTER>
+<TABLE>
+<TR><TD><B>Target</B><TD> <TD><B>Depends on</B></TD>
+<TR><TD>myprog.exe<TD><TD>main.obj, util.obj, libtree.lib
+<TR><TD>libtree.lib<TD><TD>treemake.obj, treetrav.obj
+<TR><TD>treetrav.obj<TD><TD>treetrav.c
+</TABLE>
+</CENTER>
+<P>
+Furthermore, the Main and Library rules set up recursive
+header scanning on their source targets.
+So after <b>jam</b> has finished parsing the Jamfile and
+setting the rule-driven dependencies, it scans the source
+files for "#include" lines. All #include files found during
+this scan become dependencies of the compiled object.
+E.g., all header files used to compile treetrav.c would
+be made dependencies of treetrav.obj.
+<P>
+As a result, when you run <b>jam</b>, it will rebuild targets
+if either the source files change or the
+header files change. You can't tell by looking at a Jamfile
+which header files are dependencies, but you can easily
+display those dependencies with:
+<PRE>
+ jam -nd+3
+</PRE>
+<H4>
+Rule Ordering
+</H4>
+<P>
+Rules which specify dependencies, like the Main, Library, and
+LinkLibrary rules, can be invoked in any order. <b>jam</b>
+figures out the order in which targets are built from
+their dependencies.
+<P>
+Some rules, however, set variables which are used by subsequent
+rule invocations, and their ordering is important.
+For example, the SubDir* rules (discussed
+later) must be invoked in a particular order.
+
+<P>
+<H4>
+Detailed Jambase Specifications
+</H4>
+<P>
+This document describes how to use various Jambase rules
+from a functional point of view.
+You can see the summary of available Jambase rules in the
+<a href="Jambase.html">Jambase Reference</A>.
+The detailed specifications for any Jambase rule
+can be found by reading the rule definition itself
+in the Jambase file.
+<P>
+
+<HR>
+<H2>
+Handling Directory Trees
+</H2>
+ The SubDir* rules are used to
+ define source code directory hierarchies.
+ With SubDir and SubInclude, you can use <b>jam</b>
+ to build software from source files and Jamfiles spread
+ across many directories, as is typical for large projects.
+ The SubDir* rules unify an entire
+ source code tree so that <b>jam</b> can read in
+ all the Jamfiles in one pass and
+ compute dependencies across the entire project.
+<P>
+ To use the SubDir* rules, you must:
+<P>
+<OL>
+ <LI> Preface the Jamfile in each directory with an invocation
+ of the SubDir rule.
+<P>
+ <LI> Place at the root of the tree a file named Jamrules.
+ This file could be empty, but in
+ practice it contains user-provided rules and variable
+ definitions that are shared throughout the
+ tree. Examples of such definitions are library
+ names, header directories, install directories,
+ compiler flags, etc. This file is good candidate
+ for automatic customizing with autoconf(GNU).
+<P>
+ <LI> Optionally, set an environment variable pointing
+ to the root directory of the srouce tree. The
+ variable's name is left up to you, but in these
+ examples, we use TOP.
+</OL>
+<P>
+<H4>
+ SubDir Rule
+</H4>
+<P>
+ The SubDir rule must be invoked before any rules that
+ refer to the contents of the directory - it is best to put
+ it at the top of each Jamfile. For example:
+<PRE>
+ # Jamfile in $(TOP)/src/util directory.
+
+ SubDir TOP src util ;
+
+ Main myprog : main.c util.c ;
+ LinkLibraries myprog : libtree ;
+ Library libtree : treemake.c treetrav.c ;
+</PRE>
+ This compiles four files in $(TOP)/src/util, archives
+ two of the objects into libtree, and links the whole
+ thing into myprog.
+ Outputs are placed in the $(TOP)/src/util
+ directory.
+ <P>
+ This doesn't appear to be any different from
+ the previous example that didn't have a SubDir rule,
+ but two things are happening behind the scenes:
+ <OL>
+ <LI>The SubDir rule causes <b>jam</b> to read
+ in the $(TOP)/Jamrules file.
+ (The Jamrules file can alternately be named by the
+ variable $(xxxRULES), where xxx is the name of the
+ root variable, e.g., $(TOPRULES)).
+ <P>
+ The Jamrules file can contain variable definitions
+ and rule definitions specific to your codeline.
+ It allows you to completely customize your build
+ environment without having to rewrite Jambase.
+ Jamrules is only read
+ in once, at the first SubDir invocation.
+ <P>
+ <LI>
+ The SubDir rule initializes a set of variables
+ that are used by Main and other rules to
+ uniquely identify the source files in this
+ directory and assign locations to the targets
+ built from files in this directory.
+ <P>
+ When you have set a root variable, e.g., $(TOP),
+ SubDir constructs path names rooted with $(TOP),
+ e.g., $(TOP)/src/util.
+ Otherwise, SubDir constructs relative pathnames
+ to the root directory, computed from the number
+ of arguments to the first SubDir rule, e.g.,
+ ../../src/util. In either case, the SubDir
+ rule constructs the path names that locate source
+ files.
+ You'll see how this is useful later.
+ <P>
+ </UL>
+
+<P>
+ The SubDir rule takes as its first argument the root
+ variable's name and takes as subsequent arguments the
+ directory names leading from the root to the directory of
+ the current Jamfile. Note that the name of the subdirectory
+ is given as individual elements: the SubDir rule
+ does not use system-specific directory name syntax.
+<P>
+<P>
+<H4>
+ SubInclude Rule
+</H4>
+ The SubInclude rule is used in a Jamfile to cause another
+ Jamfile to be read in.
+ Its arguments are in the same format as
+ SubDir's.
+<P>
+ The recommended practice is only to include one level of
+ subdirectories at a time, and let the Jamfile in each subdirectory
+ include its own subdirectories. This allows a
+ user to sit in any arbitrary directory of the source tree
+ and build that subtree. For example:
+<PRE>
+ # This is $(TOP)/Jamfile, top level Jamfile for mondo project.
+
+ SubInclude TOP src ;
+ SubInclude TOP man ;
+ SubInclude TOP misc ;
+ SubInclude TOP util ;
+</PRE>
+ If a directory has both subdirectories of its own as well
+ as files that need building, the SubIncludes should be
+ either before the SubDir rule or be at the end of the Jamfile
+ - not between the SubDir and other rule invocations.
+ For example:
+<PRE>
+ # This is $(TOP)/src/Jamfile:
+
+ SubDir TOP src ;
+
+ Main mondo : mondo.c ;
+ LinkLibraries mondo : libmisc libutil ;
+
+ SubInclude TOP src misc ;
+ SubInclude TOP src util ;
+</PRE>
+<P>
+ (<b>jam</b> processes all the Jamfiles it reads as if
+ it were reading one single, large Jamfile.
+ Build rules like Main and LinkLibraries rely on the
+ preceding SubDir rule to set up source file and
+ output file locations, and SubIncludes rules read in
+ Jamfiles that contain SubDir rules. So if you put
+ a SubIncludes rule between a SubDir and a Main
+ rule, <b>jam</b> will try to find the source files
+ for the Main rule in the wrong directory.)
+<P>
+<H4>
+ Variables Used to Handle Directory Trees
+</H4>
+ The following variables are set by the SubDir rule
+ and used by the Jambase rules that define file targets:
+<P>
+<CENTER>
+<TABLE>
+<TR><TD VALIGN=TOP>
+ SEARCH_SOURCE
+ <TD><TD>The SubDir targets (e.g., "TOP src util")
+ are used to construct a pathname (e.g., $(TOP)/src/util),
+ and that pathname is assigned to $(SEARCH_SOURCE).
+ Rules like Main and Library use $(SEARCH_SOURCE)
+ to set search paths on source files.
+<TR><TD VALIGN=TOP>
+ LOCATE_SOURCE
+ <TD><TD>Initialized by the SubDir rule to the same
+ value as $(SEARCH_SOURCE), unless ALL_LOCATE_TARGET
+ is set.
+ $(LOCATE_SOURCE) is used by rules that build
+ generated source files (e.g., Yacc and Lex) to
+ set location of output files.
+ Thus the default location of built source files
+ is the directory of the Jamfile that defines them.
+<TR><TD VALIGN=TOP>
+ LOCATE_TARGET
+ <TD><TD>Initalized by the SubDir rule to the same
+ value as $(SEARCH_SOURCE), unless ALL_LOCATE_TARGET
+ is set.
+ $(LOCATE_TARGET) is used by rules that build
+ binary objects (e.g., Main and Library) to
+ set location of output files.
+ Thus the default location of built binaray files
+ is the directory of the Jamfile that defines them.
+<TR><TD VALIGN=TOP>
+ ALL_LOCATE_TARGET
+ <TD><TD>
+ If $(ALL_LOCATE_TARGET) is set, LOCATE_SOURCE
+ and and LOCATE_TARGET are set to $(ALL_LOCATE_TARGET)
+ instead of to $(SEARCH_SOURCE). This can be used to
+ direct built files to be written to a location outside
+ of the source tree, and enables building from read-only
+ source trees.
+<TR><TD VALIGN=TOP>
+ SOURCE_GRIST
+ <TD><TD>The SubDir targets are formed into a string
+ like "src!util" and that string is assigned to
+ SOURCE_GRIST. Rules that define file targets
+ use $(SOURCE_GRIST) to set the "grist" attribute
+ on targets. This is used to assure uniqueness
+ of target identifiers where filenames themselves
+ are not unique.
+ For example, the target identifiers of
+ $(TOP)/src/client/main.c and $(TOP)/src/server/main.c
+ would be <src!client>main.c and <src!server>main.c.
+</TABLE>
+</CENTER>
+<P>
+ The $(LOCATE_TARGET) and $(SEARCH_SOURCE) variables are used
+ extensively by rules in Jambase: most rules that generate
+ targets (like Main, Object, etc.) set $(LOCATE) to
+ $(LOCATE_TARGET) for the targets they generate, and rules
+ that use sources (most all of them) set $(SEARCH) to be
+ $(SEARCH_SOURCE) for the sources they use.
+<P>
+ $(LOCATE) and $(SEARCH) are better explained in
+ <A HREF="Jam.html">The Jam Executable Program</A>
+ but in brief they tell <B>jam</B> where to create new targets and
+ where to find existing ones, respectively.
+<P>
+ Note that you can reset these variables
+ after SubDir sets them. For example, this Jamfile builds
+ a program called gensrc, then runs it to create a source file
+ called new.c:
+ <PRE>
+ SubDir TOP src util ;
+ Main gensrc : gensrc.c ;
+ LOCATE_SOURCE = $(NEWSRC) ;
+ GenFile new.c : gensrc ;
+ </PRE>
+ By default, new.c would be written into the
+ $(TOP)/src/util directory, but resetting LOCATE_SOURCE causes
+ it to be written to the $(NEWSRC) directory. ($(NEWSRC) is assumed
+ to have been set elsewhere, e.g., in Jamrules.)
+<P>
+<H4>
+ VMS Notes
+</H4>
+ On VMS, the logical name table is not imported as is the
+ environment on UNIX. To use the SubDir and related rules,
+ you must set the value of the variable that names the root
+ directory. For example:
+<PRE>
+ TOP = USR_DISK:[JONES.SRC] ;
+
+ SubInclude TOP util ;
+</PRE>
+ The variable must have a value that looks like a directory
+ or device. If you choose, you can use a concealed logical.
+ For example:
+<PRE>
+ TOP = TOP: ;
+
+ SubInclude TOP util ;
+</PRE>
+ The : at the end of TOP makes the value of $(TOP) look
+ like a device name, which jam respects as a directory name
+ and will use when trying to access files. TOP must then
+ be defined from DCL:
+<PRE>
+ $ define/job/translation=concealed TOP DK100:[USERS.JONES.SRC.]
+</PRE>
+ Note three things: the concealed translation allows the
+ logical to be used as a device name; the device name in
+ the logical (here DK100) cannot itself be concealed logical
+ (VMS rules, man); and the directory component of the
+ definition must end in a period (more VMS rules).
+<P>
+<H2>
+Building Executables and Libraries
+</H2>
+<P>
+The rules that build executables and libraries are: Main, Library,
+and LinkLibraries.
+<H4>
+ Main Rule
+</H4>
+ The Main rule compiles source files and links the resulting
+ objects into an executable. For example:
+<PRE>
+ Main myprog : main.c util.c ;
+</PRE>
+ This compiles main.c and util.c and links main.o and
+ util.o into myprog. The object files and resulting
+ executable are named appropriately for the platform.
+<P>
+ Main can also be used to build shared libraries and/or
+ dynamic link libraries, since those are also linked
+ objects. E.g.:
+ <PRE>
+ Main driver$(SUFSHR) : driver.c ;
+ </PRE>
+ Normally, Main uses $(SUFEXE) to determine the suffix on
+ the filename of the built target. To override it,
+ you can supply a suffix explicity.
+ In this case,
+ $(SUFSHR) is assumed to be the OS-specific shared library
+ suffix, defined in Jamrules with something
+ like:
+ <PRE>
+ if $(UNIX) { SUFSHR = .so ; }
+ else if $(NT) { SUFSHR = .dll ; }
+ </PRE>
+ <P>
+ Main uses the Objects rule to compile source targets.
+
+<H4>
+ Library Rule
+</H4>
+ The Library rule compiles source files, archives the
+ resulting object files into a library, and then deletes
+ the object files. For example:
+<PRE>
+ Library libstring : strcmp.c strcpy.c strlen.c ;
+ Library libtree : treemake.c treetrav.c ;
+</PRE>
+ This compiles five source files, archives three of the
+ object files into libstring and the other two into libtree.
+ Actual library filenames are formed with the $(SUFLIB) suffix.
+ Once the objects are safely in the libraries, the
+ objects are deleted.
+ <P>
+ Library uses the Objects rule to compile source files.
+<P>
+<H4>
+ LinkLibraries Rule
+</H4>
+ To link executables with built libraries, use
+ the LinkLibraries rule. For example:
+<PRE>
+ Main myprog : main.c util.c ;
+ LinkLibraries myprog : libstring libtree ;
+</PRE>
+ The LinkLibraries rule does two things: it makes the
+ libraries dependencies of the executable, so that they get
+ built first; and it makes the libraries show up on the
+ command line that links the executable. The ordering of
+ the lines above is not important, because <b>jam</b> builds targets
+ in the order that they are needed.
+<P>
+ You can put multiple libraries on a single invocation of
+ the LinkLibraries rule, or you can provide them in multiple
+ invocations. In both cases, the libraries appear on
+ the link command line in the order in which they were
+ encountered. You can also provide multiple executables to
+ the LinkLibraries rule, if they need the same libraries,
+ e.g.:
+ <PRE>
+ LinkLibraries prog1 prog2 prog3 : libstring libtree ;
+ </PRE>
+<P>
+<H4>
+ Variables Used in Building Executables and Libraries
+</H4>
+<CENTER>
+<TABLE>
+<TR><TD>
+ AR
+ <TD><TD>Archive command, used for Library targets.
+<TR><TD>
+ SUFEXE
+ <TD>*<TD>Suffix on filenames of executables referenced
+ by Main and LinkLibraries.
+<TR><TD>
+ LINK
+ <TD><TD>Link command, used for Main targets.
+<TR><TD>
+ LINKFLAGS
+ <TD><TD>Linker flags.
+<TR><TD>
+ LINKLIBS
+ <TD><TD>Link libraries that aren't dependencies. (See note
+ below.)
+<TR><TD>
+ EXEMODE
+ <TD>*<TD>File permissions on Main targets.
+<TR><TD>
+ MODE
+ <TD><TD>Target-specific file permissions on Main targets
+ (set from $(EXEMODE))
+<TR><TD>
+ RANLIB
+ <TD><TD>Name of ranlib program, if any.
+</TABLE>
+</CENTER>
+
+<P>
+ Variables above marked with "*" are used by the Main,
+ Library, and LinkLibraries rules. Their values at the
+ time the rules are invoked are used to set target-specific
+ variables.
+ <P>
+ All other variables listed above are globally defined,
+ and are used in actions that update Main and Library
+ targets. This means that the global values of those
+ variables are used, uness target-specific values have
+ been set.
+ (For instance, a target-specific MODE value is set by
+ the Main rule.)
+ The target-specific values always override
+ global values.
+<P>
+ Note that there are two ways to specify link libraries for
+ executables:
+ <UL>
+ <LI>Use the LinkLibraries rule
+ to specify built libraries; i.e., libraries
+ that are built by Library rules. This assures that
+ these libraries are built first, and that Main targets are
+ rebuilt when the libraries are updated.
+ <P>
+ <LI>Use the LINKLIBS variable to specify external
+ libraries; e.g., system libraries or third-party libraries.
+ The LINKLIBS variable must be set to the the actual
+ link command flag that specifies the libraries.
+ <P>
+ </UL>
+ <P>
+ For example:
+<PRE>
+ <I>#In Jamrules:</I>
+ if $(UNIX) { X11LINKLIBS = -lXext -lX11 ; }
+ if $(NT) { X11LINKLIBS = libext.lib libX11.lib ; }
+
+ <I>#In Jamfile:</I>
+ Main xprog : xprog.c ;
+ LINKLIBS on xprog$(SUFEXE) = $(X11LINKLIBS) ;
+ LinkLibraries xprog : libxutil ;
+ Library libxutil : xtop.c xbottom.c xutil.c ;
+</PRE>
+ This example uses the Jam syntax "variable on target" to
+ set a target-specific variable. In this way, only xprog
+ will be linked with this special $(X11LINKLIBS),
+ even if other executables were going to be built
+ by the same Jamfile. Note that when you set a variable
+ on a target, you have to specify the target identifer
+ exactly, which in this case is the suffixed filename of
+ the executable.
+ The actual link command line on Unix, for example, would
+ look something like this:
+<PRE>
+ cc -o xprog xprog.o libxutil.a -lXext -lX11
+</PRE>
+<H2>
+Compiling
+</H2>
+ Compiling of source files occurs normally as a byproduct
+ of the Main or Library rules, which call the rules
+ described here. These rules may also be called explicitly
+ if the Main and Library behavior doesn't satisfy your
+ requirements.
+<P>
+<H4>
+ Objects Rule
+</H4>
+ The Main and Library rules call the Objects rule on source files.
+ Compiled object files built by
+ the Objects rule are a dependency of the <I>obj</i>
+ pseudotarget, so "jam obj" will build object files used in
+ Main and Library rules.
+ <P>
+ Target identifiers created by the Objects rule have grist
+ set to $(SOURCE_GRIST). So given this Jamfile:
+ <PRE>
+ SubDir TOP src lock ;
+ Main locker : lock.c ;
+ </PRE>
+ the object file created is lock.o (or lock.obj) and
+ its target identifier is <src!lock>lock.o
+ (or <src!lock>lock.obj).
+
+ <P>
+ You can also call Objects directly. For example:
+<PRE>
+ Objects a.c b.c c.c ;
+</PRE>
+ This compiles a.c into a.o, b.c into b.o, etc. The object
+ file suffix is supplied by the Objects rule.
+<P>
+<H4>
+ Object Rule
+</H4>
+ Objects gets its work done by calling the Object rule on
+ each of the source files.
+ You could use the Object rule directly.
+ For example, on Unix, you could use:
+<PRE>
+ Object foo.o : foo.c ;
+</PRE>
+ However, the Object rule does not provide suffixes, and
+ it does not provide the grist needed to construct target
+ identifiers if you are using the SubDir* rules.
+ A portable and robust Jamfile would need to invoke Object thus:
+ <PRE>
+ Object <src!util>foo$(SUFOBJ) : <src!util>foo.c ;
+ </PRE>
+ which is inelegant and clearly shows why using Objects
+ is better than using Object.
+ <P>
+ If there's any advantage to the Object rule, it's
+ that it doesn't require that the object name bear
+ any relationship to the source. It is thus possible to
+ compile the same file into different objects. For example:
+
+<PRE>
+ Object a.o : foo.c ;
+ Object b.o : foo.c ;
+ Object c.o : foo.c ;
+</PRE>
+ This compiles foo.c (three times) into a.o, b.o, and c.o.
+ Later examples show how this is useful.
+<P>
+ The Object rule looks at the suffix of the source file and
+ calls the appropriate rules to do the actual preprocessing
+ (if any) and compiling needed to produce the output object file.
+ The Object rule is
+ capable of the generating of an object file from any
+ type of source. For example:
+<PRE>
+ Object grammar$(SUFOBJ) : grammar.y ;
+ Object scanner$(SUFOBJ) : scanner.l ;
+ Object fastf$(SUFOBJ) : fastf.f ;
+ Object util$(SUFOBJ) : util.c ;
+</PRE>
+ An even more elegant way to get the same result is to let the
+ Objects rule call Object:
+ <PRE>
+ Objects grammar.y scanner.l fastf.f util.c ;
+ </PRE>
+ <P>
+ In addition to calling the compile rules, Object sets up
+ a bunch of variables specific to the source and target
+ files. (See Variables Used in Compiling, below.)
+<P>
+<H4>
+ Cc, C++, Yacc, Lex, Fortran, As, etc. Rules
+</H4>
+<P>
+ The Object rule calls compile rules specific to the suffix of
+ the source file. (You can see which suffixes are supported
+ by looking at the Object rule definition in Jambase.)
+ Because the extra work done by the
+ Object rule, it is not always useful to call the compile
+ rules directly. But the adventurous user might attempt
+ it. For example:
+<PRE>
+ Yacc grammar.c : grammar.y ;
+ Lex scan.c : scan.l ;
+ Cc prog.o : prog.c ;
+</PRE>
+ These examples individually run yacc(1), lex(1), and the C
+ compiler on their sources.
+<P>
+<H4>
+ UserObject Rule
+</H4>
+ Any files with suffixes not understood by the Object rule
+ are passed to the UserObject rule. The default definition
+ of UserObject simply emits a warning that the suffix is
+ not understood. This Jambase rule definition is intended to be
+ overridden in Jamrules with one that recognizes the project-specific
+ source file suffixes. For example:
+
+<PRE>
+ #In Jamrules:
+
+ rule UserObject
+ {
+ switch $(>)
+ {
+ case *.rc : ResourceCompiler $(<) : $(>) ;
+ case * : ECHO "unknown suffix on" $(>) ;
+ }
+ }
+
+ rule ResourceCompiler
+ {
+ DEPENDS $(<) : $(>) ;
+ Clean clean : $(<) ;
+ }
+
+ actions ResourceCompiler
+ {
+ rc /fo $(<) $(RCFLAGS) $(>)
+ }
+
+
+ #In Jamfile:
+
+ Library liblock : lockmgr.c ;
+ if $(NT) { Library liblock : lock.rc ; }
+</PRE>
+<P>
+ In this example, the UserObject definition in Jamrules
+ allows *.rc files to be handle as regular Main and Library
+ sources. The lock.rc file is compiled into lock.obj
+ by the "rc" command, and lock.obj is archived into a library
+ with other compiled objects.
+<H4>
+ LibraryFromObjects Rule
+</H4>
+ Sometimes the Library rule's straightforward compiling of
+ source into object modules to be archived isn't flexible
+ enough. The LibraryFromObjects rule does the archiving
+ (and deleting) job of the Library rule, but not the compiling.
+ The user can make use of the Objects or Object
+ rule for that. For example:
+<PRE>
+ LibraryFromObjects libfoo.a : max.o min.o ;
+ Object max.o : maxmin.c ;
+ Object min.o : maxmin.c ;
+ ObjectCcFlags max.o : -DUSEMAX ;
+ ObjectCcFlags min.o : -DUSEMIN ;
+</PRE>
+ This Unix-specific example compiles the same source file into
+ two different
+ objects, with different compile flags, and archives them.
+ (The ObjectCcFlags rule is described shortly.)
+ Unfortunately, the portable and robust implementation of the
+ above example is not as pleasant to read:
+ <PRE>
+ SubDir TOP foo bar ;
+ LibraryFromObjects libfoo$(SUFLIB) : <foo!bar>max$(SUFOBJ)
+ <foo!bar>min$(SUFOBJ) ;
+ Object <foo!bar>min$(SUFOBJ) : <foo!bar>maxmin.c ;
+ Object <foo!bar>max$(SUFOBJ) : <foo!bar>maxmin.c ;
+ ObjectCcFlags <foo!bar>min$(SUFOBJ) : -DUSEMIN ;
+ ObjectCcFlags <foo!bar>max$(SUFOBJ) : -DUSEMAX ;
+ </PRE>
+ Note that, among other things, you must supply the library
+ file suffix when using the LibraryFromObjects rule.
+<P>
+<H4>
+ MainFromObjects Rule
+</H4>
+ Similar to LibraryFromObjects, MainFromObjects does the
+ linking part of the Main rule, but not the compiling.
+ MainFromObjects can be used when there are no
+ objects at all, and everything is to be loaded from
+ libraries. For example:
+<PRE>
+ MainFromObjects testprog ;
+ LinkLibraries testprog : libprog ;
+ Library libprog : main.c util.c ;
+</PRE>
+ On Unix, say, this generates a link command that looks like:
+<PRE>
+ cc -o testprog libprog.a
+</PRE>
+ Linking purely from libraries is something that doesn't
+ work everywhere: it depends on the symbol "main" being
+ undefined when the linker encounters the library that contains
+ the definition of "main".
+<P>
+<H4>
+ Variables Used in Compiling
+</H4>
+ The following variables control the compiling of source
+ files:
+<P>
+<CENTER>
+<TABLE>
+<TR><TD VALIGN=TOP>
+ C++
+ <TD><TD>The C++ compiler command
+<TR><TD VALIGN=TOP>
+ CC
+ <TD><TD>The C compiler command
+<TR><TD VALIGN=TOP>
+ C++FLAGS
+ <BR>
+ CCFLAGS
+ <TD VALIGN=TOP><TD VALIGN=TOP>Compile flags, used to
+ create or update compiled objects
+<TR><TD>
+ SUBDIRC++FLAGS
+ <BR>
+ SUBDIRCCFLAGS
+ <TD VALIGN=TOP><TD VALIGN=TOP>Additonal compile flags
+ for source files in this directory.
+<TR><TD VALIGN=TOP>
+ OPTIM
+ <TD><TD>Compiler optimization flag. The Cc and C++
+ actions use this as well as C++FLAGS or CCFLAGS.
+<TR><TD VALIGN=TOP>
+ HDRS
+ <TD VALIGN=TOP><TD>Non-standard header directories; i.e.,
+ the directories the compiler will not look in
+ by default and which therefore must be supplied
+ to the compile command. These directories are
+ also used by <b>jam</b> to scan for include files.
+<TR><TD VALIGN=TOP>
+ STDHDRS
+ <TD VALIGN=TOP><TD>Standard header directories, i.e., the
+ directories the compiler searches automatically.
+ These are not passed to the compiler, but they
+ are used by <b>jam</b> to scan for include files.
+<TR><TD>
+ SUBDIRHDRS
+ <TD><TD>Additional paths to add to HDRS for source files
+ in this directory.
+<TR><TD>
+ LEX
+ <TD><TD>The lex(1) command
+<TR><TD>
+ YACC
+ <TD><TD>The yacc(1) command
+</TABLE>
+</CENTER>
+<P>
+ The Cc rule sets a target-specific $(CCFLAGS) to the current
+ value of $(CCFLAGS) and $(SUBDIRCCFLAGS). Similarly
+ for the C++ rule. The Object rule sets a target-specific
+ $(HDRS) to the current value of $(HDRS) and $(SUBDDIRHDRS).
+
+<P>
+ $(CC), $(C++), $(CCFLAGS), $(C++FLAGS), $(OPTIM), and
+ $(HDRS) all affect the compiling of C and C++ files.
+ $(OPTIM) is separate from $(CCFLAGS) and $(C++FLAGS) so
+ they can be set independently.
+<P>
+ $(HDRS) lists the directories to search for header files,
+ and it is used in two ways: first, it is passed to the C
+ compiler (with the flag -I prepended); second, it is used
+ by HdrRule to locate the header files whose names were
+ found when scanning source files. $(STDHDRS) lists the
+ header directories that the C compiler already knows
+ about. It does not need passing to the C compiler, but is
+ used by HdrRule.
+<P>
+ Note that these variables, if set as target-specific variables,
+ must be set on the target, not the source file.
+ The target file in this case is the object file to be generated.
+ For example:
+<PRE>
+ Library libximage : xtiff.c xjpeg.c xgif.c ;
+
+ HDRS on xjpeg$(SUFOBJ) = /usr/local/src/jpeg ;
+ CCFLAGS on xtiff$(SUFOBJ) = -DHAVE_TIFF ;
+</PRE>
+ This can be done more easily with the rules that follow.
+<P>
+<H4>
+ ObjectCcFlags, ObjectC++Flags, ObjectHdrs Rules
+</H4>
+ $(CCFLAGS), $(C++FLAGS) and $(HDRS) can be set on object file
+ targets
+ directly, but there are rules that allow these variables
+ to be set by referring to the original source file name,
+ rather than to the derived object file name. ObjectCcFlags
+ adds object-specific flags to the $(CCFLAGS) variable,
+ ObjectC++Flags adds object-specific flags to the
+ $(C++FLAGS) variable, and ObjectHdrs add object-specific
+ directories to the $(HDRS) variable. For example:
+<PRE>
+ #In Jamrules:
+ if $(NT) { CCFLAGS_X = /DXVERSION ;
+ HDRS_X = \\\\SPARKY\\X11\\INCLUDE\\X11 ;
+ }
+
+ #In Jamfile:
+ Main xviewer : viewer.c ;
+ ObjectCcFlags viewer.c : $(CCFLAGS_X) ;
+ ObjectHdrs viewer.c : $(HDRS_X) ;
+</PRE>
+ The ObjectCcFlags and ObjectHdrs rules take .c files
+ as targets, but actually set $(CCFLAGS) and $(HDRS) values
+ on the .obj (or .o) files. As a result, the action
+ that updates the target .obj file uses the target-specific
+ values of $(CCFLAGS) and $(HDRS).
+<P>
+<H4>
+ SubDirCcFlags, SubDirC++Flags, SubDirHdrs Rules
+</H4>
+ These rules set the values of $(SUBDIRCCFLAGS), $(SUBDIRC++FLAGS)
+ and $(SUBDIRHDRS), which are used by the Cc,
+ C++, and Object rules when setting the target-specific
+ values for $(CCFLAGS), $(C++FLAGS) and $(HDRS). The SubDir
+ rule clears these variables out, and thus they provide
+ directory-specific values of $(CCFLAGS), $(C++FLAGS) and
+ $(HDRS). For example:
+<PRE>
+ #In Jamrules:
+ GZHDRS = $(TOP)/src/gz/include ;
+ GZFLAG = -DGZ ;
+
+ #In Jamfile:
+ SubDir TOP src gz utils ;
+
+ SubDirHdrs $(GZHDRS) ;
+ SubDirCcFlags $(GZFLAG) ;
+
+ Library libgz : gizmo.c ;
+ Main gizmo : main.c ;
+ LinkLibraries gizmo : libgz ;
+</PRE>
+ All .c files in this directory files will be compiled with
+ $(GZFLAG) as well as the default $(CCFLAG), and the include
+ paths used on the compile command will be $(GZHDRS) as well
+ as the default $(HDRS).
+<H2>
+Header File Processing
+</H2>
+ One of the functions of the Object rule is set up
+ scanning of source
+ files for (C style) header file inclusions. To do so, it
+ sets the special variables $(HDRSCAN) and $(HDRRULE)
+ as target-specific variables on the source file. The
+ presence of these variables triggers a special mechanism
+ in <B>jam</B> for scanning a file for header file inclusions and
+ invoking a rule with the results of the scan. The
+ $(HDRSCAN) variable is set to an egrep(1) pattern that
+ matches "#include" statements in C source files, and the
+ $(HDRRULE) variable is set to the name of the rule that
+ gets invoked as such:
+<PRE>
+ $(HDRRULE) source-file : included-files ;
+</PRE>
+ This rule is supposed to set up the dependencies between
+ the source file and the included files. The Object rule
+ uses HdrRule to do the job. HdrRule itself expects
+ another variable, $(HDRSEARCH), to be set to the list of
+ directories where the included files can be found. Object
+ does this as well, setting $(HDRSEARCH) to $(HDRS) and
+ $(STDHDRS).
+<P>
+ The header file scanning occurs during the "file binding"
+ phase of <b>jam</b>, which means that the target-specific
+ variables (for the source file) are in effect. To accomodate
+ nested includes, one of the HdrRule's jobs is to pass
+ the target-specific values of $(HDRRULE), $(HDRSCAN), and
+ $(HDRSEARCH) onto the included files, so that they will be
+ scanned as well.
+<P>
+<H4>
+ HdrRule Rule
+</H4>
+ Normally, HdrRule is not invoked directly; the Object rule
+ (called by Main and Library) invokes it.
+ <P>
+ If there are special dependencies that need to be set,
+ and which are not set by HdrRule itself, you can define
+ another rule and let it invoke HdrRule. For example:
+
+<PRE>
+ #In Jamrules:
+ rule BuiltHeaders
+ {
+ DEPENDS $(>) : mkhdr$(SUFEXE) ;
+ HdrRule $(<) : $(>) ;
+ }
+
+ #In Jamfile:
+ Main mkhdr : mkhdr.c ;
+ Main ugly : ugly.c ;
+
+ HDRRULE on ugly.c = BuiltHeaders ;
+
+</PRE>
+ This example just says that the files included by "ugly.c"
+ are generated by the program "mkhdr", which can be built
+ from "mkhdr.c". During the binding phase, <b>jam</b> will
+ scan ugly.c, and if it finds an include file, ughdr.h,
+ for example, it will automatically invoke the rule:
+ <PRE>
+ BuiltHeaders ugly.c : ughdr.h ;
+ </PRE>
+ By calling HdrRule at the end of BuiltHeaders,
+ all the gadgetry of HdrRule takes effect and it
+ doesn't need to be duplicated.
+<P>
+<H4>
+ Variables Used for Header Scanning
+</H4>
+<CENTER>
+<TABLE>
+<TR><TD VALIGN=TOP>
+ HDRPATTERN
+ <TD><TD>Default scan pattern for "include" lines.
+<TR><TD VALIGN=TOP>
+ HDRSCAN
+ <TD><TD>Scan pattern to use.
+ This is a special variable: during binding, if
+ both HDRSCAN and HDRRULE are set, scanning is activated
+ on the target being bound.
+ The HdrRule and Object rules sets this
+ to $(HDRPATTERN) on their source targets.
+<TR><TD VALIGN=TOP>
+ HDRRULE
+ <TD><TD>Name of rule to invoked on files found in header
+ scan. The HdrRule and Object rules set this to "HdrRule"
+ on their source targets. This is also a special variable;
+ it's the only <b>jam</b> variable that can hold the
+ name of a rule to be invoked.
+<TR><TD VALIGN=TOP>
+ HDRSEARCH
+ <TD><TD>Search paths for files found during header scanning.
+ This is set from $(HDRS) and $(STDHDRS), which are
+ described in the Compiling section.
+ <b>jam</b> will search $(HDRSEARCH) directories for
+ the files found by header scans.
+</TABLE>
+</CENTER>
+<P>
+ The Object rule sets HDRRULE and HDRSCAN specifically for
+ the source files to be scanned, rather than globally. If
+ they were set globally, jam would attempt to scan all
+ files, even library archives and executables, for header
+ file inclusions. That would be slow and probably not
+ yield desirable results.
+<P>
+<H2>
+Copying Files
+</H2>
+<H4>
+ File Rule
+</H4>
+ The File rule copies one file to another. The target name
+ needn't be the same as the source name. For
+ example:
+<PRE>
+ switch $(OS)
+ {
+ case NT* : File config.h : confignt.h ;
+ case * : File config.h : configunix.h ;
+ }
+ LOCATE on config.h = $(LOCATE_SOURCE) ;
+</PRE>
+ This creates a config.h file from either confignt.h or
+ configunix.h, depending on the current build platform.
+<P>
+ The File rule does not
+ use the LOCATE_SOURCE variable set by the
+ SubDir rule (although it does use SEARCH_SOURCE), which
+ means you have to set the copied file's output directory
+ yourself. That's done by setting the special
+ LOCATE variable on the target, as shown above,
+ or with the MakeLocate rule described below.
+<H4>
+ Bulk Rule
+</H4>
+ The Bulk rule is a shorthand for many invocations of the
+ File rule when all files are going to the same directory.
+ For example:
+<PRE>
+ #In Jamrules:
+ DISTRIB_GROB = d:\\distrib\\grob ;
+
+ #In Jamfile:
+ Bulk $(DISTRIB_GROB) : grobvals.txt grobvars.txt ;
+</PRE>
+ This causes gobvals.txt and grobvars.txt to be copied
+ into the $(DISTRIB_GROB) directory.
+<H4>
+ HardLink Rule
+</H4>
+ The Unix-only HardLink rule makes a hard link (using ln(1)) from the
+ source to the target, if there isn't one already. For
+ example:
+<PRE>
+ HardLink config.h : configunix.h ;
+</PRE>
+<H4>
+ Shell Rule
+</H4>
+ The Shell rule is like the File rule, except that on Unix it makes
+ sure the first line of the target is "#!/bin/sh" and sets
+ the permission to make the file executable. For example:
+<PRE>
+ Shell /usr/local/bin/add : add.sh ;
+</PRE>
+<P>
+ You can also use $(SHELLHEADER) to dictate
+ what the first line of the copied file will be.
+ For
+ example:
+<PRE>
+ Shell /usr/local/bin/add : add.awk ;
+ SHELLHEADER on /usr/local/bin/add = "#!/bin/awk -f" ;
+</PRE>
+ This installs an awk(1) script.
+<P>
+<H4>
+ Variables Used When Copying Files
+</H4>
+<CENTER>
+<TABLE>
+<TR><TD VALIGN=TOP>
+ FILEMODE
+ <TD><TD>Default file permissions for copied files
+<TR><TD VALIGN=TOP>
+ SHELLMODE
+ <TD><TD>Default file permissions for Shell rule targets
+<TR><TD VALIGN=TOP>
+ MODE
+ <TD><TD>File permissions set on files copied by
+ File, Bulk, and Shell rules.
+ File and Shell sets a target-specific MODE to the current
+ value of $(FILEMODE) or $(SHELLMODE), respectively.
+<TR><TD VALIGN=TOP>
+ SHELLHEADER
+ <TD><TD>String to write in first line of Shell targets
+ (default is #!/bin/sh).
+
+</TABLE>
+</CENTER>
+<P>
+
+<H2>
+Installing Files
+</H2>
+Jambase provides a set of Install* rules to copy files
+into an destination directory and set permissions on them.
+On Unix, the install(1) program is used.
+If the destination directory does not exist, <b>jam</b>
+creates it first.
+<P>
+All files copied with the Install* rules are dependencies
+of the <i>install</i> pseudotarget, which means that the
+command "jam install" will cause the installed copies to
+be updated. Also, "jam uninstall" will cause the installed
+copies to be removed.
+<P>
+The Install* rules are:
+<CENTER>
+<TABLE>
+<TR><TD VALIGN=TOP><B>InstallBin</B>
+ <TD VALIGN=TOP>Copies file and sets its permission to $(EXEMODE).
+ You must specify the suffixed executable name. E.g.:
+ <PRE>InstallBin $(BINDIR) : thing$(SUFEXE) ;
+ </PRE>
+
+<TR><TD VALIGN=TOP><B>InstallFile</B>
+ <TD VALIGN=TOP>Copies file and sets its permission to $(FILEMODE). E.g.:
+ <PRE>InstallFile $(DESTDIR) : readme.txt ;
+ </PRE>
+
+<TR><TD VALIGN=TOP><B>InstallLib</B>
+ <TD VALIGN=TOP>Copies file and sets its permission to $(FILEMODE).
+ You must specify the suffixed library name. E.g.:
+ <PRE>InstallLib $(LIBDIR) : libzoo$(SUFLIB) ;
+ </PRE>
+
+<TR><TD VALIGN=TOP><B>InstallMan</B>
+ <TD VALIGN=TOP>Copies file into the man<i>n</i>
+ subdirectory of the target directory
+ and sets its permission to $(FILEMODE). E.g.,
+ this copies foo.5 into the $(DESTDIR)/man5 directory:
+ <PRE>InstallMan $(DESTDIR) : foo.5 ;
+ </PRE>
+
+<TR><TD VALIGN=TOP><B>InstallShell</B>
+ <TD VALIGN=TOP>Copies file and sets its permission to $(SHELLMODE). E.g.:
+ <PRE>InstallShell $(DESTDIR) : startup ;
+ </PRE>
+
+</TABLE>
+</CENTER>
+<P>
+<P>
+<H4>
+ Variables
+</H4>
+ The following variables control the installation rules:
+<P>
+<CENTER>
+<TABLE>
+<TR><TD>
+ INSTALL
+ <TD><TD>The install program (Unix only)
+<TR><TD>
+ FILEMODE
+ <TD><TD>Default file permissions on readable files.
+<TR><TD>
+ EXEMODE
+ <TD><TD>Default file permission executable files.
+<TR><TD>
+ SHELLMODE
+ <TD><TD>Default file permission on shell script files.
+<TR><TD>
+ MODE
+ <TD><TD>Target-specific file permissions
+</TABLE>
+</CENTER>
+<P>
+<P>
+ The Install rules set a target-specific MODE to the current
+ value of $(FILEMODE), $(EXEMODE), or $(SHELLMODE),
+ depending on which Install rule was invoked.
+<P>
+ The directory variables are just defined for convenience:
+ they must be passed as the target to the appropriate
+ Install rule. The $(INSTALL) and mode variables must be
+ set (globally) before calling the Install rules in order
+ to take effect.
+<P>
+<H2>
+Miscellaneous Rules
+</H2>
+<H4>
+Clean Rule
+</H4>
+<P>
+The Clean rule defines files to be removed when you run "jam clean".
+Any site-specific build rules defined in your Jamrules should invoke
+Clean so that outputs can be removed. E.g.,
+<PRE>
+ rule ResourceCompiler
+ {
+ DEPENDS $(<) : $(>) ;
+ Clean clean : $(<) ;
+ }
+</PRE>
+<P>
+<P>
+Most Jambase rules invoke the Clean rule on their built targets,
+so "jam clean" will remove all compiled objects, libraries,
+executables, etc.
+<P>
+<H4>
+MakeLocate Rule
+</H4>
+ MakeLocate is a single convenient rule that creates a directory,
+ sets LOCATE on a target to that directory, and makes the directory
+ a dependency of the target. It is used by many Jambase rules,
+ and can be invoked directly, e.g.:
+ <PRE>
+ GenFile data.tbl : hxtract data.h ;
+ MakeLocate data.tbl : $(TABLEDIR) ;
+ </PRE>
+ In this example, the File rule creates data.tbl from data.h.
+ The MakeLocate causes data.tbl to be written into the $(TABLEDIR)
+ directory; and if the directory doesn't exist, it is created first.
+ <P>
+ The MakeLocate rule invokes another Jambase rule, MkDir,
+ to (recursively) create
+ directories. MkDir uses the $(MKDIR) variable to determine the
+ platform-specific command that creates directories.
+<P>
+<H4>
+RmTemps Rule
+</H4>
+ Some intermediate files are meant to be temporary.
+ The RmTemps rule can be used to cause
+ <b>jam</b> to delete them after they are used.
+ <P>
+ RmTemps must be:
+ <UL>
+ <LI>
+ the last rule
+ invoked on the permanent file that uses
+ the temporary file(s)
+ <LI>
+ invoked with the permanent file as the output
+ target and the temporary file(s) as the input target
+ <LI>
+ invoked with the exact target identifiers of
+ the permanent file and the temporary file(s)
+ </UL>
+ For
+ example:
+ <PRE>
+ SubDir TOP src big ;
+ GenFile big.y : joinfiles part1.y part2.y part3.y ;
+ Main bigworld : main.c big.y ;
+ RmTemps bigworld$(SUFEXE) : <src!big>big.y ;
+ </PRE>
+ This causes big.y to be deleted after it has been used to create
+ the bigworld executable.
+ The exact target identifier of big.y is <src!big>big.y
+ (the GenFile and Main rules tack on the grist automatically);
+ the exact target identifier of the bigworld executable
+ is bigworld$(SUFEXE).
+<P>
+<HR>
+<A HREF="#TOP">Back to top.</A>
+<P>
+ Copyright 1997, 2000 Perforce Software, Inc.
+ <BR>
+ Comments to <A HREF="mailto:info at perforce.com">info at perforce.com</A>
+ <BR>
+ Last updated: Dec 31, 2000
+ <BR>
+ $Id: Jamfile.html,v 1.4 2002/04/07 00:22:45 david_abrahams Exp $
+</BODY>
+</HTML>
Added: boost-jam/boost-build/branches/upstream/current/jam_src/Porting
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/Porting 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/Porting 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,68 @@
+Notes on porting Jam - revised 12/31/2000
+
+1) Working out system dependencies in the Jam code.
+
+ Jam's OS footprint is fairly small. For OS independent work Jam
+ liberally uses standard libc functions like stdio, malloc, and
+ string. The OS dependent interfaces are:
+
+ From filesys.h:
+
+ file_parse() - split a file name into dir/base/suffix/member
+ file_build() - build a filename given dir/base/suffix/member
+ file_dirscan() - scan a directory for files
+ file_archscan() - scan an archive for files
+ file_time() - get the timestamp of a file, if not already
+ done by file_dirscan().
+
+ From execcmd.h:
+
+ execcmd() - execute a shell script
+ execwait() - wait for any outstanding execcmd()'s.
+
+ The current implementations are:
+
+ filemac.c - mac MPW
+ filent.c - NT
+ fileos2.c - OS/2
+ fileunix.c - all UNIX
+ filevms.c - VMS
+
+ execmac.c - mac MPW
+ execunix.c - UNIX, OS/2, NT
+ execvms.c - VMS
+
+2) Defining OSMAJOR, OSMINOR in jam.h
+
+ So that the Jambase and Jamfile know their host, Jam defines $(OS)
+ to be something useful for each platform. Make sure that there is
+ code in jam.h to generate a useful value for $(OS), and key it off
+ the platform specific C-preprocessor symbol. If the C-preprocessor
+ doesn't itself defines such a symbol, add a define to the Makefile.
+
+ In addition to $(OS), you can also set $(OSPLAT) if the OS runs on
+ multiple platforms (like Linux or NT).
+
+3) Working out system dependencies in the Jambase
+
+ With the value of $(OS) available, the Jambase can be extended to
+ support special variables or rules for new platforms. See the
+ current support for VMS, NT, and Mac.
+
+4) Yacc troubles
+
+ The generated files jamgram.h and jamgram.c are distributed for the
+ poor souls without yacc.
+
+5) Known problematic systems:
+
+ - Pyramid has no malloc.h, memory.h
+
+ - Encore has no stdlib.h
+
+ - Bull DPX has sys/file.h problems
+
+6) Send the results back.
+
+ If you do porting work, the result can be integrated into future
+ releases if you send it back to the author's address in the README.
Added: boost-jam/boost-build/branches/upstream/current/jam_src/README
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/README 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/README 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,149 @@
+Jam/MR (aka "jam - make(1) redux")
+
+ /+\
+ +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ \+/
+
+ This is Release 2.4 of Jam/MR, a make-like program.
+
+ License is hereby granted to use this software and distribute it
+ freely, as long as this copyright notice is retained and modifications
+ are clearly marked.
+
+ ALL WARRANTIES ARE HEREBY DISCLAIMED.
+
+FEATURES
+
+ -> Jam is a make(1) replacement that makes building simple things
+ simple and building complicated things manageable.
+
+ -> Jam's language is expressive, making Jamfiles (c.f. Makefiles)
+ compact. Here's a sample:
+
+ Main smail : main.c map.c resolve.c deliver.c
+ misc.c parser.y alias.c pw.c headers.c
+ scanner.l getpath.c str.c ;
+
+ This builds "smail" from a dozen source files. Jam handles
+ header file dependencies automatically and on-the-fly.
+
+ -> Jam is very portable: it runs on UNIX, VMS, Mac, and NT.
+ Most Jamfiles themselves are portable, like the sample above.
+
+ -> Jam is unintrusive: it is small, it has negligible CPU
+ overhead, and it doesn't create any of its own funny files
+ (c.f. Odin, nmake, SunOS make).
+
+ -> Jam can build large projects spread across many directories
+ in one pass, without recursing, tracking the relationships
+ among all files. Jam can do this with multiple, concurrent
+ processes.
+
+ -> Jam isn't under the blinkin GNU copyright, so you can
+ incorporate it into commercial products.
+
+
+INFORMATION GUIDE
+
+ Jam.html jam and language reference.
+
+ Jambase.html Reference for the Jambase boilerplate file.
+
+ Jamfile.html Easy reading on creating a Jamfile and using jam.
+
+ RELNOTES Release 2.3 release notes.
+
+ Porting Notes on porting jam to wildcat platforms.
+
+ README This file. Includes installation instructions.
+
+ jam.c Contains the jam command's main() as well as an
+ introduction to the code, for serious hackers.
+
+
+INSTALLING
+
+ The Makefile (UNIX, NT), build.com (VMS), Build.mpw (Mac MPW) are
+ for bootstrapping. Once jam is built, it can rebuild itself.
+
+ UNIX
+
+ Build jam with make(1) on:
+
+ Platform $(OS)
+ -------------------------
+ AIX AIX *
+ BSD/386 1.0 BSDI
+ COHERENT/386 COHERENT
+ DGUX 5.4 DGUX
+ FreeBSD FREEBSD
+ HPUX 9.0 HPUX
+ IRIX 5.0 IRIX
+ Linux LINUX
+ NEXTSTEP 3.2 NEXT
+ OSF/1 OSF
+ PTX V2.1.0 PTX
+ Solaris 2 SOLARIS *
+ SunOS4.1 SUNOS
+ Ultrix 4.2 ULTRIX
+ BeOS BEOS *
+
+ * requires editing Makefile
+
+ Windows
+
+ Build jam with nmake on:
+
+ Platform $(OS)
+ -------------------------
+ NT NT *
+ OS/2 OS2 *
+
+ The NT MAXLINE (command line length) is still set in jam.h to
+ 996, which was apparently the NT 3.5 limit. On 4.0, the limit
+ is somewhere around 10K. For now, you can increase MAXLINE in
+ jam.h so that a jam running on 4.0 will use the full command
+ line length, but that jam.exe will fail miserably on the older OS.
+
+ On NT, a variable must be set before invoking jam to tell
+ it where the C compiler lives. The name of this variable
+ depends on which compiler you are using:
+
+ BCCROOT: The Borland C compiler
+ MSVCNT: The Microsoft Compiler 5.0 (for NT)
+ MSVC: The Microsoft Compiler 1.5 (for Windows)
+
+ Only MSVCNT has really been tested and is known to work.
+
+ Macintosh
+
+ Build jam with Build.mpw on:
+
+ Platform $(OS)
+ -------------------------
+ Macintosh MAC
+
+ You'll need to edit Build.mpw to set CW.
+
+ VMS
+
+ Build jam with @build.com on:
+
+ Platform $(OS)
+ -------------------------
+ VMS 5.4 VMS
+ OPENVMS OPENVMS
+
+Comments to the author!
+
+November, 1993 - release 1.0
+March, 1995 - release 2.0
+February, 1996 - release 2.1
+November, 1997 - release 2.2
+December, 2000 - release 2.3
+March, 2002 - release 2.4
+
+
+Christopher Seiwald
+
+seiwald at perforce.com
Added: boost-jam/boost-build/branches/upstream/current/jam_src/RELNOTES
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/RELNOTES 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/RELNOTES 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,941 @@
+Release notes for Jam/MR 2.4
+(aka Jam - make(1) redux)
+
+0. Changes between 2.4rc1 and 2.4rc2:
+
+ THESE NOTES WILL BE REMOVED WITH THE FINAL 2.4 RELEASE, SINCE THEY
+ REFER EXCLUSIVELY TO ADJUSTMENTS IN BEHAVIORS NEW BETWEEN 2.3 and
+ 2.4:
+
+ Make MATCH generate empty strings for () subexpressions that
+ match nothing, rather than generating nothing at all.
+ Thanks to David Abrahams.
+
+ GLOB now applies the pattern to the directory-less filename,
+ rather than the whole path. Thanks to Niklaus Giger.
+
+ Make Match rule do productized results, rather than
+ using just $(1[1]) as pattern and $(2[1]) as the string.
+
+1. Release info:
+
+ Jam/MR 2.4
+ March, 21, 2002
+ VERSION 2.4
+
+2. Compatibility
+
+ Jam 2.4 is upward compatible with Jam 2.3
+
+ The Jam 2.4 language is a superset of the 2.3 language;
+ Jamfiles, Jambase, and other rulesets used in 2.3 can be used
+ with the 2.4 language support.
+
+3. Changes since 2.3.
+
+3.1. Changes to Jam Language
+
+ The mechanism for calling rules that return values - "[ rule
+ args ...]", (and 'return' in the rule body), is now a
+ documented part of the language.
+
+ Add "on <target> <rulename> <field1> ..." syntax, to invoke a
+ rule under the influence of a target's specific variables.
+
+ Add "[ on targ rule ... ]" to call a rule returning a value,
+ under the influence of a target's specific variables.
+
+ New 'Glob' builtin that returns a list of files in a list of
+ directories, given a list of patterns.
+
+ New 'while expr { block }' construct.
+
+ New :E=value modifier provides default value if variable unset.
+
+ New :J=joinval modifier concatenates list elements into single
+ element, separated by joinval.
+
+ \ can now be used to escape a space (or any single whitespace
+ character), so that you don't have to resort to quotes.
+
+ New 'Match regexp : string' rule matches regexp against string
+ and returns list of results.
+
+ Rules can now be invoked indirectly, through variable names.
+ If the variable expands to an empty list, no rule is run.
+ If the variable expands to multiple entries, each rule is
+ run with the same arguments. The result of the rule invocation
+ is the concatenation of the results of the rules invoked.
+
+ 'Echo' and 'Exit' now have aliases 'echo' and 'exit', since it
+ is really hard to tell that these are built-in rules and not
+ part of the language, like 'include'. Real rules continue to
+ start with a capital.
+
+3.2. Jambase Changes
+
+ Support for YACCGEN, the suffix used on generated yacc output.
+
+ Fix ups to have jam and p4 build with borland C 5.5,
+ and minor win98 jam support for jam clean
+
+ SubDirHdrs now takes directory names in the same format as
+ SubInclude : one directory element per word.
+
+ More portable support for specifying includes and #defines:
+ New ASHDRS, CCHDRS, CCDEFS, DEFINES, ObjectDefines, FQuote,
+ FIncludes, FDefines. Ordering of cc and c++ flags grossly
+ rearranged.
+
+ Jambase has been compacted by applying the new E: and J:
+ expansion modifiers.
+
+ New SoftLink rule, courtesy of David Lindes. It currently
+ assumes you can pass a -s flag to $(LN).
+
+3.3 'jam' Changes (See Jam.html)
+
+ Added '-q' (quit quick) option; jam will exit promptly (as if it
+ received an interrupt), as soon as any target fails.
+
+ Added experimental '-g' (build newest sources first) option:
+ all things being equal, normally targets are simply built in
+ the order they appear in the Jamfiles. With this flag, targets
+ with the newest sources are built first. From an idea by Arnt
+ Gulbrandsen. Undocumented (outside this note).
+
+3.4. Jam internal code changes
+
+ jamgram.yy now defines YYMAXDEPTH to 10000, what it is on
+ FreeBSD, for older yaccs that left it at 150 or so. This is
+ needed for the right-recursion now used in the grammar.
+
+ Optimize rule compilation, with right-recursion instead of left.
+
+ Split jam's built-in rules out to builtins.c from compile.c,
+ so that compile.c only deals with the language.
+
+ Split jam's pathsys.h from filesys.h, since they are really
+ two different pieces.
+
+ evaluate_if(), which evaluated the condition tree for 'if' and
+ returned an int, has been replaced with compile_eval(), which does
+ essentially the same but returns a LIST.
+
+4. Fixed bugs
+
+ Missing TEMPORARY targets with multiple parents no longer spoil one
+ parent's time with another. The parents' time is used for comparison
+ with dependents, but no longer taken on as the target's own time.
+
+ 'actions updated', not 'actions together', now protects targets
+ from being deleted on failed/interrupted updates.
+
+ Fixed broken $(v[1-]), which always returned an empty expansion.
+ Thanks to Ian Godin <ian at sgrail.com>.
+
+ Defining a rule within another rule, and invoking the enclosing
+ rule more than once, would result in giving the first rule a
+ null definition. Fixed.
+
+ $(d:P) now works properly on the mac, climbing up directories.
+ Thanks to Miklos Fazekas <boga at mac.com>.
+
+ No longer (sometimes) treat \ as a directory separator on
+ UNIX. It isn't supposed to be, but was due to bungled ifdefs.
+
+ Applying just :U or :D (or :E, :J) mods no longer causes the
+ variable value to be treated as a filename (parsed and rebuilt
+ using the OS specific pathsys routines). Previously, if _any_
+ mods were present then the value was parsed and rebuilt as if
+ a filename, and that could in certain cases munge the value.
+ Only the file modifiers (:GDBSM) treat the value as a
+ filename.
+
+ Four rules makeCommon, makeGrist, makeString, makeSubDir from
+ jam 2.2 missing in 2.3 have been re-added, with apologies to
+ dtb at cisco.com.
+
+ Return status more likely to be correct when using -d0, now that
+ targets are could as being built even with no debugging output.
+ Thanks to Miklos Fazekas <boga at mac.com>.
+
+ yyacc now suffixes all terminals it defines with _t, so that they
+ don't conflict with other symbols (like RULE with the typedef
+ in rules.h). Thanks to Michael Allard.
+
+ InstallInto now handles multiple sources properly, rather than
+ acting as if each installed target depended on all sources to
+ be installed. $(INSTALLGRIST) is now the default grist for
+ installed targets, rather than the hardcoded 'installed'. Thanks
+ to Stephen Goodson.
+
+5. Porting
+
+ [MACINTOSH] Paths are now downshifted (internally) so as to
+ handle its case insensitivity. Thanks to Miklos Fazekas
+ <boga at mac.com>.
+
+ [NT] MS changed the macro for the IA64 Windows NT 64bit
+ compiler.
+
+ [CYGWIN] Cygwin jam porting: dance around bison and yyacc.
+ Use bison's -y flag to use yacc's output file naming
+ conventions, and don't use yyacc on systems whose SUFEXE is
+ set.
+
+ [VMS] The Jambase itself was not formatting the CCHDRS and
+ CCDEFS properly: on VMS they can't be appended to, because
+ multiple /define or /include directives don't work. Instead
+ now CCHDRS and CCDEFS is reformatted from HDRS and DEFINES
+ anytime those latter two change. This requires the recent
+ change to jam to allow access to target-specific variables
+ when setting other variables.
+
+ [VMS] Remove exception call when file_dirscan() can't, for
+ some reason, scan a directory. Use a better set of #ifdefs to
+ determine if we're on a vax, rather than relying on the C
+ compiler being a specific version: we're able to build with
+ the C++ compiler now.
+
+ [VMS] Port new jam to run with just cxx compiler.
+ (The C compiler being a extra-cost item).
+
+ [NT] Add entry for DevStudio when the settings are already in the
+ system environment.
+
+ [NT] default $(MV) to "move /y" in Jambase.
+
+ [MINGW] Mingw port by Max Blagai.
+
+===============================================================================
+===============================================================================
+
+
+======= end
+Release notes for Jam/MR 2.3
+(aka Jam - make(1) redux)
+
+0. Bugs fixed since 2.3.1
+
+ PATCHLEVEL 2 - 3/12/2001
+
+ NOCARE changed back: it once again does not applies to targets
+ with sources and/or actions. In 2.3 it was changed to apply to
+ such targets, but that broke header file builds: files that are
+ #included get marked with NOCARE, but if they have source or
+ actions, they still should get built.
+
+1. Release info:
+
+ Jam/MR 2.3
+ November 16, 2000
+ VERSION 2.3
+ PATCHLEVEL 1
+
+2. Compatibility
+
+ Jam 2.3 is upward compatible with Jam 2.2.
+
+ The Jam 2.3 language is a superset of the 2.2 language;
+ Jamfiles, Jambase, and other rulesets used in 2.2 can be used
+ with the 2.3 language support.
+
+3. Changes since 2.2
+
+3.1. Changes to Jam Language
+
+ Rules now can have values, which can expanded into a list with
+ the new "[ rule args ... ]" syntax. A rule's value is the value
+ of its last statement, though only the following statements have
+ values: if (value of the leg chosen), switch (ditto), set (value
+ of the resulting variable), return (its arguments). Note that
+ 'return' doesn't actually return. This support is EXPERIEMENTAL
+ and otherwise undocumented. (2.3.1)
+
+ Because of the new way lists are processed, if a rule has no
+ targets a warning message is no longer issued.
+
+ NOCARE now applies to targets with sources and/or actions,
+ rather than just those without.
+
+3.2. Jambase Changes
+
+ The HDRPATTERN variable now allows for leading blanks before
+ the #include, to keep up with ANSI. By john at nanaon-sha.co.jp
+ (John Belmonte) (2.2.3).
+
+ HDRPATTERN has been adjusted to avoid mistaking cases like:
+
+ # include <time.h> /* could be <sys/time.h> */
+
+ MkDir now NOUPDATE's $(DOT), so that there are no dependencies
+ on the current directory's timestamp. By john at nanaon-sha.co.jp
+ (John Belmonte).
+
+ The old mock functions like makeDirName, which assigned their
+ results to the variable named as their first argument, have
+ been replaced with real functions using the new [] synxtax.
+ E.g. "makeDirName foo : bar ola" is now "foo = [ fDirName bar ]"
+
+ Install now always does a cp/chmod/etc, rather than using
+ the system's install(1), which invariably seems broken.
+
+3.3. Jam internal code changes
+
+ $JAMUNAME is set on UNIX. (2.2.4).
+
+ Jam ANSI-fied (2.3.0).
+
+ jam.h now defines a bunch of symbols used by the other source
+ files, so as minimize compiler- and platform-specific ifdefs.
+
+ OSVER is no longer set by jam.h (it was only set for AIX).
+ Jam does not depend on this variable at all, except to set
+ $(OSFULL), which is used to determine jam's build directory.
+ If the user needs to distinguish between various revs of
+ OSs, he must set OSVER in the environment.
+
+4. Fixed bugs
+
+ Redefining a rule while it was executing could cause jam to
+ crash. Reference counts are now used to prevent that, thanks
+ to Matt Armstrong.
+
+ Logic for computing chunk size when executing PIECEMEAL rules
+ has been reworked to be a little more accurate, without danger
+ of overflow, at the cost of being a little more compute intensive.
+ Instead of computing an estimate chunksize in the (now gone)
+ make1chunk(), make1cmds() now just goes full bore and tries to
+ use all args. When that fails, it backs off by 10% of the source
+ args until the command fits. It takes a little bit more compute
+ time compared to the old logic, but when you're executing actions
+ to build all of Shinola it's still pretty small in the scheme
+ of things.
+
+ The NT handle leak in execunix.c has been fixed, thanks to
+ Gurusamy Sarathy. (2.2.1).
+
+5. Porting
+
+ Platforms newly supported or updated:
+
+ AmigaOS (with gcc), courtesy of Alain Penders (2.2.2).
+
+ Beos
+
+ CYGWIN 1.1.4, courtesy of John Belmonte <john at nanaon-sha.co.jp>.
+
+ IBM AS400 via Visual Age on NT (primitive)
+
+ IBM OS/390 Unix System Services
+
+ Linux SuSE on OS390
+
+ Linux Mips, ARM
+
+ Lynx
+
+ HPUX 11, IA64
+
+ Mac OS X Server, courtesy of Jeff_Sickel at sickel.com (2.2.5).
+
+ Mac Rhapsody
+
+ MPE IX 6.0
+
+ NetBSD
+
+ QNX RTP (QNX 6.0)
+
+ Siemens Sinix
+
+ UNICOS
+
+ VMS 6.2, 7.1
+
+ Windows NT IA64
+
+5.1. NT Porting Notes
+
+ Always create tmp .bat file for actions if JAMSHELL is set.
+ That way, if JAMSHELL is a .bat file itself, it can handle
+ single-command actions with more than 9 cmd line args.
+
+ COMSPEC is no longer examined: cmd.exe is always used
+ instead. Only cmd.exe can execute the Jambase rules anyhow.
+
+ Jam can be built with Borland C++ 5.5.
+
+ OS2 fixes: InstallBin now works. Filenames are now downshifted,
+ so mixed case works better there, too. file_dirscan() can now scan
+ the root ("c:\" or "\") directory, which it couldn't handle before.
+
+ var_defines now ignores OS=Windows_NT, because it conflicts
+ with Jam's setting of OS (to NT).
+
+5.2. Mac OS 8/9 Notes
+
+ The support for Mac is curious at best. It runs under MPW.
+
+ It requires CodeWarrior Pro 5, but no longer requires GUSI.
+
+ Use Build.mpw to bootstrap the build.
+
+ The Mac specific definitions in the Jambase are not intended
+ to be of general purpose, but are sufficient to have Jam build
+ itself.
+
+===============================================================================
+===============================================================================
+
+
+Release Notes for Jam 2.2
+
+1. Release info:
+
+ Jam 2.2
+ October 22, 1997
+ VERSION 2.2
+ PATCHLEVEL 1
+
+2. Compatibility
+
+ Jam 2.2 is a roll-up of 'Jam - make(1) redux' release 2.1+.
+ Most of the changes described below were available before this,
+ in the jam.2.1.plus.tar ball.
+
+ The Jam 2.2 language is a superset of the 2.1 language;
+ Jamfiles, Jambase, and other rulesets used in 2.1 can be used
+ with the 2.2 language support.
+
+ See 'Jambase Changes', below, to see if your Jamfiles need any
+ changes to work with the 2.2 Jambase.
+
+
+3. Changes Since 2.1
+
+ New product name: Jam. (Executable program is still named 'jam'.)
+
+ Documentation rewritten; HTML versions supplied.
+
+
+3.1 Changes to Jam Language
+
+ Rules may now have more fields than just $(<) and $(>).
+
+ Local variables are now supported.
+
+ The expression 'if $(A) in $(B)' is now supported.
+
+ New variable modifiers :U and :L result in uppercased or lowercased
+ values.
+
+ New variable modifier :P reliably results in parent directory
+ of either a file or directory. (Previously, :D was used, but on VMS
+ :D of a directory name is just the directory name.)
+
+ The :S variable modifier now results in the _last_ suffix if a
+ filename has more than one dot (.) in it.
+
+ New predefined $(JAMDATE) variable is initialized at runtime for
+ simple date stamping.
+
+ New predefined variables $(OSVER) and $(OSPLAT) are used to
+ distinguish among operating system versions and hardware platforms,
+ when possible.
+
+ New 'bind' qualifier on action definitions allows variables
+ other than $(<) and $(>) to be bound with SEARCH and LOCATE paths.
+
+ Action buffer size is no longer limited by MAXCMD. Instead, each
+ line in an action is limited by MAXLINE, defined for each OS, and
+ the entire action size is limited by CMDBUF.
+
+
+3.2 Jambase Changes (See Jamfile.html)
+
+ Jambase has been reworked to incorporate new language features.
+
+ A handful of new utility rules has been added: makeString,
+ makeDirName, etc.
+
+ New HDRGRIST variable in Jambase allows for headers with the same
+ name to be distinguished.
+
+ LOCATE_TARGET now has a new flavor, LOCATE_SOURCE, that is used by
+ rules that generate source files (e.g., Yacc and Lex).
+
+ Header file includes now happen in the proper order. The limit of
+ 10 include files has been eliminated.
+
+ The old "Install" rule is no longer available. Use InstallBin,
+ InstallFile, InstallLib, InstallMan, or InstallShell instead.
+
+
+3.3 'jam' Changes (See Jam.html)
+
+ 'jam' can now be built as a stand-alone program, with Jambase
+ compiled into the executable. An external or alternate Jambase can
+ still be referenced explicitly with -f.
+
+ On command failure, 'jam' now emits the text of the command that
+ failed. This is a compromise between the normal -d1 behavior (where
+ commands were never seen) and -d2 (where commands are always seen).
+
+ 'jam' now exits non-zero if it doesn't have a total success. A parse
+ error, sources that can't be found, and targets that can't be built
+ all generate non-zero exit status.
+
+ The debugging levels (-d flags) have been slightly redefined.
+
+ The supplied Jamfile now builds 'jam' into a platform specific
+ subdirectory. This lets you use the same source directory to
+ build 'jam' for more than one platform.
+
+ The supplied Jamfile does not rebuild generated source files by
+ default. (They are supplied with the distribution.) See Jamfile
+ for more information.
+
+
+4. Fixed Bugs
+
+ The 'include' bug has finally been fixed, so that include
+ statements take effect exactly when they are executed,
+ rather than after the current statement block. This also
+ corrects the problem where an 'include' within an 'if'
+ block would wind up including the file one token after the
+ 'if' block's closing brace. Credit goes to Thomas Woods
+ for suggesting that the parse tree generation and parse
+ tree execution be paired in their own loop, rather than
+ having the parser execute the tree directly.
+
+ The setting and extracting of grist has been regularized:
+ normally, if you set a component of a filename (using the
+ :DBSMG= modifiers), you are supposed to include the delimiters
+ that set off the component: that is, you say "$(x:S=.suffix)",
+ including the ".". But with grist it was inconsistent
+ between setting and getting: setting grist required no
+ <>'s, while getting grist included them. Getting grist
+ continues to return the <>'s, but now setting grist can
+ either include them (the new way) or not (the old way).
+
+ 'actions together' now suppresses duplicate sources from
+ showing up in $(>).
+
+ Accessing variables whose names contained ['s (as happens with
+ MkDir on VMS) wasn't working, because it treated the [ as an
+ array subscript. Now [ and ] are, like :, handled specially so
+ that they can appear in variable values.
+
+ The 'if' statement now compares all elements in expressions;
+ previously, it only compared the first element of each list.
+
+ If a command line in an action is longer than MAXLINE (formerly
+ MAXCMD), 'jam' now issues an error and exits rather than dumping
+ core.
+
+ If a Jamfile ended without a trailing newline, jam dumped core.
+ This has been fixed.
+
+
+5. Porting
+
+ See jam.h for the definitive list of supported platforms.
+ Since 2.1, support has been added for:
+
+ Macintosh MPW
+ Alpha VMS
+ Alpha NT
+ NT PowerPC
+ BeOS
+ MVS OE
+ UNIXWARE
+ QNX
+ SINIX (Nixdorf)
+ OS/2
+ Interactive UNIX (ISC), courtesy of Matthew Newhook
+
+
+5.1 NT Support Fixes
+
+ The NT command executor now handles multiple line actions, by writing
+ multi-line actions to a batch file and executing that.
+
+ Targets are universally lowercased on NT. (Matthew Newhook)
+
+ Concurrent process support is fully enabled for NT.
+ (Gurusamy Sarathy <gsar at engin.umich.edu>)
+
+ Path handling: Jam now knows that the directory component of "D:\"
+ is "D:\", just as on unix it knows that the directory component of
+ "/" is "/". It also now successfully gets the timestamp for "D:\"
+ or just plain "\".
+
+
+5.2 VMS Support Fixes
+
+ VMS support is much, much better now. The path name manipulation
+ routines (in pathvms.c) were more or less rewritten, and they now
+ handle the vagaries of combining directory and file names properly.
+
+ Targets are universally lowercased on VMS.
+
+ Multi-line command blocks on VMS are now executed in a single system()
+ call rather than separate ones for each line, so that actions can
+ be DCL scripts.
+
+===============================================================================
+===============================================================================
+
+
+Release notes for Jam 2.1.
+
+1. Release info:
+ Jam 2.1
+ February 1, 1996
+ VERSION 2.1
+ PATCHLEVEL 0
+
+2. Porting
+
+ Linux is now supported.
+
+ FREEBSD is now supported.
+
+ SCO ("M_XENIX") now supported.
+
+ NCR now supported.
+
+ NEXT support from karthy at dannug.dk (Karsten Thygesen)
+
+ DECC support from zinser at axp614.gsi.de (Martin P.J. Zinser)
+
+ I have changes for OS/2, but no way to test them. Volunteers?
+ I have VMS multiprocess support, but no way to test it. Volunteers?
+
+2.1. NT Support fixes.
+
+ The NT support is considerably more real than it was in 2.0.
+ Filent.c had its syntax error corrected, it no longer skips the
+ first entry when scanning directories, and it handles string
+ tables in archives (for long object file names).
+
+ The Jambase was changed a bit to support the various C/C++
+ compilers on NT, although it has only been thorougly tested
+ with MSVC20.
+
+ You still need to set MSVCNT or BCCROOT to the root of the
+ the compiler's directory tree, and you'll get an error if you
+ don't set it (rather than getting a pile of mysterious errors).
+
+2.2. Other porting fixes.
+
+ SPLITPATH now set up for UNIX (:), NT (;), VMS (,)
+
+ Jambase support for Solaris works better now: the location of
+ AR is hardwired to /usr/ccs/bin/ar and it knowns "install"
+ doesn't take -c. Solaris -- how the mighty have fallen.
+
+ To handle Linux's wacko yacc, jamgram.h is now included after
+ scan.h so that YYSTYPE is define.
+
+3. Jambase Changes (see Jamfile.html)
+
+ SubDir now computes the root directory for the source tree, if
+ the variable naming the root directory isn't set in the environment.
+ It counts the number of directory elements leading from the root
+ to the current directory (as passed to SubDir) and uses that many
+ "../"'s to identify the root. This means that to use SubDir you
+ no longer have to have anything special set in the environment.
+
+ InstallFile is now an alias for InstallLib.
+
+ 'first' is now dependency of all pseudo-targets (all, files,
+ exe, lib, shell), so that jamming any of these pseudo-targets
+ also builds any dependencies of 'first'.
+
+ The File rule definition in the Jambase was missing an &.
+
+ The File rule now calls the Clean rule, so that installed files
+ get cleaned.
+
+4. Jam changes (see Jam.html)
+
+ Variables may now be set on the command line with -svar=value.
+
+ Targets marked with NOUPDATE are now immune to the -a (anyhow)
+ flag. Previously, the MkDir rule would try to recreate directories
+ that already exist when jam was invoked with -a.
+
+ A new variable, $(JAMVERSION), joins the small list of built-in
+ variables. It it set to the release of jam, currently "2.1".
+
+ If an actions fails, jam now deletes the target(s). It won't
+ delete libraries or other targets that are composites. This is
+ now consistent with jam's behavior on interrupts (it deletes the
+ targets).
+
+ Jam had a nasty bug when setting multiple variables to the same
+ value: if the first two variable names were the same, the variable
+ value got trashed. This also affected "on target" variables if
+ the first two targets were the same. For example:
+
+ FOO on bar.c bar.c foo.c = a b c ;
+
+ This would mangle the value of FOO for bar.c and foo.c. This has
+ been fixed.
+
+ Jam would generate bogus numbers when reporting the number of
+ targets updated after an interrupt. It now is more careful about
+ counting.
+
+ The debugging flag -d has been extended. In addition to supporting
+ -dx (turn on debugging for all levels up to x) there is also now
+ -d+x (turn on debugging at only level x). The default output
+ level is -d1 (-or d2 if -n is given); this can be turned off with
+ -d0. The debug levels are listed in jam.1 and jam.h.
+
+ The parsing debug output now uses indenting to indicate when
+ one rule invokes another.
+
+===============================================================================
+===============================================================================
+
+
+Release notes for Jam 2.0.
+
+1. Release info:
+ Jam 2.0
+ March 10, 1994
+ VERSION 2.0
+ PATCHLEVEL 5
+
+2. Porting
+
+ Windows/NT is now (crudely) supported, courtesy of Brett Taylor
+ and Laura Wingerd.
+
+ COHERENT/386 is now supported, courtesy of Fred Smith.
+
+ Solaris archive string table for long archive names is now
+ supported, thanks to Mike Matrigali.
+
+3. Compatibility
+
+ Jam 2.0 syntax is a superset of Jam 1.0 syntax, and thus it can
+ interpret a Jam 1.0 Jambase.
+
+ The Jam 2.0 Jambase is a superset of the Jam 1.0 Jambase, and
+ thus it can include a Jamfile written for Jam 1.0.
+
+4. Changes from Jam 1.0 to Jam 2.0
+
+4.1. Documentation changes
+
+ New Jamfile.5 manual page, with lots of examples and easy
+ reading. It replaces both the old "Examples" file as well as
+ the old Jambase.5 manual page.
+
+ jam.1 edited by Stephen W. Liddle and Diane Holt.
+
+4.2. Jambase Changes (see Jamfile.5)
+
+4.2.1. New rules:
+
+ There are new rules to make handling subdirectories easier:
+ SubDir, SubInclude, SubDirCcFlags, SubDirHdrs.
+
+ There are new rules to handle file-specific CCFLAGS and HDRS:
+ ObjectCcFlags and ObjectHdrs.
+
+ Misc new rules: HardLink, InstallShell, MkDir.
+
+ New rule "clean" that deletes exactly what jam has built, and
+ "uninstall" that deletes exactly what was installed.
+
+ New rules for handling suffixes .s, .f, .cc, .cpp, .C.
+
+4.2.2. Old rules:
+
+ The InstallBin, Lib, Man, and the new Shell rules now take the
+ destination directory as the target and the files to be copied
+ as sources. These rules formerly took the files to be copied
+ as targets, and used built-in destination directories of
+ $(BINDIR), $(LIBDIR), $(MANDIR), and $(BINDIR).
+
+ The InstallBin, Lib, Man, and Shell rules use the install(1)
+ program now, instead of doing their own copying.
+
+ The Cc rule now uses -o when possible, rather than moving the
+ result. Some platforms (Pyramid?) have a broken -o.
+
+ Jambase rules taking libraries, objects, and executables now
+ all ignore the suffixes provided and use the one defined in the
+ Jambase for the platform.
+
+ Stupid yyacc support moved out of Jambase, as jam is its only
+ likely user.
+
+ Jambase now purturbs library sources with a "grist" of
+ SOURCE_GRIST.
+
+4.2.3. Misc:
+
+ The names of the default rules defined in Jambase have been
+ lowercased and un-abbreviated, to be more imake(1) like.
+
+ The Jambase has been reorganized and sorted, with VMS and NT
+ support moved in from their own files.
+
+ The Jambase has been relocated on UNIX from /usr/local/lib/jam
+ to /usr/local/lib.
+
+4.3. Jam changes (see jam.1)
+
+4.3.1. Flags:
+
+ New -a (anyhow) flag: means build everything.
+
+ New -j<x> flag: run jobs in parallel.
+
+ Old -t now rebuilds the touched target, rather that just the
+ target's parents.
+
+ -n now implies -d2, so that you see what's happening. The
+ debug level can be subsequently overridden.
+
+ New -v to dump version.
+
+4.3.2. Rules:
+
+ New ALWAYS rule behaves like -t: always builds target.
+
+ New EXIT rule makes it possible to raise a fatal error.
+
+ New LEAVES rule which say target depends only on the update
+ times of the leaf sources.
+
+ New NOUPDATE rule says built targets only if they don't exist.
+
+ NOTIME has been renamed NOTFILE, to more accurately reflect its
+ meaning (it says a target is not to be bound to a file).
+
+4.3.3. Variables:
+
+ New special variable JAMSHELL: argv template for command execution
+ shell.
+
+ Variables, both normal and target-specific, can have their
+ value appended with the syntax "var += value" or "var on target
+ += value".
+
+ "?=" is now synonymous with "default =".
+
+ Imported enviroment variable values are now split at blanks
+ (:'s if the variable name ends in PATH), so that they become
+ proper list values.
+
+4.3.4. Misc:
+
+ Files to be sourced with "include" are now bound first, so
+ $(SEARCH) and $(LOCATE) affect them. They still can't be
+ built, though.
+
+ New modifier on "actions": "existing" causes $(>) to expand
+ only those files that currently exist.
+
+4.3.5. Bug fixes:
+
+ When scanning tokens known to be argument lists (such as the
+ arguments to rule invocations and variable assignment), the
+ parser now tells the scanner to ignore alphabetic keywords, as
+ all such lists terminate with punctuation keywords (like : or
+ ;). This way, alphabetic keywords don't need to be quoted when
+ they appear as arguments.
+
+ The scanner has been fixed to handle oversized tokens,
+ unterminated quotes, unterminated action blocks, and tokens
+ abutting EOF (i.e. a token with no white space before EOF).
+
+ The progress report "...on xth target..." used to count all
+ targets, rather than just those with updating actions. Since
+ the original pronouncement of targets to be udpated included
+ only those with updating actions, the progress report has been
+ changed to match.
+
+ 'If' conditionals now must be single arguments. Previously,
+ they could be zero or more arguments, which didn't make much
+ sense, and made things like 'foo == bar' true. The comparison
+ operator is '=', and '==' just looked like the second of three
+ arguments in the unary "non-empty argument list" conditional.
+
+ Header files indirectly including themselves were mistakenly
+ reported as being dependent on themselves. Recursing through
+ header file dependencies is now done after determining the fate
+ of the target.
+
+ The variable expansion support was expanding $(X)$(UNDEF) as if
+ it were $(X). It now expands to an empty list, like it
+ should.
+
+ The UNIX version of file_build() didn't handle "dir/.suffix"
+ right. Now it does.
+
+ The VMS command buffer was assumed to be as large as 1024 bytes,
+ which isn't the case everywhere as it is related to some weird
+ quota. It has been lowered to 256.
+
+ $(>) and $(<) wouldn't expand in action blocks if the targets
+ were marked with NOTIME. Now they expand properly.
+
+ Malloc() return values are now checked.
+
+ The variable expansion routine var_expand() is now a little
+ faster, by taking a few often needed shortcuts.
+
+ The VMS version of file_build() used the wrong length when
+ re-rooting file names that already had directory compoents.
+ This was fixed.
+
+ Various tracing adjustments were made.
+
+5. Limitations/Known Bugs
+
+ The new Windows/NT support has only been marginally tested. It
+ is dependent on certain variables being set depending on which
+ compiler you are using. You'll need to look in the file
+ Jambase and see what variables are expected to be set.
+
+ The VMS support has been tested, courtesy of the DEC guest
+ machine, but has not been hammered fully in release 2.0. It
+ was used quite a bit in Jam 1.0.
+
+ Jam clean when there is nothing to clean claims it is updating
+ a target.
+
+ Because the include statement works by pushing a new file in
+ the input stream of the scanner rather than recursively
+ invoking the parser on the new file, multiple include
+ statements in a rule's procedure causes the files to be
+ included in reverse order.
+
+ If the include statement appears inside an if block, the
+ parser's attempt to find the else will cause the text of the
+ included file to appear after the first token following the
+ statement block. This is rarely what is intended.
+
+ In a rule's actions, only $(<) and $(>) refer to the bound file
+ names: all other variable references get the unbound names.
+ This is a pain for $(NEEDLIBS), because it means that library
+ path can't be bound using $(SEARCH) and $(LOCATE).
+
+ With the -j flag, errors from failed commands can get
+ staggeringly mixed up. Also, because targets tend to get built
+ in a quickest-first ordering, dependency information must be
+ quite exact. Finally, beware of parallelizing commands that
+ drop fixed-named files into the current directory, like yacc(1)
+ does.
+
+ A poorly set $(JAMSHELL) is likely to result in silent
+ failure.
Added: boost-jam/boost-build/branches/upstream/current/jam_src/boost-jam.spec
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/boost-jam.spec 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/boost-jam.spec 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,64 @@
+Name: boost-jam
+Version: 3.1.10
+Summary: Build tool
+Release: 1
+Source: %{name}-%{version}.tgz
+
+License: Boost Software License, Version 1.0
+Group: Development/Tools
+URL: http://www.boost.org
+Packager: Rene Rivera <grafik at redshift-software.com>
+BuildRoot: /var/tmp/%{name}-%{version}.root
+
+%description
+Boost Jam is a build tool based on FTJam, which in turn is based on
+Perforce Jam. It contains significant improvements made to facilitate
+its use in the Boost Build System, but should be backward compatible
+with Perforce Jam.
+
+Authors:
+ Perforce Jam : Cristopher Seiwald
+ FT Jam : David Turner
+ Boost Jam : David Abrahams
+
+Copyright:
+ /+\
+ +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ \+/
+ License is hereby granted to use this software and distribute it
+ freely, as long as this copyright notice is retained and modifications
+ are clearly marked.
+ ALL WARRANTIES ARE HEREBY DISCLAIMED.
+
+Also:
+ Copyright 2001-2004 David Abrahams.
+ Copyright 2002-2004 Rene Rivera.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+%prep
+%setup -n %{name}-%{version}
+
+%build
+LOCATE_TARGET=bin ./build.sh $BOOST_JAM_TOOLSET
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT%{_bindir}
+mkdir -p $RPM_BUILD_ROOT%{_docdir}/%{name}-%{version}
+install -m 755 bin/bjam $RPM_BUILD_ROOT%{_bindir}/bjam-%{version}
+ln -sf bjam-%{version} $RPM_BUILD_ROOT%{_bindir}/bjam
+ln -sf bjam-%{version} $RPM_BUILD_ROOT%{_bindir}/jam
+install -m 644 *.html *.txt Porting $RPM_BUILD_ROOT%{_docdir}/%{name}-%{version}
+
+find $RPM_BUILD_ROOT -name CVS -type d -depth -exec rm -r {} \;
+
+%files
+%defattr(-,root,root)
+%attr(755,root,root) /usr/bin/*
+%doc %{_docdir}/%{name}-%{version}
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
Added: boost-jam/boost-build/branches/upstream/current/jam_src/build.bat
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/build.bat 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/build.bat 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,364 @@
+ at ECHO OFF
+
+REM ~ Copyright 2002-2003 Rene Rivera.
+REM ~ Distributed under the Boost Software License, Version 1.0.
+REM ~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+setlocal
+goto Start
+
+REM NOTE: The "setlocal & endlocal" construct is used to reset the errorlevel to 0.
+REM NOTE: The "set _error_=" construct is used to set the errorlevel to 1
+
+:Error_Print
+REM Output an error message and set the errorlevel to indicate failure.
+setlocal
+ECHO ###
+ECHO ### %1
+ECHO ###
+ECHO ### You can specify the toolset as the argument, i.e.:
+ECHO ### .\build.bat msvc
+ECHO ###
+ECHO ### Toolsets supported by this script are: borland, como, gcc, gcc-nocygwin, intel-win32, metrowerks, mingw, msvc, vc7
+ECHO ###
+set _error_=
+endlocal
+goto :eof
+
+:Test_Path
+REM Tests for the given file(executable) presence in the directories in the PATH
+REM environment variable. Additionaly sets FOUND_PATH to the path of the
+REM found file.
+setlocal & endlocal
+setlocal
+set test=%~$PATH:1
+endlocal
+if not errorlevel 1 set FOUND_PATH=%~dp$PATH:1
+goto :eof
+
+:Test_Option
+REM Tests wether the given string is in the form of an option: "-*"
+setlocal & endlocal
+setlocal
+set test=%1
+if not "-" == "%test:~0,1%" set _error_=
+endlocal
+goto :eof
+
+:Guess_Toolset
+REM Try and guess the toolset to bootstrap the build with...
+REM Sets BOOST_JAM_TOOLSET to the first found toolset.
+REM May also set BOOST_JAM_TOOLSET_ROOT to the
+REM location of the found toolset.
+setlocal & endlocal
+if NOT "_%CWFolder%_" == "__" (
+ set BOOST_JAM_TOOLSET=metrowerks
+ set BOOST_JAM_TOOLSET_ROOT=%CWFolder%\
+ goto :eof )
+setlocal & endlocal
+call :Test_Path mwcc.exe
+if not errorlevel 1 (
+ set BOOST_JAM_TOOLSET=metrowerks
+ set BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\..\
+ goto :eof)
+setlocal & endlocal
+if NOT "_%VS71COMNTOOLS%_" == "__" (
+ set BOOST_JAM_TOOLSET=vc7
+ set BOOST_JAM_TOOLSET_ROOT=%VS71COMNTOOLS%\..\..\VC7\
+ goto :eof)
+setlocal & endlocal
+if NOT "_%VCINSTALLDIR%_" == "__" (
+ set BOOST_JAM_TOOLSET=vc7
+ set BOOST_JAM_TOOLSET_ROOT=%VCINSTALLDIR%\VC7\
+ goto :eof)
+setlocal & endlocal
+if EXIST "%ProgramFiles%\Microsoft Visual Studio .NET 2003\VC7\bin\VCVARS32.BAT" (
+ set BOOST_JAM_TOOLSET=vc7
+ set BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio .NET 2003\VC7\
+ goto :eof)
+setlocal & endlocal
+if EXIST "C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\bin\VCVARS32.BAT" (
+ set BOOST_JAM_TOOLSET=vc7
+ set BOOST_JAM_TOOLSET_ROOT=C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\
+ goto :eof)
+setlocal & endlocal
+if EXIST "%ProgramFiles%\Microsoft Visual Studio .NET\VC7\bin\VCVARS32.BAT" (
+ set BOOST_JAM_TOOLSET=vc7
+ set BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio .NET\VC7\
+ goto :eof)
+setlocal & endlocal
+if EXIST "C:\Program Files\Microsoft Visual Studio .NET\VC7\bin\VCVARS32.BAT" (
+ set BOOST_JAM_TOOLSET=vc7
+ set BOOST_JAM_TOOLSET_ROOT=C:\Program Files\Microsoft Visual Studio .NET\VC7\
+ goto :eof)
+setlocal & endlocal
+if NOT "_%MSVCDir%_" == "__" (
+ set BOOST_JAM_TOOLSET=msvc
+ set BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\
+ goto :eof)
+setlocal & endlocal
+if EXIST "%ProgramFiles%\Microsoft Visual Studio\VC98\bin\VCVARS32.BAT" (
+ set BOOST_JAM_TOOLSET=msvc
+ set BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio\VC98\
+ goto :eof)
+setlocal & endlocal
+if EXIST "C:\Program Files\Microsoft Visual Studio\VC98\bin\VCVARS32.BAT" (
+ set BOOST_JAM_TOOLSET=msvc
+ set BOOST_JAM_TOOLSET_ROOT=C:\Program Files\Microsoft Visual Studio\VC98\
+ goto :eof)
+setlocal & endlocal
+if EXIST "%ProgramFiles%\Microsoft Visual C++\VC98\bin\VCVARS32.BAT" (
+ set BOOST_JAM_TOOLSET=msvc
+ set BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual C++\VC98\
+ goto :eof)
+setlocal & endlocal
+if EXIST "C:\Program Files\Microsoft Visual C++\VC98\bin\VCVARS32.BAT" (
+ set BOOST_JAM_TOOLSET=msvc
+ set BOOST_JAM_TOOLSET_ROOT=C:\Program Files\Microsoft Visual C++\VC98\
+ goto :eof)
+setlocal & endlocal
+call :Test_Path cl.exe
+if not errorlevel 1 (
+ set BOOST_JAM_TOOLSET=msvc
+ set BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\
+ goto :eof)
+setlocal & endlocal
+call :Test_Path vcvars32.bat
+if not errorlevel 1 (
+ set BOOST_JAM_TOOLSET=msvc
+ call "%FOUND_PATH%VCVARS32.BAT"
+ set BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\
+ goto :eof)
+setlocal & endlocal
+if EXIST "C:\Borland\BCC55\Bin\bcc32.exe" (
+ set BOOST_JAM_TOOLSET=borland
+ set BOOST_JAM_TOOLSET_ROOT=C:\Borland\BCC55\
+ goto :eof)
+setlocal & endlocal
+call :Test_Path bcc32.exe
+if not errorlevel 1 (
+ set BOOST_JAM_TOOLSET=borland
+ set BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\
+ goto :eof)
+setlocal & endlocal
+call :Test_Path icl.exe
+if not errorlevel 1 (
+ set BOOST_JAM_TOOLSET=intel-win32
+ set BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\
+ goto :eof)
+setlocal & endlocal
+if EXIST "C:\MinGW\bin\gcc.exe" (
+ set BOOST_JAM_TOOLSET=mingw
+ set BOOST_JAM_TOOLSET_ROOT=C:\MinGW\
+ goto :eof)
+setlocal & endlocal
+call :Error_Print "Could not find a suitable toolset."
+goto :eof
+
+:Guess_Yacc
+REM Tries to find bison or yacc in common places so we can build the grammar.
+setlocal & endlocal
+call :Test_Path yacc.exe
+if not errorlevel 1 (
+ set YACC=yacc -d
+ goto :eof)
+setlocal & endlocal
+call :Test_Path bison.exe
+if not errorlevel 1 (
+ set YACC=bison -d --yacc
+ goto :eof)
+setlocal & endlocal
+if EXIST "C:\Program Files\GnuWin32\bin\bison.exe" (
+ set YACC="C:\Program Files\GnuWin32\bin\bison.exe" -d --yacc
+ goto :eof)
+setlocal & endlocal
+call :Error_Print "Could not find Yacc to build the Jam grammar."
+goto :eof
+
+:Start
+set BOOST_JAM_TOOLSET=
+
+REM If no arguments guess the toolset;
+REM or if first argument is an option guess the toolset;
+REM otherwise the argument is the toolset to use.
+if "_%1_" == "__" (
+ call :Guess_Toolset
+ if not errorlevel 1 goto Setup_Toolset
+) else (
+ call :Test_Option %1
+ if not errorlevel 1 (
+ call :Guess_Toolset
+ if not errorlevel 1 goto Setup_Toolset
+ ) else (
+ setlocal & endlocal
+ set BOOST_JAM_TOOLSET=%1
+ shift
+ goto Setup_Toolset
+ )
+)
+if errorlevel 1 goto Finish
+
+:Setup_Toolset
+REM Setup the toolset command and options. This bit of code
+REM needs to be flexible enough to handle both when
+REM the toolset was guessed at and found, or when the toolset
+REM was indicated in the command arguments.
+REM NOTE: The strange multiple "if ?? == _toolset_" tests are that way
+REM because in BAT variables are subsituted only once during a single
+REM command. A complete "if ... ( commands ) else ( commands )"
+REM is a single command, even though it's in multiple lines here.
+if "_%BOOST_JAM_TOOLSET%_" == "_metrowerks_" (
+ if NOT "_%CWFolder%_" == "__" (
+ set BOOST_JAM_TOOLSET_ROOT=%CWFolder%\) )
+if "_%BOOST_JAM_TOOLSET%_" == "_metrowerks_" (
+ if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ set PATH=%BOOST_JAM_TOOLSET_ROOT%Other Metrowerks Tools\Command Line Tools;%PATH%)
+ set BOOST_JAM_CC=mwcc -runtime ss -cwd include -DNT -ladvapi32.lib
+ set BOOST_JAM_OPT_JAM=-o bootstrap.%BOOST_JAM_TOOLSET%\jam0.exe
+ set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0.exe
+ set BOOST_JAM_OPT_YYACC=-o bootstrap.%BOOST_JAM_TOOLSET%\yyacc0.exe
+ set _known_=1
+)
+if "_%BOOST_JAM_TOOLSET%_" == "_msvc_" (
+ if NOT "_%MSVCDir%_" == "__" (
+ set BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\) )
+if "_%BOOST_JAM_TOOLSET%_" == "_msvc_" (
+ if EXIST "%BOOST_JAM_TOOLSET_ROOT%bin\VCVARS32.BAT" (
+ call "%BOOST_JAM_TOOLSET_ROOT%bin\VCVARS32.BAT" ) )
+if "_%BOOST_JAM_TOOLSET%_" == "_msvc_" (
+ if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ set PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%)
+ set BOOST_JAM_CC=cl /nologo /GZ /Zi /MLd -DNT -DYYDEBUG kernel32.lib advapi32.lib
+ set BOOST_JAM_OPT_JAM=/Febootstrap.%BOOST_JAM_TOOLSET%\jam0
+ set BOOST_JAM_OPT_MKJAMBASE=/Febootstrap.%BOOST_JAM_TOOLSET%\mkjambase0
+ set BOOST_JAM_OPT_YYACC=/Febootstrap.%BOOST_JAM_TOOLSET%\yyacc0
+ set _known_=1
+)
+if "_%BOOST_JAM_TOOLSET%_" == "_vc7_" (
+ if NOT "_%MSVCDir%_" == "__" (
+ set BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\) )
+if "_%BOOST_JAM_TOOLSET%_" == "_vc7_" (
+ if EXIST "%BOOST_JAM_TOOLSET_ROOT%bin\VCVARS32.BAT" (
+ call "%BOOST_JAM_TOOLSET_ROOT%bin\VCVARS32.BAT" ) )
+if "_%BOOST_JAM_TOOLSET%_" == "_vc7_" (
+ if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ set PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%)
+ set BOOST_JAM_CC=cl /nologo /GZ /Zi /MLd -DNT -DYYDEBUG kernel32.lib advapi32.lib
+ set BOOST_JAM_OPT_JAM=/Febootstrap.%BOOST_JAM_TOOLSET%\jam0
+ set BOOST_JAM_OPT_MKJAMBASE=/Febootstrap.%BOOST_JAM_TOOLSET%\mkjambase0
+ set BOOST_JAM_OPT_YYACC=/Febootstrap.%BOOST_JAM_TOOLSET%\yyacc0
+ set _known_=1
+)
+if "_%BOOST_JAM_TOOLSET%_" == "_borland_" (
+ if "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ call :Test_Path bcc32.exe ) )
+if "_%BOOST_JAM_TOOLSET%_" == "_borland_" (
+ if "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ if not errorlevel 1 (
+ set BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\) ) )
+if "_%BOOST_JAM_TOOLSET%_" == "_borland_" (
+ if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (set PATH=%BOOST_JAM_TOOLSET_ROOT%Bin;%PATH%)
+ set BOOST_JAM_CC=bcc32 -WC -w- -q "-I%BOOST_JAM_TOOLSET_ROOT%Include" "-L%BOOST_JAM_TOOLSET_ROOT%Lib" /DNT -nbootstrap.%BOOST_JAM_TOOLSET%
+ set BOOST_JAM_OPT_JAM=-ejam0
+ set BOOST_JAM_OPT_MKJAMBASE=-emkjambasejam0
+ set BOOST_JAM_OPT_YYACC=-eyyacc0
+ set _known_=1
+)
+if "_%BOOST_JAM_TOOLSET%_" == "_como_" (
+ set BOOST_JAM_CC=como -DNT
+ set BOOST_JAM_OPT_JAM=-o bootstrap.%BOOST_JAM_TOOLSET%\jam0.exe
+ set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0.exe
+ set BOOST_JAM_OPT_YYACC=-o bootstrap.%BOOST_JAM_TOOLSET%\yyacc0.exe
+ set _known_=1
+)
+if "_%BOOST_JAM_TOOLSET%_" == "_gcc_" (
+ set BOOST_JAM_CC=gcc -DNT
+ set BOOST_JAM_OPT_JAM=-o bootstrap.%BOOST_JAM_TOOLSET%\jam0.exe
+ set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0.exe
+ set BOOST_JAM_OPT_YYACC=-o bootstrap.%BOOST_JAM_TOOLSET%\yyacc0.exe
+ set _known_=1
+)
+if "_%BOOST_JAM_TOOLSET%_" == "_gcc-nocygwin_" (
+ set BOOST_JAM_CC=gcc -DNT -mno-cygwin
+ set BOOST_JAM_OPT_JAM=-o bootstrap.%BOOST_JAM_TOOLSET%\jam0.exe
+ set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0.exe
+ set BOOST_JAM_OPT_YYACC=-o bootstrap.%BOOST_JAM_TOOLSET%\yyacc0.exe
+ set _known_=1
+)
+if "_%BOOST_JAM_TOOLSET%_" == "_intel-win32_" (
+ set BOOST_JAM_CC=icl -DNT /nologo
+ set BOOST_JAM_OPT_JAM=/Febootstrap.%BOOST_JAM_TOOLSET%\jam0
+ set BOOST_JAM_OPT_MKJAMBASE=/Febootstrap.%BOOST_JAM_TOOLSET%\mkjambase0
+ set BOOST_JAM_OPT_YYACC=/Febootstrap.%BOOST_JAM_TOOLSET%\yyacc0
+ set _known_=1
+)
+if "_%BOOST_JAM_TOOLSET%_" == "_mingw_" (
+ if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (set PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%)
+ set BOOST_JAM_CC=gcc -DNT
+ set BOOST_JAM_OPT_JAM=-o bootstrap.%BOOST_JAM_TOOLSET%\jam0.exe
+ set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0.exe
+ set BOOST_JAM_OPT_YYACC=-o bootstrap.%BOOST_JAM_TOOLSET%\yyacc0.exe
+ set _known_=1
+)
+if "_%_known_%_" == "__" (
+ call :Error_Print "Unknown toolset: %BOOST_JAM_TOOLSET%"
+)
+if errorlevel 1 goto Finish
+
+echo ###
+echo ### Using '%BOOST_JAM_TOOLSET%' toolset.
+echo ###
+
+set YYACC_SOURCES=yyacc.c
+set MKJAMBASE_SOURCES=mkjambase.c
+set BJAM_SOURCES=
+set BJAM_SOURCES=%BJAM_SOURCES% command.c compile.c execnt.c execunix.c execvms.c expand.c
+set BJAM_SOURCES=%BJAM_SOURCES% filent.c fileos2.c fileunix.c filevms.c glob.c hash.c
+set BJAM_SOURCES=%BJAM_SOURCES% hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c
+set BJAM_SOURCES=%BJAM_SOURCES% newstr.c option.c parse.c pathunix.c pathvms.c regexp.c
+set BJAM_SOURCES=%BJAM_SOURCES% rules.c scan.c search.c subst.c timestamp.c variable.c modules.c
+set BJAM_SOURCES=%BJAM_SOURCES% strings.c filesys.c builtins.c pwd.c class.c w32_getreg.c native.c
+set BJAM_SOURCES=%BJAM_SOURCES% modules/set.c modules/path.c modules/regex.c
+set BJAM_SOURCES=%BJAM_SOURCES% modules/property-set.c modules/sequence.c modules/order.c
+
+ at echo ON
+rd /S /Q bootstrap.%BOOST_JAM_TOOLSET%
+md bootstrap.%BOOST_JAM_TOOLSET%
+ at if not exist jamgram.y goto Bootstrap_GrammarPrep
+ at if not exist jamgramtab.h goto Bootstrap_GrammarPrep
+ at goto Skip_GrammarPrep
+:Bootstrap_GrammarPrep
+%BOOST_JAM_CC% %BOOST_JAM_OPT_YYACC% %YYACC_SOURCES%
+ at if not exist ".\bootstrap.%BOOST_JAM_TOOLSET%\yyacc0.exe" goto Skip_GrammarPrep
+.\bootstrap.%BOOST_JAM_TOOLSET%\yyacc0 jamgram.y jamgramtab.h jamgram.yy
+:Skip_GrammarPrep
+ at if not exist jamgram.c goto Bootstrap_GrammarBuild
+ at if not exist jamgram.h goto Bootstrap_GrammarBuild
+ at goto Skip_GrammarBuild
+:Bootstrap_GrammarBuild
+ at echo OFF
+if "_%YACC%_" == "__" (
+ call :Guess_Yacc
+)
+if errorlevel 1 goto Finish
+ at echo ON
+%YACC% jamgram.y
+ at if errorlevel 1 goto Finish
+del /f jamgram.c
+rename y.tab.c jamgram.c
+del /f jamgram.h
+rename y.tab.h jamgram.h
+:Skip_GrammarBuild
+ at echo ON
+ at if exist jambase.c goto Skip_Jambase
+%BOOST_JAM_CC% %BOOST_JAM_OPT_MKJAMBASE% %MKJAMBASE_SOURCES%
+ at if not exist ".\bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0.exe" goto Skip_Jambase
+.\bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0 jambase.c Jambase
+:Skip_Jambase
+%BOOST_JAM_CC% %BOOST_JAM_OPT_JAM% %BJAM_SOURCES%
+ at if not exist ".\bootstrap.%BOOST_JAM_TOOLSET%\jam0.exe" goto Skip_Jam
+.\bootstrap.%BOOST_JAM_TOOLSET%\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " clean
+.\bootstrap.%BOOST_JAM_TOOLSET%\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " %1 %2 %3 %4 %5 %6 %7 %8 %9
+:Skip_Jam
+
+:Finish
Property changes on: boost-jam/boost-build/branches/upstream/current/jam_src/build.bat
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,758 @@
+#~ Copyright 2002-2004 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Platform related specifics.
+if $(NT) { rule .path { return "$(<:J=\\)" ; } }
+else if $(OS2) { rule .path { return "$(<:J=\\)" ; } }
+else if $(VMS) { rule .path { return "[.$(<:J=/)]" ; } }
+else if $(MAC) { rule .path { return ":$(<:J=\:)" ; } }
+else { rule .path { return "$(<:J=/)" ; } }
+if $(VMS) { . = "_" ; }
+else { . = "." ; }
+
+# Info about what we are building.
+NAME = boost-jam ;
+VERSION = 3$(.)1$(.)10 ;
+RELEASE = 1 ;
+LICENSE = 1_0 ;
+
+# Generate development debug binaries?
+if --debug in $(ARGV)
+{
+ debug = true ;
+}
+
+# Attempt to generate and/or build the grammar?
+if --grammar in $(ARGV)
+{
+ grammar = true ;
+}
+
+# Do we need to add a default build type argument?
+if ! ( --release in $(ARGV) ) &&
+ ! ( --debug in $(ARGV) )
+{
+ ARGV += --release ;
+}
+
+# An explicit root for the toolset? (trim spaces)
+toolset-root = [ MATCH --toolset-root=(.*) : $(ARGV) ] ;
+{
+ local t = [ MATCH "[ ]*(.*)" : $(toolset-root:J=" ") ] ;
+ toolset-root = ;
+ while $(t)
+ {
+ t = [ MATCH "([^ ]+)([ ]*)(.*)" : $(t) ] ;
+ toolset-root += $(t[1]) ;
+ if $(t[3]) { toolset-root += $(t[2]) ; }
+ t = $(t[3]) ;
+ }
+ toolset-root = $(toolset-root:J="") ;
+}
+
+# Configure the implemented toolsets. These are minimal
+# commands and options to compile the full Jam. When
+# adding new toolsets make sure to add them to the
+# "known" list also.
+rule toolset ( name command .type ? : opt.out + : opt.define * : flags * : linklibs * )
+{
+ .type ?= "" ;
+ tool.$(name)$(.type).cc ?= $(command) ;
+ tool.$(name)$(.type).opt.out ?= $(opt.out) ;
+ tool.$(name)$(.type).opt.define ?= $(opt.define) ;
+ tool.$(name)$(.type).flags ?= $(flags) ;
+ tool.$(name)$(.type).linklibs ?= $(linklibs) ;
+ if ! $(name) in $(toolsets) { toolsets += $(name) ; }
+}
+rule opt ( type : yes-opt * : no-opt * ) { if $(type) in $(ARGV) { return $(yes-opt) ; } else { return $(no-opt) ; } }
+## HP-UX aCC compiler
+toolset acc cc : "-o " : -D
+ : -Ae
+ [ opt --release : -s -O3 ]
+ [ opt --debug : -g -pg ] ;
+## Borland C++ 5.5.x
+toolset borland bcc32 : -e -n : /D
+ : -WC -w- -q "-I$(toolset-root)Include" "-L$(toolset-root)Lib"
+ [ opt --release : -O2 -vi -w-inl ]
+ [ opt --debug : -v -Od -vi- ] ;
+## Generic Unix cc
+if ! $(CC) { CC = cc ; }
+toolset cc $(CC) : "-o " : -D
+ : $(CFLAGS)
+ [ opt --release : -s -O ]
+ [ opt --debug : -g ]
+ : $(LIBS) ;
+## Comeau C/C++ 4.x
+toolset como como : "-o " : -D
+ : --c
+ [ opt --release : --inlining ]
+ [ opt --debug : --no_inlining ] ;
+## MacOSX Darwin, using GCC 2.9.x, 3.x
+toolset darwin cc : "-o " : -D
+ :
+ [ opt --release : -Wl,-x -O3 -finline-functions ]
+ [ opt --debug : -g -O0 -fno-inline -pg ] ;
+## GCC 2.x, 3.x
+toolset gcc gcc : "-o " : -D
+ : -pedantic
+ [ opt --release : [ opt --symbols : -g : -s ] -O3 -finline-functions ]
+ [ opt --debug : -g -O0 -fno-inline ] ;
+## GCC 2.x, 3.x on CYGWIN but without cygwin1.dll
+toolset gcc-nocygwin gcc : "-o " : -D
+ : -s -O3 -mno-cygwin
+ [ opt --release : -finline-functions ]
+ [ opt --debug : -s -O3 -fno-inline -pg ] ;
+## Intel C/C++ for Linux
+toolset intel-linux icc : "-o " : -D
+ :
+ [ opt --release : -Xlinker -s -O3 ]
+ [ opt --debug : -g -O0 -p ] ;
+## Intel C/C++ for Win32
+toolset intel-win32 icl : /Fe : -D
+ : /nologo
+ [ opt --release : /ML /O2 /Ob2 /Gy /GF /GA /GB ]
+ [ opt --debug : /MLd /DEBUG /Z7 /Od /Ob0 ] ;
+## KCC ?
+toolset kcc KCC : "-o " : -D
+ :
+ [ opt --release : -s +K2 ]
+ [ opt --debug : -g +K0 ] ;
+## Borland Kylix
+toolset kylix bc++ : -o : -D
+ : -tC -q
+ [ opt --release : -O2 -vi -w-inl ]
+ [ opt --debug : -v -Od -vi- ] ;
+## Metrowerks CodeWarrior 8.x
+{
+ local mwcc = ; if $(NT) { mwcc = mwcc ; } else { mwcc = mwc$(OSPLAT:L) ; }
+ mwcc ?= mwcc ;
+ toolset metrowerks $(mwcc) : "-o " : -D
+ : -subsystem console -cwd include -ladvapi32.lib
+ [ opt --release : -runtime ss -opt full -inline auto -inline level=8 ]
+ [ opt --debug : -runtime ssd -O0 -inline off ] ;
+}
+## MINGW GCC
+toolset mingw gcc : "-o " : -D
+ :
+ [ opt --release : -s -O3 -finline-functions ]
+ [ opt --debug : -g -O0 -fno-inline -pg ] ;
+## MIPS Pro
+toolset mipspro cc : "-o " : -D
+ :
+ [ opt --release : -s -O3 -g0 -INLINE:none ]
+ [ opt --debug : -g -O0 -INLINE ] ;
+## Microsoft Visual Studio C++ 6.x
+toolset msvc cl : /Fe : -D
+ : /nologo
+ [ opt --release : /ML /O2 /Ob2 /Gy /GF /GA /GB ]
+ [ opt --debug : /MLd /DEBUG /Z7 /Od /Ob0 ]
+ : kernel32.lib advapi32.lib ;
+## Sun Workshop 6 C++
+toolset sunpro cc : "-o " : -D
+ :
+ [ opt --release : -s -fast -xO4 ]
+ [ opt --debug : -g ] ;
+## Compaq Alpha CXX
+toolset tru64cxx cc : "-o " : -D
+ :
+ [ opt --release : -s -O5 -inline speed ]
+ [ opt --debug : -g -O0 -pg ] ;
+## IBM VisualAge C++
+toolset vacpp xlc : "-o " : -D
+ :
+ [ opt --release : -s -O3 -qstrict -qinline ]
+ [ opt --debug : -g -qNOOPTimize -qnoinline -pg ] ;
+## Microsoft Visual C++ .NET 7.x
+toolset vc7 cl : /Fe : -D
+ : /nologo
+ [ opt --release : /ML /O2 /Ob2 /Gy /GF /GA /GB ]
+ [ opt --debug : /MLd /DEBUG /Z7 /Od /Ob0 ]
+ : kernel32.lib advapi32.lib ;
+## VMS/OpenVMS DEC C
+toolset vmsdecc cc : /OBJECT= : "/DEFINES=(" "," ")"
+ : /STANDARD=VAXC /PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES
+ [ opt --release : /OPTIMIZE /NODEBUG ]
+ [ opt --debug : /NOOPTIMIZE /DEBUG ]
+ ;
+toolset vmsdecc link .link : /EXECUTABLE= :
+ : /NOMAP
+ [ opt --release : /NODEBUG ]
+ [ opt --debug : /DEBUG ]
+ ;
+
+# First set the build commands and options according to the
+# preset toolset.
+toolset = [ MATCH --toolset=(.*) : $(ARGV) ] ;
+if ! $(toolset)
+{
+ # For some reason, the following test does not catch
+ # empty toolset.
+ ECHO "###" ;
+ ECHO "###" No toolset specified. Please use --toolset option. ;
+ ECHO "###" ;
+ ECHO "###" Known toolsets are: $(toolsets:J=", ") ;
+ EXIT "###" ;
+}
+if ! $(toolset) in $(toolsets)
+{
+ ECHO "###" ;
+ ECHO "###" Unknown toolset: $(toolset) ;
+ ECHO "###" ;
+ ECHO "###" Known toolsets are: $(toolsets:J=", ") ;
+ EXIT "###" ;
+}
+--cc = $(tool.$(toolset).cc) ;
+if $(tool.$(toolset).opt.out[2])
+{
+ --bin = $(tool.$(toolset).opt.out[1]) ;
+ --dir = $(tool.$(toolset).opt.out[2]) ;
+}
+else
+{
+ --out = $(tool.$(toolset).opt.out) ;
+}
+--def = $(tool.$(toolset).opt.define) ;
+--flags = $(tool.$(toolset).flags) ;
+--defs = $(tool.$(toolset).defines) ;
+--libs = $(tool.$(toolset).linklibs) ;
+if $(tool.$(toolset).link.cc)
+{
+ --link = $(tool.$(toolset).link.cc) ;
+ if $(tool.$(toolset).link.opt.out[2])
+ {
+ --link-bin = $(tool.$(toolset).link.opt.out[1]) ;
+ --link-dir = $(tool.$(toolset).link.opt.out[2]) ;
+ }
+ else
+ {
+ --link-out = $(tool.$(toolset).link.opt.out) ;
+ }
+ --link-def = $(tool.$(toolset).link.opt.define) ;
+ --link-flags = $(tool.$(toolset).link.flags) ;
+ --link-defs = $(tool.$(toolset).link.defines) ;
+ --link-libs = $(tool.$(toolset).link.linklibs) ;
+}
+
+# Put executables in platform-specific subdirectory.
+locate-target = $(LOCATE_TARGET) ;
+if $(VMS)
+{
+ locate-target ?= bin$(.)vms ;
+ platform = vms ;
+}
+else if $(MAC)
+{
+ locate-target ?= bin$(.)$(OS:L)$(OSPLAT:L) ;
+ platform = $(OS:L)$(OSPLAT:L) ;
+}
+else if $(OSPLAT)
+{
+ locate-target ?= bin$(.)$(OS:L)$(OSPLAT:L) ;
+ platform = $(OS:L)$(OSPLAT:L) ;
+}
+else
+{
+ locate-target ?= bin$(.)$(OS:L) ;
+ platform = $(OS:L) ;
+}
+if $(debug)
+{
+ locate-target = [ .path $(locate-target)$(.)debug ] ;
+}
+else
+{
+ locate-target = [ .path $(locate-target) ] ;
+}
+
+# We have some different files for UNIX, VMS, and NT.
+jam.source =
+ command.c compile.c expand.c glob.c
+ hash.c hcache.c headers.c hdrmacro.c
+ jam.c jambase.c jamgram.c
+ lists.c make.c make1.c newstr.c
+ option.c parse.c regexp.c rules.c
+ scan.c search.c subst.c
+ timestamp.c variable.c modules.c strings.c filesys.c
+ builtins.c pwd.c class.c native.c modules/set.c
+ modules/path.c modules/regex.c modules/property-set.c
+ modules/sequence.c modules/order.c
+ ;
+if $(NT)
+{
+ jam.source += execnt.c filent.c pathunix.c w32_getreg.c ;
+}
+else if $(OS2)
+{
+ jam.source += execunix.c fileos2.c pathunix.c ;
+}
+else if $(VMS)
+{
+ jam.source += execvms.c filevms.c pathvms.c ;
+}
+else if $(MAC)
+{
+ jam.source += execmac.c filemac.c pathmac.c ;
+}
+else
+{
+ jam.source += execunix.c fileunix.c pathunix.c ;
+}
+
+# Debug assertions, or not.
+if ! $(debug) || --noassert in $(ARGV)
+{
+ --defs += NDEBUG ;
+}
+
+# Enable some optional features.
+--defs += OPT_HEADER_CACHE_EXT ;
+--defs += OPT_GRAPH_DEBUG_EXT ;
+--defs += OPT_SEMAPHORE ;
+
+# Bug fixes
+--defs += OPT_FIX_TARGET_VARIABLES_EXT ;
+
+# Improvements
+--defs += OPT_IMPROVED_PATIENCE_EXT ;
+
+if ( $(OS) = NT || $(NT) ) && ! NT in $(--defs)
+{
+ --defs += NT ;
+}
+if $(VMS)
+{
+ --defs += VMS ;
+}
+--defs += YYSTACKSIZE=5000 ;
+
+# The basic symbolic targets...
+NOTFILE all clean dist ;
+ALWAYS clean ;
+
+# Utility rules and actions...
+rule .clean
+{
+ .rm. clean : $(<) ;
+}
+if $(NT) { actions piecemeal together existing .rm. {
+ del /F /Q $(>)
+} }
+if $(UNIX) { actions piecemeal together existing .rm. {
+ rm -f $(>)
+} }
+if $(VMS) { actions piecemeal together existing .rm. {
+ DELETE $(>[--2]:J=";*, ") $(>[-1]);*
+} }
+if $(NT) {
+ --chmod+w = "attrib -r " ;
+}
+if $(UNIX) {
+ --chmod+w = "chmod +w " ;
+}
+if $(VMS) {
+ --chmod+w = "SET FILE/PROT=(S:RWED) " ;
+}
+
+rule .mkdir
+{
+ NOUPDATE $(<) ;
+ if $(<:P) { DEPENDS $(<) : $(<:P) ; .mkdir $(<:P) ; }
+ if ! $(md<$(<)>) { .mkdir. $(<) ; md<$(<)> = - ; }
+}
+if $(NT) { actions .mkdir. {
+ md $(<)
+} }
+if $(UNIX) { actions .mkdir. {
+ mkdir $(<)
+} }
+if $(VMS) { actions .mkdir. {
+ CREATE/DIR $(<J=", ")
+} }
+
+rule .exe
+{
+ local exe = $(<) ;
+ if $(NT) || ( $(UNIX) && $(OS) = CYGWIN ) || $(VMS) { exe = $(exe:S=.exe) ; }
+ LOCATE on $(exe) = $(locate-target) ;
+ DEPENDS all : $(exe) ;
+ .mkdir $(locate-target) ;
+ if $(--link)
+ {
+ for local s in $(>)
+ {
+ local o = $(s:S=.o) ;
+ LOCATE on $(o) = $(locate-target) ;
+ DEPENDS $(exe) : $(o) ;
+ DEPENDS $(o) : $(s) ;
+ DEPENDS $(o) : $(locate-target) ;
+ .cc. $(o) : $(s) ;
+ .clean $(o) ;
+ }
+ DEPENDS $(exe) : $(>:S=.o) ;
+ DEPENDS $(exe) : $(locate-target) ;
+ .ld. $(exe) : $(>:S=.o) ;
+ .clean $(exe) ;
+ }
+ else
+ {
+ DEPENDS $(exe) : $(>) ;
+ DEPENDS $(exe) : $(locate-target) ;
+ .cc. $(exe) : $(>) ;
+ .clean $(exe) ;
+ }
+ return $(exe) ;
+}
+if ! $(--def[2]) { actions .cc. {
+ "$(--cc)" $(--bin)$(<:D=) $(--dir)$(<:D) $(--out)$(<) $(--def)$(--defs) $(--flags) "$(--libs)" $(>)
+} }
+else { actions .cc. {
+ "$(--cc)" $(--bin)$(<:D=) $(--dir)$(<:D) $(--out)$(<) $(--def[1])$(--defs:J=$(--def[2]))$(--def[3]) $(--flags) "$(--libs)" $(>)
+} }
+if $(VMS) { actions .ld. {
+ "$(--link)" $(--link-bin)$(<:D=) $(--link-dir)$(<:D) $(--link-out)$(<) $(--link-def)$(--link-defs) $(--link-flags) "$(--link-libs)" $(>J=", ")
+} }
+else { actions .ld. {
+ "$(--link)" $(--link-bin)$(<:D=) $(--link-dir)$(<:D) $(--link-out)$(<) $(--link-def)$(--link-defs) $(--link-flags) "$(--link-libs)" $(>)
+} }
+
+rule .link
+{
+ DEPENDS all : $(<) ;
+ DEPENDS $(<) : $(>) ;
+ .link. $(<) : $(>) ;
+ .clean $(<) ;
+}
+if $(NT) { actions .link. {
+ copy $(>) $(<)
+} }
+if $(UNIX) { actions .link. {
+ ln -f $(>) $(<)
+} }
+if $(VMS) { actions .link. {
+ COPY/REPLACE $(>) $(<)
+} }
+
+rule .move
+{
+ DEPENDS $(<) : $(>) ;
+ .move. $(<) : $(>) ;
+}
+if $(NT) { actions .move. {
+ del /f $(<)
+ rename $(>) $(<)
+} }
+if $(UNIX) { actions .move. {
+ mv -f $(>) $(<)
+} }
+if $(VMS) { actions .move. {
+ RENAME $(>) $(<)
+} }
+
+# Generate the grammar tokens table, and the real yacc grammar.
+rule .yyacc
+{
+ local exe = [ .exe yyacc : yyacc.c ] ;
+ NOUPDATE $(exe) ;
+ DEPENDS $(<) : $(exe) $(>) ;
+ LEAVES $(<) ;
+ yyacc.exe on $(<) = $(exe:R=$(locate-target)) ;
+ .yyacc. $(<) : $(>) ;
+}
+actions .yyacc. {
+ $(--chmod+w)$(<[1])
+ $(--chmod+w)$(<[2])
+ "$(yyacc.exe)" $(<) $(>)
+}
+if $(grammar)
+{
+ .yyacc jamgram.y jamgramtab.h : jamgram.yy ;
+}
+else
+{
+ .exe yyacc : yyacc.c ;
+}
+
+# How to build the grammar.
+if $(NT)
+{
+ SUFEXE = .exe ;
+ # try some other likely spellings...
+ PATH ?= $(Path) ;
+ PATH ?= $(path) ;
+}
+SUFEXE ?= "" ;
+
+yacc ?= [ GLOB $(PATH) : yacc$(SUFEXE) ] ;
+yacc ?= [ GLOB $(PATH) : bison$(SUFEXE) ] ;
+yacc ?= [ GLOB "$(ProgramFiles:J= )\\GnuWin32\\bin" "C:\\Program Files\\GnuWin32\\bin" : bison$(SUFEXE) ] ;
+yacc = $(yacc[1]) ;
+switch $(yacc:D=:S=)
+{
+ case bison : yacc += -d --yacc ;
+ case yacc : yacc += -d ;
+}
+if $(debug) && $(yacc)
+{
+ yacc += -t -v ;
+}
+yacc += $(YACCFLAGS) ;
+
+rule .yacc
+{
+ DEPENDS $(<) : $(>) ;
+ LEAVES $(<) ;
+ .yacc. $(<) : $(>) ;
+}
+if $(NT) { actions .yacc. {
+ "$(yacc)" $(>)
+ if not errorlevel 1 (
+ del /f $(<[1])
+ rename y.tab$(<[1]:S) $(<[1])
+ del /f $(<[2])
+ rename y.tab$(<[2]:S) $(<[2])
+ ) else set _error_ =
+} }
+if $(UNIX) { actions .yacc. {
+ if ` "$(yacc)" $(>) ` ; then
+ mv -f y.tab$(<[1]:S) $(<[1])
+ mv -f y.tab$(<[2]:S) $(<[2])
+ else
+ exit 1
+ fi
+} }
+if $(VMS) { actions .yacc. {
+ IF "$(yacc)" $(>)
+ THEN
+ RENAME y_tab$(<[1]:S) $(<[1])
+ RENAME y_tab$(<[2]:S) $(<[2])
+ ENDIF
+} }
+if $(grammar) && ! $(yacc)
+{
+ EXIT "Could not find the 'yacc' tool, and therefore can not build the grammar." ;
+}
+if $(grammar) && $(yacc)
+{
+ .yacc jamgram.c jamgram.h : jamgram.y ;
+}
+
+# How to build the compiled in jambase.
+rule .mkjambase
+{
+ local exe = [ .exe mkjambase : mkjambase.c ] ;
+ DEPENDS $(<) : $(exe) $(>) ;
+ LEAVES $(<) ;
+ mkjambase.exe on $(<) = $(exe:R=$(locate-target)) ;
+ .mkjambase. $(<) : $(>) ;
+}
+actions .mkjambase. {
+ $(--chmod+w)$(<)
+ $(mkjambase.exe) $(<) $(>)
+}
+.mkjambase jambase.c : Jambase ;
+
+# How to build Jam.
+rule .jam
+{
+ $(>).exe = [ .exe $(>) : $(jam.source) ] ;
+ $(<).exe = $(<:S=$($(>).exe:S)) ;
+ LOCATE on $($(<).exe) = $(locate-target) ;
+ .link $($(<).exe) : $($(>).exe) ;
+
+ DEPENDS all : $($(>).exe) $($(<).exe) ;
+}
+.jam bjam : jam ;
+
+# Scan sources for header dependencies.
+rule .scan
+{
+ HDRRULE on $(<:D=) = .hdr.scan ;
+ HDRSCAN on $(<:D=) = "^[ ]*#[ ]*include[ ]*[<\"]([^\">]*)[\">].*$" ;
+}
+rule .hdr.scan
+{
+ local hdrs = [ GLOB . : $(>:D=) ] ;
+ INCLUDES $(<:D=) : $(hdrs:D=) ;
+ HDRRULE on $(>:D=) = .hdr.scan ;
+ HDRSCAN on $(>:D=) = "^[ ]*#[ ]*include[ ]*[<\"]([^\">]*)[\">].*$" ;
+}
+.scan [ GLOB . : *.c ] ;
+
+# Distribution making from here on out.
+dist.license =
+ #~ [ GLOB . : LICENSE_$(LICENSE).txt ] [ GLOB [ .path .. .. .. ] : LICENSE_$(LICENSE).txt ] ;
+ [ GLOB . : LICENSE_$(LICENSE).txt ]
+ [ GLOB [ .path .. .. .. ] : LICENSE_$(LICENSE).txt ]
+ [ GLOB [ .path .. boost ] : LICENSE_$(LICENSE).txt ] ;
+dist.docs =
+ $(dist.license[1])
+ index.html
+ Porting
+ Jam.html
+ ;
+dist.source =
+ [ GLOB . : *.c *.h ]
+ ;
+dist.source = $(dist.source:D=)
+ $(dist.docs)
+ build.jam build.bat build.sh build_vms.com
+ Jambase
+ jamgram.y jamgram.yy
+ [ .path debian changelog ]
+ [ .path debian control ]
+ [ .path debian copyright ]
+ [ .path debian jam.man.sgml ]
+ [ .path debian rules ]
+ [ .path modules set.c ]
+ [ .path modules path.c ]
+ [ .path modules regex.c ]
+ [ .path modules property-set.c ]
+ [ .path modules sequence.c ]
+ [ .path modules order.c ]
+ boost-jam.spec
+ ;
+dist.bin =
+ bjam
+ ;
+dist.bin =
+ $(dist.license[1])
+ $(dist.bin:S=$(bjam.exe:S))
+ ;
+
+if $(NT)
+{
+ zip ?= [ GLOB "$(ProgramFiles:J= )\\7-ZIP" "C:\\Program Files\\7-ZIP" : "7zn.exe" ] ;
+ zip ?= [ GLOB $(PATH) : zip.exe ] ;
+ zip ?= zip ;
+ zip = $(zip[1]) ;
+ switch $(zip:D=:S=)
+ {
+ case 7zn : zip += a -r -tzip ;
+ case zip : zip += -9r ;
+ }
+ actions piecemeal .pack. {
+ "$(zip)" "$(<)" "$(>)"
+ }
+ actions piecemeal .zip. {
+ "$(zip)" "$(<)" "$(>)"
+ }
+ actions piecemeal .cp. {
+ copy /Y "$(>)" "$(<)"
+ }
+}
+if $(UNIX)
+{
+ actions .pack. {
+ tar zcf "$(<)" "$(>)"
+ }
+ actions .zip. {
+ gzip -c9 "$(>)" > "$(<)"
+ }
+ actions .cp. {
+ cp -Rpf "$(>)" "$(<)"
+ }
+}
+
+# The single binary, compressed.
+rule .binary
+{
+ local zip = ;
+ if $(NT) { zip = $($(<).exe:S=.zip) ; }
+ if $(UNIX) { zip = $($(<).exe:S=.tgz) ; }
+ zip = $(zip:S=)-$(VERSION)-$(RELEASE)-$(platform)$(zip:S) ;
+ DEPENDS $(zip) : $($(<).exe) ;
+ DEPENDS dist : $(zip) ;
+ #~ LOCATE on $(zip) = $(locate-target) ;
+ if $(NT) { .zip. $(zip) : $($(<).exe) ; }
+ if $(UNIX) { .pack. $(zip) : $($(<).exe) ; }
+ .clean $(zip) ;
+}
+
+# Package some file.
+rule .package ( dst-dir : src-files + )
+{
+ local dst-files ;
+ for local src-path in $(src-files)
+ {
+ local src-subdir = $(src-path:D) ;
+ local src-file = $(src-path) ;
+ while $(src-subdir:D) { src-subdir = $(src-subdir:D) ; }
+ if $(src-subdir) = ".."
+ {
+ src-file = $(src-file:D=) ;
+ }
+ dst-files += $(src-file:R=$(dst-dir)) ;
+ }
+
+ local pack = ;
+ if $(NT) { pack = $(dst-dir).zip ; }
+ if $(UNIX) { pack = $(dst-dir).tgz ; }
+
+ DEPENDS dist : $(pack) ;
+ DEPENDS $(pack) : $(dst-files) ;
+
+ local dst-files-queue = $(dst-files) ;
+ for local src-path in $(src-files)
+ {
+ local dst-file = $(dst-files-queue[1]) ;
+ dst-files-queue = $(dst-files-queue[2-]) ;
+ DEPENDS $(dst-file) : $(src-path) $(dst-file:D) ;
+ .mkdir $(dst-file:D) ;
+
+ .cp. $(dst-file) : $(src-path) ;
+ .clean $(dst-file) ;
+ }
+
+ .pack. $(pack) : $(dst-files) ;
+ .clean $(pack) ;
+}
+
+# RPM distro file.
+rpm-tool = [ GLOB $(PATH) : "rpmbuild" "rpm" ] ;
+rule .rpm ( name : source )
+{
+ local rpm-arch = ;
+ switch $(OSPLAT)
+ {
+ case X86 : rpm-arch ?= i386 ;
+ case PPC : rpm-arch ?= ppc ;
+ case AXP : rpm-arch ?= alpha ;
+ # no guaranty for these:
+ case IA64 : rpm-arch ?= ia64 ;
+ case ARM : rpm-arch ?= arm ;
+ case SPARC : rpm-arch ?= sparc ;
+ case * : rpm-arch ?= other ;
+ }
+ local target = $(name)-rpm ;
+ NOTFILE $(target) ;
+ DEPENDS dist : $(target) ;
+ DEPENDS $(target) : $(name).$(rpm-arch).rpm $(name).src.rpm ;
+ DEPENDS $(name).$(rpm-arch).rpm : $(source) ;
+ DEPENDS $(name).src.rpm : $(name).$(rpm-arch).rpm ;
+ docs on $(target) = $(dist.docs:J=" ") ;
+ arch on $(target) = $(rpm-arch) ;
+ if $(rpm-arch) = ppc { target-opt on $(target) = --target= ; }
+ else { target-opt on $(target) = "--target " ; }
+ .rpm. $(target) : $(source) ;
+ .clean $(name).$(rpm-arch).rpm $(name).src.rpm ;
+}
+actions .rpm. {
+ export BOOST_JAM_TOOLSET="$(toolset)"
+ $(rpm-tool[1]) -ta $(target-opt)$(arch) $(>) | tee rpm.out
+ cp `grep -e '^Wrote:' rpm.out | sed 's/^Wrote: //'` .
+ rm -f rpm.out
+}
+
+# The distribution targets. Don't bother with the targets if
+# distribution build not requested.
+if dist in $(ARGV)
+{
+ #~ .binary bjam ;
+ .package $(NAME)-$(VERSION) : $(dist.source) ;
+ .package $(NAME)-$(VERSION)-$(RELEASE)-$(platform) : $(dist.bin) ;
+ if $(rpm-tool)
+ {
+ .rpm $(NAME)-$(VERSION)-$(RELEASE) : $(NAME)-$(VERSION).tgz ;
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/build.sh
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/build.sh 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/build.sh 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,225 @@
+#!/bin/sh
+
+#~ Copyright 2002-2003 Rene Rivera.
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+# Reset the toolset.
+BOOST_JAM_TOOLSET=
+
+# Run a command, and echo before doing so. Also checks the exit
+# status and quits if there was an error.
+echo_run ()
+{
+ echo "$@"
+ "$@"
+ r=$?
+ if test $r -ne 0 ; then
+ exit $r
+ fi
+}
+
+# Print an error message, and exit with a status of 1.
+error_exit ()
+{
+ echo "###"
+ echo "###" "$@"
+ echo "###"
+ echo "### You can specify the toolset as the argument, i.e.:"
+ echo "### ./build.sh gcc"
+ echo "###"
+ echo "### Toolsets supported by this script are:"
+ echo "### acc, como, darwin, gcc, intel-linux, kcc, kylix, mipspro,"
+ echo "### sunpro, tru64cxx, vacpp"
+ echo "###"
+ echo "### A special toolset; cc, is available which is used as a fallback"
+ echo "### when a more specific toolset is not found and the cc command is"
+ echo "### detected. The 'cc' toolset will use the CC, CFLAGS, and LIBS"
+ echo "### envrironment variables, if present."
+ echo "###"
+ exit 1
+}
+
+# Check that a command is in the PATH.
+test_path ()
+{
+ if `whence 1>/dev/null 2>/dev/null`; then
+ whence $1 1>/dev/null 2>/dev/null
+ else
+ hash $1 1>/dev/null 2>/dev/null
+ fi
+}
+
+# Check that the OS name, as returned by "uname", is as given.
+test_uname ()
+{
+ if test_path uname; then
+ test `uname` = $*
+ fi
+}
+
+# Try and guess the toolset to bootstrap the build with...
+Guess_Toolset ()
+{
+ if test_uname Darwin ; then BOOST_JAM_TOOLSET=darwin
+ elif test_uname IRIX ; then BOOST_JAM_TOOLSET=mipspro
+ elif test_uname IRIX64 ; then BOOST_JAM_TOOLSET=mipspro
+ elif test_path gcc ; then BOOST_JAM_TOOLSET=gcc
+ elif test_path icc ; then BOOST_JAM_TOOLSET=intel-linux
+ elif test -r /opt/intel/compiler70/ia32/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET=intel-linux
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler70/ia32/
+ elif test -r /opt/intel/compiler60/ia32/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET=intel-linux
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler60/ia32/
+ elif test -r /opt/intel/compiler50/ia32/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET=intel-linux
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler50/ia32/
+ elif test_path xlc ; then BOOST_JAM_TOOLSET=vacpp
+ elif test_path como ; then BOOST_JAM_TOOLSET=como
+ elif test_path KCC ; then BOOST_JAM_TOOLSET=kcc
+ elif test_path bc++ ; then BOOST_JAM_TOOLSET=kylix
+ elif test_path aCC ; then BOOST_JAM_TOOLSET=acc
+ elif test_uname HP-UX ; then BOOST_JAM_TOOLSET=acc
+ elif test -r /opt/SUNWspro/bin/cc ; then
+ BOOST_JAM_TOOLSET=sunpro
+ BOOST_JAM_TOOLSET_ROOT=/opt/SUNWspro/
+ # Test for "cc" as the default fallback.
+ elif test_path $CC ; then BOOST_JAM_TOOLSET=cc
+ elif test_path cc ; then
+ BOOST_JAM_TOOLSET=cc
+ CC=cc
+ fi
+ if test "$BOOST_JAM_TOOLSET" = "" ; then
+ error_exit "Could not find a suitable toolset."
+ fi
+}
+
+# The one option we support in the invocation
+# is the name of the toolset to force building
+# with.
+case "$1" in
+ -*) Guess_Toolset ;;
+ ?*) BOOST_JAM_TOOLSET=$1 ; shift ;;
+ *) Guess_Toolset ;;
+esac
+BOOST_JAM_OPT_JAM="-o bootstrap.$BOOST_JAM_TOOLSET/jam0"
+BOOST_JAM_OPT_MKJAMBASE="-o bootstrap.$BOOST_JAM_TOOLSET/mkjambase0"
+BOOST_JAM_OPT_YYACC="-o bootstrap.$BOOST_JAM_TOOLSET/yyacc0"
+case $BOOST_JAM_TOOLSET in
+ gcc)
+ BOOST_JAM_CC=gcc
+ ;;
+
+ darwin)
+ BOOST_JAM_CC=cc
+ ;;
+
+ intel-linux)
+ if test -r /opt/intel/compiler70/ia32/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler70/ia32/
+ elif test -r /opt/intel/compiler60/ia32/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler60/ia32/
+ elif test -r /opt/intel/compiler50/ia32/bin/iccvars.sh ; then
+ BOOST_JAM_TOOLSET_ROOT=/opt/intel/compiler50/ia32/
+ fi
+ if test -r ${BOOST_JAM_TOOLSET_ROOT}bin/iccvars.sh ; then
+ . ${BOOST_JAM_TOOLSET_ROOT}bin/iccvars.sh
+ fi
+ BOOST_JAM_CC=icc
+ ;;
+
+ vacpp)
+ BOOST_JAM_CC=xlc
+ ;;
+
+ como)
+ BOOST_JAM_CC="como --c"
+ ;;
+
+ kcc)
+ BOOST_JAM_CC=KCC
+ ;;
+
+ kylix)
+ BOOST_JAM_CC=bc++
+ ;;
+
+ mipspro)
+ BOOST_JAM_CC=cc
+ ;;
+
+ sunpro)
+ if test -r /opt/SUNWspro/bin/cc ; then
+ BOOST_JAM_TOOLSET_ROOT=/opt/SUNWspro/
+ fi
+ if test -r $BOOST_JAM_TOOLSET_ROOTbin/cc ; then
+ export PATH=$BOOST_JAM_TOOLSET_ROOTbin:$PATH
+ fi
+ BOOST_JAM_CC=cc
+ ;;
+
+ tru64cxx)
+ BOOST_JAM_CC=cc
+ ;;
+
+ acc)
+ BOOST_JAM_CC="cc -Ae"
+ ;;
+
+ cc)
+ if test -z "$CC" ; then CC=cc ; fi
+ BOOST_JAM_CC=$CC
+ BOOST_JAM_OPT_JAM="$BOOST_JAM_OPT_JAM $CFLAGS $LIBS"
+ BOOST_JAM_OPT_MKJAMBASE="$BOOST_JAM_OPT_MKJAMBASE $CFLAGS $LIBS"
+ BOOST_JAM_OPT_YYACC="$BOOST_JAM_OPT_YYACC $CFLAGS $LIBS"
+ ;;
+
+ *)
+ error_exit "Unknown toolset: $BOOST_JAM_TOOLSET"
+ ;;
+esac
+
+echo "###"
+echo "### Using '$BOOST_JAM_TOOLSET' toolset."
+echo "###"
+
+YYACC_SOURCES="yyacc.c"
+MKJAMBASE_SOURCES="mkjambase.c"
+BJAM_SOURCES="\
+ command.c compile.c execnt.c execunix.c execvms.c expand.c\
+ filent.c fileos2.c fileunix.c filevms.c glob.c hash.c\
+ hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c\
+ newstr.c option.c parse.c pathunix.c pathvms.c regexp.c\
+ rules.c scan.c search.c subst.c timestamp.c variable.c modules.c\
+ strings.c filesys.c builtins.c pwd.c class.c native.c modules/set.c\
+ modules/path.c modules/regex.c modules/property-set.c\
+ modules/sequence.c modules/order.c"
+
+echo_run rm -rf bootstrap.$BOOST_JAM_TOOLSET
+echo_run mkdir bootstrap.$BOOST_JAM_TOOLSET
+if test ! -r jamgram.y -o ! -r jamgramtab.h ; then
+ echo_run ${BOOST_JAM_CC} ${BOOST_JAM_OPT_YYACC} ${YYACC_SOURCES}
+ if test -x "./bootstrap.$BOOST_JAM_TOOLSET/yyacc0" ; then
+ echo_run ./bootstrap.$BOOST_JAM_TOOLSET/yyacc0 jamgram.y jamgramtab.h jamgram.yy
+ fi
+fi
+if test ! -r jamgram.c -o ! -r jamgram.h ; then
+ if test_path yacc ; then YACC="yacc -d"
+ elif test_path bison ; then YACC="bison -y -d --yacc"
+ fi
+ echo_run $YACC jamgram.y
+ mv -f y.tab.c jamgram.c
+ mv -f y.tab.h jamgram.h
+fi
+if test ! -r jambase.c ; then
+ echo_run ${BOOST_JAM_CC} ${BOOST_JAM_OPT_MKJAMBASE} ${MKJAMBASE_SOURCES}
+ if test -x "./bootstrap.$BOOST_JAM_TOOLSET/mkjambase0" ; then
+ echo_run ./bootstrap.$BOOST_JAM_TOOLSET/mkjambase0 jambase.c Jambase
+ fi
+fi
+echo_run ${BOOST_JAM_CC} ${BOOST_JAM_OPT_JAM} ${BJAM_SOURCES}
+if test -x "./bootstrap.$BOOST_JAM_TOOLSET/jam0" ; then
+ echo_run ./bootstrap.$BOOST_JAM_TOOLSET/jam0 -f build.jam --toolset=$BOOST_JAM_TOOLSET "--toolset-root=$BOOST_JAM_TOOLSET_ROOT" clean
+ echo_run ./bootstrap.$BOOST_JAM_TOOLSET/jam0 -f build.jam --toolset=$BOOST_JAM_TOOLSET "--toolset-root=$BOOST_JAM_TOOLSET_ROOT" "$@"
+fi
Property changes on: boost-jam/boost-build/branches/upstream/current/jam_src/build.sh
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/build_vms.com
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/build_vms.com 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/build_vms.com 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,105 @@
+$ ! Copyright 2002-2003 Rene Rivera, Johan Nilsson.
+$ ! Distributed under the Boost Software License, Version 1.0.
+$ ! (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+$ !
+$ ! bootstrap build script for Jam
+$ !
+$ SAY :== WRITE SYS$OUTPUT
+$ !
+$ ON WARNING THEN CONTINUE
+$ !
+$ IF "" .NES. F$SEARCH("[.bootstrap_vms]*.*")
+$ THEN
+$ SAY "Cleaning previous boostrap files..."
+$ !
+$ SET FILE/PROTECTION=(S:RWED) [.bootstrap_vms]*.*;*
+$ DELETE [.bootstrap_vms]*.*;*
+$ ENDIF
+$ !
+$ IF "" .NES. F$SEARCH("bootstrap_vms.dir")
+$ THEN
+$ SAY "Removing previous boostrap directory..."
+$ !
+$ SET FILE/PROT=(S:RWED) bootstrap_vms.dir
+$ DELETE bootstrap_vms.dir;
+$ ENDIF
+$ !
+$ SAY "Creating boostrap directory..."
+$ !
+$ CREATE/DIR [.bootstrap_vms]
+$ !
+$ SAY "Building bootstrap jam..."
+$ !
+$ CC_FLAGS = "/DEFINE=VMS /STANDARD=VAXC /PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES "
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]builtins.obj builtins.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]command.obj command.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]compile.obj compile.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]execvms.obj execvms.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]expand.obj expand.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]filesys.obj filesys.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]filevms.obj filevms.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]glob.obj glob.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]hash.obj hash.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]hdrmacro.obj hdrmacro.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]headers.obj headers.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]jam.obj jam.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]jambase.obj jambase.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]jamgram.obj jamgram.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]lists.obj lists.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]make.obj make.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]make1.obj make1.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]modules.obj modules.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]newstr.obj newstr.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]option.obj option.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]parse.obj parse.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]pathvms.obj pathvms.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]pwd.obj pwd.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]regexp.obj regexp.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]rules.obj rules.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]scan.obj scan.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]search.obj search.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]strings.obj strings.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]subst.obj subst.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]timestamp.obj timestamp.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]variable.obj variable.c
+$ link -
+ /EXECUTABLE=[.bootstrap_vms]jam0.exe -
+ [.bootstrap_vms]builtins.obj, -
+ [.bootstrap_vms]command.obj, -
+ [.bootstrap_vms]compile.obj, -
+ [.bootstrap_vms]execvms.obj, -
+ [.bootstrap_vms]expand.obj, -
+ [.bootstrap_vms]filesys.obj, -
+ [.bootstrap_vms]filevms.obj, -
+ [.bootstrap_vms]glob.obj, -
+ [.bootstrap_vms]hash.obj, -
+ [.bootstrap_vms]hdrmacro.obj, -
+ [.bootstrap_vms]headers.obj, -
+ [.bootstrap_vms]jam.obj, -
+ [.bootstrap_vms]jambase.obj, -
+ [.bootstrap_vms]jamgram.obj, -
+ [.bootstrap_vms]lists.obj, -
+ [.bootstrap_vms]make.obj, -
+ [.bootstrap_vms]make1.obj, -
+ [.bootstrap_vms]modules.obj, -
+ [.bootstrap_vms]newstr.obj, -
+ [.bootstrap_vms]option.obj, -
+ [.bootstrap_vms]parse.obj, -
+ [.bootstrap_vms]pathvms.obj, -
+ [.bootstrap_vms]pwd.obj, -
+ [.bootstrap_vms]regexp.obj, -
+ [.bootstrap_vms]rules.obj, -
+ [.bootstrap_vms]scan.obj, -
+ [.bootstrap_vms]search.obj, -
+ [.bootstrap_vms]strings.obj, -
+ [.bootstrap_vms]subst.obj, -
+ [.bootstrap_vms]timestamp.obj, -
+ [.bootstrap_vms]variable.obj
+$ !
+$ SAY "Cleaning any previous build..."
+$ !
+$ MCR [.bootstrap_vms]jam0.exe -f build.jam --toolset=vmsdecc clean
+$ !
+$ SAY "Building Boost.Jam..."
+$ !
+$ MCR [.bootstrap_vms]jam0.exe -f build.jam --toolset=vmsdecc
Added: boost-jam/boost-build/branches/upstream/current/jam_src/builtins.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/builtins.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/builtins.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1144 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+
+# include "lists.h"
+# include "parse.h"
+# include "builtins.h"
+# include "rules.h"
+# include "filesys.h"
+# include "newstr.h"
+# include "regexp.h"
+# include "frames.h"
+# include "hash.h"
+# include "strings.h"
+# include "pwd.h"
+# include "pathsys.h"
+# include "make.h"
+# include "hdrmacro.h"
+# include "compile.h"
+# include "native.h"
+# include <ctype.h>
+
+/*
+ * builtins.c - builtin jam rules
+ *
+ * External routines:
+ *
+ * load_builtin() - define builtin rules
+ *
+ * Internal routines:
+ *
+ * builtin_depends() - DEPENDS/INCLUDES rule
+ * builtin_echo() - ECHO rule
+ * builtin_exit() - EXIT rule
+ * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule
+ * builtin_glob() - GLOB rule
+ * builtin_match() - MATCH rule
+ *
+ * 01/10/01 (seiwald) - split from compile.c
+ */
+
+/*
+ * compile_builtin() - define builtin rules
+ */
+
+# define P0 (PARSE *)0
+# define C0 (char *)0
+
+# ifdef OS_NT
+LIST* builtin_system_registry( PARSE *parse, FRAME *frame );
+# endif
+
+int glob( char *s, char *c );
+
+void lol_build( LOL* lol, char** elements );
+void backtrace( FRAME *frame );
+void backtrace_line( FRAME *frame );
+void print_source_line( PARSE* p );
+
+RULE* bind_builtin( char* name, LIST*(*f)(PARSE*, FRAME*), int flags, char** args )
+{
+ argument_list* arg_list = 0;
+
+ if ( args )
+ {
+ arg_list = args_new();
+ lol_build( arg_list->data, args );
+ }
+
+ return new_rule_body( root_module(), name, arg_list,
+ parse_make( f, P0, P0, P0, C0, C0, flags ), 1 );
+}
+
+RULE* duplicate_rule( char* name, RULE* other )
+{
+ return import_rule( other, root_module(), name );
+}
+
+void
+load_builtins()
+{
+ duplicate_rule( "Always" ,
+ bind_builtin( "ALWAYS" ,
+ builtin_flags, T_FLAG_TOUCHED, 0 ) );
+
+ duplicate_rule( "Depends" ,
+ bind_builtin( "DEPENDS" ,
+ builtin_depends, 0, 0 ) );
+
+ duplicate_rule( "echo" ,
+ duplicate_rule( "Echo" ,
+ bind_builtin( "ECHO" ,
+ builtin_echo, 0, 0 ) ) );
+
+ duplicate_rule( "exit" ,
+ duplicate_rule( "Exit" ,
+ bind_builtin( "EXIT" ,
+ builtin_exit, 0, 0 ) ) );
+
+ {
+ char * args[] = { "directories", "*", ":", "patterns", "*", ":", "case-insensitive", "?", 0 };
+ duplicate_rule(
+ "Glob" ,
+ bind_builtin( "GLOB" , builtin_glob, 0, args )
+ );
+ }
+
+ duplicate_rule( "Includes" ,
+ bind_builtin( "INCLUDES" ,
+ builtin_depends, 1, 0 ) );
+
+ duplicate_rule( "Leaves" ,
+ bind_builtin( "LEAVES" ,
+ builtin_flags, T_FLAG_LEAVES, 0 ) );
+
+ duplicate_rule( "Match" ,
+ bind_builtin( "MATCH" ,
+ builtin_match, 0, 0 ) );
+
+ duplicate_rule( "NoCare" ,
+ bind_builtin( "NOCARE" ,
+ builtin_flags, T_FLAG_NOCARE, 0 ) );
+
+ duplicate_rule( "NOTIME" ,
+ duplicate_rule( "NotFile" ,
+ bind_builtin( "NOTFILE" ,
+ builtin_flags, T_FLAG_NOTFILE, 0 ) ) );
+
+ duplicate_rule( "NoUpdate" ,
+ bind_builtin( "NOUPDATE" ,
+ builtin_flags, T_FLAG_NOUPDATE, 0 ) );
+
+ duplicate_rule( "Temporary" ,
+ bind_builtin( "TEMPORARY" ,
+ builtin_flags, T_FLAG_TEMP, 0 ) );
+
+ duplicate_rule( "HdrMacro" ,
+ bind_builtin( "HDRMACRO" ,
+ builtin_hdrmacro, 0, 0 ) );
+
+ /* FAIL_EXPECTED is used to indicate that the result of a target build */
+ /* action should be inverted (ok <=> fail) this can be useful when */
+ /* performing test runs from Jamfiles.. */
+ bind_builtin( "FAIL_EXPECTED" ,
+ builtin_flags, T_FLAG_FAIL_EXPECTED, 0 );
+
+ bind_builtin( "RMOLD" , builtin_flags, T_FLAG_RMOLD, 0 );
+
+ {
+ char * args[] = { "targets", "*", 0 };
+ bind_builtin( "UPDATE", builtin_update, 0, args );
+ }
+
+ {
+ char * args[] = { "string", "pattern", "replacements", "+", 0 };
+ duplicate_rule( "subst" ,
+ bind_builtin( "SUBST" ,
+ builtin_subst, 0, args ) );
+ }
+
+ {
+ char * args[] = { "module", "?", 0 };
+ bind_builtin( "RULENAMES" ,
+ builtin_rulenames, 0, args );
+ }
+
+
+ {
+ char * args[] = { "module", "?", 0 };
+ bind_builtin( "VARNAMES" ,
+ builtin_varnames, 0, args );
+ }
+
+ {
+ char * args[] = { "module", "?", 0 };
+ bind_builtin( "DELETE_MODULE" ,
+ builtin_delete_module, 0, args );
+ }
+
+ {
+ char * args[] = { "source_module", "?",
+ ":", "source_rules", "*",
+ ":", "target_module", "?",
+ ":", "target_rules", "*",
+ ":", "localize", "?", 0 };
+ bind_builtin( "IMPORT" ,
+ builtin_import, 0, args );
+ }
+
+ {
+ char * args[] = { "module", "?", ":", "rules", "*", 0 };
+ bind_builtin( "EXPORT" ,
+ builtin_export, 0, args );
+ }
+
+ {
+ char * args[] = { "levels", "?", 0 };
+ bind_builtin( "CALLER_MODULE" ,
+ builtin_caller_module, 0, args );
+ }
+
+ {
+ char * args[] = { "levels", "?", 0 };
+ bind_builtin( "BACKTRACE" ,
+ builtin_backtrace, 0, args );
+ }
+
+ {
+ char * args[] = { 0 };
+ bind_builtin( "PWD" ,
+ builtin_pwd, 0, args );
+ }
+
+ {
+ char * args[] = { "target", "*", ":", "path", "*", 0 };
+ bind_builtin( "SEARCH_FOR_TARGET",
+ builtin_search_for_target, 0, args );
+ }
+
+ {
+ char * args[] = { "modules_to_import", "+", ":", "target_module", "?", 0 };
+ bind_builtin( "IMPORT_MODULE",
+ builtin_import_module, 0, args );
+ }
+
+ {
+ char * args[] = { "module", "?", 0 };
+ bind_builtin( "IMPORTED_MODULES",
+ builtin_imported_modules, 0, args );
+ }
+
+ {
+ char * args[] = { "instance_module", ":", "class_module", 0 };
+ bind_builtin( "INSTANCE",
+ builtin_instance, 0, args );
+ }
+
+ {
+ char * args[] = { "sequence", "*", 0 };
+ bind_builtin( "SORT",
+ builtin_sort, 0, args );
+ }
+
+ {
+ char * args[] = { "path", 0 };
+ bind_builtin( "NORMALIZE_PATH",
+ builtin_normalize_path, 0, args );
+ }
+
+ {
+ char * args[] = { "args", "*", 0 };
+ bind_builtin( "CALC",
+ builtin_calc, 0, args );
+ }
+
+ {
+ char * args[] = { "module", ":", "rule", 0 };
+ bind_builtin( "NATIVE_RULE",
+ builtin_native_rule, 0, args );
+ }
+
+# ifdef OS_NT
+ {
+ char * args[] = { "key_path", ":", "data", "?", 0 };
+ bind_builtin( "W32_GETREG",
+ builtin_system_registry, 0, args );
+ }
+# endif
+
+ /* Initialize builtin modules */
+ init_set();
+ init_path();
+ init_regex();
+ init_property_set();
+ init_sequence();
+ init_order();
+}
+
+/*
+* builtin_calc() - CALC rule
+*
+* The CALC rule performs simple mathematical operations on two arguments.
+*/
+
+LIST *
+builtin_calc(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *arg = lol_get( frame->args, 0 );
+
+ LIST *result = 0;
+ long lhs_value;
+ long rhs_value;
+ long result_value;
+ char buffer [16];
+ const char* lhs;
+ const char* op;
+ const char* rhs;
+
+ if (arg == 0) return L0;
+ lhs = arg->string;
+
+ arg = list_next( arg );
+ if (arg == 0) return L0;
+ op = arg->string;
+
+ arg = list_next( arg );
+ if (arg == 0) return L0;
+ rhs = arg->string;
+
+ lhs_value = atoi (lhs);
+ rhs_value = atoi (rhs);
+
+ if (strcmp ("+", op) == 0)
+ {
+ result_value = lhs_value + rhs_value;
+ }
+ else if (strcmp ("-", op) == 0)
+ {
+ result_value = lhs_value - rhs_value;
+ }
+ else
+ {
+ return L0;
+ }
+
+ sprintf (buffer, "%ld", result_value);
+ result = list_new( result, newstr( buffer ) );
+ return result;
+}
+
+/*
+ * builtin_depends() - DEPENDS/INCLUDES rule
+ *
+ * The DEPENDS builtin rule appends each of the listed sources on the
+ * dependency list of each of the listed targets. It binds both the
+ * targets and sources as TARGETs.
+ */
+
+LIST *
+builtin_depends(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *targets = lol_get( frame->args, 0 );
+ LIST *sources = lol_get( frame->args, 1 );
+ int which = parse->num;
+ LIST *l;
+
+ for( l = targets; l; l = list_next( l ) )
+ {
+ TARGET *t = bindtarget( l->string );
+
+ /* If doing INCLUDES, switch to the TARGET's include */
+ /* TARGET, creating it if needed. The internal include */
+ /* TARGET shares the name of its parent. */
+
+ if( parse->num )
+ {
+ if( !t->includes ) {
+ t->includes = copytarget( t );
+ t->includes->original_target = t;
+ }
+ t = t->includes;
+ }
+
+ t->depends = targetlist( t->depends, sources );
+ }
+
+ return L0;
+}
+
+/*
+ * builtin_echo() - ECHO rule
+ *
+ * The ECHO builtin rule echoes the targets to the user. No other
+ * actions are taken.
+ */
+
+LIST *
+builtin_echo(
+ PARSE *parse,
+ FRAME *frame )
+{
+ list_print( lol_get( frame->args, 0 ) );
+ printf( "\n" );
+ return L0;
+}
+
+/*
+ * builtin_exit() - EXIT rule
+ *
+ * The EXIT builtin rule echoes the targets to the user and exits
+ * the program with a failure status.
+ */
+
+LIST *
+builtin_exit(
+ PARSE *parse,
+ FRAME *frame )
+{
+ list_print( lol_get( frame->args, 0 ) );
+ printf( "\n" );
+ exit( EXITBAD ); /* yeech */
+ return L0;
+}
+
+/*
+ * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule
+ *
+ * Builtin_flags() marks the target with the appropriate flag, for use
+ * by make0(). It binds each target as a TARGET.
+ */
+
+LIST *
+builtin_flags(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *l = lol_get( frame->args, 0 );
+
+ for( ; l; l = list_next( l ) )
+ bindtarget( l->string )->flags |= parse->num;
+
+ return L0;
+}
+
+/*
+ * builtin_globbing() - GLOB rule
+ */
+
+struct globbing {
+ LIST *patterns;
+ LIST *results;
+ LIST *case_insensitive;
+} ;
+
+static void downcase_inplace( char* p )
+{
+ for ( ; *p; ++p )
+ {
+ *p = tolower(*p);
+ }
+}
+
+static void
+builtin_glob_back(
+ void *closure,
+ char *file,
+ int status,
+ time_t time )
+{
+ struct globbing *globbing = (struct globbing *)closure;
+ LIST *l;
+ PATHNAME f;
+ string buf[1];
+
+ /* Null out directory for matching. */
+ /* We wish we had file_dirscan() pass up a PATHNAME. */
+
+ path_parse( file, &f );
+ f.f_dir.len = 0;
+ string_new( buf );
+ path_build( &f, buf, 0 );
+
+ if (globbing->case_insensitive)
+ downcase_inplace( buf->value );
+
+ for( l = globbing->patterns; l; l = l->next )
+ {
+ if( !glob( l->string, buf->value ) )
+ {
+ globbing->results = list_new( globbing->results, newstr( file ) );
+ break;
+ }
+ }
+
+ string_free( buf );
+}
+
+static LIST* downcase_list( LIST *in )
+{
+ LIST* result = 0;
+
+ string s[1];
+ string_new( s );
+
+ while (in)
+ {
+ string_copy( s, in->string );
+ downcase_inplace( s->value );
+ result = list_append( result, list_new( 0, newstr( s->value ) ) );
+ in = in->next;
+ }
+
+ string_free( s );
+ return result;
+}
+
+LIST *
+builtin_glob(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *l = lol_get( frame->args, 0 );
+ LIST *r = lol_get( frame->args, 1 );
+
+ struct globbing globbing;
+
+ globbing.results = L0;
+ globbing.patterns = r;
+
+ globbing.case_insensitive
+# if defined( OS_NT ) || defined( OS_CYGWIN )
+ = l; /* always case-insensitive if any files can be found */
+# else
+ = lol_get( frame->args, 2 );
+# endif
+
+ if ( globbing.case_insensitive )
+ {
+ globbing.patterns = downcase_list( r );
+ }
+
+ for( ; l; l = list_next( l ) )
+ file_dirscan( l->string, builtin_glob_back, &globbing );
+
+ if ( globbing.case_insensitive )
+ {
+ list_free( globbing.patterns );
+ }
+ return globbing.results;
+}
+
+/*
+ * builtin_match() - MATCH rule, regexp matching
+ */
+
+LIST *
+builtin_match(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *l, *r;
+ LIST *result = 0;
+
+ string buf[1];
+ string_new(buf);
+
+ /* For each pattern */
+
+ for( l = lol_get( frame->args, 0 ); l; l = l->next )
+ {
+ /* Result is cached and intentionally never freed */
+ regexp *re = regex_compile( l->string );
+
+ /* For each string to match against */
+ for( r = lol_get( frame->args, 1 ); r; r = r->next )
+ {
+ if( regexec( re, r->string ) )
+ {
+ int i, top;
+
+ /* Find highest parameter */
+
+ for( top = NSUBEXP; top-- > 1; )
+ if( re->startp[top] )
+ break;
+
+ /* And add all parameters up to highest onto list. */
+ /* Must have parameters to have results! */
+
+ for( i = 1; i <= top; i++ )
+ {
+ string_append_range( buf, re->startp[i], re->endp[i] );
+ result = list_new( result, newstr( buf->value ) );
+ string_truncate( buf, 0 );
+ }
+ }
+ }
+ }
+
+ string_free( buf );
+ return result;
+}
+
+LIST *
+builtin_hdrmacro(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST* l = lol_get( frame->args, 0 );
+
+ for ( ; l; l = list_next(l) )
+ {
+ TARGET* t = bindtarget( l->string );
+
+ /* scan file for header filename macro definitions */
+ if ( DEBUG_HEADER )
+ printf( "scanning '%s' for header file macro definitions\n",
+ l->string );
+
+ macro_headers( t );
+ }
+
+ return L0;
+}
+
+/* builtin_rulenames() - RULENAMES ( MODULE ? )
+ *
+ * Returns a list of the non-local rule names in the given MODULE. If
+ * MODULE is not supplied, returns the list of rule names in the
+ * global module.
+ */
+
+/* helper function for builtin_rulenames(), below */
+static void add_rule_name( void* r_, void* result_ )
+{
+ RULE* r = (RULE*)r_;
+ LIST** result = (LIST**)result_;
+
+ if ( r->exported )
+ *result = list_new( *result, copystr( r->name ) );
+}
+
+LIST *
+builtin_rulenames(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *arg0 = lol_get( frame->args, 0 );
+ LIST *result = L0;
+ module_t* source_module = bindmodule( arg0 ? arg0->string : 0 );
+
+ if ( source_module->rules )
+ hashenumerate( source_module->rules, add_rule_name, &result );
+ return result;
+}
+
+/* builtin_varnames() - VARNAMES ( MODULE ? )
+ *
+ * Returns a list of the variable names in the given MODULE. If
+ * MODULE is not supplied, returns the list of variable names in the
+ * global module.
+ */
+
+/* helper function for builtin_varnames(), below. Used with
+ * hashenumerate, will prepend the key of each element to a list
+ */
+static void add_hash_key( void* np, void* result_ )
+{
+ LIST** result = (LIST**)result_;
+
+ *result = list_new( *result, copystr( *(char**)np ) );
+}
+
+LIST *
+builtin_varnames(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *arg0 = lol_get( frame->args, 0 );
+ LIST *result = L0;
+ module_t* source_module = bindmodule( arg0 ? arg0->string : 0 );
+
+ if ( source_module->variables )
+ hashenumerate( source_module->variables, add_hash_key, &result );
+ return result;
+}
+
+/*
+ * builtin_delete_module() - MODULE ?
+ *
+ * Clears all rules and variables from the given module.
+ */
+LIST *
+builtin_delete_module(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *arg0 = lol_get( frame->args, 0 );
+ LIST *result = L0;
+ module_t* source_module = bindmodule( arg0 ? arg0->string : 0 );
+
+ delete_module( source_module );
+ return result;
+}
+
+static void unknown_rule( FRAME *frame, char* key, char *module_name, char *rule_name )
+{
+ backtrace_line( frame->prev );
+ printf( "%s error: rule \"%s\" unknown in module \"%s\"\n", key, rule_name, module_name );
+ backtrace( frame->prev );
+ exit(1);
+
+}
+
+/*
+ * builtin_import() - IMPORT ( SOURCE_MODULE ? : SOURCE_RULES * : TARGET_MODULE ? : TARGET_RULES * : LOCALIZE ? )
+ *
+ * The IMPORT rule imports rules from the SOURCE_MODULE into the
+ * TARGET_MODULE as local rules. If either SOURCE_MODULE or
+ * TARGET_MODULE is not supplied, it refers to the global
+ * module. SOURCE_RULES specifies which rules from the SOURCE_MODULE
+ * to import; TARGET_RULES specifies the names to give those rules in
+ * TARGET_MODULE. If SOURCE_RULES contains a name which doesn't
+ * correspond to a rule in SOURCE_MODULE, or if it contains a
+ * different number of items than TARGET_RULES, an error is issued.
+ * if LOCALIZE is specified, the rules will be executed in
+ * TARGET_MODULE, with corresponding access to its module local
+ * variables.
+ */
+LIST *
+builtin_import(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *source_module_list = lol_get( frame->args, 0 );
+ LIST *source_rules = lol_get( frame->args, 1 );
+ LIST *target_module_list = lol_get( frame->args, 2 );
+ LIST *target_rules = lol_get( frame->args, 3 );
+ LIST *localize = lol_get( frame->args, 4 );
+
+ module_t* target_module = bindmodule( target_module_list ? target_module_list->string : 0 );
+ module_t* source_module = bindmodule( source_module_list ? source_module_list->string : 0 );
+
+ LIST *source_name, *target_name;
+
+ for ( source_name = source_rules, target_name = target_rules;
+ source_name && target_name;
+ source_name = list_next( source_name )
+ , target_name = list_next( target_name ) )
+ {
+ RULE r_, *r = &r_, *imported;
+ r_.name = source_name->string;
+
+ if ( !source_module->rules
+ || !hashcheck( source_module->rules, (HASHDATA**)&r )
+ )
+ {
+ unknown_rule( frame, "IMPORT", source_module->name, r_.name );
+ }
+
+ imported = import_rule( r, target_module, target_name->string );
+ if ( localize )
+ imported->module = target_module;
+ imported->exported = 0; /* this rule is really part of some other module; just refer to it here, but don't let it out */
+ }
+
+ if ( source_name || target_name )
+ {
+ backtrace_line( frame->prev );
+ printf( "import error: length of source and target rule name lists don't match!\n" );
+ printf( " source: " );
+ list_print( source_rules );
+ printf( "\n target: " );
+ list_print( target_rules );
+ printf( "\n" );
+ backtrace( frame->prev );
+ exit(1);
+ }
+
+ return L0;
+}
+
+
+/*
+ * builtin_export() - EXPORT ( MODULE ? : RULES * )
+ *
+ * The EXPORT rule marks RULES from the SOURCE_MODULE as non-local
+ * (and thus exportable). If an element of RULES does not name a rule
+ * in MODULE, an error is issued.
+ */
+LIST *
+builtin_export(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *module_list = lol_get( frame->args, 0 );
+ LIST *rules = lol_get( frame->args, 1 );
+
+ module_t* m = bindmodule( module_list ? module_list->string : 0 );
+
+
+ for ( ; rules; rules = list_next( rules ) )
+ {
+ RULE r_, *r = &r_;
+ r_.name = rules->string;
+
+ if ( !m->rules || !hashcheck( m->rules, (HASHDATA**)&r ) )
+ unknown_rule( frame, "EXPORT", m->name, r_.name );
+
+ r->exported = 1;
+ }
+ return L0;
+}
+
+/* Retrieve the file and line number that should be indicated for a
+ * given procedure in debug output or an error backtrace
+ */
+static void get_source_line( PARSE* procedure, char** file, int* line )
+{
+ if ( procedure )
+ {
+ char* f = procedure->file;
+ int l = procedure->line;
+ if ( !strcmp( f, "+" ) )
+ {
+ f = "jambase.c";
+ l += 3;
+ }
+ *file = f;
+ *line = l;
+ }
+ else
+ {
+ *file = "(builtin)";
+ *line = -1;
+ }
+}
+
+void print_source_line( PARSE* p )
+{
+ char* file;
+ int line;
+
+ get_source_line( p, &file, &line );
+ if ( line < 0 )
+ printf( "(builtin):" );
+ else
+ printf( "%s:%d:", file, line);
+}
+
+/* Print a single line of error backtrace for the given frame */
+void backtrace_line( FRAME *frame )
+{
+ if ( frame == 0 )
+ {
+ printf( "(no frame):" );
+ }
+ else
+ {
+ print_source_line( frame->procedure );
+ printf( " in %s\n", frame->rulename );
+ }
+}
+
+/* Print the entire backtrace from the given frame to the Jambase
+ * which invoked it.
+ */
+void backtrace( FRAME *frame )
+{
+ if ( !frame ) return;
+ while ( frame = frame->prev )
+ {
+ backtrace_line( frame );
+ }
+}
+
+/* A Jam version of the backtrace function, taking no arguments and
+ * returning a list of quadruples: FILENAME LINE MODULE. RULENAME
+ * describing each frame. Note that the module-name is always
+ * followed by a period.
+ */
+LIST *builtin_backtrace( PARSE *parse, FRAME *frame )
+{
+ LIST* levels_arg = lol_get( frame->args, 0 );
+ int levels = levels_arg ? atoi( levels_arg->string ) : ((unsigned int)(-1) >> 1) ;
+
+ LIST* result = L0;
+ for(; (frame = frame->prev) && levels ; --levels )
+ {
+ char* file;
+ int line;
+ char buf[32];
+ get_source_line( frame->procedure, &file, &line );
+ sprintf( buf, "%d", line );
+ result = list_new( result, newstr( file ) );
+ result = list_new( result, newstr( buf ) );
+ result = list_new( result, newstr( frame->module->name ) );
+ result = list_new( result, newstr( frame->rulename ) );
+ }
+ return result;
+}
+
+/*
+ * builtin_caller_module() - CALLER_MODULE ( levels ? )
+ *
+ * If levels is not supplied, returns the name of the module of the rule which
+ * called the one calling this one. If levels is supplied, it is interpreted as
+ * an integer specifying a number of additional levels of call stack to traverse
+ * in order to locate the module in question. If no such module exists,
+ * returns the empty list. Also returns the empty list when the module in
+ * question is the global module. This rule is needed for implementing module
+ * import behavior.
+ */
+LIST *builtin_caller_module( PARSE *parse, FRAME *frame )
+{
+ LIST* levels_arg = lol_get( frame->args, 0 );
+ int levels = levels_arg ? atoi( levels_arg->string ) : 0 ;
+
+ int i;
+ for (i = 0; i < levels + 2 && frame->prev; ++i)
+ frame = frame->prev;
+
+ if ( frame->module == root_module() )
+ {
+ return L0;
+ }
+ else
+ {
+ LIST* result;
+
+ string name;
+ string_copy( &name, frame->module->name );
+ string_pop_back( &name );
+
+ result = list_new( L0, newstr(name.value) );
+
+ string_free( &name );
+
+ return result;
+ }
+}
+
+/*
+ * Return the current working directory.
+ *
+ * Usage: pwd = [ PWD ] ;
+ */
+LIST*
+builtin_pwd( PARSE *parse, FRAME *frame )
+{
+ return pwd();
+}
+
+/*
+ * Adds targets to the list of target that jam will attempt to update.
+ */
+LIST*
+builtin_update( PARSE *parse, FRAME *frame)
+{
+ LIST* result = list_copy( L0, targets_to_update() );
+ LIST* arg1 = lol_get( frame->args, 0 );
+ clear_targets_to_update();
+ for ( ; arg1; arg1 = list_next( arg1 ) )
+ mark_target_for_updating( newstr(arg1->string) );
+ return result;
+}
+
+LIST*
+builtin_search_for_target( PARSE *parse, FRAME *frame )
+{
+ LIST* arg1 = lol_get( frame->args, 0 );
+ LIST* arg2 = lol_get( frame->args, 1 );
+
+ TARGET* t = search_for_target( arg1->string, arg2 );
+ return list_new( L0, t->name );
+}
+
+LIST *builtin_import_module( PARSE *parse, FRAME *frame )
+{
+ LIST* arg1 = lol_get( frame->args, 0 );
+ LIST* arg2 = lol_get( frame->args, 1 );
+
+ module_t* m = arg2 ? bindmodule(arg2->string) : root_module();
+
+ import_module(arg1, m);
+
+ return L0;
+}
+
+
+LIST *builtin_imported_modules( PARSE *parse, FRAME *frame )
+{
+ LIST *arg0 = lol_get( frame->args, 0 );
+ module_t* source_module = bindmodule( arg0 ? arg0->string : 0 );
+
+ return imported_modules(source_module);
+}
+
+LIST *builtin_instance( PARSE *parse, FRAME *frame )
+{
+ LIST* arg1 = lol_get( frame->args, 0 );
+ LIST* arg2 = lol_get( frame->args, 1 );
+
+ module_t* instance = bindmodule( arg1->string );
+ module_t* class_module = bindmodule( arg2->string );
+ instance->class_module = class_module;
+
+ return L0;
+}
+
+LIST*
+builtin_sort( PARSE *parse, FRAME *frame )
+{
+ LIST* arg1 = lol_get( frame->args, 0 );
+
+ return list_sort(arg1);
+}
+
+LIST *builtin_normalize_path( PARSE *parse, FRAME *frame )
+{
+ LIST* arg1 = lol_get( frame->args, 0 );
+
+ /* First, we iterate over all '/'-separated elements, starting from
+ the end of string. If we see '..', we remove previous path elements.
+ If we see '.', we remove it.
+ The removal is done by putting '\1' in the string. After all the string
+ is processed, we do a second pass, removing '\1' characters.
+ */
+
+ string in[1], out[1], tmp[1];
+ char* end; /* Last character of the part of string still to be processed. */
+ char* current; /* Working pointer. */
+ int dotdots = 0; /* Number of '..' elements seen and not processed yet. */
+ int rooted = arg1->string[0] == '/';
+ char* result;
+
+ /* Make a copy of input: we should not change it. */
+ string_new(in);
+ if (!rooted)
+ string_push_back(in, '/');
+ string_append(in, arg1->string);
+
+
+ end = in->value + in->size - 1;
+ current = end;
+
+ for(;end >= in->value;) {
+ /* Set 'current' to the next occurence of '/', which always exists. */
+ for(current = end; *current != '/'; --current)
+ ;
+
+ if (current == end && current != in->value) {
+ /* Found a trailing slash. Remove it. */
+ *current = '\1';
+ } else if (current == end && *(current+1) == '/') {
+ /* Found duplicated slash. Remove it. */
+ *current = '\1';
+ } else if (end - current == 1 && strncmp(current, "/.", 2) == 0) {
+ /* Found '/.'. Drop them all. */
+ *current = '\1';
+ *(current+1) = '\1';
+ } else if (end - current == 2 && strncmp(current, "/..", 3) == 0) {
+ /* Found '/..' */
+ *current = '\1';
+ *(current+1) = '\1';
+ *(current+2) = '\1';
+ ++dotdots;
+ } else if (dotdots) {
+ char* p = current;
+ memset(current, '\1', end-current+1);
+ --dotdots;
+ }
+ end = current-1;
+ }
+
+
+ string_new(tmp);
+ while(dotdots--)
+ string_append(tmp, "/..");
+ string_append(tmp, in->value);
+ string_copy(in, tmp->value);
+ string_free(tmp);
+
+
+ string_new(out);
+ /* The resulting path is either empty or has '/' as the first significant
+ element. If the original path was not rooted, we need to drop first '/'.
+ If the original path was rooted, and we've got empty path, need to add '/'
+ */
+ if (!rooted) {
+ current = strchr(in->value, '/');
+ if (current)
+ *current = '\1';
+ }
+
+ for (current = in->value; *current; ++current)
+ if (*current != '\1')
+ string_push_back(out, *current);
+
+
+ result = newstr(out->size ? out->value : (rooted ? "/" : "."));
+ string_free(in);
+ string_free(out);
+
+ return list_new(0, result);
+
+}
+
+LIST *builtin_native_rule( PARSE *parse, FRAME *frame )
+{
+ LIST* module_name = lol_get( frame->args, 0 );
+ LIST* rule_name = lol_get( frame->args, 1 );
+
+ module_t* module = bindmodule(module_name->string);
+
+ native_rule_t n, *np = &n;
+ n.name = rule_name->string;
+ if (module->native_rules && hashcheck(module->native_rules, (HASHDATA**)&np))
+ {
+ new_rule_body(module, np->name, np->arguments, np->procedure, 1);
+ }
+ else
+ {
+ backtrace_line( frame->prev );
+ printf( "error: no native rule \"%s\" defined in module \"%s\"\n",
+ n.name, module->name);
+ backtrace( frame->prev );
+ exit(1);
+ }
+ return L0;
+}
+
+
+void lol_build( LOL* lol, char** elements )
+{
+ LIST* l = L0;
+ lol_init( lol );
+
+ while ( elements && *elements )
+ {
+ if ( !strcmp( *elements, ":" ) )
+ {
+ lol_add( lol, l );
+ l = L0 ;
+ }
+ else
+ {
+ l = list_new( l, newstr( *elements ) );
+ }
+ ++elements;
+ }
+
+ if ( l != L0 )
+ lol_add( lol, l );
+}
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/builtins.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/builtins.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/builtins.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,46 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+#ifndef JAM_BUILTINS_H
+# define JAM_BUILTINS_H
+
+# include "frames.h"
+
+/*
+ * builtins.h - compile parsed jam statements
+ */
+
+void load_builtins();
+
+LIST *builtin_calc( PARSE *parse, FRAME *args );
+LIST *builtin_depends( PARSE *parse, FRAME *args );
+LIST *builtin_echo( PARSE *parse, FRAME *args );
+LIST *builtin_exit( PARSE *parse, FRAME *args );
+LIST *builtin_flags( PARSE *parse, FRAME *args );
+LIST *builtin_glob( PARSE *parse, FRAME *args );
+LIST *builtin_subst( PARSE *parse, FRAME *args );
+LIST *builtin_match( PARSE *parse, FRAME *args );
+LIST *builtin_hdrmacro( PARSE *parse, FRAME *args );
+LIST *builtin_rulenames( PARSE *parse, FRAME *args );
+LIST *builtin_varnames( PARSE *parse, FRAME *args );
+LIST *builtin_delete_module( PARSE *parse, FRAME *args );
+LIST *builtin_import( PARSE *parse, FRAME *args );
+LIST *builtin_export( PARSE *parse, FRAME *args );
+LIST *builtin_caller_module( PARSE *parse, FRAME *args );
+LIST *builtin_backtrace( PARSE *parse, FRAME *args );
+LIST *builtin_pwd( PARSE *parse, FRAME *args );
+LIST *builtin_update( PARSE *parse, FRAME *args );
+LIST *builtin_search_for_target( PARSE *parse, FRAME *args );
+LIST *builtin_import_module( PARSE *parse, FRAME *args );
+LIST *builtin_imported_modules( PARSE *parse, FRAME *frame );
+LIST *builtin_instance( PARSE *parse, FRAME *frame );
+LIST *builtin_sort( PARSE *parse, FRAME *frame );
+LIST *builtin_normalize_path( PARSE *parse, FRAME *frame );
+LIST *builtin_native_rule( PARSE *parse, FRAME *frame );
+
+void backtrace( FRAME *frame );
+
+#endif
Added: boost-jam/boost-build/branches/upstream/current/jam_src/bump_version.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/bump_version.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/bump_version.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,55 @@
+#!/usr/bin/python
+
+# This script is used to bump version of bjam. It takes a single argument, e.g
+#
+# ./bump_version.py 3.1.9
+#
+# and updates all necessary files. For the time being, it's assumes presense
+# of 'perl' executable and Debian-specific 'dch' executable.
+#
+
+
+import sys
+import string
+import os
+
+def spec(version):
+ os.system("perl -pi -e 's|^Version:.*|Version: %s|' boost-jam.spec" %
+ string.join(version, "."))
+
+def build_jam(version):
+ os.system("perl -pi -e 's|^VERSION = .* ;|VERSION = %s\$(.)%s\$(.)%s ;|' build.jam"
+ % (version[0], version[1], version[2]))
+
+def index_html(version):
+ os.system("perl -pi -e 's|This is version .* of BJam|This is version %s of BJam|' index.html"
+ % string.join(version, "."))
+
+def jam_c(version):
+ re = "\\*major_version = .*, \\*minor_version = .*, \\*changenum = .*";
+ new = ('*major_version = "%02d", *minor_version = "%02d", *changenum = "%02d";' %
+ (int(version[0]), int(version[1]), int(version[2])))
+ os.system("perl -pi -e 's|%s|%s|' jam.c" % (re, new))
+
+def patchlevel(version):
+ os.system("perl -pi -e 's|VERSION .*|VERSION \"%s\"|' patchlevel.h" %
+ string.join(version, "."))
+
+def dch(version):
+ os.system("dch --ignore-dirname -v " + string.join(version, ".") + "-1")
+
+bumpers = [spec, build_jam, index_html, jam_c, patchlevel, dch]
+
+def main():
+
+ if len(sys.argv) < 2:
+ print "Expect new version as argument"
+ sys.exit(1)
+
+ new_version = string.split(sys.argv[1], ".")
+ print "Setting version to", new_version
+ for b in bumpers:
+ b(new_version)
+
+if __name__ == '__main__':
+ main()
Property changes on: boost-jam/boost-build/branches/upstream/current/jam_src/bump_version.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/class.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/class.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/class.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,131 @@
+/* Copyright Vladiir Prus 2003. 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) */
+
+#include "class.h"
+#include "strings.h"
+#include "variable.h"
+#include "frames.h"
+#include "rules.h"
+#include "newstr.h"
+
+#include "hash.h"
+
+static struct hash* classes = 0;
+
+static void check_defined(LIST* class_names)
+{
+ for (; class_names; class_names = class_names->next) {
+ char** p = &class_names->string;
+ if (!hashcheck(classes, (HASHDATA**)&p)) {
+ printf("Class %s is not defined\n", class_names->string);
+ abort();
+ }
+ }
+}
+
+static char* class_module_name(char* declared_name)
+{
+ string name[1];
+ char* result;
+
+ string_new(name);
+ string_append(name, "class@");
+ string_append(name, declared_name);
+
+ result = newstr(name->value);
+ string_free(name);
+
+ return result;
+}
+
+struct import_base_data {
+ char* base_name;
+ module_t* base_module;
+ module_t* class_module;
+};
+
+static void import_base_rule(void* r_, void* d_)
+{
+ RULE* r = (RULE*)r_;
+ RULE* ir1;
+ RULE* ir2;
+ struct import_base_data* d = (struct import_base_data*)d_;
+ string qualified_name[1];
+ int basename_lenght = strlen(d->base_name)+1;
+
+ string_new(qualified_name);
+ string_append(qualified_name, d->base_name);
+ string_push_back(qualified_name, '.');
+ string_append(qualified_name, r->name);
+
+ ir1 = import_rule(r, d->class_module, r->name);
+ ir2 = import_rule(r, d->class_module, qualified_name->value);
+
+ /* Copy 'exported' flag. */
+ ir1->exported = ir2->exported = r->exported;
+
+ /* If we're importing class method, localize it. */
+ if (r->module == d->base_module
+ || r->module->class_module && r->module->class_module == d->base_module) {
+ ir1->module = ir2->module = d->class_module;
+ }
+
+ string_free(qualified_name);
+}
+
+/** For each exported rule 'n', declared in class module for base,
+ imports that rule in 'class' as 'n' and as 'base.n'. Imported
+ rules are localized and marked as exported.
+*/
+static void import_base_rules(module_t* class, char* base)
+{
+ module_t* base_module = bindmodule(class_module_name(base));
+ struct import_base_data d;
+ d.base_name = base;
+ d.base_module = base_module;
+ d.class_module = class;
+
+ if (base_module->rules)
+ hashenumerate(base_module->rules, import_base_rule, &d);
+
+ import_module( imported_modules(base_module), class );
+}
+
+char* make_class_module(LIST* xname, LIST* bases, FRAME* frame)
+{
+ char* name = class_module_name(xname->string);
+ char** pp = &xname->string;
+ module_t* class_module = 0;
+ module_t* outer_module = frame->module;
+
+ if (!classes)
+ classes = hashinit(sizeof(char*), "classes");
+
+
+ if (hashcheck(classes, (HASHDATA**)&pp)) {
+ printf("Class %s already defined\n", xname->string);
+ abort();
+ } else {
+ hashenter(classes, (HASHDATA**)&pp);
+ }
+ check_defined(bases);
+
+ class_module = bindmodule(name);
+
+ exit_module( outer_module );
+ enter_module( class_module );
+
+ var_set("__name__", xname, VAR_SET);
+ var_set("__bases__", bases, VAR_SET);
+
+ exit_module( class_module );
+ enter_module( outer_module );
+
+ for(; bases; bases = bases->next)
+ import_base_rules(class_module, bases->string);
+
+
+
+ return name;
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/class.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/class.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/class.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,13 @@
+/* Copyright Vladimir Prus 2003. 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) */
+
+#ifndef CLASS_H_VP_2003_08_01
+#define CLASS_H_VP_2003_08_01
+
+#include "lists.h"
+#include "frames.h"
+
+char* make_class_module(LIST* xname, LIST* bases, FRAME* frame);
+
+#endif
Added: boost-jam/boost-build/branches/upstream/current/jam_src/command.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/command.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/command.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,104 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * command.c - maintain lists of commands
+ */
+
+# include "jam.h"
+
+# include "lists.h"
+# include "parse.h"
+# include "variable.h"
+# include "rules.h"
+
+# include "command.h"
+# include <limits.h>
+# include <string.h>
+
+/*
+ * cmd_new() - return a new CMD or 0 if too many args
+ */
+
+CMD *
+cmd_new(
+ RULE *rule,
+ LIST *targets,
+ LIST *sources,
+ LIST *shell )
+{
+ CMD *cmd = (CMD *)malloc( sizeof( CMD ) );
+ /* lift line-length limitation entirely when JAMSHELL is just "%" */
+ int no_limit = ( shell && !strcmp(shell->string,"%") && !list_next(shell) );
+ int max_line = MAXLINE;
+ int allocated = -1;
+
+ cmd->rule = rule;
+ cmd->shell = shell;
+ cmd->next = 0;
+
+ lol_init( &cmd->args );
+ lol_add( &cmd->args, targets );
+ lol_add( &cmd->args, sources );
+ cmd->buf = 0;
+
+ do
+ {
+ free(cmd->buf); /* free any buffer from previous iteration */
+
+ cmd->buf = (char*)malloc(max_line + 1);
+
+ if (cmd->buf == 0)
+ break;
+
+ allocated = var_string( rule->actions->command, cmd->buf, max_line, &cmd->args );
+
+ max_line = max_line * 2;
+ }
+ while( allocated < 0 && max_line < INT_MAX / 2 );
+
+ if ( !no_limit )
+ {
+ /* Bail if the result won't fit in MAXLINE */
+ char *s = cmd->buf;
+ while ( *s )
+ {
+ size_t l = strcspn( s, "\n" );
+
+ if ( l > MAXLINE )
+ {
+ /* We don't free targets/sources/shell if bailing. */
+ cmd_free( cmd );
+ return 0;
+ }
+
+ s += l;
+ if ( *s )
+ ++s;
+ }
+ }
+
+ return cmd;
+}
+
+/*
+ * cmd_free() - free a CMD
+ */
+
+void
+cmd_free( CMD *cmd )
+{
+ lol_free( &cmd->args );
+ list_free( cmd->shell );
+ free( cmd->buf );
+ free( (char *)cmd );
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/command.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/command.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/command.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,58 @@
+/*
+ * Copyright 1994 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * command.h - the CMD structure and routines to manipulate them
+ *
+ * Both ACTION and CMD contain a rule, targets, and sources. An
+ * ACTION describes a rule to be applied to the given targets and
+ * sources; a CMD is what actually gets executed by the shell. The
+ * differences are due to:
+ *
+ * ACTIONS must be combined if 'actions together' is given.
+ * ACTIONS must be split if 'actions piecemeal' is given.
+ * ACTIONS must have current sources omitted for 'actions updated'.
+ *
+ * The CMD datatype holds a single command that is to be executed
+ * against a target, and they can chain together to represent the
+ * full collection of commands used to update a target.
+ *
+ * Structures:
+ *
+ * CMD - an action, ready to be formatted into a buffer and executed
+ *
+ * External routines:
+ *
+ * cmd_new() - return a new CMD or 0 if too many args
+ * cmd_free() - delete CMD and its parts
+ * cmd_next() - walk the CMD chain
+ */
+
+/*
+ * CMD - an action, ready to be formatted into a buffer and executed
+ */
+
+typedef struct _cmd CMD;
+
+struct _cmd
+{
+ CMD *next;
+ CMD *tail; /* valid on in head */
+ RULE *rule; /* rule->actions contains shell script */
+ LIST *shell; /* $(SHELL) value */
+ LOL args; /* LISTs for $(<), $(>) */
+ char* buf; /* actual commands */
+} ;
+
+CMD *cmd_new(
+ RULE *rule, /* rule (referenced) */
+ LIST *targets, /* $(<) (freed) */
+ LIST *sources, /* $(>) (freed) */
+ LIST *shell ); /* $(SHELL) (freed) */
+
+void cmd_free( CMD *cmd );
+
+# define cmd_next( c ) ((c)->next)
Added: boost-jam/boost-build/branches/upstream/current/jam_src/compile.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/compile.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/compile.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1319 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+
+# include "lists.h"
+# include "parse.h"
+# include "compile.h"
+# include "variable.h"
+# include "expand.h"
+# include "rules.h"
+# include "newstr.h"
+# include "make.h"
+# include "search.h"
+# include "hdrmacro.h"
+# include "hash.h"
+# include "modules.h"
+# include "strings.h"
+# include "builtins.h"
+# include "class.h"
+
+# include <time.h>
+# include <assert.h>
+# include <string.h>
+# include <stdarg.h>
+
+/*
+ * compile.c - compile parsed jam statements
+ *
+ * External routines:
+ *
+ * compile_append() - append list results of two statements
+ * compile_eval() - evaluate if to determine which leg to compile
+ * compile_foreach() - compile the "for x in y" statement
+ * compile_if() - compile 'if' rule
+ * compile_while() - compile 'while' rule
+ * compile_include() - support for 'include' - call include() on file
+ * compile_list() - expand and return a list
+ * compile_local() - declare (and set) local variables
+ * compile_null() - do nothing -- a stub for parsing
+ * compile_on() - run rule under influence of on-target variables
+ * compile_rule() - compile a single user defined rule
+ * compile_rules() - compile a chain of rules
+ * compile_set() - compile the "set variable" statement
+ * compile_setcomp() - support for `rule` - save parse tree
+ * compile_setexec() - support for `actions` - save execution string
+ * compile_settings() - compile the "on =" (set variable on exec) statement
+ * compile_switch() - compile 'switch' rule
+ *
+ * Internal routines:
+ *
+ * debug_compile() - printf with indent to show rule expansion.
+ * evaluate_rule() - execute a rule invocation
+ *
+ * builtin_depends() - DEPENDS/INCLUDES rule
+ * builtin_echo() - ECHO rule
+ * builtin_exit() - EXIT rule
+ * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule
+ *
+ * 02/03/94 (seiwald) - Changed trace output to read "setting" instead of
+ * the awkward sounding "settings".
+ * 04/12/94 (seiwald) - Combined build_depends() with build_includes().
+ * 04/12/94 (seiwald) - actionlist() now just appends a single action.
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 05/13/94 (seiwald) - include files are now bound as targets, and thus
+ * can make use of $(SEARCH)
+ * 06/01/94 (seiwald) - new 'actions existing' does existing sources
+ * 08/23/94 (seiwald) - Support for '+=' (append to variable)
+ * 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
+ * 01/22/95 (seiwald) - Exit rule.
+ * 02/02/95 (seiwald) - Always rule; LEAVES rule.
+ * 02/14/95 (seiwald) - NoUpdate rule.
+ * 09/11/00 (seiwald) - new evaluate_rule() for headers().
+ * 09/11/00 (seiwald) - compile_xxx() now return LIST *.
+ * New compile_append() and compile_list() in
+ * support of building lists here, rather than
+ * in jamgram.yy.
+ * 01/10/00 (seiwald) - built-ins split out to builtin.c.
+ */
+
+static void debug_compile( int which, char *s, FRAME* frame );
+int glob( char *s, char *c );
+/* Internal functions from builtins.c */
+void backtrace( FRAME *frame );
+void backtrace_line( FRAME *frame );
+void print_source_line( PARSE* p );
+
+
+void frame_init( FRAME* frame )
+{
+ frame->prev = 0;
+ lol_init(frame->args);
+ frame->module = root_module();
+ frame->rulename = "module scope";
+ frame->procedure = 0;
+}
+
+void frame_free( FRAME* frame )
+{
+ lol_free( frame->args );
+}
+
+/*
+ * compile_append() - append list results of two statements
+ *
+ * parse->left more compile_append() by left-recursion
+ * parse->right single rule
+ */
+
+LIST *
+compile_append(
+ PARSE *parse,
+ FRAME *frame )
+{
+ /* Append right to left. */
+
+ return list_append(
+ parse_evaluate( parse->left, frame ),
+ parse_evaluate( parse->right, frame ) );
+}
+
+/*
+ * compile_eval() - evaluate if to determine which leg to compile
+ *
+ * Returns:
+ * list if expression true - compile 'then' clause
+ * L0 if expression false - compile 'else' clause
+ */
+
+static int
+lcmp( LIST *t, LIST *s )
+{
+ int status = 0;
+
+ while( !status && ( t || s ) )
+ {
+ char *st = t ? t->string : "";
+ char *ss = s ? s->string : "";
+
+ status = strcmp( st, ss );
+
+ t = t ? list_next( t ) : t;
+ s = s ? list_next( s ) : s;
+ }
+
+ return status;
+}
+
+LIST *
+compile_eval(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *ll, *lr, *s, *t;
+ int status = 0;
+
+ /* Short circuit lr eval for &&, ||, and 'in' */
+
+ ll = parse_evaluate( parse->left, frame );
+ lr = 0;
+
+ switch( parse->num )
+ {
+ case EXPR_AND:
+ case EXPR_IN: if( ll ) goto eval; break;
+ case EXPR_OR: if( !ll ) goto eval; break;
+ default: eval: lr = parse_evaluate( parse->right, frame );
+ }
+
+ /* Now eval */
+
+ switch( parse->num )
+ {
+ case EXPR_NOT:
+ if( !ll ) status = 1;
+ break;
+
+ case EXPR_AND:
+ if( ll && lr ) status = 1;
+ break;
+
+ case EXPR_OR:
+ if( ll || lr ) status = 1;
+ break;
+
+ case EXPR_IN:
+ /* "a in b": make sure each of */
+ /* ll is equal to something in lr. */
+
+ for( t = ll; t; t = list_next( t ) )
+ {
+ for( s = lr; s; s = list_next( s ) )
+ if( !strcmp( t->string, s->string ) )
+ break;
+ if( !s ) break;
+ }
+
+ /* No more ll? Success */
+
+ if( !t ) status = 1;
+
+ break;
+
+ case EXPR_EXISTS: if( lcmp( ll, L0 ) != 0 ) status = 1; break;
+ case EXPR_EQUALS: if( lcmp( ll, lr ) == 0 ) status = 1; break;
+ case EXPR_NOTEQ: if( lcmp( ll, lr ) != 0 ) status = 1; break;
+ case EXPR_LESS: if( lcmp( ll, lr ) < 0 ) status = 1; break;
+ case EXPR_LESSEQ: if( lcmp( ll, lr ) <= 0 ) status = 1; break;
+ case EXPR_MORE: if( lcmp( ll, lr ) > 0 ) status = 1; break;
+ case EXPR_MOREEQ: if( lcmp( ll, lr ) >= 0 ) status = 1; break;
+
+ }
+
+ if( DEBUG_IF )
+ {
+ debug_compile( 0, "if", frame );
+ list_print( ll );
+ printf( "(%d) ", status );
+ list_print( lr );
+ printf( "\n" );
+ }
+
+ /* Find something to return. */
+ /* In odd circumstances (like "" = "") */
+ /* we'll have to return a new string. */
+
+ if( !status ) t = 0;
+ else if( ll ) t = ll, ll = 0;
+ else if( lr ) t = lr, lr = 0;
+ else t = list_new( L0, newstr( "1" ) );
+
+ if( ll ) list_free( ll );
+ if( lr ) list_free( lr );
+ return t;
+}
+
+
+/*
+ * compile_foreach() - compile the "for x in y" statement
+ *
+ * Compile_foreach() resets the given variable name to each specified
+ * value, executing the commands enclosed in braces for each iteration.
+ *
+ * parse->string index variable
+ * parse->left variable values
+ * parse->right rule to compile
+ */
+
+LIST *
+compile_foreach(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *nv = parse_evaluate( parse->left, frame );
+ LIST *l;
+ SETTINGS *s = 0;
+
+ if ( parse->num )
+ {
+ s = addsettings( s, 0, parse->string, L0 );
+ pushsettings( s );
+ }
+
+ /* Call var_set to reset $(parse->string) for each val. */
+
+ for( l = nv; l; l = list_next( l ) )
+ {
+ LIST *val = list_new( L0, copystr( l->string ) );
+
+ var_set( parse->string, val, VAR_SET );
+
+ list_free( parse_evaluate( parse->right, frame ) );
+ }
+
+ if ( parse->num )
+ {
+ popsettings( s );
+ freesettings( s );
+ }
+
+ list_free( nv );
+
+ return L0;
+}
+
+/*
+ * compile_if() - compile 'if' rule
+ *
+ * parse->left condition tree
+ * parse->right then tree
+ * parse->third else tree
+ */
+
+LIST *
+compile_if(
+ PARSE *p,
+ FRAME *frame )
+{
+ LIST *l = parse_evaluate( p->left, frame );
+ if( l )
+ {
+ list_free( l );
+ return parse_evaluate( p->right, frame );
+ }
+ else
+ {
+ return parse_evaluate( p->third, frame );
+ }
+}
+
+LIST *
+compile_while(
+ PARSE *p,
+ FRAME *frame )
+{
+ LIST *r = 0;
+ LIST *l;
+ while ( l = parse_evaluate( p->left, frame ) )
+ {
+ list_free( l );
+ if( r ) list_free( r );
+ r = parse_evaluate( p->right, frame );
+ }
+ return r;
+}
+
+
+/*
+ * compile_include() - support for 'include' - call include() on file
+ *
+ * parse->left list of files to include (can only do 1)
+ */
+
+LIST *
+compile_include(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *nt = parse_evaluate( parse->left, frame );
+
+ if( DEBUG_COMPILE )
+ {
+ debug_compile( 0, "include", frame);
+ list_print( nt );
+ printf( "\n" );
+ }
+
+ if( nt )
+ {
+ TARGET *t = bindtarget( nt->string );
+
+ /* DWA 2001/10/22 - Perforce Jam clears the arguments here, which
+ * prevents an included file from being treated as part of the body
+ * of a rule. I didn't see any reason to do that, so I lifted the
+ * restriction.
+ */
+
+ /* Bind the include file under the influence of */
+ /* "on-target" variables. Though they are targets, */
+ /* include files are not built with make(). */
+
+ pushsettings( t->settings );
+ /* We don't expect that file to be included is generated by some
+ action. Therefore, pass 0 as third argument. */
+ t->boundname = search( t->name, &t->time, 0 );
+ popsettings( t->settings );
+
+ parse_file( t->boundname, frame );
+ }
+
+ list_free( nt );
+
+ return L0;
+}
+
+static LIST* evaluate_in_module ( char* module_name, PARSE * p, FRAME* frame)
+{
+ LIST* result;
+
+ module_t* outer_module = frame->module;
+ frame->module = module_name ? bindmodule( module_name ) : root_module();
+
+ if ( outer_module != frame->module )
+ {
+ exit_module( outer_module );
+ enter_module( frame->module );
+ }
+
+ result = parse_evaluate( p, frame );
+
+ if ( outer_module != frame->module )
+ {
+ exit_module( frame->module );
+ enter_module( outer_module );
+ frame->module = outer_module;
+ }
+
+ return result;
+}
+
+LIST *
+compile_module(
+ PARSE *p,
+ FRAME *frame )
+{
+ /* Here we are entering a module declaration block.
+ */
+ LIST* module_name = parse_evaluate( p->left, frame );
+ LIST* result = evaluate_in_module( module_name ? module_name->string : 0,
+ p->right, frame );
+
+ list_free( module_name );
+ return result;
+}
+
+LIST *
+compile_class(
+ PARSE *p,
+ FRAME *frame )
+{
+ /** Todo: check for empty class name.
+ Check for class redeclaration. */
+
+ char* class_module = 0;
+
+ LIST* name = parse_evaluate( p->left->right, frame );
+ LIST* bases = 0;
+
+ if (p->left->left)
+ bases = parse_evaluate( p->left->left->right, frame );
+
+ class_module = make_class_module(name, bases, frame);
+ evaluate_in_module( class_module, p->right, frame );
+
+ return L0;
+}
+
+
+/*
+ * compile_list() - expand and return a list
+ *
+ * parse->string - character string to expand
+ */
+
+LIST *
+compile_list(
+ PARSE *parse,
+ FRAME *frame )
+{
+ /* voodoo 1 means: s is a copyable string */
+ char *s = parse->string;
+ return var_expand( L0, s, s + strlen( s ), frame->args, 1 );
+}
+
+/*
+ * compile_local() - declare (and set) local variables
+ *
+ * parse->left list of variables
+ * parse->right list of values
+ * parse->third rules to execute
+ */
+
+LIST *
+compile_local(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *l;
+ SETTINGS *s = 0;
+ LIST *nt = parse_evaluate( parse->left, frame );
+ LIST *ns = parse_evaluate( parse->right, frame );
+ LIST *result;
+
+ if( DEBUG_COMPILE )
+ {
+ debug_compile( 0, "local", frame);
+ list_print( nt );
+ printf( " = " );
+ list_print( ns );
+ printf( "\n" );
+ }
+
+ /* Initial value is ns */
+
+ for( l = nt; l; l = list_next( l ) )
+ s = addsettings( s, 0, l->string, list_copy( (LIST*)0, ns ) );
+
+ list_free( ns );
+ list_free( nt );
+
+ /* Note that callees of the current context get this "local" */
+ /* variable, making it not so much local as layered. */
+
+ pushsettings( s );
+ result = parse_evaluate( parse->third, frame );
+ popsettings( s );
+
+ freesettings( s );
+
+ return result;
+}
+
+/*
+ * compile_null() - do nothing -- a stub for parsing
+ */
+
+LIST *
+compile_null(
+ PARSE *parse,
+ FRAME *frame )
+{
+ return L0;
+}
+
+/*
+ * compile_on() - run rule under influence of on-target variables
+ *
+ * parse->left list of files to include (can only do 1)
+ * parse->right rule to run
+ *
+ * EXPERIMENTAL!
+ */
+
+LIST *
+compile_on(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *nt = parse_evaluate( parse->left, frame );
+ LIST *result = 0;
+
+ if( DEBUG_COMPILE )
+ {
+ debug_compile( 0, "on", frame );
+ list_print( nt );
+ printf( "\n" );
+ }
+
+ if( nt )
+ {
+ TARGET *t = bindtarget( nt->string );
+ pushsettings( t->settings );
+
+ result = parse_evaluate( parse->right, frame );
+
+ popsettings( t->settings );
+ }
+
+ list_free( nt );
+
+ return result;
+}
+
+
+/*
+ * compile_rule() - compile a single user defined rule
+ *
+ * parse->string name of user defined rule
+ * parse->left parameters (list of lists) to rule, recursing left
+ *
+ * Wrapped around evaluate_rule() so that headers() can share it.
+ */
+
+LIST *
+compile_rule(
+ PARSE *parse,
+ FRAME *frame )
+{
+ FRAME inner[1];
+ LIST *result;
+ PARSE *p;
+
+
+ /* Build up the list of arg lists */
+
+ frame_init( inner );
+ inner->prev = frame;
+ inner->module = frame->module; /* This gets fixed up in evaluate_rule(), below */
+ inner->procedure = parse;
+
+ for( p = parse->left; p; p = p->left )
+ lol_add( inner->args, parse_evaluate( p->right, frame ) );
+
+ /* And invoke rule */
+
+ result = evaluate_rule( parse->string, inner );
+
+ frame_free( inner );
+
+ return result;
+}
+
+static void argument_error( char* message, RULE* rule, FRAME* frame, LIST* arg )
+{
+ LOL* actual = frame->args;
+ assert( frame->procedure != 0 );
+ backtrace_line( frame->prev );
+ printf( "*** argument error\n* rule %s ( ", frame->rulename );
+ lol_print( rule->arguments->data );
+ printf( " )\n* called with: ( " );
+ lol_print( actual );
+ printf( " )\n* %s %s\n", message, arg ? arg->string : "" );
+ print_source_line( rule->procedure );
+ printf( "see definition of rule '%s' being called\n", rule->name );
+ backtrace( frame->prev );
+ exit(1);
+}
+
+/* define delimiters for type check elements in argument lists (and
+ * return type specifications, eventually)
+ */
+# define TYPE_OPEN_DELIM '['
+# define TYPE_CLOSE_DELIM ']'
+
+/* is_type_name - true iff the given string represents a type check
+ * specification
+ */
+static int
+is_type_name( char* s )
+{
+ return s[0] == TYPE_OPEN_DELIM
+ && s[strlen(s) - 1] == TYPE_CLOSE_DELIM;
+}
+
+/*
+ * arg_modifier - if the next element of formal is a single character,
+ * return that; return 0 otherwise. Used to extract "*+?" modifiers
+ * from argument lists.
+ */
+static char
+arg_modifier( LIST* formal )
+{
+ if ( formal->next )
+ {
+ char *next = formal->next->string;
+ if ( next && next[0] != 0 && next[1] == 0 )
+ return next[0];
+ }
+ return 0;
+}
+
+/*
+ * type_check - checks that each element of values satisfies the
+ * requirements of type_name.
+ *
+ * caller - the frame of the rule calling the rule whose
+ * arguments are being checked
+ *
+ * called - the rule being called
+ *
+ * arg_name - a list element containing the name of the argument
+ * being checked
+ */
+static void
+type_check( char* type_name, LIST *values, FRAME* caller, RULE* called, LIST* arg_name )
+{
+ static module_t *typecheck = 0;
+
+ /* if nothing to check, bail now */
+ if ( !values || !type_name )
+ return;
+
+ if ( !typecheck )
+ typecheck = bindmodule(".typecheck");
+
+ /* if the checking rule can't be found, also bail */
+ {
+ RULE checker_, *checker = &checker_;
+
+ checker->name = type_name;
+ if ( !typecheck->rules || !hashcheck( typecheck->rules, (HASHDATA**)&checker ) )
+ return;
+ }
+
+ exit_module( caller->module );
+
+ while ( values != 0 )
+ {
+ LIST *error;
+ FRAME frame[1];
+ frame_init( frame );
+ frame->module = typecheck;
+ frame->prev = caller;
+
+ enter_module( typecheck );
+ /* Prepare the argument list */
+ lol_add( frame->args, list_new( L0, values->string ) );
+ error = evaluate_rule( type_name, frame );
+
+ exit_module( typecheck );
+
+ if ( error )
+ argument_error( error->string, called, caller, arg_name );
+
+ frame_free( frame );
+ values = values->next;
+ }
+
+ enter_module( caller->module );
+}
+
+/*
+ * collect_arguments() - local argument checking and collection
+ */
+static SETTINGS *
+collect_arguments( RULE* rule, FRAME* frame )
+{
+ SETTINGS *locals = 0;
+
+ LOL* all_actual = frame->args;
+ LOL *all_formal = rule->arguments ? rule->arguments->data : 0;
+ if ( all_formal ) /* Nothing to set; nothing to check */
+ {
+ int max = all_formal->count > all_actual->count
+ ? all_formal->count
+ : all_actual->count;
+
+ int n;
+ for ( n = 0; n < max ; ++n )
+ {
+ LIST *actual = lol_get( all_actual, n );
+ char *type_name = 0;
+
+ LIST *formal;
+ for ( formal = lol_get( all_formal, n ); formal; formal = formal->next )
+ {
+ char* name = formal->string;
+
+ if ( is_type_name(name) )
+ {
+ if ( type_name )
+ argument_error( "missing argument name before type name:", rule, frame, formal );
+
+ if ( !formal->next )
+ argument_error( "missing argument name after type name:", rule, frame, formal );
+
+ type_name = formal->string;
+ }
+ else
+ {
+ LIST* value = 0;
+ char modifier;
+ LIST* arg_name = formal; /* hold the argument name for type checking */
+
+ /* Stop now if a variable number of arguments are specified */
+ if ( name[0] == '*' && name[1] == 0 )
+ return locals;
+
+ modifier = arg_modifier( formal );
+
+ if ( !actual && modifier != '?' && modifier != '*' )
+ argument_error( "missing argument", rule, frame, formal );
+
+ switch ( modifier )
+ {
+ case '+':
+ case '*':
+ value = list_copy( 0, actual );
+ actual = 0;
+ /* skip an extra element for the modifier */
+ formal = formal->next;
+ break;
+ case '?':
+ /* skip an extra element for the modifier */
+ formal = formal->next;
+ /* fall through */
+ default:
+ if ( actual ) /* in case actual is missing */
+ {
+ value = list_new( 0, actual->string );
+ actual = actual->next;
+ }
+ }
+
+ locals = addsettings( locals, 0, name, value );
+ type_check( type_name, value, frame, rule, arg_name );
+ type_name = 0;
+ }
+ }
+
+ if ( actual )
+ {
+ argument_error( "extra argument", rule, frame, actual );
+ }
+ }
+ }
+ return locals;
+}
+
+struct profile_info
+{
+ char* name; /* name of rule being called */
+ clock_t cumulative; /* cumulative time spent in rule */
+ clock_t net; /* time spent in rule proper */
+ unsigned long num_entries; /* number of time rule was entered */
+ unsigned long stack_count; /* number of the times this function is present in stack */
+};
+typedef struct profile_info profile_info;
+
+struct profile_frame
+{
+ profile_info* info; /* permanent storage where data accumulates */
+ clock_t overhead; /* overhead for profiling in this call */
+ clock_t entry_time; /* time of last entry to rule */
+ struct profile_frame* caller; /* stack frame of caller */
+ clock_t subrules; /* time spent in subrules */
+};
+typedef struct profile_frame profile_frame;
+
+static profile_frame* profile_stack = 0;
+static struct hash* profile_hash = 0;
+
+static void profile_enter( char* rulename, profile_frame* frame )
+{
+ clock_t start = clock();
+ profile_info info, *p = &info;
+
+ if ( !profile_hash )
+ profile_hash = hashinit(sizeof(profile_info), "profile");
+
+ info.name = rulename;
+
+ if ( hashenter( profile_hash, (HASHDATA **)&p ) )
+ p->cumulative = p->net = p->num_entries = p->stack_count = 0;
+
+ ++(p->num_entries);
+ ++(p->stack_count);
+
+ frame->info = p;
+
+ frame->caller = profile_stack;
+ profile_stack = frame;
+
+ frame->entry_time = clock();
+ frame->overhead = 0;
+ frame->subrules = 0;
+
+ /* caller pays for the time it takes to play with the hash table */
+ if ( frame->caller )
+ frame->caller->overhead += frame->entry_time - start;
+}
+
+static void profile_exit(profile_frame* frame)
+{
+ /* cumulative time for this call */
+ clock_t t = clock() - frame->entry_time - frame->overhead;
+ /* If this rule is already present on the stack, don't add the time for
+ this instance. */
+ if (frame->info->stack_count == 1)
+ frame->info->cumulative += t;
+ /* Net time does not depend on presense of the same rule in call stack. */
+ frame->info->net += t - frame->subrules;
+
+ if (frame->caller)
+ {
+ /* caller's cumulative time must account for this overhead */
+ frame->caller->overhead += frame->overhead;
+ frame->caller->subrules += t;
+ }
+ /* pop this stack frame */
+ --frame->info->stack_count;
+ profile_stack = frame->caller;
+}
+
+static void dump_profile_entry(void* p_, void* ignored)
+{
+ profile_info* p = (profile_info*)p_;
+ printf("%10d %10d %10d %s\n", p->cumulative, p->net, p->num_entries, p->name);
+}
+
+void profile_dump()
+{
+ if ( profile_hash )
+ {
+ printf("%10s %10s %10s %s\n", "gross", "net", "# entries", "name");
+ hashenumerate( profile_hash, dump_profile_entry, 0 );
+ }
+}
+
+/*
+ * evaluate_rule() - execute a rule invocation
+ */
+
+LIST *
+evaluate_rule(
+ char *rulename,
+ FRAME *frame )
+{
+ LIST *result = L0;
+ RULE *rule;
+ profile_frame prof[1];
+ module_t *prev_module = frame->module;
+
+ LIST *l;
+ {
+ LOL arg_context_, *arg_context = &arg_context_;
+ if ( !frame->prev )
+ lol_init(arg_context);
+ else
+ arg_context = frame->prev->args;
+
+ l = var_expand( L0, rulename, rulename+strlen(rulename), arg_context, 0 );
+ }
+
+ if ( !l )
+ {
+ backtrace_line( frame->prev );
+ printf( "warning: rulename %s expands to empty string\n", rulename );
+ backtrace( frame->prev );
+ return result;
+ }
+
+ rulename = l->string;
+ rule = bindrule( l->string, frame->module );
+
+ /* drop the rule name */
+ l = list_pop_front( l );
+
+ /* tack the rest of the expansion onto the front of the first argument */
+ frame->args->list[0] = list_append( l, lol_get( frame->args, 0 ) );
+
+ if ( DEBUG_COMPILE )
+ {
+ /* Try hard to indicate in which module the rule is going to execute */
+ if ( rule->module != frame->module
+ && rule->procedure != 0 && strcmp(rulename, rule->procedure->rulename) )
+ {
+ char buf[256] = "";
+ strncat( buf, rule->module->name, sizeof(buf) - 1 );
+ strncat( buf, rule->name, sizeof(buf) - 1 );
+ debug_compile( 1, buf, frame);
+ }
+ else
+ {
+ debug_compile( 1, rulename, frame);
+ }
+
+ lol_print( frame->args );
+ printf( "\n" );
+ }
+
+ if ( rule->procedure && rule->module != prev_module )
+ {
+ /* propagate current module to nested rule invocations */
+ frame->module = rule->module;
+
+ /* swap variables */
+ exit_module( prev_module );
+ enter_module( rule->module );
+ }
+
+ /* record current rule name in frame */
+ if ( rule->procedure )
+ {
+ frame->rulename = rulename;
+ /* and enter record profile info */
+ if ( DEBUG_PROFILE )
+ profile_enter( rule->procedure->rulename, prof );
+ }
+
+ /* Check traditional targets $(<) and sources $(>) */
+
+ if( !rule->actions && !rule->procedure )
+ {
+ backtrace_line( frame->prev );
+ printf( "rule %s unknown in module %s\n", rule->name, frame->module->name );
+ backtrace( frame->prev );
+ exit(1);
+ }
+
+ /* If this rule will be executed for updating the targets */
+ /* then construct the action for make(). */
+
+ if( rule->actions )
+ {
+ TARGETS *t;
+ ACTION *action;
+
+ /* The action is associated with this instance of this rule */
+
+ action = (ACTION *)malloc( sizeof( ACTION ) );
+ memset( (char *)action, '\0', sizeof( *action ) );
+
+ action->rule = rule;
+ action->targets = targetlist( (TARGETS *)0, lol_get( frame->args, 0 ) );
+ action->sources = targetlist( (TARGETS *)0, lol_get( frame->args, 1 ) );
+
+ /* Append this action to the actions of each target */
+
+ for( t = action->targets; t; t = t->next )
+ t->target->actions = actionlist( t->target->actions, action );
+ }
+
+ /* Now recursively compile any parse tree associated with this rule */
+ /* refer/free to ensure rule not freed during use */
+
+ if( rule->procedure )
+ {
+ SETTINGS *local_args = collect_arguments( rule, frame );
+ PARSE *parse = rule->procedure;
+ parse_refer( parse );
+
+ pushsettings( local_args );
+ result = parse_evaluate( parse, frame );
+ popsettings( local_args );
+ freesettings( local_args );
+
+ parse_free( parse );
+ }
+
+ if ( frame->module != prev_module )
+ {
+ exit_module( frame->module );
+ enter_module( prev_module );
+ }
+
+ if ( DEBUG_PROFILE && rule->procedure )
+ profile_exit( prof );
+
+ if( DEBUG_COMPILE )
+ debug_compile( -1, 0, frame);
+
+ return result;
+}
+
+/*
+ * Call the given rule with the specified parameters.
+ * The parameters should be of LIST* and end with NULL pointer.
+ * This differs from the 'evaluate_rule' in that frame
+ * for called rule is prepared in 'call_rule'.
+ *
+ * This function is usefull when builtin rule (in C) wants to
+ * call another rule, which might be implemented in Jam.
+ */
+LIST *call_rule( char *rulename, FRAME* caller_frame, ...)
+{
+ va_list va;
+ LIST *result;
+
+ FRAME inner[1];
+ frame_init( inner );
+ inner->prev = caller_frame;
+ inner->module = caller_frame->module;
+ inner->procedure = 0;
+
+ va_start(va, caller_frame);
+ for(;;)
+ {
+ LIST* l = va_arg(va, LIST*);
+ if (!l)
+ break;
+ lol_add(inner->args, l);
+ }
+ va_end(va);
+
+ result = evaluate_rule(rulename, inner);
+
+ frame_free(inner);
+
+ return result;
+}
+
+/*
+ * compile_rules() - compile a chain of rules
+ *
+ * parse->left single rule
+ * parse->right more compile_rules() by right-recursion
+ */
+
+LIST *
+compile_rules(
+ PARSE *parse,
+ FRAME *frame )
+{
+ /* Ignore result from first statement; return the 2nd. */
+ /* Optimize recursion on the right by looping. */
+
+ do list_free( parse_evaluate( parse->left, frame ) );
+ while( (parse = parse->right)->func == compile_rules );
+
+ return parse_evaluate( parse, frame );
+}
+
+/*
+ * compile_set() - compile the "set variable" statement
+ *
+ * parse->left variable names
+ * parse->right variable values
+ * parse->num ASSIGN_SET/APPEND/DEFAULT
+ */
+
+LIST *
+compile_set(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *nt = parse_evaluate( parse->left, frame );
+ LIST *ns = parse_evaluate( parse->right, frame );
+ LIST *l;
+ int setflag;
+ char *trace;
+
+ switch( parse->num )
+ {
+ case ASSIGN_SET: setflag = VAR_SET; trace = "="; break;
+ case ASSIGN_APPEND: setflag = VAR_APPEND; trace = "+="; break;
+ case ASSIGN_DEFAULT: setflag = VAR_DEFAULT; trace = "?="; break;
+ default: setflag = VAR_SET; trace = ""; break;
+ }
+
+ if( DEBUG_COMPILE )
+ {
+ debug_compile( 0, "set", frame);
+ list_print( nt );
+ printf( " %s ", trace );
+ list_print( ns );
+ printf( "\n" );
+ }
+
+ /* Call var_set to set variable */
+ /* var_set keeps ns, so need to copy it */
+
+ for( l = nt; l; l = list_next( l ) )
+ var_set( l->string, list_copy( L0, ns ), setflag );
+
+ list_free( nt );
+
+ return ns;
+}
+
+/*
+ * compile_setcomp() - support for `rule` - save parse tree
+ *
+ * parse->string rule name
+ * parse->left rules for rule
+ * parse->right optional list-of-lists describing arguments
+ */
+
+LIST *
+compile_setcomp(
+ PARSE *parse,
+ FRAME *frame)
+{
+ argument_list* arg_list = 0;
+
+ /* Create new LOL describing argument requirements if supplied */
+ if ( parse->right )
+ {
+ PARSE *p;
+ arg_list = args_new();
+ for( p = parse->right; p; p = p->left )
+ lol_add( arg_list->data, parse_evaluate( p->right, frame ) );
+ }
+
+ new_rule_body( frame->module, parse->string, arg_list, parse->left, !parse->num );
+ return L0;
+}
+
+/*
+ * compile_setexec() - support for `actions` - save execution string
+ *
+ * parse->string rule name
+ * parse->string1 OS command string
+ * parse->num flags
+ * parse->left `bind` variables
+ *
+ * Note that the parse flags (as defined in compile.h) are transfered
+ * directly to the rule flags (as defined in rules.h).
+ */
+
+LIST *
+compile_setexec(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST* bindlist = parse_evaluate( parse->left, frame );
+
+ new_rule_actions( frame->module, parse->string, parse->string1, bindlist, parse->num );
+
+ return L0;
+}
+
+/*
+ * compile_settings() - compile the "on =" (set variable on exec) statement
+ *
+ * parse->left variable names
+ * parse->right target name
+ * parse->third variable value
+ * parse->num ASSIGN_SET/APPEND
+ */
+
+LIST *
+compile_settings(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *nt = parse_evaluate( parse->left, frame );
+ LIST *ns = parse_evaluate( parse->third, frame );
+ LIST *targets = parse_evaluate( parse->right, frame );
+ LIST *ts;
+ int append = parse->num == ASSIGN_APPEND;
+
+ if( DEBUG_COMPILE )
+ {
+ debug_compile( 0, "set", frame);
+ list_print( nt );
+ printf( " on " );
+ list_print( targets );
+ printf( " %s ", append ? "+=" : "=" );
+ list_print( ns );
+ printf( "\n" );
+ }
+
+ /* Call addsettings to save variable setting */
+ /* addsettings keeps ns, so need to copy it */
+ /* Pass append flag to addsettings() */
+
+ for( ts = targets; ts; ts = list_next( ts ) )
+ {
+ TARGET *t = bindtarget( ts->string );
+ LIST *l;
+
+ for( l = nt; l; l = list_next( l ) )
+ t->settings = addsettings( t->settings, append,
+ l->string, list_copy( (LIST*)0, ns ) );
+ }
+
+ list_free( nt );
+ list_free( targets );
+
+ return ns;
+}
+
+/*
+ * compile_switch() - compile 'switch' rule
+ *
+ * parse->left switch value (only 1st used)
+ * parse->right cases
+ *
+ * cases->left 1st case
+ * cases->right next cases
+ *
+ * case->string argument to match
+ * case->left parse tree to execute
+ */
+
+LIST *
+compile_switch(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST *nt = parse_evaluate( parse->left, frame );
+ LIST *result = 0;
+
+ if( DEBUG_COMPILE )
+ {
+ debug_compile( 0, "switch", frame);
+ list_print( nt );
+ printf( "\n" );
+ }
+
+ /* Step through cases */
+
+ for( parse = parse->right; parse; parse = parse->right )
+ {
+ if( !glob( parse->left->string, nt ? nt->string : "" ) )
+ {
+ /* Get & exec parse tree for this case */
+ parse = parse->left->left;
+ result = parse_evaluate( parse, frame );
+ break;
+ }
+ }
+
+ list_free( nt );
+
+ return result;
+}
+
+/*
+ * debug_compile() - printf with indent to show rule expansion.
+ */
+
+static void
+debug_compile( int which, char *s, FRAME* frame )
+{
+ static int level = 0;
+ static char indent[36] = ">>>>|>>>>|>>>>|>>>>|>>>>|>>>>|>>>>|";
+
+ if ( which >= 0 )
+ {
+ int i;
+
+ print_source_line( frame->procedure );
+
+ i = (level+1)*2;
+ while ( i > 35 )
+ {
+ printf( indent );
+ i -= 35;
+ }
+
+ printf( "%*.*s ", i, i, indent );
+ }
+
+ if( s )
+ printf( "%s ", s );
+
+ level += which;
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/compile.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/compile.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/compile.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,84 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef COMPILE_DWA20011022_H
+# define COMPILE_DWA20011022_H
+
+# include "frames.h"
+# include "parse.h"
+# include "regexp.h"
+
+/*
+ * compile.h - compile parsed jam statements
+ */
+
+void compile_builtins();
+
+LIST *compile_append( PARSE *parse, FRAME *frame );
+LIST *compile_foreach( PARSE *parse, FRAME *frame );
+LIST *compile_if( PARSE *parse, FRAME *frame );
+LIST *compile_eval( PARSE *parse, FRAME *args );
+LIST *compile_include( PARSE *parse, FRAME *frame );
+LIST *compile_list( PARSE *parse, FRAME *frame );
+LIST *compile_local( PARSE *parse, FRAME *frame );
+LIST *compile_module( PARSE *parse, FRAME *frame );
+LIST *compile_class( PARSE *parse, FRAME *frame );
+LIST *compile_null( PARSE *parse, FRAME *frame );
+LIST *compile_on( PARSE *parse, FRAME *frame );
+LIST *compile_rule( PARSE *parse, FRAME *frame );
+LIST *compile_rules( PARSE *parse, FRAME *frame );
+LIST *compile_set( PARSE *parse, FRAME *frame );
+LIST *compile_setcomp( PARSE *parse, FRAME *frame );
+LIST *compile_setexec( PARSE *parse, FRAME *frame );
+LIST *compile_settings( PARSE *parse, FRAME *frame );
+LIST *compile_switch( PARSE *parse, FRAME *frame );
+LIST *compile_while( PARSE *parse, FRAME *frame );
+
+LIST *evaluate_rule( char *rulename, FRAME *frame );
+LIST *call_rule( char *rulename, FRAME* caller_frame, ...);
+
+regexp* regex_compile( const char* pattern );
+
+void profile_dump();
+
+/* Flags for compile_set(), etc */
+
+# define ASSIGN_SET 0x00 /* = assign variable */
+# define ASSIGN_APPEND 0x01 /* += append variable */
+# define ASSIGN_DEFAULT 0x02 /* set only if unset */
+
+/* Flags for compile_setexec() */
+
+# define EXEC_UPDATED 0x01 /* executes updated */
+# define EXEC_TOGETHER 0x02 /* executes together */
+# define EXEC_IGNORE 0x04 /* executes ignore */
+# define EXEC_QUIETLY 0x08 /* executes quietly */
+# define EXEC_PIECEMEAL 0x10 /* executes piecemeal */
+# define EXEC_EXISTING 0x20 /* executes existing */
+
+/* Conditions for compile_if() */
+
+# define EXPR_NOT 0 /* ! cond */
+# define EXPR_AND 1 /* cond && cond */
+# define EXPR_OR 2 /* cond || cond */
+
+# define EXPR_EXISTS 3 /* arg */
+# define EXPR_EQUALS 4 /* arg = arg */
+# define EXPR_NOTEQ 5 /* arg != arg */
+# define EXPR_LESS 6 /* arg < arg */
+# define EXPR_LESSEQ 7 /* arg <= arg */
+# define EXPR_MORE 8 /* arg > arg */
+# define EXPR_MOREEQ 9 /* arg >= arg */
+# define EXPR_IN 10 /* arg in arg */
+
+#endif
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/debian/changelog
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/debian/changelog 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/debian/changelog 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,54 @@
+bjam (3.1.9-2) unstable; urgency=low
+
+ * Use default value of BOOST_BUILD_PATH is not is set in environment.
+
+ -- Vladimir Prus <ghost at zigzag.lvk.cs.msu.su> Wed, 17 Dec 2003 16:44:35 +0300
+
+bjam (3.1.9-1) unstable; urgency=low
+
+ * Implement NATIVE_FILE builtin and several native rules.
+
+ -- Vladimir Prus <ghost at zigzag.lvk.cs.msu.su> Thu, 11 Dec 2003 13:15:26 +0300
+
+bjam (3.1.8-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Vladimir Prus <ghost at zigzag.lvk.cs.msu.su> Tue, 4 Nov 2003 20:50:43 +0300
+
+bjam (3.1.7-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Vladimir Prus <ghost at zigzag.lvk.cs.msu.su> Thu, 11 Sep 2003 10:45:44 +0400
+
+bjam (3.1.6-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Vladimir Prus <ghost at zigzag.lvk.cs.msu.su> Tue, 1 Jul 2003 09:12:18 +0400
+
+bjam (3.1.5-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Vladimir Prus <ghost at zigzag.lvk.cs.msu.su> Mon, 19 May 2003 14:05:13 +0400
+
+bjam (3.1.3-2) unstable; urgency=low
+
+ * Changed Debian package to be similar to Jam's package.
+
+ -- Vladimir Prus <ghost at cs.msu.su> Thu, 10 Oct 2002 18:43:26 +0400
+
+bjam (3.1.3-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Vladimir Prus <ghost at zigzag.lvk.cs.msu.su> Fri, 4 Oct 2002 18:16:54 +0400
+
+bjam (3.1.2-1) unstable; urgency=low
+
+ * Initial Release.
+
+ -- Vladimir Prus <ghost at cs.msu.su> Wed, 14 Aug 2002 14:08:00 +0400
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/debian/control
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/debian/control 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/debian/control 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,16 @@
+Source: bjam
+Section: devel
+Priority: optional
+Maintainer: Vladimir Prus <ghost at cs.msu.su>
+Build-Depends: debhelper (>> 3.0.0), docbook-to-man, bison
+Standards-Version: 3.5.2
+
+Package: bjam
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: Build tool
+ Boost.Jam is a portable build tool with its own interpreted language, which
+ allows to implement rather complex logic in a readable way and without
+ resorting to external programs. It is a descendant of Jam/MR tool modified to
+ suit the needs of Boost.Build. In particular, modules and rule parameters
+ were added, as well as several new builtins.
Added: boost-jam/boost-build/branches/upstream/current/jam_src/debian/copyright
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/debian/copyright 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/debian/copyright 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,24 @@
+This package was debianized by Vladimir Prus <ghost at cs.msu.su> on
+Wed, 17 July 2002, 19:27:00 +0400.
+
+Copyright:
+
+ /+\
+ +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ \+/
+
+ This is Release 2.4 of Jam/MR, a make-like program.
+
+ License is hereby granted to use this software and distribute it
+ freely, as long as this copyright notice is retained and modifications
+ are clearly marked.
+
+ ALL WARRANTIES ARE HEREBY DISCLAIMED.
+
+Some portions are also:
+
+ Copyright 2001-2004 David Abrahams.
+ Copyright 2002-2004 Rene Rivera.
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
Added: boost-jam/boost-build/branches/upstream/current/jam_src/debian/jam.man.sgml
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/debian/jam.man.sgml 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/debian/jam.man.sgml 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,236 @@
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
+
+<!-- Process this file with docbook-to-man to generate an nroff manual
+ page: `docbook-to-man manpage.sgml > manpage.1'. You may view
+ the manual page with: `docbook-to-man manpage.sgml | nroff -man |
+ less'. A typical entry in a Makefile or Makefile.am is:
+
+manpage.1: manpage.sgml
+ docbook-to-man $< > $@
+ -->
+
+ <!ENTITY dhfirstname "<firstname>Yann</firstname>">
+ <!ENTITY dhsurname "<surname>Dirson</surname>">
+ <!-- Please adjust the date whenever revising the manpage. -->
+ <!ENTITY dhdate "<date>mai 23, 2001</date>">
+ <!ENTITY dhemail "<email>dirson at debian.org</email>">
+ <!ENTITY dhusername "Yann Dirson">
+ <!ENTITY dhpackage "jam">
+
+ <!ENTITY debian "<productname>Debian GNU/Linux</productname>">
+ <!ENTITY gnu "<acronym>GNU</acronym>">
+]>
+
+<refentry>
+ <refentryinfo>
+ <address>
+ &dhemail;
+ </address>
+ <author>
+ &dhfirstname;
+ &dhsurname;
+ </author>
+ <copyright>
+ <year>2001</year>
+ <holder>&dhusername;</holder>
+ </copyright>
+ &dhdate;
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>JAM</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>Jam/MR</refname>
+ <refpurpose>Make(1) Redux</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>jam</command>
+
+ <arg><option>-a</option></arg>
+ <arg><option>-n</option></arg>
+ <arg><option>-v</option></arg>
+
+ <arg><option>-d <replaceable/debug/</option></arg>
+ <arg><option>-f <replaceable/jambase/</option></arg>
+ <arg><option>-j <replaceable/jobs/</option></arg>
+ <arg><option>-o <replaceable/actionsfile/</option></arg>
+ <arg><option>-s <replaceable/var/=<replaceable/value/</option></arg>
+ <arg><option>-t <replaceable/target/</option></arg>
+
+ <arg repeat><option><replaceable/target/</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para>Jam is a program construction tool, like make(1).</para>
+
+ <para>Jam recursively builds target files from source files, using
+ dependency information and updating actions expressed in the
+ Jambase file, which is written in jam's own interpreted language.
+ The default Jambase is compiled into jam and provides a
+ boilerplate for common use, relying on a user-provide file
+ "Jamfile" to enumerate actual targets and sources.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><option/-a/</term>
+ <listitem>
+ <para>Build all targets anyway, even if they are up-to-date.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-d <replaceable/n/</option></term>
+ <listitem>
+ <para>Enable cummulative debugging levels from 1 to
+ <replaceable/n/. Interesting values are:
+
+ <glosslist>
+ <glossentry><glossterm/1/ <glossdef><simpara/Show
+ actions (the default)/</glossdef></glossentry>
+
+ <glossentry><glossterm/2/ <glossdef><simpara/Show
+ "quiet" actions and display all action
+ text/</glossdef></glossentry>
+
+ <glossentry><glossterm/3/ <glossdef><simpara>Show
+ dependency analysis, and target/source
+ timestamps/paths</simpara></glossdef></glossentry>
+
+ <glossentry><glossterm/4/ <glossdef><simpara/Show shell
+ arguments/</glossdef></glossentry>
+
+ <glossentry><glossterm/5/ <glossdef><simpara/Show rule
+ invocations and variable
+ expansions/</glossdef></glossentry>
+
+ <glossentry><glossterm/6/ <glossdef><simpara>Show
+ directory/header file/archive
+ scans</simpara></glossdef></glossentry>
+
+ <glossentry><glossterm/7/ <glossdef><simpara/Show
+ variable settings/</glossdef></glossentry>
+
+ <glossentry><glossterm/8/ <glossdef><simpara/Show
+ variable fetches/</glossdef></glossentry>
+
+ <glossentry><glossterm/9/ <glossdef><simpara/Show
+ variable manipulation, scanner
+ tokens/</glossdef></glossentry>
+ </glosslist>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-d +<replaceable/n/</option></term>
+ <listitem>
+ <para>Enable debugging level <replaceable/n/.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option/-d 0/</term>
+ <listitem>
+ <para>Turn off all debugging levels. Only errors are not
+ suppressed.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-f <replaceable/jambase/</option></term>
+ <listitem>
+ <para>Read <replaceable/jambase/ instead of using the
+ built-in Jambase. Only one <option/-f/ flag is permitted,
+ but the <replaceable/jambase/ may explicitly include other
+ files.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-j <replaceable/n/</option></term>
+ <listitem>
+ <para>Run up to <replaceable/n/ shell commands concurrently
+ (UNIX and NT only). The default is 1.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option/-n/</term>
+ <listitem>
+ <para>Don't actually execute the updating actions, but do
+ everything else. This changes the debug level default to
+ <option/-d2/.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-o <replaceable/file/</option></term>
+ <listitem>
+ <para>Write the updating actions to the specified file
+ instead of running them (or outputting them, as on the
+ Mac).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-s <replaceable/var/=<replaceable/value/</option></term>
+ <listitem>
+ <para>Set the variable <replaceable/var/ to
+ <replaceable/value/, overriding both internal variables and
+ variables imported from the environment. </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-t <replaceable/target/</option></term>
+ <listitem>
+ <para>Rebuild <replaceable/target/ and everything that
+ depends on it, even if it is up-to-date.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option/-v/</term>
+ <listitem>
+ <para>Print the version of jam and exit.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+
+ <para>Jam is documented fully in HTML pages available on Debian
+ systems from
+ <filename>/usr/share/doc/jam/Jam.html</filename>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+
+ <para>This manual page was created by &dhusername; &dhemail; from
+ the <filename/Jam.html/ documentation, for the &debian; system
+ (but may be used by others).</para>
+ </refsect1>
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+sgml-omittag:t
+sgml-shorttag:t
+End:
+-->
Added: boost-jam/boost-build/branches/upstream/current/jam_src/debian/rules
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/debian/rules 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/debian/rules 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,73 @@
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# GNU copyright 1997 to 1999 by Joey Hess.
+# GNU copyright 2001 by Yann Dirson.
+
+# This is the debian/rules file for packages jam and ftjam
+# It should be usable with both packages without any change
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# This is the debhelper compatability version to use.
+export DH_COMPAT=3
+
+topdir=$(shell pwd)
+
+jam=bjam
+binname=bjam
+
+build: build-stamp
+build-stamp: debian/jam.1
+ dh_testdir
+
+ ./build.sh
+
+ touch build-stamp
+
+%.1: %.man.sgml
+ /usr/bin/docbook-to-man $< > $@
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp
+ rm -rf bin.*
+ rm -f jam0 debian/jam.1
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ install -d ${topdir}/debian/${jam}/usr/bin
+ install -m755 bin.linuxx86/bjam ${topdir}/debian/${jam}/usr/bin/
+ install -d ${topdir}/debian/${jam}/usr/share/man/man1/
+ install -m644 debian/jam.1 ${topdir}/debian/${jam}/usr/share/man/man1/${binname}.1
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installdocs README RELNOTES Jambase *.html
+# dh_installemacsen
+# dh_undocumented
+ dh_installchangelogs
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
Property changes on: boost-jam/boost-build/branches/upstream/current/jam_src/debian/rules
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/execcmd.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/execcmd.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/execcmd.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,23 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * execcmd.h - execute a shell script
+ *
+ * 05/04/94 (seiwald) - async multiprocess interface
+ */
+
+void execcmd(
+ char *string,
+ void (*func)( void *closure, int status ),
+ void *closure,
+ LIST *shell );
+
+int execwait();
+
+# define EXEC_CMD_OK 0
+# define EXEC_CMD_FAIL 1
+# define EXEC_CMD_INTR 2
Added: boost-jam/boost-build/branches/upstream/current/jam_src/execmac.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/execmac.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/execmac.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,69 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "execcmd.h"
+# include <errno.h>
+
+# ifdef OS_MAC
+
+/*
+ * execunix.c - execute a shell script on UNIX
+ *
+ * If $(JAMSHELL) is defined, uses that to formulate execvp().
+ * The default is:
+ *
+ * /bin/sh -c %
+ *
+ * Each word must be an individual element in a jam variable value.
+ *
+ * In $(JAMSHELL), % expands to the command string and ! expands to
+ * the slot number (starting at 1) for multiprocess (-j) invocations.
+ * If $(JAMSHELL) doesn't include a %, it is tacked on as the last
+ * argument.
+ *
+ * Don't just set JAMSHELL to /bin/sh - it won't work!
+ *
+ * External routines:
+ * execcmd() - launch an async command execution
+ * execwait() - wait and drive at most one execution completion
+ *
+ * Internal routines:
+ * onintr() - bump intr to note command interruption
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 05/04/94 (seiwald) - async multiprocess interface
+ * 01/22/95 (seiwald) - $(JAMSHELL) support
+ */
+
+/*
+ * execcmd() - launch an async command execution
+ */
+
+void
+execcmd(
+ char *string,
+ void (*func)( void *closure, int status ),
+ void *closure,
+ LIST *shell )
+{
+
+ printf( "%s", string );
+ (*func)( closure, EXEC_CMD_OK );
+}
+
+/*
+ * execwait() - wait and drive at most one execution completion
+ */
+
+int
+execwait()
+{
+ return 0;
+}
+
+# endif /* OS_MAC */
Added: boost-jam/boost-build/branches/upstream/current/jam_src/execnt.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/execnt.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/execnt.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,838 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "execcmd.h"
+# include <errno.h>
+# include <assert.h>
+# include <ctype.h>
+
+# ifdef USE_EXECNT
+
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h> /* do the ugly deed */
+# include <process.h>
+
+# if !defined( __BORLANDC__ ) && !defined( OS_OS2 )
+# define wait my_wait
+static int my_wait( int *status );
+# endif
+
+/*
+ * execnt.c - execute a shell command on Windows NT and Windows 95/98
+ *
+ * If $(JAMSHELL) is defined, uses that to formulate execvp()/spawnvp().
+ * The default is:
+ *
+ * /bin/sh -c % [ on UNIX/AmigaOS ]
+ * cmd.exe /c % [ on Windows NT ]
+ *
+ * Each word must be an individual element in a jam variable value.
+ *
+ * In $(JAMSHELL), % expands to the command string and ! expands to
+ * the slot number (starting at 1) for multiprocess (-j) invocations.
+ * If $(JAMSHELL) doesn't include a %, it is tacked on as the last
+ * argument.
+ *
+ * Don't just set JAMSHELL to /bin/sh or cmd.exe - it won't work!
+ *
+ * External routines:
+ * execcmd() - launch an async command execution
+ * execwait() - wait and drive at most one execution completion
+ *
+ * Internal routines:
+ * onintr() - bump intr to note command interruption
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 05/04/94 (seiwald) - async multiprocess interface
+ * 01/22/95 (seiwald) - $(JAMSHELL) support
+ * 06/02/97 (gsar) - full async multiprocess support for Win32
+ */
+
+static int intr = 0;
+static int cmdsrunning = 0;
+static void (*istat)( int );
+
+static int is_nt_351 = 0;
+static int is_win95 = 1;
+static int is_win95_defined = 0;
+
+
+static struct
+{
+ int pid; /* on win32, a real process handle */
+ void (*func)( void *closure, int status );
+ void *closure;
+ char *tempfile;
+
+} cmdtab[ MAXJOBS ] = {{0}};
+
+
+static void
+set_is_win95( void )
+{
+ OSVERSIONINFO os_info;
+
+ os_info.dwOSVersionInfoSize = sizeof(os_info);
+ os_info.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
+ GetVersionEx( &os_info );
+
+ is_win95 = (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
+ is_win95_defined = 1;
+
+ /* now, test wether we're running Windows 3.51 */
+ /* this is later used to limit the system call command length */
+ if (os_info.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ is_nt_351 = os_info.dwMajorVersion == 3;
+}
+
+int maxline()
+{
+ if (!is_win95_defined)
+ set_is_win95();
+
+ /* Set the maximum command line length according to the OS */
+ return is_nt_351 ? 996
+ : is_win95 ? 1023
+ : 2047;
+}
+
+static char**
+string_to_args( const char* string, int* pcount )
+{
+ int total = strlen( string );
+ int in_quote = 0,
+ num_args = 0; /* was uninitialized -- dwa */
+ char* line;
+ char* p;
+ char** arg;
+ char** args;
+
+ *pcount = 0;
+
+ /* do not copy trailing newlines, if any */
+ while ( total > 0 )
+ {
+ if ( !isspace( string[total - 1] ) )
+ break;
+ --total;
+ }
+
+ /* first of all, copy the input string */
+ line = (char*)malloc( total+2 );
+ if (!line)
+ return 0;
+
+ memcpy( line+1, string, total );
+ line[0] = 0;
+ line[total+1] = 0;
+
+ in_quote = 0;
+ for ( p = line+1; p[0]; p++ )
+ {
+ switch (p[0])
+ {
+ case '"':
+ in_quote = !in_quote;
+ break;
+
+ case ' ':
+ case '\t':
+ if (!in_quote)
+ p[0] = 0;
+
+ default:
+ ;
+ }
+ }
+
+ /* now count the arguments.. */
+ for ( p = line; p < line+total+1; p++ )
+ if ( !p[0] && p[1] )
+ num_args++;
+
+ /* allocate the args array */
+ /* dwa -- did you really mean to allocate only 2 additional bytes? */
+#if 0 /* was like this */
+ args = (char**)malloc( num_args*sizeof(char*)+2 );
+#endif
+ args = (char**)malloc( (num_args + 2) * sizeof(char*) );
+ if (!args)
+ {
+ free( line );
+ return 0;
+ }
+
+ arg = args+1;
+ for ( p = line; p < line+total+1; p++ )
+ if ( !p[0] && p[1] )
+ {
+ arg[0] = p+1;
+ arg++;
+ }
+ arg[0] = 0;
+ *pcount = num_args;
+ args[0] = line;
+ return args+1;
+}
+
+static void
+free_args( char** args )
+{
+ free( args[-1] );
+ free( args-1 );
+}
+
+
+/* process a "del" or "erase" command under Windows 95/98 */
+static int
+process_del( char* command )
+{
+ char** arg;
+ char* p = command, *q;
+ int wildcard = 0, result = 0;
+
+ /* first of all, skip the command itself */
+ if ( p[0] == 'd' )
+ p += 3; /* assumes "del..;" */
+ else if ( p[0] == 'e' )
+ p += 5; /* assumes "erase.." */
+ else
+ return 1; /* invalid command */
+
+ /* process all targets independently */
+ for (;;)
+ {
+ /* skip leading spaces */
+ while ( *p && isspace(*p) )
+ p++;
+
+ /* exit if we encounter an end of string */
+ if (!*p)
+ return 0;
+
+ /* ignore toggles/flags */
+ while (*p == '/')
+ {
+ p++;
+ while ( *p && isalnum(*p) )
+ p++;
+ while (*p && isspace(*p) )
+ ++p;
+ }
+
+
+ {
+ int in_quote = 0;
+ int wildcard = 0;
+ int go_on = 1;
+
+ q = p;
+ while (go_on)
+ {
+ switch (*p)
+ {
+ case '"':
+ in_quote = !in_quote;
+ break;
+
+ case '?':
+ case '*':
+ if (!in_quote)
+ wildcard = 1;
+ break;
+
+ case '\0':
+ if (in_quote)
+ return 1;
+ /* fall-through */
+
+ case ' ':
+ case '\t':
+ if (!in_quote)
+ {
+ int len = p - q;
+ int result;
+ char* line;
+
+ /* q..p-1 contains the delete argument */
+ if ( len <= 0 )
+ return 1;
+
+ line = (char*)malloc( len+4+1 );
+ if (!line)
+ return 1;
+
+ strncpy( line, "del ", 4 );
+ strncpy( line+4, q, len );
+ line[len+4] = '\0';
+
+ if ( wildcard )
+ result = system( line );
+ else
+ result = !DeleteFile( line+4 );
+
+ free( line );
+ if (result)
+ return 1;
+
+ go_on = 0;
+ }
+
+ default:
+ ;
+ }
+ p++;
+ } /* while (go_on) */
+ }
+ }
+}
+
+
+/*
+ * onintr() - bump intr to note command interruption
+ */
+
+void
+onintr( int disp )
+{
+ intr++;
+ printf( "...interrupted\n" );
+}
+
+#if 0 // the shell is too different from direct invocation; let's
+ // always use the shell unless forced.
+/*
+ * use_bat_file() - return true iff the command demands the use of a
+ * .bat file to run it
+ */
+int use_bat_file(char* command)
+{
+ char *p = command;
+
+ char inquote = 0;
+
+ p += strspn( p, " \t" );
+
+ /* spawnvp can't handle any paths with spaces or quoted filenames with no directory prefix */
+ if ( *p == '"' )
+ {
+ char* q = p + 1 + strcspn( p + 1, "\" /\\" );
+ if ( *q == '"' || *q == ' ' )
+ return 1;
+ }
+
+ /* Look for newlines and unquoted i/o redirection */
+ do
+ {
+ p += strcspn( p, "'\n\"<>|" );
+
+ switch (*p)
+ {
+ case '\n':
+ /* skip over any following spaces */
+ while( isspace( *p ) )
+ ++p;
+ /* return true iff there is anything significant following
+ * the newline
+ */
+ if (*p)
+ return 1;
+ break;
+
+ case '"':
+ case '\'':
+ if (p > command && p[-1] != '\\')
+ {
+ if (inquote == *p)
+ inquote = 0;
+ else if (inquote == 0)
+ inquote = *p;
+ }
+
+ ++p;
+ break;
+
+ case '<':
+ case '>':
+ case '|':
+ if (!inquote)
+ return 1;
+ ++p;
+ break;
+ }
+ }
+ while (*p);
+
+ return p - command >= MAXLINE;
+}
+#endif
+
+void execnt_unit_test()
+{
+#if 0 && !defined(NDEBUG)
+ /* vc6 preprocessor is broken, so assert with these strings gets
+ * confused. Use a table instead.
+ */
+ typedef struct test { char* command; int result; } test;
+ test tests[] = {
+ { "x", 0 },
+ { "x\n ", 0 },
+ { "x\ny", 1 },
+ { "x\n\n y", 1 },
+ { "\"x\"", 1 },
+ { "\"x y\"", 1 },
+ { "\"x/y\"", 0 },
+ { "\"x\\y\"", 0 },
+ { "echo x > foo.bar", 1 },
+ { "echo x < foo.bar", 1 },
+ { "echo x \">\" foo.bar", 0 },
+ { "echo x \"<\" foo.bar", 0 },
+ { "echo x \\\">\\\" foo.bar", 1 },
+ { "echo x \\\"<\\\" foo.bar", 1 }
+ };
+ int i;
+ for ( i = 0; i < sizeof(tests)/sizeof(*tests); ++i)
+ {
+ assert( use_bat_file( tests[i].command ) == tests[i].result );
+ }
+
+ {
+ char* long_command = malloc(MAXLINE + 10);
+ assert( long_command != 0 );
+ memset( long_command, 'x', MAXLINE + 9 );
+ long_command[MAXLINE + 9] = 0;
+ assert( use_bat_file( long_command ) );
+ free( long_command );
+ }
+#endif
+}
+
+// SVA - handle temp dirs with spaces in the path
+static const char *getTempDir(void)
+{
+ static char tempPath[_MAX_PATH];
+ static char *pTempPath=NULL;
+
+ if(pTempPath == NULL)
+ {
+ char *p;
+
+ p = getenv("TEMP");
+ if(p == NULL)
+ {
+ p = getenv("TMP");
+ }
+ if(p == NULL)
+ {
+ pTempPath = "\\temp";
+ }
+ else
+ {
+ GetShortPathName(p, tempPath, _MAX_PATH);
+ pTempPath = tempPath;
+ }
+ }
+ return pTempPath;
+}
+
+/*
+ * execcmd() - launch an async command execution
+ */
+
+void
+execcmd(
+ char *string,
+ void (*func)( void *closure, int status ),
+ void *closure,
+ LIST *shell )
+{
+ int pid;
+ int slot;
+ int raw_cmd = 0 ;
+ char *argv_static[ MAXARGC + 1 ]; /* +1 for NULL */
+ char **argv = argv_static;
+ char *p;
+
+ /* Check to see if we need to hack around the line-length limitation. */
+ /* Look for a JAMSHELL setting of "%", indicating that the command
+ * should be invoked directly */
+ if ( shell && !strcmp(shell->string,"%") && !list_next(shell) )
+ {
+ raw_cmd = 1;
+ shell = 0;
+ }
+
+ if ( !is_win95_defined )
+ set_is_win95();
+
+ /* Find a slot in the running commands table for this one. */
+ if ( is_win95 )
+ {
+ /* only synchronous spans are supported on Windows 95/98 */
+ slot = 0;
+ }
+ else
+ {
+ for( slot = 0; slot < MAXJOBS; slot++ )
+ if( !cmdtab[ slot ].pid )
+ break;
+ }
+ if( slot == MAXJOBS )
+ {
+ printf( "no slots for child!\n" );
+ exit( EXITBAD );
+ }
+
+ if( !cmdtab[ slot ].tempfile )
+ {
+ const char *tempdir;
+ DWORD procID;
+
+ tempdir = getTempDir();
+
+ // SVA - allocate 64 other just to be safe
+ cmdtab[ slot ].tempfile = malloc( strlen( tempdir ) + 64 );
+
+ procID = GetCurrentProcessId();
+
+ sprintf( cmdtab[ slot ].tempfile, "%s\\jam%d-%02d.bat",
+ tempdir, procID, slot );
+ }
+
+ /* Trim leading, ending white space */
+
+ while( isspace( *string ) )
+ ++string;
+
+ /* If multi line, or too long, or JAMSHELL is set, write to bat file. */
+ /* Otherwise, exec directly. */
+ /* Frankly, if it is a single long line I don't think the */
+ /* command interpreter will do any better -- it will fail. */
+
+ if( shell || !raw_cmd // && use_bat_file( string )
+ )
+ {
+ FILE *f;
+
+ /* Write command to bat file. */
+
+ f = fopen( cmdtab[ slot ].tempfile, "w" );
+ fputs( string, f );
+ fclose( f );
+
+ string = cmdtab[ slot ].tempfile;
+
+ if( DEBUG_EXECCMD )
+ {
+ if (shell)
+ printf("using user-specified shell: %s", shell->string);
+ else
+ printf("Executing through .bat file\n");
+ }
+ }
+ else if( DEBUG_EXECCMD )
+ {
+ printf("Executing raw command directly\n");
+ }
+
+ /* Forumulate argv */
+ /* If shell was defined, be prepared for % and ! subs. */
+ /* Otherwise, use stock /bin/sh (on unix) or cmd.exe (on NT). */
+
+ if( shell )
+ {
+ int i;
+ char jobno[4];
+ int gotpercent = 0;
+
+ sprintf( jobno, "%d", slot + 1 );
+
+ for( i = 0; shell && i < MAXARGC; i++, shell = list_next( shell ) )
+ {
+ switch( shell->string[0] )
+ {
+ case '%': argv[i] = string; gotpercent++; break;
+ case '!': argv[i] = jobno; break;
+ default: argv[i] = shell->string;
+ }
+ if( DEBUG_EXECCMD )
+ printf( "argv[%d] = '%s'\n", i, argv[i] );
+ }
+
+ if( !gotpercent )
+ argv[i++] = string;
+
+ argv[i] = 0;
+ }
+ else if (raw_cmd)
+ {
+ int ignored;
+ argv = string_to_args(string, &ignored);
+ }
+ else
+ {
+ /* don't worry, this is ignored on Win95/98, see later.. */
+ argv[0] = "cmd.exe";
+ argv[1] = "/Q/C"; /* anything more is non-portable */
+ argv[2] = string;
+ argv[3] = 0;
+ }
+
+ /* Catch interrupts whenever commands are running. */
+
+ if( !cmdsrunning++ )
+ istat = signal( SIGINT, onintr );
+
+ /* Start the command */
+
+ /* on Win95, we only do a synchronous call */
+ if ( is_win95 )
+ {
+ static const char* hard_coded[] =
+ {
+ "del", "erase", "copy", "mkdir", "rmdir", "cls", "dir",
+ "ren", "rename", "move", 0
+ };
+
+ const char** keyword;
+ int len, spawn = 1;
+ int result;
+
+ for ( keyword = hard_coded; keyword[0]; keyword++ )
+ {
+ len = strlen( keyword[0] );
+ if ( strnicmp( string, keyword[0], len ) == 0 &&
+ !isalnum(string[len]) )
+ {
+ /* this is one of the hard coded symbols, use 'system' to run */
+ /* them.. except for "del"/"erase" */
+ if ( keyword - hard_coded < 2 )
+ result = process_del( string );
+ else
+ result = system( string );
+
+ spawn = 0;
+ break;
+ }
+ }
+
+ if (spawn)
+ {
+ char** args;
+ int num_args;
+
+ /* convert the string into an array of arguments */
+ /* we need to take care of double quotes !! */
+ args = string_to_args( string, &num_args );
+ if ( args )
+ {
+#if 0
+ char** arg;
+ fprintf( stderr, "%s: ", args[0] );
+ arg = args+1;
+ while ( arg[0] )
+ {
+ fprintf( stderr, " {%s}", arg[0] );
+ arg++;
+ }
+ fprintf( stderr, "\n" );
+#endif
+ result = spawnvp( P_WAIT, args[0], args );
+ free_args( args );
+ }
+ else
+ result = 1;
+ }
+ func( closure, result ? EXEC_CMD_FAIL : EXEC_CMD_OK );
+ return;
+ }
+
+ if( DEBUG_EXECCMD )
+ {
+ char **argp = argv;
+
+ printf("Executing command");
+ while(*argp != 0)
+ {
+ printf(" [%s]", *argp);
+ argp++;
+ }
+ printf("\n");
+ }
+
+ /* the rest is for Windows NT only */
+ /* spawn doesn't like quotes aroudn the command name */
+ if ( argv[0][0] == '"')
+ {
+ int l = strlen(argv[0]);
+ if (argv[0][l-1] == '"') argv[0][l-1] = '\0';
+ strcpy(argv[0],argv[0]+1);
+ }
+ if( ( pid = spawnvp( P_NOWAIT, argv[0], argv ) ) == -1 )
+ {
+ perror( "spawn" );
+ exit( EXITBAD );
+ }
+ /* Save the operation for execwait() to find. */
+
+ cmdtab[ slot ].pid = pid;
+ cmdtab[ slot ].func = func;
+ cmdtab[ slot ].closure = closure;
+
+ /* Wait until we're under the limit of concurrent commands. */
+ /* Don't trust globs.jobs alone. */
+
+ while( cmdsrunning >= MAXJOBS || cmdsrunning >= globs.jobs )
+ if( !execwait() )
+ break;
+
+ if (argv != argv_static)
+ {
+ free_args(argv);
+ }
+}
+
+/*
+ * execwait() - wait and drive at most one execution completion
+ */
+
+int
+execwait()
+{
+ int i;
+ int status, w;
+ int rstat;
+
+ /* Handle naive make1() which doesn't know if cmds are running. */
+
+ if( !cmdsrunning )
+ return 0;
+
+ if ( is_win95 )
+ return 0;
+
+ /* Pick up process pid and status */
+
+ while( ( w = wait( &status ) ) == -1 && errno == EINTR )
+ ;
+
+ if( w == -1 )
+ {
+ printf( "child process(es) lost!\n" );
+ perror("wait");
+ exit( EXITBAD );
+ }
+
+ /* Find the process in the cmdtab. */
+
+ for( i = 0; i < MAXJOBS; i++ )
+ if( w == cmdtab[ i ].pid )
+ break;
+
+ if( i == MAXJOBS )
+ {
+ printf( "waif child found!\n" );
+ exit( EXITBAD );
+ }
+
+ /* Clear the temp file */
+ if ( cmdtab[i].tempfile )
+ unlink( cmdtab[ i ].tempfile );
+
+ /* Drive the completion */
+
+ if( !--cmdsrunning )
+ signal( SIGINT, istat );
+
+ if( intr )
+ rstat = EXEC_CMD_INTR;
+ else if( w == -1 || status != 0 )
+ rstat = EXEC_CMD_FAIL;
+ else
+ rstat = EXEC_CMD_OK;
+
+ cmdtab[ i ].pid = 0;
+ // SVA don't leak temp files
+ if(cmdtab[i].tempfile != NULL)
+ {
+ free(cmdtab[i].tempfile);
+ cmdtab[i].tempfile = NULL;
+ }
+ (*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat );
+
+ return 1;
+}
+
+# if !defined( __BORLANDC__ )
+
+static int
+my_wait( int *status )
+{
+ int i, num_active = 0;
+ DWORD exitcode, waitcode;
+ static HANDLE *active_handles = 0;
+
+ if (!active_handles)
+ active_handles = (HANDLE *)malloc(globs.jobs * sizeof(HANDLE) );
+
+ /* first see if any non-waited-for processes are dead,
+ * and return if so.
+ */
+ for ( i = 0; i < globs.jobs; i++ ) {
+ if ( cmdtab[i].pid ) {
+ if ( GetExitCodeProcess((HANDLE)cmdtab[i].pid, &exitcode) ) {
+ if ( exitcode == STILL_ACTIVE )
+ active_handles[num_active++] = (HANDLE)cmdtab[i].pid;
+ else {
+ CloseHandle((HANDLE)cmdtab[i].pid);
+ *status = (int)((exitcode & 0xff) << 8);
+ return cmdtab[i].pid;
+ }
+ }
+ else
+ goto FAILED;
+ }
+ }
+
+ /* if a child exists, wait for it to die */
+ if ( !num_active ) {
+ errno = ECHILD;
+ return -1;
+ }
+ waitcode = WaitForMultipleObjects( num_active,
+ active_handles,
+ FALSE,
+ INFINITE );
+ if ( waitcode != WAIT_FAILED ) {
+ if ( waitcode >= WAIT_ABANDONED_0
+ && waitcode < WAIT_ABANDONED_0 + num_active )
+ i = waitcode - WAIT_ABANDONED_0;
+ else
+ i = waitcode - WAIT_OBJECT_0;
+ if ( GetExitCodeProcess(active_handles[i], &exitcode) ) {
+ CloseHandle(active_handles[i]);
+ *status = (int)((exitcode & 0xff) << 8);
+ return (int)active_handles[i];
+ }
+ }
+
+FAILED:
+ errno = GetLastError();
+ return -1;
+
+}
+
+# endif /* !__BORLANDC__ */
+
+# endif /* USE_EXECNT */
Added: boost-jam/boost-build/branches/upstream/current/jam_src/execunix.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/execunix.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/execunix.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,375 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "execcmd.h"
+# include <errno.h>
+
+#if defined(sun) || defined(__sun)
+#include <unistd.h> /* need to include unistd.h on sun for the vfork prototype*/
+#include <wait.h>
+#endif
+
+# ifdef USE_EXECUNIX
+
+# ifdef NO_VFORK
+# define vfork() fork()
+# endif
+
+# if defined( OS_NT ) || defined( OS_OS2 )
+
+# define USE_EXECNT
+
+# include <process.h>
+
+# if !defined( __BORLANDC__ ) && !defined( OS_OS2 )
+# define wait my_wait
+static int my_wait( int *status );
+# endif
+
+# endif
+
+/*
+ * execunix.c - execute a shell script on UNIX/WinNT/OS2/AmigaOS
+ *
+ * If $(JAMSHELL) is defined, uses that to formulate execvp()/spawnvp().
+ * The default is:
+ *
+ * /bin/sh -c % [ on UNIX/AmigaOS ]
+ * cmd.exe /c % [ on OS2/WinNT ]
+ *
+ * Each word must be an individual element in a jam variable value.
+ *
+ * In $(JAMSHELL), % expands to the command string and ! expands to
+ * the slot number (starting at 1) for multiprocess (-j) invocations.
+ * If $(JAMSHELL) doesn't include a %, it is tacked on as the last
+ * argument.
+ *
+ * Don't just set JAMSHELL to /bin/sh or cmd.exe - it won't work!
+ *
+ * External routines:
+ * execcmd() - launch an async command execution
+ * execwait() - wait and drive at most one execution completion
+ *
+ * Internal routines:
+ * onintr() - bump intr to note command interruption
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 05/04/94 (seiwald) - async multiprocess interface
+ * 01/22/95 (seiwald) - $(JAMSHELL) support
+ * 06/02/97 (gsar) - full async multiprocess support for Win32
+ */
+
+static int intr = 0;
+static int cmdsrunning = 0;
+static void (*istat)( int );
+
+static struct
+{
+ int pid; /* on win32, a real process handle */
+ void (*func)( void *closure, int status );
+ void *closure;
+
+# ifdef USE_EXECNT
+ char *tempfile;
+# endif
+
+} cmdtab[ MAXJOBS ] = {{0}};
+
+/*
+ * onintr() - bump intr to note command interruption
+ */
+
+void
+onintr( int disp )
+{
+ intr++;
+ printf( "...interrupted\n" );
+}
+
+/*
+ * execcmd() - launch an async command execution
+ */
+
+void
+execcmd(
+ char *string,
+ void (*func)( void *closure, int status ),
+ void *closure,
+ LIST *shell )
+{
+ int pid;
+ int slot;
+ char *argv[ MAXARGC + 1 ]; /* +1 for NULL */
+
+# ifdef USE_EXECNT
+ char *p;
+# endif
+
+ /* Find a slot in the running commands table for this one. */
+
+ for( slot = 0; slot < MAXJOBS; slot++ )
+ if( !cmdtab[ slot ].pid )
+ break;
+
+ if( slot == MAXJOBS )
+ {
+ printf( "no slots for child!\n" );
+ exit( EXITBAD );
+ }
+
+# ifdef USE_EXECNT
+ if( !cmdtab[ slot ].tempfile )
+ {
+ char *tempdir;
+
+ if( !( tempdir = getenv( "TEMP" ) ) &&
+ !( tempdir = getenv( "TMP" ) ) )
+ tempdir = "\\temp";
+
+ cmdtab[ slot ].tempfile = malloc( strlen( tempdir ) + 14 );
+
+ sprintf( cmdtab[ slot ].tempfile, "%s\\jamtmp%02d.bat",
+ tempdir, slot );
+ }
+
+ /* Trim leading, ending white space */
+
+ while( isspace( *string ) )
+ ++string;
+
+ p = strchr( string, '\n' );
+
+ while( p && isspace( *p ) )
+ ++p;
+
+ /* If multi line, or too long, or JAMSHELL is set, write to bat file. */
+ /* Otherwise, exec directly. */
+ /* Frankly, if it is a single long line I don't think the */
+ /* command interpreter will do any better -- it will fail. */
+
+ if( p && *p || strlen( string ) > MAXLINE || shell )
+ {
+ FILE *f;
+
+ /* Write command to bat file. */
+
+ f = fopen( cmdtab[ slot ].tempfile, "w" );
+ fputs( string, f );
+ fclose( f );
+
+ string = cmdtab[ slot ].tempfile;
+ }
+# endif
+
+ /* Forumulate argv */
+ /* If shell was defined, be prepared for % and ! subs. */
+ /* Otherwise, use stock /bin/sh (on unix) or cmd.exe (on NT). */
+
+ if( shell )
+ {
+ int i;
+ char jobno[4];
+ int gotpercent = 0;
+
+ sprintf( jobno, "%d", slot + 1 );
+
+ for( i = 0; shell && i < MAXARGC; i++, shell = list_next( shell ) )
+ {
+ switch( shell->string[0] )
+ {
+ case '%': argv[i] = string; gotpercent++; break;
+ case '!': argv[i] = jobno; break;
+ default: argv[i] = shell->string;
+ }
+ if( DEBUG_EXECCMD )
+ printf( "argv[%d] = '%s'\n", i, argv[i] );
+ }
+
+ if( !gotpercent )
+ argv[i++] = string;
+
+ argv[i] = 0;
+ }
+ else
+ {
+# ifdef USE_EXECNT
+ argv[0] = "cmd.exe";
+ argv[1] = "/Q/C"; /* anything more is non-portable */
+# else
+ argv[0] = "/bin/sh";
+ argv[1] = "-c";
+# endif
+ argv[2] = string;
+ argv[3] = 0;
+ }
+
+ /* Catch interrupts whenever commands are running. */
+
+ if( !cmdsrunning++ )
+ istat = signal( SIGINT, onintr );
+
+ /* Start the command */
+
+# ifdef USE_EXECNT
+ if( ( pid = spawnvp( P_NOWAIT, argv[0], argv ) ) == -1 )
+ {
+ perror( "spawn" );
+ exit( EXITBAD );
+ }
+# else
+ if ((pid = vfork()) == 0)
+ {
+ execvp( argv[0], argv );
+ _exit(127);
+ }
+
+ if( pid == -1 )
+ {
+ perror( "vfork" );
+ exit( EXITBAD );
+ }
+# endif
+ /* Save the operation for execwait() to find. */
+
+ cmdtab[ slot ].pid = pid;
+ cmdtab[ slot ].func = func;
+ cmdtab[ slot ].closure = closure;
+
+ /* Wait until we're under the limit of concurrent commands. */
+ /* Don't trust globs.jobs alone. */
+
+ while( cmdsrunning >= MAXJOBS || cmdsrunning >= globs.jobs )
+ if( !execwait() )
+ break;
+}
+
+/*
+ * execwait() - wait and drive at most one execution completion
+ */
+
+int
+execwait()
+{
+ int i;
+ int status, w;
+ int rstat;
+
+ /* Handle naive make1() which doesn't know if cmds are running. */
+
+ if( !cmdsrunning )
+ return 0;
+
+ /* Pick up process pid and status */
+
+ while( ( w = wait( &status ) ) == -1 && errno == EINTR )
+ ;
+
+ if( w == -1 )
+ {
+ printf( "child process(es) lost!\n" );
+ perror("wait");
+ exit( EXITBAD );
+ }
+
+ /* Find the process in the cmdtab. */
+
+ for( i = 0; i < MAXJOBS; i++ )
+ if( w == cmdtab[ i ].pid )
+ break;
+
+ if( i == MAXJOBS )
+ {
+ printf( "waif child found!\n" );
+ exit( EXITBAD );
+ }
+
+ /* Drive the completion */
+
+ if( !--cmdsrunning )
+ signal( SIGINT, istat );
+
+ if( intr )
+ rstat = EXEC_CMD_INTR;
+ else if( w == -1 || status != 0 )
+ rstat = EXEC_CMD_FAIL;
+ else
+ rstat = EXEC_CMD_OK;
+
+ cmdtab[ i ].pid = 0;
+
+ (*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat );
+
+ return 1;
+}
+
+# if defined( OS_NT ) && !defined( __BORLANDC__ )
+
+# define WIN32_LEAN_AND_MEAN
+
+# include <windows.h> /* do the ugly deed */
+
+static int
+my_wait( int *status )
+{
+ int i, num_active = 0;
+ DWORD exitcode, waitcode;
+ static HANDLE *active_handles = 0;
+
+ if (!active_handles)
+ active_handles = (HANDLE *)malloc(globs.jobs * sizeof(HANDLE) );
+
+ /* first see if any non-waited-for processes are dead,
+ * and return if so.
+ */
+ for ( i = 0; i < globs.jobs; i++ ) {
+ if ( cmdtab[i].pid ) {
+ if ( GetExitCodeProcess((HANDLE)cmdtab[i].pid, &exitcode) ) {
+ if ( exitcode == STILL_ACTIVE )
+ active_handles[num_active++] = (HANDLE)cmdtab[i].pid;
+ else {
+ CloseHandle((HANDLE)cmdtab[i].pid);
+ *status = (int)((exitcode & 0xff) << 8);
+ return cmdtab[i].pid;
+ }
+ }
+ else
+ goto FAILED;
+ }
+ }
+
+ /* if a child exists, wait for it to die */
+ if ( !num_active ) {
+ errno = ECHILD;
+ return -1;
+ }
+ waitcode = WaitForMultipleObjects( num_active,
+ active_handles,
+ FALSE,
+ INFINITE );
+ if ( waitcode != WAIT_FAILED ) {
+ if ( waitcode >= WAIT_ABANDONED_0
+ && waitcode < WAIT_ABANDONED_0 + num_active )
+ i = waitcode - WAIT_ABANDONED_0;
+ else
+ i = waitcode - WAIT_OBJECT_0;
+ if ( GetExitCodeProcess(active_handles[i], &exitcode) ) {
+ CloseHandle(active_handles[i]);
+ *status = (int)((exitcode & 0xff) << 8);
+ return (int)active_handles[i];
+ }
+ }
+
+FAILED:
+ errno = GetLastError();
+ return -1;
+
+}
+
+# endif /* NT && !__BORLANDC__ */
+
+# endif /* USE_EXECUNIX */
Added: boost-jam/boost-build/branches/upstream/current/jam_src/execvms.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/execvms.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/execvms.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,167 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "execcmd.h"
+
+# ifdef OS_VMS
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <iodef.h>
+#include <ssdef.h>
+#include <descrip.h>
+#include <dvidef.h>
+#include <clidef.h>
+
+/*
+ * execvms.c - execute a shell script, ala VMS
+ *
+ * The approach is this:
+ *
+ * If the command is a single line, and shorter than WRTLEN (what we
+ * believe to be the maximum line length), we just system() it.
+ *
+ * If the command is multi-line, or longer than WRTLEN, we write the
+ * command block to a temp file, splitting long lines (using "-" at
+ * the end of the line to indicate contiuation), and then source that
+ * temp file. We use special logic to make sure we don't continue in
+ * the middle of a quoted string.
+ *
+ * 05/04/94 (seiwald) - async multiprocess interface; noop on VMS
+ * 12/20/96 (seiwald) - rewritten to handle multi-line commands well
+ * 01/14/96 (seiwald) - don't put -'s between "'s
+ */
+
+#define WRTLEN 240
+
+#define MIN( a, b ) ((a) < (b) ? (a) : (b))
+
+/* 1 for the @ and 4 for the .com */
+
+char tempnambuf[ L_tmpnam + 1 + 4 ] = {0};
+
+void
+execcmd(
+ char *string,
+ void (*func)( void *closure, int status ),
+ void *closure,
+ LIST *shell )
+{
+ char *s, *e, *p;
+ int rstat = EXEC_CMD_OK;
+ int status;
+
+ /* See if string is more than one line */
+ /* discounting leading/trailing white space */
+
+ for( s = string; *s && isspace( *s ); s++ )
+ ;
+
+ e = p = strchr( s, '\n' );
+
+ while( p && isspace( *p ) )
+ ++p;
+
+ /* If multi line or long, write to com file. */
+ /* Otherwise, exec directly. */
+
+ if( p && *p || e - s > WRTLEN )
+ {
+ FILE *f;
+
+ /* Create temp file invocation "@sys$scratch:tempfile.com" */
+
+ if( !*tempnambuf )
+ {
+ tempnambuf[0] = '@';
+ (void)tmpnam( tempnambuf + 1 );
+ strcat( tempnambuf, ".com" );
+ }
+
+ /* Open tempfile */
+
+ if( !( f = fopen( tempnambuf + 1, "w" ) ) )
+ {
+ printf( "can't open command file\n" );
+ (*func)( closure, EXEC_CMD_FAIL );
+ return;
+ }
+
+ /* For each line of the string */
+
+ while( *string )
+ {
+ char *s = strchr( string, '\n' );
+ int len = s ? s + 1 - string : strlen( string );
+
+ fputc( '$', f );
+
+ /* For each chunk of a line that needs to be split */
+
+ while( len > 0 )
+ {
+ char *q = string;
+ char *qe = string + MIN( len, WRTLEN );
+ char *qq = q;
+ int quote = 0;
+
+ /* Look for matching "'s */
+
+ for( ; q < qe; q++ )
+ if( *q == '"' && ( quote = !quote ) )
+ qq = q;
+
+ /* Back up to opening quote, if in one */
+
+ if( quote )
+ q = qq;
+
+ fwrite( string, ( q - string ), 1, f );
+
+ len -= ( q - string );
+ string = q;
+
+ if( len )
+ {
+ fputc( '-', f );
+ fputc( '\n', f );
+ }
+ }
+ }
+
+ fclose( f );
+
+ status = system( tempnambuf ) & 0x07;
+
+ unlink( tempnambuf + 1 );
+ }
+ else
+ {
+ /* Execute single line command */
+ /* Strip trailing newline before execing */
+ if( e ) *e = 0;
+ status = system( s ) & 0x07;
+ }
+
+ /* Fail for error or fatal error */
+ /* OK on OK, warning, or info exit */
+
+ if( status == 2 || status == 4 )
+ rstat = EXEC_CMD_FAIL;
+
+ (*func)( closure, rstat );
+}
+
+int
+execwait()
+{
+ return 0;
+}
+
+# endif /* VMS */
Added: boost-jam/boost-build/branches/upstream/current/jam_src/expand.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/expand.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/expand.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,710 @@
+# include "jam.h"
+# include "lists.h"
+# include "variable.h"
+# include "expand.h"
+# include "pathsys.h"
+# include "newstr.h"
+# include <assert.h>
+
+# ifdef OS_CYGWIN
+# include <sys/cygwin.h>
+# include <windows.h>
+# endif
+
+/*
+ * expand.c - expand a buffer, given variable values
+ *
+ * External routines:
+ *
+ * var_expand() - variable-expand input string into list of strings
+ *
+ * Internal routines:
+ *
+ * var_edit_parse() - parse : modifiers into PATHNAME structure
+ * var_edit_file() - copy input target name to output, modifying filename
+ * var_edit_shift() - do upshift/downshift mods
+ *
+ * 01/25/94 (seiwald) - $(X)$(UNDEF) was expanding like plain $(X)
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 01/11/01 (seiwald) - added support for :E=emptyvalue, :J=joinval
+ */
+
+typedef struct {
+ PATHNAME f; /* :GDBSMR -- pieces */
+ char parent; /* :P -- go to parent directory */
+ char filemods; /* one of the above applied */
+ char downshift; /* :L -- downshift result */
+ char upshift; /* :U -- upshift result */
+ char to_slashes; /* :T -- convert "\" to "/" */
+ char to_windows; /* :W -- convert cygwin to native paths */
+ PATHPART empty; /* :E -- default for empties */
+ PATHPART join; /* :J -- join list with char */
+} VAR_EDITS ;
+
+static void var_edit_parse( char *mods, VAR_EDITS *edits );
+static void var_edit_file( char *in, string *out, VAR_EDITS *edits );
+static void var_edit_shift( string *out, VAR_EDITS *edits );
+
+# define MAGIC_COLON '\001'
+# define MAGIC_LEFT '\002'
+# define MAGIC_RIGHT '\003'
+
+/*
+ * var_expand() - variable-expand input string into list of strings
+ *
+ * Would just copy input to output, performing variable expansion,
+ * except that since variables can contain multiple values the result
+ * of variable expansion may contain multiple values (a list). Properly
+ * performs "product" operations that occur in "$(var1)xxx$(var2)" or
+ * even "$($(var2))".
+ *
+ * Returns a newly created list.
+ */
+
+LIST *
+var_expand(
+ LIST *l,
+ char *in,
+ char *end,
+ LOL *lol,
+ int cancopyin )
+{
+ char out_buf[ MAXSYM ];
+ string buf[1];
+ string out1[1]; /* Temporary buffer */
+ size_t prefix_length;
+ char *out;
+ char *inp = in;
+ char *ov; /* for temp copy of variable in outbuf */
+ int depth;
+
+ if( DEBUG_VAREXP )
+ printf( "expand '%.*s'\n", end - in, in );
+
+ /* This gets alot of cases: $(<) and $(>) */
+
+ if( in[0] == '$' && in[1] == '(' && in[3] == ')' && !in[4] )
+ {
+ switch( in[2] )
+ {
+ case '1':
+ case '<':
+ return list_copy( l, lol_get( lol, 0 ) );
+
+ case '2':
+ case '>':
+ return list_copy( l, lol_get( lol, 1 ) );
+ }
+ }
+
+ /* Just try simple copy of in to out. */
+
+ while( in < end )
+ if( *in++ == '$' && *in == '(' )
+ goto expand;
+
+ /* No variables expanded - just add copy of input string to list. */
+
+ /* Cancopyin is an optimization: if the input was already a list */
+ /* item, we can use the copystr() to put it on the new list. */
+ /* Otherwise, we use the slower newstr(). */
+
+ if( cancopyin )
+ {
+ return list_new( l, copystr( inp ) );
+ }
+ else
+ {
+ LIST* r;
+ string_new( buf );
+ string_append_range( buf, inp, end );
+
+ r = list_new( l, newstr( buf->value) );
+ string_free( buf );
+ return r;
+ }
+
+expand:
+ string_new( buf );
+ string_append_range( buf, inp, in - 1); /* copy the part before '$'. */
+ /*
+ * Input so far (ignore blanks):
+ *
+ * stuff-in-outbuf $(variable) remainder
+ * ^ ^
+ * in end
+ * Output so far:
+ *
+ * stuff-in-outbuf $
+ * ^ ^
+ * out_buf out
+ *
+ *
+ * We just copied the $ of $(...), so back up one on the output.
+ * We now find the matching close paren, copying the variable and
+ * modifiers between the $( and ) temporarily into out_buf, so that
+ * we can replace :'s with MAGIC_COLON. This is necessary to avoid
+ * being confused by modifier values that are variables containing
+ * :'s. Ugly.
+ */
+
+ depth = 1;
+ inp = ++in; /* skip over the '(' */
+
+ while( in < end && depth )
+ {
+ switch( *in++ )
+ {
+ case '(': depth++; break;
+ case ')': depth--; break;
+ }
+ }
+
+ /*
+ * Input so far (ignore blanks):
+ *
+ * stuff-in-outbuf $(variable) remainder
+ * ^ ^ ^
+ * inp in end
+ */
+ prefix_length = buf->size;
+ string_append_range( buf, inp, in - 1 );
+
+ out = buf->value + prefix_length;
+ for ( ov = out; ov < buf->value + buf->size; ++ov )
+ {
+ switch( *ov )
+ {
+ case ':': *ov = MAGIC_COLON; break;
+ case '[': *ov = MAGIC_LEFT; break;
+ case ']': *ov = MAGIC_RIGHT; break;
+ }
+ }
+
+ /*
+ * Input so far (ignore blanks):
+ *
+ * stuff-in-outbuf $(variable) remainder
+ * ^ ^
+ * in end
+ * Output so far:
+ *
+ * stuff-in-outbuf variable
+ * ^ ^ ^
+ * out_buf out ov
+ *
+ * Later we will overwrite 'variable' in out_buf, but we'll be
+ * done with it by then. 'variable' may be a multi-element list,
+ * so may each value for '$(variable element)', and so may 'remainder'.
+ * Thus we produce a product of three lists.
+ */
+
+ {
+ LIST *variables = 0;
+ LIST *remainder = 0;
+ LIST *vars;
+
+ /* Recursively expand variable name & rest of input */
+
+ if( out < ov )
+ variables = var_expand( L0, out, ov, lol, 0 );
+ if( in < end )
+ remainder = var_expand( L0, in, end, lol, 0 );
+
+ /* Now produce the result chain */
+
+ /* For each variable name */
+
+ for( vars = variables; vars; vars = list_next( vars ) )
+ {
+ LIST *value, *evalue = 0;
+ char *colon;
+ char *bracket;
+ string variable[1];
+ char *varname;
+ int sub1 = 0, sub2 = -1;
+ VAR_EDITS edits;
+
+ /* Look for a : modifier in the variable name */
+ /* Must copy into varname so we can modify it */
+
+ string_copy( variable, vars->string );
+ varname = variable->value;
+
+ if( colon = strchr( varname, MAGIC_COLON ) )
+ {
+ string_truncate( variable, colon - varname );
+ var_edit_parse( colon + 1, &edits );
+ }
+
+ /* Look for [x-y] subscripting */
+ /* sub1 and sub2 are x and y. */
+
+ if ( bracket = strchr( varname, MAGIC_LEFT ) )
+ {
+ /*
+ ** Make all syntax errors in [] subscripting
+ ** result in the same behavior: silenty return an empty
+ ** expansion (by setting sub2 = 0). Brute force parsing;
+ ** May get moved into yacc someday.
+ */
+
+ char *s = bracket + 1;
+
+ string_truncate( variable, bracket - varname );
+
+ do /* so we can use "break" */
+ {
+ /* Allow negative indexes. */
+ if (! isdigit( *s ) && ! ( *s == '-') )
+ {
+ sub2 = 0;
+ break;
+ }
+ sub1 = atoi(s);
+
+ /* Skip over the first symbol, which is either a digit or dash. */
+ s++;
+ while ( isdigit( *s ) ) s++;
+
+ if ( *s == MAGIC_RIGHT )
+ {
+ sub2 = sub1;
+ break;
+ }
+
+ if ( *s != '-')
+ {
+ sub2 = 0;
+ break;
+ }
+
+ s++;
+
+ if ( *s == MAGIC_RIGHT )
+ {
+ sub2 = -1;
+ break;
+ }
+
+ if (! isdigit( *s ) && ! ( *s == '-') )
+ {
+ sub2 = 0;
+ break;
+ }
+
+ /* First, compute the index of the last element. */
+ sub2 = atoi(s);
+ s++;
+ while ( isdigit( *s ) ) s++;
+
+ if ( *s != MAGIC_RIGHT)
+ sub2 = 0;
+
+ } while (0);
+
+ /*
+ ** Anything but the end of the string, or the colon
+ ** introducing a modifier is a syntax error.
+ */
+
+ s++;
+ if (*s && *s != MAGIC_COLON)
+ sub2 = 0;
+
+ *bracket = '\0';
+ }
+
+ /* Get variable value, specially handling $(<), $(>), $(n) */
+
+ if( varname[0] == '<' && !varname[1] )
+ value = lol_get( lol, 0 );
+ else if( varname[0] == '>' && !varname[1] )
+ value = lol_get( lol, 1 );
+ else if( varname[0] >= '1' && varname[0] <= '9' && !varname[1] )
+ value = lol_get( lol, varname[0] - '1' );
+ else
+ value = var_get( varname );
+
+ /* Handle negitive indexes: part two. */
+ {
+ int length = list_length( value );
+
+ if (sub1 < 0)
+ sub1 = length + sub1;
+ else
+ sub1 -= 1;
+
+ if (sub2 < 0)
+ sub2 = length + 1 + sub2 - sub1;
+ else
+ sub2 -= sub1;
+ /*
+ ** The "sub2 < 0" test handles the semantic error
+ ** of sub2 < sub1.
+ */
+ if ( sub2 < 0 )
+ sub2 = 0;
+ }
+
+
+
+ /* The fast path: $(x) - just copy the variable value. */
+ /* This is only an optimization */
+
+ if( out == out_buf && !bracket && !colon && in == end )
+ {
+ string_free( variable );
+ l = list_copy( l, value );
+ continue;
+ }
+
+ /* Handle start subscript */
+
+ while( sub1 > 0 && value )
+ --sub1, value = list_next( value );
+
+ /* Empty w/ :E=default? */
+
+ if( !value && colon && edits.empty.ptr )
+ evalue = value = list_new( L0, newstr( edits.empty.ptr ) );
+
+ /* For each variable value */
+
+ string_new( out1 );
+ for( ; value; value = list_next( value ) )
+ {
+ LIST *rem;
+ size_t postfix_start;
+
+ /* Handle end subscript (length actually) */
+
+ if( sub2 >= 0 && --sub2 < 0 )
+ break;
+
+ string_truncate( buf, prefix_length );
+
+ /* Apply : mods, if present */
+
+ if( colon && edits.filemods )
+ var_edit_file( value->string, out1, &edits );
+ else
+ string_append( out1, value->string );
+
+ if( colon && ( edits.upshift || edits.downshift || edits.to_slashes || edits.to_windows ) )
+ var_edit_shift( out1, &edits );
+
+ /* Handle :J=joinval */
+ /* If we have more values for this var, just */
+ /* keep appending them (with the join value) */
+ /* rather than creating separate LIST elements. */
+
+ if( colon && edits.join.ptr &&
+ ( list_next( value ) || list_next( vars ) ) )
+ {
+ string_append( out1, edits.join.ptr );
+ continue;
+ }
+
+ string_append( buf, out1->value );
+ string_free( out1 );
+ string_new( out1 );
+
+ /* If no remainder, append result to output chain. */
+
+ if( in == end )
+ {
+ l = list_new( l, newstr( buf->value ) );
+ continue;
+ }
+
+ /* For each remainder, append the complete string */
+ /* to the output chain. */
+ /* Remember the end of the variable expansion so */
+ /* we can just tack on each instance of 'remainder' */
+
+ postfix_start = buf->size;
+
+ for( rem = remainder; rem; rem = list_next( rem ) )
+ {
+ string_truncate( buf, postfix_start );
+ string_append( buf, rem->string );
+ l = list_new( l, newstr( buf->value ) );
+ }
+ }
+ string_free( out1 );
+
+ /* Toss used empty */
+
+ if( evalue )
+ list_free( evalue );
+
+ string_free( variable );
+ }
+
+ /* variables & remainder were gifts from var_expand */
+ /* and must be freed */
+
+ if( variables )
+ list_free( variables );
+ if( remainder)
+ list_free( remainder );
+
+ if( DEBUG_VAREXP )
+ {
+ printf( "expanded to " );
+ list_print( l );
+ printf( "\n" );
+ }
+
+ string_free( buf );
+ return l;
+ }
+}
+
+/*
+ * var_edit_parse() - parse : modifiers into PATHNAME structure
+ *
+ * The : modifiers in a $(varname:modifier) currently support replacing
+ * or omitting elements of a filename, and so they are parsed into a
+ * PATHNAME structure (which contains pointers into the original string).
+ *
+ * Modifiers of the form "X=value" replace the component X with
+ * the given value. Modifiers without the "=value" cause everything
+ * but the component X to be omitted. X is one of:
+ *
+ * G <grist>
+ * D directory name
+ * B base name
+ * S .suffix
+ * M (member)
+ * R root directory - prepended to whole path
+ *
+ * This routine sets:
+ *
+ * f->f_xxx.ptr = 0
+ * f->f_xxx.len = 0
+ * -> leave the original component xxx
+ *
+ * f->f_xxx.ptr = string
+ * f->f_xxx.len = strlen( string )
+ * -> replace component xxx with string
+ *
+ * f->f_xxx.ptr = ""
+ * f->f_xxx.len = 0
+ * -> omit component xxx
+ *
+ * var_edit_file() below and path_build() obligingly follow this convention.
+ */
+
+static void
+var_edit_parse(
+ char *mods,
+ VAR_EDITS *edits )
+{
+ int havezeroed = 0;
+ memset( (char *)edits, 0, sizeof( *edits ) );
+
+ while( *mods )
+ {
+ char *p;
+ PATHPART *fp;
+
+ switch( *mods++ )
+ {
+ case 'L': edits->downshift = 1; continue;
+ case 'U': edits->upshift = 1; continue;
+ case 'P': edits->parent = edits->filemods = 1; continue;
+ case 'E': fp = &edits->empty; goto strval;
+ case 'J': fp = &edits->join; goto strval;
+ case 'G': fp = &edits->f.f_grist; goto fileval;
+ case 'R': fp = &edits->f.f_root; goto fileval;
+ case 'D': fp = &edits->f.f_dir; goto fileval;
+ case 'B': fp = &edits->f.f_base; goto fileval;
+ case 'S': fp = &edits->f.f_suffix; goto fileval;
+ case 'M': fp = &edits->f.f_member; goto fileval;
+ case 'T': edits->to_slashes = 1; continue;
+ case 'W': edits->to_windows = 1; continue;
+
+ default: return; /* should complain, but so what... */
+ }
+
+ fileval:
+
+ /* Handle :CHARS, where each char (without a following =) */
+ /* selects a particular file path element. On the first such */
+ /* char, we deselect all others (by setting ptr = "", len = 0) */
+ /* and for each char we select that element (by setting ptr = 0) */
+
+ edits->filemods = 1;
+
+ if( *mods != '=' )
+ {
+ int i;
+
+ if( !havezeroed++ )
+ for( i = 0; i < 6; i++ )
+ {
+ edits->f.part[ i ].len = 0;
+ edits->f.part[ i ].ptr = "";
+ }
+
+ fp->ptr = 0;
+ continue;
+ }
+
+ strval:
+
+ /* Handle :X=value, or :X */
+
+ if( *mods != '=' )
+ {
+ fp->ptr = "";
+ fp->len = 0;
+ }
+ else if( p = strchr( mods, MAGIC_COLON ) )
+ {
+ *p = 0;
+ fp->ptr = ++mods;
+ fp->len = p - mods;
+ mods = p + 1;
+ }
+ else
+ {
+ fp->ptr = ++mods;
+ fp->len = strlen( mods );
+ mods += fp->len;
+ }
+ }
+}
+
+/*
+ * var_edit_file() - copy input target name to output, modifying filename
+ */
+
+static void
+var_edit_file(
+ char *in,
+ string *out,
+ VAR_EDITS *edits )
+{
+ PATHNAME pathname;
+
+ /* Parse apart original filename, putting parts into "pathname" */
+
+ path_parse( in, &pathname );
+
+ /* Replace any pathname with edits->f */
+
+ if( edits->f.f_grist.ptr )
+ pathname.f_grist = edits->f.f_grist;
+
+ if( edits->f.f_root.ptr )
+ pathname.f_root = edits->f.f_root;
+
+ if( edits->f.f_dir.ptr )
+ pathname.f_dir = edits->f.f_dir;
+
+ if( edits->f.f_base.ptr )
+ pathname.f_base = edits->f.f_base;
+
+ if( edits->f.f_suffix.ptr )
+ pathname.f_suffix = edits->f.f_suffix;
+
+ if( edits->f.f_member.ptr )
+ pathname.f_member = edits->f.f_member;
+
+ /* If requested, modify pathname to point to parent */
+
+ if( edits->parent )
+ path_parent( &pathname );
+
+ /* Put filename back together */
+
+ path_build( &pathname, out, 0 );
+}
+
+/*
+ * var_edit_shift() - do upshift/downshift mods
+ */
+
+static void
+var_edit_shift(
+ string *out,
+ VAR_EDITS *edits )
+{
+ /* Handle upshifting, downshifting and slash translation now */
+
+ char *p;
+ for ( p = out->value; *p; ++p)
+ {
+ if (edits->upshift)
+ {
+ *p = toupper( *p );
+ }
+ else if ( edits->downshift )
+ {
+ *p = tolower( *p );
+ }
+ if ( edits->to_slashes )
+ {
+ if ( *p == '\\')
+ *p = '/';
+ }
+# ifdef OS_CYGWIN
+ if ( edits->to_windows )
+ {
+ char result[MAX_PATH + 1];
+ cygwin_conv_to_win32_path(out->value, result);
+ assert(strlen(result) <= MAX_PATH);
+ string_free( out );
+ string_copy( out, result );
+ }
+# endif
+ }
+ out->size = p - out->value;
+}
+
+#ifndef NDEBUG
+void var_expand_unit_test()
+{
+ LOL lol[1];
+ LIST* l, *l2;
+ LIST *expected = list_new( list_new( L0, newstr( "axb" ) ), newstr( "ayb" ) );
+ LIST *e2;
+ char axyb[] = "a$(xy)b";
+ char azb[] = "a$($(z))b";
+ char path[] = "$(p:W)";
+
+ lol_init(lol);
+ var_set("xy", list_new( list_new( L0, newstr( "x" ) ), newstr( "y" ) ), VAR_SET );
+ var_set("z", list_new( L0, newstr( "xy" ) ), VAR_SET );
+ var_set("p", list_new( L0, newstr( "/cygdrive/c/foo/bar" ) ), VAR_SET );
+
+ l = var_expand( 0, axyb, axyb + sizeof(axyb) - 1, lol, 0 );
+ for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next(l2), e2 = list_next(e2) )
+ assert( !strcmp( e2->string, l2->string ) );
+ assert(l2 == 0 && e2 == 0);
+ list_free(l);
+
+ l = var_expand( 0, azb, azb + sizeof(azb) - 1, lol, 0 );
+ for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next(l2), e2 = list_next(e2) )
+ assert( !strcmp( e2->string, l2->string ) );
+ assert(l2 == 0 && e2 == 0);
+ list_free(l);
+
+ l = var_expand( 0, path, path + sizeof(path) - 1, lol, 0 );
+ assert(l != 0);
+ assert(list_next(l) == 0);
+# ifdef OS_CYGWIN
+ assert( !strcmp( l->string, "c:\\foo\\bar" ) );
+# else
+ assert( !strcmp( l->string, "/cygdrive/c/foo/bar" ) );
+# endif
+ list_free(l);
+
+ list_free(expected);
+
+ lol_free(lol);
+}
+#endif
Added: boost-jam/boost-build/branches/upstream/current/jam_src/expand.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/expand.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/expand.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,14 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * expand.h - expand a buffer, given variable values
+ */
+
+#include "lists.h"
+
+LIST *var_expand( LIST *l, char *in, char *end, LOL *lol, int cancopyin );
+void var_expand_unit_test();
Added: boost-jam/boost-build/branches/upstream/current/jam_src/filemac.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/filemac.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/filemac.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,173 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "filesys.h"
+# include "pathsys.h"
+
+# ifdef OS_MAC
+
+#include <Files.h>
+#include <Folders.h>
+
+# include <:sys:stat.h>
+
+/*
+ * filemac.c - manipulate file names and scan directories on macintosh
+ *
+ * External routines:
+ *
+ * file_dirscan() - scan a directory for files
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ * file_archscan() - scan an archive for files
+ *
+ * File_dirscan() and file_archscan() call back a caller provided function
+ * for each file found. A flag to this callback function lets file_dirscan()
+ * and file_archscan() indicate that a timestamp is being provided with the
+ * file. If file_dirscan() or file_archscan() do not provide the file's
+ * timestamp, interested parties may later call file_time().
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 12/19/94 (mikem) - solaris string table insanity support
+ * 02/14/95 (seiwald) - parse and build /xxx properly
+ * 05/03/96 (seiwald) - split into pathunix.c
+ * 11/21/96 (peterk) - BEOS does not have Unix-style archives
+ */
+
+void CopyC2PStr(const char * cstr, StringPtr pstr)
+{
+ int len;
+
+ for (len = 0; *cstr && len<255; pstr[++len] = *cstr++)
+ ;
+
+ pstr[0] = len;
+}
+
+/*
+ * file_dirscan() - scan a directory for files
+ */
+
+void
+file_dirscan(
+ char *dir,
+ scanback func,
+ void *closure )
+{
+ PATHNAME f;
+ string filename[1];
+ unsigned char fullPath[ 512 ];
+
+ FSSpec spec;
+ WDPBRec vol;
+ Str63 volName;
+ CInfoPBRec lastInfo;
+ int index = 1;
+
+ /* First enter directory itself */
+
+ memset( (char *)&f, '\0', sizeof( f ) );
+
+ f.f_dir.ptr = dir;
+ f.f_dir.len = strlen(dir);
+
+ if( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", dir );
+
+ /* Special case ":" - enter it */
+
+ if( f.f_dir.len == 1 && f.f_dir.ptr[0] == ':' )
+ (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
+
+ /* Now enter contents of directory */
+
+ vol.ioNamePtr = volName;
+
+ if( PBHGetVolSync( &vol ) )
+ return;
+
+ CopyC2PStr( dir, fullPath );
+
+ if( FSMakeFSSpec( vol.ioWDVRefNum, vol.ioWDDirID, fullPath, &spec ) )
+ return;
+
+ lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
+ lastInfo.dirInfo.ioDrDirID = spec.parID;
+ lastInfo.dirInfo.ioNamePtr = spec.name;
+ lastInfo.dirInfo.ioFDirIndex = 0;
+ lastInfo.dirInfo.ioACUser = 0;
+
+ if( PBGetCatInfoSync(&lastInfo) )
+ return;
+
+ if (!(lastInfo.dirInfo.ioFlAttrib & 0x10))
+ return;
+
+ // ioDrDirID must be reset each time.
+
+ spec.parID = lastInfo.dirInfo.ioDrDirID;
+
+ string_new( filename );
+ for( ;; )
+ {
+ lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
+ lastInfo.dirInfo.ioDrDirID = spec.parID;
+ lastInfo.dirInfo.ioNamePtr = fullPath;
+ lastInfo.dirInfo.ioFDirIndex = index++;
+
+ if( PBGetCatInfoSync(&lastInfo) )
+ return;
+
+ f.f_base.ptr = (char *)fullPath + 1;
+ f.f_base.len = *fullPath;
+
+ string_truncate( filename, 0 );
+ path_build( &f, filename, 0 );
+ (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
+ }
+ string_free( filename );
+}
+
+/*
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ */
+
+int
+file_time(
+ char *filename,
+ time_t *time )
+{
+ struct stat statbuf;
+
+ if( stat( filename, &statbuf ) < 0 )
+ return -1;
+
+ *time = statbuf.st_mtime;
+
+ return 0;
+}
+
+/*
+ * file_archscan() - scan an archive for files
+ */
+
+void
+file_archscan(
+ char *archive,
+ scanback func,
+ void *closure )
+{
+}
+
+
+# endif /* macintosh */
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/filent.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/filent.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/filent.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,287 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "filesys.h"
+# include "pathsys.h"
+# include "strings.h"
+
+# ifdef OS_NT
+
+# ifdef __BORLANDC__
+# if __BORLANDC__ < 0x550
+# include <dir.h>
+# include <dos.h>
+# endif
+# undef FILENAME /* cpp namespace collision */
+# define _finddata_t ffblk
+# endif
+
+# include <io.h>
+# include <sys/stat.h>
+# include <ctype.h>
+
+/*
+ * filent.c - scan directories and archives on NT
+ *
+ * External routines:
+ *
+ * file_dirscan() - scan a directory for files
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ * file_archscan() - scan an archive for files
+ *
+ * File_dirscan() and file_archscan() call back a caller provided function
+ * for each file found. A flag to this callback function lets file_dirscan()
+ * and file_archscan() indicate that a timestamp is being provided with the
+ * file. If file_dirscan() or file_archscan() do not provide the file's
+ * timestamp, interested parties may later call file_time().
+ *
+ * 07/10/95 (taylor) Findfirst() returns the first file on NT.
+ * 05/03/96 (seiwald) split apart into pathnt.c
+ */
+
+/*
+ * file_dirscan() - scan a directory for files
+ */
+
+void
+file_dirscan(
+ char *dir,
+ scanback func,
+ void *closure )
+{
+ PATHNAME f;
+ string filespec[1];
+ string filename[1];
+ long handle;
+ int ret;
+ struct _finddata_t finfo[1];
+
+ dir = short_path_to_long_path( dir );
+
+ /* First enter directory itself */
+
+ memset( (char *)&f, '\0', sizeof( f ) );
+
+ f.f_dir.ptr = dir;
+ f.f_dir.len = strlen(dir);
+
+ dir = *dir ? dir : ".";
+
+ /* Special case \ or d:\ : enter it */
+
+ if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
+ (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
+ else if( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
+ (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
+
+ /* Now enter contents of directory */
+
+ string_copy( filespec, dir );
+ string_append( filespec, "/*" );
+
+ if( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", dir );
+
+# if defined(__BORLANDC__) && __BORLANDC__ < 0x550
+ if ( ret = findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) )
+ {
+ string_free( filespec );
+ return;
+ }
+
+ string_new( filename );
+ while( !ret )
+ {
+ time_t time_write = finfo->ff_fdate;
+
+ time_write = (time_write << 16) | finfo->ff_ftime;
+ f.f_base.ptr = finfo->ff_name;
+ f.f_base.len = strlen( finfo->ff_name );
+
+ string_truncate( filename, 0 );
+ path_build( &f, filename );
+
+ (*func)( closure, filename->value, 1 /* stat()'ed */, time_write );
+
+ ret = findnext( finfo );
+ }
+# else
+ handle = _findfirst( filespec->value, finfo );
+
+ if( ret = ( handle < 0L ) )
+ {
+ string_free( filespec );
+ return;
+ }
+
+ string_new( filename );
+ while( !ret )
+ {
+ f.f_base.ptr = finfo->name;
+ f.f_base.len = strlen( finfo->name );
+
+ string_truncate( filename, 0 );
+ path_build( &f, filename, 0 );
+
+ (*func)( closure, filename->value, 1 /* stat()'ed */, finfo->time_write );
+
+ ret = _findnext( handle, finfo );
+ }
+
+ _findclose( handle );
+# endif
+ string_free( filename );
+ string_free( filespec );
+}
+
+/*
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ */
+
+int
+file_time(
+ char *filename,
+ time_t *time )
+{
+ /* On NT this is called only for C:/ */
+
+ struct stat statbuf;
+
+ if( stat( filename, &statbuf ) < 0 )
+ return -1;
+
+ *time = statbuf.st_mtime;
+
+ return 0;
+}
+
+/*
+ * file_archscan() - scan an archive for files
+ */
+
+/* Straight from SunOS */
+
+#define ARMAG "!<arch>\n"
+#define SARMAG 8
+
+#define ARFMAG "`\n"
+
+struct ar_hdr {
+ char ar_name[16];
+ char ar_date[12];
+ char ar_uid[6];
+ char ar_gid[6];
+ char ar_mode[8];
+ char ar_size[10];
+ char ar_fmag[2];
+};
+
+# define SARFMAG 2
+# define SARHDR sizeof( struct ar_hdr )
+
+void
+file_archscan(
+ char *archive,
+ scanback func,
+ void *closure )
+{
+ struct ar_hdr ar_hdr;
+ char *string_table = 0;
+ char buf[ MAXJPATH ];
+ long offset;
+ int fd;
+
+ if( ( fd = open( archive, O_RDONLY | O_BINARY, 0 ) ) < 0 )
+ return;
+
+ if( read( fd, buf, SARMAG ) != SARMAG ||
+ strncmp( ARMAG, buf, SARMAG ) )
+ {
+ close( fd );
+ return;
+ }
+
+ offset = SARMAG;
+
+ if( DEBUG_BINDSCAN )
+ printf( "scan archive %s\n", archive );
+
+ while( read( fd, &ar_hdr, SARHDR ) == SARHDR &&
+ !memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG ) )
+ {
+ long lar_date;
+ long lar_size;
+ char *name = 0;
+ char *endname;
+ char *c;
+
+ sscanf( ar_hdr.ar_date, "%ld", &lar_date );
+ sscanf( ar_hdr.ar_size, "%ld", &lar_size );
+
+ lar_size = ( lar_size + 1 ) & ~1;
+
+ if (ar_hdr.ar_name[0] == '/' && ar_hdr.ar_name[1] == '/' )
+ {
+ /* this is the "string table" entry of the symbol table,
+ ** which holds strings of filenames that are longer than
+ ** 15 characters (ie. don't fit into a ar_name
+ */
+
+ string_table = malloc(lar_size);
+ if (read(fd, string_table, lar_size) != lar_size)
+ printf("error reading string table\n");
+ offset += SARHDR + lar_size;
+ continue;
+ }
+ else if (ar_hdr.ar_name[0] == '/' && ar_hdr.ar_name[1] != ' ')
+ {
+ /* Long filenames are recognized by "/nnnn" where nnnn is
+ ** the offset of the string in the string table represented
+ ** in ASCII decimals.
+ */
+
+ name = string_table + atoi( ar_hdr.ar_name + 1 );
+ endname = name + strlen( name );
+ }
+ else
+ {
+ /* normal name */
+ name = ar_hdr.ar_name;
+ endname = name + sizeof( ar_hdr.ar_name );
+ }
+
+ /* strip trailing white-space, slashes, and backslashes */
+
+ while( endname-- > name )
+ if( !isspace(*endname) && *endname != '\\' && *endname != '/' )
+ break;
+ *++endname = 0;
+
+ /* strip leading directory names, an NT specialty */
+
+ if( c = strrchr( name, '/' ) )
+ name = c + 1;
+ if( c = strrchr( name, '\\' ) )
+ name = c + 1;
+
+ sprintf( buf, "%s(%.*s)", archive, endname - name, name );
+ (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+
+ offset += SARHDR + lar_size;
+ lseek( fd, offset, 0 );
+ }
+
+ close( fd );
+}
+
+# endif /* NT */
Added: boost-jam/boost-build/branches/upstream/current/jam_src/fileos2.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/fileos2.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/fileos2.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,139 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "filesys.h"
+# include "pathsys.h"
+
+/* note that we use "fileunix.c" when compiling with EMX on OS/2 */
+# if defined(OS_OS2) && !defined(__EMX__)
+
+# include <io.h>
+# include <dos.h>
+
+/*
+ * fileos2.c - scan directories and archives on NT
+ *
+ * External routines:
+ *
+ * file_dirscan() - scan a directory for files
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ * file_archscan() - scan an archive for files
+ *
+ * File_dirscan() and file_archscan() call back a caller provided function
+ * for each file found. A flag to this callback function lets file_dirscan()
+ * and file_archscan() indicate that a timestamp is being provided with the
+ * file. If file_dirscan() or file_archscan() do not provide the file's
+ * timestamp, interested parties may later call file_time().
+ *
+ * 07/10/95 (taylor) Findfirst() returns the first file on NT.
+ * 05/03/96 (seiwald) split apart into pathnt.c
+ * 09/22/00 (seiwald) handle \ and c:\ specially: don't add extra /
+ */
+
+/*
+ * file_dirscan() - scan a directory for files
+ */
+
+void
+file_dirscan(
+ char *dir,
+ scanback func,
+ void *closure )
+{
+ PATHNAME f;
+ string filespec[1];
+ long handle;
+ int ret;
+ struct _find_t finfo[1];
+
+ /* First enter directory itself */
+
+ memset( (char *)&f, '\0', sizeof( f ) );
+
+ f.f_dir.ptr = dir;
+ f.f_dir.len = strlen(dir);
+
+ dir = *dir ? dir : ".";
+
+ /* Special case \ or d:\ : enter it */
+ string_copy( filespec, dir );
+
+ if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
+ (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
+ else if( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
+ (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
+ else
+ string_push_back( filespec, '/' );
+
+ string_push_back( filespec, '*' );
+
+ /* Now enter contents of directory */
+
+ if( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", filespec->value );
+
+ /* Time info in dos find_t is not very useful. It consists */
+ /* of a separate date and time, and putting them together is */
+ /* not easy. So we leave that to a later stat() call. */
+
+ if( !_dos_findfirst( filespec->value, _A_NORMAL|_A_RDONLY|_A_SUBDIR, finfo ) )
+ {
+ string filename[1];
+ string_new( filename );
+ do
+ {
+
+ f.f_base.ptr = finfo->name;
+ f.f_base.len = strlen( finfo->name );
+
+ string_truncate( filename, 0 );
+ path_build( &f, filename, 0 );
+ (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
+ }
+ while( !_dos_findnext( finfo ) );
+ string_free( filename );
+ }
+}
+
+/*
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ */
+
+int
+file_time(
+ char *filename,
+ time_t *time )
+{
+ /* This is called on OS2, not NT. */
+ /* NT fills in the time in the dirscan. */
+
+ struct stat statbuf;
+
+ if( stat( filename, &statbuf ) < 0 )
+ return -1;
+
+ *time = statbuf.st_mtime;
+
+ return 0;
+}
+
+void
+file_archscan(
+ char *archive,
+ scanback func,
+ void *closure )
+{
+}
+
+# endif /* OS2 && !__EMX__ */
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/filesys.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/filesys.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/filesys.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,33 @@
+# include "jam.h"
+# include "pathsys.h"
+# include "strings.h"
+
+void
+file_build1(
+ PATHNAME *f,
+ string* file)
+{
+ if( DEBUG_SEARCH )
+ {
+ printf("build file: ");
+ if( f->f_root.len )
+ printf( "root = '%.*s' ", f->f_root.len, f->f_root.ptr );
+ if( f->f_dir.len )
+ printf( "dir = '%.*s' ", f->f_dir.len, f->f_dir.ptr );
+ if( f->f_base.len )
+ printf( "base = '%.*s' ", f->f_base.len, f->f_base.ptr );
+ }
+
+ /* Start with the grist. If the current grist isn't */
+ /* surrounded by <>'s, add them. */
+
+ if( f->f_grist.len )
+ {
+ if( f->f_grist.ptr[0] != '<' )
+ string_push_back( file, '<' );
+ string_append_range(
+ file, f->f_grist.ptr, f->f_grist.ptr + f->f_grist.len );
+ if( file->value[file->size - 1] != '>' )
+ string_push_back( file, '>' );
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/filesys.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/filesys.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/filesys.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * filesys.h - OS specific file routines
+ */
+
+#ifndef FILESYS_DWA20011025_H
+# define FILESYS_DWA20011025_H
+
+# include "pathsys.h"
+
+typedef void (*scanback)( void *closure, char *file, int found, time_t t );
+
+void file_dirscan( char *dir, scanback func, void *closure );
+void file_archscan( char *arch, scanback func, void *closure );
+
+int file_time( char *filename, time_t *time );
+
+void file_build1(PATHNAME *f, string* file) ;
+
+#endif
Added: boost-jam/boost-build/branches/upstream/current/jam_src/fileunix.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/fileunix.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/fileunix.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,441 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "filesys.h"
+# include "strings.h"
+# include "pathsys.h"
+# include <stdio.h>
+
+#if defined(sun) || defined(__sun)
+# include <unistd.h> /* needed for read and close prototype */
+#endif
+
+# ifdef USE_FILEUNIX
+
+#if defined(sun) || defined(__sun)
+# include <unistd.h> /* needed for read and close prototype */
+#endif
+
+# if defined( OS_SEQUENT ) || \
+ defined( OS_DGUX ) || \
+ defined( OS_SCO ) || \
+ defined( OS_ISC )
+# define PORTAR 1
+# endif
+
+# ifdef __EMX__
+# include <sys/types.h>
+# include <sys/stat.h>
+# endif
+
+# if defined( OS_RHAPSODY ) || \
+ defined( OS_MACOSX ) || \
+ defined( OS_NEXT )
+/* need unistd for rhapsody's proper lseek */
+# include <sys/dir.h>
+# include <unistd.h>
+# define STRUCT_DIRENT struct direct
+# else
+# include <dirent.h>
+# define STRUCT_DIRENT struct dirent
+# endif
+
+# ifdef OS_COHERENT
+# include <arcoff.h>
+# define HAVE_AR
+# endif
+
+# if defined( OS_MVS ) || \
+ defined( OS_INTERIX )
+
+#define ARMAG "!<arch>\n"
+#define SARMAG 8
+#define ARFMAG "`\n"
+
+struct ar_hdr /* archive file member header - printable ascii */
+{
+ char ar_name[16]; /* file member name - `/' terminated */
+ char ar_date[12]; /* file member date - decimal */
+ char ar_uid[6]; /* file member user id - decimal */
+ char ar_gid[6]; /* file member group id - decimal */
+ char ar_mode[8]; /* file member mode - octal */
+ char ar_size[10]; /* file member size - decimal */
+ char ar_fmag[2]; /* ARFMAG - string to end header */
+};
+
+# define HAVE_AR
+# endif
+
+# if defined( OS_QNX ) || \
+ defined( OS_BEOS ) || \
+ defined( OS_MPEIX )
+# define NO_AR
+# define HAVE_AR
+# endif
+
+# ifndef HAVE_AR
+
+# ifdef OS_AIX
+/* Define those for AIX to get the definitions for both the small and the
+ * big variant of the archive file format. */
+# define __AR_SMALL__
+# define __AR_BIG__
+# endif
+
+# include <ar.h>
+# endif
+
+/*
+ * fileunix.c - manipulate file names and scan directories on UNIX/AmigaOS
+ *
+ * External routines:
+ *
+ * file_dirscan() - scan a directory for files
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ * file_archscan() - scan an archive for files
+ *
+ * File_dirscan() and file_archscan() call back a caller provided function
+ * for each file found. A flag to this callback function lets file_dirscan()
+ * and file_archscan() indicate that a timestamp is being provided with the
+ * file. If file_dirscan() or file_archscan() do not provide the file's
+ * timestamp, interested parties may later call file_time().
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 12/19/94 (mikem) - solaris string table insanity support
+ * 02/14/95 (seiwald) - parse and build /xxx properly
+ * 05/03/96 (seiwald) - split into pathunix.c
+ * 11/21/96 (peterk) - BEOS does not have Unix-style archives
+ */
+
+/*
+ * file_dirscan() - scan a directory for files
+ */
+
+void
+file_dirscan(
+ char *dir,
+ scanback func,
+ void *closure )
+{
+ PATHNAME f;
+ DIR *d;
+ STRUCT_DIRENT *dirent;
+ string filename[1];
+
+ /* First enter directory itself */
+
+ memset( (char *)&f, '\0', sizeof( f ) );
+
+ f.f_dir.ptr = dir;
+ f.f_dir.len = strlen(dir);
+
+ dir = *dir ? dir : ".";
+
+ /* Special case / : enter it */
+
+ if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '/' )
+ (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
+
+ /* Now enter contents of directory */
+
+ if( !( d = opendir( dir ) ) )
+ return;
+
+ if( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", dir );
+
+ string_new( filename );
+ while( dirent = readdir( d ) )
+ {
+# ifdef old_sinix
+ /* Broken structure definition on sinix. */
+ f.f_base.ptr = dirent->d_name - 2;
+# else
+ f.f_base.ptr = dirent->d_name;
+# endif
+ f.f_base.len = strlen( f.f_base.ptr );
+
+ string_truncate( filename, 0 );
+ path_build( &f, filename, 0 );
+
+ (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
+ }
+ string_free( filename );
+
+ closedir( d );
+}
+
+/*
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ */
+
+int
+file_time(
+ char *filename,
+ time_t *time )
+{
+ struct stat statbuf;
+
+ if( stat( filename, &statbuf ) < 0 )
+ return -1;
+
+ /* Technically, existing files can have 0 as statbuf.st_mtime
+ --- in particular, the /cygdrive directory under cygwin. However,
+ though all the code jam assumes that timestamp of 0 means
+ "does not exist" and will try to create the "missing" target, causing
+ problems. Work around this problem by chanding 0 to 1.
+ */
+ *time = statbuf.st_mtime ? statbuf.st_mtime : 1 ;
+ return 0;
+}
+
+/*
+ * file_archscan() - scan an archive for files
+ */
+
+# ifndef AIAMAG /* God-fearing UNIX */
+
+# define SARFMAG 2
+# define SARHDR sizeof( struct ar_hdr )
+
+void
+file_archscan(
+ char *archive,
+ scanback func,
+ void *closure )
+{
+# ifndef NO_AR
+ struct ar_hdr ar_hdr;
+ char buf[ MAXJPATH ];
+ long offset;
+ char *string_table = 0;
+ int fd;
+
+ if( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
+ return;
+
+ if( read( fd, buf, SARMAG ) != SARMAG ||
+ strncmp( ARMAG, buf, SARMAG ) )
+ {
+ close( fd );
+ return;
+ }
+
+ offset = SARMAG;
+
+ if( DEBUG_BINDSCAN )
+ printf( "scan archive %s\n", archive );
+
+ while( read( fd, &ar_hdr, SARHDR ) == SARHDR
+ && ! ( memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG )
+#ifdef ARFZMAG
+ /* OSF also has a compressed format */
+ && memcmp( ar_hdr.ar_fmag, ARFZMAG, SARFMAG )
+#endif
+ ) )
+ {
+ char lar_name_[257];
+ char* lar_name = lar_name_ + 1;
+ long lar_date;
+ long lar_size;
+ long lar_offset;
+ char *c;
+ char *src, *dest;
+
+ strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) );
+
+ sscanf( ar_hdr.ar_date, "%ld", &lar_date );
+ sscanf( ar_hdr.ar_size, "%ld", &lar_size );
+
+ if (ar_hdr.ar_name[0] == '/')
+ {
+ if (ar_hdr.ar_name[1] == '/')
+ {
+ /* this is the "string table" entry of the symbol table,
+ ** which holds strings of filenames that are longer than
+ ** 15 characters (ie. don't fit into a ar_name
+ */
+
+ string_table = (char *)malloc(lar_size);
+ lseek(fd, offset + SARHDR, 0);
+ if (read(fd, string_table, lar_size) != lar_size)
+ printf("error reading string table\n");
+ }
+ else if (string_table && ar_hdr.ar_name[1] != ' ')
+ {
+ /* Long filenames are recognized by "/nnnn" where nnnn is
+ ** the offset of the string in the string table represented
+ ** in ASCII decimals.
+ */
+ dest = lar_name;
+ lar_offset = atoi(lar_name + 1);
+ src = &string_table[lar_offset];
+ while (*src != '/')
+ *dest++ = *src++;
+ *dest = '/';
+ }
+ }
+
+ c = lar_name - 1;
+ while( *++c != ' ' && *c != '/' )
+ ;
+ *c = '\0';
+
+ if ( DEBUG_BINDSCAN )
+ printf( "archive name %s found\n", lar_name );
+
+ sprintf( buf, "%s(%s)", archive, lar_name );
+
+ (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+
+ offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
+ lseek( fd, offset, 0 );
+ }
+
+ if (string_table)
+ free(string_table);
+
+ close( fd );
+
+# endif /* NO_AR */
+
+}
+
+# else /* AIAMAG - RS6000 AIX */
+
+static void file_archscan_small(
+ int fd, char const *archive, scanback func, void *closure)
+{
+ struct fl_hdr fl_hdr;
+
+ struct {
+ struct ar_hdr hdr;
+ char pad[ 256 ];
+ } ar_hdr ;
+
+ char buf[ MAXJPATH ];
+ long offset;
+
+ if( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ)
+ return;
+
+ sscanf( fl_hdr.fl_fstmoff, "%ld", &offset );
+
+ if( DEBUG_BINDSCAN )
+ printf( "scan archive %s\n", archive );
+
+ while( offset > 0
+ && lseek( fd, offset, 0 ) >= 0
+ && read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) )
+ {
+ long lar_date;
+ int lar_namlen;
+
+ sscanf( ar_hdr.hdr.ar_namlen, "%d", &lar_namlen );
+ sscanf( ar_hdr.hdr.ar_date, "%ld", &lar_date );
+ sscanf( ar_hdr.hdr.ar_nxtmem, "%ld", &offset );
+
+ if( !lar_namlen )
+ continue;
+
+ ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
+
+ sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
+
+ (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+ }
+}
+
+/* Check for OS version which supports the big variant. */
+#ifdef AR_HSZ_BIG
+
+static void file_archscan_big(
+ int fd, char const *archive, scanback func, void *closure)
+{
+ struct fl_hdr_big fl_hdr;
+
+ struct {
+ struct ar_hdr_big hdr;
+ char pad[ 256 ];
+ } ar_hdr ;
+
+ char buf[ MAXJPATH ];
+ long long offset;
+
+ if( read( fd, (char *)&fl_hdr, FL_HSZ_BIG) != FL_HSZ_BIG)
+ return;
+
+ sscanf( fl_hdr.fl_fstmoff, "%lld", &offset );
+
+ if( DEBUG_BINDSCAN )
+ printf( "scan archive %s\n", archive );
+
+ while( offset > 0
+ && lseek( fd, offset, 0 ) >= 0
+ && read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) )
+ {
+ long lar_date;
+ int lar_namlen;
+
+ sscanf( ar_hdr.hdr.ar_namlen, "%d", &lar_namlen );
+ sscanf( ar_hdr.hdr.ar_date, "%ld", &lar_date );
+ sscanf( ar_hdr.hdr.ar_nxtmem, "%lld", &offset );
+
+ if( !lar_namlen )
+ continue;
+
+ ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
+
+ sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
+
+ (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+ }
+
+}
+
+#endif /* AR_HSZ_BIG */
+
+void file_archscan(char *archive, scanback func, void *closure)
+{
+ int fd;
+ char fl_magic[SAIAMAG];
+
+ if(( fd = open(archive, O_RDONLY, 0)) < 0)
+ return;
+
+ if(read( fd, fl_magic, SAIAMAG) != SAIAMAG
+ || lseek(fd, 0, SEEK_SET) == -1)
+ {
+ close(fd);
+ return;
+ }
+
+ if (strncmp(AIAMAG, fl_magic, SAIAMAG) == 0)
+ {
+ /* read small variant */
+ file_archscan_small(fd, archive, func, closure);
+ }
+#ifdef AR_HSZ_BIG
+ else if (strncmp(AIAMAGBIG, fl_magic, SAIAMAG) == 0)
+ {
+ /* read big variant */
+ file_archscan_big(fd, archive, func, closure);
+ }
+#endif
+
+ close( fd );
+}
+
+# endif /* AIAMAG - RS6000 AIX */
+
+# endif /* USE_FILEUNIX */
Added: boost-jam/boost-build/branches/upstream/current/jam_src/filevms.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/filevms.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/filevms.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,331 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "filesys.h"
+# include "pathsys.h"
+
+# ifdef OS_VMS
+
+/*
+ * filevms.c - scan directories and libaries on VMS
+ *
+ * External routines:
+ *
+ * file_dirscan() - scan a directory for files
+ * file_time() - get timestamp of file, if not done by file_dirscan()
+ * file_archscan() - scan an archive for files
+ *
+ * File_dirscan() and file_archscan() call back a caller provided function
+ * for each file found. A flag to this callback function lets file_dirscan()
+ * and file_archscan() indicate that a timestamp is being provided with the
+ * file. If file_dirscan() or file_archscan() do not provide the file's
+ * timestamp, interested parties may later call file_time().
+ *
+ * 02/09/95 (seiwald) - bungled R=[xxx] - was using directory length!
+ * 05/03/96 (seiwald) - split into pathvms.c
+ */
+
+# include <rms.h>
+# include <iodef.h>
+# include <ssdef.h>
+# include <string.h>
+# include <stdlib.h>
+# include <stdio.h>
+# include <descrip.h>
+
+#include <lbrdef.h>
+#include <credef.h>
+#include <mhddef.h>
+#include <lhidef.h>
+#include <lib$routines.h>
+#include <starlet.h>
+
+/* Supply missing prototypes for lbr$-routines*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int lbr$set_module(
+ void **,
+ unsigned long *,
+ struct dsc$descriptor_s *,
+ unsigned short *,
+ void * );
+
+int lbr$open( void **,
+ struct dsc$descriptor_s *,
+ void *,
+ void *,
+ void *,
+ void *,
+ void * );
+
+int lbr$ini_control(
+ void **,
+ unsigned long *,
+ unsigned long *,
+ void * );
+
+int lbr$get_index(
+ void **,
+ unsigned long *,
+ int (*func)( struct dsc$descriptor_s *, unsigned long *),
+ void * );
+
+int lbr$close(
+ void ** );
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+static void
+file_cvttime(
+ unsigned int *curtime,
+ time_t *unixtime )
+{
+ static const size_t divisor = 10000000;
+ static unsigned int bastim[2] = { 0x4BEB4000, 0x007C9567 }; /* 1/1/1970 */
+ int delta[2], remainder;
+
+ lib$subx( curtime, bastim, delta );
+ lib$ediv( &divisor, delta, unixtime, &remainder );
+}
+
+# define DEFAULT_FILE_SPECIFICATION "[]*.*;0"
+
+# define min( a,b ) ((a)<(b)?(a):(b))
+
+void
+file_dirscan(
+ char *dir,
+ scanback func,
+ void *closure )
+{
+
+ struct FAB xfab;
+ struct NAM xnam;
+ struct XABDAT xab;
+ char esa[256];
+ char filename[256];
+ string filename2[1];
+ char dirname[256];
+ register int status;
+ PATHNAME f;
+
+ memset( (char *)&f, '\0', sizeof( f ) );
+
+ f.f_root.ptr = dir;
+ f.f_root.len = strlen( dir );
+
+ /* get the input file specification
+ */
+ xnam = cc$rms_nam;
+ xnam.nam$l_esa = esa;
+ xnam.nam$b_ess = sizeof( esa ) - 1;
+ xnam.nam$l_rsa = filename;
+ xnam.nam$b_rss = min( sizeof( filename ) - 1, NAM$C_MAXRSS );
+
+ xab = cc$rms_xabdat; /* initialize extended attributes */
+ xab.xab$b_cod = XAB$C_DAT; /* ask for date */
+ xab.xab$l_nxt = NULL; /* terminate XAB chain */
+
+ xfab = cc$rms_fab;
+ xfab.fab$l_dna = DEFAULT_FILE_SPECIFICATION;
+ xfab.fab$b_dns = sizeof( DEFAULT_FILE_SPECIFICATION ) - 1;
+ xfab.fab$l_fop = FAB$M_NAM;
+ xfab.fab$l_fna = dir; /* address of file name */
+ xfab.fab$b_fns = strlen( dir ); /* length of file name */
+ xfab.fab$l_nam = &xnam; /* address of NAB block */
+ xfab.fab$l_xab = (char *)&xab; /* address of XAB block */
+
+
+ status = sys$parse( &xfab );
+
+ if( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", dir );
+
+ if ( !( status & 1 ) )
+ return;
+
+
+
+ /* Add bogus directory for [000000] */
+
+ if( !strcmp( dir, "[000000]" ) )
+ {
+ (*func)( closure, "[000000]", 1 /* time valid */, 1 /* old but true */ );
+ }
+
+ /* Add bogus directory for [] */
+
+ if( !strcmp( dir, "[]" ) )
+ {
+ (*func)( closure, "[]", 1 /* time valid */, 1 /* old but true */ );
+ (*func)( closure, "[-]", 1 /* time valid */, 1 /* old but true */ );
+ }
+
+ string_new( filename2 );
+ while ( (status = sys$search( &xfab )) & 1 )
+ {
+ char *s;
+ time_t time;
+
+ /* "I think that might work" - eml */
+
+ sys$open( &xfab );
+ sys$close( &xfab );
+
+ file_cvttime( (unsigned int *)&xab.xab$q_rdt, &time );
+
+ filename[xnam.nam$b_rsl] = '\0';
+
+ /* What we do with the name depends on the suffix: */
+ /* .dir is a directory */
+ /* .xxx is a file with a suffix */
+ /* . is no suffix at all */
+
+ if( xnam.nam$b_type == 4 && !strncmp( xnam.nam$l_type, ".DIR", 4 ) )
+ {
+ /* directory */
+ sprintf( dirname, "[.%.*s]", xnam.nam$b_name, xnam.nam$l_name );
+ f.f_dir.ptr = dirname;
+ f.f_dir.len = strlen( dirname );
+ f.f_base.ptr = 0;
+ f.f_base.len = 0;
+ f.f_suffix.ptr = 0;
+ f.f_suffix.len = 0;
+ }
+ else
+ {
+ /* normal file with a suffix */
+ f.f_dir.ptr = 0;
+ f.f_dir.len = 0;
+ f.f_base.ptr = xnam.nam$l_name;
+ f.f_base.len = xnam.nam$b_name;
+ f.f_suffix.ptr = xnam.nam$l_type;
+ f.f_suffix.len = xnam.nam$b_type;
+ }
+
+ string_truncate( filename2, 0 );
+ path_build( &f, filename2, 0 );
+
+ /*
+ if( DEBUG_SEARCH )
+ printf("root '%s' base %.*s suf %.*s = %s\n",
+ dir,
+ xnam.nam$b_name, xnam.nam$l_name,
+ xnam.nam$b_type, xnam.nam$l_type,
+ filename2);
+ */
+
+ (*func)( closure, filename2->value, 1 /* time valid */, time );
+ }
+ string_free( filename2 );
+}
+
+int
+file_time(
+ char *filename,
+ time_t *time )
+{
+ /* This should never be called, as all files are */
+ /* timestampped in file_dirscan() and file_archscan() */
+ return -1;
+}
+
+static char *VMS_archive = 0;
+static scanback VMS_func;
+static void *VMS_closure;
+static void *context;
+
+static int
+file_archmember(
+ struct dsc$descriptor_s *module,
+ unsigned long *rfa )
+{
+ static struct dsc$descriptor_s bufdsc =
+ {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
+
+ struct mhddef *mhd;
+ char filename[128];
+ char buf[ MAXJPATH ];
+
+ int status;
+ time_t library_date;
+
+ register int i;
+ register char *p;
+
+ bufdsc.dsc$a_pointer = filename;
+ bufdsc.dsc$w_length = sizeof( filename );
+ status = lbr$set_module( &context, rfa, &bufdsc,
+ &bufdsc.dsc$w_length, NULL );
+
+ if ( !(status & 1) )
+ return ( 1 );
+
+ mhd = (struct mhddef *)filename;
+
+ file_cvttime( &mhd->mhd$l_datim, &library_date );
+
+ for ( i = 0, p = module->dsc$a_pointer; i < module->dsc$w_length; i++, p++ )
+ filename[i] = *p;
+
+ filename[i] = '\0';
+
+ sprintf( buf, "%s(%s.obj)", VMS_archive, filename );
+
+ (*VMS_func)( VMS_closure, buf, 1 /* time valid */, (time_t)library_date );
+
+ return ( 1 );
+}
+
+void
+file_archscan(
+ char *archive,
+ scanback func,
+ void *closure )
+{
+ static struct dsc$descriptor_s library =
+ {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
+
+ unsigned long lfunc = LBR$C_READ;
+ unsigned long typ = LBR$C_TYP_UNK;
+ unsigned long index = 1;
+
+ register int status;
+
+ VMS_archive = archive;
+ VMS_func = func;
+ VMS_closure = closure;
+
+ status = lbr$ini_control( &context, &lfunc, &typ, NULL );
+ if ( !( status & 1 ) )
+ return;
+
+ library.dsc$a_pointer = archive;
+ library.dsc$w_length = strlen( archive );
+
+ status = lbr$open( &context, &library, NULL, NULL, NULL, NULL, NULL );
+ if ( !( status & 1 ) )
+ return;
+
+ (void) lbr$get_index( &context, &index, file_archmember, NULL );
+
+ (void) lbr$close( &context );
+}
+
+# endif /* VMS */
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/frames.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/frames.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/frames.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "frames.h"
+# include "lists.h"
+
+
+void frame_init( FRAME* frame )
+{
+ frame->prev = 0;
+ lol_init(frame->args);
+ frame->module = root_module();
+ frame->rulename = "module scope";
+ frame->procedure = 0;
+}
+
+void frame_free( FRAME* frame )
+{
+ lol_free( frame->args );
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/frames.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/frames.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/frames.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef FRAMES_DWA20011021_H
+# define FRAMES_DWA20011021_H
+
+# include "lists.h"
+# include "modules.h"
+
+typedef struct _PARSE PARSE;
+typedef struct frame FRAME;
+
+struct frame
+{
+ FRAME* prev;
+ LOL args[1];
+ module_t* module;
+ PARSE* procedure;
+ char* rulename;
+};
+
+void frame_init( FRAME* ); /* implemented in compile.c */
+void frame_free( FRAME* ); /* implemented in compile.c */
+
+#endif
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/glob.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/glob.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/glob.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,157 @@
+/*
+ * Copyright 1994 Christopher Seiwald. All rights reserved.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * glob.c - match a string against a simple pattern
+ *
+ * Understands the following patterns:
+ *
+ * * any number of characters
+ * ? any single character
+ * [a-z] any single character in the range a-z
+ * [^a-z] any single character not in the range a-z
+ * \x match x
+ *
+ * External functions:
+ *
+ * glob() - match a string against a simple pattern
+ *
+ * Internal functions:
+ *
+ * globchars() - build a bitlist to check for character group match
+ */
+
+# include "jam.h"
+
+# define CHECK_BIT( tab, bit ) ( tab[ (bit)/8 ] & (1<<( (bit)%8 )) )
+# define BITLISTSIZE 16 /* bytes used for [chars] in compiled expr */
+
+static void globchars( char *s, char *e, char *b );
+
+/*
+ * glob() - match a string against a simple pattern
+ */
+
+int
+glob(
+ register char *c,
+ register char *s )
+{
+ char bitlist[ BITLISTSIZE ];
+ char *here;
+
+ for( ;; )
+ switch( *c++ )
+ {
+ case '\0':
+ return *s ? -1 : 0;
+
+ case '?':
+ if( !*s++ )
+ return 1;
+ break;
+
+ case '[':
+ /* scan for matching ] */
+
+ here = c;
+ do if( !*c++ )
+ return 1;
+ while( here == c || *c != ']' );
+ c++;
+
+ /* build character class bitlist */
+
+ globchars( here, c, bitlist );
+
+ if( !CHECK_BIT( bitlist, *(unsigned char *)s ) )
+ return 1;
+ s++;
+ break;
+
+ case '*':
+ here = s;
+
+ while( *s )
+ s++;
+
+ /* Try to match the rest of the pattern in a recursive */
+ /* call. If the match fails we'll back up chars, retrying. */
+
+ while( s != here )
+ {
+ int r;
+
+ /* A fast path for the last token in a pattern */
+
+ r = *c ? glob( c, s ) : *s ? -1 : 0;
+
+ if( !r )
+ return 0;
+ else if( r < 0 )
+ return 1;
+
+ --s;
+ }
+ break;
+
+ case '\\':
+ /* Force literal match of next char. */
+
+ if( !*c || *s++ != *c++ )
+ return 1;
+ break;
+
+ default:
+ if( *s++ != c[-1] )
+ return 1;
+ break;
+ }
+}
+
+/*
+ * globchars() - build a bitlist to check for character group match
+ */
+
+static void
+globchars(
+ char *s,
+ char *e,
+ char *b )
+{
+ int neg = 0;
+
+ memset( b, '\0', BITLISTSIZE );
+
+ if( *s == '^')
+ neg++, s++;
+
+ while( s < e )
+ {
+ int c;
+
+ if( s+2 < e && s[1] == '-' )
+ {
+ for( c = s[0]; c <= s[2]; c++ )
+ b[ c/8 ] |= (1<<(c%8));
+ s += 3;
+ } else {
+ c = *s++;
+ b[ c/8 ] |= (1<<(c%8));
+ }
+ }
+
+ if( neg )
+ {
+ int i;
+ for( i = 0; i < BITLISTSIZE; i++ )
+ b[ i ] ^= 0377;
+ }
+
+ /* Don't include \0 in either $[chars] or $[^chars] */
+
+ b[0] &= 0376;
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/hash.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/hash.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/hash.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,337 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "hash.h"
+# include <assert.h>
+
+/*
+ * hash.c - simple in-memory hashing routines
+ *
+ * External routines:
+ *
+ * hashinit() - initialize a hash table, returning a handle
+ * hashitem() - find a record in the table, and optionally enter a new one
+ * hashdone() - free a hash table, given its handle
+ *
+ * Internal routines:
+ *
+ * hashrehash() - resize and rebuild hp->tab, the hash table
+ *
+ * 4/29/93 - ensure ITEM's are aligned
+ */
+
+char *hashsccssid="@(#)hash.c 1.14 () 6/20/88";
+
+/* Header attached to all data items entered into a hash table. */
+
+struct hashhdr {
+ struct item *next;
+ unsigned int keyval; /* for quick comparisons */
+} ;
+
+/* This structure overlays the one handed to hashenter(). */
+/* It's actual size is given to hashinit(). */
+
+struct hashdata {
+ char *key;
+ /* rest of user data */
+} ;
+
+typedef struct item {
+ struct hashhdr hdr;
+ struct hashdata data;
+} ITEM ;
+
+# define MAX_LISTS 32
+
+struct hash
+{
+ /*
+ * the hash table, just an array of item pointers
+ */
+ struct {
+ int nel;
+ ITEM **base;
+ } tab;
+
+ int bloat; /* tab.nel / items.nel */
+ int inel; /* initial number of elements */
+
+ /*
+ * the array of records, maintained by these routines
+ * essentially a microallocator
+ */
+ struct {
+ int more; /* how many more ITEMs fit in lists[ list ] */
+ ITEM *free; /* free list of items */
+ char *next; /* where to put more ITEMs in lists[ list ] */
+ int datalen; /* length of records in this hash table */
+ int size; /* sizeof( ITEM ) + aligned datalen */
+ int nel; /* total ITEMs held by all lists[] */
+ int list; /* index into lists[] */
+
+ struct {
+ int nel; /* total ITEMs held by this list */
+ char *base; /* base of ITEMs array */
+ } lists[ MAX_LISTS ];
+ } items;
+
+ char *name; /* just for hashstats() */
+} ;
+
+static void hashrehash( struct hash *hp );
+static void hashstat( struct hash *hp );
+
+/*
+ * hash_free() - remove the given item from the table if it's there.
+ * Returns 1 if found, 0 otherwise.
+ *
+ * NOTE: 2nd argument is HASHDATA*, not HASHDATA** as elsewhere.
+ */
+int
+hash_free(
+ register struct hash *hp,
+ HASHDATA *data)
+{
+ ITEM **prev;
+ register ITEM **i;
+ unsigned char *b = (unsigned char*)data->key;
+ unsigned int keyval;
+
+ keyval = *b;
+
+ while( *b )
+ keyval = keyval * 2147059363 + *b++;
+
+ prev = hp->tab.base + ( keyval % hp->tab.nel );
+ while(*prev )
+ {
+ register ITEM* i = *prev;
+ if( keyval == i->hdr.keyval &&
+ !strcmp( i->data.key, data->key ) )
+ {
+ /* unlink the record from the hash chain */
+ *prev = i->hdr.next;
+ /* link it into the freelist */
+ i->hdr.next = hp->items.free;
+ hp->items.free = i;
+ /* mark it free so we skip it during enumeration */
+ i->data.key = 0;
+ /* we have another item */
+ hp->items.more++;
+ return 1;
+ }
+ prev = &i->hdr.next;
+ }
+ return 0;
+}
+
+/*
+ * hashitem() - find a record in the table, and optionally enter a new one
+ */
+
+int
+hashitem(
+ register struct hash *hp,
+ HASHDATA **data,
+ int enter )
+{
+ ITEM **base;
+ register ITEM *i;
+ unsigned char *b = (unsigned char*)(*data)->key;
+ unsigned int keyval;
+
+ if( enter && !hp->items.more )
+ hashrehash( hp );
+
+ if( !enter && !hp->items.nel )
+ return 0;
+
+ keyval = *b;
+
+ while( *b )
+ keyval = keyval * 2147059363 + *b++;
+
+ base = hp->tab.base + ( keyval % hp->tab.nel );
+
+ for( i = *base; i; i = i->hdr.next )
+ if( keyval == i->hdr.keyval &&
+ !strcmp( i->data.key, (*data)->key ) )
+ {
+ *data = &i->data;
+ return !0;
+ }
+
+ if( enter )
+ {
+ /* try to grab one from the free list */
+ if ( hp->items.free )
+ {
+ i = hp->items.free;
+ hp->items.free = i->hdr.next;
+ assert( i->data.key == 0 );
+ }
+ else
+ {
+ i = (ITEM *)hp->items.next;
+ hp->items.next += hp->items.size;
+ }
+ hp->items.more--;
+ memcpy( (char *)&i->data, (char *)*data, hp->items.datalen );
+ i->hdr.keyval = keyval;
+ i->hdr.next = *base;
+ *base = i;
+ *data = &i->data;
+ }
+
+ return 0;
+}
+
+/*
+ * hashrehash() - resize and rebuild hp->tab, the hash table
+ */
+
+static void hashrehash( register struct hash *hp )
+{
+ int i = ++hp->items.list;
+
+ hp->items.more = i ? 2 * hp->items.nel : hp->inel;
+ hp->items.next = (char *)malloc( hp->items.more * hp->items.size );
+ hp->items.free = 0;
+
+ hp->items.lists[i].nel = hp->items.more;
+ hp->items.lists[i].base = hp->items.next;
+ hp->items.nel += hp->items.more;
+
+ if( hp->tab.base )
+ free( (char *)hp->tab.base );
+
+ hp->tab.nel = hp->items.nel * hp->bloat;
+ hp->tab.base = (ITEM **)malloc( hp->tab.nel * sizeof(ITEM **) );
+
+ memset( (char *)hp->tab.base, '\0', hp->tab.nel * sizeof( ITEM * ) );
+
+ for( i = 0; i < hp->items.list; i++ )
+ {
+ int nel = hp->items.lists[i].nel;
+ char *next = hp->items.lists[i].base;
+
+ for( ; nel--; next += hp->items.size )
+ {
+ register ITEM *i = (ITEM *)next;
+ ITEM **ip = hp->tab.base + i->hdr.keyval % hp->tab.nel;
+ /* code currently assumes rehashing only when there are no free items */
+ assert( i->data.key != 0 );
+
+ i->hdr.next = *ip;
+ *ip = i;
+ }
+ }
+}
+
+void hashenumerate( struct hash *hp, void (*f)(void*,void*), void* data )
+{
+ int i;
+ for( i = 0; i <= hp->items.list; i++ )
+ {
+ char *next = hp->items.lists[i].base;
+ int nel = hp->items.lists[i].nel;
+ if ( i == hp->items.list )
+ nel -= hp->items.more;
+
+ for( ; nel--; next += hp->items.size )
+ {
+ register ITEM *i = (ITEM *)next;
+
+ if ( i->data.key != 0 ) /* don't enumerate freed items */
+ f(&i->data, data);
+ }
+ }
+}
+
+/* --- */
+
+# define ALIGNED(x) ( ( x + sizeof( ITEM ) - 1 ) & ~( sizeof( ITEM ) - 1 ) )
+
+/*
+ * hashinit() - initialize a hash table, returning a handle
+ */
+
+struct hash *
+hashinit(
+ int datalen,
+ char *name )
+{
+ struct hash *hp = (struct hash *)malloc( sizeof( *hp ) );
+
+ hp->bloat = 3;
+ hp->tab.nel = 0;
+ hp->tab.base = (ITEM **)0;
+ hp->items.more = 0;
+ hp->items.free = 0;
+ hp->items.datalen = datalen;
+ hp->items.size = sizeof( struct hashhdr ) + ALIGNED( datalen );
+ hp->items.list = -1;
+ hp->items.nel = 0;
+ hp->inel = 11;
+ hp->name = name;
+
+ return hp;
+}
+
+/*
+ * hashdone() - free a hash table, given its handle
+ */
+
+void
+hashdone( struct hash *hp )
+{
+ int i;
+
+ if( !hp )
+ return;
+
+ if( DEBUG_MEM )
+ hashstat( hp );
+
+ if( hp->tab.base )
+ free( (char *)hp->tab.base );
+ for( i = 0; i <= hp->items.list; i++ )
+ free( hp->items.lists[i].base );
+ free( (char *)hp );
+}
+
+/* ---- */
+
+static void
+hashstat( struct hash *hp )
+{
+ ITEM **tab = hp->tab.base;
+ int nel = hp->tab.nel;
+ int count = 0;
+ int sets = 0;
+ int run = ( tab[ nel - 1 ] != (ITEM *)0 );
+ int i, here;
+
+ for( i = nel; i > 0; i-- )
+ {
+ if( here = ( *tab++ != (ITEM *)0 ) )
+ count++;
+ if( here && !run )
+ sets++;
+ run = here;
+ }
+
+ printf( "%s table: %d+%d+%d (%dK+%dK) items+table+hash, %f density\n",
+ hp->name,
+ count,
+ hp->items.nel,
+ hp->tab.nel,
+ hp->items.nel * hp->items.size / 1024,
+ hp->tab.nel * sizeof( ITEM ** ) / 1024,
+ (float)count / (float)sets );
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/hash.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/hash.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/hash.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,20 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * hash.h - simple in-memory hashing routines
+ */
+
+typedef struct hashdata HASHDATA;
+
+struct hash * hashinit( int datalen, char *name );
+int hashitem( struct hash *hp, HASHDATA **data, int enter );
+void hashdone( struct hash *hp );
+void hashenumerate( struct hash *hp, void (*f)(void*,void*), void* data );
+int hash_free( struct hash *hp, HASHDATA *data);
+
+# define hashenter( hp, data ) (!hashitem( hp, data, !0 ))
+# define hashcheck( hp, data ) hashitem( hp, data, 0 )
Added: boost-jam/boost-build/branches/upstream/current/jam_src/hcache.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/hcache.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/hcache.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,423 @@
+/*
+ * This file has been donated to Jam.
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "parse.h"
+# include "rules.h"
+# include "regexp.h"
+# include "headers.h"
+# include "newstr.h"
+# include "hash.h"
+# include "hcache.h"
+# include "variable.h"
+# include "search.h"
+
+#ifdef OPT_HEADER_CACHE_EXT
+
+/*
+ * Craig W. McPheeters, Alias|Wavefront.
+ *
+ * hcache.c hcache.h - handle cacheing of #includes in source files
+ *
+ * Create a cache of files scanned for headers. When starting jam,
+ * look for the cache file and load it if present. When finished the
+ * binding phase, create a new header cache. The cache contains
+ * files, their timestamps and the header files found in their scan.
+ * During the binding phase of jam, look in the header cache first for
+ * the headers contained in a file. If the cache is present and
+ * valid, use its contents. This results in dramatic speedups with
+ * large projects (eg. 3min -> 1min startup for one project.)
+ *
+ * External routines:
+ * hcache_init() - read and parse the local .jamdeps file.
+ * hcache_done() - write a new .jamdeps file
+ * hcache() - return list of headers on target. Use cache or do a scan.
+ *
+ * The dependency file format is an ascii file with 1 line per target.
+ * Each line has the following fields:
+ * @boundname@ timestamp @file@ @file@ @file@ ... \n
+ * */
+
+struct hcachedata {
+ char *boundname;
+ time_t time;
+ LIST *includes;
+ LIST *hdrscan; /* the HDRSCAN value for this target */
+ int age; /* if too old, we'll remove it from cache */
+ struct hcachedata *next;
+} ;
+
+typedef struct hcachedata HCACHEDATA ;
+
+
+static struct hash *hcachehash = 0;
+static HCACHEDATA *hcachelist = 0;
+
+static int queries = 0;
+static int hits = 0;
+
+#define CACHE_FILE_VERSION "version 4"
+#define CACHE_RECORD_HEADER "header"
+#define CACHE_RECORD_END "end"
+
+/*
+ * Return the name of the header cache file. May return NULL.
+ *
+ * The user sets this by setting the HCACHEFILE variable in a Jamfile.
+ * We cache the result so the user can't change the cache file during
+ * header scanning.
+ */
+static char*
+cache_name(void)
+{
+ static char* name = 0;
+ if (!name) {
+ LIST *hcachevar = var_get("HCACHEFILE");
+
+ if (hcachevar) {
+ TARGET *t = bindtarget( hcachevar->string );
+
+ pushsettings( t->settings );
+ /* Don't expect cache file to be generated, so pass 0
+ as third argument to search. */
+ t->boundname = search( t->name, &t->time, 0 );
+ popsettings( t->settings );
+
+ if (hcachevar) {
+ name = copystr(t->boundname);
+ }
+ }
+ }
+ return name;
+}
+
+/*
+ * Return the maximum age a cache entry can have before it is purged
+ * from the cache.
+ */
+static int
+cache_maxage(void)
+{
+ int age = 100;
+ LIST *var = var_get("HCACHEMAXAGE");
+
+ if (var) {
+ age = atoi(var->string);
+ if (age < 0)
+ age = 0;
+ }
+
+ return age;
+}
+
+/*
+ * Read a netstring. The caveat is that the string can't contain
+ * ASCII 0. The returned value is as returned by newstr(), so it need
+ * not be freed.
+ */
+char*
+read_netstring(FILE* f)
+{
+ unsigned long len;
+ static char* buf = NULL;
+ static unsigned long buf_len = 0;
+
+ if (fscanf(f, " %9lu", &len) != 1)
+ return NULL;
+ if (fgetc(f) != (int)'\t')
+ return NULL;
+
+ if (len > 1024 * 64)
+ return NULL; /* sanity check */
+
+ if (len > buf_len)
+ {
+ unsigned long new_len = buf_len * 2;
+ if (new_len < len)
+ new_len = len;
+ buf = (char*)realloc(buf, new_len + 1);
+ if (buf)
+ buf_len = new_len;
+ }
+
+ if (!buf)
+ return NULL;
+
+ if (fread(buf, 1, len, f) != len)
+ return NULL;
+ if (fgetc(f) != (int)'\n')
+ return NULL;
+
+ buf[len] = 0;
+ return newstr(buf);
+}
+
+/*
+ * Write a netstring.
+ */
+void
+write_netstring(FILE* f, const char* s)
+{
+ if (!s)
+ s = "";
+ fprintf(f, "%lu\t%s\n", strlen(s), s);
+}
+
+void
+hcache_init()
+{
+ HCACHEDATA cachedata, *c;
+ FILE *f;
+ char *version;
+ int header_count = 0;
+ char* hcachename;
+
+ hcachehash = hashinit (sizeof (HCACHEDATA), "hcache");
+
+ if (! (hcachename = cache_name()))
+ return;
+
+ if (! (f = fopen (hcachename, "rb" )))
+ return;
+
+ version = read_netstring(f);
+ if (!version || strcmp(version, CACHE_FILE_VERSION)) {
+ fclose(f);
+ return;
+ }
+
+ while (1)
+ {
+ char* record_type;
+ char *time_str;
+ char *age_str;
+ char *includes_count_str;
+ char *hdrscan_count_str;
+ int i, count;
+ LIST *l;
+
+ record_type = read_netstring(f);
+ if (!record_type) {
+ fprintf(stderr, "invalid %s\n", hcachename);
+ goto bail;
+ }
+ if (!strcmp(record_type, CACHE_RECORD_END)) {
+ break;
+ }
+ if (strcmp(record_type, CACHE_RECORD_HEADER)) {
+ fprintf(stderr, "invalid %s with record separator <%s>\n",
+ hcachename, record_type ? record_type : "<null>");
+ goto bail;
+ }
+
+ c = &cachedata;
+
+ c->boundname = read_netstring(f);
+ time_str = read_netstring(f);
+ age_str = read_netstring(f);
+ includes_count_str = read_netstring(f);
+
+ if (!c->boundname || !time_str || !age_str
+ || !includes_count_str)
+ {
+ fprintf(stderr, "invalid %s\n", hcachename);
+ goto bail;
+ }
+
+ c->time = atoi(time_str);
+ c->age = atoi(age_str) + 1;
+
+ count = atoi(includes_count_str);
+ for (l = 0, i = 0; i < count; i++) {
+ char* s = read_netstring(f);
+ if (!s) {
+ fprintf(stderr, "invalid %s\n", hcachename);
+ goto bail;
+ }
+ l = list_new(l, s);
+ }
+ c->includes = l;
+
+ hdrscan_count_str = read_netstring(f);
+ if (!includes_count_str) {
+ list_free(c->includes);
+ fprintf(stderr, "invalid %s\n", hcachename);
+ goto bail;
+ }
+
+ count = atoi(hdrscan_count_str);
+ for (l = 0, i = 0; i < count; i++) {
+ char* s = read_netstring(f);
+ if (!s) {
+ fprintf(stderr, "invalid %s\n", hcachename);
+ goto bail;
+ }
+ l = list_new(l, s);
+ }
+ c->hdrscan = l;
+
+ if (!hashenter(hcachehash, (HASHDATA **)&c)) {
+ fprintf(stderr, "can't insert header cache item, bailing on %s\n",
+ hcachename);
+ goto bail;
+ }
+
+ c->next = hcachelist;
+ hcachelist = c;
+
+ header_count++;
+ }
+
+ if (DEBUG_HEADER) {
+ printf("hcache read from file %s\n", hcachename);
+ }
+
+ bail:
+ fclose(f);
+}
+
+void
+hcache_done()
+{
+ FILE *f;
+ HCACHEDATA *c;
+ int header_count = 0;
+ char* hcachename;
+ int maxage;
+
+ if (!hcachehash)
+ return;
+
+ if (! (hcachename = cache_name()))
+ return;
+
+ if (! (f = fopen (hcachename, "wb" )))
+ return;
+
+ maxage = cache_maxage();
+
+ /* print out the version */
+ write_netstring(f, CACHE_FILE_VERSION);
+
+ c = hcachelist;
+ for (c = hcachelist; c; c = c->next) {
+ LIST *l;
+ char time_str[30];
+ char age_str[30];
+ char includes_count_str[30];
+ char hdrscan_count_str[30];
+
+ if (maxage == 0)
+ c->age = 0;
+ else if (c->age > maxage)
+ continue;
+
+ sprintf(includes_count_str, "%lu", list_length(c->includes));
+ sprintf(hdrscan_count_str, "%lu", list_length(c->hdrscan));
+ sprintf(time_str, "%lu", c->time);
+ sprintf(age_str, "%lu", c->age);
+
+ write_netstring(f, CACHE_RECORD_HEADER);
+ write_netstring(f, c->boundname);
+ write_netstring(f, time_str);
+ write_netstring(f, age_str);
+ write_netstring(f, includes_count_str);
+ for (l = c->includes; l; l = list_next(l)) {
+ write_netstring(f, l->string);
+ }
+ write_netstring(f, hdrscan_count_str);
+ for (l = c->hdrscan; l; l = list_next(l)) {
+ write_netstring(f, l->string);
+ }
+ fputs("\n", f);
+ header_count++;
+ }
+ write_netstring(f, CACHE_RECORD_END);
+
+ if (DEBUG_HEADER) {
+ printf("hcache written to %s. %d dependencies, %.0f%% hit rate\n",
+ hcachename, header_count,
+ queries ? 100.0 * hits / queries : 0);
+ }
+
+ fclose (f);
+}
+
+LIST *
+hcache (TARGET *t, int rec, regexp *re[], LIST *hdrscan)
+{
+ HCACHEDATA cachedata, *c = &cachedata;
+ LIST *l = 0;
+
+ ++queries;
+
+ c->boundname = t->boundname;
+
+ if (hashcheck (hcachehash, (HASHDATA **) &c))
+ {
+ if (c->time == t->time)
+ {
+ LIST *l1 = hdrscan, *l2 = c->hdrscan;
+ while (l1 && l2) {
+ if (l1->string != l2->string) {
+ l1 = NULL;
+ } else {
+ l1 = list_next(l1);
+ l2 = list_next(l2);
+ }
+ }
+ if (l1 || l2) {
+ if (DEBUG_HEADER)
+ printf("HDRSCAN out of date in cache for %s\n",
+ t->boundname);
+
+ printf("HDRSCAN out of date for %s\n", t->boundname);
+ printf(" real : ");
+ list_print(hdrscan);
+ printf("\n cached: ");
+ list_print(c->hdrscan);
+ printf("\n");
+
+ list_free(c->includes);
+ list_free(c->hdrscan);
+ c->includes = 0;
+ c->hdrscan = 0;
+ } else {
+ if (DEBUG_HEADER)
+ printf ("using header cache for %s\n", t->boundname);
+ c->age = 0;
+ ++hits;
+ l = list_copy (0, c->includes);
+ return l;
+ }
+ } else {
+ if (DEBUG_HEADER)
+ printf ("header cache out of date for %s\n", t->boundname);
+ list_free (c->includes);
+ list_free(c->hdrscan);
+ c->includes = 0;
+ c->hdrscan = 0;
+ }
+ } else {
+ if (hashenter (hcachehash, (HASHDATA **)&c)) {
+ c->boundname = newstr (c->boundname);
+ c->next = hcachelist;
+ hcachelist = c;
+ }
+ }
+
+ /* 'c' points at the cache entry. Its out of date. */
+
+ l = headers1 (0, t->boundname, rec, re);
+
+ c->time = t->time;
+ c->age = 0;
+ c->includes = list_copy (0, l);
+ c->hdrscan = list_copy(0, hdrscan);
+
+ return l;
+}
+
+#endif
Added: boost-jam/boost-build/branches/upstream/current/jam_src/hcache.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/hcache.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/hcache.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,18 @@
+/*
+ * This file is not part of Jam
+ */
+
+/*
+ * hcache.h - handle #includes in source files
+ */
+#ifndef HCACHE_H
+# define HCACHE_H
+
+# include "regexp.h"
+# include "lists.h"
+
+void hcache_init(void);
+void hcache_done(void);
+LIST *hcache(TARGET *t, int rec, regexp *re[], LIST *hdrscan);
+
+#endif
Added: boost-jam/boost-build/branches/upstream/current/jam_src/hdrmacro.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/hdrmacro.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/hdrmacro.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,139 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "parse.h"
+# include "compile.h"
+# include "rules.h"
+# include "variable.h"
+# include "regexp.h"
+# include "hdrmacro.h"
+# include "hash.h"
+# include "newstr.h"
+# include "strings.h"
+
+/*
+ * hdrmacro.c - handle header files that define macros used in
+ * #include statements.
+ *
+ * we look for lines like "#define MACRO <....>" or '#define MACRO " "'
+ * in the target file. When found, we
+ *
+ * we then phony up a rule invocation like:
+ *
+ * $(HDRRULE) <target> : <resolved included files> ;
+ *
+ * External routines:
+ * headers1() - scan a target for "#include MACRO" lines and try
+ * to resolve them when needed
+ *
+ * Internal routines:
+ * headers1() - using regexp, scan a file and build include LIST
+ *
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 09/10/00 (seiwald) - replaced call to compile_rule with evaluate_rule,
+ * so that headers() doesn't have to mock up a parse structure
+ * just to invoke a rule.
+ */
+
+static LIST *header_macros1( LIST *l, char *file, int rec, regexp *re[] );
+
+/* this type is used to store a dictionary of file header macros */
+typedef struct header_macro
+{
+ char* symbol;
+ char* filename; /* we could maybe use a LIST here ?? */
+
+} HEADER_MACRO;
+
+static struct hash* header_macros_hash = 0;
+
+/*
+ * headers() - scan a target for include files and call HDRRULE
+ */
+
+# define MAXINC 10
+
+void
+macro_headers( TARGET *t )
+{
+ static regexp *re = 0;
+ FILE *f;
+ char buf[ 1024 ];
+
+ if ( DEBUG_HEADER )
+ printf( "macro header scan for %s\n", t->name );
+
+ /* this regexp is used to detect lines of the form */
+ /* "#define MACRO <....>" or "#define MACRO "....." */
+ /* in the header macro files.. */
+ if ( re == 0 )
+ {
+ re = regex_compile(
+ "^[ ]*#[ ]*define[ ]*([A-Za-z][A-Za-z0-9_]*)[ ]*"
+ "[<\"]([^\">]*)[\">].*$" );
+ }
+
+ if( !( f = fopen( t->boundname, "r" ) ) )
+ return;
+
+ while( fgets( buf, sizeof( buf ), f ) )
+ {
+ HEADER_MACRO var, *v = &var;
+
+ if ( regexec( re, buf ) && re->startp[1] )
+ {
+ /* we detected a line that looks like "#define MACRO filename */
+ re->endp[1][0] = '\0';
+ re->endp[2][0] = '\0';
+
+ if ( DEBUG_HEADER )
+ printf( "macro '%s' used to define filename '%s' in '%s'\n",
+ re->startp[1], re->startp[2], t->boundname );
+
+ /* add macro definition to hash table */
+ if ( !header_macros_hash )
+ header_macros_hash = hashinit( sizeof( HEADER_MACRO ), "hdrmacros" );
+
+ v->symbol = re->startp[1];
+ v->filename = 0;
+ if ( hashenter( header_macros_hash, (HASHDATA **)&v ) )
+ {
+ v->symbol = newstr( re->startp[1] ); /* never freed */
+ v->filename = newstr( re->startp[2] ); /* never freed */
+ }
+ /* XXXX: FOR NOW, WE IGNORE MULTIPLE MACRO DEFINITIONS !! */
+ /* WE MIGHT AS WELL USE A LIST TO STORE THEM.. */
+ }
+ }
+
+ fclose( f );
+}
+
+
+char*
+macro_header_get( const char* macro_name )
+{
+ HEADER_MACRO var, *v = &var;
+
+ v->symbol = (char*)macro_name;
+
+ if( header_macros_hash && hashcheck( header_macros_hash, (HASHDATA **)&v ) )
+ {
+ if ( DEBUG_HEADER )
+ printf( "### macro '%s' evaluated to '%s'\n", macro_name, v->filename );
+ return v->filename;
+ }
+ return 0;
+}
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/hdrmacro.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/hdrmacro.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/hdrmacro.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,14 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * hdrmacro.h - parses header files for #define MACRO <filename> or
+ * #define MACRO "filename" definitions
+ */
+
+void macro_headers( TARGET *t );
+
+char* macro_header_get( const char* macro_name );
Added: boost-jam/boost-build/branches/upstream/current/jam_src/headers.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/headers.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/headers.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,196 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "parse.h"
+# include "compile.h"
+# include "rules.h"
+# include "variable.h"
+# include "regexp.h"
+# include "headers.h"
+# include "hdrmacro.h"
+# include "newstr.h"
+
+#ifdef OPT_HEADER_CACHE_EXT
+# include "hcache.h"
+#endif
+
+/*
+ * headers.c - handle #includes in source files
+ *
+ * Using regular expressions provided as the variable $(HDRSCAN),
+ * headers() searches a file for #include files and phonies up a
+ * rule invocation:
+ *
+ * $(HDRRULE) <target> : <include files> ;
+ *
+ * External routines:
+ * headers() - scan a target for include files and call HDRRULE
+ *
+ * Internal routines:
+ * headers1() - using regexp, scan a file and build include LIST
+ *
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 09/10/00 (seiwald) - replaced call to compile_rule with evaluate_rule,
+ * so that headers() doesn't have to mock up a parse structure
+ * just to invoke a rule.
+ */
+
+#ifndef OPT_HEADER_CACHE_EXT
+static LIST *headers1( LIST *l, char *file, int rec, regexp *re[]);
+#endif
+
+/*
+ * headers() - scan a target for include files and call HDRRULE
+ */
+
+# define MAXINC 10
+
+void
+headers( TARGET *t )
+{
+ LIST *hdrscan;
+ LIST *hdrrule;
+ LIST *headlist = 0;
+ regexp *re[ MAXINC ];
+ int rec = 0;
+
+ if( !( hdrscan = var_get( "HDRSCAN" ) ) ||
+ !( hdrrule = var_get( "HDRRULE" ) ) )
+ return;
+
+ if( DEBUG_HEADER )
+ printf( "header scan %s\n", t->name );
+
+ /* Compile all regular expressions in HDRSCAN */
+
+ while( rec < MAXINC && hdrscan )
+ {
+ re[rec++] = regex_compile( hdrscan->string );
+ hdrscan = list_next( hdrscan );
+ }
+
+ /* Doctor up call to HDRRULE rule */
+ /* Call headers1() to get LIST of included files. */
+ {
+ FRAME frame[1];
+ frame_init( frame );
+ lol_add( frame->args, list_new( L0, t->name ) );
+#ifdef OPT_HEADER_CACHE_EXT
+ lol_add( frame->args, hcache( t, rec, re, hdrscan ) );
+#else
+ lol_add( frame->args, headers1( headlist, t->boundname, rec, re ) );
+#endif
+
+ if( lol_get( frame->args, 1 ) )
+ {
+ /* The third argument to HDRRULE is the bound name of
+ * $(<) */
+ lol_add( frame->args, list_new( L0, t->boundname ) );
+
+ list_free( evaluate_rule( hdrrule->string, frame ) );
+ }
+
+ /* Clean up */
+
+ frame_free( frame );
+ }
+}
+
+/*
+ * headers1() - using regexp, scan a file and build include LIST
+ */
+
+#ifdef OPT_HEADER_CACHE_EXT
+LIST *
+#else
+static LIST *
+#endif
+headers1(
+ LIST *l,
+ char *file,
+ int rec,
+ regexp *re[] )
+{
+ FILE *f;
+ char buf[ 1024 ];
+ int i;
+ static regexp *re_macros = 0;
+
+
+#ifdef OPT_IMPROVED_PATIENCE_EXT
+ static int count = 0;
+ ++count;
+ if ( ((count == 100) || !( count % 1000 )) && DEBUG_MAKE )
+ printf("...patience...\n");
+#endif
+
+ /* the following regexp is used to detect cases where a */
+ /* file is included through a line line "#include MACRO" */
+ if ( re_macros == 0 )
+ {
+ re_macros = regex_compile(
+ "^[ ]*#[ ]*include[ ]*([A-Za-z][A-Za-z0-9_]*).*$" );
+ }
+
+
+ if( !( f = fopen( file, "r" ) ) )
+ return l;
+
+ while( fgets( buf, sizeof( buf ), f ) )
+ {
+ for( i = 0; i < rec; i++ )
+ if( regexec( re[i], buf ) && re[i]->startp[1] )
+ {
+ re[i]->endp[1][0] = '\0';
+
+ if( DEBUG_HEADER )
+ printf( "header found: %s\n", re[i]->startp[1] );
+
+ l = list_new( l, newstr( re[i]->startp[1] ) );
+ }
+
+ /* special treatment for #include MACRO */
+ if ( regexec( re_macros, buf ) && re_macros->startp[1] )
+ {
+ char* header_filename;
+
+ re_macros->endp[1][0] = '\0';
+
+ if ( DEBUG_HEADER )
+ printf( "macro header found: %s", re_macros->startp[1] );
+
+ header_filename = macro_header_get( re_macros->startp[1] );
+ if (header_filename)
+ {
+ if ( DEBUG_HEADER )
+ printf( " resolved to '%s'\n", header_filename );
+ l = list_new( l, newstr( header_filename ) );
+ }
+ else
+ {
+ if ( DEBUG_HEADER )
+ printf( " ignored !!\n" );
+ }
+ }
+ }
+
+ fclose( f );
+
+ return l;
+}
+
+void
+regerror( char *s )
+{
+ printf( "re error %s\n", s );
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/headers.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/headers.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/headers.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,16 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * headers.h - handle #includes in source files
+ */
+
+void headers( TARGET *t );
+
+#ifdef OPT_HEADER_CACHE_EXT
+struct regexp;
+LIST *headers1( LIST *l, char *file, int rec, struct regexp *re[] );
+#endif
Added: boost-jam/boost-build/branches/upstream/current/jam_src/index.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/index.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/index.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1220 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st September 2003), see www.w3.org">
+ <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+ <link rel="stylesheet" type="text/css" href="../../../../boost.css">
+
+ <title>Boost.Jam</title>
+ <meta name="author" content="Rene Rivera">
+ <meta name="description" content=
+ "Boost.Jam (bjam) is the core build tool for using the Boost.Build system. BJam is based on Perforce's Jam/MR.">
+ </head>
+
+<body link="#0000FF" vlink="#800080">
+ <table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
+ "header">
+ <tbody>
+ <tr>
+ <td valign="top" width="300">
+ <h3><a href="../../../index.htm"><img height="86" width="277" alt=
+ "C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
+ </td>
+
+ <td valign="top">
+ <h1 align="center">Boost.Jam</h1>
+
+ <h2 align="center"></h2>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <hr>
+
+ <dl class="index">
+ <dt><a href="#introduction">Introduction</a></dt>
+
+ <dt><a href="#features">Features</a></dt>
+
+ <dt><a href="#contents">Contents</a></dt>
+
+ <dt><a href="#building_bjam">Building Boost.Jam</a></dt>
+
+ <dt><a href="#core_extensions">Core Jam Extensions</a></dt>
+
+ <dd>
+ <dl class="index">
+ <dt><a href="#variable_quoting">Command-line and Environment Variable
+ Quoting</a></dt>
+
+ <dt><a href="#jambase_replacement">Startup Behavior</a></dt>
+
+ <dt><a href="#rule_indirection">Rule Indirection</a></dt>
+
+ <dt><a href="#argument_lists">Argument Lists</a></dt>
+
+ <dt><a href="#module_support">Module Support</a></dt>
+
+ <dd>
+ <dl class="index">
+ <dt><a href="#module_declaration">Declaration</a></dt>
+
+ <dt><a href="#module_locals">Variable Scope</a></dt>
+
+ <dt><a href="#local_rules">Local Rules</a></dt>
+
+ <dt><a href="#RULENAMES_rule">The <tt>RULENAMES</tt>
+ rule</a></dt>
+
+ <dt><a href="#VARNAMES_rule">The <tt>VARNAMES</tt> rule</a></dt>
+
+ <dt><a href="#IMPORT_rule">The <tt>IMPORT</tt> rule</a></dt>
+
+ <dt><a href="#EXPORT_rule">The <tt>EXPORT</tt> rule</a></dt>
+
+ <dt><a href="#CALLER_MODULE_rule">The
+ <tt>CALLER_MODULE</tt></a></dt>
+
+ <dt><a href="#DELETE_MODULE_rule">The <tt>DELETE_MODULE</tt>
+ rule</a></dt>
+ </dl>
+ </dd>
+
+ <dt><a href="#local_foreach">Local for Loop Variables</a></dt>
+
+ <dt><a href="#negative_indexing">Negative Indexing</a></dt>
+
+ <dt><a href="#cygwin_support">Support for Cygwin</a></dt>
+
+ <dt><a href="#BINDRULE">Target Binding Detection</a></dt>
+
+ <dt><a href="#FAIL_EXPECTED">Return Code Inversion</a></dt>
+
+ <dt><a href="#NOCARE">Ignoring Return Codes</a></dt>
+
+ <dt><a href="#RMOLD">Removing outdated targets</a></dt>
+
+ <dt><a href="#SUBST_rule">The <tt>SUBST</tt> Rule</a></dt>
+
+ <dt><a href="#JAM_VERSION">The <tt>JAM_VERSION</tt> global
+ variable</a></dt>
+
+ <dt><a href="#debugging_support">Debugging Support</a></dt>
+
+ <dd>
+ <dl class="index">
+ <dt><a href="#BACKTRACE_rule">The BACKTRACE rule</a></dt>
+
+ <dt><a href="#profiling">Profiling</a></dt>
+
+ <dt><a href="#parse_debugging">Parser Debugging</a></dt>
+
+ <dt><a href="#dependency_graph">Dependency Graph Output</a></dt>
+ </dl>
+ </dd>
+
+ <dt><a href="#UPDATE">The <tt>UPDATE</tt> rule and changes to command
+ line handling</a></dt>
+
+ <dt><a href="#semaphores">Semaphores</a></dt>
+
+ <dt><a href="#semaphores">The W32_GETREG rule</a></dt>
+ </dl>
+ </dd>
+
+ <dt><a href="#jam_fundamentals">Jam Fundamentals</a></dt>
+ </dl>
+
+ <h2><a name="introduction"></a>Introduction</h2>
+
+ <p>Boost.Jam (BJam) is a build tool based on FTJam, which in turn is
+ based on Perforce Jam. It contains significant improvements made to
+ facilitate its use in the Boost Build System, but should be backward
+ compatible with Perforce Jam.</p>
+
+ <p>This is version 3.1.10 of BJam and is based on version 2.4 of Jam/MR:</p>
+ <pre>
+/+\
++\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+\+/
+This is Release 2.4 of Jam/MR, a make-like program.
+License is hereby granted to use this software and distribute it
+freely, as long as this copyright notice is retained and modifications
+are clearly marked.
+ALL WARRANTIES ARE HEREBY DISCLAIMED.
+</pre>
+
+ <h2><a name="features"></a>Features</h2>
+
+ <p>Jam is a make(1) replacement that makes building simple things simple
+ and building complicated things manageable.</p>
+
+ <p>Jam's language is expressive, making Jamfiles (c.f. Makefiles) compact.
+ Here's a sample:</p>
+ <pre>
+Main smail : main.c map.c resolve.c deliver.c
+ misc.c parser.y alias.c pw.c headers.c
+ scanner.l getpath.c str.c ;
+</pre>
+
+ <p>This builds "smail" from a dozen source files. Jam handles header file
+ dependencies automatically and on-the-fly.</p>
+
+ <p>Jam is very portable: it runs on UNIX, VMS, Mac, and NT. Most Jamfiles
+ themselves are portable, like the sample above.</p>
+
+ <p>Jam is unintrusive: it is small, it has negligible CPU overhead, and it
+ doesn't create any of its own funny files (c.f. Odin, nmake, SunOS
+ make).</p>
+
+ <p>Jam can build large projects spread across many directories in one pass,
+ without recursing, tracking the relationships among all files. Jam can do
+ this with multiple, concurrent processes.</p>
+
+ <p>Jam isn't under the blinkin GNU copyright, so you can incorporate it
+ into commercial products.</p>
+
+ <h2><a name="contents"></a>Contents</h2>
+
+ <table cellpadding="2" cellspacing="2" border="0" summary=
+ "Contents of Jam documents.">
+ <tr>
+ <td valign="top"><a href="Jam.html">Jam.html</a></td>
+
+ <td valign="top">Jam and language reference.</td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href="Porting">Porting</a></td>
+
+ <td valign="top">Notes on porting jam to wildcat platforms.</td>
+ </tr>
+ </table>
+
+ <h2><a name="building_bjam"></a>Building Boost.Jam</h2>
+
+ <p>Installing BJam after building it is simply a matter of copying the
+ generated executables someplace in your <tt>PATH</tt>. For building the
+ executables there are a set of <tt>build</tt> bootstrap scripts to
+ accomodate particular environments. The scripts take one optional argument,
+ the name of the toolset to build with. When the toolset is not given an
+ attempt is made to detect an available toolset and use that. The build
+ scripts accept these areguments:</p>
+ <pre>
+<build script name> [toolset]
+</pre>
+
+ <p>Running the scripts without arguments will give you the best chance of
+ success. On Windows platforms from a command console do:</p>
+ <pre>
+cd <jam source location>
+.\build.bat
+</pre>
+
+ <p>On Unix type platforms do:</p>
+ <pre>
+cd <jam source location>
+sh ./build.sh
+</pre>
+
+ <p>For the Boost.Jam source included with the Boost distribution the
+ <tt><jam source location></tt> is
+ <tt>BOOST_ROOT/tools/build/jam_src.</tt></p>
+
+ <p>If the scripts fail to detect an appropriate toolset to build with your
+ particular toolset may not be auto-detectable. In that case, you can
+ specify the toolset as the first argument, this assumes that the toolset is
+ readily available in the <tt>PATH</tt>. NOTE: The toolset used to build
+ Boost.Jam is independent of the toolsets used for Boost.Build. Only one
+ version of Boost.Jam is needed to use Boost.Build. The supported toolsets,
+ and wether they are auto-detected, are:</p>
+
+ <table cellpadding="2" cellspacing="2" border="1" summary=
+ "Bootstrap supported platforms and toolsets.">
+ <tr>
+ <th valign="top">Script</th>
+
+ <th valign="top">Platforms</th>
+
+ <th valign="top">Toolsets</th>
+
+ <th valign="top">Detection</th>
+ </tr>
+
+ <tr>
+ <td valign="top" rowspan="9" colspan="1"><tt>build.bat</tt></td>
+
+ <td valign="top" rowspan="9" colspan="1">Windows NT, 2000, and XP</td>
+
+ <td valign="top"><a href=
+ "http://www.comeaucomputing.com"><tt>como</tt></a>, Comeau.Computing
+ C/C++</td>
+
+ <td valign="top"></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href=
+ "http://www.borland.com/bcppbuilder/freecompiler"><tt>borland</tt></a>,
+ <a href="http://www.borland.com/">Borland</a> C++Builder (BCC 5.5)</td>
+
+ <td valign="top">* Common install location:
+ <tt>"C:\Borland\BCC55"</tt><br>
+ * <tt>BCC32.EXE</tt> in <tt>PATH</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href="http://gcc.gnu.org">gcc</a>, GNU GCC</td>
+
+ <td valign="top"></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href="http://gcc.gnu.org">gcc-nocygwin</a>, GNU
+ GCC</td>
+
+ <td valign="top"></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href=
+ "http://www.intel.com/software/products/compilers/c60"><tt>intel-win32</tt></a>,
+ Intel C++ Compiler for Windows</td>
+
+ <td valign="top">* <tt>ICL.EXE</tt> in <tt>PATH</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href=
+ "http://www.metrowerks.com"><tt>metrowerks</tt></a>, MetroWerks
+ CodeWarrior C/C++ 7.x, 8.x</td>
+
+ <td valign="top">* <tt>CWFolder</tt> variable configured<br>
+ * <tt>MWCC.EXE</tt> in <tt>PATH</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href="http://www.mingw.org">mingw</a>, GNU <a href=
+ "http://gcc.gnu.org">GCC</a> as the <a href=
+ "http://www.mingw.org">MinGW</a> configuration</td>
+
+ <td valign="top">* Common install location: <tt>"C:\MinGW"</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href="http://msdn.microsoft.com/visualc/">msvc</a>,
+ Microsoft Visual C++ 6.x</td>
+
+ <td valign="top">* <tt>VCVARS32.BAT</tt> already configured<br>
+ * Common install locations: <tt>"C:\Program Files\Microsoft Visual
+ Studio"</tt>, <tt>"C:\Program Files\Microsoft Visual C++"<br></tt> *
+ <tt>CL.EXE</tt> in <tt>PATH</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href="http://msdn.microsoft.com/visualc/">vc7</a>,
+ Microsoft Visual C++ 7.x</td>
+
+ <td valign="top">* <tt>VCVARS32.BAT</tt> or <tt>VSVARS32.BAT</tt>
+ already configured<br>
+ * Common install location: <tt>"C:\Program Files\Microsoft Visual
+ Studio .NET"</tt><br>
+ * Common install location: <tt>"C:\Program Files\Microsoft Visual
+ Studio .NET 2003"</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top" rowspan="11" colspan="1"><tt>build.sh</tt></td>
+
+ <td valign="top" rowspan="10" colspan="1">Unix, Linux, Cygwin,
+ etc.</td>
+
+ <td valign="top"><a href="http://www.hp.com/go/c++">acc</a>, HP-UX
+ aCC</td>
+
+ <td valign="top">* <tt>aCC</tt> in <tt>PATH</tt><br>
+ * <tt>uname</tt> is "HP-UX"</td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href="http://www.comeaucomputing.com">como</a>,
+ Comeau.Computing C/C++</td>
+
+ <td valign="top">* <tt>como</tt> in <tt>PATH</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href="http://gcc.gnu.org">gcc</a>, GNU GCC</td>
+
+ <td valign="top">* <tt>gcc</tt> in <tt>PATH</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href=
+ "http://www.intel.com/software/products/compilers/c60l/">intel-linux</a>,
+ Intel C++ for Linux</td>
+
+ <td valign="top">* <tt>icc</tt> in <tt>PATH</tt><br>
+ * Common install locations: <tt>"/opt/intel/compiler70"</tt>,
+ <tt>"/opt/intel/compiler60"</tt>, <tt>"/opt/intel/compiler50"</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href=
+ "http://developer.intel.com/software/products/kcc/">kcc</a>, Intel KAI
+ C++</td>
+
+ <td valign="top">* <tt>KCC</tt> in <tt>PATH</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href=
+ "http://www.borland.com/bcppbuilder/freecompiler"><tt>kylix</tt></a>,
+ <a href="http://www.borland.com/">Borland</a> C++Builder</td>
+
+ <td valign="top">* <tt>bc++</tt> in <tt>PATH</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href=
+ "http://www.sgi.com/developers/devtools/languages/mipspro.html">mipspro</a>,
+ SGI MIPSpro C</td>
+
+ <td valign="top"></td>
+ </tr>
+
+ <tr>
+ <td valign="top">sunpro, Sun Workshop 6 C++</td>
+
+ <td valign="top">* Standard install location:
+ <tt>"/opt/SUNWspro"</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href=
+ "http://www.tru64unix.compaq.com/cplus/">true64cxx</a>, Compaq C++
+ Compiler for True64 UNIX</td>
+
+ <td valign="top"></td>
+ </tr>
+
+ <tr>
+ <td valign="top"><a href=
+ "http://www-3.ibm.com/software/ad/vacpp/">vacpp</a>, IBM VisualAge
+ C++</td>
+
+ <td valign="top">* <tt>xlc</tt> in <tt>PATH</tt></td>
+ </tr>
+
+ <tr>
+ <td valign="top">MacOS X<br></td>
+
+ <td valign="top"><a href=
+ "http://developer.apple.com/tools/compilers.html">darwin</a>, Apple
+ MacOS X GCC</td>
+
+ <td valign="top">* <tt>uname</tt> is <tt>"Darwin"</tt></td>
+ </tr>
+ </table>
+
+ <p>The built executables are placed in a subdirectory specific to your
+ platform. For example, in Linux running on an Intel x86 compatible chip,
+ the executables are placed in: <tt>"bin.linuxx86"</tt>. There are two
+ executables generated: <tt>jam[.exe]</tt>, and <tt>bjam[.exe]</tt>, both
+ are the same binary but with different names. The "jam" invocation is used
+ for compatability with the Perforce Jam/MR functionality, whereas "bjam" is
+ used for the extended Boost.Build functionality.</p>
+
+ <p>The <tt>build</tt> scripts support additional invocation arguments for
+ use by developers of Boost.Jam. The extra arguments come after the toolset,
+ and can take the form of <tt>"--option"</tt> or targets for the
+ <tt>build.jam</tt> script:</p>
+ <pre>
+<build script name> [toolset] [--option+ target*]
+</pre>
+
+ <p>There is current only one available option, <tt>"--debug"</tt>, which
+ builds debugging versions of the executable. When built they are placed in
+ their own directory <tt>"bin.<platform>.debug"</tt>. To specify
+ targets without options, one can suply a special ignore option
+ <tt>"---"</tt>.</p>
+
+ <p>Currently there are two targets supported: <tt>dist</tt>, and
+ <tt>clean</tt>. Respectively they: generate packages (compressed archives)
+ as appropriate for distribution in the platform, or remove all the built
+ executables and objects.</p>
+
+ <h2><a name="core_extensions">Core Jam Extensions</a></h2>
+
+ <p>A number of enhancements have been made to the core language of Classic
+ Jam. These changes were aimed primarily at making it easier to manage the
+ complexity of a large system such as Boost.Build.</p>
+
+ <h3><a name="variable_quoting"></a>Command-line and Environment Variable
+ Quoting</h3>
+
+ <p>Classic Jam had an <a href="#variable_splitting">odd behavior</a> with
+ respect to command-line variable ( <tt>-s...</tt>) and environment variable
+ settings which made it impossible to define an arbitrary variable with
+ spaces in the value. Boost Jam remedies that by treating all such settings
+ as a single string if they are surrounded by double-quotes. Uses of this
+ feature can look interesting, since shells require quotes to keep
+ characters separated by whitespace from being treated as separate
+ arguments:</p>
+ <pre>
+jam -sMSVCNT="\"\"C:\Program Files\Microsoft Visual C++\VC98\"\"" ...
+</pre>
+
+ <p>The outer quote is for the shell. The middle quote is for Jam, to tell
+ it to take everything within those quotes literally, and the inner quotes
+ are for the shell again when paths are passed as arguments to build
+ actions. Under NT, it looks a lot more sane to use environment variables
+ before invoking jam when you have to do this sort of quoting:</p>
+ <pre>
+set MSVCNT=""C:\Program Files\Microsoft Visual C++\VC98\""
+</pre>
+
+ <h3><a name="jambase_replacement">Startup Behavior</a></h3>
+
+ <p>The Boost.Build v2 initialization behavior has been implemented. This
+ behavior only applies when the executable being invoked is called
+ "<code>bjam</code>" or, for backward-compatibility, when the
+ <code>BOOST_ROOT</code> variable is set.</p>
+
+ <ol>
+ <li>We attempt to load "boost-build.jam" by searching from the current
+ invocation directory up to the root of the file-system. This file is
+ expected to invoke the <tt>boost-build</tt> rule to indicate where the
+ Boost.Build system files are, and to load them.</li>
+
+ <li>If boost-build.jam is not found we error and exit, giving brief
+ instructions on possible errors.
+
+ <blockquote>
+ As a backward-compatibility measure for older versions of
+ Boost.Build, when the <code>BOOST_ROOT</code> variable is set, we
+ first search for <code>boost-build.jam</code> in
+ <code>$(BOOST_ROOT)/tools/build</code> and
+ <code>$(BOOST_BUILD_PATH)</code>. If found, it is loaded and
+ initialization is complete.
+ </blockquote>
+ </li>
+
+ <li>The <code>boost-build</code> rule adds its (optional) argument to the
+ front of <code>BOOST_BUILD_PATH</code>, and attempts to load
+ <code>bootstrap.jam</code> from those directories. If a relative path is
+ specified as an argument, it is treated as though it was relative to the
+ <code>boost-build.jam</code> file.</li>
+
+ <li>If the bootstrap.jam file was not found, we print a likely error
+ message and exit.</li>
+ </ol>
+
+ <h3><a name="rule_indirection">Rule Indirection</a></h3>
+
+ <p>Boost Jam allows you to call a rule whose name is held in a variable or
+ computed as the result of an expression:</p>
+ <pre>
+x = foo ;
+rule foobar { ECHO foobar ; } # a trivial rule
+$(x)bar ; # invokes foobar
+</pre>
+
+ <p>Furthermore, if the first expression expands to more than one list item,
+ everything after the first item becomes part of the first argument. This
+ allows a crude form of argument binding:</p>
+ <pre>
+# return the elements of sequence for which predicate returns non-nil
+rule filter ( sequence * : predicate + )
+{
+ local result ;
+ for local x in $(sequence)
+ {
+ if [ $(predicate) $(x) ] { result += $(x); }
+ }
+ return $(result);
+}
+# true iff x == y
+rule equal ( x y )
+{
+ if $(x) = $(y) { return true; }
+}
+# bind 3 to the first argument of equal
+ECHO [ filter 1 2 3 4 5 4 3 : equal 3 ] ; # prints "3 3"
+</pre>
+
+ <h3><a name="argument_lists">Argument lists</a></h3>
+
+ <p>You can now describe the arguments accepted by a rule, and refer to them
+ by name within the rule. For example, the following prints ``I'm sorry,
+ Dave'' to the console:</p>
+ <pre>
+rule report ( pronoun index ? : state : names + )
+{
+ local he.suffix she.suffix it.suffix = s ;
+ local I.suffix = m ;
+ local they.suffix you.suffix = re ;
+ ECHO $(pronoun)'$($(pronoun).suffix) $(state), $(names[$(index)]) ;
+}
+report I 2 : sorry : Joe Dave Pete ;
+</pre>
+
+ <p>Each name in a list of formal arguments (separated by ``<tt>:</tt>'' in
+ the rule declaration) is bound to a single element of the corresponding
+ actual argument unless followed by one of these modifiers:</p>
+
+ <table border="1" summary="Argument modifiers">
+ <tr>
+ <th>Symbol</th>
+
+ <th>Semantics of preceding symbol</th>
+ </tr>
+
+ <tr>
+ <td><tt>?</tt></td>
+
+ <td>optional</td>
+ </tr>
+
+ <tr>
+ <td><tt>*</tt></td>
+
+ <td>Bind to zero or more unbound elements of the actual argument. When
+ ``<tt>*</tt>'' appears where an argument name is expected, any number
+ of additional arguments are accepted. This feature can be used to
+ implement "varargs" rules.</td>
+ </tr>
+
+ <tr>
+ <td><tt>+</tt></td>
+
+ <td>Bind to one or more unbound elements of the actual argument.</td>
+ </tr>
+ </table>
+
+ <p>The actual and formal arguments are checked for inconsistencies, which
+ cause Jam to exit with an error code:</p>
+ <pre>
+### argument error
+# rule report ( pronoun index ? : state : names + )
+# called with: ( I 2 foo : sorry : Joe Dave Pete )
+# extra argument foo
+### argument error
+# rule report ( pronoun index ? : state : names + )
+# called with: ( I 2 : sorry )
+# missing argument names
+</pre>
+
+ <p>If you omit the list of formal arguments, all checking is bypassed as in
+ ``classic'' Jam. Argument lists drastically improve the reliability and
+ readability of your rules, however, and are <b>strongly recommended</b> for
+ any new Jam code you write.</p>
+
+ <h3><a name="module_support">Module Support</a></h3>
+
+ <p>Boost Jam introduces support for modules, which provide some rudimentary
+ namespace protection for rules and variables. A new keyword,
+ ``<tt>module</tt>'' was also introduced. The features described in this
+ section are <i>primitives</i>, meaning that they are meant to provide the
+ operations needed to write Jam rules which provide a more elegant module
+ interface.</p>
+
+ <h4><a name="module_declaration">Declaration</a></h4>
+ <pre>
+module <i>expression</i> { ... }
+</pre>
+
+ <p>Code within the <tt>{</tt> ... <tt>}</tt> executes within the module
+ named by evaluating <i>expression</i>. Rule definitions can be found in the
+ module's own namespace, and in the namespace of the global module as
+ <i>module-name</i><tt>.</tt><i>rule-name</i>, so within a module, other
+ rules in that module may always be invoked without qualification:</p>
+ <pre>
+<b>module my_module
+{</b>
+ rule salute ( x ) { ECHO $(x), world ; }
+ rule greet ( ) { salute hello ; }
+ greet ;
+<b>}
+my_module.salute</b> goodbye ;
+</pre>
+
+ <p>When an invoked rule is not found in the current module's namespace, it
+ is looked up in the namespace of the global module, so qualified calls work
+ across modules:</p>
+ <pre>
+module your_module
+{
+ rule bedtime ( ) { <b>my_module.salute</b> goodnight ; }
+}
+</pre>
+
+ <h4><a name="module_locals">Variable Scope</a></h4>
+
+ <p>Each module has its own set of dynamically nested variable scopes. When
+ execution passes from module A to module B, all the variable bindings from
+ A become unavailable, and are replaced by the bindings that belong to B.
+ This applies equally to local and global variables:</p>
+ <pre>
+module A
+{
+ x = 1 ;
+ rule f ( )
+ {
+ local y = 999 ; # becomes visible again when B.f calls A.g
+ B.f ;
+ }
+ rule g ( )
+ {
+ ECHO $(y) ; # prints "999"
+ }
+}
+module B
+{
+ y = 2 ;
+ rule f ( )
+ {
+ ECHO $(y) ; # always prints "2"
+ A.g ;
+ }
+}
+</pre>
+
+ <p>The only way to access another module's variables is by entering that
+ module:</p>
+ <pre>
+rule peek ( module-name ? : variables + )
+{
+ module $(module-name)
+ {
+ return $($(>)) ;
+ }
+}
+</pre>Note that because existing variable bindings change whenever a new
+module scope is entered, argument bindings become unavailable. That explains
+the use of "<code>$(>)</code>" in the <code>peek</code> rule above.
+
+ <h4><a name="local_rules">Local Rules</a></h4>
+ <pre>
+local rule <i>rulename...</i>
+</pre>
+
+ <p>The rule is declared locally to the current module. It is not entered in
+ the global module with qualification, and its name will not appear in the
+ result of:</p>
+ <pre>
+[ RULENAMES <i>module-name</i> ]
+</pre>
+
+ <h4><a name="RULENAMES_rule">The <tt>RULENAMES</tt> Rule</a></h4>
+ <pre>
+rule RULENAMES ( module ? )
+</pre>
+
+ <p>Returns a list of the names of all non-local rules in the given module.
+ If <tt>module</tt> is omitted, the names of all non-local rules in the
+ global module are returned.</p>
+
+ <h4><a name="VARNAMES_rule">The <tt>VARNAMES</tt> Rule</a></h4>
+ <pre>
+rule VARNAMES ( module ? )
+</pre>
+
+ <p>Returns a list of the names of all variable bindings in the given
+ module. If <tt>module</tt> is omitted, the names of all variable bindings
+ in the global module are returned. <b>Note:</b>this includes any local
+ variables in rules from the call stack which have not returned at the time
+ of the <code>VARNAMES</code> invocation.</p>
+
+ <h4><a name="IMPORT_rule">The <tt>IMPORT</tt> Rule</a></h4>
+
+ <p><tt>IMPORT</tt> allows rule name aliasing across modules:</p>
+ <pre>
+rule IMPORT ( source_module ? : source_rules *
+ : target_module ? : target_rules * )
+</pre>
+
+ <p>The <tt>IMPORT</tt> rule copies rules from the <tt>source_module</tt>
+ into the <tt>target_module</tt> as <tt>local</tt> rules. If either
+ <tt>source_module</tt> or <tt>target_module</tt> is not supplied, it refers
+ to the global module. <tt>source_rules</tt> specifies which rules from the
+ <tt>source_module</tt> to import; <tt>TARGET_RULES</tt> specifies the names
+ to give those rules in <tt>target_module</tt>. If <tt>source_rules</tt>
+ contains a name which doesn't correspond to a rule in
+ <tt>source_module</tt>, or if it contains a different number of items than
+ <tt>target_rules</tt>, an error is issued. For example,</p>
+ <pre>
+# import m1.rule1 into m2 as local rule m1-rule1.
+IMPORT m1 : rule1 : m2 : m1-rule1 ;
+# import all non-local rules from m1 into m2
+IMPORT m1 : [ RULENAMES m1 ] : m2 : [ RULENAMES m1 ] ;
+</pre>
+
+ <h4><a name="EXPORT_rule">The <tt>EXPORT</tt> Rule</a></h4>
+
+ <p><tt>EXPORT</tt> allows rule name aliasing across modules:</p>
+ <pre>
+rule EXPORT ( module ? : rules * )
+</pre>
+
+ <p>The <tt>EXPORT</tt> rule marks <tt>rules</tt> from the
+ <tt>source_module</tt> as non-local (and thus exportable). If an element of
+ <tt>rules</tt> does not name a rule in <tt>module</tt>, an error is issued.
+ For example,</p>
+ <pre>
+module X {
+ local rule r { ECHO X.r ; }
+}
+IMPORT X : r : : r ; # error - r is local in X
+EXPORT X : r ;
+IMPORT X : r : : r ; # OK.
+</pre>
+
+ <h4><a name="CALLER_MODULE_rule">The <tt>CALLER_MODULE</tt> Rule</a></h4>
+ <pre>
+rule CALLER_MODULE ( levels ? )
+</pre>
+
+ <p><tt>CALLER_MODULE</tt> returns the name of the module scope enclosing
+ the call to its caller (if levels is supplied, it is interpreted as an
+ integer number of additional levels of call stack to traverse to locate the
+ module). If the scope belongs to the global module, or if no such module
+ exists, returns the empty list. For example, the following prints "{Y}
+ {X}":</p>
+ <pre>
+module X {
+ rule get-caller { return [ CALLER_MODULE ] ; }
+ rule get-caller's-caller { return [ CALLER_MODULE 1 ] ; }
+ rule call-Y { return Y.call-X2 ; }
+}
+module Y {
+ rule call-X { return X.get-caller ; }
+ rule call-X2 { return X.get-caller's-caller ; }
+}
+callers = [ X.get-caller ] [ Y.call-X ] [ X.call-Y ] ;
+ECHO {$(callers)} ;
+</pre>
+
+ <h4><a name="DELETE_MODULE_rule">The <tt>DELETE_MODULE</tt> Rule</a></h4>
+ <pre>
+rule DELETE_MODULE ( module ? )
+</pre>
+
+ <p><tt>DELETE_MODULE</tt> removes all of the variable bindings and
+ otherwise-unreferenced rules from the given module (or the global module,
+ if no module is supplied), and returns their memory to the system.
+ <b>Note:</b> though it won't affect rules that are currently executing
+ until they complete, <code>DELETE_MODULE</code> should be used with extreme
+ care because it will wipe out any others and all variable (including locals
+ in that module) immediately. Because of the way dynamic binding works,
+ variables which are shadowed by locals will not be destroyed, so the
+ results can be really unpredictable.</p>
+
+ <h3><a name="local_foreach">Local For Loop Variables</a></h3>
+
+ <p>Boost Jam allows you to declare a local <tt>for</tt> loop control
+ variable right in the loop:</p>
+ <pre>
+x = 1 2 3 ;
+y = 4 5 6 ;
+for <b>local</b> y in $(x)
+{
+ ECHO $(y) ; # prints "1", "2", or "3"
+}
+ECHO $(y) ; # prints "4 5 6"
+</pre>
+
+ <h4><a name="negative_indexing">Negative Indexing</a></h4>
+
+ <p>Classic Jam supplies 1-based list indexing, and slicing on a closed
+ (inclusive) range:</p>
+ <pre>
+x = 1 2 3 4 5 ;
+ECHO $(x[3]) ; # prints "3"
+ECHO $(x[2-4]) ; # prints "2 3 4"
+ECHO $(x[2-]) ; # prints "2 3 4 5"
+</pre>
+
+ <p>Boost Jam adds Python-style negative indexing to access locations
+ relative to the <i>end</i> of the list.</p>
+ <pre>
+ECHO $(x[-1]) $(x[-3]) ; # prints "5 3"
+ECHO $(x[-3--1]) ; # prints "3 4 5"
+ECHO $(x[-3-4]) ; # prints "3 4"
+ECHO $(x[2--2]) ; # prints "2 3 4"
+</pre>
+
+ <p>Consistency with the 1-based, inclusive indexing of Classic Jam and the
+ use of ``<tt>-</tt>'' as the range separator make this feature a bit
+ clumsier than it would otherwise need to be, but it does work.</p>
+
+ <h4><a name="cygwin_support">Support for Cygwin</a></h4>
+
+ <p>When invoking Windows-based tools from <a href=
+ "www.cygwin.com">Cygwin</a> it can be important to pass them true
+ windows-style paths. Boost.Jam supplies the <code>:W</code> modifier which,
+ <em>under Cygwin only</em>, turns a cygwin path into a Win32 path using the
+ <a href=
+ "http://www.cygwin.com/cygwin-api/func-cygwin-conv-to-win32-path.html"><code>
+ cygwin_conv_to_win32_path</code></a> function. On other platforms, the
+ string is unchanged.</p>
+ <pre>
+x = /cygdrive/c/Program Files/Borland ;
+ECHO $(x:W) ; # prints "c:\Program Files\Borland" on Cygwin
+</pre>
+
+ <h4><a name="BINDRULE">Target Binding Detection</a></h4>
+
+ <p>Whenever a target is <a href="#binding">bound</a> to a location in the
+ filesystem, Boost Jam will look for a variable called <tt>BINDRULE</tt>
+ (first ``<tt>on</tt>'' the target being bound, then in the global module).
+ If non-empty, <tt>$(BINDRULE[1])</tt> names a rule which is called with the
+ name of the target and the path it is being bound to. The signature of the
+ rule named by <tt>$(BINDRULE[1])</tt> should match the following:</p>
+ <pre>
+rule bind-rule ( target : path )
+</pre>
+
+ <p>This facility is useful for correct header file scanning, since many
+ compilers will search for <tt>#include</tt>d files first in the directory
+ containing the file doing the <tt>#include</tt> directive.
+ <tt>$(BINDRULE)</tt> can be used to make a record of that directory.</p>
+
+ <h4><a name="FAIL_EXPECTED">Return Code Inversion</a></h4>
+
+ <p>For handling targets whose build actions are expected to fail (e.g. when
+ testing that assertions or compile-time type checkin work properly), Boost
+ Jam supplies a <tt>FAIL_EXPECTED</tt> rule in the same style as
+ <tt>NOCARE</tt>, et. al. During target updating, the return code of the
+ build actions for arguments to <tt>FAIL_EXPECTED</tt> is inverted: if it
+ fails, building of dependent targets continues as though it succeeded. If
+ it succeeds, dependent targets are skipped.</p>
+
+ <h4><a name="NOCARE">Ignoring Return Codes</a></h4>
+
+ <p>Perforce Jam supplied a <tt>NOCARE</tt> rule which is typically used for
+ header files to indicate that if they are not found, the dependent targets
+ should be built anyway. Boost Jam extends <tt>NOCARE</tt> to apply to
+ targets with build actions: if their build actions exit with a nonzero
+ return code, dependent targets will still be built.</p>
+
+ <h4><a name="RMOLD">Removing Outdated Targets</a></h4>
+ <pre>
+rule RMOLD ( targets * )
+</pre>
+
+ <p>Perforce Jam removes any target files that may exist on disk when the
+ rule used to build those targets fails. However, targets whose dependencies
+ fail to build are not removed by default. The <code>RMOLD</code> rule
+ causes its arguments to be removed if any of their dependencies fail to
+ build.</p>
+
+ <h3><a name="SUBST_rule">The <tt>SUBST</tt> Rule</a></h3>
+
+ <p><b>Note:</b> the <code>SUBST</code> rule is deprecated in favor of
+ Perforce Jam's built-in <code>MATCH</code> rule, which has been rolled into
+ Boost.Jam.</p>
+
+ <p>The behavior of the <tt>SUBST</tt> rule for regular-expression matching
+ and replacement (originally added in <a href=
+ "http://freetype.sourceforge.net/jam/index.html">FTJam</a>) has been
+ modified:</p>
+
+ <ul>
+ <li>One or more replacement patterns may be supplied. The new signature
+ for <tt>SUBST</tt> is:
+ <pre>
+SUBST ( source pattern replacements + )
+</pre>The return value is the concatenated results of applying each element
+of <tt>replacements</tt> in turn. For example, the following will print
+``<tt>[x] (y) {z}</tt>'':
+ <pre>
+ECHO [ SUBST xyz (.)(.)(.) [$1] ($2) {$3} ] ;
+</pre>
+ </li>
+
+ <li>If there is no match, <tt>SUBST</tt> now returns an empty list. In
+ FTJam, the original <tt>source</tt> string was returned, making it
+ awkward to check whether a pattern was matched.</li>
+
+ <li>Compiled regular expressions are now internally cached, making it
+ much faster to use <tt>SUBST</tt> multiple times with the same
+ string.</li>
+ </ul>
+
+ <h3><a name="JAM_VERSION">The <tt>JAM_VERSION</tt> global variable</a></h3>
+
+ <p>A predefined global variable with two elements indicates the version
+ number of Boost Jam. Boost Jam versions start at <tt>"03" "00"</tt>.
+ Earlier versions of Jam do not automatically define
+ <tt>JAM_VERSION</tt>.</p>
+
+ <h3><a name="debugging_support">Debugging Support</a></h3>
+
+ <h4><a name="BACKTRACE_rule">The BACKTRACE rule</a></h4>
+ <pre>
+rule BACKTRACE ( )
+</pre>
+
+ <p>Returns a list of quadruples: <i>filename line module rulename</i>...,
+ describing each shallower level of the call stack. This rule can be used to
+ generate useful diagnostic messages from Jam rules.</p>
+
+ <p>The <tt>-d</tt> command-line option admits new arguments:</p>
+
+ <ul>
+ <li><tt>-d+10</tt> - enables <a name="profiling"><b>profiling</b></a> of
+ rule invocations. When Jam exits, it dumps all rules invoked, their gross
+ and net times in platform-dependent units, and the number of times the
+ rule was invoked.</li>
+
+ <li><tt>-d+11</tt> - enables <a name="parse_debugging"><b>parser
+ debugging</b></a>, if Jam has been compiled with the "--debug" option to
+ the parser generator named by $(YACC).</li>
+
+ <li><tt>-d+12</tt> - enables <a name="dependency_graph"><b>dependency
+ graph output</b></a> . This feature was ``stolen'' from a version of Jam
+ modified by <a href="mailto:cmcpheeters at aw.sgi.com">Craig
+ McPheeters</a>.</li>
+ </ul>
+
+ <h3><a name="UPDATE">The <tt>UPDATE</tt> rule and changes to command line
+ handling</a></h3>
+
+ <p>Classic jam treats any non-option element of command line as a name of
+ target to be updated. This prevented more sophisticated handling of command
+ line. This is now enabled again but with additional changes to the
+ <tt>UPDATE></tt> rule to allow for the flexibility of changing the list
+ of targets to update. The <tt>UPDATE</tt> builtin rule is:</p>
+ <pre>
+rule UPDATE ( targets * )
+</pre>
+
+ <p>The rule has two effects: 1. it clears the list of targets to update,
+ and 2. causes the specified targets to be updated. If no target was
+ specified with the <tt>UPDATE</tt> rule, no targets will be updated. To
+ support changing of the update list in more usefull ways, the rule also
+ returns the targets previously in the update list. This makes it possible
+ to add targets as such:</p>
+ <pre>
+local previous-updates = [ UPDATE ] ;
+UPDATE $(previous-updates) a-new-target ;
+</pre>
+
+ <h3 id="semaphores">Semaphores</h3>
+
+ <p>It is sometimes desirable to disallow parallel execution of some
+ actions. For example:</p>
+
+ <ul>
+ <li>Old versions of <tt>yacc</tt> use files with fixed names. So, running
+ two yacc actions is dangerous.</li>
+
+ <li>One might want to perform parallel compiling, but not do parallel
+ linking, because linking is i/o bound and only gets slower.</li>
+ </ul>Craig McPeeters has extended Perforce Jam to solve such problems, and
+ that extension was integrated in Boost.Jam.
+
+ <p>Any target can be assigned a <em>semaphore</em>, by setting a variable
+ called <tt>SEMAPHORE</tt> on that target. The value of the variable is the
+ semaphore name. It must be different from names of any declared target, but
+ is arbitrary otherwise.</p>
+
+ <p>The semantic of semaphores is that in a group of targets which have the
+ same semaphore, only one can be updated at the moment, regardless of "-j"
+ option.</p>
+
+ <h3 id="w32_getreg">The W32_GETREG rule</h3>
+<pre>
+ rule W32_GETREG ( path : data ? )
+</pre>
+
+<p>
+ Defined only for win32 platform. It reads the registry of Windows.
+ 'path' is the location of the information, and 'data' is
+ the name of the value which we want to get. If 'data' is omitted,
+ the default value of 'path' will be returned. The 'path' value
+ must conform to MS key path format and must be prefixed with
+ one of the predefined root keys. As usual,
+
+<ul>
+ <li>'HKLM' is equivalent to 'HKEY_LOCAL_MACHINE'.
+ <li>'HKCU' is equivalent to 'HKEY_CURRENT_USER'.
+ <li>'HKCR' is equivalent to 'HKEY_CLASSES_ROOT'.
+</ul>
+
+<p>
+ Other predefined root keys are not supported.
+<p>
+ Currently supported data types : 'REG_DWORD', 'REG_SZ',
+ 'REG_EXPAND_SZ', 'REG_MULTI_SZ'. The data with 'REG_DWORD' type
+ will be turned into a string, 'REG_MULTI_SZ' into a list of strings,
+ and for those with 'REG_EXPAND_SZ' type environment variables
+ in it will be replaced with their defined values.
+ The data with 'REG_SZ' type and other unsupported types
+ will be put into a string without modification. If it can't
+ receive the value of the data, it just return an empty list.
+ For example,
+
+<pre>
+ local PSDK-location =
+ [ PROFILE HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MicrosoftSDK\\Directories : "Install Dir" ] ;
+</pre>
+
+ <h2><a name="jam_fundamentals">Jam Fundamentals</a></h2>
+
+ <p>This section is derived from the official Jam documentation and from my
+ experience using it and reading the Jambase rules. I repeat the information
+ here mostly because it is essential to understanding and using Jam, but is
+ not consolidated in a single place. Some of it is missing from the official
+ documentation altogether. I hope it will be useful to anyone wishing to
+ become familiar with Jam and the Boost build system.</p>
+
+ <p>· Jam ``<b>rules</b>'' are actually simple procedural entities.
+ Think of them as functions. Arguments are separated by colons.</p>
+
+ <p>· A Jam <b>target</b> is an abstract entity identified by an
+ arbitrary string. The build-in <tt>DEPENDS</tt> rule creates a link in the
+ dependency graph between the named targets.</p>
+
+ <p>· Note that the documentation for the built-in <tt>INCLUDES</tt>
+ rule is incorrect: <tt>INCLUDES targets1 : targets2</tt> causes everything
+ that depends on a member of <i>targets1</i> to depend on all members of
+ <i>targets2</i>. It does this in an odd way, by tacking <i>targets2</i>
+ onto a special tail section in the dependency list of everything in
+ <i>targets1</i>. It seems to be OK to create circular dependencies this
+ way; in fact, it appears to be the ``right thing to do'' when a single
+ build action produces both <i>targets1</i> and <i>targets2</i>.</p>
+
+ <p>· When a rule is invoked, if there are <b><tt>actions</tt></b>
+ declared with the same name as the rule, the <tt>actions</tt> are added to
+ the updating actions for the target identified by the rule's first
+ argument. It is actually possible to invoke an undeclared rule if
+ corresponding actions are declared: the rule is treated as empty.</p>
+
+ <p>· <a name="binding">Targets</a> (other than <tt>NOTFILE</tt>
+ targets) are associated with paths in the file system through a process
+ called <a href="./Jam.html#binding">binding</a>. Binding is a process of
+ searching for a file with the same name as the target (sans grist), based
+ on the settings of the <a href="#target_specific">target-specific</a>
+ <tt>SEARCH</tt> and <tt>LOCATE</tt> variables.</p>
+
+ <p>· <a name="target_specific">In addition to</a> local and global
+ variables, jam allows you to set a variable <tt><b>on</b></tt> a target.
+ Target-specific variable values can usually not be read, and take effect
+ <i>only</i> in the following contexts:</p>
+
+ <ul>
+ <li>In updating <tt>actions</tt>, variable values are first looked up
+ <tt><b>on</b></tt> the target named by the first argument (the target
+ being updated). Because Jam builds its entire dependency tree before
+ executing <tt>actions</tt>, Jam rules make target-specific variable
+ settings as a way of supplying parameters to the corresponding
+ <tt>actions</tt>.</li>
+
+ <li>Binding is controlled <i>entirely</i> by the target-specific setting
+ of the <tt>SEARCH</tt> and <tt>LOCATE</tt> variables, as described
+ <a href="./Jam.html#search">here</a>.</li>
+
+ <li>In the special rule used for <a href="./Jam.html#hdrscan">header file
+ scanning</a>, variable values are first looked up <tt><b>on</b></tt> the
+ target named by the rule's first argument (the source file being
+ scanned).</li>
+ </ul>
+
+ <p>· The ``<b>bound value</b>'' of a variable is the path associated
+ with the target named by the variable. In build <tt>actions</tt>, the first
+ two arguments are automatically replaced with their bound values.
+ Target-specific variables can be selectively replaced by their bound values
+ using the <a href="./Jam.html#actionmods">bind</a> action modifier.</p>
+
+ <p>· Note that the term ``binding'' as used in the Jam documentation
+ indicates a phase of processing that includes three sub-phases:
+ <i>binding</i> (yes!), update determination, and header file scanning. The
+ repetition of the term ``binding'' can lead to some confusion. In
+ particular, the <a href="./Jam.html#bindingmods">Modifying Binding</a>
+ section in the Jam documentation should probably be titled ``Modifying
+ Update Determination''.</p>
+
+ <p>· ``Grist'' is just a string prefix of the form
+ <tt><</tt><i>characters</i><tt>></tt>. It is used in Jam to create
+ unique target names based on simpler names. For example, the file name
+ ``<tt>test.exe</tt>'' may be used by targets in separate subprojects, or
+ for the debug and release variants of the ``same'' abstract target. Each
+ distinct target bound to a file called ``<tt>test.exe</tt>'' has its own
+ unique grist prefix. The Boost build system also takes full advantage of
+ Jam's ability to divide strings on grist boundaries, sometimes
+ concatenating multiple gristed elements at the beginning of a string. Grist
+ is used instead of identifying targets with absolute paths for two
+ reasons:</p>
+
+ <ol>
+ <li>The location of targets cannot always be derived solely from what the
+ user puts in a Jamfile, but sometimes depends also on the <a href=
+ "#binding">binding</a> process. Some mechanism to distinctly identify
+ targets with the same name is still needed.</li>
+
+ <li>Grist allows us to use a uniform abstract identifier for each built
+ target, regardless of target file location (as allowed by setting
+ <tt>ALL_LOCATE_TARGET</tt>.</li>
+ </ol>
+
+ <p>When grist is extracted from a name with
+ <tt>$(</tt><i>var</i><tt>:G)</tt>, the result includes the leading and
+ trailing angle brackets. When grist is added to a name with
+ <tt>$(</tt><i>var</i><tt>:G=</tt><i>expr</i><tt>)</tt>, existing grist is
+ first stripped. Then, if <i>expr</i> is non-empty, leading <tt><</tt>s
+ and trailing <tt>></tt>s are added if necessary to form an expression of
+ the form <tt><</tt><i>expr2</i><tt>></tt>;
+ <tt><</tt><i>expr2</i><tt>></tt> is then prepended.</p>
+
+ <p>· <a name="variable_splitting">When Jam</a> is invoked it imports
+ all environment variable settings into corresponding Jam variables,
+ followed by all command-line (<tt>-s...</tt>) variable settings. Variables
+ whose name ends in <tt>PATH</tt>, <tt>Path</tt>, or <tt>path</tt> are split
+ into string lists on OS-specific path-list separator boundaries (e.g.
+ "<tt>:</tt>" for UNIX and "<tt>;</tt>" for Windows). All other variables
+ are split on space (" ") boundaries. Boost Jam modifies that behavior by
+ allowing variables to be <a href="#variable_quoting">quoted</a>.</p>
+
+ <p>· A variable whose value is an empty list <i>or</i> which
+ consists entirely of empty strings has a negative logical value. Thus, for
+ example, code like the following allows a sensible non-empty default which
+ can easily be overridden by the user:</p>
+ <pre>
+MESSAGE ?= starting jam... ;
+if $(MESSAGE) { ECHO The message is: $(MESSAGE) ; }
+</pre>
+
+ <p>If the user wants a specific message, he invokes jam with
+ <tt>"-sMESSAGE=</tt><i>message text</i><tt>"</tt>. If he wants no message,
+ he invokes jam with <tt>-sMESSAGE=</tt> and nothing at all is printed.</p>
+
+ <p>· The parsing of command line options in Jam can be rather
+ unintuitive, with regards to how other Unix programs accept options. There
+ are two variants accepted as valid for an option:</p>
+
+ <ol>
+ <li><tt>-xvalue</tt>, and</li>
+
+ <li><tt>-x value</tt>.</li>
+ </ol>
+
+ <p>Please also read <a href="./Jam.html">The Jam language reference</a> for
+ the additional details.</p>
+ <hr>
+
+ <p>Revised
+ <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
+ 18 November, 2003
+ <!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
+
+ <p>Copyright 2003-2004 Rene Rivera, David Abrahams, Vladimir Prus.</p>
+
+ <p>Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or <a href="http://www.boost.org/LICENSE_1_0.txt">
+ http://www.boost.org/LICENSE_1_0.txt)</a></p>
+</body>
+</html>
Added: boost-jam/boost-build/branches/upstream/current/jam_src/jam.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/jam.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/jam.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,467 @@
+/*
+ * /+\
+ * +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ * \+/
+ *
+ * This file is part of jam.
+ *
+ * License is hereby granted to use this software and distribute it
+ * freely, as long as this copyright notice is retained and modifications
+ * are clearly marked.
+ *
+ * ALL WARRANTIES ARE HEREBY DISCLAIMED.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * jam.c - make redux
+ *
+ * See Jam.html for usage information.
+ *
+ * These comments document the code.
+ *
+ * The top half of the code is structured such:
+ *
+ * jam
+ * / | \
+ * +---+ | \
+ * / | \
+ * jamgram option \
+ * / | \ \
+ * / | \ \
+ * / | \ |
+ * scan | compile make
+ * | | / | \ / | \
+ * | | / | \ / | \
+ * | | / | \ / | \
+ * jambase parse | rules search make1
+ * | | | \
+ * | | | \
+ * | | | \
+ * builtins timestamp command execute
+ * |
+ * |
+ * |
+ * filesys
+ *
+ *
+ * The support routines are called by all of the above, but themselves
+ * are layered thus:
+ *
+ * variable|expand
+ * / | | |
+ * / | | |
+ * / | | |
+ * lists | | pathsys
+ * \ | |
+ * \ | |
+ * \ | |
+ * newstr |
+ * \ |
+ * \ |
+ * \ |
+ * hash
+ *
+ * Roughly, the modules are:
+ *
+ * builtins.c - jam's built-in rules
+ * command.c - maintain lists of commands
+ * compile.c - compile parsed jam statements
+ * execunix.c - execute a shell script on UNIX
+ * execvms.c - execute a shell script, ala VMS
+ * expand.c - expand a buffer, given variable values
+ * file*.c - scan directories and archives on *
+ * hash.c - simple in-memory hashing routines
+ * hdrmacro.c - handle header file parsing for filename macro definitions
+ * headers.c - handle #includes in source files
+ * jambase.c - compilable copy of Jambase
+ * jamgram.y - jam grammar
+ * lists.c - maintain lists of strings
+ * make.c - bring a target up to date, once rules are in place
+ * make1.c - execute command to bring targets up to date
+ * newstr.c - string manipulation routines
+ * option.c - command line option processing
+ * parse.c - make and destroy parse trees as driven by the parser
+ * path*.c - manipulate file names on *
+ * hash.c - simple in-memory hashing routines
+ * regexp.c - Henry Spencer's regexp
+ * rules.c - access to RULEs, TARGETs, and ACTIONs
+ * scan.c - the jam yacc scanner
+ * search.c - find a target along $(SEARCH) or $(LOCATE)
+ * timestamp.c - get the timestamp of a file or archive member
+ * variable.c - handle jam multi-element variables
+ *
+ * 05/04/94 (seiwald) - async multiprocess (-j) support
+ * 02/08/95 (seiwald) - -n implies -d2.
+ * 02/22/95 (seiwald) - -v for version info.
+ * 09/11/00 (seiwald) - PATCHLEVEL folded into VERSION.
+ * 01/10/01 (seiwald) - pathsys.h split from filesys.h
+ */
+
+# include "jam.h"
+# include "option.h"
+# include "patchlevel.h"
+
+/* These get various function declarations. */
+
+# include "lists.h"
+# include "parse.h"
+# include "variable.h"
+# include "compile.h"
+# include "builtins.h"
+# include "rules.h"
+# include "newstr.h"
+# include "scan.h"
+# include "timestamp.h"
+# include "make.h"
+# include "strings.h"
+# include "expand.h"
+
+/* Macintosh is "special" */
+
+# ifdef OS_MAC
+# include <QuickDraw.h>
+# endif
+
+/* And UNIX for this */
+
+# ifdef unix
+# include <sys/utsname.h>
+# endif
+
+struct globs globs = {
+ 0, /* noexec */
+ 1, /* jobs */
+ 0, /* quitquick */
+ 0, /* newestfirst */
+# ifdef OS_MAC
+ { 0, 0 }, /* debug - suppress tracing output */
+# else
+ { 0, 1 }, /* debug ... */
+# endif
+ 0 /* output commands, not run them */
+} ;
+
+/* Symbols to be defined as true for use in Jambase */
+
+static char *othersyms[] = { OSMAJOR, OSMINOR, OSPLAT, JAMVERSYM, 0 } ;
+
+/* Known for sure:
+ * mac needs arg_enviro
+ * OS2 needs extern environ
+ */
+
+# ifdef OS_MAC
+# define use_environ arg_environ
+# ifdef MPW
+QDGlobals qd;
+# endif
+# endif
+
+/* on Win32-LCC */
+# if defined( OS_NT ) && defined( __LCC__ )
+# define use_environ _environ
+# endif
+
+# if defined( __MWERKS__)
+# define use_environ _environ
+extern char **_environ;
+#endif
+
+# ifndef use_environ
+# define use_environ environ
+# if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT )
+extern char **environ;
+# endif
+# endif
+
+# if YYDEBUG != 0
+extern int yydebug;
+# endif
+
+#ifndef NDEBUG
+static void run_unit_tests()
+{
+# if defined( USE_EXECNT )
+ extern void execnt_unit_test();
+ execnt_unit_test();
+# endif
+ string_unit_test();
+ var_expand_unit_test();
+}
+#endif
+
+int main( int argc, char **argv, char **arg_environ )
+{
+ int n;
+ char *s;
+ struct option optv[N_OPTS];
+ const char *all = "all";
+ int anyhow = 0;
+ int status;
+ int arg_c = argc;
+ char ** arg_v = argv;
+
+# ifdef OS_MAC
+ InitGraf(&qd.thePort);
+# endif
+
+ argc--, argv++;
+
+ if( ( n = getoptions( argc, argv, "-:d:j:f:gs:t:ano:qv", optv ) ) < 0 )
+ {
+ printf( "\nusage: jam [ options ] targets...\n\n" );
+
+ printf( "-a Build all targets, even if they are current.\n" );
+ printf( "-dx Set the debug level to x (0-9).\n" );
+ printf( "-fx Read x instead of Jambase.\n" );
+ /* printf( "-g Build from newest sources first.\n" ); */
+ printf( "-jx Run up to x shell commands concurrently.\n" );
+ printf( "-n Don't actually execute the updating actions.\n" );
+ printf( "-ox Write the updating actions to file x.\n" );
+ printf( "-q Quit quickly as soon as a target fails.\n" );
+ printf( "-sx=y Set variable x=y, overriding environment.\n" );
+ printf( "-tx Rebuild x, even if it is up-to-date.\n" );
+ printf( "-v Print the version of jam and exit.\n" );
+ printf( "--x Option is ignored.\n\n" );
+
+ exit( EXITBAD );
+ }
+
+ argc -= n, argv += n;
+
+ /* Version info. */
+
+ if( ( s = getoptval( optv, 'v', 0 ) ) )
+ {
+ printf( "Boost.Jam " );
+ printf( "Version %s. %s.\n", VERSION, OSMINOR );
+ printf( " Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. \n" );
+ printf( " Copyright 2001 David Turner.\n" );
+ printf( " Copyright 2001-2004 David Abrahams.\n" );
+ printf( " Copyright 2002-2004 Rene Rivera.\n" );
+
+ return EXITOK;
+ }
+
+ /* Pick up interesting options */
+
+ if( ( s = getoptval( optv, 'n', 0 ) ) )
+ globs.noexec++, globs.debug[2] = 1;
+
+ if( ( s = getoptval( optv, 'q', 0 ) ) )
+ globs.quitquick = 1;
+ if( ( s = getoptval( optv, 'a', 0 ) ) )
+ anyhow++;
+
+ if( ( s = getoptval( optv, 'j', 0 ) ) )
+ globs.jobs = atoi( s );
+
+ if( ( s = getoptval( optv, 'g', 0 ) ) )
+ globs.newestfirst = 1;
+
+ /* Turn on/off debugging */
+
+ for( n = 0; s = getoptval( optv, 'd', n ); n++ )
+ {
+ int i;
+
+ /* First -d, turn off defaults. */
+
+ if( !n )
+ for( i = 0; i < DEBUG_MAX; i++ )
+ globs.debug[i] = 0;
+
+ i = atoi( s );
+
+ if( i < 0 || i >= DEBUG_MAX )
+ {
+ printf( "Invalid debug level '%s'.\n", s );
+ continue;
+ }
+
+ /* n turns on levels 1-n */
+ /* +n turns on level n */
+
+ if( *s == '+' )
+ globs.debug[i] = 1;
+ else while( i )
+ globs.debug[i--] = 1;
+ }
+
+#ifndef NDEBUG
+ run_unit_tests();
+#endif
+#if YYDEBUG != 0
+ if ( DEBUG_PARSE )
+ yydebug = 1;
+#endif
+
+ /* Set JAMDATE first */
+
+ {
+ char *date;
+ time_t clock;
+ time( &clock );
+ date = newstr( ctime( &clock ) );
+
+ /* Trim newline from date */
+
+ if( strlen( date ) == 25 )
+ date[ 24 ] = 0;
+
+ var_set( "JAMDATE", list_new( L0, newstr( date ) ), VAR_SET );
+ }
+
+
+ {
+ /* Pleace don't change the following line. The 'bump_version.py' script
+ expect a specific format of it. */
+ char *major_version = "03", *minor_version = "01", *changenum = "10";
+ var_set( "JAM_VERSION",
+ list_new( list_new( list_new( L0, newstr( major_version ) ),
+ newstr( minor_version ) ),
+ newstr( changenum ) ),
+ VAR_SET );
+ }
+
+ /* And JAMUNAME */
+# ifdef unix
+ {
+ struct utsname u;
+
+ if( uname( &u ) >= 0 )
+ {
+ var_set( "JAMUNAME",
+ list_new(
+ list_new(
+ list_new(
+ list_new(
+ list_new( L0,
+ newstr( u.sysname ) ),
+ newstr( u.nodename ) ),
+ newstr( u.release ) ),
+ newstr( u.version ) ),
+ newstr( u.machine ) ), VAR_SET );
+ }
+ }
+# endif /* unix */
+
+ /* load up environment variables */
+
+ var_defines( use_environ );
+
+ /*
+ * Jam defined variables OS, OSPLAT
+ * We load them after environment, so that
+ * setting OS in environment does not
+ * change Jam notion of the current platform.
+ */
+
+ var_defines( othersyms );
+
+
+ /* Load up variables set on command line. */
+
+ for( n = 0; s = getoptval( optv, 's', n ); n++ )
+ {
+ char *symv[2];
+ symv[0] = s;
+ symv[1] = 0;
+ var_defines( symv );
+ }
+
+ /* Set the ARGV to reflect the complete list of arguments of invocation. */
+
+ for ( n = 0; n < arg_c; ++n )
+ {
+ var_set( "ARGV", list_new( L0, newstr( arg_v[n] ) ), VAR_APPEND );
+ }
+
+ /* Initialize built-in rules */
+
+ load_builtins();
+
+ /* Add the targets in the command line to update list */
+
+ for ( n = 0; n < argc; ++n )
+ {
+ mark_target_for_updating(argv[n]);
+ }
+
+ /* Parse ruleset */
+
+ {
+ FRAME frame[1];
+ frame_init( frame );
+ for( n = 0; s = getoptval( optv, 'f', n ); n++ )
+ parse_file( s, frame );
+
+ if( !n )
+ parse_file( "+", frame );
+ }
+
+ status = yyanyerrors();
+
+ /* Manually touch -t targets */
+
+ for( n = 0; s = getoptval( optv, 't', n ); n++ )
+ touchtarget( s );
+
+ /* If an output file is specified, set globs.cmdout to that */
+
+ if( s = getoptval( optv, 'o', 0 ) )
+ {
+ if( !( globs.cmdout = fopen( s, "w" ) ) )
+ {
+ printf( "Failed to write to '%s'\n", s );
+ exit( EXITBAD );
+ }
+ globs.noexec++;
+ }
+
+ /* Now make target */
+
+ {
+ LIST* targets = targets_to_update();
+ if ( !targets )
+ {
+ status |= make( 1, &all, anyhow );
+ }
+ else
+ {
+ int targets_count = list_length(targets);
+ const char **targets2 = (const char **)malloc(targets_count * sizeof(char *));
+ int n = 0;
+ for ( ; targets; targets = list_next(targets) )
+ {
+ targets2[n++] = targets->string;
+ }
+ status |= make( targets_count, targets2, anyhow );
+ free(targets);
+ }
+ }
+
+
+ if ( DEBUG_PROFILE )
+ profile_dump();
+
+ /* Widely scattered cleanup */
+
+ var_done();
+ donerules();
+ donestamps();
+ donestr();
+
+ /* close cmdout */
+
+ if( globs.cmdout )
+ fclose( globs.cmdout );
+
+ return status ? EXITBAD : EXITOK;
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/jam.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/jam.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/jam.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,531 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * jam.h - includes and globals for jam
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 04/21/94 (seiwald) - DGUX is __DGUX__, not just __DGUX.
+ * 05/04/94 (seiwald) - new globs.jobs (-j jobs)
+ * 11/01/94 (wingerd) - let us define path of Jambase at compile time.
+ * 12/30/94 (wingerd) - changed command buffer size for NT (MS-DOS shell).
+ * 02/22/95 (seiwald) - Jambase now in /usr/local/lib.
+ * 04/30/95 (seiwald) - FreeBSD added. Live Free or Die.
+ * 05/10/95 (seiwald) - SPLITPATH character set up here.
+ * 08/20/95 (seiwald) - added LINUX.
+ * 08/21/95 (seiwald) - added NCR.
+ * 10/23/95 (seiwald) - added SCO.
+ * 01/03/96 (seiwald) - SINIX (nixdorf) added.
+ * 03/13/96 (seiwald) - Jambase now compiled in; remove JAMBASE variable.
+ * 04/29/96 (seiwald) - AIX now has 31 and 42 OSVERs.
+ * 11/21/96 (peterk) - added BeOS with MW CW mwcc
+ * 12/21/96 (seiwald) - OSPLAT now defined for NT.
+ * 07/19/99 (sickel) - Mac OS X Server and Client support added
+ * 02/18/00 (belmonte)- Support for Cygwin.
+ * 09/12/00 (seiwald) - OSSYMS split to OSMAJOR/OSMINOR/OSPLAT
+ * 12/29/00 (seiwald) - OSVER dropped.
+ */
+
+#ifndef JAM_H_VP_2003_08_01
+#define JAM_H_VP_2003_08_01
+/*
+ * VMS, OPENVMS
+ */
+
+# ifdef VMS
+
+# include <types.h>
+# include <file.h>
+# include <stat.h>
+# include <stdio.h>
+# include <ctype.h>
+# include <stdlib.h>
+# include <signal.h>
+# include <string.h>
+# include <time.h>
+# include <unistd.h>
+# include <unixlib.h>
+
+# define OSMINOR "OS=VMS"
+# define OSMAJOR "VMS=true"
+# define OS_VMS
+# define MAXLINE 1024 /* longest 'together' actions */
+# define SPLITPATH ','
+# define EXITOK 1
+# define EXITBAD 0
+# define DOWNSHIFT_PATHS
+
+/* This may be inaccurate */
+# ifndef __DECC
+# define OSPLAT "OSPLAT=VAX"
+# endif
+
+# endif
+
+/*
+ * Windows NT
+ */
+
+# ifdef NT
+
+# include <fcntl.h>
+# include <stdlib.h>
+# include <stdio.h>
+# include <ctype.h>
+# include <malloc.h>
+# ifndef __MWERKS__
+# include <memory.h>
+#endif
+# include <signal.h>
+# include <string.h>
+# include <time.h>
+
+# define OSMAJOR "NT=true"
+# define OSMINOR "OS=NT"
+# define OS_NT
+# define SPLITPATH ';'
+/* Windows NT 3.51 only allows 996 chars per line, but we deal */
+/* with problem in "execnt.c". */
+# define MAXLINE (maxline()) /* longest 'together' actions */
+# define USE_EXECNT
+# define USE_PATHUNIX
+# define PATH_DELIM '\\'
+# define DOWNSHIFT_PATHS
+
+/* AS400 cross-compile from NT */
+
+# ifdef AS400
+# undef OSMINOR
+# undef OSMAJOR
+# define OSMAJOR "AS400=true"
+# define OSMINOR "OS=AS400"
+# define OS_AS400
+# endif
+
+# endif
+
+/*
+ * Windows MingW32
+ */
+
+# ifdef MINGW
+
+# include <fcntl.h>
+# include <stdlib.h>
+# include <stdio.h>
+# include <ctype.h>
+# include <malloc.h>
+# include <memory.h>
+# include <signal.h>
+# include <string.h>
+# include <time.h>
+
+# define OSMAJOR "MINGW=true"
+# define OSMINOR "OS=MINGW"
+# define OS_NT
+# define SPLITPATH ';'
+# define MAXLINE 996 /* longest 'together' actions */
+# define USE_EXECUNIX
+# define USE_PATHUNIX
+# define PATH_DELIM '\\'
+# define DOWNSHIFT_PATHS
+
+# endif
+
+/*
+ * OS2
+ */
+
+# ifdef __OS2__
+
+# include <fcntl.h>
+# include <stdlib.h>
+# include <stdio.h>
+# include <ctype.h>
+# include <malloc.h>
+# include <signal.h>
+# include <string.h>
+# include <time.h>
+
+# define OSMAJOR "OS2=true"
+# define OSMINOR "OS=OS2"
+# define OS_OS2
+# define SPLITPATH ';'
+# define MAXLINE 996 /* longest 'together' actions */
+# define USE_EXECUNIX
+# define USE_PATHUNIX
+# define PATH_DELIM '\\'
+# define DOWNSHIFT_PATHS
+
+# ifdef __EMX__
+# define USE_FILEUNIX
+# endif
+
+# endif
+
+/*
+ * Macintosh MPW
+ */
+
+# ifdef macintosh
+
+# include <time.h>
+# include <stdlib.h>
+# include <string.h>
+# include <stdio.h>
+
+# define OSMAJOR "MAC=true"
+# define OSMINOR "OS=MAC"
+# define OS_MAC
+# define SPLITPATH ','
+
+# endif
+
+/*
+ * God fearing UNIX
+ */
+
+# ifndef OSMINOR
+
+# define OSMAJOR "UNIX=true"
+# define USE_EXECUNIX
+# define USE_FILEUNIX
+# define USE_PATHUNIX
+# define PATH_DELIM '/'
+
+# ifdef _AIX
+# define unix
+# define OSMINOR "OS=AIX"
+# define OS_AIX
+# define NO_VFORK
+# endif
+# ifdef AMIGA
+# define OSMINOR "OS=AMIGA"
+# define OS_AMIGA
+# endif
+# ifdef __BEOS__
+# define unix
+# define OSMINOR "OS=BEOS"
+# define OS_BEOS
+# define NO_VFORK
+# endif
+# ifdef __bsdi__
+# define OSMINOR "OS=BSDI"
+# define OS_BSDI
+# endif
+# if defined (COHERENT) && defined (_I386)
+# define OSMINOR "OS=COHERENT"
+# define OS_COHERENT
+# define NO_VFORK
+# endif
+# if defined(__cygwin__) || defined(__CYGWIN__)
+# define OSMINOR "OS=CYGWIN"
+# define OS_CYGWIN
+# endif
+# ifdef __FreeBSD__
+# define OSMINOR "OS=FREEBSD"
+# define OS_FREEBSD
+# endif
+# ifdef __DGUX__
+# define OSMINOR "OS=DGUX"
+# define OS_DGUX
+# endif
+# ifdef __hpux
+# define OSMINOR "OS=HPUX"
+# define OS_HPUX
+# endif
+# ifdef __OPENNT
+# define unix
+# define OSMINOR "OS=INTERIX"
+# define OS_INTERIX
+# define NO_VFORK
+# endif
+# ifdef __sgi
+# define OSMINOR "OS=IRIX"
+# define OS_IRIX
+# define NO_VFORK
+# endif
+# ifdef __ISC
+# define OSMINOR "OS=ISC"
+# define OS_ISC
+# define NO_VFORK
+# endif
+# ifdef linux
+# define OSMINOR "OS=LINUX"
+# define OS_LINUX
+# endif
+# ifdef __Lynx__
+# define OSMINOR "OS=LYNX"
+# define OS_LYNX
+# define NO_VFORK
+# define unix
+# endif
+# ifdef __MACHTEN__
+# define OSMINOR "OS=MACHTEN"
+# define OS_MACHTEN
+# endif
+# ifdef mpeix
+# define unix
+# define OSMINOR "OS=MPEIX"
+# define OS_MPEIX
+# define NO_VFORK
+# endif
+# ifdef __MVS__
+# define unix
+# define OSMINOR "OS=MVS"
+# define OS_MVS
+# endif
+# ifdef _ATT4
+# define OSMINOR "OS=NCR"
+# define OS_NCR
+# endif
+# ifdef __NetBSD__
+# define unix
+# define OSMINOR "OS=NETBSD"
+# define OS_NETBSD
+# define NO_VFORK
+# endif
+# ifdef __QNX__
+# ifdef __QNXNTO__
+# define OSMINOR "OS=QNXNTO"
+# define OS_QNXNTO
+# else
+# define unix
+# define OSMINOR "OS=QNX"
+# define OS_QNX
+# define NO_VFORK
+# define MAXLINE 996
+# endif
+# endif
+# ifdef NeXT
+# ifdef __APPLE__
+# define OSMINOR "OS=RHAPSODY"
+# define OS_RHAPSODY
+# else
+# define OSMINOR "OS=NEXT"
+# define OS_NEXT
+# endif
+# endif
+# ifdef __APPLE__
+# define unix
+# define OSMINOR "OS=MACOSX"
+# define OS_MACOSX
+# endif
+# ifdef __osf__
+# define OSMINOR "OS=OSF"
+# define OS_OSF
+# endif
+# ifdef _SEQUENT_
+# define OSMINOR "OS=PTX"
+# define OS_PTX
+# endif
+# ifdef M_XENIX
+# define OSMINOR "OS=SCO"
+# define OS_SCO
+# define NO_VFORK
+# endif
+# ifdef sinix
+# define unix
+# define OSMINOR "OS=SINIX"
+# define OS_SINIX
+# endif
+# ifdef sun
+# if defined(__svr4__) || defined(__SVR4)
+# define OSMINOR "OS=SOLARIS"
+# define OS_SOLARIS
+# else
+# define OSMINOR "OS=SUNOS"
+# define OS_SUNOS
+# endif
+# endif
+# ifdef ultrix
+# define OSMINOR "OS=ULTRIX"
+# define OS_ULTRIX
+# endif
+# ifdef _UNICOS
+# define OSMINOR "OS=UNICOS"
+# define OS_UNICOS
+# endif
+# if defined(__USLC__) && !defined(M_XENIX)
+# define OSMINOR "OS=UNIXWARE"
+# define OS_UNIXWARE
+# endif
+# ifdef __OpenBSD__
+# define OSMINOR "OS=OPENBSD"
+# define OS_OPENBSD
+# define unix
+# endif
+# ifndef OSMINOR
+# define OSMINOR "OS=UNKNOWN"
+# endif
+
+/* All the UNIX includes */
+
+# include <sys/types.h>
+# include <sys/stat.h>
+
+# ifndef OS_MPEIX
+# include <sys/file.h>
+# endif
+
+# include <fcntl.h>
+# include <stdio.h>
+# include <ctype.h>
+# include <signal.h>
+# include <string.h>
+# include <time.h>
+
+# ifndef OS_QNX
+# include <memory.h>
+# endif
+
+# ifndef OS_ULTRIX
+# include <stdlib.h>
+# endif
+
+# if !defined(OS_BSDI) && \
+ !defined(OS_FREEBSD) && \
+ !defined(OS_NEXT) && \
+ !defined(OS_MACHTEN) && \
+ !defined(OS_MACOSX) && \
+ !defined(OS_RHAPSODY) && \
+ !defined(OS_MVS) && \
+ !defined(OS_OPENBSD)
+# include <malloc.h>
+# endif
+
+# endif
+
+/*
+ * OSPLAT definitions - suppressed when it's a one-of-a-kind
+ */
+
+# if defined( _M_PPC ) || \
+ defined( PPC ) || \
+ defined( ppc ) || \
+ defined( __powerpc__ ) || \
+ defined( __ppc__ )
+# define OSPLAT "OSPLAT=PPC"
+# endif
+
+# if defined( _ALPHA_ ) || \
+ defined( __alpha__ )
+# define OSPLAT "OSPLAT=AXP"
+# endif
+
+# if defined( _i386_ ) || \
+ defined( __i386__ ) || \
+ defined( _M_IX86 )
+# if !defined( OS_FREEBSD ) && \
+ !defined( OS_OS2 ) && \
+ !defined( OS_AS400 )
+# define OSPLAT "OSPLAT=X86"
+# endif
+# endif
+
+# ifdef __sparc__
+# if !defined( OS_SUNOS ) && \
+ !defined( OS_SOLARIS )
+# define OSPLAT "OSPLAT=SPARC"
+# endif
+# endif
+
+# ifdef __mips__
+# if !defined( OS_SGI )
+# define OSPLAT "OSPLAT=MIPS"
+# endif
+# endif
+
+# ifdef __arm__
+# define OSPLAT "OSPLAT=ARM"
+# endif
+
+# if defined( __ia64__ ) || defined( __IA64__ )
+# define OSPLAT "OSPLAT=IA64"
+# endif
+
+# ifdef __s390__
+# define OSPLAT "OSPLAT=390"
+# endif
+
+# ifndef OSPLAT
+# define OSPLAT ""
+# endif
+
+/*
+ * Jam implementation misc.
+ */
+
+# ifndef MAXLINE
+# define MAXLINE 102400 /* longest 'together' actions' */
+# endif
+
+# ifndef EXITOK
+# define EXITOK 0
+# define EXITBAD 1
+# endif
+
+# ifndef SPLITPATH
+# define SPLITPATH ':'
+# endif
+
+/* You probably don't need to muck with these. */
+
+# define MAXSYM 1024 /* longest symbol in the environment */
+# define MAXJPATH 1024 /* longest filename */
+
+# define MAXJOBS 64 /* silently enforce -j limit */
+# define MAXARGC 32 /* words in $(JAMSHELL) */
+
+/* Jam private definitions below. */
+
+# define DEBUG_MAX 14
+
+struct globs {
+ int noexec;
+ int jobs;
+ int quitquick;
+ int newestfirst; /* build newest sources first */
+ char debug[DEBUG_MAX];
+ FILE *cmdout; /* print cmds, not run them */
+} ;
+
+extern struct globs globs;
+
+# define DEBUG_MAKE ( globs.debug[ 1 ] ) /* show actions when executed */
+# define DEBUG_MAKEQ ( globs.debug[ 2 ] ) /* show even quiet actions */
+# define DEBUG_EXEC ( globs.debug[ 2 ] ) /* show text of actons */
+# define DEBUG_MAKEPROG ( globs.debug[ 3 ] ) /* show progress of make0 */
+# define DEBUG_BIND ( globs.debug[ 3 ] ) /* show when files bound */
+
+# define DEBUG_EXECCMD ( globs.debug[ 4 ] ) /* show execcmds()'s work */
+
+# define DEBUG_COMPILE ( globs.debug[ 5 ] ) /* show rule invocations */
+
+# define DEBUG_HEADER ( globs.debug[ 6 ] ) /* show result of header scan */
+# define DEBUG_BINDSCAN ( globs.debug[ 6 ] ) /* show result of dir scan */
+# define DEBUG_SEARCH ( globs.debug[ 6 ] ) /* show attempts at binding */
+
+# define DEBUG_VARSET ( globs.debug[ 7 ] ) /* show variable settings */
+# define DEBUG_VARGET ( globs.debug[ 8 ] ) /* show variable fetches */
+# define DEBUG_VAREXP ( globs.debug[ 8 ] ) /* show variable expansions */
+# define DEBUG_IF ( globs.debug[ 8 ] ) /* show 'if' calculations */
+# define DEBUG_LISTS ( globs.debug[ 9 ] ) /* show list manipulation */
+# define DEBUG_SCAN ( globs.debug[ 9 ] ) /* show scanner tokens */
+# define DEBUG_MEM ( globs.debug[ 9 ] ) /* show memory use */
+
+# define DEBUG_PROFILE ( globs.debug[ 10 ] ) /* dump rule execution times */
+# define DEBUG_PARSE ( globs.debug[ 11 ] ) /* debug parsing */
+# define DEBUG_GRAPH ( globs.debug[ 12 ] ) /* debug dependencies */
+# define DEBUG_FATE ( globs.debug[ 13 ] ) /* show changes to fate in make0() */
+
+#endif
Added: boost-jam/boost-build/branches/upstream/current/jam_src/jambase.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/jambase.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/jambase.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1678 @@
+/* Generated by mkjambase from Jambase */
+char *jambase[] = {
+/* Jambase */
+"if $(NT)\n",
+"{\n",
+"SLASH ?= \\\\ ;\n",
+"}\n",
+"SLASH ?= / ;\n",
+"rule find-to-root ( dir : patterns + )\n",
+"{\n",
+"local globs = [ GLOB $(dir) : $(patterns) ] ;\n",
+"while ! $(globs) && $(dir:P) != $(dir)\n",
+"{\n",
+"dir = $(dir:P) ;\n",
+"globs = [ GLOB $(dir) : $(patterns) ] ;\n",
+"}\n",
+"return $(globs) ;\n",
+"}\n",
+".boost-build-file = ;\n",
+".bootstrap-file = ;\n",
+"BOOST_BUILD_PATH.user-value = $(BOOST_BUILD_PATH) ;\n",
+"if ! $(BOOST_BUILD_PATH) && $(UNIX)\n",
+"{\n",
+"BOOST_BUILD_PATH = /usr/share/boost-build ;\n",
+"}\n",
+"rule boost-build ( dir ? )\n",
+"{\n",
+"if $(.bootstrap-file)\n",
+"{\n",
+"EXIT \"Error: Illegal attempt to re-bootstrap the build system by invoking\" ;\n",
+"ECHO ;\n",
+"ECHO \" 'boost-build\" $(dir) \";'\" ;\n",
+"ECHO ;\n",
+"EXIT \"Please consult the documentation at 'http://www.boost.org'.\" ;\n",
+"}\n",
+"BOOST_BUILD_PATH = $(dir:R=$(.boost-build-file:D)) $(BOOST_BUILD_PATH) ;\n",
+"local bootstrap-file =\n",
+"[ GLOB $(BOOST_BUILD_PATH) : bootstrap.jam ] ;\n",
+".bootstrap-file = $(bootstrap-file[1]) ;\n",
+"if ! $(.bootstrap-file)\n",
+"{\n",
+"ECHO \"Unable to load Boost.Build: could not find build system.\" ;\n",
+"ECHO --------------------------------------------------------- ;\n",
+"ECHO \"$(.boost-build-file) attempted to load the build system by invoking\" ;\n",
+"ECHO ;\n",
+"ECHO \" 'boost-build\" $(dir) \";'\" ;\n",
+"ECHO ;\n",
+"ECHO \"but we were unable to find \\\"bootstrap.jam\\\" in the specified directory\" ;\n",
+"ECHO \"or in BOOST_BUILD_PATH (searching \"$(BOOST_BUILD_PATH:J=\", \")\").\" ;\n",
+"ECHO ;\n",
+"EXIT \"Please consult the documentation at 'http://www.boost.org'.\" ;\n",
+"}\n",
+"if [ MATCH .*(--debug-configuration).* : $(ARGV) ]\n",
+"{\n",
+"ECHO \"notice: loading Boost.Build from\" \n",
+"[ NORMALIZE_PATH $(.bootstrap-file:D) ] ;\n",
+"}\n",
+"include $(.bootstrap-file) ;\n",
+"}\n",
+"if [ MATCH .*(bjam).* : $(ARGV[1]:BL) ]\n",
+"|| $(BOOST_ROOT) # A temporary measure so Jam works with Boost.Build v1\n",
+"{\n",
+"local search-path = $(BOOST_BUILD_PATH) $(BOOST_ROOT) ;\n",
+"local boost-build-files =\n",
+"[ find-to-root [ PWD ] : boost-build.jam ]\n",
+"[ GLOB $(search-path) : boost-build.jam ] ;\n",
+".boost-build-file = $(boost-build-files[1]) ;\n",
+"if [ MATCH .*(--debug-configuration).* : $(ARGV) ]\n",
+"{\n",
+"ECHO \"notice: found boost-build.jam at\" \n",
+"[ NORMALIZE_PATH $(.boost-build-file) ] ;\n",
+"}\n",
+"if ! $(.boost-build-file)\n",
+"{\n",
+"ECHO \"Unable to load Boost.Build: could not find \\\"boost-build.jam\\\"\" ;\n",
+"ECHO --------------------------------------------------------------- ;\n",
+"if ! [ MATCH .*(bjam).* : $(ARGV[1]:BL) ]\n",
+"{\n",
+"ECHO \"BOOST_ROOT must be set, either in the environment, or \" ;\n",
+"ECHO \"on the command-line with -sBOOST_ROOT=..., to the root\" ;\n",
+"ECHO \"of the boost installation.\" ;\n",
+"ECHO ;\n",
+"}\n",
+"ECHO \"Attempted search from\" [ PWD ] \"up to the root\" ;\n",
+"ECHO \"and in these directories from BOOST_BUILD_PATH and BOOST_ROOT: \"$(search-path:J=\", \")\".\" ;\n",
+"EXIT \"Please consult the documentation at 'http://www.boost.org'.\" ;\n",
+"}\n",
+"include $(.boost-build-file) ;\n",
+"if ! $(.bootstrap-file)\n",
+"{\n",
+"ECHO \"Unable to load Boost.Build\" ;\n",
+"ECHO -------------------------- ;\n",
+"ECHO \"\\\"$(.boost-build-file)\\\" was found by searching from\" [ PWD ] \"up to the root\" ;\n",
+"ECHO \"and in these directories from BOOST_BUILD_PATH and BOOST_ROOT: \"$(search-path:J=\", \")\".\" ;\n",
+"ECHO ;\n",
+"ECHO \"However, it failed to call the \\\"boost-build\\\" rule to indicate\" ;\n",
+"ECHO \"the location of the build system.\" ;\n",
+"ECHO ;\n",
+"EXIT \"Please consult the documentation at 'http://www.boost.org'.\" ;\n",
+"}\n",
+"}\n",
+"else\n",
+"{\n",
+"if $(NT)\n",
+"{\n",
+"local SUPPORTED_TOOLSETS = \"BORLANDC\" \"VC7\" \"VISUALC\" \"VISUALC16\" \"INTELC\" \"WATCOM\"\n",
+"\"MINGW\" \"LCC\" ;\n",
+"TOOLSET = \"\" ;\n",
+"if $(JAM_TOOLSET)\n",
+"{\n",
+"local t ;\n",
+"for t in $(SUPPORTED_TOOLSETS)\n",
+"{\n",
+"$(t) = $($(t):J=\" \") ; # reconstitute paths with spaces in them\n",
+"if $(t) = $(JAM_TOOLSET) { TOOLSET = $(t) ; }\n",
+"}\n",
+"if ! $(TOOLSET)\n",
+"{\n",
+"ECHO \"The JAM_TOOLSET environment variable is defined but its value\" ;\n",
+"ECHO \"is invalid, please use one of the following:\" ;\n",
+"ECHO ;\n",
+"for t in $(SUPPORTED_TOOLSETS) { ECHO \" \" $(t) ; }\n",
+"EXIT ;\n",
+"}\n",
+"}\n",
+"if ! $(TOOLSET)\n",
+"{\n",
+"if $(BCCROOT)\n",
+"{\n",
+"TOOLSET = BORLANDC ;\n",
+"BORLANDC = $(BCCROOT:J=\" \") ;\n",
+"}\n",
+"else if $(MSVC)\n",
+"{\n",
+"TOOLSET = VISUALC16 ;\n",
+"VISUALC16 = $(MSVC:J=\" \") ;\n",
+"}\n",
+"else if $(MSVCNT)\n",
+"{\n",
+"TOOLSET = VISUALC ;\n",
+"VISUALC = $(MSVCNT:J=\" \") ;\n",
+"}\n",
+"else if $(MSVCDir)\n",
+"{\n",
+"TOOLSET = VISUALC ;\n",
+"VISUALC = $(MSVCDir:J=\" \") ;\n",
+"}\n",
+"else if $(MINGW)\n",
+"{\n",
+"TOOLSET = MINGW ;\n",
+"}\n",
+"else\n",
+"{\n",
+"ECHO \"Jam cannot be run because, either:\" ;\n",
+"ECHO \" a. You didn't set BOOST_ROOT to indicate the root of your\" ;\n",
+"ECHO \" Boost installation.\" ;\n",
+"ECHO \" b. You are trying to use stock Jam but didn't indicate which\" ;\n",
+"ECHO \" compilation toolset to use. To do so, follow these simple\" ;\n",
+"ECHO \" instructions:\" ;\n",
+"ECHO ;\n",
+"ECHO \" - define one of the following environment variable, with the\" ;\n",
+"ECHO \" appropriate value according to this list:\" ;\n",
+"ECHO ;\n",
+"ECHO \" Variable Toolset Description\" ;\n",
+"ECHO ;\n",
+"ECHO \" BORLANDC Borland C++ BC++ install path\" ;\n",
+"ECHO \" VISUALC Microsoft Visual C++ VC++ install path\" ;\n",
+"ECHO \" VISUALC16 Microsoft Visual C++ 16 bit VC++ 16 bit install\" ;\n",
+"ECHO \" INTELC Intel C/C++ IC++ install path\" ;\n",
+"ECHO \" WATCOM Watcom C/C++ Watcom install path\" ;\n",
+"ECHO \" MINGW MinGW (gcc) MinGW install path\" ;\n",
+"ECHO \" LCC Win32-LCC LCC-Win32 install path\" ;\n",
+"ECHO ;\n",
+"ECHO \" - define the JAM_TOOLSET environment variable with the *name*\" ;\n",
+"ECHO \" of the toolset variable you want to use.\" ;\n",
+"ECHO ;\n",
+"ECHO \" e.g.: set VISUALC=C:\\\\Visual6\" ;\n",
+"ECHO \" set JAM_TOOLSET=VISUALC\" ;\n",
+"EXIT ;\n",
+"}\n",
+"}\n",
+"CP ?= copy ;\n",
+"RM ?= del /f/q ;\n",
+"SLASH ?= \\\\ ;\n",
+"SUFLIB ?= .lib ;\n",
+"SUFOBJ ?= .obj ;\n",
+"SUFEXE ?= .exe ;\n",
+"if $(TOOLSET) = BORLANDC\n",
+"{\n",
+"ECHO \"Compiler is Borland C++\" ;\n",
+"AR ?= tlib /C /P64 ;\n",
+"CC ?= bcc32 ;\n",
+"CCFLAGS ?= -q -y -d -v -w-par -w-ccc -w-rch -w-pro -w-aus ;\n",
+"C++ ?= bcc32 ;\n",
+"C++FLAGS ?= -q -y -d -v -w-par -w-ccc -w-rch -w-pro -w-aus -P ;\n",
+"LINK ?= $(CC) ;\n",
+"LINKFLAGS ?= $(CCFLAGS) ;\n",
+"STDLIBPATH ?= $(BORLANDC)\\\\lib ;\n",
+"STDHDRS ?= $(BORLANDC)\\\\include ;\n",
+"NOARSCAN ?= true ;\n",
+"}\n",
+"else if $(TOOLSET) = VISUALC16\n",
+"{\n",
+"ECHO \"Compiler is Microsoft Visual C++ 16 bit\" ;\n",
+"AR ?= lib /nologo ;\n",
+"CC ?= cl /nologo ;\n",
+"CCFLAGS ?= /D \\\"WIN\\\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= $(CC) ;\n",
+"LINKFLAGS ?= $(CCFLAGS) ;\n",
+"LINKLIBS ?= \n",
+"\\\"$(VISUALC16)\\\\lib\\\\mlibce.lib\\\"\n",
+"\\\"$(VISUALC16)\\\\lib\\\\oldnames.lib\\\"\n",
+";\n",
+"LINKLIBS ?= ;\n",
+"NOARSCAN ?= true ;\n",
+"OPTIM ?= \"\" ;\n",
+"STDHDRS ?= $(VISUALC16)\\\\include ;\n",
+"UNDEFFLAG ?= \"/u _\" ;\n",
+"}\n",
+"else if $(TOOLSET) = VISUALC\n",
+"{\n",
+"ECHO \"Compiler is Microsoft Visual C++\" ;\n",
+"AR ?= lib ;\n",
+"AS ?= masm386 ;\n",
+"CC ?= cl /nologo ;\n",
+"CCFLAGS ?= \"\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= link /nologo ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= \\\"$(VISUALC)\\\\lib\\\\advapi32.lib\\\"\n",
+"\\\"$(VISUALC)\\\\lib\\\\gdi32.lib\\\"\n",
+"\\\"$(VISUALC)\\\\lib\\\\user32.lib\\\"\n",
+"\\\"$(VISUALC)\\\\lib\\\\kernel32.lib\\\" ;\n",
+"OPTIM ?= \"\" ;\n",
+"STDHDRS ?= $(VISUALC)\\\\include ;\n",
+"UNDEFFLAG ?= \"/u _\" ;\n",
+"}\n",
+"else if $(TOOLSET) = VC7\n",
+"{\n",
+"ECHO \"Compiler is Microsoft Visual C++ .NET\" ;\n",
+"AR ?= lib ;\n",
+"AS ?= masm386 ;\n",
+"CC ?= cl /nologo ;\n",
+"CCFLAGS ?= \"\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= link /nologo ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= \\\"$(VISUALC)\\\\PlatformSDK\\\\lib\\\\advapi32.lib\\\"\n",
+"\\\"$(VISUALC)\\\\PlatformSDK\\\\lib\\\\gdi32.lib\\\"\n",
+"\\\"$(VISUALC)\\\\PlatformSDK\\\\lib\\\\user32.lib\\\"\n",
+"\\\"$(VISUALC)\\\\PlatformSDK\\\\lib\\\\kernel32.lib\\\" ;\n",
+"OPTIM ?= \"\" ;\n",
+"STDHDRS ?= \\\"$(VISUALC)\\\\include\\\"\n",
+"\\\"$(VISUALC)\\\\PlatformSDK\\\\include\\\" ;\n",
+"UNDEFFLAG ?= \"/u _\" ;\n",
+"}\n",
+"else if $(TOOLSET) = INTELC\n",
+"{\n",
+"ECHO \"Compiler is Intel C/C++\" ;\n",
+"if ! $(VISUALC)\n",
+"{\n",
+"ECHO \"As a special exception, when using the Intel C++ compiler, you need\" ;\n",
+"ECHO \"to define the VISUALC environment variable to indicate the location\" ;\n",
+"ECHO \"of your Visual C++ installation. Aborting..\" ;\n",
+"EXIT ;\n",
+"}\n",
+"AR ?= lib ;\n",
+"AS ?= masm386 ;\n",
+"CC ?= icl /nologo ;\n",
+"CCFLAGS ?= \"\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= link /nologo ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= $(VISUALC)\\\\lib\\\\advapi32.lib\n",
+"$(VISUALC)\\\\lib\\\\kernel32.lib\n",
+";\n",
+"OPTIM ?= \"\" ;\n",
+"STDHDRS ?= $(INTELC)\\include $(VISUALC)\\\\include ;\n",
+"UNDEFFLAG ?= \"/u _\" ;\n",
+"}\n",
+"else if $(TOOLSET) = WATCOM\n",
+"{\n",
+"ECHO \"Compiler is Watcom C/C++\" ;\n",
+"AR ?= wlib ;\n",
+"CC ?= wcc386 ;\n",
+"CCFLAGS ?= /zq /DWIN32 /I$(WATCOM)\\\\h ; # zq=quiet\n",
+"C++ ?= wpp386 ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"CP ?= copy ;\n",
+"DOT ?= . ;\n",
+"DOTDOT ?= .. ;\n",
+"LINK ?= wcl386 ;\n",
+"LINKFLAGS ?= /zq ; # zq=quiet\n",
+"LINKLIBS ?= ;\n",
+"MV ?= move ;\n",
+"NOARSCAN ?= true ;\n",
+"OPTIM ?= ;\n",
+"RM ?= del /f ;\n",
+"SLASH ?= \\\\ ;\n",
+"STDHDRS ?= $(WATCOM)\\\\h $(WATCOM)\\\\h\\\\nt ;\n",
+"SUFEXE ?= .exe ;\n",
+"SUFLIB ?= .lib ;\n",
+"SUFOBJ ?= .obj ;\n",
+"UNDEFFLAG ?= \"/u _\" ;\n",
+"}\n",
+"else if $(TOOLSET) = MINGW\n",
+"{\n",
+"ECHO \"Compiler is GCC with Mingw\" ;\n",
+"AR ?= ar -ru ;\n",
+"CC ?= gcc ;\n",
+"CCFLAGS ?= \"\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= $(CC) ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= \"\" ;\n",
+"OPTIM ?= ;\n",
+"SUFOBJ = .o ;\n",
+"SUFLIB = .a ;\n",
+"SLASH = / ;\n",
+"}\n",
+"else if $(TOOLSET) = LCC\n",
+"{\n",
+"ECHO \"Compiler is Win32-LCC\" ;\n",
+"AR ?= lcclib ;\n",
+"CC ?= lcc ;\n",
+"CCFLAGS ?= \"\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= lcclnk ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= \"\" ;\n",
+"OPTIM ?= ;\n",
+"NOARSCAN = true ;\n",
+"}\n",
+"else\n",
+"{\n",
+"EXIT On NT, set BCCROOT, MSVCNT, MINGW or MSVC to the root of the\n",
+"Borland or Microsoft directories. ;\n",
+"}\n",
+"}\n",
+"else if $(OS2)\n",
+"{\n",
+"local SUPPORTED_TOOLSETS = \"EMX\" \"WATCOM\" ;\n",
+"TOOLSET = \"\" ;\n",
+"if $(JAM_TOOLSET)\n",
+"{\n",
+"local t ;\n",
+"for t in $(SUPPORTED_TOOLSETS)\n",
+"{\n",
+"$(t) = $($(t):J=\" \") ; # reconstitute paths with spaces in them\n",
+"if $(t) = $(JAM_TOOLSET) { TOOLSET = $(t) ; }\n",
+"}\n",
+"if ! $(TOOLSET)\n",
+"{\n",
+"ECHO \"The JAM_TOOLSET environment variable is defined but its value\" ;\n",
+"ECHO \"is invalid, please use one of the following:\" ;\n",
+"ECHO ;\n",
+"for t in $(SUPPORTED_TOOLSETS) { ECHO \" \" $(t) ; }\n",
+"EXIT ;\n",
+"}\n",
+"}\n",
+"if ! $(TOOLSET)\n",
+"{\n",
+"if $(watcom)\n",
+"{\n",
+"WATCOM = $(watcom:J=\" \") ;\n",
+"TOOLSET = WATCOM ;\n",
+"}\n",
+"else\n",
+"{\n",
+"ECHO \"Jam cannot be run because you didn't indicate which compilation toolset\" ;\n",
+"ECHO \"to use. To do so, follow these simple instructions:\" ;\n",
+"ECHO ;\n",
+"ECHO \" - define one of the following environment variable, with the\" ;\n",
+"ECHO \" appropriate value according to this list:\" ;\n",
+"ECHO ;\n",
+"ECHO \" Variable Toolset Description\" ;\n",
+"ECHO ;\n",
+"ECHO \" WATCOM Watcom C/C++ Watcom install path\" ;\n",
+"ECHO \" EMX EMX (gcc) EMX install path\" ;\n",
+"ECHO \" VISUALAGE IBM Visual Age C/C++ VisualAge install path\" ;\n",
+"ECHO ;\n",
+"ECHO \" - define the JAM_TOOLSET environment variable with the *name*\" ;\n",
+"ECHO \" of the toolset variable you want to use.\" ;\n",
+"ECHO ;\n",
+"ECHO \" e.g.: set WATCOM=C:\\WATCOM\" ;\n",
+"ECHO \" set JAM_TOOLSET=WATCOM\" ;\n",
+"ECHO ;\n",
+"EXIT ;\n",
+"}\n",
+"}\n",
+"RM = del /f ;\n",
+"CP = copy ;\n",
+"MV ?= move ;\n",
+"DOT ?= . ;\n",
+"DOTDOT ?= .. ;\n",
+"SUFLIB ?= .lib ;\n",
+"SUFOBJ ?= .obj ;\n",
+"SUFEXE ?= .exe ;\n",
+"if $(TOOLSET) = WATCOM\n",
+"{\n",
+"AR ?= wlib ;\n",
+"BINDIR ?= \\\\os2\\\\apps ;\n",
+"CC ?= wcc386 ;\n",
+"CCFLAGS ?= /zq /DOS2 /I$(WATCOM)\\\\h ; # zq=quiet\n",
+"C++ ?= wpp386 ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= wcl386 ;\n",
+"LINKFLAGS ?= /zq ; # zq=quiet\n",
+"LINKLIBS ?= ;\n",
+"NOARSCAN ?= true ;\n",
+"OPTIM ?= ;\n",
+"SLASH ?= \\\\ ;\n",
+"STDHDRS ?= $(WATCOM)\\\\h ;\n",
+"UNDEFFLAG ?= \"/u _\" ;\n",
+"}\n",
+"else if $(TOOLSET) = EMX\n",
+"{\n",
+"ECHO \"Compiler is GCC-EMX\" ;\n",
+"AR ?= ar -ru ;\n",
+"CC ?= gcc ;\n",
+"CCFLAGS ?= \"\" ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"LINK ?= $(CC) ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= \"\" ;\n",
+"OPTIM ?= ;\n",
+"SUFOBJ = .o ;\n",
+"SUFLIB = .a ;\n",
+"UNDEFFLAG ?= \"-U\" ;\n",
+"SLASH = / ;\n",
+"}\n",
+"else\n",
+"{\n",
+"EXIT \"Sorry, but the $(JAM_TOOLSET) toolset isn't supported for now\" ;\n",
+"}\n",
+"}\n",
+"else if $(VMS)\n",
+"{\n",
+"C++ ?= cxx ;\n",
+"C++FLAGS ?= ;\n",
+"CC ?= cc ;\n",
+"CCFLAGS ?= ;\n",
+"CHMOD ?= set file/prot= ;\n",
+"CP ?= copy/replace ;\n",
+"CRELIB ?= true ;\n",
+"DOT ?= [] ;\n",
+"DOTDOT ?= [-] ;\n",
+"EXEMODE ?= (w:e) ;\n",
+"FILEMODE ?= (w:r) ;\n",
+"HDRS ?= ;\n",
+"LINK ?= link ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"LINKLIBS ?= ;\n",
+"MKDIR ?= create/dir ;\n",
+"MV ?= rename ;\n",
+"OPTIM ?= \"\" ;\n",
+"RM ?= delete ;\n",
+"RUNVMS ?= mcr ;\n",
+"SHELLMODE ?= (w:er) ;\n",
+"SLASH ?= . ;\n",
+"STDHDRS ?= decc$library_include ;\n",
+"SUFEXE ?= .exe ;\n",
+"SUFLIB ?= .olb ;\n",
+"SUFOBJ ?= .obj ;\n",
+"switch $(OS) \n",
+"{\n",
+"case OPENVMS : CCFLAGS ?= /stand=vaxc ;\n",
+"case VMS : LINKLIBS ?= sys$library:vaxcrtl.olb/lib ;\n",
+"}\n",
+"}\n",
+"else if $(MAC)\n",
+"{\n",
+"local OPT ;\n",
+"CW ?= \"{CW}\" ;\n",
+"MACHDRS ?=\n",
+"\"$(UMACHDRS):Universal:Interfaces:CIncludes\"\n",
+"\"$(CW):MSL:MSL_C:MSL_Common:Include\"\n",
+"\"$(CW):MSL:MSL_C:MSL_MacOS:Include\" ;\n",
+"MACLIBS ?=\n",
+"\"$(CW):MacOS Support:Universal:Libraries:StubLibraries:Interfacelib\"\n",
+"\"$(CW):MacOS Support:Universal:Libraries:StubLibraries:Mathlib\" ;\n",
+"MPWLIBS ?= \n",
+"\"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib\"\n",
+"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW.Lib\" ;\n",
+"MPWNLLIBS ?= \n",
+"\"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib\"\n",
+"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW(NL).Lib\" ;\n",
+"SIOUXHDRS ?= ;\n",
+"SIOUXLIBS ?= \n",
+"\"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL RuntimePPC.lib\"\n",
+"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL SIOUX.PPC.Lib\" \n",
+"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC.Lib\" ;\n",
+"C++ ?= mwcppc ;\n",
+"C++FLAGS ?= -w off -nomapcr ;\n",
+"CC ?= mwcppc ;\n",
+"CCFLAGS ?= -w off -nomapcr ;\n",
+"CP ?= duplicate -y ;\n",
+"DOT ?= \":\" ;\n",
+"DOTDOT ?= \"::\" ;\n",
+"HDRS ?= $(MACHDRS) $(MPWHDRS) ;\n",
+"LINK ?= mwlinkppc ;\n",
+"LINKFLAGS ?= -mpwtool -warn ; \n",
+"LINKLIBS ?= $(MACLIBS) $(MPWLIBS) ; \n",
+"MKDIR ?= newfolder ;\n",
+"MV ?= rename -y ;\n",
+"NOARSCAN ?= true ;\n",
+"OPTIM ?= ;\n",
+"RM ?= delete -y ;\n",
+"SLASH ?= \":\" ;\n",
+"STDHDRS ?= ; \n",
+"SUFLIB ?= .lib ;\n",
+"SUFOBJ ?= .o ;\n",
+"}\n",
+"else if $(OS) = BEOS && $(METROWERKS)\n",
+"{\n",
+"AR ?= mwld -xml -o ;\n",
+"BINDIR ?= /boot/apps ;\n",
+"CC ?= mwcc ;\n",
+"CCFLAGS ?= -nosyspath ;\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= -nosyspath ;\n",
+"FORTRAN ?= \"\" ;\n",
+"LIBDIR ?= /boot/develop/libraries ;\n",
+"LINK ?= mwld ;\n",
+"LINKFLAGS ?= \"\" ;\n",
+"MANDIR ?= /boot/documentation/\"Shell Tools\"/HTML ;\n",
+"NOARSCAN ?= true ;\n",
+"STDHDRS ?= /boot/develop/headers/posix ;\n",
+"}\n",
+"else if $(OS) = BEOS \n",
+"{\n",
+"BINDIR ?= /boot/apps ;\n",
+"CC ?= gcc ;\n",
+"C++ ?= $(CC) ;\n",
+"FORTRAN ?= \"\" ;\n",
+"LIBDIR ?= /boot/develop/libraries ;\n",
+"LINK ?= gcc ;\n",
+"LINKLIBS ?= -lnet ;\n",
+"NOARSCAN ?= true ;\n",
+"STDHDRS ?= /boot/develop/headers/posix ;\n",
+"}\n",
+"else if $(UNIX)\n",
+"{\n",
+"switch $(OS)\n",
+"{\n",
+"case AIX :\n",
+"LINKLIBS ?= -lbsd ;\n",
+"case AMIGA :\n",
+"CC ?= gcc ;\n",
+"YACC ?= \"bison -y\" ;\n",
+"case CYGWIN : \n",
+"CC ?= gcc ;\n",
+"CCFLAGS += -D__cygwin__ ;\n",
+"LEX ?= flex ;\n",
+"RANLIB ?= \"\" ;\n",
+"SUFEXE ?= .exe ;\n",
+"YACC ?= \"bison -y\" ;\n",
+"case DGUX :\n",
+"RANLIB ?= \"\" ;\n",
+"RELOCATE ?= true ;\n",
+"case HPUX :\n",
+"YACC = ;\n",
+"CFLAGS += -Ae ;\n",
+"CCFLAGS += -Ae ;\n",
+"RANLIB ?= \"\" ;\n",
+"case INTERIX :\n",
+"CC ?= gcc ;\n",
+"RANLIB ?= \"\" ;\n",
+"case IRIX :\n",
+"RANLIB ?= \"\" ;\n",
+"case MPEIX :\n",
+"CC ?= gcc ;\n",
+"C++ ?= gcc ;\n",
+"CCFLAGS += -D_POSIX_SOURCE ;\n",
+"HDRS += /usr/include ;\n",
+"RANLIB ?= \"\" ; \n",
+"NOARSCAN ?= true ;\n",
+"NOARUPDATE ?= true ;\n",
+"case MVS :\n",
+"RANLIB ?= \"\" ; \n",
+"case NEXT :\n",
+"AR ?= libtool -o ;\n",
+"RANLIB ?= \"\" ;\n",
+"case MACOSX :\n",
+"AR ?= libtool -o ;\n",
+"C++ ?= c++ ;\n",
+"MANDIR ?= /usr/local/share/man ;\n",
+"RANLIB ?= \"\" ;\n",
+"case NCR :\n",
+"RANLIB ?= \"\" ;\n",
+"case PTX :\n",
+"RANLIB ?= \"\" ;\n",
+"case QNX :\n",
+"AR ?= wlib ;\n",
+"CC ?= cc ;\n",
+"CCFLAGS ?= -Q ; # quiet\n",
+"C++ ?= $(CC) ;\n",
+"C++FLAGS ?= -Q ; # quiet\n",
+"LINK ?= $(CC) ;\n",
+"LINKFLAGS ?= -Q ; # quiet\n",
+"NOARSCAN ?= true ;\n",
+"RANLIB ?= \"\" ;\n",
+"case SCO :\n",
+"RANLIB ?= \"\" ;\n",
+"RELOCATE ?= true ;\n",
+"case SINIX :\n",
+"RANLIB ?= \"\" ;\n",
+"case SOLARIS :\n",
+"RANLIB ?= \"\" ;\n",
+"AR ?= \"/usr/ccs/bin/ar ru\" ;\n",
+"case UNICOS :\n",
+"NOARSCAN ?= true ;\n",
+"OPTIM ?= -O0 ;\n",
+"case UNIXWARE :\n",
+"RANLIB ?= \"\" ;\n",
+"RELOCATE ?= true ;\n",
+"}\n",
+"CCFLAGS ?= ;\n",
+"C++FLAGS ?= $(CCFLAGS) ;\n",
+"CHMOD ?= chmod ;\n",
+"CHGRP ?= chgrp ;\n",
+"CHOWN ?= chown ;\n",
+"LEX ?= lex ;\n",
+"LINKFLAGS ?= $(CCFLAGS) ;\n",
+"LINKLIBS ?= ;\n",
+"OPTIM ?= -O ;\n",
+"RANLIB ?= ranlib ;\n",
+"YACC ?= yacc ;\n",
+"YACCFILES ?= y.tab ;\n",
+"YACCFLAGS ?= -d ;\n",
+"}\n",
+"AR ?= ar ru ;\n",
+"AS ?= as ;\n",
+"ASFLAGS ?= ;\n",
+"AWK ?= awk ;\n",
+"BINDIR ?= /usr/local/bin ;\n",
+"C++ ?= cc ;\n",
+"C++FLAGS ?= ;\n",
+"CC ?= cc ;\n",
+"CCFLAGS ?= ;\n",
+"CP ?= cp -f ;\n",
+"CRELIB ?= ;\n",
+"DOT ?= . ;\n",
+"DOTDOT ?= .. ;\n",
+"EXEMODE ?= 711 ;\n",
+"FILEMODE ?= 644 ;\n",
+"FORTRAN ?= f77 ;\n",
+"FORTRANFLAGS ?= ;\n",
+"HDRS ?= ;\n",
+"INSTALLGRIST ?= installed ;\n",
+"JAMFILE ?= Jamfile ;\n",
+"JAMRULES ?= Jamrules ;\n",
+"LEX ?= ;\n",
+"LIBDIR ?= /usr/local/lib ;\n",
+"LINK ?= $(CC) ;\n",
+"LINKFLAGS ?= ;\n",
+"LINKLIBS ?= ;\n",
+"LN ?= ln ;\n",
+"MANDIR ?= /usr/local/man ;\n",
+"MKDIR ?= mkdir ;\n",
+"MV ?= mv -f ;\n",
+"OPTIM ?= ;\n",
+"RCP ?= rcp ;\n",
+"RM ?= rm -f ;\n",
+"RSH ?= rsh ;\n",
+"SED ?= sed ;\n",
+"SHELLHEADER ?= \"#!/bin/sh\" ;\n",
+"SHELLMODE ?= 755 ;\n",
+"SLASH ?= / ;\n",
+"STDHDRS ?= /usr/include ;\n",
+"SUFEXE ?= \"\" ;\n",
+"SUFLIB ?= .a ;\n",
+"SUFOBJ ?= .o ;\n",
+"UNDEFFLAG ?= \"-u _\" ;\n",
+"YACC ?= ;\n",
+"YACCFILES ?= ;\n",
+"YACCFLAGS ?= ;\n",
+"HDRPATTERN = \n",
+"\"^[ ]*#[ ]*include[ ]*[<\\\"]([^\\\">]*)[\\\">].*$\" ;\n",
+"OSFULL = $(OS)$(OSVER)$(OSPLAT) $(OS)$(OSPLAT) $(OS)$(OSVER) $(OS) ;\n",
+"DEPENDS all : shell files lib exe obj ;\n",
+"DEPENDS all shell files lib exe obj : first ;\n",
+"NOTFILE all first shell files lib exe obj dirs clean uninstall ;\n",
+"ALWAYS clean uninstall ;\n",
+"rule As\n",
+"{\n",
+"DEPENDS $(<) : $(>) ;\n",
+"ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;\n",
+"}\n",
+"rule Bulk\n",
+"{\n",
+"local i ;\n",
+"for i in $(>)\n",
+"{\n",
+"File $(i:D=$(<)) : $(i) ;\n",
+"}\n",
+"}\n",
+"rule Cc\n",
+"{\n",
+"local _h ;\n",
+"DEPENDS $(<) : $(>) ;\n",
+"CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) ;\n",
+"if $(RELOCATE)\n",
+"{\n",
+"CcMv $(<) : $(>) ;\n",
+"}\n",
+"_h = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;\n",
+"if $(VMS) && $(_h)\n",
+"{\n",
+"SLASHINC on $(<) = \"/inc=(\" $(_h[1]) ,$(_h[2-]) \")\" ;\n",
+"}\n",
+"else if $(MAC) && $(_h)\n",
+"{\n",
+"local _i _j ;\n",
+"_j = $(_h[1]) ;\n",
+"for _i in $(_h[2-])\n",
+"{\n",
+"_j = $(_j),$(_i) ;\n",
+"}\n",
+"MACINC on $(<) = \\\"$(_j)\\\" ;\n",
+"}\n",
+"}\n",
+"rule C++\n",
+"{\n",
+"local _h ;\n",
+"DEPENDS $(<) : $(>) ;\n",
+"C++FLAGS on $(<) += $(C++FLAGS) $(SUBDIRC++FLAGS) ;\n",
+"if $(RELOCATE)\n",
+"{\n",
+"CcMv $(<) : $(>) ;\n",
+"}\n",
+"_h = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;\n",
+"if $(VMS) && $(_h)\n",
+"{\n",
+"SLASHINC on $(<) = \"/inc=(\" $(_h[1]) ,$(_h[2-]) \")\" ;\n",
+"}\n",
+"else if $(MAC) && $(_h)\n",
+"{\n",
+"local _i _j ;\n",
+"_j = $(_h[1]) ;\n",
+"for _i in $(_h[2-])\n",
+"{\n",
+"_j = $(_j),$(_i) ;\n",
+"}\n",
+"MACINC on $(<) = \\\"$(_j)\\\" ;\n",
+"}\n",
+"}\n",
+"rule Chmod\n",
+"{\n",
+"if $(CHMOD) { Chmod1 $(<) ; }\n",
+"}\n",
+"rule File\n",
+"{\n",
+"DEPENDS files : $(<) ;\n",
+"DEPENDS $(<) : $(>) ;\n",
+"SEARCH on $(>) = $(SEARCH_SOURCE) ;\n",
+"MODE on $(<) = $(FILEMODE) ;\n",
+"Chmod $(<) ;\n",
+"}\n",
+"rule Fortran\n",
+"{\n",
+"DEPENDS $(<) : $(>) ;\n",
+"}\n",
+"rule GenFile \n",
+"{\n",
+"local _t = [ FGristSourceFiles $(<) ] ;\n",
+"local _s = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;\n",
+"Depends $(_t) : $(_s) $(>[2-]) ;\n",
+"GenFile1 $(_t) : $(_s) $(>[2-]) ;\n",
+"Clean clean : $(_t) ;\n",
+"}\n",
+"rule GenFile1\n",
+"{\n",
+"MakeLocate $(<) : $(LOCATE_SOURCE) ;\n",
+"SEARCH on $(>) = $(SEARCH_SOURCE) ;\n",
+"}\n",
+"rule HardLink\n",
+"{\n",
+"DEPENDS files : $(<) ;\n",
+"DEPENDS $(<) : $(>) ;\n",
+"SEARCH on $(>) = $(SEARCH_SOURCE) ;\n",
+"}\n",
+"rule HdrMacroFile\n",
+"{\n",
+"HDRMACRO $(<) ;\n",
+"}\n",
+"rule HdrRule\n",
+"{\n",
+"local s ;\n",
+"if $(HDRGRIST) \n",
+"{ \n",
+"s = $(>:G=$(HDRGRIST)) ;\n",
+"} else { \n",
+"s = $(>) ; \n",
+"}\n",
+"INCLUDES $(<) : $(s) ;\n",
+"SEARCH on $(s) = $(HDRSEARCH) ;\n",
+"NOCARE $(s) ;\n",
+"HDRSEARCH on $(s) = $(HDRSEARCH) ;\n",
+"HDRSCAN on $(s) = $(HDRSCAN) ;\n",
+"HDRRULE on $(s) = $(HDRRULE) ;\n",
+"HDRGRIST on $(s) = $(HDRGRIST) ;\n",
+"}\n",
+"rule InstallInto\n",
+"{\n",
+"local i t ;\n",
+"t = $(>:G=$(INSTALLGRIST)) ;\n",
+"Depends install : $(t) ;\n",
+"Clean uninstall : $(t) ;\n",
+"SEARCH on $(>) = $(SEARCH_SOURCE) ;\n",
+"MakeLocate $(t) : $(<) ;\n",
+"for i in $(>)\n",
+"{\n",
+"local tt = $(i:G=$(INSTALLGRIST)) ;\n",
+"Depends $(tt) : $(i) ;\n",
+"Install $(tt) : $(i) ;\n",
+"Chmod $(tt) ;\n",
+"if $(OWNER) && $(CHOWN) \n",
+"{ \n",
+"Chown $(tt) ;\n",
+"OWNER on $(tt) = $(OWNER) ;\n",
+"}\n",
+"if $(GROUP) && $(CHGRP) \n",
+"{ \n",
+"Chgrp $(tt) ;\n",
+"GROUP on $(tt) = $(GROUP) ;\n",
+"}\n",
+"}\n",
+"}\n",
+"rule InstallBin\n",
+"{\n",
+"local _t = [ FAppendSuffix $(>) : $(SUFEXE) ] ;\n",
+"InstallInto $(<) : $(_t) ;\n",
+"MODE on $(_t:G=installed) = $(EXEMODE) ;\n",
+"}\n",
+"rule InstallFile\n",
+"{\n",
+"InstallInto $(<) : $(>) ;\n",
+"MODE on $(>:G=installed) = $(FILEMODE) ;\n",
+"}\n",
+"rule InstallLib\n",
+"{\n",
+"InstallInto $(<) : $(>) ;\n",
+"MODE on $(>:G=installed) = $(FILEMODE) ;\n",
+"}\n",
+"rule InstallMan\n",
+"{\n",
+"local i s d ;\n",
+"for i in $(>)\n",
+"{\n",
+"switch $(i:S)\n",
+"{\n",
+"case .1 : s = 1 ; case .2 : s = 2 ; case .3 : s = 3 ;\n",
+"case .4 : s = 4 ; case .5 : s = 5 ; case .6 : s = 6 ;\n",
+"case .7 : s = 7 ; case .8 : s = 8 ; case .l : s = l ;\n",
+"case .n : s = n ; case .man : s = 1 ;\n",
+"}\n",
+"d = man$(s) ;\n",
+"InstallInto $(d:R=$(<)) : $(i) ;\n",
+"}\n",
+"MODE on $(>:G=installed) = $(FILEMODE) ;\n",
+"}\n",
+"rule InstallShell\n",
+"{\n",
+"InstallInto $(<) : $(>) ;\n",
+"MODE on $(>:G=installed) = $(SHELLMODE) ;\n",
+"}\n",
+"rule Lex\n",
+"{\n",
+"LexMv $(<) : $(>) ;\n",
+"DEPENDS $(<) : $(>) ;\n",
+"MakeLocate $(<) : $(LOCATE_SOURCE) ;\n",
+"Clean clean : $(<) ;\n",
+"}\n",
+"rule Library\n",
+"{\n",
+"LibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ;\n",
+"Objects $(>) ;\n",
+"}\n",
+"rule LibraryFromObjects\n",
+"{\n",
+"local _i _l _s ;\n",
+"_s = [ FGristFiles $(>) ] ;\n",
+"_l = $(<:S=$(SUFLIB)) ;\n",
+"if $(KEEPOBJS)\n",
+"{\n",
+"DEPENDS obj : $(_s) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"DEPENDS lib : $(_l) ;\n",
+"}\n",
+"if ! $(_l:D)\n",
+"{\n",
+"MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ;\n",
+"}\n",
+"if $(NOARSCAN) \n",
+"{ \n",
+"DEPENDS $(_l) : $(_s) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"DEPENDS $(_l) : $(_l)($(_s:BS)) ;\n",
+"for _i in $(_s)\n",
+"{\n",
+"DEPENDS $(_l)($(_i:BS)) : $(_i) ;\n",
+"}\n",
+"}\n",
+"Clean clean : $(_l) ;\n",
+"if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; }\n",
+"Archive $(_l) : $(_s) ;\n",
+"if $(RANLIB) { Ranlib $(_l) ; }\n",
+"if ! ( $(NOARSCAN) || $(KEEPOBJS) ) { RmTemps $(_l) : $(_s) ; }\n",
+"}\n",
+"rule Link\n",
+"{\n",
+"MODE on $(<) = $(EXEMODE) ;\n",
+"Chmod $(<) ;\n",
+"}\n",
+"rule LinkLibraries\n",
+"{\n",
+"local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;\n",
+"DEPENDS $(_t) : $(>:S=$(SUFLIB)) ;\n",
+"NEEDLIBS on $(_t) += $(>:S=$(SUFLIB)) ;\n",
+"}\n",
+"rule Main\n",
+"{\n",
+"MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;\n",
+"Objects $(>) ;\n",
+"}\n",
+"rule MainFromObjects\n",
+"{\n",
+"local _s _t ;\n",
+"_s = [ FGristFiles $(>) ] ;\n",
+"_t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;\n",
+"if $(_t) != $(<)\n",
+"{\n",
+"DEPENDS $(<) : $(_t) ;\n",
+"NOTFILE $(<) ;\n",
+"}\n",
+"DEPENDS exe : $(_t) ;\n",
+"DEPENDS $(_t) : $(_s) ;\n",
+"MakeLocate $(_t) : $(LOCATE_TARGET) ;\n",
+"Clean clean : $(_t) ;\n",
+"Link $(_t) : $(_s) ;\n",
+"}\n",
+"rule MakeLocate\n",
+"{\n",
+"if $(>)\n",
+"{\n",
+"LOCATE on $(<) = $(>) ;\n",
+"Depends $(<) : $(>[1]) ;\n",
+"MkDir $(>[1]) ;\n",
+"}\n",
+"}\n",
+"rule MkDir\n",
+"{\n",
+"NOUPDATE $(<) ;\n",
+"if $(<) != $(DOT) && ! $($(<)-mkdir) \n",
+"{\n",
+"local s ;\n",
+"$(<)-mkdir = true ;\n",
+"MkDir1 $(<) ;\n",
+"Depends dirs : $(<) ;\n",
+"s = $(<:P) ;\n",
+"if $(NT)\n",
+"{\n",
+"switch $(s)\n",
+"{\n",
+"case *: : s = ;\n",
+"case *:\\\\ : s = ;\n",
+"}\n",
+"}\n",
+"if $(s) && $(s) != $(<)\n",
+"{\n",
+"Depends $(<) : $(s) ;\n",
+"MkDir $(s) ;\n",
+"}\n",
+"else if $(s)\n",
+"{\n",
+"NOTFILE $(s) ;\n",
+"}\n",
+"}\n",
+"}\n",
+"rule Object\n",
+"{\n",
+"local h ;\n",
+"Clean clean : $(<) ;\n",
+"MakeLocate $(<) : $(LOCATE_TARGET) ;\n",
+"SEARCH on $(>) = $(SEARCH_SOURCE) ;\n",
+"HDRS on $(<) = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;\n",
+"if $(SEARCH_SOURCE)\n",
+"{\n",
+"h = $(SEARCH_SOURCE) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"h = \"\" ;\n",
+"}\n",
+"HDRRULE on $(>) = HdrRule ;\n",
+"HDRSCAN on $(>) = $(HDRPATTERN) ;\n",
+"HDRSEARCH on $(>) = $(HDRS) $(SUBDIRHDRS) $(h) $(STDHDRS) ;\n",
+"HDRGRIST on $(>) = $(HDRGRIST) ;\n",
+"switch $(>:S)\n",
+"{\n",
+"case .asm : As $(<) : $(>) ;\n",
+"case .c : Cc $(<) : $(>) ;\n",
+"case .C : C++ $(<) : $(>) ;\n",
+"case .cc : C++ $(<) : $(>) ;\n",
+"case .cpp : C++ $(<) : $(>) ;\n",
+"case .f : Fortran $(<) : $(>) ;\n",
+"case .l : Cc $(<) : $(<:S=.c) ;\n",
+"Lex $(<:S=.c) : $(>) ;\n",
+"case .s : As $(<) : $(>) ;\n",
+"case .y : Cc $(<) : $(<:S=.c) ;\n",
+"Yacc $(<:S=.c) : $(>) ;\n",
+"case * : UserObject $(<) : $(>) ;\n",
+"}\n",
+"}\n",
+"rule ObjectCcFlags\n",
+"{\n",
+"CCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;\n",
+"}\n",
+"rule ObjectC++Flags\n",
+"{\n",
+"C++FLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;\n",
+"}\n",
+"rule ObjectHdrs\n",
+"{\n",
+"HDRS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;\n",
+"}\n",
+"rule Objects\n",
+"{\n",
+"local _i ;\n",
+"for _i in [ FGristFiles $(<) ]\n",
+"{\n",
+"Object $(_i:S=$(SUFOBJ)) : $(_i) ;\n",
+"DEPENDS obj : $(_i:S=$(SUFOBJ)) ;\n",
+"}\n",
+"}\n",
+"rule RmTemps\n",
+"{\n",
+"TEMPORARY $(>) ;\n",
+"}\n",
+"rule Setuid\n",
+"{\n",
+"MODE on [ FAppendSuffix $(<) : $(SUFEXE) ] = 4711 ;\n",
+"}\n",
+"rule Shell\n",
+"{\n",
+"DEPENDS shell : $(<) ;\n",
+"DEPENDS $(<) : $(>) ;\n",
+"SEARCH on $(>) = $(SEARCH_SOURCE) ;\n",
+"MODE on $(<) = $(SHELLMODE) ;\n",
+"Clean clean : $(<) ;\n",
+"Chmod $(<) ;\n",
+"}\n",
+"rule SubDir\n",
+"{\n",
+"local _r _s ;\n",
+"if ! $($(<[1]))\n",
+"{\n",
+"if ! $(<[1])\n",
+"{\n",
+"EXIT SubDir syntax error ;\n",
+"}\n",
+"$(<[1]) = [ FSubDir $(<[2-]) ] ;\n",
+"}\n",
+"if ! $($(<[1])-included)\n",
+"{\n",
+"$(<[1])-included = TRUE ;\n",
+"_r = $($(<[1])RULES) ;\n",
+"if ! $(_r)\n",
+"{\n",
+"_r = $(JAMRULES:R=$($(<[1]))) ;\n",
+"}\n",
+"include $(_r) ;\n",
+"}\n",
+"_s = [ FDirName $(<[2-]) ] ;\n",
+"SUBDIR = $(_s:R=$($(<[1]))) ;\n",
+"SUBDIR_TOKENS = $(<[2-]) ;\n",
+"SEARCH_SOURCE = $(SUBDIR) ;\n",
+"LOCATE_SOURCE = $(ALL_LOCATE_TARGET) $(SUBDIR) ;\n",
+"LOCATE_TARGET = $(ALL_LOCATE_TARGET) $(SUBDIR) ;\n",
+"SOURCE_GRIST = [ FGrist $(<[2-]) ] ;\n",
+"SUBDIRCCFLAGS = ;\n",
+"SUBDIRC++FLAGS = ;\n",
+"SUBDIRHDRS = ;\n",
+"}\n",
+"rule SubDirCcFlags\n",
+"{\n",
+"SUBDIRCCFLAGS += $(<) ;\n",
+"}\n",
+"rule SubDirC++Flags\n",
+"{\n",
+"SUBDIRC++FLAGS += $(<) ;\n",
+"}\n",
+"rule SubDirHdrs\n",
+"{\n",
+"SUBDIRHDRS += $(<) ;\n",
+"}\n",
+"rule SubInclude\n",
+"{\n",
+"local _s ;\n",
+"if ! $($(<[1]))\n",
+"{\n",
+"EXIT Top level of source tree has not been set with $(<[1]) ;\n",
+"}\n",
+"_s = [ FDirName $(<[2-]) ] ;\n",
+"include $(JAMFILE:D=$(_s):R=$($(<[1]))) ;\n",
+"}\n",
+"rule Undefines\n",
+"{\n",
+"UNDEFS on [ FAppendSuffix $(<) : $(SUFEXE) ] += $(UNDEFFLAG)$(>) ;\n",
+"}\n",
+"rule UserObject\n",
+"{\n",
+"EXIT \"Unknown suffix on\" $(>) \"- see UserObject rule in Jamfile(5).\" ;\n",
+"}\n",
+"rule Yacc\n",
+"{\n",
+"local _h ;\n",
+"_h = $(<:BS=.h) ;\n",
+"MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ;\n",
+"if $(YACC)\n",
+"{\n",
+"DEPENDS $(<) $(_h) : $(>) ;\n",
+"Yacc1 $(<) $(_h) : $(>) ;\n",
+"YaccMv $(<) $(_h) : $(>) ;\n",
+"Clean clean : $(<) $(_h) ;\n",
+"}\n",
+"INCLUDES $(<) : $(_h) ;\n",
+"}\n",
+"rule FGrist\n",
+"{\n",
+"local _g _i ;\n",
+"_g = $(<[1]) ;\n",
+"for _i in $(<[2-])\n",
+"{\n",
+"_g = $(_g)!$(_i) ;\n",
+"}\n",
+"return $(_g) ;\n",
+"}\n",
+"rule FGristFiles \n",
+"{\n",
+"if ! $(SOURCE_GRIST)\n",
+"{\n",
+"return $(<) ;\n",
+"}\n",
+"else \n",
+"{\n",
+"return $(<:G=$(SOURCE_GRIST)) ;\n",
+"}\n",
+"}\n",
+"rule FGristSourceFiles\n",
+"{\n",
+"if ! $(SOURCE_GRIST)\n",
+"{\n",
+"return $(<) ;\n",
+"}\n",
+"else \n",
+"{\n",
+"local _i _o ;\n",
+"for _i in $(<)\n",
+"{\n",
+"switch $(_i)\n",
+"{\n",
+"case *.h : _o += $(_i) ;\n",
+"case * : _o += $(_i:G=$(SOURCE_GRIST)) ;\n",
+"}\n",
+"}\n",
+"return $(_o) ;\n",
+"}\n",
+"}\n",
+"rule FConcat\n",
+"{\n",
+"local _t _r ;\n",
+"$(_r) = $(<[1]) ;\n",
+"for _t in $(<[2-])\n",
+"{\n",
+"$(_r) = $(_r)$(_t) ;\n",
+"}\n",
+"return $(_r) ;\n",
+"}\n",
+"rule FSubDir\n",
+"{\n",
+"local _i _d ;\n",
+"if ! $(<[1]) \n",
+"{\n",
+"_d = $(DOT) ;\n",
+"} \n",
+"else\n",
+"{\n",
+"_d = $(DOTDOT) ;\n",
+"for _i in $(<[2-])\n",
+"{\n",
+"_d = $(_d:R=$(DOTDOT)) ;\n",
+"}\n",
+"}\n",
+"return $(_d) ;\n",
+"}\n",
+"rule FDirName\n",
+"{\n",
+"local _s _i ;\n",
+"if ! $(<)\n",
+"{\n",
+"_s = $(DOT) ;\n",
+"}\n",
+"else if $(VMS)\n",
+"{\n",
+"switch $(<[1])\n",
+"{\n",
+"case *:* : _s = $(<[1]) ;\n",
+"case \\\\[*\\\\] : _s = $(<[1]) ;\n",
+"case * : _s = [.$(<[1])] ;\n",
+"}\n",
+"for _i in [.$(<[2-])]\n",
+"{\n",
+"_s = $(_i:R=$(_s)) ;\n",
+"}\n",
+"}\n",
+"else if $(MAC)\n",
+"{\n",
+"_s = $(DOT) ;\n",
+"for _i in $(<)\n",
+"{\n",
+"_s = $(_i:R=$(_s)) ;\n",
+"}\n",
+"}\n",
+"else\n",
+"{\n",
+"_s = $(<[1]) ; \n",
+"for _i in $(<[2-])\n",
+"{\n",
+"_s = $(_i:R=$(_s)) ;\n",
+"}\n",
+"}\n",
+"return $(_s) ;\n",
+"}\n",
+"rule _makeCommon\n",
+"{\n",
+"if $($(<)[1]) && $($(<)[1]) = $($(>)[1])\n",
+"{\n",
+"$(<) = $($(<)[2-]) ;\n",
+"$(>) = $($(>)[2-]) ;\n",
+"_makeCommon $(<) : $(>) ;\n",
+"}\n",
+"}\n",
+"rule FRelPath\n",
+"{\n",
+"local _l _r ;\n",
+"_l = $(<) ;\n",
+"_r = $(>) ;\n",
+"_makeCommon _l : _r ;\n",
+"_l = [ FSubDir $(_l) ] ;\n",
+"_r = [ FDirName $(_r) ] ;\n",
+"if $(_r) = $(DOT) {\n",
+"return $(_l) ;\n",
+"} else {\n",
+"return $(_r:R=$(_l)) ;\n",
+"}\n",
+"}\n",
+"rule FAppendSuffix\n",
+"{\n",
+"if $(>)\n",
+"{\n",
+"local _i _o ;\n",
+"for _i in $(<)\n",
+"{\n",
+"if $(_i:S)\n",
+"{\n",
+"_o += $(_i) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"_o += $(_i:S=$(>)) ;\n",
+"}\n",
+"}\n",
+"return $(_o) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"return $(<) ;\n",
+"}\n",
+"}\n",
+"rule unmakeDir\n",
+"{\n",
+"if $(>[1]:D) && $(>[1]:D) != $(>[1]) && $(>[1]:D) != \\\\\\\\ \n",
+"{\n",
+"unmakeDir $(<) : $(>[1]:D) $(>[1]:BS) $(>[2-]) ;\n",
+"}\n",
+"else\n",
+"{\n",
+"$(<) = $(>) ;\n",
+"}\n",
+"}\n",
+"rule FConvertToSlashes\n",
+"{\n",
+"local _d, _s, _i ;\n",
+"unmakeDir _d : $(<) ;\n",
+"_s = $(_d[1]) ; \n",
+"for _i in $(_d[2-])\n",
+"{\n",
+"_s = $(_s)/$(_i) ;\n",
+"}\n",
+"return $(_s) ;\n",
+"}\n",
+"actions updated together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) $(>)\n",
+"}\n",
+"actions As\n",
+"{\n",
+"$(AS) $(ASFLAGS) -I$(HDRS) -o $(<) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o $(<) $(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o $(<) $(>)\n",
+"}\n",
+"actions Chgrp\n",
+"{\n",
+"$(CHGRP) $(GROUP) $(<)\n",
+"}\n",
+"actions Chmod1\n",
+"{\n",
+"$(CHMOD) $(MODE) $(<)\n",
+"}\n",
+"actions Chown\n",
+"{\n",
+"$(CHOWN) $(OWNER) $(<)\n",
+"}\n",
+"actions piecemeal together existing Clean\n",
+"{\n",
+"$(RM) $(>)\n",
+"}\n",
+"actions File\n",
+"{\n",
+"$(CP) $(>) $(<)\n",
+"}\n",
+"actions GenFile1\n",
+"{\n",
+"$(>[1]) $(<) $(>[2-])\n",
+"}\n",
+"actions Fortran\n",
+"{\n",
+"$(FORTRAN) $(FORTRANFLAGS) -o $(<) $(>)\n",
+"}\n",
+"actions HardLink\n",
+"{\n",
+"$(RM) $(<) && $(LN) $(>) $(<)\n",
+"}\n",
+"actions Install\n",
+"{\n",
+"$(CP) $(>) $(<) \n",
+"}\n",
+"actions Lex\n",
+"{\n",
+"$(LEX) $(>)\n",
+"}\n",
+"actions LexMv\n",
+"{\n",
+"$(MV) lex.yy.c $(<)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) \n",
+"}\n",
+"actions MkDir1\n",
+"{\n",
+"$(MKDIR) $(<)\n",
+"}\n",
+"actions together Ranlib\n",
+"{\n",
+"$(RANLIB) $(<)\n",
+"}\n",
+"actions quietly updated piecemeal together RmTemps\n",
+"{\n",
+"$(RM) $(>)\n",
+"}\n",
+"actions Shell\n",
+"{\n",
+"$(AWK) '\n",
+"NR == 1 { print \"$(SHELLHEADER)\" }\n",
+"NR == 1 && /^[#:]/ { next }\n",
+"/^##/ { next }\n",
+"{ print }\n",
+"' < $(>) > $(<)\n",
+"}\n",
+"actions Yacc1\n",
+"{\n",
+"$(YACC) $(YACCFLAGS) $(>)\n",
+"}\n",
+"actions YaccMv\n",
+"{\n",
+"$(MV) $(YACCFILES).c $(<[1])\n",
+"$(MV) $(YACCFILES).h $(<[2])\n",
+"}\n",
+"if $(RELOCATE)\n",
+"{\n",
+"actions C++\n",
+"{\n",
+"$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) $(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) $(>)\n",
+"}\n",
+"actions ignore CcMv\n",
+"{\n",
+"[ $(<) != $(>:BS=$(SUFOBJ)) ] && $(MV) $(>:BS=$(SUFOBJ)) $(<)\n",
+"}\n",
+"}\n",
+"if $(NOARUPDATE)\n",
+"{\n",
+"actions Archive\n",
+"{\n",
+"$(AR) $(<) $(>)\n",
+"}\n",
+"}\n",
+"if $(NT)\n",
+"{\n",
+"if $(TOOLSET) = VISUALC || $(TOOLSET) = VC7 || $(TOOLSET) = INTELC\n",
+"{\n",
+"actions updated together piecemeal Archive\n",
+"{\n",
+"if exist $(<) set _$(<:B)_=$(<)\n",
+"$(AR) /out:$(<) %_$(<:B)_% $(>)\n",
+"}\n",
+"actions As\n",
+"{\n",
+"$(AS) /Ml /p /v /w2 $(>) $(<) ,nul,nul;\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) /c $(CCFLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /I$(STDHDRS) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) /c $(C++FLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /I$(STDHDRS) /Tp$(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)\n",
+"}\n",
+"}\n",
+"else if $(TOOLSET) = VISUALC16\n",
+"{\n",
+"actions updated together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) -+$(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) /c $(CCFLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) /c $(C++FLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /Tp$(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)\n",
+"}\n",
+"}\n",
+"else if $(TOOLSET) = BORLANDC\n",
+"{\n",
+"actions updated together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) -+$(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) -e$(<) $(LINKFLAGS) $(UNDEFS) -L$(LINKLIBS) $(NEEDLIBS) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)\n",
+"}\n",
+"}\n",
+"else if $(TOOLSET) = MINGW\n",
+"{\n",
+"actions together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) $(>:T)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)\n",
+"}\n",
+"}\n",
+"else if $(TOOLSET) = WATCOM\n",
+"{\n",
+"actions together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) +-$(>) \n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) $(CCFLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) $(C++FLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)\n",
+"}\n",
+"actions Shell\n",
+"{\n",
+"$(CP) $(>) $(<)\n",
+"}\n",
+"}\n",
+"else if $(TOOLSET) = LCC\n",
+"{\n",
+"actions together piecemeal Archive\n",
+"{\n",
+"$(AR) /out:$(<) $(>) \n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) $(CCFLAGS) $(OPTIM) -Fo$(<) -I$(HDRS) $(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)\n",
+"}\n",
+"actions Shell\n",
+"{\n",
+"$(CP) $(>) $(<)\n",
+"}\n",
+"}\n",
+"}\n",
+"else if $(OS2) \n",
+"{\n",
+"if $(TOOLSET) = WATCOM\n",
+"{\n",
+"actions together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) +-$(>) \n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) $(CCFLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) $(C++FLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)\n",
+"}\n",
+"actions Shell\n",
+"{\n",
+"$(CP) $(>) $(<)\n",
+"}\n",
+"}\n",
+"else if $(TOOLSET) = EMX\n",
+"{\n",
+"actions together piecemeal Archive\n",
+"{\n",
+"$(AR) $(<) $(>:T)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)\n",
+"}\n",
+"actions C++\n",
+"{\n",
+"$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)\n",
+"}\n",
+"}\n",
+"}\n",
+"else if $(VMS)\n",
+"{\n",
+"actions updated together piecemeal Archive \n",
+"{\n",
+"lib/replace $(<) $(>[1]) ,$(>[2-])\n",
+"}\n",
+"actions Cc\n",
+"{ \n",
+"$(CC)/obj=$(<) $(CCFLAGS) $(OPTIM) $(SLASHINC) $(>) \n",
+"}\n",
+"actions C++\n",
+"{ \n",
+"$(C++)/obj=$(<) $(C++FLAGS) $(OPTIM) $(SLASHINC) $(>) \n",
+"}\n",
+"actions piecemeal together existing Clean\n",
+"{\n",
+"$(RM) $(>[1]);* ,$(>[2-]);*\n",
+"}\n",
+"actions together quietly CreLib\n",
+"{\n",
+"if f$search(\"$(<)\") .eqs. \"\" then lib/create $(<)\n",
+"}\n",
+"actions GenFile1\n",
+"{\n",
+"mcr $(>[1]) $(<) $(>[2-])\n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK)/exe=$(<) $(LINKFLAGS) $(>[1]) ,$(>[2-]) ,$(NEEDLIBS)/lib ,$(LINKLIBS)\n",
+"}\n",
+"actions quietly updated piecemeal together RmTemps\n",
+"{\n",
+"$(RM) $(>[1]);* ,$(>[2-]);*\n",
+"}\n",
+"actions Shell\n",
+"{\n",
+"$(CP) $(>) $(<)\n",
+"}\n",
+"}\n",
+"else if $(MAC)\n",
+"{\n",
+"actions together Archive \n",
+"{\n",
+"$(LINK) -library -o $(<) $(>)\n",
+"}\n",
+"actions Cc\n",
+"{\n",
+"set -e MWCincludes $(MACINC)\n",
+"$(CC) -o $(<) $(CCFLAGS) $(OPTIM) $(>) \n",
+"}\n",
+"actions C++\n",
+"{ \n",
+"set -e MWCincludes $(MACINC)\n",
+"$(CC) -o $(<) $(C++FLAGS) $(OPTIM) $(>) \n",
+"}\n",
+"actions Link bind NEEDLIBS\n",
+"{\n",
+"$(LINK) -o $(<) $(LINKFLAGS) $(>) $(NEEDLIBS) \"$(LINKLIBS)\"\n",
+"}\n",
+"}\n",
+"rule BULK { Bulk $(<) : $(>) ; }\n",
+"rule FILE { File $(<) : $(>) ; }\n",
+"rule HDRRULE { HdrRule $(<) : $(>) ; }\n",
+"rule INSTALL { Install $(<) : $(>) ; }\n",
+"rule LIBRARY { Library $(<) : $(>) ; }\n",
+"rule LIBS { LinkLibraries $(<) : $(>) ; }\n",
+"rule LINK { Link $(<) : $(>) ; }\n",
+"rule MAIN { Main $(<) : $(>) ; }\n",
+"rule SETUID { Setuid $(<) ; }\n",
+"rule SHELL { Shell $(<) : $(>) ; }\n",
+"rule UNDEFINES { Undefines $(<) : $(>) ; }\n",
+"rule INSTALLBIN { InstallBin $(BINDIR) : $(<) ; }\n",
+"rule INSTALLLIB { InstallLib $(LIBDIR) : $(<) ; }\n",
+"rule INSTALLMAN { InstallMan $(MANDIR) : $(<) ; }\n",
+"rule addDirName { $(<) += [ FDirName $(>) ] ; }\n",
+"rule makeDirName { $(<) = [ FDirName $(>) ] ; }\n",
+"rule makeGristedName { $(<) = [ FGristSourceFiles $(>) ] ; }\n",
+"rule makeRelPath { $(<[1]) = [ FRelPath $(<[2-]) : $(>) ] ; }\n",
+"rule makeSuffixed { $(<[1]) = [ FAppendSuffix $(>) : $(<[2]) ] ; }\n",
+"{\n",
+"if $(JAMFILE) { include $(JAMFILE) ; }\n",
+"}\n",
+"}\n",
+0 };
Added: boost-jam/boost-build/branches/upstream/current/jam_src/jambase.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/jambase.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/jambase.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,15 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * jambase.h - declaration for the internal jambase
+ *
+ * The file Jambase is turned into a C array of strings in jambase.c
+ * so that it can be built in to the executable. This is the
+ * declaration for that array.
+ */
+
+extern char *jambase[];
Added: boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1830 @@
+/* A Bison parser, made by GNU Bison 1.875. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Written by Richard Stallman by simplifying the original so called
+ ``semantic'' parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ _BANG_t = 258,
+ _BANG_EQUALS_t = 259,
+ _AMPER_t = 260,
+ _AMPERAMPER_t = 261,
+ _LPAREN_t = 262,
+ _RPAREN_t = 263,
+ _PLUS_EQUALS_t = 264,
+ _COLON_t = 265,
+ _SEMIC_t = 266,
+ _LANGLE_t = 267,
+ _LANGLE_EQUALS_t = 268,
+ _EQUALS_t = 269,
+ _RANGLE_t = 270,
+ _RANGLE_EQUALS_t = 271,
+ _QUESTION_EQUALS_t = 272,
+ _LBRACKET_t = 273,
+ _RBRACKET_t = 274,
+ ACTIONS_t = 275,
+ BIND_t = 276,
+ CASE_t = 277,
+ CLASS_t = 278,
+ DEFAULT_t = 279,
+ ELSE_t = 280,
+ EXISTING_t = 281,
+ FOR_t = 282,
+ IF_t = 283,
+ IGNORE_t = 284,
+ IN_t = 285,
+ INCLUDE_t = 286,
+ LOCAL_t = 287,
+ MODULE_t = 288,
+ ON_t = 289,
+ PIECEMEAL_t = 290,
+ QUIETLY_t = 291,
+ RETURN_t = 292,
+ RULE_t = 293,
+ SWITCH_t = 294,
+ TOGETHER_t = 295,
+ UPDATED_t = 296,
+ WHILE_t = 297,
+ _LBRACE_t = 298,
+ _BAR_t = 299,
+ _BARBAR_t = 300,
+ _RBRACE_t = 301,
+ ARG = 302,
+ STRING = 303
+ };
+#endif
+#define _BANG_t 258
+#define _BANG_EQUALS_t 259
+#define _AMPER_t 260
+#define _AMPERAMPER_t 261
+#define _LPAREN_t 262
+#define _RPAREN_t 263
+#define _PLUS_EQUALS_t 264
+#define _COLON_t 265
+#define _SEMIC_t 266
+#define _LANGLE_t 267
+#define _LANGLE_EQUALS_t 268
+#define _EQUALS_t 269
+#define _RANGLE_t 270
+#define _RANGLE_EQUALS_t 271
+#define _QUESTION_EQUALS_t 272
+#define _LBRACKET_t 273
+#define _RBRACKET_t 274
+#define ACTIONS_t 275
+#define BIND_t 276
+#define CASE_t 277
+#define CLASS_t 278
+#define DEFAULT_t 279
+#define ELSE_t 280
+#define EXISTING_t 281
+#define FOR_t 282
+#define IF_t 283
+#define IGNORE_t 284
+#define IN_t 285
+#define INCLUDE_t 286
+#define LOCAL_t 287
+#define MODULE_t 288
+#define ON_t 289
+#define PIECEMEAL_t 290
+#define QUIETLY_t 291
+#define RETURN_t 292
+#define RULE_t 293
+#define SWITCH_t 294
+#define TOGETHER_t 295
+#define UPDATED_t 296
+#define WHILE_t 297
+#define _LBRACE_t 298
+#define _BAR_t 299
+#define _BARBAR_t 300
+#define _RBRACE_t 301
+#define ARG 302
+#define STRING 303
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 96 "jamgram.y"
+
+#include "jam.h"
+
+#include "lists.h"
+#include "parse.h"
+#include "scan.h"
+#include "compile.h"
+#include "newstr.h"
+#include "rules.h"
+
+# define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
+
+# define F0 (LIST *(*)(PARSE *, FRAME *))0
+# define P0 (PARSE *)0
+# define S0 (char *)0
+
+# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
+# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
+# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
+# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
+# define pincl( l ) parse_make( compile_include,l,P0,P0,S0,S0,0 )
+# define plist( s ) parse_make( compile_list,P0,P0,P0,s,S0,0 )
+# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
+# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
+# define pclass( l,r ) parse_make( compile_class,l,r,P0,S0,S0,0 )
+# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
+# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 )
+# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
+# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
+# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
+# define pset1( l,r,t,a ) parse_make( compile_settings,l,r,t,S0,S0,a )
+# define psetc( s,p,a,l ) parse_make( compile_setcomp,p,a,P0,s,S0,l )
+# define psete( s,l,s1,f ) parse_make( compile_setexec,l,P0,P0,s,s1,f )
+# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
+# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
+
+# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
+# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
+
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+typedef int YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 214 of yacc.c. */
+#line 223 "y.tab.c"
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# if YYSTACK_USE_ALLOCA
+# define YYSTACK_ALLOC alloca
+# else
+# ifndef YYSTACK_USE_ALLOCA
+# if defined (alloca) || defined (_ALLOCA_H)
+# define YYSTACK_ALLOC alloca
+# else
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+# define YYSTACK_ALLOC malloc
+# define YYSTACK_FREE free
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+ && (! defined (__cplusplus) \
+ || (YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ short yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (short) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ register YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+ typedef signed char yysigned_char;
+#else
+ typedef short yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 43
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 261
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 49
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 24
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 75
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 159
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 303
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const unsigned char yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const unsigned char yyprhs[] =
+{
+ 0, 0, 3, 4, 6, 8, 10, 12, 15, 21,
+ 22, 25, 27, 31, 32, 34, 35, 39, 43, 47,
+ 52, 59, 63, 72, 78, 84, 90, 96, 102, 110,
+ 116, 120, 121, 122, 132, 134, 136, 138, 141, 143,
+ 147, 151, 155, 159, 163, 167, 171, 175, 179, 183,
+ 187, 190, 194, 195, 198, 203, 205, 209, 211, 212,
+ 215, 217, 218, 223, 226, 231, 236, 237, 240, 242,
+ 244, 246, 248, 250, 252, 253
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yysigned_char yyrhs[] =
+{
+ 50, 0, -1, -1, 52, -1, 53, -1, 52, -1,
+ 57, -1, 57, 52, -1, 32, 65, 54, 11, 51,
+ -1, -1, 14, 65, -1, 53, -1, 7, 64, 8,
+ -1, -1, 32, -1, -1, 43, 51, 46, -1, 31,
+ 65, 11, -1, 47, 64, 11, -1, 67, 60, 65,
+ 11, -1, 67, 34, 65, 60, 65, 11, -1, 37,
+ 65, 11, -1, 27, 56, 47, 30, 65, 43, 51,
+ 46, -1, 39, 65, 43, 62, 46, -1, 28, 61,
+ 43, 51, 46, -1, 33, 65, 43, 51, 46, -1,
+ 23, 64, 43, 51, 46, -1, 42, 61, 43, 51,
+ 46, -1, 28, 61, 43, 51, 46, 25, 57, -1,
+ 56, 38, 47, 55, 57, -1, 34, 67, 57, -1,
+ -1, -1, 20, 70, 47, 72, 43, 58, 48, 59,
+ 46, -1, 14, -1, 9, -1, 17, -1, 24, 14,
+ -1, 67, -1, 61, 14, 61, -1, 61, 4, 61,
+ -1, 61, 12, 61, -1, 61, 13, 61, -1, 61,
+ 15, 61, -1, 61, 16, 61, -1, 61, 5, 61,
+ -1, 61, 6, 61, -1, 61, 44, 61, -1, 61,
+ 45, 61, -1, 67, 30, 65, -1, 3, 61, -1,
+ 7, 61, 8, -1, -1, 63, 62, -1, 22, 47,
+ 10, 51, -1, 65, -1, 65, 10, 64, -1, 66,
+ -1, -1, 66, 67, -1, 47, -1, -1, 18, 68,
+ 69, 19, -1, 67, 64, -1, 34, 67, 67, 64,
+ -1, 34, 67, 37, 65, -1, -1, 70, 71, -1,
+ 41, -1, 40, -1, 29, -1, 36, -1, 35, -1,
+ 26, -1, -1, 21, 65, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const unsigned short yyrline[] =
+{
+ 0, 139, 139, 141, 152, 154, 158, 160, 162, 167,
+ 170, 172, 176, 179, 182, 185, 188, 190, 192, 194,
+ 196, 198, 200, 202, 204, 206, 208, 210, 212, 214,
+ 216, 219, 221, 218, 230, 232, 234, 236, 243, 245,
+ 247, 249, 251, 253, 255, 257, 259, 261, 263, 265,
+ 267, 269, 281, 282, 286, 295, 297, 307, 312, 313,
+ 317, 319, 319, 328, 330, 332, 343, 344, 348, 350,
+ 352, 354, 356, 358, 368, 369
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "_BANG_t", "_BANG_EQUALS_t", "_AMPER_t",
+ "_AMPERAMPER_t", "_LPAREN_t", "_RPAREN_t", "_PLUS_EQUALS_t", "_COLON_t",
+ "_SEMIC_t", "_LANGLE_t", "_LANGLE_EQUALS_t", "_EQUALS_t", "_RANGLE_t",
+ "_RANGLE_EQUALS_t", "_QUESTION_EQUALS_t", "_LBRACKET_t", "_RBRACKET_t",
+ "ACTIONS_t", "BIND_t", "CASE_t", "CLASS_t", "DEFAULT_t", "ELSE_t",
+ "EXISTING_t", "FOR_t", "IF_t", "IGNORE_t", "IN_t", "INCLUDE_t",
+ "LOCAL_t", "MODULE_t", "ON_t", "PIECEMEAL_t", "QUIETLY_t", "RETURN_t",
+ "RULE_t", "SWITCH_t", "TOGETHER_t", "UPDATED_t", "WHILE_t", "_LBRACE_t",
+ "_BAR_t", "_BARBAR_t", "_RBRACE_t", "ARG", "STRING", "$accept", "run",
+ "block", "rules", "null", "assign_list_opt", "arglist_opt", "local_opt",
+ "rule", "@1", "@2", "assign", "expr", "cases", "case", "lol", "list",
+ "listp", "arg", "@3", "func", "eflags", "eflag", "bindlist", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const unsigned short yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const unsigned char yyr1[] =
+{
+ 0, 49, 50, 50, 51, 51, 52, 52, 52, 53,
+ 54, 54, 55, 55, 56, 56, 57, 57, 57, 57,
+ 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+ 57, 58, 59, 57, 60, 60, 60, 60, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 62, 62, 63, 64, 64, 65, 66, 66,
+ 67, 68, 67, 69, 69, 69, 70, 70, 71, 71,
+ 71, 71, 71, 71, 72, 72
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const unsigned char yyr2[] =
+{
+ 0, 2, 0, 1, 1, 1, 1, 2, 5, 0,
+ 2, 1, 3, 0, 1, 0, 3, 3, 3, 4,
+ 6, 3, 8, 5, 5, 5, 5, 5, 7, 5,
+ 3, 0, 0, 9, 1, 1, 1, 2, 1, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 3, 0, 2, 4, 1, 3, 1, 0, 2,
+ 1, 0, 4, 2, 4, 4, 0, 2, 1, 1,
+ 1, 1, 1, 1, 0, 2
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const unsigned char yydefact[] =
+{
+ 2, 61, 66, 58, 15, 0, 58, 58, 58, 0,
+ 58, 58, 0, 9, 60, 0, 3, 0, 6, 0,
+ 0, 0, 0, 55, 57, 14, 0, 0, 0, 60,
+ 0, 38, 0, 9, 0, 15, 0, 0, 0, 0,
+ 5, 4, 0, 1, 0, 7, 35, 34, 36, 0,
+ 58, 58, 0, 58, 0, 73, 70, 72, 71, 69,
+ 68, 74, 67, 9, 58, 59, 0, 50, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,
+ 58, 17, 58, 11, 0, 9, 30, 21, 52, 9,
+ 16, 18, 13, 37, 0, 0, 0, 63, 62, 58,
+ 0, 0, 56, 58, 51, 40, 45, 46, 41, 42,
+ 39, 43, 44, 0, 47, 48, 49, 10, 9, 0,
+ 0, 0, 52, 0, 58, 15, 58, 19, 58, 58,
+ 75, 31, 26, 0, 24, 8, 25, 0, 23, 53,
+ 27, 0, 29, 0, 65, 64, 0, 9, 15, 9,
+ 12, 20, 32, 0, 28, 54, 0, 22, 33
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const short yydefgoto[] =
+{
+ -1, 15, 39, 40, 41, 84, 125, 17, 18, 146,
+ 156, 51, 30, 121, 122, 22, 23, 24, 31, 20,
+ 54, 21, 62, 100
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -48
+static const short yypact[] =
+{
+ 179, -48, -48, -48, -15, 7, -48, -16, -48, 3,
+ -48, -48, 7, 179, 1, 27, -48, -9, 179, 19,
+ -3, 33, -11, 24, 3, -48, -10, 7, 7, -48,
+ 138, 9, 30, 35, 13, 205, 53, 22, 151, 20,
+ -48, -48, 56, -48, 23, -48, -48, -48, -48, 61,
+ -48, -48, 3, -48, 62, -48, -48, -48, -48, -48,
+ -48, 58, -48, 179, -48, -48, 52, -48, 164, 7,
+ 7, 7, 7, 7, 7, 7, 7, 179, 7, 7,
+ -48, -48, -48, -48, 72, 179, -48, -48, 68, 179,
+ -48, -48, 85, -48, 77, 73, 8, -48, -48, -48,
+ 50, 57, -48, -48, -48, 45, 93, 93, -48, -48,
+ 45, -48, -48, 64, 245, 245, -48, -48, 179, 66,
+ 67, 69, 68, 71, -48, 205, -48, -48, -48, -48,
+ -48, -48, -48, 70, 79, -48, -48, 109, -48, -48,
+ -48, 112, -48, 115, -48, -48, 75, 179, 205, 179,
+ -48, -48, -48, 81, -48, -48, 82, -48, -48
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const short yypgoto[] =
+{
+ -48, -48, -47, 5, 104, -48, -48, 136, -27, -48,
+ -48, 47, 60, 36, -48, -13, -4, -48, 0, -48,
+ -48, -48, -48, -48
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -59
+static const short yytable[] =
+{
+ 19, 42, 32, 33, 34, 16, 36, 37, 86, 35,
+ 27, -58, -58, 19, 28, 1, 101, 25, 19, -58,
+ 53, 1, -14, 45, 65, 1, 1, 43, 46, 44,
+ 113, 52, 63, 47, 64, 19, 48, 66, 119, 80,
+ 97, 81, 123, 49, 29, 128, 94, 95, -58, 82,
+ 29, 102, 96, 50, 29, 29, 85, 72, 73, 55,
+ 75, 76, 56, 19, 87, 88, 90, 91, 57, 58,
+ 92, 135, 38, 59, 60, 93, 116, 19, 117, 99,
+ 61, 98, 103, 118, 127, 19, 46, 67, 68, 19,
+ 120, 47, 124, 131, 48, 130, 129, 69, 142, 133,
+ 153, 49, 155, 132, 148, 72, 73, 74, 75, 76,
+ 134, 141, 136, 147, 137, 138, 145, 140, 19, 149,
+ 150, 154, 143, 152, 144, 19, 151, 157, 158, 105,
+ 106, 107, 108, 109, 110, 111, 112, 83, 114, 115,
+ 26, 126, 69, 70, 71, 0, 0, 19, 19, 19,
+ 72, 73, 74, 75, 76, 69, 70, 71, 139, 0,
+ 0, 0, 0, 72, 73, 74, 75, 76, 69, 70,
+ 71, 0, 104, 0, 0, 0, 72, 73, 74, 75,
+ 76, 77, 78, 79, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 89, 78, 79, 1, 0, 2,
+ 0, 0, 3, 0, 0, 0, 4, 5, 78, 79,
+ 6, 7, 8, 9, 0, 0, 10, -15, 11, 0,
+ 0, 12, 13, 1, 0, 2, 14, 0, 3, 0,
+ 0, 0, 4, 5, 0, 0, 6, 25, 8, 9,
+ 0, 0, 10, 0, 11, 0, 0, 12, 13, 69,
+ 70, 71, 14, 0, 0, 0, 0, 72, 73, 74,
+ 75, 76
+};
+
+static const short yycheck[] =
+{
+ 0, 14, 6, 7, 8, 0, 10, 11, 35, 9,
+ 3, 10, 11, 13, 7, 18, 63, 32, 18, 18,
+ 20, 18, 38, 18, 24, 18, 18, 0, 9, 38,
+ 77, 34, 43, 14, 10, 35, 17, 47, 85, 30,
+ 53, 11, 89, 24, 47, 37, 50, 51, 47, 14,
+ 47, 64, 52, 34, 47, 47, 43, 12, 13, 26,
+ 15, 16, 29, 63, 11, 43, 46, 11, 35, 36,
+ 47, 118, 12, 40, 41, 14, 80, 77, 82, 21,
+ 47, 19, 30, 11, 11, 85, 9, 27, 28, 89,
+ 22, 14, 7, 43, 17, 99, 96, 4, 125, 103,
+ 147, 24, 149, 46, 25, 12, 13, 14, 15, 16,
+ 46, 124, 46, 43, 47, 46, 129, 46, 118, 10,
+ 8, 148, 126, 48, 128, 125, 11, 46, 46, 69,
+ 70, 71, 72, 73, 74, 75, 76, 33, 78, 79,
+ 4, 94, 4, 5, 6, -1, -1, 147, 148, 149,
+ 12, 13, 14, 15, 16, 4, 5, 6, 122, -1,
+ -1, -1, -1, 12, 13, 14, 15, 16, 4, 5,
+ 6, -1, 8, -1, -1, -1, 12, 13, 14, 15,
+ 16, 43, 44, 45, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 43, 44, 45, 18, -1, 20,
+ -1, -1, 23, -1, -1, -1, 27, 28, 44, 45,
+ 31, 32, 33, 34, -1, -1, 37, 38, 39, -1,
+ -1, 42, 43, 18, -1, 20, 47, -1, 23, -1,
+ -1, -1, 27, 28, -1, -1, 31, 32, 33, 34,
+ -1, -1, 37, -1, 39, -1, -1, 42, 43, 4,
+ 5, 6, 47, -1, -1, -1, -1, 12, 13, 14,
+ 15, 16
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const unsigned char yystos[] =
+{
+ 0, 18, 20, 23, 27, 28, 31, 32, 33, 34,
+ 37, 39, 42, 43, 47, 50, 52, 56, 57, 67,
+ 68, 70, 64, 65, 66, 32, 56, 3, 7, 47,
+ 61, 67, 65, 65, 65, 67, 65, 65, 61, 51,
+ 52, 53, 64, 0, 38, 52, 9, 14, 17, 24,
+ 34, 60, 34, 67, 69, 26, 29, 35, 36, 40,
+ 41, 47, 71, 43, 10, 67, 47, 61, 61, 4,
+ 5, 6, 12, 13, 14, 15, 16, 43, 44, 45,
+ 30, 11, 14, 53, 54, 43, 57, 11, 43, 43,
+ 46, 11, 47, 14, 65, 65, 67, 64, 19, 21,
+ 72, 51, 64, 30, 8, 61, 61, 61, 61, 61,
+ 61, 61, 61, 51, 61, 61, 65, 65, 11, 51,
+ 22, 62, 63, 51, 7, 55, 60, 11, 37, 67,
+ 65, 43, 46, 65, 46, 51, 46, 47, 46, 62,
+ 46, 64, 57, 65, 65, 64, 58, 43, 25, 10,
+ 8, 11, 48, 51, 57, 51, 59, 46, 46
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrlab1
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror ("syntax error: cannot back up");\
+ YYERROR; \
+ } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+ are run). */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ Current.first_line = Rhs[1].first_line; \
+ Current.first_column = Rhs[1].first_column; \
+ Current.last_line = Rhs[N].last_line; \
+ Current.last_column = Rhs[N].last_column;
+#endif
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+# define YYDSYMPRINT(Args) \
+do { \
+ if (yydebug) \
+ yysymprint Args; \
+} while (0)
+
+# define YYDSYMPRINTF(Title, Token, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yysymprint (stderr, \
+ Token, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (cinluded). |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short *bottom, short *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ short *bottom;
+ short *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (/* Nothing. */; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+ int yyrule;
+#endif
+{
+ int yyi;
+ unsigned int yylineno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+ yyrule - 1, yylineno);
+ /* Print the symbols being reduced, and their result. */
+ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+ YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+ YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (Rule); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YYDSYMPRINT(Args)
+# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined (__GLIBC__) && defined (_STRING_H)
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+# if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+# else
+yystrlen (yystr)
+ const char *yystr;
+# endif
+{
+ register const char *yys = yystr;
+
+ while (*yys++ != '\0')
+ continue;
+
+ return yys - yystr - 1;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+# if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+# else
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+# endif
+{
+ register char *yyd = yydest;
+ register const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+
+
+#if YYDEBUG
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ if (yytype < YYNTOKENS)
+ {
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+# ifdef YYPRINT
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ }
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+ YYFPRINTF (yyoutput, ")");
+}
+
+#endif /* ! YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yydestruct (int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yytype, yyvaluep)
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+# else
+int yyparse ();
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+ register int yystate;
+ register int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ short yyssa[YYINITDEPTH];
+ short *yyss = yyssa;
+ register short *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK (yyvsp--, yyssp--)
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* When reducing, the number of symbols on the RHS of the reduced
+ rule. */
+ int yylen;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks.
+ */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow ("parser stack overflow",
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyoverflowlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyoverflowlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ short *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyoverflowlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 3:
+#line 142 "jamgram.y"
+ { parse_save( yyvsp[0].parse ); }
+ break;
+
+ case 4:
+#line 153 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; }
+ break;
+
+ case 5:
+#line 155 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; }
+ break;
+
+ case 6:
+#line 159 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; }
+ break;
+
+ case 7:
+#line 161 "jamgram.y"
+ { yyval.parse = prules( yyvsp[-1].parse, yyvsp[0].parse ); }
+ break;
+
+ case 8:
+#line 163 "jamgram.y"
+ { yyval.parse = plocal( yyvsp[-3].parse, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 9:
+#line 167 "jamgram.y"
+ { yyval.parse = pnull(); }
+ break;
+
+ case 10:
+#line 171 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; yyval.number = ASSIGN_SET; }
+ break;
+
+ case 11:
+#line 173 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; yyval.number = ASSIGN_APPEND; }
+ break;
+
+ case 12:
+#line 177 "jamgram.y"
+ { yyval.parse = yyvsp[-1].parse; }
+ break;
+
+ case 13:
+#line 179 "jamgram.y"
+ { yyval.parse = P0; }
+ break;
+
+ case 14:
+#line 183 "jamgram.y"
+ { yyval.number = 1; }
+ break;
+
+ case 15:
+#line 185 "jamgram.y"
+ { yyval.number = 0; }
+ break;
+
+ case 16:
+#line 189 "jamgram.y"
+ { yyval.parse = yyvsp[-1].parse; }
+ break;
+
+ case 17:
+#line 191 "jamgram.y"
+ { yyval.parse = pincl( yyvsp[-1].parse ); }
+ break;
+
+ case 18:
+#line 193 "jamgram.y"
+ { yyval.parse = prule( yyvsp[-2].string, yyvsp[-1].parse ); }
+ break;
+
+ case 19:
+#line 195 "jamgram.y"
+ { yyval.parse = pset( yyvsp[-3].parse, yyvsp[-1].parse, yyvsp[-2].number ); }
+ break;
+
+ case 20:
+#line 197 "jamgram.y"
+ { yyval.parse = pset1( yyvsp[-5].parse, yyvsp[-3].parse, yyvsp[-1].parse, yyvsp[-2].number ); }
+ break;
+
+ case 21:
+#line 199 "jamgram.y"
+ { yyval.parse = yyvsp[-1].parse; }
+ break;
+
+ case 22:
+#line 201 "jamgram.y"
+ { yyval.parse = pfor( yyvsp[-5].string, yyvsp[-3].parse, yyvsp[-1].parse, yyvsp[-6].number ); }
+ break;
+
+ case 23:
+#line 203 "jamgram.y"
+ { yyval.parse = pswitch( yyvsp[-3].parse, yyvsp[-1].parse ); }
+ break;
+
+ case 24:
+#line 205 "jamgram.y"
+ { yyval.parse = pif( yyvsp[-3].parse, yyvsp[-1].parse, pnull() ); }
+ break;
+
+ case 25:
+#line 207 "jamgram.y"
+ { yyval.parse = pmodule( yyvsp[-3].parse, yyvsp[-1].parse ); }
+ break;
+
+ case 26:
+#line 209 "jamgram.y"
+ { yyval.parse = pclass( yyvsp[-3].parse, yyvsp[-1].parse ); }
+ break;
+
+ case 27:
+#line 211 "jamgram.y"
+ { yyval.parse = pwhile( yyvsp[-3].parse, yyvsp[-1].parse ); }
+ break;
+
+ case 28:
+#line 213 "jamgram.y"
+ { yyval.parse = pif( yyvsp[-5].parse, yyvsp[-3].parse, yyvsp[0].parse ); }
+ break;
+
+ case 29:
+#line 215 "jamgram.y"
+ { yyval.parse = psetc( yyvsp[-2].string, yyvsp[0].parse, yyvsp[-1].parse, yyvsp[-4].number ); }
+ break;
+
+ case 30:
+#line 217 "jamgram.y"
+ { yyval.parse = pon( yyvsp[-1].parse, yyvsp[0].parse ); }
+ break;
+
+ case 31:
+#line 219 "jamgram.y"
+ { yymode( SCAN_STRING ); }
+ break;
+
+ case 32:
+#line 221 "jamgram.y"
+ { yymode( SCAN_NORMAL ); }
+ break;
+
+ case 33:
+#line 223 "jamgram.y"
+ { yyval.parse = psete( yyvsp[-6].string,yyvsp[-5].parse,yyvsp[-2].string,yyvsp[-7].number ); }
+ break;
+
+ case 34:
+#line 231 "jamgram.y"
+ { yyval.number = ASSIGN_SET; }
+ break;
+
+ case 35:
+#line 233 "jamgram.y"
+ { yyval.number = ASSIGN_APPEND; }
+ break;
+
+ case 36:
+#line 235 "jamgram.y"
+ { yyval.number = ASSIGN_DEFAULT; }
+ break;
+
+ case 37:
+#line 237 "jamgram.y"
+ { yyval.number = ASSIGN_DEFAULT; }
+ break;
+
+ case 38:
+#line 244 "jamgram.y"
+ { yyval.parse = peval( EXPR_EXISTS, yyvsp[0].parse, pnull() ); }
+ break;
+
+ case 39:
+#line 246 "jamgram.y"
+ { yyval.parse = peval( EXPR_EQUALS, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 40:
+#line 248 "jamgram.y"
+ { yyval.parse = peval( EXPR_NOTEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 41:
+#line 250 "jamgram.y"
+ { yyval.parse = peval( EXPR_LESS, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 42:
+#line 252 "jamgram.y"
+ { yyval.parse = peval( EXPR_LESSEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 43:
+#line 254 "jamgram.y"
+ { yyval.parse = peval( EXPR_MORE, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 44:
+#line 256 "jamgram.y"
+ { yyval.parse = peval( EXPR_MOREEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 45:
+#line 258 "jamgram.y"
+ { yyval.parse = peval( EXPR_AND, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 46:
+#line 260 "jamgram.y"
+ { yyval.parse = peval( EXPR_AND, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 47:
+#line 262 "jamgram.y"
+ { yyval.parse = peval( EXPR_OR, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 48:
+#line 264 "jamgram.y"
+ { yyval.parse = peval( EXPR_OR, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 49:
+#line 266 "jamgram.y"
+ { yyval.parse = peval( EXPR_IN, yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 50:
+#line 268 "jamgram.y"
+ { yyval.parse = peval( EXPR_NOT, yyvsp[0].parse, pnull() ); }
+ break;
+
+ case 51:
+#line 270 "jamgram.y"
+ { yyval.parse = yyvsp[-1].parse; }
+ break;
+
+ case 52:
+#line 281 "jamgram.y"
+ { yyval.parse = P0; }
+ break;
+
+ case 53:
+#line 283 "jamgram.y"
+ { yyval.parse = pnode( yyvsp[-1].parse, yyvsp[0].parse ); }
+ break;
+
+ case 54:
+#line 287 "jamgram.y"
+ { yyval.parse = psnode( yyvsp[-2].string, yyvsp[0].parse ); }
+ break;
+
+ case 55:
+#line 296 "jamgram.y"
+ { yyval.parse = pnode( P0, yyvsp[0].parse ); }
+ break;
+
+ case 56:
+#line 298 "jamgram.y"
+ { yyval.parse = pnode( yyvsp[0].parse, yyvsp[-2].parse ); }
+ break;
+
+ case 57:
+#line 308 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; yymode( SCAN_NORMAL ); }
+ break;
+
+ case 58:
+#line 312 "jamgram.y"
+ { yyval.parse = pnull(); yymode( SCAN_PUNCT ); }
+ break;
+
+ case 59:
+#line 314 "jamgram.y"
+ { yyval.parse = pappend( yyvsp[-1].parse, yyvsp[0].parse ); }
+ break;
+
+ case 60:
+#line 318 "jamgram.y"
+ { yyval.parse = plist( yyvsp[0].string ); }
+ break;
+
+ case 61:
+#line 319 "jamgram.y"
+ { yymode( SCAN_NORMAL ); }
+ break;
+
+ case 62:
+#line 320 "jamgram.y"
+ { yyval.parse = yyvsp[-1].parse; }
+ break;
+
+ case 63:
+#line 329 "jamgram.y"
+ { yyval.parse = prule( yyvsp[-1].string, yyvsp[0].parse ); }
+ break;
+
+ case 64:
+#line 331 "jamgram.y"
+ { yyval.parse = pon( yyvsp[-2].parse, prule( yyvsp[-1].string, yyvsp[0].parse ) ); }
+ break;
+
+ case 65:
+#line 333 "jamgram.y"
+ { yyval.parse = pon( yyvsp[-2].parse, yyvsp[0].parse ); }
+ break;
+
+ case 66:
+#line 343 "jamgram.y"
+ { yyval.number = 0; }
+ break;
+
+ case 67:
+#line 345 "jamgram.y"
+ { yyval.number = yyvsp[-1].number | yyvsp[0].number; }
+ break;
+
+ case 68:
+#line 349 "jamgram.y"
+ { yyval.number = EXEC_UPDATED; }
+ break;
+
+ case 69:
+#line 351 "jamgram.y"
+ { yyval.number = EXEC_TOGETHER; }
+ break;
+
+ case 70:
+#line 353 "jamgram.y"
+ { yyval.number = EXEC_IGNORE; }
+ break;
+
+ case 71:
+#line 355 "jamgram.y"
+ { yyval.number = EXEC_QUIETLY; }
+ break;
+
+ case 72:
+#line 357 "jamgram.y"
+ { yyval.number = EXEC_PIECEMEAL; }
+ break;
+
+ case 73:
+#line 359 "jamgram.y"
+ { yyval.number = EXEC_EXISTING; }
+ break;
+
+ case 74:
+#line 368 "jamgram.y"
+ { yyval.parse = pnull(); }
+ break;
+
+ case 75:
+#line 370 "jamgram.y"
+ { yyval.parse = yyvsp[0].parse; }
+ break;
+
+
+ }
+
+/* Line 991 of yacc.c. */
+#line 1621 "y.tab.c"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+
+
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (YYPACT_NINF < yyn && yyn < YYLAST)
+ {
+ YYSIZE_T yysize = 0;
+ int yytype = YYTRANSLATE (yychar);
+ char *yymsg;
+ int yyx, yycount;
+
+ yycount = 0;
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ for (yyx = yyn < 0 ? -yyn : 0;
+ yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+ yysize += yystrlen ("syntax error, unexpected ") + 1;
+ yysize += yystrlen (yytname[yytype]);
+ yymsg = (char *) YYSTACK_ALLOC (yysize);
+ if (yymsg != 0)
+ {
+ char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
+ yyp = yystpcpy (yyp, yytname[yytype]);
+
+ if (yycount < 5)
+ {
+ yycount = 0;
+ for (yyx = yyn < 0 ? -yyn : 0;
+ yyx < (int) (sizeof (yytname) / sizeof (char *));
+ yyx++)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ const char *yyq = ! yycount ? ", expecting " : " or ";
+ yyp = yystpcpy (yyp, yyq);
+ yyp = yystpcpy (yyp, yytname[yyx]);
+ yycount++;
+ }
+ }
+ yyerror (yymsg);
+ YYSTACK_FREE (yymsg);
+ }
+ else
+ yyerror ("syntax error; also virtual memory exhausted");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror ("syntax error");
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ {
+ /* Pop the error token. */
+ YYPOPSTACK;
+ /* Pop the rest of the stack. */
+ while (yyss < yyssp)
+ {
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[*yyssp], yyvsp);
+ YYPOPSTACK;
+ }
+ YYABORT;
+ }
+
+ YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+ yydestruct (yytoken, &yylval);
+ yychar = YYEMPTY;
+
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab2;
+
+
+/*----------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action. |
+`----------------------------------------------------*/
+yyerrlab1:
+
+ /* Suppress GCC warning that yyerrlab1 is unused when no action
+ invokes YYERROR. */
+#if defined (__GNUC_MINOR__) && 2093 <= (__GNUC__ * 1000 + __GNUC_MINOR__)
+ __attribute__ ((__unused__))
+#endif
+
+
+ goto yyerrlab2;
+
+
+/*---------------------------------------------------------------.
+| yyerrlab2 -- pop states until the error token can be shifted. |
+`---------------------------------------------------------------*/
+yyerrlab2:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[yystate], yyvsp);
+ yyvsp--;
+ yystate = *--yyssp;
+
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ YYDPRINTF ((stderr, "Shifting error token, "));
+
+ *++yyvsp = yylval;
+
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here. |
+`----------------------------------------------*/
+yyoverflowlab:
+ yyerror ("parser stack overflow");
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+ return yyresult;
+}
+
+
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,140 @@
+/* A Bison parser, made by GNU Bison 1.875. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ _BANG_t = 258,
+ _BANG_EQUALS_t = 259,
+ _AMPER_t = 260,
+ _AMPERAMPER_t = 261,
+ _LPAREN_t = 262,
+ _RPAREN_t = 263,
+ _PLUS_EQUALS_t = 264,
+ _COLON_t = 265,
+ _SEMIC_t = 266,
+ _LANGLE_t = 267,
+ _LANGLE_EQUALS_t = 268,
+ _EQUALS_t = 269,
+ _RANGLE_t = 270,
+ _RANGLE_EQUALS_t = 271,
+ _QUESTION_EQUALS_t = 272,
+ _LBRACKET_t = 273,
+ _RBRACKET_t = 274,
+ ACTIONS_t = 275,
+ BIND_t = 276,
+ CASE_t = 277,
+ CLASS_t = 278,
+ DEFAULT_t = 279,
+ ELSE_t = 280,
+ EXISTING_t = 281,
+ FOR_t = 282,
+ IF_t = 283,
+ IGNORE_t = 284,
+ IN_t = 285,
+ INCLUDE_t = 286,
+ LOCAL_t = 287,
+ MODULE_t = 288,
+ ON_t = 289,
+ PIECEMEAL_t = 290,
+ QUIETLY_t = 291,
+ RETURN_t = 292,
+ RULE_t = 293,
+ SWITCH_t = 294,
+ TOGETHER_t = 295,
+ UPDATED_t = 296,
+ WHILE_t = 297,
+ _LBRACE_t = 298,
+ _BAR_t = 299,
+ _BARBAR_t = 300,
+ _RBRACE_t = 301,
+ ARG = 302,
+ STRING = 303
+ };
+#endif
+#define _BANG_t 258
+#define _BANG_EQUALS_t 259
+#define _AMPER_t 260
+#define _AMPERAMPER_t 261
+#define _LPAREN_t 262
+#define _RPAREN_t 263
+#define _PLUS_EQUALS_t 264
+#define _COLON_t 265
+#define _SEMIC_t 266
+#define _LANGLE_t 267
+#define _LANGLE_EQUALS_t 268
+#define _EQUALS_t 269
+#define _RANGLE_t 270
+#define _RANGLE_EQUALS_t 271
+#define _QUESTION_EQUALS_t 272
+#define _LBRACKET_t 273
+#define _RBRACKET_t 274
+#define ACTIONS_t 275
+#define BIND_t 276
+#define CASE_t 277
+#define CLASS_t 278
+#define DEFAULT_t 279
+#define ELSE_t 280
+#define EXISTING_t 281
+#define FOR_t 282
+#define IF_t 283
+#define IGNORE_t 284
+#define IN_t 285
+#define INCLUDE_t 286
+#define LOCAL_t 287
+#define MODULE_t 288
+#define ON_t 289
+#define PIECEMEAL_t 290
+#define QUIETLY_t 291
+#define RETURN_t 292
+#define RULE_t 293
+#define SWITCH_t 294
+#define TOGETHER_t 295
+#define UPDATED_t 296
+#define WHILE_t 297
+#define _LBRACE_t 298
+#define _BAR_t 299
+#define _BARBAR_t 300
+#define _RBRACE_t 301
+#define ARG 302
+#define STRING 303
+
+
+
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+typedef int YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE yylval;
+
+
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.y
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.y 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.y 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,373 @@
+%token _BANG_t
+%token _BANG_EQUALS_t
+%token _AMPER_t
+%token _AMPERAMPER_t
+%token _LPAREN_t
+%token _RPAREN_t
+%token _PLUS_EQUALS_t
+%token _COLON_t
+%token _SEMIC_t
+%token _LANGLE_t
+%token _LANGLE_EQUALS_t
+%token _EQUALS_t
+%token _RANGLE_t
+%token _RANGLE_EQUALS_t
+%token _QUESTION_EQUALS_t
+%token _LBRACKET_t
+%token _RBRACKET_t
+%token ACTIONS_t
+%token BIND_t
+%token CASE_t
+%token CLASS_t
+%token DEFAULT_t
+%token ELSE_t
+%token EXISTING_t
+%token FOR_t
+%token IF_t
+%token IGNORE_t
+%token IN_t
+%token INCLUDE_t
+%token LOCAL_t
+%token MODULE_t
+%token ON_t
+%token PIECEMEAL_t
+%token QUIETLY_t
+%token RETURN_t
+%token RULE_t
+%token SWITCH_t
+%token TOGETHER_t
+%token UPDATED_t
+%token WHILE_t
+%token _LBRACE_t
+%token _BAR_t
+%token _BARBAR_t
+%token _RBRACE_t
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * jamgram.yy - jam grammar
+ *
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 06/01/94 (seiwald) - new 'actions existing' does existing sources
+ * 08/23/94 (seiwald) - Support for '+=' (append to variable)
+ * 08/31/94 (seiwald) - Allow ?= as alias for "default =".
+ * 09/15/94 (seiwald) - if conditionals take only single arguments, so
+ * that 'if foo == bar' gives syntax error (use =).
+ * 02/11/95 (seiwald) - when scanning arguments to rules, only treat
+ * punctuation keywords as keywords. All arg lists
+ * are terminated with punctuation keywords.
+ *
+ * 09/11/00 (seiwald) - Support for function calls:
+ *
+ * Rules now return lists (LIST *), rather than void.
+ *
+ * New "[ rule ]" syntax evals rule into a LIST.
+ *
+ * Lists are now generated by compile_list() and
+ * compile_append(), and any other rule that indirectly
+ * makes a list, rather than being built directly here,
+ * so that lists values can contain rule evaluations.
+ *
+ * New 'return' rule sets the return value, though
+ * other statements also may have return values.
+ *
+ * 'run' production split from 'block' production so
+ * that empty blocks can be handled separately.
+ */
+
+%token ARG STRING
+
+%left _BARBAR_t _BAR_t
+%left _AMPERAMPER_t _AMPER_t
+%left _EQUALS_t _BANG_EQUALS_t IN_t
+%left _LANGLE_t _LANGLE_EQUALS_t _RANGLE_t _RANGLE_EQUALS_t
+%left _BANG_t
+
+%{
+#include "jam.h"
+
+#include "lists.h"
+#include "parse.h"
+#include "scan.h"
+#include "compile.h"
+#include "newstr.h"
+#include "rules.h"
+
+# define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
+
+# define F0 (LIST *(*)(PARSE *, FRAME *))0
+# define P0 (PARSE *)0
+# define S0 (char *)0
+
+# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
+# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
+# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
+# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
+# define pincl( l ) parse_make( compile_include,l,P0,P0,S0,S0,0 )
+# define plist( s ) parse_make( compile_list,P0,P0,P0,s,S0,0 )
+# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
+# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
+# define pclass( l,r ) parse_make( compile_class,l,r,P0,S0,S0,0 )
+# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
+# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 )
+# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
+# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
+# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
+# define pset1( l,r,t,a ) parse_make( compile_settings,l,r,t,S0,S0,a )
+# define psetc( s,p,a,l ) parse_make( compile_setcomp,p,a,P0,s,S0,l )
+# define psete( s,l,s1,f ) parse_make( compile_setexec,l,P0,P0,s,s1,f )
+# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
+# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
+
+# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
+# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
+
+%}
+
+%%
+
+run : /* empty */
+ /* do nothing */
+ | rules
+ { parse_save( $1.parse ); }
+ ;
+
+/*
+ * block - zero or more rules
+ * rules - one or more rules
+ * rule - any one of jam's rules
+ * right-recursive so rules execute in order.
+ */
+
+block : null
+ { $$.parse = $1.parse; }
+ | rules
+ { $$.parse = $1.parse; }
+ ;
+
+rules : rule
+ { $$.parse = $1.parse; }
+ | rule rules
+ { $$.parse = prules( $1.parse, $2.parse ); }
+ | LOCAL_t list assign_list_opt _SEMIC_t block
+ { $$.parse = plocal( $2.parse, $3.parse, $5.parse ); }
+ ;
+
+null : /* empty */
+ { $$.parse = pnull(); }
+ ;
+
+assign_list_opt : _EQUALS_t list
+ { $$.parse = $2.parse; $$.number = ASSIGN_SET; }
+ | null
+ { $$.parse = $1.parse; $$.number = ASSIGN_APPEND; }
+ ;
+
+arglist_opt : _LPAREN_t lol _RPAREN_t
+ { $$.parse = $2.parse; }
+ |
+ { $$.parse = P0; }
+ ;
+
+local_opt : LOCAL_t
+ { $$.number = 1; }
+ | /* empty */
+ { $$.number = 0; }
+ ;
+
+rule : _LBRACE_t block _RBRACE_t
+ { $$.parse = $2.parse; }
+ | INCLUDE_t list _SEMIC_t
+ { $$.parse = pincl( $2.parse ); }
+ | ARG lol _SEMIC_t
+ { $$.parse = prule( $1.string, $2.parse ); }
+ | arg assign list _SEMIC_t
+ { $$.parse = pset( $1.parse, $3.parse, $2.number ); }
+ | arg ON_t list assign list _SEMIC_t
+ { $$.parse = pset1( $1.parse, $3.parse, $5.parse, $4.number ); }
+ | RETURN_t list _SEMIC_t
+ { $$.parse = $2.parse; }
+ | FOR_t local_opt ARG IN_t list _LBRACE_t block _RBRACE_t
+ { $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); }
+ | SWITCH_t list _LBRACE_t cases _RBRACE_t
+ { $$.parse = pswitch( $2.parse, $4.parse ); }
+ | IF_t expr _LBRACE_t block _RBRACE_t
+ { $$.parse = pif( $2.parse, $4.parse, pnull() ); }
+ | MODULE_t list _LBRACE_t block _RBRACE_t
+ { $$.parse = pmodule( $2.parse, $4.parse ); }
+ | CLASS_t lol _LBRACE_t block _RBRACE_t
+ { $$.parse = pclass( $2.parse, $4.parse ); }
+ | WHILE_t expr _LBRACE_t block _RBRACE_t
+ { $$.parse = pwhile( $2.parse, $4.parse ); }
+ | IF_t expr _LBRACE_t block _RBRACE_t ELSE_t rule
+ { $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
+ | local_opt RULE_t ARG arglist_opt rule
+ { $$.parse = psetc( $3.string, $5.parse, $4.parse, $1.number ); }
+ | ON_t arg rule
+ { $$.parse = pon( $2.parse, $3.parse ); }
+ | ACTIONS_t eflags ARG bindlist _LBRACE_t
+ { yymode( SCAN_STRING ); }
+ STRING
+ { yymode( SCAN_NORMAL ); }
+ _RBRACE_t
+ { $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); }
+ ;
+
+/*
+ * assign - = or +=
+ */
+
+assign : _EQUALS_t
+ { $$.number = ASSIGN_SET; }
+ | _PLUS_EQUALS_t
+ { $$.number = ASSIGN_APPEND; }
+ | _QUESTION_EQUALS_t
+ { $$.number = ASSIGN_DEFAULT; }
+ | DEFAULT_t _EQUALS_t
+ { $$.number = ASSIGN_DEFAULT; }
+ ;
+
+/*
+ * expr - an expression for if
+ */
+expr : arg
+ { $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); }
+ | expr _EQUALS_t expr
+ { $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); }
+ | expr _BANG_EQUALS_t expr
+ { $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); }
+ | expr _LANGLE_t expr
+ { $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); }
+ | expr _LANGLE_EQUALS_t expr
+ { $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); }
+ | expr _RANGLE_t expr
+ { $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); }
+ | expr _RANGLE_EQUALS_t expr
+ { $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); }
+ | expr _AMPER_t expr
+ { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
+ | expr _AMPERAMPER_t expr
+ { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
+ | expr _BAR_t expr
+ { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
+ | expr _BARBAR_t expr
+ { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
+ | arg IN_t list
+ { $$.parse = peval( EXPR_IN, $1.parse, $3.parse ); }
+ | _BANG_t expr
+ { $$.parse = peval( EXPR_NOT, $2.parse, pnull() ); }
+ | _LPAREN_t expr _RPAREN_t
+ { $$.parse = $2.parse; }
+ ;
+
+
+/*
+ * cases - action elements inside a 'switch'
+ * case - a single action element inside a 'switch'
+ * right-recursive rule so cases can be examined in order.
+ */
+
+cases : /* empty */
+ { $$.parse = P0; }
+ | case cases
+ { $$.parse = pnode( $1.parse, $2.parse ); }
+ ;
+
+case : CASE_t ARG _COLON_t block
+ { $$.parse = psnode( $2.string, $4.parse ); }
+ ;
+
+/*
+ * lol - list of lists
+ * right-recursive rule so that lists can be added in order.
+ */
+
+lol : list
+ { $$.parse = pnode( P0, $1.parse ); }
+ | list _COLON_t lol
+ { $$.parse = pnode( $3.parse, $1.parse ); }
+ ;
+
+/*
+ * list - zero or more args in a LIST
+ * listp - list (in puncutation only mode)
+ * arg - one ARG or function call
+ */
+
+list : listp
+ { $$.parse = $1.parse; yymode( SCAN_NORMAL ); }
+ ;
+
+listp : /* empty */
+ { $$.parse = pnull(); yymode( SCAN_PUNCT ); }
+ | listp arg
+ { $$.parse = pappend( $1.parse, $2.parse ); }
+ ;
+
+arg : ARG
+ { $$.parse = plist( $1.string ); }
+ | _LBRACKET_t { yymode( SCAN_NORMAL ); } func _RBRACKET_t
+ { $$.parse = $3.parse; }
+ ;
+
+/*
+ * func - a function call (inside [])
+ * This needs to be split cleanly out of 'rule'
+ */
+
+func : arg lol
+ { $$.parse = prule( $1.string, $2.parse ); }
+ | ON_t arg arg lol
+ { $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
+ | ON_t arg RETURN_t list
+ { $$.parse = pon( $2.parse, $4.parse ); }
+ ;
+
+
+/*
+ * eflags - zero or more modifiers to 'executes'
+ * eflag - a single modifier to 'executes'
+ */
+
+eflags : /* empty */
+ { $$.number = 0; }
+ | eflags eflag
+ { $$.number = $1.number | $2.number; }
+ ;
+
+eflag : UPDATED_t
+ { $$.number = EXEC_UPDATED; }
+ | TOGETHER_t
+ { $$.number = EXEC_TOGETHER; }
+ | IGNORE_t
+ { $$.number = EXEC_IGNORE; }
+ | QUIETLY_t
+ { $$.number = EXEC_QUIETLY; }
+ | PIECEMEAL_t
+ { $$.number = EXEC_PIECEMEAL; }
+ | EXISTING_t
+ { $$.number = EXEC_EXISTING; }
+ ;
+
+
+/*
+ * bindlist - list of variable to bind for an action
+ */
+
+bindlist : /* empty */
+ { $$.parse = pnull(); }
+ | BIND_t list
+ { $$.parse = $2.parse; }
+ ;
+
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.yy
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.yy 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/jamgram.yy 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,329 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * jamgram.yy - jam grammar
+ *
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 06/01/94 (seiwald) - new 'actions existing' does existing sources
+ * 08/23/94 (seiwald) - Support for '+=' (append to variable)
+ * 08/31/94 (seiwald) - Allow ?= as alias for "default =".
+ * 09/15/94 (seiwald) - if conditionals take only single arguments, so
+ * that 'if foo == bar' gives syntax error (use =).
+ * 02/11/95 (seiwald) - when scanning arguments to rules, only treat
+ * punctuation keywords as keywords. All arg lists
+ * are terminated with punctuation keywords.
+ *
+ * 09/11/00 (seiwald) - Support for function calls:
+ *
+ * Rules now return lists (LIST *), rather than void.
+ *
+ * New "[ rule ]" syntax evals rule into a LIST.
+ *
+ * Lists are now generated by compile_list() and
+ * compile_append(), and any other rule that indirectly
+ * makes a list, rather than being built directly here,
+ * so that lists values can contain rule evaluations.
+ *
+ * New 'return' rule sets the return value, though
+ * other statements also may have return values.
+ *
+ * 'run' production split from 'block' production so
+ * that empty blocks can be handled separately.
+ */
+
+%token ARG STRING
+
+%left `||` `|`
+%left `&&` `&`
+%left `=` `!=` `in`
+%left `<` `<=` `>` `>=`
+%left `!`
+
+%{
+#include "jam.h"
+
+#include "lists.h"
+#include "parse.h"
+#include "scan.h"
+#include "compile.h"
+#include "newstr.h"
+#include "rules.h"
+
+# define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
+
+# define F0 (LIST *(*)(PARSE *, FRAME *))0
+# define P0 (PARSE *)0
+# define S0 (char *)0
+
+# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
+# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
+# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
+# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
+# define pincl( l ) parse_make( compile_include,l,P0,P0,S0,S0,0 )
+# define plist( s ) parse_make( compile_list,P0,P0,P0,s,S0,0 )
+# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
+# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
+# define pclass( l,r ) parse_make( compile_class,l,r,P0,S0,S0,0 )
+# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
+# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 )
+# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
+# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
+# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
+# define pset1( l,r,t,a ) parse_make( compile_settings,l,r,t,S0,S0,a )
+# define psetc( s,p,a,l ) parse_make( compile_setcomp,p,a,P0,s,S0,l )
+# define psete( s,l,s1,f ) parse_make( compile_setexec,l,P0,P0,s,s1,f )
+# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
+# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
+
+# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
+# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
+
+%}
+
+%%
+
+run : /* empty */
+ /* do nothing */
+ | rules
+ { parse_save( $1.parse ); }
+ ;
+
+/*
+ * block - zero or more rules
+ * rules - one or more rules
+ * rule - any one of jam's rules
+ * right-recursive so rules execute in order.
+ */
+
+block : null
+ { $$.parse = $1.parse; }
+ | rules
+ { $$.parse = $1.parse; }
+ ;
+
+rules : rule
+ { $$.parse = $1.parse; }
+ | rule rules
+ { $$.parse = prules( $1.parse, $2.parse ); }
+ | `local` list assign_list_opt `;` block
+ { $$.parse = plocal( $2.parse, $3.parse, $5.parse ); }
+ ;
+
+null : /* empty */
+ { $$.parse = pnull(); }
+ ;
+
+assign_list_opt : `=` list
+ { $$.parse = $2.parse; $$.number = ASSIGN_SET; }
+ | null
+ { $$.parse = $1.parse; $$.number = ASSIGN_APPEND; }
+ ;
+
+arglist_opt : `(` lol `)`
+ { $$.parse = $2.parse; }
+ |
+ { $$.parse = P0; }
+ ;
+
+local_opt : `local`
+ { $$.number = 1; }
+ | /* empty */
+ { $$.number = 0; }
+ ;
+
+rule : `{` block `}`
+ { $$.parse = $2.parse; }
+ | `include` list `;`
+ { $$.parse = pincl( $2.parse ); }
+ | ARG lol `;`
+ { $$.parse = prule( $1.string, $2.parse ); }
+ | arg assign list `;`
+ { $$.parse = pset( $1.parse, $3.parse, $2.number ); }
+ | arg `on` list assign list `;`
+ { $$.parse = pset1( $1.parse, $3.parse, $5.parse, $4.number ); }
+ | `return` list `;`
+ { $$.parse = $2.parse; }
+ | `for` local_opt ARG `in` list `{` block `}`
+ { $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); }
+ | `switch` list `{` cases `}`
+ { $$.parse = pswitch( $2.parse, $4.parse ); }
+ | `if` expr `{` block `}`
+ { $$.parse = pif( $2.parse, $4.parse, pnull() ); }
+ | `module` list `{` block `}`
+ { $$.parse = pmodule( $2.parse, $4.parse ); }
+ | `class` lol `{` block `}`
+ { $$.parse = pclass( $2.parse, $4.parse ); }
+ | `while` expr `{` block `}`
+ { $$.parse = pwhile( $2.parse, $4.parse ); }
+ | `if` expr `{` block `}` `else` rule
+ { $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
+ | local_opt `rule` ARG arglist_opt rule
+ { $$.parse = psetc( $3.string, $5.parse, $4.parse, $1.number ); }
+ | `on` arg rule
+ { $$.parse = pon( $2.parse, $3.parse ); }
+ | `actions` eflags ARG bindlist `{`
+ { yymode( SCAN_STRING ); }
+ STRING
+ { yymode( SCAN_NORMAL ); }
+ `}`
+ { $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); }
+ ;
+
+/*
+ * assign - = or +=
+ */
+
+assign : `=`
+ { $$.number = ASSIGN_SET; }
+ | `+=`
+ { $$.number = ASSIGN_APPEND; }
+ | `?=`
+ { $$.number = ASSIGN_DEFAULT; }
+ | `default` `=`
+ { $$.number = ASSIGN_DEFAULT; }
+ ;
+
+/*
+ * expr - an expression for if
+ */
+expr : arg
+ { $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); }
+ | expr `=` expr
+ { $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); }
+ | expr `!=` expr
+ { $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); }
+ | expr `<` expr
+ { $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); }
+ | expr `<=` expr
+ { $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); }
+ | expr `>` expr
+ { $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); }
+ | expr `>=` expr
+ { $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); }
+ | expr `&` expr
+ { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
+ | expr `&&` expr
+ { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
+ | expr `|` expr
+ { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
+ | expr `||` expr
+ { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
+ | arg `in` list
+ { $$.parse = peval( EXPR_IN, $1.parse, $3.parse ); }
+ | `!` expr
+ { $$.parse = peval( EXPR_NOT, $2.parse, pnull() ); }
+ | `(` expr `)`
+ { $$.parse = $2.parse; }
+ ;
+
+
+/*
+ * cases - action elements inside a 'switch'
+ * case - a single action element inside a 'switch'
+ * right-recursive rule so cases can be examined in order.
+ */
+
+cases : /* empty */
+ { $$.parse = P0; }
+ | case cases
+ { $$.parse = pnode( $1.parse, $2.parse ); }
+ ;
+
+case : `case` ARG `:` block
+ { $$.parse = psnode( $2.string, $4.parse ); }
+ ;
+
+/*
+ * lol - list of lists
+ * right-recursive rule so that lists can be added in order.
+ */
+
+lol : list
+ { $$.parse = pnode( P0, $1.parse ); }
+ | list `:` lol
+ { $$.parse = pnode( $3.parse, $1.parse ); }
+ ;
+
+/*
+ * list - zero or more args in a LIST
+ * listp - list (in puncutation only mode)
+ * arg - one ARG or function call
+ */
+
+list : listp
+ { $$.parse = $1.parse; yymode( SCAN_NORMAL ); }
+ ;
+
+listp : /* empty */
+ { $$.parse = pnull(); yymode( SCAN_PUNCT ); }
+ | listp arg
+ { $$.parse = pappend( $1.parse, $2.parse ); }
+ ;
+
+arg : ARG
+ { $$.parse = plist( $1.string ); }
+ | `[` { yymode( SCAN_NORMAL ); } func `]`
+ { $$.parse = $3.parse; }
+ ;
+
+/*
+ * func - a function call (inside [])
+ * This needs to be split cleanly out of 'rule'
+ */
+
+func : arg lol
+ { $$.parse = prule( $1.string, $2.parse ); }
+ | `on` arg arg lol
+ { $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
+ | `on` arg `return` list
+ { $$.parse = pon( $2.parse, $4.parse ); }
+ ;
+
+
+/*
+ * eflags - zero or more modifiers to 'executes'
+ * eflag - a single modifier to 'executes'
+ */
+
+eflags : /* empty */
+ { $$.number = 0; }
+ | eflags eflag
+ { $$.number = $1.number | $2.number; }
+ ;
+
+eflag : `updated`
+ { $$.number = EXEC_UPDATED; }
+ | `together`
+ { $$.number = EXEC_TOGETHER; }
+ | `ignore`
+ { $$.number = EXEC_IGNORE; }
+ | `quietly`
+ { $$.number = EXEC_QUIETLY; }
+ | `piecemeal`
+ { $$.number = EXEC_PIECEMEAL; }
+ | `existing`
+ { $$.number = EXEC_EXISTING; }
+ ;
+
+
+/*
+ * bindlist - list of variable to bind for an action
+ */
+
+bindlist : /* empty */
+ { $$.parse = pnull(); }
+ | `bind` list
+ { $$.parse = $2.parse; }
+ ;
+
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/jamgramtab.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/jamgramtab.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/jamgramtab.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,44 @@
+ { "!", _BANG_t },
+ { "!=", _BANG_EQUALS_t },
+ { "&", _AMPER_t },
+ { "&&", _AMPERAMPER_t },
+ { "(", _LPAREN_t },
+ { ")", _RPAREN_t },
+ { "+=", _PLUS_EQUALS_t },
+ { ":", _COLON_t },
+ { ";", _SEMIC_t },
+ { "<", _LANGLE_t },
+ { "<=", _LANGLE_EQUALS_t },
+ { "=", _EQUALS_t },
+ { ">", _RANGLE_t },
+ { ">=", _RANGLE_EQUALS_t },
+ { "?=", _QUESTION_EQUALS_t },
+ { "[", _LBRACKET_t },
+ { "]", _RBRACKET_t },
+ { "actions", ACTIONS_t },
+ { "bind", BIND_t },
+ { "case", CASE_t },
+ { "class", CLASS_t },
+ { "default", DEFAULT_t },
+ { "else", ELSE_t },
+ { "existing", EXISTING_t },
+ { "for", FOR_t },
+ { "if", IF_t },
+ { "ignore", IGNORE_t },
+ { "in", IN_t },
+ { "include", INCLUDE_t },
+ { "local", LOCAL_t },
+ { "module", MODULE_t },
+ { "on", ON_t },
+ { "piecemeal", PIECEMEAL_t },
+ { "quietly", QUIETLY_t },
+ { "return", RETURN_t },
+ { "rule", RULE_t },
+ { "switch", SWITCH_t },
+ { "together", TOGETHER_t },
+ { "updated", UPDATED_t },
+ { "while", WHILE_t },
+ { "{", _LBRACE_t },
+ { "|", _BAR_t },
+ { "||", _BARBAR_t },
+ { "}", _RBRACE_t },
Added: boost-jam/boost-build/branches/upstream/current/jam_src/lists.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/lists.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/lists.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,369 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "newstr.h"
+# include "lists.h"
+
+/*
+ * lists.c - maintain lists of strings
+ *
+ * This implementation essentially uses a singly linked list, but
+ * guarantees that the head element of every list has a valid pointer
+ * to the tail of the list, so the new elements can efficiently and
+ * properly be appended to the end of a list.
+ *
+ * To avoid massive allocation, list_free() just tacks the whole freed
+ * chain onto freelist and list_new() looks on freelist first for an
+ * available list struct. list_free() does not free the strings in the
+ * chain: it lazily lets list_new() do so.
+ *
+ * 08/23/94 (seiwald) - new list_append()
+ * 09/07/00 (seiwald) - documented lol_*() functions
+ */
+
+static LIST *freelist = 0; /* junkpile for list_free() */
+
+/*
+ * list_append() - append a list onto another one, returning total
+ */
+
+LIST *
+list_append(
+ LIST *l,
+ LIST *nl )
+{
+ if( !nl )
+ {
+ /* Just return l */
+ }
+ else if( !l )
+ {
+ l = nl;
+ }
+ else
+ {
+ /* Graft two non-empty lists. */
+ l->tail->next = nl;
+ l->tail = nl->tail;
+ }
+
+ return l;
+}
+
+/*
+ * list_new() - tack a string onto the end of a list of strings
+ */
+
+LIST *
+list_new(
+ LIST *head,
+ char *string )
+{
+ LIST *l;
+
+ if( DEBUG_LISTS )
+ printf( "list > %s <\n", string );
+
+ /* Get list struct from freelist, if one available. */
+ /* Otherwise allocate. */
+ /* If from freelist, must free string first */
+
+ if( freelist )
+ {
+ l = freelist;
+ freestr( l->string );
+ freelist = freelist->next;
+ }
+ else
+ {
+ l = (LIST *)malloc( sizeof( *l ) );
+ }
+
+ /* If first on chain, head points here. */
+ /* If adding to chain, tack us on. */
+ /* Tail must point to this new, last element. */
+
+ if( !head ) head = l;
+ else head->tail->next = l;
+ head->tail = l;
+ l->next = 0;
+
+ l->string = string;
+
+ return head;
+}
+
+/*
+ * list_copy() - copy a whole list of strings (nl) onto end of another (l)
+ */
+
+LIST *
+list_copy(
+ LIST *l,
+ LIST *nl )
+{
+ for( ; nl; nl = list_next( nl ) )
+ l = list_new( l, copystr( nl->string ) );
+
+ return l;
+}
+
+/*
+ * list_sublist() - copy a subset of a list of strings
+ */
+
+LIST *
+list_sublist(
+ LIST *l,
+ int start,
+ int count )
+{
+ LIST *nl = 0;
+
+ for( ; l && start--; l = list_next( l ) )
+ ;
+
+ for( ; l && count--; l = list_next( l ) )
+ nl = list_new( nl, copystr( l->string ) );
+
+ return nl;
+}
+
+LIST *
+list_sort(
+ LIST *l)
+{
+
+ LIST* first = 0;
+ LIST* second = 0;
+ LIST* merged = l;
+ LIST* result;
+
+ if (!l)
+ return L0;
+
+ for(;;) {
+
+ /* Split the list in two */
+ LIST** dst = &first;
+ LIST* src = merged;
+
+ for(;;) {
+
+ *dst = list_append(*dst, list_new(0, src->string));
+
+ if (!src->next)
+ break;
+
+ if (strcmp(src->string, src->next->string) > 0)
+ {
+ if (dst == &first)
+ dst = &second;
+ else
+ dst = &first;
+ }
+
+ src = src->next;
+ }
+
+ if (merged != l)
+ list_free( merged );
+ merged = 0;
+
+ if (second == 0) {
+ result = first;
+ break;
+ }
+
+
+ /* Merge lists 'first' and 'second' into 'merged' and free
+ 'first'/'second'. */
+ {
+ LIST* f = first;
+ LIST* s = second;
+
+ while(f && s)
+ {
+ if (strcmp(f->string, s->string) < 0)
+ {
+ merged = list_append( merged, list_new(0, f->string ));
+ f = f->next;
+ }
+ else
+ {
+ merged = list_append( merged, list_new(0, s->string ));
+ s = s->next;
+ }
+ }
+
+ merged = list_copy( merged, f );
+ merged = list_copy( merged, s );
+ list_free( first );
+ list_free( second );
+ first = 0;
+ second = 0;
+ }
+ }
+
+ return result;
+}
+
+/*
+ * list_free() - free a list of strings
+ */
+
+void
+list_free( LIST *head )
+{
+ /* Just tack onto freelist. */
+
+ if( head )
+ {
+ head->tail->next = freelist;
+ freelist = head;
+ }
+}
+
+/*
+ * list_pop_front() - remove the front element from a list of strings
+ */
+LIST * list_pop_front( LIST *l )
+{
+ LIST * result = l->next;
+ if( result )
+ {
+ result->tail = l->tail;
+ l->next = L0;
+ l->tail = l;
+ }
+ list_free( l );
+ return result;
+}
+
+/*
+ * list_print() - print a list of strings to stdout
+ */
+
+void
+list_print( LIST *l )
+{
+ LIST *p = 0;
+ for( ; l; p = l, l = list_next( l ) )
+ if ( p )
+ printf( "%s ", p->string );
+ if ( p )
+ printf( "%s", p->string );
+}
+
+/*
+ * list_length() - return the number of items in the list
+ */
+
+int
+list_length( LIST *l )
+{
+ int n = 0;
+
+ for( ; l; l = list_next( l ), ++n )
+ ;
+
+ return n;
+}
+
+int
+list_in(LIST* l, char* value)
+{
+ for(; l; l = l->next)
+ if (strcmp(l->string, value) == 0)
+ return 1;
+ return 0;
+}
+
+LIST *
+list_unique( LIST *sorted_list)
+{
+ LIST* result = 0;
+ LIST* last_added = 0;
+
+ for(; sorted_list; sorted_list = sorted_list->next)
+ {
+ if (!last_added || strcmp(sorted_list->string, last_added->string) != 0)
+ {
+ result = list_new(result, sorted_list->string);
+ last_added = sorted_list;
+ }
+ }
+ return result;
+}
+
+
+/*
+ * lol_init() - initialize a LOL (list of lists)
+ */
+
+void
+lol_init( LOL *lol )
+{
+ lol->count = 0;
+}
+
+/*
+ * lol_add() - append a LIST onto an LOL
+ */
+
+void
+lol_add(
+ LOL *lol,
+ LIST *l )
+{
+ if( lol->count < LOL_MAX )
+ lol->list[ lol->count++ ] = l;
+}
+
+/*
+ * lol_free() - free the LOL and its LISTs
+ */
+
+void
+lol_free( LOL *lol )
+{
+ int i;
+
+ for( i = 0; i < lol->count; i++ )
+ list_free( lol->list[i] );
+
+ lol->count = 0;
+}
+
+/*
+ * lol_get() - return one of the LISTs in the LOL
+ */
+
+LIST *
+lol_get(
+ LOL *lol,
+ int i )
+{
+ return i < lol->count ? lol->list[i] : 0;
+}
+
+/*
+ * lol_print() - debug print LISTS separated by ":"
+ */
+
+void
+lol_print( LOL *lol )
+{
+ int i;
+
+ for( i = 0; i < lol->count; i++ )
+ {
+ if( i )
+ printf( " : " );
+ list_print( lol->list[i] );
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/lists.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/lists.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/lists.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,96 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * lists.h - the LIST structure and routines to manipulate them
+ *
+ * The whole of jam relies on lists of strings as a datatype. This
+ * module, in conjunction with newstr.c, handles these relatively
+ * efficiently.
+ *
+ * Structures defined:
+ *
+ * LIST - list of strings
+ * LOL - list of LISTs
+ *
+ * External routines:
+ *
+ * list_append() - append a list onto another one, returning total
+ * list_new() - tack a string onto the end of a list of strings
+ * list_copy() - copy a whole list of strings
+ * list_sublist() - copy a subset of a list of strings
+ * list_free() - free a list of strings
+ * list_print() - print a list of strings to stdout
+ * list_length() - return the number of items in the list
+ *
+ * lol_init() - initialize a LOL (list of lists)
+ * lol_add() - append a LIST onto an LOL
+ * lol_free() - free the LOL and its LISTs
+ * lol_get() - return one of the LISTs in the LOL
+ * lol_print() - debug print LISTS separated by ":"
+ *
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 08/23/94 (seiwald) - new list_append()
+ */
+
+#ifndef LISTS_DWA20011022_H
+# define LISTS_DWA20011022_H
+
+/*
+ * LIST - list of strings
+ */
+
+typedef struct _list LIST;
+
+struct _list {
+ LIST *next;
+ LIST *tail; /* only valid in head node */
+ char *string; /* private copy */
+} ;
+
+/*
+ * LOL - list of LISTs
+ */
+
+typedef struct _lol LOL;
+
+# define LOL_MAX 9
+
+struct _lol {
+ int count;
+ LIST *list[ LOL_MAX ];
+} ;
+
+LIST * list_append( LIST *l, LIST *nl );
+LIST * list_copy( LIST *l, LIST *nl );
+void list_free( LIST *head );
+LIST * list_new( LIST *head, char *string );
+void list_print( LIST *l );
+int list_length( LIST *l );
+LIST * list_sublist( LIST *l, int start, int count );
+LIST * list_pop_front( LIST *l );
+LIST * list_sort( LIST *l);
+LIST * list_unique( LIST *sorted_list);
+int list_in(LIST* l, char* value);
+
+# define list_next( l ) ((l)->next)
+
+# define L0 ((LIST *)0)
+
+void lol_add( LOL *lol, LIST *l );
+void lol_init( LOL *lol );
+void lol_free( LOL *lol );
+LIST * lol_get( LOL *lol, int i );
+void lol_print( LOL *lol );
+
+#endif
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/make.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/make.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/make.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,779 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * make.c - bring a target up to date, once rules are in place
+ *
+ * This modules controls the execution of rules to bring a target and
+ * its dependencies up to date. It is invoked after the targets, rules,
+ * et. al. described in rules.h are created by the interpreting of the
+ * jam files.
+ *
+ * This file contains the main make() entry point and the first pass
+ * make0(). The second pass, make1(), which actually does the command
+ * execution, is in make1.c.
+ *
+ * External routines:
+ * make() - make a target, given its name
+ *
+ * Internal routines:
+ * make0() - bind and scan everything to make a TARGET
+ * make0sort() - reorder TARGETS chain by their time (newest to oldest)
+ *
+ * 12/26/93 (seiwald) - allow NOTIME targets to be expanded via $(<), $(>)
+ * 01/04/94 (seiwald) - print all targets, bounded, when tracing commands
+ * 04/08/94 (seiwald) - progress report now reflects only targets with actions
+ * 04/11/94 (seiwald) - Combined deps & headers into deps[2] in TARGET.
+ * 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
+ * 12/20/94 (seiwald) - make0() headers after determining fate of target, so
+ * that headers aren't seen as dependents on themselves.
+ * 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets.
+ * 02/02/95 (seiwald) - propagate leaf source time for new LEAVES rule.
+ * 02/14/95 (seiwald) - NOUPDATE rule means don't update existing target.
+ * 08/22/95 (seiwald) - NOUPDATE targets immune to anyhow (-a) flag.
+ * 09/06/00 (seiwald) - NOCARE affects targets with sources/actions.
+ * 03/02/01 (seiwald) - reverse NOCARE change.
+ * 03/14/02 (seiwald) - TEMPORARY targets no longer take on parents age
+ * 03/16/02 (seiwald) - support for -g (reorder builds by source time)
+ */
+
+# include "jam.h"
+
+# include "lists.h"
+# include "parse.h"
+# include "variable.h"
+# include "rules.h"
+
+#ifdef OPT_HEADER_CACHE_EXT
+# include "hcache.h"
+#endif
+
+# include "search.h"
+# include "newstr.h"
+# include "make.h"
+# include "headers.h"
+# include "command.h"
+# include <assert.h>
+
+# ifndef max
+# define max( a,b ) ((a)>(b)?(a):(b))
+# endif
+
+static TARGETS *make0sort( TARGETS *c );
+
+#ifdef OPT_GRAPH_DEBUG_EXT
+static void dependGraphOutput( TARGET *t, int depth );
+#endif
+
+static const char *target_fate[] =
+{
+ "init", /* T_FATE_INIT */
+ "making", /* T_FATE_MAKING */
+ "stable", /* T_FATE_STABLE */
+ "newer", /* T_FATE_NEWER */
+ "temp", /* T_FATE_ISTMP */
+ "touched", /* T_FATE_TOUCHED */
+ "missing", /* T_FATE_MISSING */
+ "needtmp", /* T_FATE_NEEDTMP */
+ "old", /* T_FATE_OUTDATED */
+ "update", /* T_FATE_UPDATE */
+ "nofind", /* T_FATE_CANTFIND */
+ "nomake" /* T_FATE_CANTMAKE */
+} ;
+
+static const char *target_bind[] =
+{
+ "unbound",
+ "missing",
+ "parents",
+ "exists",
+} ;
+
+# define spaces(x) ( " " + ( x > 20 ? 0 : 20-x ) )
+
+/*
+ * make() - make a target, given its name
+ */
+
+int
+make(
+ int n_targets,
+ const char **targets,
+ int anyhow )
+{
+ int i;
+ COUNTS counts[1];
+ int status = 0; /* 1 if anything fails */
+
+#ifdef OPT_HEADER_CACHE_EXT
+ hcache_init();
+#endif
+
+ memset( (char *)counts, 0, sizeof( *counts ) );
+
+ /* First bind all targets with LOCATE_TARGET setting. This is
+ needed to correctly handle dependencies to generated headers.
+ */
+ bind_explicitly_located_targets();
+
+ for( i = 0; i < n_targets; i++ )
+ {
+ TARGET *t = bindtarget( targets[i] );
+
+ make0( t, 0, 0, counts, anyhow );
+ }
+
+#ifdef OPT_GRAPH_DEBUG_EXT
+ if( DEBUG_GRAPH )
+ {
+ for( i = 0; i < n_targets; i++ )
+ {
+ TARGET *t = bindtarget( targets[i] );
+ dependGraphOutput( t, 0 );
+ }
+ }
+#endif
+
+ if( DEBUG_MAKE )
+ {
+ if( counts->targets )
+ printf( "...found %d target%s...\n", counts->targets,
+ counts->targets > 1 ? "s" : "" );
+ if( counts->temp )
+ printf( "...using %d temp target%s...\n", counts->temp,
+ counts->temp > 1 ? "s" : "" );
+ if( counts->updating )
+ printf( "...updating %d target%s...\n", counts->updating,
+ counts->updating > 1 ? "s" : "" );
+ if( counts->cantfind )
+ printf( "...can't find %d target%s...\n", counts->cantfind,
+ counts->cantfind > 1 ? "s" : "" );
+ if( counts->cantmake )
+ printf( "...can't make %d target%s...\n", counts->cantmake,
+ counts->cantmake > 1 ? "s" : "" );
+ }
+
+#ifdef OPT_HEADER_CACHE_EXT
+ hcache_done();
+#endif
+
+ status = counts->cantfind || counts->cantmake;
+
+ for( i = 0; i < n_targets; i++ )
+ status |= make1( bindtarget( targets[i] ) );
+
+ return status;
+}
+
+/*
+ * make0() - bind and scan everything to make a TARGET
+ *
+ * Make0() recursively binds a target, searches for #included headers,
+ * calls itself on those headers, and calls itself on any dependents.
+ */
+
+void
+make0(
+ TARGET *t,
+ TARGET *p, /* parent */
+ int depth, /* for display purposes */
+ COUNTS *counts, /* for reporting */
+ int anyhow ) /* forcibly touch all (real) targets */
+{
+ TARGETS *c, *d, *incs;
+ TARGET *ptime = t;
+ time_t last, leaf, hlast;
+ int fate;
+ const char *flag = "";
+ SETTINGS *s;
+
+#ifdef OPT_GRAPH_DEBUG_EXT
+ int savedFate, oldTimeStamp;
+#endif
+
+ if( DEBUG_MAKEPROG )
+ printf( "make\t--\t%s%s\n", spaces( depth ), t->name );
+
+ /*
+ * Step 1: initialize
+ */
+
+ if( DEBUG_MAKEPROG )
+ printf( "make\t--\t%s%s\n", spaces( depth ), t->name );
+
+ t->fate = T_FATE_MAKING;
+
+ /*
+ * Step 2: under the influence of "on target" variables,
+ * bind the target and search for headers.
+ */
+
+ /* Step 2a: set "on target" variables. */
+
+ s = copysettings( t->settings );
+ pushsettings( s );
+
+ /* Step 2b: find and timestamp the target file (if it's a file). */
+
+ if( t->binding == T_BIND_UNBOUND && !( t->flags & T_FLAG_NOTFILE ) )
+ {
+ char* another_target;
+ t->boundname = search( t->name, &t->time, &another_target );
+ /* If it was detected that this target refers to an already
+ existing and bound one, we add include dependency, so that
+ every target which depends on us will depend on that other
+ target. */
+ if( another_target )
+ {
+ TARGET* includes;
+ if (!t->includes) {
+ t->includes = copytarget(t);
+ t->includes->original_target = t;
+ }
+ includes = t->includes;
+ includes->depends = targetlist( includes->depends,
+ list_new( L0, another_target ) );
+ }
+
+ t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
+ }
+
+ /* INTERNAL, NOTFILE header nodes have the time of their parents */
+
+ if( p && t->flags & T_FLAG_INTERNAL )
+ ptime = p;
+
+ /* If temp file doesn't exist but parent does, use parent */
+ if( p && t->flags & T_FLAG_TEMP &&
+ t->binding == T_BIND_MISSING &&
+ p->binding != T_BIND_MISSING )
+ {
+ t->binding = T_BIND_PARENTS;
+ ptime = p;
+ }
+
+#ifdef OPT_SEMAPHORE
+ {
+ LIST *var = var_get( "JAM_SEMAPHORE" );
+ if( var )
+ {
+ TARGET *semaphore = bindtarget( var->string );
+
+ semaphore->progress = T_MAKE_SEMAPHORE;
+ t->semaphore = semaphore;
+ }
+ }
+#endif
+
+ /* Step 2c: If its a file, search for headers. */
+
+ if( t->binding == T_BIND_EXISTS )
+ headers( t );
+
+ /* Step 2d: reset "on target" variables */
+
+ popsettings( s );
+ freesettings( s );
+
+ /*
+ * Pause for a little progress reporting
+ */
+
+ if( DEBUG_BIND )
+
+ {
+ if( strcmp( t->name, t->boundname ) )
+ {
+ printf( "bind\t--\t%s%s: %s\n",
+ spaces( depth ), t->name, t->boundname );
+ }
+
+ switch( t->binding )
+ {
+ case T_BIND_UNBOUND:
+ case T_BIND_MISSING:
+ case T_BIND_PARENTS:
+ printf( "time\t--\t%s%s: %s\n",
+ spaces( depth ), t->name, target_bind[ t->binding ] );
+ break;
+
+ case T_BIND_EXISTS:
+ printf( "time\t--\t%s%s: %s",
+ spaces( depth ), t->name, ctime( &t->time ) );
+ break;
+ }
+ }
+
+ /*
+ * Step 3: recursively make0() dependents & headers
+ */
+
+ /* Step 3a: recursively make0() dependents */
+
+ for( c = t->depends; c; c = c->next )
+ {
+ int internal = t->flags & T_FLAG_INTERNAL;
+/* Seems like it's not relevant for us....
+ if( DEBUG_DEPENDS )
+ printf( "%s \"%s\" : \"%s\" ;\n",
+ internal ? "Includes" : "Depends",
+ t->name, c->target->name );
+*/
+
+ /* Warn about circular deps, except for includes, */
+ /* which include each other alot. */
+
+ if( c->target->fate == T_FATE_INIT )
+ make0( c->target, ptime, depth + 1, counts, anyhow );
+ else if( c->target->fate == T_FATE_MAKING && !internal )
+ printf( "warning: %s depends on itself\n", c->target->name );
+ }
+
+ /* Step 3b: recursively make0() internal includes node */
+
+ if( t->includes )
+ make0( t->includes, p, depth + 1, counts, anyhow );
+
+ /* Step 3c: add dependents' includes to our direct dependencies */
+
+ incs = 0;
+
+ for( c = t->depends; c; c = c->next )
+ if( c->target->includes )
+ incs = targetentry( incs, c->target->includes );
+
+ t->depends = targetchain( t->depends, incs );
+
+ /*
+ * Step 4: compute time & fate
+ */
+
+ /* Step 4a: pick up dependents' time and fate */
+
+
+ last = 0;
+ leaf = 0;
+ fate = T_FATE_STABLE;
+
+ for( c = t->depends; c; c = c->next )
+ {
+ /* If LEAVES has been applied, we only heed the timestamps of */
+ /* the leaf source nodes. */
+
+ leaf = max( leaf, c->target->leaf );
+
+ if( t->flags & T_FLAG_LEAVES )
+ {
+ last = leaf;
+ continue;
+ }
+
+ last = max( last, c->target->time );
+ fate = max( fate, c->target->fate );
+
+#ifdef OPT_GRAPH_DEBUG_EXT
+ if( DEBUG_FATE )
+ if( fate < c->target->fate )
+ printf( "fate change %s from %s to %s by dependency %s\n",
+ t->name,
+ target_fate[fate], target_fate[c->target->fate],
+ c->target->name);
+#endif
+
+ }
+
+ /* Step 4b: pick up included headers time */
+
+ /*
+ * If a header is newer than a temp source that includes it,
+ * the temp source will need building.
+ */
+
+ hlast = t->includes ? t->includes->time : 0;
+
+ /* Step 4c: handle NOUPDATE oddity */
+
+ /*
+ * If a NOUPDATE file exists, make dependents eternally old.
+ * Don't inherit our fate from our dependents. Decide fate
+ * based only upon other flags and our binding (done later).
+ */
+
+ if( t->flags & T_FLAG_NOUPDATE )
+ {
+#ifdef OPT_GRAPH_DEBUG_EXT
+ if( DEBUG_FATE )
+ if( fate != T_FATE_STABLE )
+ printf( "fate change %s back to stable, NOUPDATE.\n",
+ t->name);
+#endif
+
+ last = 0;
+ t->time = 0;
+
+
+ /*
+ * Don't inherit our fate from our dependents. Decide fate
+ * based only upon other flags and our binding (done later).
+ */
+
+ fate = T_FATE_STABLE;
+ }
+
+ /* Step 4d: determine fate: rebuild target or what? */
+
+ /*
+ In English:
+ If can't find or make child, can't make target.
+ If children changed, make target.
+ If target missing, make it.
+ If children newer, make target.
+ If temp's children newer than parent, make temp.
+ If temp's headers newer than parent, make temp.
+ If deliberately touched, make it.
+ If up-to-date temp file present, use it.
+ If target newer than non-notfile parent, mark target newer.
+ Otherwise, stable!
+
+ Note this block runs from least to most stable:
+ as we make it further down the list, the target's
+ fate is getting stabler.
+ */
+
+#ifdef OPT_GRAPH_DEBUG_EXT
+ savedFate = fate;
+ oldTimeStamp = 0;
+#endif
+
+ if( fate >= T_FATE_BROKEN )
+ {
+ fate = T_FATE_CANTMAKE;
+ }
+ else if( fate >= T_FATE_SPOIL )
+ {
+ fate = T_FATE_UPDATE;
+ }
+ else if( t->binding == T_BIND_MISSING )
+ {
+ fate = T_FATE_MISSING;
+ }
+ else if( t->binding == T_BIND_EXISTS && last > t->time )
+ {
+#ifdef OPT_GRAPH_DEBUG_EXT
+ oldTimeStamp = 1;
+#endif
+ fate = T_FATE_OUTDATED;
+ }
+ else if( t->binding == T_BIND_PARENTS && last > p->time )
+ {
+#ifdef OPT_GRAPH_DEBUG_EXT
+ oldTimeStamp = 1;
+#endif
+ fate = T_FATE_NEEDTMP;
+ }
+ else if( t->binding == T_BIND_PARENTS && hlast > p->time )
+ {
+ fate = T_FATE_NEEDTMP;
+ }
+ else if( t->flags & T_FLAG_TOUCHED )
+ {
+ fate = T_FATE_TOUCHED;
+ }
+ else if( anyhow && !( t->flags & T_FLAG_NOUPDATE ) )
+ {
+ fate = T_FATE_TOUCHED;
+ }
+ else if( t->binding == T_BIND_EXISTS && t->flags & T_FLAG_TEMP )
+ {
+ fate = T_FATE_ISTMP;
+ }
+ else if( t->binding == T_BIND_EXISTS && p &&
+ p->binding != T_BIND_UNBOUND && t->time > p->time )
+ {
+#ifdef OPT_GRAPH_DEBUG_EXT
+ oldTimeStamp = 1;
+#endif
+ fate = T_FATE_NEWER;
+ }
+ else
+ {
+ fate = T_FATE_STABLE;
+ }
+#ifdef OPT_GRAPH_DEBUG_EXT
+ if( DEBUG_FATE && fate != savedFate )
+ if( savedFate == T_FATE_STABLE )
+ printf( "fate change %s set to %s%s\n",
+ t->name, target_fate[fate],
+ oldTimeStamp ? " (by timestamp)" : "" );
+ else
+ printf( "fate change %s adjusted from %s to %s%s\n",
+ t->name, target_fate[savedFate], target_fate[fate],
+ oldTimeStamp ? " (by timestamp)" : "" );
+#endif
+
+ /* Step 4e: handle missing files */
+ /* If it's missing and there are no actions to create it, boom. */
+ /* If we can't make a target we don't care about, 'sokay */
+ /* We could insist that there are updating actions for all missing */
+ /* files, but if they have dependents we just pretend it's NOTFILE. */
+
+ if( fate == T_FATE_MISSING && !t->actions && !t->depends )
+ {
+ if( t->flags & T_FLAG_NOCARE )
+ {
+#ifdef OPT_GRAPH_DEBUG_EXT
+ if( DEBUG_FATE )
+ printf( "fate change %s to STABLE from %s, "
+ "no actions, no dependents and don't care\n",
+ t->name, target_fate[fate]);
+#endif
+ fate = T_FATE_STABLE;
+ }
+ else
+ {
+ printf( "don't know how to make %s\n", t->name );
+
+ fate = T_FATE_CANTFIND;
+ }
+ }
+
+ /* Step 4f: propagate dependents' time & fate. */
+ /* Set leaf time to be our time only if this is a leaf. */
+
+ t->time = max( t->time, last );
+ t->leaf = leaf ? leaf : t->time ;
+ t->fate = fate;
+
+ /*
+ * Step 5: sort dependents by their update time.
+ */
+
+ if( globs.newestfirst )
+ t->depends = make0sort( t->depends );
+
+ /*
+ * Step 6: a little harmless tabulating for tracing purposes
+ */
+
+ /* Don't count or report interal includes nodes. */
+
+ if( t->flags & T_FLAG_INTERNAL )
+ return;
+
+ if (counts) {
+#ifdef OPT_IMPROVED_PATIENCE_EXT
+ ++counts->targets;
+#else
+ if( !( ++counts->targets % 1000 ) && DEBUG_MAKE )
+ printf( "...patience...\n" );
+#endif
+
+ if( fate == T_FATE_ISTMP )
+ counts->temp++;
+ else if( fate == T_FATE_CANTFIND )
+ counts->cantfind++;
+ else if( fate == T_FATE_CANTMAKE && t->actions )
+ counts->cantmake++;
+ else if( fate >= T_FATE_BUILD && fate < T_FATE_BROKEN && t->actions )
+ counts->updating++;
+ }
+
+ if( !( t->flags & T_FLAG_NOTFILE ) && fate >= T_FATE_SPOIL )
+ flag = "+";
+ else if( t->binding == T_BIND_EXISTS && p && t->time > p->time )
+ flag = "*";
+
+ if( DEBUG_MAKEPROG )
+ printf( "made%s\t%s\t%s%s\n",
+ flag, target_fate[ t->fate ],
+ spaces( depth ), t->name );
+
+/* We don't have DEBUG_CAUSES.
+ if( DEBUG_CAUSES &&
+ t->fate >= T_FATE_NEWER &&
+ t->fate <= T_FATE_MISSING )
+ printf( "%s %s\n", target_fate[ t->fate ], t->name );
+*/
+}
+
+#ifdef OPT_GRAPH_DEBUG_EXT
+
+static const char* target_name( TARGET* t )
+{
+ static char buf[1000];
+ if (t->flags & T_FLAG_INTERNAL) {
+ sprintf(buf, "%s (internal node)", t->name);
+ return buf;
+ } else {
+ return t->name;
+ }
+}
+
+/*
+ * dependGraphOutput() - output the DG after make0 has run
+ */
+
+static void
+dependGraphOutput( TARGET *t, int depth )
+{
+ TARGETS *c;
+
+ if ( (t->flags & T_FLAG_VISITED) != 0
+ || !t->name
+ || !t->boundname)
+ return;
+
+ t->flags |= T_FLAG_VISITED;
+
+ switch (t->fate)
+ {
+ case T_FATE_TOUCHED:
+ case T_FATE_MISSING:
+ case T_FATE_OUTDATED:
+ case T_FATE_UPDATE:
+ printf( "->%s%2d Name: %s\n", spaces(depth), depth, target_name(t) );
+ break;
+ default:
+ printf( " %s%2d Name: %s\n", spaces(depth), depth, target_name(t) );
+ break;
+ }
+
+ if( strcmp (t->name, t->boundname) )
+ {
+ printf( " %s Loc: %s\n", spaces(depth), t->boundname );
+ }
+
+ switch( t->fate )
+ {
+ case T_FATE_STABLE:
+ printf( " %s : Stable\n", spaces(depth) );
+ break;
+ case T_FATE_NEWER:
+ printf( " %s : Newer\n", spaces(depth) );
+ break;
+ case T_FATE_ISTMP:
+ printf( " %s : Up to date temp file\n", spaces(depth) );
+ case T_FATE_NEEDTMP:
+ printf( " %s : Temporary file, to be updated\n", spaces(depth) );
+ break;
+ case T_FATE_TOUCHED:
+ printf( " %s : Been touched, updating it\n", spaces(depth) );
+ break;
+ case T_FATE_MISSING:
+ printf( " %s : Missing, creating it\n", spaces(depth) );
+ break;
+ case T_FATE_OUTDATED:
+ printf( " %s : Outdated, updating it\n", spaces(depth) );
+ break;
+ case T_FATE_UPDATE:
+ printf( " %s : Updating it\n", spaces(depth) );
+ break;
+ case T_FATE_CANTFIND:
+ printf( " %s : Can't find it\n", spaces(depth) );
+ break;
+ case T_FATE_CANTMAKE:
+ printf( " %s : Can't make it\n", spaces(depth) );
+ break;
+ }
+
+ if( t->flags & ~T_FLAG_VISITED )
+ {
+ printf( " %s : ", spaces(depth) );
+ if( t->flags & T_FLAG_TEMP ) printf ("TEMPORARY ");
+ if( t->flags & T_FLAG_NOCARE ) printf ("NOCARE ");
+ if( t->flags & T_FLAG_NOTFILE ) printf ("NOTFILE ");
+ if( t->flags & T_FLAG_TOUCHED ) printf ("TOUCHED ");
+ if( t->flags & T_FLAG_LEAVES ) printf ("LEAVES ");
+ if( t->flags & T_FLAG_NOUPDATE ) printf ("NOUPDATE ");
+ printf( "\n" );
+ }
+
+ for( c = t->depends; c; c = c->next )
+ {
+ printf( " %s : Depends on %s (%s)", spaces(depth),
+ target_name(c->target), target_fate[ c->target->fate ] );
+ if (c->target->time == t->time)
+ printf( " (max time)");
+ printf("\n");
+
+ }
+
+
+ for( c = t->depends; c; c = c->next )
+ {
+
+ dependGraphOutput( c->target, depth + 1 );
+ }
+}
+
+#endif
+/*
+ * make0sort() - reorder TARGETS chain by their time (newest to oldest)
+ */
+
+static TARGETS *
+make0sort( TARGETS *chain )
+{
+ TARGETS *result = 0;
+
+ /* We walk chain, taking each item and inserting it on the */
+ /* sorted result, with newest items at the front. This involves */
+ /* updating each TARGETS' c->next and c->tail. Note that we */
+ /* make c->tail a valid prev pointer for every entry. Normally, */
+ /* it is only valid at the head, where prev == tail. Note also */
+ /* that while tail is a loop, next ends at the end of the chain. */
+
+ /* Walk current target list */
+
+ while( chain )
+ {
+ TARGETS *c = chain;
+ TARGETS *s = result;
+
+ chain = chain->next;
+
+ /* Find point s in result for c */
+
+ while( s && s->target->time > c->target->time )
+ s = s->next;
+
+ /* Insert c in front of s (might be 0). */
+ /* Don't even think of deciphering this. */
+
+ c->next = s; /* good even if s = 0 */
+ if( result == s ) result = c; /* new head of chain? */
+ if( !s ) s = result; /* wrap to ensure a next */
+ if( result != c ) s->tail->next = c; /* not head? be prev's next */
+ c->tail = s->tail; /* take on next's prev */
+ s->tail = c; /* make next's prev us */
+ }
+
+ return result;
+}
+
+static LIST *targets_to_update_ = 0;
+
+void mark_target_for_updating(char *target)
+{
+ targets_to_update_ = list_new( targets_to_update_, target );
+}
+
+LIST *targets_to_update()
+{
+ return targets_to_update_;
+}
+
+void clear_targets_to_update()
+{
+ list_free(targets_to_update_);
+ targets_to_update_ = 0;
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/make.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/make.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/make.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * make.h - bring a target up to date, once rules are in place
+ */
+
+#include "lists.h"
+
+int make( int n_targets, const char **targets, int anyhow );
+int make1( TARGET *t );
+
+typedef struct {
+ int temp;
+ int updating;
+ int cantfind;
+ int cantmake;
+ int targets;
+ int made;
+} COUNTS ;
+
+
+void make0( TARGET *t, TARGET *p, int depth,
+ COUNTS *counts, int anyhow );
+
+
+/*
+ * Specifies that the target should be updated.
+ */
+void mark_target_for_updating(char *target);
+/*
+ * Returns the list of all the target previously passed to 'mark_target_for_updating'.
+ */
+LIST *targets_to_update();
+/*
+ * Cleasr/unmarks all targets that are currently marked for update.
+ */
+void clear_targets_to_update();
Added: boost-jam/boost-build/branches/upstream/current/jam_src/make1.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/make1.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/make1.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1046 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * make1.c - execute command to bring targets up to date
+ *
+ * This module contains make1(), the entry point called by make() to
+ * recursively decend the dependency graph executing update actions as
+ * marked by make0().
+ *
+ * External routines:
+ *
+ * make1() - execute commands to update a TARGET and all its dependents
+ *
+ * Internal routines, the recursive/asynchronous command executors:
+ *
+ * make1a() - recursively traverse target tree, calling make1b()
+ * make1b() - dependents of target built, now build target with make1c()
+ * make1c() - launch target's next command, call make1b() when done
+ * make1d() - handle command execution completion and call back make1c()
+ *
+ * Internal support routines:
+ *
+ * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc
+ * make1list() - turn a list of targets into a LIST, for $(<) and $(>)
+ * make1settings() - for vars that get bound values, build up replacement lists
+ * make1bind() - bind targets that weren't bound in dependency analysis
+ *
+ * 04/16/94 (seiwald) - Split from make.c.
+ * 04/21/94 (seiwald) - Handle empty "updated" actions.
+ * 05/04/94 (seiwald) - async multiprocess (-j) support
+ * 06/01/94 (seiwald) - new 'actions existing' does existing sources
+ * 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
+ * 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets.
+ * 01/22/94 (seiwald) - pass per-target JAMSHELL down to execcmd().
+ * 02/28/95 (seiwald) - Handle empty "existing" actions.
+ * 03/10/95 (seiwald) - Fancy counts.
+ */
+
+# include "jam.h"
+
+# include "lists.h"
+# include "parse.h"
+# include "assert.h"
+# include "variable.h"
+# include "rules.h"
+# include "headers.h"
+
+# include "search.h"
+# include "newstr.h"
+# include "make.h"
+# include "command.h"
+# include "execcmd.h"
+
+#if defined(sun) || defined(__sun)
+#include <unistd.h> /* for unlink */
+#endif
+
+static CMD *make1cmds( TARGET *t );
+static LIST *make1list( LIST *l, TARGETS *targets, int flags );
+static SETTINGS *make1settings( LIST *vars );
+static void make1bind( TARGET *t, int warn );
+
+/* Ugly static - it's too hard to carry it through the callbacks. */
+
+static struct {
+ int failed;
+ int skipped;
+ int total;
+ int made;
+} counts[1] ;
+
+/*
+ * Target state - remove recursive calls by just keeping track of state target is in
+ */
+typedef struct _state
+{
+ struct _state *prev; /* previous state on stack */
+ TARGET *t; /* current target */
+ TARGET *parent; /* parent argument necessary for make1a() */
+#define T_STATE_MAKE1A 0 /* make1a() should be called */
+#define T_STATE_MAKE1ATAIL 1 /* make1atail() should be called */
+#define T_STATE_MAKE1B 2 /* make1b() should be called */
+#define T_STATE_MAKE1C 3 /* make1c() should be called */
+#define T_STATE_MAKE1D 4 /* make1d() should be called */
+ int curstate; /* current state */
+ int status;
+} state;
+
+static void make1a( state *pState);
+static void make1atail(state *pState);
+static void make1b( state *pState );
+static void make1c( state *pState );
+static void make1d( state *pState );
+static void make_closure(void *closure, int status);
+
+typedef struct _stack
+{
+ state *stack;
+} stack;
+
+static stack state_stack = { NULL };
+
+static state *state_freelist = NULL;
+
+static state *alloc_state()
+{
+ if(state_freelist != NULL)
+ {
+ state *pState;
+
+ pState = state_freelist;
+ state_freelist = pState->prev;
+ memset(pState, 0, sizeof(state));
+ return pState;
+ }
+ else
+ {
+ return (state *)malloc(sizeof(state));
+ }
+}
+
+static void free_state(state *pState)
+{
+ pState->prev = state_freelist;
+ state_freelist = pState;
+}
+
+static void clear_state_freelist()
+{
+ while(state_freelist != NULL)
+ {
+ state *pState = state_freelist;
+ state_freelist = state_freelist->prev;
+ free(pState);
+ }
+}
+
+static state *current_state(stack *pStack)
+{
+ return pStack->stack;
+}
+
+static void pop_state(stack *pStack)
+{
+ state *pState;
+
+ if(pStack->stack != NULL)
+ {
+ pState = pStack->stack->prev;
+ free_state(pStack->stack);
+ pStack->stack = pState;
+ }
+}
+
+static state *push_state(stack *pStack, TARGET *t, TARGET *parent, int curstate)
+{
+ state *pState;
+
+ pState = alloc_state();
+
+ pState->t = t;
+ pState->parent = parent;
+ pState->prev = pStack->stack;
+ pState->curstate = curstate;
+
+ pStack->stack = pState;
+
+ return pStack->stack;
+}
+
+/* pushes a stack onto another stack, effectively reversing the order */
+static void push_stack_on_stack(stack *pDest, stack *pSrc)
+{
+ while(pSrc->stack != NULL)
+ {
+ state *pState;
+
+ pState = pSrc->stack;
+ pSrc->stack = pSrc->stack->prev;
+ pState->prev = pDest->stack;
+ pDest->stack = pState;
+ }
+}
+
+/*
+ * make1() - execute commands to update a TARGET and all its dependents
+ */
+
+static int intr = 0;
+
+int
+make1( TARGET *t )
+{
+ state *pState;
+
+ memset( (char *)counts, 0, sizeof( *counts ) );
+
+ /* Recursively make the target and its dependents */
+ push_state(&state_stack, t, NULL, T_STATE_MAKE1A);
+
+ do
+ {
+ while((pState = current_state(&state_stack)) != NULL)
+ {
+ if (intr)
+ pop_state(&state_stack);
+
+ switch(pState->curstate)
+ {
+ case T_STATE_MAKE1A:
+ make1a(pState);
+ break;
+ case T_STATE_MAKE1ATAIL:
+ make1atail(pState);
+ break;
+ case T_STATE_MAKE1B:
+ make1b(pState);
+ break;
+ case T_STATE_MAKE1C:
+ make1c(pState);
+ break;
+ case T_STATE_MAKE1D:
+ make1d(pState);
+ break;
+ default:
+ break;
+ }
+ }
+
+
+ /* Wait for any outstanding commands to finish running. */
+ } while( execwait() );
+
+ clear_state_freelist();
+
+ /* Talk about it */
+ if( counts->failed )
+ printf( "...failed updating %d target%s...\n", counts->failed,
+ counts->failed > 1 ? "s" : "" );
+
+ if( DEBUG_MAKE && counts->skipped )
+ printf( "...skipped %d target%s...\n", counts->skipped,
+ counts->skipped > 1 ? "s" : "" );
+
+ if( DEBUG_MAKE && counts->made )
+ printf( "...updated %d target%s...\n", counts->made,
+ counts->made > 1 ? "s" : "" );
+
+ return counts->total != counts->made;
+}
+
+/*
+ * make1a() - recursively traverse target tree, calling make1b()
+ */
+
+static void
+make1a( state *pState)
+{
+ TARGET* t = pState->t;
+ TARGETS *c;
+ TARGETS *inc;
+
+ /* If the parent is the first to try to build this target */
+ /* or this target is in the make1c() quagmire, arrange for the */
+ /* parent to be notified when this target is built. */
+
+ if( pState->parent )
+ switch( pState->t->progress )
+ {
+ case T_MAKE_INIT:
+ case T_MAKE_ACTIVE:
+ case T_MAKE_RUNNING:
+ pState->t->parents = targetentry( pState->t->parents, pState->parent );
+ pState->parent->asynccnt++;
+ }
+
+ if( pState->t->progress != T_MAKE_INIT )
+ {
+ pop_state(&state_stack);
+ return;
+ }
+
+ /* Asynccnt counts the dependents preventing this target from */
+ /* proceeding to make1b() for actual building. We start off with */
+ /* a count of 1 to prevent anything from happening until we can */
+ /* call all dependents. This 1 is accounted for when we call */
+ /* make1b() ourselves, below. */
+
+ pState->t->asynccnt = 1;
+
+ /* Add header node that was created during building process. */
+
+ inc = 0;
+ for (c = t->depends; c; c = c->next) {
+ if (c->target->rescanned && c->target->includes)
+ inc = targetentry(inc, c->target->includes);
+ }
+ t->depends = targetchain(t->depends, inc);
+
+ /* against circular dependency. */
+
+ pState->t->progress = T_MAKE_ONSTACK;
+
+ {
+ stack temp_stack = { NULL };
+ for( c = t->depends; c && !intr; c = c->next )
+ push_state(&temp_stack, c->target, pState->t, T_STATE_MAKE1A);
+
+ /* using stacks reverses the order of execution. Reverse it back */
+ push_stack_on_stack(&state_stack, &temp_stack);
+ }
+
+ pState->curstate = T_STATE_MAKE1ATAIL;
+}
+
+static void make1atail(state *pState)
+{
+ pState->t->progress = T_MAKE_ACTIVE;
+
+ /* Now that all dependents have bumped asynccnt, we now allow */
+ /* decrement our reference to asynccnt. */
+ pState->curstate = T_STATE_MAKE1B;
+}
+
+/*
+ * make1b() - dependents of target built, now build target with make1c()
+ */
+
+static void
+make1b( state *pState )
+{
+ TARGET *t = pState->t;
+ TARGETS *c;
+ TARGET *failed = 0;
+ char* failed_name = "dependencies";
+
+ /* If any dependents are still outstanding, wait until they */
+ /* call make1b() to signal their completion. */
+
+ if( --(pState->t->asynccnt) )
+ {
+ pop_state(&state_stack);
+ return;
+ }
+
+ /* Try to aquire a semaphore. If it's locked, wait until the target
+ that locked it is build and signals completition. */
+#ifdef OPT_SEMAPHORE
+ if( t->semaphore && t->semaphore->asynccnt )
+ {
+ /* Append 't' to the list of targets waiting on semaphore. */
+ t->semaphore->parents = targetentry( t->semaphore->parents, t );
+ t->asynccnt++;
+
+ if( DEBUG_EXECCMD )
+ printf( "SEM: %s is busy, delaying launch of %s\n",
+ t->semaphore->name, t->name);
+ pop_state(&state_stack);
+ return;
+ }
+#endif
+
+
+ /* Now ready to build target 't'... if dependents built ok. */
+
+ /* Collect status from dependents */
+
+
+ for( c = t->depends; c; c = c->next )
+ if( c->target->status > t->status && !( c->target->flags & T_FLAG_NOCARE ))
+ {
+ failed = c->target;
+ pState->t->status = c->target->status;
+ }
+ /* If a internal header node failed to build, we'd want to output the
+ target that it failed on. */
+ if (failed && (failed->flags & T_FLAG_INTERNAL)) {
+ failed_name = failed->failed;
+ } else if (failed) {
+ failed_name = failed->name;
+ }
+ t->failed = failed_name;
+
+ /* If actions on deps have failed, bail. */
+ /* Otherwise, execute all actions to make target */
+
+ if( pState->t->status == EXEC_CMD_FAIL && pState->t->actions )
+ {
+ ++counts->skipped;
+ if ( ( pState->t->flags & ( T_FLAG_RMOLD | T_FLAG_NOTFILE ) ) == T_FLAG_RMOLD )
+ {
+ if( !unlink( pState->t->boundname ) )
+ printf( "...removing outdated %s\n", pState->t->boundname );
+ }
+ else {
+ printf( "...skipped %s for lack of %s...\n", pState->t->name, failed_name );
+ }
+ }
+
+ if( pState->t->status == EXEC_CMD_OK )
+ switch( pState->t->fate )
+ {
+ case T_FATE_INIT:
+ case T_FATE_MAKING:
+ /* shouldn't happen */
+
+ case T_FATE_STABLE:
+ case T_FATE_NEWER:
+ break;
+
+ case T_FATE_CANTFIND:
+ case T_FATE_CANTMAKE:
+ pState->t->status = EXEC_CMD_FAIL;
+ break;
+
+ case T_FATE_ISTMP:
+ if( DEBUG_MAKE )
+ printf( "...using %s...\n", pState->t->name );
+ break;
+
+ case T_FATE_TOUCHED:
+ case T_FATE_MISSING:
+ case T_FATE_NEEDTMP:
+ case T_FATE_OUTDATED:
+ case T_FATE_UPDATE:
+
+ /* Set "on target" vars, build actions, unset vars */
+ /* Set "progress" so that make1c() counts this target among */
+ /* the successes/failures. */
+
+ if( pState->t->actions )
+ {
+ ++counts->total;
+ if( DEBUG_MAKE && !( counts->total % 100 ) )
+ printf( "...on %dth target...\n", counts->total );
+
+ pState->t->cmds = (char *)make1cmds( pState->t );
+ pState->t->progress = T_MAKE_RUNNING;
+ }
+
+ break;
+ }
+
+ /* Call make1c() to begin the execution of the chain of commands */
+ /* needed to build target. If we're not going to build target */
+ /* (because of dependency failures or because no commands need to */
+ /* be run) the chain will be empty and make1c() will directly */
+ /* signal the completion of target. */
+
+ /* Recurse on our dependents, manipulating progress to guard */
+
+#ifdef OPT_SEMAPHORE
+ /* If there is a semaphore, indicate that its in use */
+ if( pState->t->semaphore )
+ {
+ ++(pState->t->semaphore->asynccnt);
+
+ if( DEBUG_EXECCMD )
+ printf( "SEM: %s now used by %s\n", pState->t->semaphore->name,
+ pState->t->name );
+ }
+#endif
+
+ pState->curstate = T_STATE_MAKE1C;
+}
+
+/*
+ * make1c() - launch target's next command, call make1b() when done
+ */
+
+static void
+make1c( state *pState )
+{
+ CMD *cmd = (CMD *)pState->t->cmds;
+
+ /* If there are (more) commands to run to build this target */
+ /* (and we haven't hit an error running earlier comands) we */
+ /* launch the command with execcmd(). */
+
+ /* If there are no more commands to run, we collect the status */
+ /* from all the actions then report our completion to all the */
+ /* parents. */
+
+ if( cmd && pState->t->status == EXEC_CMD_OK )
+ {
+ if( DEBUG_MAKEQ ||
+ ! ( cmd->rule->actions->flags & RULE_QUIETLY ) && DEBUG_MAKE)
+ {
+ printf( "%s ", cmd->rule->name );
+ list_print( lol_get( &cmd->args, 0 ) );
+ printf( "\n" );
+ }
+
+ if( DEBUG_EXEC )
+ printf( "%s\n", cmd->buf );
+
+ if( globs.cmdout )
+ fprintf( globs.cmdout, "%s", cmd->buf );
+
+ if( globs.noexec )
+ {
+ pState->curstate = T_STATE_MAKE1D;
+ pState->status = EXEC_CMD_OK;
+ }
+ else
+ {
+ TARGET *t = pState->t;
+ fflush( stdout );
+
+ pop_state(&state_stack); /* pop state first because execcmd could push state */
+ execcmd( cmd->buf, make_closure, t, cmd->shell );
+ }
+ }
+ else
+ {
+ TARGETS *c;
+ ACTIONS *actions;
+
+ /* Collect status from actions, and distribute it as well */
+
+ for( actions = pState->t->actions; actions; actions = actions->next )
+ if( actions->action->status > pState->t->status )
+ pState->t->status = actions->action->status;
+
+ for( actions = pState->t->actions; actions; actions = actions->next )
+ if( pState->t->status > actions->action->status )
+ actions->action->status = pState->t->status;
+
+ /* Tally success/failure for those we tried to update. */
+
+ if( pState->t->progress == T_MAKE_RUNNING )
+ switch( pState->t->status )
+ {
+ case EXEC_CMD_OK:
+ ++counts->made;
+ break;
+ case EXEC_CMD_FAIL:
+ ++counts->failed;
+ break;
+ }
+
+ /* Tell parents dependent has been built */
+ {
+ stack temp_stack = { NULL };
+ TARGET *t = pState->t;
+ TARGET* additional_includes = NULL;
+
+ t->progress = T_MAKE_DONE;
+
+ /* Target was updated. Rescan dependencies. */
+ if (t->fate >= T_FATE_MISSING &&
+ t->status == EXEC_CMD_OK &&
+ !t->rescanned) {
+
+ TARGET *target_to_rescan = t;
+ SETTINGS *s;
+
+ target_to_rescan->rescanned = 1;
+
+ if (target_to_rescan->flags & T_FLAG_INTERNAL) {
+ target_to_rescan = t->original_target;
+ }
+
+ /* Clean current includes */
+ if (target_to_rescan->includes) {
+ target_to_rescan->includes = 0;
+ }
+
+ s = copysettings( target_to_rescan->settings );
+ pushsettings( s );
+ headers(target_to_rescan);
+ popsettings( s );
+ freesettings( s );
+
+ if (target_to_rescan->includes) {
+ target_to_rescan->includes->rescanned = 1;
+ /* Tricky. The parents were already processed, but they
+ did not seen the internal node, because it was just
+ created. We need to make the calls to make1a that would
+ have been done by parents here, and also make sure all
+ unprocessed parents will pick up the includes. We must
+ make sure processing of the additional make1a invocations
+ is done before make1b which means this target is built,
+ otherwise the parent will be considered built before this
+ make1a processing is even started.
+ */
+ make0(target_to_rescan->includes, target_to_rescan->parents->target, 0, 0, 0);
+ for( c = target_to_rescan->parents; c; c = c->next) {
+ c->target->depends = targetentry( c->target->depends,
+ target_to_rescan->includes );
+ }
+ /* Will be processed below. */
+ additional_includes = target_to_rescan->includes;
+ }
+ }
+
+ if (additional_includes)
+ for ( c = t->parents; c; c = c->next ) {
+ push_state(&temp_stack, additional_includes, c->target, T_STATE_MAKE1A);
+
+ }
+
+ for( c = t->parents; c; c = c->next ) {
+ push_state(&temp_stack, c->target, NULL, T_STATE_MAKE1B);
+ }
+
+
+
+#ifdef OPT_SEMAPHORE
+ /* If there is a semaphore, its now free */
+ if( t->semaphore )
+ {
+ assert( t->semaphore->asynccnt == 1 );
+ --(t->semaphore->asynccnt);
+
+ if( DEBUG_EXECCMD )
+ printf( "SEM: %s is now free\n", t->semaphore->name);
+
+ /* If anything is waiting, notify the next target. There's no
+ point in notifying all waiting targets, since they'll be
+ serialized again. */
+ if( t->semaphore->parents )
+ {
+ TARGETS *first = t->semaphore->parents;
+ if( first->next )
+ first->next->tail = first->tail;
+ t->semaphore->parents = first->next;
+
+ if( DEBUG_EXECCMD )
+ printf( "SEM: placing %s on stack\n", first->target->name);
+ push_state(&temp_stack, first->target, NULL, T_STATE_MAKE1B);
+ free( first );
+ }
+ }
+#endif
+
+
+ /* must pop state before pushing any more */
+ pop_state(&state_stack);
+
+ /* using stacks reverses the order of execution. Reverse it back */
+ push_stack_on_stack(&state_stack, &temp_stack);
+
+ }
+ }
+}
+
+static void make_closure(void *closure, int status)
+{
+ push_state(&state_stack, (TARGET *)closure, NULL, T_STATE_MAKE1D)->status = status;
+}
+
+/*
+ * make1d() - handle command execution completion and call back make1c()
+ */
+
+static void
+make1d(state *pState)
+{
+ TARGET *t = pState->t;
+ CMD *cmd = (CMD *)t->cmds;
+ int status = pState->status;
+
+ /* Execcmd() has completed. All we need to do is fiddle with the */
+ /* status and signal our completion so make1c() can run the next */
+ /* command. On interrupts, we bail heavily. */
+
+ if ( t->flags & T_FLAG_FAIL_EXPECTED )
+ {
+ /* invert execution result when FAIL_EXPECTED was applied */
+ switch (status)
+ {
+ case EXEC_CMD_FAIL: status = EXEC_CMD_OK; break;
+ case EXEC_CMD_OK: status = EXEC_CMD_FAIL; break;
+ default:
+ ;
+ }
+ }
+
+ if( status == EXEC_CMD_FAIL && ( cmd->rule->actions->flags & RULE_IGNORE ) )
+ status = EXEC_CMD_OK;
+
+ /* On interrupt, set intr so _everything_ fails */
+
+ if( status == EXEC_CMD_INTR )
+ ++intr;
+
+ if( status == EXEC_CMD_FAIL && DEBUG_MAKE )
+ {
+ /* Print command text on failure */
+
+ if( !DEBUG_EXEC )
+ printf( "%s\n", cmd->buf );
+
+ printf( "...failed %s ", cmd->rule->name );
+ list_print( lol_get( &cmd->args, 0 ) );
+ printf( "...\n" );
+ }
+
+ if (status == EXEC_CMD_FAIL)
+ if( globs.quitquick ) ++intr;
+
+ /* If the command was interrupted or failed and the target */
+ /* is not "precious", remove the targets */
+
+ if( status != EXEC_CMD_OK && !( cmd->rule->actions->flags & RULE_TOGETHER ) )
+ {
+ LIST *targets = lol_get( &cmd->args, 0 );
+
+ for( ; targets; targets = list_next( targets ) )
+ if( !unlink( targets->string ) )
+ printf( "...removing %s\n", targets->string );
+ }
+
+ /* Free this command and call make1c() to move onto next command. */
+
+ t->status = status;
+ t->cmds = (char *)cmd_next( cmd );
+
+ cmd_free( cmd );
+
+ pState->curstate = T_STATE_MAKE1C;
+}
+
+/*
+ * swap_settings() - replace the settings from the current module and
+ * target with those from the new module and target
+ */
+static void swap_settings(
+ module_t** current_module
+ , TARGET** current_target
+ , module_t* new_module
+ , TARGET* new_target)
+{
+ if (new_module == root_module())
+ new_module = 0;
+
+ if (new_target == *current_target && new_module == *current_module)
+ return;
+
+ if (*current_target)
+ popsettings( (*current_target)->settings );
+
+ if (new_module != *current_module)
+ {
+ if (*current_module)
+ exit_module( *current_module );
+
+ *current_module = new_module;
+
+ if (new_module)
+ enter_module( new_module );
+ }
+
+ *current_target = new_target;
+ if (new_target)
+ pushsettings( new_target->settings );
+}
+
+/*
+ * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc
+ *
+ * Essentially copies a chain of ACTIONs to a chain of CMDs,
+ * grouping RULE_TOGETHER actions, splitting RULE_PIECEMEAL actions,
+ * and handling RULE_NEWSRCS actions. The result is a chain of
+ * CMDs which can be expanded by var_string() and executed with
+ * execcmd().
+ */
+
+static CMD *
+make1cmds( TARGET *t )
+{
+ CMD *cmds = 0;
+ LIST *shell = 0;
+
+ module_t *settings_module = 0;
+ TARGET *settings_target = 0;
+
+ /* Step through actions */
+ /* Actions may be shared with other targets or grouped with */
+ /* RULE_TOGETHER, so actions already seen are skipped. */
+
+ ACTIONS* a0;
+ for(a0 = t->actions ; a0; a0 = a0->next )
+ {
+ RULE *rule = a0->action->rule;
+ rule_actions *actions = rule->actions;
+ SETTINGS *boundvars;
+ LIST *nt, *ns;
+ ACTIONS *a1;
+ int start, chunk, length;
+
+ /* Only do rules with commands to execute. */
+ /* If this action has already been executed, use saved status */
+
+ if( !actions || a0->action->running )
+ continue;
+
+ a0->action->running = 1;
+
+ /* Make LISTS of targets and sources */
+ /* If `execute together` has been specified for this rule, tack */
+ /* on sources from each instance of this rule for this target. */
+
+ nt = make1list( L0, a0->action->targets, 0 );
+ ns = make1list( L0, a0->action->sources, actions->flags );
+
+ if( actions->flags & RULE_TOGETHER )
+ for( a1 = a0->next; a1; a1 = a1->next )
+ if( a1->action->rule == rule && !a1->action->running )
+ {
+ ns = make1list( ns, a1->action->sources, actions->flags );
+ a1->action->running = 1;
+ }
+
+ /* If doing only updated (or existing) sources, but none have */
+ /* been updated (or exist), skip this action. */
+
+ if( !ns && ( actions->flags & ( RULE_NEWSRCS | RULE_EXISTING ) ) )
+ {
+ list_free( nt );
+ continue;
+ }
+
+ swap_settings( &settings_module, &settings_target, rule->module, t );
+ if (!shell)
+ shell = var_get( "JAMSHELL" ); /* shell is per-target */
+
+ /* If we had 'actions xxx bind vars' we bind the vars now */
+
+ boundvars = make1settings( actions->bindlist );
+ pushsettings( boundvars );
+
+ /*
+ * Build command, starting with all source args.
+ *
+ * If cmd_new returns 0, it's because the resulting command
+ * length is > MAXLINE. In this case, we'll slowly reduce
+ * the number of source arguments presented until it does
+ * fit. This only applies to actions that allow PIECEMEAL
+ * commands.
+ *
+ * While reducing slowly takes a bit of compute time to get
+ * things just right, it's worth it to get as close to MAXLINE
+ * as possible, because launching the commands we're executing
+ * is likely to be much more compute intensive!
+ *
+ * Note we loop through at least once, for sourceless actions.
+ */
+
+ start = 0;
+ chunk = length = list_length( ns );
+
+ do
+ {
+ /* Build cmd: cmd_new consumes its lists. */
+
+ CMD *cmd = cmd_new( rule,
+ list_copy( L0, nt ),
+ list_sublist( ns, start, chunk ),
+ list_copy( L0, shell ) );
+
+ if( cmd )
+ {
+ /* It fit: chain it up. */
+
+ if( !cmds ) cmds = cmd;
+ else cmds->tail->next = cmd;
+ cmds->tail = cmd;
+ start += chunk;
+ }
+ else if( ( actions->flags & RULE_PIECEMEAL ) && chunk > 1 )
+ {
+ /* Reduce chunk size slowly. */
+
+ chunk = chunk * 9 / 10;
+ }
+ else
+ {
+ /* Too long and not splittable. */
+
+ printf( "%s actions too long (max %d):\n",
+ rule->name, MAXLINE );
+
+ /* Tell the user what didn't fit */
+ cmd = cmd_new(
+ rule, list_copy( L0, nt ),
+ list_sublist( ns, start, chunk ),
+ list_new( L0, newstr( "%" ) ) );
+
+ printf( cmd->buf );
+
+ exit( EXITBAD );
+ }
+ }
+ while( start < length );
+
+ /* These were always copied when used. */
+
+ list_free( nt );
+ list_free( ns );
+
+ /* Free the variables whose values were bound by */
+ /* 'actions xxx bind vars' */
+
+ popsettings( boundvars );
+ freesettings( boundvars );
+ }
+
+ swap_settings( &settings_module, &settings_target, 0, 0 );
+ return cmds;
+}
+
+/*
+ * make1list() - turn a list of targets into a LIST, for $(<) and $(>)
+ */
+
+static LIST *
+make1list(
+ LIST *l,
+ TARGETS *targets,
+ int flags )
+{
+ for( ; targets; targets = targets->next )
+ {
+ TARGET *t = targets->target;
+
+ /* Sources to 'actions existing' are never in the dependency */
+ /* graph (if they were, they'd get built and 'existing' would */
+ /* be superfluous, so throttle warning message about independent */
+ /* targets. */
+
+ if( t->binding == T_BIND_UNBOUND )
+ make1bind( t, !( flags & RULE_EXISTING ) );
+
+ if ( ( flags & RULE_EXISTING ) && ( flags & RULE_NEWSRCS ) )
+ {
+ if ( t->binding != T_BIND_EXISTS && t->fate <= T_FATE_STABLE)
+ continue;
+ }
+ else
+ {
+ if( ( flags & RULE_EXISTING ) && t->binding != T_BIND_EXISTS )
+ continue;
+
+ if( ( flags & RULE_NEWSRCS ) && t->fate <= T_FATE_STABLE )
+ continue;
+ }
+
+ /* Prohibit duplicates for RULE_TOGETHER */
+
+ if( flags & RULE_TOGETHER )
+ {
+ LIST *m;
+
+ for( m = l; m; m = m->next )
+ if( !strcmp( m->string, t->boundname ) )
+ break;
+
+ if( m )
+ continue;
+ }
+
+ /* Build new list */
+
+ l = list_new( l, copystr( t->boundname ) );
+ }
+
+ return l;
+}
+
+/*
+ * make1settings() - for vars that get bound values, build up replacement lists
+ */
+
+static SETTINGS *
+make1settings( LIST *vars )
+{
+ SETTINGS *settings = 0;
+
+ for( ; vars; vars = list_next( vars ) )
+ {
+ LIST *l = var_get( vars->string );
+ LIST *nl = 0;
+
+ for( ; l; l = list_next( l ) )
+ {
+ TARGET *t = bindtarget( l->string );
+
+ /* Make sure the target is bound, warning if it is not in the */
+ /* dependency graph. */
+
+ if( t->binding == T_BIND_UNBOUND )
+ make1bind( t, 1 );
+
+ /* Build new list */
+
+ nl = list_new( nl, copystr( t->boundname ) );
+ }
+
+ /* Add to settings chain */
+
+ settings = addsettings( settings, 0, vars->string, nl );
+ }
+
+ return settings;
+}
+
+/*
+ * make1bind() - bind targets that weren't bound in dependency analysis
+ *
+ * Spot the kludge! If a target is not in the dependency tree, it didn't
+ * get bound by make0(), so we have to do it here. Ugly.
+ */
+
+static void
+make1bind(
+ TARGET *t,
+ int warn )
+{
+ if( t->flags & T_FLAG_NOTFILE )
+ return;
+
+ /* Sources to 'actions existing' are never in the dependency */
+ /* graph (if they were, they'd get built and 'existing' would */
+ /* be superfluous, so throttle warning message about independent */
+ /* targets. */
+
+ if( warn )
+ printf( "warning: using independent target %s\n", t->name );
+
+ pushsettings( t->settings );
+ t->boundname = search( t->name, &t->time, 0 );
+ t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
+ popsettings( t->settings );
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/mkjambase.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/mkjambase.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/mkjambase.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,131 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * mkjambase.c - turn Jambase into a big C structure
+ *
+ * Usage: mkjambase jambase.c Jambase ...
+ *
+ * Results look like this:
+ *
+ * char *jambase[] = {
+ * "...\n",
+ * ...
+ * 0 };
+ *
+ * Handles \'s and "'s specially; knows to delete blank and comment lines.
+ *
+ */
+
+# include <stdio.h>
+# include <string.h>
+
+int main( int argc, char **argv, char **envp )
+{
+ char buf[ 1024 ];
+ FILE *fin;
+ FILE *fout;
+ char *p;
+ int doDotC = 0;
+
+ if( argc < 3 )
+ {
+ fprintf( stderr, "usage: %s jambase.c Jambase ...\n", argv[0] );
+ return -1;
+ }
+
+ if( !( fout = fopen( argv[1], "w" ) ) )
+ {
+ perror( argv[1] );
+ return -1;
+ }
+
+ /* If the file ends in .c generate a C source file */
+
+ if( ( p = strrchr( argv[1], '.' ) ) && !strcmp( p, ".c" ) )
+ doDotC++;
+
+ /* Now process the files */
+
+ argc -= 2, argv += 2;
+
+ if( doDotC )
+ {
+ fprintf( fout, "/* Generated by mkjambase from Jambase */\n" );
+ fprintf( fout, "char *jambase[] = {\n" );
+ }
+
+ for( ; argc--; argv++ )
+ {
+ if( !( fin = fopen( *argv, "r" ) ) )
+ {
+ perror( *argv );
+ return -1;
+ }
+
+ if( doDotC )
+ {
+ fprintf( fout, "/* %s */\n", *argv );
+ }
+ else
+ {
+ fprintf( fout, "### %s ###\n", *argv );
+ }
+
+ while( fgets( buf, sizeof( buf ), fin ) )
+ {
+ if( doDotC )
+ {
+ char *p = buf;
+
+ /* Strip leading whitespace. */
+
+ while( *p == ' ' || *p == '\t' || *p == '\n' )
+ p++;
+
+ /* Drop comments and empty lines. */
+
+ if( *p == '#' || !*p )
+ continue;
+
+ /* Copy */
+
+ putc( '"', fout );
+
+ for( ; *p && *p != '\n'; p++ )
+ switch( *p )
+ {
+ case '\\': putc( '\\', fout ); putc( '\\', fout ); break;
+ case '"': putc( '\\', fout ); putc( '"', fout ); break;
+ case '\r': break;
+ default: putc( *p, fout ); break;
+ }
+
+ fprintf( fout, "\\n\",\n" );
+ }
+ else
+ {
+ fprintf( fout, "%s", buf );
+ }
+
+ }
+
+ fclose( fin );
+ }
+
+ if( doDotC )
+ fprintf( fout, "0 };\n" );
+
+ fclose( fout );
+
+ return 0;
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/modules/order.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/modules/order.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/modules/order.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,142 @@
+/* Copyright Vladimir Prus 2004. 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) */
+
+#include "../native.h"
+#include "../lists.h"
+#include "../strings.h"
+#include "../newstr.h"
+#include "../variable.h"
+
+
+/* Use quite klugy approach: when we add order dependency from 'a' to 'b',
+ just append 'b' to of value of variable 'a'.
+*/
+LIST *add_pair( PARSE *parse, FRAME *frame )
+{
+ LIST* arg = lol_get( frame->args, 0 );
+
+ var_set(arg->string, list_copy(0, arg->next), VAR_APPEND);
+
+ return L0;
+}
+
+/** Given a list and a value, returns position of that value in
+ the list, or -1 if not found.
+*/
+int list_index(LIST* list, const char* value)
+{
+ int result = 0;
+ for(; list; list = list->next, ++result) {
+ if (strcmp(list->string, value) == 0)
+ return result;
+ }
+ return -1;
+}
+
+enum colors { white, gray, black };
+
+/* Main routite of topological sort. Calls itself recursively on all
+ adjacent vertices which were not yet visited. After that, 'current_vertex'
+ is added to '*result_ptr'.
+*/
+void do_ts(int** graph, int current_vertex, int* colors, int** result_ptr)
+{
+ int i;
+
+ colors[current_vertex] = gray;
+ for(i = 0; graph[current_vertex][i] != -1; ++i) {
+ int adjacent_vertex = graph[current_vertex][i];
+
+ if (colors[adjacent_vertex] == white)
+ do_ts(graph, adjacent_vertex, colors, result_ptr);
+ else if (colors[adjacent_vertex] == gray)
+ ; /* This is loop. Not sure what to do... */
+ }
+ colors[current_vertex] = black;
+ **result_ptr = current_vertex;
+ (*result_ptr)++;
+}
+
+void topological_sort(int** graph, int num_vertices, int* result)
+{
+ int i;
+ int* colors = (int*)calloc(num_vertices, sizeof(int));
+ for (i = 0; i < num_vertices; ++i)
+ colors[i] = white;
+
+ for(i = 0; i < num_vertices; ++i)
+ if (colors[i] == white)
+ do_ts(graph, i, colors, &result);
+
+ free(colors);
+}
+
+LIST *order( PARSE *parse, FRAME *frame )
+{
+ LIST* arg = lol_get( frame->args, 0 );
+ LIST* tmp;
+ LIST* result = 0;
+ int src, dst;
+
+ /* We need to create a graph of order dependencies between
+ the passed objects. We assume that there are no duplicates
+ passed to 'add_pair'.
+ */
+ int length = list_length(arg);
+ int** graph = (int**)calloc(length, sizeof(int*));
+ int* order = (int*)malloc((length+1)*sizeof(int));
+
+ for(tmp = arg, src = 0; tmp; tmp = tmp->next, ++src) {
+ /* For all object this one depend upon, add elements
+ to 'graph' */
+ LIST* dependencies = var_get(tmp->string);
+ int index = 0;
+
+ graph[src] = (int*)calloc(list_length(dependencies)+1, sizeof(int));
+ for(; dependencies; dependencies = dependencies->next) {
+ int dst = list_index(arg, dependencies->string);
+ if (dst != -1)
+ graph[src][index++] = dst;
+ }
+ graph[src][index] = -1;
+ }
+
+ topological_sort(graph, length, order);
+
+ {
+ int index = length-1;
+ for(; index >= 0; --index) {
+ int i;
+ tmp = arg;
+ for (i = 0; i < order[index]; ++i, tmp = tmp->next);
+ result = list_new(result, tmp->string);
+ }
+ }
+
+ /* Clean up */
+ {
+ int i;
+ for(i = 0; i < length; ++i)
+ free(graph[i]);
+ free(graph);
+ free(order);
+ }
+
+ return result;
+}
+
+void init_order()
+{
+ {
+ char* args[] = { "first", "second", 0 };
+ declare_native_rule("class at order", "add-pair", args, add_pair);
+ }
+
+ {
+ char* args[] = { "objects", "*", 0 };
+ declare_native_rule("class at order", "order", args, order);
+ }
+
+
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/modules/path.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/modules/path.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/modules/path.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,32 @@
+/* Copyright Vladimir Prus 2003. 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) */
+
+#include "../native.h"
+#include "../timestamp.h"
+#include "../newstr.h"
+
+LIST *path_exists( PARSE *parse, FRAME *frame )
+{
+ LIST* l = lol_get( frame->args, 0 );
+
+ time_t time;
+ timestamp(l->string, &time);
+ if (time != 0)
+ {
+ return list_new(0, newstr("true"));
+ }
+ else
+ {
+ return L0;
+ }
+}
+
+void init_path()
+{
+ {
+ char* args[] = { "location", 0 };
+ declare_native_rule("path", "exists", args, path_exists);
+ }
+
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/modules/property-set.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/modules/property-set.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/modules/property-set.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,109 @@
+/* Copyright Vladimir Prus 2003. 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) */
+
+#include "../native.h"
+#include "../timestamp.h"
+#include "../newstr.h"
+#include "../strings.h"
+#include "../lists.h"
+#include "../variable.h"
+#include "../compile.h"
+
+LIST* get_grist(char* f)
+{
+ char* end = strchr(f, '>');
+ string s[1];
+ LIST* result;
+
+ string_new(s);
+
+ string_append_range(s, f, end+1);
+ result = list_new(0, newstr(s->value));
+
+ string_free(s);
+ return result;
+}
+
+/*
+rule create ( raw-properties * )
+{
+ raw-properties = [ sequence.unique
+ [ sequence.insertion-sort $(raw-properties) ] ] ;
+
+ local key = $(raw-properties:J=-:E=) ;
+
+ if ! $(.ps.$(key))
+ {
+ .ps.$(key) = [ new property-set $(raw-properties) ] ;
+ }
+ return $(.ps.$(key)) ;
+}
+*/
+
+LIST *property_set_create( PARSE *parse, FRAME *frame )
+{
+ LIST* properties = lol_get( frame->args, 0 );
+ LIST* sorted = 0;
+ LIST* order_sensitive = 0;
+ LIST* unique;
+ LIST* tmp;
+ LIST* val;
+ string var[1];
+
+#if 0
+ /* Sort all properties which are not order sensitive */
+ for(tmp = properties; tmp; tmp = tmp->next) {
+ LIST* g = get_grist(tmp->string);
+ LIST* att = call_rule("feature.attributes", frame, g, 0);
+ if (list_in(att, "order-sensitive")) {
+ order_sensitive = list_new( order_sensitive, tmp->string);
+ } else {
+ sorted = list_new( sorted, tmp->string);
+ }
+ list_free(att);
+ }
+
+ sorted = list_sort(sorted);
+ sorted = list_append(sorted, order_sensitive);
+ unique = list_unique(sorted);
+#endif
+ sorted = list_sort(properties);
+ unique = list_unique(sorted);
+
+ string_new(var);
+ string_append(var, ".ps.");
+
+ for(tmp = unique; tmp; tmp = tmp->next) {
+ string_append(var, tmp->string);
+ string_push_back(var, '-');
+ }
+ val = var_get(var->value);
+ if (val == 0)
+ {
+ val = call_rule("new", frame,
+ list_append(list_new(0, "property-set"), unique), 0);
+
+ var_set(newstr(var->value), list_copy(0, val), VAR_SET);
+ }
+ else
+ {
+ val = list_copy(0, val);
+ }
+
+ string_free(var);
+ /* The 'unique' variable is freed in 'call_rule'. */
+ list_free(sorted);
+
+ return val;
+
+}
+
+void init_property_set()
+{
+ {
+ char* args[] = { "raw-properties", "*", 0 };
+ declare_native_rule("property-set", "create", args, property_set_create);
+ }
+
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/modules/readme.txt
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/modules/readme.txt 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/modules/readme.txt 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,3 @@
+
+This directory constains sources which declare native
+rules for Boost.Build modules.
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/jam_src/modules/regex.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/modules/regex.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/modules/regex.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,65 @@
+/* Copyright Vladimir Prus 2003. 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) */
+
+#include "../native.h"
+#include "../timestamp.h"
+#include "../newstr.h"
+#include "../strings.h"
+#include "../regexp.h"
+#include "../compile.h"
+
+/*
+rule transform ( list * : pattern )
+{
+ local result ;
+ for local e in $(list)
+ {
+ local m = [ MATCH $(pattern) : $(e) ] ;
+ if $(m)
+ {
+ result += $(m[1]) ;
+ }
+ }
+ return $(result) ;
+}
+*/
+LIST *regex_transform( PARSE *parse, FRAME *frame )
+{
+ LIST* l = lol_get( frame->args, 0 );
+ LIST* pattern = lol_get( frame->args, 1 );
+ LIST* result = 0;
+
+ string buf[1];
+ string_new(buf);
+
+
+ /* Result is cached and intentionally never freed */
+ {
+ regexp *re = regex_compile( pattern->string );
+
+ for(; l; l = l->next)
+ {
+ if( regexec( re, l->string ) )
+ {
+ if (re->startp[1])
+ {
+ string_append_range( buf, re->startp[1], re->endp[1] );
+ result = list_new( result, newstr( buf->value ) );
+ string_truncate( buf, 0 );
+ }
+ }
+ }
+ string_free( buf );
+ }
+
+ return result;
+}
+
+void init_regex()
+{
+ {
+ char* args[] = { "list", "*", ":", "pattern", 0 };
+ declare_native_rule("regex", "transform", args, regex_transform);
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/modules/sequence.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/modules/sequence.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/modules/sequence.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,42 @@
+/* Copyright Vladimir Prus 2003. 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) */
+
+#include "../native.h"
+
+# ifndef max
+# define max( a,b ) ((a)>(b)?(a):(b))
+# endif
+
+
+LIST *sequence_select_highest_ranked( PARSE *parse, FRAME *frame )
+{
+ /* Returns all of 'elements' for which corresponding element in parallel */
+ /* list 'rank' is equal to the maximum value in 'rank'. */
+
+ LIST* elements = lol_get( frame->args, 0 );
+ LIST* rank = lol_get( frame->args, 1 );
+
+ LIST* result = 0;
+ LIST* tmp;
+ int highest_rank = -1;
+
+ for (tmp = rank; tmp; tmp = tmp->next)
+ highest_rank = max(highest_rank, atoi(tmp->string));
+
+ for (; rank; rank = rank->next, elements = elements->next)
+ if (atoi(rank->string) == highest_rank)
+ result = list_new(result, elements->string);
+
+ return result;
+}
+
+void init_sequence()
+{
+ {
+ char* args[] = { "elements", "*", ":", "rank", "*", 0 };
+ declare_native_rule("sequence", "select-highest-ranked", args,
+ sequence_select_highest_ranked);
+ }
+
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/modules/set.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/modules/set.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/modules/set.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,41 @@
+/* Copyright Vladimir Prus 2003. 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) */
+
+#include "../native.h"
+
+/*
+ local result = ;
+ local element ;
+ for element in $(B)
+ {
+ if ! ( $(element) in $(A) )
+ {
+ result += $(element) ;
+ }
+ }
+ return $(result) ;
+*/
+LIST *set_difference( PARSE *parse, FRAME *frame )
+{
+
+ LIST* b = lol_get( frame->args, 0 );
+ LIST* a = lol_get( frame->args, 1 );
+
+ LIST* result = 0;
+ for(; b; b = b->next)
+ {
+ if (!list_in(a, b->string))
+ result = list_new(result, b->string);
+ }
+ return result;
+}
+
+void init_set()
+{
+ {
+ char* args[] = { "B", "*", ":", "A", "*", 0 };
+ declare_native_rule("set", "difference", args, set_difference);
+ }
+
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/modules.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/modules.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/modules.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+#include "modules.h"
+#include "jam.h"
+#include "string.h"
+#include "hash.h"
+#include "newstr.h"
+#include "lists.h"
+#include "parse.h"
+#include "rules.h"
+#include "variable.h"
+#include "strings.h"
+#include <assert.h>
+
+static struct hash* module_hash = 0;
+
+static char* new_module_str( module_t* m, char* suffix )
+{
+ char* result;
+ string s;
+ string_copy( &s, m->name );
+ string_append( &s, suffix );
+ result = newstr( s.value );
+ string_free( &s );
+ return result;
+}
+
+module_t* bindmodule( char* name )
+{
+ string s;
+ module_t m_, *m = &m_;
+
+ if( !module_hash )
+ module_hash = hashinit( sizeof( module_t ), "modules" );
+
+ string_new( &s );
+ if (name)
+ {
+ string_append( &s, name );
+ string_push_back( &s, '.' );
+ }
+
+ m->name = s.value;
+
+ if ( hashenter( module_hash, (HASHDATA **)&m ) )
+ {
+ m->name = newstr( m->name );
+ m->variables = 0;
+ m->rules = 0;
+ m->imported_modules = 0;
+ m->class_module = 0;
+ m->native_rules = 0;
+ }
+ string_free( &s );
+ return m;
+}
+
+/*
+ * demand_rules() - Get the module's "rules" hash on demand
+ */
+struct hash* demand_rules( module_t* m )
+{
+ if ( !m->rules )
+ m->rules = hashinit( sizeof( RULE ), new_module_str( m, "rules" ) );
+ return m->rules;
+}
+
+/*
+ * delete_module() - wipe out the module's rules and variables
+ */
+static void delete_rule_( void* xrule, void* data )
+{
+ rule_free( (RULE*)xrule );
+}
+
+void delete_module( module_t* m )
+{
+ /* clear out all the rules */
+ if ( m->rules )
+ {
+ hashenumerate( m->rules, delete_rule_, (void*)0 );
+ hashdone( m->rules );
+ m->rules = 0;
+ }
+
+ if ( m->variables )
+ {
+ var_hash_swap( &m->variables );
+ var_done();
+ var_hash_swap( &m->variables );
+ m->variables = 0;
+ }
+}
+
+module_t* root_module()
+{
+ static module_t* root = 0;
+ if ( !root )
+ root = bindmodule(0);
+ return root;
+}
+
+void enter_module( module_t* m )
+{
+ var_hash_swap( &m->variables );
+}
+
+void exit_module( module_t* m )
+{
+ var_hash_swap( &m->variables );
+}
+
+void import_module(LIST* module_names, module_t* target_module)
+{
+ struct hash* h;
+
+ if (!target_module->imported_modules)
+ target_module->imported_modules = hashinit( sizeof(char*), "imported");
+ h = target_module->imported_modules;
+
+ for(;module_names; module_names = module_names->next) {
+
+ char* s = module_names->string;
+ char** ss = &s;
+
+ hashenter(h, (HASHDATA**)&ss);
+ }
+}
+
+static void add_module_name( void* r_, void* result_ )
+{
+ char** r = (char**)r_;
+ LIST** result = (LIST**)result_;
+
+ *result = list_new( *result, copystr( *r ) );
+}
+
+LIST* imported_modules(module_t* module)
+{
+ LIST *result = L0;
+
+ if ( module->imported_modules )
+ hashenumerate( module->imported_modules, add_module_name, &result );
+
+ return result;
+}
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/modules.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/modules.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/modules.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef MODULES_DWA10182001_H
+# define MODULES_DWA10182001_H
+
+#include "lists.h"
+
+struct module_t
+{
+ char* name;
+ struct hash* rules;
+ struct hash* variables;
+ struct hash* imported_modules;
+ struct module_t* class_module;
+ struct hash* native_rules;
+};
+
+typedef struct module_t module_t ; /* MSVC debugger gets confused unless this is provided */
+
+module_t* bindmodule( char* name );
+module_t* root_module();
+void bind_module_var( module_t*, char* name );
+void enter_module( module_t* );
+void exit_module( module_t* );
+void delete_module( module_t* );
+
+void import_module(LIST* module_names, module_t* target_module);
+LIST* imported_modules(module_t* module);
+
+struct hash* demand_rules( module_t* );
+
+
+#endif
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/native.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/native.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/native.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,37 @@
+/* Copyright Vladimir Prus 2003. 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) */
+
+#include "native.h"
+#include "hash.h"
+
+# define P0 (PARSE *)0
+# define C0 (char *)0
+
+
+void declare_native_rule(char* module, char* rule, char** args,
+ LIST*(*f)(PARSE*, FRAME*))
+
+{
+ module_t* m = bindmodule(module);
+ if (m->native_rules == 0) {
+ m->native_rules = hashinit( sizeof( native_rule_t ), "native rules");
+ }
+
+ {
+ native_rule_t n, *np = &n;
+ n.name = rule;
+ if (args)
+ {
+ n.arguments = args_new();
+ lol_build( n.arguments->data, args );
+ }
+ else
+ {
+ n.arguments = 0;
+ }
+ n.procedure = parse_make( f, P0, P0, P0, C0, C0, 0 );
+ hashenter(m->native_rules, (HASHDATA**)&np);
+ }
+}
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/native.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/native.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/native.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,25 @@
+/* Copyright David Abrahams 2003. 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) */
+
+#ifndef NATIVE_H_VP_2003_12_09
+#define NATIVE_H_VP_2003_12_09
+
+#include "rules.h"
+
+struct native_rule_t
+{
+ char* name;
+ argument_list* arguments;
+ PARSE* procedure;
+};
+
+/* MSVC debugger gets confused unless this is provided */
+typedef struct native_rule_t native_rule_t ;
+
+void declare_native_rule(char* module, char* rule, char** args,
+ LIST*(*f)(PARSE*, FRAME*));
+
+
+
+#endif
Added: boost-jam/boost-build/branches/upstream/current/jam_src/newstr.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/newstr.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/newstr.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,158 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "newstr.h"
+# include "hash.h"
+# include <stddef.h>
+# include <stdlib.h>
+
+/*
+ * newstr.c - string manipulation routines
+ *
+ * To minimize string copying, string creation, copying, and freeing
+ * is done through newstr.
+ *
+ * External functions:
+ *
+ * newstr() - return a dynamically allocated copy of a string
+ * copystr() - return a copy of a string previously returned by newstr()
+ * freestr() - free a string returned by newstr() or copystr()
+ * donestr() - free string tables
+ *
+ * Once a string is passed to newstr(), the returned string is readonly.
+ *
+ * This implementation builds a hash table of all strings, so that multiple
+ * calls of newstr() on the same string allocate memory for the string once.
+ * Strings are never actually freed.
+ */
+
+typedef char *STRING;
+
+static struct hash *strhash = 0;
+static int strtotal = 0;
+
+/*
+ * Immortal string allocator implementation speeds string allocation
+ * and cuts down on internal fragmentation
+ */
+
+# define STRING_BLOCK 4096
+typedef struct strblock
+{
+ struct strblock* next;
+ char data[STRING_BLOCK];
+} strblock;
+
+static strblock* strblock_chain = 0;
+
+/* Storage remaining in the current strblock */
+static char* storage_start = 0;
+static char* storage_finish = 0;
+
+/*
+ * allocate() - Allocate n bytes of immortal string storage
+ */
+static char* allocate(size_t n)
+{
+ /* See if we can grab storage from an existing block */
+ size_t remaining = storage_finish - storage_start;
+ if ( remaining >= n )
+ {
+ char* result = storage_start;
+ storage_start += n;
+ return result;
+ }
+ else /* Must allocate a new block */
+ {
+ strblock* new_block;
+ size_t nalloc = n;
+ if ( nalloc < STRING_BLOCK )
+ nalloc = STRING_BLOCK;
+
+ /* allocate a new block and link into the chain */
+ new_block = (strblock*)malloc( offsetof( strblock, data[0] ) + nalloc * sizeof(new_block->data[0]) );
+ if ( new_block == 0 )
+ return 0;
+ new_block->next = strblock_chain;
+ strblock_chain = new_block;
+
+ /* Take future allocations out of the larger remaining space */
+ if ( remaining < nalloc - n )
+ {
+ storage_start = new_block->data + n;
+ storage_finish = new_block->data + nalloc;
+ }
+ return new_block->data;
+ }
+}
+
+/*
+ * newstr() - return a dynamically allocated copy of a string
+ */
+
+char *
+newstr( char *string )
+{
+ STRING str, *s = &str;
+
+ if( !strhash )
+ strhash = hashinit( sizeof( STRING ), "strings" );
+
+ *s = string;
+
+ if( hashenter( strhash, (HASHDATA **)&s ) )
+ {
+ int l = strlen( string );
+ char *m = (char *)allocate( l + 1 );
+
+ strtotal += l + 1;
+ memcpy( m, string, l + 1 );
+ *s = m;
+ }
+
+ return *s;
+}
+
+/*
+ * copystr() - return a copy of a string previously returned by newstr()
+ */
+
+char *
+copystr( char *s )
+{
+ return s;
+}
+
+/*
+ * freestr() - free a string returned by newstr() or copystr()
+ */
+
+void
+freestr( char *s )
+{
+}
+
+/*
+ * donestr() - free string tables
+ */
+
+void
+donestr()
+{
+ /* Reclaim string blocks */
+ while ( strblock_chain != 0 )
+ {
+ strblock* n = strblock_chain->next;
+ free(strblock_chain);
+ strblock_chain = n;
+ }
+
+ hashdone( strhash );
+
+ if( DEBUG_MEM )
+ printf( "%dK in strings\n", strtotal / 1024 );
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/newstr.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/newstr.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/newstr.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,14 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * newstr.h - string manipulation routines
+ */
+
+char *newstr( char *string );
+char *copystr( char *s );
+void freestr( char *s );
+void donestr();
Added: boost-jam/boost-build/branches/upstream/current/jam_src/option.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/option.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/option.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,103 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "option.h"
+
+/*
+ * option.c - command line option processing
+ *
+ * {o >o
+ * \<>) "Process command line options as defined in <option.h>.
+ * Return the number of argv[] elements used up by options,
+ * or -1 if an invalid option flag was given or an argument
+ * was supplied for an option that does not require one."
+ */
+
+int
+getoptions(
+ int argc,
+ char **argv,
+ char *opts,
+ option *optv )
+{
+ int i;
+ int optc = N_OPTS;
+
+ memset( (char *)optv, '\0', sizeof( *optv ) * N_OPTS );
+
+ for( i = 0; i < argc; i++ )
+ {
+ char *arg;
+
+ if( argv[i][0] != '-' || ( argv[i][1] != '-' && !isalpha( argv[i][1] ) ) )
+ break;
+
+ if( !optc-- )
+ {
+ printf( "too many options (%d max)\n", N_OPTS );
+ return -1;
+ }
+
+ for( arg = &argv[i][1]; *arg; arg++ )
+ {
+ char *f;
+
+ for( f = opts; *f; f++ )
+ if( *f == *arg )
+ break;
+
+ if( !*f )
+ {
+ printf( "Invalid option: -%c\n", *arg );
+ return -1;
+ }
+
+ optv->flag = *f;
+
+ if( f[1] != ':' )
+ {
+ optv++->val = "true";
+ }
+ else if( arg[1] )
+ {
+ optv++->val = &arg[1];
+ break;
+ }
+ else if( ++i < argc )
+ {
+ optv++->val = argv[i];
+ break;
+ }
+ else
+ {
+ printf( "option: -%c needs argument\n", *f );
+ return -1;
+ }
+ }
+ }
+
+ return i;
+}
+
+/*
+ * Name: getoptval() - find an option given its character
+ */
+
+char *
+getoptval(
+ option *optv,
+ char opt,
+ int subopt )
+{
+ int i;
+
+ for( i = 0; i < N_OPTS; i++, optv++ )
+ if( optv->flag == opt && !subopt-- )
+ return optv->val;
+
+ return 0;
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/option.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/option.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/option.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,23 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * option.h - command line option processing
+ *
+ * {o >o
+ * \ -) "Command line option."
+ */
+
+typedef struct option
+{
+ char flag; /* filled in by getoption() */
+ char *val; /* set to random address if true */
+} option;
+
+# define N_OPTS 256
+
+int getoptions( int argc, char **argv, char *opts, option *optv );
+char * getoptval( option *optv, char opt, int subopt );
Added: boost-jam/boost-build/branches/upstream/current/jam_src/parse.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/parse.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/parse.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,137 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "parse.h"
+# include "scan.h"
+# include "newstr.h"
+# include "modules.h"
+# include "frames.h"
+
+/*
+ * parse.c - make and destroy parse trees as driven by the parser
+ *
+ * 09/07/00 (seiwald) - ref count on PARSE to avoid freeing when used,
+ * as per Matt Armstrong.
+ * 09/11/00 (seiwald) - structure reworked to reflect that (*func)()
+ * returns a LIST *.
+ */
+
+static PARSE *yypsave;
+
+void
+parse_file( char *f, FRAME* frame )
+{
+ /* Suspend scan of current file */
+ /* and push this new file in the stream */
+
+ yyfparse(f);
+
+ /* Now parse each block of rules and execute it. */
+ /* Execute it outside of the parser so that recursive */
+ /* calls to yyrun() work (no recursive yyparse's). */
+
+ for(;;)
+ {
+ PARSE *p;
+
+ /* Filled by yyparse() calling parse_save() */
+
+ yypsave = 0;
+
+ /* If parse error or empty parse, outta here */
+
+ if( yyparse() || !( p = yypsave ) )
+ break;
+
+ /* Run the parse tree. */
+
+ parse_evaluate( p, frame );
+ parse_free( p );
+ }
+}
+
+void
+parse_save( PARSE *p )
+{
+ yypsave = p;
+}
+
+PARSE *
+parse_make(
+ LIST *(*func)( PARSE *p, FRAME *args ),
+ PARSE *left,
+ PARSE *right,
+ PARSE *third,
+ char *string,
+ char *string1,
+ int num )
+{
+ PARSE *p = (PARSE *)malloc( sizeof( PARSE ) );
+
+ p->func = func;
+ p->left = left;
+ p->right = right;
+ p->third = third;
+ p->string = string;
+ p->string1 = string1;
+ p->num = num;
+ p->refs = 1;
+ p->rulename = 0;
+
+ if ( left )
+ {
+ p->file = left->file;
+ p->line = left->line;
+ }
+ else
+ {
+ yyinput_stream( &p->file, &p->line );
+ }
+
+ return p;
+}
+
+void
+parse_refer( PARSE *p )
+{
+ ++p->refs;
+}
+
+void
+parse_free( PARSE *p )
+{
+ if( --p->refs )
+ return;
+
+ if( p->string )
+ freestr( p->string );
+ if( p->string1 )
+ freestr( p->string1 );
+ if( p->left )
+ parse_free( p->left );
+ if( p->right )
+ parse_free( p->right );
+ if( p->third )
+ parse_free( p->third );
+ if ( p->rulename )
+ freestr( p->rulename );
+
+ free( (char *)p );
+}
+
+LIST* parse_evaluate( PARSE *p, FRAME* frame )
+{
+ frame->procedure = p;
+ return (*p->func)(p, frame);
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/parse.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/parse.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/parse.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,59 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef PARSE_DWA20011020_H
+# define PARSE_DWA20011020_H
+# include "frames.h"
+# include "modules.h"
+# include "lists.h"
+
+/*
+ * parse.h - make and destroy parse trees as driven by the parser
+ */
+
+/*
+ * parse tree node
+ */
+
+struct _PARSE {
+ LIST *(*func)( PARSE *p, FRAME *frame );
+ PARSE *left;
+ PARSE *right;
+ PARSE *third;
+ char *string;
+ char *string1;
+ int num;
+ int refs;
+/* module* module; */
+ char* rulename;
+ char* file;
+ int line;
+} ;
+
+void parse_file( char *f, FRAME* frame );
+void parse_save( PARSE *p );
+
+PARSE * parse_make(
+ LIST *(*func)( PARSE *p, FRAME* frame ),
+ PARSE *left,
+ PARSE *right,
+ PARSE *third,
+ char *string,
+ char *string1,
+ int num );
+
+void parse_refer( PARSE *p );
+void parse_free( PARSE *p );
+LIST* parse_evaluate( PARSE *p, FRAME* frame );
+
+#endif
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/patchlevel.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/patchlevel.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/patchlevel.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,5 @@
+/* Keep JAMVERSYM in sync with VERSION. */
+/* It can be accessed as $(JAMVERSION) in the Jamfile. */
+
+#define VERSION "3.1.10"
+#define JAMVERSYM "JAMVERSION=3.1"
Added: boost-jam/boost-build/branches/upstream/current/jam_src/pathmac.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/pathmac.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/pathmac.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,261 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "pathsys.h"
+
+# ifdef OS_MAC
+
+# define DELIM ':'
+
+/*
+ * pathunix.c - manipulate file names on UNIX, NT, OS2
+ *
+ * External routines:
+ *
+ * path_parse() - split a file name into dir/base/suffix/member
+ * path_build() - build a filename given dir/base/suffix/member
+ * path_parent() - make a PATHNAME point to its parent dir
+ *
+ * File_parse() and path_build() just manipuate a string and a structure;
+ * they do not make system calls.
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 12/26/93 (seiwald) - handle dir/.suffix properly in path_build()
+ * 12/19/94 (mikem) - solaris string table insanity support
+ * 12/21/94 (wingerd) Use backslashes for pathnames - the NT way.
+ * 02/14/95 (seiwald) - parse and build /xxx properly
+ * 02/23/95 (wingerd) Compilers on NT can handle "/" in pathnames, so we
+ * should expect hdr searches to come up with strings
+ * like "thing/thing.h". So we need to test for "/" as
+ * well as "\" when parsing pathnames.
+ * 03/16/95 (seiwald) - fixed accursed typo on line 69.
+ * 05/03/96 (seiwald) - split from filent.c, fileunix.c
+ * 12/20/96 (seiwald) - when looking for the rightmost . in a file name,
+ * don't include the archive member name.
+ * 01/10/01 (seiwald) - path_parse now strips the trailing : from the
+ * directory name, unless the directory name is all
+ * :'s, so that $(d:P) works.
+ */
+
+/*
+ * path_parse() - split a file name into dir/base/suffix/member
+ */
+
+void
+path_parse(
+ char *file,
+ PATHNAME *f )
+{
+ char *p, *q;
+ char *end;
+
+ memset( (char *)f, 0, sizeof( *f ) );
+
+ /* Look for <grist> */
+
+ if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
+ {
+ f->f_grist.ptr = file;
+ f->f_grist.len = p - file;
+ file = p + 1;
+ }
+
+ /* Look for dir: */
+
+ if( p = strrchr( file, DELIM ) )
+ {
+ f->f_dir.ptr = file;
+ f->f_dir.len = p - file;
+ file = p + 1;
+
+ /* All :'s? Include last : as part of directory name */
+
+ while( p > f->f_dir.ptr && *--p == DELIM )
+ ;
+
+ if( p == f->f_dir.ptr )
+ f->f_dir.len++;
+ }
+
+ end = file + strlen( file );
+
+ /* Look for (member) */
+
+ if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
+ {
+ f->f_member.ptr = p + 1;
+ f->f_member.len = end - p - 2;
+ end = p;
+ }
+
+ /* Look for .suffix */
+ /* This would be memrchr() */
+
+ p = 0;
+ q = file;
+
+ while( q = memchr( q, '.', end - q ) )
+ p = q++;
+
+ if( p )
+ {
+ f->f_suffix.ptr = p;
+ f->f_suffix.len = end - p;
+ end = p;
+ }
+
+ /* Leaves base */
+
+ f->f_base.ptr = file;
+ f->f_base.len = end - file;
+}
+
+/*
+ * path_build() - build a filename given dir/base/suffix/member
+ */
+
+# define DIR_EMPTY 0 /* "" */
+# define DIR_DOT 1 /* : */
+# define DIR_DOTDOT 2 /* :: */
+# define DIR_ABS 3 /* dira:dirb: */
+# define DIR_REL 4 /* :dira:dirb: */
+
+# define G_DIR 0 /* take dir */
+# define G_ROOT 1 /* take root */
+# define G_CAT 2 /* prepend root to dir */
+# define G_DTDR 3 /* :: of rel dir */
+# define G_DDDD 4 /* make it ::: (../..) */
+# define G_MT 5 /* leave it empty */
+
+char grid[5][5] = {
+/* EMPTY DOT DOTDOT ABS REL */
+/* EMPTY */ { G_MT, G_DIR, G_DIR, G_DIR, G_DIR },
+/* DOT */ { G_ROOT, G_DIR, G_DIR, G_DIR, G_DIR },
+/* DOTDOT */ { G_ROOT, G_ROOT, G_DDDD, G_DIR, G_DTDR },
+/* ABS */ { G_ROOT, G_ROOT, G_ROOT, G_DIR, G_CAT },
+/* REL */ { G_ROOT, G_ROOT, G_ROOT, G_DIR, G_CAT }
+} ;
+
+static int
+file_flags(
+ char *ptr,
+ int len )
+{
+ if( !len )
+ return DIR_EMPTY;
+ if( len == 1 && ptr[0] == DELIM )
+ return DIR_DOT;
+ if( len == 2 && ptr[0] == DELIM && ptr[1] == DELIM )
+ return DIR_DOTDOT;
+ if( ptr[0] == DELIM )
+ return DIR_REL;
+ return DIR_ABS;
+}
+
+void
+path_build(
+ PATHNAME *f,
+ string* file,
+ int binding )
+{
+ int dflag, rflag, act;
+
+ file_build1( f, file );
+
+ /* Combine root & directory, according to the grid. */
+
+ dflag = file_flags( f->f_dir.ptr, f->f_dir.len );
+ rflag = file_flags( f->f_root.ptr, f->f_root.len );
+
+ switch( act = grid[ rflag ][ dflag ] )
+ {
+ case G_DTDR:
+ {
+ /* :: of rel dir */
+ string_push_back( file, DELIM );
+ }
+ /* fall through */
+
+ case G_DIR:
+ /* take dir */
+ string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
+ break;
+
+ case G_ROOT:
+ /* take root */
+ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
+ break;
+
+ case G_CAT:
+ /* prepend root to dir */
+ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
+ if( file->value[file->size - 1] == DELIM )
+ string_pop_back( file );
+ string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
+ break;
+
+ case G_DDDD:
+ /* make it ::: (../..) */
+ string_append( file, ":::" );
+ break;
+ }
+
+ /* Put : between dir and file (if none already) */
+
+ if( act != G_MT &&
+ file->value[file->size - 1] != DELIM &&
+ ( f->f_base.len || f->f_suffix.len ) )
+ {
+ string_push_back( file, DELIM );
+ }
+
+ if( f->f_base.len )
+ {
+ string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
+ }
+
+ if( f->f_suffix.len )
+ {
+ string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
+ }
+
+ if( f->f_member.len )
+ {
+ string_push_back( file, '(' );
+ string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len );
+ string_push_back( file, ')' );
+ }
+
+ if( DEBUG_SEARCH )
+ printf(" -> '%s'\n", file->value);
+}
+
+/*
+ * path_parent() - make a PATHNAME point to its parent dir
+ */
+
+void
+path_parent( PATHNAME *f )
+{
+ /* just set everything else to nothing */
+
+ f->f_base.ptr =
+ f->f_suffix.ptr =
+ f->f_member.ptr = "";
+
+ f->f_base.len =
+ f->f_suffix.len =
+ f->f_member.len = 0;
+}
+
+# endif /* OS_MAC */
Added: boost-jam/boost-build/branches/upstream/current/jam_src/pathsys.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/pathsys.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/pathsys.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * pathsys.h - PATHNAME struct
+ */
+
+/*
+ * PATHNAME - a name of a file, broken into <grist>dir/base/suffix(member)
+ *
+ * <grist> is salt to distinguish between targets that otherwise would
+ * have the same name: it never appears in the bound name of a target.
+ * (member) is an archive member name: the syntax is arbitrary, but must
+ * agree in path_parse(), path_build() and the Jambase.
+ *
+ * On VMS, we keep track of whether the original path was a directory
+ * (without a file), so that $(VAR:D) can climb to the parent.
+ */
+
+#ifndef PATHSYS_VP_20020211_H
+# define PATHSYS_VP_20020211_H
+
+#include "strings.h"
+
+typedef struct _pathname PATHNAME;
+typedef struct _pathpart PATHPART;
+
+struct _pathpart {
+ char *ptr;
+ int len;
+};
+
+struct _pathname {
+ PATHPART part[6];
+# ifdef OS_VMS
+ int parent;
+# endif
+
+# define f_grist part[0]
+# define f_root part[1]
+# define f_dir part[2]
+# define f_base part[3]
+# define f_suffix part[4]
+# define f_member part[5]
+
+} ;
+
+void path_build( PATHNAME *f, string *file, int binding );
+void path_build1( PATHNAME *f, string *file );
+
+void path_parse( char *file, PATHNAME *f );
+void path_parent( PATHNAME *f );
+
+#ifdef NT
+
+/** Returns newstr-allocated string with long equivivalent of 'short_name'.
+ If none exists -- i.e. 'short_path' is already long path, it's returned
+ unaltered. */
+char* short_path_to_long_path(char* short_path);
+
+#endif
+
+#endif
Added: boost-jam/boost-build/branches/upstream/current/jam_src/pathunix.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/pathunix.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/pathunix.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,397 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "pathsys.h"
+# include "strings.h"
+# include "newstr.h"
+# include "filesys.h"
+
+# ifdef USE_PATHUNIX
+
+/*
+ * pathunix.c - manipulate file names on UNIX, NT, OS2, AmigaOS
+ *
+ * External routines:
+ *
+ * path_parse() - split a file name into dir/base/suffix/member
+ * path_build() - build a filename given dir/base/suffix/member
+ * path_parent() - make a PATHNAME point to its parent dir
+ *
+ * File_parse() and path_build() just manipuate a string and a structure;
+ * they do not make system calls.
+ *
+ * 04/08/94 (seiwald) - Coherent/386 support added.
+ * 12/26/93 (seiwald) - handle dir/.suffix properly in path_build()
+ * 12/19/94 (mikem) - solaris string table insanity support
+ * 12/21/94 (wingerd) Use backslashes for pathnames - the NT way.
+ * 02/14/95 (seiwald) - parse and build /xxx properly
+ * 02/23/95 (wingerd) Compilers on NT can handle "/" in pathnames, so we
+ * should expect hdr searches to come up with strings
+ * like "thing/thing.h". So we need to test for "/" as
+ * well as "\" when parsing pathnames.
+ * 03/16/95 (seiwald) - fixed accursed typo on line 69.
+ * 05/03/96 (seiwald) - split from filent.c, fileunix.c
+ * 12/20/96 (seiwald) - when looking for the rightmost . in a file name,
+ * don't include the archive member name.
+ * 01/13/01 (seiwald) - turn on \ handling on UNIX, on by accident
+ */
+
+/*
+ * path_parse() - split a file name into dir/base/suffix/member
+ */
+
+void
+path_parse(
+ char *file,
+ PATHNAME *f )
+{
+ char *p, *q;
+ char *end;
+
+ memset( (char *)f, 0, sizeof( *f ) );
+
+ /* Look for <grist> */
+
+ if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
+ {
+ f->f_grist.ptr = file;
+ f->f_grist.len = p - file;
+ file = p + 1;
+ }
+
+ /* Look for dir/ */
+
+ p = strrchr( file, '/' );
+
+# if PATH_DELIM == '\\'
+ /* On NT, look for dir\ as well */
+ {
+ char *p1 = strrchr( file, '\\' );
+ p = p1 > p ? p1 : p;
+ }
+# endif
+
+ if( p )
+ {
+ f->f_dir.ptr = file;
+ f->f_dir.len = p - file;
+
+ /* Special case for / - dirname is /, not "" */
+
+ if( !f->f_dir.len )
+ f->f_dir.len = 1;
+
+# if PATH_DELIM == '\\'
+ /* Special case for D:/ - dirname is D:/, not "D:" */
+
+ if( f->f_dir.len == 2 && file[1] == ':' )
+ f->f_dir.len = 3;
+# endif
+
+ file = p + 1;
+ }
+
+ end = file + strlen( file );
+
+ /* Look for (member) */
+
+ if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
+ {
+ f->f_member.ptr = p + 1;
+ f->f_member.len = end - p - 2;
+ end = p;
+ }
+
+ /* Look for .suffix */
+ /* This would be memrchr() */
+
+ p = 0;
+ q = file;
+
+ while( q = (char *)memchr( q, '.', end - q ) )
+ p = q++;
+
+ if( p )
+ {
+ f->f_suffix.ptr = p;
+ f->f_suffix.len = end - p;
+ end = p;
+ }
+
+ /* Leaves base */
+
+ f->f_base.ptr = file;
+ f->f_base.len = end - file;
+}
+
+/*
+ * path_delims - the string of legal path delimiters
+ */
+static char path_delims[] = {
+ PATH_DELIM,
+# if PATH_DELIM == '\\'
+ '/',
+# endif
+ 0
+};
+
+/*
+ * is_path_delim() - true iff c is a path delimiter
+ */
+static int is_path_delim( char c )
+{
+ char* p = strchr( path_delims, c );
+ return p && *p;
+}
+
+/*
+ * as_path_delim() - convert c to a path delimiter if it isn't one
+ * already
+ */
+static char as_path_delim( char c )
+{
+ return is_path_delim( c ) ? c : PATH_DELIM;
+}
+
+/*
+ * path_build() - build a filename given dir/base/suffix/member
+ *
+ * To avoid changing slash direction on NT when reconstituting paths,
+ * instead of unconditionally appending PATH_DELIM we check the
+ * past-the-end character of the previous path element. If it is in
+ * path_delims, we append that, and only append PATH_DELIM as a last
+ * resort. This heuristic is based on the fact that PATHNAME objects
+ * are usually the result of calling path_parse, which leaves the
+ * original slashes in the past-the-end position. Correctness depends
+ * on the assumption that all strings are zero terminated, so a
+ * past-the-end character will always be available.
+ *
+ * As an attendant patch, we had to ensure that backslashes are used
+ * explicitly in timestamp.c
+ */
+
+void
+path_build(
+ PATHNAME *f,
+ string *file,
+ int binding )
+{
+ file_build1( f, file );
+
+ /* Don't prepend root if it's . or directory is rooted */
+# if PATH_DELIM == '/'
+
+ if( f->f_root.len
+ && !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' )
+ && !( f->f_dir.len && f->f_dir.ptr[0] == '/' ) )
+
+# else /* unix */
+
+ if( f->f_root.len
+ && !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' )
+ && !( f->f_dir.len && f->f_dir.ptr[0] == '/' )
+ && !( f->f_dir.len && f->f_dir.ptr[0] == '\\' )
+ && !( f->f_dir.len && f->f_dir.ptr[1] == ':' ) )
+
+# endif /* unix */
+
+ {
+ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
+ /* If 'root' already ends with path delimeter,
+ don't add yet another one. */
+ if( ! is_path_delim( f->f_root.ptr[f->f_root.len-1] ) )
+ string_push_back( file, as_path_delim( f->f_root.ptr[f->f_root.len] ) );
+ }
+
+ if( f->f_dir.len )
+ {
+ string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
+ }
+
+ /* UNIX: Put / between dir and file */
+ /* NT: Put \ between dir and file */
+
+ if( f->f_dir.len && ( f->f_base.len || f->f_suffix.len ) )
+ {
+ /* UNIX: Special case for dir \ : don't add another \ */
+ /* NT: Special case for dir / : don't add another / */
+
+# if PATH_DELIM == '\\'
+ if( !( f->f_dir.len == 3 && f->f_dir.ptr[1] == ':' ) )
+# endif
+ if( !( f->f_dir.len == 1 && is_path_delim( f->f_dir.ptr[0] ) ) )
+ string_push_back( file, as_path_delim( f->f_dir.ptr[f->f_dir.len] ) );
+ }
+
+ if( f->f_base.len )
+ {
+ string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
+ }
+
+ if( f->f_suffix.len )
+ {
+ string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
+ }
+
+ if( f->f_member.len )
+ {
+ string_push_back( file, '(' );
+ string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len );
+ string_push_back( file, ')' );
+ }
+}
+
+/*
+ * path_parent() - make a PATHNAME point to its parent dir
+ */
+
+void
+path_parent( PATHNAME *f )
+{
+ /* just set everything else to nothing */
+
+ f->f_base.ptr =
+ f->f_suffix.ptr =
+ f->f_member.ptr = "";
+
+ f->f_base.len =
+ f->f_suffix.len =
+ f->f_member.len = 0;
+}
+
+#ifdef NT
+#include <windows.h>
+#include <tchar.h>
+
+/* The definition of this in winnt.h is not ANSI-C compatible. */
+#undef INVALID_FILE_ATTRIBUTES
+#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+
+
+DWORD ShortPathToLongPath(LPCTSTR lpszShortPath,LPTSTR lpszLongPath,DWORD
+ cchBuffer)
+{
+ DWORD i=0;
+ TCHAR path[_MAX_PATH]={0};
+ TCHAR ret[_MAX_PATH]={0};
+ DWORD pos=0, prev_pos=0;
+ DWORD len=_tcslen(lpszShortPath);
+
+ /* Is the string valid? */
+ if (!lpszShortPath) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ /* Is the path valid? */
+ if (GetFileAttributes(lpszShortPath)==INVALID_FILE_ATTRIBUTES)
+ return 0;
+
+ /* Convert "/" to "\" */
+ for (i=0;i<len;++i) {
+ if (lpszShortPath[i]==_T('/'))
+ path[i]=_T('\\');
+ else
+ path[i]=lpszShortPath[i];
+ }
+
+ /* UNC path? */
+ if (path[0]==_T('\\') && path[1]==_T('\\')) {
+ pos=2;
+ for (i=0;i<2;++i) {
+ while (path[pos]!=_T('\\') && path[pos]!=_T('\0'))
+ ++pos;
+ ++pos;
+ }
+ _tcsncpy(ret,path,pos-1);
+ } /* Drive letter? */
+ else if (path[1]==_T(':')) {
+ if (path[2]==_T('\\'))
+ pos=3;
+ if (len==3) {
+ if (cchBuffer>3)
+ _tcscpy(lpszLongPath,lpszShortPath);
+ return len;
+ }
+ _tcsncpy(ret,path,2);
+ }
+
+ /* Expand the path for each subpath, and strip trailing backslashes */
+ for (prev_pos = pos-1;pos<=len;++pos) {
+ if (path[pos]==_T('\\') || (path[pos]==_T('\0') &&
+ path[pos-1]!=_T('\\'))) {
+ WIN32_FIND_DATA fd;
+ HANDLE hf=0;
+ TCHAR c=path[pos];
+ char* new_element;
+ path[pos]=_T('\0');
+
+ /* the path[prev_pos+1]... path[pos] range is the part of
+ path we're handling right now. We need to find long
+ name for that element and add it. */
+ new_element = path + prev_pos + 1;
+
+ /* First add separator, but only if there's something in result already. */
+ if (ret[0] != _T('\0'))
+ {
+ _tcscat(ret,_T("\\"));
+ }
+
+ /* If it's ".." element, we need to append it, not
+ the name in parent that FindFirstFile will return.
+ Same goes for "." */
+
+ if (new_element[0] == _T('.') && new_element[1] == _T('\0') ||
+ new_element[0] == _T('.') && new_element[1] == _T('.')
+ && new_element[2] == _T('\0'))
+ {
+ _tcscat(ret, new_element);
+ }
+ else
+ {
+ hf=FindFirstFile(path, &fd);
+ if (hf==INVALID_HANDLE_VALUE)
+ return 0;
+
+ _tcscat(ret,fd.cFileName);
+ FindClose(hf);
+ }
+
+ path[pos]=c;
+
+ prev_pos = pos;
+ }
+ }
+
+ len=_tcslen(ret)+1;
+ if (cchBuffer>=len)
+ _tcscpy(lpszLongPath,ret);
+
+ return len;
+}
+
+char* short_path_to_long_path(char* short_path)
+{
+ char buffer2[_MAX_PATH];
+ int ret = ShortPathToLongPath(short_path, buffer2, _MAX_PATH);
+
+ if (ret)
+ return newstr(buffer2);
+ else
+ return newstr(short_path);
+}
+
+#endif
+
+
+# endif /* unix, NT, OS/2, AmigaOS */
Added: boost-jam/boost-build/branches/upstream/current/jam_src/pathvms.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/pathvms.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/pathvms.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,424 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "pathsys.h"
+
+# ifdef OS_VMS
+
+# define DEBUG
+
+/*
+ * pathvms.c - manipulate file names on VMS
+ *
+ * External routines:
+ *
+ * path_parse() - split a file name into dir/base/suffix/member
+ * path_build() - build a filename given dir/base/suffix/member
+ * path_parent() - make a PATHNAME point to its parent dir
+ *
+ * File_parse() and path_build() just manipuate a string and a structure;
+ * they do not make system calls.
+ *
+ * WARNING! This file contains voodoo logic, as black magic is
+ * necessary for wrangling with VMS file name. Woe be to people
+ * who mess with this code.
+ *
+ * 02/09/95 (seiwald) - bungled R=[xxx] - was using directory length!
+ * 05/03/96 (seiwald) - split from filevms.c
+ */
+
+/*
+ * path_parse() - split a file name into dir/base/suffix/member
+ */
+
+void
+path_parse(
+ char *file,
+ PATHNAME *f )
+{
+ char *p, *q;
+ char *end;
+
+ memset( (char *)f, 0, sizeof( *f ) );
+
+ /* Look for <grist> */
+
+ if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
+ {
+ f->f_grist.ptr = file;
+ f->f_grist.len = p - file;
+ file = p + 1;
+ }
+
+ /* Look for dev:[dir] or dev: */
+
+ if( ( p = strchr( file, ']' ) ) || ( p = strchr( file, ':' ) ) )
+ {
+ f->f_dir.ptr = file;
+ f->f_dir.len = p + 1 - file;
+ file = p + 1;
+ }
+
+ end = file + strlen( file );
+
+ /* Look for (member) */
+
+ if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
+ {
+ f->f_member.ptr = p + 1;
+ f->f_member.len = end - p - 2;
+ end = p;
+ }
+
+ /* Look for .suffix */
+ /* This would be memrchr() */
+
+ p = 0;
+ q = file;
+
+ while( q = (char *)memchr( q, '.', end - q ) )
+ p = q++;
+
+ if( p )
+ {
+ f->f_suffix.ptr = p;
+ f->f_suffix.len = end - p;
+ end = p;
+ }
+
+ /* Leaves base */
+
+ f->f_base.ptr = file;
+ f->f_base.len = end - file;
+
+ /* Is this a directory without a file spec? */
+
+ f->parent = 0;
+}
+
+/*
+ * dir mods result
+ * --- --- ------
+ * Rerooting:
+ *
+ * (none) :R=dev: dev:
+ * devd: :R=dev: devd:
+ * devd:[dir] :R=dev: devd:[dir]
+ * [.dir] :R=dev: dev:[dir] questionable
+ * [dir] :R=dev: dev:[dir]
+ *
+ * (none) :R=[rdir] [rdir] questionable
+ * devd: :R=[rdir] devd:
+ * devd:[dir] :R=[rdir] devd:[dir]
+ * [.dir] :R=[rdir] [rdir.dir] questionable
+ * [dir] :R=[rdir] [rdir]
+ *
+ * (none) :R=dev:[root] dev:[root]
+ * devd: :R=dev:[root] devd:
+ * devd:[dir] :R=dev:[root] devd:[dir]
+ * [.dir] :R=dev:[root] dev:[root.dir]
+ * [dir] :R=dev:[root] [dir]
+ *
+ * Climbing to parent:
+ *
+ */
+
+# define DIR_EMPTY 0 /* empty string */
+# define DIR_DEV 1 /* dev: */
+# define DIR_DEVDIR 2 /* dev:[dir] */
+# define DIR_DOTDIR 3 /* [.dir] */
+# define DIR_DASHDIR 4 /* [-] or [-.dir] */
+# define DIR_ABSDIR 5 /* [dir] */
+# define DIR_ROOT 6 /* [000000] or dev:[000000] */
+
+# define G_DIR 0 /* take just dir */
+# define G_ROOT 1 /* take just root */
+# define G_VAD 2 /* root's dev: + [abs] */
+# define G_DRD 3 /* root's dev:[dir] + [.rel] */
+# define G_VRD 4 /* root's dev: + [.rel] made [abs] */
+# define G_DDD 5 /* root's dev:[dir] + . + [dir] */
+
+static int grid[7][7] = {
+
+/* root/dir EMPTY DEV DEVDIR DOTDIR DASH, ABSDIR ROOT */
+/* EMPTY */ G_DIR, G_DIR, G_DIR, G_DIR, G_DIR, G_DIR, G_DIR,
+/* DEV */ G_ROOT, G_DIR, G_DIR, G_VRD, G_VAD, G_VAD, G_VAD,
+/* DEVDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_VAD, G_VAD, G_VAD,
+/* DOTDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DIR, G_DIR, G_DIR,
+/* DASHDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DDD, G_DIR, G_DIR,
+/* ABSDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DIR, G_DIR, G_DIR,
+/* ROOT */ G_ROOT, G_DIR, G_DIR, G_VRD, G_DIR, G_DIR, G_DIR,
+
+} ;
+
+struct dirinf {
+ int flags;
+
+ struct {
+ char *ptr;
+ int len;
+ } dev, dir;
+} ;
+
+static char *
+strnchr(
+ char *buf,
+ int c,
+ int len )
+{
+ while( len-- )
+ if( *buf && *buf++ == c )
+ return buf - 1;
+
+ return 0;
+}
+
+static void
+dir_flags(
+ char *buf,
+ int len,
+ struct dirinf *i )
+{
+ char *p;
+
+ if( !buf || !len )
+ {
+ i->flags = DIR_EMPTY;
+ i->dev.ptr =
+ i->dir.ptr = 0;
+ i->dev.len =
+ i->dir.len = 0;
+ }
+ else if( p = strnchr( buf, ':', len ) )
+ {
+ i->dev.ptr = buf;
+ i->dev.len = p + 1 - buf;
+ i->dir.ptr = buf + i->dev.len;
+ i->dir.len = len - i->dev.len;
+ i->flags = i->dir.len && *i->dir.ptr == '[' ? DIR_DEVDIR : DIR_DEV;
+ }
+ else
+ {
+ i->dev.ptr = buf;
+ i->dev.len = 0;
+ i->dir.ptr = buf;
+ i->dir.len = len;
+
+ if( *buf == '[' && buf[1] == ']' )
+ i->flags = DIR_EMPTY;
+ else if( *buf == '[' && buf[1] == '.' )
+ i->flags = DIR_DOTDIR;
+ else if( *buf == '[' && buf[1] == '-' )
+ i->flags = DIR_DASHDIR;
+ else
+ i->flags = DIR_ABSDIR;
+ }
+
+ /* But if its rooted in any way */
+
+ if( i->dir.len == 8 && !strncmp( i->dir.ptr, "[000000]", 8 ) )
+ i->flags = DIR_ROOT;
+}
+
+/*
+ * path_build() - build a filename given dir/base/suffix/member
+ */
+
+void
+path_build(
+ PATHNAME *f,
+ string *file,
+ int binding )
+{
+ struct dirinf root, dir;
+ int g;
+
+ file_build1( f, file );
+
+ /* Get info on root and dir for combining. */
+
+ dir_flags( f->f_root.ptr, f->f_root.len, &root );
+ dir_flags( f->f_dir.ptr, f->f_dir.len, &dir );
+
+ /* Combine */
+
+ switch( g = grid[ root.flags ][ dir.flags ] )
+ {
+ case G_DIR:
+ /* take dir */
+ string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
+ break;
+
+ case G_ROOT:
+ /* take root */
+ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
+ break;
+
+ case G_VAD:
+ /* root's dev + abs directory */
+ string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len );
+ string_append_range( file, dir.dir.ptr, dir.dir.ptr + dir.dir.len );
+ break;
+
+ case G_DRD:
+ case G_DDD:
+ /* root's dev:[dir] + rel directory */
+ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
+
+ /* sanity checks: root ends with ] */
+
+ if( file->value[file->size - 1] == ']' )
+ string_pop_back( file );
+
+ /* Add . if separating two -'s */
+
+ if( g == G_DDD )
+ string_push_back( file, '.' );
+
+ /* skip [ of dir */
+ string_append_range( file, dir.dir.ptr + 1, dir.dir.ptr + 1 + dir.dir.len - 1 );
+ break;
+
+ case G_VRD:
+ /* root's dev + rel directory made abs */
+ string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len );
+ string_push_back( file, '[' );
+ /* skip [. of rel dir */
+ string_append_range( file, dir.dir.ptr + 2, dir.dir.ptr + 2 + dir.dir.len - 2 );
+ break;
+ }
+
+# ifdef DEBUG
+ if( DEBUG_SEARCH && ( root.flags || dir.flags ) )
+ {
+ printf( "%d x %d = %d (%s)\n", root.flags, dir.flags,
+ grid[ root.flags ][ dir.flags ], file->value );
+ }
+# endif
+
+ /*
+ * Now do the special :P modifier when no file was present.
+ * (none) (none)
+ * [dir1.dir2] [dir1]
+ * [dir] [000000]
+ * [.dir] (none)
+ * [] []
+ */
+
+ if( file->value[file->size - 1] == ']' && f->parent )
+ {
+ char* p = file->value + file->size;
+ while( p-- > file->value )
+ {
+ if( *p == '.' )
+ {
+ /* If we've truncated everything and left with '[',
+ return empty string. */
+ if (p == file->value + 1)
+ string_truncate( file, 0 );
+ else {
+ string_truncate( file, p - file->value );
+ string_push_back( file, ']' );
+ }
+ break;
+ }
+ else if( *p == '-' )
+ {
+ /* handle .- or - */
+ if( p > file->value && p[-1] == '.' )
+ --p;
+
+ *p++ = ']';
+ break;
+ }
+ else if( *p == '[' )
+ {
+ if( p[1] == ']' )
+ {
+ /* CONSIDER: I don't see any use of this code. We immediately
+ break, and 'p' is a local variable. */
+ p += 2;
+ }
+ else
+ {
+ string_truncate( file, p - file->value );
+ string_append( file, "[000000]" );
+ }
+ break;
+ }
+ }
+ }
+
+ /* Now copy the file pieces. */
+
+ if( f->f_base.len )
+ {
+ string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
+ }
+
+ /* If there is no suffix, we append a "." onto all generated */
+ /* names. This keeps VMS from appending its own (wrong) idea */
+ /* of what the suffix should be. */
+
+ if( f->f_suffix.len )
+ {
+ string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
+ }
+ else if( binding && f->f_base.len )
+ {
+ string_push_back( file, '.' );
+ }
+
+ if( f->f_member.len )
+ {
+ string_push_back( file, '(' );
+ string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len );
+ string_push_back( file, ')' );
+ }
+
+# ifdef DEBUG
+ if( DEBUG_SEARCH )
+ printf("built %.*s + %.*s / %.*s suf %.*s mem %.*s -> %s\n",
+ f->f_root.len, f->f_root.ptr,
+ f->f_dir.len, f->f_dir.ptr,
+ f->f_base.len, f->f_base.ptr,
+ f->f_suffix.len, f->f_suffix.ptr,
+ f->f_member.len, f->f_member.ptr,
+ file->value );
+# endif
+}
+
+/*
+ * path_parent() - make a PATHNAME point to its parent dir
+ */
+
+void
+path_parent( PATHNAME *f )
+{
+ if( f->f_base.len )
+ {
+ f->f_base.ptr =
+ f->f_suffix.ptr =
+ f->f_member.ptr = "";
+
+ f->f_base.len =
+ f->f_suffix.len =
+ f->f_member.len = 0;
+ }
+ else
+ {
+ f->parent = 1;
+ }
+}
+
+# endif /* VMS */
Added: boost-jam/boost-build/branches/upstream/current/jam_src/pwd.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/pwd.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/pwd.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,44 @@
+/* Copyright Vladimir Prus 2002. 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) */
+
+#include "jam.h"
+#include "lists.h"
+#include "newstr.h"
+#include "pathsys.h"
+
+#include <limits.h>
+
+/* MinGW on windows declares PATH_MAX in limits.h */
+#if defined(NT) && ! defined(__GNUC__)
+#include <direct.h>
+#define PATH_MAX _MAX_PATH
+#else
+#include <limits.h>
+#include <unistd.h>
+#if defined(__COMO__)
+ #include <linux/limits.h>
+#endif
+#endif
+
+
+
+LIST*
+pwd(void)
+{
+ char buffer[PATH_MAX];
+ if (getcwd(buffer, sizeof(buffer)) == NULL)
+ {
+ perror("can not get current directory");
+ return L0;
+ }
+ else
+ {
+#ifdef NT
+ return list_new(L0, short_path_to_long_path(buffer));
+#else
+ return list_new(L0, newstr(buffer));
+#endif
+ }
+}
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/pwd.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/pwd.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/pwd.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,10 @@
+/* Copyright Vladimir Prus 2002. 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) */
+
+#ifndef PWD_H
+#define PWD_H
+
+LIST* pwd(void);
+
+#endif
Added: boost-jam/boost-build/branches/upstream/current/jam_src/regexp.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/regexp.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/regexp.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,1317 @@
+/*
+ * regcomp and regexec -- regsub and regerror are elsewhere
+ *
+ * Copyright (c) 1986 by University of Toronto.
+ * Written by Henry Spencer. Not derived from licensed software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose on any computer system, and to redistribute it freely,
+ * subject to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of
+ * this software, no matter how awful, even if they arise
+ * from defects in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either
+ * by explicit claim or by omission.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore,
+ *** hoptoad!gnu, on 27 Dec 1986, to add \n as an alternative to |
+ *** to assist in implementing egrep.
+ *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore,
+ *** hoptoad!gnu, on 27 Dec 1986, to add \< and \> for word-matching
+ *** as in BSD grep and ex.
+ *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore,
+ *** hoptoad!gnu, on 28 Dec 1986, to optimize characters quoted with \.
+ *** THIS IS AN ALTERED VERSION. It was altered by James A. Woods,
+ *** ames!jaw, on 19 June 1987, to quash a regcomp() redundancy.
+ *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald
+ *** seiwald at vix.com, on 28 August 1993, for use in jam. Regmagic.h
+ *** was moved into regexp.h, and the include of regexp.h now uses "'s
+ *** to avoid conflicting with the system regexp.h. Const, bless its
+ *** soul, was removed so it can compile everywhere. The declaration
+ *** of strchr() was in conflict on AIX, so it was removed (as it is
+ *** happily defined in string.h).
+ *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald
+ *** seiwald at perforce.com, on 20 January 2000, to use function prototypes.
+ *
+ * Beware that some of this code is subtly aware of the way operator
+ * precedence is structured in regular expressions. Serious changes in
+ * regular-expression syntax might require a total rethink.
+ */
+#include "regexp.h"
+#include <stdio.h>
+#include <ctype.h>
+#ifndef ultrix
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+/*
+ * The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases. They are:
+ *
+ * regstart char that must begin a match; '\0' if none obvious
+ * reganch is the match anchored (at beginning-of-line only)?
+ * regmust string (pointer into program) that match must include, or NULL
+ * regmlen length of regmust string
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot. Regmust permits fast rejection
+ * of lines that cannot possibly match. The regmust tests are costly enough
+ * that regcomp() supplies a regmust only if the r.e. contains something
+ * potentially expensive (at present, the only such thing detected is * or +
+ * at the start of the r.e., which can involve a lot of backup). Regmlen is
+ * supplied because the test in regexec() needs it and regcomp() is computing
+ * it anyway.
+ */
+
+/*
+ * Structure for regexp "program". This is essentially a linear encoding
+ * of a nondeterministic finite-state machine (aka syntax charts or
+ * "railroad normal form" in parsing technology). Each node is an opcode
+ * plus a "next" pointer, possibly plus an operand. "Next" pointers of
+ * all nodes except BRANCH implement concatenation; a "next" pointer with
+ * a BRANCH on both ends of it is connecting two alternatives. (Here we
+ * have one of the subtle syntax dependencies: an individual BRANCH (as
+ * opposed to a collection of them) is never concatenated with anything
+ * because of operator precedence.) The operand of some types of node is
+ * a literal string; for others, it is a node leading into a sub-FSM. In
+ * particular, the operand of a BRANCH node is the first node of the branch.
+ * (NB this is *not* a tree structure: the tail of the branch connects
+ * to the thing following the set of BRANCHes.) The opcodes are:
+ */
+
+/* definition number opnd? meaning */
+#define END 0 /* no End of program. */
+#define BOL 1 /* no Match "" at beginning of line. */
+#define EOL 2 /* no Match "" at end of line. */
+#define ANY 3 /* no Match any one character. */
+#define ANYOF 4 /* str Match any character in this string. */
+#define ANYBUT 5 /* str Match any character not in this string. */
+#define BRANCH 6 /* node Match this alternative, or the next... */
+#define BACK 7 /* no Match "", "next" ptr points backward. */
+#define EXACTLY 8 /* str Match this string. */
+#define NOTHING 9 /* no Match empty string. */
+#define STAR 10 /* node Match this (simple) thing 0 or more times. */
+#define PLUS 11 /* node Match this (simple) thing 1 or more times. */
+#define WORDA 12 /* no Match "" at wordchar, where prev is nonword */
+#define WORDZ 13 /* no Match "" at nonwordchar, where prev is word */
+#define OPEN 20 /* no Mark this point in input as start of #n. */
+ /* OPEN+1 is number 1, etc. */
+#define CLOSE 30 /* no Analogous to OPEN. */
+
+/*
+ * Opcode notes:
+ *
+ * BRANCH The set of branches constituting a single choice are hooked
+ * together with their "next" pointers, since precedence prevents
+ * anything being concatenated to any individual branch. The
+ * "next" pointer of the last BRANCH in a choice points to the
+ * thing following the whole choice. This is also where the
+ * final "next" pointer of each individual branch points; each
+ * branch starts with the operand node of a BRANCH node.
+ *
+ * BACK Normal "next" pointers all implicitly point forward; BACK
+ * exists to make loop structures possible.
+ *
+ * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
+ * BRANCH structures using BACK. Simple cases (one character
+ * per match) are implemented with STAR and PLUS for speed
+ * and to minimize recursive plunges.
+ *
+ * OPEN,CLOSE ...are numbered at compile time.
+ */
+
+/*
+ * A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit pieces, high order first. The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node. (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+#define OP(p) (*(p))
+#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+#define OPERAND(p) ((p) + 3)
+
+/*
+ * See regmagic.h for one further detail of program structure.
+ */
+
+
+/*
+ * Utility definitions.
+ */
+#ifndef CHARBITS
+#define UCHARAT(p) ((int)*(unsigned char *)(p))
+#else
+#define UCHARAT(p) ((int)*(p)&CHARBITS)
+#endif
+
+#define FAIL(m) { regerror(m); return(NULL); }
+#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
+
+/*
+ * Flags to be passed up and down.
+ */
+#define HASWIDTH 01 /* Known never to match null string. */
+#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
+#define SPSTART 04 /* Starts with * or +. */
+#define WORST 0 /* Worst case. */
+
+/*
+ * Global work variables for regcomp().
+ */
+static char *regparse; /* Input-scan pointer. */
+static int regnpar; /* () count. */
+static char regdummy;
+static char *regcode; /* Code-emit pointer; ®dummy = don't. */
+static long regsize; /* Code size. */
+
+/*
+ * Forward declarations for regcomp()'s friends.
+ */
+#ifndef STATIC
+#define STATIC static
+#endif
+STATIC char *reg( int paren, int *flagp );
+STATIC char *regbranch( int *flagp );
+STATIC char *regpiece( int *flagp );
+STATIC char *regatom( int *flagp );
+STATIC char *regnode( int op );
+STATIC char *regnext( register char *p );
+STATIC void regc( int b );
+STATIC void reginsert( char op, char *opnd );
+STATIC void regtail( char *p, char *val );
+STATIC void regoptail( char *p, char *val );
+#ifdef STRCSPN
+STATIC int strcspn();
+#endif
+
+/*
+ - regcomp - compile a regular expression into internal code
+ *
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code. So we cheat: we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it. (Note that it has to be in
+ * one piece because free() must be able to free it all.)
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ */
+regexp *
+regcomp( char *exp )
+{
+ register regexp *r;
+ register char *scan;
+ register char *longest;
+ register unsigned len;
+ int flags;
+
+ if (exp == NULL)
+ FAIL("NULL argument");
+
+ /* First pass: determine size, legality. */
+#ifdef notdef
+ if (exp[0] == '.' && exp[1] == '*') exp += 2; /* aid grep */
+#endif
+ regparse = (char *)exp;
+ regnpar = 1;
+ regsize = 0L;
+ regcode = ®dummy;
+ regc(MAGIC);
+ if (reg(0, &flags) == NULL)
+ return(NULL);
+
+ /* Small enough for pointer-storage convention? */
+ if (regsize >= 32767L) /* Probably could be 65535L. */
+ FAIL("regexp too big");
+
+ /* Allocate space. */
+ r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
+ if (r == NULL)
+ FAIL("out of space");
+
+ /* Second pass: emit code. */
+ regparse = (char *)exp;
+ regnpar = 1;
+ regcode = r->program;
+ regc(MAGIC);
+ if (reg(0, &flags) == NULL)
+ return(NULL);
+
+ /* Dig out information for optimizations. */
+ r->regstart = '\0'; /* Worst-case defaults. */
+ r->reganch = 0;
+ r->regmust = NULL;
+ r->regmlen = 0;
+ scan = r->program+1; /* First BRANCH. */
+ if (OP(regnext(scan)) == END) { /* Only one top-level choice. */
+ scan = OPERAND(scan);
+
+ /* Starting-point info. */
+ if (OP(scan) == EXACTLY)
+ r->regstart = *OPERAND(scan);
+ else if (OP(scan) == BOL)
+ r->reganch++;
+
+ /*
+ * If there's something expensive in the r.e., find the
+ * longest literal string that must appear and make it the
+ * regmust. Resolve ties in favor of later strings, since
+ * the regstart check works with the beginning of the r.e.
+ * and avoiding duplication strengthens checking. Not a
+ * strong reason, but sufficient in the absence of others.
+ */
+ if (flags&SPSTART) {
+ longest = NULL;
+ len = 0;
+ for (; scan != NULL; scan = regnext(scan))
+ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
+ longest = OPERAND(scan);
+ len = strlen(OPERAND(scan));
+ }
+ r->regmust = longest;
+ r->regmlen = len;
+ }
+ }
+
+ return(r);
+}
+
+/*
+ - reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+static char *
+reg(
+ int paren, /* Parenthesized? */
+ int *flagp )
+{
+ register char *ret;
+ register char *br;
+ register char *ender;
+ register int parno;
+ int flags;
+
+ *flagp = HASWIDTH; /* Tentatively. */
+
+ /* Make an OPEN node, if parenthesized. */
+ if (paren) {
+ if (regnpar >= NSUBEXP)
+ FAIL("too many ()");
+ parno = regnpar;
+ regnpar++;
+ ret = regnode(OPEN+parno);
+ } else
+ ret = NULL;
+
+ /* Pick up the branches, linking them together. */
+ br = regbranch(&flags);
+ if (br == NULL)
+ return(NULL);
+ if (ret != NULL)
+ regtail(ret, br); /* OPEN -> first. */
+ else
+ ret = br;
+ if (!(flags&HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags&SPSTART;
+ while (*regparse == '|' || *regparse == '\n') {
+ regparse++;
+ br = regbranch(&flags);
+ if (br == NULL)
+ return(NULL);
+ regtail(ret, br); /* BRANCH -> BRANCH. */
+ if (!(flags&HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags&SPSTART;
+ }
+
+ /* Make a closing node, and hook it on the end. */
+ ender = regnode((paren) ? CLOSE+parno : END);
+ regtail(ret, ender);
+
+ /* Hook the tails of the branches to the closing node. */
+ for (br = ret; br != NULL; br = regnext(br))
+ regoptail(br, ender);
+
+ /* Check for proper termination. */
+ if (paren && *regparse++ != ')') {
+ FAIL("unmatched ()");
+ } else if (!paren && *regparse != '\0') {
+ if (*regparse == ')') {
+ FAIL("unmatched ()");
+ } else
+ FAIL("junk on end"); /* "Can't happen". */
+ /* NOTREACHED */
+ }
+
+ return(ret);
+}
+
+/*
+ - regbranch - one alternative of an | operator
+ *
+ * Implements the concatenation operator.
+ */
+static char *
+regbranch( int *flagp )
+{
+ register char *ret;
+ register char *chain;
+ register char *latest;
+ int flags;
+
+ *flagp = WORST; /* Tentatively. */
+
+ ret = regnode(BRANCH);
+ chain = NULL;
+ while (*regparse != '\0' && *regparse != ')' &&
+ *regparse != '\n' && *regparse != '|') {
+ latest = regpiece(&flags);
+ if (latest == NULL)
+ return(NULL);
+ *flagp |= flags&HASWIDTH;
+ if (chain == NULL) /* First piece. */
+ *flagp |= flags&SPSTART;
+ else
+ regtail(chain, latest);
+ chain = latest;
+ }
+ if (chain == NULL) /* Loop ran zero times. */
+ (void) regnode(NOTHING);
+
+ return(ret);
+}
+
+/*
+ - regpiece - something followed by possible [*+?]
+ *
+ * Note that the branching code sequences used for ? and the general cases
+ * of * and + are somewhat optimized: they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+static char *
+regpiece( int *flagp )
+{
+ register char *ret;
+ register char op;
+ register char *next;
+ int flags;
+
+ ret = regatom(&flags);
+ if (ret == NULL)
+ return(NULL);
+
+ op = *regparse;
+ if (!ISMULT(op)) {
+ *flagp = flags;
+ return(ret);
+ }
+
+ if (!(flags&HASWIDTH) && op != '?')
+ FAIL("*+ operand could be empty");
+ *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+
+ if (op == '*' && (flags&SIMPLE))
+ reginsert(STAR, ret);
+ else if (op == '*') {
+ /* Emit x* as (x&|), where & means "self". */
+ reginsert(BRANCH, ret); /* Either x */
+ regoptail(ret, regnode(BACK)); /* and loop */
+ regoptail(ret, ret); /* back */
+ regtail(ret, regnode(BRANCH)); /* or */
+ regtail(ret, regnode(NOTHING)); /* null. */
+ } else if (op == '+' && (flags&SIMPLE))
+ reginsert(PLUS, ret);
+ else if (op == '+') {
+ /* Emit x+ as x(&|), where & means "self". */
+ next = regnode(BRANCH); /* Either */
+ regtail(ret, next);
+ regtail(regnode(BACK), ret); /* loop back */
+ regtail(next, regnode(BRANCH)); /* or */
+ regtail(ret, regnode(NOTHING)); /* null. */
+ } else if (op == '?') {
+ /* Emit x? as (x|) */
+ reginsert(BRANCH, ret); /* Either x */
+ regtail(ret, regnode(BRANCH)); /* or */
+ next = regnode(NOTHING); /* null. */
+ regtail(ret, next);
+ regoptail(ret, next);
+ }
+ regparse++;
+ if (ISMULT(*regparse))
+ FAIL("nested *?+");
+
+ return(ret);
+}
+
+/*
+ - regatom - the lowest level
+ *
+ * Optimization: gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run. Backslashed characters are exceptions, each becoming a
+ * separate node; the code is simpler that way and it's not worth fixing.
+ */
+static char *
+regatom( int *flagp )
+{
+ register char *ret;
+ int flags;
+
+ *flagp = WORST; /* Tentatively. */
+
+ switch (*regparse++) {
+ /* FIXME: these chars only have meaning at beg/end of pat? */
+ case '^':
+ ret = regnode(BOL);
+ break;
+ case '$':
+ ret = regnode(EOL);
+ break;
+ case '.':
+ ret = regnode(ANY);
+ *flagp |= HASWIDTH|SIMPLE;
+ break;
+ case '[': {
+ register int classr;
+ register int classend;
+
+ if (*regparse == '^') { /* Complement of range. */
+ ret = regnode(ANYBUT);
+ regparse++;
+ } else
+ ret = regnode(ANYOF);
+ if (*regparse == ']' || *regparse == '-')
+ regc(*regparse++);
+ while (*regparse != '\0' && *regparse != ']') {
+ if (*regparse == '-') {
+ regparse++;
+ if (*regparse == ']' || *regparse == '\0')
+ regc('-');
+ else {
+ classr = UCHARAT(regparse-2)+1;
+ classend = UCHARAT(regparse);
+ if (classr > classend+1)
+ FAIL("invalid [] range");
+ for (; classr <= classend; classr++)
+ regc(classr);
+ regparse++;
+ }
+ } else
+ regc(*regparse++);
+ }
+ regc('\0');
+ if (*regparse != ']')
+ FAIL("unmatched []");
+ regparse++;
+ *flagp |= HASWIDTH|SIMPLE;
+ }
+ break;
+ case '(':
+ ret = reg(1, &flags);
+ if (ret == NULL)
+ return(NULL);
+ *flagp |= flags&(HASWIDTH|SPSTART);
+ break;
+ case '\0':
+ case '|':
+ case '\n':
+ case ')':
+ FAIL("internal urp"); /* Supposed to be caught earlier. */
+ break;
+ case '?':
+ case '+':
+ case '*':
+ FAIL("?+* follows nothing");
+ break;
+ case '\\':
+ switch (*regparse++) {
+ case '\0':
+ FAIL("trailing \\");
+ break;
+ case '<':
+ ret = regnode(WORDA);
+ break;
+ case '>':
+ ret = regnode(WORDZ);
+ break;
+ /* FIXME: Someday handle \1, \2, ... */
+ default:
+ /* Handle general quoted chars in exact-match routine */
+ goto de_fault;
+ }
+ break;
+ de_fault:
+ default:
+ /*
+ * Encode a string of characters to be matched exactly.
+ *
+ * This is a bit tricky due to quoted chars and due to
+ * '*', '+', and '?' taking the SINGLE char previous
+ * as their operand.
+ *
+ * On entry, the char at regparse[-1] is going to go
+ * into the string, no matter what it is. (It could be
+ * following a \ if we are entered from the '\' case.)
+ *
+ * Basic idea is to pick up a good char in ch and
+ * examine the next char. If it's *+? then we twiddle.
+ * If it's \ then we frozzle. If it's other magic char
+ * we push ch and terminate the string. If none of the
+ * above, we push ch on the string and go around again.
+ *
+ * regprev is used to remember where "the current char"
+ * starts in the string, if due to a *+? we need to back
+ * up and put the current char in a separate, 1-char, string.
+ * When regprev is NULL, ch is the only char in the
+ * string; this is used in *+? handling, and in setting
+ * flags |= SIMPLE at the end.
+ */
+ {
+ char *regprev;
+ register char ch;
+
+ regparse--; /* Look at cur char */
+ ret = regnode(EXACTLY);
+ for ( regprev = 0 ; ; ) {
+ ch = *regparse++; /* Get current char */
+ switch (*regparse) { /* look at next one */
+
+ default:
+ regc(ch); /* Add cur to string */
+ break;
+
+ case '.': case '[': case '(':
+ case ')': case '|': case '\n':
+ case '$': case '^':
+ case '\0':
+ /* FIXME, $ and ^ should not always be magic */
+ magic:
+ regc(ch); /* dump cur char */
+ goto done; /* and we are done */
+
+ case '?': case '+': case '*':
+ if (!regprev) /* If just ch in str, */
+ goto magic; /* use it */
+ /* End mult-char string one early */
+ regparse = regprev; /* Back up parse */
+ goto done;
+
+ case '\\':
+ regc(ch); /* Cur char OK */
+ switch (regparse[1]){ /* Look after \ */
+ case '\0':
+ case '<':
+ case '>':
+ /* FIXME: Someday handle \1, \2, ... */
+ goto done; /* Not quoted */
+ default:
+ /* Backup point is \, scan * point is after it. */
+ regprev = regparse;
+ regparse++;
+ continue; /* NOT break; */
+ }
+ }
+ regprev = regparse; /* Set backup point */
+ }
+ done:
+ regc('\0');
+ *flagp |= HASWIDTH;
+ if (!regprev) /* One char? */
+ *flagp |= SIMPLE;
+ }
+ break;
+ }
+
+ return(ret);
+}
+
+/*
+ - regnode - emit a node
+ */
+static char * /* Location. */
+regnode( int op )
+{
+ register char *ret;
+ register char *ptr;
+
+ ret = regcode;
+ if (ret == ®dummy) {
+ regsize += 3;
+ return(ret);
+ }
+
+ ptr = ret;
+ *ptr++ = op;
+ *ptr++ = '\0'; /* Null "next" pointer. */
+ *ptr++ = '\0';
+ regcode = ptr;
+
+ return(ret);
+}
+
+/*
+ - regc - emit (if appropriate) a byte of code
+ */
+static void
+regc( int b )
+{
+ if (regcode != ®dummy)
+ *regcode++ = b;
+ else
+ regsize++;
+}
+
+/*
+ - reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+static void
+reginsert(
+ char op,
+ char *opnd )
+{
+ register char *src;
+ register char *dst;
+ register char *place;
+
+ if (regcode == ®dummy) {
+ regsize += 3;
+ return;
+ }
+
+ src = regcode;
+ regcode += 3;
+ dst = regcode;
+ while (src > opnd)
+ *--dst = *--src;
+
+ place = opnd; /* Op node, where operand used to be. */
+ *place++ = op;
+ *place++ = '\0';
+ *place++ = '\0';
+}
+
+/*
+ - regtail - set the next-pointer at the end of a node chain
+ */
+static void
+regtail(
+ char *p,
+ char *val )
+{
+ register char *scan;
+ register char *temp;
+ register int offset;
+
+ if (p == ®dummy)
+ return;
+
+ /* Find last node. */
+ scan = p;
+ for (;;) {
+ temp = regnext(scan);
+ if (temp == NULL)
+ break;
+ scan = temp;
+ }
+
+ if (OP(scan) == BACK)
+ offset = scan - val;
+ else
+ offset = val - scan;
+ *(scan+1) = (offset>>8)&0377;
+ *(scan+2) = offset&0377;
+}
+
+/*
+ - regoptail - regtail on operand of first argument; nop if operandless
+ */
+
+static void
+regoptail(
+ char *p,
+ char *val )
+{
+ /* "Operandless" and "op != BRANCH" are synonymous in practice. */
+ if (p == NULL || p == ®dummy || OP(p) != BRANCH)
+ return;
+ regtail(OPERAND(p), val);
+}
+
+/*
+ * regexec and friends
+ */
+
+/*
+ * Global work variables for regexec().
+ */
+static char *reginput; /* String-input pointer. */
+static char *regbol; /* Beginning of input, for ^ check. */
+static char **regstartp; /* Pointer to startp array. */
+static char **regendp; /* Ditto for endp. */
+
+/*
+ * Forwards.
+ */
+STATIC int regtry( regexp *prog, char *string );
+STATIC int regmatch( char *prog );
+STATIC int regrepeat( char *p );
+
+#ifdef DEBUG
+int regnarrate = 0;
+void regdump();
+STATIC char *regprop();
+#endif
+
+/*
+ - regexec - match a regexp against a string
+ */
+int
+regexec(
+ register regexp *prog,
+ register char *string )
+{
+ register char *s;
+
+ /* Be paranoid... */
+ if (prog == NULL || string == NULL) {
+ regerror("NULL parameter");
+ return(0);
+ }
+
+ /* Check validity of program. */
+ if (UCHARAT(prog->program) != MAGIC) {
+ regerror("corrupted program");
+ return(0);
+ }
+
+ /* If there is a "must appear" string, look for it. */
+ if (prog->regmust != NULL) {
+ s = (char *)string;
+ while ((s = strchr(s, prog->regmust[0])) != NULL) {
+ if (strncmp(s, prog->regmust, prog->regmlen) == 0)
+ break; /* Found it. */
+ s++;
+ }
+ if (s == NULL) /* Not present. */
+ return(0);
+ }
+
+ /* Mark beginning of line for ^ . */
+ regbol = (char *)string;
+
+ /* Simplest case: anchored match need be tried only once. */
+ if (prog->reganch)
+ return(regtry(prog, string));
+
+ /* Messy cases: unanchored match. */
+ s = (char *)string;
+ if (prog->regstart != '\0')
+ /* We know what char it must start with. */
+ while ((s = strchr(s, prog->regstart)) != NULL) {
+ if (regtry(prog, s))
+ return(1);
+ s++;
+ }
+ else
+ /* We don't -- general case. */
+ do {
+ if (regtry(prog, s))
+ return(1);
+ } while (*s++ != '\0');
+
+ /* Failure. */
+ return(0);
+}
+
+/*
+ - regtry - try match at specific point
+ */
+static int /* 0 failure, 1 success */
+regtry(
+ regexp *prog,
+ char *string )
+{
+ register int i;
+ register char **sp;
+ register char **ep;
+
+ reginput = string;
+ regstartp = prog->startp;
+ regendp = prog->endp;
+
+ sp = prog->startp;
+ ep = prog->endp;
+ for (i = NSUBEXP; i > 0; i--) {
+ *sp++ = NULL;
+ *ep++ = NULL;
+ }
+ if (regmatch(prog->program + 1)) {
+ prog->startp[0] = string;
+ prog->endp[0] = reginput;
+ return(1);
+ } else
+ return(0);
+}
+
+/*
+ - regmatch - main matching routine
+ *
+ * Conceptually the strategy is simple: check to see whether the current
+ * node matches, call self recursively to see whether the rest matches,
+ * and then act accordingly. In practice we make some effort to avoid
+ * recursion, in particular by going through "ordinary" nodes (that don't
+ * need to know whether the rest of the match failed) by a loop instead of
+ * by recursion.
+ */
+static int /* 0 failure, 1 success */
+regmatch( char *prog )
+{
+ register char *scan; /* Current node. */
+ char *next; /* Next node. */
+
+ scan = prog;
+#ifdef DEBUG
+ if (scan != NULL && regnarrate)
+ fprintf(stderr, "%s(\n", regprop(scan));
+#endif
+ while (scan != NULL) {
+#ifdef DEBUG
+ if (regnarrate)
+ fprintf(stderr, "%s...\n", regprop(scan));
+#endif
+ next = regnext(scan);
+
+ switch (OP(scan)) {
+ case BOL:
+ if (reginput != regbol)
+ return(0);
+ break;
+ case EOL:
+ if (*reginput != '\0')
+ return(0);
+ break;
+ case WORDA:
+ /* Must be looking at a letter, digit, or _ */
+ if ((!isalnum(*reginput)) && *reginput != '_')
+ return(0);
+ /* Prev must be BOL or nonword */
+ if (reginput > regbol &&
+ (isalnum(reginput[-1]) || reginput[-1] == '_'))
+ return(0);
+ break;
+ case WORDZ:
+ /* Must be looking at non letter, digit, or _ */
+ if (isalnum(*reginput) || *reginput == '_')
+ return(0);
+ /* We don't care what the previous char was */
+ break;
+ case ANY:
+ if (*reginput == '\0')
+ return(0);
+ reginput++;
+ break;
+ case EXACTLY: {
+ register int len;
+ register char *opnd;
+
+ opnd = OPERAND(scan);
+ /* Inline the first character, for speed. */
+ if (*opnd != *reginput)
+ return(0);
+ len = strlen(opnd);
+ if (len > 1 && strncmp(opnd, reginput, len) != 0)
+ return(0);
+ reginput += len;
+ }
+ break;
+ case ANYOF:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
+ return(0);
+ reginput++;
+ break;
+ case ANYBUT:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
+ return(0);
+ reginput++;
+ break;
+ case NOTHING:
+ break;
+ case BACK:
+ break;
+ case OPEN+1:
+ case OPEN+2:
+ case OPEN+3:
+ case OPEN+4:
+ case OPEN+5:
+ case OPEN+6:
+ case OPEN+7:
+ case OPEN+8:
+ case OPEN+9: {
+ register int no;
+ register char *save;
+
+ no = OP(scan) - OPEN;
+ save = reginput;
+
+ if (regmatch(next)) {
+ /*
+ * Don't set startp if some later
+ * invocation of the same parentheses
+ * already has.
+ */
+ if (regstartp[no] == NULL)
+ regstartp[no] = save;
+ return(1);
+ } else
+ return(0);
+ }
+ break;
+ case CLOSE+1:
+ case CLOSE+2:
+ case CLOSE+3:
+ case CLOSE+4:
+ case CLOSE+5:
+ case CLOSE+6:
+ case CLOSE+7:
+ case CLOSE+8:
+ case CLOSE+9: {
+ register int no;
+ register char *save;
+
+ no = OP(scan) - CLOSE;
+ save = reginput;
+
+ if (regmatch(next)) {
+ /*
+ * Don't set endp if some later
+ * invocation of the same parentheses
+ * already has.
+ */
+ if (regendp[no] == NULL)
+ regendp[no] = save;
+ return(1);
+ } else
+ return(0);
+ }
+ break;
+ case BRANCH: {
+ register char *save;
+
+ if (OP(next) != BRANCH) /* No choice. */
+ next = OPERAND(scan); /* Avoid recursion. */
+ else {
+ do {
+ save = reginput;
+ if (regmatch(OPERAND(scan)))
+ return(1);
+ reginput = save;
+ scan = regnext(scan);
+ } while (scan != NULL && OP(scan) == BRANCH);
+ return(0);
+ /* NOTREACHED */
+ }
+ }
+ break;
+ case STAR:
+ case PLUS: {
+ register char nextch;
+ register int no;
+ register char *save;
+ register int min;
+
+ /*
+ * Lookahead to avoid useless match attempts
+ * when we know what character comes next.
+ */
+ nextch = '\0';
+ if (OP(next) == EXACTLY)
+ nextch = *OPERAND(next);
+ min = (OP(scan) == STAR) ? 0 : 1;
+ save = reginput;
+ no = regrepeat(OPERAND(scan));
+ while (no >= min) {
+ /* If it could work, try it. */
+ if (nextch == '\0' || *reginput == nextch)
+ if (regmatch(next))
+ return(1);
+ /* Couldn't or didn't -- back up. */
+ no--;
+ reginput = save + no;
+ }
+ return(0);
+ }
+ break;
+ case END:
+ return(1); /* Success! */
+ break;
+ default:
+ regerror("memory corruption");
+ return(0);
+ break;
+ }
+
+ scan = next;
+ }
+
+ /*
+ * We get here only if there's trouble -- normally "case END" is
+ * the terminating point.
+ */
+ regerror("corrupted pointers");
+ return(0);
+}
+
+/*
+ - regrepeat - repeatedly match something simple, report how many
+ */
+static int
+regrepeat( char *p )
+{
+ register int count = 0;
+ register char *scan;
+ register char *opnd;
+
+ scan = reginput;
+ opnd = OPERAND(p);
+ switch (OP(p)) {
+ case ANY:
+ count = strlen(scan);
+ scan += count;
+ break;
+ case EXACTLY:
+ while (*opnd == *scan) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYOF:
+ while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYBUT:
+ while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
+ count++;
+ scan++;
+ }
+ break;
+ default: /* Oh dear. Called inappropriately. */
+ regerror("internal foulup");
+ count = 0; /* Best compromise. */
+ break;
+ }
+ reginput = scan;
+
+ return(count);
+}
+
+/*
+ - regnext - dig the "next" pointer out of a node
+ */
+static char *
+regnext( register char *p )
+{
+ register int offset;
+
+ if (p == ®dummy)
+ return(NULL);
+
+ offset = NEXT(p);
+ if (offset == 0)
+ return(NULL);
+
+ if (OP(p) == BACK)
+ return(p-offset);
+ else
+ return(p+offset);
+}
+
+#ifdef DEBUG
+
+STATIC char *regprop();
+
+/*
+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
+ */
+void
+regdump( regexp *r )
+{
+ register char *s;
+ register char op = EXACTLY; /* Arbitrary non-END op. */
+ register char *next;
+
+
+ s = r->program + 1;
+ while (op != END) { /* While that wasn't END last time... */
+ op = OP(s);
+ printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */
+ next = regnext(s);
+ if (next == NULL) /* Next ptr. */
+ printf("(0)");
+ else
+ printf("(%d)", (s-r->program)+(next-s));
+ s += 3;
+ if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
+ /* Literal string, where present. */
+ while (*s != '\0') {
+ putchar(*s);
+ s++;
+ }
+ s++;
+ }
+ putchar('\n');
+ }
+
+ /* Header fields of interest. */
+ if (r->regstart != '\0')
+ printf("start `%c' ", r->regstart);
+ if (r->reganch)
+ printf("anchored ");
+ if (r->regmust != NULL)
+ printf("must have \"%s\"", r->regmust);
+ printf("\n");
+}
+
+/*
+ - regprop - printable representation of opcode
+ */
+static char *
+regprop( char *op )
+{
+ register char *p;
+ static char buf[50];
+
+ (void) strcpy(buf, ":");
+
+ switch (OP(op)) {
+ case BOL:
+ p = "BOL";
+ break;
+ case EOL:
+ p = "EOL";
+ break;
+ case ANY:
+ p = "ANY";
+ break;
+ case ANYOF:
+ p = "ANYOF";
+ break;
+ case ANYBUT:
+ p = "ANYBUT";
+ break;
+ case BRANCH:
+ p = "BRANCH";
+ break;
+ case EXACTLY:
+ p = "EXACTLY";
+ break;
+ case NOTHING:
+ p = "NOTHING";
+ break;
+ case BACK:
+ p = "BACK";
+ break;
+ case END:
+ p = "END";
+ break;
+ case OPEN+1:
+ case OPEN+2:
+ case OPEN+3:
+ case OPEN+4:
+ case OPEN+5:
+ case OPEN+6:
+ case OPEN+7:
+ case OPEN+8:
+ case OPEN+9:
+ sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
+ p = NULL;
+ break;
+ case CLOSE+1:
+ case CLOSE+2:
+ case CLOSE+3:
+ case CLOSE+4:
+ case CLOSE+5:
+ case CLOSE+6:
+ case CLOSE+7:
+ case CLOSE+8:
+ case CLOSE+9:
+ sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
+ p = NULL;
+ break;
+ case STAR:
+ p = "STAR";
+ break;
+ case PLUS:
+ p = "PLUS";
+ break;
+ case WORDA:
+ p = "WORDA";
+ break;
+ case WORDZ:
+ p = "WORDZ";
+ break;
+ default:
+ regerror("corrupted opcode");
+ break;
+ }
+ if (p != NULL)
+ (void) strcat(buf, p);
+ return(buf);
+}
+#endif
+
+/*
+ * The following is provided for those people who do not have strcspn() in
+ * their C libraries. They should get off their butts and do something
+ * about it; at least one public-domain implementation of those (highly
+ * useful) string routines has been published on Usenet.
+ */
+#ifdef STRCSPN
+/*
+ * strcspn - find length of initial segment of s1 consisting entirely
+ * of characters not from s2
+ */
+
+static int
+strcspn(
+ char *s1,
+ char *s2 )
+{
+ register char *scan1;
+ register char *scan2;
+ register int count;
+
+ count = 0;
+ for (scan1 = s1; *scan1 != '\0'; scan1++) {
+ for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */
+ if (*scan1 == *scan2++)
+ return(count);
+ count++;
+ }
+ return(count);
+}
+#endif
Added: boost-jam/boost-build/branches/upstream/current/jam_src/regexp.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/regexp.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/regexp.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,32 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+#ifndef REGEXP_DWA20011023_H
+# define REGEXP_DWA20011023_H
+
+#define NSUBEXP 10
+typedef struct regexp {
+ char *startp[NSUBEXP];
+ char *endp[NSUBEXP];
+ char regstart; /* Internal use only. */
+ char reganch; /* Internal use only. */
+ char *regmust; /* Internal use only. */
+ int regmlen; /* Internal use only. */
+ char program[1]; /* Unwarranted chumminess with compiler. */
+} regexp;
+
+regexp *regcomp( char *exp );
+int regexec( regexp *prog, char *string );
+void regerror( char *s );
+
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define MAGIC 0234
+
+#endif
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/rules.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/rules.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/rules.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,782 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "parse.h"
+# include "variable.h"
+# include "rules.h"
+# include "newstr.h"
+# include "hash.h"
+# include "modules.h"
+# include "search.h"
+# include "lists.h"
+# include "pathsys.h"
+# include "timestamp.h"
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * rules.c - access to RULEs, TARGETs, and ACTIONs
+ *
+ * External routines:
+ *
+ * bindrule() - return pointer to RULE, creating it if necessary
+ * bindtarget() - return pointer to TARGET, creating it if necessary
+ * touchtarget() - mark a target to simulate being new
+ * targetlist() - turn list of target names into a TARGET chain
+ * targetentry() - add a TARGET to a chain of TARGETS
+ * actionlist() - append to an ACTION chain
+ * addsettings() - add a deferred "set" command to a target
+#ifndef OPT_FIX_TARGET_VARIABLES_EXT
+ * usesettings() - set all target specific variables
+#endif
+ * pushsettings() - set all target specific variables
+ * popsettings() - reset target specific variables to their pre-push values
+ * freesettings() - delete a settings list
+ * donerules() - free RULE and TARGET tables
+ *
+ * 04/12/94 (seiwald) - actionlist() now just appends a single action.
+ * 08/23/94 (seiwald) - Support for '+=' (append to variable)
+ */
+
+static void set_rule_actions( RULE* rule, rule_actions* actions );
+static void set_rule_body( RULE* rule, argument_list* args, PARSE* procedure );
+static struct hash *targethash = 0;
+
+typedef struct _located_target LOCATED_TARGET ;
+
+struct _located_target {
+ char* file_name;
+ TARGET* target;
+};
+static struct hash *located_targets = 0;
+
+
+
+
+/*
+ * enter_rule() - return pointer to RULE, creating it if necessary in
+ * target_module.
+ */
+static RULE *
+enter_rule( char *rulename, module_t *target_module )
+{
+ RULE rule, *r = &rule;
+
+ r->name = rulename;
+
+ if ( hashenter( demand_rules( target_module ), (HASHDATA **)&r ) )
+ {
+ r->name = newstr( rulename ); /* never freed */
+ r->procedure = (PARSE *)0;
+ r->module = 0;
+ r->actions = 0;
+ r->arguments = 0;
+ r->exported = 0;
+ r->module = target_module;
+ }
+ return r;
+}
+
+/*
+ * define_rule() - return pointer to RULE, creating it if necessary in
+ * target_module. Prepare it to accept a body or action originating in
+ * src_module.
+ */
+static RULE *
+define_rule( module_t *src_module, char *rulename, module_t *target_module )
+{
+ RULE *r = enter_rule( rulename, target_module );
+
+ if ( r->module != src_module ) /* if the rule was imported from elsewhere, clear it now */
+ {
+ set_rule_body( r, 0, 0 );
+ set_rule_actions( r, 0 );
+ r->module = src_module; /* r will be executed in the source module */
+ }
+
+ return r;
+}
+
+void
+rule_free( RULE* r )
+{
+ freestr( r->name );
+ r->name = "";
+ parse_free( r->procedure );
+ r->procedure = 0;
+ if ( r->arguments )
+ args_free( r->arguments );
+ r->arguments = 0;
+ if ( r->actions )
+ actions_free( r->actions );
+ r->actions = 0;
+}
+
+/*
+ * bindtarget() - return pointer to TARGET, creating it if necessary
+ */
+
+TARGET *
+bindtarget( const char *targetname )
+{
+ TARGET target, *t = ⌖
+
+ if( !targethash )
+ targethash = hashinit( sizeof( TARGET ), "targets" );
+
+ /* Perforce added const everywhere. No time to merge that change. */
+ t->name = (char*)targetname;
+
+ if( hashenter( targethash, (HASHDATA **)&t ) )
+ {
+ memset( (char *)t, '\0', sizeof( *t ) );
+ t->name = newstr( (char*)targetname ); /* never freed */
+ t->boundname = t->name; /* default for T_FLAG_NOTFILE */
+ }
+
+ return t;
+}
+
+
+static void bind_explicitly_located_target(void* xtarget, void* data)
+{
+ TARGET* t = (TARGET*)xtarget;
+ if (! (t->flags & T_FLAG_NOTFILE) )
+ {
+ /* Check if there's a setting for LOCATE */
+ SETTINGS* s = t->settings;
+ for(; s ; s = s->next)
+ {
+ if (strcmp(s->symbol, "LOCATE") == 0)
+ {
+ pushsettings(t->settings);
+ /* We're binding a target with explicit LOCATE. So
+ third argument is of now use: nothing will be returned
+ through it. */
+ t->boundname = search( t->name, &t->time, 0 );
+ popsettings(t->settings);
+ break;
+ }
+ }
+ }
+}
+
+void bind_explicitly_located_targets()
+{
+ if (targethash)
+ hashenumerate(targethash, bind_explicitly_located_target, (void*)0);
+}
+
+/* TODO: this is probably not a good idea to use functions in other modules like
+ that. */
+void call_bind_rule(char* target, char* boundname);
+
+TARGET* search_for_target ( char * name, LIST* search_path )
+{
+ PATHNAME f[1];
+ string buf[1];
+ LOCATED_TARGET lt, *lta = <
+ time_t time;
+ int found = 0;
+ TARGET* result;
+
+ string_new( buf );
+
+ path_parse( name, f );
+
+ f->f_grist.ptr = 0;
+ f->f_grist.len = 0;
+
+ while( search_path )
+ {
+ f->f_root.ptr = search_path->string;
+ f->f_root.len = strlen( search_path->string );
+
+ string_truncate( buf, 0 );
+ path_build( f, buf, 1 );
+
+ lt.file_name = buf->value ;
+
+ if (! located_targets )
+ located_targets = hashinit( sizeof(LOCATED_TARGET),
+ "located targets" );
+
+
+ if ( hashcheck( located_targets, (HASHDATA **)<a ) )
+ {
+ return lta->target;
+ }
+
+ timestamp( buf->value, &time );
+ if (time)
+ {
+ found = 1;
+ break;
+ }
+
+ search_path = list_next( search_path );
+ }
+
+ if ( ! found )
+ {
+ f->f_root.ptr = 0;
+ f->f_root.len = 0;
+
+ string_truncate( buf, 0 );
+ path_build( f, buf, 1 );
+
+ timestamp( buf->value, &time );
+ }
+
+ result = bindtarget( name );
+ result->boundname = newstr( buf->value );
+ result->time = time;
+ result->binding = time ? T_BIND_EXISTS : T_BIND_MISSING;
+
+ call_bind_rule( result->name, result->boundname );
+
+ string_free( buf );
+
+ return result;
+
+}
+
+/*
+ * copytarget() - make a new target with the old target's name
+ *
+ * Not entered into hash table -- for internal nodes.
+ */
+
+TARGET *
+copytarget( const TARGET *ot )
+{
+ TARGET *t;
+
+ t = (TARGET *)malloc( sizeof( *t ) );
+ memset( (char *)t, '\0', sizeof( *t ) );
+ t->name = copystr( ot->name );
+ t->boundname = t->name;
+
+ t->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL;
+
+ return t;
+}
+
+/*
+ * touchtarget() - mark a target to simulate being new
+ */
+
+void
+touchtarget( char *t )
+{
+ bindtarget( t )->flags |= T_FLAG_TOUCHED;
+}
+
+/*
+ * targetlist() - turn list of target names into a TARGET chain
+ *
+ * Inputs:
+ * chain existing TARGETS to append to
+ * targets list of target names
+ */
+
+TARGETS *
+targetlist(
+ TARGETS *chain,
+ LIST *targets )
+{
+ for( ; targets; targets = list_next( targets ) )
+ chain = targetentry( chain, bindtarget( targets->string ) );
+
+ return chain;
+}
+
+/*
+ * targetentry() - add a TARGET to a chain of TARGETS
+ *
+ * Inputs:
+ * chain exisitng TARGETS to append to
+ * target new target to append
+ */
+
+TARGETS *
+targetentry(
+ TARGETS *chain,
+ TARGET *target )
+{
+ TARGETS *c;
+
+ c = (TARGETS *)malloc( sizeof( TARGETS ) );
+ c->target = target;
+
+ if( !chain ) chain = c;
+ else chain->tail->next = c;
+ chain->tail = c;
+ c->next = 0;
+
+ return chain;
+}
+
+/*
+ * targetchain() - append two TARGET chains
+ *
+ * Inputs:
+ * chain exisitng TARGETS to append to
+ * target new target to append
+ */
+
+TARGETS *
+targetchain(
+ TARGETS *chain,
+ TARGETS *targets )
+{
+ TARGETS *c;
+
+ if( !targets )
+ return chain;
+ else if( !chain )
+ return targets;
+
+ chain->tail->next = targets;
+ chain->tail = targets->tail;
+
+ return chain;
+}
+
+/*
+ * actionlist() - append to an ACTION chain
+ */
+
+ACTIONS *
+actionlist(
+ ACTIONS *chain,
+ ACTION *action )
+{
+ ACTIONS *actions = (ACTIONS *)malloc( sizeof( ACTIONS ) );
+
+ actions->action = action;
+
+ if( !chain ) chain = actions;
+ else chain->tail->next = actions;
+ chain->tail = actions;
+ actions->next = 0;
+
+ return chain;
+}
+
+static SETTINGS* settings_freelist;
+
+/*
+ * addsettings() - add a deferred "set" command to a target
+ *
+ * Adds a variable setting (varname=list) onto a chain of settings
+ * for a particular target. Replaces the previous previous value,
+ * if any, unless 'append' says to append the new list onto the old.
+ * Returns the head of the chain of settings.
+ */
+
+SETTINGS *
+addsettings(
+ SETTINGS *head,
+ int append,
+ char *symbol,
+ LIST *value )
+{
+ SETTINGS *v;
+
+ /* Look for previous setting */
+
+ for( v = head; v; v = v->next )
+ if( !strcmp( v->symbol, symbol ) )
+ break;
+
+ /* If not previously set, alloc a new. */
+ /* If appending, do so. */
+ /* Else free old and set new. */
+
+ if( !v )
+ {
+ v = settings_freelist;
+
+ if ( v )
+ settings_freelist = v->next;
+ else
+ v = (SETTINGS *)malloc( sizeof( *v ) );
+
+ v->symbol = newstr( symbol );
+ v->value = value;
+ v->next = head;
+ head = v;
+ }
+ else if( append )
+ {
+ v->value = list_append( v->value, value );
+ }
+ else
+ {
+ list_free( v->value );
+ v->value = value;
+ }
+
+ /* Return (new) head of list. */
+
+ return head;
+}
+
+/*
+ * pushsettings() - set all target specific variables
+ */
+
+void
+pushsettings( SETTINGS *v )
+{
+ for( ; v; v = v->next )
+ v->value = var_swap( v->symbol, v->value );
+}
+
+/*
+ * popsettings() - reset target specific variables to their pre-push values
+ */
+
+void
+popsettings( SETTINGS *v )
+{
+ pushsettings( v ); /* just swap again */
+}
+
+/*
+ * copysettings() - duplicate a settings list, returning the new copy
+ */
+SETTINGS*
+copysettings( SETTINGS *head )
+{
+ SETTINGS *copy = 0, *v;
+
+ for (v = head; v; v = v->next)
+ copy = addsettings(copy, 0, v->symbol, list_copy(0, v->value));
+
+ return copy;
+}
+
+/*
+ * freetargets() - delete a targets list
+ */
+void freetargets( TARGETS *chain )
+{
+ while( chain )
+ {
+ TARGETS* n = chain->next;
+ free( chain );
+ chain = n;
+ }
+}
+
+/*
+ * freeactions() - delete an action list
+ */
+void freeactions( ACTIONS *chain )
+{
+ while( chain )
+ {
+ ACTIONS* n = chain->next;
+ free( chain );
+ chain = n;
+ }
+}
+
+
+/*
+ * freesettings() - delete a settings list
+ */
+
+void
+freesettings( SETTINGS *v )
+{
+ while( v )
+ {
+ SETTINGS *n = v->next;
+
+ freestr( v->symbol );
+ list_free( v->value );
+ v->next = settings_freelist;
+ settings_freelist = v;
+
+ v = n;
+ }
+}
+
+static void freetarget( void *xt, void *data )
+{
+ TARGET* t = (TARGET *)xt;
+ if ( t->settings )
+ freesettings( t->settings );
+ if ( t->depends )
+ freetargets( t->depends );
+ if ( t->includes )
+ freetarget( t->includes, (void*)0);
+ if ( t->actions )
+ freeactions( t->actions );
+}
+
+/*
+ * donerules() - free TARGET tables
+ */
+
+void
+donerules()
+{
+ hashenumerate( targethash, freetarget, 0 );
+ hashdone( targethash );
+ while ( settings_freelist )
+ {
+ SETTINGS* n = settings_freelist->next;
+ free( settings_freelist );
+ settings_freelist = n;
+ }
+}
+
+/*
+ * args_new() - make a new reference-counted argument list
+ */
+argument_list* args_new()
+{
+ argument_list* r = (argument_list*)malloc( sizeof(argument_list) );
+ r->reference_count = 0;
+ lol_init(r->data);
+ return r;
+}
+
+/*
+ * args_refer() - add a new reference to the given argument list
+ */
+void args_refer( argument_list* a )
+{
+ ++a->reference_count;
+}
+
+/*
+ * args_free() - release a reference to the given argument list
+ */
+void args_free( argument_list* a )
+{
+ if (--a->reference_count <= 0)
+ {
+ lol_free(a->data);
+ free(a);
+ }
+}
+
+/*
+ * actions_refer() - add a new reference to the given actions
+ */
+void actions_refer(rule_actions* a)
+{
+ ++a->reference_count;
+}
+
+/*
+ * actions_free() - release a reference to the given actions
+ */
+void actions_free(rule_actions* a)
+{
+ if (--a->reference_count <= 0)
+ {
+ freestr(a->command);
+ list_free(a->bindlist);
+ free(a);
+ }
+}
+
+/*
+ * set_rule_body() - set the argument list and procedure of the given rule
+ */
+static void set_rule_body( RULE* rule, argument_list* args, PARSE* procedure )
+{
+ if ( args )
+ args_refer( args );
+ if ( rule->arguments )
+ args_free( rule->arguments );
+ rule->arguments = args;
+
+ if ( procedure )
+ parse_refer( procedure );
+ if ( rule->procedure )
+ parse_free( rule->procedure );
+ rule->procedure = procedure;
+}
+
+/*
+ * global_name() - given a rule, return the name for a corresponding rule in the global module
+ */
+static char* global_rule_name( RULE* r )
+{
+ if ( r->module == root_module() )
+ {
+ return r->name;
+ }
+ else
+ {
+ char name[4096] = "";
+ strncat(name, r->module->name, sizeof(name) - 1);
+ strncat(name, r->name, sizeof(name) - 1 );
+ return newstr(name);
+ }
+}
+
+/*
+ * global_rule() - given a rule, produce the corresponding entry in the global module
+ */
+static RULE* global_rule( RULE* r )
+{
+ if ( r->module == root_module() )
+ {
+ return r;
+ }
+ else
+ {
+ char* name = global_rule_name( r );
+ RULE* result = define_rule( r->module, name, root_module() );
+ freestr(name);
+ return result;
+ }
+}
+
+/*
+ * new_rule_body() - make a new rule named rulename in the given
+ * module, with the given argument list and procedure. If exported is
+ * true, the rule is exported to the global module as
+ * modulename.rulename.
+ */
+RULE* new_rule_body( module_t* m, char* rulename, argument_list* args, PARSE* procedure, int exported )
+{
+ RULE* local = define_rule( m, rulename, m );
+ local->exported = exported;
+ set_rule_body( local, args, procedure );
+
+ /* Mark the procedure with the global rule name, regardless of
+ * whether the rule is exported. That gives us something
+ * reasonably identifiable that we can use, e.g. in profiling
+ * output. Only do this once, since this could be called multiple
+ * times with the same procedure.
+ */
+ if ( procedure->rulename == 0 )
+ procedure->rulename = global_rule_name( local );
+
+ return local;
+}
+
+static void set_rule_actions( RULE* rule, rule_actions* actions )
+{
+ if ( actions )
+ actions_refer( actions );
+ if ( rule->actions )
+ actions_free( rule->actions );
+ rule->actions = actions;
+
+}
+
+static rule_actions* actions_new( char* command, LIST* bindlist, int flags )
+{
+ rule_actions* result = (rule_actions*)malloc(sizeof(rule_actions));
+ result->command = copystr( command );
+ result->bindlist = bindlist;
+ result->flags = flags;
+ result->reference_count = 0;
+ return result;
+}
+
+RULE* new_rule_actions( module_t* m, char* rulename, char* command, LIST* bindlist, int flags )
+{
+ RULE* local = define_rule( m, rulename, m );
+ RULE* global = global_rule( local );
+ set_rule_actions( local, actions_new( command, bindlist, flags ) );
+ set_rule_actions( global, local->actions );
+ return local;
+}
+
+/* Looks for a rule in the specified module, and returns it, if found.
+ First checks if the rule is present in the module's rule table.
+ Second, if name of the rule is in the form name1.name2 and name1 is in
+ the list of imported modules, look in module 'name1' for rule 'name2'.
+*/
+RULE *lookup_rule( char *rulename, module_t *m, int local_only )
+{
+ RULE rule, *r = &rule, *result = 0;
+ module_t* original_module = m;
+ r->name = rulename;
+
+ if (m->class_module)
+ m = m->class_module;
+
+ if (m->rules && hashcheck( m->rules, (HASHDATA **)&r ) )
+ result = r;
+ else if (!local_only && m->imported_modules) {
+ /* Try splitting the name into module and rule. */
+ char *p = strchr(r->name, '.') ;
+ if (p) {
+ *p = '\0';
+ /* Now, r->name keeps the module name, and p+1 keeps the rule name. */
+ if (hashcheck( m->imported_modules, (HASHDATA **)&r))
+ {
+ result = lookup_rule(p+1, bindmodule(rulename), 1);
+ }
+ *p = '.';
+ }
+ }
+
+ if (result)
+ {
+ if (local_only && !result->exported)
+ result = 0;
+ else
+ {
+ /* Lookup started in class module. We've found a rule in class module,
+ which is marked for execution in that module, or in some instances.
+ Mark it for execution in the instance where we've started lookup.
+ */
+ int execute_in_class = (result->module == m);
+ int execute_in_some_instance =
+ (result->module->class_module && result->module->class_module == m);
+ if (original_module != m && (execute_in_class || execute_in_some_instance))
+ result->module = original_module;
+ }
+ }
+
+ return result;
+
+}
+
+
+RULE *bindrule( char *rulename, module_t* m)
+{
+ RULE *result;
+
+ result = lookup_rule(rulename, m, 0);
+ if (!result)
+ result = lookup_rule(rulename, root_module(), 0);
+ /* We've only one caller, 'evaluate_rule', which will complain about
+ calling underfined rule. We could issue the error
+ here, but we don't have necessary information, such as frame.
+ */
+ if (!result)
+ result = enter_rule( rulename, root_module() );
+
+ return result;
+}
+
+RULE* import_rule( RULE* source, module_t* m, char* name )
+{
+ RULE* dest = define_rule( source->module, name, m );
+ set_rule_body( dest, source->arguments, source->procedure );
+ set_rule_actions( dest, source->actions );
+ return dest;
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/rules.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/rules.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/rules.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,255 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef RULES_DWA_20011020_H
+# define RULES_DWA_20011020_H
+
+# include "modules.h"
+# include "jam.h"
+# include "parse.h"
+
+/*
+ * rules.h - targets, rules, and related information
+ *
+ * This file describes the structures holding the targets, rules, and
+ * related information accumulated by interpreting the statements
+ * of the jam files.
+ *
+ * The following are defined:
+ *
+ * RULE - a generic jam rule, the product of RULE and ACTIONS
+ * ACTIONS - a chain of ACTIONs
+ * ACTION - a RULE instance with targets and sources
+ * SETTINGS - variables to set when executing a TARGET's ACTIONS
+ * TARGETS - a chain of TARGETs
+ * TARGET - a file or "thing" that can be built
+ *
+ * 04/11/94 (seiwald) - Combined deps & headers into deps[2] in TARGET.
+ * 04/12/94 (seiwald) - actionlist() now just appends a single action.
+ * 06/01/94 (seiwald) - new 'actions existing' does existing sources
+ * 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
+ * 01/19/95 (seiwald) - split DONTKNOW into CANTFIND/CANTMAKE.
+ * 02/02/95 (seiwald) - new LEAVES modifier on targets.
+ * 02/14/95 (seiwald) - new NOUPDATE modifier on targets.
+ */
+
+typedef struct _rule RULE;
+typedef struct _target TARGET;
+typedef struct _targets TARGETS;
+typedef struct _action ACTION;
+typedef struct _actions ACTIONS;
+typedef struct _settings SETTINGS ;
+
+/* RULE - a generic jam rule, the product of RULE and ACTIONS */
+
+/* A rule's argument list */
+struct argument_list
+{
+ int reference_count;
+ LOL data[1];
+};
+
+/* The build actions corresponding to a rule */
+struct rule_actions
+{
+ int reference_count;
+ char* command; /* command string from ACTIONS */
+ LIST* bindlist;
+ int flags; /* modifiers on ACTIONS */
+
+# define RULE_NEWSRCS 0x01 /* $(>) is updated sources only */
+# define RULE_TOGETHER 0x02 /* combine actions on single target */
+# define RULE_IGNORE 0x04 /* ignore return status of executes */
+# define RULE_QUIETLY 0x08 /* don't mention it unless verbose */
+# define RULE_PIECEMEAL 0x10 /* split exec so each $(>) is small */
+# define RULE_EXISTING 0x20 /* $(>) is pre-exisitng sources only */
+};
+
+typedef struct rule_actions rule_actions;
+typedef struct argument_list argument_list;
+
+struct _rule {
+ char *name;
+ PARSE *procedure; /* parse tree from RULE */
+ argument_list* arguments; /* argument checking info, or NULL for unchecked */
+ rule_actions* actions; /* build actions, or NULL for no actions */
+ module_t *module; /* module in which this rule is executed */
+ int exported; /* nonzero if this rule is supposed to
+ * appear in the global module and be
+ * automatically imported into other modules
+ */
+};
+
+/* ACTIONS - a chain of ACTIONs */
+
+struct _actions {
+ ACTIONS *next;
+ ACTIONS *tail; /* valid only for head */
+ ACTION *action;
+} ;
+
+/* ACTION - a RULE instance with targets and sources */
+
+struct _action {
+ RULE *rule;
+ TARGETS *targets;
+ TARGETS *sources; /* aka $(>) */
+ char running; /* has been started */
+ char status; /* see TARGET status */
+} ;
+
+/* SETTINGS - variables to set when executing a TARGET's ACTIONS */
+
+struct _settings {
+ SETTINGS *next;
+ char *symbol; /* symbol name for var_set() */
+ LIST *value; /* symbol value for var_set() */
+} ;
+
+/* TARGETS - a chain of TARGETs */
+
+struct _targets {
+ TARGETS *next;
+ TARGETS *tail; /* valid only for head */
+ TARGET *target;
+} ;
+
+/* TARGET - a file or "thing" that can be built */
+
+struct _target {
+ char *name;
+ char *boundname; /* if search() relocates target */
+ ACTIONS *actions; /* rules to execute, if any */
+ SETTINGS *settings; /* variables to define */
+
+ short flags; /* status info */
+
+# define T_FLAG_TEMP 0x0001 /* TEMPORARY applied */
+# define T_FLAG_NOCARE 0x0002 /* NOCARE applied */
+# define T_FLAG_NOTFILE 0x0004 /* NOTFILE applied */
+# define T_FLAG_TOUCHED 0x0008 /* ALWAYS applied or -t target */
+# define T_FLAG_LEAVES 0x0010 /* LEAVES applied */
+# define T_FLAG_NOUPDATE 0x0020 /* NOUPDATE applied */
+# define T_FLAG_VISITED 0x0040 /* CWM: Used in debugging */
+
+/* this flag was added to support a new builtin rule named "RMBAD" */
+/* it is used to force removal of outdated targets whose dependencies
+ * fail to build */
+
+# define T_FLAG_RMOLD 0x0080 /* RMBAD applied */
+
+/* this flag was added to support a new builting rule named "FAIL_EXPECTED" */
+/* it is used to indicate that the result of running a given action should */
+/* be inverted (i.e. ok <=> fail). This is useful to launch certain test */
+/* runs from a Jamfile.. */
+/* */
+# define T_FLAG_FAIL_EXPECTED 0x0100 /* FAIL_EXPECTED applied */
+
+# define T_FLAG_INTERNAL 0x0200 /* internal INCLUDES node */
+
+
+
+#ifdef OPT_SEMAPHORE
+# define T_MAKE_SEMAPHORE 5 /* Special target type for semaphores */
+#endif
+
+
+ char binding; /* how target relates to real file */
+
+# define T_BIND_UNBOUND 0 /* a disembodied name */
+# define T_BIND_MISSING 1 /* couldn't find real file */
+#ifdef OPT_SEMAPHORE
+ TARGET *semaphore; /* used in serialization */
+#endif
+# define T_BIND_PARENTS 2 /* using parent's timestamp */
+# define T_BIND_EXISTS 3 /* real file, timestamp valid */
+
+ TARGETS *depends; /* dependencies */
+ TARGET *includes; /* includes */
+ TARGET *original_target; /* original_target->includes = this */
+ char rescanned;
+
+ time_t time; /* update time */
+ time_t leaf; /* update time of leaf sources */
+
+ char fate; /* make0()'s diagnosis */
+
+# define T_FATE_INIT 0 /* nothing done to target */
+# define T_FATE_MAKING 1 /* make0(target) on stack */
+
+# define T_FATE_STABLE 2 /* target didn't need updating */
+# define T_FATE_NEWER 3 /* target newer than parent */
+
+# define T_FATE_SPOIL 4 /* >= SPOIL rebuilds parents */
+# define T_FATE_ISTMP 4 /* unneeded temp target oddly present */
+
+# define T_FATE_BUILD 5 /* >= BUILD rebuilds target */
+# define T_FATE_TOUCHED 5 /* manually touched with -t */
+# define T_FATE_MISSING 6 /* is missing, needs updating */
+# define T_FATE_NEEDTMP 7 /* missing temp that must be rebuild */
+# define T_FATE_OUTDATED 8 /* is out of date, needs updating */
+# define T_FATE_UPDATE 9 /* deps updated, needs updating */
+
+# define T_FATE_BROKEN 10 /* >= BROKEN ruins parents */
+# define T_FATE_CANTFIND 10 /* no rules to make missing target */
+# define T_FATE_CANTMAKE 11 /* can't find dependents */
+
+ char progress; /* tracks make1() progress */
+
+# define T_MAKE_INIT 0 /* make1(target) not yet called */
+# define T_MAKE_ONSTACK 1 /* make1(target) on stack */
+# define T_MAKE_ACTIVE 2 /* make1(target) in make1b() */
+# define T_MAKE_RUNNING 3 /* make1(target) running commands */
+# define T_MAKE_DONE 4 /* make1(target) done */
+
+ char status; /* execcmd() result */
+
+ int asynccnt; /* child deps outstanding */
+ TARGETS *parents; /* used by make1() for completion */
+ char *cmds; /* type-punned command list */
+
+ char* failed;
+} ;
+
+RULE *bindrule( char *rulename, module_t* );
+
+RULE* import_rule( RULE* source, module_t* m, char* name );
+RULE* new_rule_body( module_t* m, char* rulename, argument_list* args, PARSE* procedure, int exprt );
+RULE* new_rule_actions( module_t* m, char* rulename, char* command, LIST* bindlist, int flags );
+TARGET *bindtarget( const char *targetname );
+TARGET *copytarget( const TARGET *t );
+void bind_explicitly_located_targets();
+TARGET* search_for_target( char * name, LIST* search_path );
+void touchtarget( char *t );
+TARGETS *targetlist( TARGETS *chain, LIST *targets );
+TARGETS *targetentry( TARGETS *chain, TARGET *target );
+TARGETS *targetchain( TARGETS *chain, TARGETS *targets );
+void freetargets( TARGETS *chain );
+ACTIONS *actionlist( ACTIONS *chain, ACTION *action );
+void freeactions( ACTIONS *chain );
+SETTINGS *addsettings( SETTINGS *head, int append, char *symbol, LIST *value );
+void pushsettings( SETTINGS *v );
+void popsettings( SETTINGS *v );
+SETTINGS *copysettings( SETTINGS *v );
+void freesettings( SETTINGS *v );
+void rule_free( RULE *r );
+void donerules();
+
+argument_list* args_new();
+void args_refer( argument_list* );
+void args_free( argument_list* );
+
+void actions_refer(rule_actions*);
+void actions_free(rule_actions*);
+
+#endif
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/scan.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/scan.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/scan.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,424 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "parse.h"
+# include "scan.h"
+# include "jamgram.h"
+# include "jambase.h"
+# include "newstr.h"
+
+/*
+ * scan.c - the jam yacc scanner
+ *
+ * 12/26/93 (seiwald) - bump buf in yylex to 10240 - yuk.
+ * 09/16/94 (seiwald) - check for overflows, unmatched {}'s, etc.
+ * Also handle tokens abutting EOF by remembering
+ * to return EOF now matter how many times yylex()
+ * reinvokes yyline().
+ * 02/11/95 (seiwald) - honor only punctuation keywords if SCAN_PUNCT.
+ * 07/27/95 (seiwald) - Include jamgram.h after scan.h, so that YYSTYPE is
+ * defined before Linux's yacc tries to redefine it.
+ */
+
+struct keyword {
+ char *word;
+ int type;
+} keywords[] = {
+# include "jamgramtab.h"
+ { 0, 0 }
+} ;
+
+struct include {
+ struct include *next; /* next serial include file */
+ char *string; /* pointer into current line */
+ char **strings; /* for yyfparse() -- text to parse */
+ FILE *file; /* for yyfparse() -- file being read */
+ char *fname; /* for yyfparse() -- file name */
+ int line; /* line counter for error messages */
+ char buf[ 512 ]; /* for yyfparse() -- line buffer */
+} ;
+
+static struct include *incp = 0; /* current file; head of chain */
+
+static int scanmode = SCAN_NORMAL;
+static int anyerrors = 0;
+static char *symdump( YYSTYPE *s );
+
+# define BIGGEST_TOKEN 10240 /* no single token can be larger */
+
+/*
+ * Set parser mode: normal, string, or keyword
+ */
+
+void
+yymode( int n )
+{
+ scanmode = n;
+}
+
+void
+yyerror( char *s )
+{
+ if( incp )
+ printf( "%s:%d: ", incp->fname, incp->line );
+
+ printf( "%s at %s\n", s, symdump( &yylval ) );
+
+ ++anyerrors;
+}
+
+int
+yyanyerrors()
+{
+ return anyerrors != 0;
+}
+
+void
+yyfparse( char *s )
+{
+ struct include *i = (struct include *)malloc( sizeof( *i ) );
+
+ /* Push this onto the incp chain. */
+
+ i->string = "";
+ i->strings = 0;
+ i->file = 0;
+ i->fname = copystr( s );
+ i->line = 0;
+ i->next = incp;
+ incp = i;
+
+ /* If the filename is "+", it means use the internal jambase. */
+
+ if( !strcmp( s, "+" ) )
+ i->strings = jambase;
+}
+
+/*
+ * yyline() - read new line and return first character
+ *
+ * Fabricates a continuous stream of characters across include files,
+ * returning EOF at the bitter end.
+ */
+
+int
+yyline()
+{
+ struct include *i = incp;
+
+ if( !incp )
+ return EOF;
+
+ /* Once we start reading from the input stream, we reset the */
+ /* include insertion point so that the next include file becomes */
+ /* the head of the list. */
+
+ /* If there is more data in this line, return it. */
+
+ if( *i->string )
+ return *i->string++;
+
+ /* If we're reading from an internal string list, go to the */
+ /* next string. */
+
+ if( i->strings )
+ {
+ if( !*i->strings )
+ goto next;
+
+ i->line++;
+ i->string = *(i->strings++);
+ return *i->string++;
+ }
+
+ /* If necessary, open the file */
+
+ if( !i->file )
+ {
+ FILE *f = stdin;
+
+ if( strcmp( i->fname, "-" ) && !( f = fopen( i->fname, "r" ) ) )
+ perror( i->fname );
+
+ i->file = f;
+ }
+
+ /* If there's another line in this file, start it. */
+
+ if( i->file && fgets( i->buf, sizeof( i->buf ), i->file ) )
+ {
+ i->line++;
+ i->string = i->buf;
+ return *i->string++;
+ }
+
+ next:
+ /* This include is done. */
+ /* Free it up and return EOF so yyparse() returns to parse_file(). */
+
+ incp = i->next;
+
+ /* Close file, free name */
+
+ if( i->file && i->file != stdin )
+ fclose( i->file );
+ freestr( i->fname );
+ free( (char *)i );
+
+ return EOF;
+}
+
+/*
+ * yylex() - set yylval to current token; return its type
+ *
+ * Macros to move things along:
+ *
+ * yychar() - return and advance character; invalid after EOF
+ * yyprev() - back up one character; invalid before yychar()
+ *
+ * yychar() returns a continuous stream of characters, until it hits
+ * the EOF of the current include file.
+ */
+
+# define yychar() ( *incp->string ? *incp->string++ : yyline() )
+# define yyprev() ( incp->string-- )
+
+int
+yylex()
+{
+ int c;
+ char buf[BIGGEST_TOKEN];
+ char *b = buf;
+
+ if( !incp )
+ goto eof;
+
+ /* Get first character (whitespace or of token) */
+
+ c = yychar();
+
+ if( scanmode == SCAN_STRING )
+ {
+ /* If scanning for a string (action's {}'s), look for the */
+ /* closing brace. We handle matching braces, if they match! */
+
+ int nest = 1;
+
+ while( c != EOF && b < buf + sizeof( buf ) )
+ {
+ if( c == '{' )
+ nest++;
+
+ if( c == '}' && !--nest )
+ break;
+
+ *b++ = c;
+
+ c = yychar();
+
+ /* turn trailing "\r\n" sequences into plain "\n"
+ * for Cygwin
+ */
+ if (c == '\n' && b[-1] == '\r')
+ --b;
+ }
+
+ /* We ate the ending brace -- regurgitate it. */
+
+ if( c != EOF )
+ yyprev();
+
+ /* Check obvious errors. */
+
+ if( b == buf + sizeof( buf ) )
+ {
+ yyerror( "action block too big" );
+ goto eof;
+ }
+
+ if( nest )
+ {
+ yyerror( "unmatched {} in action block" );
+ goto eof;
+ }
+
+ *b = 0;
+ yylval.type = STRING;
+ yylval.string = newstr( buf );
+ yylval.file = incp->fname;
+ yylval.line = incp->line;
+
+ }
+ else
+ {
+ char *b = buf;
+ struct keyword *k;
+ int inquote = 0;
+ int notkeyword;
+
+ /* Eat white space */
+
+ for( ;; )
+ {
+ /* Skip past white space */
+
+ while( c != EOF && isspace( c ) )
+ c = yychar();
+
+ /* Not a comment? Swallow up comment line. */
+
+ if( c != '#' )
+ break;
+ while( ( c = yychar() ) != EOF && c != '\n' )
+ ;
+ }
+
+ /* c now points to the first character of a token. */
+
+ if( c == EOF )
+ goto eof;
+
+ yylval.file = incp->fname;
+ yylval.line = incp->line;
+
+ /* While scanning the word, disqualify it for (expensive) */
+ /* keyword lookup when we can: $anything, "anything", \anything */
+
+ notkeyword = c == '$';
+
+ /* look for white space to delimit word */
+ /* "'s get stripped but preserve white space */
+ /* \ protects next character */
+
+ while(
+ c != EOF &&
+ b < buf + sizeof( buf ) &&
+ ( inquote || !isspace( c ) ) )
+ {
+ if( c == '"' )
+ {
+ /* begin or end " */
+ inquote = !inquote;
+ notkeyword = 1;
+ }
+ else if( c != '\\' )
+ {
+ /* normal char */
+ *b++ = c;
+ }
+ else if( ( c = yychar()) != EOF )
+ {
+ /* \c */
+ *b++ = c;
+ notkeyword = 1;
+ }
+ else
+ {
+ /* \EOF */
+ break;
+ }
+
+ c = yychar();
+ }
+
+ /* Check obvious errors. */
+
+ if( b == buf + sizeof( buf ) )
+ {
+ yyerror( "string too big" );
+ goto eof;
+ }
+
+ if( inquote )
+ {
+ yyerror( "unmatched \" in string" );
+ goto eof;
+ }
+
+ /* We looked ahead a character - back up. */
+
+ if( c != EOF )
+ yyprev();
+
+ /* scan token table */
+ /* don't scan if it's obviously not a keyword or if its */
+ /* an alphabetic when were looking for punctuation */
+
+ *b = 0;
+ yylval.type = ARG;
+
+ if( !notkeyword && !( isalpha( *buf ) && scanmode == SCAN_PUNCT ) )
+ {
+ for( k = keywords; k->word; k++ )
+ if( *buf == *k->word && !strcmp( k->word, buf ) )
+ {
+ yylval.type = k->type;
+ yylval.string = k->word; /* used by symdump */
+ break;
+ }
+ }
+
+ if( yylval.type == ARG )
+ yylval.string = newstr( buf );
+ }
+
+ if( DEBUG_SCAN )
+ printf( "scan %s\n", symdump( &yylval ) );
+
+ return yylval.type;
+
+eof:
+ yylval.file = "end-of-input"; /* just in case */
+ yylval.line = 0;
+
+ yylval.type = EOF;
+ return yylval.type;
+}
+
+static char *
+symdump( YYSTYPE *s )
+{
+ static char buf[ BIGGEST_TOKEN + 20 ];
+
+ switch( s->type )
+ {
+ case EOF:
+ sprintf( buf, "EOF" );
+ break;
+ case 0:
+ sprintf( buf, "unknown symbol %s", s->string );
+ break;
+ case ARG:
+ sprintf( buf, "argument %s", s->string );
+ break;
+ case STRING:
+ sprintf( buf, "string \"%s\"", s->string );
+ break;
+ default:
+ sprintf( buf, "keyword %s", s->string );
+ break;
+ }
+ return buf;
+}
+
+/* Get information about the current file and line, for those epsilon
+ * transitions that produce a parse
+ */
+void yyinput_stream( char** name, int* line )
+{
+ if (incp)
+ {
+ *name = incp->fname;
+ *line = incp->line;
+ }
+ else
+ {
+ *name = "(builtin)";
+ *line = -1;
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/scan.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/scan.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/scan.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,55 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * scan.h - the jam yacc scanner
+ *
+ * External functions:
+ *
+ * yyerror( char *s ) - print a parsing error message
+ * yyfparse( char *s ) - scan include file s
+ * yylex() - parse the next token, returning its type
+ * yymode() - adjust lexicon of scanner
+ * yyparse() - declaration for yacc parser
+ * yyanyerrors() - indicate if any parsing errors occured
+ *
+ * The yymode() function is for the parser to adjust the lexicon of the
+ * scanner. Aside from normal keyword scanning, there is a mode to
+ * handle action strings (look only for the closing }) and a mode to
+ * ignore most keywords when looking for a punctuation keyword. This
+ * allows non-punctuation keywords to be used in lists without quoting.
+ */
+
+/*
+ * YYSTYPE - value of a lexical token
+ */
+
+# define YYSTYPE YYSYMBOL
+
+typedef struct _YYSTYPE {
+ int type;
+ char *string;
+ PARSE *parse;
+ LIST *list;
+ int number;
+ char *file;
+ int line;
+} YYSTYPE;
+
+extern YYSTYPE yylval;
+
+void yymode( int n );
+void yyerror( char *s );
+int yyanyerrors();
+void yyfparse( char *s );
+int yyline();
+int yylex();
+int yyparse();
+void yyinput_stream( char** name, int* line );
+
+# define SCAN_NORMAL 0 /* normal parsing */
+# define SCAN_STRING 1 /* look only for matching } */
+# define SCAN_PUNCT 2 /* only punctuation keywords */
Added: boost-jam/boost-build/branches/upstream/current/jam_src/search.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/search.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/search.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,208 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "search.h"
+# include "timestamp.h"
+# include "pathsys.h"
+# include "variable.h"
+# include "newstr.h"
+# include "compile.h"
+# include "strings.h"
+# include "hash.h"
+# include <string.h>
+
+typedef struct _binding {
+ char* binding;
+ char* target;
+} BINDING;
+
+static struct hash *explicit_bindings = 0;
+
+void call_bind_rule(
+ char* target_,
+ char* boundname_ )
+{
+ LIST* bind_rule = var_get( "BINDRULE" );
+ if( bind_rule )
+ {
+ /* No guarantee that target is an allocated string, so be on the
+ * safe side */
+ char* target = copystr( target_ );
+
+ /* Likewise, don't rely on implementation details of newstr.c: allocate
+ * a copy of boundname */
+ char* boundname = copystr( boundname_ );
+ if( boundname && target )
+ {
+ /* Prepare the argument list */
+ FRAME frame[1];
+ frame_init( frame );
+
+ /* First argument is the target name */
+ lol_add( frame->args, list_new( L0, target ) );
+
+ lol_add( frame->args, list_new( L0, boundname ) );
+ if( lol_get( frame->args, 1 ) )
+ evaluate_rule( bind_rule->string, frame );
+
+ /* Clean up */
+ frame_free( frame );
+ }
+ else
+ {
+ if( boundname )
+ freestr( boundname );
+ if( target )
+ freestr( target );
+ }
+ }
+}
+
+/*
+ * search.c - find a target along $(SEARCH) or $(LOCATE)
+ * First, check if LOCATE is set. If so, use it to determine
+ * the location of target and return, regardless of whether anything
+ * exists on that location.
+ *
+ * Second, examine all directories in SEARCH. If there's file already
+ * or there's another target with the same name which was placed
+ * to this location via LOCATE setting, stop and return the location.
+ * In case of previous target, return it's name via the third argument.
+ *
+ * This bevahiour allow to handle dependency on generated files. If
+ * caller does not expect that target is generated, 0 can be passed as
+ * the third argument.
+ */
+
+char *
+search(
+ char *target,
+ time_t *time,
+ char **another_target
+)
+{
+ PATHNAME f[1];
+ LIST *varlist;
+ string buf[1];
+ int found = 0;
+ /* Will be set to 1 if target location is specified via LOCATE. */
+ int explicitly_located = 0;
+ char *boundname = 0;
+
+ if( another_target )
+ *another_target = 0;
+
+ if (! explicit_bindings )
+ explicit_bindings = hashinit( sizeof(BINDING),
+ "explicitly specified locations");
+
+ string_new( buf );
+ /* Parse the filename */
+
+ path_parse( target, f );
+
+ f->f_grist.ptr = 0;
+ f->f_grist.len = 0;
+
+ if( varlist = var_get( "LOCATE" ) )
+ {
+ f->f_root.ptr = varlist->string;
+ f->f_root.len = strlen( varlist->string );
+
+ path_build( f, buf, 1 );
+
+ if( DEBUG_SEARCH )
+ printf( "locate %s: %s\n", target, buf->value );
+
+ explicitly_located = 1;
+
+ timestamp( buf->value, time );
+ found = 1;
+ }
+ else if( varlist = var_get( "SEARCH" ) )
+ {
+ while( varlist )
+ {
+ BINDING b, *ba = &b;
+
+ f->f_root.ptr = varlist->string;
+ f->f_root.len = strlen( varlist->string );
+
+ string_truncate( buf, 0 );
+ path_build( f, buf, 1 );
+
+ if( DEBUG_SEARCH )
+ printf( "search %s: %s\n", target, buf->value );
+
+ timestamp( buf->value, time );
+
+ b.binding = buf->value;
+
+ if( hashcheck( explicit_bindings, (HASHDATA**)&ba ) )
+ {
+ if( DEBUG_SEARCH )
+ printf(" search %s: found explicitly located target %s\n",
+ target, ba->target);
+ if( another_target )
+ *another_target = ba->target;
+ found = 1;
+ break;
+ }
+ else if( *time )
+ {
+ found = 1;
+ break;
+ }
+
+ varlist = list_next( varlist );
+ }
+ }
+
+ if (!found)
+ {
+ /* Look for the obvious */
+ /* This is a questionable move. Should we look in the */
+ /* obvious place if SEARCH is set? */
+
+ f->f_root.ptr = 0;
+ f->f_root.len = 0;
+
+ string_truncate( buf, 0 );
+ path_build( f, buf, 1 );
+
+ if( DEBUG_SEARCH )
+ printf( "search %s: %s\n", target, buf->value );
+
+ timestamp( buf->value, time );
+ }
+
+ boundname = newstr( buf->value );
+ string_free( buf );
+
+ if (explicitly_located)
+ {
+ BINDING b, *ba = &b;
+ b.binding = boundname;
+ b.target = target;
+ /* CONSIDER: we probably should issue a warning is another file
+ is explicitly bound to the same location. This might break
+ compatibility, though. */
+ hashenter(explicit_bindings, (HASHDATA**)&ba);
+ }
+
+ /* prepare a call to BINDRULE if the variable is set */
+ call_bind_rule( target, boundname );
+
+ return boundname;
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/search.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/search.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/search.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,11 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * search.h - find a target along $(SEARCH) or $(LOCATE)
+ */
+
+char *search( char *target, time_t *time, char **another_target );
Added: boost-jam/boost-build/branches/upstream/current/jam_src/strings.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/strings.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/strings.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,191 @@
+/* Copyright David Abrahams 2004. 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) */
+
+#include "strings.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+
+
+#ifndef NDEBUG
+# define JAM_STRING_MAGIC ((char)0xcf)
+# define JAM_STRING_MAGIC_SIZE 4
+static void assert_invariants( string* self )
+{
+ int i;
+
+ assert( self->size < self->capacity );
+ assert( ( self->capacity <= sizeof(self->opt) ) == ( self->value == self->opt ) );
+ assert( strlen( self->value ) == self->size );
+
+ for (i = 0; i < 4; ++i)
+ {
+ assert( self->magic[i] == JAM_STRING_MAGIC );
+ assert( self->value[self->capacity + i] == JAM_STRING_MAGIC );
+ }
+}
+#else
+# define JAM_STRING_MAGIC_SIZE 0
+# define assert_invariants(x) do {} while (0)
+#endif
+
+void string_new( string* s )
+{
+ s->value = s->opt;
+ s->size = 0;
+ s->capacity = sizeof(s->opt);
+ s->opt[0] = 0;
+#ifndef NDEBUG
+ memset(s->magic, JAM_STRING_MAGIC, sizeof(s->magic));
+#endif
+ assert_invariants( s );
+}
+
+void string_free( string* s )
+{
+ assert_invariants( s );
+ if ( s->value != s->opt )
+ free( s->value );
+}
+
+static void string_reserve_internal( string* self, size_t capacity )
+{
+ if ( self->value == self->opt )
+ {
+ self->value = (char*)malloc( capacity + JAM_STRING_MAGIC_SIZE );
+ self->value[0] = 0;
+ strncat( self->value, self->opt, sizeof(self->opt) );
+ assert( strlen( self->value ) <= self->capacity ); /* This is a regression test */
+ }
+ else
+ {
+ self->value = (char*)realloc( self->value, capacity + JAM_STRING_MAGIC_SIZE );
+ }
+#ifndef NDEBUG
+ memcpy( self->value + capacity, self->magic, JAM_STRING_MAGIC_SIZE );
+#endif
+ self->capacity = capacity;
+}
+
+void string_reserve( string* self, size_t capacity )
+{
+ assert_invariants( self );
+ if ( capacity <= self->capacity )
+ return;
+ string_reserve_internal( self, capacity );
+ assert_invariants( self );
+}
+
+static void extend_full( string* self, char* start, char *finish )
+{
+ size_t new_size = self->capacity + ( finish - start );
+ size_t new_capacity = self->capacity;
+ size_t old_size = self->capacity;
+ while ( new_capacity < new_size + 1)
+ new_capacity <<= 1;
+ string_reserve_internal( self, new_capacity );
+ memcpy( self->value + old_size, start, new_size - old_size );
+ self->value[new_size] = 0;
+ self->size = new_size;
+}
+
+void string_append( string* self, char* rhs )
+{
+ char* p = self->value + self->size;
+ char* end = self->value + self->capacity;
+ assert_invariants( self );
+
+ while ( *rhs && p != end)
+ *p++ = *rhs++;
+
+ if ( p != end )
+ {
+ *p = 0;
+ self->size = p - self->value;
+ }
+ else
+ {
+ extend_full( self, rhs, rhs + strlen(rhs) );
+ }
+ assert_invariants( self );
+}
+
+void string_append_range( string* self, char* start, char* finish )
+{
+ char* p = self->value + self->size;
+ char* end = self->value + self->capacity;
+ assert_invariants( self );
+
+ while ( p != end && start != finish )
+ *p++ = *start++;
+
+ if ( p != end )
+ {
+ *p = 0;
+ self->size = p - self->value;
+ }
+ else
+ {
+ extend_full( self, start, finish );
+ }
+ assert_invariants( self );
+}
+
+void string_copy( string* s, char* rhs )
+{
+ string_new( s );
+ string_append( s, rhs );
+}
+
+void string_truncate( string* self, size_t n )
+{
+ assert_invariants( self );
+ assert( n <= self->capacity );
+ self->value[self->size = n] = 0;
+ assert_invariants( self );
+}
+
+void string_pop_back( string* self )
+{
+ string_truncate( self, self->size - 1 );
+}
+
+void string_push_back( string* self, char x )
+{
+ string_append_range( self, &x, &x + 1 );
+}
+
+char string_back( string* self )
+{
+ assert_invariants( self );
+ return self->value[self->size - 1];
+}
+
+#ifndef NDEBUG
+void string_unit_test()
+{
+ string s[1];
+ int i;
+ char buffer[sizeof(s->opt) * 2 + 2];
+ int limit = sizeof(buffer) > 254 ? 254 : sizeof(buffer);
+
+ string_new(s);
+
+ for (i = 0; i < limit; ++i)
+ {
+ string_push_back( s, (char)(i + 1) );
+ };
+
+ for (i = 0; i < limit; ++i)
+ {
+ assert( i < s->size );
+ assert( s->value[i] == (char)(i + 1));
+ }
+
+ string_free(s);
+
+}
+#endif
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/strings.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/strings.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/strings.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,34 @@
+#ifndef STRINGS_DWA20011024_H
+# define STRINGS_DWA20011024_H
+
+/* Copyright David Abrahams 2004. 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) */
+
+# include <stddef.h>
+
+typedef struct string
+{
+ char* value;
+ unsigned long size;
+ unsigned long capacity;
+ char opt[32];
+#ifndef NDEBUG
+ char magic[4];
+#endif
+} string;
+
+void string_new( string* );
+void string_copy( string*, char* );
+void string_free( string* );
+void string_append( string*, char* );
+void string_append_range( string*, char*, char* );
+void string_push_back( string* s, char x );
+void string_reserve( string*, size_t );
+void string_truncate( string*, size_t );
+void string_pop_back( string* );
+char string_back( string* );
+void string_unit_test();
+
+#endif
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/subst.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/subst.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/subst.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,94 @@
+#include <stddef.h>
+#include "jam.h"
+#include "regexp.h"
+#include "hash.h"
+
+#include "newstr.h"
+#include "lists.h"
+#include "parse.h"
+#include "compile.h"
+#include "frames.h"
+
+struct regex_entry
+{
+ const char* pattern;
+ regexp* regex;
+};
+typedef struct regex_entry regex_entry;
+
+static struct hash* regex_hash;
+
+regexp* regex_compile( const char* pattern )
+{
+ regex_entry entry, *e = &entry;
+ entry.pattern = pattern;
+
+ if ( !regex_hash )
+ regex_hash = hashinit(sizeof(regex_entry), "regex");
+
+ if ( hashenter( regex_hash, (HASHDATA **)&e ) )
+ e->regex = regcomp( (char*)pattern );
+
+ return e->regex;
+}
+
+LIST*
+builtin_subst(
+ PARSE *parse,
+ FRAME *frame )
+{
+ LIST* result = L0;
+ LIST* arg1 = lol_get( frame->args, 0 );
+
+ if ( arg1 && list_next(arg1) && list_next(list_next(arg1)) )
+ {
+
+ const char* source = arg1->string;
+ const char* pattern = list_next(arg1)->string;
+ regexp* repat = regex_compile( pattern );
+
+ if ( regexec( repat, (char*)source) )
+ {
+ LIST* subst = list_next(arg1);
+
+ while ((subst = list_next(subst)) != L0)
+ {
+# define BUFLEN 4096
+ char buf[BUFLEN + 1];
+ const char* in = subst->string;
+ char* out = buf;
+
+ for ( in = subst->string; *in && out < buf + BUFLEN; ++in )
+ {
+ if ( *in == '\\' || *in == '$' )
+ {
+ ++in;
+ if ( *in == 0 )
+ {
+ break;
+ }
+ else if ( *in >= '0' && *in <= '9' )
+ {
+ unsigned n = *in - '0';
+ const size_t srclen = repat->endp[n] - repat->startp[n];
+ const size_t remaining = buf + BUFLEN - out;
+ const size_t len = srclen < remaining ? srclen : remaining;
+ memcpy( out, repat->startp[n], len );
+ out += len;
+ continue;
+ }
+ /* fall through and copy the next character */
+ }
+ *out++ = *in;
+ }
+ *out = 0;
+
+ result = list_new( result, newstr( buf ) );
+#undef BUFLEN
+ }
+ }
+ }
+
+ return result;
+}
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/timestamp.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/timestamp.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/timestamp.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,227 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "hash.h"
+# include "filesys.h"
+# include "pathsys.h"
+# include "timestamp.h"
+# include "newstr.h"
+# include "strings.h"
+
+/*
+ * timestamp.c - get the timestamp of a file or archive member
+ *
+ * 09/22/00 (seiwald) - downshift names on OS2, too
+ */
+
+/*
+ * BINDING - all known files
+ */
+
+typedef struct _binding BINDING;
+
+struct _binding {
+ char *name;
+ short flags;
+
+# define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
+
+ short progress;
+
+# define BIND_INIT 0 /* never seen */
+# define BIND_NOENTRY 1 /* timestamp requested but file never found */
+# define BIND_SPOTTED 2 /* file found but not timed yet */
+# define BIND_MISSING 3 /* file found but can't get timestamp */
+# define BIND_FOUND 4 /* file found and time stamped */
+
+ time_t time; /* update time - 0 if not exist */
+} ;
+
+static struct hash *bindhash = 0;
+static void time_enter( void *, char *, int , time_t );
+
+static char *time_progress[] =
+{
+ "INIT",
+ "NOENTRY",
+ "SPOTTED",
+ "MISSING",
+ "FOUND"
+} ;
+
+
+/*
+ * timestamp() - return timestamp on a file, if present
+ */
+
+void
+timestamp(
+ char *target,
+ time_t *time )
+{
+ PATHNAME f1, f2;
+ BINDING binding, *b = &binding;
+ string buf[1];
+
+# ifdef DOWNSHIFT_PATHS
+ string path;
+ char *p;
+
+ string_copy( &path, target );
+ p = path.value;
+
+ do
+ {
+ *p = tolower( *p );
+# ifdef NT
+ /* On NT, we must use backslashes or the file won't be found. */
+ if (*p == '/')
+ *p = PATH_DELIM;
+# endif
+ }
+ while( *p++ );
+
+ target = path.value;
+# endif
+ string_new( buf );
+
+ if( !bindhash )
+ bindhash = hashinit( sizeof( BINDING ), "bindings" );
+
+ /* Quick path - is it there? */
+
+ b->name = target;
+ b->time = b->flags = 0;
+ b->progress = BIND_INIT;
+
+ if( hashenter( bindhash, (HASHDATA **)&b ) )
+ b->name = newstr( target ); /* never freed */
+
+ if( b->progress != BIND_INIT )
+ goto afterscanning;
+
+ b->progress = BIND_NOENTRY;
+
+ /* Not found - have to scan for it */
+
+ path_parse( target, &f1 );
+
+ /* Scan directory if not already done so */
+
+ {
+ BINDING binding, *b = &binding;
+
+ f2 = f1;
+ f2.f_grist.len = 0;
+ path_parent( &f2 );
+ path_build( &f2, buf, 0 );
+
+ b->name = buf->value;
+ b->time = b->flags = 0;
+ b->progress = BIND_INIT;
+
+ if( hashenter( bindhash, (HASHDATA **)&b ) )
+ b->name = newstr( buf->value ); /* never freed */
+
+ if( !( b->flags & BIND_SCANNED ) )
+ {
+ file_dirscan( buf->value, time_enter, bindhash );
+ b->flags |= BIND_SCANNED;
+ }
+ }
+
+ /* Scan archive if not already done so */
+
+ if( f1.f_member.len )
+ {
+ BINDING binding, *b = &binding;
+
+ f2 = f1;
+ f2.f_grist.len = 0;
+ f2.f_member.len = 0;
+ string_truncate( buf, 0 );
+ path_build( &f2, buf, 0 );
+
+ b->name = buf->value;
+ b->time = b->flags = 0;
+ b->progress = BIND_INIT;
+
+ if( hashenter( bindhash, (HASHDATA **)&b ) )
+ b->name = newstr( buf->value ); /* never freed */
+
+ if( !( b->flags & BIND_SCANNED ) )
+ {
+ file_archscan( buf->value, time_enter, bindhash );
+ b->flags |= BIND_SCANNED;
+ }
+ }
+
+ afterscanning:
+
+ if( b->progress == BIND_SPOTTED )
+ {
+ if( file_time( b->name, &b->time ) < 0 )
+ b->progress = BIND_MISSING;
+ else
+ b->progress = BIND_FOUND;
+ }
+
+ *time = b->progress == BIND_FOUND ? b->time : 0;
+ string_free( buf );
+# ifdef DOWNSHIFT_PATHS
+ string_free( &path );
+#endif
+}
+
+static void
+time_enter(
+ void *closure,
+ char *target,
+ int found,
+ time_t time )
+{
+ BINDING binding, *b = &binding;
+ struct hash *bindhash = (struct hash *)closure;
+
+# ifdef DOWNSHIFT_PATHS
+ char path[ MAXJPATH ];
+ char *p = path;
+
+ do *p++ = tolower( *target );
+ while( *target++ );
+
+ target = path;
+# endif
+
+ b->name = target;
+ b->flags = 0;
+
+ if( hashenter( bindhash, (HASHDATA **)&b ) )
+ b->name = newstr( target ); /* never freed */
+
+ b->time = time;
+ b->progress = found ? BIND_FOUND : BIND_SPOTTED;
+
+ if( DEBUG_BINDSCAN )
+ printf( "time ( %s ) : %s\n", target, time_progress[b->progress] );
+}
+
+/*
+ * donestamps() - free timestamp tables
+ */
+
+void
+donestamps()
+{
+ hashdone( bindhash );
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/timestamp.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/timestamp.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/timestamp.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,12 @@
+/*
+ * Copyright 1993, 1995 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * timestamp.h - get the timestamp of a file or archive member
+ */
+
+void timestamp( char *target, time_t *time );
+void donestamps();
Added: boost-jam/boost-build/branches/upstream/current/jam_src/variable.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/variable.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/variable.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,386 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+# include "jam.h"
+# include "lists.h"
+# include "parse.h"
+# include "variable.h"
+# include "expand.h"
+# include "hash.h"
+# include "filesys.h"
+# include "newstr.h"
+# include "strings.h"
+# include <stdlib.h>
+
+/*
+ * variable.c - handle jam multi-element variables
+ *
+ * External routines:
+ *
+ * var_defines() - load a bunch of variable=value settings
+ * var_string() - expand a string with variables in it
+ * var_get() - get value of a user defined symbol
+ * var_set() - set a variable in jam's user defined symbol table
+ * var_swap() - swap a variable's value with the given one
+ * var_done() - free variable tables
+ *
+ * Internal routines:
+ *
+ * var_enter() - make new var symbol table entry, returning var ptr
+ * var_dump() - dump a variable to stdout
+ *
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
+ * 08/23/94 (seiwald) - Support for '+=' (append to variable)
+ * 01/22/95 (seiwald) - split environment variables at blanks or :'s
+ * 05/10/95 (seiwald) - split path variables at SPLITPATH (not :)
+ * 09/11/00 (seiwald) - defunct var_list() removed
+ */
+
+static struct hash *varhash = 0;
+
+/*
+ * VARIABLE - a user defined multi-value variable
+ */
+
+typedef struct _variable VARIABLE ;
+
+struct _variable {
+ char *symbol;
+ LIST *value;
+} ;
+
+static VARIABLE *var_enter( char *symbol );
+static void var_dump( char *symbol, LIST *value, char *what );
+
+
+
+/*
+ * var_hash_swap() - swap all variable settings with those passed
+ *
+ * Used to implement separate settings spaces for modules
+ */
+void var_hash_swap( struct hash** new_vars )
+{
+ struct hash* old = varhash;
+ varhash = *new_vars;
+ *new_vars = old;
+}
+
+/*
+ * var_defines() - load a bunch of variable=value settings
+ *
+ * If variable name ends in PATH, split value at :'s.
+ * Otherwise, split at blanks.
+ */
+
+void
+var_defines( char **e )
+{
+ string buf[1];
+
+ string_new( buf );
+
+ for( ; *e; e++ )
+ {
+ char *val;
+
+ /* Just say "no": windows defines this in the env, */
+ /* but we don't want it to override our notion of OS. */
+
+ if( !strcmp( *e, "OS=Windows_NT" ) )
+ continue;
+
+# ifdef OS_MAC
+ /* On the mac (MPW), the var=val is actually var\0val */
+ /* Think different. */
+
+ if( ( val = strchr( *e, '=' ) ) || ( val = *e + strlen( *e ) ) )
+# else
+ if( val = strchr( *e, '=' ) )
+# endif
+ {
+ LIST *l = L0;
+ char *pp, *p;
+# ifdef OS_MAC
+ char split = ',';
+# else
+ char split = ' ';
+# endif
+ size_t len = strlen(val + 1);
+ if ( val[1] == '"' && val[len] == '"')
+ {
+ string_append_range( buf, val + 2, val + len );
+ l = list_new( l, newstr( buf->value ) );
+ string_truncate( buf, 0 );
+ }
+ else
+ {
+ /* Split *PATH at :'s, not spaces */
+
+ if( val - 4 >= *e )
+ {
+ if( !strncmp( val - 4, "PATH", 4 ) ||
+ !strncmp( val - 4, "Path", 4 ) ||
+ !strncmp( val - 4, "path", 4 ) )
+ split = SPLITPATH;
+ }
+
+ /* Do the split */
+
+ for( pp = val + 1; p = strchr( pp, split ); pp = p + 1 )
+ {
+ string_append_range( buf, pp, p );
+ l = list_new( l, newstr( buf->value ) );
+ string_truncate( buf, 0 );
+ }
+
+ l = list_new( l, newstr( pp ) );
+ }
+
+ /* Get name */
+ string_append_range( buf, *e, val );
+ var_set( buf->value, l, VAR_SET );
+ string_truncate( buf, 0 );
+ }
+ }
+ string_free( buf );
+}
+
+/*
+ * var_string() - expand a string with variables in it
+ *
+ * Copies in to out; doesn't modify targets & sources.
+ */
+
+int
+var_string(
+ char *in,
+ char *out,
+ int outsize,
+ LOL *lol )
+{
+ char *out0 = out;
+ char *oute = out + outsize - 1;
+
+ while( *in )
+ {
+ char *lastword;
+ int dollar = 0;
+
+ /* Copy white space */
+
+ while( isspace( *in ) )
+ {
+ if( out >= oute )
+ return -1;
+
+ *out++ = *in++;
+ }
+
+ lastword = out;
+
+ /* Copy non-white space, watching for variables */
+
+ while( *in && !isspace( *in ) )
+ {
+ if( out >= oute )
+ return -1;
+
+ if( in[0] == '$' && in[1] == '(' )
+ dollar++;
+
+ *out++ = *in++;
+ }
+
+ /* Add zero to 'out' so that 'lastword' is correctly zero-terminated. */
+ if (out >= oute)
+ return -1;
+ /* Don't increment, intentionally. */
+ *out= '\0';
+
+ /* If a variable encountered, expand it and and embed the */
+ /* space-separated members of the list in the output. */
+
+ if( dollar )
+ {
+ LIST *l;
+
+ l = var_expand( L0, lastword, out, lol, 0 );
+
+ out = lastword;
+
+ for( ; l; l = list_next( l ) )
+ {
+ int so = strlen( l->string );
+
+ if( out + so >= oute )
+ return -1;
+
+ strcpy( out, l->string );
+ out += so;
+ *out++ = ' ';
+ }
+
+ list_free( l );
+ }
+ }
+
+ if( out >= oute )
+ return -1;
+
+ *out++ = '\0';
+
+ return out - out0;
+}
+
+/*
+ * var_get() - get value of a user defined symbol
+ *
+ * Returns NULL if symbol unset.
+ */
+
+LIST *
+var_get( char *symbol )
+{
+ VARIABLE var, *v = &var;
+
+ v->symbol = symbol;
+
+ if( varhash && hashcheck( varhash, (HASHDATA **)&v ) )
+ {
+ if( DEBUG_VARGET )
+ var_dump( v->symbol, v->value, "get" );
+ return v->value;
+ }
+
+ return 0;
+}
+
+/*
+ * var_set() - set a variable in jam's user defined symbol table
+ *
+ * 'flag' controls the relationship between new and old values of
+ * the variable: SET replaces the old with the new; APPEND appends
+ * the new to the old; DEFAULT only uses the new if the variable
+ * was previously unset.
+ *
+ * Copies symbol. Takes ownership of value.
+ */
+
+void
+var_set(
+ char *symbol,
+ LIST *value,
+ int flag )
+{
+ VARIABLE *v = var_enter( symbol );
+
+ if( DEBUG_VARSET )
+ var_dump( symbol, value, "set" );
+
+ switch( flag )
+ {
+ case VAR_SET:
+ /* Replace value */
+ list_free( v->value );
+ v->value = value;
+ break;
+
+ case VAR_APPEND:
+ /* Append value */
+ v->value = list_append( v->value, value );
+ break;
+
+ case VAR_DEFAULT:
+ /* Set only if unset */
+ if( !v->value )
+ v->value = value;
+ else
+ list_free( value );
+ break;
+ }
+}
+
+/*
+ * var_swap() - swap a variable's value with the given one
+ */
+
+LIST *
+var_swap(
+ char *symbol,
+ LIST *value )
+{
+ VARIABLE *v = var_enter( symbol );
+ LIST *oldvalue = v->value;
+
+ if( DEBUG_VARSET )
+ var_dump( symbol, value, "set" );
+
+ v->value = value;
+
+ return oldvalue;
+}
+
+
+
+/*
+ * var_enter() - make new var symbol table entry, returning var ptr
+ */
+
+static VARIABLE *
+var_enter( char *symbol )
+{
+ VARIABLE var, *v = &var;
+
+ if( !varhash )
+ varhash = hashinit( sizeof( VARIABLE ), "variables" );
+
+ v->symbol = symbol;
+ v->value = 0;
+
+ if( hashenter( varhash, (HASHDATA **)&v ) )
+ v->symbol = newstr( symbol ); /* never freed */
+
+ return v;
+}
+
+/*
+ * var_dump() - dump a variable to stdout
+ */
+
+static void
+var_dump(
+ char *symbol,
+ LIST *value,
+ char *what )
+{
+ printf( "%s %s = ", what, symbol );
+ list_print( value );
+ printf( "\n" );
+}
+
+/*
+ * var_done() - free variable tables
+ */
+static void delete_var_( void* xvar, void* data )
+{
+ VARIABLE *v = (VARIABLE*)xvar;
+ freestr( v->symbol );
+ list_free( v-> value );
+}
+
+void
+var_done()
+{
+ hashenumerate( varhash, delete_var_, (void*)0 );
+ hashdone( varhash );
+}
Added: boost-jam/boost-build/branches/upstream/current/jam_src/variable.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/variable.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/variable.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,28 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * variable.h - handle jam multi-element variables
+ */
+
+struct hash;
+
+void var_defines( char **e );
+int var_string( char *in, char *out, int outsize, LOL *lol );
+LIST * var_get( char *symbol );
+void var_set( char *symbol, LIST *value, int flag );
+LIST * var_swap( char *symbol, LIST *value );
+void var_done();
+void var_hash_swap( struct hash** );
+
+/*
+ * Defines for var_set().
+ */
+
+# define VAR_SET 0 /* override previous value */
+# define VAR_APPEND 1 /* append to previous value */
+# define VAR_DEFAULT 2 /* set only if no previous value */
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/w32_getreg.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/w32_getreg.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/w32_getreg.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,123 @@
+/* Copyright Paul Lin 2003. 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) */
+
+# include "jam.h"
+# include "lists.h"
+# include "newstr.h"
+# include "parse.h"
+# include "frames.h"
+# include "strings.h"
+
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+# define MAX_REGISTRY_DATA_LENGTH 4096
+
+typedef struct
+{
+ LPCSTR name;
+ HKEY value;
+} KeyMap;
+
+static const KeyMap dlRootKeys[] = {
+ { "HKLM", HKEY_LOCAL_MACHINE },
+ { "HKCU", HKEY_CURRENT_USER },
+ { "HKCR", HKEY_CLASSES_ROOT },
+ { "HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE },
+ { "HKEY_CURRENT_USER", HKEY_CURRENT_USER },
+ { "HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT },
+ { 0, 0 }
+};
+
+LIST*
+builtin_system_registry(
+ PARSE *parse,
+ FRAME *frame )
+{
+ char const* path = lol_get(frame->args, 0)->string;
+ LIST* result = L0;
+ HKEY key;
+
+ {
+ const KeyMap *p;
+
+ for (p = dlRootKeys; p->name; ++p)
+ {
+ int n = strlen(p->name);
+ if (!strncmp(path,p->name,n))
+ {
+ if (path[n] == '\\' || path[n] == 0)
+ {
+ path += n + 1;
+ break;
+ }
+ }
+ }
+
+ key = p->value;
+ }
+
+ if (
+ key != 0
+ && ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key)
+ )
+ {
+ DWORD type, len;
+ BYTE data[MAX_REGISTRY_DATA_LENGTH];
+ LIST const* const field = lol_get(frame->args, 1);
+
+ if ( ERROR_SUCCESS ==
+ RegQueryValueEx(key, field ? field->string : 0, 0, &type, data, &len) )
+ {
+ switch (type)
+ {
+
+ case REG_EXPAND_SZ:
+ {
+ long len;
+ string expanded[1];
+ string_new(expanded);
+
+ while (
+ (len = ExpandEnvironmentStrings(
+ (LPCSTR)data, expanded->value, expanded->capacity))
+ > expanded->capacity
+ )
+ string_reserve(expanded, len);
+
+ expanded->size = len - 1;
+
+ result = list_new( result, newstr(expanded->value) );
+ string_free( expanded );
+ }
+ break;
+
+ case REG_MULTI_SZ:
+ {
+ char* s;
+
+ for (s = (char*)data; *s; s += strlen(s) + 1)
+ result = list_new( result, newstr(s) );
+
+ }
+ break;
+
+ case REG_DWORD:
+ {
+ char buf[100];
+ sprintf( buf, "%u", *(PDWORD)data );
+ result = list_new( result, newstr(buf) );
+ }
+ break;
+
+ case REG_SZ:
+ result = list_new( result, newstr((char*)data) );
+ break;
+ }
+ }
+ RegCloseKey(key);
+ }
+ return result;
+}
+
Added: boost-jam/boost-build/branches/upstream/current/jam_src/yyacc.c
===================================================================
--- boost-jam/boost-build/branches/upstream/current/jam_src/yyacc.c 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/jam_src/yyacc.c 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,268 @@
+/* Copyright 2002 Rene Rivera.
+** Distributed under the Boost Software License, Version 1.0.
+** (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+/*
+# yyacc - yacc wrapper
+#
+# Allows tokens to be written as `literal` and then automatically
+# substituted with #defined tokens.
+#
+# Usage:
+# yyacc file.y filetab.h file.yy
+#
+# inputs:
+# file.yy yacc grammar with ` literals
+#
+# outputs:
+# file.y yacc grammar
+# filetab.h array of string <-> token mappings
+#
+# 3-13-93
+# Documented and p moved in sed command (for some reason,
+# s/x/y/p doesn't work).
+# 10-12-93
+# Take basename as second argument.
+# 12-31-96
+# reversed order of args to be compatible with GenFile rule
+# 11-20-2002
+# Reimplemented as a C program for portability. (Rene Rivera)
+*/
+
+void print_usage();
+char * copy_string(char * s, int l);
+char * tokenize_string(char * s);
+int cmp_literal(const void * a, const void * b);
+
+typedef struct
+{
+ char * string;
+ char * token;
+} literal;
+
+int main(int argc, char ** argv)
+{
+ int result = 0;
+ if (argc != 4)
+ {
+ print_usage();
+ result = 1;
+ }
+ else
+ {
+ FILE * token_output_f = 0;
+ FILE * grammar_output_f = 0;
+ FILE * grammar_source_f = 0;
+
+ grammar_source_f = fopen(argv[3],"r");
+ if (grammar_source_f == 0) { result = 1; }
+ if (result == 0)
+ {
+ literal literals[1024];
+ int t = 0;
+ char l[2048];
+ while (1)
+ {
+ if (fgets(l,2048,grammar_source_f) != 0)
+ {
+ char * c = l;
+ while (1)
+ {
+ char * c1 = strchr(c,'`');
+ if (c1 != 0)
+ {
+ char * c2 = strchr(c1+1,'`');
+ if (c2 != 0)
+ {
+ literals[t].string = copy_string(c1+1,c2-c1-1);
+ literals[t].token = tokenize_string(literals[t].string);
+ t += 1;
+ c = c2+1;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ literals[t].string = 0;
+ literals[t].token = 0;
+ qsort(literals,t,sizeof(literal),cmp_literal);
+ {
+ int p = 1;
+ int i = 1;
+ while (literals[i].string != 0)
+ {
+ if (strcmp(literals[p-1].string,literals[i].string) != 0)
+ {
+ literals[p] = literals[i];
+ p += 1;
+ }
+ i += 1;
+ }
+ literals[p].string = 0;
+ literals[p].token = 0;
+ t = p;
+ }
+ token_output_f = fopen(argv[2],"w");
+ if (token_output_f != 0)
+ {
+ int i = 0;
+ while (literals[i].string != 0)
+ {
+ fprintf(token_output_f," { \"%s\", %s },\n",literals[i].string,literals[i].token);
+ i += 1;
+ }
+ fclose(token_output_f);
+ }
+ else
+ result = 1;
+ if (result == 0)
+ {
+ grammar_output_f = fopen(argv[1],"w");
+ if (grammar_output_f != 0)
+ {
+ int i = 0;
+ while (literals[i].string != 0)
+ {
+ fprintf(grammar_output_f,"%%token %s\n",literals[i].token);
+ i += 1;
+ }
+ rewind(grammar_source_f);
+ while (1)
+ {
+ if (fgets(l,2048,grammar_source_f) != 0)
+ {
+ char * c = l;
+ while (1)
+ {
+ char * c1 = strchr(c,'`');
+ if (c1 != 0)
+ {
+ char * c2 = strchr(c1+1,'`');
+ if (c2 != 0)
+ {
+ literal key;
+ literal * replacement = 0;
+ key.string = copy_string(c1+1,c2-c1-1);
+ key.token = 0;
+ replacement = (literal*)bsearch(
+ &key,literals,t,sizeof(literal),cmp_literal);
+ *c1 = 0;
+ fprintf(grammar_output_f,"%s%s",c,replacement->token);
+ c = c2+1;
+ }
+ else
+ {
+ fprintf(grammar_output_f,"%s",c);
+ break;
+ }
+ }
+ else
+ {
+ fprintf(grammar_output_f,"%s",c);
+ break;
+ }
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ fclose(grammar_output_f);
+ }
+ else
+ result = 1;
+ }
+ }
+ if (result != 0)
+ {
+ perror("yyacc");
+ }
+ }
+ return result;
+}
+
+static char * usage[] = {
+ "yyacc <grammar output.y> <token table output.h> <grammar source.yy>",
+ 0 };
+
+void print_usage()
+{
+ char ** u;
+ for (u = usage; *u != 0; ++u)
+ {
+ fputs(*u,stderr); putc('\n',stderr);
+ }
+}
+
+char * copy_string(char * s, int l)
+{
+ char * result = (char*)malloc(l+1);
+ strncpy(result,s,l);
+ result[l] = 0;
+ return result;
+}
+
+char * tokenize_string(char * s)
+{
+ char * result;
+ char * literal = s;
+ int l;
+ int c;
+
+ if (strcmp(s,":") == 0) literal = "_colon";
+ else if (strcmp(s,"!") == 0) literal = "_bang";
+ else if (strcmp(s,"!=") == 0) literal = "_bang_equals";
+ else if (strcmp(s,"&&") == 0) literal = "_amperamper";
+ else if (strcmp(s,"&") == 0) literal = "_amper";
+ else if (strcmp(s,"+") == 0) literal = "_plus";
+ else if (strcmp(s,"+=") == 0) literal = "_plus_equals";
+ else if (strcmp(s,"||") == 0) literal = "_barbar";
+ else if (strcmp(s,"|") == 0) literal = "_bar";
+ else if (strcmp(s,";") == 0) literal = "_semic";
+ else if (strcmp(s,"-") == 0) literal = "_minus";
+ else if (strcmp(s,"<") == 0) literal = "_langle";
+ else if (strcmp(s,"<=") == 0) literal = "_langle_equals";
+ else if (strcmp(s,">") == 0) literal = "_rangle";
+ else if (strcmp(s,">=") == 0) literal = "_rangle_equals";
+ else if (strcmp(s,".") == 0) literal = "_period";
+ else if (strcmp(s,"?") == 0) literal = "_question";
+ else if (strcmp(s,"?=") == 0) literal = "_question_equals";
+ else if (strcmp(s,"=") == 0) literal = "_equals";
+ else if (strcmp(s,",") == 0) literal = "_comma";
+ else if (strcmp(s,"[") == 0) literal = "_lbracket";
+ else if (strcmp(s,"]") == 0) literal = "_rbracket";
+ else if (strcmp(s,"{") == 0) literal = "_lbrace";
+ else if (strcmp(s,"}") == 0) literal = "_rbrace";
+ else if (strcmp(s,"(") == 0) literal = "_lparen";
+ else if (strcmp(s,")") == 0) literal = "_rparen";
+ l = strlen(literal)+2;
+ result = (char*)malloc(l+1);
+ for (c = 0; literal[c] != 0; ++c)
+ {
+ result[c] = toupper(literal[c]);
+ }
+ result[l-2] = '_';
+ result[l-1] = 't';
+ result[l] = 0;
+ return result;
+}
+
+int cmp_literal(const void * a, const void * b)
+{
+ return strcmp(((const literal *)a)->string,((const literal *)b)->string);
+}
Added: boost-jam/boost-build/branches/upstream/current/kernel/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/kernel/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/kernel/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,6 @@
+# Copyright David Abrahams 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.
+boost-build . ;
\ No newline at end of file
Property changes on: boost-jam/boost-build/branches/upstream/current/kernel/boost-build.jam
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/kernel/bootstrap.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/kernel/bootstrap.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/kernel/bootstrap.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,121 @@
+# (C) Copyright David Abrahams, 2001.
+# (C) Copyright Rene Rivera, 2003.
+#
+# See accompanying license for terms and conditions of use.
+#
+
+# First of all, check the jam version
+
+if $(JAM_VERSION:J="") < 030109
+{
+ ECHO "error: Boost.Jam version 3.1.9 or later required" ;
+ EXIT ;
+}
+
+# Bootstrap the module system. Then bring the import rule into the global module.
+#
+SEARCH on <module@>modules.jam = $(.bootstrap-file:D) ;
+module modules { include <module@>modules.jam ; }
+IMPORT modules : import : : import ;
+
+{
+ # Add module subdirectories to the BOOST_BUILD_PATH, which allows
+ # us to make an incremental refactoring step by moving modules to
+ # the appropriate subdirectories, thereby achieving some physical
+ # separation of different layers without changing all of our code
+ # to specify subdirectories in import statements or use an extra
+ # level of qualification on imported names.
+
+ local subdirs =
+ kernel # only the most-intrinsic modules: modules, errors
+ util # low-level substrate: string/number handling, etc.
+ build # essential elements of the build system architecture
+ tools # toolsets for handling specific build jobs and targets.
+
+ new # until we get everything sorted out, there is
+ # still some code here
+
+ . # build-system.jam lives here
+
+ ;
+ local whereami = [ NORMALIZE_PATH $(.bootstrap-file:DT) ] ;
+ BOOST_BUILD_PATH += $(whereami:D)/$(subdirs) ;
+}
+
+# Reload the modules, to clean up things. The modules module can tolerate
+# being included twice.
+#
+import modules ;
+
+# Check command-line args as soon as possible. For each option try
+# to load module named after option. Is that succeeds, invoke 'process'
+# rule in the module. The rule may return "true" to indicate that the
+# regular built process should not be attempted.
+#
+# Options take the general form of: --<name>[=<value>] [<value>]
+#
+local dont-build ;
+local args = $(ARGV) ;
+while $(args)
+{
+ local arg = [ MATCH ^--(.*) : $(args[1]) ] ;
+ while $(args[2-]) && ! $(arg)
+ {
+ args = $(args[2-]) ;
+ arg = [ MATCH ^--(.*) : $(args[1]) ] ;
+ }
+ args = $(args[2-]) ;
+
+ if $(arg)
+ {
+ local split = [ MATCH ^(([^-=]+)[^=]*)(=?)(.*)$ : $(arg) ] ;
+ local full-name = $(split[1]) ;
+ local prefix = $(split[2]) ;
+ local values ;
+
+ if $(split[3])
+ {
+ values = $(split[4]) ;
+ }
+ if $(args) && ! [ MATCH ^(--).* : $(args[1]) ]
+ {
+ values += $(args[1]) ;
+ args = $(args[2-]) ;
+ }
+
+ # look in options subdirectories of BOOST_BUILD_PATH for modules
+ # matching the full option name and then its prefix.
+ local plugin-dir = options ;
+ local option-files = [
+ GLOB $(plugin-dir:D=$(BOOST_BUILD_PATH)) : $(full-name).jam $(prefix).jam
+ ] ;
+
+ if $(option-files)
+ {
+ # load the file into a module named for the option
+ local f = $(option-files[1]) ;
+ local module-name = --$(f:D=:S=) ;
+ modules.load $(module-name) : $(f:D=) : $(f:D) ;
+
+ # if there's a process rule, call it with the full option name
+ # and its value (if any). If there was no "=" in the option,
+ # the value will be empty.
+ if process in [ RULENAMES $(module-name) ]
+ {
+ dont-build +=
+ [ modules.call-in $(module-name) : process --$(full-name) : $(values) ] ;
+ }
+ }
+ }
+}
+
+if ! $(dont-build)
+{
+ # Allow users to override the build system file from the
+ # command-line (mostly for testing)
+ local build-system = [ MATCH --build-system=(.*) : $(ARGV) ] ;
+ build-system ?= build-system ;
+
+ # Use last element in case of multiple command-line options
+ import $(build-system[-1]) ;
+}
Property changes on: boost-jam/boost-build/branches/upstream/current/kernel/bootstrap.jam
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/kernel/class.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/kernel/class.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/kernel/class.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,430 @@
+# (C) Copyright David Abrahams 2002. 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.
+
+# Polymorphic class system built on top of core Jam facilities.
+#
+# Classes are defined by 'class' keywords::
+#
+# class myclass ( arg1 )
+# {
+# rule __init__ ( ) # constructor
+# {
+# self.attribute = $(arg1) ;
+# }
+#
+# rule method1 ( ) # method
+# {
+# return [ method2 ] ;
+# }
+#
+# rule method2 ( ) # method
+# {
+# return $(self.attribute) ;
+# }
+# }
+#
+# The __init__ rule is the constructor, and sets member variables.
+#
+# New instances are created by invoking [ new <class> <args...> ]::
+#
+# local x = [ new myclass foo ] ; # x is a new myclass object
+# assert.result foo : [ $(x).method1 ] ; # $(x).method1 returns "foo"
+#
+# Derived class are created by mentioning base classes in the declaration::
+#
+# class derived : myclass
+# {
+# rule __init__ ( arg )
+# {
+# myclass.__init__ $(arg) ; # call base __init__
+#
+# }
+#
+# rule method2 ( ) # method override
+# {
+# return $(self.attribute)XXX ;
+# }
+# }
+#
+# All methods operate virtually, replacing behavior in the base
+# classes. For example::
+#
+# local y = [ new derived foo ] ; # y is a new derived object
+# assert.result fooXXX : [ $(y).method1 ] ; # $(y).method1 returns "foo"
+#
+# Each class instance is its own core Jam module. All instance
+# attributes and methods are accessible without additional
+# qualification from within the class instance. All rules imported in
+# class declaration, or visible in base classses are also visible.
+# Base methods are available in qualified form: base-name.method-name.
+# By convention, attribute names are prefixed with "self.".
+
+import numbers ;
+import errors : * ;
+import set ;
+import modules ;
+import assert ;
+
+classes = ;
+
+
+rule xinit ( instance : class )
+{
+ module $(instance)
+ {
+ __class__ = $(2) ;
+ __name__ = $(1) ;
+ }
+}
+
+
+rule new ( class args * : * )
+{
+ .next-instance.$(class) ?= 1 ;
+ local id = object($(class))@$(.next-instance.$(class)) ;
+
+ xinit $(id) : $(class) ;
+
+ INSTANCE $(id) : class@$(class) ;
+ IMPORT_MODULE $(id) : ;
+ $(id).__init__ $(args) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+
+ # bump the next unique object name
+ .next-instance.$(class) = [ numbers.increment $(.next-instance.$(class)) ] ;
+
+ # Return the name of the new instance.
+ return $(id) ;
+}
+
+
+rule bases ( class )
+{
+ #if ! ( $(class) in $(classes) )
+ #{
+ # error class $(class) not defined ;
+ #}
+
+ module class@$(class)
+ {
+ return $(__bases__) ;
+ }
+}
+
+rule is-derived ( class : bases + )
+{
+ #local all = $(class) $(bases) ;
+ #if ! ( $(all) in $(classes) )
+ #{
+ # error class(es) [ set.difference $(class) $(bases) : $(classes) ] not defined ;
+ #}
+
+ local stack = $(class) ;
+ local visited found ;
+ while ( ! $(found) ) && $(stack)
+ {
+ local top = $(stack[1]) ;
+ stack = $(stack[2-]) ;
+ if ! ( $(top) in $(visited) )
+ {
+ visited += $(top) ;
+ stack += [ bases $(top) ] ;
+
+ if $(bases) in $(visited)
+ {
+ found = true ;
+ }
+ }
+ }
+ return $(found) ;
+}
+
+# Returns true if the 'value' is a class instance.
+rule is-instance ( value # The value to check
+ )
+{
+ return [ MATCH "^(object\\()[^@]+\\)@.*" : $(value) ] ;
+}
+
+# Check if the given value is of the given type.
+#
+rule is-a (
+ instance # The value to check.
+ : type # The type to test for.
+ )
+{
+ if [ is-instance $(instance) ]
+ {
+ return [ class.is-derived [ modules.peek $(instance) : __class__ ] : $(type) ] ;
+ }
+}
+
+local rule typecheck ( x )
+{
+ local class-name = [ MATCH "^\\[(.*)\\]$" : [ BACKTRACE 1 ] ] ;
+ if ! [ is-a $(x) : $(class-name) ]
+ {
+ return "Expected an instance of "$(class-name)" but got \""$(x)"\" for argument" ;
+ }
+}
+
+local rule __test__ ( )
+{
+ import "class" : * ;
+ import assert ;
+ import errors : * ;
+
+ # This will be the construction function for a class called
+ # 'myclass'
+ class myclass
+ {
+ import assert : nonempty-variable ;
+
+ rule __init__ ( x_ * : y_ * )
+ {
+ # set some instance variables
+ x = $(x_) ;
+ y = $(y_) ;
+ foo += 10 ;
+ }
+
+ rule set-x ( newx * )
+ {
+ x = $(newx) ;
+ }
+
+ rule get-x ( )
+ {
+ return $(x) ;
+ }
+
+ rule set-y ( newy * )
+ {
+ y = $(newy) ;
+ }
+
+ rule get-y ( )
+ {
+ return $(y) ;
+ }
+
+ rule f ( )
+ {
+ return [ g $(x) ] ;
+ }
+
+ rule g ( args * )
+ {
+ if $(x) in $(y)
+ {
+ return $(x) ;
+ }
+ else if $(y) in $(x)
+ {
+ return $(y) ;
+ }
+ else
+ {
+ return ;
+ }
+ }
+
+ rule get-class ( )
+ {
+ return $(__class__) ;
+ }
+
+ rule get-instance ( )
+ {
+ return $(__name__) ;
+ }
+
+ rule invariant ( )
+ {
+ assert.equal 1 : 1 ;
+ }
+
+ rule get-foo ( )
+ {
+ return $(foo) ;
+ }
+ }
+# class myclass ;
+
+ class derived1 : myclass
+ {
+ rule __init__ ( z_ )
+ {
+ myclass.__init__ $(z_) : X ;
+ z = $(z_) ;
+ }
+
+ # override g
+ rule g ( args * )
+ {
+ return derived1.g ;
+ }
+
+ rule h ( )
+ {
+ return derived1.h ;
+ }
+
+ rule get-z ( )
+ {
+ return $(z) ;
+ }
+
+ # Check that 'assert.equal' visible in base class is visible
+ # here.
+ rule invariant2 ( )
+ {
+ assert.equal 2 : 2 ;
+ }
+
+ # Check that 'nonempty-variable' visible in base class is
+ # visible here.
+ rule invariant3 ( )
+ {
+ local v = 10 ;
+ nonempty-variable v ;
+ }
+ }
+# class derived1 : myclass ;
+
+ class derived2 : myclass
+ {
+ rule __init__ ( )
+ {
+ myclass.__init__ 1 : 2 ;
+ }
+
+ # override g
+ rule g ( args * )
+ {
+ return derived2.g ;
+ }
+
+ rule get-x ( )
+ {
+ # Test the ability to call base class functions with qualification.
+ return [ myclass.get-x ] ;
+ }
+ }
+# class derived2 : myclass ;
+
+ class derived2a : derived2
+ {
+ rule __init__
+ {
+ derived2.__init__ ;
+ }
+ }
+# class derived2a : derived2 ;
+
+ local rule expect_derived2 ( [derived2] x ) { }
+
+ local a = [ new myclass 3 4 5 : 4 5 ] ;
+ local b = [ new derived1 4 ] ;
+ local b2 = [ new derived1 4 ] ;
+ local c = [ new derived2 ] ;
+ local d = [ new derived2 ] ;
+ local e = [ new derived2a ] ;
+
+ expect_derived2 $(d) ;
+ expect_derived2 $(e) ;
+
+ # argument checking is set up to call exit(1) directly on
+ # failure, and we can't hijack that with try, so we'd better
+ # not do this test by default. We could fix this by having
+ # errors look up and invoke the EXIT rule instead; EXIT can be
+ # hijacked (;-)
+ if --fail-typecheck in [ modules.peek : ARGV ]
+ {
+ try ;
+ {
+ expect_derived2 $(a) ;
+ }
+ catch
+ "Expected an instance of derived2 but got" instead
+ ;
+ }
+
+
+ #try ;
+ #{
+ # new bad_subclass ;
+ #}
+ #catch
+ # bad_subclass.bad_subclass failed to call base class constructor myclass.__init__
+ # ;
+
+ #try ;
+ #{
+ # class bad_subclass ;
+ #}
+ #catch bad_subclass has already been declared ;
+
+ assert.result 3 4 5 : $(a).get-x ;
+ assert.result 4 5 : $(a).get-y ;
+ assert.result 4 : $(b).get-x ;
+ assert.result X : $(b).get-y ;
+ assert.result 4 : $(b).get-z ;
+ assert.result 1 : $(c).get-x ;
+ assert.result 2 : $(c).get-y ;
+ assert.result 4 5 : $(a).f ;
+ assert.result derived1.g : $(b).f ;
+ assert.result derived2.g : $(c).f ;
+ assert.result derived2.g : $(d).f ;
+
+ assert.result 10 : $(b).get-foo ;
+
+ $(a).invariant ;
+ $(b).invariant2 ;
+ $(b).invariant3 ;
+
+ # Check that the __class__ attribute is getting properly set.
+ assert.result myclass : $(a).get-class ;
+ assert.result derived1 : $(b).get-class ;
+ assert.result $(a) : $(a).get-instance ;
+
+ $(a).set-x a.x ;
+ $(b).set-x b.x ;
+ $(c).set-x c.x ;
+ $(d).set-x d.x ;
+ assert.result a.x : $(a).get-x ;
+ assert.result b.x : $(b).get-x ;
+ assert.result c.x : $(c).get-x ;
+ assert.result d.x : $(d).get-x ;
+
+ class derived3 : derived1 derived2
+ {
+ rule __init__ ( )
+ {
+ }
+ }
+
+
+ assert.result : bases myclass ;
+ assert.result myclass : bases derived1 ;
+ assert.result myclass : bases derived2 ;
+ assert.result derived1 derived2 : bases derived3 ;
+
+ assert.true is-derived derived1 : myclass ;
+ assert.true is-derived derived2 : myclass ;
+ assert.true is-derived derived3 : derived1 ;
+ assert.true is-derived derived3 : derived2 ;
+ assert.true is-derived derived3 : derived1 derived2 myclass ;
+ assert.true is-derived derived3 : myclass ;
+
+ assert.false is-derived myclass : derived1 ;
+
+ assert.true is-instance $(a) ;
+ assert.false is-instance bar ;
+
+ assert.true is-a $(a) : myclass ;
+ assert.true is-a $(c) : derived2 ;
+ assert.true is-a $(d) : myclass ;
+ assert.false is-a literal : myclass ;
+}
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/kernel/errors.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/kernel/errors.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/kernel/errors.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,249 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+# Print a stack backtrace leading to this rule's caller. Each
+# argument represents a line of output to be printed after the first
+# line of the backtrace.
+rule backtrace ( skip-frames prefix messages * : * )
+{
+ local frame-skips = 5 9 13 17 21 25 29 33 37 41 45 49 53 57 61 65 69 73 77 81 ;
+ local drop-elements = $(frame-skips[$(skip-frames)]) ;
+ if ! ( $(skip-frames) in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 )
+ {
+ ECHO warning: backtrace doesn't support skipping
+ $(skip-frames) frames; using 1 instead. ;
+ drop-elements = 5 ;
+ }
+
+ # get the whole backtrace, then drop the initial quadruples
+ # corresponding to the frames that must be skipped.
+ local bt = [ BACKTRACE ] ;
+ bt = $(bt[$(drop-elements)-]) ;
+
+ local args = $(.args) ;
+ while $(bt)
+ {
+ local m = [ MATCH ^(.+)\\.$ : $(bt[3]) ] ;
+ local user-modules = ([Jj]amfile(.jam|.v2)|user-config.jam|site-config.jam|project-root.jam) ;
+
+ if $(.user-modules-only)
+ {
+ if [ MATCH $(user-modules) : $(bt[1]:D=) ]
+ {
+ ECHO "$(prefix) at $(bt[1]):$(bt[2]) " ;
+ }
+ }
+ else
+ {
+ ECHO $(bt[1]):$(bt[2]): "in" $(bt[4]) "from module" $(m) ;
+ }
+
+ # the first time through, print each argument on a separate
+ # line
+ for local n in $(args)
+ {
+ if $($(n))-is-not-empty
+ {
+ ECHO $(prefix) $($(n)) ;
+ }
+ }
+ args = ; # kill args so that this never happens again
+
+ # Move on to the next quadruple
+ bt = $(bt[5-]) ;
+ }
+}
+
+.args ?= messages 2 3 4 5 6 7 8 9 ;
+.disabled ?= ;
+.last-error-$(.args) ?= ;
+
+# try-catch --
+#
+# This is not really an exception-handling mechanism, but it does
+# allow us to perform some error-checking on our
+# error-checking. Errors are suppressed after a try, and the first one
+# is recorded. Use catch to check that the error message matched
+# expectations.
+
+# begin looking for error messages
+rule try ( )
+{
+ .disabled += true ;
+ .last-error-$(.args) = ;
+}
+
+# stop looking for error messages; generate an error if an argument of
+# messages is not found in the corresponding argument in the error call.
+rule catch ( messages * : * )
+{
+ .disabled = $(.disabled[2-]) ; # pop the stack
+
+ import sequence ;
+
+ if ! $(.last-error-$(.args))-is-nonempty
+ {
+ error-skip-frames 3 expected an error, but none occurred ;
+ }
+ else
+ {
+ for local n in $(.args)
+ {
+ if ! $($(n)) in $(.last-error-$(n))
+ {
+ local v = [ sequence.join $($(n)) : " " ] ;
+ v ?= "" ;
+ local joined = [ sequence.join $(.last-error-$(n)) : " " ] ;
+
+ .last-error-$(.args) = ;
+ error-skip-frames 3 expected \"$(v)\" in argument $(n) of error
+ : got \"$(joined)\" instead ;
+ }
+ }
+ }
+}
+
+rule error-skip-frames ( skip-frames messages * : * )
+{
+ if ! $(.disabled)
+ {
+ backtrace $(skip-frames) error: $(messages) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ EXIT ;
+ }
+ else if ! $(.last-error-$(.args))
+ {
+ for local n in $(.args)
+ {
+ # Add an extra empty string so that we always have
+ # something in the event of an error
+ .last-error-$(n) = $($(n)) "" ;
+ }
+ }
+}
+
+if --no-error-backtrace in [ modules.peek : ARGV ]
+{
+ .no-error-backtrace = true ;
+}
+
+
+# Print an error message with a stack backtrace and exit.
+rule error ( messages * : * )
+{
+ if $(.no-error-backtrace)
+ {
+ # Print each argument on a separate line.
+ for local n in $(.args)
+ {
+ if $($(n))-is-not-empty
+ {
+ if ! $(first-printed)
+ {
+ ECHO error: $($(n)) ;
+ first-printed = true ;
+ }
+ else
+ {
+ ECHO $($(n)) ;
+ }
+ }
+ }
+ EXIT ;
+ }
+ else
+ {
+ error-skip-frames 3 $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+}
+
+# Same as 'error', but the generated backtrace will include only user files.
+rule user-error ( messages * : * )
+{
+ .user-modules-only = 1 ;
+ error-skip-frames 3 $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+}
+
+
+# Print a warning message with a stack backtrace and exit.
+rule warning
+{
+ backtrace 2 warning: $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+}
+
+# convert an arbitrary argument list into a list with ":" separators
+# and quoted elements representing the same information. This is
+# mostly useful for formatting descriptions of the arguments with
+# which a rule was called when reporting an error.
+rule lol->list ( * )
+{
+ local result ;
+ local remaining = 1 2 3 4 5 6 7 8 9 ;
+ while $($(remaining))
+ {
+ local n = $(remaining[1]) ;
+ remaining = $(remaining[2-]) ;
+
+ if $(n) != 1
+ {
+ result += ":" ;
+ }
+ result += \"$($(n))\" ;
+ }
+ return $(result) ;
+}
+
+# Return the file:line for the nearest entry in backtrace which correspond
+# to a user module.
+rule nearest-user-location ( )
+{
+ local bt = [ BACKTRACE ] ;
+
+ local result ;
+ while $(bt) && ! $(result)
+ {
+ local m = [ MATCH ^(.+)\\.$ : $(bt[3]) ] ;
+ local user-modules = ([Jj]amfile(.jam|.v2|)|user-config.jam|site-config.jam|project-root.jam) ;
+
+ if [ MATCH $(user-modules) : $(bt[1]:D=) ]
+ {
+ result = $(bt[1]):$(bt[2]) ;
+ }
+ bt = $(bt[5-]) ;
+ }
+ return $(result) ;
+}
+
+
+rule __test__ ( )
+{
+ # show that we can correctly catch an expected error
+ try ;
+ {
+ error an error occurred : somewhere ;
+ }
+ catch an error occurred : somewhere ;
+
+ # show that unexpected errors generate real errors
+ try ;
+ {
+ try ;
+ {
+ error an error occurred : somewhere ;
+ }
+ catch an error occurred : nowhere ;
+ }
+ catch expected \"nowhere\" in argument 2 ;
+
+ # show that not catching an error where one was expected is an
+ # error
+ try ;
+ {
+ try ;
+ {
+ }
+ catch ;
+ }
+ catch expected an error, but none occurred ;
+}
Property changes on: boost-jam/boost-build/branches/upstream/current/kernel/errors.jam
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/kernel/modules.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/kernel/modules.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/kernel/modules.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,329 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+# Essentially an include guard; ensures that no module is loaded multiple times
+.loaded ?= ;
+
+# A list of modules currently being loaded for error reporting of circular dependencies
+.loading ?= ;
+
+# A list of modules needing to be tested via __test__ rule
+.untested ?= ;
+
+# A list of modules which have been tested via __test__
+.tested ?= ;
+
+# meant to be invoked from import when no __test__ rule is defined in a given
+# module
+local rule no-test-defined
+{
+ import modules ;
+ if ! ( --quiet in [ modules.peek : ARGV ] )
+ {
+ ECHO warning: no __test__ rule defined in module $(__module__) ;
+ }
+}
+
+# return the binding of the given module
+rule binding ( module )
+{
+ return $($(module).__binding__) ;
+}
+
+# Sets the module-local value of a variable. This is the most
+# reliable way to set a module-local variable in a different module;
+# it eliminates issues of name shadowing due to dynamic scoping.
+rule poke ( module-name ? : variables + : value * )
+{
+ module $(<)
+ {
+ $(>) = $(3) ;
+ }
+}
+
+# Returns the module-local value of a variable. This is the most
+# reliable way to examine a module-local variable in a different
+# module; it eliminates issues of name shadowing due to dynamic
+# scoping.
+rule peek ( module-name ? : variables + )
+{
+ module $(<)
+ {
+ return $($(>)) ;
+ }
+}
+
+# Call the given rule locally in the given module. Use this for rules
+# which accept rule names as arguments, so that the passed rule may be
+# invoked in the context of the rule's caller (for example, if the
+# rule accesses module globals or is a local rule).
+rule call-in ( module-name ? : rule-name args * : * )
+{
+ module $(module-name)
+ {
+ return [ $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+}
+
+# Given a possibly qualified rule name and arguments, remove any
+# initial module qualification from the rule and invoke it in that
+# module. If there is no module qualification, the rule is invoked in
+# the global module.
+rule call-locally ( qualified-rule-name args * : * )
+{
+ local module-rule = [ MATCH (.*)\\.(.*) : $(qualified-rule-name) ] ;
+ local rule-name = $(module-rule[2]) ;
+ rule-name ?= $(qualified-rule-name) ;
+ return [
+ call-in $(module-rule[1])
+ : $(rule-name) $(args) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9)
+ ] ;
+}
+
+# load the indicated module if it is not already loaded.
+rule load (
+ module-name # name of module to load. Rules will be defined in this module
+ : filename ? # (partial) path to file; Defaults to $(module-name).jam
+ : search * # Directories in which to search for filename. Defaults to $(BOOST_BUILD_PATH)
+)
+{
+ # Avoid loading modules twice
+ if ! ( $(module-name) in $(.loaded) )
+ {
+ filename ?= $(module-name).jam ;
+
+ # Mark the module loaded so we don't try to load it recursively
+ .loaded += $(module-name) ;
+
+ # suppress tests if any module loads are already in progress.
+ local suppress-test = $(.loading[1]) ;
+
+ # Push this module on the loading stack
+ .loading += $(module-name) ;
+
+ # Remember that it's untested
+ .untested += $(module-name) ;
+
+ # Insert the new module's __name__ and __file__ globals
+ poke $(module-name) : __name__ : $(module-name) ;
+ poke $(module-name) : __file__ : $(filename) ;
+
+ module $(module-name)
+ {
+ # Prepare a default behavior, in case no __test__ is defined.
+ IMPORT modules : no-test-defined : $(__name__) : __test__ ;
+
+ # Add some grist so that the module will have a unique target name
+ local module-target = $(__file__:G=module@) ;
+
+ local search = $(3) ;
+ search ?= [ modules.peek : BOOST_BUILD_PATH ] ;
+ SEARCH on $(module-target) = $(search) ;
+ BINDRULE on $(module-target) = modules.record-binding ;
+
+ include $(module-target) ;
+
+ # Allow the module to see its own names with full qualification
+ local rules = [ RULENAMES $(__name__) ] ;
+ IMPORT $(__name__) : $(rules) : $(__name__) : $(__name__).$(rules) ;
+ }
+
+ if $(module-name) != modules && ! [ binding $(module-name) ]
+ {
+ import errors ;
+ errors.error "couldn't find module" $(module-name) in $(search) ;
+ }
+
+ # Pop the loading stack. Must happen before testing or we'll find a circular loading dependency
+ .loading = $(.loading[1--2]) ;
+
+ # Run any pending tests if this is an outer load
+ if ! $(suppress-test)
+ {
+ local argv = [ peek : ARGV ] ;
+ for local m in $(.untested)
+ {
+ if ( ! $(m) in $(.tested) ) # avoid recursive test invocations
+ && ( ( --debug in $(argv) ) || ( --debug-module=$(m) in $(argv) ) )
+ {
+ .tested += $(m) ;
+ if ! ( --quiet in $(argv) )
+ {
+ ECHO testing module $(m)... ;
+ }
+
+ # Import m's rules into __test-$(m)__ for easy access
+ IMPORT $(m) : [ RULENAMES $(m) ] : __test-$(m)__ : [ RULENAMES $(m) ] ;
+
+ # execute the module's __test__ rule in its own module to
+ # eliminate the inadvertent effects of testing
+ # module dependencies (such as assert) on the module itself.
+ IMPORT $(m) : __test__ : __test-$(m)__ : __test__ : LOCALIZE ;
+
+ module __test-$(m)__
+ {
+ # set up the name of the module we're testing
+ # so that no-test-defined can find it.
+ __module__ = $(1) ;
+ __test__ ;
+ }
+ }
+ }
+ .untested = ;
+ }
+ }
+ else if $(module-name) in $(.loading)
+ {
+ import errors ;
+ errors.error loading \"$(module-name)\"
+ : circular module loading dependency:
+ : $(.loading)" ->" $(module-name) ;
+ }
+}
+
+# This helper is used by load (above) to record the binding (path) of
+# each loaded module.
+rule record-binding ( module-target : binding )
+{
+ $(.loading[-1]).__binding__ = $(binding) ;
+}
+
+# Transform each path in the list, with all backslashes converted to
+# forward slashes and all detectable redundancy removed. Something
+# like this is probably needed in path.jam, but I'm not sure of that,
+# I don't understand it, and I'm not ready to move all of path.jam
+# into the kernel.
+local rule normalize-raw-paths ( paths * )
+{
+ local result ;
+ for p in $(paths:T)
+ {
+ result += [ NORMALIZE_PATH $(p) ] ;
+ }
+ return $(result) ;
+}
+
+# load the indicated module and import rule names into the current
+# module. Any members of rules-opt will be available without
+# qualification in the caller's module. Any members of rename-opt will
+# be taken as the names of the rules in the caller's module, in place
+# of the names they have in the imported module. If rules-opt = '*',
+# all rules from the indicated module are imported into the caller's
+# module. If rename-opt is supplied, it must have the same number of
+# elements as rules-opt.
+rule import ( module-names + : rules-opt * : rename-opt * )
+{
+ if $(rules-opt) = * || ! $(rules-opt)
+ {
+ if $(rename-opt)
+ {
+ errors.error "rule aliasing is only available for explicit imports." ;
+ }
+ }
+
+ if $(module-names[2]) && ( $(rules-opt) || $(rename-opt) )
+ {
+ errors.error when loading multiple modules, no specific rules or renaming is allowed ;
+ }
+
+ local caller = [ CALLER_MODULE ] ;
+
+ # Import each specified module
+ for local m in $(module-names)
+ {
+ if ! $(m) in $(.loaded)
+ {
+ # if the importing module isn't already in the BOOST_BUILD_PATH,
+ # prepend it to the path. We don't want to invert the search
+ # order of modules that are already there.
+ local cwd = [ PWD ] ;
+
+ local caller-location ;
+ if $(caller)
+ {
+ caller-location = [ binding $(caller) ] ;
+ caller-location = $(caller-location:D) ;
+ caller-location = [ normalize-raw-paths $(caller-location:R=$(cwd)) ] ;
+ }
+
+ local search = [ peek : BOOST_BUILD_PATH ] ;
+ search = [ normalize-raw-paths $(search:R=$(cwd)) ] ;
+
+ if $(caller-location) && ! $(caller-location) in $(search)
+ {
+ search = $(caller-location) $(search) ;
+ }
+
+ load $(m) : : $(search) ;
+ }
+
+ IMPORT_MODULE $(m) : $(caller) ;
+
+ if $(rules-opt)
+ {
+ local source-names ;
+ if $(rules-opt) = *
+ {
+ local all-rules = [ RULENAMES $(m) ] ;
+ source-names = $(all-rules) ;
+ }
+ else
+ {
+ source-names = $(rules-opt) ;
+ }
+ local target-names = $(rename-opt) ;
+ target-names ?= $(source-names) ;
+ IMPORT $(m) : $(source-names) : $(caller) : $(target-names) ;
+ }
+ }
+}
+
+# Define exported copies in $(target-module) of all rules exported
+# from $(source-module). Also make them available in the global
+# module with qualification, so that it is just as though the rules
+# were defined originally in $(target-module).
+rule clone-rules (
+ source-module
+ target-module
+ )
+{
+ local rules = [ RULENAMES $(source-module) ] ;
+
+ IMPORT $(source-module) : $(rules) : $(target-module) : $(rules) : LOCALIZE ;
+ EXPORT $(target-module) : $(rules) ;
+ IMPORT $(target-module) : $(rules) : : $(target-module).$(rules) ;
+}
+
+# These rules need to be available in all modules to implement
+# module loading itself and other fundamental operations.
+local globalize = peek poke record-binding ;
+IMPORT modules : $(globalize) : : modules.$(globalize) ;
+
+local rule __test__ ( )
+{
+ import assert ;
+ import modules : normalize-raw-paths ;
+
+ module modules.__test__
+ {
+ foo = bar ;
+ }
+
+ assert.result bar : peek modules.__test__ : foo ;
+ poke modules.__test__ : foo : bar baz ;
+ assert.result bar baz : peek modules.__test__ : foo ;
+ assert.result c:/foo/bar : normalize-raw-paths c:/x/../foo/./xx/yy/../../bar ;
+ assert.result . : normalize-raw-paths . ;
+ assert.result .. : normalize-raw-paths .. ;
+ assert.result ../.. : normalize-raw-paths ../.. ;
+ assert.result .. : normalize-raw-paths ./.. ;
+ assert.result / / : normalize-raw-paths / \\ ;
+ assert.result a : normalize-raw-paths a ;
+ assert.result a : normalize-raw-paths a/ ;
+ assert.result /a : normalize-raw-paths /a/ ;
+ assert.result / : normalize-raw-paths /a/.. ;
+}
+
+
Property changes on: boost-jam/boost-build/branches/upstream/current/kernel/modules.jam
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/options/help.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/options/help.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/options/help.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,174 @@
+# (C) Copyright David Abrahams, 2003.
+# (C) Copyright Rene Rivera, 2003.
+#
+# See accompanying license for terms and conditions of use.
+#
+
+# This module is the plug-in handler for the --help and --help-.*
+# command-line options
+import modules ;
+import assert ;
+import doc : do-scan set-option set-output set-output-file print-help-usage print-help-top ;
+import sequence ;
+import set ;
+
+
+# List of possible modules, but which really aren't.
+#
+.not-modules =
+ boost-build bootstrap site-config test user-config
+ -tools allyourbase boost-base features python stlport testing unit-tests ;
+
+# The help system options are parsed here and handed off to the doc
+# module to translate into documentation requests and actions. The
+# understood options are::
+#
+# --help-all
+# --help-enable-<option>
+# --help-disable-<option>
+# --help-output <type>
+# --help-output-file <file>
+# --help-options
+# --help-usage
+# --help [<module-or-class>]
+#
+rule process (
+ command # The option.
+ : values * # The values, starting after the "=".
+ )
+{
+ assert.result --help : MATCH ^(--help).* : $(command) ;
+ local did-help = ;
+ switch $(command)
+ {
+ case --help-all :
+ local path-to-modules = [ modules.peek : BOOST_BUILD_PATH ] ;
+ path-to-modules ?= . ;
+ local possible-modules = [ GLOB $(path-to-modules) : *\\.jam ] ;
+ local not-modules = [ GLOB $(path-to-modules) : *$(.not-modules)\\.jam ] ;
+ local modules-to-list =
+ [ sequence.insertion-sort
+ [ set.difference $(possible-modules:D=:S=) : $(not-modules:D=:S=) ] ] ;
+ local modules-to-scan ;
+ for local m in $(modules-to-list)
+ {
+ local module-files = [ GLOB $(path-to-modules) : $(m)\\.jam ] ;
+ modules-to-scan += $(module-files[1]) ;
+ }
+ do-scan $(modules-to-scan[1--2]) ;
+ do-scan $(modules-to-scan[-1]) : print-help-all ;
+ did-help = true ;
+
+ case --help-enable-* :
+ local option = [ MATCH --help-enable-(.*) : $(command) ] ; option = $(option:L) ;
+ set-option $(option) : enabled ;
+ did-help = true ;
+
+ case --help-disable-* :
+ local option = [ MATCH --help-disable-(.*) : $(command) ] ; option = $(option:L) ;
+ set-option $(option) ;
+ did-help = true ;
+
+ case --help-output :
+ set-output $(values[1]) ;
+ did-help = true ;
+
+ case --help-output-file :
+ set-output-file $(values[1]) ;
+ did-help = true ;
+
+ case --help-options :
+ local doc-module-spec = [ split-symbol doc ] ;
+ do-scan $(doc-module-spec[1]) : print-help-options ;
+ did-help = true ;
+
+ case --help-usage :
+ print-help-usage ;
+ did-help = true ;
+
+ case --help :
+ local spec = $(values[1]) ;
+ if $(spec)
+ {
+ local spec-parts = [ split-symbol $(spec) ] ;
+ if $(spec-parts)
+ {
+ if $(spec-parts[2])
+ {
+ do-scan $(spec-parts[1]) : print-help-classes $(spec-parts[2]) ;
+ do-scan $(spec-parts[1]) : print-help-rules $(spec-parts[2]) ;
+ do-scan $(spec-parts[1]) : print-help-variables $(spec-parts[2]) ;
+ }
+ else
+ {
+ do-scan $(spec-parts[1]) : print-help-module ;
+ }
+ }
+ else
+ {
+ EXIT "Unrecognized help option '"$(command)" "$(spec)"'." ;
+ }
+ }
+ else
+ {
+ print-help-top ;
+ }
+ did-help = true ;
+ }
+ if $(did-help)
+ {
+ UPDATE all ;
+ }
+ return $(did-help) ;
+}
+
+# Split a reference to a symbol into module and symbol parts.
+#
+local rule split-symbol (
+ symbol # The symbol to split.
+ )
+{
+ local path-to-modules = [ modules.peek : BOOST_BUILD_PATH ] ;
+ path-to-modules ?= . ;
+ local module-name = $(symbol) ;
+ local symbol-name = ;
+ local result = ;
+ while ! $(result)
+ {
+ local module-path = [ GLOB $(path-to-modules) : $(module-name)\\.jam ] ;
+ if $(module-path)
+ {
+ # The 'module-name' in fact refers to module. Return the full
+ # module path and a symbol within it. If 'symbol' passed to this
+ # rule is already module, 'symbol-name' will be empty. Otherwise,
+ # it's initialized on the previous loop iteration.
+ # In case there are several modules by this name,
+ # use the first one.
+ result = $(module-path[1]) $(symbol-name) ;
+ }
+ else
+ {
+ if ! $(module-name:S)
+ {
+ result = - ;
+ }
+ else
+ {
+ local next-symbol-part = [ MATCH ^.(.*) : $(module-name:S) ] ;
+ if $(symbol-name)
+ {
+ symbol-name = $(next-symbol-part).$(symbol-name) ;
+ }
+ else
+ {
+ symbol-name = $(next-symbol-part) ;
+ }
+ module-name = $(module-name:B) ;
+ }
+ }
+ }
+ if $(result) != -
+ {
+ return $(result) ;
+ }
+}
Property changes on: boost-jam/boost-build/branches/upstream/current/options/help.jam
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/site-config.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/site-config.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/site-config.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+# No copyright, since this file is empty
Added: boost-jam/boost-build/branches/upstream/current/test/BoostBuild.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/BoostBuild.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/BoostBuild.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,625 @@
+
+import TestCmd
+from tree import build_tree, trees_difference
+import copy
+import fnmatch
+import os
+import shutil
+import string
+import types
+import time
+import tempfile
+import sys
+import re
+
+def get_toolset():
+ toolset = None;
+ for arg in sys.argv[1:]:
+ if not arg.startswith('-'):
+ toolset = arg
+ return toolset or 'gcc'
+
+windows = 0
+suffixes = {}
+
+# Prepare the map of suffixes
+def prepare_suffix_map(toolset):
+ global windows, suffixes
+ suffixes = {'.exe': '', '.dll': '.so', '.lib': '.a', '.obj': '.o'}
+ if os.environ.get('OS','').lower().startswith('windows') or \
+ os.__dict__.has_key('uname') and \
+ os.uname()[0].lower().startswith('cygwin'):
+ windows = 1
+ suffixes = {}
+ if toolset in ["gcc"]:
+ suffixes['.lib'] = '.a' # static libs have '.a' suffix with mingw...
+ suffixes['.obj'] = '.o'
+ if os.__dict__.has_key('uname') and os.uname()[0] == 'Darwin':
+ suffixes['.dll'] = '.dylib'
+
+
+
+
+#
+# FIXME: this is copy-pasted from TestSCons.py
+# Should be moved to TestCmd.py?
+#
+if os.name == 'posix':
+ def _failed(self, status = 0):
+ if self.status is None:
+ return None
+ if os.WIFSIGNALED(status):
+ return None
+ return _status(self) != status
+ def _status(self):
+ if os.WIFEXITED(self.status):
+ return os.WEXITSTATUS(self.status)
+ else:
+ return None
+elif os.name == 'nt':
+ def _failed(self, status = 0):
+ return not self.status is None and self.status != status
+ def _status(self):
+ return self.status
+
+class Tester(TestCmd.TestCmd):
+ """Class for testing Boost.Build.
+
+ Optional argument `executable` indicates the name of the
+ executable to invoke. Set this to "jam" to test Boost.Build v1
+ behavior.
+ """
+ def __init__(self, arguments="", executable = 'bjam', match =
+ TestCmd.match_exact, boost_build_path = None,
+ translate_suffixes = 1, pass_toolset = 1,
+ **keywords):
+
+ self.original_workdir = os.getcwd()
+ self.last_build_time = 0
+ self.translate_suffixes = translate_suffixes
+
+ self.toolset = get_toolset()
+ self.pass_toolset = pass_toolset
+
+ prepare_suffix_map(pass_toolset and self.toolset or 'gcc')
+
+ jam_build_dir = ""
+ if os.name == 'nt':
+ jam_build_dir = "bin.ntx86"
+ elif os.name == 'posix' and os.__dict__.has_key('uname'):
+ if os.uname()[0].lower().startswith('cygwin'):
+ jam_build_dir = "bin.cygwinx86"
+ if 'TMP' in os.environ and os.environ['TMP'].find('~') != -1:
+ print 'Setting $TMP to /tmp to get around problem with short path names'
+ os.environ['TMP'] = '/tmp'
+ elif os.uname()[0] == 'Linux':
+ jam_build_dir = "bin.linuxx86"
+ elif os.uname()[0] == 'SunOS':
+ jam_build_dir = "bin.solaris"
+ elif os.uname()[0] == 'Darwin':
+ jam_build_dir = "bin.macosxppc"
+ elif os.uname()[0] == "AIX":
+ jam_build_dir = "bin.aix"
+ elif os.uname()[0] == "IRIX64":
+ jam_build_dir = "bin.irix"
+ else:
+ raise "Don't know directory where jam is build for this system: " + os.name + "/" + os.uname()[0]
+ else:
+ raise "Don't know directory where jam is build for this system: " + os.name
+
+ if boost_build_path is None:
+ boost_build_path = self.original_workdir
+
+
+ verbosity = ['-d0', '--quiet']
+ if '--verbose' in sys.argv:
+ keywords['verbose'] = 1
+ verbosity = ['-d+2']
+
+ program_list = []
+
+ # Find there jam_src is located.
+ # try for the debug version if it's lying around
+
+ dirs = [os.path.join('../../jam_src', jam_build_dir + '.debug'),
+ os.path.join('../../jam_src', jam_build_dir),
+ os.path.join('../jam_src', jam_build_dir + '.debug'),
+ os.path.join('../jam_src', jam_build_dir),
+ ]
+
+ for d in dirs:
+ if os.path.exists(d):
+ jam_build_dir = d
+ break
+ else:
+ print "Cannot find built Boost.Jam"
+ os.exit(1)
+
+
+ program_list.append(os.path.join(jam_build_dir, executable))
+ program_list.append('-sBOOST_BUILD_PATH=' + boost_build_path)
+ if verbosity:
+ program_list += verbosity
+ if arguments:
+ program_list += arguments.split(" ")
+
+ TestCmd.TestCmd.__init__(
+ self
+ , program=program_list
+ , match=match
+ , workdir=''
+ , **keywords)
+
+ os.chdir(self.workdir)
+
+ def cleanup(self):
+ try:
+ TestCmd.TestCmd.cleanup(self)
+ os.chdir(self.original_workdir)
+ except AttributeError:
+ # Whe this is called during by TestCmd.TestCmd.__del__ we can have both
+ # 'TestCmd' and 'os' unavailable in our scope. Do nothing in this case.
+ pass
+
+ #
+ # Methods that change working directory's content
+ #
+ def set_tree(self, tree_location):
+ # Seem like it's not possible to remove a directory which is
+ # current.
+ d = os.getcwd()
+ os.chdir(os.path.dirname(self.workdir))
+ shutil.rmtree(self.workdir, ignore_errors=0)
+
+ if not os.path.isabs(tree_location):
+ tree_location = os.path.join(self.original_workdir, tree_location)
+ shutil.copytree(tree_location, self.workdir)
+
+ os.chdir(d)
+
+ def make_writable(unused, dir, entries):
+ for e in entries:
+ name = os.path.join(dir, e)
+ os.chmod(name, os.stat(name)[0] | 0222)
+
+ os.path.walk(".", make_writable, None)
+
+
+ def write(self, file, content):
+ self.wait_for_time_change()
+ nfile = self.native_file_name(file)
+ try:
+ os.makedirs(os.path.dirname(nfile))
+ except Exception, e:
+ pass
+ open(nfile, "wb").write(content)
+
+ def rename(self, old, new):
+ try:
+ os.makedirs(os.path.dirname(new))
+ except:
+ pass
+
+ try:
+ os.remove(new)
+ except:
+ pass
+
+ os.rename(old, new)
+ self.touch(new);
+
+ def copy(self, src, dst):
+ self.wait_for_time_change()
+ self.write(dst, self.read(src))
+
+ def touch(self, names):
+ self.wait_for_time_change()
+ for name in self.adjust_names(names):
+ os.utime(self.native_file_name(name), None)
+
+ def rm(self, names):
+ self.wait_for_time_change()
+ if not type(names) == types.ListType:
+ names = [names]
+
+ # Avoid attempts to remove current dir
+ os.chdir(self.original_workdir)
+ for name in names:
+ n = self.native_file_name(name)
+ if os.path.isdir(n):
+ shutil.rmtree(n, ignore_errors=0)
+ else:
+ os.unlink(n)
+
+ # Create working dir root again, in case
+ # we've removed it
+ if not os.path.exists(self.workdir):
+ os.mkdir(self.workdir)
+ os.chdir(self.workdir)
+
+ def expand_toolset(self, name):
+ """Expands $toolset in the given file to tested toolset"""
+ content = self.read(name)
+ content = string.replace(content, "$toolset", self.toolset)
+ self.write(name, content)
+
+ def dump_stdio(self):
+ print "STDOUT ============"
+ print self.stdout()
+ print "STDERR ============"
+ print self.stderr()
+ print "END ==============="
+
+ #
+ # FIXME: Large portion copied from TestSCons.py, should be moved?
+ #
+ def run_build_system(
+ self, extra_args='', subdir='', stdout = None, stderr = '',
+ status = 0, match = None, pass_toolset = None, **kw):
+
+ self.previous_tree = build_tree(self.workdir)
+
+ if match is None:
+ match = self.match
+
+ if pass_toolset is None:
+ pass_toolset = self.pass_toolset
+
+ try:
+ kw['program'] = []
+ kw['program'] += self.program
+ if extra_args:
+ kw['program'] += extra_args.split(" ")
+ if pass_toolset:
+ kw['program'].append(self.toolset)
+ kw['chdir'] = subdir
+ apply(TestCmd.TestCmd.run, [self], kw)
+ except:
+ self.dump_stdio()
+ raise
+
+ if status != None and _failed(self, status):
+ expect = ''
+ if status != 0:
+ expect = " (expected %d)" % status
+
+ print '"%s" returned %d%s' % (
+ kw['program'], _status(self), expect)
+
+ self.fail_test(1)
+
+ if not stdout is None and not match(self.stdout(), stdout):
+ print "Expected STDOUT =========="
+ print stdout
+ print "Actual STDOUT ============"
+ print self.stdout()
+ stderr = self.stderr()
+ if stderr:
+ print "STDERR ==================="
+ print stderr
+ self.maybe_do_diff(self.stdout(), stdout)
+ self.fail_test(1, dump_stdio = 0)
+
+ # Intel tends to produce some message to stderr, which makes tests
+ # fail
+ intel_workaround = re.compile("^xi(link|lib): executing.*\n", re.M)
+ actual_stderr = re.sub(intel_workaround, "", self.stderr())
+
+ if not stderr is None and not match(actual_stderr, stderr):
+ print "STDOUT ==================="
+ print self.stdout()
+ print "Expected STDERR =========="
+ print stderr
+ print "Actual STDERR ============"
+ print actual_stderr
+ self.maybe_do_diff(actual_stderr, stderr)
+ self.fail_test(1, dump_stdio = 0)
+
+ self.tree = build_tree(self.workdir)
+ self.difference = trees_difference(self.previous_tree, self.tree)
+ self.difference.ignore_directories()
+ self.unexpected_difference = copy.deepcopy(self.difference)
+
+ self.last_build_time = time.time()
+
+ def read(self, name):
+ return open(self.native_file_name(name), "rb").read()
+
+ def read_and_strip(self, name):
+ lines = open(self.native_file_name(name), "rb").readlines()
+ result = string.join(map(string.rstrip, lines), "\n")
+ if lines and lines[-1][-1] == '\n':
+ return result + '\n'
+ else:
+ return result
+
+ def fail_test(self, condition, dump_stdio = 1, *args):
+ # If test failed, print the difference
+ if condition and hasattr(self, 'difference'):
+ print '-------- all changes caused by last build command ----------'
+ self.difference.pprint()
+
+ if condition and dump_stdio:
+ self.dump_stdio()
+
+ if '--preserve' in sys.argv:
+ print
+ print "*** Copying the state of working dir into 'failed_test' ***"
+ print
+ path = os.path.join(self.original_workdir, "failed_test")
+ if os.path.isdir(path):
+ shutil.rmtree(path, ignore_errors=0)
+ elif os.path.exists(path):
+ raise "The path " + path + " already exists and is not directory";
+ shutil.copytree(self.workdir, path)
+
+ TestCmd.TestCmd.fail_test(self, condition, *args)
+
+ # A number of methods below check expectations with actual difference
+ # between directory trees before and after build.
+ # All the 'expect*' methods require exact names to be passed.
+ # All the 'ignore*' methods allow wildcards.
+
+ # All names can be lists, which are taken to be directory components
+ def expect_addition(self, names):
+ for name in self.adjust_names(names):
+ try:
+ self.unexpected_difference.added_files.remove(name)
+ except:
+ print "File %s not added as expected" % (name,)
+ self.fail_test(1)
+
+ def ignore_addition(self, wildcard):
+ self.ignore_elements(self.unexpected_difference.added_files, wildcard)
+
+ def expect_removal(self, names):
+ for name in self.adjust_names(names):
+ try:
+ self.unexpected_difference.removed_files.remove(name)
+ except:
+ print "File %s not removed as expected" % (name,)
+ self.fail_test(1)
+
+ def ignore_removal(self, wildcard):
+ self.ignore_elements(self.unexpected_difference.removed_files, wildcard)
+
+ def expect_modification(self, names):
+ for name in self.adjust_names(names):
+ try:
+ self.unexpected_difference.modified_files.remove(name)
+ except:
+ print "File %s not modified as expected" % (name,)
+ self.fail_test(1)
+
+ def ignore_modification(self, wildcard):
+ self.ignore_elements(self.unexpected_difference.modified_files, wildcard)
+
+ def expect_touch(self, names):
+
+ d = self.unexpected_difference
+ for name in self.adjust_names(names):
+
+ # We need to check in both touched and modified files.
+ # The reason is that:
+ # (1) for windows binaries often have slight
+ # differences even with identical inputs
+ # (2) Intel's compiler for Linux has the same behaviour
+ filesets = [d.modified_files, d.touched_files]
+
+ while filesets:
+ try:
+ filesets[-1].remove(name)
+ break
+ except ValueError:
+ filesets.pop()
+
+ if not filesets:
+ print "File %s not touched as expected" % (name,)
+ self.fail_test(1)
+
+
+ def ignore_touch(self, wildcard):
+ self.ignore_elements(self.unexpected_difference.touched_files, wildcard)
+
+ def ignore(self, wildcard):
+ self.ignore_elements(self.unexpected_difference.added_files, wildcard)
+ self.ignore_elements(self.unexpected_difference.removed_files, wildcard)
+ self.ignore_elements(self.unexpected_difference.modified_files, wildcard)
+ self.ignore_elements(self.unexpected_difference.touched_files, wildcard)
+
+ def expect_nothing(self, names):
+ for name in self.adjust_names(names):
+ if name in self.difference.added_files:
+ print "File %s is added, but no action was expected" % (name,)
+ self.fail_test(1)
+ if name in self.difference.removed_files:
+ print "File %s is removed, but no action was expected" % (name,)
+ self.fail_test(1)
+ pass
+ if name in self.difference.modified_files:
+ print "File %s is modified, but no action was expected" % (name,)
+ self.fail_test(1)
+ if name in self.difference.touched_files:
+ print "File %s is touched, but no action was expected" % (name,)
+ self.fail_test(1)
+
+ def expect_nothing_more(self):
+
+ # not totally sure about this change, but I don't see a good alternative
+ if windows:
+ self.ignore('*.ilk') # msvc incremental linking files
+ self.ignore('*.pdb') # msvc program database files
+ self.ignore('*.rsp') # response files
+ self.ignore('*.tds') # borland debug symbols
+
+ # debug builds of bjam built with gcc produce this profiling data
+ self.ignore('gmon.out')
+ self.ignore('*/gmon.out')
+
+ if not self.unexpected_difference.empty():
+ print 'FAILED'
+ print '------- The following changes were unexpected ------- '
+ self.unexpected_difference.pprint()
+ self.fail_test(1)
+
+ def expect_content(self, name, content, exact=0):
+ name = self.adjust_names(name)[0]
+ try:
+ if exact:
+ actual = self.read(name)
+ else:
+ actual = string.replace(self.read_and_strip(name), "\\", "/")
+ except IOError:
+ print "Note: could not open file", name
+ self.fail_test(1)
+
+ content = string.replace(content, "$toolset", self.toolset)
+
+ if actual != content:
+ print "Expected:\n"
+ print content
+ print "Got:\n"
+ print actual
+ self.fail_test(1)
+
+ def maybe_do_diff(self, actual, expected):
+ if os.environ.has_key("DO_DIFF") and os.environ["DO_DIFF"] != '':
+
+ e = tempfile.mktemp("expected")
+ a = tempfile.mktemp("actual")
+ open(e, "w").write(expected)
+ open(a, "w").write(actual)
+ print "DIFFERENCE"
+ if os.system("diff -u " + e + " " + a):
+ print "Unable to compute difference"
+ os.unlink(e)
+ os.unlink(a)
+ else:
+ print "Set environmental variable 'DO_DIFF' to examine difference."
+
+ # Helpers
+ def mul(self, *arguments):
+ if len(arguments) == 0:
+ return None
+ else:
+ here = arguments[0]
+ if type(here) == type(''):
+ here = [here]
+
+ if len(arguments) > 1:
+ there = apply(self.mul, arguments[1:])
+ result = []
+ for i in here:
+ for j in there:
+ result.append(i + j)
+ return result
+ else:
+ return here
+
+
+
+ # Internal methods
+ def ignore_elements(self, list, wildcard):
+ """Removes in-place, element of 'list' that match the given wildcard."""
+ list[:] = filter(lambda x, w=wildcard: not fnmatch.fnmatch(x, w), list)
+
+ def adjust_suffix(self, name):
+ if not self.translate_suffixes:
+ return name
+
+ pos = string.rfind(name, ".")
+ if pos != -1:
+ suffix = name[pos:]
+ name = name[:pos]
+
+ if suffixes.has_key(suffix):
+ suffix = suffixes[suffix]
+ else:
+ suffix = ''
+
+ return name + suffix
+
+ # Acceps either string of list of string and returns list of strings
+ # Adjusts suffixes on all names.
+ def adjust_names(self, names):
+ if type(names) == types.StringType:
+ names = [names]
+ r = map(self.adjust_suffix, names)
+ r = map(lambda x, t=self.toolset: string.replace(x, "$toolset", t), r)
+ return r
+
+ def native_file_name(self, name):
+ name = self.adjust_names(name)[0]
+ elements = string.split(name, "/")
+ return os.path.normpath(apply(os.path.join, [self.workdir]+elements))
+
+ # Wait while time is no longer equal to the time last "run_build_system"
+ # call finished.
+ def wait_for_time_change(self):
+ while int(time.time()) == int(self.last_build_time):
+ time.sleep(0.1)
+
+
+class List:
+
+ def __init__(self, s=""):
+ elements = []
+ if isinstance(s, type("")):
+ # Have to handle espaced spaces correctly
+ s = string.replace(s, "\ ", '\001')
+ elements = string.split(s)
+ else:
+ elements = s;
+
+ self.l = []
+ for e in elements:
+ self.l.append(string.replace(e, '\001', ' '))
+
+ def __len__(self):
+ return len(self.l)
+
+ def __getitem__(self, key):
+ return self.l[key]
+
+ def __setitem__(self, key, value):
+ self.l[key] = value
+
+ def __delitem__(self, key):
+ del self.l[key]
+
+ def __str__(self):
+ return str(self.l)
+
+ def __repr__(self):
+ return ( self.__module__ + '.List('
+ + repr(string.join(self.l, ' '))
+ + ')')
+
+ def __mul__(self, other):
+ result = List()
+ if not isinstance(other, List):
+ other = List(other)
+ for f in self:
+ for s in other:
+ result.l.append(f + s)
+ return result
+
+ def __rmul__(self, other):
+ if not isinstance(other, List):
+ other = List(other)
+ return List.__mul__(other, self)
+
+ def __add__(self, other):
+ result = List()
+ result.l = self.l[:] + other.l[:]
+ return result
+
+# quickie tests. Should use doctest instead.
+if __name__ == '__main__':
+ assert str(List("foo bar") * "/baz") == "['foo/baz', 'bar/baz']"
+ assert repr("foo/" * List("bar baz")) == "__main__.List('foo/bar foo/baz')"
+ print 'tests passed'
+
+
+
+
Added: boost-jam/boost-build/branches/upstream/current/test/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,7 @@
+
+# establish a project root right here in the test directory, so that we can test
+# things independently of the boost jambase, etc.
+project-root ;
+
+include check-test-tools.jam ;
+include check-jam-patches.jam ;
Added: boost-jam/boost-build/branches/upstream/current/test/Jamrules
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/Jamrules 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/Jamrules 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,4 @@
+# This simple Jamrules file is used for the Boost.Build test project.
+
+# The testing framework itself gets no boost-Jambase
+BOOST_JAMBASE = empty.jam ;
Added: boost-jam/boost-build/branches/upstream/current/test/TestCmd.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/TestCmd.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/TestCmd.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,602 @@
+"""
+TestCmd.py: a testing framework for commands and scripts.
+
+The TestCmd module provides a framework for portable automated testing
+of executable commands and scripts (in any language, not just Python),
+especially commands and scripts that require file system interaction.
+
+In addition to running tests and evaluating conditions, the TestCmd module
+manages and cleans up one or more temporary workspace directories, and
+provides methods for creating files and directories in those workspace
+directories from in-line data, here-documents), allowing tests to be
+completely self-contained.
+
+A TestCmd environment object is created via the usual invocation:
+
+ test = TestCmd()
+
+The TestCmd module provides pass_test(), fail_test(), and no_result()
+unbound methods that report test results for use with the Aegis change
+management system. These methods terminate the test immediately,
+reporting PASSED, FAILED, or NO RESULT respectively, and exiting with
+status 0 (success), 1 or 2 respectively. This allows for a distinction
+between an actual failed test and a test that could not be properly
+evaluated because of an external condition (such as a full file system
+or incorrect permissions).
+"""
+
+# Copyright 2000 Steven Knight
+# This module is free software, and you may redistribute it and/or modify
+# it under the same terms as Python itself, so long as this copyright message
+# and disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+# SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
+# THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+#
+# THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
+# AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+from string import join, split
+
+__author__ = "Steven Knight <knight at baldmt.com>"
+__revision__ = "TestCmd.py 0.D002 2001/08/31 14:56:12 software"
+__version__ = "0.02"
+
+from types import *
+
+import os
+import os.path
+import popen2
+import re
+import shutil
+import stat
+import sys
+import tempfile
+import traceback
+
+tempfile.template = 'testcmd.'
+
+_Cleanup = []
+
+def _clean():
+ global _Cleanup
+ list = _Cleanup[:]
+ _Cleanup = []
+ list.reverse()
+ for test in list:
+ test.cleanup()
+
+sys.exitfunc = _clean
+
+def _caller(tblist, skip):
+ string = ""
+ arr = []
+ for file, line, name, text in tblist:
+ if file[-10:] == "TestCmd.py":
+ break
+ arr = [(file, line, name, text)] + arr
+ atfrom = "at"
+ for file, line, name, text in arr[skip:]:
+ if name == "?":
+ name = ""
+ else:
+ name = " (" + name + ")"
+ string = string + ("%s line %d of %s%s\n" % (atfrom, line, file, name))
+ atfrom = "\tfrom"
+ return string
+
+def fail_test(self = None, condition = 1, function = None, skip = 0):
+ """Cause the test to fail.
+
+ By default, the fail_test() method reports that the test FAILED
+ and exits with a status of 1. If a condition argument is supplied,
+ the test fails only if the condition is true.
+ """
+ if not condition:
+ return
+ if not function is None:
+ function()
+ of = ""
+ desc = ""
+ sep = " "
+ if not self is None:
+ if self.program:
+ of = " of " + join(self.program, " ")
+ sep = "\n\t"
+ if self.description:
+ desc = " [" + self.description + "]"
+ sep = "\n\t"
+
+ at = _caller(traceback.extract_stack(), skip)
+
+ sys.stderr.write("FAILED test" + of + desc + sep + at + """
+in directory: """ + os.getcwd() )
+
+ sys.exit(1)
+
+def no_result(self = None, condition = 1, function = None, skip = 0):
+ """Causes a test to exit with no valid result.
+
+ By default, the no_result() method reports NO RESULT for the test
+ and exits with a status of 2. If a condition argument is supplied,
+ the test fails only if the condition is true.
+ """
+ if not condition:
+ return
+ if not function is None:
+ function()
+ of = ""
+ desc = ""
+ sep = " "
+ if not self is None:
+ if self.program:
+ of = " of " + self.program
+ sep = "\n\t"
+ if self.description:
+ desc = " [" + self.description + "]"
+ sep = "\n\t"
+
+ at = _caller(traceback.extract_stack(), skip)
+ sys.stderr.write("NO RESULT for test" + of + desc + sep + at)
+
+ sys.exit(2)
+
+def pass_test(self = None, condition = 1, function = None):
+ """Causes a test to pass.
+
+ By default, the pass_test() method reports PASSED for the test
+ and exits with a status of 0. If a condition argument is supplied,
+ the test passes only if the condition is true.
+ """
+ if not condition:
+ return
+ if not function is None:
+ function()
+ sys.stderr.write("PASSED\n")
+ sys.exit(0)
+
+def match_exact(lines = None, matches = None):
+ """
+ """
+ if not type(lines) is ListType:
+ lines = split(lines, "\n")
+ if not type(matches) is ListType:
+ matches = split(matches, "\n")
+ if len(lines) != len(matches):
+ return
+ for i in range(len(lines)):
+ if lines[i] != matches[i]:
+ return
+ return 1
+
+def match_re(lines = None, res = None):
+ """
+ """
+ if not type(lines) is ListType:
+ lines = split(lines, "\n")
+ if not type(res) is ListType:
+ res = split(res, "\n")
+ if len(lines) != len(res):
+ return
+ for i in range(len(lines)):
+ if not re.compile("^" + res[i] + "$").search(lines[i]):
+ return
+ return 1
+
+class TestCmd:
+ """Class TestCmd
+ """
+
+ def __init__(self, description = None,
+ program = None,
+ interpreter = None,
+ workdir = None,
+ subdir = None,
+ verbose = 0,
+ match = None):
+ self._cwd = os.getcwd()
+ self.description_set(description)
+ self.program_set(program)
+ self.interpreter_set(interpreter)
+ self.verbose_set(verbose)
+ if not match is None:
+ self.match_func = match
+ else:
+ self.match_func = match_re
+ self._dirlist = []
+ self._preserve = {'pass_test': 0, 'fail_test': 0, 'no_result': 0}
+ if os.environ.has_key('PRESERVE') and not os.environ['PRESERVE'] is '':
+ self._preserve['pass_test'] = os.environ['PRESERVE']
+ self._preserve['fail_test'] = os.environ['PRESERVE']
+ self._preserve['no_result'] = os.environ['PRESERVE']
+ else:
+ try:
+ self._preserve['pass_test'] = os.environ['PRESERVE_PASS']
+ except KeyError:
+ pass
+ try:
+ self._preserve['fail_test'] = os.environ['PRESERVE_FAIL']
+ except KeyError:
+ pass
+ try:
+ self._preserve['no_result'] = os.environ['PRESERVE_NO_RESULT']
+ except KeyError:
+ pass
+ self._stdout = []
+ self._stderr = []
+ self.status = None
+ self.condition = 'no_result'
+ self.workdir_set(workdir)
+ self.subdir(subdir)
+
+ def __del__(self):
+ self.cleanup()
+
+ def __repr__(self):
+ return "%x" % id(self)
+
+ def cleanup(self, condition = None):
+ """Removes any temporary working directories for the specified
+ TestCmd environment. If the environment variable PRESERVE was
+ set when the TestCmd environment was created, temporary working
+ directories are not removed. If any of the environment variables
+ PRESERVE_PASS, PRESERVE_FAIL, or PRESERVE_NO_RESULT were set
+ when the TestCmd environment was created, then temporary working
+ directories are not removed if the test passed, failed, or had
+ no result, respectively. Temporary working directories are also
+ preserved for conditions specified via the preserve method.
+
+ Typically, this method is not called directly, but is used when
+ the script exits to clean up temporary working directories as
+ appropriate for the exit status.
+ """
+ if not self._dirlist:
+ return
+ if condition is None:
+ condition = self.condition
+ if self._preserve[condition]:
+ for dir in self._dirlist:
+ print "Preserved directory", dir
+ else:
+ list = self._dirlist[:]
+ list.reverse()
+ for dir in list:
+ self.writable(dir, 1)
+ shutil.rmtree(dir, ignore_errors = 1)
+
+ self._dirlist = []
+ self.workdir = None
+ os.chdir(self._cwd)
+ try:
+ global _Cleanup
+ _Cleanup.remove(self)
+ except (AttributeError, ValueError):
+ pass
+
+ def description_set(self, description):
+ """Set the description of the functionality being tested.
+ """
+ self.description = description
+
+# def diff(self):
+# """Diff two arrays.
+# """
+
+ def fail_test(self, condition = 1, function = None, skip = 0):
+ """Cause the test to fail.
+ """
+ if not condition:
+ return
+ self.condition = 'fail_test'
+ fail_test(self = self,
+ condition = condition,
+ function = function,
+ skip = skip)
+
+ def interpreter_set(self, interpreter):
+ """Set the program to be used to interpret the program
+ under test as a script.
+ """
+ self.interpreter = interpreter
+
+ def match(self, lines, matches):
+ """Compare actual and expected file contents.
+ """
+ return self.match_func(lines, matches)
+
+ def match_exact(self, lines, matches):
+ """Compare actual and expected file contents.
+ """
+ return match_exact(lines, matches)
+
+ def match_re(self, lines, res):
+ """Compare actual and expected file contents.
+ """
+ return match_re(lines, res)
+
+ def no_result(self, condition = 1, function = None, skip = 0):
+ """Report that the test could not be run.
+ """
+ if not condition:
+ return
+ self.condition = 'no_result'
+ no_result(self = self,
+ condition = condition,
+ function = function,
+ skip = skip)
+
+ def pass_test(self, condition = 1, function = None):
+ """Cause the test to pass.
+ """
+ if not condition:
+ return
+ self.condition = 'pass_test'
+ pass_test(self = self, condition = condition, function = function)
+
+ def preserve(self, *conditions):
+ """Arrange for the temporary working directories for the
+ specified TestCmd environment to be preserved for one or more
+ conditions. If no conditions are specified, arranges for
+ the temporary working directories to be preserved for all
+ conditions.
+ """
+ if conditions is ():
+ conditions = ('pass_test', 'fail_test', 'no_result')
+ for cond in conditions:
+ self._preserve[cond] = 1
+
+ def program_set(self, program):
+ """Set the executable program or script to be tested.
+ """
+ if program and program[0] and not os.path.isabs(program[0]):
+ program[0] = os.path.join(self._cwd, program[0])
+ self.program = program
+
+ def read(self, file, mode = 'rb'):
+ """Reads and returns the contents of the specified file name.
+ The file name may be a list, in which case the elements are
+ concatenated with the os.path.join() method. The file is
+ assumed to be under the temporary working directory unless it
+ is an absolute path name. The I/O mode for the file may
+ be specified; it must begin with an 'r'. The default is
+ 'rb' (binary read).
+ """
+ if type(file) is ListType:
+ file = apply(os.path.join, tuple(file))
+ if not os.path.isabs(file):
+ file = os.path.join(self.workdir, file)
+ if mode[0] != 'r':
+ raise ValueError, "mode must begin with 'r'"
+ return open(file, mode).read()
+
+ def run(self, program = None,
+ interpreter = None,
+ arguments = None,
+ chdir = None,
+ stdin = None):
+ """Runs a test of the program or script for the test
+ environment. Standard output and error output are saved for
+ future retrieval via the stdout() and stderr() methods.
+ """
+ if chdir:
+ oldcwd = os.getcwd()
+ if not os.path.isabs(chdir):
+ chdir = os.path.join(self.workpath(chdir))
+ if self.verbose:
+ sys.stderr.write("chdir(" + chdir + ")\n")
+ os.chdir(chdir)
+ cmd = []
+ if program and program[0]:
+ if not os.path.isabs(program[0]):
+ program[0] = os.path.join(self._cwd, program[0])
+ cmd += program
+ # if interpreter:
+ # cmd = interpreter + " " + cmd
+ else:
+ cmd += self.program
+ # if self.interpreter:
+ # cmd = self.interpreter + " " + cmd
+ if arguments:
+ cmd += arguments.split(" ")
+ if self.verbose:
+ sys.stderr.write(join(cmd, " ") + "\n")
+ try:
+ p = popen2.Popen3(cmd, 1)
+ except AttributeError:
+ (tochild, fromchild, childerr) = os.popen3(join(cmd, " "))
+ if stdin:
+ if type(stdin) is ListType:
+ for line in stdin:
+ tochild.write(line)
+ else:
+ tochild.write(stdin)
+ tochild.close()
+ self._stdout.append(fromchild.read())
+ self._stderr.append(childerr.read())
+ fromchild.close()
+ self.status = childerr.close()
+ if not self.status:
+ self.status = 0
+ except:
+ raise
+ else:
+ if stdin:
+ if type(stdin) is ListType:
+ for line in stdin:
+ p.tochild.write(line)
+ else:
+ p.tochild.write(stdin)
+ p.tochild.close()
+ self._stdout.append(p.fromchild.read())
+ self._stderr.append(p.childerr.read())
+ self.status = p.wait()
+
+ if self.verbose:
+ sys.stdout.write(self._stdout[-1])
+ sys.stderr.write(self._stderr[-1])
+
+ if chdir:
+ os.chdir(oldcwd)
+
+ def stderr(self, run = None):
+ """Returns the error output from the specified run number.
+ If there is no specified run number, then returns the error
+ output of the last run. If the run number is less than zero,
+ then returns the error output from that many runs back from the
+ current run.
+ """
+ if not run:
+ run = len(self._stderr)
+ elif run < 0:
+ run = len(self._stderr) + run
+ run = run - 1
+ if (run < 0):
+ return ''
+ return self._stderr[run]
+
+ def stdout(self, run = None):
+ """Returns the standard output from the specified run number.
+ If there is no specified run number, then returns the standard
+ output of the last run. If the run number is less than zero,
+ then returns the standard output from that many runs back from
+ the current run.
+ """
+ if not run:
+ run = len(self._stdout)
+ elif run < 0:
+ run = len(self._stdout) + run
+ run = run - 1
+ if (run < 0):
+ return ''
+ return self._stdout[run]
+
+ def subdir(self, *subdirs):
+ """Create new subdirectories under the temporary working
+ directory, one for each argument. An argument may be a list,
+ in which case the list elements are concatenated using the
+ os.path.join() method. Subdirectories multiple levels deep
+ must be created using a separate argument for each level:
+
+ test.subdir('sub', ['sub', 'dir'], ['sub', 'dir', 'ectory'])
+
+ Returns the number of subdirectories actually created.
+ """
+ count = 0
+ for sub in subdirs:
+ if sub is None:
+ continue
+ if type(sub) is ListType:
+ sub = apply(os.path.join, tuple(sub))
+ new = os.path.join(self.workdir, sub)
+ try:
+ os.mkdir(new)
+ except:
+ pass
+ else:
+ count = count + 1
+ return count
+
+ def unlink (self, file):
+ """Unlinks the specified file name.
+ The file name may be a list, in which case the elements are
+ concatenated with the os.path.join() method. The file is
+ assumed to be under the temporary working directory unless it
+ is an absolute path name.
+ """
+ if type(file) is ListType:
+ file = apply(os.path.join, tuple(file))
+ if not os.path.isabs(file):
+ file = os.path.join(self.workdir, file)
+ os.unlink(file)
+
+
+ def verbose_set(self, verbose):
+ """Set the verbose level.
+ """
+ self.verbose = verbose
+
+ def workdir_set(self, path):
+ """Creates a temporary working directory with the specified
+ path name. If the path is a null string (''), a unique
+ directory name is created.
+ """
+ if (path != None):
+ if path == '':
+ path = tempfile.mktemp()
+ if path != None:
+ os.mkdir(path)
+ self._dirlist.append(path)
+ global _Cleanup
+ try:
+ _Cleanup.index(self)
+ except ValueError:
+ _Cleanup.append(self)
+ # We'd like to set self.workdir like this:
+ # self.workdir = path
+ # But symlinks in the path will report things
+ # differently from os.getcwd(), so chdir there
+ # and back to fetch the canonical path.
+ cwd = os.getcwd()
+ os.chdir(path)
+ self.workdir = os.getcwd()
+ os.chdir(cwd)
+ else:
+ self.workdir = None
+
+ def workpath(self, *args):
+ """Returns the absolute path name to a subdirectory or file
+ within the current temporary working directory. Concatenates
+ the temporary working directory name with the specified
+ arguments using the os.path.join() method.
+ """
+ return apply(os.path.join, (self.workdir,) + tuple(args))
+
+ def writable(self, top, write):
+ """Make the specified directory tree writable (write == 1)
+ or not (write == None).
+ """
+
+ def _walk_chmod(arg, dirname, names):
+ st = os.stat(dirname)
+ os.chmod(dirname, arg(st[stat.ST_MODE]))
+ for name in names:
+ n = os.path.join(dirname, name)
+ st = os.stat(n)
+ os.chmod(n, arg(st[stat.ST_MODE]))
+
+ def _mode_writable(mode):
+ return stat.S_IMODE(mode|0200)
+
+ def _mode_non_writable(mode):
+ return stat.S_IMODE(mode&~0200)
+
+ if write:
+ f = _mode_writable
+ else:
+ f = _mode_non_writable
+ try:
+ os.path.walk(top, _walk_chmod, f)
+ except:
+ pass # ignore any problems changing modes
+
+ def write(self, file, content, mode = 'wb'):
+ """Writes the specified content text (second argument) to the
+ specified file name (first argument). The file name may be
+ a list, in which case the elements are concatenated with the
+ os.path.join() method. The file is created under the temporary
+ working directory. Any subdirectories in the path must already
+ exist. The I/O mode for the file may be specified; it must
+ begin with a 'w'. The default is 'wb' (binary write).
+ """
+ if type(file) is ListType:
+ file = apply(os.path.join, tuple(file))
+ if not os.path.isabs(file):
+ file = os.path.join(self.workdir, file)
+ if mode[0] != 'w':
+ raise ValueError, "mode must begin with 'w'"
+ open(file, mode).write(content)
Added: boost-jam/boost-build/branches/upstream/current/test/absolute_sources.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/absolute_sources.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/absolute_sources.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,55 @@
+#!/usr/bin/python
+
+# Test that sources with absolute names are handled OK.
+
+from BoostBuild import Tester
+t = Tester()
+
+t.write("project-root.jam", """
+path-constant TOP : . ;
+""")
+t.write("Jamfile", """
+local pwd = [ PWD ] ;
+ECHO $(pwd) XXXXX ;
+exe hello : $(pwd)/hello.cpp $(TOP)/empty.cpp ;
+""")
+t.write("hello.cpp", "int main() { return 0; }\n")
+t.write("empty.cpp", "\n")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+# Test a contrived case. There, absolute name is used in
+# standalone project (not Jamfile). Moreover, the target with
+# absolute name is returned by 'alias' and used from other project.
+t.write("a.cpp", """
+int main()
+{
+ return 0;
+}
+
+""")
+
+t.write("Jamfile", """
+exe a : /standalone//a ;
+""")
+
+t.write("project-root.jam", """
+import standalone ;
+""")
+
+t.write("standalone.jam", """
+import project ;
+
+project.initialize $(__name__) ;
+project standalone ;
+
+local pwd = [ PWD ] ;
+
+alias a : $(pwd)/a.cpp ;
+
+""")
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/absolute_sources.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/alias.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/alias.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/alias.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,75 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester, List
+t = Tester()
+
+# Test that top-level project can affect build dir
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+
+exe a : a.cpp ;
+exe b : b.cpp ;
+exe c : c.cpp ;
+
+alias bin1 : a ;
+alias bin2 : a b ;
+
+alias src : s.cpp ;
+exe hello : hello.cpp src ;
+
+""")
+t.write("a.cpp", "int main() { return 0; }\n")
+t.copy("a.cpp", "b.cpp")
+t.copy("a.cpp", "c.cpp")
+t.copy("a.cpp", "hello.cpp")
+t.write("s.cpp", "")
+
+# Check that targets to which "bin1" refers are updated,
+# and only those.
+t.run_build_system("bin1")
+t.ignore("*.tds")
+t.expect_addition(List("bin/$toolset/debug/") * "a.exe a.obj")
+t.expect_nothing_more()
+
+# Try again with "bin2"
+t.run_build_system("bin2")
+t.ignore("*.tds")
+t.expect_addition(List("bin/$toolset/debug/") * "b.exe b.obj")
+t.expect_nothing_more()
+
+# Try building everything, making sure 'hello' target is
+# created
+t.run_build_system()
+t.ignore("*.tds")
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+# Regression test.
+# Check if usage requirements are propagated via "alias"
+
+t.write("l.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+foo() {}
+
+""")
+
+t.write("Jamfile", """
+lib l : l.cpp : : : <define>WANT_MAIN ;
+alias la : l ;
+exe main : main.cpp la ;
+""")
+
+t.write("main.cpp", """
+#ifdef WANT_MAIN
+int main() { return 0; }
+#endif
+
+""")
+
+t.write("project-root.jam", "")
+
+t.run_build_system()
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/alias.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/alternatives.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/alternatives.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/alternatives.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,115 @@
+#!/usr/bin/python
+
+# Test main target alternatives.
+
+from BoostBuild import Tester
+from string import find
+t = Tester()
+
+
+# Test that basic alternatives selection works.
+t.write("project-root.jam", " ")
+t.write("Jamfile", """
+
+exe a : a_empty.cpp ;
+exe a : a.cpp : <variant>release ;
+""")
+t.write("a_empty.cpp", "")
+t.write("a.cpp", "int main() { return 0; }\n")
+
+t.run_build_system("release")
+t.expect_addition("bin/$toolset/release/a.exe")
+
+# Test that alternative selection works for ordinary
+# properties, in particular user-defined.
+t.write("project-root.jam", " ")
+t.write("Jamfile", """
+
+import feature ;
+feature.feature X : off on : propagated ;
+
+exe a : b.cpp ;
+exe a : a.cpp : <X>on ;
+""")
+t.write("b.cpp", "int main() { return 0; }\n")
+
+t.rm("bin")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/b.obj")
+
+t.run_build_system("X=on")
+t.expect_addition("bin/$toolset/debug/X-on/a.obj")
+
+t.rm("bin")
+
+# Test that everything works ok even with default
+# build.
+
+t.write("Jamfile", """
+
+exe a : a_empty.cpp : <variant>release ;
+exe a : a.cpp : <variant>debug ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+
+# Test that only properties which are in build request
+# matters when selection alternative. IOW, alternative
+# with <variant>release is better than one with
+# <variant>debug when building release version.
+t.write("Jamfile", """
+
+exe a : a_empty.cpp : <variant>debug ;
+exe a : a.cpp : <variant>release ;
+""")
+
+t.run_build_system("release")
+t.expect_addition("bin/$toolset/release/a.exe")
+
+# Test that free properties do not matter. We really don't
+# want <cxxflags> property in build request to affect
+# alternative selection.
+t.write("Jamfile", """
+exe a : a_empty.cpp : <variant>debug <define>FOO <include>BAR ;
+exe a : a.cpp : <variant>release ;
+""")
+
+t.rm("bin/$toolset/release/a.exe")
+t.run_build_system("release define=FOO")
+t.expect_addition("bin/$toolset/release/a.exe")
+
+# Test that abibuity is reported correctly
+t.write("Jamfile", """
+exe a : a_empty.cpp ;
+exe a : a.cpp ;
+""")
+t.run_build_system("--no-error-backtrace", status=1)
+t.fail_test(find(t.stdout(), "because no best-matching alternative could be found") == -1)
+
+# Another ambiguity test: two matches properties in one alternative are
+# neither better nor worse than a single one in another alternative.
+t.write("Jamfile", """
+exe a : a_empty.cpp : <optimization>off <profiling>off ;
+exe a : a.cpp : <debug-symbols>on ;
+""")
+
+t.run_build_system("--no-error-backtrace", status=1)
+t.fail_test(find(t.stdout(), "because no best-matching alternative could be found") == -1)
+
+
+
+# Test that we can have alternative without sources
+t.write("Jamfile", """
+alias specific-sources ;
+import feature ;
+feature.extend os : MAGIC ;
+alias specific-sources : b.cpp : <os>MAGIC ;
+exe a : a.cpp specific-sources ;
+""")
+t.rm("bin")
+t.run_build_system()
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/alternatives.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/assert-equal.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/assert-equal.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/assert-equal.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,29 @@
+# Evaluates [ rulename arg1... : arg2... : ... : argN... ] and compares the
+# result to expected-results. If there is a mismatch, prints an error message
+# and exits.
+rule assert-equal ( expected-results *
+ : rulename a1 * : a2 * : a3 * : a4 * : a5 * : a6 * : a7 * : a8 * : a9 * )
+{
+
+ local results = [ $(rulename) $(a1) : $(a2) : $(a3)
+ : $(a4) : $(a5) : $(a6) : $(a7) : $(a8) ] ;
+
+ if $(results) != $(expected-results)
+ {
+ EXIT ******ASSERTION FAILURE******* "
+ [ $(rulename) " $(a1)
+ ": "$(a2[1]) $(a2[2-])
+ ": "$(a3[1]) $(a3[2-])
+ ": "$(a4[1]) $(a4[2-])
+ ": "$(a5[1]) $(a5[2-])
+ ": "$(a6[1]) $(a6[2-])
+ ": "$(a7[1]) $(a7[2-])
+ ": "$(a8[1]) $(a8[2-]) "]
+expected:
+ (" $(expected-results) ")
+result was:
+ (" $(results) ")"
+ ;
+
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/test/bad_dirname.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/bad_dirname.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/bad_dirname.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,25 @@
+#!/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: when directory of project root contained regex metacharacters,
+# Boost.Build failed to work. Bug reported by Michael Stevens
+
+from BoostBuild import Tester, List
+
+t = Tester()
+
+t.write("bad[abc]dirname/Jamfile", """
+""")
+
+t.write("bad[abc]dirname/project-root.jam", """
+""")
+
+t.run_build_system(subdir="bad[abc]dirname")
+
+t.cleanup()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/bad_dirname.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,10 @@
+
+# Assume BOOST_BUILD_PATH point to the 'test' directory.
+# We need to leave 'test' there, so that 'test-config.jam'
+# can be found, but also add parent directory, to find
+# all the other modules.
+
+BOOST_BUILD_PATH = $(BOOST_BUILD_PATH)/.. $(BOOST_BUILD_PATH) ;
+
+# Find the boost build system in the ../kernel directory.
+boost-build ../kernel ;
Added: boost-jam/boost-build/branches/upstream/current/test/build_dir.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/build_dir.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/build_dir.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+
+# Test that we can change build directory using
+# the 'build-dir' project attribute.
+
+from BoostBuild import Tester
+t = Tester()
+
+
+# Test that top-level project can affect build dir
+t.write("project-root.jam", "import gcc ; ")
+t.write("Jamfile", """
+project
+ : build-dir build
+ ;
+
+exe a : a.cpp ;
+build-project src ;
+""")
+t.write("a.cpp", "int main() { return 0; }\n")
+
+t.write("src/Jamfile", "exe b : b.cpp ; ")
+t.write("src/b.cpp", "int main() { return 0; }\n")
+
+t.run_build_system()
+
+t.expect_addition(["build/$toolset/debug/a.exe",
+ "build/src/$toolset/debug/b.exe"])
+
+# Test that building from child projects work
+t.run_build_system(subdir='src')
+t.expect_nothing_more()
+
+# Test that project can override build dir
+t.write("Jamfile", """
+exe a : a.cpp ;
+build-project src ;
+""")
+
+t.write("src/Jamfile", """
+project
+ : build-dir build
+ ;
+exe b : b.cpp ;
+""")
+
+t.run_build_system()
+t.expect_addition(["bin/$toolset/debug/a.exe",
+ "src/build/$toolset/debug/b.exe"])
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/build_dir.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/c_file.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/c_file.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/c_file.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,35 @@
+#!/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.
+
+# Test that C files are compiled by C compiler
+from BoostBuild import Tester, List
+
+t = Tester()
+
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+project ;
+
+exe hello : hello.cpp a.c ;
+""")
+t.write("hello.cpp", """
+extern "C" int foo();
+int main() { return foo(); }
+""")
+t.write("a.c", """
+// This won't compile unless in C mode
+int foo()
+{
+ int new = 0;
+ new = (new+1)*7;
+ return new;
+}
+""")
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/c_file.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/chain.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/chain.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/chain.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,55 @@
+#!/usr/bin/python
+
+# This tests that
+# 1) the 'make' correctly assigns types to produced targets
+# 2) than if 'make' create targets of type CPP, they are
+# correctly used (there was a bug with it).
+
+from BoostBuild import Tester
+t = Tester()
+
+# In order to correctly link this app, 'b.cpp', created by 'make'
+# rule, should be compiled.
+t.write("project-root.jam", "import gcc ;")
+t.write("Jamfile", r'''
+rule create ( dst : src * : properties * )
+{
+ # hack to echo a space under NT
+ setup on $(dst) = "set x=int main(){ return 0; }" ;
+}
+
+import modules ;
+if [ modules.peek : NT ]
+{
+ actions create
+ {
+ $(setup)
+ echo %x% > $(<)
+ }
+}
+else
+{
+ actions create
+ {
+ echo "int main(){ return 0; }" > $(<)
+ }
+}
+
+IMPORT $(__name__) : create : : create ;
+
+exe a : l dummy.cpp ;
+
+# needs to be static lib for Windows - main cannot appear in DLL
+static-lib l : a.cpp b.cpp ;
+
+make b.cpp : : create ;
+
+''')
+t.write("a.cpp", "")
+t.write("dummy.cpp", "// msvc needs at least one object file\n")
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/a.exe")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/chain.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/check-arguments.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/check-arguments.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/check-arguments.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,73 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+#
+# Jam code for testing the named-argument patch.
+#
+
+include recursive.jam ;
+
+# Prefixes for all of the jam code we're going to test
+local ECHO_ARGS = "include echo_args.jam ; echo_args "
+ ;
+
+local ECHO_VARARGS = "include echo_args.jam ; echo_varargs "
+ ;
+
+# Check that it will find missing arguments
+Jam-fail $(ECHO_ARGS)";"
+ : "missing argument a"
+ ;
+
+# Check that it will find if too many arguments are passed
+Jam-fail $(ECHO_ARGS)"1 2 : 3 : 4 : 5 ;"
+ : "extra argument 5"
+ ;
+
+# Check that it will find when an argument has too many elements
+Jam-fail $(ECHO_ARGS)"a b c1 c2 : d ;"
+ : "extra argument c2"
+ ;
+
+# Check modifier '?'
+Jam $(ECHO_ARGS)"1 2 3 : 4 ;"
+ : "a= 1 b= 2 c= 3 : d= 4 : e=" ;
+Jam $(ECHO_ARGS)"1 2 : 3 ;"
+ : "a= 1 b= 2 c= : d= 3 : e=" ;
+Jam $(ECHO_ARGS)"1 : 2 ;"
+ : "a= 1 b= c= : d= 2 : e=" ;
+
+# Check modifier '+'
+Jam-fail $(ECHO_ARGS)"1 ;"
+ : "missing argument d" ;
+Jam $(ECHO_ARGS)"1 : 2 3 ;"
+ : "a= 1 b= c= : d= 2 3 : e=" ;
+Jam $(ECHO_ARGS)"1 : 2 3 4 ;"
+ : "a= 1 b= c= : d= 2 3 4 : e=" ;
+
+# Check modifier '*'
+Jam $(ECHO_ARGS)"1 : 2 : 3 ;"
+ : "a= 1 b= c= : d= 2 : e= 3" ;
+Jam $(ECHO_ARGS)"1 : 2 : 3 4 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4" ;
+Jam $(ECHO_ARGS)"1 : 2 : 3 4 5 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4 5" ;
+
+#
+# Check varargs
+#
+Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4 5" ;
+Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 : 6 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6" ;
+Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 : 6 7 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7" ;
+Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 : 6 7 : 8 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7 : 8" ;
+Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 : 6 7 : 8 : 9 ;"
+ : "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7 : 8 : 9" ;
+
+
Added: boost-jam/boost-build/branches/upstream/current/test/check-bindrule.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/check-bindrule.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/check-bindrule.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,25 @@
+# This rule establishes a dependency, with no special build actions
+rule do-nothing ( target : source )
+{
+ DEPENDS $(target) : $(source) ;
+}
+actions quietly do-nothing
+{
+}
+
+# Make a non-file target which depends on a file that exists
+NOTFILE fake-target ;
+SEARCH on file-to-bind = subdir1 ;
+
+do-nothing fake-target
+ : file-to-bind ;
+
+# Set jam up to call our bind-rule
+BINDRULE = bind-rule ;
+
+rule bind-rule ( target : path )
+{
+ ECHO found: $(target) at $(path) ;
+}
+
+DEPENDS all : fake-target ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/check-jam-patches.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/check-jam-patches.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/check-jam-patches.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,289 @@
+# Get the recursive Jam invocation code
+include recursive.jam ;
+include assert-equal.jam ;
+
+Jam "include check-bindrule.jam ;"
+ : "found: file-to-bind at subdir1$(SLASH)file-to-bind"
+ ;
+
+include check-arguments.jam ;
+
+if $(NT)
+{
+ # if this one fails, you don't have the line length patch
+ Jam "include test_nt_line_length.jam ;" ;
+}
+
+# a little utility for assertions
+rule identity ( list * )
+{
+ return $(list) ;
+}
+
+#
+# test rule indirection
+#
+rule select ( n list * )
+{
+ return $(list[$(n)]) ;
+}
+
+rule indirect1 ( rule + : args * )
+{
+ return [ $(rule) $(args) ] ;
+}
+
+assert-equal a : indirect1 select 1 : a b c d e ;
+assert-equal b : indirect1 select 2 : a b c d e ;
+
+x = reset ;
+rule reset-x ( new-value )
+{
+ x = $(new-value) ;
+}
+$(x)-x bar ; # invokes reset-x...
+assert-equal bar : identity $(x) ; # which changes x
+
+# Check that unmatched subst returns an empty list
+assert-equal # nothing
+ : SUBST "abc" "d+" x ;
+
+# Check that a matched subst works
+assert-equal x
+ : SUBST "ddd" "d+" x ;
+
+# Check that we can get multiple substitutions from a single invocation
+assert-equal x y x-y
+ : SUBST "x/y/z" "([^/]*)/([^/]*).*" "\\1" $2 "\\1-\\2" ;
+
+#
+# test local foreach modification
+#
+{
+ local x = 0 ;
+ local entered = ;
+ for local x in a b c # x declared local to for loop.
+ {
+ entered = 1 ;
+ if ! ( $(x) in a b c )
+ {
+ EXIT "local foreach: expected one of a, b, c; got" $(x) ;
+ }
+ }
+
+ if $(x) != 0 # if x was modified, it failed to be a local variable
+ {
+ EXIT "local foreach failed" ;
+ }
+}
+
+#
+# test while loops
+#
+{
+ local x = a b c ;
+ local y = $(x) ;
+ local z = ;
+
+ while $(y)
+ {
+ z += $(y[1]) ;
+ y = $(y[2-]) ;
+ }
+
+ if $(z) != $(x)
+ {
+ EXIT "while loops failed" ;
+ }
+}
+
+#
+# test negative list indices and slices
+#
+{
+ local x = a b c d e ;
+
+ rule assert-index ( index : list * )
+ {
+ if $(x[$(index)]) != $(list)
+ {
+ ECHO with x= $(x) ;
+ ECHO x[$(index)] == $(x[$(index)]) ;
+ EXIT expected $(list) ;
+ }
+ }
+
+ assert-index 1 : a ;
+ assert-index 3 : c ;
+ assert-index 1-2 : a b ;
+ assert-index -1 : e ;
+ assert-index -2 : d ;
+ assert-index 2--2 : b c d ;
+ assert-index -3--2 : c d ;
+ assert-index 1--2 : a b c d ;
+ assert-index 1--2 : a b c d ;
+ assert-index 1--10 : ;
+ x = a ;
+ assert-index 1--2 : ;
+ assert-index 1--2 : ;
+}
+
+#
+# test module primitives
+#
+{
+ local x = a b c d e f g h i j ;
+ local y = $(x[3-]) ;
+
+ rule shift1 ( dummy ) { }
+
+ rule my_module.not_really ( ) { return something ; }
+
+ # import the identity rule into my_module as "id"
+ IMPORT : identity : my_module : id ;
+ module my_module
+ {
+ # assert-equal operates in its own module, so call id in here and use
+ # identity later.
+ local f = [ id x y z ] ;
+ assert-equal x y z : identity $(f) ;
+
+ w = ;
+ y = ;
+ x2 = 1 2 3 ;
+ x3 = $(x2) ;
+ z = $(x2) ;
+
+ x3 = ; # should reset x3
+
+ # drops one element from the head of x
+ # moves the first element of z from the head of z to the head of y
+ rule shift1 ( )
+ {
+ x = $(x[2-]) ;
+ y = $(z[1]) $(y) ;
+ z = $(z[2-]) ;
+ }
+
+ rule shift2 ( )
+ {
+ shift1 ;
+ }
+
+ shift1 ;
+ shift2 ;
+
+ rule get ( symbol )
+ {
+ return $($(symbol)) ;
+ }
+ local rule not_really ( ) { return nothing ; }
+ }
+
+ local expected = shift1 shift2 get ;
+ if ! ( $(expected) in [ RULENAMES my_module ] )
+ || ! ( [ RULENAMES my_module ] in $(expected) )
+ {
+ EXIT "[ RULENAMES my_module ] =" [ RULENAMES my_module ] "!=" shift1 shift2 get ;
+ }
+
+
+ # show that not_really was actually a local definition
+ assert-equal something : my_module.not_really ;
+
+ if not_really in [ RULENAMES my_module ]
+ {
+ EXIT unexpectedly found local rule "not_really" in "my_module" ;
+ }
+ EXPORT my_module : not_really ;
+
+ if ! ( not_really in [ RULENAMES my_module ] )
+ {
+ EXIT unexpectedly failed to find exported rule "not_really" in "my_module" ;
+ }
+
+ # show that my_module doesn't have access to our variables
+ my_module.shift1 ;
+ assert-equal $(x[3-]) : identity $(y) ;
+
+ # check module locals
+ assert-equal : my_module.get w ;
+ assert-equal 3 2 1 : my_module.get y ;
+ assert-equal 1 2 3 : my_module.get x2 ;
+ assert-equal : my_module.get x3 ;
+ assert-equal : my_module.get z ;
+
+ my_module.shift2 ;
+ x = $(x[3-]) ;
+ assert-equal $(x) : identity $(y) ;
+
+ # Prove that the module's rule is not exposed to the world at large without
+ # qualification
+ shift1 nothing ;
+ assert-equal $(x) : identity $(y) ;
+
+ # import my_module.shift1 into the global module as "shifty", and
+ # my_module.shift2 into the global module as "shift2".
+ IMPORT my_module : shift1 shift2 : : shifty shift2 ;
+
+ shifty ;
+ assert-equal $(x) : identity $(y) ;
+
+ shift2 ;
+ assert-equal $(x) : identity $(y) ;
+
+ # Now do the same with localization
+ IMPORT my_module : shift1 : : shifty : LOCALIZE ;
+
+ shifty ;
+ y = $(y[3-]) ;
+ assert-equal $(x) : identity $(y) ;
+
+ # import everything from my_module into the global module using
+ # the same names.
+ IMPORT my_module : [ RULENAMES my_module ] : : [ RULENAMES my_module ] : LOCALIZE ;
+
+ shift1 ;
+ y = $(y[2-]) ;
+ assert-equal $(x) : identity $(y) ;
+
+ shift2 ;
+ y = $(y[2-]) ;
+ assert-equal $(x) : identity $(y) ;
+}
+
+#
+# test CALLER_MODULE and backtrace
+#
+{
+ rule backtrace ( )
+ {
+ local bt = [ BACKTRACE ] ;
+ bt = $(bt[5-]) ;
+ while $(bt)
+ {
+ ECHO $(bt[1]):$(bt[2]): "in" $(bt[4]) ;
+ bt = $(bt[5-]) ;
+ }
+ }
+ module module1
+ {
+ rule f ( )
+ {
+ local m = [ CALLER_MODULE ] ;
+ assert-equal : identity $(m) ;
+ module2.f ;
+ }
+
+ }
+ module module2
+ {
+ rule f ( )
+ {
+ local m = [ CALLER_MODULE ] ;
+ assert-equal module1 : identity $(m) ;
+ backtrace ;
+ }
+ }
+ module1.f ;
+}
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/check-test-tools.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/check-test-tools.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/check-test-tools.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,22 @@
+include recursive.jam ;
+include assert-equal.jam ;
+
+#####################################
+# Test the testing tools right here #
+#####################################
+
+# This command always exits with a failure.
+Jam-fail "EXIT error ;" ;
+
+# This should fail to fail
+Jam-fail
+ "include recursive.jam ; Jam-fail \"# this innocuous Jamfile should fail to fail\" ;"
+ ;
+
+# the ECHO rule always has an empty result.
+Jam-fail "include assert-equal.jam ; assert-equal fubar : ECHO checking that assertions fail ;"
+ : "ASSERTION FAILURE"
+ ;
+
+local NOTHING = ;
+assert-equal $(NOTHING) : ECHO checking that assertions succeed ;
Added: boost-jam/boost-build/branches/upstream/current/test/composite.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/composite.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/composite.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,30 @@
+#!/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.
+
+# Test that composite properties are handled correctly.
+from BoostBuild import Tester, List
+
+t = Tester()
+
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+exe hello : hello.cpp : <variant>release ;
+""")
+t.write("hello.cpp", """
+int main()
+{
+ return 0;
+}
+
+""")
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/release/hello.exe")
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/composite.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/conditionals.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/conditionals.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/conditionals.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,50 @@
+#!/usr/bin/python
+
+# Test conditional properties
+
+from BoostBuild import Tester, List
+import os
+from string import strip
+
+t = Tester()
+
+# Arrange a project which will build only if
+# 'a.cpp' is compiled with "STATIC" define.
+t.write("project-root.jam", "import gcc ;")
+t.write("a.cpp", """
+#ifdef STATIC
+int main() { return 0; }
+#endif
+""")
+t.write("Jamfile", "exe a : a.cpp : <link>static:<define>STATIC ;")
+t.run_build_system("link=static")
+t.expect_addition("bin/$toolset/debug/link-static/a.exe")
+
+t.write("Jamfile", """
+project : requirements <link>static:<define>STATIC ;
+exe a : a.cpp ;
+""")
+t.rm("bin")
+t.run_build_system("link=static")
+t.expect_addition("bin/$toolset/debug/link-static/a.exe")
+
+# Regression test for a bug found by Ali Azarbayejani.
+# Conditionals inside usage requirement were not evaluated.
+# This breaks
+
+t.write("Jamfile", """
+lib l : l.cpp : : : <link>static:<define>STATIC ;
+exe a : a.cpp l ;
+""")
+t.write("l.cpp", "")
+t.write("l.cpp", """
+int i;
+""")
+
+t.rm("bin")
+t.run_build_system("link=static")
+t.expect_addition("bin/$toolset/debug/link-static/a.exe")
+
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/conditionals.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/conditionals2.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/conditionals2.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/conditionals2.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,49 @@
+#!/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: it was possible that due to evaluation of conditional
+# requirements, two different values of non-free features were present in
+# property set.
+
+from BoostBuild import Tester, List
+
+t = Tester()
+
+t.write("project-root.jam", "")
+
+t.write("a.cpp", "")
+
+t.write("Jamfile", """
+import feature : feature ;
+import common : file-creation-command ;
+
+feature the_feature : false true : propagated ;
+
+rule maker ( targets * : sources * : properties * )
+{
+ if <the_feature>false in $(properties)
+ && <the_feature>true in $(properties)
+ {
+ EXIT "Oops, two different values of non-free feature" ;
+ }
+ CMD on $(targets) = [ file-creation-command ] ;
+}
+
+actions maker
+{
+ $(CMD) $(<) ;
+}
+
+make a : a.cpp : maker : <variant>debug:<the_feature>true ;
+""")
+
+t.run_build_system()
+
+t.cleanup()
+
+
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/conditionals2.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/conditionals3.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/conditionals3.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/conditionals3.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,34 @@
+#!/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.
+
+# Test that conditional properties work, even if property is free, and
+# value includes colon.
+from BoostBuild import Tester, List
+
+
+t = Tester()
+
+# Create the needed files
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+exe hello : hello.cpp : <variant>debug:<define>CLASS=Foo::Bar ;
+""")
+t.write("hello.cpp", """
+namespace Foo { class Bar { } ; }
+int main()
+{
+ CLASS c;
+ return 0;
+}
+
+""")
+
+# Don't check stderr, which can include warning about unused 'c'.
+t.run_build_system(stdout=None, stderr=None)
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/conditionals3.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/core_d12.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/core_d12.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/core_d12.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+
+# This tests correct handling of "-d1" and "-d2" options.
+
+import BoostBuild
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write("file.jam", """
+actions a {
+}
+
+actions quietly b {
+}
+
+ALWAYS all ;
+
+a all ;
+b all ;
+""")
+
+t.run_build_system("-ffile.jam -d0", stdout="")
+
+t.run_build_system("-ffile.jam -d1", stdout=
+"""...found 1 target...
+...updating 1 target...
+a all
+...updated 1 target...
+""")
+
+t.run_build_system("-ffile.jam -d2")
+
+t.fail_test(t.stdout().find("a all") == -1)
+t.fail_test(t.stdout().find("b all") == -1)
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/core_d12.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/core_delete_module.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/core_delete_module.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/core_delete_module.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+
+# This tests the facilities for deleting modules.
+
+import BoostBuild
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write("file.jam", """
+module foo
+{
+ rule bar { }
+ var = x y ;
+}
+DELETE_MODULE foo ;
+if [ RULENAMES foo ]
+{
+ EXIT DELETE_MODULE failed to kill foo's rules: [ RULENAMES foo ] ;
+}
+
+module foo
+{
+ if $(var)
+ {
+ EXIT DELETE_MODULE failed to kill foo's variables ;
+ }
+
+ rule bar { }
+ var = x y ;
+
+ DELETE_MODULE foo ;
+
+ if $(var)
+ {
+ EXIT internal DELETE_MODULE failed to kill foo's variables ;
+ }
+ if [ RULENAMES foo ]
+ {
+ EXIT internal DELETE_MODULE failed to kill foo's rules: [ RULENAMES foo ] ;
+ }
+}
+DEPENDS all : xx ;
+NOTFILE xx ;
+""")
+
+t.run_build_system("-ffile.jam", status=0)
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/core_delete_module.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/core_dependencies.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/core_dependencies.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/core_dependencies.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,152 @@
+#!/usr/bin/python
+
+# This tests correct handling of dependencies, specifically, on
+# generated sources, and from generated sources.
+
+import BoostBuild
+from string import find
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write("core-dependency-helpers", """
+rule hdrrule
+{
+ INCLUDES $(1) : $(2) ;
+}
+actions copy
+{
+ cp $(>) $(<)
+}
+""")
+
+code = """include core-dependency-helpers ;
+DEPENDS all : a ;
+DEPENDS a : b ;
+
+actions create-b
+{
+ echo '#include <foo.h>' > $(<)
+}
+copy a : b ;
+create-b b ;
+HDRRULE on b foo.h bar.h = hdrrule ;
+HDRSCAN on b foo.h bar.h = \"#include <(.*)>\" ;
+"""
+
+# This creates 'a' which depends on 'b', which is generated.
+# The generated 'b' contains '#include <foo.h>' and no rules for
+# foo.h are given. The system should error out on the first invocation.
+t.run_build_system("-f-", stdin=code)
+t.fail_test(find(t.stdout(), "...skipped a for lack of foo.h...") == -1)
+
+t.rm('b')
+# Now test that if target 'c' also depends on 'b', then it won't be built, as well.
+t.run_build_system("-f-", stdin=code + " copy c : b ; DEPENDS c : b ; DEPENDS all : c ; ")
+t.fail_test(find(t.stdout(), "...skipped c for lack of foo.h...") == -1)
+
+
+# Now add a rule for creating foo.h
+t.rm('b')
+code += """
+actions create-foo
+{
+ echo // > $(<)
+}
+create-foo foo.h ;
+"""
+t.run_build_system("-f-", stdin=code)
+
+# Run two times, adding explicit dependency from all to foo.h at
+# the beginning and at the end, to make sure that foo.h is generated before
+# 'a' in all cases.
+
+def mk_right_order_func(s1, s2):
+ def right_order(s):
+ n1 = find(s, s1)
+ n2 = find(s, s2)
+ return n1 != -1 and n2 != -1 and n1 < n2
+ return right_order
+
+right_order = mk_right_order_func("create-foo", "copy a")
+
+t.rm(["a", "b", "foo.h"])
+t.run_build_system("-d+2 -f-", stdin=code + " DEPENDS all : foo.h ;")
+t.fail_test(not right_order(t.stdout()))
+
+t.rm(["a", "b", "foo.h"])
+t.run_build_system("-d+2 -f-", stdin=" DEPENDS all : foo.h ; " + code)
+t.fail_test(not right_order(t.stdout()))
+
+# Now foo.h exists. Test include from b -> foo.h -> bar.h -> biz.h
+# b and foo.h already have updating actions.
+t.rm(["a", "b"])
+t.write("foo.h", "#include <bar.h>")
+t.write("bar.h", "#include <biz.h>")
+t.run_build_system("-d+2 -f-", stdin=code)
+t.fail_test(find(t.stdout(), "...skipped a for lack of biz.h...") == -1)
+
+# Add an action for biz.h
+code += """
+actions create-biz
+{
+ echo // > $(<)
+}
+create-biz biz.h ;
+"""
+t.rm(["b"])
+right_order = mk_right_order_func("create-biz", "copy a")
+t.run_build_system("-d+2 -f-", stdin=code + " DEPENDS all : biz.h ;")
+t.fail_test(not right_order(t.stdout()))
+
+t.rm(["a", "biz.h"])
+t.run_build_system("-d+2 -f-", stdin=" DEPENDS all : biz.h ; " + code)
+t.fail_test(not right_order(t.stdout()))
+
+
+t.write("a", "")
+
+code="""
+DEPENDS all : main d ;
+
+actions copy
+{
+ cp $(>) $(<) ;
+}
+
+DEPENDS main : a ;
+copy main : a ;
+
+INCLUDES a : <1>c ;
+
+NOCARE <1>c ;
+SEARCH on <1>c = . ;
+
+actions create-c
+{
+ echo d > $(<)
+}
+
+actions create-d
+{
+ echo // > $(<)
+}
+
+create-c <2>c ;
+LOCATE on <2>c = . ;
+create-d d ;
+
+HDRSCAN on <1>c = (.*) ;
+HDRRULE on <1>c = hdrrule ;
+
+rule hdrrule
+{
+ INCLUDES $(1) : d ;
+}
+"""
+right_order = mk_right_order_func("create-d", "copy main")
+t.run_build_system("-d2 -f-", stdin=code)
+t.fail_test(not right_order(t.stdout()))
+
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/core_dependencies.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/core_import_module.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/core_import_module.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/core_import_module.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,65 @@
+#!/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.
+
+from BoostBuild import Tester, List
+
+
+t = Tester(pass_toolset=0)
+
+# Test that
+
+t.write("code", """
+module a {
+ rule r1 ( )
+ {
+ ECHO R1 ;
+ }
+}
+module a2 {
+ rule r2 ( )
+ {
+ ECHO R2 ;
+ }
+}
+IMPORT a2 : r2 : : a2.r2 ;
+
+module b {
+ IMPORT_MODULE a : b ;
+
+ rule test
+ {
+ # Call rule visible via IMPORT_MODULE
+ a.r1 ;
+ # Call rule in global scope
+ a2.r2 ;
+ }
+}
+
+IMPORT b : test : : test ;
+test ;
+
+module c {
+ rule test
+ {
+ ECHO CTEST ;
+ }
+}
+
+IMPORT_MODULE c : ;
+c.test ;
+
+actions do-nothing { }
+do-nothing all ;
+
+""")
+
+t.run_build_system("-fcode", stdout="""R1
+R2
+CTEST
+""")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/core_import_module.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/core_modifiers.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/core_modifiers.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/core_modifiers.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,56 @@
+#!/usr/bin/python
+
+# This tests the "existing" and "updated" modifiers on actions.
+
+import BoostBuild
+from string import strip, replace
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+code = """
+
+DEPENDS all : a ;
+ALWAYS a ;
+NOTFILE a ;
+
+actions existing make-a
+{
+ echo $(>) > list
+}
+make-a a : a-1 a-2 a-3 ;
+DEPENDS a : a-1 a-2 a-3 ;
+NOCARE a-1 a-2 ;
+
+actions make-a3
+{
+ echo foo > $(<)
+}
+make-a3 a-3 ;
+"""
+
+t.write("file.jam", code)
+t.write("a-1", "")
+
+t.run_build_system("-ffile.jam")
+t.fail_test(strip(t.read("list")) != "a-1")
+t.rm(["a-3", "list"])
+
+code = replace(code, "existing", "updated")
+t.write("file.jam", code)
+t.run_build_system("-ffile.jam")
+t.fail_test(strip(t.read("list")) != "a-3")
+
+code = replace(code, "updated", "existing updated")
+t.write("file.jam", code)
+t.run_build_system("-ffile.jam")
+t.fail_test(strip(t.read("list")) != "a-1 a-3")
+
+
+
+
+
+
+
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/core_modifiers.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/core_typecheck.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/core_typecheck.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/core_typecheck.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,43 @@
+#!/usr/bin/python
+
+# This tests the typechecking facilities.
+
+import BoostBuild
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write("file.jam", """
+module .typecheck
+{
+ rule [path] ( x )
+ {
+ if ! [ MATCH "^(::)" : $(x) ]
+ {
+ ECHO "Error: $(x) is not a path" ;
+ return true ;
+ }
+ }
+}
+
+rule do ( [path] a )
+{
+}
+
+do $(ARGUMENT) ;
+
+actions dummy { }
+dummy all ;
+""")
+
+t.run_build_system("-ffile.jam -sARGUMENT=::a/b/c")
+t.run_build_system("-ffile.jam -sARGUMENT=a/b/c", status=1,
+ stdout="""Error: a/b/c is not a path
+file.jam:18: in module scope
+*** argument error
+* rule do ( [path] a )
+* called with: ( a/b/c )
+* true a
+file.jam:16:see definition of rule 'do' being called
+""")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/core_typecheck.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/core_varnames.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/core_varnames.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/core_varnames.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+
+# This tests the core rule for enumerating the variable names in a module
+
+import BoostBuild
+
+t = BoostBuild.Tester(pass_toolset=0)
+
+t.write("file.jam", """
+module foo
+{
+ rule bar { }
+ var1 = x y ;
+ var2 = fubar ;
+}
+
+expected = var1 var2 ;
+names = [ VARNAMES foo ] ;
+if $(names) in $(expected) && $(expected) in $(names)
+{
+ # everything OK
+}
+else
+{
+ EXIT expected to find variables $(expected:J=", ") in module foo,
+ but found $(names:J=", ") instead. ;
+}
+DEPENDS all : xx ;
+NOTFILE xx ;
+""")
+
+t.run_build_system("-ffile.jam", status=0)
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/core_varnames.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/custom_generator.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/custom_generator.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/custom_generator.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,56 @@
+#!/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.
+
+
+from BoostBuild import Tester, List
+
+
+t = Tester()
+
+# Attempt to declare a generator for creating OBJ from RC files.
+# That generator should be considered together with standard
+# CPP->OBJ generators and successfully create the target.
+# Since we don't have RC compiler everywhere, we fake the action.
+# The resulting OBJ will be unusable, but it must be created.
+
+t.write("project-root.jam", """
+import rcc ;
+""")
+
+t.write("rcc.jam", """
+import type ;
+import generators ;
+import print ;
+
+# Use 'RCC' to avoid conflicts with definitions in
+# the standard rc.jam and msvc.jam
+type.register RCC : rcc ;
+
+rule resource-compile ( targets * : sources * : properties * )
+{
+ print.output $(targets[1]) ;
+ print.text "rc-object" ;
+}
+
+generators.register-standard rcc.resource-compile : RCC : OBJ ;
+
+""")
+
+t.write("Jamfile", """
+obj r : r.rcc ;
+""")
+
+t.write("r.rcc", """
+""")
+
+t.run_build_system()
+t.expect_content("bin/$toolset/debug/r.obj", "rc-object\n")
+
+t.cleanup()
+
+
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/custom_generator.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/default_build.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/default_build.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/default_build.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,87 @@
+#!/usr/bin/python
+
+# Test that default build clause actually has any effect.
+
+from BoostBuild import Tester, List
+t = Tester()
+
+t.write("project-root.jam", "import gcc ;")
+t.write("Jamfile", "exe a : a.cpp : : debug release ;")
+t.write("a.cpp", "int main() { return 0; }\n")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+t.expect_addition("bin/$toolset/release/a.exe")
+
+# Check that explictly-specified build variant supresses
+# default-build
+t.rm("bin")
+t.run_build_system("release")
+t.expect_addition(List("bin/$toolset/release/") * "a.exe a.obj")
+t.expect_nothing_more()
+
+# Now check that we can specify explicit build request and
+# default-build will be combined with it
+t.run_build_system("optimization=space")
+t.expect_addition("bin/$toolset/debug/optimization-space/a.exe")
+t.expect_addition("bin/$toolset/release/optimization-space/a.exe")
+
+# Test that default-build must be identical in all alternatives. Error case.
+t.write("Jamfile", """
+exe a : a.cpp : : debug ;
+exe a : b.cpp : : ;
+""")
+expected="""error: default build must be identical in all alternatives
+main target is ./a
+with
+differing from previous default build <variant>debug
+
+"""
+t.run_build_system("-n --no-error-backtrace", status=1, stdout=expected)
+
+# Test that default-build must be identical in all alternatives. No Error case, empty default build.
+t.write("Jamfile", """
+exe a : a.cpp : <variant>debug ;
+exe a : b.cpp : <variant>release ;
+""")
+t.run_build_system("-n --no-error-backtrace", status=0)
+
+
+# Now try a harder example: default build which contains <define>
+# should cause <define> to be present when "b" is compiled.
+# This happens only of "build-project b" is placed first.
+t.write("Jamfile", """
+ project
+ : default-build <define>FOO
+ ;
+
+ build-project a ;
+ build-project b ;
+""")
+
+t.write("a/Jamfile", """
+ exe a : a.cpp ../b//b ;
+""")
+t.write("a/a.cpp", """
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+void foo();
+int main() { foo(); return 0; }
+""")
+
+t.write("b/Jamfile", """
+ lib b : b.cpp ;
+""")
+t.write("b/b.cpp", """
+#ifdef FOO
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {}
+#endif
+""")
+
+t.run_build_system()
+
+t.cleanup()
Added: boost-jam/boost-build/branches/upstream/current/test/default_features.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/default_features.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/default_features.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,57 @@
+#!/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.
+
+# Test that features with default values are always present
+# in build properties of any target.
+
+from BoostBuild import Tester, List
+
+t = Tester()
+
+# Declare *non-propagated* feature foo.
+t.write("project-root.jam", """
+import feature : feature ;
+
+feature foo : on off ;
+""")
+
+# Note that '<foo>on' won't be propagated
+# to 'd/l'.
+t.write("Jamfile", """
+exe hello : hello.cpp d//l ;
+""")
+t.write("hello.cpp", """
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+void foo();
+int main()
+{
+ foo();
+ return 1;
+}
+
+""")
+
+t.write("d/Jamfile", """
+lib l : l.cpp : <foo>on:<define>FOO ;
+""")
+t.write("d/l.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+#ifdef FOO
+void foo() {}
+#endif
+
+""")
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/hello.exe")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/default_features.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,21 @@
+
+project test
+ : requirements <include>src1
+ ;
+
+exe a
+ : x.foo a.cpp
+ ;
+
+exe b
+ : b.cpp
+ ;
+
+# Because of <define>, c.cpp will be compiled to different
+# directory than everything for main target "a". Therefore
+# without <implicit-dependency>, it won't find "x.h", which is part
+# of "a"'s dependency graph.
+exe c
+ : c.cpp
+ : <define>FOO <implicit-dependency>a
+ ;
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/a.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/a.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/a.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,17 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#include <a.h>
+# include "a.h"
+#include <x.h>
+
+int main()
+{
+ return 0;
+}
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/a.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/a.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/a.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/b.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/b.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/b.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,14 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#include "a.h"
+
+int main()
+{
+}
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/b.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/b.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/b.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/c.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/c.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/c.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,14 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#include "x.h"
+
+int main()
+{
+}
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/e.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/e.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/e.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,15 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#include "x.h"
+
+int main()
+{
+ return 0;
+}
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/foo.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/foo.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/foo.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,35 @@
+import type ;
+import generators ;
+import os ;
+import print ;
+
+type.register FOO : foo ;
+
+generators.register-standard foo.foo : FOO : CPP H ;
+
+rule foo ( targets * : sources * : properties * )
+{
+ # On NT, you need an exported symbol in order to have an import lib generated
+ if [ os.name ] = NT && <main-target-type>LIB in $(properties)
+ {
+ .decl = "echo void __declspec(dllexport) foo(){}" ;
+ }
+ if [ modules.peek : OS ] in CYGWIN && <main-target-type>LIB in $(properties) && $toolset != gcc
+ {
+ .decl = "echo 'void __declspec(dllexport) foo(){}'" ;
+ }
+
+
+ .decl1 on $(<) = $(.decl:E="echo //") ;
+
+ # Further files must be touched also; NT doesn't have a touch command
+ local i = [ print.echo-cmd "#include <z.h>" ] ;
+ .decl2 on $(<) = "
+ $(i) > " ;
+}
+
+actions foo
+{
+ $(.decl1) > $(<[1]) $(.decl2)$(<[2-])
+}
+
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,3 @@
+
+import gcc ;
+import foo ;
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/a.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/a.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/a.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,10 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#include "b.h"
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/b.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/b.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/b.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,10 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#include "c.h"
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/c.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/c.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/c.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/z.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/z.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/src1/z.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/src2/b.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency-test/src2/b.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency-test/src2/b.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/x.foo
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/test/dependency-test/y.foo
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/test/dependency_property.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency_property.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency_property.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,42 @@
+#!/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: virtual targets with different dependency properties
+# were considered different by 'virtual-target.register', but the code
+# which determined target paths ignored dependency properties --- so both
+# targets used to be placed to the same location.
+
+from BoostBuild import Tester, List
+from string import find
+
+
+t = Tester()
+
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+lib foo : foo.cpp ;
+exe hello : hello.cpp ;
+exe hello2 : hello.cpp : <library>foo ;
+""")
+t.write("hello.cpp", """
+int main()
+{
+ return 0;
+}
+
+""")
+t.write("foo.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {}
+""")
+
+t.run_build_system("--no-error-backtrace", status=1)
+t.fail_test(find(t.stdout(), "Duplicate name of actual target") == -1)
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/dependency_property.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/dependency_test.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dependency_test.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dependency_test.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester, List
+
+t = Tester()
+
+t.set_tree("dependency-test")
+t.run_build_system()
+# Check that main target 'c' was able to find 'x.h' from
+# 'a's dependency graph
+t.expect_addition("bin/$toolset/debug/c.exe")
+
+# Check handling of first level includes.
+
+# Both 'a' and 'b' include "a.h" and should be updated
+t.touch("a.h")
+t.run_build_system()
+
+t.expect_touch("bin/$toolset/debug/a.exe")
+t.expect_touch("bin/$toolset/debug/a.obj")
+t.expect_touch("bin/$toolset/debug/b.exe")
+t.expect_touch("bin/$toolset/debug/b.obj")
+# Now, <dependency> does not add dependency.
+# It sound weird, but is intentional. Need
+# to rename <dependency> eventually.
+#t.expect_touch("bin/$toolset/debug/main-target-c/c.exe")
+t.ignore("*.tds")
+t.expect_nothing_more()
+
+# Only 'a' include <a.h> and should be updated
+t.touch("src1/a.h")
+t.run_build_system()
+
+t.expect_touch("bin/$toolset/debug/a.exe")
+t.expect_touch("bin/$toolset/debug/a.obj")
+t.ignore("*.tds")
+t.expect_nothing_more()
+
+# "src/a.h" includes "b.h" (in the same dir)
+t.touch("src1/b.h")
+t.run_build_system()
+t.expect_touch("bin/$toolset/debug/a.exe")
+t.expect_touch("bin/$toolset/debug/a.obj")
+t.ignore("*.tds")
+t.expect_nothing_more()
+
+# included by "src/b.h". We had a bug: file included via "",
+# like "b.h" is in this case was not scanned at all.
+t.touch("src1/c.h")
+t.run_build_system()
+t.expect_touch("bin/$toolset/debug/a.exe")
+
+t.touch("b.h")
+t.run_build_system()
+t.expect_nothing_more()
+
+# Test dependency on generated header.
+# TODO: we have also to check that generated header is found correctly
+# if it is different for different subvariants. Lacking any toolset
+# support, this check will be implemented later.
+t.touch("x.foo")
+t.run_build_system()
+t.expect_touch("bin/$toolset/debug/a.obj")
+
+# Check that generated headers are scanned for dependencies as well
+t.touch("src1/z.h")
+t.run_build_system()
+t.expect_touch("bin/$toolset/debug/a.obj")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/dependency_test.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/direct-request-test/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/direct-request-test/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/direct-request-test/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,9 @@
+
+# This will link correctly only if symbol MACROS is defined when compiling
+# b.cpp. However, this is only possible if that symbol is requested
+# on command line and b.cpp is compiled with directly requested
+# properties.
+
+exe a : a.cpp b ;
+
+lib b : b.cpp ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/direct-request-test/Jamfile2
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/direct-request-test/Jamfile2 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/direct-request-test/Jamfile2 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,9 @@
+
+# This will link correctly only if symbol MACROS is not defined when
+# compiling b.cpp. This tests if direct build request
+# 'release <define>MACROS' to 'b' does not add 'MACROS' when 'b'
+# is compiled with 'debug' -- the version needed by 'a'.
+
+exe a : a.cpp b : <variant>debug ;
+
+lib b : b.cpp ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/direct-request-test/a.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/direct-request-test/a.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/direct-request-test/a.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,19 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+void
+# ifdef _WIN32
+__declspec(dllimport)
+# endif
+foo();
+
+int main()
+{
+ foo();
+}
Added: boost-jam/boost-build/branches/upstream/current/test/direct-request-test/b.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/direct-request-test/b.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/direct-request-test/b.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,22 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+// This file will declare 'foo' is 'MACROS' is defined.
+
+#ifdef MACROS
+void
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+foo() {}
+#endif
+
+# ifdef _WIN32
+int __declspec(dllexport) force_implib_creation;
+# endif
Added: boost-jam/boost-build/branches/upstream/current/test/direct-request-test/b_inverse.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/direct-request-test/b_inverse.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/direct-request-test/b_inverse.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,22 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+// This file will declare 'foo' is 'MACROS' is NOT defined.
+
+#ifndef MACROS
+void
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+foo() {}
+#endif
+
+# ifdef _WIN32
+int __declspec(dllexport) force_implib_creation;
+# endif
Added: boost-jam/boost-build/branches/upstream/current/test/direct-request-test/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/direct-request-test/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/direct-request-test/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+import gcc ;
Added: boost-jam/boost-build/branches/upstream/current/test/direct_request_test.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/direct_request_test.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/direct_request_test.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,46 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester, List
+import os
+from string import strip
+
+t = Tester()
+
+# First check some startup
+t.set_tree("direct-request-test")
+t.run_build_system(extra_args="define=MACROS")
+
+t.expect_addition("bin/$toolset/debug/"
+ * (List("a.obj b.obj b.dll a.exe")))
+
+# When building debug version, the 'define' still applies
+t.rm("bin")
+t.run_build_system(extra_args="debug define=MACROS")
+t.expect_addition("bin/$toolset/debug/"
+ * (List("a.obj b.obj b.dll a.exe")))
+
+# When building release version, the 'define' should not
+# apply: we'll have direct build request 'release <define>MACROS'
+# and real build properties 'debug'.
+t.copy("Jamfile2", "Jamfile")
+t.copy("b_inverse.cpp", "b.cpp")
+t.rm("bin")
+t.run_build_system(extra_args="release define=MACROS")
+
+
+# Regression test: direct build request was not working
+# when there's more than one level of 'build-project'
+
+t.rm(".")
+t.write('project-root.jam', '')
+t.write('Jamfile', 'build-project a ;')
+t.write('a/Jamfile', 'build-project b ;')
+t.write('a/b/Jamfile', '')
+
+t.run_build_system("release")
+
+
+
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/direct_request_test.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/dll_path.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/dll_path.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/dll_path.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,128 @@
+#!/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.
+
+# Test that the <dll-path> property is correctly set when using
+# <hardcode-dll-paths>true.
+from BoostBuild import Tester, List
+from string import find
+
+
+t = Tester()
+
+# The point of this test is to have exe "main" which uses library "b",
+# which uses library "a". When "main" is built with <hardcode-dll-paths>true,
+# paths to both libraries should be present as values of <dll-path> feature.
+# We create a special target type which reports <dll-path> values on its sources
+# and compare the list of found values with out expectations.
+
+t.write("Jamfile", """
+exe main : main.cpp b//b ;
+explicit main ;
+
+path-list mp : main ;
+""")
+
+t.write("main.cpp", """
+int main() { return 0; }
+
+""")
+
+t.write("project-root.jam", """
+using dll-paths ;
+""")
+
+t.write("dll-paths.jam", """
+import type ;
+import generators ;
+import feature ;
+import sequence ;
+import print ;
+import "class" : new ;
+
+rule init ( )
+{
+ type.register PATH_LIST : pathlist : : main ;
+
+ class dll-paths-list-generator : generator
+ {
+ rule __init__ ( )
+ {
+ generator.__init__ dll-paths.list : EXE : PATH_LIST ;
+ }
+
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ local dll-paths ;
+ for local s in $(sources)
+ {
+ local a = [ $(s).action ] ;
+ if $(a)
+ {
+ local p = [ $(a).properties ] ;
+ dll-paths += [ $(p).get <dll-path> ] ;
+ }
+ }
+ return [ generator.generated-targets $(sources)
+ : [ $(property-set).add-raw $(dll-paths:G=<dll-path>) ] : $(project) $(name) ] ;
+
+ }
+ }
+ generators.register [ new dll-paths-list-generator ] ;
+
+}
+
+rule list ( target : sources * : properties * )
+{
+ local paths = [ feature.get-values <dll-path> : $(properties) ] ;
+ paths = [ sequence.insertion-sort $(paths) ] ;
+ print.output $(target) ;
+ print.text $(paths) ;
+}
+
+""")
+
+t.write("a/a.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+foo() {}
+
+
+""")
+
+t.write("a/Jamfile", """
+lib a : a.cpp ;
+""")
+
+t.write("b/b.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+bar() {}
+
+
+""")
+
+t.write("b/Jamfile", """
+lib b : b.cpp ../a//a ;
+""")
+
+t.run_build_system("hardcode-dll-paths=true")
+
+t.expect_addition("bin/$toolset/debug/mp.pathlist")
+
+es1 = t.adjust_names(["a/bin/$toolset/debug"])[0]
+es2 = t.adjust_names(["b/bin/$toolset/debug"])[0]
+content = t.read("bin/$toolset/debug/mp.pathlist")
+
+t.fail_test(find(content, es1) == -1)
+t.fail_test(find(content, es2) == -1)
+
+t.cleanup()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/dll_path.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/double_loading.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/double_loading.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/double_loading.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,47 @@
+#!/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.
+
+from BoostBuild import Tester, List
+import string
+
+t = Tester()
+
+# Regression test for double loading of the same Jamfile.
+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)
+
+# Regression test for a more contrived case. The top-level
+# jamfile refers to subdir via use-project, while subdir's
+# Jamfile is being loaded. The motivation why use-project
+# referring to subprojects are usefull can be found at
+# http://article.gmane.org/gmane.comp.lib.boost.build/3906/
+t.write("Jamfile", """
+use-project /subdir : subdir ;
+""")
+
+t.write("project-root.jam", """
+""")
+
+t.write("subdir/Jamfile", """
+project subdir ;
+""")
+
+t.run_build_system(subdir="subdir");
+
+t.cleanup()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/double_loading.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/duplicate.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/duplicate.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/duplicate.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2004. 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.
+
+# This test tries to stage the same file to the same location by *two*
+# different stage rules, in two different projects. This is not exactly
+# good thing to do, but still, V2 should handle this. We had two bugs:
+# - since the file is referred from two projects, we created to different
+# virtual targets
+# - we also failed to figure out that the two target corresponding to the
+# copied files (created in two projects) are actually equivivalent.
+
+from BoostBuild import Tester, List
+
+
+t = Tester()
+
+t.write("a.cpp", """
+""")
+
+t.write("Jamfile", """
+build-project a ;
+build-project b ;
+""")
+
+t.write("project-root.jam", """
+""")
+
+t.write("a/Jamfile", """
+stage bin : ../a.cpp : <location>../dist ;
+""")
+
+t.write("b/Jamfile", """
+stage bin : ../a.cpp : <location>../dist ;
+""")
+
+t.run_build_system()
+t.expect_addition("dist/a.cpp")
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/duplicate.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/echo_args.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/echo_args.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/echo_args.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,16 @@
+rule echo_args ( a b ? c ? : d + : e * )
+{
+ ECHO a= $(a) b= $(b) c= $(c) ":" d= $(d) ":" e= $(e) ;
+}
+
+rule echo_varargs ( a b ? c ? : d + : e * : * )
+{
+ ECHO a= $(a) b= $(b) c= $(c) ":" d= $(d) ":" e= $(e)
+ ": rest= "$(4[1]) $(4[2])
+ ": "$(5[1]) $(5[2])
+ ": "$(6[1]) $(6[2])
+ ": "$(7[1]) $(7[2])
+ ": "$(8[1]) $(8[2])
+ ": "$(9[1]) $(9[2]) ;
+}
+
Added: boost-jam/boost-build/branches/upstream/current/test/empty.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/empty.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/empty.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+# This file is empty; it just suppresses warnings
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/expansion.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/expansion.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/expansion.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,92 @@
+#!/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.
+
+# This file is template for Boost.Build tests. It creates a simple
+# project that builds one exe from one source, and checks that the exe
+# is really created.
+from BoostBuild import Tester, List
+
+
+t = Tester()
+
+t.write("a.cpp", """
+#ifdef CF_IS_OFF
+int main() { return 0; }
+#endif
+
+""")
+
+t.write("b.cpp", """
+#ifdef CF_1
+int main() { return 0; }
+#endif
+
+""")
+
+t.write("c.cpp", """
+#ifdef FOO
+int main() { return 0; }
+#endif
+
+""")
+
+
+t.write("Jamfile", """
+# See if default value of composite feature 'cf'
+# will be expanded to <define>CF_IS_OFF
+exe a : a.cpp ;
+
+# See if subfeature in requirements in expanded.
+exe b : b.cpp : <cf>on-1 ;
+
+# See if conditional requirements are recursively expanded.
+exe c : c.cpp : <toolset>$toolset:<variant>release <variant>release:<define>FOO ;
+""")
+
+t.write("project-root.jam", """
+import feature ;
+
+feature.feature cf : off on : composite incidental ;
+
+feature.compose <cf>off : <define>CF_IS_OFF ;
+
+feature.subfeature cf on : version : 1 2 : composite optional incidental ;
+
+feature.compose <cf-on:version>1 : <define>CF_1 ;
+
+""")
+
+t.expand_toolset("Jamfile")
+
+t.run_build_system()
+t.expect_addition(["bin/$toolset/debug/a.exe",
+ "bin/$toolset/debug/b.exe",
+ "bin/$toolset/release/c.exe",
+ ])
+
+t.rm("bin")
+
+# Test for issue BB60
+t.write("test.cpp", """
+#include "header.h"
+int main() { return 0; }
+""")
+t.write("Jamfile", """
+project
+ : requirements <toolset>$toolset:<include>foo
+ ;
+exe test : test.cpp : <toolset>$toolset ;
+""")
+t.expand_toolset("Jamfile")
+t.write("foo/header.h", """
+""")
+t.write("project-root.jam", "")
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/test.exe")
+
+t.cleanup()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/expansion.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/explicit.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/explicit.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/explicit.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,40 @@
+#!/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.
+
+# This file is template for Boost.Build tests. It creates a simple
+# project that builds one exe from one source, and checks that the exe
+# is really created.
+from BoostBuild import Tester, List
+
+t = Tester()
+
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+
+exe hello : hello.cpp ;
+exe hello2 : hello.cpp ;
+
+explicit hello2 ;
+""")
+t.write("hello.cpp", """
+int main()
+{
+ return 0;
+}
+
+""")
+
+t.run_build_system()
+t.ignore("*.tds")
+t.expect_addition(List("bin/$toolset/debug/hello") * [".exe", ".obj"])
+t.expect_nothing_more()
+
+t.run_build_system("hello2")
+t.expect_addition("bin/$toolset/debug/hello2.exe")
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/explicit.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/gcc_runtime.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/gcc_runtime.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/gcc_runtime.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2004. 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.
+
+# Tests that on gcc, we correctly report problem when static runtime
+# is requested when building DLL.
+from BoostBuild import Tester, List
+import string
+
+t = Tester()
+
+# Create the needed files
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+lib hello : hello.cpp ;
+""")
+t.write("hello.cpp", """
+int main()
+{
+ return 0;
+}
+""")
+
+t.run_build_system("link-runtime=static", status=1)
+t.fail_test(string.find(t.stdout(),
+ "on gcc, DLL can't be build with <link-runtime>static") == -1)
+
+t.run_build_system("link=static link-runtime=static")
+t.expect_addition("bin/$toolset/debug/link-runtime-static/link-static/hello.lib")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/gcc_runtime.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,15 @@
+
+project
+ # This is needed to supress gcc warning on flex output, which otherwise
+ # results in test failure
+ : requirements <define>YY_NO_UNPUT
+ ;
+
+exe a : a.cpp b.cxx obj_1 obj_2 c.ui d.wd x.l y.x_pro lib//auxilliary ;
+# This should not cause second compilation of a.cpp
+exe f : a.cpp b.cxx obj_1 obj_2 lib//auxilliary ;
+
+obj obj_1 : z.cpp : <define>SELECT=1 ;
+obj obj_2 : z.cpp : <define>SELECT=2 ;
+
+nm-exe e : e.cpp ;
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/a.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/a.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/a.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,22 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+int foo();
+int bar();
+
+void z1(), z2();
+
+int main()
+{
+ foo();
+ bar();
+ z1();
+ z2();
+ return 0;
+}
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/b.cxx
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/b.cxx 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/b.cxx 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,10 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+int foo() { return 0; }
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/c.ui
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/d.wd
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/e.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/e.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/e.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/extra.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/extra.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/extra.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,68 @@
+
+import type ;
+import generators ;
+
+type.register WHL : whl ;
+type.register DLP : dlp ;
+type.register WHL_LR0 : lr0 ;
+type.register WD : wd ;
+
+generators.register-standard extra.whale : WHL : CPP WHL_LR0 H H(%_symbols) ;
+generators.register-standard extra.dolphin : DLP : CPP ;
+generators.register-standard extra.wd : WD : WHL(%_parser) DLP(%_lexer) ;
+
+rule whale ( targets * : sources * : properties * )
+{
+}
+
+actions whale
+{
+ echo "Whale consuming " $(>)
+ touch $(<)
+}
+
+rule dolphin ( targets * : source * : properties * )
+{
+}
+
+actions dolphin
+{
+ echo "Dolphin consuming" $(>)
+ touch $(<)
+}
+
+rule wd ( targets * : source * : properties * )
+{
+}
+
+actions wd
+{
+ echo "WD consuming" $(>)
+ touch $(<)
+}
+
+rule x ( target * : source * : properties * )
+{
+}
+
+
+actions x
+{
+ echo "X: source is " $(>)
+ touch $(<)
+}
+
+rule x_pro ( target * : source * : properties * )
+{
+}
+
+
+actions x_pro
+{
+ echo "X_PRO: source is " $(>)
+ touch $(<)
+}
+
+
+
+
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/lex.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/lex.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/lex.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,26 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+import type ;
+import generators ;
+import feature ;
+import property ;
+import print ;
+
+type.register LEX : l ;
+
+generators.register-standard lex.lex : LEX : C ;
+
+rule lex ( targets * : sources * : properties * )
+{
+ print.output $(<) ;
+ # Need to supress SunCC's warning about empty source
+ # file.
+ print.text "void foo() {}" ;
+}
+
+actions lex
+{
+}
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/lib/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/lib/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/lib/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,4 @@
+
+static-lib auxilliary : c.cpp ;
+
+lib auxilliary2 : c.cpp ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/lib/c.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/lib/c.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/lib/c.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,10 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+int bar() { return 0; }
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/nm.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/nm.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/nm.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,34 @@
+import modules ;
+
+rule target-source ( targets * : sources * : properties * )
+{
+ if [ modules.peek : NT ]
+ {
+ main on $(<) = "int main() { return 0; }" ;
+ }
+ else
+ {
+ main on $(<) = "\"int main() { return 0; }\"" ;
+ }
+}
+
+actions target-source
+{
+ echo "NM target source consuming " $(>)
+ echo $(main) > $(<)
+}
+
+rule cpp-mark ( targets * : sources * : properties * )
+{
+}
+
+actions cpp-mark
+{
+ echo "CPP-MARK consuming " $(>)
+ touch $(<)
+}
+
+
+
+
+
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,91 @@
+
+import "class" : new ;
+
+import lex ;
+import qt ;
+import extra ;
+
+import type ;
+
+type.register UI : ui ;
+type.register UIC_H ;
+type.set-generated-target-suffix UIC_H : : h ;
+
+type.register X1 : x1 ;
+type.register X2 : x2 ;
+type.register X_PRO : x_pro ;
+
+import generators ;
+
+generators.register-standard qt.uic : UI UIC_H : CPP ;
+generators.register-standard qt.uic-h : UI : UIC_H ;
+
+# That's an interesting example. Currently, X_PRO will be processed
+# twice.
+generators.register-standard extra.x : X1 X2 : CPP ;
+generators.register-standard extra.x_pro : X_PRO : X1 X2 ;
+
+# The point of this setup of to implement this functionality
+# "When main target type is EST_EXE, build OBJ from CPP-MARKED, not
+# for anything else (like CPP)
+# Unfortunately, this does not really works.
+
+#if $(no-var) {
+import nm ;
+
+type.register CPP_MARKED : marked.cpp : CPP ;
+type.register POSITIONS : positions ;
+type.register NM.TARGET.CPP : target.cpp : CPP ;
+type.register NM_EXE : : EXE : main ;
+
+generators.register-standard nm.target-source : CPP_MARKED : NM.TARGET.CPP ;
+generators.register-standard nm.cpp-mark : CPP : CPP_MARKED POSITIONS ;
+
+class nm::target::cpp-obj-generator : generator
+{
+ rule __init__ ( )
+ {
+ generator.__init__ nm.target-obj : NM.TARGET.CPP : OBJ ;
+ }
+
+ rule requirements ( )
+ {
+ return <main-target-type>NM_EXE ;
+ }
+
+ # Consider: it it OK to ignore all other generated targets except for the first?
+ rule run ( project name ? : properties * : source : multiple ? )
+ {
+ if [ $(source).type ] = CPP {
+ local converted = [ generators.construct $(project) : NM.TARGET.CPP : $(properties) : $(source) ] ;
+ if $(converted[1])
+ {
+ local result = [ generators.construct $(project) : OBJ : $(properties) : $(converted[1]) ] ;
+ return $(result) ;
+ }
+ else
+ {
+ return ;
+ }
+ }
+ else
+ {
+ return ;
+ }
+ }
+}
+
+generators.register [ new nm::target::cpp-obj-generator ] ;
+
+generators.override nm.target-obj : all ;
+
+#}
+
+
+
+
+
+
+
+
+
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/qt.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/qt.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/qt.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,29 @@
+import modules ;
+
+if [ modules.peek : NT ]
+{
+ comment = // ;
+}
+else
+{
+ comment = \"//\" ;
+}
+
+rule uic ( target : sources * : properties * )
+{
+ comment on $(<) = $(comment) ;
+}
+rule uic-h ( target : sources * : properties * )
+{
+ comment on $(<) = $(comment) ;
+}
+
+actions uic
+{
+ echo $(comment) $(>) > $(<)
+}
+
+actions uic-h
+{
+ echo $(comment) $(>) > $(<)
+}
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/x.l
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/x.l 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/x.l 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,5 @@
+%option noyywrap
+
+%%
+
+%%
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/y.x_pro
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/test/generators-test/z.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators-test/z.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators-test/z.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,16 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#if SELECT == 1
+void z1() {}
+#elif SELECT == 2
+void z2() {}
+#else
+#error Invlid value of SELECT
+#endif
Added: boost-jam/boost-build/branches/upstream/current/test/generators_test.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/generators_test.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/generators_test.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester, List
+import os
+
+t = Tester()
+
+t.set_tree("generators-test")
+t.run_build_system()
+
+t.expect_addition(
+ "bin/$toolset/debug/"
+ * (
+ List(
+ "a.obj b.obj c.h c.cpp c.obj d_parser.whl d_lexer.dlp d_parser.cpp d_lexer.cpp "
+ + "d_parser.lr0 d_parser.h d_parser_symbols.h x.c x.obj y.x1 y.x2 "
+ + "y.cpp y.obj e.marked.cpp e.positions e.target.cpp e.obj "))
+ )
+ok = 0
+
+t.expect_addition("bin/$toolset/debug/a.exe")
+
+t.expect_addition(["lib/bin/$toolset/debug/c.obj",
+ "lib/bin/$toolset/debug/auxilliary.lib",
+ ])
+
+
+t.run_build_system(subdir='lib')
+
+t.expect_addition(["lib/bin/$toolset/debug/auxilliary2.dll"])
+
+t.run_build_system(subdir='lib', extra_args="link=static")
+
+t.expect_addition(["lib/bin/$toolset/debug/link-static/auxilliary2.lib"])
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/generators_test.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/glob.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/glob.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/glob.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,91 @@
+#!/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.
+
+# Test the 'glob' rule in Jamfile context.
+from BoostBuild import Tester, List
+
+# Create a temporary working directory
+t = Tester()
+
+t.write("project-root.jam", """
+""")
+
+t.write("Jamfile", """
+""")
+
+t.write("d1/a.cpp", """
+int main() { return 0; }
+
+""")
+
+t.write("d1/Jamfile", """
+exe a : [ glob *.cpp ] ../d2/d//l ;
+""")
+
+t.write("d2/d/l.cpp", """
+#if defined(_WIN32)
+__declspec(dllexport)
+void force_import_lib_creation() {}
+#endif
+""")
+
+t.write("d2/d/Jamfile", """
+lib l : [ glob *.cpp ] ;
+""")
+
+t.run_build_system(subdir="d1")
+
+t.expect_addition("d1/bin/$toolset/debug/a.exe")
+
+t.rm("d2/d/bin")
+t.run_build_system(subdir="d2/d")
+t.expect_addition("d2/d/bin/$toolset/debug/l.dll")
+
+# Test that when 'source-location' is explicitly-specified
+# glob works relatively to source location
+t.rm("d1")
+
+t.write("d1/src/a.cpp", """
+int main() { return 0; }
+
+""")
+
+t.write("d1/Jamfile", """
+project : source-location src ;
+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
+t.rm("d1")
+
+t.write("d1/src/foo/a.cpp", """
+void bar();
+int main() { bar(); return 0; }
+
+""")
+
+t.write("d1/src/bar/b.cpp", """
+void bar() {}
+
+""")
+
+
+t.write("d1/Jamfile", """
+project : source-location src ;
+exe a : [ glob foo/*.cpp bar/*.cpp ] ../d2/d//l ;
+""")
+
+t.run_build_system(subdir="d1")
+t.expect_addition("d1/bin/$toolset/debug/a.exe")
+
+
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/glob.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/inherit_toolset.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/inherit_toolset.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/inherit_toolset.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,78 @@
+#!/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.
+
+from BoostBuild import Tester, List
+from string import find
+
+t = Tester(pass_toolset=0)
+
+t.write("a.cpp", """
+""")
+
+t.write("yfc1.jam", """
+import toolset ;
+import generators ;
+
+toolset.register yfc1 ;
+
+rule init ( )
+{
+}
+
+generators.register-standard yfc1.compile : CPP : OBJ : <toolset>yfc1 ;
+generators.register-standard yfc1.link : OBJ : EXE : <toolset>yfc1 ;
+
+actions compile
+{
+ yfc1-compile
+}
+
+actions link
+{
+ yfc1-link
+}
+
+
+""")
+
+t.write("yfc2.jam", """
+import toolset ;
+
+toolset.register yfc2 ;
+toolset.inherit yfc2 : yfc1 ;
+
+rule init ( )
+{
+}
+
+actions link
+{
+ yfc2-link
+}
+""")
+
+t.write("Jamfile", """
+exe a : a.cpp ;
+""")
+
+t.write("project-root.jam", """
+using yfc1 ;
+""")
+
+t.run_build_system("-n -d2 yfc1")
+t.fail_test(find(t.stdout(), "yfc1-link") == -1)
+
+# Make sure we don't have to explicit 'use' yfc1.
+t.write("project-root.jam", """
+using yfc2 ;
+""")
+
+t.run_build_system("-n -d2 yfc2")
+t.fail_test(find(t.stdout(), "yfc2-link") == -1)
+
+t.cleanup()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/inherit_toolset.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/inline.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/inline.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/inline.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,50 @@
+#!/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.
+
+from BoostBuild import Tester, List
+
+t = Tester()
+
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+alias everything : [ exe a : a.cpp ] ;
+""")
+
+t.write("a.cpp", """
+int main()
+{
+ return 0;
+}
+
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/everything..a.exe")
+t.rm("bin/$toolset/debug/everything..a.exe")
+
+t.run_build_system("everything..a")
+t.expect_addition("bin/$toolset/debug/everything..a.exe")
+
+t.rm("bin")
+
+# Now check that inline targets with the same name but
+# present in different places are not confused between
+# each other, and with top-level targets.
+t.write("Jamfile", """
+exe a : a.cpp ;
+alias everything : [ exe a : a.cpp ] ;
+alias everything2 : [ exe a : a.cpp ] ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+t.expect_addition("bin/$toolset/debug/everything..a.exe")
+t.expect_addition("bin/$toolset/debug/everything2..a.exe")
+
+
+t.cleanup()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/inline.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/library_chain.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/library_chain.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/library_chain.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,94 @@
+#!/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.
+
+# Test that a chain of libraries work ok, not matter if we use static or
+# shared linking.
+from BoostBuild import Tester, List
+import string
+
+t = Tester()
+
+t.write("Jamfile", """
+# Stage the binary, so that it will be relinked
+# without hardcode-dll-paths. That will chech that
+# we pass correct -rpath-link, even if not passing
+# -rpath.
+stage dist : main ;
+exe main : main.cpp b ;
+""")
+
+t.write("main.cpp", """
+void foo();
+
+int main() { foo(); return 0; }
+
+""")
+
+t.write("project-root.jam", """
+""")
+
+t.write("a/a.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+gee() {}
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+geek() {}
+""")
+
+t.write("a/Jamfile", """
+lib a : a.cpp ;
+""")
+
+t.write("b/b.cpp", """
+void geek();
+
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+foo() { geek(); }
+
+""")
+
+t.write("b/Jamfile", """
+lib b : b.cpp ../a//a ;
+""")
+
+t.run_build_system(stderr=None)
+t.expect_addition("bin/$toolset/debug/main.exe")
+t.rm(["bin", "a/bin", "b/bin"])
+
+t.run_build_system("link=static")
+t.expect_addition("bin/$toolset/debug/link-static/main.exe")
+t.rm(["bin", "a/bin", "b/bin"])
+
+t.write("b/Jamfile", """
+lib b : b.cpp ../a//a/<link>shared : <link>static ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/main.exe")
+t.rm(["bin", "a/bin", "b/bin"])
+
+# Test that putting library in sources of a searched library
+# works.
+t.write("Jamfile", """
+exe main : main.cpp png ;
+lib png : z : <name>png ;
+lib z : : <name>zzz ;
+""")
+t.run_build_system("-a -n -d+2")
+t.fail_test(string.find(t.stdout(), "zzz") == -1)
+
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/library_chain.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/library_order.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/library_order.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/library_order.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,123 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2004. 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.
+
+from BoostBuild import Tester, List
+import string
+
+
+# Test that on compilers which are sensitive to library order on
+# linker's command line, we generate the right order.
+t = Tester()
+
+t.write("a.cpp", """
+void b();
+
+void a()
+{
+ b();
+}
+
+""")
+
+t.write("b.cpp", """
+void c();
+
+void b()
+{
+ c();
+}
+""")
+
+t.write("c.cpp", """
+void d();
+
+void c()
+{
+ d();
+}
+
+""")
+
+t.write("d.cpp", """
+void d() {}
+
+""")
+
+# The order of libraries in 'main' is crafted so that
+# we get error unless we do something about the order ourselfs.
+t.write("Jamfile", """
+exe main : main.cpp libd libc libb liba ;
+lib libd : d.cpp ;
+lib libc : c.cpp : <link>static <use>libd ;
+lib libb : b.cpp : <use>libc ;
+lib liba : a.cpp : <use>libb ;
+
+""")
+
+t.write("main.cpp", """
+void a();
+
+int main()
+{
+ a();
+ return 0;
+}
+
+""")
+
+t.write("project-root.jam", """
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/main.exe")
+
+# Test the order between searched libraries
+t.write("Jamfile", """
+exe main : main.cpp png z ;
+lib png : z : <name>png ;
+lib z : : <name>zzz ;
+""")
+
+t.run_build_system("-a -n -d+2")
+t.fail_test(string.find(t.stdout(), "png") > string.find(t.stdout(), "zzz"))
+
+t.write("Jamfile", """
+exe main : main.cpp png z ;
+lib png : : <name>png ;
+lib z : png : <name>zzz ;
+""")
+
+t.run_build_system("-a -n -d+2")
+t.fail_test(string.find(t.stdout(), "png") < string.find(t.stdout(), "zzz"))
+
+# Test the order between prebuilt libraries
+
+t.write("first.a", "")
+t.write("second.a", "")
+
+t.write("Jamfile", """
+exe main : main.cpp first second ;
+lib first : second : <file>first.a ;
+lib second : : <file>second.a ;
+""")
+
+t.run_build_system("-a -n -d+2")
+t.fail_test(string.find(t.stdout(), "first") > string.find(t.stdout(), "second"))
+
+t.write("Jamfile", """
+exe main : main.cpp first second ;
+lib first : : <file>first.a ;
+lib second : first : <file>second.a ;
+""")
+
+t.run_build_system("-a -n -d+2")
+t.fail_test(string.find(t.stdout(), "first") < string.find(t.stdout(), "second"))
+
+
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/library_order.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/library_property.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/library_property.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/library_property.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2004. 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.
+
+# Test that the <library> property has no effect on "obj" targets.
+# Previously, it affected all targets, so
+#
+# project : requirements <library>foo ;
+# exe a : a.cpp helper ;
+# obj helper : helper.cpp : <optimization>off ;
+#
+# caused 'foo' to be built with with and without optimization.
+from BoostBuild import Tester, List
+
+# Create a temporary working directory
+t = Tester()
+
+t.write("Jamfile", """
+project
+ : requirements <library>lib//x
+ ;
+exe a : a.cpp foo ;
+obj foo : foo.cpp : <variant>release ;
+""")
+
+t.write("a.cpp", """
+void aux();
+int main() { aux(); }
+""")
+
+t.write("foo.cpp", """
+void gee();
+void aux() { gee(); }
+""")
+
+t.write("project-root.jam", """
+""")
+
+t.write("lib/x.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+gee() {}
+""")
+
+t.write("lib/Jamfile", """
+lib x : x.cpp ;
+""")
+
+t.write("lib/project-root.jam", """
+""")
+
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+t.expect_nothing("lib/bin/$toolset/release/x.obj")
+t.cleanup()
+
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/library_property.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/load_dir.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/load_dir.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/load_dir.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+
+"""
+Traverses a directory and output the code that would
+create the same directory structure during testing.
+Assumes that the instance of Tester is called 't'.
+"""
+
+import sys
+import os
+import stat
+import string
+
+def usage():
+ print "usage: load_dir.py directory"
+
+def remove_first_component(path):
+ result = [path]
+ while 1:
+ s = os.path.split(result[0])
+ if not s[0]:
+ break
+ result[:1] = list(s)
+ return apply(os.path.join, result[1:])
+
+
+
+def create_file(arg, dirname, fnames):
+ for n in fnames:
+ path = os.path.join(dirname, n)
+ if not os.path.isdir(path):
+ print "t.write(\"%s\", \"\"\"" % (remove_first_component(path),),
+ f = open(path, "r")
+ for l in f:
+ print l,
+ print '\n""")\n'
+
+def main():
+ if len(sys.argv) != 2:
+ usage()
+ else:
+ path = sys.argv[1]
+
+ if not os.access(path, os.F_OK):
+ print "Path '%s' does not exist" % (path,)
+ sys.exit(1)
+
+ if not os.path.isdir(path):
+ print "Path '%s' is not a directory" % (path,)
+
+ os.path.walk(path, create_file, None)
+
+if __name__ == '__main__':
+ main()
+
+
+
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/load_dir.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/loop.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/loop.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/loop.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,28 @@
+#!/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.
+
+from BoostBuild import Tester, List
+from string import find
+
+t = Tester()
+
+
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+
+lib main : main.cpp l ;
+lib l : l.cpp main ;
+""")
+
+t.write("main.cpp", "")
+t.write("l.cpp", "")
+
+t.run_build_system("--no-error-backtrace", status=1)
+t.fail_test(find(t.stdout(), "error: Recursion in main target references") == -1)
+t.fail_test(find(t.stdout(), "./main ./l ./main") == -1)
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/loop.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/m1-01.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/m1-01.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/m1-01.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+# Test the very basic 'make' functionality.
+
+from BoostBuild import Tester, List
+
+t = Tester()
+t.set_tree("test1")
+
+
+# Check that we can build something
+
+t.run_build_system("-sTOOLSET=yfc")
+
+t.expect_addition("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
+t.expect_addition("bin/a/yfc/debug/runtime-link-dynamic/a")
+t.expect_nothing_more()
+
+t.fail(t.read("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj") !=\
+"""
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+""")
+
+t.fail(t.read("bin/a/yfc/debug/runtime-link-dynamic/a") !=\
+"""
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+""")
+
+# Check that we have vanilla target names available
+
+t.touch("a.cpp")
+t.run_build_system("-sTOOLSET a.obj")
+t.expect_touch("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
+t.expect_no_modification("bin/a/yfc/debug/runtime-link-dynamic/a")
+
+
+# Check that if build request cannot be completely matches, a warning is
+# issued and subvariant with link-compatible properties is used
+
+t.write("Jamfile", t.read("Jamfile2"))
+stdout="""Warning: cannot exactly satisfy request for ./a with properties
+ <optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+Using
+ <optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+instead.
+""")
+t.run_build_system("-sTOOLSET=yfc", stdout=stdout)
+
+# Check that conflicting link-incompatible requirements prevent building.
+t.write("Jamfile", t.read("Jamfile3"))
+stdout="""Warning: cannot satisfy request for ./a with properties
+ <optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+Nothing will be built.
+""")
+t.run_build_system("-sTOOLSET=yfc", stdout=stdout, status=1)
+
+t.pass_test()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/m1-01.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/m1-02.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/m1-02.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/m1-02.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,88 @@
+#!/usr/bin/python
+
+# Tests that 'make' accepts target from other directories and that
+# build request for those targets can be overriden.
+
+from BoostBuild import Tester, List
+
+t = Tester()
+t.set_tree("test1")
+
+t.run_build_system("-sTOOLSET=yfc")
+
+t.expect_addition("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
+t.expect_addition("auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/optimization-space/b.obj")
+t.expect_addition("bin/a/yfc/debug/runtime-link-dynamic/a")
+t.expect_nothing_more()
+
+t.fail(t.read("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj") !=\
+"""
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+""")
+
+t.fail(t.read("auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/b.obj") !=\
+"""
+<optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+b.cpp
+""")
+
+
+t.fail(t.read("bin/a/yfc/debug/runtime-link-dynamic/a") !=\
+"""
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+<optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+b.cpp
+""")
+
+# Check that we have vanilla target names available in subdirs
+
+t.touch("auxillary/b.cpp")
+t.run_build_system("-sTOOLSET b.obj", subdir="auxillary")
+t.expect_touch("auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/optimization-space/b.obj")
+t.expect_no_modification("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
+t.expect_no_modification("bin/a/yfc/debug/runtime-link-dynamic/a")
+
+
+# Check that we cannot request link-incompatible property for source target
+
+t.write('Jamfile', t.read('Jamfile2'))
+stdout="""Error: subvariant of target ./a with properties
+ <optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+requests link-incompatible property
+ <rtti>off
+for source @auxillary/b.obj
+"""
+t.run_build_system("-sTOOLSET=yfc", stdout=stdout)
+
+# Check that if we request link-compatible property then requirement for
+# the source target will override it, with warning. This is similar to
+# the way build requests are satisfied (see the first test)
+# CONSIDER: should be print the main target which requests this one
+# (and modifies requiremenets)?
+
+t.write('Jamfile3', t.read('Jamfile3'))
+t.write('auxillary/Jamfile3', t.read('auxillary/Jamfile3'))
+stdout="""Warning: cannot exactly satisfy request for auxillary/b.obj with properties
+ <optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+Using
+ <optimization>speed <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+instead.
+"""
+t.run_build_system("-sTOOLSET=yfc", stdout=stdout)
+
+
+# Check for link-incompatible properties
+
+t.write('Jamfile4', t.read('Jamfile4'))
+t.write('auxillary/Jamfile4', t.read('auxillary/Jamfile4'))
+stdout="""Warning: cannot satisfy request for auxillary/b.obj with properties
+ <optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+Nothing will be built.
+""")
+
+
+t.pass_test()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/m1-02.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/m1-03.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/m1-03.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/m1-03.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,56 @@
+#!/usr/bin/python
+# Tests that we can use objects from other projects
+# (i.e. with other project root)
+# Test also that we can refer to those target using project-id.
+
+from BoostBuild import Tester, List
+
+t = Tester()
+t.set_tree("test1")
+
+t.run_build_system("-sTOOLSET=yfc", subdir="p1")
+
+t.expect_addition("p1/bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
+t.expect_addition("p1/auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/optimization-space/b.obj")
+t.expect_addition("p2/bin/c.obj/yfc/debug/runtime-link-dynamic/c.obj")
+t.expect_addition("bin/a/yfc/debug/runtime-link-dynamic/a")
+t.expect_nothing_more()
+
+t.fail(t.read("p1/bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj") !=\
+"""
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+""")
+
+t.fail(t.read("p1/auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/b.obj") !=\
+"""
+<optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+b.cpp
+""")
+
+t.fail(t.read("p2/bin/c.obj/yfc/debug/runtime-link-dynamic/c.obj") !=\
+"""
+<include>everything <optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+""")
+
+
+t.fail(t.read("bin/a/yfc/debug/runtime-link-dynamic/a") !=\
+"""
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+a.cpp
+<optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+b.cpp
+<include>everything <optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
+c.cpp
+""")
+
+t.expect_nothing_more()
+
+# TODO: need to write test cases for referring to targets using project-id.
+
+
+
+t.pass_test()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/m1-03.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/make_rule.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/make_rule.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/make_rule.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+
+# Test the 'make' rule
+
+from BoostBuild import Tester
+from string import find
+
+t = Tester(pass_toolset=1)
+
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+
+rule creator ( string targets * : sources * : * )
+{
+ STRING on $(targets) = $(string) ;
+ creator2 $(targets) : $(sources) ;
+}
+
+actions creator2
+{
+ echo $(STRING) > $(<)
+}
+
+make foo.bar : : creator foobar ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/foo.bar")
+t.fail_test(find(t.read("bin/$toolset/debug/foo.bar"), "foobar") == -1)
+
+# Regression test. Make sure that if main target requested two times,
+# and build request differ only in incidental properties, the main target
+# if created only once. The bug was discovered by Kirill Lapshin.
+
+t.write("Jamfile", """
+# Make sure that incidental property does not
+# cause second creation of 'hello1.cpp'.
+exe a : dir//hello1.cpp ;
+exe b : dir//hello1.cpp/<hardcode-dll-paths>true ;
+""")
+
+t.write("project-root.jam", "")
+
+t.write("dir/Jamfile", """
+import common ;
+make hello1.cpp : hello.cpp : common.copy ;
+
+""")
+
+t.write("dir/hello.cpp", """
+int main()
+{
+ return 1;
+}
+""")
+t.run_build_system("-d2")
+t.fail_test(t.stdout().count("common.copy") != 1)
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/make_rule.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/module-actions/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/module-actions/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/module-actions/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+boost-build . ;
Added: boost-jam/boost-build/branches/upstream/current/test/module-actions/bootstrap.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/module-actions/bootstrap.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/module-actions/bootstrap.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,79 @@
+# Demonstration that module variables have the right effect in actions
+
+# Set a variable which says how to dump a file to stdout
+if $(NT)
+{
+ CATENATE = type ;
+}
+else
+{
+ CATENATE = cat ;
+}
+
+# invoke the given action rule `act' to build target from sources
+rule do-make ( target : sources * : act )
+{
+ DEPENDS $(target) : $(sources) ;
+ $(act) $(target) : $(sources) ;
+}
+
+# top-level version of do-make which causes target to be built by
+# default
+rule make ( target : sources * : act )
+{
+ DEPENDS all : $(target) ;
+ do-make $(target) : $(sources) : $(act) ;
+}
+
+X1 = X1-global ;
+X2 = X2-global ;
+X3 = X3-global ;
+
+module A
+{
+ X1 = X1-A ;
+
+ rule act ( target )
+ {
+ NOTFILE $(target) ;
+ ALWAYS $(target) ;
+ }
+
+ actions act
+ {
+ echo A.act $(<): $(X1) $(X2) $(X3)
+ }
+
+ make t1 : : A.act ;
+ make t2 : : A.act ;
+ make t3 : : A.act ;
+}
+
+module B
+{
+ X2 = X2-B ;
+
+ actions act
+ {
+ echo B.act $(<): $(X1) $(X2) $(X3)
+ }
+
+ make t1 : : B.act ;
+ make t2 : : B.act ;
+ make t3 : : B.act ;
+}
+
+actions act
+{
+ echo act $(<): $(X1) $(X2) $(X3)
+}
+
+make t1 : : act ;
+make t2 : : act ;
+make t3 : : act ;
+
+X1 on t1 = X1-t1 ;
+X2 on t2 = X2-t2 ;
+X3 on t3 = X3-t3 ;
+
+DEPENDS all : t1 t2 t3 ;
Added: boost-jam/boost-build/branches/upstream/current/test/module_actions.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/module_actions.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/module_actions.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester, List
+import os
+import re
+
+spaces_re = re.compile("\ \ +")
+trailing_spaces_re = re.compile("\ +\n")
+
+t = Tester(pass_toolset=0)
+
+t.set_tree('module-actions')
+
+expected = r'''A.act t1: X1-t1
+B.act t1: X1-t1 X2-B
+act t1: X1-t1 X2-global X3-global
+A.act t2: X1-A X2-t2
+B.act t2: X2-t2
+act t2: X1-global X2-t2 X3-global
+A.act t3: X1-A X3-t3
+B.act t3: X2-B X3-t3
+act t3: X1-global X2-global X3-t3
+'''
+
+# On Unixes, call to 'echo 1 2 3' produces '1 2 3' (note spacing)
+# Accomodate for that fact.
+if os.name != 'nt':
+ expected = re.sub(spaces_re, " ", expected)
+ expected = re.sub(trailing_spaces_re, "\n", expected)
+
+# We expect t5 and t7's output to be dumped to stdout
+t.run_build_system(
+ stdout = expected
+)
+
+t.expect_nothing_more()
+t.cleanup()
+
Added: boost-jam/boost-build/branches/upstream/current/test/ndebug.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/ndebug.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/ndebug.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,47 @@
+#!/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.
+
+# Test that building with optimization brings NDEBUG define, and, more
+# importantly, that dependency targets are built with NDEBUG as well,
+# even if they are not directly requested.
+
+
+from BoostBuild import Tester, List
+
+
+t = Tester()
+
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+exe hello : hello.cpp lib//lib1 ;
+""")
+t.write("hello.cpp", """
+#ifdef NDEBUG
+void foo();
+int main()
+{
+ foo();
+ return 0;
+}
+#endif
+""")
+t.write("lib/Jamfile", """
+lib lib1 : lib1.cpp ;
+""")
+t.write("lib/lib1.cpp", """
+#ifdef NDEBUG
+void foo() {}
+#endif
+""")
+
+# 'release' builds should get NDEBUG define
+# use static linking to avoid messing with
+# imports/exports on windows.
+t.run_build_system("link=static release")
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/ndebug.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/no_type.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/no_type.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/no_type.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,18 @@
+#!/usr/bin/python
+
+# Test that we cannot specify targets of unknown type as sources.
+# This is based on the fact that Unix 'ar' will happily consume
+# just about anything.
+
+from BoostBuild import Tester
+t = Tester()
+
+t.write("project-root.jam", "import gcc ;")
+t.write("Jamfile", """
+static-lib a : a.foo ;
+""")
+t.write("a.foo", "")
+
+t.run_build_system(status=1)
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/no_type.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/ordered_properties.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/ordered_properties.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/ordered_properties.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,46 @@
+#!/usr/bin/python
+
+# Copyright (C) Vladimir Prus 2004. 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.
+
+# This file is template for Boost.Build tests. It creates a simple
+# project that builds one exe from one source, and checks that the exe
+# is really created.
+from BoostBuild import Tester, List
+
+# This checks that Boost.Build does not reorder <include> properties
+# lexicographically.
+t = Tester()
+
+t.write("a.cpp", """
+#include <a.h>
+
+int main()
+{
+ foo();
+ return 0;
+}
+
+""")
+
+t.write("Jamfile", """
+exe a : a.cpp : <include>d2 <include>d1 ;
+""")
+
+t.write("project-root.jam", """
+""")
+
+t.write("d1/a.h", """
+""")
+
+t.write("d2/a.h", """
+inline void foo() {}
+
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a.exe")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/ordered_properties.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/path_features.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/path_features.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/path_features.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester
+t = Tester()
+
+t.write("project-root.jam", "import gcc ;")
+t.write("Jamfile", "lib a : a.cpp : <include>. ;")
+t.write("a.cpp", """
+#include <a.h>
+void
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+foo() {}
+""")
+t.write("a.h", "//empty file\n")
+
+t.write("d/Jamfile", "exe b : b.cpp ..//a ; ")
+t.write("d/b.cpp", """
+ void foo();
+ int main() { foo(); }
+""")
+
+t.run_build_system(subdir="d")
+
+# Now test the path features with condition work as well
+t.write("Jamfile", "lib a : a.cpp : <variant>debug:<include>. ;")
+t.rm("bin")
+t.run_build_system(subdir="d")
+
+# Test path features with condtion in usage requirements
+t.write("Jamfile", "lib a : a.cpp : <include>. : : <variant>debug:<include>. ;")
+t.write("d/b.cpp", """
+#include <a.h>
+void foo();
+int main() { foo(); }
+""")
+t.rm("d/bin")
+t.run_build_system(subdir="d")
+
+# Test that absolute paths inside requirements are ok. The problem
+# appear only when building targets in subprojects.
+t.write("project-root.jam", "")
+t.write("Jamfile", "build-project x ; ")
+t.write("x/Jamfile", """
+local pwd = [ PWD ] ;
+project : requirements <include>$(pwd)/x/include ;
+exe m : m.cpp : <include>$(pwd)/x/include2 ;
+""")
+t.write("x/m.cpp", """
+#include <h1.hpp>
+#include <h2.hpp>
+
+int main() {}
+""")
+t.write("x/include/h1.hpp", "\n")
+t.write("x/include2/h2.hpp", "\n")
+
+t.run_build_system()
+t.expect_addition("x/bin/$toolset/debug/m.exe")
+
+# Test that "&&" in path features is handled correctly.
+t.rm("bin")
+t.write("Jamfile", "build-project sub ;")
+t.write("sub/Jamfile", """
+exe a : a.cpp : <include>../h1&&../h2 ;
+""")
+t.write("sub/a.cpp", """
+#include <header.h>
+int main() { return OK; }
+""")
+t.write("h2/header.h", """
+const int OK = 0;
+""")
+t.run_build_system()
+t.expect_addition("sub/bin/$toolset/debug/a.exe")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/path_features.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/prebuilt/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/prebuilt/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/prebuilt/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,9 @@
+
+project test
+ : requirements <variant>release:<define>RELEASE
+ ;
+
+use-project /ext : ext ;
+
+exe hello : hello.cpp /ext//a ;
+
Added: boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,6 @@
+
+project ext
+ : requirements <variant>release:<define>RELEASE
+ ;
+
+lib a : a.cpp ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/Jamfile2
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/Jamfile2 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/Jamfile2 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,34 @@
+
+import modules ;
+
+local dll-suffix = so ;
+if [ modules.peek : OS ] in CYGWIN NT
+{
+ if $toolset = gcc
+ {
+ dll-suffix = dll ;
+ }
+ else
+ {
+ dll-suffix = lib ;
+ }
+}
+if $toolset = darwin
+{
+ dll-suffix = dylib ;
+}
+
+project ext ;
+
+lib a :
+ : <file>bin/$toolset/debug/a.$(dll-suffix) <variant>debug
+ :
+ : <include>debug
+ ;
+
+lib a :
+ : <file>bin/$toolset/release/a.$(dll-suffix) <variant>release
+ :
+ : <include>release
+ ;
+
Added: boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/Jamfile3
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/Jamfile3 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/Jamfile3 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,43 @@
+
+# This Jamfile is the same as Jamfile2, except that
+# it tries to access prebuilt targets using absolute
+# paths. It used to be broken on Windows.
+
+import modules ;
+
+local dll-suffix = so ;
+if [ modules.peek : OS ] in CYGWIN NT
+{
+ if $toolset = gcc
+ {
+ dll-suffix = dll ;
+ }
+ else
+ {
+ dll-suffix = lib ;
+ }
+}
+if $toolset = darwin
+{
+ dll-suffix = dylib ;
+}
+
+
+
+project ext ;
+
+# Assumed bjam was invoked from the project root
+local pwd = [ PWD ] ;
+
+lib a :
+ : <file>$(pwd)/ext/bin/$toolset/debug/a.$(dll-suffix) <variant>debug
+ :
+ : <include>debug
+ ;
+
+lib a :
+ : <file>$(pwd)/ext/bin/$toolset/release/a.$(dll-suffix) <variant>release
+ :
+ : <include>release
+ ;
+
Added: boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/a.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/a.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/a.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,17 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+#ifdef RELEASE
+void release() {}
+#else
+void debug() {}
+#endif
Added: boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/debug/a.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/debug/a.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/debug/a.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,13 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+void debug();
Added: boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+
Added: boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/release/a.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/release/a.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/prebuilt/ext/release/a.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,13 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+void release();
Added: boost-jam/boost-build/branches/upstream/current/test/prebuilt/hello.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/prebuilt/hello.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/prebuilt/hello.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,20 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+#include <a.h>
+
+int main()
+{
+ #ifdef RELEASE
+ release();
+ #else
+ debug();
+ #endif
+ return 0;
+}
Added: boost-jam/boost-build/branches/upstream/current/test/prebuilt/project-root.jam
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/test/prebuilt.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/prebuilt.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/prebuilt.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,39 @@
+#!/usr/bin/python
+
+# Test that we can use already built sources
+
+from BoostBuild import Tester
+t = Tester()
+
+t.set_tree('prebuilt')
+
+t.expand_toolset("ext/project-root.jam")
+t.expand_toolset("project-root.jam")
+# First, build the external project
+t.run_build_system("debug release", subdir="ext")
+
+# Then pretend that we don't have the sources for the external project,
+# and can only use compiled binaries
+t.copy("ext/Jamfile2", "ext/Jamfile")
+t.expand_toolset("ext/Jamfile")
+
+# Now check that we can build the main project, and that
+# correct prebuilt file is picked, depending of variant.
+# This also checks that correct includes for prebuilt
+# libraries are used.
+
+t.run_build_system("debug release")
+t.expect_addition("bin/$toolset/debug/hello.exe")
+t.expect_addition("bin/$toolset/release/hello.exe")
+
+t.rm("bin")
+# Now test that prebuilt file specified by absolute name
+# works too.
+t.copy("ext/Jamfile3", "ext/Jamfile")
+t.expand_toolset("ext/Jamfile")
+t.run_build_system("debug release")
+t.expect_addition("bin/$toolset/debug/hello.exe")
+t.expect_addition("bin/$toolset/release/hello.exe")
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/prebuilt.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/print.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/print.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/print.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,45 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester, List
+
+t = Tester()
+
+t.write("project-root.jam", "import gcc ;")
+t.write("Jamfile", """
+import print ;
+print.output foo ;
+print.text \\\"Something\\\" ;
+DEPENDS all : foo ;
+ALWAYS foo ;
+""")
+
+t.run_build_system()
+t.expect_content("foo", """\"Something\"
+""")
+
+t.write("Jamfile", """
+import print ;
+print.output foo ;
+print.text \\\"Somethingelse\\\" ;
+DEPENDS all : foo ;
+ALWAYS foo ;
+""")
+
+t.run_build_system()
+t.expect_content("foo", """\"Something\"
+\"Somethingelse\"
+""")
+
+t.write("Jamfile", """
+import print ;
+print.output foo ;
+print.text \\\"Different\\\" : true ;
+DEPENDS all : foo ;
+ALWAYS foo ;
+""")
+
+t.run_build_system()
+t.expect_content("foo", """\"Different\"
+""")
+
+t.cleanup()
Added: boost-jam/boost-build/branches/upstream/current/test/project-test1/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test1/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test1/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,5 @@
+project /boost-build-test-project-1
+ : requirements <threading>multi <include>/home/ghost/local/include ;
+
+build-project dir2 ;
+build-project dir ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test1/dir/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test1/dir/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test1/dir/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,5 @@
+
+project /boost-build-test-project-1/dir
+ : source-location src
+ : default-build release
+ ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/project-test1/dir2/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test1/dir2/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test1/dir2/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,4 @@
+
+project /cool-library
+ : requirements <include>/home/ghost/build/boost-cvs
+ ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test1/dir2/project-root.jam
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/test/project-test1/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test1/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test1/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+import builtin ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/project-test1/project-test1.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test1/project-test1.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test1/project-test1.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,16 @@
+import project ;
+import targets ;
+import assert ;
+import project-roots ;
+
+project.load "." ;
+
+import standalone-project ;
+
+project-roots.print ;
+
+assert.result standalone-project : project.find /teeest : "." ;
+
+NOTFILE all ;
+
+
Added: boost-jam/boost-build/branches/upstream/current/test/project-test1/readme.txt
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test1/readme.txt 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test1/readme.txt 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,3 @@
+
+This tests for basic project handling -- declaring subprojects, finding
+parent projects and project roots and for working project-ids.
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/project-test1/standalone-project.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test1/standalone-project.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test1/standalone-project.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+
+import project ;
+
+# Convert ourself into a real project.
+project.initialize $(__name__) ;
+
+# Now we can identify ourselfs.
+project /teeest ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/project-test1.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test1.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test1.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,12 @@
+import project ;
+import targets ;
+import assert ;
+
+project.load project-test1 ;
+import project-roots ;
+
+project-roots.print ;
+
+NOTFILE all ;
+
+
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,9 @@
+
+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.obj : a.cpp : yfc-compile ;
+
+build-project lib2 ;
+build-project lib ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/a.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/a.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/a.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/lib/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/lib/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/lib/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,5 @@
+
+use-project /lib2 : ../lib2 ;
+
+make b.obj : b.cpp : yfc-compile ;
+make m.exe : b.obj /lib2//c.obj : yfc-link ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/lib/b.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/lib/b.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/lib/b.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,7 @@
+
+project lib2 ;
+use-project /lib2/helper : helper ;
+
+make c.obj : c.cpp : yfc-compile ;
+make d.obj : d.cpp : yfc-compile ;
+make l.exe : c.obj ..//a.obj : yfc-link ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/c.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/c.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/c.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/d.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/d.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/d.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/helper/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/helper/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/helper/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,5 @@
+
+project lib2/helper ;
+
+make e.obj : e.cpp : yfc-compile ;
+
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/helper/e.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/helper/e.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/lib2/helper/e.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/lib3/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/lib3/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/lib3/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,21 @@
+
+# This project-root.jam also serves the role of Jamfile
+project lib3 ;
+
+use-project /lib2/helper : ../lib2/helper ;
+
+import property ;
+
+rule mfc-compile ( target : sources * : property-set * )
+{
+ PROPERTIES on $(target) = [
+ property.as-path [ property.remove incidental : $(property-set) ] ] ;
+}
+
+actions mfc-compile
+{
+ echo $(PROPERTIES) > $(<)
+ echo $(>) >> $(<)
+}
+
+make f.obj : f.cpp /lib2/helper//e.obj : mfc-compile ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/lib3/f.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/lib3/f.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/lib3/f.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/lib3/project-root.jam
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,30 @@
+
+import gcc ;
+import property ;
+
+rule yfc-compile ( target : sources * : property-set * )
+{
+ PROPERTIES on $(target) = [
+ property.as-path [ property.remove incidental : $(property-set) ] ] ;
+}
+
+actions yfc-compile
+{
+ echo $(PROPERTIES) > $(<)
+ echo $(>) >> $(<)
+}
+
+rule yfc-link ( target : sources * : property-set * )
+{
+ PROPERTIES on $(target) = [
+ property.as-path [ property.remove incidental : $(property-set) ] ] ;
+}
+
+actions yfc-link
+{
+ echo $(PROPERTIES) > $(<)
+ echo $(>) >> $(<)
+}
+
+
+IMPORT $(__name__) : yfc-compile yfc-link : : yfc-compile yfc-link ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test3/readme.txt
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test3/readme.txt 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test3/readme.txt 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,3 @@
+
+This test checks that we have minimally working 'make' rule and that we can use target from
+different project with different project roots.
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,6 @@
+
+project test : requirements <include>everything <threading>single ;
+
+make a.exe : a.obj lib//b.obj/<optimization>speed : yfc-link ;
+make b.exe : a.obj : yfc-link : <define>MACROS ;
+make a.obj : a.cpp : yfc-compile ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile3
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile3 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile3 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,5 @@
+
+make a.exe : a.obj lib//b.obj/<optimization>on a_gcc.obj : yfc-link : <toolset>gcc ;
+make a.exe : a.obj lib//b.obj/<optimization>on : yfc-link : <threading>multi ;
+make a.obj : a.cpp : yfc-compile ;
+make a_gcc.obj : a_gcc.cpp : yfc-compile ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile4
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile4 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile4 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,4 @@
+
+project test : requirements <include>everything <threading>single ;
+
+build-project lib2 ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile5
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile5 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/Jamfile5 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,6 @@
+
+project test : requirements <include>everything <threading>single ;
+
+make a.exe : a.obj lib//b.obj/<variant>release : yfc-link ;
+make b.exe : a.obj : yfc-link : <define>MACROS ;
+make a.obj : a.cpp : yfc-compile ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/a.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/a.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/a.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/a_gcc.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/a_gcc.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/a_gcc.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+make b.obj : b.cpp : yfc-compile ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile1
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile1 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile1 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+make b.obj : b.cpp : yfc-compile ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile2
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile2 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile2 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,4 @@
+
+project lib : requirements <threading>multi ;
+
+make b.obj : b.cpp : yfc-compile ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile3
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile3 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/Jamfile3 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+make b.obj : b.cpp : yfc-compile : <rtti>off ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/b.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/b.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/lib/b.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/lib2/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/lib2/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/lib2/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,4 @@
+
+project
+ : requirements <rtti>off
+ ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/lib2/Jamfile2
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/lib2/Jamfile2 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/lib2/Jamfile2 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,4 @@
+
+project mylib
+ : requirements <rtti>off
+ ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,30 @@
+
+import gcc ;
+import property ;
+
+rule yfc-compile ( target : sources * : property-set * )
+{
+ PROPERTIES on $(target) = [
+ property.as-path [ property.remove incidental : $(property-set) ] ] ;
+}
+
+actions yfc-compile
+{
+ echo $(PROPERTIES) > $(<)
+ echo $(>) >> $(<)
+}
+
+rule yfc-link ( target : sources * : property-set * )
+{
+ PROPERTIES on $(target) = [
+ property.as-path [ property.remove incidental : $(property-set) ] ] ;
+}
+
+actions yfc-link
+{
+ echo $(PROPERTIES) > $(<)
+ echo $(>) >> $(<)
+}
+
+
+IMPORT $(__name__) : yfc-compile yfc-link : : yfc-compile yfc-link ;
Added: boost-jam/boost-build/branches/upstream/current/test/project-test4/readme.txt
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project-test4/readme.txt 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project-test4/readme.txt 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+
+This test checks for correct properties of generated and used targets.
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/project_dependencies.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project_dependencies.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project_dependencies.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+
+# Test that we can specify a dependency property
+# in project requirements, and that it won't
+# cause every main target in the project to
+# be generated in it's own subdirectory.
+
+# The whole test is somewhat moot now.
+
+from BoostBuild import Tester, List
+
+t = Tester()
+
+t.write("project-root.jam", "import gcc ;")
+t.write("Jamfile", "build-project src ;")
+t.write("lib/Jamfile", "lib lib1 : lib1.cpp ;")
+t.write("lib/lib1.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {}\n
+""")
+t.write("src/Jamfile", """
+project
+ : requirements <library>../lib//lib1
+ ;
+
+exe a : a.cpp ;
+exe b : b.cpp ;
+""")
+t.write("src/a.cpp", """
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+void foo();
+int main() { foo(); return 0; }
+""")
+t.copy("src/a.cpp", "src/b.cpp")
+
+t.run_build_system()
+
+# Test that there's no "main-target-a" part.
+# t.expect_addition("src/bin/$toolset/debug/a.exe")
+# t.expect_addition("src/bin/$toolset/debug/b.exe")
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/project_dependencies.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/project_root.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project_root.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project_root.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,23 @@
+#!/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.
+
+# Test that we can access project-root attributes from Jamfiles.
+from BoostBuild import Tester, List
+
+# Create a temporary working directory
+t = Tester()
+
+t.write("Jamfile", """
+local l = [ project-root get-location ] ;
+ECHO XXX $(l) ;
+""")
+
+t.write("project-root.jam", "")
+
+t.run_build_system(stdout="XXX .\n")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/project_root.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/project_root_constants.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project_root_constants.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project_root_constants.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,43 @@
+#!/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.
+
+from BoostBuild import Tester, List
+from string import find
+
+# Create a temporary working directory
+t = Tester()
+
+# Create the needed files
+t.write("project-root.jam", """
+constant FOO : foobar ;
+ECHO $(FOO) ;
+""")
+t.write("Jamfile", """
+""")
+
+t.run_build_system()
+t.fail_test(find(t.stdout(), "foobar") == -1)
+
+# Regression test: when absolute paths were passed to path-constant rule,
+# Boost.Build failed to recognize path as absolute and prepended current dir.
+t.write("project-root.jam", """
+import path ;
+local here = [ path.native [ path.pwd ] ] ;
+path-constant HERE : $(here) ;
+if $(HERE) != $(here)
+{
+ ECHO "PWD =" $(here) ;
+ ECHO "path constant =" $(HERE) ;
+ EXIT ;
+}
+""")
+t.write("Jamfile", "")
+
+t.run_build_system()
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/project_root_constants.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/project_test1.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project_test1.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project_test1.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,74 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester
+import os
+
+t = Tester("--build-system=project-test1", boost_build_path='', pass_toolset=0)
+
+# This test does no modifications, so run in in the invocation dir
+
+os.chdir(t.original_workdir)
+
+
+expected_output1="""Project Roots:
+
+"""
+
+expected_output2="""'%(root-dir-prefix)sdir2':
+
+ Module for project-root is 'project-root<%(root-dir-prefix)sdir2>'
+
+Projects:
+
+'/cool-library':
+
+* Parent project: (none)
+* Requirements: <include>/home/ghost/build/boost-cvs
+* Default build:
+* Source location: %(root-dir-prefix)sdir2
+* Projects to build:
+
+"""
+
+expected_output3="""'%(root-dir)s':
+
+ Module for project-root is 'project-root<%(root-dir)s>'
+
+Projects:
+
+'/boost-build-test-project-1':
+
+* Parent project: (none)
+* Requirements: <include>/home/ghost/local/include <threading>multi
+* Default build:
+* Source location: %(root-dir)s
+* Projects to build: dir dir2
+
+'/boost-build-test-project-1/dir':
+
+* Parent project: %(root-dir)s
+* Requirements: <include>/home/ghost/local/include <threading>multi
+* Default build: <variant>release
+* Source location: %(root-dir-prefix)sdir/src
+* Projects to build:
+
+"""
+
+# Test that correct project structure is created when jam is invoked
+# outside of the source tree.
+expected = (expected_output1 + expected_output2 + expected_output3) % \
+ {"root-dir": "project-test1",
+ "root-dir-prefix": "project-test1/" }
+
+t.run_build_system(stdout=expected)
+
+# Test that correct project structure is created when jam is invoked
+# at the top of the source tree.
+expected = (expected_output1 + expected_output3 + expected_output2) % \
+ {"root-dir": ".",
+ "root-dir-prefix": "" }
+
+os.chdir("project-test1")
+t.run_build_system(stdout=expected)
+
+t.cleanup()
Added: boost-jam/boost-build/branches/upstream/current/test/project_test3.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project_test3.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project_test3.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,135 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester, List
+import os
+from string import strip
+
+t = Tester(translate_suffixes=0)
+
+# First check some startup
+t.set_tree("project-test3")
+os.remove("project-root.jam")
+t.run_build_system(status=1, stdout=
+"""Failed to find the project root for directory '.'.
+Did not find a project-root.jam file there or in any of its parent directories.
+Please consult the documentation at 'http://www.boost.org'.
+""")
+
+t.set_tree("project-test3")
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/a.obj")
+t.expect_content("bin/$toolset/debug/a.obj",
+"""$toolset/debug
+a.cpp
+""")
+
+t.expect_addition("bin/$toolset/debug/a.exe")
+t.expect_content("bin/$toolset/debug/a.exe",
+"$toolset/debug\n" +
+"bin/$toolset/debug/a.obj lib/bin/$toolset/debug/b.obj " +
+"lib2/bin/$toolset/debug/c.obj lib2/bin/$toolset/debug/d.obj " +
+"lib2/helper/bin/$toolset/debug/e.obj " +
+"lib3/bin/$toolset/debug/f.obj\n"
+)
+
+t.expect_addition("lib/bin/$toolset/debug/b.obj")
+t.expect_content("lib/bin/$toolset/debug/b.obj",
+"""$toolset/debug
+lib/b.cpp
+""")
+
+t.expect_addition("lib/bin/$toolset/debug/m.exe")
+t.expect_content("lib/bin/$toolset/debug/m.exe",
+"""$toolset/debug
+lib/bin/$toolset/debug/b.obj lib2/bin/$toolset/debug/c.obj
+""")
+
+t.expect_addition("lib2/bin/$toolset/debug/c.obj")
+t.expect_content("lib2/bin/$toolset/debug/c.obj",
+"""$toolset/debug
+lib2/c.cpp
+""")
+
+t.expect_addition("lib2/bin/$toolset/debug/d.obj")
+t.expect_content("lib2/bin/$toolset/debug/d.obj",
+"""$toolset/debug
+lib2/d.cpp
+""")
+
+t.expect_addition("lib2/bin/$toolset/debug/l.exe")
+t.expect_content("lib2/bin/$toolset/debug/l.exe",
+"""$toolset/debug
+lib2/bin/$toolset/debug/c.obj bin/$toolset/debug/a.obj
+""")
+
+t.expect_addition("lib2/helper/bin/$toolset/debug/e.obj")
+t.expect_content("lib2/helper/bin/$toolset/debug/e.obj",
+"""$toolset/debug
+lib2/helper/e.cpp
+""")
+
+t.expect_addition("lib3/bin/$toolset/debug/f.obj")
+t.expect_content("lib3/bin/$toolset/debug/f.obj",
+"""$toolset/debug
+lib3/f.cpp lib2/helper/bin/$toolset/debug/e.obj
+""")
+
+
+t.touch("a.cpp")
+t.run_build_system()
+t.expect_touch(["bin/$toolset/debug/a.obj",
+ "bin/$toolset/debug/a.exe",
+ "lib2/bin/$toolset/debug/l.exe"])
+
+
+t.run_build_system(extra_args="release optimization=off,speed")
+t.expect_addition(["bin/$toolset/release/a.exe",
+ "bin/$toolset/release/a.obj",
+ "bin/$toolset/release/optimization-off/a.exe",
+ "bin/$toolset/release/optimization-off/a.obj"])
+
+t.run_build_system(extra_args='clean')
+t.expect_removal(["bin/$toolset/debug/a.obj",
+ "bin/$toolset/debug/a.exe",
+ "lib/bin/$toolset/debug/b.obj",
+ "lib/bin/$toolset/debug/m.exe",
+ "lib2/bin/$toolset/debug/c.obj",
+ "lib2/bin/$toolset/debug/d.obj",
+ "lib2/bin/$toolset/debug/l.exe",
+ "lib3/bin/$toolset/debug/f.obj",
+ ])
+
+# Now test target ids in command line
+t.set_tree("project-test3")
+t.run_build_system("lib//b.obj")
+t.expect_addition("lib/bin/$toolset/debug/b.obj")
+t.expect_nothing_more()
+
+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")
+t.expect_nothing_more()
+
+# Test project ids in command line work as well
+t.set_tree("project-test3")
+t.run_build_system("/lib2")
+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.run_build_system("lib")
+t.expect_addition("lib/bin/$toolset/debug/" * List("b.obj m.exe"))
+t.expect_nothing_more()
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/project_test3.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/project_test4.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/project_test4.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/project_test4.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester
+import os
+from string import strip, find
+
+t = Tester(translate_suffixes=0)
+
+
+t.set_tree("project-test4")
+
+t.run_build_system()
+
+t.expect_addition("bin/$toolset/debug/a.obj")
+t.expect_content("bin/$toolset/debug/a.obj",
+"""$toolset/debug/include-everything
+a.cpp
+""")
+
+t.expect_addition("bin/$toolset/debug/a.exe")
+t.expect_content("bin/$toolset/debug/a.exe",
+"$toolset/debug/include-everything\n" +
+"bin/$toolset/debug/a.obj lib/bin/$toolset/debug/optimization-speed/b.obj\n"
+)
+
+t.expect_addition("lib/bin/$toolset/debug/optimization-speed/b.obj")
+t.expect_content("lib/bin/$toolset/debug/optimization-speed/b.obj",
+"""$toolset/debug/include-everything/optimization-speed
+lib/b.cpp
+""")
+
+t.expect_addition("bin/$toolset/debug/b.exe")
+t.expect_content("bin/$toolset/debug/b.exe",
+"$toolset/debug/define-MACROS/include-everything\n" +
+"bin/$toolset/debug/a.obj\n"
+)
+
+
+t.copy("lib/Jamfile3", "lib/Jamfile")
+
+# Link-compatibility check for rtti is disabled...
+#t.run_build_system(status=None)
+#t.fail_test(find(t.stdout(),
+#"""warning: targets produced from b.obj are link incompatible
+#warning: with main target a.exe""") !=-0)
+
+# Test that if we specified composite property in target reference,
+# everything works OK.
+
+t.copy("lib/Jamfile1", "lib/Jamfile")
+t.copy("Jamfile5", "Jamfile")
+
+t.run_build_system()
+
+t.expect_addition("lib/bin/$toolset/release/b.obj")
+
+t.expect_content("bin/$toolset/debug/a.exe",
+"$toolset/debug/include-everything\n" +
+"bin/$toolset/debug/a.obj lib/bin/$toolset/release/b.obj\n"
+)
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/project_test4.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/property_expansion.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/property_expansion.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/property_expansion.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,35 @@
+#!/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.
+
+from BoostBuild import Tester, List
+
+# Test that free property inside
+t = Tester()
+
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+project ;
+
+variant debug-AA : debug : <define>AA ;
+
+alias all : hello ;
+exe hello : hello.cpp ;
+explicit hello ;
+""")
+t.write("hello.cpp", """
+#ifdef AA
+int main()
+{
+ return 0;
+}
+#endif
+""")
+
+t.run_build_system("debug-AA")
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/property_expansion.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/railsys/libx/include/test_libx.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/railsys/libx/include/test_libx.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/railsys/libx/include/test_libx.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,25 @@
+// Copyright (c) 2003 Institute of Transport,
+// Railway Construction and Operation,
+// University of Hanover, Germany
+//
+// Use, modification and distribution are subject to 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)
+
+#ifdef _WIN32
+#ifdef LIBX_SOURCE
+__declspec(dllexport)
+#else
+__declspec(dllimport)
+#endif
+#endif
+class TestLibX
+{
+public:
+
+ TestLibX();
+
+ // Needed to suppress 'unused variable' warning
+ // in some cases.
+ void do_something() {}
+};
Added: boost-jam/boost-build/branches/upstream/current/test/railsys/libx/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/railsys/libx/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/railsys/libx/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+
+import toolset ;
+
+# Tell that QT should be used. QTDIR will give installation
+# prefix.
+toolset.using qt ;
+
+
Added: boost-jam/boost-build/branches/upstream/current/test/railsys/libx/src/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/railsys/libx/src/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/railsys/libx/src/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,18 @@
+# Copyright (c) 2003 Institute of Transport,
+# Railway Construction and Operation,
+# University of Hanover, Germany
+#
+# 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.
+
+project libx
+ : requirements
+ <include>../include
+ : usage-requirements
+ <include>../include
+ ;
+
+
+lib libx : test_libx.cpp ;
Added: boost-jam/boost-build/branches/upstream/current/test/railsys/libx/src/test_libx.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/railsys/libx/src/test_libx.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/railsys/libx/src/test_libx.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,15 @@
+// Copyright (c) 2003 Institute of Transport,
+// Railway Construction and Operation,
+// University of Hanover, Germany
+//
+// Use, modification and distribution are subject to 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)
+
+
+#define LIBX_SOURCE
+#include <test_libx.h>
+
+TestLibX::TestLibX()
+{
+}
Added: boost-jam/boost-build/branches/upstream/current/test/railsys/program/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/railsys/program/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/railsys/program/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,46 @@
+# ================================================================
+#
+# Railsys
+# --------------
+#
+# Copyright (c) 2002 Institute of Transport,
+# Railway Construction and Operation,
+# University of Hanover, Germany
+#
+# 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.
+#
+# 02/21/02! Jürgen Hunold
+#
+# $Id: Jamfile,v 1.5 2004/10/05 07:55:20 vladimir_prus Exp $
+#
+# ================================================================
+
+local BOOST_ROOT = [ modules.peek : BOOST_ROOT ] ;
+
+use-project /libx : ../libx/src ;
+
+project program
+ : requirements
+ <include>$(BOOST_ROOT)
+ <threading>multi
+ <library>/qt//qt
+ <hardcode-dll-paths>true
+ <stdlib>stlport
+ <use>/libx
+ <library>/libx//libx
+
+ : usage-requirements
+ <include>$(BOOST_ROOT)
+ :
+ default-build release
+ <threading>multi
+ <library>/qt//qt
+ <hardcode-dll-paths>true
+ ;
+
+
+build-project main ;
+
Added: boost-jam/boost-build/branches/upstream/current/test/railsys/program/include/test_a.h
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/railsys/program/include/test_a.h 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/railsys/program/include/test_a.h 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,22 @@
+// Copyright (c) 2003 Institute of Transport,
+// Railway Construction and Operation,
+// University of Hanover, Germany
+//
+// Use, modification and distribution are subject to 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)
+
+
+#include <qobject.h>
+
+class TestA : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ TestA();
+
+ // Needed to suppress 'unused variable' varning.
+ void do_something() { }
+};
Added: boost-jam/boost-build/branches/upstream/current/test/railsys/program/liba/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/railsys/program/liba/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/railsys/program/liba/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,14 @@
+# Copyright (c) 2003 Institute of Transport,
+# Railway Construction and Operation,
+# University of Hanover, Germany
+#
+# 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.
+
+project liba ;
+
+lib liba : test ../include/test_a.h ;
+
+obj test : test_a.cpp : <optimization>off ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/railsys/program/liba/test_a.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/railsys/program/liba/test_a.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/railsys/program/liba/test_a.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,17 @@
+// Copyright (c) 2003 Institute of Transport,
+// Railway Construction and Operation,
+// University of Hanover, Germany
+//
+// Use, modification and distribution are subject to 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)
+
+#include "../include/test_a.h"
+
+#include <test_libx.h>
+
+TestA::TestA()
+{
+ TestLibX aTestLibX;
+ aTestLibX.do_something();
+}
Added: boost-jam/boost-build/branches/upstream/current/test/railsys/program/main/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/railsys/program/main/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/railsys/program/main/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,12 @@
+# Copyright (c) 2002 Institute of Transport,
+# Railway Construction and Operation,
+# University of Hanover, Germany
+#
+# 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.
+
+project main ;
+
+exe test_a : main.cpp ../liba//liba /libx ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/railsys/program/main/main.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/railsys/program/main/main.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/railsys/program/main/main.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,19 @@
+// Copyright (c) 2002 Institute of Transport,
+// Railway Construction and Operation,
+// University of Hanover, Germany
+//
+// Use, modification and distribution are subject to 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)
+
+#include "../include/test_a.h"
+
+#include <test_libx.h>
+
+int main()
+{
+ TestLibX stTestLibX;
+ TestA stTestA;
+
+ stTestLibX.do_something();
+};
Added: boost-jam/boost-build/branches/upstream/current/test/railsys/program/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/railsys/program/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/railsys/program/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,9 @@
+
+import toolset ;
+
+# Tell that QT should be used. QTDIR will give installation
+# prefix.
+toolset.using qt ;
+
+# Not that good, but sufficient for testing
+toolset.using stlport : : /path/to/stlport ;
Added: boost-jam/boost-build/branches/upstream/current/test/railsys.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/railsys.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/railsys.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,15 @@
+#!/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.
+
+from BoostBuild import Tester, List
+
+t = Tester()
+
+t.set_tree("railsys")
+t.run_build_system("--v2", subdir="program")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/railsys.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/readme.txt
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/readme.txt 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/readme.txt 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,3 @@
+Comprehensive tests for Boost.Build v2; requires Python. To test, execute:
+
+ python test_all.py
Added: boost-jam/boost-build/branches/upstream/current/test/recursive.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/recursive.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/recursive.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,118 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+##############################################################
+# Rules and actions that test Jam by invoking it recursively #
+# #
+# This is neccessary for testing anything that requires Jam #
+# to execute build actions whose results must be checked, #
+# and anything which exits Jam with a failure code (e.g. a #
+# failed assertion). #
+##############################################################
+
+# Creates a fake target, always built, which succeeds in building if Invoking a
+# Jamfile containing the given string succeeds. If optional-expected-output is
+# supplied, creates another fake target which succeeds in building if
+# optional-expected-output is in the Jam output.
+#
+# RETURNS: the target name of the Jam command.
+rule Jam ( command : expected-output ? )
+{
+ local jam-cmd = "$(command:G=jam_command)" ;
+
+ NOTFILE "$(jam-cmd)" ;
+ ALWAYS "$(jam-cmd)" ;
+ DEPENDS all : "$(jam-cmd)" ;
+
+ if ($NT)
+ {
+ redirect on $(jam-cmd) = "nul" ;
+ }
+ else if $(UNIX)
+ {
+ redirect on $(jam-cmd) = "/dev/null" ;
+ }
+
+ if $(VERBOSE)
+ {
+ redirect on $(jam-cmd) = ;
+ }
+
+ invoke-Jam "$(jam-cmd)" ;
+
+ if $(expected-output)
+ {
+ redirect on $(jam-cmd) = "scratch-output.txt" ;
+ local output-target = "$(expected-output:G=$(command))" ;
+ NOTFILE "$(output-target)" ;
+ ALWAYS "$(output-target)" ;
+ DEPENDS all : "$(output-target)" ;
+ Expect-in-output "$(output-target)" ;
+
+ if $(VERBOSE)
+ {
+ if $(NT) { VERBOSE on $(output-target) = "type " ; }
+ else { VERBOSE on $(output-target) = "cat " ; }
+ }
+ }
+ return $(jam-cmd) ;
+}
+
+# Just like the "Jam" rule, above, but only succeeds if the Jam command /fails/.
+rule Jam-fail ( command : expected-output ? )
+{
+ local target = [ Jam $(command) : $(expected-output) ] ;
+ FAIL_EXPECTED $(target) ;
+ return $(target) ;
+}
+
+# The temporary jamfile we write is called "temp.jam". If the user has set
+# BOOST_BUILD_ROOT, it will be built there.
+gBOOST_TEST_JAMFILE = temp.jam ;
+LOCATE on gBOOST_TEST_JAMFILE ?= $(BOOST_BUILD_ROOT) ;
+
+# Runs Jam on a temporary Jamfile which contains the string in $(command:G=)
+# and redirects the results into a file whose name is given by $(redirect) on
+# command
+rule invoke-Jam ( command )
+{
+ PREFIX on $(command) = "actions unbuilt { } unbuilt all ;" ;
+ if $(NT)
+ {
+ REMOVE on $(command) = $(SystemRoot)\System32\find ;
+ }
+ REMOVE on $(command) ?= rm ;
+}
+actions invoke-Jam
+{
+ echo $(PREFIX) $(<:G=) > $(gBOOST_TEST_JAMFILE)
+ jam -sBOOST_ROOT=../../.. -sJAMFILE=$(gBOOST_TEST_JAMFILE) $(JAMARGS) >$(redirect)
+}
+# $(REMOVE) $(gBOOST_TEST_JAMFILE)
+
+
+# These actions expect to find the ungristed part of $(<) in scratch-output.txt
+# and return a nonzero exit code otherwise
+if $(NT)
+{
+ # Explicitly get the NT find command in case someone has another find in their path.
+ actions quietly Expect-in-output
+ {
+ $(VERBOSE)scratch-output.txt ;
+ $(SystemRoot)\System32\find /C "$(<:G=)" scratch-output.txt >nul
+ }
+}
+else
+{
+ # Not really the right actions for Unix; the argument will be interpreted as
+ # a regular expression. Is there a simpler find?
+ actions quietly Expect-in-output
+ {
+ $(VERBOSE)scratch-output.txt;
+ grep "$(<:G=)" scratch-output.txt
+ }
+}
+
Added: boost-jam/boost-build/branches/upstream/current/test/regression.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/regression.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/regression.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,130 @@
+#!/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.
+
+# Test for the regression testing framework.
+from BoostBuild import Tester, List
+
+# Create a temporary working directory
+t = Tester()
+
+t.write("c.cpp", "")
+
+t.write("r.cpp", """
+
+void helper();
+
+#include <iostream>
+int main(int ac, char* av[])
+{
+ helper();
+
+ for (int i = 1; i < ac; ++i)
+ std::cout << av[i] << '\\n';
+ return 0;
+}
+""")
+
+t.write("c-f.cpp", """
+int
+""")
+
+t.write("r-f.cpp", """
+int main()
+{
+ return 1;
+}
+""")
+
+
+t.write("Jamfile", """
+import testing ;
+
+compile c.cpp ;
+compile-fail c-f.cpp ;
+run r.cpp libs//helper : foo bar ;
+run-fail r-f.cpp ;
+
+""")
+
+t.write("libs/Jamfile", """
+lib helper : helper.cpp ;
+""")
+
+t.write("libs/helper.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+helper() {}
+
+""")
+
+t.write("project-root.jam", "")
+
+# First test that when outcomes are expected, all .test files are created.
+t.run_build_system("hardcode-dll-paths=true", stderr=None, status=None)
+t.expect_addition("bin/c.test/$toolset/debug/c.test")
+t.expect_addition("bin/c-f.test/$toolset/debug/c-f.test")
+t.expect_addition("bin/r.test/$toolset/debug/r.test")
+t.expect_addition("bin/r-f.test/$toolset/debug/r-f.test")
+
+# Make sure args are handled.
+t.expect_content("bin/r.test/$toolset/debug/r.output",
+ "foo\nbar\n\nEXIT STATUS: 0\n")
+
+# Test that input file is handled as well.
+t.write("r.cpp", """
+#include <iostream>
+#include <fstream>
+int main(int ac, char* av[])
+{
+ for (int i = 1; i < ac; ++i) {
+ std::ifstream ifs(av[i]);
+ std::cout << ifs.rdbuf();
+ }
+
+ return 0;
+}
+""")
+
+t.write("dir/input.txt", "test input")
+
+t.write("Jamfile", """
+import testing ;
+
+compile c.cpp ;
+compile-fail c-f.cpp ;
+run r.cpp : : dir/input.txt ;
+run-fail r-f.cpp ;
+
+""")
+
+t.run_build_system("hardcode-dll-paths=true")
+t.expect_content("bin/r.test/$toolset/debug/r.output",
+ "test input\nEXIT STATUS: 0\n")
+
+# Make sure test failures are detected. Reverse expectation and see
+# if .test files are created or not.
+t.write("Jamfile", """
+import testing ;
+
+compile-fail c.cpp ;
+compile c-f.cpp ;
+run-fail r.cpp : : dir/input.txt ;
+run r-f.cpp ;
+
+""")
+
+t.touch(List("c.cpp c-f.cpp r.cpp r-f.cpp"))
+
+t.run_build_system("hardcode-dll-paths=true", stderr=None, status=1)
+t.expect_removal("bin/c.test/$toolset/debug/c.test")
+t.expect_removal("bin/c-f.test/$toolset/debug/c-f.test")
+t.expect_removal("bin/r.test/$toolset/debug/r.test")
+t.expect_removal("bin/r-f.test/$toolset/debug/r-f.test")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/regression.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/relative_sources.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/relative_sources.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/relative_sources.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+# Test that we can specify sources using relative names.
+
+from BoostBuild import Tester
+t = Tester()
+
+t.write("project-root.jam", "import gcc ;")
+t.write("Jamfile", "exe a : src/a.cpp ;")
+t.write("src/a.cpp", "int main() { return 0; }\n")
+
+t.run_build_system()
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/relative_sources.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/searched_lib.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/searched_lib.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/searched_lib.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,144 @@
+#!/usr/bin/python
+
+# Test usage of searched-libs: one which are found via -l
+# switch to the linker/compiler.
+
+from BoostBuild import Tester, get_toolset
+import string
+import os
+t = Tester()
+
+# To start with, we have to prepate a library to link with
+t.write("lib/project-root.jam", "")
+t.write("lib/Jamfile", "lib libtest_lib : test_lib.cpp ;")
+t.write("lib/test_lib.cpp", """
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void foo() {}
+""");
+
+t.run_build_system(subdir="lib")
+t.expect_addition("lib/bin/$toolset/debug/libtest_lib.dll")
+
+# Auto adjusting of suffixes does not work, since we need to
+# change dll to lib.
+#
+if (os.name == 'nt' or os.uname()[0].lower().startswith('cygwin')) and get_toolset() != 'gcc':
+ t.copy("lib/bin/$toolset/debug/libtest_lib.lib", "lib/test_lib.lib")
+else:
+ t.copy("lib/bin/$toolset/debug/libtest_lib.dll", "lib/libtest_lib.dll")
+
+
+# Test that the simplest usage of searched library works.
+t.write('project-root.jam', '')
+t.write('Jamfile', """
+
+import path ;
+import project ;
+
+local here = [ project.attribute $(__name__) location ] ;
+here = [ path.root $(here) [ path.pwd ] ] ;
+
+exe main : main.cpp helper ;
+lib helper : helper.cpp test_lib : <dll-path>$(here)/lib ;
+lib test_lib : : <name>test_lib <search>lib ;
+""")
+t.write("main.cpp", """
+void helper();
+int main() { helper(); return 0; }
+""")
+t.write("helper.cpp", """
+void foo();
+
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+helper() { foo(); }
+""")
+t.run_build_system(stderr=None) # gcc warns about libraries which are not in -rpath.
+t.expect_addition("bin/$toolset/debug/main.exe")
+t.rm("bin/$toolset/debug/main.exe")
+
+# Now try using searched lib from static lib. Request shared version
+# of searched lib, since we don't have static one handy.
+t.write('Jamfile', """
+exe main : main.cpp helper ;
+lib helper : helper.cpp test_lib/<link>shared : <link>static ;
+lib test_lib : : <name>test_lib <search>lib ;
+""")
+t.run_build_system(stderr=None)
+t.expect_addition("bin/$toolset/debug/main.exe")
+t.expect_addition("bin/$toolset/debug/link-static/helper.lib")
+t.rm("bin/$toolset/debug/main.exe")
+
+# A regression test: <library>property referring to
+# searched-lib was mishandled. As the result, we were
+# putting target name to the command line!
+# Note that
+# g++ ...... <.>z
+# works nicely in some cases, sending output from compiler
+# to file 'z'.
+# This problem shows up when searched libs are in usage
+# requirements.
+
+t.write('Jamfile', 'exe main : main.cpp d/d2//a ;')
+t.write('main.cpp',"""
+void foo();
+int main() { foo(); return 0; }
+
+""")
+t.write('d/d2/Jamfile', """
+lib test_lib : : <name>test_lib <search>../../lib ;
+lib a : a.cpp : : : <library>test_lib ;
+""")
+t.write('d/d2/a.cpp', """
+#ifdef _WIN32
+__declspec(dllexport) int force_library_creation_for_a;
+#endif
+""")
+
+t.run_build_system()
+
+# A regression test. Searched targets were not associated
+# with any properties. For that reason, if the same searched
+# lib is generated with two different properties, we had an
+# error saying they are actualized to the same Jam target name.
+
+t.write("project-root.jam", "")
+
+t.write("a.cpp", "")
+
+# The 'l' library will be built in two variants:
+# 'debug' (directly requested) and 'release' (requested
+# from 'a').
+t.write("Jamfile", """
+exe a : a.cpp l/<variant>release ;
+
+lib l : : <name>l_d <variant>debug ;
+lib l : : <name>l_r <variant>release ;
+""")
+
+t.run_build_system("-n")
+
+# A regression test. Two virtual target with the same properties
+# were created for 'l' target, which caused and error to be reported
+# when actualizing targets. The final error is correct, but we should
+# not create two duplicated targets. Thanks to Andre Hentz
+# for finding this bug.
+t.write("project-root.jam", "")
+
+t.write("a.cpp", "")
+
+t.write("Jamfile", """
+project a : requirements <link-runtime>static ;
+
+static-lib a : a.cpp l ;
+lib l : : <name>l_f ;
+""")
+
+t.run_build_system("-n")
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/searched_lib.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/skipping.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/skipping.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/skipping.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,41 @@
+#!/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.
+
+# Test that V2 does not fail gracelessy when any target is skipped.
+from BoostBuild import Tester, List
+
+# Create a temporary working directory
+t = Tester()
+t.write("a.cpp", """
+int main() {}
+""")
+
+t.write("b.cpp", """
+int main() {}
+""")
+
+t.write("c.cpp", """
+int main() {}
+""")
+
+t.write("Jamfile", """
+import feature : feature ;
+
+feature foo : 1 2 : link-incompatible ;
+
+exe a : a.cpp : <foo>1 ;
+exe b : b.cpp : <foo>2 ;
+exe c : c.cpp ;
+""")
+
+t.write("project-root.jam", """
+""")
+
+t.run_build_system("foo=1")
+
+t.cleanup()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/skipping.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/stage.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/stage.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/stage.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,143 @@
+#!/usr/bin/python
+
+# Test staging
+
+from BoostBuild import Tester
+t = Tester()
+
+t.write("project-root.jam", "import gcc ;")
+
+t.write(
+ "Jamfile",
+"""
+lib a : a.cpp ;
+stage dist : a a.h auxilliary/1 ;
+""")
+
+t.write(
+ "a.cpp",
+"""
+int
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+must_export_something;
+""")
+
+t.write("a.h", "")
+t.write("auxilliary/1", "")
+
+t.run_build_system()
+t.expect_addition(["dist/a.dll", "dist/a.h", "dist/1"])
+
+
+# Regression test: the following was causing the "duplicate target name"
+# error.
+t.write(
+ "Jamfile",
+"""
+project : requirements <hardcode-dll-paths>true ;
+lib a : a.cpp ;
+stage dist : a a.h auxilliary/1 ;
+alias dist-alias : dist ;
+""")
+t.run_build_system()
+
+
+# Test the <location> property
+t.write("Jamfile", """
+lib a : a.cpp ;
+stage dist : a
+ : <variant>debug:<location>ds <variant>release:<location>rs
+ ;
+""")
+
+t.run_build_system()
+t.expect_addition("ds/a.dll")
+
+t.run_build_system("release")
+t.expect_addition("rs/a.dll")
+
+# Test the <location> property in subprojects.
+# Thanks to Kirill Lapshin for bug report.
+
+t.write("project-root.jam", """
+path-constant DIST : dist ;
+""")
+
+t.write("Jamfile", "build-project d ;")
+
+t.write(
+ "d/Jamfile",
+"""
+exe a : a.cpp ;
+stage dist : a : <location>$(DIST) ;
+""")
+
+t.write("d/a.cpp", "int main() { return 0;}\n")
+
+t.run_build_system()
+t.expect_addition("dist/a.exe")
+
+t.rm("dist")
+# Workaround a BIG BUG: the response file is not deleted,
+# even if application *is* deleted. We'll try to use the
+# same response file when building from subdir, with very
+# bad results.
+t.rm("d/bin")
+t.run_build_system(subdir="d")
+t.expect_addition("dist/a.exe")
+
+
+# Check that 'stage' does not incorrectly reset target suffixes.
+t.write("a.cpp", """
+int main() {}
+""")
+
+t.write("project-root.jam", """
+import type ;
+type.register MYEXE : : EXE : main ;
+type.set-generated-target-suffix MYEXE : <optimization>off : myexe ;
+""")
+
+# Since <optimization>off is in properties when 'a' is built, and staged,
+# it's suffix should be "myexe".
+t.write("Jamfile", """
+stage dist : a ;
+myexe a : a.cpp ;
+""")
+
+t.run_build_system()
+t.expect_addition("dist/a.myexe")
+
+# Test 'stage's ability to traverse dependencies.
+t.write("a.cpp", """
+int main() { return 0; }
+
+""")
+
+t.write("l.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+foo() { }
+
+""")
+
+t.write("Jamfile", """
+lib l : l.cpp ;
+exe a : a.cpp l ;
+stage dist : a : <traverse-dependencies>on <include-type>EXE <include-type>LIB ;
+""")
+
+t.write("project-root.jam", "")
+
+t.rm("dist")
+t.run_build_system()
+t.expect_addition("dist/a.exe")
+t.expect_addition("dist/l.dll")
+
+
+t.cleanup()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/stage.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/standalone.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/standalone.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/standalone.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,48 @@
+#!/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.
+
+
+from BoostBuild import Tester, List
+
+t = Tester()
+
+# Regression tests: standalone project were not able to refer to targets
+# declared in themselfs!
+
+t.write("a.cpp", """
+int main()
+{
+ return 0;
+}
+
+""")
+
+t.write("project-root.jam", """
+import standalone ;
+""")
+
+t.write("standalone.jam", """
+import project ;
+
+project.initialize $(__name__) ;
+project standalone ;
+
+local pwd = [ PWD ] ;
+
+alias x : $(pwd)/../a.cpp ;
+alias runtime : x ;
+
+""")
+
+t.write("sub/Jamfile", """
+stage bin : /standalone//runtime ;
+""")
+
+t.run_build_system(subdir="sub")
+t.expect_addition("sub/bin/a.cpp")
+t.cleanup()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/standalone.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+# Emulate v1 behavior; with the boost-build file in the boost root directory.
+boost-build build ;
Added: boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/build/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/build/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/build/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+# The presence of this file emulates the Boost 1.27.0 release
+include $(BOOST_ROOT)/tools/build/bootstrap.jam ;
Added: boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/build/bootstrap.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/build/bootstrap.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/startup/boost-root/build/bootstrap.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,3 @@
+ECHO build system bootstrapped ;
+DEPENDS all : nothing ;
+NOTFILE nothing ;
Added: boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-env/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-env/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-env/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+boost-build ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-explicit/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-explicit/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-explicit/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+boost-build ../boost-root/build ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-implicit/readme.txt
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-implicit/readme.txt 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/startup/bootstrap-implicit/readme.txt 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+This file is only here so that cvs update -P won't fail to create a directory
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap1/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap1/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap1/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+# Bootstrap file not found via implicit lookup in BOOST_BUILD_PATH
+boost-build ;
Added: boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap1/subdir/readme.txt
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap1/subdir/readme.txt 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap1/subdir/readme.txt 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+This file is only here so cvs update -P will create the directory.
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap2/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap2/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap2/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+# Bootstrap file not found via explicit lookup in .
+boost-build . ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap3/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap3/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/startup/no-bootstrap3/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+# Call to boost-build is intentionally missing
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/startup_v1.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/startup_v1.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/startup_v1.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,94 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester
+import os
+import re
+
+def expect_substring(actual,expected):
+ return actual.find(expected) != -1
+
+def match_re(actual,expected):
+ return re.match(expected,actual,re.DOTALL) != None
+
+# Test the v1 startup behavior
+t = Tester(
+ executable='jam'
+ , match=match_re
+ , boost_build_path=''
+ , pass_toolset=0
+ )
+
+t.set_tree('startup')
+
+if os.name == 'nt':
+ t.run_build_system(
+ status=1, stdout="You didn't set BOOST_ROOT", match = expect_substring)
+
+t.run_build_system(
+ extra_args = '-sBOOST_ROOT=.', status=1
+ , stdout=r'''Unable to load Boost\.Build: could not find "boost-build\.jam".*BOOST_ROOT must be set'''
+ )
+
+os.chdir('no-bootstrap1')
+
+t.run_build_system(
+ extra_args = '-sBOOST_ROOT=.', status=1
+ , stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
+ + r'''.*attempted to load the build system by invoking'''
+ + r'''.*'boost-build ;'.*'''
+ + r'''but we were unable to find "bootstrap\.jam"'''
+ )
+
+# Descend to a subdirectory which /doesn't/ contain a boost-build.jam
+# file, and try again to test the crawl-up behavior.
+os.chdir('subdir')
+
+t.run_build_system(
+ extra_args = '-sBOOST_ROOT=.', status=1
+ , stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
+ + r'''.*attempted to load the build system by invoking'''
+ + r'''.*'boost-build ;'.*'''
+ + r'''but we were unable to find "bootstrap\.jam"'''
+ )
+
+os.chdir('../../no-bootstrap2')
+
+t.run_build_system(
+ extra_args = '-sBOOST_ROOT=.', status=1
+ , stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
+ + r'''.*attempted to load the build system by invoking'''
+ + r'''.*'boost-build \. ;'.*'''
+ + r'''but we were unable to find "bootstrap\.jam"'''
+ )
+
+os.chdir('../no-bootstrap3')
+
+t.run_build_system(
+ extra_args = '-sBOOST_ROOT=.', status=1
+ , stdout=r'''Unable to load Boost.Build
+.*boost-build.jam" was found.*
+However, it failed to call the "boost-build" rule'''
+ )
+
+# test bootstrapping based on BOOST_BUILD_PATH
+os.chdir('../bootstrap-env')
+t.run_build_system(
+ extra_args = '-sBOOST_ROOT=../boost-root -sBOOST_BUILD_PATH=../boost-root/build'
+ , stdout = 'build system bootstrapped'
+ )
+
+# test bootstrapping based on an explicit path in boost-build.jam
+os.chdir('../bootstrap-explicit')
+t.run_build_system(
+ extra_args = '-sBOOST_ROOT=../boost-root'
+ , stdout = 'build system bootstrapped'
+ )
+
+# test bootstrapping based on BOOST_ROOT
+os.chdir('../bootstrap-implicit')
+t.run_build_system(
+ extra_args = '-sBOOST_ROOT=../boost-root'
+ , stdout = 'build system bootstrapped'
+ )
+
+t.cleanup()
Added: boost-jam/boost-build/branches/upstream/current/test/startup_v2.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/startup_v2.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/startup_v2.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester
+import os
+import re
+
+def match_re(actual,expected):
+ return re.match(expected,actual,re.DOTALL) != None
+
+# Test the v1 startup behavior
+t = Tester(
+ match= match_re
+ , boost_build_path=''
+ , pass_toolset=0
+ )
+
+t.set_tree('startup')
+
+t.run_build_system(
+ status=1, stdout=r'''Unable to load Boost\.Build: could not find "boost-build.jam"
+.*Attempted search from .* up to the root''', match = match_re)
+
+os.chdir('no-bootstrap1')
+
+t.run_build_system(
+ status=1
+ , stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
+ + r'''.*attempted to load the build system by invoking'''
+ + r'''.*'boost-build ;'.*'''
+ + r'''but we were unable to find "bootstrap\.jam"'''
+ )
+
+# Descend to a subdirectory which /doesn't/ contain a boost-build.jam
+# file, and try again to test the crawl-up behavior.
+os.chdir('subdir')
+
+t.run_build_system(
+ status=1
+ , stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
+ + r'''.*attempted to load the build system by invoking'''
+ + r'''.*'boost-build ;'.*'''
+ + r'''but we were unable to find "bootstrap\.jam"'''
+ )
+
+os.chdir('../../no-bootstrap2')
+
+t.run_build_system(
+ status=1
+ , stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
+ + r'''.*attempted to load the build system by invoking'''
+ + r'''.*'boost-build \. ;'.*'''
+ + r'''but we were unable to find "bootstrap\.jam"'''
+ )
+
+os.chdir('../no-bootstrap3')
+
+t.run_build_system(
+ status=1
+ , stdout=r'''Unable to load Boost.Build
+.*boost-build.jam" was found.*
+However, it failed to call the "boost-build" rule'''
+ )
+
+# test bootstrapping based on BOOST_BUILD_PATH
+os.chdir('../bootstrap-env')
+t.run_build_system(
+ extra_args = '-sBOOST_BUILD_PATH=../boost-root/build'
+ , stdout = 'build system bootstrapped'
+ )
+
+# test bootstrapping based on an explicit path in boost-build.jam
+os.chdir('../bootstrap-explicit')
+t.run_build_system(
+ stdout = 'build system bootstrapped'
+ )
+
+t.cleanup()
+
Added: boost-jam/boost-build/branches/upstream/current/test/subdir1/file-to-bind
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/subdir1/file-to-bind 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/subdir1/file-to-bind 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+# This file intentionally left blank
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/suffix.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/suffix.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/suffix.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,65 @@
+#!/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.
+
+from BoostBuild import Tester, List
+
+t = Tester()
+
+# Regression test: when staging V2 used to change suffixes on targets
+# corresponding to real files.
+t.write("Jamfile", """
+import type : register ;
+register A : a1 a2 a3 ;
+
+stage a : a.a3 ;
+""")
+
+t.write("project-root.jam", "")
+t.write("a.a3", "")
+
+t.run_build_system()
+t.expect_addition("a/a.a3");
+
+# Regression test: we should be able to specify empty suffix for
+# derived target type, even if base type has non-empty suffix.
+t.write("a.cpp", "")
+
+t.write("suffixes.jam", """
+import type ;
+import generators ;
+import common ;
+
+type.register First : first : ;
+type.register Second : "" : First : main ;
+
+generators.register-standard $(__name__).second : CPP : Second ;
+
+rule second
+{
+ TOUCH on $(<) = [ common.file-creation-command ] ;
+}
+
+actions second
+{
+ $(TOUCH) $(<)
+}
+
+""")
+
+t.write("project-root.jam", """
+import suffixes ;
+""")
+
+t.write("Jamfile", """
+second a : a.cpp ;
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/a")
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/suffix.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/svn_tree.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/svn_tree.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/svn_tree.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,670 @@
+#!/usr/bin/env python
+#
+# tree.py: tools for comparing directory trees
+#
+# Subversion is a tool for revision control.
+# See http://subversion.tigris.org for more information.
+#
+# ====================================================================
+# Copyright (c) 2001 Sam Tobin-Hochstadt. All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at http://subversion.tigris.org/license-1.html.
+# If newer versions of this license are posted there, you may use a
+# newer version instead, at your option.
+#
+######################################################################
+
+# This file was modified by Vladimir Prus to store modification times in
+# tree nodes.
+
+import re
+import string
+import os.path
+import os
+import stat
+
+
+
+#========================================================================
+
+# ===> Overview of our Datastructures <===
+
+# The general idea here is that many, many things can be represented by
+# a tree structure:
+
+# - a working copy's structure and contents
+# - the output of 'svn status'
+# - the output of 'svn checkout/update'
+# - the output of 'svn commit'
+
+# The idea is that a test function creates a "expected" tree of some
+# kind, and is then able to compare it to an "actual" tree that comes
+# from running the Subversion client. This is what makes a test
+# automated; if an actual and expected tree match exactly, then the test
+# has passed. (See compare_trees() below.)
+
+# The SVNTreeNode class is the fundamental data type used to build tree
+# structures. The class contains a method for "dropping" a new node
+# into an ever-growing tree structure. (See also create_from_path()).
+
+# We have four parsers in this file for the four use cases listed above:
+# each parser examines some kind of input and returns a tree of
+# SVNTreeNode objects. (See build_tree_from_checkout(),
+# build_tree_from_commit(), build_tree_from_status(), and
+# build_tree_from_wc()). These trees are the "actual" trees that result
+# from running the Subversion client.
+
+# Also necessary, of course, is a convenient way for a test to create an
+# "expected" tree. The test *could* manually construct and link a bunch
+# of SVNTreeNodes, certainly. But instead, all the tests are using the
+# build_generic_tree() routine instead.
+
+# build_generic_tree() takes a specially-formatted list of lists as
+# input, and returns a tree of SVNTreeNodes. The list of lists has this
+# structure:
+
+# [ ['/full/path/to/item', 'text contents', {prop-hash}, {att-hash}],
+# [...],
+# [...],
+# ... ]
+
+# You can see that each item in the list essentially defines an
+# SVNTreeNode. build_generic_tree() instantiates a SVNTreeNode for each
+# item, and then drops it into a tree by parsing each item's full path.
+
+# So a typical test routine spends most of its time preparing lists of
+# this format and sending them to build_generic_tree(), rather than
+# building the "expected" trees directly.
+
+# ### Note: in the future, we'd like to remove this extra layer of
+# ### abstraction. We'd like the SVNTreeNode class to be more
+# ### directly programmer-friendly, providing a number of accessor
+# ### routines, so that tests can construct trees directly.
+
+# The first three fields of each list-item are self-explanatory. It's
+# the fourth field, the "attribute" hash, that needs some explanation.
+# The att-hash is used to place extra information about the node itself,
+# depending on the parsing context:
+
+# - in the 'svn co/up' use-case, each line of output starts with two
+# characters from the set of (A, D, G, U, C, _). This status code
+# is stored in a attribute named 'status'.
+
+# - in the 'svn ci/im' use-case, each line of output starts with one
+# of the words (Adding, Deleting, Sending). This verb is stored in
+# an attribute named 'verb'.
+
+# - in the 'svn status' use-case (which is always run with the -v
+# (--verbose) flag), each line of output contains a working revision
+# number and a two-letter status code similar to the 'svn co/up'
+# case. The repository revision is also printed. All of this
+# information is stored in attributes named 'wc_rev', 'status', and
+# 'repos_rev', respectively.
+
+# - in the working-copy use-case, the att-hash is ignored.
+
+
+# Finally, one last explanation: the file 'actions.py' contain a number
+# of helper routines named 'run_and_verify_FOO'. These routines take
+# one or more "expected" trees as input, then run some svn subcommand,
+# then push the output through an appropriate parser to derive an
+# "actual" tree. Then it runs compare_trees() and returns the result.
+# This is why most tests typically end with a call to
+# run_and_verify_FOO().
+
+
+
+
+# A node in a tree.
+#
+# If CHILDREN is None, then the node is a file. Otherwise, CHILDREN
+# is a list of the nodes making up that directory's children.
+#
+# NAME is simply the name of the file or directory. CONTENTS is a
+# string that contains the file's contents (if a file), PROPS are
+# properties attached to files or dirs, and ATTS is a dictionary of
+# other metadata attached to the node.
+
+class SVNTreeNode:
+
+ def __init__(self, name, children=None, contents=None, props={}, atts={}):
+ self.name = name
+ self.mtime = 0
+ self.children = children
+ self.contents = contents
+ self.props = props
+ self.atts = atts
+ self.path = name
+
+# TODO: Check to make sure contents and children are mutually exclusive
+
+ def add_child(self, newchild):
+ if self.children is None: # if you're a file,
+ self.children = [] # become an empty dir.
+ child_already_exists = 0
+ for a in self.children:
+ if a.name == newchild.name:
+ child_already_exists = 1
+ break
+ if child_already_exists == 0:
+ self.children.append(newchild)
+ newchild.path = os.path.join (self.path, newchild.name)
+
+ # If you already have the node,
+ else:
+ if newchild.children is None:
+ # this is the 'end' of the chain, so copy any content here.
+ a.contents = newchild.contents
+ a.props = newchild.props
+ a.atts = newchild.atts
+ a.path = os.path.join (self.path, newchild.name)
+ else:
+ # try to add dangling children to your matching node
+ for i in newchild.children:
+ a.add_child(i)
+
+
+ def pprint(self):
+ print " * Node name: ", self.name
+ print " Path: ", self.path
+ print " Contents: ", self.contents
+ print " Properties:", self.props
+ print " Attributes:", self.atts
+ ### FIXME: I'd like to be able to tell the difference between
+ ### self.children is None (file) and self.children == [] (empty
+ ### diretory), but it seems that most places that construct
+ ### SVNTreeNode objects don't even try to do that. --xbc
+ if self.children is not None:
+ print " Children: ", len(self.children)
+ else:
+ print " Children: is a file."
+
+# reserved name of the root of the tree
+
+root_node_name = "__SVN_ROOT_NODE"
+
+# Exception raised if you screw up in this module.
+
+class SVNTreeError(Exception): pass
+
+# Exception raised if two trees are unequal
+
+class SVNTreeUnequal(Exception): pass
+
+# Exception raised if one node is file and other is dir
+
+class SVNTypeMismatch(Exception): pass
+
+# Exception raised if get_child is passed a file.
+
+class SVNTreeIsNotDirectory(Exception): pass
+
+
+# Some attributes 'stack' on each other if the same node is added
+# twice to a tree. Place all such special cases in here.
+def attribute_merge(orighash, newhash):
+ "Merge the attributes in NEWHASH into ORIGHASH."
+
+ if orighash.has_key('verb') and newhash.has_key('verb'):
+ # Special case: if a commit reports a node as "deleted", then
+ # "added", it's a replacment.
+ if orighash['verb'] == "Deleting":
+ if newhash['verb'] == "Adding":
+ orighash['verb'] = "Replacing"
+
+ # Add future stackable attributes here...
+
+ return orighash
+
+
+# helper func
+def add_elements_as_path(top_node, element_list):
+ """Add the elements in ELEMENT_LIST as if they were a single path
+ below TOP_NODE."""
+
+ # The idea of this function is to take a list like so:
+ # ['A', 'B', 'C'] and a top node, say 'Z', and generate a tree
+ # like this:
+ #
+ # Z -> A -> B -> C
+ #
+ # where 1 -> 2 means 2 is a child of 1.
+ #
+
+ prev_node = top_node
+ for i in element_list:
+ new_node = SVNTreeNode(i, None)
+ prev_node.add_child(new_node)
+ prev_node = new_node
+
+
+# Sorting function -- sort 2 nodes by their names.
+def node_is_greater(a, b):
+ "Sort the names of two nodes."
+ # Interal use only
+ if a.name == b.name:
+ return 0
+ if a.name > b.name:
+ return 1
+ else:
+ return -1
+
+
+# Helper for compare_trees
+def compare_file_nodes(a, b):
+ """Compare two nodes' names, contents, and properties, ignoring
+ children. Return 0 if the same, 1 otherwise."""
+ if a.name != b.name:
+ return 1
+ if a.contents != b.contents:
+ return 1
+ if a.props != b.props:
+ return 1
+ if a.atts != b.atts:
+ return 1
+
+
+# Internal utility used by most build_tree_from_foo() routines.
+#
+# (Take the output and .add_child() it to a root node.)
+
+def create_from_path(path, contents=None, props={}, atts={}):
+ """Create and return a linked list of treenodes, given a PATH
+ representing a single entry into that tree. CONTENTS and PROPS are
+ optional arguments that will be deposited in the tail node."""
+
+ # get a list of all the names in the path
+ # each of these will be a child of the former
+ elements = path.split("/")
+ if len(elements) == 0:
+ raise SVNTreeError
+
+ root_node = SVNTreeNode(elements[0], None)
+
+ add_elements_as_path(root_node, elements[1:])
+
+ # deposit contents in the very last node.
+ node = root_node
+ while 1:
+ if node.children is None:
+ node.contents = contents
+ node.props = props
+ node.atts = atts
+ break
+ node = node.children[0]
+
+ return root_node
+
+
+# helper for handle_dir(), which is a helper for build_tree_from_wc()
+def get_props(path):
+ "Return a hash of props for PATH, using the svn client."
+
+ # It's not kosher to look inside SVN/ and try to read the internal
+ # property storage format. Instead, we use 'svn proplist'. After
+ # all, this is the only way the user can retrieve them, so we're
+ # respecting the black-box paradigm.
+
+ props = {}
+ output, errput = main.run_svn(1, "proplist", path, "--verbose")
+
+ for line in output:
+ name, value = line.split(' : ')
+ name = string.strip(name)
+ value = string.strip(value)
+ props[name] = value
+
+ return props
+
+
+# helper for handle_dir(), which helps build_tree_from_wc()
+def get_text(path):
+ "Return a string with the textual contents of a file at PATH."
+
+ # sanity check
+ if not os.path.isfile(path):
+ return None
+
+ fp = open(path, 'r')
+ contents = fp.read()
+ fp.close()
+ return contents
+
+
+# main recursive helper for build_tree_from_wc()
+def handle_dir(path, current_parent, load_props, ignore_svn):
+
+ # get a list of all the files
+ all_files = os.listdir(path)
+ files = []
+ dirs = []
+
+ # put dirs and files in their own lists, and remove SVN dirs
+ for f in all_files:
+ f = os.path.join(path, f)
+ if (os.path.isdir(f) and os.path.basename(f) != 'SVN'):
+ dirs.append(f)
+ elif os.path.isfile(f):
+ files.append(f)
+
+ # add each file as a child of CURRENT_PARENT
+ for f in files:
+ fcontents = get_text(f)
+ if load_props:
+ fprops = get_props(f)
+ else:
+ fprops = {}
+ c = SVNTreeNode(os.path.basename(f), None,
+ fcontents, fprops)
+ c.mtime = os.stat(f)[stat.ST_MTIME]
+ current_parent.add_child(c)
+
+ # for each subdir, create a node, walk its tree, add it as a child
+ for d in dirs:
+ if load_props:
+ dprops = get_props(d)
+ else:
+ dprops = {}
+ new_dir_node = SVNTreeNode(os.path.basename(d), [], None, dprops)
+ handle_dir(d, new_dir_node, load_props, ignore_svn)
+ new_dir_node.mtime = os.stat(f)[stat.ST_MTIME]
+ current_parent.add_child(new_dir_node)
+
+def get_child(node, name):
+ """If SVNTreeNode NODE contains a child named NAME, return child;
+ else, return None. If SVNTreeNode is not a directory, raise a
+ SVNTreeIsNotDirectory exception"""
+ if node.children == None:
+ raise SVNTreeIsNotDirectory
+ for n in node.children:
+ if (name == n.name):
+ return n
+ return None
+
+
+# Helper for compare_trees
+def default_singleton_handler(a, baton):
+ "Printing SVNTreeNode A's name, then raise SVNTreeUnequal."
+ print "Got singleton", a.name
+ a.pprint()
+ raise SVNTreeUnequal
+
+
+###########################################################################
+###########################################################################
+# EXPORTED ROUTINES ARE BELOW
+
+
+# Main tree comparison routine!
+
+def compare_trees(a, b,
+ singleton_handler_a = None,
+ a_baton = None,
+ singleton_handler_b = None,
+ b_baton = None):
+ """Compare SVNTreeNodes A and B, expressing differences using FUNC_A
+ and FUNC_B. FUNC_A and FUNC_B are functions of two arguments (a
+ SVNTreeNode and a context baton), and may raise exception
+ SVNTreeUnequal. Their return value is ignored.
+
+ If A and B are both files, then return 0 if their contents,
+ properties, and names are all the same; else raise a SVNTreeUnequal.
+ If A is a file and B is a directory, raise a SVNTypeMismatch; same
+ vice-versa. If both are directories, then for each entry that
+ exists in both, call compare_trees on the two entries; otherwise, if
+ the entry exists only in A, invoke FUNC_A on it, and likewise for
+ B with FUNC_B."""
+
+ def display_nodes(a, b):
+ 'Display two nodes, expected and actual.'
+ print "============================================================="
+ print "Expected", b.name, "and actual", a.name, "are different!"
+ print "============================================================="
+ print "EXPECTED NODE TO BE:"
+ print "============================================================="
+ b.pprint()
+ print "============================================================="
+ print "ACTUAL NODE FOUND:"
+ print "============================================================="
+ a.pprint()
+
+ # Setup singleton handlers
+ if (singleton_handler_a is None):
+ singleton_handler_a = default_singleton_handler
+ if (singleton_handler_b is None):
+ singleton_handler_b = default_singleton_handler
+
+ try:
+ # A and B are both files.
+ if ((a.children is None) and (b.children is None)):
+ if compare_file_nodes(a, b):
+ display_nodes(a, b)
+ raise main.SVNTreeUnequal
+ # One is a file, one is a directory.
+ elif (((a.children is None) and (b.children is not None))
+ or ((a.children is not None) and (b.children is None))):
+ display_nodes(a, b)
+ raise main.SVNTypeMismatch
+ # They're both directories.
+ else:
+ # First, compare the directories' two hashes.
+ if (a.props != b.props) or (a.atts != b.atts):
+ display_nodes(a, b)
+ raise main.SVNTreeUnequal
+
+ accounted_for = []
+ # For each child of A, check and see if it's in B. If so, run
+ # compare_trees on the two children and add b's child to
+ # accounted_for. If not, run FUNC_A on the child. Next, for each
+ # child of B, check and see if it's in accounted_for. If it is,
+ # do nothing. If not, run FUNC_B on it.
+ for a_child in a.children:
+ b_child = get_child(b, a_child.name)
+ if b_child:
+ accounted_for.append(b_child)
+ compare_trees(a_child, b_child,
+ singleton_handler_a, a_baton,
+ singleton_handler_b, b_baton)
+ else:
+ singleton_handler_a(a_child, a_baton)
+ for b_child in b.children:
+ if (b_child not in accounted_for):
+ singleton_handler_b(b_child, b_baton)
+ return 0
+ except SVNTypeMismatch:
+ print 'Unequal Types: one Node is a file, the other is a directory'
+ raise SVNTreeUnequal
+ except SVNTreeIsNotDirectory:
+ print "Error: Foolish call to get_child."
+ sys.exit(1)
+ except IndexError:
+ print "Error: unequal number of children"
+ raise SVNTreeUnequal
+ except SVNTreeUnequal:
+ if a.name == root_node_name:
+ return 1
+ else:
+ print "Unequal at node %s" % a.name
+ raise SVNTreeUnequal
+ return 0
+
+
+
+
+# Visually show a tree's structure
+
+def dump_tree(n,indent=""):
+ "Print out a nice representation of the tree's structure."
+
+ # Code partially stolen from Dave Beazley
+ if n.children is None:
+ tmp_children = []
+ else:
+ tmp_children = n.children
+
+ if n.name == root_node_name:
+ print "%s%s" % (indent, "ROOT")
+ else:
+ print "%s%s" % (indent, n.name)
+
+ indent = indent.replace("-"," ")
+ indent = indent.replace("+"," ")
+ for i in range(len(tmp_children)):
+ c = tmp_children[i]
+ if i == len(tmp_children
+ )-1:
+ dump_tree(c,indent + " +-- ")
+ else:
+ dump_tree(c,indent + " |-- ")
+
+
+###################################################################
+###################################################################
+# PARSERS that return trees made of SVNTreeNodes....
+
+
+###################################################################
+# Build an "expected" static tree from a list of lists
+
+
+# Create a list of lists, of the form:
+#
+# [ [path, contents, props, atts], ... ]
+#
+# and run it through this parser. PATH is a string, a path to the
+# object. CONTENTS is either a string or None, and PROPS and ATTS are
+# populated dictionaries or {}. Each CONTENTS/PROPS/ATTS will be
+# attached to the basename-node of the associated PATH.
+
+def build_generic_tree(nodelist):
+ "Given a list of lists of a specific format, return a tree."
+
+ root = SVNTreeNode(root_node_name)
+
+ for list in nodelist:
+ new_branch = create_from_path(list[0], list[1], list[2], list[3])
+ root.add_child(new_branch)
+
+ return root
+
+
+####################################################################
+# Build trees from different kinds of subcommand output.
+
+
+# Parse co/up output into a tree.
+#
+# Tree nodes will contain no contents, and only one 'status' att.
+
+def build_tree_from_checkout(lines):
+ "Return a tree derived by parsing the output LINES from 'co' or 'up'."
+
+ root = SVNTreeNode(root_node_name)
+ rm = re.compile ('^([MAGCUD_ ][MAGCUD_ ]) (.+)')
+
+ for line in lines:
+ match = rm.search(line)
+ if match and match.groups():
+ new_branch = create_from_path(match.group(2), None, {},
+ {'status' : match.group(1)})
+ root.add_child(new_branch)
+
+ return root
+
+
+# Parse ci/im output into a tree.
+#
+# Tree nodes will contain no contents, and only one 'verb' att.
+
+def build_tree_from_commit(lines):
+ "Return a tree derived by parsing the output LINES from 'ci' or 'im'."
+
+ # Lines typically have a verb followed by whitespace then a path.
+ root = SVNTreeNode(root_node_name)
+ rm1 = re.compile ('^(\w+)\s+(.+)')
+ rm2 = re.compile ('^Transmitting')
+
+ for line in lines:
+ match = rm2.search(line)
+ if not match:
+ match = rm1.search(line)
+ if match and match.groups():
+ new_branch = create_from_path(match.group(2), None, {},
+ {'verb' : match.group(1)})
+ root.add_child(new_branch)
+
+ return root
+
+
+# Parse status output into a tree.
+#
+# Tree nodes will contain no contents, and these atts:
+#
+# 'status', 'wc_rev', 'repos_rev'
+# ... and possibly 'locked', 'copied', IFF columns non-empty.
+#
+
+def build_tree_from_status(lines):
+ "Return a tree derived by parsing the output LINES from 'st'."
+
+ root = SVNTreeNode(root_node_name)
+ rm = re.compile ('^.+\:.+(\d+)')
+ lastline = string.strip(lines.pop())
+ match = rm.search(lastline)
+ if match and match.groups():
+ repos_rev = match.group(1)
+ else:
+ repos_rev = '?'
+
+ # Try http://www.wordsmith.org/anagram/anagram.cgi?anagram=ACDRMGU
+ rm = re.compile ('^([MACDRUG_ ][MACDRUG_ ])(.)(.) . [^0-9-]+(\d+|-)(.{23})(.+)')
+ for line in lines:
+ match = rm.search(line)
+ if match and match.groups():
+ if match.group(5) != '-': # ignore items that only exist on repos
+ atthash = {'status' : match.group(1),
+ 'wc_rev' : match.group(4),
+ 'repos_rev' : repos_rev}
+ if match.group(2) != ' ':
+ atthash['locked'] = match.group(2)
+ if match.group(3) != ' ':
+ atthash['copied'] = match.group(3)
+ new_branch = create_from_path(match.group(6), None, {}, atthash)
+
+ root.add_child(new_branch)
+
+ return root
+
+
+####################################################################
+# Build trees by looking at the working copy
+
+
+# The reason the 'load_props' flag is off by default is because it
+# creates a drastic slowdown -- we spawn a new 'svn proplist'
+# process for every file and dir in the working copy!
+
+
+def build_tree_from_wc(wc_path, load_props=0, ignore_svn=1):
+ """Takes WC_PATH as the path to a working copy. Walks the tree below
+ that path, and creates the tree based on the actual found
+ files. If IGNORE_SVN is true, then exclude SVN dirs from the tree.
+ If LOAD_PROPS is true, the props will be added to the tree."""
+
+ root = SVNTreeNode(root_node_name, None)
+
+ # if necessary, store the root dir's props in the root node.
+ if load_props:
+ root.props = get_props(wc_path)
+
+ # Walk the tree recursively
+ handle_dir(os.path.normpath(wc_path), root, load_props, ignore_svn)
+
+ return root
+
+### End of file.
+# local variables:
+# eval: (load-file "../../../../../tools/dev/svn-dev.el")
+# end:
Added: boost-jam/boost-build/branches/upstream/current/test/symlink.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/symlink.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/symlink.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+
+# Test the 'symlink' rule
+
+from BoostBuild import Tester, List
+import os
+t = Tester()
+
+if os.name != 'posix':
+ print "The symlink tests can be run on posix only"
+ sys.exit(1)
+
+t.write("project-root.jam", "import gcc ;")
+t.write("Jamfile", """
+exe hello : hello.cpp ;
+symlink hello_release : hello/<variant>release ;
+symlink hello_debug : hello/<variant>debug ;
+symlink links/hello_release : hello/<variant>release ;
+""")
+t.write("hello.cpp", """
+int main()
+{
+ return 0;
+}
+""")
+
+t.run_build_system()
+t.expect_addition(List('hello_debug.exe hello_release.exe links/hello_release.exe'))
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/symlink.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/tag.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/tag.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/tag.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,54 @@
+#!/usr/bin/python
+
+# Copyright (C) Pedro Ferreira 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.
+
+from BoostBuild import Tester, List
+
+t = Tester()
+
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+local tags = <variant>debug:<tag>_d <variant>release:<tag>_r <link>shared:<tag>s <link>static:<tag>t ;
+exe a : a.cpp : $(tags) ;
+lib b : a.cpp : $(tags) ;
+stage c : a ;
+""")
+
+t.write("a.cpp", """
+int main()
+{
+ return 0;
+}
+
+#ifdef _MSC_VER
+__declspec (dllexport) void x () {}
+#endif
+""")
+
+file_list = \
+List("bin/$toolset/debug/a_ds.exe") + \
+List("bin/$toolset/debug/b_ds.dll") + \
+List("c/a_ds.exe") + \
+List("bin/$toolset/release/a_rs.exe") + \
+List("bin/$toolset/release/b_rs.dll") + \
+List("c/a_rs.exe") + \
+List("bin/$toolset/debug/link-static/a_dt.exe") + \
+List("bin/$toolset/debug/link-static/b_dt.lib") + \
+List("c/a_dt.exe") + \
+List("bin/$toolset/release/link-static/a_rt.exe") + \
+List("bin/$toolset/release/link-static/b_rt.lib") + \
+List("c/a_rt.exe")
+
+variants = "debug release link=static,shared"
+
+t.run_build_system(variants)
+t.expect_addition(file_list)
+
+t.run_build_system(variants + " clean")
+t.expect_removal(file_list)
+
+t.cleanup()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/tag.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/template.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/template.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/template.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,42 @@
+#!/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.
+
+# This file is template for Boost.Build tests. It creates a simple
+# project that builds one exe from one source, and checks that the exe
+# is really created.
+from BoostBuild import Tester, List
+
+# Create a temporary working directory
+t = Tester()
+
+# Create the needed files
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+exe hello : hello.cpp ;
+""")
+t.write("hello.cpp", """
+int main()
+{
+ return 0;
+}
+
+""")
+
+t.run_build_system()
+
+# First, create a list of three pathnames
+file_list = List("bin/$toolset/debug/") * List("hello.exe hello.obj")
+# Second, assert that those files were added as result of the last build system invocation.
+t.expect_addition(file_list)
+
+# Invoke the build system once again
+t.run_build_system("clean")
+# Check if the files added previously were removed.
+t.expect_removal(file_list)
+
+# Remove temporary directories
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/template.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/test-config-example.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/test-config-example.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/test-config-example.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,11 @@
+
+# Skeleton for test configuration. If your local configuration
+# interferes with testing, rename this files to 'test-system.jam'
+# and tweak it. When tests are run, only this file will be loaded,
+# while site-config.jam and user-config.jam will be ignored.
+
+import toolset : using ;
+
+using gcc ;
+using msvc : : "P:/Program Files/Microsoft Visual Studio/vc98" : : vcvars32-p.bat ;
+using borland ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/test.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/test.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/test.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,15 @@
+import indirect ;
+import string ;
+import numbers ;
+import sequence ;
+import "class" ;
+import os ;
+import path ;
+import feature ;
+import property ;
+import build-request ;
+import container ;
+
+
+actions nothing { }
+nothing all ;
Added: boost-jam/boost-build/branches/upstream/current/test/test1.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/test1.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/test1.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+
+import BoostBuild
+
+t = BoostBuild.Tester()
+
+t.write("test.jam","""
+actions unbuilt { } unbuilt all ;
+ECHO "Hi" ;
+""")
+
+t.run_build_system("-ftest.jam", stdout="Hi\n")
+t.pass_test()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/test1.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/test2/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/test2/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/test2/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,4 @@
+
+project-root ;
+
+exe foo : foo.cpp ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/test2/Jamrules
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/test/test2/foo.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/test2/foo.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/test2/foo.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,10 @@
+// Copyright (c) 2003 Vladimir Prus
+//
+// 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)
+//
+// http://www.boost.org
+//
+
+int main() { return 0; }
Added: boost-jam/boost-build/branches/upstream/current/test/test2.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/test2.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/test2.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester, List
+from time import sleep
+
+t = Tester()
+
+t.set_tree("test2")
+t.run_build_system("-sBOOST_BUILD_PATH=" + t.original_workdir + "/..")
+
+file_list = 'bin/foo/$toolset/debug/runtime-link-dynamic/' * List("foo foo.o")
+t.expect_addition(file_list)
+
+
+t.write("foo.cpp", "int main(int, char**) { return 0; }\n")
+t.run_build_system("-d2 -sBOOST_BUILD_PATH=" + t.original_workdir + "/..")
+t.expect_touch(file_list)
+t.pass_test()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/test2.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/test_all.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/test_all.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/test_all.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,145 @@
+#!/usr/bin/python
+import os, sys, string
+from BoostBuild import get_toolset
+
+# clear environment for testing
+#
+for s in (
+ 'BOOST_ROOT','BOOST_BUILD_PATH','JAM_TOOLSET','BCCROOT',
+ 'MSVCDir','MSVC','MSVCNT','MINGW','watcom'
+ ):
+
+ try:
+ del os.environ[s]
+ except:
+ pass
+
+def run_tests(critical_tests, other_tests):
+ """Runs first critical tests and then other_tests.
+
+ Stops on first error, and write the name of failed test to
+ test_results.txt. Critical tests are run in the specified order,
+ other tests are run starting with the one that failed the last time.
+ """
+ last_failed = last_failed_test()
+ other_tests = reorder_tests(other_tests, last_failed)
+ all_tests = critical_tests + other_tests
+
+ invocation_dir = os.getcwd()
+
+ failures_count = 0
+ for i in all_tests:
+ print ("%-25s : " %(i)),
+ try:
+ __import__(i)
+ except SystemExit:
+ print "FAILED"
+ if failures_count == 0:
+ f = open(os.path.join(invocation_dir, 'test_results.txt'), 'w')
+ f.write(i)
+ f.close()
+ failures_count = failures_count + 1
+ # Restore the current directory, which might be changed by the
+ # test
+ os.chdir(invocation_dir)
+ continue
+ print "PASSED"
+ sys.stdout.flush() # makes testing under emacs more entertaining.
+
+ # Erase the file on success
+ if failures_count == 0:
+ open('test_results.txt', 'w')
+
+
+def last_failed_test():
+ "Returns the name of last failed test or None"
+ try:
+ f = open("test_results.txt")
+ s = string.strip(f.read())
+ return s
+ except:
+ return None
+
+def reorder_tests(tests, first_test):
+ try:
+ n = tests.index(first_test)
+ return [first_test] + tests[:n] + tests[n+1:]
+ except ValueError:
+ return tests
+
+
+critical_tests = ["unit_tests", "module_actions", "startup_v1", "startup_v2"]
+
+critical_tests += ["core_d12", "core_typecheck", "core_delete_module",
+ "core_varnames", "core_import_module"]
+
+tests = [ "project_test1",
+ "project_test3",
+ "project_test4",
+ "generators_test",
+ "dependency_test",
+ "path_features",
+ "relative_sources",
+ "no_type",
+ "chain",
+ "default_build",
+ "use_requirements",
+ "conditionals",
+ "stage",
+ "prebuilt",
+ "project_dependencies",
+ "build_dir",
+ "searched_lib",
+ "make_rule",
+ "alias",
+ "alternatives",
+ "default_features",
+ "print",
+ "ndebug",
+ "explicit",
+ "absolute_sources",
+ "dependency_property",
+ "custom_generator",
+ "bad_dirname",
+ "c_file",
+ "inline",
+ "conditionals2",
+ "property_expansion",
+ "loop",
+ "conditionals3",
+ "tag",
+ "suffix",
+ "inherit_toolset",
+ "skipping",
+ "project_root",
+ "glob",
+ "project_root_constants",
+ "double_loading",
+ "dll_path",
+ "regression",
+ "composite",
+ "library_chain",
+ "unit_test",
+ "standalone",
+ "expansion",
+ "wrapper",
+ "duplicate",
+ "library_property",
+ #"ordered_properties",
+ ]
+
+if os.name == 'posix':
+ tests.append("symlink")
+ # On windows, library order is not important, so skip this test
+ # Besides, it fails ;-)
+ tests.append("library_order")
+
+if string.find(get_toolset(), 'gcc') == 0:
+ tests.append("gcc_runtime")
+
+if os.environ.has_key('QTDIR'):
+ tests.append("railsys")
+else:
+ print 'skipping railsys test since QTDIR environment variable is unset'
+
+run_tests(critical_tests, tests)
Added: boost-jam/boost-build/branches/upstream/current/test/test_nt_line_length.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/test_nt_line_length.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/test_nt_line_length.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,41 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+# Test that the patch which allows long command-lines in actions on NT is
+# working. For reasons of backward-compatibility, this patch requires that the
+# action fits on a single command-line, and that the JAMSHELL variable on the
+# target being built is set to "%".
+if $(NT)
+{
+ #
+ # Build a really long commandline. (> 10K characters).
+ #
+ ten = 0 1 2 3 4 5 6 7 8 9 ;
+ 1x7chars = 0_____ ;
+ # add a digit and multiply by 10
+ 10x8chars = $(ten)$(1x7chars) ;
+ # add a digit to each of 10 strings and multiply by 10
+ 100x9chars = $(ten)$(10x8chars) ;
+ # add a digit to each of 100 strings and multiply by 10
+ 1000x10chars = $(ten)$(100x9chars) ;
+
+ #
+ # Cause line_length_test to be built
+ #
+ actions do_echo
+ {
+ echo $(text)
+ }
+
+ 400x10chars = $(ten[1-4])$(100x9chars) ;
+
+ text on line_length_test = $(400x10chars) 40$(10x8chars[1-9]) 01234 ;
+ text on line_length_test = $(1000x10chars) $(1000x10chars) ;
+ JAMSHELL on line_length_test = % ;
+ DEPENDS all : line_length_test ;
+
+ do_echo line_length_test ;
+}
Added: boost-jam/boost-build/branches/upstream/current/test/test_system.html
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/test_system.html 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/test_system.html 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,551 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+"http://www.w3.org/TR/html4/strict.dtd">
+
+<html>
+ <head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st April 2002), see www.w3.org">
+ <!--tidy options: -i -wrap 78 -->
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+
+ <title>A testing system for Boost.Build</title>
+
+ <style type="text/css">
+ hr { color: black }
+ p.revision { text-align: right; font-style: italic }
+ pre.code { margin-left: 2em }
+ pre.example { margin-left: 2em; border: solid black thin }
+ pre.output { margin-left: 2em }
+ img.banner { border: 0; float: left }
+ h1 { text-align: right }
+ br.clear { clear: left }
+ div.attention { color: red }
+ </style>
+ </head>
+
+ <body>
+ <p><a href="../../../../index.htm"><img class="banner" height="86" width=
+ "277" alt="C++ Boost" src="../../../../boost.png"></a></p>
+
+ <h1>A testing system for Boost.Build<br class="clear">
+ </h1>
+ <hr>
+
+ <dl class="page-index">
+ <dt><a href="#sec-intro">Introduction for users</a></dt>
+
+ <dt><a href="#sec-developers">Introduction for developers</a></dt>
+
+ <dd>
+ <dl class="page-index">
+ <dt><a href="#sec-intro-changing">Changing the working
+ directory</a></dt>
+
+ <dt><a href="#sec-intro-examining">Examining the working directory
+ and changing it</a></dt>
+
+ <dt><a href="#sec-intro-results">Test result</a></dt>
+ </dl>
+ </dd>
+
+ <dt><a href="#sec-reference">Reference documentation</a></dt>
+
+ <dd>
+ <dl class="page-index">
+ <dt><a href="#method-__init__">Method __init__</a></dt>
+
+ <dt><a href="#method-set_tree">Method <tt>set_tree</tt></a></dt>
+
+ <dt><a href="#method-write">Method <tt>write</tt></a></dt>
+
+ <dt><a href="#method-copy">Method <tt>copy</tt></a></dt>
+
+ <dt><a href="#method-touch">Method <tt>touch</tt></a></dt>
+
+ <dt><a href="#method-run_build_system">Method
+ <tt>run_build_system</tt></a></dt>
+
+ <dt><a href="#method-read">Method <tt>read</tt></a></dt>
+
+ <dt><a href="#method-read_and_strip">Method
+ <tt>read_and_strip</tt></a></dt>
+
+ <dt><a href="#methods-expectations">Methods for declaring
+ expectations</a></dt>
+
+ <dt><a href="#methods-ignoring">Methods for ignoring
+ changes</a></dt>
+
+ <dt><a href="#methods-result">Methods for explicitly specifying
+ results</a></dt>
+
+ <dt><a href="#class-list">Helper class <tt>List</tt></a></dt>
+ </dl>
+ </dd>
+ </dl>
+ <hr>
+
+ <h2><a name="sec-intro">Introduction for users</a></h2>
+
+ <p>The testing system for Boost.Build is a small set of Python modules
+ and scripts for automatically testing user-obversable behaviour. It uses
+ components from testing systems of <a href=
+ "http://www.scons.org">Scons</a> and <a href=
+ "http://subversion.tigris.org">Subverion</a>, together with some
+ additional functionality.</p>
+
+ <p>To run the tests you'd need:</p>
+
+ <ol>
+ <li>Get the source tree of Boost.Build (located at <tt>tools/build</tt>
+ in Boost)</li>
+
+ <li>Have <a href="http://www.python.org">Python</a> installed. Version
+ 2.1 is known to work.</li>
+
+ <li>Build Boost.Jam. See <a href=
+ "../../jam_src/index.html">$boost_build_root/jam_src/index.html</a> for
+ instructions.</li>
+
+ <li>Configure at least one toolset. You can edit
+ <tt>site-config.jam</tt> or <tt>user-config.jam</tt> to add new
+ toolsets. Or you can create file <tt>test-config.jam</tt> in
+ <tt>$boost_build_root/test</tt> directory. In this case,
+ <tt>site-config.jam</tt> and <tt>user-config.jam</tt> will be ignored
+ for testing.</li>
+ </ol>
+
+ <p>When all is done, you can run the tests with</p>
+<pre class="code">
+python test_all.py
+</pre>
+
+ <p>which will use the default toolset, or you can specify toolset on the
+ command line, for example:</p>
+<pre class="code">
+python test_all.py borland
+</pre>
+
+ <p>If everything's OK, you'll see a list of passed tests. Otherwise, a
+ failure will be reported.</p>
+
+ <p>It is possible to run a specific test, for example:</p>
+<pre class="code">
+python generators_test.py
+</pre>
+
+ <h2><a name="sec-developers">Introduction for developers</a></h2>
+
+ <p>It is suggested that every new functionality come together with tests,
+ and that bugfixes are accompanied by tests. There's no need to say that
+ tests are good, but two points are extremely important:</p>
+
+ <ul>
+ <li>For an interpreted language like Jam, without any static checks,
+ testing is simply the only sefeguard we can have.</li>
+
+ <li>Good tests allow to change internal design much more safely, and we
+ didn't nailed everything down yet.</li>
+ </ul>
+
+ <p>Adding a new test is simple:</p>
+
+ <ol>
+ <li>Go to <tt>$boost_build_root/test/test_all.py</tt> and add new test
+ name to the list at the end of file. Suppose the test name is
+ "hello".</li>
+
+ <li>Add a new python module, in this example "hello.py", to do actual
+ testing.</li>
+ </ol>
+
+ <p>The module, in general will perform these basic actions:</p>
+
+ <ol>
+ <li>Setting the initial working directory state</li>
+
+ <li>
+ Running the build system and checking:
+
+ <ol>
+ <li>generated output,</li>
+
+ <li>changes made to the working directory,</li>
+
+ <li>new content of the working directory.</li>
+ </ol>
+ </li>
+
+ <li>Adding, removing or touching files, or changing their content and
+ then repeating the previous step, until satisfied.</li>
+
+ <li>Cleaning up</li>
+ </ol>
+
+ <p>The "hello.py" module might contain:</p>
+<pre class="example">
+from BoostBuild import Tester, List
+
+# Create a temporary working directory
+t = Tester()
+
+# Create the needed files
+t.write("project-root.jam", "")
+t.write("Jamfile", """
+exe hello : hello.cpp ;
+""")
+t.write("hello.cpp", """
+int main()
+{
+ return 0;
+}
+
+""")
+
+t.run_build_system()
+
+# First, create a list of three pathnames
+file_list = List("bin/$toolset/debug/") * List("hello.exe hello.obj")
+# Second, assert that those files were added as result of the last build system invocation.
+t.expect_addition(file_list)
+
+# Invoke the build system once again
+t.run_build_system("clean")
+# Check if the files added previously were removed.
+t.expect_removal(file_list)
+
+# Remove temporary directories
+t.cleanup()
+</pre>
+
+ <p>The <tt>test</tt> directory contains a file "template.py" which can be
+ used as a start for your own tests.</p>
+
+ <p>Overview of the most important methods of class
+ <tt>TestBoostBuild</tt> follows.</p>
+
+ <h3><a name="sec-intro-changing">Changing the working directory</a></h3>
+
+ <p>The class <tt>TestBoostBuild</tt> creates a temporary directory in its
+ constructor and changes to that directory. It can be modified by calling
+ these methods:</p>
+
+ <ul>
+ <li><tt>set_tree</tt> -- sets the content of the working directory to
+ be equal to the content of the specified directory. This method is
+ preferrable when directory tree for testing is large.</li>
+
+ <li><tt>write</tt> -- sets the content of file in a working directory.
+ This is optimal if you want to create a directory tree with 3-4 small
+ files.</li>
+
+ <li><tt>touch</tt> -- changes the modification times of a file</li>
+ </ul>
+
+ <h3><a name="sec-intro-examining">Examining the working directory and
+ changing it</a></h3>
+
+ <p>The method <tt>read</tt>, inherited from the <tt>TestCmd</tt> class,
+ can be used to read any file in the working directory and check its
+ content. <tt>TestBoostBuild</tt> adds another method for tracking
+ changes. Whenever build system is run (via <tt>run_build_system</tt>),
+ the state of working dir before and after running is recorded. In
+ addition, difference between the two states -- i.e. lists of files that
+ were added, removed, modified or touched -- is stored in two member
+ variables, <tt>tree_difference</tt> and
+ <tt>unexpected_difference</tt>.</p>
+
+ <p>After than, the test author may specify that some change is expected,
+ for example, by calling <tt>expect_addition("foo")</tt>. This call will
+ check if the file was indeed added, and if so, will remove its name from
+ the list of added files in <tt>unexpected_difference</tt>. Likewise, it's
+ possible to specify that some changes are not interesting, for example a
+ call <tt>ignore("*.obj")</tt> will just remove every files with ".obj"
+ extension from <tt>unexpected_difference</tt>.</p>
+
+ <p>When test has finished with expectations and ignoring, the member
+ <tt>unexpected_difference</tt> will contain the list of all changes not
+ yet accounted for. It is possible to assure that this list is empty by
+ calling <tt>expect_nothing_more</tt> member function.</p>
+
+ <h3><a name="sec-intro-results">Test result</a></h3>
+
+ <p>Any of the <tt>expect*</tt> methods below will fail the test if the
+ expectation is not met. It is also possible to perform manually arbitrary
+ test and explicitly cause the test to either pass or fail. Ordinary
+ filesystem functions can be used to work with the directory tree. Methods
+ <tt>pass_test</tt> and <tt>fail_test</tt> are used to explicitly give the
+ test outcome.</p>
+
+ <p>Typically, after test termination, the working directory is erased. To
+ debug a failed test, you should add "--preserve" option when invoking
+ test. On failure, the working directory will be copied to "failed_test"
+ directory in the current dir.</p>
+
+ <h2 id="sec-reference">Reference documentation</h2>
+
+ <p>The test system is composed of class <tt>Tester</tt>, derived form
+ <tt>TestCmd.TestCmd</tt>, and helper class <tt>List</tt>. The methods of
+ <tt>Tester</tt>, and the class <tt>List</tt> are described below.</p>
+
+ <p>The documentation frequently refer to filename. In all cases, files
+ are specified in unix style: a sequence of components, separated by "/".
+ This is true on all platforms. In some contexts, a list of files is
+ allowed. In that case any object with sequence interface is allowed.</p>
+
+ <h3><a name="method-__init__">Method <tt>__init__(self, arguments='',
+ executable='bjam')</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <ol>
+ <li>Remembers the current working directory in member
+ <tt>original_workdir</tt>.</li>
+
+ <li>Determines the location of executable (<code>bjam</code> by
+ default) and build system files, assuming that the current directory is
+ <tt>tools/build/test</tt>. Formulates jam invocation command, which
+ will include explicit setting for <tt>BOOST_BUILD_PATH</tt> variable
+ and arguments passed to this methods, if any. This command will be used
+ by subsequent invocation of <a href=
+ "#method-run_build_system"><tt>run_build_system</tt></a>. Finally,
+ initializes the base class.</li>
+
+ <li>Changes current working dir to the temporary working directory
+ created by the base constructor.</li>
+ </ol>
+
+ <h3><a name="method-set_tree">Method <tt>set_tree(self,
+ tree_location)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <p>Replaces the content of the current working directory with the content
+ of directory at <tt>tree_location</tt>. If <tt>tree_location</tt> is not
+ absolute pathname, it will be treated as relative to
+ <tt>self.original_workdir</tt>. This methods also explicitly makes the
+ copied files writeable.</p>
+
+ <h3><a name="method-write">Method <tt>write(self, name,
+ content)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <p>Writes the specified content to the file given by <tt>name</tt> under
+ the temporary working directory. If the file already exists, it is
+ overwritten. Any required directories are automatically created.</p>
+
+ <h3><a name="method-copy">Method <tt>copy(self, src, dst)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <p>Equvivalent to <tt>self.write(self.read(src), dst)</tt>.</p>
+
+ <h3><a name="method-touch">Method <tt>touch(self, names)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <p>Sets the access and modification times for all files in <tt>names</tt>
+ to the current time. All the elements in <tt>names</tt> should be
+ relative paths.</p>
+
+ <h3><a name="method-run_build_system">Method <tt>run_build_system(self,
+ subdir='', extra_args='', stdout=None, stderr='', status=0,
+ **kw)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <ol>
+ <li>Stores the state of the working directory in
+ <tt>self.previous_tree</tt>.</li>
+
+ <li>Changes to <tt>subdir</tt>, if it is specified. If it is not
+ absolute path, it is relative to the working dir.</li>
+
+ <li>Invokes the <tt>bjam</tt> executable, passing <tt>extra_args</tt>
+ to it. The binary should be located under
+ <tt><test_invocation_dir>/../jam_src/bin.<platform></tt>.
+ This is to make sure tests use the version of jam build from CVS.</li>
+
+ <li>Compares the stdout, stderr and exit status of build system
+ invocation with values to appropriate parameters, if they are not
+ <tt>None</tt>. If any difference is found, the test fails.</li>
+
+ <li>
+ <p>Stores the new state of the working directory in
+ <tt>self.tree</tt>. Computes the difference between previous and
+ current trees and store them in variables
+ <tt>self.tree_difference</tt> and
+ <tt>self.unexpected_difference</tt>.</p>
+
+ <p>Both variables are instances of class
+ <tt>tree.Trees_different</tt>, which have four attributes:
+ <tt>added_files</tt>, <tt>removed_files</tt>, <tt>modified_files</tt>
+ and <tt>touched_files</tt>. Each is a list of strings.</p>
+ </li>
+ </ol>
+
+ <h3><a name="method-read">Method <tt>read(self, name)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <p>Read the specified file and returns it content. Raises an exception is
+ the file is absent.</p>
+
+ <h3><a name="method-read_and_strip">Method <tt>read_and_strip(self,
+ name)</tt></a></h3>
+
+ <p><b>Effects:</b></p>
+
+ <p>Read the specified file and returns it content, after removing
+ trailing whitespace from every line. Raises an exception is the file is
+ absent.</p>
+
+ <p><b>Rationale:</b></p>
+
+ <p>Althought this method is questionable, there are a lot of cases when
+ jam or shells it uses insert spaces. It seems that introducing this
+ method is much simpler than dealing with all those cases.</p>
+
+ <h3><a name="methods-expectations">Methods for declaring
+ expectations</a></h3>
+
+ <p>Accordingly to the number of changes kinds that are detected, there
+ are four methods that specify that test author expects a specific change
+ to occur. They check <tt>self.unexpected_difference</tt>, and if the
+ change is present there, it is removed. Otherwise, test fails.</p>
+
+ <p>Each method accepts a list of names. Those names use <tt>/</tt> path
+ separator on all systems. Additionaly, the test system translates
+ suffixes appropriately. For the test to be portable, suffixes should use
+ Windows convention: <tt>exe</tt> for executables, <tt>dll</tt> for
+ dynamic libraries and <tt>lib</tt> for static libraries. Lastly, the
+ string "$toolset" in file names is replaced by the name of tested
+ toolset.</p>
+
+ <p><b>Note:</b> The <tt>List</tt> helper class might be useful to create
+ lists of names.</p>
+
+ <p><b>Note:</b> The file content can be examined using
+ <tt>TestCmd.read</tt> function.</p>
+
+ <p>The members are:</p>
+
+ <ul>
+ <li>expect_addition</li>
+
+ <li>expect_removal</li>
+
+ <li>expect_modification</li>
+
+ <li>expect_nothing</li>
+ </ul>
+
+ <p>Note that <tt>expect_modification</tt> is used to check that a either
+ file content or timestamp has changed. The rationale is that some
+ compilers change content even if sources does not change, and it's easier
+ to have a method which checks for both content and time changes.</p>
+
+ <p>There's also a member <tt>expect_nothing_more</tt>, which checks that
+ all the changes are either expected or ignored, in other words that
+ <tt>unexpected_difference</tt> is empty by now.</p>
+
+ <p>Lastly, there's a method to compare file content with expected
+ content:</p>
+ <tt>expect_content(self, name, content, exact=0)</tt>
+
+ <p>The method fails the test if the content of file identified by 'name'
+ is different from 'content'. If 'exact' is true, the file content is used
+ as-is, otherwise, two transformations are applied:</p>
+
+ <ul>
+ <li>The <tt>read_and_strip</tt> method is used to read the file, which
+ removes trailing whitespace</li>
+
+ <li>Each backslash in the file content is converted to forward
+ slash.</li>
+ </ul>
+
+ <h3><a name="methods-ignoring">Methods for ignoring changes</a></h3>
+
+ <p>There are five methods which ignore changes made to the working tree.
+ They silently remove elements from <tt>self.unexpected_difference</tt>,
+ and don't generate error if element is not found. They accept shell style
+ wildcard.</p>
+
+ <p>The following methods correspond to four kinds of changes:</p>
+
+ <ul>
+ <li>ignore_addition(self, wildcard)</li>
+
+ <li>ignore_removal(self, wildcard)</li>
+
+ <li>ignore_modification(self, wildcard)</li>
+
+ <li>ignore_touch(self, wilcard)</li>
+ </ul>
+
+ <p>The method <tt>ignore(self, wildcard)</tt> ignores all the changes
+ made to files that match a wildcard.</p>
+
+ <h3><a name="methods-result">Methods for explicitly specifying
+ results</a></h3>
+
+ <h4>Method <tt>pass_test(self, condition=1)</tt></h4>
+
+ <div class="attention">
+ At this moment, the method should not be used.
+ </div>
+
+ <h4>Method <tt>fail_test(self, condition=1)</tt></h4>
+
+ <p><b>Effects:</b> Cause the test to fail if <tt>condition</tt> is
+ true.</p>
+
+ <h3><a name="class-list">Helper class <tt>List</tt></a></h3>
+ The class has sequence interface and two additional methods.
+
+ <h4>Method <tt>__init__(self, string)</tt></h4>
+
+ <p><b>Effects:</b> Splits the string on unescaped spaces and tabs. The
+ split components can further be retrieved using standard sequence
+ access.</p>
+
+ <h4>Method <tt>__mul__(self, other)</tt></h4>
+
+ <p><b>Effects:</b> Returns an <tt>List</tt> instance, which elements are
+ all possible concatenations of two string, first of which is from
+ <tt>self</tt>, and second of which is from <tt>other</tt>.</p>
+
+ <p>The class also defines <tt>__str__</tt> and <tt>__repr__</tt> methods.
+ Finally, there's <tt>__coerce__</tt> method which allows to convert
+ strings to instances of <tt>List</tt>.</p>
+
+ <p><b>Example:</b></p>
+<pre>
+ l = "a b" * List("c d")
+ for e in l:
+ print e
+
+</pre>
+
+ <p>will output</p>
+<pre>
+ ac
+ ad
+ bc
+ bd
+
+</pre>
+ <hr>
+
+ <p class="revision">Last modified: Mar 3, 2003</p>
+
+ <p>© Copyright Vladimir Prus 2002, 2003. Permission to copy, use,
+ modify, sell and distribute this document is granted provided this
+ copyright notice appears in all copies. This document is provided ``as
+ is'' without express or implied warranty, and with no claim as to its
+ suitability for any purpose.</p>
+ </body>
+</html>
+
Added: boost-jam/boost-build/branches/upstream/current/test/testing-primitives/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/testing-primitives/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/testing-primitives/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+boost-build . ;
Added: boost-jam/boost-build/branches/upstream/current/test/testing-primitives/bootstrap.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/testing-primitives/bootstrap.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/testing-primitives/bootstrap.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,133 @@
+# Proof-of-concept for bjam-based testing mechanism. This file should
+# work on NT, Cygwin, and Linux. No promises for other platforms.
+
+# Set a variable which says how to dump a file to stdout
+if $(NT)
+{
+ CATENATE = type ;
+}
+else
+{
+ CATENATE = cat ;
+}
+
+# invoke the given action rule `act' to build target from sources
+rule do-make ( target : sources * : act )
+{
+ DEPENDS $(target) : $(sources) ;
+ $(act) $(target) : $(sources) ;
+}
+
+# top-level version of do-make which causes target to be built by
+# default
+rule make ( target : sources * : act )
+{
+ DEPENDS all : $(target) ;
+ do-make $(target) : $(sources) : $(act) ;
+}
+
+# cause `target' to exist and building to succeed if invoking
+#
+# $(act) $(target) : $(sources)
+#
+# fails, and to fail if the action succeeds.
+rule make-fail ( target : sources * : act )
+{
+ # Establish another logical target which refers to the same file,
+ # by using different grist.
+ DEPENDS all : <different-grist>$(target) ;
+
+ # Make the new logical target depend on the target
+ DEPENDS <different-grist>$(target) : $(target) ;
+
+ # Cause the target to be built from sources using $(act).
+ do-make $(target) : $(sources) : $(act) ;
+
+ # Note that we expect target to fail to build
+ FAIL_EXPECTED $(target) ;
+
+ # Build a failure marker file. Because targets are only built if
+ # all their dependents "succeed", the marker will only be
+ # generated if $(target) failed to build, as expected.
+ failure-marker <different-grist>$(target) ;
+}
+
+# Simple action rules which write text into the target. Different
+# names for different purposes.
+actions failure-marker
+{
+ echo failed as expected > $(<)
+}
+
+actions create
+{
+ echo creating > $(<)
+}
+
+# An action which will always fail, for testing expected failure rules
+actions fail-to-create
+{
+ exit 1
+}
+
+# Basic rule-action pair which builds the target by executing the
+# given commands
+rule do-run ( target : commands + )
+{
+ COMMANDS on $(target) = $(commands) ;
+ NOTFILE $(commands) ;
+}
+
+# Run commands, leaving the output behind in $(<:S=.out). Echo to
+# stdout if the command fails.
+#
+# Detailed explanation:
+#
+# $(COMMANDS) Run commands
+# > $(<:S=.out) into the output file
+# 2>&1 including stderr
+# && and if that succeeds
+# cp -f $(<:S=.out) $(<) copy the output file into the target
+# || otherwise
+# ( $(CATENATE) $(<:S=.out) dump any output to stdout
+# && exit 1 and exit with an error code
+# )
+actions do-run
+{
+ $(COMMANDS) > $(<:S=.out) 2>&1 && cp -f $(<:S=.out) $(<) || ( $(CATENATE) $(<:S=.out) && exit 1 )
+}
+
+# top-level version of do-run which causes target to be built by
+# default
+rule run ( target : commands + )
+{
+ DEPENDS all : $(target) ;
+ do-run $(target) : $(commands) ;
+}
+
+# experimental expected-failure version of run. This doesn't have
+# quite the right semantics w.r.t. output dumping (it is still only
+# dumped if the run fails), but we don't need run-fail anyway so it
+# doesn't matter too much.
+rule run-fail ( target : commands + )
+{
+ make-fail $(target) : $(commands) : do-run ;
+}
+
+# A command which will always fail to run. There is no file called
+# nonexistent, so executing $(error) always causes an error. We can't
+# just use `exit 1' below because that will cause all command
+# processing to stop, and we want the rest of the do-run action
+# command-line to execute.
+error = $(CATENATE)" nonexistent" ;
+
+make-fail t1.txt : : create ;
+make-fail t2.txt : : fail-to-create ;
+make t3.txt : : create ;
+make t4.txt : : fail-to-create ;
+
+run t5.txt : "( echo failing t5 && $(error) )" ;
+run t6.txt : echo hi ;
+
+run-fail t7.txt : "( echo failing t7 && $(error) )" ;
+run-fail t8.txt : echo hi ;
Added: boost-jam/boost-build/branches/upstream/current/test/testing_primitives.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/testing_primitives.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/testing_primitives.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester, List
+import os
+from string import strip
+import re
+
+def match_re(actual,expected):
+ return re.match(expected,actual,re.DOTALL) != None
+
+t = Tester(match = match_re)
+
+t.set_tree('testing-primitives')
+
+# We expect t5 and t7's output to be dumped to stdout
+t.run_build_system(stdout=r'''.*failing t5.*failing t7''')
+
+t.expect_addition('t2.txt')
+t.expect_addition('t3.txt')
+
+t.expect_addition('t5.out')
+
+t.expect_addition('t6.out')
+t.expect_addition('t6.txt')
+
+t.expect_addition('t7.out')
+t.expect_addition('t7.txt')
+
+t.expect_addition('t8.out')
+
+t.expect_nothing_more()
+t.cleanup()
+print 'tesing complete'
Added: boost-jam/boost-build/branches/upstream/current/test/tree.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/tree.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/tree.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,119 @@
+# Copyright (C) 2001 Vladimir Prus. Permission to copy, use, modify, sell and
+# distribute this software is granted, provided this copyright notice appears
+# in all copies and modified versions are clearly marked as such. This software
+# is provided "as is" without express or implied warranty, and with no claim as
+# to is suitability for any purpose.
+
+# This file is based in part on the content of svn_tree.py.
+
+import svn_tree;
+
+class Trees_difference:
+
+ def __init__(self):
+ self.added_files = []
+ self.removed_files = []
+ self.modified_files = []
+ self.touched_files = []
+
+ def append(self, other):
+ self.added_files.extend(other.added_files)
+ self.removed_files.extend(other.removed_files)
+ self.modified_files.extend(other.modified_files)
+ self.touched_files.extend(other.touched_files)
+
+ def ignore_directories(self):
+ "Removes directories for list of found differences"
+
+ def not_dir(x):
+ return x[-1] != "/"
+ self.added_files = filter(not_dir, self.added_files)
+ self.removed_files = filter(not_dir, self.removed_files)
+ self.modified_files = filter(not_dir, self.modified_files)
+ self.touched_files = filter(not_dir, self.touched_files)
+
+ def pprint(self):
+ print "Added files :", self.added_files
+ print "Removed files :", self.removed_files
+ print "Modified files:", self.modified_files
+ print "Touched files :", self.touched_files
+
+ def empty(self):
+ return (len(self.added_files) == 0 and len(self.removed_files) == 0)\
+ and len(self.modified_files) == 0 and len(self.touched_files) == 0
+
+def build_tree(dir):
+ return svn_tree.build_tree_from_wc(dir, load_props=0, ignore_svn=1)
+
+def trees_difference(a, b, current_name=""):
+ """Compare SVNTreeNodes A and B, and create Trees_difference class."""
+
+ assert a.name == b.name
+
+ result = Trees_difference()
+ try:
+ # A and B are both files.
+ if ((a.children is None) and (b.children is None)):
+ assert a.name == b.name
+ if svn_tree.compare_file_nodes(a, b):
+ result.modified_files.append(current_name)
+ elif (a.mtime != b.mtime):
+ result.touched_files.append(current_name)
+
+ # One is a file, one is a directory.
+ # this case is disabled because svn_tree doesn't distinguish
+ # empty directories from files, at least on Cygwin.
+ elif 0 and (((a.children is None) and (b.children is not None))
+ or ((a.children is not None) and (b.children is None))):
+ a.pprint()
+ b.pprint()
+ raise svn_tree.SVNTypeMismatch
+ # They're both directories.
+ else:
+ # accounted_for holds childrens present in both trees
+ accounted_for = []
+ for a_child in (a.children or []):
+ b_child = svn_tree.get_child(b, a_child.name)
+ if b_child:
+ accounted_for.append(b_child)
+ if current_name:
+ result.append(trees_difference(a_child, b_child, current_name + "/" + a_child.name))
+ else:
+ result.append(trees_difference(a_child, b_child, a_child.name))
+ else:
+ if current_name:
+ result.removed_files.append(current_name + "/" + a_child.name)
+ else:
+ result.removed_files.append(a_child.name)
+ for b_child in (b.children or []):
+ if (b_child not in accounted_for):
+ result.added_files.extend(traverse_tree(b_child, current_name))
+
+ except svn_tree.SVNTypeMismatch:
+ print 'Unequal Types: one Node is a file, the other is a directory'
+ raise svn_tree.SVNTreeUnequal
+ except svn_tree.SVNTreeIsNotDirectory:
+ print "Error: Foolish call to get_child."
+ sys.exit(1)
+ except IndexError:
+ print "Error: unequal number of children"
+ raise svn_tree.SVNTreeUnequal
+ return result
+
+def dump_tree(t):
+ svn_tree.dump_tree(t)
+
+def traverse_tree(t, parent_name=""):
+ """ Returns the list of all names in tree. """
+ if parent_name:
+ full_node_name = parent_name + "/" + t.name
+ else:
+ full_node_name = t.name
+
+ if (t.children is None):
+ result = [full_node_name]
+ else:
+ result = [full_node_name + "/"]
+ for i in t.children:
+ result.extend(traverse_tree(i, full_node_name))
+ return result
Added: boost-jam/boost-build/branches/upstream/current/test/unit-tests.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/unit-tests.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/unit-tests.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,264 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+# assert_equal a : b
+#
+# exits with an assertion failure if a != b
+rule assert_equal
+{
+ if $(<) != $(>)
+ {
+ EXIT "assertion failure: [" $(<) "] != [" $(>) "]" ;
+ }
+}
+
+rule assert_equal_sets
+{
+ if ! [ equal-sets $(<) : $(>) ]
+ {
+ EXIT "assertion failure: [" $(<) "] !=(set) [" $(>) "]" ;
+ }
+}
+
+# FAppendSuffix
+assert_equal [ FAppendSuffix yacc lex foo.bat : ] : yacc lex foo.bat ;
+assert_equal [ FAppendSuffix yacc lex foo.bat : .exe ] : yacc.exe lex.exe foo.bat ;
+assert_equal [ FAppendSuffix yacc lex foo.bat : .dll .lib ] : yacc.dll yacc.lib lex.dll lex.lib foo.bat foo.lib ;
+
+# sort
+assert_equal [ sort 7 3 5 6 2 4 ] : 2 3 4 5 6 7 ;
+
+# min
+assert_equal [ min 7 3 5 6 2 4 ] : 2 ;
+
+# difference
+assert_equal [ difference 0 1 2 3 4 5 6 7 8 9 : 2 3 5 7 ] : 0 1 4 6 8 9 ;
+
+# replace
+assert_equal [ replace 1 3 5 7 7 9 2 5 4 3 1 : 7 x ] : 1 3 5 x x 9 2 5 4 3 1 ;
+
+# select-ungristed
+assert_equal [ select-ungristed <a>b c <d>e f ] : c f ;
+
+# split-qualified-property
+assert_equal [ split-qualified-property <feature>value ]
+ : <*> <*> <feature>value ;
+
+assert_equal [ split-qualified-property <variant><feature>value ]
+ : <*> <variant> <feature>value ;
+
+assert_equal [ split-qualified-property <toolset><variant><feature>value ]
+ : <toolset> <variant> <feature>value ;
+
+# unique
+assert_equal [ unique 0 1 2 3 1 7 6 6 4 5 ] : 0 1 2 3 7 6 4 5 ;
+
+# get-properties
+assert_equal [ get-properties <foo> <bar> : <foo>bar <foo>baz <bar>fight <baz>niss ]
+ : <foo>bar <foo>baz <bar>fight ;
+
+# get-values
+assert_equal [ get-values <foo> : <foo>bar <foo>baz <bar>fight <baz>niss ] : bar baz ;
+
+# normalize-properties
+assert_equal [ normalize-properties <a>b <c><d>e <f><g><h>i ] :
+ <*><*><a>b <*><c><d>e <f><g><h>i ;
+
+# intersection
+assert_equal [ intersection 1 2 2 3 3 4 5 6 7 : 5 1 3 7 3 9 11 ] : 1 3 3 5 7 ;
+
+# is-subset
+assert_equal [ is-subset a b c : c a b d ] : true ;
+assert_equal [ is-subset a b z : c a b d ] : ;
+
+# split-path
+assert_equal [ split-path <a>b/c/<d>e ] : <a>b c <d>e ;
+assert_equal [ split-path <a>/<d>/<e> ] : <a> <d> <e> ;
+assert_equal [ split-path <a> ] : <a> ;
+assert_equal [ split-path x ] : x ;
+assert_equal [ split-path $(DOT) ] : $(DOT) ;
+assert_equal [ split-path a/b.c/d.e/f ] : a b.c d.e f ;
+if $(NT)
+{
+ assert_equal [ split-path x:\\y\\z\\w ] : x: y z w ;
+ assert_equal [ split-path x:\\y\\z ] : x: y z ;
+ assert_equal [ split-path x:\\y ] : x: y ;
+ assert_equal [ split-path x:\\ ] : x: ;
+ assert_equal [ split-path x: ] : x: ;
+}
+
+# distribute-feature
+assert_equal [ distribute-feature <feature>value1 ] : <feature>value1 ;
+assert_equal [ distribute-feature <feature>value1/value2 ] : <feature>value1 <feature>value2 ;
+assert_equal [ distribute-feature <feature>value1/value2/value3 ] : <feature>value1 <feature>value2 <feature>value3 ;
+
+# segregate-free-properties
+{
+ local gFREE_FEATURES = <a> <c> <e> ;
+ local x = <a>b <b>c <d>e ;
+ local y = <a>b <a>c <b>c <e>f ;
+ local free = [ segregate-free-properties x y ] ;
+ assert_equal $(free) : <a>b <a>c <e>f ;
+ assert_equal $(x) : <b>c <d>e ;
+ assert_equal $(y) : <b>c ;
+}
+
+# set-insert
+{
+ local gTEST_SET = 1 2 3 ;
+ set-insert gTEST_SET : 2 ;
+ assert_equal $(gTEST_SET) : 1 2 3 ;
+ set-insert gTEST_SET : 0 ;
+ assert_equal $(gTEST_SET) : 1 2 3 0 ;
+}
+
+# equal-sets
+assert_equal [ equal-sets 1 2 3 : 3 2 2 1 ] : true ;
+assert_equal [ equal-sets 1 2 3 3 : 3 2 2 1 ] : true ;
+assert_equal [ equal-sets 1 2 3 3 4 : 3 2 2 1 ] : ;
+
+# segregate-overrides
+{
+ local base = <a>b <c>d <e>f ;
+ local overrides = <a>b <c>c <d>e <f>g ;
+ segregate-overrides overrides : base ;
+ assert_equal $(overrides) : <c>c <d>e <f>g ;
+ assert_equal $(base) : <a>b <e>f ;
+}
+
+# select-properties
+{
+ local TOOLS = gcc msvc ;
+
+ local gRELEVANT_FEATURES(msvc) = <debug-symbols> <optimization> <inlining> <inline> <runtime-build> <runtime-link> <threading> <define> <undef> <include> <target-type> ;
+ local gRELEVANT_FEATURES(gcc) = <runtime-link> <debug-symbols> <optimization> <inlining> <profiling> <define> <undef> <include> <shared-linkable> <target-type> ;
+ local gFREE_FEATURES = <define> <undef> <include> ;
+
+ local gBASE_PROPERTIES(msvc,debug) = <debug-symbols>on <inlining>off <optimization>off <runtime-build>debug <threading>single ;
+ local gBASE_PROPERTIES(gcc,debug) = <debug-symbols>on <inlining>off <optimization>off <profiling>off <shared-linkable>false ;
+ local gBASE_PROPERTIES(msvc,release) = <debug-symbols>off <define>NDEBUG <inlining>full <optimization>speed <runtime-build>release <threading>single ;
+ local gBASE_PROPERTIES(gcc,release) = <debug-symbols>off <define>NDEBUG <inlining>full <optimization>speed <profiling>off <shared-linkable>false ;
+
+ local TEST_PROPERTIES = <inlining>off <define>FOO <*><release><inlining>on
+ <debug><define>DEBUG <msvc><release><foo>bar
+ <gcc><*><inlining>on
+ <msvc><*><foo>baz
+ <msvc><release><optimization>speed
+ <msvc><*><optimization>off
+ <*><debug><optimization>off
+ ;
+
+ assert_equal_sets [ select-properties gcc debug my-target : $(TEST_PROPERTIES) ]
+ : <define>FOO <define>DEBUG <inlining>on <optimization>off ;
+
+ assert_equal_sets [ select-properties gcc release my-target : $(TEST_PROPERTIES) ]
+ : <define>FOO <inlining>on ;
+
+ assert_equal_sets [ select-properties msvc debug my-target : $(TEST_PROPERTIES) ]
+ : <define>FOO <define>DEBUG <inlining>off <optimization>off ;
+
+ assert_equal_sets [ select-properties msvc release my-target : $(TEST_PROPERTIES) ]
+ : <define>FOO <inlining>on <optimization>speed ;
+}
+
+
+# ungrist-properties
+feature TEST_FEATURE1 : a b ;
+feature TEST_FEATURE2 : c d ;
+assert_equal [ ungrist-properties <TEST_FEATURE1>a <TEST_FEATURE2>c ]
+ : TEST_FEATURE1-a TEST_FEATURE2-c ;
+
+
+# fixup-path-properties
+{
+ local RELATIVE_SUBDIR = foobar ;
+ local gPATH_FEATURES = <include> ;
+ assert_equal [ fixup-path-properties <a>b <include>.. <c>d ]
+ : <include>foobar$(SLASH).. <a>b <c>d ;
+}
+# multiply-property-sets
+assert_equal [ multiply-property-sets <b>1 <a>2/3 <c>4/5 ]
+ : <a>2/<b>1/<c>4 <a>2/<b>1/<c>5 <a>3/<b>1/<c>4 <a>3/<b>1/<c>5 ;
+
+# make-path-property-sets
+{
+ local gUNGRISTED(<a>) = a ;
+ local gUNGRISTED(<c>) = c ;
+ local gUNGRISTED(<e>) = e ;
+ local gUNGRISTED(<g>) = g ;
+ local gUNGRISTED(<i>) = i ;
+ assert_equal [ make-path-property-sets foo$(SLASH)bar : <a>b <c>d : <e>f$(SLASH)<g>h <i>j ]
+ : foo$(SLASH)bar$(SLASH)e-f$(SLASH)g-h$(SLASH)<a>b$(SLASH)<c>d$(SLASH)<e>f$(SLASH)<g>h foo$(SLASH)bar$(SLASH)i-j$(SLASH)<a>b$(SLASH)<c>d$(SLASH)<i>j ;
+ assert_equal [ make-path-property-sets foo$(SLASH)bar : <a>b <c>d : ]
+ : foo$(SLASH)bar$(SLASH)<a>b$(SLASH)<c>d ;
+}
+
+
+# split-path-at-grist
+assert_equal
+ [ split-path-at-grist <a>b$(SLASH)c$(SLASH)<d>e$(SLASH)<f>g$(SLASH)h$(SLASH)i ]
+ : <a>b$(SLASH)c <d>e <f>g$(SLASH)h$(SLASH)i ;
+assert_equal
+ [ split-path-at-grist b$(SLASH)c$(SLASH)<d>e$(SLASH)<f>g$(SLASH)h$(SLASH)i ]
+ : b$(SLASH)c <d>e <f>g$(SLASH)h$(SLASH)i ;
+if $(NT)
+{
+ assert_equal
+ [ split-path-at-grist b\\c\\<include>e:\\f\\g\\<h>i ]
+ : b\\c <include>e:\\f\\g <h>i ;
+}
+# directory-of
+assert_equal [ directory-of a$(SLASH)b c d$(SLASH)e$(SLASH)f ] : a . d$(SLASH)e ;
+
+# top-relative-tokens
+{
+ local SUBDIR_TOKENS = a b c ;
+ assert_equal [ top-relative-tokens ..$(SLASH)d$(SLASH)e ] : a b d e ;
+}
+
+# flags
+{
+ local gBUILD_PROPERTIES = <a>b <c>d <e>f ;
+ local FLAGS1 FLAGS2 FLAGS3 ;
+ flags toolset FLAGS1 <a>b/<c>d <a>b/<e>f <x>y <a>/<c> <e> : foobar ;
+ assert_equal $(FLAGS1) : foobar b d f ;
+ flags toolset FLAGS2 <a> : foobar ;
+ assert_equal $(FLAGS2) : b ;
+ flags toolset FLAGS1 <a>b/<c>d <a>b/<e>f : foobar ;
+ assert_equal $(FLAGS1) : foobar b d f foobar ;
+}
+
+# get-BUILD
+{
+ local DEFAULT_BUILD = a ;
+ local BUILD = b ;
+ assert_equal [ get-BUILD c <d>e ] : b ;
+ BUILD = ;
+ assert_equal [ get-BUILD c <d>e ] : c <d>e ;
+ assert_equal [ get-BUILD ] : a ;
+ assert_equal [ get-BUILD <d>e ] : <d>e a ;
+ BUILD = <f>g ;
+ assert_equal [ get-BUILD c <d>e ] : <f>g a ;
+}
+
+# strip-initial
+assert_equal [ strip-initial a b c : a b c d e f g ] : d e f g ;
+assert_equal [ strip-initial a b c : a b d e f g ] : a b d e f g ;
+assert_equal [ strip-initial a b c : b d e f g ] : b d e f g ;
+assert_equal [ strip-initial a b c : ] : ;
+
+# simplify-path-tokens
+{
+ local $(gTOP)_TOKENS = .. .. .. ;
+ local gINVOCATION_SUBDIR_TOKENS = d e ;
+ assert_equal [ simplify-path-tokens a b . c .. .. d e ] : a d e ;
+ assert_equal [ simplify-path-tokens a b .. .. .. d e ] : .. d e ;
+ assert_equal [ simplify-path-tokens .. .. d e : xxx ] : .. .. d e ;
+ assert_equal [ simplify-path-tokens a b .. .. : xxx ] : xxx ;
+ $(gTOP)_TOKENS = .. .. ;
+ assert_equal [ simplify-path-tokens .. .. d e : xxx ] : xxx ;
+ assert_equal [ simplify-path-tokens .. .. d e f g : xxx ] : f g ;
+}
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/unit_test.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/unit_test.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/unit_test.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,44 @@
+#!/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.
+
+# Test the unit_test rule
+from BoostBuild import Tester, List
+
+t = Tester()
+
+# Create the needed files
+t.write("project-root.jam", """
+using testing ;
+""")
+t.write("Jamfile", """
+lib helper : helper.cpp ;
+unit-test test : test.cpp : <library>helper ;
+""")
+t.write("test.cpp", """
+void helper();
+int main()
+{
+ helper();
+ return 0;
+}
+""")
+
+t.write("helper.cpp", """
+void
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+helper() {}
+""")
+
+t.run_build_system("link=static")
+t.expect_addition("bin/$toolset/debug/link-static/test.passed")
+
+
+
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/unit_test.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/unit_tests.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/unit_tests.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/unit_tests.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester
+
+t = Tester(pass_toolset=0)
+t.run_build_system(extra_args="--debug --build-system=test")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/unit_tests.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/unused/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/unused/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/unused/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,7 @@
+
+exe a : a.cpp b c ;
+
+make-b-main-target ;
+
+# Expands to nothing, intentionally.
+alias c ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/unused/a.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/unused/a.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/unused/a.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,9 @@
+// Copyright Vladimir Prus 2003.
+// 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)
+
+int main()
+{
+ return 0;
+}
Added: boost-jam/boost-build/branches/upstream/current/test/unused/b.cpp
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/test/unused/b.x
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/test/unused/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/unused/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/unused/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,53 @@
+
+import type ;
+import generators ;
+import print ;
+import virtual-target ;
+import "class" : new ;
+import modules ;
+import targets ;
+
+
+type.register X : x ;
+
+class test-target-class : basic-target
+{
+ rule __init__ ( name : project )
+ {
+ basic-target.__init__ $(name) : $(project) ;
+ }
+
+ rule construct ( source-targets * : property-set )
+ {
+ if [ modules.peek : GENERATE_NOTHING ]
+ {
+ return ;
+ }
+ else if [ modules.peek : GENERATE_ONLY_UNUSABLE ]
+ {
+ return [ virtual-target.from-file b.x : $(self.project) ]
+ ;
+ }
+ else
+ {
+ return [ virtual-target.from-file b.x : $(self.project) ]
+ [ virtual-target.from-file b.cpp : $(self.project) ]
+ ;
+ }
+ }
+
+ rule compute-usage-requirements ( rproperties : targets * )
+ {
+ return [ property-set.create <define>FOO ] ;
+ }
+}
+
+rule make-b-main-target
+{
+ local project = [ CALLER_MODULE ] ;
+
+ targets.main-target-alternative
+ [ new test-target-class b : $(project) ] ;
+}
+
+IMPORT $(__name__) : make-b-main-target : : make-b-main-target ;
Added: boost-jam/boost-build/branches/upstream/current/test/unused.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/unused.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/unused.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,32 @@
+#!/usr/bin/python
+
+# Test that unused sources are at least reported.
+
+from BoostBuild import Tester
+from string import find
+t = Tester()
+
+t.set_tree("unused")
+
+t.run_build_system()
+# The second invocation should do nothing, and produce
+# no warning. The previous invocation might have printed
+# executed actions and other things, so it's not easy
+# to check if warning was issued or not.
+t.run_build_system()
+t.fail_test(find(t.stdout(), "warning: Unused source { b.X } in main target ./a") == -1)
+
+t.run_build_system("-sGENERATE_ONLY_UNUSABLE=1")
+t.fail_test(find(t.stdout(), "warning: Unused source { b.X } in main target ./a") == -1)
+
+# Now check that even if main target generates nothing, its
+# usage requirements are still propagated to dependents.
+t.write("a.cpp","""
+#ifdef FOO
+int main() {}
+#endif
+""")
+t.run_build_system("-sGENERATE_NOTHING=1")
+
+t.cleanup()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/unused.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/use_requirements.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/use_requirements.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/use_requirements.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,307 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester
+t = Tester()
+
+# Test that use requirements on main target work
+t.write("project-root.jam", "import gcc ;")
+
+t.write(
+ "Jamfile",
+"""
+ lib b : b.cpp : <link>shared:<define>SHARED_B
+ : : <define>FOO <link>shared:<define>SHARED_B
+ ;
+ exe a : a.cpp b ;
+""")
+
+t.write(
+ "b.cpp",
+"""
+void
+#if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+#endif
+foo() {}\n
+""")
+
+t.write(
+ "a.cpp",
+"""
+#ifdef FOO
+void
+# if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+# endif
+foo() {}
+#endif
+
+int main() { foo(); }
+""")
+
+t.run_build_system()
+
+t.run_build_system("--clean")
+
+# Test that use requirements on main target work, when they are referred using
+# 'dependency' features.
+t.write("project-root.jam", "import gcc ;")
+
+t.write(
+ "Jamfile",
+"""
+ lib b : b.cpp : <link>shared:<define>SHARED_B
+ : : <define>FOO <link>shared:<define>SHARED_B
+ ;
+ exe a : a.cpp : <use>b ;
+""")
+
+t.write(
+ "b.cpp",
+"""
+void
+#if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+#endif
+foo() {}
+""")
+
+t.write(
+ "a.cpp",
+"""
+#ifdef FOO
+int main() { return 0; }
+#endif
+""")
+
+t.run_build_system()
+
+t.run_build_system("--clean")
+
+
+# Test that use requirement on project work
+t.write("Jamfile", "exe a : a.cpp lib//b ;")
+
+t.write(
+ "lib/Jamfile",
+"""
+project
+ : requirements <link>shared:<define>SHARED_B
+ : usage-requirements <define>FOO <link>shared:<define>SHARED_B
+ ;
+lib b : b.cpp ;
+""")
+
+t.write(
+ "lib/b.cpp",
+"""
+void
+#if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+#endif
+foo() {}\n
+""")
+
+t.run_build_system()
+
+# Test that use requirements are inherited correctly
+
+t.write("Jamfile", "exe a : a.cpp lib/1//b ;")
+
+t.write(
+ "a.cpp",
+"""
+#if defined(FOO) && defined(ZOO)
+void foo() {}
+#endif
+
+int main() { foo(); }
+""")
+
+t.write(
+ "lib/Jamfile",
+"""
+project
+ : requirements
+ : usage-requirements <define>FOO
+ ;
+""")
+
+t.write(
+ "lib/1/Jamfile",
+"""
+project
+ : requirements <link>shared:<define>SHARED_B
+ : usage-requirements <define>ZOO <link>shared:<define>SHARED_B
+ ;
+lib b : b.cpp ;
+""")
+
+t.write(
+ "lib/1/b.cpp",
+"""
+void
+#if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+#endif
+foo() {}\n
+""")
+
+t.run_build_system()
+t.run_build_system("--clean")
+
+# Test that we correctly handle dependency features
+# in use requirements on target
+
+t.write(
+ "Jamfile",
+"""
+ lib b : b.cpp : <link>shared:<define>SHARED_B
+ : : <define>FOO <link>shared:<define>SHARED_B
+ ;
+
+ # Here's the test: we should correctly
+ # handle dependency feature and get
+ # use requirements from 'b'.
+ lib c : c.cpp : <link>shared:<define>SHARED_C : : <library>b ;
+
+ # This will build only if <define>FOO
+ # was propagated from 'c'.
+ exe a : a.cpp c ;
+""")
+
+t.write(
+ "a.cpp",
+"""
+#ifdef FOO
+void
+# if defined(_WIN32) && defined(SHARED_B)
+__declspec(dllexport)
+# endif
+foo();
+#endif
+
+int main() { foo(); }
+""")
+
+t.write(
+ "c.cpp",
+"""
+int
+#if defined(_WIN32) && defined(SHARED_C)
+__declspec(dllexport)
+#endif
+must_export_something;
+""")
+
+t.run_build_system()
+t.run_build_system("--clean")
+
+# Test correct handling of dependency features in
+# project requirements.
+t.write(
+ "Jamfile",
+"""
+ exe a : a.cpp lib1//c ;
+""")
+
+t.write(
+ "lib1/Jamfile",
+"""
+ project
+ : requirements <link>shared:<define>SHARED_C
+ : usage-requirements <library>../lib2//b <link>shared:<define>SHARED_C
+ ;
+
+ lib c : c.cpp ;
+""")
+
+t.write(
+ "lib1/c.cpp",
+"""
+int
+#if defined(_WIN32) && defined(SHARED_C)
+__declspec(dllexport)
+#endif
+must_export_something;
+""")
+
+t.write(
+ "lib2/Jamfile",
+"""
+ lib b : b.cpp : <link>shared:<define>SHARED_B
+ : : <define>FOO <link>shared:<define>SHARED_B ;
+""")
+
+t.copy("b.cpp", "lib2/b.cpp")
+
+t.run_build_system()
+
+# Test that dependency feature in use requirements are built
+# with the correct properties
+t.rm(".")
+
+t.write(
+ "Jamfile",
+"""
+lib main : main.cpp : <use>libs//lib1 : : <library>libs//lib1 ;
+exe hello : hello.cpp main : ;
+""")
+
+t.write(
+ "main.cpp",
+"""
+void
+#if defined(_WIN32) && defined(SHARED_LIB1)
+__declspec(dllimport)
+#endif
+foo();
+
+int main() { foo(); return 0; }
+""")
+
+t.write("hello.cpp", "\n")
+
+t.write(
+ "project-root.jam",
+"""
+import gcc ;
+""")
+
+t.write(
+ "libs/a.cpp",
+"""
+void
+#if defined(_WIN32) && defined(SHARED_LIB1)
+__declspec(dllexport)
+#endif
+foo() {}
+""")
+
+# This library should be build with the same properties as
+# 'main'. There were a bug when they were generated with
+# empty properties, and there were ambiguity between variants.
+t.write(
+ "libs/Jamfile",
+"""
+lib lib1 : a_d.cpp : <variant>debug <link>shared:<define>SHARED_LIB1
+: : <link>shared:<define>SHARED_LIB1 ;
+
+lib lib1 : a.cpp : <variant>release <link>shared:<define>SHARED_LIB1
+: : <link>shared:<define>SHARED_LIB1 ;
+""")
+
+t.write(
+ "libs/a_d.cpp",
+"""
+void
+#if defined(_WIN32) && defined(SHARED_LIB1)
+__declspec(dllexport)
+#endif
+foo() {}
+""")
+
+t.run_build_system("link=static")
+t.expect_addition("libs/bin/$toolset/debug/link-static/a_d.obj")
+
+t.cleanup()
Property changes on: boost-jam/boost-build/branches/upstream/current/test/use_requirements.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/test/v1-testing/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/v1-testing/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/v1-testing/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,22 @@
+import testing ;
+
+# A number of tests which should succeed
+compile a.cpp ;
+compile-fail b.cpp ;
+link-fail a.cpp : : link-no ;
+link c.cpp : : link-yes ;
+run c.cpp : : : : run-yes ;
+run-fail c.cpp : : : <define>RESULTCODE=1 : run-no ;
+
+# some tests which should fail
+
+compile-fail a.cpp : : fail-compile-no ;
+compile b.cpp : : fail-compile-yes ;
+link a.cpp : : fail-link-yes ;
+link-fail c.cpp : : fail-link-no ;
+run-fail c.cpp : : : : fail-run-no ;
+run c.cpp : : : <define>RESULTCODE=1 : fail-run-yes ;
+
+# Make sure we still fail if a dependency of an expected-failure test
+# fails.
+link-fail b.cpp : : fail-link-no-dependency ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/v1-testing/a.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/v1-testing/a.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/v1-testing/a.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,5 @@
+// Copyright David Abrahams 2003-2004. 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)
+
+void foo() {}
Added: boost-jam/boost-build/branches/upstream/current/test/v1-testing/b.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/v1-testing/b.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/v1-testing/b.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,5 @@
+// Copyright David Abrahams 2002.
+// 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)
+#error this does not compile.
Added: boost-jam/boost-build/branches/upstream/current/test/v1-testing/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/v1-testing/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/v1-testing/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+TOOLS = gcc ;
+boost-build ../.. ;
Added: boost-jam/boost-build/branches/upstream/current/test/v1-testing/c.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/v1-testing/c.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/v1-testing/c.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,16 @@
+// Copyright David Abrahams 2002.
+// 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)
+#include <iostream>
+
+#ifndef RESULTCODE
+# define RESULTCODE 0
+#endif
+
+int main()
+{
+ std::cout << "returning result: " << RESULTCODE << std::endl;
+ return RESULTCODE;
+}
+
Added: boost-jam/boost-build/branches/upstream/current/test/v1_testing/Jamfile
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/v1_testing/Jamfile 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/v1_testing/Jamfile 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,19 @@
+TOOLS = $(TOOLS[1]) ;
+project-root ;
+
+# bring in rules for testing
+import testing ;
+
+lib mylib : lib.cpp ;
+
+compile foo.cpp : : compile ;
+compile-fail foo.cpp : <define>NOCOMPILE : nocompile ;
+
+link foo.cpp <lib>mylib : : link ;
+link-fail foo.cpp <lib>mylib : <define>NOLINK : nolink ;
+
+run foo.cpp <lib>mylib
+ : # args
+ : # input-files
+ : <define>RUN
+ : run ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/v1_testing/Jamrules
===================================================================
Added: boost-jam/boost-build/branches/upstream/current/test/v1_testing/boost-build.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/v1_testing/boost-build.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/v1_testing/boost-build.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,2 @@
+TOOLS = gcc ;
+boost-build ../.. ;
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/v1_testing/foo.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/v1_testing/foo.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/v1_testing/foo.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,22 @@
+// Copyright David Abrahams 2002.
+// 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)
+
+#if NOCOMPILE
+1 = 1;
+#endif
+
+void lib();
+
+void f()
+{
+ lib();
+}
+
+#ifndef NOLINK
+int main()
+{
+}
+#endif
+
Added: boost-jam/boost-build/branches/upstream/current/test/v1_testing/lib-err.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/v1_testing/lib-err.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/v1_testing/lib-err.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,7 @@
+// Copyright David Abrahams 2002.
+// 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)
+
+3 = 4;
+void lib() {}
Added: boost-jam/boost-build/branches/upstream/current/test/v1_testing/lib.cpp
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/v1_testing/lib.cpp 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/v1_testing/lib.cpp 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,6 @@
+// Copyright David Abrahams 2002.
+// 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)
+
+void lib() {}
Added: boost-jam/boost-build/branches/upstream/current/test/v1_testing/project-root.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/v1_testing/project-root.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/v1_testing/project-root.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1 @@
+# just label the project root
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/test/v1_testing.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/v1_testing.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/v1_testing.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,83 @@
+#!/usr/bin/python
+
+from BoostBuild import Tester, List
+import os
+from string import strip
+import re
+import time
+
+def match_re(actual,expected):
+ return re.match(expected,actual,re.DOTALL) != None
+
+t = Tester(match = match_re, boost_build_path = os.path.join(os.getcwd(), ".."))
+t.set_tree('v1_testing')
+
+os.environ['TOOLS'] = 'gcc'
+os.environ['NOARSCAN'] = '1'
+
+# 1) No existing bin directories. Both build and test ran fine. As
+# expected, the residue files were a bit different: There was no
+# path_test.success, and path_test.test contained the word "passed"
+# instead of the path to the .cpp file. I've haven't looked yet to
+# see if the lack of the path is a problem for reporting, but
+# hopefully the information is trivially available somewhere else.
+t.run_build_system(arguments = 'test', status = 0)
+t.expect_addition(
+ ['bin/compile.test/gcc/debug/runtime-link-dynamic/compile.test'
+ , 'bin/nocompile.test/gcc/debug/runtime-link-dynamic/nocompile.test'
+ , 'bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
+ , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
+ , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
+
+
+# 2) Missing source file for the library build. path_test.test was
+# deleted, so the reporting programs would know that failure
+# occurred. The stdout messages also indicated what had
+# happened. Excellent!
+t.rename('lib.cpp', 'lib.cpp.bak')
+t.run_build_system(arguments = 'test', status = 1)
+t.expect_removal(
+ ['bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
+ , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
+ , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
+
+# 3) Missing file restored. Worked fine; path_test.test was recreated,
+# no other files were touched.
+t.rename('lib.cpp.bak', 'lib.cpp')
+t.run_build_system(arguments = 'test', status = 0)
+t.expect_addition(
+ [ 'bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
+ , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
+ , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
+ # I didn't add a test for 'no other files were touched', because
+ # it's a little complicated. There is an expect_nothing_more()
+ # function, but we actually need to spell out a lot more than
+ # what we currently have to do that.
+
+# 4) Introduced error into one of the library files, causing a library build
+# compile to fail. path_test.test was deleted, so the reporting programs
+# would know that failure occurred. Excellent! This is the case that has
+# caused regression testing to report the wrong results in the past, so it
+# was good news to see it working correctly now. We probably should figure
+# out some other test cases just to be sure it is working for full coverage.
+t.rename('lib.cpp', 'lib.cpp.bak')
+t.rename('lib-err.cpp', 'lib.cpp')
+t.touch('lib.cpp')
+t.run_build_system(arguments = 'test', status=1)
+t.expect_removal(
+ ['bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
+ , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
+ , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
+
+# 5) Fixed the error in the library file. The library build then worked, and
+# path_test.exe was relinked, without first recompiling path_test.obj. Test
+# was rerun. Exactly right behavior!
+t.rename('lib.cpp.bak', 'lib.cpp')
+t.run_build_system(arguments = 'test', status = 0)
+t.expect_addition(
+ [ 'bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
+ , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
+ , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
+
+t.cleanup()
+print 'tesing complete'
Added: boost-jam/boost-build/branches/upstream/current/test/wrapper.py
===================================================================
--- boost-jam/boost-build/branches/upstream/current/test/wrapper.py 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/test/wrapper.py 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,47 @@
+#!/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.
+
+# Test that the user can define his own rule that will call builtin main
+# target rule and that this will work.
+
+from BoostBuild import Tester, List
+
+t = Tester()
+
+t.write("Jamfile", """ my-test : test.cpp ;
+
+
+""")
+
+t.write("test.cpp", """
+int main()
+{
+ return 0;
+}
+
+""")
+
+t.write("project-root.jam", """ using testing ;
+
+rule my-test ( name ? : sources + )
+{
+ {
+ name ?= test ;
+ unit-test $(name) : $(sources) ; # /site-config//cppunit /util//testMain ;
+ }
+}
+
+IMPORT $(__name__) : my-test : : my-test ;
+
+
+""")
+
+t.run_build_system()
+t.expect_addition("bin/$toolset/debug/test.passed")
+
+t.cleanup()
+
Property changes on: boost-jam/boost-build/branches/upstream/current/test/wrapper.py
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/tools/bison.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/bison.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/bison.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,33 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+import generators ;
+import feature ;
+import type ;
+import property ;
+
+feature.feature bison.prefix : : free ;
+type.register Y : y ;
+type.register YY : yy ;
+generators.register-standard bison.bison : Y : C H ;
+generators.register-standard bison.bison : YY : CPP HPP ;
+
+rule init ( )
+{
+}
+
+rule bison ( dst dst_header : src : properties * )
+{
+ local r = [ property.select bison.prefix : $(properties) ] ;
+ if $(r)
+ {
+ PREFIX_OPT on $(<) = -p $(r:G=) ;
+ }
+}
+
+actions bison
+{
+ bison $(PREFIX_OPT) -d -o $(<[1]) $(>)
+}
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/tools/boostbook.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/boostbook.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/boostbook.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,418 @@
+# Copyright (C) 2003 Doug Gregor. 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.
+
+# This module defines rules to handle generation of documentation
+# from BoostBook sources.
+
+import "class" : new ;
+import common ;
+import errors ;
+import targets ;
+import feature ;
+import generators ;
+import print ;
+import property ;
+import project ;
+import property-set ;
+import regex ;
+import scanner ;
+import sequence ;
+import make ;
+import type ;
+import modules path project ;
+import xsltproc : xslt xslt-dir ;
+
+feature.feature format : html onehtml man pdf ps docbook fo tests
+ : incidental implicit composite ;
+
+type.register DTDXML : dtdxml ;
+type.register XML : xml : : main ;
+type.register BOOSTBOOK : boostbook : XML ;
+type.register DOCBOOK : docbook : XML ;
+type.register HTML : html ;
+type.register FO : fo : XML ;
+type.register PDF : pdf ;
+type.register PS : ps ;
+type.register XSLT : xsl : XML ;
+type.register HTMLDIR ;
+type.register MANPAGES ;
+type.register TESTS : tests ;
+
+
+# Initialize BoostBook support. The parameters are:
+# docbook-xsl-dir: The DocBook XSL stylesheet directory. If not provided,
+# we use DOCBOOK_XSL_DIR from the environment (if available). Otherwise,
+# we let the XML processor load the stylesheets remotely.
+#
+# docbook-dtd-dir: The DocBook DTD directory. If not provided, we use
+# DOCBOOK_DTD_DIR From the environment (if available). Otherwise, we let
+# the XML processor load the DTD remotely.
+rule init ( docbook-xsl-dir ? : docbook-dtd-dir ? )
+{
+
+ if ! $(docbook-xsl-dir)
+ {
+ docbook-xsl-dir = [ modules.peek : DOCBOOK_XSL_DIR ] ;
+ }
+
+ if ! $(docbook-dtd-dir)
+ {
+ docbook-dtd-dir = [ modules.peek : DOCBOOK_DTD_DIR ] ;
+ }
+
+ if ! $(.initialized)
+ {
+ $(.initialized) = true ;
+ if $(docbook-xsl-dir)
+ {
+ .docbook-xsl-dir = [ path.make $(docbook-xsl-dir) ] ;
+ }
+ if $(docbook-dtd-dir)
+ {
+ .docbook-dtd-dir = [ path.make $(docbook-dtd-dir) ] ;
+ }
+
+ local boost-root = [ modules.peek : BOOST_ROOT ] ;
+ if $(boost-root)
+ {
+ boost-root = [ path.make $(boost-root) ] ;
+ }
+ local boost-build-root = [
+ sequence.transform path.make : [ modules.peek : BOOST_BUILD_PATH ]
+ ] ;
+ local search-dirs = [ path.join $(boost-root) tools boostbook ]
+ $(boost-build-root)/../../boostbook ;
+
+ if --debug-configuration in [ modules.peek : ARGV ]
+ {
+ ECHO "notice: Boost.Book: searching XSLS/DTD in" ;
+ ECHO "notice:" [ sequence.transform path.native : $(search-dirs) ] ;
+ }
+ local boostbook-xsl-dir ;
+ for local dir in $(search-dirs) {
+ boostbook-xsl-dir += [ path.glob $(dir) : xsl ] ;
+ }
+ local boostbook-dtd-dir ;
+ for local dir in $(search-dirs) {
+ boostbook-dtd-dir += [ path.glob $(dir) : dtd ] ;
+ }
+ if $(boostbook-xsl-dir)
+ {
+ .boostbook-xsl-dir = [ path.make $(boostbook-xsl-dir[1]) ] ;
+ }
+ if $(boostbook-dtd-dir)
+ {
+ .boostbook-dtd-dir = [ path.make $(boostbook-dtd-dir[1]) ] ;
+ }
+
+
+ if ! $(.boostbook-xsl-dir) || ! $(.boostbook-dtd-dir)
+ {
+ errors.warning
+ couldn't find BoostBook xsl or dtd directories;
+ : please set \"BOOST_ROOT\" variable to the root directory of
+ your boost installation. Searched in:
+ : $(search-dirs:J="
+") ;
+ }
+ # Add trailing slash since some other code
+ # uses :B modifier to add last element, and fails
+ # without trailing slash. The code really should be fixed,
+ # but not now.
+ .boostbook-xsl-dir = $(.boostbook-xsl-dir)/ ;
+ .boostbook-dtd-dir = $(.boostbook-dtd-dir)/ ;
+
+ # Register generators only if we've were called via "using boostbook ; "
+ generators.register-standard boostbook.dtdxml-to-boostbook : DTDXML : XML ;
+ generators.register-standard boostbook.boostbook-to-docbook : XML : DOCBOOK ;
+ generators.register-standard boostbook.boostbook-to-tests : XML : TESTS ;
+ generators.register-standard boostbook.docbook-to-onehtml : DOCBOOK : HTML ;
+ generators.register-standard boostbook.docbook-to-htmldir : DOCBOOK : HTMLDIR ;
+ generators.register-standard boostbook.docbook-to-manpages : DOCBOOK : MANPAGES ;
+ generators.register-standard boostbook.docbook-to-fo : DOCBOOK : FO ;
+
+ # The same about Jamfile main target rules.
+ IMPORT $(__name__) : boostbook : : boostbook ;
+ }
+}
+
+rule xsl-dir
+{
+ return $(.boostbook-xsl-dir) ;
+}
+
+rule dtd-dir
+{
+ return $(.boostbook-dtd-dir) ;
+}
+
+rule docbook-xsl-dir
+{
+ return $(.docbook-xsl-dir) ;
+}
+
+rule docbook-dtd-dir
+{
+ return $(.docbook-dtd-dir) ;
+}
+
+rule dtdxml-to-boostbook ( target : source : properties * )
+{
+ xslt $(target) : $(source) "$(.boostbook-xsl-dir)/dtd/dtd2boostbook.xsl"
+ : $(properties) ;
+}
+
+rule boostbook-to-docbook ( target : source : properties * )
+{
+ local native-path = [ path.native $(.boostbook-xsl-dir) ] ;
+ local stylesheet = $(native-path:B=docbook:S=.xsl) ;
+ xslt $(target) : $(source) $(stylesheet) : $(properties) ;
+}
+
+rule docbook-to-onehtml ( target : source : properties * )
+{
+ local native-path = [ path.native $(.boostbook-xsl-dir) ] ;
+ local stylesheet = $(native-path:B=html-single:S=.xsl) ;
+ xslt $(target) : $(source) $(stylesheet) : $(properties) ;
+}
+
+rule docbook-to-htmldir ( target : source : properties * )
+{
+ local native-path = [ path.native $(.boostbook-xsl-dir) ] ;
+ local stylesheet = $(native-path:B=html:S=.xsl) ;
+ xslt-dir $(target) : $(source) $(stylesheet) : $(properties) : html ;
+}
+
+rule docbook-to-manpages ( target : source : properties * )
+{
+ local native-path = [ path.native $(.boostbook-xsl-dir) ] ;
+ local stylesheet = $(native-path:B=manpages:S=.xsl) ;
+ xslt-dir $(target) : $(source) $(stylesheet) : $(properties) : man ;
+}
+
+rule docbook-to-fo ( target : source : properties * )
+{
+ local native-path = [ path.native $(.boostbook-xsl-dir) ] ;
+ local stylesheet = $(native-path:B=fo:S=.xsl) ;
+ xslt $(target) : $(source) $(stylesheet) : $(properties) ;
+}
+
+class xml-catalog-action : action
+{
+ import boostbook ;
+ import print ;
+
+ rule __init__ ( target : property-set ? : catalog-entries * )
+ {
+ action.__init__ $(target) : : generate-xml-catalog : $(property-set) ;
+ }
+
+ rule actualize ( )
+ {
+ if ! $(self.actualized)
+ {
+ self.actualized = true ;
+ local actual = [ $(self.targets[1]).actualize ] ;
+ local text = "<?xml version=\"1.0\"?>" ;
+
+ text += "<!DOCTYPE catalog " ;
+ text += " PUBLIC \"-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN\"" ;
+ text += " \"http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd\">" ;
+ text += "<catalog xmlns=\"urn:oasis:names:tc:entity:xmlns:xml:catalog\">" ;
+
+ # BoostBook DTD catalog entry
+ local boostbook-dtd-dir = [ boostbook.dtd-dir ] ;
+
+ text += " <rewriteURI uriStartString=\"http://www.boost.org/tools/boostbook/dtd/\" rewritePrefix=\"file://$(boostbook-dtd-dir)/\"/>" ;
+
+ local docbook-xsl-dir = [ boostbook.docbook-xsl-dir ] ;
+ if ! $(docbook-xsl-dir)
+ {
+ ECHO "BoostBook warning: no DocBook XSL directory specified." ;
+ ECHO " If you have the DocBook XSL stylesheets installed, please " ;
+ ECHO " set DOCBOOK_XSL_DIR to the stylesheet directory on either " ;
+ ECHO " the command line (via -sDOCBOOK_XSL_DIR=...) or in a " ;
+ ECHO " Boost.Jam configuration file. The DocBook XSL stylesheets " ;
+ ECHO " are available here: http://docbook.sourceforge.net/ " ;
+ ECHO " Stylesheets will be downloaded on-the-fly (very slow!) " ;
+ }
+ else
+ {
+ text += " <rewriteURI uriStartString=\"http://docbook.sourceforge.net/release/xsl/current/\" rewritePrefix=\"file://$(docbook-xsl-dir)/\"/>" ;
+ }
+
+ local docbook-dtd-dir = [ boostbook.docbook-dtd-dir ] ;
+ if ! $(docbook-dtd-dir)
+ {
+ ECHO "BoostBook warning: no DocBook DTD directory specified." ;
+ ECHO " If you have the DocBook DTD installed, please set " ;
+ ECHO " DOCBOOK_DTD_DIR to the DTD directory on either " ;
+ ECHO " the command line (via -sDOCBOOK_DTD_DIR=...) or in a " ;
+ ECHO " Boost.Jam configuration file. The DocBook DTD is available " ;
+ ECHO " here: http://www.oasis-open.org/docbook/xml/4.2/index.shtml" ;
+ ECHO " The DTD will be downloaded on-the-fly (very slow!) " ;
+ }
+ else
+ {
+ text += " <rewriteURI uriStartString=\"http://www.oasis-open.org/docbook/xml/4.2/\" rewritePrefix=\"file://$(docbook-dtd-dir)/\"/>" ;
+ }
+
+ text += "</catalog>" ;
+
+ print.output $(actual) ;
+ print.text $(text) : true ;
+ }
+ }
+}
+
+class boostbook-target-class : basic-target
+{
+ import feature ;
+ import virtual-target ;
+ import generators ;
+
+ rule __init__ ( name : project : sources * : requirements *
+ : default-build * : catalog-entries * )
+ {
+
+ basic-target.__init__ $(name) : $(project) : $(sources) : $(requirements)
+ : $(default-build) ;
+ self.catalog-entries = $(catalog-entries) ;
+ }
+
+ rule construct ( source-targets * : property-set )
+ {
+ local path = [ $(self.project).get location ] ;
+ local catalog = [ new file-target catalog : XML : $(self.project) ] ;
+ $(catalog).action [ new xml-catalog-action $(catalog) : $(property-set)
+ : $(self.catalog-entries) ] ;
+
+ $(catalog).set-path $(path) ;
+ catalog = [ virtual-target.register $(catalog) ] ;
+ local properties = [ $(property-set).raw ] ;
+
+ local format = [ feature.get-values <format> : $(properties) ] ;
+ local targets = $(catalog) ;
+
+ local type = none ;
+ local manifest ;
+ switch $(format)
+ {
+ case html :
+ {
+ type = HTMLDIR ;
+ manifest = HTML.manifest ;
+ }
+
+ case onehtml : type = HTML ;
+
+ case man :
+ {
+ type = MANPAGES ;
+ manifest = man.manifest ;
+ }
+
+ case docbook : type = DOCBOOK ;
+ case fo : type = FO ;
+ case pdf : type = PDF ;
+ case ps : type = PS ;
+ case tests : type = TESTS ;
+ }
+
+ if $(manifest)
+ {
+ local base-target = [ generators.construct $(self.project)
+ : DOCBOOK : $(property-set) : $(source-targets) ] ;
+ $(base-target).depends $(catalog) ;
+
+ local target = [ generators.construct $(self.project) $(manifest)
+ : $(type) : $(property-set) : $(base-target) ] ;
+ $(target).set-path $(format) ;
+
+ targets += $(target) ;
+ }
+ else {
+ local target = [ generators.construct $(self.project)
+ : $(type) : $(property-set) : $(source-targets) ] ;
+
+ if ! $(target)
+ {
+ errors.error "Cannot build documentation type '$(format)'" ;
+ }
+ else
+ {
+ $(target).depends $(catalog) ;
+ targets += $(target) ;
+ }
+ }
+
+ return $(targets) ;
+ }
+}
+
+rule boostbook ( target-name : sources * : requirements * : default-build * )
+{
+ local project = [ project.current ] ;
+
+ targets.main-target-alternative
+ [ new boostbook-target-class $(target-name) : $(project)
+ : [ targets.main-target-sources $(sources) : $(target-name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+}
+
+#############################################################################
+# Dependency scanners
+#############################################################################
+# XInclude scanner. Mostly stolen from c-scanner :)
+# Note that this assumes an "xi" prefix for XIncludes. This isn't always the
+# case for XML documents, but we'll assume it's true for anything we encounter.
+class xinclude-scanner : scanner
+{
+ import virtual-target ;
+ import path ;
+ import scanner ;
+
+ rule __init__ ( includes * )
+ {
+ scanner.__init__ ;
+ self.includes = $(includes) ;
+ }
+
+ rule pattern ( )
+ {
+ return "xi:include[ ]*href=\"([^\"]*)\"" ;
+ }
+
+ rule process ( target : matches * : binding )
+ {
+ local target_path = [ NORMALIZE_PATH $(binding:D) ] ;
+
+ NOCARE $(matches) ;
+ INCLUDES $(target) : $(matches) ;
+ SEARCH on $(matches) = $(target_path) $(self.includes:G=) ;
+
+ scanner.propagate $(__name__) : $(matches) : $(target) ;
+ }
+}
+
+scanner.register xinclude-scanner : xsl:path ;
+type.set-scanner XML : xinclude-scanner ;
+
+#############################################################################
+# Testsuite handling
+#############################################################################
+rule boostbook-to-tests ( target : source : properties * )
+{
+ local boost_root = [ modules.peek : BOOST_ROOT ] ;
+ local native-path =
+ [ path.native [ path.join $(.boostbook-xsl-dir) testing Jamfile ] ] ;
+ local stylesheet = $(native-path:S=.xsl) ;
+ xslt $(target) : $(source) $(stylesheet)
+ : $(properties) <xsl:param>boost.root=$(boost_root)
+ ;
+}
Added: boost-jam/boost-build/branches/upstream/current/tools/borland.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/borland.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/borland.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,208 @@
+# (C) Copyright David Abrahams 2001.
+# (C) Copyright Vladimir Prus 2003.
+# (C) Copyright Rene Rivera 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.
+
+# Support for the Borland's command line compiler
+
+import property ;
+import generators ;
+import os ;
+import toolset : flags ;
+import feature : get-values ;
+import type ;
+import common ;
+
+toolset.register borland ;
+
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters borland :
+ version $(version) ] ;
+
+ local command = [ common.get-invocation-command borland : bcc32.exe
+ : $(command) ] ;
+
+ common.handle-options borland : $(condition) : $(command) : $(options) ;
+
+ if $(command)
+ {
+ command = [ common.get-absolute-tool-path $(command[-1]) ] ;
+ }
+ root = $(command:D) ;
+
+ flags borland.compile STDHDRS $(condition) : $(root)/include/ ;
+ flags borland.link STDLIBPATH $(condition) : $(root)/lib ;
+ flags borland .root $(condition) : $(root)/bin/ ;
+}
+
+
+# A borland-specific target type
+type.register BORLAND.TDS : tds ;
+
+# Declare generators
+
+generators.register-linker borland.link : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE RSP : <toolset>borland ;
+generators.register-linker borland.link.dll : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB RSP : <toolset>borland ;
+
+generators.register-composing borland.archive : OBJ : STATIC_LIB : <toolset>borland ;
+generators.register-c-compiler borland.compile.c++ : CPP : OBJ : <toolset>borland ;
+generators.register-c-compiler borland.compile.c : C : OBJ : <toolset>borland ;
+
+
+# Declare flags
+
+flags borland.compile OPTIONS <debug-symbols>on : -v ;
+flags borland.link OPTIONS <debug-symbols>on : -v ;
+
+flags borland.compile OPTIONS <optimization>off : -Od ;
+flags borland.compile OPTIONS <optimization>speed : -O2 ;
+flags borland.compile OPTIONS <optimization>space : -O1 ;
+
+flags borland CFLAGS <inlining>off : -vi- ;
+flags borland CFLAGS <inlining>on : -vi -w-inl ;
+flags borland CFLAGS <inlining>full : -vi -w-inl ;
+
+
+# Deal with various runtime configs...
+
+# This should be not for DLL
+flags borland OPTIONS <user-interface>console : -tWC ;
+
+# -tWR sets -tW as well, so we turn it off here and then turn it
+# on again later if we need it:
+flags borland OPTIONS <link-runtime>shared : -tWR -tWC ;
+flags borland OPTIONS <user-interface>gui : -tW ;
+
+flags borland OPTIONS <main-target-type>LIB/<link>shared : -tWD ;
+# Hmm.. not sure what's going on here.
+flags borland OPTIONS : -WM- ;
+flags borland OPTIONS <threading>multi : -tWM ;
+
+
+
+flags borland.compile OPTIONS <cxxflags> ;
+flags borland.compile DEFINES <define> ;
+flags borland.compile INCLUDES <include> ;
+
+flags borland NEED_IMPLIB <main-target-type>LIB/<link>shared : "" ;
+
+#
+# for C++ compiles the following options are turned on by default:
+#
+# -j5 stops after 5 errors
+# -g255 allow an unlimited number of warnings
+# -q no banner
+# -c compile to object
+# -P C++ code regardless of file extention
+# -w turns on all warnings
+# -Ve zero sized empty base classes, this option is on in the IDE by default
+# and effects binary compatibility.
+# -Vx zero sized empty members, this option is on in the IDE by default
+# and effects binary compatibility.
+# -a8 8 byte alignment, this option is on in the IDE by default
+# and effects binary compatibility.
+#
+
+# -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(C++FLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -o"$(<)" "$(>)"
+
+
+actions compile.c++
+{
+ $(CONFIG_COMMAND) -j5 -g255 -q -c -P -w -Ve -Vx -a8 -b- $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -I"$(STDHDRS)" -o"$(<)" "$(>)"
+}
+
+# For C, we don't pass -P flag
+actions compile.c
+{
+ $(CONFIG_COMMAND) -j5 -g255 -q -c -w -Ve -Vx -a8 -b- $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -I"$(STDHDRS)" -o"$(<)" "$(>)"
+}
+
+
+# Declare flags and action for linking
+toolset.flags borland.link OPTIONS <debug-symbols>on : -v ;
+toolset.flags borland.link LIBRARY_PATH <library-path> ;
+toolset.flags borland.link FINDLIBS_ST <find-static-library> ;
+toolset.flags borland.link FINDLIBS_SA <find-shared-library> ;
+toolset.flags borland.link LIBRARIES <library-file> ;
+toolset.flags borland.link LIBRARIES <library> ;
+
+flags borland.link OPTIONS <linkflags> ;
+flags borland.link OPTIONS <link>shared : -tWD ;
+
+flags borland.link LIBRARY_PATH_OPTION <toolset>borland : -L : unchecked ;
+flags borland.link LIBRARY_OPTION <toolset>borland : "" : unchecked ;
+
+
+
+# bcc32 needs to have ilink32 in the path in order to invoke it, so explicitly
+# specifying $(BCC_TOOL_PATH)bcc32 doesn't help. You need to add
+# $(BCC_TOOL_PATH) to the path
+# The NEED_IMPLIB variable controls whether we need to invoke implib.
+
+flags borland.archive AROPTIONS <archiveflags> ;
+# Declare action for archives. We don't use response file
+# since it's hard to get "+-" there.
+# CONSIDER: don't know what 'together' is for...
+actions updated together piecemeal archive
+{
+ "$(.root)tlib" $(AROPTIONS) /u /a /C "$(<:W)" +-"$(>:W)"
+}
+
+
+if [ os.name ] = CYGWIN
+{
+ .set-path = "cmd /S /C set \"PATH=" ;
+ .old-path = ";%PATH%\" \"&&\"" ;
+
+ # Couldn't get TLIB to stop being confused about pathnames
+ # containing dashes (it seemed to treat them as option separators
+ # when passed through from bash), so we explicitly write the
+ # command into a .bat file and execute that. TLIB is also finicky
+ # about pathname style! Forward slashes, too, are treated as
+ # options.
+ actions updated together piecemeal archive
+ {
+ echo "\"$(.root)tlib\" $(OPTIONS) /u /a /C \"$(<:W)\" +-\"$(>:W)\"" > $(<:D)/tlib.bat
+ chmod +x $(<:D)/tlib.bat && $(<:D)/tlib.bat && rm $(<:D)/tlib.bat ;
+ }
+}
+else if [ os.name ] = NT
+{
+ .set-path = "set \"PATH=" ;
+ .old-path = ";%PATH%\"
+ " ;
+}
+else
+{
+ .set-path = "PATH=\"" ;
+ .old-path = "\":$PATH
+ export PATH
+ " ;
+}
+
+
+rule link ( targets + : sources * : properties * )
+{
+ common.response-file $(targets) : $(sources) : $(targets[2])
+ : $(properties) ;
+}
+
+actions link bind LIBRARIES
+{
+ $(.set-path)$(.root:W)$(.old-path) $(CONFIG_COMMAND) -v -q $(OPTIONS) -L"$(LIBRARY_PATH:W)" -L"$(STDLIBPATH:W)" -e"$(<[1]:W)" @"$(<[2]:W)"
+}
+
+rule link.dll ( targets + : sources * : properties * )
+{
+ common.response-file $(targets) : $(sources) : $(targets[3]) : $(properties) ;
+}
+
+actions link.dll bind LIBRARIES
+{
+ $(.set-path)$(.root:W)$(.old-path) $(CONFIG_COMMAND) -v -q $(OPTIONS) -L"$(LIBRARY_PATH:W)" -L"$(STDLIBPATH:W)" -e"$(<[1]:W)" @"$(<[3]:W)"
+ "$(.root)implib" "$(<[2]:W)" "$(<[1]:W)"
+}
Added: boost-jam/boost-build/branches/upstream/current/tools/builtin.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/builtin.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/builtin.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,774 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+# Defines standard features and rules.
+
+import "class" : new ;
+
+import feature : feature compose ;
+import toolset : flags ;
+import errors : error ;
+import type ;
+import scanner ;
+import generators ;
+import regex ;
+import virtual-target ;
+import os ;
+import symlink ;
+import alias ;
+import property ;
+import print ;
+import utility ;
+import project ;
+
+# This feature is used to determine which OS we're on.
+# In future, this may become <target-os> and <host-os>
+local os = [ modules.peek : OS ] ;
+feature os : $(os) : propagated link-incompatible ;
+
+feature toolset : : implicit propagated symmetric ;
+
+feature stdlib : native : propagated link-incompatible composite ;
+
+feature link : shared static : propagated ;
+feature link-runtime : shared static : propagated ;
+feature runtime-debugging : on off : propagated ;
+
+
+feature optimization : off speed space : propagated ;
+feature profiling : off on : propagated ;
+feature inlining : off on full : propagated ;
+
+feature threading : single multi : propagated ;
+feature rtti : on off : propagated ;
+feature exception-handling : on off : propagated ;
+feature debug-symbols : on off : propagated ;
+feature define : : free ;
+feature "include" : : free path ; #order-sensitive ;
+feature cflags : : free ;
+feature cxxflags : : free ;
+feature linkflags : : free ;
+feature archiveflags : : free ;
+feature version : : free ;
+
+feature.feature location-prefix : : free ;
+
+# The following features are incidental, since
+# in themself they have no effect on build products.
+# Not making them incidental will result in problems in corner
+# cases, for example:
+#
+# unit-test a : a.cpp : <use>b ;
+# lib b : a.cpp b ;
+#
+# Here, if <use> is not incidental, we'll decide we have two
+# targets for a.obj with different properties, and will complain.
+#
+# Note that making feature incidental does not mean it's ignored. It may
+# be ignored when creating the virtual target, but the rest of build process
+# will use them.
+feature use : : free dependency incidental ;
+feature dependency : : free dependency incidental ;
+feature implicit-dependency : : free dependency incidental ;
+
+feature source : : free dependency incidental ;
+feature library : : free dependency incidental ;
+feature file : : free dependency incidental ;
+feature find-shared-library : : free ; #order-sensitive ;
+feature find-static-library : : free ; #order-sensitive ;
+feature library-path : : free path ; #order-sensitive ;
+# Internal feature.
+feature library-file : : free dependency ;
+
+feature name : : free ;
+feature tag : : free ;
+feature search : : free path ; #order-sensitive ;
+feature location : : free path ;
+
+feature dll-path : : free path ;
+feature hardcode-dll-paths : true false : incidental ;
+
+
+# This is internal feature which holds the paths of all dependency
+# dynamic libraries. On Windows, it's needed so that we can all
+# those paths to PATH, when running applications.
+# On Linux, it's needed to add proper -rpath-link command line options.
+feature xdll-path : : free path ;
+
+#provides means to specify def-file for windows dlls.
+feature def-file : : free dependency ;
+
+# This feature is used to allow specific generators to run.
+# For example, QT tools can only be invoked when QT library
+# is used. In that case, <allow>qt will be in usage requirement
+# of the library.
+feature allow : : free ;
+
+# Windows-specific features
+
+feature user-interface : console gui wince native auto ;
+
+feature variant : : implicit composite propagated symmetric ;
+
+# Declares a new variant.
+# First determines explicit properties for this variant, by
+# refining parents' explicit properties with the passed explicit
+# properties. The result is remembered and will be used if
+# this variant is used as parent.
+#
+# Second, determines the full property set for this variant by
+# adding to the explicit properties default values for all properties
+# which neither present nor are symmetric.
+#
+# Lastly, makes appropriate value of 'variant' property expand
+# to the full property set.
+rule variant ( name # Name of the variant
+ : parents-or-properties * # Specifies parent variants, if
+ # 'explicit-properties' are given,
+ # and explicit-properties otherwise.
+ : explicit-properties * # Explicit properties.
+ )
+{
+ local parents ;
+ if ! $(explicit-properties)
+ {
+ if $(parents-or-properties[1]:G)
+ {
+ explicit-properties = $(parents-or-properties) ;
+ }
+ else
+ {
+ parents = $(parents-or-properties) ;
+ }
+ }
+ else
+ {
+ parents = $(parents-or-properties) ;
+ }
+
+ # The problem is that we have to check for conflicts
+ # between base variants.
+ if $(parents[2])
+ {
+ error "multiple base variants are not yet supported" ;
+ }
+
+ local inherited ;
+ # Add explicitly specified properties for parents
+ for local p in $(parents)
+ {
+ # TODO: the check may be sticter
+ if ! [ feature.is-implicit-value $(p) ]
+ {
+ error "Invalid base varaint" $(p) ;
+ }
+
+ inherited += $(.explicit-properties.$(p)) ;
+ }
+ property.validate $(explicit-properties) ;
+ explicit-properties = [ property.refine $(inherited) : $(explicit-properties) ] ;
+
+ # Record explicitly specified properties for this variant
+ # We do this after inheriting parents' properties, so that
+ # they affect other variants, derived from this one.
+ .explicit-properties.$(name) = $(explicit-properties) ;
+
+ feature.extend variant : $(name) ;
+ feature.compose <variant>$(name) : $(explicit-properties) ;
+}
+IMPORT $(__name__) : variant : : variant ;
+
+variant debug : <optimization>off <debug-symbols>on <inlining>off <runtime-debugging>on ;
+variant release : <optimization>speed <debug-symbols>off <inlining>full
+ <runtime-debugging>off <define>NDEBUG ;
+variant profile : release : <profiling>on <debug-symbols>on ;
+
+class searched-lib-target : abstract-file-target
+{
+ rule __init__ ( name
+ : project
+ : shared ?
+ : real-name ?
+ : search *
+ )
+ {
+ abstract-file-target.__init__ $(name) : SEARCHED_LIB : $(project) ;
+
+ self.shared = $(shared) ;
+ self.real-name = $(real-name) ;
+ self.real-name ?= $(name) ;
+ self.search = $(search) ;
+ }
+
+
+ rule shared ( )
+ {
+ return $(self.shared) ;
+ }
+
+ rule real-name ( )
+ {
+ return $(self.real-name) ;
+ }
+
+ rule search ( )
+ {
+ return $(self.search) ;
+ }
+
+ rule actualize-location ( target )
+ {
+ NOTFILE $(target) ;
+ }
+
+ rule path ( )
+ {
+ }
+}
+
+type.register LIB : : : main ;
+
+# register the given type on the specified OSes, or on remaining OSes
+# if os is not specified.
+local rule declare-type ( os * : type : suffixes * : base-type ? : main ? )
+{
+ if ! [ type.registered $(type) ]
+ {
+ if ( ! $(os) ) || [ os.name ] in $(os)
+ {
+ type.register $(type) : $(suffixes) : $(base-type) : $(main) ;
+ }
+ }
+}
+
+#
+# Common target types.
+#
+
+declare-type NT CYGWIN : OBJ : obj : : main ;
+declare-type : OBJ : o : : main ;
+
+declare-type NT CYGWIN : STATIC_LIB : lib a : LIB : main ;
+declare-type : STATIC_LIB : a : LIB : main ;
+
+declare-type : IMPORT_LIB : : STATIC_LIB : main ;
+type.set-generated-target-suffix IMPORT_LIB : : lib ;
+
+declare-type NT CYGWIN : SHARED_LIB : dll : LIB : main ;
+declare-type : SHARED_LIB : so : LIB : main ;
+
+declare-type : SEARCHED_LIB : : LIB : main ;
+
+declare-type NT CYGWIN : EXE : exe : : ;
+declare-type : EXE : : : ;
+
+declare-type : PYTHON_EXTENSION : : SHARED_LIB : main ;
+# We can't give "dll" suffix to PYTHON_EXTENSION, because
+# we would not know what "a.dll" is: python extenstion or
+# ordinary library. Therefore, we specify only suffixes
+# used for generation of targets.
+type.set-generated-target-suffix PYTHON_EXTENSION : : so ;
+type.set-generated-target-suffix PYTHON_EXTENSION : <os>NT : so ;
+type.set-generated-target-suffix PYTHON_EXTENSION : <os>CYGWIN : dll ;
+
+type.register CPP : cpp cxx cc ;
+
+import stage ;
+
+
+class c-scanner : scanner
+{
+ import regex virtual-target path scanner ;
+
+ rule __init__ ( includes * )
+ {
+ scanner.__init__ ;
+
+ self.includes = $(includes) ;
+ }
+
+ rule pattern ( )
+ {
+ return "#[ \t]*include[ ]*(<(.*)>|\"(.*)\")" ;
+ }
+
+ rule process ( target : matches * : binding )
+ {
+ local angle = [ regex.transform $(matches) : "<(.*)>" ] ;
+ local quoted = [ regex.transform $(matches) : "\"(.*)\"" ] ;
+
+ # CONSIDER: the new scoping rule seem to defeat "on target" variables.
+ local g = [ on $(target) return $(HDRGRIST) ] ;
+ local b = [ NORMALIZE_PATH $(binding:D) ] ;
+
+ # Attach binding of including file to included targets.
+ # When target is directly created from virtual target
+ # this extra information is unnecessary. But in other
+ # cases, it allows to distinguish between two headers of the
+ # same name included from different places.
+ # We don't need this extra information for angle includes,
+ # since they should not depend on including file (we can't
+ # get literal "." in include path).
+ local g2 = $(g)"#"$(b) ;
+
+ angle = $(angle:G=$(g)) ;
+ quoted = $(quoted:G=$(g2)) ;
+
+ local all = $(angle) $(quoted) ;
+
+ INCLUDES $(target) : $(all) ;
+ NOCARE $(all) ;
+ SEARCH on $(angle) = $(self.includes:G=) ;
+ SEARCH on $(quoted) = $(b) $(self.includes:G=) ;
+
+ # Just propagate current scanner to includes, in a hope
+ # that includes do not change scanners.
+ scanner.propagate $(__name__) : $(angle) $(quoted) : $(target) ;
+ }
+}
+
+scanner.register c-scanner : include ;
+
+type.set-scanner CPP : c-scanner ;
+
+
+type.register H : h ;
+type.register HPP : hpp : H ;
+type.register C : c ;
+
+class lib-target-class : basic-target
+{
+ import generators : construct : generators.construct ;
+ import type ;
+ import path ;
+
+ rule __init__ ( name : project
+ : sources * : requirements * : default-build * : usage-requirements * )
+ {
+ basic-target.__init__ $(name) : $(project)
+ : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ;
+ }
+
+ rule construct ( source-targets * : property-set )
+ {
+ local properties = [ $(property-set).raw ] ;
+ # Determine the needed target type
+ local actual-type ;
+ if <search> in $(properties:G) || <name> in $(properties:G)
+ {
+ actual-type = SEARCHED_LIB ;
+ }
+ else if <file> in $(properties:G)
+ {
+ # The generator for
+ actual-type = LIB ;
+ }
+ else if <link>shared in $(properties)
+ {
+ actual-type = SHARED_LIB ;
+ }
+ else
+ {
+ actual-type = STATIC_LIB ;
+ }
+ property-set = [ $(property-set).add-raw <main-target-type>LIB ] ;
+ # Construct the target.
+ return [ generators.construct $(self.project) $(self.name) : $(actual-type)
+ : $(property-set) : $(source-targets) : LIB ] ;
+ }
+
+ rule compute-usage-requirements ( subvariant )
+ {
+ local rproperties = [ $(subvariant).build-properties ] ;
+ local created-targets = [ $(subvariant).created-targets ] ;
+ local result = [ basic-target.compute-usage-requirements $(subvariant) ] ;
+
+ # For lib targets with <search>, add the value of <search> as <library-path>
+ # usage requirement.
+ local search = [ $(rproperties).get <search> ] ;
+ if $(search)
+ {
+ result = [ $(result).add [
+ property-set.create $(search:G=<library-path>) ] ] ;
+ }
+
+ # Add appropricate <xdll-path> usage requirements.
+ local raw = [ $(rproperties).raw ] ;
+ if <link>shared in $(raw)
+ {
+ local paths ;
+ local pwd = [ path.pwd ] ;
+ for local t in $(created-targets)
+ {
+ if [ type.is-derived [ $(t).type ] SHARED_LIB ]
+ {
+ paths += [ path.root [ path.make [ $(t).path ] ] $(pwd) ] ;
+ }
+ }
+ if $(paths)
+ {
+ result = [ $(result).add
+ [ property-set.create $(paths:G=<xdll-path>) ] ] ;
+ }
+ }
+
+ # Pass <xdll-path> features that we've got from sources.
+ local u = [ $(subvariant).sources-usage-requirements ] ;
+ local values = [ $(u).get <xdll-path> ] ;
+ result = [ $(result).add-raw $(values:G=<xdll-path>) ] ;
+
+ # For libraries that we've failed to consume, we need to
+ # pass <library-path> usage requirements, if any.
+ # We look at all generated target, and if they are created in different
+ # subvariant, we add usage requirements.
+ for local t in [ $(subvariant).created-targets ]
+ {
+ local s = [ $(t).creating-subvariant ] ;
+ if $(s) != $(subvariant)
+ {
+ result = [ $(result).add [ $(s).usage-requirements ] ] ;
+ }
+ }
+
+ return $(result) ;
+ }
+}
+
+rule lib ( names + : sources * : requirements * : default-build *
+ : usage-requirements * )
+{
+ local project = [ project.current ] ;
+
+ # This is a circular module dependency, so it must be imported here
+ import targets ;
+
+ local result ;
+ if ! $(sources) && ! $(requirements)
+ && ! $(default-build) && ! $(usage-requirements)
+ {
+ for local name in $(names)
+ {
+ result += [
+ targets.main-target-alternative
+ [ new lib-target-class $(name) : $(project)
+ :
+ : [ targets.main-target-requirements $(requirements) <name>$(name) :
+ $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
+ ] ] ;
+ }
+ }
+ else
+ {
+ if $(names[2])
+ {
+ errors.user-error "When several names are given to the 'lib' rule" :
+ "it's not allows to specify sources or requirements. " ;
+ }
+
+ local name = $(names[1]) ;
+ result = [ targets.main-target-alternative
+ [ new lib-target-class $(name) : $(project)
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
+ ] ] ;
+ }
+ return $(result) ;
+}
+IMPORT $(__name__) : lib : : lib ;
+
+
+class exe-target-class : typed-target
+{
+ import type ;
+
+ rule __init__ ( name : project
+ : sources * : requirements * : default-build * : usage-requirements * )
+ {
+ typed-target.__init__ $(name) : $(project) : EXE
+ : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ;
+ }
+
+ rule compute-usage-requirements ( subvariant )
+ {
+ local result = [ typed-target.compute-usage-requirements $(subvariant) ] ;
+ local p = [ $(subvariant).build-properties ] ;
+
+ local xdll-paths = [ $(p).get <xdll-path> ] ;
+ if $(xdll-paths)
+ {
+ result = [ $(result).add-raw $(xdll-paths:G=<xdll-path>) ] ;
+ }
+
+ return $(result) ;
+ }
+
+ rule check-for-unused-sources ( result * : sources * )
+ {
+ # For exes, we typically don't consume ignore DLL on windows.
+ # We also handle searched libraries via special properties
+ # on actions, so should not check for search libraries.
+ # As the result, we don't check for unused LIB sources
+ # at all.
+
+ local sources-to-check ;
+ for local s in $(sources)
+ {
+ if ! [ type.is-derived [ $(s).type ] LIB ]
+ {
+ sources-to-check += $(s) ;
+ }
+ }
+ basic-target.check-for-unused-sources $(result) : $(sources-to-check) ;
+ }
+}
+
+rule exe ( name : sources * : requirements * : default-build *
+ : usage-requirements * )
+{
+ local project = [ project.current ] ;
+
+ # This is a circular module dependency, so it must be imported here
+ import targets ;
+ targets.main-target-alternative
+ [ new exe-target-class $(name) : $(project)
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
+ ] ;
+}
+IMPORT $(__name__) : exe : : exe ;
+
+
+
+class searched-lib-generator : generator
+{
+ rule __init__ ( )
+ {
+ # The requirements cause the generators to be tried *only* when we're building
+ # lib target and there's 'search' feature. This seems ugly --- all we want
+ # is make sure searched-lib-generator is not invoced deep in transformation
+ # search.
+ generator.__init__ searched-lib-generator : : SEARCHED_LIB ;
+ }
+
+ rule run ( project name ? : property-set : sources * : multiple ? )
+ {
+ if $(name)
+ {
+ # If name is empty, it means we're called not from top-level.
+ # In this case, we just fail immediately, because searched-lib-generator
+ # cannot be used to produce intermediate targets.
+
+ local properties = [ $(property-set).raw ] ;
+ local shared ;
+ if <link>shared in $(properties)
+ {
+ shared = true ;
+ }
+
+ local t = [ new searched-lib-target $(name) : $(project) : $(shared)
+ : [ feature.get-values <name> : $(properties) ]
+ : [ feature.get-values <search> : $(properties) ]
+ ] ;
+ # attach an action and properties to the target
+ a = [ new null-action $(t) : $(property-set) ] ;
+ $(t).action $(a) ;
+ # We return sources for a simple reason. If there's
+ # lib png : z : <name>png ;
+ # the 'z' target should be returned, so that apps linking to
+ # 'png' will link to 'z', too.
+ return [ virtual-target.register $(t) ] $(sources) ;
+ }
+ }
+}
+
+generators.register [ new searched-lib-generator ] ;
+
+class prebuilt-lib-generator : generator
+{
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule run ( project name ? : property-set : sources * : multiple ? )
+ {
+ local f = [ $(property-set).get <file> ] ;
+ return $(f) $(sources) ;
+ }
+}
+
+generators.register
+ [ new prebuilt-lib-generator builtin.prebuilt : : LIB : <file> ] ;
+
+
+
+
+
+class compile-action : action
+{
+ import sequence ;
+
+ rule __init__ ( targets + : sources * : action-name : properties * )
+ {
+ action.__init__ $(targets) : $(sources) : $(action-name) : $(properties) ;
+ }
+
+
+ # For all virtual targets for the same dependency graph as self,
+ # i.e. which belong to the same main target, add their directories
+ # to include path.
+ rule adjust-properties ( properties * )
+ {
+ local s = [ $(self.targets[1]).creating-subvariant ] ;
+ return $(properties) [ $(s).implicit-includes "include" : H ] ;
+ }
+}
+
+class C-compiling-generator : generator
+{
+ rule __init__ ( id : source-types + : target-types + :
+ requirements * : optional-properties * )
+ {
+ generator.__init__ $(id) : $(source-types) : $(target-types) :
+ $(requirements) : $(optional-properties) ;
+ }
+
+ rule action-class ( )
+ {
+ return compile-action ;
+ }
+}
+
+rule register-c-compiler ( id : source-types + : target-types + :
+ requirements * : optional-properties * )
+{
+ local g = [ new C-compiling-generator $(id) : $(source-types)
+ : $(target-types) : $(requirements) : $(optional-properties) ] ;
+ generators.register $(g) ;
+}
+
+# FIXME: this is ugly, should find a better way (we'd want client code to
+# register all generators as "generator.some-rule", not with "some-module.some-rule".)
+IMPORT $(__name__) : register-c-compiler : : generators.register-c-compiler ;
+
+class linking-generator : generator
+{
+ import property-set ;
+ import type ;
+ import path ;
+ import project ;
+
+ rule __init__ ( id
+ composing ? : # Specify if generator is composing. The generator will be
+ # composing if non-empty string is passed, or parameter is
+ # not given. To make generator non-composing, pass empty
+ # string ("")
+ source-types + : target-types + :
+ requirements * )
+ {
+ composing ?= true ;
+ generator.__init__ $(id) $(composing) : $(source-types) : $(target-types) :
+ $(requirements) ;
+ }
+
+ rule run ( project name ? : property-set : sources + : multiple ? )
+ {
+ sources += [ $(property-set).get <library> ] ;
+
+ if [ $(property-set).get <hardcode-dll-paths> ] = true
+ && [ type.is-derived $(self.target-types[1]) EXE ]
+ {
+ local xdll-path = [ $(property-set).get <xdll-path> ] ;
+ # It's possible that we have libraries in sources which did not came
+ # from 'lib' target. For example, libraries which are specified
+ # just as filenames as sources. We don't have xdll-path properties
+ # for such target, but still need to add proper dll-path properties.
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] SHARED_LIB ] && ! [ $(s).action ]
+ {
+ # Unfortunately, we don't have a good way to find the path
+ # to a file, so use this nasty approach.
+ local p = [ $(s).project ] ;
+ local location = [ path.root [ $(s).name ]
+ [ $(p).get source-location ] ] ;
+ xdll-path += [ path.parent $(location) ] ;
+ }
+ }
+
+ if $(xdll-path)
+ {
+ property-set = [ $(property-set).add-raw $(xdll-path:G=<dll-path>) ] ;
+ }
+
+ }
+
+ local result = [ generator.run $(project) $(name) : $(property-set)
+ : $(sources) : $(multiple) ] ;
+
+ return $(result) ;
+ }
+
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ local sources2 ; # sources to pass to inherited rule
+ local properties2 ; # properties to pass to inherited rule
+ local libraries ; # sources which are libraries
+
+ # Searched libraries are not passed as argument to linker
+ # but via some option. So, we pass them to the action
+ # via property.
+ properties2 = [ $(property-set).raw ] ;
+ local fsa ;
+ local fst ;
+ for local s in $(sources)
+ {
+ if [ type.is-derived [ $(s).type ] LIB ] &&
+ [ class.is-a $(s) : searched-lib-target ]
+ {
+ local name = [ $(s).real-name ] ;
+ if [ $(s).shared ]
+ {
+ fsa += $(name) ;
+ }
+ else
+ {
+ fst += $(name) ;
+ }
+ }
+ else
+ {
+ sources2 += $(s) ;
+ }
+ }
+ properties2 += <find-shared-library>$(fsa:J=&&)
+ <find-static-library>$(fst:J=&&) ;
+
+ local spawn = [ generator.generated-targets $(sources2)
+ : [ property-set.create $(properties2) ] : $(project) $(name) ] ;
+
+ return $(spawn) ;
+ }
+}
+
+rule register-linker ( id composing ? : source-types + : target-types + :
+ requirements * )
+{
+ local g = [ new linking-generator $(id) $(composing) : $(source-types)
+ : $(target-types) : $(requirements) ] ;
+ generators.register $(g) ;
+}
+
+IMPORT $(__name__) : register-linker : : generators.register-linker ;
+
+declare-type : RSP : rsp ;
+
+
Added: boost-jam/boost-build/branches/upstream/current/tools/common.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/common.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/common.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,480 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+# Provides actions common to all toolsets, for as making directoies and
+# removing files.
+
+import os ;
+import modules ;
+import utility ;
+import print ;
+import type ;
+import feature ;
+import errors ;
+import path ;
+import sequence ;
+import toolset ;
+
+
+# The rule checks toolset parameters. Each trailing parameter
+# should be a pair of parameter name and parameter value.
+# The rule will check that each parameter either has value in
+# each invocation, or has no value in each invocation. Also,
+# the rule will check that the combination of all parameter values is
+# unique in all invocations.
+#
+# Each parameter name corresponds to subfeature. This rule will declare subfeature
+# the first time non-empty parameter value is passed, and will extend it with
+# all the values.
+#
+# The return value from this rule is a condition to be used for flags settings.
+rule check-init-parameters ( toolset : * )
+{
+ local sig = $(toolset) ;
+ local condition = <toolset>$(toolset) ;
+ for local index in 2 3 4 5 6 7 8 9
+ {
+ local name = $($(index)[1]) ;
+ local value = $($(index)[2]) ;
+
+ if $(value)-is-specified
+ {
+ condition = $(condition)-$(value) ;
+ if $(.had-unspecified-value.$(toolset).$(name))
+ {
+ errors.user-error
+ "$(toolset) initialization: parameter '$(name)' inconsistent" :
+ "no value was specified in earlier initialization" :
+ "an explicit value is specified now" ;
+ }
+ # The below logic is for intel compiler. It calls this rule
+ # with 'intel-linux' and 'intel-win' as toolset, so we need to
+ # get the base part of toolset name.
+ # We can't pass 'intel' as toolset, because it that case it will
+ # be impossible to register versionles intel-linux and
+ # intel-win of specific version.
+ local t = $(toolset) ;
+ local m = [ MATCH ([^-]*)- : $(toolset) ] ;
+ if $(m)
+ {
+ t = $(m[1]) ;
+ }
+ if ! $(.had-value.$(toolset).$(name))
+ {
+ if ! $(.declared-subfeature.$(t).$(name))
+ {
+ feature.subfeature toolset $(t) : $(name) : : propagated ;
+ .declared-subfeature.$(t).$(name) = true ;
+ }
+ .had-value.$(toolset).$(name) = true ;
+ }
+ feature.extend-subfeature toolset $(t) : $(name) : $(value) ;
+ }
+ else
+ {
+ if $(.had-value.$(toolset).$(name))
+ {
+ errors.user-error
+ "$(toolset) initialization: parameter '$(name)' inconsistent" :
+ "an explicit value was specified in an earlier initialization" :
+ "no value is specified now" ;
+ }
+ .had-unspecified-value.$(toolset).$(name) = true ;
+ }
+ sig = $(sig)$(value:E="")- ;
+ }
+ if $(sig) in $(.all-signatures)
+ {
+ local message =
+ "duplicate initialization of $(toolset) with the following parameters: " ;
+ for local index in 2 3 4 5 6 7 8 9
+ {
+ local p = $($(index)) ;
+ if $(p)
+ {
+ message += "$(p[1]) = $(p[2]:E=<unspecified>)" ;
+ }
+ }
+ message += "previous initialization at $(.init-loc.$(sig))" ;
+ errors.user-error $(message[1]) : $(message[2]) : $(message[3]) : $(message[4])
+ : $(message[5]) : $(message[6]) : $(message[7]) : $(message[8]) ;
+ }
+ .all-signatures += $(sig) ;
+ .init-loc.$(sig) = [ errors.nearest-user-location ] ;
+
+ return $(condition) ;
+}
+
+# A helper rule to get the command to invoke some tool. The rule is either passed
+# a user provided command, it which case it checks it for correctness, or it tries
+# to find the tool using it's name, the PATH, and additional path.
+# This rule returns the command to be used when invoking the tool. If we can't
+# find the tool, a warning is issued.
+# If 'path-last' is specified, path is checked after 'additional-paths'.
+rule get-invocation-command (
+ toolset : tool : user-provided-command * : additional-paths * : path-last ? )
+{
+ local command ;
+ if ! $(user-provided-command)
+ {
+ command = [ common.find-tool $(tool) : $(additional-paths) : $(path-last) ] ;
+ if ! $(command)
+ {
+ ECHO "warning: toolset $(toolset) initialization: can't find tool $(tool)" ;
+ ECHO "warning: initialized from" [ errors.nearest-user-location ] ;
+ }
+ }
+ else
+ {
+ command = [ common.check-tool $(user-provided-command) ] ;
+ if ! $(command)
+ {
+ ECHO "warning: toolset $(toolset) initialization: " ;
+ ECHO "warning: can't find user-provided command '$(user-provided-command:J= )'" ;
+ ECHO "warning: initialized from" [ errors.nearest-user-location ] ;
+ # It's possible, in theory, that user-provided command is OK, but we're
+ # not smart enough to understand that.
+ command = $(user-provided-command) ;
+ }
+ }
+ if ! $(command)
+ {
+ command = $(user-provided-command) ;
+ }
+ return $(command) ;
+}
+
+# Given an invocation command,
+# return the absolute path to the command. This works even if commnad
+# has not path element and is present in PATH.
+rule get-absolute-tool-path ( command )
+{
+ if $(command:D)
+ {
+ return $(command:D) ;
+ }
+ else
+ {
+ local m = [ GLOB [ modules.peek : PATH Path path ] : $(command) $(command).exe ] ;
+ return $(m[1]:D) ;
+ }
+}
+
+
+
+# Attempts to find tool (binary) named 'name' in PATH and in 'additiona-paths'.
+# If found in path, returns 'name'.
+# If found in additional paths, returns full name. If there are several possibilities,
+# returns them all.
+# Otherwise, returns empty string.
+# If 'path-last' is specified, path is checked after 'additional-paths'.
+rule find-tool ( name : additional-paths * : path-last ? )
+{
+ local path = [ path.programs-path ] ;
+ local match = [ path.glob $(path) : $(name) $(name).exe ] ;
+ local additional-match = [ path.glob $(additional-paths) : $(name) $(name).exe ] ;
+
+ local result ;
+ if $(path-last)
+ {
+ result = $(additional-match) ;
+ if ! $(result) && $(match)
+ {
+ result = $(name) ;
+ }
+ }
+ else
+ {
+ if $(match)
+ {
+ result = $(name) ;
+ }
+ else
+ {
+ result = $(additional-match) ;
+ }
+ }
+ if $(result)
+ {
+ return [ path.native $(result[1]) ] ;
+ }
+}
+
+# Checks if 'command' can be found either in path
+# or is a full name to an existing file.
+rule check-tool-aux ( command )
+{
+ if $(command:D)
+ {
+ if [ path.exists $(command) ]
+ {
+ return $(command) ;
+ }
+ }
+ else
+ {
+ if [ GLOB [ modules.peek : PATH Path path ] : $(command) ]
+ {
+ return $(command) ;
+ }
+ }
+}
+
+
+# Checks that a tool can be invoked by 'command'.
+# If command is not an absolute path, checks if it can be found in 'path'.
+# If comand is absolute path, check that it exists. Returns 'command'
+# if ok and empty string otherwise.
+rule check-tool ( xcommand + )
+{
+ if [ check-tool-aux $(xcommand[1]) ]
+ || [ check-tool-aux $(xcommand[-1]) ]
+ {
+ return $(xcommand) ;
+ }
+}
+
+# Handle common options for toolset, specifically sets the following
+# flag variables:
+# - CONFIG_COMMAND to 'command'
+# - OPTIONS for compile.c to the value of <cflags> in options
+# - OPTIONS for compile.c++ to the value of <cxxflags> in options
+# - OPTIOns for compile to the value of <compileflags> in options
+# - OPTIONs for link to the value of <linkflags> in options
+rule handle-options ( toolset : condition * : command ? : options * )
+{
+ # The last parameter ('true') says it's OK to set flags for another
+ # module,
+ toolset.flags $(toolset) CONFIG_COMMAND $(condition) : $(command) : unchecked ;
+ toolset.flags $(toolset).compile OPTIONS $(condition) :
+ [ feature.get-values <compileflags> : $(options) ] : unchecked ;
+ toolset.flags $(toolset).compile.c OPTIONS $(condition) :
+ [ feature.get-values <cflags> : $(options) ] : unchecked ;
+ toolset.flags $(toolset).compile.c++ OPTIONS $(condition) :
+ [ feature.get-values <cxxflags> : $(options) ] : unchecked ;
+ toolset.flags $(toolset).link OPTIONS $(condition) :
+ [ feature.get-values <linkflags> : $(options) ] : unchecked ;
+}
+
+
+# returns the location of the "program files" directory on a windows
+# platform
+rule get-program-files-dir ( )
+{
+ local ProgramFiles = [ modules.peek : ProgramFiles ] ;
+ if $(ProgramFiles)
+ {
+ ProgramFiles = "$(ProgramFiles:J= )" ;
+ }
+ else
+ {
+ ProgramFiles = "c:\\Program Files" ;
+ }
+ return $(ProgramFiles) ;
+}
+
+if [ os.name ] = NT
+{
+ RM = del /f ;
+ CP = copy ;
+}
+else
+{
+ RM = rm -f ;
+ CP = cp ;
+}
+
+nl = "
+" ;
+
+# Returns the command needed to set shell variable on the
+# current platform.
+rule variable-setting-command ( variable value )
+{
+ if [ modules.peek : NT ]
+ {
+ return "set $(variable)=$(value)$(nl)" ;
+ }
+ else
+ {
+ return "$(variable)=$(value)" ;
+ }
+}
+
+# Returns the command needed to set shell variable on the
+# current platform. Each element of values is expected to be a path,
+# elements are joined with os-specific characer which delimits paths in
+# environment variables.
+rule path-variable-setting-command ( variable : values * : exported ? )
+{
+ local result ;
+ if [ modules.peek : NT ]
+ {
+ result = set $(variable)=$(values:J=";")$(nl) ;
+ }
+ else
+ {
+ # We can't put ":" directly in :J modifier.
+ local sep = ":" ;
+ if $(exported)
+ {
+ result = $(variable)=$(values:J=$(sep));export $(variable) ;
+ }
+ else
+ {
+ result = $(variable)=$(values:J=$(sep)) ;
+ }
+ }
+ return $(result:J=" ") ;
+}
+
+
+# Return a command which can create a file. If 'r' is result of invocation,
+# then
+# r foobar
+# will create foobar with unspecified content. What happens if file already
+# exists is unspecified.
+rule file-creation-command ( )
+{
+ if [ modules.peek : NT ]
+ {
+ return "echo. > " ;
+ }
+ else
+ {
+ return "touch " ;
+ }
+}
+
+
+rule MkDir
+{
+ # If dir exists, don't update it
+ # Do this even for $(DOT).
+
+ NOUPDATE $(<) ;
+
+ if $(<) != $(DOT) && ! $($(<)-mkdir)
+ {
+ local s ;
+
+ # Cheesy gate to prevent multiple invocations on same dir
+ # MkDir1 has the actions
+ # Arrange for jam dirs
+
+ $(<)-mkdir = true ;
+ MkDir1 $(<) ;
+ Depends dirs : $(<) ;
+
+ # Recursively make parent directories.
+ # $(<:P) = $(<)'s parent, & we recurse until root
+
+ s = $(<:P) ;
+
+ if $(NT)
+ {
+ switch $(s)
+ {
+ case *: : s = ;
+ case *:\\ : s = ;
+ }
+ }
+
+ if $(s) && $(s) != $(<)
+ {
+ Depends $(<) : $(s) ;
+ MkDir $(s) ;
+ }
+ else if $(s)
+ {
+ NOTFILE $(s) ;
+ }
+ }
+}
+
+actions MkDir1
+{
+ mkdir "$(<)"
+}
+
+actions piecemeal together existing Clean
+{
+ $(RM) "$(>)"
+}
+
+rule copy
+{
+}
+
+
+actions copy
+{
+ $(CP) "$(>)" "$(<)"
+}
+
+# Cause creation of response file, containing the sources in 'sources'
+# All the targets in 'targets' will depend on response file, and response
+# file will be created before the targets are built.
+rule response-file ( targets + : sources * : the-response-file : properties * )
+{
+ # Manufacture a fake target for response file.
+ # If response file is in targets, we're in trouble.
+ # The actions for response file are already generated, and bjam thinks it's
+ # created. So setting dependency on response file will not help to create
+ # it before other targets. So, we need another target.
+
+ local g = [ utility.ungrist $(the-response-file:G) ] ;
+ local rsp = $(the-response-file:G=$(g)-rsp) ;
+ LOCATE on $(rsp) = [ on $(the-response-file) return $(LOCATE) ] ;
+ DEPENDS $(targets) : $(rsp) ;
+ # Cause RSP to be recreated if sources are out-of-date.
+ DEPENDS $(rsp) : $(sources) ;
+
+ # Add libraries from <library> property to the list of sources.
+ local libraries ;
+ for local p in $(properties)
+ {
+ if $(p:G) = <library-file> &&
+ ! [ type.is-derived [ $(p:G=).type ] SHARED_LIB ]
+ {
+ libraries += $(p:G=) ;
+ }
+ }
+ # Get real jam targets
+ local xlibraries ;
+ for local l in $(libraries)
+ {
+ xlibraries += [ $(l).actualize ] ;
+ }
+
+ sources += $(xlibraries) ;
+
+ response-file-1 $(rsp) : $(sources[1]) ;
+ if $(sources[2-])
+ {
+ response-file-2 $(rsp) : $(sources[2-]) ;
+ }
+
+ print.output $(rsp) ;
+ print.text [ utility.apply-default-suffix .lib :
+ [ on $(targets[1])
+ return "$(LIBRARY_OPTION)$(FINDLIBS_ST)"
+ "$(LIBRARY_OPTION)$(FINDLIBS_SA)"
+ ] ] ;
+}
+
+# response-file generation is broken up into two phases, the first of
+# which overwrites any existing file and the second of which appends
+# to the file, piecemeal, so that no command-line is too long.
+actions quietly response-file-1
+{
+ echo "$(>)" > "$(<)"
+}
+
+actions quietly piecemeal response-file-2
+{
+ echo "$(>)" >> "$(<)"
+}
+
Added: boost-jam/boost-build/branches/upstream/current/tools/como-linux.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/como-linux.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/como-linux.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,98 @@
+# 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.
+
+# The following #// line will be used by the regression test table generation
+# program as the column heading for HTML tables. Must not include version number.
+#//<a href="http://www.comeaucomputing.com/">Comeau<br>C++</a>
+
+import toolset ;
+import feature ;
+import toolset : flags ;
+import common ;
+
+import unix ;
+import como ;
+feature.extend-subfeature toolset como : platform : linux ;
+
+toolset.inherit-generators como-linux
+ <toolset>como <toolset-como:platform>linux : unix ;
+toolset.inherit-flags como-linux : unix ;
+toolset.inherit-rules como-linux : gcc ;
+
+generators.register-c-compiler como-linux.compile.c++ : CPP : OBJ
+ : <toolset>como <toolset-como:platform>linux ;
+generators.register-c-compiler como-linux.compile.c : C : OBJ
+ : <toolset>como <toolset-como:platform>linux ;
+
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters como-linux
+ : version $(version) ] ;
+
+ command = [ common.get-invocation-command como-linux : como
+ : $(command) ] ;
+
+ common.handle-options como-linux : $(condition) : $(command) : $(options) ;
+}
+
+flags como-linux C++FLAGS <exception-handling>off : --no_exceptions ;
+flags como-linux C++FLAGS <exception-handling>on : --exceptions ;
+
+flags como-linux CFLAGS <inlining>off : --no_inlining ;
+flags como-linux CFLAGS <inlining>on <inlining>full : --inlining ;
+
+flags como-linux CFLAGS <optimization>off : -O0 ;
+flags como-linux CFLAGS <optimization>speed : -O3 ;
+flags como-linux CFLAGS <optimization>space : -Os ;
+
+flags como-linux CFLAGS <debug-symbols>on : -g ;
+flags como-linux LINKFLAGS <debug-symbols>on : -g ;
+
+flags como-linux FINDLIBS : m ;
+flags como-linux FINDLIBS : rt ;
+
+flags como-linux CFLAGS <cflags> ;
+flags como-linux C++FLAGS <cxxflags> ;
+flags como-linux DEFINES <define> ;
+flags como-linux UNDEFS <undef> ;
+flags como-linux HDRS <include> ;
+flags como-linux STDHDRS <sysinclude> ;
+flags como-linux LINKFLAGS <linkflags> ;
+flags como-linux ARFLAGS <arflags> ;
+
+flags como-linux.link LIBRARIES <library-file> ;
+flags como-linux.link LINKPATH <library-path> ;
+flags como-linux.link FINDLIBS-ST <find-static-library> ;
+flags como-linux.link FINDLIBS-SA <find-shared-library> ;
+
+flags como-linux.link RPATH <dll-path> ;
+flags como-linux.link RPATH_LINK <xdll-path> ;
+
+
+actions link bind LIBRARIES
+{
+ $(CONFIG_COMMAND) $(LINKFLAGS) -o "$(<[1])" "$(>)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" "$(LIBRARIES)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) 2>&1
+}
+
+actions link.dll bind LIBRARIES
+{
+ $(CONFIG_COMMAND) $(LINKFLAGS) -shared -o "$(<[1])" "$(>)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" "$(LIBRARIES)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) 2>&1
+}
+
+actions compile.c
+{
+ $(CONFIG_COMMAND) -c --c99 --long_long -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -o "$(<)" "$(>)" 2>&1
+}
+
+actions compile.c++
+{
+ $(CONFIG_COMMAND) -tused -c --long_long -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(C++FLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -o "$(<)" "$(>)" 2>&1
+}
+
+actions archive
+{
+ ar rcu $(<) $(>)
+}
+
Added: boost-jam/boost-build/branches/upstream/current/tools/como-win.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/como-win.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/como-win.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,122 @@
+# (C) Copyright David Abrahams 2001.
+# (C) Copyright MetaCommunications, Inc. 2004.
+
+# 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)
+
+# The following #// line will be used by the regression test table generation
+# program as the column heading for HTML tables. Must not include version number.
+#//<a href="http://www.comeaucomputing.com/">Comeau<br>C++</a>
+
+import common ;
+import como ;
+import feature ;
+import generators ;
+import toolset : flags ;
+
+feature.extend-subfeature toolset como : platform : win ;
+
+# Initializes the Comeau toolset for windows.
+# The command is the command which invokes the compiler.
+# You should either set environment variable COMO_XXX_INCLUDE where
+# XXX is the used backed (as described in documentation), or pass
+# that as part of command, e.g:
+#
+# using como-win : 4.3 : "set COMO_BCC_INCLUDE=C:/include &&" como.exe ;
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters como-win
+ : version $(version) ] ;
+
+ command = [ common.get-invocation-command como-win : como.exe :
+ $(command) ] ;
+
+ common.handle-options como-win : $(condition) : $(command) : $(options) ;
+}
+
+generators.register-c-compiler como-win.compile.c++ : CPP : OBJ
+ : <toolset>como <toolset-como:platform>win ;
+generators.register-c-compiler como-win.compile.c : C : OBJ
+ : <toolset>como <toolset-como:platform>win ;
+
+generators.register-linker como-win.link
+ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB
+ : EXE RSP
+ : <toolset>como <toolset-como:platform>win ;
+# Note that status of shared libraries support is not clear, so we don't
+# define the link.dll generator.
+generators.register-composing como-winc.archive
+ : OBJ : STATIC_LIB RSP
+ : <toolset>como <toolset-como:platform>win ;
+
+flags como-win C++FLAGS <exception-handling>off : --no_exceptions ;
+flags como-win C++FLAGS <exception-handling>on : --exceptions ;
+
+flags como-win CFLAGS <inlining>off : --no_inlining ;
+flags como-win CFLAGS <inlining>on <inlining>full : --inlining ;
+
+# The following seems to be VC-specific options. At least,
+# when I uncomment then, Comeau with bcc as backend reports
+# that bcc32 invocation.
+#
+#flags como-win CFLAGS <debug-symbols>on : /Zi ;
+#flags como-win CFLAGS <optimization>off : /Od ;
+
+flags como-win CFLAGS <cflags> ;
+flags como-win CFLAGS : -D_WIN32 ; # make sure that we get the Boost Win32 platform config header.
+flags como-win CFLAGS <threading>multi : -D_MT ; # make sure that our config knows that threading is on.
+flags como-win C++FLAGS <cxxflags> ;
+flags como-win DEFINES <define> ;
+flags como-win UNDEFS <undef> ;
+flags como-win HDRS <include> ;
+flags como-win SYSHDRS <sysinclude> ;
+flags como-win LINKFLAGS <linkflags> ;
+flags como-win ARFLAGS <arflags> ;
+flags como-win NO_WARN <no-warn> ;
+
+#flags como-win STDHDRS : $(COMO_INCLUDE_PATH) ;
+#flags como-win STDLIB_PATH : $(COMO_STDLIB_PATH)$(SLASH) ;
+
+flags como-win LIBPATH <library-path> ;
+flags como-win LIBRARIES <library-file> ;
+flags como-win FINDLIBS <find-shared-library> ;
+flags como-win FINDLIBS <find-static-library> ;
+
+#### Link ####
+
+rule link ( targets + : sources * : properties * )
+{
+ common.response-file $(targets) : $(sources) : $(targets[2])
+ : $(properties) ;
+}
+
+# for como, we repeat all libraries so that dependencies are always resolved
+actions link bind LIBRARIES
+{
+ $(CONFIG_COMMAND) --no_version --no_prelink_verbose $(LINKFLAGS) -o "$(<[1]:S=)" @"$(<[2])" "$(LIBRARIES)" "$(FINDLIBS:S=.lib)"
+}
+
+actions compile.c
+{
+ $(CONFIG_COMMAND) -c --c99 -e5 --no_version --display_error_number --diag_suppress=9,21,161,748,940,962 -U$(UNDEFS) -D$(DEFINES) $(WARN) $(CFLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -I"$(SYSHDRS)" -o "$(<:D=)" "$(>)"
+}
+
+actions compile.c++
+{
+ $(CONFIG_COMMAND) -c -e5 --no_version --no_prelink_verbose --display_error_number --long_long --diag_suppress=9,21,161,748,940,962 -D__STL_LONG_LONG -U$(UNDEFS) -D$(DEFINES) $(WARN) $(CFLAGS) $(C++FLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -I"$(SYSHDRS)" -o "$(<)" "$(>)"
+}
+
+#### Archive ####
+
+rule archive ( targets + : sources * : properties * )
+{
+ common.response-file $(targets) : $(sources) : $(targets[2]) : $(properties) ;
+}
+
+actions updated together piecemeal archive
+{
+ $(CONFIG_COMMAND) --no_version --no_prelink_verbose --prelink_object @"$(>)"
+ lib $(ARFLAGS) /nologo /out:"$(<:S=.lib)" @"$(>)"
+}
+
Added: boost-jam/boost-build/branches/upstream/current/tools/como.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/como.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/como.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,30 @@
+# Copyright Vladimir Prus 2004.
+# 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)
+
+# This is a generic 'intel' toolset. Depending on the current
+# system, it forwards either to 'intel-linux' or 'intel-win'
+# modules.
+
+import feature ;
+import os ;
+import toolset ;
+
+feature.extend toolset : como ;
+feature.subfeature toolset como : platform : : propagated link-incompatible ;
+
+rule init ( * : * )
+{
+ if [ os.name ] = LINUX
+ {
+ toolset.using como-linux :
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+ else
+ {
+ toolset.using como-win :
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/tools/cw.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/cw.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/cw.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,234 @@
+# Copyright (C) Reece H Dunn 2004
+# 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)
+
+# based on the msvc.jam toolset
+
+import property ;
+import generators ;
+import os ;
+import type ;
+import toolset : flags ;
+import errors : error ;
+import feature : feature get-values ;
+import path ;
+import sequence : unique ;
+import common ;
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+
+feature.extend toolset : cw ;
+
+rule init ( version ? : command * : options * )
+{
+ # TODO: fix the $(command[1]) = $(compiler) issue
+
+ setup = [ get-values <setup> : $(options) ] ;
+ setup ?= cwenv.bat ;
+ compiler = [ get-values <compiler> : $(options) ] ;
+ compiler ?= mwcc ;
+ linker = [ get-values <linker> : $(options) ] ;
+ linker ?= mwld ;
+
+ local condition = [ common.check-init-parameters cw :
+ version $(version) ] ;
+
+ command = [ common.get-invocation-command cw : mwcc.exe : $(command) :
+ [ default-paths $(version) ] ] ;
+
+ common.handle-options cw : $(condition) : $(command) : $(options) ;
+
+ if $(command)
+ {
+ command = [ common.get-absolute-tool-path $(command[-1]) ] ;
+ }
+ local root = $(command) ;
+
+ setup = $(root)\\$(setup) ;
+
+ # map the batch file in setup so it can be executed
+
+ setup = "call \""$(setup)"\" > nul " ;
+
+ if [ os.name ] = NT
+ {
+ setup = $(setup)"
+" ;
+ }
+ else
+ {
+ setup = "cmd /S /C "$(setup)" \"&&\" " ;
+ }
+
+ # bind the setup command to the tool so it can be executed before the
+ # command
+
+ local prefix = $(setup) ;
+
+ flags cw.compile .CC $(condition) : $(prefix)$(compiler) ;
+ flags cw.link .LD $(condition) : $(prefix)$(linker) ;
+ flags cw.archive .LD $(condition) : $(prefix)$(linker) ;
+}
+
+rule default-paths ( version ? ) # FIXME
+{
+ local possible-paths ;
+ local ProgramFiles = [ common.get-program-files-dir ] ;
+
+ # TODO: add support for cw8 and cw9 detection
+
+ local version-6-path = $(ProgramFiles)"\\Metrowerks\\CodeWarrior" ;
+ possible-paths += $(version-6-path) ;
+
+ # perform post-processing
+
+ possible-paths
+ = $(possible-paths)"\\Other Metrowerks Tools\\Command Line Tools" ;
+
+ possible-paths += [ modules.peek : PATH Path path ] ;
+
+ return $(possible-paths) ;
+}
+
+## declare generators
+
+generators.register-c-compiler cw.compile.c++ : CPP : OBJ : <toolset>cw ;
+generators.register-c-compiler cw.compile.c : C : OBJ : <toolset>cw ;
+
+generators.register-linker cw.link
+ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB
+ : EXE RSP
+ : <toolset>cw
+ ;
+generators.register-linker cw.link.dll
+ : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB
+ : SHARED_LIB IMPORT_LIB RSP
+ : <toolset>cw
+ ;
+
+generators.register-composing cw.archive
+ : OBJ
+ : STATIC_LIB RSP
+ : <toolset>cw
+ ;
+
+## compilation phase
+
+flags cw WHATEVER <toolset-cw:version> ;
+
+flags cw.compile CFLAGS <debug-symbols>on : -g ;
+flags cw.compile CFLAGS <optimization>off : -O0 ;
+flags cw.compile CFLAGS <optimization>speed : -O4,p ;
+flags cw.compile CFLAGS <optimization>space : -O4,s ;
+flags cw.compile CFLAGS <inlining>off : -inline off ;
+flags cw.compile CFLAGS <inlining>on : -inline on ;
+flags cw.compile CFLAGS <inlining>full : -inline all ;
+flags cw.compile CFLAGS <exception-handling>off : -Cpp_exceptions off ;
+flags cw.compile CFLAGS <rtti>off : -RTTI off ;
+
+flags cw.compile USER_CFLAGS <cflags> : ;
+flags cw.compile.c++ USER_CFLAGS <cxxflags> : ;
+
+flags cw.compile DEFINES <define> ;
+flags cw.compile UNDEFS <undef> ;
+flags cw.compile INCLUDES <include> ;
+
+actions compile.c
+{
+ $(.CC) -c -cwd include -lang c -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(USER_CFLAGS) -I- -I"$(INCLUDES)" -o "$(<)" "$(>)"
+}
+actions compile.c++
+{
+ $(.CC) -c -cwd include -lang c++ -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(USER_CFLAGS) -I- -I"$(INCLUDES)" -o "$(<)" "$(>)"
+}
+
+## linking phase
+
+flags cw.link DEF_FILE <def-file> ;
+
+flags cw LINKFLAGS <debug-symbols>on : -g ;
+flags cw LINKFLAGS <user-interface>console : -subsystem console ;
+flags cw LINKFLAGS <user-interface>gui : -subsystem windows ;
+flags cw LINKFLAGS <user-interface>wince : -subsystem wince ;
+flags cw LINKFLAGS <user-interface>native : -subsystem native ;
+flags cw LINKFLAGS <user-interface>auto : -subsystem auto ;
+
+flags cw LINKFLAGS <main-target-type>LIB/<link>static : -library ;
+flags cw LINKFLAGS <main-target-type>LIB/<link>shared : -shared ;
+
+toolset.flags cw.link USER_LINKFLAGS <linkflags> ;
+toolset.flags cw.link LINKPATH <library-path> ;
+
+if [ os.name ] in NT
+{
+ rule link ( targets + : sources * : properties * )
+ {
+ common.response-file $(targets) : $(sources) : $(targets[2])
+ : $(properties) ;
+ }
+
+ rule link.dll ( targets + : sources * : properties * )
+ {
+ common.response-file $(targets) : $(sources) : $(targets[3])
+ : $(properties) ;
+ DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
+ }
+
+ rule archive ( targets + : sources * : properties * )
+ {
+ common.response-file $(targets) : $(sources) : $(targets[2])
+ : $(properties) ;
+ }
+
+ actions archive
+ {
+ if exist "$(<[1])" DEL "$(<[1])"
+ $(.LD) -library -o "$(<[1])" @"$(<[2])"
+ }
+}
+else # cygwin
+{
+ rule link ( targets + : sources * : properties * )
+ {
+ common.response-file $(targets) : $(sources) : $(targets[2])
+ : $(properties) ;
+ }
+
+ rule link.dll ( targets + : sources + : properties * )
+ {
+ common.response-file $(targets) : $(sources) : $(targets[3])
+ : $(properties) ;
+ .cygpath = "cygpath -d " ;
+ DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
+ }
+
+ rule archive ( targets + : sources * : properties * )
+ {
+ common.response-file $(targets) : $(sources) : $(targets[2])
+ : $(properties) ;
+ }
+
+ actions archive
+ {
+ _bbv2_out_="$(<)"
+ if test -f "$_bbv2_out_" ; then
+ _bbv2_existing_="$(<:W)"
+ fi
+ $(.LD) -library -o "$(<:W)" $_bbv2_existing_ @"$(>:W)"
+ }
+}
+
+actions link bind DEF_FILE
+{
+ $(.LD) -o "$(<[1]:W)" -L"$(LINKPATH)" $(LINKFLAGS) $(USER_LINKFLAGS) @"$(<[2]:W)"
+}
+
+actions link.dll bind DEF_FILE
+{
+ $(.LD) -o "$(<[1]:W)" -implib "$(<[2]:W)" -L"$(LINKPATH)" $(LINKFLAGS) -f "$(DEF_FILE)" $(USER_LINKFLAGS) @"$(<[3]:W)"
+}
+
Added: boost-jam/boost-build/branches/upstream/current/tools/darwin.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/darwin.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/darwin.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,68 @@
+# Copyright (C) Christopher Currie 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.
+
+# Please see http://article.gmane.org/gmane.comp.lib.boost.build/3389/
+# for explanation why it's a separate toolset.
+
+import feature : feature ;
+import toolset : flags ;
+import type ;
+import common ;
+
+toolset.register darwin ;
+import gcc ;
+toolset.inherit-generators darwin : gcc ;
+toolset.inherit-rules darwin : gcc ;
+toolset.inherit-flags darwin : gcc ;
+
+# No additional initialization should be necessary
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters darwin : version $(version) ] ;
+ local command = [ common.get-invocation-command darwin : g++ : $(command) ] ;
+
+ common.handle-options darwin : $(condition) : $(command) : $(options) ;
+
+ gcc.init-link-flags darwin darwin $(condition) ;
+}
+
+# Darwin has a different shared library suffix
+type.set-generated-target-suffix SHARED_LIB : <toolset>darwin : dylib ;
+# we need to be able to tell the type of .dylib files
+type.register-suffixes dylib : SHARED_LIB ;
+
+feature framework : : free ;
+
+flags darwin.compile OPTIONS <link>shared : -dynamic ;
+flags darwin.compile OPTIONS : -Wno-long-double -no-cpp-precomp ;
+flags darwin.compile.c++ OPTIONS : -fcoalesce-templates ;
+
+flags darwin.link FRAMEWORK <framework> ;
+
+# This is flag is useful for debugging the link step
+# uncomment to see what libtool is doing under the hood
+# flags darwin.link.dll OPTIONS : -Wl,-v ;
+
+actions link bind LIBRARIES
+{
+ $(CONFIG_COMMAND) $(ST_OPTIONS) -L"$(LINKPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) -framework$(_)$(FRAMEWORK) $(OPTIONS)
+}
+
+rule link.dll
+{
+ _ on $(<) = " " ;
+}
+
+actions link.dll bind LIBRARIES
+{
+ $(CONFIG_COMMAND) -dynamiclib -L"$(LINKPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) -framework$(_)$(FRAMEWORK) $(OPTIONS)
+}
+
+actions piecemeal archive
+{
+ ar -c -r -s $(ARFLAGS) "$(<:T)" "$(>:T)"
+}
+
Added: boost-jam/boost-build/branches/upstream/current/tools/doxygen.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/doxygen.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/doxygen.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,178 @@
+# Copyright (C) 2003 Doug Gregor. 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.
+
+# This module defines rules to handle generation of BoostBook XML
+# from Doxygen XML output.
+
+import "class" : new ;
+import targets ;
+import feature ;
+import property ;
+import generators ;
+import boostbook ;
+import type ;
+import path ;
+import print ;
+import regex ;
+import stage ;
+import project ;
+
+feature.feature doxygen:param : : free ;
+feature.feature prefix : : free ;
+feature.feature reftitle : : free ;
+
+type.register DOXYFILE : doxyfile ; # Doxygen input file
+type.register DOXYGEN_XML_MULTIFILE : : XML ; # Doxygen XML multi-file output
+type.register DOXYGEN_XML : doxygen : XML : main ; # Doxygen XML output
+
+# Initialize the Doxygen module. Parameters are:
+# name: the name of the 'doxygen' executable. If not specified, the name
+# 'doxygen' will be used
+rule init ( name ? )
+{
+ if ! $(.initialized)
+ {
+ .initialized = true ;
+
+ if $(name)
+ {
+ .doxygen = $(name) ;
+ }
+
+ generators.register-composing doxygen.headers-to-doxyfile : H HPP : DOXYFILE ;
+ generators.register-standard doxygen.run : DOXYFILE : DOXYGEN_XML_MULTIFILE ;
+ generators.register-standard doxygen.xml-to-boostbook : DOXYGEN_XML : BOOSTBOOK ;
+
+ if ! [ boostbook.xsl-dir ]
+ {
+ ECHO "warning: Doxygen initialization: Boost.Build stylesheets not found " ;
+ ECHO "warning: Generation of single XML file won't be possible. " ;
+ }
+ else
+ {
+ generators.register-standard doxygen.collect : DOXYGEN_XML_MULTIFILE : DOXYGEN_XML ;
+ }
+
+ IMPORT $(__name__) : doxygen : : doxygen ;
+ }
+}
+
+rule name ( )
+{
+ return $(.doxygen) ;
+}
+
+# Runs Doxygen on the given Doxygen configuration file (the source) to
+# generate Doxygen XML (in multiple files). The output is dumped
+# according to the settings in the Doxygen configuration file, not
+# according to the target! Because of this, we essentially "touch" the
+# target file, in effect making it look like we've really written
+# something useful to it. Anyone that uses this action must deal with
+# this behavior.
+actions doxygen-action
+{
+ "$(NAME:E=doxygen)" $(>) ;
+ echo "Stamped" > "$(<)"
+}
+
+# Generates a doxygen configuration file (doxyfile) given a set of C++
+# sources anda property list that may contain <doxygen:param>
+# features.
+rule headers-to-doxyfile ( target : sources * : properties * )
+{
+ local text "# Generated by Boost.Build version 2" ;
+
+ # Translate <doxygen:param> into command line flags.
+ for local param in [ feature.get-values <doxygen:param> : $(properties) ]
+ {
+ local namevalue = [ regex.match ([^=]*)=(.*) : $(param) ] ;
+ text += "$(namevalue[1]) = $(namevalue[2])" ;
+ }
+
+ local headers = "" ;
+ for local source in $(sources:G=)
+ {
+ headers = "$(headers) $(source)" ;
+ }
+
+ text += "GENERATE_HTML = NO" ;
+ text += "GENERATE_LATEX = NO" ;
+ text += "GENERATE_XML = YES" ;
+ text += "INPUT = $(headers) " ;
+ print.output $(target) plain ;
+ print.text $(text) : true ;
+}
+
+# Run Doxygen. See doxygen-action for a description of the strange
+# properties of this rule
+rule run ( target : source : properties * )
+{
+ doxygen-action $(target) : $(source) ;
+ NAME on $(target) = $(.doxygen) ;
+}
+
+# Collect the set of Doxygen XML files into a single XML source file
+# that can be handled by an XSLT processor. The source is completely
+# ignored (see doxygen-action), because this action picks up the
+# Doxygen XML index file xml/index.xml. This is because we can't teach
+# Doxygen to act like a NORMAL program and take a "-o output.xml"
+# argument (grrrr). The target of the collection will be a single
+# Doxygen XML file.
+rule collect ( target : source : properties * )
+{
+ local collect-xsl-dir = [ path.native
+ [ path.join [ boostbook.xsl-dir ] doxygen collect ]
+ ] ;
+ local collect-path = [ path.join [ path.pwd ] xml ] ;
+ local real-source = [ path.native xml/index.xml ] ;
+ NOTFILE $(real-source) ;
+ xslt $(target) : $(real-source) $(collect-xsl-dir:S=.xsl)
+ : <xsl:param>doxygen.xml.path=$(collect-path)
+ ;
+}
+
+# Translate Doxygen XML into BoostBook
+rule xml-to-boostbook ( target : source : properties * )
+{
+ local xsl-dir = [ boostbook.xsl-dir ] ;
+ local d2b-xsl = [ path.native
+ [ path.join [ boostbook.xsl-dir ] doxygen
+ doxygen2boostbook.xsl ] ] ;
+
+ local xslt-properties = $(properties) ;
+ for local prefix in [ feature.get-values <prefix> : $(properties) ]
+ {
+ xslt-properties += "<xsl:param>boost.doxygen.header.prefix=$(prefix)" ;
+ }
+ for local title in [ feature.get-values <reftitle> : $(properties) ]
+ {
+ xslt-properties += "<xsl:param>boost.doxygen.reftitle=\"$(title)\"" ;
+ }
+
+ xslt $(target) : $(source) $(d2b-xsl) : $(xslt-properties) ;
+}
+
+# User-level rule to generate BoostBook XML from a set of headers via Doxygen.
+rule doxygen ( target-name : sources * : requirements * : default-build * )
+{
+ local project = [ project.current ] ;
+
+ local doxyfile = [
+ new typed-target $(target-name) : $(project) : BOOSTBOOK
+ : [ targets.main-target-sources $(sources) : $(target-name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+
+ targets.main-target-alternative $(doxyfile) ;
+
+ targets.main-target-alternative
+ [ new stage-target-class $(target-name:S=.xml) : $(project)
+ : [ $(doxyfile).name ]
+ : [ targets.main-target-requirements $(requirements) <location>. : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+}
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/tools/fop.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/fop.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/fop.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,40 @@
+# Copyright (C) 2003 Doug Gregor. 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.
+
+# This module defines rules to handle generation of PDF and PostScript files
+# from XSL Formatting Objects via Apache FOP
+
+import generators ;
+
+generators.register-standard fop.fo-to-print : FO : PDF ;
+generators.register-standard fop.fo-to-print : FO : PS ;
+
+rule init ( fop-dir ? : java-home ? )
+{
+ if ! $(fop-dir)
+ {
+ fop-dir = [ modules.peek : FOP_DIR ] ;
+ }
+
+ if ! $(.initialized)
+ {
+ .initialized = true ;
+ .fop-dir = $(fop-dir) ;
+ .java-home = $(java-home) ;
+ }
+}
+
+rule fo-to-print ( target : source : properties * )
+{
+ JAVA_HOME on $(target) = $(.java-home) ;
+ FOP_DIR on $(target) = $(.fop-dir) ;
+ fop $(target) : $(source) ;
+}
+
+actions fop
+{
+ JAVA_HOME=$(JAVA_HOME) $(FOP_DIR)/fop.sh $(>) $(<)
+}
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/tools/gcc.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/gcc.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/gcc.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,335 @@
+# Copyright (c) 2001 David Abrahams.
+# Copyright (c) 2002-2003 Rene Rivera.
+# Copyright (c) 2002-2003 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import toolset : flags ;
+import property ;
+import generators ;
+import os ;
+import type ;
+import feature ;
+import "class" : new ;
+import set ;
+import common ;
+import errors ;
+
+feature.extend toolset : gcc ;
+
+import unix ;
+toolset.inherit-generators gcc : unix : unix.link unix.link.dll ;
+toolset.inherit-flags gcc : unix ;
+toolset.inherit-rules gcc : unix ;
+
+
+
+# Make the "o" suffix used for gcc toolset on all
+# platforms
+type.set-generated-target-suffix OBJ : <toolset>gcc : o ;
+type.set-generated-target-suffix STATIC_LIB : <toolset>gcc : a ;
+
+
+# Initializes the gcc toolset for the given version.
+# If necessary, command may be used to specify where the compiler
+# is located.
+# The parameter 'options' is a space-delimited list of options, each
+# one being specified as <option-name>option-value. Valid option names
+# are: cxxflags, linkflags and linker-type. Accepted values for linker-type
+# are gnu and sun, gnu being the default.
+# Example:
+# using gcc : 3.4 : : <cxxflags>foo <linkflags>bar <linker-type>sun ;
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters gcc : version $(version) ] ;
+
+ local command = [ common.get-invocation-command gcc : g++ : $(command) ] ;
+
+ common.handle-options gcc : $(condition) : $(command) : $(options) ;
+
+ local linker = [ feature.get-values <linker-type> : $(options) ] ;
+ if ! $(linker) {
+ linker = gnu ;
+ }
+ init-link-flags gcc $(linker) $(condition) ;
+}
+
+if [ os.name ] = NT
+{
+ # This causes single-line command invocation to not go through
+ # .bat files, thus avoiding command-line length limitations
+ JAMSHELL = % ;
+}
+
+generators.register-c-compiler gcc.compile.c++ : CPP : OBJ : <toolset>gcc ;
+generators.register-c-compiler gcc.compile.c : C : OBJ : <toolset>gcc ;
+
+
+# Declare flags and action for compilation
+flags gcc.compile OPTIONS <optimization>off : -O0 ;
+flags gcc.compile OPTIONS <optimization>speed : -O3 ;
+flags gcc.compile OPTIONS <optimization>space : -Os ;
+
+flags gcc.compile OPTIONS <inlining>off : -fno-inline ;
+flags gcc.compile OPTIONS <inlining>on : -Wno-inline ;
+flags gcc.compile OPTIONS <inlining>full : -finline-functions -Wno-inline ;
+
+flags gcc.compile OPTIONS <debug-symbols>on : -g ;
+flags gcc.compile OPTIONS <profiling>on : -pg ;
+# On cygwin and mingw, gcc generates position independent code by default,
+# and warns if -fPIC is specified. This might not be the right way
+# of checking if we're using cygwin. For example, it's possible
+# to run cygwin gcc from NT shell, or using crosscompiling.
+# But we'll solve that problem when it's time. In that case
+# we'll just add another parameter to 'init' and move this login
+# inside 'init'.
+if [ os.name ] != CYGWIN && [ os.name ] != NT
+{
+ flags gcc.compile OPTIONS <link>shared/<main-target-type>LIB : -fPIC ;
+}
+if [ os.name ] != NT
+{
+ HAVE_SONAME = "" ;
+}
+
+
+
+flags gcc.compile OPTIONS <cflags> ;
+flags gcc.compile.c++ OPTIONS <cxxflags> ;
+flags gcc.compile DEFINES <define> ;
+flags gcc.compile INCLUDES <include> ;
+
+rule compile.c++
+{
+ # Some extensions are compiled as C++ by default. For others, we need
+ # to pass -x c++.
+ # We could always pass -x c++ but distcc does not work with it.
+ if ! $(>:S) in .cc .cp .cxx .cpp .c++ .C
+ {
+ LANG on $(<) = "-x c++" ;
+ }
+}
+
+
+actions compile.c++
+{
+ "$(CONFIG_COMMAND)" $(LANG) -Wall -ftemplate-depth-100 $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+rule compile.c
+{
+ # If we use the name g++ then default file suffix -> language mapping
+ # does not work. So have to pass -x option. Maybe, we can work around this
+ # by allowing the user to specify both C and C++ compiler names.
+ #if $(>:S) != .c
+ #{
+ LANG on $(<) = "-x c" ;
+ #}
+}
+
+
+actions compile.c
+{
+ "$(CONFIG_COMMAND)" $(LANG) -Wall $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+# The class which check that we don't try to use
+# the <link-runtime>static property while creating or using shared library,
+# since it's not supported by gcc/libc.
+class gcc-linking-generator : unix-linking-generator
+{
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ if <link-runtime>static in [ $(property-set).raw ]
+ {
+ local m ;
+ if [ id ] = "gcc.link.dll"
+ {
+ m = "on gcc, DLL can't be build with <link-runtime>static" ;
+ }
+ if ! $(m) {
+ for local s in $(sources)
+ {
+ local type = [ $(s).type ] ;
+ if $(type) && [ type.is-derived $(type) SHARED_LIB ]
+ {
+ m = "on gcc, using DLLS together with the <link-runtime>static options is not possible " ;
+ }
+ }
+ }
+ if $(m)
+ {
+ errors.user-error $(m) :
+ "it's suggested to use <link-runtime>static together with the <link>static" ;
+ }
+
+ }
+
+ return [ unix-linking-generator.generated-targets
+ $(sources) : $(property-set) : $(project) $(name) ] ;
+ }
+}
+
+generators.register [ new gcc-linking-generator gcc.link : LIB OBJ : EXE
+ : <toolset>gcc ] ;
+
+generators.register [ new gcc-linking-generator gcc.link.dll : LIB OBJ : SHARED_LIB
+ : <toolset>gcc ] ;
+
+generators.override gcc.prebuilt : builtin.prebuilt ;
+
+
+
+# Declare flags for linking
+# First, the common flags
+flags gcc.link OPTIONS <debug-symbols>on : -g ;
+flags gcc.link OPTIONS <profiling>on : -pg ;
+flags gcc.link OPTIONS <linkflags> ;
+flags gcc.link LINKPATH <library-path> ;
+flags gcc.link FINDLIBS-ST <find-static-library> ;
+flags gcc.link FINDLIBS-SA <find-shared-library> ;
+flags gcc.link LIBRARIES <library-file> ;
+
+# For <link-runtime>static we made sure there are no dynamic libraries
+# in the link
+flags gcc.link OPTIONS <link-runtime>static : -static ;
+
+# Now, the vendor specific flags
+# The parameter linker can be either gnu or sun
+rule init-link-flags ( toolset linker condition )
+{
+ switch $(linker)
+ {
+ case gnu :
+ {
+ # Strip the binary when no debugging is needed.
+ # We use --strip-all flag as opposed to -s since icc
+ # (intel's compiler) is generally option-compatible with
+ # and inherits from gcc toolset, but does not support -s
+ flags $(toolset).link OPTIONS $(condition)/<debug-symbols>off : -Wl,--strip-all
+ : unchecked ;
+ flags $(toolset).link RPATH $(condition) : <dll-path> : unchecked ;
+ flags $(toolset).link RPATH_LINK $(condition) : <xdll-path> : unchecked ;
+ }
+ case darwin :
+ {
+ # we can't pass -s to ld unless we also pass -static
+ # so we removed -s completly from OPTIONS and add it
+ # to ST_OPTIONS
+ flags $(toolset).link ST_OPTIONS $(condition)/<debug-symbols>off : -s
+ : unchecked ;
+ flags $(toolset).link RPATH $(condition) : <dll-path> : unchecked ;
+ flags $(toolset).link RPATH_LINK $(condition) : <xdll-path> : unchecked ;
+ }
+
+ case sun :
+ {
+ flags $(toolset).link OPTIONS $(condition)/<debug-symbols>off : -Wl,-s
+ : unchecked ;
+ flags $(toolset).link RPATH $(condition) : <dll-path> : unchecked ;
+ # Solaris linker does not have a separate -rpath-link, but
+ # allows to use -L for the same purpose.
+ flags $(toolset).link LINKPATH $(condition) : <xdll-path> : unchecked ;
+
+ # This permits shared libraries with non-PIC code on Solaris
+ # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll,
+ # the following is not needed. Whether -fPIC should be hardcoded,
+ # is a separate question.
+ # AH, 2004/10/16: it is still necessary because some tests link
+ # against static libraries that were compiled without PIC.
+ flags $(toolset).link OPTIONS $(condition)/<link>shared : -mimpure-text
+ : unchecked ;
+ }
+ case * :
+ {
+ errors.user-error
+ "$(toolset) initialization: invalid linker '$(linker)'" :
+ "The value '$(linker)' specified for <linker> is not recognized." :
+ "Possible values are 'sun', 'gnu'" ;
+ }
+ }
+}
+
+# Declare actions for linking
+rule link ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+}
+
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-ST) -l$(FINDLIBS-SA) $(OPTIONS)
+}
+
+# Declare action for creating static libraries
+# The 'r' letter means to replace files in the archive
+# The 'u' letter means only outdated files in the archive
+# should be replaced.
+# The 'c' letter means suppresses warning in case the archive
+# does not exists yet. That warning is produced only on
+# some platforms, for whatever reasons.
+actions piecemeal archive
+{
+ ar ruc "$(<)" "$(>)"
+}
+
+
+rule link.dll ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+}
+
+# Differ from 'link' above only by -shared.
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -o "$(<)" $(HAVE_SONAME)-Wl,-h$(SPACE)-Wl,$(<[1]:D=) -shared "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-ST) -l$(FINDLIBS-SA) $(OPTIONS)
+}
+
+# Set up threading support. It's somewhat contrived, so perform it at the end,
+# to avoid cluttering other code.
+
+if [ os.on-windows ]
+{
+ flags gcc OPTIONS <threading>multi : -mthreads ;
+}
+else if [ modules.peek : UNIX ]
+{
+ switch [ modules.peek : JAMUNAME ]
+ {
+ case SunOS* :
+ {
+ flags gcc OPTIONS <threading>multi : -pthreads ;
+ flags gcc FINDLIBS-SA <threading>multi : rt ;
+ }
+ case BeOS :
+ {
+ # BeOS has no threading options, don't set anything here.
+ }
+ case *BSD :
+ {
+ flags gcc OPTIONS <threading>multi : -pthread ;
+ # there is no -lrt on BSD
+ }
+ case DragonFly :
+ {
+ flags gcc OPTIONS <threading>multi : -pthread ;
+ # there is no -lrt on BSD - DragonFly is a FreeBSD variant,
+ # which anoyingly doesn't say it's a *BSD.
+ }
+ case IRIX :
+ {
+ # gcc on IRIX does not support multi-threading, don't set anything here.
+ }
+ case HP_UX :
+ {
+ # gcc on HP-UX does not support multi-threading, don't set anything here
+ }
+ case * :
+ {
+ flags gcc OPTIONS <threading>multi : -pthread ;
+ flags gcc FINDLIBS-SA <threading>multi : rt ;
+ }
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/tools/gettext.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/gettext.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/gettext.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,222 @@
+# 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.
+
+# This module support GNU gettext internationalization utilities.
+#
+# It provides two main target rules: 'gettext.catalog', used for
+# creating machine-readable catalogs from translations files, and
+# 'gettext.update', used for update translation files from modified
+# sources.
+#
+# To add i18n support to your application you should follow these
+# steps.
+#
+# - Decide on a file name which will contain translations and
+# what main target name will be used to update it. For example::
+#
+# gettext.update update-russian : russian.po a.cpp my_app ;
+#
+# - Create the initial translation file by running::
+#
+# bjam update-russian
+#
+# - Edit russian.po. For example, you might change fields like LastTranslator.
+#
+# - Create a main target for final message catalog::
+#
+# gettext.catalog russian : russian.po ;
+#
+# The machine-readable catalog will be updated whenever you update
+# "russian.po". The "russian.po" file will be updated only on explicit
+# request. When you're ready to update translations, you should
+#
+# - Run::
+#
+# bjam update-russian
+#
+# - Edit "russian.po" in appropriate editor.
+#
+# The next bjam run will convert "russian.po" into machine-readable form.
+#
+# By default, translations are marked by 'i18n' call. The 'gettext.keyword'
+# feature can be used to alter this.
+
+
+import targets ;
+import property-set ;
+import virtual-target ;
+import "class" : new ;
+import project ;
+import type ;
+import generators ;
+import errors ;
+import feature : feature ;
+import toolset : flags ;
+import regex ;
+
+.path = "" ;
+
+# Initializes the gettext module.
+rule init ( path ? # Path where all tools are located. If not specified,
+ # they should be in PATH.
+ )
+{
+ if $(.initialized) && $(.path) != $(path)
+ {
+ errors.error "Attempt to reconfigure with different path" ;
+ }
+ .initialized = true ;
+ if $(path)
+ {
+ .path = $(path)/ ;
+ }
+}
+
+# Creates a main target 'name', which, when updated, will cause
+# file 'existing-translation' to be updated with translations
+# extracted from 'sources'. It's possible to specify main target
+# in sources --- it which case all target from dependency graph
+# of those main targets will be scanned, provided they are of
+# appropricate type. The 'gettext.types' feature can be used to
+# control the types.
+#
+# The target will be updated only if explicitly requested on the
+# command line.
+rule update ( name : existing-translation sources + : requirements * )
+{
+ local project = [ project.current ] ;
+
+ targets.main-target-alternative
+ [ new update-translations-class $(name) : $(project) :
+ $(existing-translation) $(sources)
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ ] ;
+ $(project).mark-target-as-explicit $(name) ;
+}
+
+
+# The human editable source, containing translation.
+type.register gettext.PO : po ;
+# The machine readable message catalog.
+type.register gettext.catalog : mo : : main ;
+# Intermediate type produce by extracting translations from
+# sources.
+type.register gettext.POT : pot ;
+
+# Identifies the keyword that should be used when scanning sources.
+# Default: i18n
+feature gettext.keyword : : free ;
+# Contains space-separated list of sources types which should be scanned.
+# Default: "C CPP"
+feature gettext.types : : free ;
+
+generators.register-standard gettext.compile : gettext.PO : gettext.catalog ;
+
+class update-translations-class : basic-target
+{
+ import regex : split ;
+
+ rule __init__ ( name : project : sources * : requirements )
+ {
+ basic-target.__init__ $(name) : $(project) : $(sources) : $(requirements)
+ : $(default-build) ;
+ }
+
+ rule construct ( source-targets * : property-set )
+ {
+ local types = [ $(property-set).get <gettext.types> ] ;
+ types ?= "C CPP" ;
+ types = [ regex.split $(types) " " ] ;
+ property-set = [ property-set.empty ] ;
+
+ if ! $(.constructed)
+ {
+ # First deterime the list of sources that must be scanned to
+ # messages.
+ local all-sources ;
+ for local s in $(source-targets[2-])
+ {
+ all-sources += [ virtual-target.traverse $(s) : : include-sources ] ;
+ }
+ local right-sources ;
+ for local s in $(all-sources)
+ {
+ if [ $(s).type ] in $(types)
+ {
+ right-sources += $(s) ;
+ }
+ }
+
+ if $(right-sources)
+ {
+ local new-messages = [ new file-target $(self.name) : gettext.POT : $(self.project) ] ;
+ local extract =
+ [ new action $(new-messages) : $(right-sources) : gettext.extract ] ;
+ $(new-messages).action $(extract) ;
+
+ local r = [ new notfile-target $(self.name) : $(self.project) ] ;
+ local a = [ new action $(r) : $(source-targets[1]) $(new-messages)
+ : gettext.update-po-dispatch ] ;
+ $(r).action $(a) ;
+ .constructed = [ virtual-target.register $(r) ] ;
+ }
+ else
+ {
+ errors.error "No source could be scanned by gettext tools" ;
+ }
+ }
+ return $(.constructed) ;
+ }
+}
+
+flags gettext.extract KEYWORD <gettext.keyword> ;
+actions extract
+{
+ $(.path)xgettext -k$(KEYWORD:E=i18n) -o $(<) $(>)
+}
+
+# Does realy updating of po file. The tricky part is that
+# we're actually updating one of the sources:
+# $(<) is the NOTFILE target we're updating
+# $(>[1]) is the PO file to be really updated.
+# $(>[2]) is the PO file created from sources.
+#
+# When file to be updated does not exist (during the
+# first run), we need to copy the file created from sources.
+# In all other cases, we need to update the file.
+rule update-po-dispatch
+{
+ NOCARE $(>[1]) ;
+ gettext.create-po $(<) : $(>) ;
+ gettext.update-po $(<) : $(>) ;
+ _ on $(<) = " " ;
+ ok on $(<) = "" ;
+ EXISTING_PO on $(<) = $(>[1]) ;
+}
+
+# Due to fancy interaction of existing and updated, this rule
+# can be called with with one source, in which case we copy
+# the lonely source into EXISTING_PO, or with two sources,
+# in which case the action body expands to nothing.
+# I'd really like to have "missing" action modifier.
+actions quietly existing updated create-po bind EXISTING_PO
+{
+ cp$(_)"$(>[1])"$(_)"$(EXISTING_PO)"$($(>[2]:E=ok))
+}
+
+actions updated update-po bind EXISTING_PO
+{
+ $(.path)msgmerge$(_)-U$(_)"$(EXISTING_PO)"$(_)"$(>[1])"
+}
+
+actions gettext.compile
+{
+ $(.path)msgfmt -o $(<) $(>)
+}
+
+IMPORT $(__name__) : update : : gettext.update ;
+
+
+
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/tools/intel-linux.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/intel-linux.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/intel-linux.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,65 @@
+# Copyright (c) 2003 Michael Stevens
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import toolset ;
+import feature ;
+import toolset : flags ;
+
+import intel ;
+import gcc ;
+import common ;
+import errors ;
+
+feature.extend-subfeature toolset intel : platform : linux ;
+
+toolset.inherit-generators intel-linux
+ <toolset>intel <toolset-intel:platform>linux : gcc ;
+toolset.inherit-rules intel-linux : gcc ;
+toolset.inherit-flags intel-linux : gcc
+ : <inlining>off <inlining>on <inlining>full <optimization>space ;
+
+# Initializes the intel-linux toolset
+# version in mandatory
+# name (default icc) is used to invoke the specified intellinux complier
+# compile and link options allow you to specify addition command line options for each version
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters intel-linux
+ : version $(version) ] ;
+
+ command = [ common.get-invocation-command intel-linux : icc
+ : $(command) : /opt/intel_cc_80/bin ] ;
+
+ common.handle-options intel-linux : $(condition) : $(command) : $(options) ;
+
+ gcc.init-link-flags intel-linux gnu $(condition) ;
+
+}
+
+flags intel-linux.compile OPTIONS <inlining>off : "-Ob0" ;
+flags intel-linux.compile OPTIONS <inlining>on : "-Ob1" ;
+flags intel-linux.compile OPTIONS <inlining>full : "-Ob2" ;
+flags intel-linux.compile OPTIONS <optimization>space : "-O1" ; # no specific space optimization flag in icc
+actions compile.c++
+{
+ "$(CONFIG_COMMAND)" -c -xc++ $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.c
+{
+ "$(CONFIG_COMMAND)" -c -xc $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(OPTIONS)
+}
+
+# Differ from 'link' above only by -shared.
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,-R$(SPACE)-Wl,"$(RPATH)" -o "$(<)" -Wl,-h$(SPACE)-Wl,$(<[1]:D=) -shared "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(OPTIONS)
+}
Added: boost-jam/boost-build/branches/upstream/current/tools/intel-win.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/intel-win.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/intel-win.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,127 @@
+# Copyright Vladimir Prus 2004.
+# 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)
+
+import toolset ;
+import feature ;
+import toolset : flags ;
+import os ;
+
+# This is needed because the rule we import here depend on 'common'
+# That's nasty.
+import common ;
+
+import intel ;
+
+feature.extend-subfeature toolset intel : platform : win ;
+
+import msvc ;
+toolset.inherit-generators intel-win <toolset>intel <toolset-intel:platform>win : msvc ;
+toolset.inherit-flags intel-win : msvc ;
+toolset.inherit-rules intel-win : msvc ;
+
+# Initializes the intel toolset for windows
+rule init ( version ? : # the compiler version
+ command * : # the command to invoke the compiler itself
+ options * # Additional option: <compatibility>
+ # either 'vc6', 'vc7', 'vc7.1'
+ # or 'native'(default).
+ )
+{
+ local compatibility =
+ [ feature.get-values <compatibility> : $(options) ] ;
+ local condition = [ common.check-init-parameters intel-win
+ : version $(version) : compatibility $(compatibility) ] ;
+
+ command = [ common.get-invocation-command intel-win : icc.exe :
+ $(command) ] ;
+
+ common.handle-options intel-win : $(condition) : $(command) : $(options) ;
+
+ local root = [ common.get-absolute-tool-path $(command[-1]) ] ;)
+
+ local setup ;
+ setup = $(root:D)/iclvars.bat ;
+ setup = "call \""$(setup)"\" > nul " ;
+
+ if [ os.name ] = NT
+ {
+ setup = $(setup)"
+" ;
+ }
+ else
+ {
+ setup = "cmd /S /C "$(setup)" \"&&\" " ;
+ }
+
+
+ flags intel-win.compile .CC $(condition) : $(setup)icl ;
+ flags intel-win.link .LD $(condition) : $(setup)xilink ;
+ flags intel-win.archive .LD $(condition) : $(setup)xilink ;
+
+ local m = [ MATCH (.).* : $(version) ] ;
+ local major = $(m[1]) ;
+
+ local C++FLAGS ;
+ # Reduce the number of spurious error messages
+ C++FLAGS += /Qwn5 /Qwd985 ;
+
+ # Enable ADL
+ C++FLAGS += -Qoption,c,--arg_dep_lookup ; #"c" works for C++, too
+
+ if $(major) > 5
+ {
+ C++FLAGS += /Zc:forScope ; # Add support for correct for loop scoping
+ }
+
+ # Add options recognized only by intel7
+ if $(major) >= 7
+ {
+ C++FLAGS += /Qansi_alias ;
+ }
+
+ if $(compatibility) = vc6
+ {
+ C++FLAGS +=
+ # Emulate VC6
+ /Qvc6
+
+ # no wchar_t support in vc6 dinkum library. Furthermore, in vc6
+ # compatibility-mode, wchar_t is not a distinct type from unsigned
+ # short
+ -DBOOST_NO_INTRINSIC_WCHAR_T
+ ;
+ }
+ else
+ {
+ if $(major) > 5
+ {
+ # Add support for wchar_t
+ C++FLAGS += /Zc:wchar_t
+ # Tell the dinkumware library about it.
+ -D_NATIVE_WCHAR_T_DEFINED
+ ;
+ }
+ }
+ if $(compatibility) && $(compatibility) != native
+ {
+ C++FLAGS += /Q$(base-vc) ;
+ }
+ else
+ {
+ C++FLAGS +=
+ -Qoption,cpp,--arg_dep_lookup
+ -Qoption,cpp,--const_string_literals
+ -Qoption,cpp,--new_for_init
+ -Qoption,cpp,--no_implicit_typename
+ -Qoption,cpp,--no_friend_injection
+ -Qoption,cpp,--no_microsoft_bugs
+ ;
+ }
+
+ flags intel-win CFLAGS $(condition) : $(C++FLAGS) ;
+
+}
+
+flags intel-win.link LIBRARY_OPTION <toolset>intel : "" ;
Added: boost-jam/boost-build/branches/upstream/current/tools/intel.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/intel.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/intel.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,30 @@
+# Copyright Vladimir Prus 2004.
+# 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)
+
+# This is a generic 'intel' toolset. Depending on the current
+# system, it forwards either to 'intel-linux' or 'intel-win'
+# modules.
+
+import feature ;
+import os ;
+import toolset ;
+
+feature.extend toolset : intel ;
+feature.subfeature toolset intel : platform : : propagated link-incompatible ;
+
+rule init ( * : * )
+{
+ if [ os.name ] = LINUX
+ {
+ toolset.using intel-linux :
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+ else
+ {
+ toolset.using intel-win :
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/tools/kylix.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/kylix.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/kylix.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,22 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+# Support for the Borland's Kylix command line compiler
+
+import toolset ;
+
+toolset.register kylix ;
+
+toolset.inherit kylix : borland ;
+
+COMPILER_NAME = bc++ ;
+LINKER_NAME = bc++ ;
+
+actions link bind LIBRARIES
+{
+ $(LINKER_NAME) $(OPTIONS) -q -L$(LINKPATH) -e$(<[1]) $(>) $(LIBRARIES) lib$(FINDLIBS-ST).a lib$(FINDLIBS-SA).so
+}
+
+
Added: boost-jam/boost-build/branches/upstream/current/tools/lex.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/lex.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/lex.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,34 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+import type ;
+import generators ;
+import feature ;
+import property ;
+
+
+feature.feature flex.prefix : : free ;
+type.register LEX : l ;
+type.register LEX++ : ll ;
+generators.register-standard lex.lex : LEX : C ;
+generators.register-standard lex.lex : LEX++ : CPP ;
+
+rule init ( )
+{
+}
+
+rule lex ( target : source : properties * )
+{
+ local r = [ property.select flex.prefix : $(properties) ] ;
+ if $(r)
+ {
+ PREFIX on $(<) = $(r:G=) ;
+ }
+}
+
+actions lex
+{
+ flex -P$(PREFIX) -o$(<) $(>)
+}
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/tools/make.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/make.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/make.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,70 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+# This module defines the 'make' main target rule.
+
+import targets ;
+import "class" : new ;
+import property ;
+import errors : error ;
+import type : type ;
+import regex ;
+import property-set ;
+import project ;
+
+class make-target-class : basic-target
+{
+ import type regex virtual-target ;
+ import "class" : new ;
+
+ rule __init__ ( name : project : sources * : requirements *
+ : make-rule + : default-build * )
+ {
+ basic-target.__init__ $(name) : $(project) : $(sources) : $(requirements)
+ : $(default-build) ;
+
+ self.make-rule = $(make-rule) ;
+ }
+
+ rule construct ( source-targets * : property-set )
+ {
+ local t = [ new file-target $(self.name:S=) : [ type.type $(self.name) ]
+ : $(self.project) ] ;
+ $(t).suffix [ regex.match .(.*) : $(self.name:S) ] ;
+ local a = [ new action $(t) : $(source-targets) : $(self.make-rule)
+ : $(property-set) ] ;
+ $(t).action $(a) ;
+ return [ virtual-target.register $(t) ] ;
+ }
+}
+
+# Declares the 'make' main target.
+rule make ( target-name : sources * : generating-rule + : requirements *
+ : caller ? )
+{
+ caller ?= [ project.current ] ;
+ caller-module = [ $(caller).project-module ] ;
+ local rules = [ RULENAMES $(caller-module) ] ;
+ if $(generating-rule[1]) in $(rules)
+ {
+ # This is local rule, make it global
+ local n = $(caller-module).$(generating-rule[1]) ;
+ IMPORT $(caller-module) : $(generating-rule[1]) : : $(n) ;
+ generating-rule = $(n) $(generating-rule[2-]) ;
+ }
+
+ targets.main-target-alternative
+ [ new make-target-class $(target-name) : $(caller)
+ : [ targets.main-target-sources $(sources) : $(target-name) ]
+ : [ targets.main-target-requirements $(requirements) : $(caller) ]
+ : $(generating-rule)
+ : [ targets.main-target-default-build : $(caller) ]
+ ] ;
+
+}
+
+IMPORT $(__name__) : make : : make ;
+
+
Added: boost-jam/boost-build/branches/upstream/current/tools/msvc.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/msvc.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/msvc.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,361 @@
+# Copyright David Abrahams 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.
+import property ;
+import generators ;
+import os ;
+import type ;
+import toolset : flags ;
+import errors : error ;
+import feature : feature get-values ;
+import path ;
+import sequence : unique ;
+import common ;
+
+import rc ;
+
+if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
+{
+ .debug-configuration = true ;
+}
+
+feature.extend toolset : msvc ;
+
+feature.subfeature toolset msvc : vendor
+ : intel
+ : propagated optional
+ # intel and msvc supposedly have link-compatible objects... remains
+ # to be seen, though ;-)
+ ;
+
+RM = [ modules.peek common : RM ] ;
+
+# Initialize the toolset for a specific version. As the result, path to
+# compiler and, possible, program names are set up, and will be used when
+# that version of compiler is requested. For example, you might have::
+#
+# using msvc : 6.5 : X:/some_dir ;
+# using msvc : 7.0 : Y:/some_dir ;
+# using msvc : : Z:/some_dir
+#
+# If you have "msvc-6.5" in build request, the version from X: drive will be used,
+# and if you put only "msvc", then drive "Z:" will be used. Note that it's not possible
+# the specify that by default, version 7.0 must be used --- you should use 'using'
+# without version number for that effect.
+#
+# version --
+# path --
+#
+# When invoking tools, we'll first run vcvars32.bat from the configured path and
+# then cl/link, without path.
+#
+# Note: for free VC7.1 tools, we don't correctly find vcvars32.bar when user
+# explicitly provides a path.
+rule init (
+ version ? # the msvc version which is being configured. When omitted
+ # the tools invoked when no explicit version is given will be configured.
+ : command *
+ # the command to invoke the compiler. If not specified:
+ # - if version is given, default location for that version will be searched
+ #
+ # - if version is not given, default locations for 7.1, 7.0 and 6.* will
+ # be searched
+ #
+ # - if compiler is not found in default locations, PATH will be searched.
+ : options *
+ # options can include <setup>, <compiler>, <linker> and <resource-compiler>
+)
+{
+ # setup will be used iff a path has been specified. If setup is
+ # not specified, vcvars32.bat will be used instead.
+ setup = [ get-values <setup> : $(options) ] ;
+ setup ?= vcvars32.bat ;
+ compiler = [ get-values <compiler> : $(options) ] ;
+ compiler ?= cl ;
+ linker = [ get-values <linker> : $(options) ] ;
+ linker ?= link ;
+ resource-compiler = [ get-values <resource-compiler> : $(options) ] ;
+ resource-compiler ?= rc ;
+
+ local condition = [ common.check-init-parameters msvc :
+ version $(version) ] ;
+
+ # If version is specified, we try to search first in default paths,
+ # and only then in PATH.
+ command = [ common.get-invocation-command msvc : cl.exe : $(command)
+ : [ default-paths $(version) ] : $(version) ] ;
+
+ common.handle-options msvc : $(condition) : $(command) : $(options) ;
+
+ if $(command)
+ {
+ command = [ common.get-absolute-tool-path $(command[-1]) ] ;
+ }
+ local root = $(command:D) ;
+
+ setup = $(root)\\bin\\$(setup) ;
+
+ # CONSIDER: What's the point of 'call'. Can we invoke the script directly?
+ setup = "call \""$(setup)"\" > nul " ;
+
+ if [ os.name ] = NT
+ {
+ setup = $(setup)"
+" ;
+ }
+ else
+ {
+ setup = "cmd /S /C "$(setup)" \"&&\" " ;
+ }
+
+ # prefix with setup, or quoted path if any
+ local prefix = $(setup) ;
+
+ flags msvc.compile .CC $(condition) : $(prefix)$(compiler) ;
+ flags msvc.compile .RC $(condition) : $(prefix)$(resource-compiler) ;
+ flags msvc.link .LD $(condition) : $(prefix)$(linker) ;
+ flags msvc.archive .LD $(condition) : $(prefix)$(linker) ;
+
+ if ! $(version)
+ {
+ # Even if version is not explicitly specified, try to detect the version
+ # from the path.
+ if [ MATCH "(Microsoft Visual Studio 8)" : $(command) ]
+ {
+ version = 8.0 ;
+ }
+ else if [ MATCH "(\\.NET 2003\\VC7)" : $(command) ] ||
+ [ MATCH "(Microsoft Visual C\\+\\+ Toolkit 2003)" : $(command) ]
+ {
+ version = 7.1 ;
+ }
+ else if [ MATCH "(.NET\\VC7)" : $(command) ]
+ {
+ version = 7.0 ;
+ }
+ else
+ {
+ version = 6.0 ;
+ }
+ }
+
+ # The following options work only for 7* versions. It means
+ # that if the user has not specified a version he gets 6.0 compatible
+ # behavious (i.e. a bit buggy)
+ if [ MATCH ^(7\..*) : $(version) ]
+ {
+ flags msvc.compile CFLAGS $(condition) : /Zc:forScope /Zc:wchar_t ;
+ }
+
+ # 8.0 deprecates some of the options
+ if [ MATCH ^(8) : $(version) ]
+ {
+ flags msvc.compile CFLAGS $(condition)/<optimization>speed : /O2 ;
+ flags msvc.compile CFLAGS $(condition)/<optimization>space : /O1 ;
+ }
+ else
+ {
+ flags msvc.compile CFLAGS $(condition)/<optimization>speed : /Ogity /O2 /Gs ;
+ flags msvc.compile CFLAGS $(condition)/<optimization>space : /Ogisy /O1 /Gs ;
+ }
+}
+
+rule default-paths ( version ? )
+{
+ local possible-paths ;
+
+ local ProgramFiles = [ modules.peek : ProgramFiles ] ;
+ if $(ProgramFiles)
+ {
+ ProgramFiles = "$(ProgramFiles:J= )" ;
+ }
+ else
+ {
+ ProgramFiles = "c:\\Program Files" ;
+ }
+
+ local version-6-path = $(ProgramFiles)"\\Microsoft Visual Studio\\VC98" ;
+ local version-7-path = $(ProgramFiles)"\\Microsoft Visual Studio .NET\\VC7" ;
+ local version-7.0-path = $(version-7-path) ;
+ local version-7.1-path = $(ProgramFiles)"\\Microsoft Visual Studio .NET 2003\\VC7" ;
+ local version-8.0-path = $(ProgramFiles)"\\Microsoft Visual Studio 8" ;
+
+ local VS71COMNTOOLS = [ modules.peek : VS71COMNTOOLS ] ;
+ if $(VS71COMNTOOLS)
+ {
+ # VS71COMNTOOLS is set by VS .NET 2003 to <VSDIR>\Common7\Tools
+ version-7.1-path = [ path.make "$(VS71COMNTOOLS:J= )" ] ;
+ version-7.1-path = [ path.parent $(version-7.1-path) ] ;
+ version-7.1-path = [ path.parent $(version-7.1-path) ] ;
+ version-7.1-path = [ path.join $(version-7.1-path) "VC7" ] ;
+ version-7.1-path = [ path.native $(version-7.1-path) ] ;
+ }
+
+ local VCToolkitInstallDir = [ modules.peek : VCToolkitInstallDir ] ;
+ if $(VCToolkitInstallDir)
+ {
+ version-7.1-path = [ path.make "$(VCToolkitInstallDir:J= )" ] ;
+ }
+
+ if $(version)
+ {
+ local v = [ MATCH ^(6|[^6].*) : $(version) ] ;
+ possible-paths += $(version-$(v)-path) ;
+ }
+ else
+ {
+ possible-paths += $(version-7.1-path) $(version-7.0-path) $(version-6-path) ;
+ }
+ # The vccars32.bat is actually in "bin" directory.
+ # (except for free VC7.1 tools)
+ possible-paths = $(possible-paths)\\bin $(possible-paths) ;
+
+ return $(possible-paths) ;
+}
+
+
+# Declare generators
+
+# is it possible to combine these?
+# make the generators non-composing, so that they don't convert each source
+# into separate rsp file.
+generators.register-linker msvc.link : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE RSP : <toolset>msvc ;
+generators.register-linker msvc.link.dll : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB RSP : <toolset>msvc ;
+
+generators.register-composing msvc.archive : OBJ : STATIC_LIB RSP : <toolset>msvc ;
+generators.register-c-compiler msvc.compile.c++ : CPP : OBJ : <toolset>msvc ;
+generators.register-c-compiler msvc.compile.c : C : OBJ : <toolset>msvc ;
+generators.register-standard msvc.compile.rc : RC : OBJ(%_res) : <toolset>msvc ;
+generators.override msvc.compile.rc : rc.resource-compile ;
+
+#
+# Declare flags and action for compilation
+#
+feature.feature debug-store : object database : propagated ;
+flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>object : /Z7 ;
+flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>database : /Zi ;
+flags msvc.compile CFLAGS <optimization>off : /Od ;
+flags msvc.compile CFLAGS <inlining>off : /Ob0 ;
+flags msvc.compile CFLAGS <inlining>on : /Ob1 ;
+flags msvc.compile CFLAGS <inlining>full : /Ob2 ;
+flags msvc.compile CFLAGS <exception-handling>on : /EHsc ;
+flags msvc.compile CFLAGS <rtti>on : /GR ;
+flags msvc.compile CFLAGS <runtime-debugging>off/<link-runtime>shared : /MD ;
+flags msvc.compile CFLAGS <runtime-debugging>on/<link-runtime>shared : /MDd ;
+
+flags msvc.compile CFLAGS <runtime-debugging>off/<link-runtime>static/<threading>single : /ML ;
+flags msvc.compile CFLAGS <runtime-debugging>on/<link-runtime>static/<threading>single : /MLd ;
+flags msvc.compile CFLAGS <runtime-debugging>off/<link-runtime>static/<threading>multi : /MT ;
+flags msvc.compile CFLAGS <runtime-debugging>on/<link-runtime>static/<threading>multi : /MTd ;
+flags msvc.compile CFLAGS <base-target-type>CPP : /EHsc ;
+
+flags msvc.compile USER_CFLAGS <cflags> : ;
+flags msvc.compile.c++ USER_CFLAGS <cxxflags> : ;
+
+flags msvc.compile PDB_CFLAG <debug-symbols>on/<debug-store>database : /Fd ; # not used yet
+
+flags msvc.compile DEFINES <define> ;
+flags msvc.compile UNDEFS <undef> ;
+flags msvc.compile INCLUDES <include> ;
+
+flags msvc WHATEVER <toolset-msvc:version> ;
+
+# The actions differ only by explicit selection of input language
+actions compile.c
+{
+ $(.CC) /Zm800 -nologo -TC -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(USER_CFLAGS) -I"$(INCLUDES)" -c -Fo"$(<:W)" "$(>:W)"
+}
+actions compile.c++
+{
+ $(.CC) /Zm800 -nologo -TP -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(USER_CFLAGS) -I"$(INCLUDES)" -c -Fo"$(<:W)" "$(>:W)"
+}
+
+actions compile.rc
+{
+ $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES)" -fo "$(<:W)" "$(>:W)"
+}
+
+# Declare flags and action for linking
+flags msvc.link PDB_LINKFLAG <debug-symbols>on/<debug-store>database : /PDB: ; # not used yet
+flags msvc.link LINKFLAGS <debug-symbols>on : /DEBUG ;
+flags msvc.link DEF_FILE <def-file> ;
+# The linker disables the default optimizations when using /DEBUG. Whe have
+# to enable them manually for release builds with debug symbols.
+flags msvc LINKFLAGS <debug-symbols>on/<runtime-debugging>off : /OPT:REF,ICF ;
+
+flags msvc LINKFLAGS <user-interface>console : /subsystem:console ;
+flags msvc LINKFLAGS <user-interface>gui : /subsystem:windows ;
+flags msvc LINKFLAGS <user-interface>wince : /subsystem:windowsce ;
+flags msvc LINKFLAGS <user-interface>native : /subsystem:native ;
+flags msvc LINKFLAGS <user-interface>auto : /subsystem:posix ;
+
+flags msvc LINKFLAGS <main-target-type>LIB/<link>shared : /DLL ;
+
+toolset.flags msvc.link USER_LINKFLAGS <linkflags> ;
+toolset.flags msvc.link LINKPATH <library-path> ;
+
+
+flags msvc.link FINDLIBS_ST <find-static-library> ;
+flags msvc.link FINDLIBS_SA <find-shared-library> ;
+flags msvc.link LIBRARY_OPTION <toolset>msvc : "" : unchecked ;
+
+
+rule archive ( targets + : sources * : properties * )
+{
+ common.response-file $(targets) : $(sources) : $(targets[2]) : $(properties) ;
+}
+
+rule link ( targets + : sources * : properties * )
+{
+ common.response-file $(targets) : $(sources) : $(targets[2])
+ : $(properties) ;
+}
+
+rule link.dll ( targets + : sources * : properties * )
+{
+ common.response-file $(targets) : $(sources) : $(targets[3]) : $(properties) ;
+ DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
+}
+
+# Declare action for creating static libraries
+# If library exists, remove it before adding files. See
+# http://article.gmane.org/gmane.comp.lib.boost.build/4241
+# for rationale.
+if [ os.name ] in NT
+{
+ # The 'DEL' command would issue a message to stdout
+ # if the file does not exist, so need a check.
+ actions archive
+ {
+ if exist "$(<[1])" DEL "$(<[1])"
+ $(.LD) /lib /NOLOGO /out:"$(<[1])" @"$(<[2])"
+ }
+}
+else
+{
+ actions archive
+ {
+ $(RM) "$(<[1])"
+ $(.LD) /lib /NOLOGO /out:"$(<[1])" @"$(<[2])"
+ }
+}
+
+# incremental linking a DLL causes no end of problems: if the
+# actual exports don't change, the import .lib file is never
+# updated. Therefore, the .lib is always out-of-date and gets
+# rebuilt every time. I'm not sure that incremental linking is
+# such a great idea in general, but in this case I'm sure we
+# don't want it.
+actions link bind DEF_FILE
+{
+ $(.LD) /NOLOGO $(LINKFLAGS) /out:"$(<[1]:W)" /INCREMENTAL:NO /LIBPATH:"$(LINKPATH:W)" $(USER_LINKFLAGS) @"$(<[2]:W)"
+}
+
+actions link.dll bind DEF_FILE
+{
+ $(.LD) /NOLOGO $(LINKFLAGS) /out:"$(<[1]:W)" /INCREMENTAL:NO /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:$(DEF_FILE) $(USER_LINKFLAGS) @"$(<[3]:W)"
+}
+
+
Added: boost-jam/boost-build/branches/upstream/current/tools/qt.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/qt.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/qt.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,154 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+import modules ;
+import feature ;
+import errors ;
+import type ;
+import "class" : new ;
+import generators ;
+import project ;
+import toolset : flags ;
+
+# Convert this module into a project, so that we can declare
+# targets here.
+
+project.initialize $(__name__) ;
+project qt ;
+
+# Initialized the QT support module. The 'prefix' parameter
+# tells where QT is installed. When not given, environmental
+# variable QTDIR should be set.
+rule init ( prefix ? )
+{
+ if ! $(prefix)
+ {
+ prefix = [ modules.peek : QTDIR ] ;
+ if ! $(prefix)
+ {
+ errors.error
+ "QT installation prefix not given and QTDIR variable is empty" ;
+ }
+ }
+
+ if $(.initialized)
+ {
+ if $(prefix) != $(.prefix)
+ {
+ errors.error
+ "Attempt the reinitialize QT with different installation prefix" ;
+ }
+ }
+ else
+ {
+ .initialized = true ;
+ .prefix = $(prefix) ;
+
+ generators.register-standard qt.moc : H : CPP(moc_%) : <allow>qt ;
+
+ type.register UI : ui ;
+ type.register UIC_H : : H ;
+
+ generators.register-standard qt.uic-h : UI : UIC_H : <allow>qt ;
+
+ # The following generator is used to convert UI files to CPP
+ # It creates UIC_H from UI, and constructs CPP from UI/UIC_H
+ # In addition, it also returns UIC_H target, so that it can bee
+ # mocced.
+ class qt::uic-cpp-generator : generator
+ {
+ rule __init__ ( )
+ {
+ generator.__init__ qt.uic-cpp : UI UIC_H : CPP : <allow>qt ;
+ }
+
+ rule run ( project name ? : properties * : sources + : multiple ? )
+ {
+ # Consider this:
+ # obj test : test_a.cpp : <optimization>off ;
+ #
+ # This generator will somehow be called in this case, and,
+ # will fail -- which is okay. However, if there are <library>
+ # properties they will be converted to sources, so the size of
+ # 'sources' will be more than 1. In this case, the base generator
+ # will just crash -- and that's not good. Just use a quick test
+ # here.
+
+ local result ;
+ if ! $(sources[2])
+ {
+ # Construct CPP as usual
+ result = [ generator.run $(project) $(name)
+ : $(properties) : $(sources) : $(multiple) ] ;
+ # If OK, add "UIC_H" target to the returned list
+ if $(result)
+ {
+ local action = [ $(result[1]).action ] ;
+ local sources = [ $(action).sources ] ;
+ result += $(sources[2]) ;
+ }
+ }
+
+ return $(result) ;
+ }
+ }
+
+ generators.register [ new qt::uic-cpp-generator ] ;
+
+ # Finally, declare prebuilt target for QT library.
+ local usage-requirements =
+ <include>$(.prefix)/include
+ <dll-path>$(.prefix)/lib
+ <library-path>$(.prefix)/lib
+ <allow>qt
+ ;
+ lib qt : : <name>qt-mt <threading>multi : : $(usage-requirements) ;
+ lib qt : : <name>qt <threading>single : : $(usage-requirements) ;
+ }
+}
+
+# Query the installation directory
+# This is needed in at least two scenarios
+# First, when re-using sources from the Qt-Tree.
+# Second, to "install" custom Qt plugins to the Qt-Tree.
+rule directory
+{
+ return $(.prefix) ;
+}
+
+# -f forces moc to include the processed source file.
+# Without it, it would think that .qpp is not a header and would not
+# include it from the generated file.
+actions moc
+{
+ $(.prefix)/bin/moc -f $(>) -o $(<)
+}
+
+space = " " ;
+
+# Sometimes it's required to make 'plugins' available during
+# uic invocation. To help with this we add paths to all dependency
+# libraries to uic commane line. The intention is that it's possible
+# to write
+#
+# exe a : ... a.ui ... : <uses>some_plugin ;
+#
+# and have everything work. We'd add quite a bunch of unrelated paths
+# but it won't hurt.
+flags qt.uic-h LIBRARY_PATH <xdll-path> ;
+actions uic-h
+{
+ $(.prefix)/bin/uic $(>) -o $(<) -L$(space)$(LIBRARY_PATH)
+}
+
+flags qt.uic-cpp LIBRARY_PATH <xdll-path> ;
+# The second target is uic-generated header name. It's placed in
+# build dir, but we want to include it using only basename.
+actions uic-cpp
+{
+ $(.prefix)/bin/uic $(>[1]) -i $(>[2]:D=) -o $(<) -L$(space)$(LIBRARY_PATH)
+}
+
+
Added: boost-jam/boost-build/branches/upstream/current/tools/rc.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/rc.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/rc.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,131 @@
+# Copyright (C) Andre Hentz 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.
+
+import type ;
+import generators ;
+import feature ;
+import errors ;
+import scanner ;
+
+type.register RC : rc ;
+
+rule init ( )
+{
+}
+
+rule resource-compile ( target : sources * : properties * )
+{
+ local OS = [ feature.get-values <os> : $(properties) ] ;
+ switch $(OS)
+ {
+ case "NT" :
+ resource-compile-nt $(target) : $(sources[1]) ;
+ case "CYGWIN" :
+ resource-compile-cygwin $(target) : $(sources[1]) ;
+ case "FREEBSD" :
+ create-empty-object $(target) : $(sources[1]) ;
+ case "SOLARIS" :
+ create-empty-object $(target) : $(sources[1]) ;
+ case "LINUX" :
+ create-empty-object $(target) : $(sources[1]) ;
+ case "*" :
+ errors.error "Cannot process RC files for OS=$(OS)" ;
+ }
+}
+
+
+actions quietly resource-compile-nt
+{
+ rc /i "$(>:D)" /i "$(<:D)" /fo "$(<)" "$(>)"
+}
+
+actions quietly resource-compile-cygwin
+{
+ windres --include-dir "$(>:D)" -o "$(<)" -i "$(>)"
+}
+
+actions quietly create-empty-object
+{
+ as /dev/null -o "$(<)"
+}
+
+# Since it's a common practice to write
+# exe hello : hello.cpp hello.rc
+# we change the name of object created from RC file, to
+# avoid conflict with hello.cpp.
+# The reason we generate OBJ and not RES, is that gcc does not
+# seem to like RES files, but works OK with OBJ.
+# See http://article.gmane.org/gmane.comp.lib.boost.build/5643/
+generators.register-standard rc.resource-compile : RC : OBJ(%_res) ;
+
+# Register scanner for resources
+class res-scanner : scanner
+{
+ import regex virtual-target path scanner ;
+
+ rule __init__ ( includes * )
+ {
+ scanner.__init__ ;
+
+ self.includes = $(includes) ;
+ }
+
+ rule pattern ( )
+ {
+ return "(([^ ]+[ ]+(BITMAP|CURSOR|FONT|ICON|MESSAGETABLE|RT_MANIFEST)[ ]+([^ \"]+|\"[^\"]+\"))|(#include[ ]*(<[^<]+>|\"[^\"]+\")))" ;
+ }
+
+ rule process ( target : matches * : binding )
+ {
+ local angle = [ regex.transform $(matches) : "#include[ ]*<([^<]+)>" ] ;
+ local quoted = [ regex.transform $(matches) : "#include[ ]*\"([^\"]+)\"" ] ;
+ local res = [ regex.transform $(matches) : "[^ ]+[ ]+(BITMAP|CURSOR|FONT|ICON|MESSAGETABLE|RT_MANIFEST)[ ]+(([^ \"]+)|\"([^\"]+)\")" : 3 4 ] ;
+
+ # Icons and other includes may referenced as
+ #
+ # IDR_MAINFRAME ICON "res\\icon.ico"
+ #
+ # so we have to replace double backslashes to single ones.
+ res = [ regex.replace-list $(res) : "\\\\\\\\" : "/" ] ;
+
+ # CONSIDER: the new scoping rule seem to defeat "on target" variables.
+ local g = [ on $(target) return $(HDRGRIST) ] ;
+ local b = [ NORMALIZE_PATH $(binding:D) ] ;
+
+ # Attach binding of including file to included targets.
+ # When target is directly created from virtual target
+ # this extra information is unnecessary. But in other
+ # cases, it allows to distinguish between two headers of the
+ # same name included from different places.
+ # We don't need this extra information for angle includes,
+ # since they should not depend on including file (we can't
+ # get literal "." in include path).
+ local g2 = $(g)"#"$(b) ;
+
+ angle = $(angle:G=$(g)) ;
+ quoted = $(quoted:G=$(g2)) ;
+ res = $(res:G=$(g2)) ;
+
+ local all = $(angle) $(quoted) ;
+
+ INCLUDES $(target) : $(all) ;
+ DEPENDS $(target) : $(res) ;
+ NOCARE $(all) $(res) ;
+ SEARCH on $(angle) = $(self.includes:G=) ;
+ SEARCH on $(quoted) = $(b) $(self.includes:G=) ;
+ SEARCH on $(res) = $(b) $(self.includes:G=) ;
+
+ # Just propagate current scanner to includes, in a hope
+ # that includes do not change scanners.
+ scanner.propagate $(__name__) : $(angle) $(quoted) : $(target) ;
+ }
+}
+
+scanner.register res-scanner : include ;
+type.set-scanner RC : res-scanner ;
+
+
+
+
Added: boost-jam/boost-build/branches/upstream/current/tools/stage.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/stage.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/stage.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,332 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+# This module defines the 'stage' rule, used to copy a set of targets to
+# a single location
+#
+# Typical usage:
+#
+# stage dist : hello_world : <location>/usr/bin ;
+#
+# The source target will be copied to the specified location. Some targets will
+# we specially processed. In particular, binaries will be relinked. Free properties
+# from stage dist will be included to properties used for relinking. For example
+#
+# stage dist : hello_world : <location>/usr/bin <dll-path>/opt/lib ;
+#
+# will cause 'hello_world' to be relinked to the new location, and <dll-path>
+# property will be added when relinking.
+#
+# Two properties specifically control 'stage' rule.
+#
+# - <location> tells where to put targets. If not specified, directory
+# with the same name as stage name will be used.
+#
+# - <name> tells the new name of the staged target. In this case, only
+# one target can be specified in sources.
+#
+# The stage rule can also traverse dependencies, for example to install a
+# program an all required libraries. Two properties affect this.
+#
+# - <traverse-dependencies>on tells that dependencies should be traversed.
+# For each target in 'stage' sources, all sources to that target and all
+# dependency properties are traversed. Sources and dependecy properties of
+# those target are traversed recursively.
+#
+# - <include-type>SOME_TYPE tells that targets of SOME_TYPE or a type derived
+# from SOME_TYPE, should be included.
+# If no such property is specified, then all found targets will be staged.
+# Otherwise, only targets with types mentioned in <include-type> property
+# will be included.
+#
+# Example usage::
+#
+# stage dist : hello_world :
+# <traverse-dependencies>on <include-type>EXE <include-type>SHARED_LIB ;
+#
+
+import targets ;
+import "class" : new ;
+import property ;
+import errors : error ;
+import type : type ;
+import type ;
+import regex ;
+import generators ;
+import feature ;
+import project ;
+
+feature.feature <traverse-dependencies> : off on : incidental ;
+feature.feature <include-type> : : free incidental ;
+
+class stage-target-class : basic-target
+{
+ import feature project type errors generators path ;
+ import "class" : new ;
+
+ rule __init__ ( name-and-dir : project : sources * : requirements * : default-build * )
+ {
+ basic-target.__init__ $(name-and-dir) : $(project) : $(sources) : $(requirements)
+ : $(default-build) ;
+ }
+
+ # If <location> is not set, sets it based on the project data.
+ rule update-location ( property-set )
+ {
+ local loc = [ $(property-set).get <location> ] ;
+ if ! $(loc)
+ {
+ loc = [ path.root $(self.name) [ $(self.project).get location ] ] ;
+
+ property-set = [ $(property-set).add-raw $(loc:G=<location>) ] ;
+ }
+
+ return $(property-set) ;
+ }
+
+ # Constructs the targets of types for which a type exists
+ # with the form STAGED_*.
+ rule construct-special-targets ( property-set : source : type )
+ {
+ local targets = [ generators.construct $(self.project) : $(type) :
+ $(property-set) : $(source) : * ] ;
+
+ return $(targets) ;
+ }
+
+ # Constructs the targets of types for which there is no STAGED_* type.
+ rule construct-regular-targets ( property-set : source )
+ {
+ local n = [ $(source).name ] ;
+ if $(name)
+ {
+ n = $(name) ;
+ }
+
+ targets = [ new file-target $(n:D=) : [ $(source).type ]
+ : $(self.project) ] ;
+ local a = [ $(source).action ] ;
+ local new-a ;
+ if $(a)
+ {
+ # Copy the properties of original target. They, in particular
+ # can affect the suffix of the target.
+ new-a = [ new action $(targets) : $(source) : common.copy : [ $(a).properties ] ] ;
+ }
+ else
+ {
+ new-a = [ new action $(targets) : $(source) : common.copy ] ;
+ }
+ $(targets).suffix [ $(source).suffix ] ;
+ $(targets).action $(new-a) ;
+
+ return $(targets) ;
+ }
+
+ rule construct ( source-targets * : property-set )
+ {
+ local name = [ $(property-set).get <name> ] ;
+ if $(name) && $(source-targets[2])
+ {
+ errors.error "<name> property cannot be specified when staging several targets" ;
+ }
+
+ if [ $(property-set).get <traverse-dependencies> ] = "on"
+ {
+ source-targets = [ collect-targets $(source-targets)
+ : [ $(property-set).get <include-type> ] ] ;
+ }
+
+
+ property-set = [ update-location $(property-set) ] ;
+ local include-types = [ $(property-set).get <include-type> ] ;
+
+ local result ;
+ for local i in $(source-targets)
+ {
+ # Intermediate targets are those with "unrequested" types.
+ # For example, given "exe a : a.cpp" we can end with RSP
+ # target on windows, and it will be marked as "intermediate".
+ # By default, we don't install such targets.
+ # If specific list of installable types is given, we don't
+ # care if target is intermediate or not.
+ if ! [ $(i).intermediate ] && [ $(i).type ] != SEARCHED_LIB
+ {
+ local staged-targets ;
+
+ local t = [ $(i).type ] ;
+
+ # See if something special should be done when staging this
+ # type. It is indicated by presense of special "staged" type
+ if $(t) && [ type.registered STAGED_$(t) ]
+ {
+ staged-targets = [ construct-special-targets $(property-set) : $(i) : STAGED_$(t) ] ;
+ }
+ else
+ {
+ staged-targets = [ construct-regular-targets $(property-set) : $(i) ] ;
+ }
+
+ if ! $(staged-targets)
+ {
+ errors.error "Unable to generate staged version of " [ $(source).str ] ;
+ }
+
+ for t in [ select-included $(staged-targets) : $(include-types) ]
+ {
+ local a = [ $(t).action ] ;
+ {
+ for local s in [ $(a).targets ]
+ {
+ $(s).set-path [ $(property-set).get <location> ] ;
+ }
+ }
+
+ result += [ virtual-target.register $(t) ] ;
+ }
+ }
+ }
+
+ return $(result) ;
+ }
+
+ rule select-included ( source-targets * : types-to-include * )
+ {
+ local result-targets ;
+ if $(types-to-include)
+ {
+ for local r in $(source-targets)
+ {
+ local ty = [ $(r).type ] ;
+ if $(ty)
+ {
+ if [ include-type $(ty) : $(types-to-include) ]
+ {
+ result-targets += $(r) ;
+ }
+ }
+ }
+ }
+ else
+ {
+ result-targets = $(source-targets) ;
+ }
+
+
+ return $(result-targets) ;
+ }
+
+ rule collect-targets ( targets * : types-to-include * )
+ {
+ # Find subvariants
+ local s ;
+ for local t in $(targets)
+ {
+ s += [ $(t).creating-subvariant ] ;
+ }
+ s = [ sequence.unique $(s) ] ;
+
+ local result = $(targets) ;
+ for local i in $(s)
+ {
+ result += [ $(i).all-referenced-targets ] ;
+ }
+ result = [ sequence.unique $(result) ] ;
+ }
+
+ rule check-for-link-compatibility ( * : * )
+ {
+ }
+
+ # Returns true iff 'type' is subtype of some element of 'types-to-include'.
+ local rule include-type ( type : types-to-include * )
+ {
+ local found ;
+ while $(types-to-include) && ! $(found)
+ {
+ if [ type.is-subtype $(type) $(types-to-include[1]) ]
+ {
+ found = true ;
+ }
+ types-to-include = $(types-to-include[2-]) ;
+ }
+
+ return $(found) ;
+ }
+
+
+}
+
+# Declare staged version of the EXE type. Generator for this type will
+# cause relinking to the new location.
+type.register STAGED_EXE : : EXE ;
+
+class stage-exe-generator : generator
+{
+ import type property-set modules ;
+
+ rule __init__ ( )
+ {
+ generator.__init__ stage-exe : EXE : STAGED_EXE ;
+ }
+
+ rule run ( project name ? : property-set : source : multiple ? )
+ {
+ local action = [ $(source).action ] ;
+
+ # stage can affect the relinking details.
+ local ps = [ $(action).properties ] ;
+ local ps-raw = [ $(ps).raw ] ;
+ # Unless <hardcode-dll-paths>true is in properties, which can
+ # happen only if the user has explicitly requested it, nuke all
+ # <dll-path> properties.
+ if [ $(property-set).get <hardcode-dll-paths> ] != true
+ {
+ ps-raw = [ property.change $(ps-raw) : <dll-path> ] ;
+ }
+ ps-raw = $(ps-raw) [ $(property-set).free ] ;
+ local new-ps = [ property-set.create $(ps-raw) ] ;
+
+ local cloned-action = [ virtual-target.clone-action $(action) : $(project) :
+ "" : $(new-ps) ] ;
+ local result = [ $(cloned-action).targets ] ;
+
+ return $(result) ;
+ }
+}
+
+generators.register [ new stage-exe-generator ] ;
+
+
+
+# Declares a stage target. When build, it will construct all sources
+# and place in one directory. The directory can be specified in requirements
+# with 'location' property. If not specified, the directory name will be
+# the same as target name, relative to the project where the target
+# is declared.
+rule stage ( name : sources * : requirements * : default-build * )
+{
+ local project = [ project.current ] ;
+
+ # Unless the user has explicitly asked us to hardcode dll paths, add
+ # <hardcode-dll-paths>false in requirements, to override default
+ # value.
+ if ! <hardcode-dll-paths>true in $(requirements)
+ {
+ requirements += <hardcode-dll-paths>false ;
+ }
+
+ targets.main-target-alternative
+ [ new stage-target-class $(name) : $(project)
+ : [ targets.main-target-sources $(sources) : $(name) ]
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
+ ] ;
+}
+
+IMPORT $(__name__) : stage : : stage ;
+
+
+
Added: boost-jam/boost-build/branches/upstream/current/tools/stlport.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/stlport.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/stlport.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,188 @@
+# (C) Copyright Gennadiy Rozental 2002.
+# (C) Copyright 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.
+
+# The STLPort is usable by means of 'stdlib' feature. When
+# stdlib=stlport is specified, default version of STLPort will be used,
+# while stdlib=stlport-4.5 will use specific version.
+# The subfeature value 'hostios' means to use host compiler's iostreams.
+#
+# The specific version of stlport is selected by features:
+# The <link> feature selects between static and shared library
+# The <runtime-debugging>on selects STLPort with debug symbols
+# and stl debugging.
+# There's no way to use STLPort with debug symbols but without
+# stl debugging.
+
+# TODO: must implement selection of different STLPort installations based
+# on used toolset.
+# Also, finish various flags:
+#
+# This is copied from V1 toolset, "+" means "impelemnted"
+#+flags $(CURR_TOOLSET) DEFINES <stlport-iostream>off : _STLP_NO_OWN_IOSTREAMS=1 _STLP_HAS_NO_NEW_IOSTREAMS=1 ;
+#+flags $(CURR_TOOLSET) DEFINES <stlport-extensions>off : _STLP_NO_EXTENSIONS=1 ;
+# flags $(CURR_TOOLSET) DEFINES <stlport-anachronisms>off : _STLP_NO_ANACHRONISMS=1 ;
+# flags $(CURR_TOOLSET) DEFINES <stlport-cstd-namespace>global : _STLP_VENDOR_GLOBAL_CSTD=1 ;
+# flags $(CURR_TOOLSET) DEFINES <exception-handling>off : _STLP_NO_EXCEPTIONS=1 ;
+# flags $(CURR_TOOLSET) DEFINES <stlport-debug-alloc>on : _STLP_DEBUG_ALLOC=1 ;
+#+flags $(CURR_TOOLSET) DEFINES <runtime-build>debug : _STLP_DEBUG=1 _STLP_DEBUG_UNINITIALIZED=1 ;
+#+flags $(CURR_TOOLSET) DEFINES <runtime-link>dynamic : _STLP_USE_DYNAMIC_LIB=1 ;
+
+
+import feature : feature subfeature ;
+import project ;
+import "class" : new ;
+import targets ;
+import property-set ;
+
+# Make this module into a project.
+project.initialize $(__name__) ;
+project stlport ;
+
+# The problem: how to request to use host compiler's iostreams?
+#
+# Solution 1: Global 'stlport-iostream' feature.
+# That's ugly. Subfeature make more sense for stlport-specific thing.
+# Solution 2: Use subfeature with two values, one of which ("use STLPort iostream")
+# is default.
+# The problem is that such subfeature will appear in target paths, and that's ugly
+# Solution 3: Use optional subfeature with only one value.
+
+feature.extend stdlib : stlport ;
+feature.compose <stdlib>stlport : <library>/stlport//stlport ;
+
+subfeature stdlib stlport : version : : optional propagated link-incompatible ;
+
+# STLport iostreams or native iostreams
+subfeature stdlib stlport : iostream : hostios : optional propagated ;
+
+# STLport extensions
+subfeature stdlib stlport : extensions : noext : optional propagated ;
+
+# STLport anachronisms -- NOT YET SUPPORTED
+# subfeature stdlib stlport : anachronisms : on off ;
+
+# STLport debug allocation -- NOT YET SUPPORTED
+#subfeature stdlib stlport : debug-alloc : off on ;
+
+# Declare a special target class to handle the creation of search-lib-target
+# instances for STLport. We need a special class, because otherwise we'll have
+# - declare prebuilt targets for all possible toolsets. And by the time 'init'
+# is called we don't even know the list of toolsets that are registered
+# - when host iostreams are used, we really should produce nothing. It would
+# be hard/impossible to achieve this using prebuilt targets.
+
+class stlport-target-class : basic-target
+{
+ import feature project type errors generators ;
+ import set : difference ;
+
+ rule __init__ ( project : headers ? : libraries ? : requirements * )
+ {
+ basic-target.__init__ stlport : $(project) : : $(requirements) ;
+ self.headers = $(headers) ;
+ self.libraries = $(libraries) ;
+ }
+
+ rule generate ( property-set )
+ {
+ # Since this target is built with <stdlib>stlport, it will also
+ # have <library>/stlport//stlport in requirements, which will
+ # cause a loop in main target references. Remove that property
+ # manually.
+
+ property-set = [ property-set.create [ difference
+ [ $(property-set).raw ] : <library>/stlport//stlport <stdlib>stlport ] ] ;
+ return [ basic-target.generate $(property-set) ] ;
+ }
+
+
+ rule construct ( source-targets * : property-set )
+ {
+ # Deduce the name of stlport library, based on toolset and
+ # debug setting.
+ local raw = [ $(property-set).raw ] ;
+ local hostios = [ feature.get-values <stdlib-stlport:iostream> : $(raw) ] ;
+ local toolset = [ feature.get-values <toolset> : $(raw) ] ;
+
+
+ # We don't need libraries if host istreams are used. For
+ # msvc, automatic library selection will be used.
+ if ! $(hostios) && $(toolset) != msvc
+ {
+ local debug = [ feature.get-values <runtime-debugging> : $(raw) ] ;
+
+ local name = stlport ;
+ name = $(name)_$(toolset) ;
+ if $(debug) = "on"
+ {
+ name = $(name)_stldebug ;
+ }
+
+ return [ generators.construct $(self.project) $(name) : SEARCHED_LIB
+ : $(property-set) ] ;
+ }
+
+ }
+
+ rule compute-usage-requirements ( subvariant )
+ {
+ local usage-requirements ;
+ usage-requirements +=
+ <include>$(self.headers)
+ <dll-path>$(self.libraries)
+ <library-path>$(self.libraries)
+ ;
+
+ local rproperties = [ $(subvariant).build-properties ] ;
+ # CONSIDER: should this "if" sequence be replaced with
+ # some use of 'property-map' class?
+ if [ $(rproperties).get <runtime-debugging> ] = "on"
+ {
+ usage-requirements += <define>_STLP_DEBUG=1
+ <define>_STLP_DEBUG_UNINITIALIZED=1 ;
+ }
+ if [ $(rproperties).get <runtime-debugging> ] = "on"
+ {
+ usage-requirements += <define>_STLP_USE_DYNAMIC_LIB=1 ;
+ }
+ if [ $(rproperties).get <stdlib-stlport:extensions> ] = noext
+ {
+ usage-requirements += <define>_STLP_NO_EXTENSIONS=1 ;
+ }
+ if [ $(rproperties).get <stdlib-stlport:iostream> ] = hostios
+ {
+ usage-requirements += <define>_STLP_NO_OWN_IOSTREAMS=1
+ <define>_STLP_HAS_NO_NEW_IOSTREAMS=1 ;
+ }
+
+ return [ property-set.create $(usage-requirements) ] ;
+ }
+}
+
+rule stlport-target ( headers ? : libraries ? : requirements * )
+{
+ local project = [ project.current ] ;
+
+ targets.main-target-alternative
+ [ new stlport-target-class $(project) : $(headers) : $(libraries)
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
+ ] ;
+}
+
+# Initialize stlport support.
+rule init ( version ? :
+ headers # Location of header files
+ libraries ? # Location of libraries
+ )
+{
+ feature.extend-subfeature stdlib stlport : version : $(version) ;
+
+ # Declare the main target for this STLPort version.
+ stlport-target $(headers) : $(libraries) : <stdlib>stlport-$(version) ;
+}
+
Added: boost-jam/boost-build/branches/upstream/current/tools/sun.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/sun.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/sun.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,112 @@
+# Copyright (C) Christopher Currie 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.
+
+import property ;
+import generators ;
+import os ;
+import toolset : flags ;
+import feature ;
+import type ;
+import common ;
+
+feature.extend toolset : sun ;
+toolset.inherit sun : unix ;
+feature.subfeature toolset sun : version ;
+
+feature.extend stdlib : sun-stlport ;
+feature.compose <stdlib>sun-stlport
+ : <cxxflags>-library=stlport4 <linkflags>-library=stlport4
+ ;
+
+rule init ( version ? : command * : options * )
+{
+ local condition = [
+ common.check-init-parameters sun : version $(version) ] ;
+
+ command = [ common.get-invocation-command sun : CC
+ : $(command) : "/opt/SUNWspro/bin" ] ;
+
+ common.handle-options sun : $(condition) : $(command) : $(options) ;
+
+ command_c = $(command[1--2]) $(command[-1]:B=cc) ;
+
+ toolset.flags sun CONFIG_C_COMMAND $(condition) : $(command_c) ;
+}
+
+# Declare generators
+generators.register-c-compiler sun.compile.c : C : OBJ : <toolset>sun ;
+generators.register-c-compiler sun.compile.c++ : CPP : OBJ : <toolset>sun ;
+
+# Declare flags and actions for compilation
+flags sun.compile OPTIONS <debug-symbols>on : -g ;
+flags sun.compile OPTIONS <profiling>on : -xprofile=tcov ;
+flags sun.compile OPTIONS <optimization>speed : -fast -xarch=generic ;
+flags sun.compile OPTIONS <optimization>space : -xO2 -xspace ;
+flags sun.compile OPTIONS <threading>multi : -mt ;
+
+flags sun.compile.c++ OPTIONS <inlining>off : +d ;
+
+flags sun.compile OPTIONS <cflags> ;
+flags sun.compile.c++ OPTIONS <cxxflags> ;
+flags sun.compile DEFINES <define> ;
+flags sun.compile INCLUDES <include> ;
+
+actions compile.c
+{
+ "$(CONFIG_C_COMMAND)" $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+actions compile.c++
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"
+}
+
+# Declare flags and actions for linking
+flags sun.link OPTIONS <debug-symbols>on : -g ;
+# Strip the binary when no debugging is needed
+flags sun.link OPTIONS <debug-symbols>off : -s ;
+flags sun.link OPTIONS <profiling>on : -xprofile=tcov ;
+flags sun.link OPTIONS <threading>multi : -mt ;
+flags sun.link OPTIONS <linkflags> ;
+flags sun.link LINKPATH <library-path> ;
+flags sun.link FINDLIBS-ST <find-static-library> ;
+flags sun.link FINDLIBS-SA <find-shared-library> ;
+flags sun.link LIBRARIES <library-file> ;
+flags sun.link LINK-RUNTIME <link-runtime>static : static ;
+flags sun.link LINK-RUNTIME <link-runtime>shared : dynamic ;
+flags sun.link RPATH <dll-path> ;
+# On gcc, there are separate options for dll path at runtime and
+# link time. On Solaris, there's only one: -R, so we have to use
+# it, even though it's bad idea.
+flags sun.link RPATH <xdll-path> ;
+
+rule link ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+}
+
+actions link bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) -L"$(LINKPATH)" -R"$(RPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -Bdynamic -l$(FINDLIBS-SA) -Bstatic -l$(FINDLIBS-ST) -B$(LINK-RUNTIME)
+}
+
+# Slight mods for dlls
+rule link.dll ( targets * : sources * : properties * )
+{
+ SPACE on $(targets) = " " ;
+}
+
+actions link.dll bind LIBRARIES
+{
+ "$(CONFIG_COMMAND)" $(OPTIONS) -L"$(LINKPATH)" -R"$(RPATH)" -o "$(<)" -h$(<[1]:D=) -G "$(>)" "$(LIBRARIES)" -Bdynamic -l$(FINDLIBS-SA) -Bstatic -l$(FINDLIBS-ST) -B$(LINK-RUNTIME)
+}
+
+# Declare action for creating static libraries
+actions piecemeal archive
+{
+ "$(CONFIG_COMMAND)" -xar -o "$(<)" "$(>)"
+}
+
Added: boost-jam/boost-build/branches/upstream/current/tools/symlink.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/symlink.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/symlink.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,136 @@
+# (C) Copyright Rene Rivera, 2002-2003.
+#
+# See accompanying license for terms and conditions of use.
+#
+
+# Defines the "symlink" special target. 'symlink' targets make symbolic links
+# to the sources.
+
+import targets modules path class os feature project ;
+
+.count = 0 ;
+
+feature.feature symlink-location : project-relative build-relative : incidental ;
+
+# The class representing "symlink" targets.
+#
+class symlink-targets : basic-target
+{
+ import numbers modules class property project path ;
+
+ rule __init__ (
+ project
+ : targets *
+ : sources *
+ )
+ {
+ # Generate a fake name for now. Need unnamed targets eventually.
+ local c = [ modules.peek symlink : .count ] ;
+ modules.poke symlink : .count : [ numbers.increment $(c) ] ;
+ local fake-name = symlink#$(c) ;
+
+ basic-target.__init__ $(fake-name) : $(project) : $(sources) ;
+
+ # Remember the targets to map the sources onto. Pad or truncate
+ # to fit the sources given.
+ self.targets = ;
+ for local source in $(sources)
+ {
+ if $(targets)
+ {
+ self.targets += $(targets[1]) ;
+ targets = $(targets[2-]) ;
+ }
+ else
+ {
+ self.targets += $(source) ;
+ }
+ }
+
+ # The virtual targets corresponding to the given targets.
+ self.virtual-targets = ;
+ }
+
+ rule construct ( source-targets * : property-set )
+ {
+ local i = 1 ;
+ for local t in $(source-targets)
+ {
+ local s = $(self.targets[$(i)]) ;
+ local vt = [ class.new file-target $(s:D=) : [ $(t).type ] : $(self.project) ] ;
+ $(vt).action [ class.new action $(vt) : $(t) : symlink.ln : $(property-set) ] ;
+
+ # Place the symlink in the directory relative to the project
+ # location, instead of placing it in the build directory.
+ if [ property.select <symlink-location> : [ $(property-set).raw ] ] = <symlink-location>project-relative
+ {
+ $(vt).set-path [ path.root $(s:D) [ $(self.project).get location ] ] ;
+ }
+
+ self.virtual-targets += $(vt) ;
+ i = [ numbers.increment $(i) ] ;
+ }
+ return $(self.virtual-targets) ;
+ }
+}
+
+# Creates a symbolic link from a set of targets to a set of sources.
+# The targets and sources map one to one. The symlinks generated are
+# limited to be the ones given as the sources. That is, the targets
+# are either padded or trimmed to equate to the sources. The padding
+# is done with the name of the corresponding source. For example::
+#
+# symlink : one two ;
+#
+# Is equal to::
+#
+# symlink one two : one two ;
+#
+# Names for symlink are relative to the project location. They cannot
+# include ".." path components.
+rule symlink (
+ targets *
+ : sources *
+ )
+{
+ local project = [ project.current ] ;
+
+ return [ targets.main-target-alternative
+ [ class.new symlink-targets $(project) : $(targets) :
+ # Note: inline targets are not supported for symlink, intentionally,
+ # since it's used to linking existing non-local targets.
+ $(sources) ] ] ;
+}
+
+rule ln
+{
+ local os ;
+ if [ modules.peek : UNIX ] { os = UNIX ; }
+ else { os ?= [ os.name ] ; }
+ # Remember the path to make the link relative to where the symlink is located.
+ local path-to-source = [ path.relative-to
+ [ path.make [ on $(<) return $(LOCATE) ] ]
+ [ path.make [ on $(>) return $(LOCATE) ] ] ] ;
+ if $(path-to-source) = .
+ {
+ PATH_TO_SOURCE on $(<) = "" ;
+ }
+ else
+ {
+ PATH_TO_SOURCE on $(<) = [ path.native $(path-to-source) ] ;
+ }
+ ln-$(os) $(<) : $(>) ;
+}
+
+actions ln-UNIX
+{
+ ln -f -s '$(>:D=:R=$(PATH_TO_SOURCE))' '$(<)'
+}
+
+# there is a way to do this; it's a dummy rule for now
+actions ln-NT
+{
+ echo "NT symlinks not supported yet"
+}
+
+IMPORT $(__name__) : symlink : : symlink ;
Added: boost-jam/boost-build/branches/upstream/current/tools/testing.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/testing.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/testing.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,395 @@
+# (C) Copyright David Abrahams 2002.
+# (C) Copyright Vladimir Prus 2002-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.
+
+# This module implements regression testing framework. It declares a number of
+# main target rules, which perform some action, and if the results are ok,
+# creates an output file.
+#
+# The exact list of rules is:
+# 'compile' -- creates .test file if compilation of sources was successfull
+# 'compile-fail' -- creates .test file if compilation of sources failed
+# 'run' -- creates .test file is running of executable produced from
+# sources was successfull. Also leaves behing .output file
+# with the output from program run.
+# 'run-fail' -- same as above, but .test file is created if running fails.
+#
+# In all cases, presense of .test file is an incication that
+# the test passed. For more convenient reporting, you might want to use C++ Boost
+# regression testing utilities, see
+# http://www.boost.org/more/regression.html
+#
+# For historical reason, a 'unit-test' rule is available which
+# has the same syntax as 'exe' and behaves just like 'run'.
+
+# Things to do:
+# - Teach compiler_status handle Jamfile.v2.
+# Notes:
+# - <no-warn> is not implemented, since in Como-specific, and it's not clear how
+# to implement it
+# - std::locale-support is not impelemted (it's used in one test).
+
+
+import targets ;
+import "class" : new ;
+import property ;
+import feature ;
+import toolset ;
+import alias ;
+import type ;
+import generators ;
+import project ;
+import property-set ;
+import virtual-target ;
+import path ;
+import os ;
+import common ;
+import sequence ;
+
+rule init ( ) { }
+
+# The feature which controls the name of program used to
+# lanch test programs.
+feature.feature testing.launcher : : optional free ;
+feature.feature test-info : : free incidental ;
+feature.feature testing.arg : : free incidental ;
+feature.feature testing.input-file : : free dependency ;
+
+# Register target types.
+type.register TEST : test ;
+type.register COMPILE : : TEST : main ;
+type.register COMPILE_FAIL : : TEST : main ;
+type.register RUN_OUTPUT : run : : main ;
+type.register RUN : : TEST : main ;
+type.register RUN_FAIL : : TEST : main ;
+type.register UNIT_TEST : passed : TEST : main ;
+
+# Declare the rules which create main targets.
+# While the 'type' module already creates rules with the same names for us,
+# we need extra convenience: default name of main target, so write
+# our own versions.
+
+# Helper rule. Create a test target, using basename of first source of no
+# target name is explicitly passed. Remembers the created target in
+# a global variable.
+rule make-test ( target-type : sources + : requirements * : target-name ? )
+{
+ target-name ?= $(sources[1]:D=:S=) ;
+
+ local project = [ project.current ] ;
+ # The <location-prefix> forces the build system for generate paths in the form
+ # $build_dir/array1.test/gcc/debug
+ # This is necessary to allow post-processing tools to work.
+ local t =
+ [ targets.create-typed-target
+ [ type.type-from-rule-name $(target-type) ] : $(project)
+ : $(target-name) : $(sources)
+ : $(requirements) <location-prefix>$(target-name).test ] ;
+
+ # Remember the test (for --dump-test).
+ # A good way would be to collect all given a project.
+ # This has some technical problems: e.g. we can't call this dump from
+ # Jamfile since projects referred by 'build-project' are not available until
+ # whole Jamfile is loaded.
+ .all-tests += $(t) ;
+ return $(t) ;
+}
+
+rule compile ( sources + : requirements * : target-name ? )
+{
+ return [ make-test compile : $(sources) : $(requirements) : $(target-name) ] ;
+}
+
+rule compile-fail ( sources + : requirements * : target-name ? )
+{
+ return [ make-test compile-fail : $(sources) : $(requirements) : $(target-name) ] ;
+}
+
+rule run ( sources + : args * : input-files * : requirements * : target-name ?
+ : default-build * )
+{
+ requirements += <testing.arg>$(args:J=" ") ;
+ requirements += <testing.input-file>$(input-files[1]) ;
+ if $(input-files[2]) || $(default-build)
+ {
+ EXIT "NOT supported" ;
+ }
+ return [ make-test run : $(sources) : $(requirements) : $(target-name) ] ;
+}
+
+rule run-fail ( sources + : args * : input-files * : requirements * : target-name ?
+ : default-build * )
+{
+ requirements += <testing.arg>$(args:J=" ") ;
+ requirements += <testing.input-file>$(input-files[1]) ;
+ if $(input-files[2]) || $(default-build)
+ {
+ EXIT "NOT supported" ;
+ }
+ return [ make-test run-fail : $(sources) : $(requirements) : $(target-name) ] ;
+}
+
+
+# Rule for grouping tests in suites.
+rule test-suite ( suite-name : tests + )
+{
+ # In V2, if 'tests' are instances of 'abstract-target', they will be considered
+ # 'inline-targets' and will suffer some adjustments. This will not be compatible
+ # with V1 behaviour, so we get names of 'tests' and use them.
+ local names ;
+ for local t in $(tests)
+ {
+ names += [ $(t).name ] ;
+ }
+ modules.call-in [ CALLER_MODULE ] : alias $(suite-name) : $(names) ;
+}
+
+# For all main target in 'project-module',
+# which are typed target with type derived from 'TEST',
+# produce some interesting information.
+rule dump-tests # ( project-module )
+{
+ for local t in $(.all-tests)
+ {
+ dump-test $(t) ;
+ }
+}
+
+rule dump-test ( target )
+{
+ local type = [ $(target).type ] ;
+ local name = [ $(target).name ] ;
+ local project = [ $(target).project ] ;
+
+ local project-root = [ $(project).get project-root ] ;
+ local project-root-location = [ $(project-root).get-location ] ;
+
+ local sources = [ $(target).sources ] ;
+ local source-files ;
+ for local s in $(sources)
+ {
+ if [ class.is-a $(s) : file-reference ]
+ {
+ source-files +=
+ [ path.relative
+ [ path.root [ $(s).location ] [ path.pwd ] ]
+ [ path.root $(project-root-location) [ path.pwd ] ] ] ;
+ }
+ }
+
+ local r = [ $(t).requirements ] ;
+ # Extract values of the <test-info> feature
+ local test-info = [ $(r).get <test-info> ] ;
+
+ # Format them into a single string of quoted strings
+ test-info = \"$(test-info:J=\"\ \")\" ;
+
+ ECHO boost-test($(type)) \"$(name)\"
+ [$(test-info)]
+ ":" \"$(source-files)\"
+ ;
+}
+
+# Register generators. Depending on target type, either
+# 'expect-success' or 'expect-failure' rule will be used.
+generators.register-standard testing.expect-success : OBJ : COMPILE ;
+generators.register-standard testing.expect-failure : OBJ : COMPILE_FAIL ;
+generators.register-standard testing.expect-success : RUN_OUTPUT : RUN ;
+generators.register-standard testing.expect-failure : RUN_OUTPUT : RUN_FAIL ;
+
+# Generator which runs an EXE and captures output.
+generators.register-standard testing.capture-output : EXE : RUN_OUTPUT ;
+
+# Generator which creates target if sources runs successfully.
+# Differers from RUN in that run output is not captured.
+# The reason why it exists is that the 'run' rule is much better for
+# automated testing, but is not user-friendly. See
+# http://article.gmane.org/gmane.comp.lib.boost.build/6353/
+generators.register-standard testing.unit-test : EXE : UNIT_TEST ;
+
+
+# The action rules called by generators.
+
+# Causes the 'target' to exist after bjam invocation if and only if all the
+# dependencies were successfully built.
+rule expect-success ( target : dependency + : requirements * )
+{
+ **passed** $(target) : $(sources) ;
+}
+
+# Causes the 'target' to exist after bjam invocation if and only if all some
+# of the dependencies were not successfully built.
+rule expect-failure ( target : dependency + : properties * )
+{
+ local grist = [ MATCH ^<(.*)> : $(dependency:G) ] ;
+ local marker = $(dependency:G=$(grist)*fail) ;
+ (failed-as-expected) $(marker) ;
+ FAIL_EXPECTED $(dependency) ;
+ LOCATE on $(marker) = [ on $(dependency) return $(LOCATE) ] ;
+ RMOLD $(marker) ;
+ DEPENDS $(marker) : $(dependency) ;
+
+ DEPENDS $(target) : $(marker) ;
+ **passed** $(target) : $(marker) ;
+}
+
+# The rule/action combination used to report successfull passing
+# of a test.
+rule **passed**
+{
+ # Dump all the tests, if needed.
+ # We do it here, since dump should happen after all Jamfiles are read,
+ # and there's no such place currently defined (but should).
+ if ! $(.dumped-tests) && --dump-tests in [ modules.peek : ARGV ]
+ {
+ .dumped-tests = true ;
+ dump-tests ;
+ }
+
+ # Force deletion of the target, in case any dependencies failed
+ # to build.
+ RMOLD $(<) ;
+}
+
+actions **passed**
+{
+ echo passed > $(<)
+}
+
+actions (failed-as-expected)
+{
+ echo failed as expected > $(<)
+}
+
+rule run-path-setup ( target : source : properties * )
+{
+ # For testing, we need to make sure that all dynamic libraries needed by
+ # the test are found. So, we collect all paths from dependency libraries
+ # (via xdll-path property) and add whatever explicit dll-path user has
+ # specified. The resulting paths are added to environment on each test
+ # invocation.
+ local dll-paths = [ feature.get-values <dll-path> : $(properties) ] ;
+ dll-paths += [ feature.get-values <xdll-path> : $(properties) ] ;
+ dll-paths = [ sequence.unique $(dll-paths) ] ;
+ if $(dll-paths)
+ {
+ dll-paths = [ sequence.transform path.native : $(dll-paths) ] ;
+ if [ modules.peek : NT ]
+ {
+ PATH_SETUP on $(target) =
+ [ common.path-variable-setting-command PATH : $(dll-paths) %PATH% ] ;
+ }
+ else
+ {
+ PATH_SETUP on $(target) =
+ [ common.path-variable-setting-command LD_LIBRARY_PATH :
+ $(dll-paths) $LD_LIBRARY_PATH : exported ] ;
+ }
+ }
+}
+
+
+toolset.flags testing.capture-output ARGS <testing.arg> ;
+toolset.flags testing.capture-output INPUT_FILES <testing.input-file> ;
+toolset.flags testing.capture-output LAUNCHER <testing.launcher> ;
+rule capture-output ( target : source : properties * )
+{
+ output-file on $(target) = $(target:S=.output) ;
+ LOCATE on $(target:S=.output) = [ on $(target) return $(LOCATE) ] ;
+
+ # The INCLUDES kill a warning about independent target...
+ INCLUDES $(target) : $(target:S=.output) ;
+ # but it also puts .output into dependency graph, so we must tell jam
+ # it's OK if it cannot find the target or updating rule.
+ NOCARE $(target:S=.output) ;
+
+ # This has two-fold effect. First it adds input files to the dependendency
+ # graph, preventing a warning. Second, it causes input files to be bound
+ # before target is created. Therefore, they are bound using SEARCH setting
+ # on them and not LOCATE setting of $(target), as in other case (due to jam bug).
+ DEPENDS $(target) : [ on $(target) return $(INPUT_FILES) ] ;
+
+ run-path-setup $(target) : $(source) : $(properties) ;
+}
+
+
+if [ os.name ] = NT
+{
+ STATUS = %status% ;
+ SET_STATUS = "set status=%ERRORLEVEL%" ;
+ RUN_OUTPUT_NL = "echo." ;
+ STATUS_0 = "%status% EQU 0 (" ;
+ STATUS_NOT_0 = "%status% NEQ 0 (" ;
+ VERBOSE = "%verbose% EQU 1 (" ;
+ ENDIF = ")" ;
+ SHELL_SET = "set " ;
+
+ CATENATE = type ;
+ CP = copy ;
+}
+else
+{
+ STATUS = "$status" ;
+ SET_STATUS = "status=$?" ;
+ RUN_OUTPUT_NL = "echo" ;
+ STATUS_0 = "test $status -eq 0 ; then" ;
+ STATUS_NOT_0 = "test $status -ne 0 ; then" ;
+ VERBOSE = "test $verbose -eq 1 ; then" ;
+ ENDIF = "fi" ;
+ SHELL_SET = "" ;
+
+ CATENATE = cat ;
+ CP = cp ;
+}
+
+if --verbose-test in [ modules.peek : ARGV ]
+{
+ VERBOSE_TEST = 1 ;
+}
+else
+{
+ VERBOSE_TEST = 0 ;
+}
+
+actions capture-output bind INPUT_FILES output-file
+{
+ $(PATH_SETUP)
+ $(LAUNCHER) $(>) $(ARGS) "$(INPUT_FILES)" > $(output-file) 2>&1
+ $(SET_STATUS)
+ $(RUN_OUTPUT_NL) >> $(output-file)
+ echo EXIT STATUS: $(STATUS) >> $(output-file)
+ if $(STATUS_0)
+ $(CP) $(output-file) $(<)
+ $(ENDIF)
+ $(SHELL_SET)verbose=$(VERBOSE_TEST)
+ if $(STATUS_NOT_0)
+ $(SHELL_SET)verbose=1
+ $(ENDIF)
+ if $(VERBOSE)
+ echo ====== BEGIN OUTPUT ======
+ $(CATENATE) $(output-file)
+ echo ====== END OUTPUT ======
+ $(ENDIF)
+ exit $(STATUS)
+}
+
+MAKE_FILE = [ common.file-creation-command ] ;
+
+toolset.flags testing.unit-test LAUNCHER <testing.launcher> ;
+rule unit-test ( target : source : properties * )
+{
+ run-path-setup $(target) : $(source) : $(properties) ;
+}
+
+actions unit-test
+{
+ $(PATH_SETUP)
+ $(LAUNCHER) $(>) && $(MAKE_FILE) $(<)
+}
+
+IMPORT $(__name__) : compile compile-fail test-suite run run-fail
+ : : compile compile-fail test-suite run run-fail ;
+
Added: boost-jam/boost-build/branches/upstream/current/tools/unix.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/unix.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/unix.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,224 @@
+# Copyright (c) 2004 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# This file implements linking semantic common to all unixes. On unix, static
+# libraries must be specified in a fixed order on the linker command line. Generators
+# declared there store information about the order and use it property.
+
+import feature ;
+import "class" : new ;
+import generators ;
+import type ;
+import set ;
+import order ;
+import builtin ;
+
+class unix-linking-generator : linking-generator
+{
+ import property-set ;
+ import type ;
+ import unix ;
+
+ rule __init__ ( id
+ composing ? : # Specify if generator is composing. The generator will be
+ # composing if non-empty string is passed, or parameter is
+ # not given. To make generator non-composing, pass empty
+ # string ("")
+ source-types + : target-types + :
+ requirements * )
+ {
+ composing ?= true ;
+ generator.__init__ $(id) $(composing) : $(source-types) : $(target-types) :
+ $(requirements) ;
+ }
+
+ rule run ( project name ? : property-set : sources + : multiple ? )
+ {
+ local result = [ linking-generator.run $(project) $(name) : $(property-set)
+ : $(sources) : $(multiple) ] ;
+
+ unix.set-library-order $(sources) : $(property-set) : $(result) ;
+
+ return $(result) ;
+ }
+
+ rule generated-targets ( sources + : property-set : project name ? )
+ {
+ local sources2 ;
+ local libraries ;
+ for local l in $(sources)
+ {
+ if [ type.is-derived [ $(l).type ] LIB ]
+ {
+ libraries += $(l) ;
+ }
+ else
+ {
+ sources2 += $(l) ;
+ }
+ }
+
+ sources = $(sources2) [ unix.order-libraries $(libraries) ] ;
+
+ return [ linking-generator.generated-targets $(sources) : $(property-set)
+ : $(project) $(name) ] ;
+ }
+
+}
+
+class unix-archive-generator : generator
+{
+ import unix ;
+
+ rule __init__ ( id composing ? : source-types + : target-types + :
+ requirements * )
+ {
+ composing ?= true ;
+ generator.__init__ $(id) $(composing) : $(source-types) : $(target-types) :
+ $(requirements) ;
+ }
+
+ rule run ( project name ? : property-set : sources + : multiple ? )
+ {
+ local result = [ generator.run $(project) $(name) : $(property-set)
+ : $(sources) : $(multiple) ] ;
+
+ unix.set-library-order $(sources) : $(property-set) : $(result) ;
+
+ return $(result) ;
+
+ }
+}
+
+class unix-searched-lib-generator : searched-lib-generator
+{
+ import unix ;
+ rule __init__ ( * : * )
+ {
+ generator.__init__
+ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule optional-properties ( )
+ {
+ return $(self.requirements) ;
+ }
+
+ rule run ( project name ? : property-set : sources * : multiple ? )
+ {
+ local result = [ searched-lib-generator.run $(project) $(name)
+ : $(property-set) : $(sources) : $(multiple) ] ;
+
+ unix.set-library-order $(sources) : $(property-set) : $(result) ;
+
+ return $(result) ;
+ }
+}
+
+class unix-prebuilt-lib-generator : generator
+{
+ import unix ;
+ rule __init__ ( * : * )
+ {
+ generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
+ }
+
+ rule run ( project name ? : property-set : sources * : multiple ? )
+ {
+ local f = [ $(property-set).get <file> ] ;
+ unix.set-library-order-aux $(f) : $(sources) ;
+ return $(f) $(sources) ;
+ }
+}
+
+generators.register
+ [ new unix-prebuilt-lib-generator unix.prebuilt : : LIB
+ : <file> <toolset>unix ] ;
+
+
+
+
+# Declare generators
+generators.register [ new unix-linking-generator unix.link : LIB OBJ : EXE
+ : <toolset>unix ] ;
+
+generators.register [ new unix-archive-generator unix.archive : OBJ : STATIC_LIB
+ : <toolset>unix ] ;
+
+generators.register [ new unix-linking-generator unix.link.dll : LIB OBJ : SHARED_LIB
+ : <toolset>unix ] ;
+
+generators.register [ new unix-searched-lib-generator
+ unix.searched-lib-generator : : SEARCHED_LIB : <toolset>unix ] ;
+
+
+# The derived toolset must specify their own actions.
+actions link {
+}
+
+actions link.dll {
+}
+
+actions archive {
+}
+
+actions searched-lib-generator {
+}
+
+actions prebuilt {
+}
+
+
+
+
+
+.order = [ new order ] ;
+
+rule set-library-order-aux ( from * : to * )
+{
+ for local f in $(from)
+ {
+ for local t in $(to)
+ {
+ if $(f) != $(t)
+ {
+ $(.order).add-pair $(f) $(t) ;
+ }
+ }
+ }
+}
+
+rule set-library-order ( sources * : property-set : result * )
+{
+ local used-libraries ;
+ local deps = [ $(property-set).dependency ] ;
+ for local l in $(sources) $(deps:G=)
+ {
+ if [ $(l).type ] && [ type.is-derived [ $(l).type ] LIB ]
+ {
+ used-libraries += $(l) ;
+ }
+ }
+
+ local created-libraries ;
+ for local l in $(result)
+ {
+ if [ $(l).type ] && [ type.is-derived [ $(l).type ] LIB ]
+ {
+ created-libraries += $(l) ;
+ }
+ }
+
+ created-libraries = [ set.difference $(created-libraries) : $(used-libraries) ] ;
+ set-library-order-aux $(created-libraries) : $(used-libraries) ;
+}
+
+rule order-libraries ( libraries * )
+{
+ local r = [ $(.order).order $(libraries) ] ;
+ return $(r) ;
+}
+
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/tools/vacpp.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/vacpp.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/vacpp.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,108 @@
+# Copyright Vladimir Prus 2004.
+# Copyright Toon Knapen 2004.
+# 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)
+
+#
+# Boost.Build V2 toolset for the IBM VisualAge compiler
+#
+
+import toolset : flags ;
+import feature ;
+
+feature.extend toolset : vacpp ;
+toolset.inherit vacpp : unix ;
+feature.subfeature toolset vacpp : version ;
+
+# Configures the vacpp toolset.
+rule init ( version ? : command * : options * )
+{
+ local condition = [ common.check-init-parameters vacpp : version $(version) ] ;
+ local command = [ common.get-invocation-command vacpp : xlc : $(command) ] ;
+
+ common.handle-options acc : $(condition) : $(command) : $(options) ;
+
+ if $(command)
+ {
+ command = [ common.get-absolute-tool-path $(command[-1]) ] ;
+ }
+ local root = $(command:D) ;
+
+ flags vacpp ROOT $(condition) : $(root) ;
+}
+
+
+# Declare generators
+generators.register-c-compiler vacpp.compile.c : C : OBJ : <toolset>vacpp ;
+generators.register-c-compiler vacpp.compile.c++ : CPP : OBJ : <toolset>vacpp ;
+
+# Declare flags.
+flags vacpp CFLAGS <optimization>off : -qNOOPTimize ;
+flags vacpp CFLAGS <optimization>speed : -O3 -qstrict ;
+flags vacpp CFLAGS <optimization>space : -O2 -qcompact ;
+
+flags vacpp CFLAGS <inlining>off : -qnoinline ;
+flags vacpp CFLAGS <inlining>on : -qinline ;
+flags vacpp CFLAGS <inlining>full : -qinline ;
+
+flags vacpp C++FLAGS <exception-handling>off : -qnoeh ;
+flags vacpp C++FLAGS <exception-handling>on : -qeh ;
+
+flags vacpp C++FLAGS <rtti>off : -qnortti ;
+flags vacpp C++FLAGS <rtti>on : -qrtti ;
+
+# flags vacpp LINKFLAGS <link-runtime>static : -llibstd_v2.a ;
+# flags vacpp LINKFLAGS <link-runtime>shared : -llibstd_v2.sl ;
+
+# We want the full path to the sources in the debug symbols because otherwise
+# the debugger won't find the sources when we use boost.build.
+flags vacpp CFLAGS <debug-symbols>on : -g ;
+flags vacpp LINKFLAGS <debug-symbols>on : -g ;
+flags vacpp LINKFLAGS <debug-symbols>off : -s ;
+
+# V2 does not have <shared-linkable>, not sure what this meant in V1.
+#flags vacpp CFLAGS <shared-linkable>true : +Z ;
+
+flags vacpp CFLAGS <profiling>on : -pg ;
+flags vacpp LINKFLAGS <profiling>on : -pg ;
+
+flags vacpp CFLAGS <cflags> ;
+flags vacpp C++FLAGS <cxxflags> ;
+flags vacpp DEFINES <define> ;
+flags vacpp UNDEFS <undef> ;
+flags vacpp HDRS <include> ;
+flags vacpp STDHDRS <sysinclude> ;
+flags vacpp LINKFLAGS <linkflags> ;
+flags vacpp ARFLAGS <arflags> ;
+
+flags vacpp LIBPATH <library-path> ;
+flags vacpp NEEDLIBS <library-file> ;
+flags vacpp FINDLIBS <find-shared-library> ;
+flags vacpp FINDLIBS <find-static-library> ;
+
+# Select the compiler name according to the threading model.
+flags vacpp VA_C_COMPILER <threading>single : xlc ;
+flags vacpp VA_C_COMPILER <threading>multi : xlc_r ;
+flags vacpp VA_CXX_COMPILER <threading>single : xlC ;
+flags vacpp VA_CXX_COMPILER <threading>multi : xlC_r ;
+
+actions vacpp.link bind NEEDLIBS
+{
+ $(ROOT)/$(VA_CXX_COMPILER) $(LINKFLAGS) -o "$(<[1])" -L$(LIBPATH) -L$(STDLIBPATH) "$(>)" "$(NEEDLIBS)" "$(NEEDLIBS)" -l$(FINDLIBS)
+}
+
+actions vacpp.compile.c
+{
+ $(ROOT)/$(VA_C_COMPILER) -c -I$(BOOST_ROOT) -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -o "$(<)" "$(>)"
+}
+
+actions vacpp.compile.c++
+{
+ $(ROOT)/$(VA_CXX_COMPILER) -c -I$(BOOST_ROOT) -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(C++FLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -o "$(<)" "$(>)"
+}
+
+actions updated together piecemeal vacpp.archive
+{
+ ar ru$(ARFLAGS:E="") "$(<)" "$(>)"
+}
Added: boost-jam/boost-build/branches/upstream/current/tools/xsltproc.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/tools/xsltproc.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/tools/xsltproc.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,87 @@
+# Copyright (C) 2003 Doug Gregor. 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.
+
+# This module defines rules to apply an XSLT stylesheet to an XML file
+# using the xsltproc driver, part of libxslt.
+#
+# Note: except for 'init', this modules does not provide any rules
+# for end users.
+
+import feature ;
+import regex ;
+import common ;
+
+feature.feature xsl:param : : free ;
+feature.feature xsl:path : : free ;
+
+# Initialize xsltproc support. The parameters are:
+# xsltproc: The xsltproc executable
+rule init ( xsltproc ? )
+{
+ if ! $(xsltproc)
+ {
+ xsltproc = [ modules.peek : XSLTPROC ] ;
+ }
+
+ if ! $(.initialized)
+ {
+ $(.initialized) = true ;
+ .xsltproc = $(xsltproc) ;
+ }
+}
+
+rule compute-xslt-flags ( target : properties * )
+{
+ local flags ;
+ # Translate <xsl:param> into command line flags.
+ for local param in [ feature.get-values <xsl:param> : $(properties) ]
+ {
+ local namevalue = [ regex.split $(param) "=" ] ;
+ flags += --stringparam $(namevalue[1]) $(namevalue[2]) ;
+ }
+ # Translate <xsl:path>
+ for local path in [ feature.get-values <xsl:path> : $(properties) ]
+ {
+ flags += --path $(path:G=) ;
+ }
+
+ return $(flags) ;
+}
+
+
+rule xslt ( target : source stylesheet : properties * )
+{
+ STYLESHEET on $(target) = $(stylesheet) ;
+ FLAGS on $(target) = [ compute-xslt-flags $(target) : $(properties) ] ;
+ NAME on $(target) = $(.xsltproc) ;
+
+ CATALOG = [ common.variable-setting-command "XML_CATALOG_FILES" "catalog.xml" ] ;
+ xslt-xsltproc $(target) : $(source) ;
+}
+
+rule xslt-dir ( target : source stylesheet : properties * : dirname )
+{
+ STYLESHEET on $(target) = $(stylesheet) ;
+ FLAGS on $(target) = [ compute-xslt-flags $(target) : $(properties) ] ;
+ DIRECTORY on $(target) = $(dirname) ;
+ NAME on $(target) = $(.xsltproc) ;
+ CATALOG = [ common.variable-setting-command "XML_CATALOG_FILES" "catalog.xml" ] ;
+ xslt-xsltproc-dir $(target) : $(source) ;
+}
+
+
+actions xslt-xsltproc
+{
+ $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --xinclude -o "$(<)" "$(STYLESHEET)" "$(>)"
+}
+
+actions xslt-xsltproc-dir
+{
+ $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --xinclude -o "$(DIRECTORY)/" "$(STYLESHEET)" "$(>)"
+}
+
+IMPORT $(__name__) : xslt : : xslt ;
+IMPORT $(__name__) : xslt-dir : : xslt-dir ;
Added: boost-jam/boost-build/branches/upstream/current/user-config.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/user-config.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/user-config.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,68 @@
+# 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.
+
+# This file is used to configure your Boost.Build installation. Please read
+# the user manual to find out where to put it.
+
+# Toolset declarations are most important in this file. The tell Boost.Build
+# what compilers are available and where to look for them. The first toolset
+# will become "default" one.
+# Some important libraries can also be configured.
+# Uncomment relevant parts to suite your local configuration and preferences.
+
+import toolset : using ;
+
+# GCC configuration
+
+# Configure gcc (default version)
+# using gcc ;
+
+# Configure specific gcc version, giving alternative name to use
+# using gcc : 3.2 g++-3.2 ;
+
+# MSVC configuration
+
+# Configure msvc (default version, searched in standard location
+# and PATH).
+# using msvc ;
+
+# Borland configuration
+# using borland ;
+
+
+# STLPort configuration
+
+# Configure, specifying location of STLPort headers.
+# Libraries must be either not needed, or available to
+# the compiler by default
+# using stlport : : /usr/include/stlport ;
+
+# Configure, specifying locatioh of both headers and libraries
+# using stlport : : /usr/include/stlport : /usr/lib ;
+
+
+# QT configuration
+
+# Configure, assuming QTDIR gives the installation prefix
+# using qt ;
+
+# Configure with explicit installation prefix
+# using qt : /usr/opt/qt ;
+
+# xsltproc (from libxslt) configuration
+# using xsltproc ;
+
+# BoostBook configuration. Please see BoostBook for documentation
+# on this.
+# using boostbook ;
+# using boostbook : /home/gregod/Projects/share/docbook-xsl-1.60.1/
+# : /home/gregod/Projects/share/docbook-dtd-4.2/
+# ;
+
+
+
+
+
+
Added: boost-jam/boost-build/branches/upstream/current/util/assert.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/assert.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/assert.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,112 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+import errors : error-skip-frames lol->list ;
+import modules ;
+
+# assert the equality of A and B
+rule equal ( a * : b * )
+{
+ if $(a) != $(b)
+ {
+ error-skip-frames 3 assertion failure: \"$(a)\" "!=" \"$(b)\" ;
+ }
+}
+
+# assert that EXPECTED is the result of calling RULE-NAME with the
+# given arguments
+rule result ( expected * : rule-name args * : * )
+{
+ local result ;
+ module [ CALLER_MODULE ]
+ {
+ modules.poke assert : result
+ : [ $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+
+ if $(result) != $(expected)
+ {
+ error-skip-frames 3 assertion failure: "[" $(rule-name)
+ [ lol->list $(args) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ]
+ "]"
+ : expected: \"$(expected)\"
+ : got: \"$(result)\" ;
+ }
+}
+
+# assert that the given variable is nonempty.
+rule nonempty-variable ( name )
+{
+ local value = [ modules.peek [ CALLER_MODULE ] : $(name) ] ;
+
+ if ! $(value)-is-nonempty
+ {
+ error-skip-frames 3 assertion failure: expecting non-empty variable $(variable) ;
+ }
+}
+
+# assert that the result of calling RULE-NAME on the given arguments
+# has a true logical value (is neither an empty list nor all empty
+# strings).
+rule true ( rule-name args * : * )
+{
+ local result ;
+ module [ CALLER_MODULE ]
+ {
+ modules.poke assert : result
+ : [ $(1) : $(2) $(3) : $(4)
+ : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+
+ if ! $(result)
+ {
+ error-skip-frames 3 assertion failure: expecting true result from
+ "[" $(rule-name)
+ [ lol->list $(args) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ]
+ "]" ;
+ }
+}
+
+# assert that the result of calling RULE-NAME on the given arguments
+# has a false logical value (is either an empty list or all empty
+# strings).
+rule false ( rule-name args * : * )
+{
+ local result ;
+ module [ CALLER_MODULE ]
+ {
+ modules.poke assert : result
+ : [ $(1) : $(2) $(3) : $(4)
+ : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+
+ if $(result)
+ {
+ error-skip-frames 3 assertion failure: expecting false result from
+ "[" $(rule-name)
+ [ lol->list $(args) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ]
+ "]" : got [ lol->list $(result) ] instead ;
+ }
+}
+
+# assert that 'element' is present in 'list'.
+rule "in" ( element : list * )
+{
+ if ! $(element) in $(list)
+ {
+ error-skip-frames 3 assertion failure: expecting $(element) in
+ "[" $(list) "]" ;
+ }
+}
+
+# assert that 'element' is not present in 'list'.
+rule not-in ( element : list * )
+{
+ if $(element) in $(list)
+ {
+ error-skip-frames 3 assertion failure: did not expect $(element) in
+ "[" $(list) "]" ;
+ }
+}
\ No newline at end of file
Added: boost-jam/boost-build/branches/upstream/current/util/container.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/container.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/container.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,312 @@
+# (C) Copyright Rene Rivera, 2002.
+#
+# See accompanying license for terms and conditions of use.
+#
+
+# Various container classes.
+
+import "class" : * ;
+
+# Base for container objects. This lets us construct recursive structures.
+# That is containers with containers in them, specifically so we can tell
+# literal values from node values.
+#
+class node
+{
+ rule __init__ (
+ value ? # Optional value to set node to initially.
+ )
+ {
+ self.value = $(value) ;
+ }
+
+ # Set the value of this node, passing nothing will clear it.
+ #
+ rule set ( value ? )
+ {
+ self.value = $(value) ;
+ }
+
+ # Get the value of this node.
+ #
+ rule get ( )
+ {
+ return $(self.value) ;
+ }
+}
+
+
+# A simple vector. Interface mimics the C++ std::vector and std::list,
+# with the exception that indices are one (1) based to follow Jam standard.
+#
+# TODO: Possibly add assertion checks.
+#
+class vector : node
+{
+ import numbers : range ;
+ import utility ;
+ import sequence ;
+
+ rule __init__ (
+ values * # Initial contents of vector.
+ )
+ {
+ node.__init__ ;
+ self.value = $(values) ;
+ }
+
+ # Get the value of the first element.
+ #
+ rule front ( )
+ {
+ return $(self.value[1]) ;
+ }
+
+ # Get the value of the last element.
+ #
+ rule back ( )
+ {
+ return $(self.value[-1]) ;
+ }
+
+ # Get the value of the element at the given index, one based.
+ # Access to elements of recursive structures is supported directly.
+ # Specifying additional index values recursively accesses the elements as
+ # containers. For example: [ $(v).at 1 : 2 ] would retrieve the second element
+ # of our first element. This assuming the first element is a container.
+ #
+ rule at (
+ index # The element index, one based.
+ : * # Additional indices to access recursively.
+ )
+ {
+ local r = $(self.value[$(index)]) ;
+ if $(2)
+ {
+ r = [ $(r).at $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+ return $(r) ;
+ }
+
+ # Get the value contained in the given element. This has the same
+ # functionality and interface as "at" but in addition gets the value
+ # of the referenced element, assuming it's a "node".
+ #
+ rule get-at (
+ index # The element index, one based.
+ : * # Additional indices to access recursively.
+ )
+ {
+ local r = $(self.value[$(index)]) ;
+ if $(2)
+ {
+ r = [ $(r).at $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+ return [ $(r).get ] ;
+ }
+
+ # Insert the given value into the front of the vector pushing the
+ # rest of the elements back.
+ #
+ rule push-front (
+ value # Value to become first element.
+ )
+ {
+ self.value = $(value) $(self.value) ;
+ }
+
+ # Remove the front element from the vector. Does not return the value.
+ # No effect if vector is empty.
+ #
+ rule pop-front ( )
+ {
+ self.value = $(self.value[2-]) ;
+ }
+
+ # Add the given value at the end of the vector.
+ #
+ rule push-back (
+ value # Value to become back element.
+ )
+ {
+ self.value += $(value) ;
+ }
+
+ # Remove the back element from the vector. Does not return the value.
+ # No effect if vector is empty.
+ #
+ rule pop-back ( )
+ {
+ self.value = $(self.value[1--2]) ;
+ }
+
+ # Insert the given value at the given index, one based. The values
+ # at and to the right of the of the index are push back to make room
+ # for the new value.
+ #
+ rule insert (
+ index # The index to insert at, one based.
+ : value # The value to insert.
+ )
+ {
+ local left = $(self.value[1-$(index)]) ;
+ left = $(left[1--2]) ;
+ local right = $(self.value[$(index)-]) ;
+ self.value = $(left) $(value) $(right) ;
+ }
+
+ # Remove one or more elements from the vector. The range is inclusive,
+ # and not specifying an end is equivalent to the [start,start] range.
+ #
+ rule erase (
+ start # Index of first element ro remove.
+ end ? # Optional, index of last element to remove.
+ )
+ {
+ end ?= $(start) ;
+ local left = $(self.value[1-$(start)]) ;
+ left = $(left[1--2]) ;
+ local right = $(self.value[$(end)-]) ;
+ right = $(right[2-]) ;
+ self.value = $(left) $(right) ;
+ }
+
+ # Remove all elements from the vector.
+ #
+ rule clear ( )
+ {
+ self.value = ;
+ }
+
+ # The number of elements in the vector.
+ #
+ rule size ( )
+ {
+ return [ sequence.length $(self.value) ] ;
+ }
+
+ # Returns "true" if there are NO elements in the vector, empty
+ # otherwise.
+ #
+ rule empty ( )
+ {
+ if ! $(self.value)
+ {
+ return true ;
+ }
+ }
+
+ # Returns the list of all valid indices for this vector.
+ rule indices ( )
+ {
+ if ! [ empty ]
+ {
+ local size = [ size ] ;
+ return [ range 1 : $(size) ] $(size) ;
+ }
+ }
+
+ # Returns the textual representation of content.
+ rule str ( )
+ {
+ return "[" [ sequence.transform utility.str : $(self.value) ] "]" ;
+ }
+
+ # Sorts the vector inplace, calling 'utility.less' for
+ # comparisons.
+ rule sort ( )
+ {
+ self.value =
+ [ sequence.insertion-sort $(self.value) : utility.less ] ;
+ }
+
+ # Returns true if content is equal to the content of other vector.
+ # Uses 'utility.equal' for comparison.
+ rule equal ( another )
+ {
+ local mismatch ;
+ if [ size ] = [ $(another).size ]
+ {
+ for local i in [ indices ]
+ {
+ if ! [ utility.equal [ at $(i) ] [ $(another).at $(i) ] ]
+ {
+ mismatch = true ;
+ }
+ }
+ }
+ else
+ {
+ mismatch = true ;
+ }
+
+ if ! $(mismatch)
+ {
+ return true ;
+ }
+ }
+}
+
+local rule __test__ ( )
+{
+ import assert ;
+ import "class" : new ;
+
+ local l = [ new vector ] ;
+ assert.result 0 : $(l).size ;
+ assert.result : $(l).indices ;
+ assert.result "[" "]" : $(l).str ;
+ $(l).push-back b ;
+ $(l).push-front a ;
+ assert.result 1 2 : $(l).indices ;
+ assert.result "[" a b "]" : $(l).str ;
+ assert.result a : $(l).front ;
+ assert.result b : $(l).back ;
+ $(l).insert 2 : d ;
+ $(l).insert 2 : c ;
+ $(l).insert 4 : f ;
+ $(l).insert 4 : e ;
+ $(l).pop-back ;
+ assert.result 5 : $(l).size ;
+ assert.result d : $(l).at 3 ;
+ $(l).pop-front ;
+ assert.result c : $(l).front ;
+ assert.false $(l).empty ;
+ $(l).erase 3 4 ;
+ assert.result 2 : $(l).size ;
+
+ local l2 = [ new vector q w e r t y ] ;
+ assert.result 6 : $(l2).size ;
+ $(l).push-back $(l2) ;
+ assert.result 3 : $(l).size ;
+ local l2-alias = [ $(l).back ] ;
+ assert.result e : $(l2-alias).at 3 ;
+ $(l).clear ;
+ assert.true $(l).empty ;
+ assert.false $(l2-alias).empty ;
+ $(l2).pop-back ;
+ assert.result t : $(l2-alias).back ;
+
+ local l3 = [ new vector ] ;
+ $(l3).push-back [ new vector 1 2 3 4 5 ] ;
+ $(l3).push-back [ new vector a b c ] ;
+ assert.result "[" "[" 1 2 3 4 5 "]" "[" a b c "]" "]" : $(l3).str ;
+ $(l3).push-back [ new vector [ new vector x y z ] [ new vector 7 8 9 ] ] ;
+ assert.result 1 : $(l3).at 1 : 1 ;
+ assert.result b : $(l3).at 2 : 2 ;
+ assert.result a b c : $(l3).get-at 2 ;
+ assert.result 7 8 9 : $(l3).get-at 3 : 2 ;
+
+ local l4 = [ new vector 4 3 6 ] ;
+ $(l4).sort ;
+ assert.result 3 4 6 : $(l4).get ;
+
+ assert.false $(l4).equal $(l3) ;
+ local l5 = [ new vector 3 4 6 ] ;
+ assert.true $(l4).equal $(l5) ;
+ # Check that vectors of different sizes are considered non-equal
+ $(l5).pop-back ;
+ assert.false $(l4).equal $(l5) ;
+ local l6 = [ new vector [ new vector 1 2 3 ] ] ;
+ assert.true $(l6).equal [ new vector [ new vector 1 2 3 ] ] ;
+}
Added: boost-jam/boost-build/branches/upstream/current/util/doc.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/doc.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/doc.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,903 @@
+# (C) Copyright Rene Rivera, 2002-2003.
+#
+# See accompanying license for terms and conditions of use.
+#
+
+# Documentation system, handles --help requests.
+# It defines rules that attach documentation to modules, rules, and variables.
+# Collects and generates documentation for the various parts of the build system.
+# The documentation is collected from comments integrated into the code.
+
+import modules ;
+import print ;
+import set ;
+import container ;
+import "class" ;
+import sequence ;
+
+# The type of output to generate.
+# "console" is formated text echoed to the console (the default);
+# "text" is formated text appended to the output file;
+# "html" is HTLM output to the file.
+#
+help-output = console ;
+
+# The file to output documentation to when generating "text" or "html"
+# help. This is without extension as the extension is determined by the
+# type of output.
+#
+help-output-file = help ;
+
+# Whether to include local rules in help output.
+#
+.option.show-locals ?= ;
+
+# When showing documentation for a module, whether to also generate
+# automatically the detailed docs for each item in the module.
+#
+.option.detailed ?= ;
+
+# Generate debug output as the help is generated and modules
+# are parsed.
+#
+.option.debug ?= ;
+
+# Enable or disable a documentation option.
+#
+local rule set-option (
+ option # The option name.
+ : value ? # Enabled (non-empty), or disabled (empty)
+ )
+{
+ .option.$(option) = $(value) ;
+}
+
+# Set the type of output.
+#
+local rule set-output (
+ type
+ )
+{
+ help-output = $(type) ;
+}
+
+# Set the output to a file.
+#
+local rule set-output-file (
+ file
+ )
+{
+ help-output-file = $(file) ;
+}
+
+# Extracts the brief comment from a complete comment. The brief
+# comment is the first sentence.
+#
+local rule brief-comment (
+ docs * # The comment documentation.
+ )
+{
+ local d = $(docs:J=" ") ;
+ local p = [ MATCH ".*([.])$" : $(d) ] ;
+ if ! $(p) { d = $(d)"." ; }
+ d = $(d)" " ;
+ local m = [ MATCH "^([^.]+[.])(.*)" : $(d) ] ;
+ local brief = $(m[1]) ;
+ while $(m[2]) && [ MATCH "^([^ ])" : $(m[2]) ]
+ {
+ m = [ MATCH "^([^.]+[.])(.*)" : $(m[2]) ] ;
+ brief += $(m[1]) ;
+ }
+ return $(brief:J="") ;
+}
+
+# Specifies the documentation for the current module.
+#
+local rule set-module-doc (
+ module-name ? # The name of the module to document.
+ : docs * # The documentation for the module.
+ )
+{
+ module-name ?= * ;
+
+ $(module-name).brief = [ brief-comment $(docs) ] ;
+ $(module-name).docs = $(docs) ;
+
+ if ! $(module-name) in $(documented-modules)
+ {
+ documented-modules += $(module-name) ;
+ }
+}
+
+# Specifies the documentation for the current module.
+#
+local rule set-module-copyright (
+ module-name ? # The name of the module to document.
+ : copyright * # The copyright for the module.
+ )
+{
+ module-name ?= * ;
+
+ $(module-name).copy-brief = [ brief-comment $(copyright) ] ;
+ $(module-name).copy-docs = $(docs) ;
+
+ if ! $(module-name) in $(documented-modules)
+ {
+ documented-modules += $(module-name) ;
+ }
+}
+
+# Specifies the documentation for a rule in the current module.
+# If called in the global module, this documents a global rule.
+#
+local rule set-rule-doc (
+ name # The name of the rule.
+ module-name ? # The name of the module to document.
+ is-local ? # Whether the rule is local to the module.
+ : docs * # The documentation for the rule.
+ )
+{
+ module-name ?= * ;
+
+ $(module-name).$(name).brief = [ brief-comment $(docs) ] ;
+ $(module-name).$(name).docs = $(docs) ;
+ $(module-name).$(name).is-local = $(is-local) ;
+
+ if ! $(name) in $($(module-name).rules)
+ {
+ $(module-name).rules += $(name) ;
+ }
+}
+
+# Specify a class, will turn a rule into a class.
+#
+local rule set-class-doc (
+ name # The name of the class.
+ module-name ? # The name of the module to document.
+ : super-name ? # The super class name.
+ )
+{
+ module-name ?= * ;
+
+ $(module-name).$(name).is-class = true ;
+ $(module-name).$(name).super-name = $(super-name) ;
+ $(module-name).$(name).class-rules =
+ [ MATCH "^($(name)[.].*)" : $($(module-name).rules) ] ;
+ $(module-name).$($(module-name).$(name).class-rules).is-class-rule = true ;
+
+ $(module-name).classes += $(name) ;
+ $(module-name).class-rules += $($(module-name).$(name).class-rules) ;
+ $(module-name).rules =
+ [ set.difference $($(module-name).rules) :
+ $(name) $($(module-name).$(name).class-rules) ] ;
+}
+
+# Set the argument call signature of a rule.
+#
+local rule set-rule-arguments-signature (
+ name # The name of the rule.
+ module-name ? # The name of the module to document.
+ : signature * # The arguments signature.
+ )
+{
+ module-name ?= * ;
+
+ $(module-name).$(name).signature = $(signature) ;
+}
+
+# Specifies the documentation for an argument of a rule.
+#
+local rule set-argument-doc (
+ name # The name of the argument.
+ qualifier # Argument syntax qualifier, "*", "+", etc.
+ rule-name # The name of the rule.
+ module-name ? # THe optional name of the module.
+ : docs * # The documentation.
+ )
+{
+ module-name ?= * ;
+
+ $(module-name).$(rule-name).args.$(name).qualifier = $(qualifier) ;
+ $(module-name).$(rule-name).args.$(name).docs = $(docs) ;
+
+ if ! $(name) in $($(module-name).$(rule-name).args)
+ {
+ $(module-name).$(rule-name).args += $(name) ;
+ }
+}
+
+# Specifies the documentation for a variable in the current module.
+# If called in the global module, the global variable is documented.
+#
+local rule set-variable-doc (
+ name # The name of the variable.
+ default # The default value.
+ initial # The initial value.
+ module-name ? # The name of the module to document.
+ : docs * # The documentation for the variable.
+ )
+{
+ module-name ?= * ;
+
+ $(module-name).$(name).brief = [ brief-comment $(docs) ] ;
+ $(module-name).$(name).default = $(default) ;
+ $(module-name).$(name).initial = $(initial) ;
+ $(module-name).$(name).docs = $(docs) ;
+
+ if ! $(name) in $($(module-name).variables)
+ {
+ $(module-name).variables += $(name) ;
+ }
+}
+
+# Generates a general description of the documentation and help system.
+#
+local rule print-help-top ( )
+{
+ print.section "Available Help"
+ These are the available options for obtaining documentation.
+ Some options have additional instructions on how to get more
+ detailed information. Multiple options are allowed and
+ sometimes required. For example, the options that configure
+ the help system still require a regular help request option
+ for any output to be generated.
+ ;
+ print.list-start ;
+ print.list-item --help; This help message. ;
+ print.list-item --help-usage; How to invoke '"bjam".' ;
+ print.list-item --help-all; Brief information on available modules. ;
+ print.list-item --help <module-name>; Get information about a module. ;
+ print.list-item --help-options; Options for controlling the help display. ;
+ print.list-item --help-output <type>; The type of output to genetare.
+ '"console" is formated text echoed to the console (the default);'
+ '"text" is formated text appended to the output file;'
+ '"html" is HTLM output to the file.' ;
+ print.list-item --help-output-file <file>; The file to output the documentation. ;
+ print.list-end ;
+}
+
+# Generate Jam/Boost.Jam command usage information.
+#
+local rule print-help-usage ( )
+{
+ print.section "Boost.Jam Usage"
+ "bjam [ options... ] targets..."
+ ;
+ print.list-start ;
+ print.list-item -a;
+ Build all targets, even if they are current. ;
+ print.list-item -fx;
+ Read '"x"' as the Jamfile for building instead of searching
+ for the Boost.Build system. ;
+ print.list-item -jx;
+ Run up to '"x"' commands concurrently. ;
+ print.list-item -n;
+ Do not execute build commands. Instead print out the commands
+ as they would be executed if building. ;
+ print.list-item -ox;
+ Write the build commands to the file '"x"'. ;
+ print.list-item -q;
+ Quit as soon as the build of a target fails. Specifying this prevents the
+ attempt of building as many targets as possible regardless of failures. ;
+ print.list-item -sx=y;
+ Sets a Jam variable '"x"' to the value '"y"', overriding any value that
+ variable would have from the environment. ;
+ print.list-item -tx;
+ Rebuild the target '"x"', even if it is up-to-date. ;
+ print.list-item -v;
+ Display the version of bjam. ;
+ print.list-item --x;
+ Option '"x"' is ignored but considered and option. The option is then
+ available from the '"ARGV"' variable. ;
+ print.list-item -dn;
+ Enables output of diagnostic messages. The debug level '"n"' and all
+ below it are enabled by this option. ;
+ print.list-item -d+n;
+ Enables output of diagnostic messages. Only the output for debug level '"n"'
+ is enabled. ;
+ print.list-end ;
+ print.section "Debug Levels"
+ Each debug level shows a different set of information. Usually with the higher
+ levels producing more verbose information. The following levels are supported:
+ ;
+ print.list-start ;
+ print.list-item 0;
+ Turn off all diagnostic output. Only errors are reported. ;
+ print.list-item 1;
+ Show the actions taken for building targets, as they are executed. ;
+ print.list-item 2;
+ Show "quiet" actions and display all action text, as they are executed. ;
+ print.list-item 3;
+ Show dependency analysis, and target/source timestamps/paths. ;
+ print.list-item 4;
+ Show arguments of shell invocations. ;
+ print.list-item 5;
+ Show rule invocations and variable expansions. ;
+ print.list-item 6;
+ Show directory/header file/archive scans, and attempts at binding to targets. ;
+ print.list-item 7;
+ Show variable settings. ;
+ print.list-item 8;
+ Show variable fetches, variable expansions, and evaluation of '"if"' expressions. ;
+ print.list-item 9;
+ Show variable manipulation, scanner tokens, and memory usage. ;
+ print.list-item 10;
+ Show execution times for rules. ;
+ print.list-item 11;
+ Show parsing progress of Jamfiles. ;
+ print.list-item 12;
+ Show graph for target dependencies. ;
+ print.list-item 13;
+ Show changes in target status (fate). ;
+ print.list-end ;
+}
+
+# Generates description of options controlling the help system.
+# This automatically reads the options as all variables in the doc
+# module of the form ".option.*".
+#
+local rule print-help-options (
+ module-name # The doc module.
+ )
+{
+ print.section "Help Options"
+ These are all the options available for enabling or disabling
+ to control the help system in various ways. Options can be enabled
+ or disabled with '"--help-enable-<option>"', and "'--help-disable-<option>'"
+ respectively.
+ ;
+ local options-to-list = [ MATCH ^[.]option[.](.*) : $($(module-name).variables) ] ;
+ if $(options-to-list)
+ {
+ print.list-start ;
+ for local option in [ sequence.insertion-sort $(options-to-list) ]
+ {
+ local def = disabled ;
+ if $($(module-name)..option.$(option).default) != "(empty)"
+ {
+ def = enabled ;
+ }
+ print.list-item $(option): $($(module-name)..option.$(option).docs)
+ Default is $(def). ;
+ }
+ print.list-end ;
+ }
+}
+
+# Generate brief documentation for all the known items in the section
+# for a module. Possible sections are: "rules", and "variables".
+#
+local rule print-help-module-section (
+ module # The module name.
+ section # rules or variables.
+ : section-head # The title of the section.
+ section-description * # The detailed description of the section.
+ )
+{
+ if $($(module).$(section))
+ {
+ print.section $(section-head) $(section-description) ;
+ print.list-start ;
+ for local item in [ sequence.insertion-sort $($(module).$(section)) ]
+ {
+ local show = ;
+ if ! $($(module).$(item).is-local)
+ {
+ show = yes ;
+ }
+ if $(.option.show-locals)
+ {
+ show = yes ;
+ }
+ if $(show)
+ {
+ print.list-item $(item): $($(module).$(item).brief) ;
+ }
+ }
+ print.list-end ;
+ }
+}
+
+# Generate documentation for possible modules. We attempt to list all known
+# modules, and a brief description of each.
+#
+local rule print-help-all (
+ ignored # Usually the module name, but is ignored here.
+ )
+{
+ print.section "Modules"
+ "These are all the known modules. Use --help <module> to get more"
+ "detailed information."
+ ;
+ if $(documented-modules)
+ {
+ print.list-start ;
+ for local module-name in [ sequence.insertion-sort $(documented-modules) ]
+ {
+ # The brief docs for each module.
+ print.list-item $(module-name): $($(module-name).brief) ;
+ }
+ print.list-end ;
+ }
+ # The documentation for each module when details are requested.
+ if $(documented-modules) && $(.option.detailed)
+ {
+ for local module-name in [ sequence.insertion-sort $(documented-modules) ]
+ {
+ # The brief docs for each module.
+ print-help-module $(module-name) ;
+ }
+ }
+}
+
+# Generate documentation for a module. Basic information about
+# the module is generated.
+#
+local rule print-help-module (
+ module-name # The module to generate docs for.
+ )
+{
+ # Print the docs.
+ print.section "Module '$(module-name)'" $($(module-name).docs) ;
+
+ # Print out the documented classes.
+ print-help-module-section $(module-name) classes : "Module '$(module-name)' classes"
+ Use --help $(module-name).<class-name> to get more information. ;
+
+ # Print out the documented rules.
+ print-help-module-section $(module-name) rules : "Module '$(module-name)' rules"
+ Use --help $(module-name).<rule-name> to get more information. ;
+
+ # Print out the documented variables.
+ print-help-module-section $(module-name) variables : "Module '$(module-name)' variables"
+ Use --help $(module-name).<variable-name> to get more information. ;
+
+ # Print out all the same information but indetailed form.
+ if $(.option.detailed)
+ {
+ print-help-classes $(module-name) ;
+ print-help-rules $(module-name) ;
+ print-help-variables $(module-name) ;
+ }
+}
+
+# Generate documentation for a set of rules in a module.
+#
+local rule print-help-rules (
+ module-name # Module of the rules.
+ : name * # Optional list of rules to describe.
+ )
+{
+ name ?= $($(module-name).rules) ;
+ if [ set.intersection $(name) : $($(module-name).rules) $($(module-name).class-rules) ]
+ {
+ # Print out the given rules.
+ for local rule-name in [ sequence.insertion-sort $(name) ]
+ {
+ if $(.option.show-locals) || ! $($(module-name).$(rule-name).is-local)
+ {
+ local signature = $($(module-name).$(rule-name).signature:J=" ") ;
+ signature ?= "" ;
+ print.section "Rule '$(module-name).$(rule-name) ( $(signature) )'"
+ $($(module-name).$(rule-name).docs) ;
+ if $($(module-name).$(rule-name).args)
+ {
+ print.list-start ;
+ for local arg-name in $($(module-name).$(rule-name).args)
+ {
+ print.list-item $(arg-name): $($(module-name).$(rule-name).args.$(arg-name).docs) ;
+ }
+ print.list-end ;
+ }
+ }
+ }
+ }
+}
+
+# Generate documentation for a set of classes in a module.
+#
+local rule print-help-classes (
+ module-name # Module of the classes.
+ : name * # Optional list of classes to describe.
+ )
+{
+ name ?= $($(module-name).classes) ;
+ if [ set.intersection $(name) : $($(module-name).classes) ]
+ {
+ # Print out the given classes.
+ for local class-name in [ sequence.insertion-sort $(name) ]
+ {
+ if $(.option.show-locals) || ! $($(module-name).$(class-name).is-local)
+ {
+ local signature = $($(module-name).$(class-name).signature:J=" ") ;
+ signature ?= "" ;
+ print.section "Class '$(module-name).$(class-name) ( $(signature) )'"
+ $($(module-name).$(class-name).docs)
+ "Inherits from '"$($(module-name).$(class-name).super-name)"'." ;
+ if $($(module-name).$(class-name).args)
+ {
+ print.list-start ;
+ for local arg-name in $($(module-name).$(class-name).args)
+ {
+ print.list-item $(arg-name): $($(module-name).$(class-name).args.$(arg-name).docs) ;
+ }
+ print.list-end ;
+ }
+ }
+
+ # Print out the documented rules of the class.
+ print-help-module-section $(module-name) $(class-name).class-rules : "Class '$(module-name).$(class-name)' rules"
+ Use --help $(module-name).<rule-name> to get more information. ;
+
+ # Print out all the rules if details are requested.
+ if $(.option.detailed)
+ {
+ print-help-rules $(module-name) : $($(module-name).$(class-name).class-rules) ;
+ }
+ }
+ }
+}
+
+# Generate documentation for a set of variables in a module.
+#
+local rule print-help-variables (
+ module-name ? # Module of the variables.
+ : name * # Optional list of variables to describe.
+ )
+{
+ name ?= $($(module-name).variables) ;
+ if [ set.intersection $(name) : $($(module-name).variables) ]
+ {
+ # Print out the given variables.
+ for local variable-name in [ sequence.insertion-sort $(name) ]
+ {
+ print.section "Variable '$(module-name).$(variable-name)'" $($(module-name).$(variable-name).docs) ;
+ if $($(module-name).$(variable-name).default) ||
+ $($(module-name).$(variable-name).initial)
+ {
+ print.list-start ;
+ if $($(module-name).$(variable-name).default)
+ {
+ print.list-item "default value:" '$($(module-name).$(variable-name).default:J=" ")' ;
+ }
+ if $($(module-name).$(variable-name).initial)
+ {
+ print.list-item "initial value:" '$($(module-name).$(variable-name).initial:J=" ")' ;
+ }
+ print.list-end ;
+ }
+ }
+ }
+}
+
+local rule __test__
+{
+}
+
+ws = " " ;
+
+# Extract the text from a block of comments.
+#
+local rule extract-comment (
+ var # The name of the variable to extract from.
+ )
+{
+ local comment = ;
+ local line = $($(var)[1]) ;
+ local l = [ MATCH "^[$(ws)]*(#)(.*)$" : $(line) ] ;
+ while $(l[1]) && $($(var))
+ {
+ if $(l[2]) { comment += [ MATCH "^[$(ws)](.*)$" : $(l[2]) ] ; }
+ else { comment += "" ; }
+ $(var) = $($(var)[2-]) ;
+ line = $($(var)[1]) ;
+ l = [ MATCH "^[$(ws)]*(#)(.*)$" : $(line) ] ;
+ }
+ return $(comment) ;
+}
+
+# Extract s single line of Jam syntax, ignoring any comments.
+#
+local rule extract-syntax (
+ var # The name of the variable to extract from.
+ )
+{
+ local syntax = ;
+ local line = $($(var)[1]) ;
+ while ! $(syntax) && ! [ MATCH "^[$(ws)]*(#)" : $(line) ] && $($(var))
+ {
+ local m = [ MATCH "^[$(ws)]*(.*)$" : $(line) ] ;
+ if $(m) && ! $(m) = ""
+ {
+ syntax = $(m) ;
+ }
+ $(var) = $($(var)[2-]) ;
+ line = $($(var)[1]) ;
+ }
+ return $(syntax) ;
+}
+
+# Extract the next token, this is either a single Jam construct
+# or a comment as a single token.
+#
+local rule extract-token (
+ var # The name of the variable to extract from.
+ )
+{
+ local parts = ;
+ while ! $(parts)
+ {
+ parts = [ MATCH "^[$(ws)]*([^$(ws)]+)[$(ws)]*(.*)" : $($(var)[1]) ] ;
+ if ! $(parts)
+ {
+ $(var) = $($(var)[2-]) ;
+ }
+ }
+ local token = ;
+ if [ MATCH "^(#)" : $(parts[1]) ]
+ {
+ token = $(parts:J=" ") ;
+ $(var) = $($(var)[2-]) ;
+ }
+ else
+ {
+ token = $(parts[1]) ;
+ $(var) = $(parts[2-]:J=" ") $($(var)[2-]) ;
+ }
+ return $(token) ;
+}
+
+# Scan for a rule declaration as the next item in the variable.
+#
+local rule scan-rule (
+ syntax ? # The first part of the text which contains the rule declaration.
+ : var # The name of the variable to extract from.
+ )
+{
+ local rule-parts =
+ [ MATCH "^[$(ws)]*(rule|local[$(ws)]*rule)[$(ws)]+([^$(ws)]+)[$(ws)]*(.*)" : $(syntax:J=" ") ] ;
+ if $(rule-parts[1])
+ {
+ # mark as doc for rule.
+ local rule-name = $(rule-parts[2]) ;
+ if $(scope-name)
+ {
+ rule-name = $(scope-name).$(rule-name) ;
+ }
+ local is-local = [ MATCH "^(local).*" : $(rule-parts[1]) ] ;
+ if $(comment-block)
+ {
+ set-rule-doc $(rule-name) $(module-name) $(is-local) : $(comment-block) ;
+ }
+ # parse args of rule.
+ $(var) = $(rule-parts[3-]) $($(var)) ;
+ set-rule-arguments-signature $(rule-name) $(module-name) : [ scan-rule-arguments $(var) ] ;
+ # scan within this rules scope.
+ local scope-level = [ extract-token $(var) ] ;
+ local scope-name = $(rule-name) ;
+ while $(scope-level)
+ {
+ local comment-block = [ extract-comment $(var) ] ;
+ local syntax-block = [ extract-syntax $(var) ] ;
+ if [ scan-rule $(syntax-block) : $(var) ]
+ {
+ }
+ else if [ MATCH "^(\\{)" : $(syntax-block) ]
+ {
+ scope-level += "{" ;
+ }
+ else if [ MATCH "^[^\\}]*([\\}])[$(ws)]*$" : $(syntax-block) ]
+ {
+ scope-level = $(scope-level[2-]) ;
+ }
+ }
+
+ return true ;
+ }
+}
+
+# Scan the arguments of a rule.
+#
+local rule scan-rule-arguments (
+ var # The name of the variable to extract from.
+ )
+{
+ local arg-syntax = ;
+ local token = [ extract-token $(var) ] ;
+ while $(token) != "(" && $(token) != "{"
+ {
+ token = [ extract-token $(var) ] ;
+ }
+ if $(token) != "{"
+ {
+ token = [ extract-token $(var) ] ;
+ }
+ local arg-signature = ;
+ while $(token) != ")" && $(token) != "{"
+ {
+ local arg-name = ;
+ local arg-qualifier = " " ;
+ local arg-doc = ;
+ if $(token) = ":"
+ {
+ arg-signature += $(token) ;
+ token = [ extract-token $(var) ] ;
+ }
+ arg-name = $(token) ;
+ arg-signature += $(token) ;
+ token = [ extract-token $(var) ] ;
+ if [ MATCH "^([\\*\\+\\?])" : $(token) ]
+ {
+ arg-qualifier = $(token) ;
+ arg-signature += $(token) ;
+ token = [ extract-token $(var) ] ;
+ }
+ if $(token) = ":"
+ {
+ arg-signature += $(token) ;
+ token = [ extract-token $(var) ] ;
+ }
+ if [ MATCH "^(#)" : $(token) ]
+ {
+ $(var) = $(token) $($(var)) ;
+ arg-doc = [ extract-comment $(var) ] ;
+ token = [ extract-token $(var) ] ;
+ }
+ set-argument-doc $(arg-name) $(arg-qualifier) $(rule-name) $(module-name) : $(arg-doc) ;
+ }
+ while $(token) != "{"
+ {
+ token = [ extract-token $(var) ] ;
+ }
+ $(var) = "{" $($(var)) ;
+ arg-signature ?= "" ;
+ return $(arg-signature) ;
+}
+
+# Scan for a variable declaration.
+local rule scan-variable (
+ syntax ? # The first part of the text which contains the variable declaration.
+ : var # The name of the variable to extract from.
+ )
+{
+ # [1] = name, [2] = value(s)
+ local var-parts =
+ [ MATCH "^[$(ws)]*([^$(ws)]+)[$(ws)]+([\\?\\=]*)[$(ws)]+([^\\;]*)\\;" : $(syntax) ] ;
+ if $(var-parts)
+ {
+ local value = [ MATCH "^(.*)[ ]$" : $(var-parts[3-]:J=" ") ] ;
+ local default-value = "" ;
+ local initial-valie = "" ;
+ if $(var-parts[2]) = "?="
+ {
+ default-value = $(value) ;
+ default-value ?= "(empty)" ;
+ }
+ else
+ {
+ initial-value = $(value) ;
+ initial-value ?= "(empty)" ;
+ }
+ if $(comment-block)
+ {
+ set-variable-doc $(var-parts[1]) $(default-value) $(initial-value) $(module-name) : $(comment-block) ;
+ }
+ return true ;
+ }
+}
+
+# Scan a class declaration.
+local rule scan-class (
+ syntax ? # The syntax text for the class declaration.
+ )
+{
+ # [1] = class?, [2] = name, [3] = superclass
+ local class-parts =
+ [ MATCH "^[$(ws)]*([^$(ws)]+)[$(ws)]+([^$(ws)]+)[$(ws)]+:*[$(ws)]*([^$(ws);]*)" : $(syntax) ] ;
+ if $(class-parts[1]) = "class" || $(class-parts[1]) = "class.class"
+ {
+ set-class-doc $(class-parts[2]) $(module-name) : $(class-parts[3]) ;
+ }
+}
+
+# Scan a module file for documentation comments. This also
+# invokes any actions assigned to the module. The actions
+# are the rules that do the actual output of the documentation.
+# This rue is invoked as the header scan rule for the module file.
+#
+rule scan-module (
+ target # The module file.
+ : text * # The text in the file, one item per line.
+ : binding
+ )
+{
+ if $(.option.debug) { ECHO "HELP:" scanning module target '$(target)' ; }
+ local module-name = $(.module<$(target)>.name) ;
+ local module-documented = ;
+ local comment-block = ;
+ local syntax-block = ;
+ # This is a hack because we can't get the line of a file if it
+ # happens to not have a new-line termination.
+ text += "}" ;
+ while $(text)
+ {
+ comment-block = [ extract-comment text ] ;
+ syntax-block = [ extract-syntax text ] ;
+ if $(.option.debug)
+ {
+ ECHO "HELP:" comment block; '$(comment-block)' ;
+ ECHO "HELP:" syntax block; '$(syntax-block)' ;
+ }
+ if [ scan-rule $(syntax-block) : text ] { }
+ else if [ scan-variable $(syntax-block) : text ] { }
+ else if [ scan-class $(syntax-block) ] { }
+ else if [ MATCH .*([cC]opyright).* : $(comment-block:J=" ") ]
+ {
+ # mark as the copy for the module.
+ set-module-copyright $(module-name) : $(comment-block) ;
+ }
+ else if ! $(module-documented)
+ {
+ # document the module.
+ set-module-doc $(module-name) : $(comment-block) ;
+ module-documented = true ;
+ }
+ }
+ for local action in $(.module<$(target)>.actions)
+ {
+ local action-rule = [ $(action).front ] ; $(action).pop-front ;
+ local action-args = [ $(action).get ] ;
+ local ignored = [ $(action-rule) $(module-name) : $(action-args) ] ;
+ }
+}
+
+# Import scan-module to global scope, so that it's available during
+# header scanning phase.
+IMPORT $(__name__) : scan-module : : doc.scan-module ;
+
+
+# Add a scan action to perform to generate the help documentation.
+# The action rule is passed the name of the module as the first argument.
+# The second argument(s) are optional and passed directly as specified
+# here.
+#
+local rule do-scan (
+ modules + # The modules to scan and perform the action on.
+ : action * # The action rule, plus the secondary arguments to pass to the action rule.
+ )
+{
+ local targets = ;
+ for local module-file in $(modules)
+ {
+ local module-name = $(module-file:B) ;
+ .module<$(module-file)>.name = $(module-name) ;
+ if $(action)
+ {
+ .module<$(module-file)>.actions += [ class.new vector $(action) ] ;
+ }
+ HDRSCAN on $(module-file) = "^(.*).$" ;
+ HDRRULE on $(module-file) = doc.scan-module ;
+ NOTFILE $(module-name).scan ;
+ ALWAYS $(module-name).scan ;
+ INCLUDES $(module-name).scan : $(module-file) ;
+ targets += $(module-name).scan ;
+ }
+ if $(help-output) = console
+ {
+ DEPENDS all : $(targets) ;
+ }
+ if $(help-output) = text
+ {
+ print.output $(help-output-file).txt plain ;
+ ALWAYS $(help-output-file).txt ;
+ DEPENDS $(help-output-file).txt : $(targets) ;
+ DEPENDS all : $(help-output-file).txt ;
+ }
+ if $(help-output) = html
+ {
+ print.output $(help-output-file).html html ;
+ ALWAYS $(help-output-file).html ;
+ DEPENDS $(help-output-file).html : $(targets) ;
+ DEPENDS all : $(help-output-file).html ;
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/util/indirect.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/indirect.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/indirect.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,103 @@
+# Copyright David Abrahams 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.
+import modules ;
+import numbers ;
+
+# The pattern that indirect rules must match: module$rule
+.pattern = ^([^%]*)%([^%]+)$ ;
+
+#
+# Type checking rules.
+#
+local rule indirect-rule ( x )
+{
+ if ! [ MATCH $(.pattern) : $(x) ]
+ {
+ return "expected a string of the form module$rule, but got \""$(x)"\" for argument" ;
+ }
+}
+
+# make an indirect rule which calls the given rule; if context is
+# supplied it is expected to be the module in which to invoke the rule
+# by the 'call' rule below. Otherwise, the rule will be invoked in
+# the module of this rule's caller.
+rule make ( rulename bound-args * : context ? )
+{
+ context ?= [ CALLER_MODULE ] ;
+ context ?= "" ;
+ return $(context)%$(rulename) $(bound-args) ;
+}
+
+# make an indirect rule which calls the given rule. rulename may be a
+# qualified rule; if so it is returned unchanged. Otherwise, if
+# frames is not supplied, the result will be invoked (by 'call',
+# below) in the module of the caller. Otherwise, frames > 1
+# specifies additional call frames to back up in order to find the
+# module context.
+rule make-qualified ( rulename bound-args * : frames ? )
+{
+ if [ MATCH $(.pattern) : $(rulename) ]
+ {
+ return $(rulename) $(bound-args) ;
+ }
+ else
+ {
+ frames ?= 1 ;
+ # Take the first dot-separated element as module name.
+ # This disallows module names with dots, but allows rule names
+ # with dots.
+ local module-context = [ MATCH ^([^.]*)\\..* : $(rulename) ] ;
+ module-context ?= [ CALLER_MODULE $(frames) ] ;
+ return [ make $(rulename) $(bound-args) : $(module-context) ] ;
+ }
+}
+
+# return the module name in which the given indirect rule will be
+# invoked.
+rule get-module ( [indirect-rule] x )
+{
+ local m = [ MATCH $(.pattern) : $(x) ] ;
+ if ! $(m[1])
+ {
+ m = ;
+ }
+ return $(m[1]) ;
+}
+
+# return the rulename that will be called when x is invoked
+rule get-rule ( [indirect-rule] x )
+{
+ local m = [ MATCH $(.pattern) : $(x) ] ;
+ return $(m[2]) ;
+}
+
+# Invoke the given indirect-rule.
+rule call ( [indirect-rule] r args * : * )
+{
+ return [
+ modules.call-in [ get-module $(r) ]
+ : [ get-rule $(r) ] $(args) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9)
+ ] ;
+}
+
+rule __test__
+{
+ import assert ;
+
+ rule foo-barr! ( x )
+ {
+ assert.equal $(x) : x ;
+ }
+
+ assert.equal [ get-rule [ make foo-barr! ] ] : foo-barr! ;
+ assert.equal [ get-module [ make foo-barr! ] ] : [ CALLER_MODULE ] ;
+
+ call [ make foo-barr! ] x ;
+ call [ make foo-barr! x ] ;
+
+
+ call [ make foo-barr! : [ CALLER_MODULE ] ] x ;
+}
\ No newline at end of file
Property changes on: boost-jam/boost-build/branches/upstream/current/util/indirect.jam
___________________________________________________________________
Name: svn:executable
+
Added: boost-jam/boost-build/branches/upstream/current/util/numbers.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/numbers.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/numbers.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,230 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+digits = 0 1 2 3 4 5 6 7 8 9 ;
+powers = 1 ;
+zeros = "" ;
+natural = $(digits) ;
+positive = $(digits[2-]) ;
+incr = $(positive[2-]) ;
+znatural = $(digits) ;
+zero-test = is zero ; # if $(zero-test[$(n)]) == "is" "zero", n == 0
+
+import errors : * ;
+
+local rule extend ( )
+{
+ local next = $(digits[2-])$(znatural) ;
+ natural += $(next) ;
+ positive += $(next) ;
+ incr += $(next) ;
+ znatural = $(digits)$(znatural) ;
+}
+
+rule check ( numbers * )
+{
+ for local n in $(numbers)
+ {
+ switch $(n)
+ {
+ case *[^0-9]* :
+ error $(n) "in" $(numbers) : is not a number ;
+ }
+ }
+}
+
+rule increment ( number )
+{
+ return [ CALC $(number) + 1 ] ;
+}
+
+rule decrement ( number )
+{
+ # Previous rule did not allow decrementing zero.
+ # Is that what we want?
+ return [ CALC $(number) - 1 ] ;
+}
+
+rule range ( start finish ? : step ? )
+{
+ if ! $(finish)
+ {
+ finish = $(start) ;
+ start = 1 ;
+ }
+ step ?= 1 ;
+
+ check $(start) $(finish) $(step) ;
+
+ if $(finish) != 0
+ {
+ while ! $(positive[$(finish)])
+ {
+ extend ;
+ }
+
+ if $(step) = 1
+ {
+ return $(positive[$(start)-$(finish)]) ;
+ }
+ else
+ {
+ local index = [ increment $(step) ] ;
+ local by1 = $(positive[$(start)-$(finish)]) ;
+ local result ;
+ while $(by1)
+ {
+ result += $(by1[1]) ;
+ by1 = $(by1[$(index)-]) ;
+ }
+ return $(result) ;
+ }
+ }
+}
+
+rule less ( n1 n2 )
+{
+ check $(n1) $(n2) ;
+ # avoid messy 0 case by appending 1
+ local l1 = [ range 2 [ log10 $(n1)1 ] ] ;
+ local l2 = [ range 2 [ log10 $(n2)1 ] ] ;
+
+ # number of digits mismatch?
+ if ( $(l1) < $(l2) ) || ( ( $(l1) = $(l2) ) && $(n1) < $(n2) )
+ {
+ return true ;
+ }
+}
+
+rule log10 ( number )
+{
+ switch $(number)
+ {
+ case *[^0-9]* : error $(number) is not a number ;
+ case 0 : error can't take log of zero ;
+ case [1-9] : return 0 ;
+ case [1-9]? : return 1 ;
+ case [1-9]?? : return 2 ;
+ case [1-9]??? : return 3 ;
+ case [1-9]???? : return 4 ;
+ case [1-9]????? : return 5 ;
+ case [1-9]?????? : return 6 ;
+ case [1-9]??????? : return 7 ;
+ case [1-9]???????? : return 8 ;
+ case [1-9]????????? : return 9 ;
+ case * :
+ {
+ import sequence ;
+ import string ;
+ local chars = [ string.chars $(number) ] ;
+ while $(chars[1]) = 0
+ {
+ chars = $(chars[2-]) ;
+ }
+
+ if ! $(chars)
+ {
+ error can't take log of zero ;
+ }
+ else
+ {
+ return [ sequence.length $(chars) ] ;
+ }
+ }
+ }
+}
+
+rule __test__ ( )
+{
+ import assert ;
+
+ assert.result 1 : increment 0 ;
+ assert.result 2 : increment 1 ;
+ assert.result 1 : decrement 2 ;
+ assert.result 0 : decrement 1 ;
+ assert.result 50 : increment 49 ;
+ assert.result 49 : decrement 50 ;
+ assert.result 99 : increment 98 ;
+ assert.result 99 : decrement 100 ;
+ assert.result 100 : increment 99 ;
+ # This just makes debugging output too large
+ # assert.result 1000 : increment 999 ;
+ # assert.result 999 : decrement 1000 ;
+
+ assert.result 1 2 3 : range 3 ;
+ assert.result 1 2 3 4 5 6 7 8 9 10 11 12 : range 12 ;
+ assert.result 3 4 5 6 7 8 9 10 11 : range 3 11 ;
+ assert.result : range 0 ;
+ assert.result 1 4 7 10 : range 10 : 3 ;
+ assert.result 2 4 6 8 10 : range 2 10 : 2 ;
+ assert.result 25 50 75 100 : range 25 100 : 25 ;
+
+ assert.true less 1 2 ;
+ assert.true less 1 12 ;
+ assert.true less 1 21 ;
+ assert.false less 0 0 ;
+
+ # TEMPORARY disabled, because nested "try"/"catch" do not work, I don't the
+ # time to fix that right now.
+ if $(0)
+ {
+ try ;
+ {
+ decrement 0 ;
+ }
+ catch can't decrement zero! ;
+
+ try ;
+ {
+ check foo ;
+ }
+ catch : not a number ;
+
+ try ;
+ {
+ increment foo ;
+ }
+ catch : not a number ;
+
+ try ;
+ {
+ log10 0 ;
+ }
+ catch can't take log of zero ;
+
+ try ;
+ {
+ log10 000 ;
+ }
+ catch can't take log of zero ;
+
+ }
+
+ assert.result 0 : log10 1 ;
+ assert.result 0 : log10 9 ;
+ assert.result 1 : log10 10 ;
+ assert.result 1 : log10 99 ;
+ assert.result 2 : log10 125 ;
+ assert.result 11 : log10 12345678901 ;
+
+ for local x in [ range 75 110 : 5 ]
+ {
+ for local y in [ range $(x) 111 : 3 ]
+ {
+ if $(x) != $(y)
+ {
+ assert.true less $(x) $(y) ;
+ }
+ }
+ }
+
+ for local x in [ range 90 110 : 2 ]
+ {
+ for local y in [ range 80 $(x) : 4 ]
+ {
+ assert.false less $(x) $(y) ;
+ }
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/util/order.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/order.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/order.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,173 @@
+# Copyright (C) 2003 Vladimir Prus
+# Use, modification, and distribution is subject to 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)
+
+# This module defines a class which allows to order arbitrary object
+# with regard to arbitrary binary relation.
+#
+# The primary use case is the gcc toolset, which is sensitive to
+# library order: if library 'a' uses symbols from library 'b',
+# then 'a' must be present before 'b' on the linker's command line.
+#
+# This requirement can be lifted for gcc with GNU ld, but for gcc with
+# Solaris LD (and for Solaris toolset as well), the order always matters.
+#
+# So, we need to store order requirements and then order libraries
+# according to them. It it not possible to use dependency graph as
+# order requirements. What we need is "use symbols" relationship
+# while dependency graph provides "needs to be updated" relationship.
+#
+# For example::
+# lib a : a.cpp b;
+# lib b ;
+#
+# For static linking, the 'a' library need not depend on 'b'. However, it
+# still should come before 'b' on the command line.
+
+class order
+{
+ rule __init__ ( ) {
+ }
+
+ # Adds the constraint that 'first' should precede 'second'
+ rule add-pair ( first second )
+ {
+ .constraits += $(first)--$(second) ;
+ }
+ NATIVE_RULE class at order : add-pair ;
+
+ # Given a list of objects, reorder them so that the constains specified
+ # by 'add-pair' are satisfied.
+ #
+ # The algorithm was adopted from an awk script by Nikita Youshchenko
+ # (yoush at cs dot msu dot su)
+ rule order ( objects * )
+ {
+ # The algorithm used is the same is standard transitive closure,
+ # except that we're not keeping in-degree for all vertices, but
+ # rather removing edges.
+ local result ;
+ if $(objects)
+ {
+ local constraints = [ eliminate-unused-constraits $(objects) ] ;
+
+ # Find some library that nobody depends upon and add it to
+ # the 'result' array.
+ local obj ;
+ while $(objects)
+ {
+ local new_objects ;
+ while $(objects)
+ {
+ obj = $(objects[1]) ;
+ if [ has-no-dependents $(obj) : $(constraints) ]
+ {
+ # Emulate break ;
+ new_objects += $(objects[2-]) ;
+ objects = ;
+ }
+ else
+ {
+ new_objects += $(obj) ;
+ obj = ;
+ objects = $(objects[2-]) ;
+ }
+ }
+
+ if ! $(obj)
+ {
+ errors.error "Circular order dependencies" ;
+ }
+ # No problem with placing first.
+ result += $(obj) ;
+ # Remove all containts where 'obj' comes first,
+ # since they are already satisfied.
+ constraints = [ remove-satisfied $(constraints) : $(obj) ] ;
+ # Add the remaining objects for further processing
+ # on the next iteration
+
+ objects = $(new_objects) ;
+ }
+
+ }
+ return $(result) ;
+ }
+ NATIVE_RULE class at order : order ;
+
+ # Eliminate constains which mentions objects not in 'objects'.
+ # In graph-theory terms, this is finding subgraph induced by
+ # ordered vertices.
+ rule eliminate-unused-constraits ( objects * )
+ {
+ local result ;
+ for local c in $(.constraints)
+ {
+ local m = [ MATCH (.*)--(.*) : $(c) ] ;
+ if $(m[1]) in $(objects) && $(m[2]) in $(objects)
+ {
+ result += $(c) ;
+ }
+ }
+ return $(result) ;
+ }
+
+ # Returns true if there's no constrain in 'constaraint' where
+ # 'obj' comes second.
+ rule has-no-dependents ( obj : constraints * )
+ {
+ local failed ;
+ while $(constraints) && ! $(failed)
+ {
+ local c = $(constraints[1]) ;
+ local m = [ MATCH (.*)--(.*) : $(c) ] ;
+ if $(m[2]) = $(obj)
+ {
+ failed = true ;
+ }
+ constraints = $(constraints[2-]) ;
+ }
+ if ! $(failed)
+ {
+ return true ;
+ }
+ }
+
+ rule remove-satisfied ( constraints * : obj )
+ {
+ local result ;
+ for local c in $(constraints)
+ {
+ local m = [ MATCH (.*)--(.*) : $(c) ] ;
+ if $(m[1]) != $(obj)
+ {
+ result += $(c) ;
+ }
+ }
+ return $(result) ;
+ }
+}
+
+rule __test__ ( )
+{
+ import "class" : new ;
+ import assert ;
+
+ c1 = [ new order ] ;
+ $(c1).add-pair l1 l2 ;
+
+ assert.result l1 l2 : $(c1).order l1 l2 ;
+ assert.result l1 l2 : $(c1).order l2 l1 ;
+
+ $(c1).add-pair l2 l3 ;
+ assert.result l1 l2 : $(c1).order l2 l1 ;
+ $(c1).add-pair x l2 ;
+ assert.result l1 l2 : $(c1).order l2 l1 ;
+ assert.result l1 l2 l3 : $(c1).order l2 l3 l1 ;
+
+
+
+
+}
+
+
Added: boost-jam/boost-build/branches/upstream/current/util/os.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/os.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/os.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,51 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+import modules ;
+name = [ modules.peek : OS ] ;
+platform = [ modules.peek : OSPLAT ] ;
+version = [ modules.peek : OSVER ] ;
+
+rule name { return $(name) ; }
+rule platform { return $(platform) ; }
+rule version { return $(version) ; }
+
+# Returns true if running on windows, whether in cygwin or not.
+rule on-windows
+{
+ local result ;
+ if [ modules.peek : NT ]
+ {
+ result = true ;
+ }
+ else if [ modules.peek : UNIX ]
+ {
+ switch [ modules.peek : JAMUNAME ]
+ {
+ case CYGWIN* :
+ {
+ result = true ;
+ }
+ }
+ }
+ return $(result) ;
+}
+
+
+
+import regex ;
+
+rule __test__
+{
+ import assert ;
+ rule identity ( args * ) { return $(args) ; }
+
+ if ! ( --quiet in [ modules.peek : ARGV ] )
+ {
+ ECHO os: name= [ name ] ;
+ ECHO os: version= [ version ] ;
+ }
+ assert.true name ;
+}
Added: boost-jam/boost-build/branches/upstream/current/util/path.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/path.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/path.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,727 @@
+# Copyright (C) Vladimir Prus 2002. 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.
+
+# Performs various path manipulations. Path are always in a 'normilized'
+# representation. In it, a path may be either:
+#
+# - '.', or
+#
+# - ['/'] [ ( '..' '/' )* (token '/')* token ]
+#
+# In plain english, path can be rooted, '..' elements are allowed only
+# at the beginning, and it never ends in slash, except for path consisting
+# of slash only.
+
+import modules ;
+import sequence ;
+import regex ;
+import errors : error ;
+
+
+os = [ modules.peek : OS ] ;
+if [ modules.peek : UNIX ]
+{
+ local uname = [ modules.peek : JAMUNAME ] ;
+ switch $(uname)
+ {
+ case CYGWIN* :
+ os = CYGWIN ;
+
+ case * :
+ os = UNIX ;
+ }
+}
+
+#
+# Converts the native path into normalized form.
+#
+rule make ( native )
+{
+ return [ make-$(os) $(native) ] ;
+}
+
+#
+# Builds native representation of the path.
+#
+rule native ( path )
+{
+ return [ native-$(os) $(path) ] ;
+}
+
+#
+# Tests if a path is rooted.
+#
+rule is-rooted ( path )
+{
+ return [ MATCH "^(/)" : $(path) ] ;
+}
+
+#
+# Tests if a path has a parent.
+#
+rule has-parent ( path )
+{
+ if $(path) != / {
+ return 1 ;
+ } else {
+ return ;
+ }
+}
+
+#
+# Returns the path without any directory components.
+#
+rule basename ( path )
+{
+ return [ MATCH "([^/]+)$" : $(path) ] ;
+}
+
+#
+# Returns parent directory of the path. If no parent exists, error is issued.
+#
+rule parent ( path )
+{
+ if [ has-parent $(path) ] {
+
+ if $(path) = . {
+ return .. ;
+ } else {
+
+ # Strip everything at the end of path up to and including
+ # the last slash
+ local result = [ regex.match "((.*)/)?([^/]+)" : $(path) : 2 3 ] ;
+
+ # Did we strip what we shouldn't?
+ if $(result[2]) = ".." {
+ return $(path)/.. ;
+ } else {
+ if ! $(result[1]) {
+ if [ is-rooted $(path) ] {
+ result = / ;
+ } else {
+ result = . ;
+ }
+ }
+ return $(result[1]) ;
+ }
+ }
+ } else {
+ error "Path '$(path)' has no parent" ;
+ }
+}
+
+#
+# Returns path2 such that "[ join path path2 ] = .".
+# The path may not contain ".." element or be rooted.
+#
+rule reverse ( path )
+{
+ if $(path) = .
+ {
+ return $(path) ;
+ }
+ else
+ {
+ local tokens = [ regex.split $(path) "/" ] ;
+ local tokens2 ;
+ for local i in $(tokens) {
+ tokens2 += .. ;
+ }
+ return [ sequence.join $(tokens2) : "/" ] ;
+ }
+}
+
+#
+# Auxillary rule: does all the semantic of 'join', except for error cheching.
+# The error checking is separated because this rule is recursive, and I don't
+# like the idea of checking the same input over and over.
+#
+local rule join-imp ( elements + )
+{
+ return [ NORMALIZE_PATH $(elements:J="/") ] ;
+}
+
+#
+# Contanenates the passed path elements. Generates an error if
+# any element other than the first one is rooted.
+#
+rule join ( elements + )
+{
+ if ! $(elements[2])
+ {
+ return $(elements[1]) ;
+ }
+ else
+ {
+ for local e in $(elements[2-])
+ {
+ if [ is-rooted $(e) ]
+ {
+ error only first element may be rooted ;
+ }
+ }
+ return [ join-imp $(elements) ] ;
+ }
+}
+
+
+#
+# If 'path' is relative, it is rooted at 'root'. Otherwise, it's unchanged.
+#
+rule root ( path root )
+{
+ if [ is-rooted $(path) ] {
+ return $(path) ;
+ } else {
+ return [ join $(root) $(path) ] ;
+ }
+}
+
+#
+# Returns the current working directory.
+#
+rule pwd ( )
+{
+ return [ make [ PWD ] ] ;
+}
+
+#
+# Returns the list of files matching the given pattern in the specified directory.
+#
+rule glob ( dirs * : patterns + )
+{
+ local result ;
+ for dir in $(dirs)
+ {
+ result += [ sequence.transform make : [ GLOB [ native $(dir) ] : $(patterns) ] ] ;
+ }
+ return $(result) ;
+}
+
+#
+# Returns true is the specified file exists.
+#
+rule exists ( file )
+{
+ return [ path.glob $(file:D) : $(file:D=) ] ;
+}
+NATIVE_RULE path : exists ;
+
+
+
+#
+# Find out the absolute name of path and returns the list of all the parents,
+# starting with the immediate one. Parents are returned as relative names.
+# If 'upper_limit' is specified, directories above it will be pruned.
+#
+rule all-parents ( path : upper_limit ? : cwd ? )
+{
+ cwd ?= [ pwd ] ;
+ local path_ele = [ regex.split [ root $(path) $(cwd) ] "/" ] ;
+
+ if ! $(upper_limit) {
+ upper_limit = / ;
+ }
+ local upper_ele = [ regex.split [ root $(upper_limit) $(cwd) ] "/" ] ;
+
+ # Leave only elements in 'path_ele' below 'upper_ele'
+ while $(path_ele) && $(upper_ele[1]) = $(path_ele[1]) {
+ upper_ele = $(upper_ele[2-]) ;
+ path_ele = $(path_ele[2-]) ;
+ }
+
+ # All upper elements removed ?
+ if ! $(upper_ele) {
+ # Create the relative paths to parents, number of elements in 'path_ele'
+ local result ;
+ for local i in $(path_ele) {
+ path = [ parent $(path) ] ;
+ result += $(path) ;
+ }
+ return $(result) ;
+ }
+ else {
+ error "$(upper_limit) is not prefix of $(path)" ;
+ }
+}
+
+
+#
+# Search for 'pattern' in parent directories of 'dir', up till and including
+# 'upper_limit', if it is specified, or till the filesystem root otherwise.
+#
+rule glob-in-parents ( dir : patterns + : upper-limit ? )
+{
+ local result ;
+ local parent-dirs = [ all-parents $(dir) : $(upper-limit) ] ;
+
+ while $(parent-dirs) && ! $(result)
+ {
+ result = [ glob $(parent-dirs[1]) : $(patterns) ] ;
+ parent-dirs = $(parent-dirs[2-]) ;
+ }
+ return $(result) ;
+}
+
+#
+# Assuming 'child' is a subdirectory of 'parent', return the relative
+# path from 'parent' to 'child'
+#
+rule relative ( child parent )
+{
+ if $(parent) = "."
+ {
+ return $(child) ;
+ }
+ else
+ {
+ local split1 = [ regex.split $(parent) / ] ;
+ local split2 = [ regex.split $(child) / ] ;
+
+ while $(split1)
+ {
+ if $(split1[1]) = $(split2[1])
+ {
+ split1 = $(split1[2-]) ;
+ split2 = $(split2[2-]) ;
+ }
+ else
+ {
+ errors.error $(child) is not a subdir of $(parent) ;
+ }
+ }
+ return [ join $(split2) ] ;
+ }
+}
+
+# Returns the minimal path to path2 that is relative path1.
+#
+rule relative-to ( path1 path2 )
+{
+ local root_1 = [ regex.split [ reverse $(path1) ] / ] ;
+ local split1 = [ regex.split $(path1) / ] ;
+ local split2 = [ regex.split $(path2) / ] ;
+
+ while $(split1) && $(root_1)
+ {
+ if $(split1[1]) = $(split2[1])
+ {
+ root_1 = $(root_1[2-]) ;
+ split1 = $(split1[2-]) ;
+ split2 = $(split2[2-]) ;
+ }
+ else
+ {
+ split1 = ;
+ }
+ }
+ return [ join . $(root_1) $(split2) ] ;
+}
+
+# Returns the list of paths which are used by the operating system
+# for looking up programs
+rule programs-path ( )
+{
+ local result ;
+ local raw = [ modules.peek : PATH Path path ] ;
+ for local p in $(raw)
+ {
+ if $(p)
+ {
+ result += [ path.make $(p) ] ;
+ }
+ }
+ return $(result) ;
+}
+
+rule make-NT ( native )
+{
+ local tokens = [ regex.split $(native) "[/\\]" ] ;
+ local result ;
+
+ # Handle paths ending with slashes
+ if $(tokens[-1]) = ""
+ {
+ tokens = $(tokens[1--2]) ; # discard the empty element
+ }
+
+ result = [ path.join $(tokens) ] ;
+
+ if [ regex.match "(^.:)" : $(native) ]
+ {
+ result = /$(result) ;
+ }
+
+ if $(native) = ""
+ {
+ result = "." ;
+ }
+
+ return $(result) ;
+}
+
+rule native-NT ( path )
+{
+ local result = [ MATCH "^/?(.*)" : $(path) ] ;
+ result = [ sequence.join [ regex.split $(result) "/" ] : "\\" ] ;
+ return $(result) ;
+}
+
+rule make-UNIX ( native )
+{
+ # VP: I have no idea now 'native' can be empty here! But it can!
+ if $(native) = ""
+ {
+ errors.error "Empty path passed to 'make-UNIX'" ;
+ }
+ else
+ {
+ return [ NORMALIZE_PATH $(native:T) ] ;
+ }
+}
+
+rule native-UNIX ( path )
+{
+ return $(path) ;
+}
+
+rule make-CYGWIN ( path )
+{
+ return [ make-NT $(path) ] ;
+}
+
+rule native-CYGWIN ( path )
+{
+ local result = $(path) ;
+ if [ regex.match "(^/.:)" : $(path) ] # win absolute
+ {
+ result = [ MATCH "^/?(.*)" : $(path) ] ; # remove leading '/'
+ }
+ return [ native-UNIX $(result) ] ;
+}
+
+#
+# split-VMS: splits input native path into
+# device dir file (each part is optional),
+# example:
+#
+# dev:[dir]file.c => dev: [dir] file.c
+#
+rule split-path-VMS ( native )
+{
+ local matches = [ MATCH ([a-zA-Z0-9_-]+:)?(\\[[^\]]*\\])?(.*)?$ : $(native) ] ;
+ local device = $(matches[1]) ;
+ local dir = $(matches[2]) ;
+ local file = $(matches[3]) ;
+
+ return $(device) $(dir) $(file) ;
+}
+
+#
+# Converts a native VMS path into a portable path spec.
+#
+# Does not handle current-device absolute paths such
+# as "[dir]File.c" as it is not clear how to represent
+# them in the portable path notation.
+#
+# Adds a trailing dot (".") to the file part if no extension
+# is present (helps when converting it back into native path).
+#
+rule make-VMS ( native )
+{
+ if [ MATCH ^(\\[[a-zA-Z0-9]) : $(native) ]
+ {
+ errors.error "Can't handle default-device absolute paths: " $(native) ;
+ }
+
+ local parts = [ split-path-VMS $(native) ] ;
+ local device = $(parts[1]) ;
+ local dir = $(parts[2]) ;
+ local file = $(parts[3]) ;
+ local elems ;
+
+ if $(device)
+ {
+ #
+ # rooted
+ #
+ elems = /$(device) ;
+ }
+
+ if $(dir) = "[]"
+ {
+ #
+ # Special case: current directory
+ #
+ elems = $(elems) "." ;
+ }
+ else if $(dir)
+ {
+ dir = [ regex.replace $(dir) "\\[|\\]" "" ] ;
+ local dir_parts = [ regex.split $(dir) \\. ] ;
+
+ if $(dir_parts[1]) = ""
+ {
+ #
+ # Relative path
+ #
+ dir_parts = $(dir_parts[2--1]) ;
+ }
+
+ #
+ # replace "parent-directory" parts (- => ..)
+ #
+ dir_parts = [ regex.replace-list $(dir_parts) : - : .. ] ;
+
+ elems = $(elems) $(dir_parts) ;
+ }
+
+ if $(file)
+ {
+ if ! [ MATCH (\\.) : $(file) ]
+ {
+ #
+ # Always add "." to end of non-extension file
+ #
+ file = $(file). ;
+ }
+ elems = $(elems) $(file) ;
+ }
+
+ local portable = [ path.join $(elems) ] ;
+
+ return $(portable) ;
+}
+
+#
+# Converts a portable path spec into a native VMS path.
+#
+# Relies on having at least one dot (".") included in the file
+# name to be able to differentiate it ftom the directory part.
+#
+rule native-VMS ( path )
+{
+ local device = "" ;
+ local dir = $(path) ;
+ local file = "" ;
+ local native ;
+ local split ;
+
+ #
+ # Has device ?
+ #
+ if [ is-rooted $(dir) ]
+ {
+ split = [ MATCH ^/([^:]+:)/?(.*) : $(dir) ] ;
+ device = $(split[1]) ;
+ dir = $(split[2]) ;
+ }
+
+ #
+ # Has file ?
+ #
+ # This is no exact science, just guess work:
+ #
+ # If the last part of the current path spec
+ # includes some chars, followed by a dot,
+ # optionally followed by more chars -
+ # then it is a file (keep your fingers crossed).
+ #
+ split = [ regex.split $(dir) / ] ;
+ local maybe_file = $(split[-1]) ;
+
+ if [ MATCH ^([^.]+\\..*) : $(maybe_file) ]
+ {
+ file = $(maybe_file) ;
+ dir = [ sequence.join $(split[1--2]) : / ] ;
+ }
+
+ #
+ # Has dir spec ?
+ #
+ if $(dir) = "."
+ {
+ dir = "[]" ;
+ }
+ else if $(dir)
+ {
+ dir = [ regex.replace $(dir) \\.\\. - ] ;
+ dir = [ regex.replace $(dir) / . ] ;
+
+ if $(device) = ""
+ {
+ #
+ # Relative directory
+ #
+ dir = "."$(dir) ;
+ }
+ dir = "["$(dir)"]" ;
+ }
+
+ native = [ sequence.join $(device) $(dir) $(file) ] ;
+
+ return $(native) ;
+}
+
+
+rule __test__ ( ) {
+
+ import assert ;
+ import errors : try catch ;
+
+ assert.true is-rooted "/" ;
+ assert.true is-rooted "/foo" ;
+ assert.true is-rooted "/foo/bar" ;
+ assert.result : is-rooted "." ;
+ assert.result : is-rooted "foo" ;
+ assert.result : is-rooted "foo/bar" ;
+
+ assert.true has-parent "foo" ;
+ assert.true has-parent "foo/bar" ;
+ assert.true has-parent "." ;
+ assert.result : has-parent "/" ;
+
+ assert.result "." : basename "." ;
+ assert.result ".." : basename ".." ;
+ assert.result "foo" : basename "foo" ;
+ assert.result "foo" : basename "bar/foo" ;
+ assert.result "foo" : basename "gaz/bar/foo" ;
+ assert.result "foo" : basename "/gaz/bar/foo" ;
+
+ assert.result "." : parent "foo" ;
+ assert.result "/" : parent "/foo" ;
+ assert.result "foo/bar" : parent "foo/bar/giz" ;
+ assert.result ".." : parent "." ;
+ assert.result ".." : parent "../foo" ;
+ assert.result "../../foo" : parent "../../foo/bar" ;
+
+
+ assert.result "." : reverse "." ;
+ assert.result ".." : reverse "foo" ;
+ assert.result "../../.." : reverse "foo/bar/giz" ;
+
+ assert.result "foo" : join "foo" ;
+ assert.result "/foo" : join "/" "foo" ;
+ assert.result "foo/bar" : join "foo" "bar" ;
+ assert.result "foo/bar" : join "foo/giz" "../bar" ;
+ assert.result "foo/giz" : join "foo/bar/baz" "../../giz" ;
+ assert.result ".." : join "." ".." ;
+ assert.result ".." : join "foo" "../.." ;
+ assert.result "../.." : join "../foo" "../.." ;
+ assert.result "/foo" : join "/bar" "../foo" ;
+ assert.result "foo/giz" : join "foo/giz" "." ;
+ assert.result "." : join lib2 ".." ;
+ assert.result "/" : join "/a" ".." ;
+
+ assert.result /a/b : join /a/b/c .. ;
+
+ assert.result "foo/bar/giz" : join "foo" "bar" "giz" ;
+ assert.result "giz" : join "foo" ".." "giz" ;
+ assert.result "foo/giz" : join "foo" "." "giz" ;
+
+ try ;
+ {
+ join "a" "/b" ;
+ }
+ catch only first element may be rooted ;
+
+ local CWD = "/home/ghost/build" ;
+ assert.result : all-parents . : . : $(CWD) ;
+ assert.result . .. ../.. ../../.. : all-parents "Jamfile" : "" : $(CWD) ;
+ assert.result foo . .. ../.. ../../.. : all-parents "foo/Jamfile" : "" : $(CWD) ;
+ assert.result ../Work .. ../.. ../../.. : all-parents "../Work/Jamfile" : "" : $(CWD) ;
+
+ local CWD = "/home/ghost" ;
+ assert.result . .. : all-parents "Jamfile" : "/home" : $(CWD) ;
+ assert.result . : all-parents "Jamfile" : "/home/ghost" : $(CWD) ;
+
+ assert.result "c/d" : relative "a/b/c/d" "a/b" ;
+ assert.result "foo" : relative "foo" "." ;
+
+ local save-os = [ modules.peek path : os ] ;
+ modules.poke path : os : NT ;
+
+ assert.result "foo/bar/giz" : make "foo/bar/giz" ;
+ assert.result "foo/bar/giz" : make "foo\\bar\\giz" ;
+ assert.result "foo" : make "foo/." ;
+ assert.result "foo" : make "foo/bar/.." ;
+ assert.result "/D:/My Documents" : make "D:\\My Documents" ;
+ assert.result "/c:/boost/tools/build/new/project.jam" : make "c:\\boost\\tools\\build\\test\\..\\new\\project.jam" ;
+
+ assert.result "foo\\bar\\giz" : native "foo/bar/giz" ;
+ assert.result "foo" : native "foo" ;
+ assert.result "D:\\My Documents\\Work" : native "/D:/My Documents/Work" ;
+
+ modules.poke path : os : UNIX ;
+
+ assert.result "foo/bar/giz" : make "foo/bar/giz" ;
+ assert.result "/sub1" : make "/sub1/." ;
+ assert.result "/sub1" : make "/sub1/sub2/.." ;
+ assert.result "sub1" : make "sub1/." ;
+ assert.result "sub1" : make "sub1/sub2/.." ;
+ assert.result "/foo/bar" : native "/foo/bar" ;
+
+ modules.poke path : os : VMS ;
+
+ #
+ # Don't really need to poke os before these
+ #
+ assert.result "disk:" "[dir]" "file" : split-path-VMS "disk:[dir]file" ;
+ assert.result "disk:" "[dir]" "" : split-path-VMS "disk:[dir]" ;
+ assert.result "disk:" "" "" : split-path-VMS "disk:" ;
+ assert.result "disk:" "" "file" : split-path-VMS "disk:file" ;
+ assert.result "" "[dir]" "file" : split-path-VMS "[dir]file" ;
+ assert.result "" "[dir]" "" : split-path-VMS "[dir]" ;
+ assert.result "" "" "file" : split-path-VMS "file" ;
+ assert.result "" "" "" : split-path-VMS "" ;
+
+ #
+ # Special case: current directory
+ #
+ assert.result "" "[]" "" : split-path-VMS "[]" ;
+ assert.result "disk:" "[]" "" : split-path-VMS "disk:[]" ;
+ assert.result "" "[]" "file" : split-path-VMS "[]file" ;
+ assert.result "disk:" "[]" "file" : split-path-VMS "disk:[]file" ;
+
+ #
+ # Make portable paths
+ #
+ assert.result "/disk:" : make "disk:" ;
+ assert.result "foo/bar/giz" : make "[.foo.bar.giz]" ;
+ assert.result "foo" : make "[.foo]" ;
+ assert.result "foo" : make "[.foo.bar.-]" ;
+ assert.result ".." : make "[.-]" ;
+ assert.result ".." : make "[-]" ;
+ assert.result "." : make "[]" ;
+ assert.result "giz.h" : make "giz.h" ;
+ assert.result "foo/bar/giz.h" : make "[.foo.bar]giz.h" ;
+ assert.result "/disk:/my_docs" : make "disk:[my_docs]" ;
+ assert.result "/disk:/boost/tools/build/new/project.jam" : make "disk:[boost.tools.build.test.-.new]project.jam" ;
+
+ #
+ # Special case (adds '.' to end of file w/o extension to
+ # disambiguate from directory in portable path spec).
+ #
+ assert.result "Jamfile." : make "Jamfile" ;
+ assert.result "dir/Jamfile." : make "[.dir]Jamfile" ;
+ assert.result "/disk:/dir/Jamfile." : make "disk:[dir]Jamfile" ;
+
+ #
+ # Make native paths
+ #
+ assert.result "disk:" : native "/disk:" ;
+ assert.result "[.foo.bar.giz]" : native "foo/bar/giz" ;
+ assert.result "[.foo]" : native "foo" ;
+ assert.result "[.-]" : native ".." ;
+ assert.result "[.foo.-]" : native "foo/.." ;
+ assert.result "[]" : native "." ;
+ assert.result "disk:[my_docs.work]" : native "/disk:/my_docs/work" ;
+ assert.result "giz.h" : native "giz.h" ;
+ assert.result "disk:Jamfile." : native "/disk:Jamfile." ;
+ assert.result "disk:[my_docs.work]Jamfile." : native "/disk:/my_docs/work/Jamfile." ;
+
+ modules.poke path : os : $(save-os) ;
+
+}
Added: boost-jam/boost-build/branches/upstream/current/util/print.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/print.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/print.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,465 @@
+# (C) Copyright Rene Rivera, 2002-2003.
+#
+# See accompanying license for terms and conditions of use.
+#
+
+# Utilities for generating format independent output. Using these
+# will help in generation of documentation in at minimum plain/console
+# and html.
+
+import modules ;
+import numbers ;
+import string ;
+import regex ;
+
+# The current output target. Defaults to console.
+output-target = console ;
+
+# The current output type. Defaults to plain.
+output-type = plain ;
+
+# Whitespace.
+.whitespace = [ string.whitespace ] ;
+
+# Set the target and type of output to generate. This sets both
+# the destination output and the type of docs to generate to that
+# output. The target can be either a file or "console" for echoing
+# to the console. If the type of output is not specified it defaults
+# to plain text.
+#
+rule output (
+ target # The target file or device; file or "console".
+ type ? # The type of output; "plain", or "html".
+ )
+{
+ type ?= plain ;
+ if $(output-target) != $(target)
+ {
+ output-target = $(target) ;
+ output-type = $(type) ;
+ if $(output-type) = html
+ {
+ text
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"
+ "<html>"
+ "<head>"
+ "</head>"
+ "<body link=\"#0000ff\" vlink=\"#800080\">"
+ : true
+ : prefix ;
+ text
+ "</body>"
+ "</html>"
+ :
+ : suffix ;
+ }
+ }
+}
+
+# Generate a section with a description. The type of output can be
+# controlled by the value of the 'output-type' variable. If not set
+# it defaults to 'console' indicating immediate display to the console.
+# Other possible values are: 'html-file'.
+#
+rule section (
+ name # The name of the section.
+ description * # A number of description lines.
+ )
+{
+ if $(output-type) = plain
+ {
+ lines [ split-at-words $(name): ] ;
+ lines ;
+ }
+ else if $(output-type) = html
+ {
+ name = [ escape-html $(name) ] ;
+ text <h3>$(name)</h3> <p> ;
+ }
+ local pre = ;
+ while $(description)
+ {
+ local paragraph = ;
+ while $(description) && [ string.is-whitespace $(description[1]) ] { description = $(description[2-]) ; }
+ if $(pre)
+ {
+ while $(description) && (
+ $(pre) = " $(description[1])" ||
+ ( $(pre) < [ string.chars [ MATCH "^([$(.whitespace)]*)" : " $(description[1])" ] ] )
+ )
+ { paragraph += $(description[1]) ; description = $(description[2-]) ; }
+ while [ string.is-whitespace $(paragraph[-1]) ] { paragraph = $(paragraph[1--2]) ; }
+ pre = ;
+ if $(output-type) = plain
+ {
+ lines $(paragraph) "" : " " " " ;
+ }
+ else if $(output-type) = html
+ {
+ text <blockquote> ;
+ lines $(paragraph) ;
+ text </blockquote> ;
+ }
+ }
+ else
+ {
+ while $(description) && ! [ string.is-whitespace $(description[1]) ]
+ { paragraph += $(description[1]) ; description = $(description[2-]) ; }
+ if $(paragraph[1]) = :: && ! $(paragraph[2])
+ {
+ pre = " " ;
+ }
+ if $(paragraph[1]) = ::
+ {
+ if $(output-type) = plain
+ {
+ lines $(paragraph[2-]) "" : " " " " ;
+ lines ;
+ }
+ else if $(output-type) = html
+ {
+ text <blockquote> ;
+ lines $(paragraph[2-]) ;
+ text </blockquote> ;
+ }
+ }
+ else
+ {
+ local p = [ MATCH "(.*)(::)$" : $(paragraph[-1]) ] ;
+ local pws = [ MATCH "([ ]*)$" : $(p[1]) ] ;
+ p = [ MATCH "(.*)($(pws))($(p[2]))$" : $(paragraph[-1]) ] ;
+ if $(p[3]) = ::
+ {
+ pre = [ string.chars [ MATCH "^([$(.whitespace)]*)" : " $(p[1])" ] ] ;
+ if ! $(p[2]) || $(p[2]) = "" { paragraph = $(paragraph[1--2]) $(p[1]): ; }
+ else { paragraph = $(paragraph[1--2]) $(p[1]) ; }
+ if $(output-type) = plain
+ {
+ lines [ split-at-words " " $(paragraph) ] : " " " " ;
+ lines ;
+ }
+ else if $(output-type) = html
+ {
+ text </p> <p> [ escape-html $(paragraph) ] ;
+ }
+ }
+ else
+ {
+ if $(output-type) = plain
+ {
+ lines [ split-at-words " " $(paragraph) ] : " " " " ;
+ lines ;
+ }
+ else if $(output-type) = html
+ {
+ text </p> <p> [ escape-html $(paragraph) ] ;
+ }
+ }
+ }
+ }
+ }
+ if $(output-type) = html
+ {
+ text </p> ;
+ }
+}
+
+# Generate the start of a list of items. The type of output can be
+# controlled by the value of the 'output-type' variable. If not set
+# it defaults to 'console' indicating immediate display to the console.
+# Other possible values are: 'html-file'.
+#
+rule list-start ( )
+{
+ if $(output-type) = plain
+ {
+ }
+ else if $(output-type) = html
+ {
+ text <ul> ;
+ }
+}
+
+# Generate an item in a list. The type of output can be
+# controlled by the value of the 'output-type' variable. If not set
+# it defaults to 'console' indicating immediate display to the console.
+# Other possible values are: 'html-file'.
+#
+rule list-item (
+ item + # The item to list.
+ )
+{
+ if $(output-type) = plain
+ {
+ lines [ split-at-words "*" $(item) ] : " " ;
+ }
+ else if $(output-type) = html
+ {
+ text <li> [ escape-html $(item) ] </li> ;
+ }
+}
+
+# Generate the end of a list of items. The type of output can be
+# controlled by the value of the 'output-type' variable. If not set
+# it defaults to 'console' indicating immediate display to the console.
+# Other possible values are: 'html-file'.
+#
+rule list-end ( )
+{
+ if $(output-type) = plain
+ {
+ lines ;
+ }
+ else if $(output-type) = html
+ {
+ text </ul> ;
+ }
+}
+
+# Split the given text into separate lines, word-wrapping to a margin.
+# The default margin is 78 characters.
+#
+rule split-at-words (
+ text + # The text to split.
+ : margin ? # An optional margin, default is 78.
+ )
+{
+ local lines = ;
+ text = [ string.words $(text:J=" ") ] ;
+ text = $(text:J=" ") ;
+ margin ?= 78 ;
+ local char-match-1 = ".?" ;
+ local char-match = "" ;
+ while $(margin) != 0
+ {
+ char-match = $(char-match)$(char-match-1) ;
+ margin = [ numbers.decrement $(margin) ] ;
+ }
+ while $(text)
+ {
+ local s = "" ;
+ local t = "" ;
+ # divide s into the first X characters and the rest
+ s = [ MATCH "^($(char-match))(.*)" : $(text) ] ;
+
+ if $(s[2])
+ {
+ # split the first half at a space
+ t = [ MATCH "^(.*)[\\ ]([^\\ ]*)$" : $(s[1]) ] ;
+ }
+ else
+ {
+ t = $(s) ;
+ }
+
+ if ! $(t[2])
+ {
+ t += "" ;
+ }
+
+ text = $(t[2])$(s[2]) ;
+ lines += $(t[1]) ;
+ }
+ return $(lines) ;
+}
+
+# Generate a set of fixed lines. Each single item passed in is
+# output on a separate line. For console this just echos each line,
+# but for html this will split them with <br>.
+#
+rule lines (
+ text * # The lines of text.
+ : indent ? # Optional indentation prepended to each line after the first one.
+ outdent ? # Optional indentation to prepend to the first line.
+ )
+{
+ text ?= "" ;
+ indent ?= "" ;
+ outdent ?= "" ;
+ if $(output-type) = plain
+ {
+ text $(outdent)$(text[1]) $(indent)$(text[2-]) ;
+ }
+ else if $(output-type) = html
+ {
+ local indent-chars = [ string.chars $(indent) ] ;
+ indent = "" ;
+ for local c in $(indent-chars)
+ {
+ if $(c) = " " { c = ; }
+ else if $(c) = " " { c = ; }
+ indent = $(indent)$(c) ;
+ }
+ local html-text = [ escape-html $(text) : ] ;
+ text $(html-text[1])<br> $(indent)$(html-text[2-])<br> ;
+ }
+}
+
+# Output text directly to the current target. When doing output
+# to a file, one can indicate if the text should be output to
+# "prefix" it, as the "body" (default), or "suffix" of the file. This is
+# independant of the actual execution order of the text rule. This rule
+# invokes a singular action, one action only once, which does the
+# build of the file. Therefore actions on the target outside of this
+# rule will happen entirely before and/or after all output using this rule.
+#
+rule text (
+ strings * # The strings of text to output.
+ : overwrite ? # true to overwrite the output (if it is a file)
+ : prefix-body-suffix ? # Indication to output prefix, body, or suffix (for a file).
+ )
+{
+ prefix-body-suffix ?= body ;
+ if $(output-target) = console
+ {
+ if ! $(strings)
+ {
+ ECHO ;
+ }
+ else
+ {
+ while $(strings)
+ {
+ ECHO $(strings[1]) ;
+ strings = $(strings[2-]) ;
+ }
+ }
+ }
+ # We ignore empty output because the Windows ECHO command is
+ # braindamaged. It doesn't have any facility for echoing a blank line.
+ else if $(output-target)
+ {
+ if ! $($(output-target).did-action)
+ {
+ $(output-target).did-action = yes ;
+ _ on $(output-target) = " " ;
+ nl on $(output-target) = "
+" ;
+ text-redirect-0 on $(output-target) = ">>" ;
+ text-redirect-n on $(output-target) = ">>" ;
+ text-front on $(output-target) = ;
+ text-prefix on $(output-target) = ;
+ text-body on $(output-target) = ;
+ text-suffix on $(output-target) = ;
+ text-action $(output-target) ;
+ text-front-section.$(soutput-target) = ;
+ }
+ if $(overwrite)
+ {
+ text-redirect-0 on $(output-target) = ">" ;
+ }
+ if ! $(text-front-section.$(output-target))
+ {
+ text-front on $(output-target) = [ echo-cmd $(strings[1]) ] ;
+ text-front-section.$(output-target) = $(prefix-body-suffix) ;
+ strings = $(strings[2-]) ;
+ }
+ if $(strings)
+ {
+ if ( $(prefix-body-suffix) = prefix &&
+ $(text-front-section.$(output-target)) != prefix ) ||
+ ( $(prefix-body-suffix) = body &&
+ $(text-front-section.$(output-target)) = suffix )
+ {
+ text-$(text-front-section.$(output-target)) on $(output-target) =
+ [ on $(output-target) return $(text-front) ]
+ [ on $(output-target) return $(text-$(text-front-section.$(output-target))) ] ;
+ text-front on $(output-target) = [ echo-cmd $(strings[1]) ] ;
+ text-front-section.$(output-target) = $(prefix-body-suffix) ;
+ strings = $(strings[2-]) ;
+ }
+ while $(strings)
+ {
+ text-$(prefix-body-suffix) on $(output-target) += [ echo-cmd $(strings[1]) ] ;
+ strings = $(strings[2-]) ;
+ }
+ }
+ }
+}
+
+# Outputs the text to the current targets, after word-wrapping it.
+rule wrapped-text ( text + )
+{
+ local lines = [ split-at-words $(text) ] ;
+ text $(lines) ;
+}
+
+# Escapes text into html/xml printable equivalents.
+# Does not know about tags and therefore tags fed into
+# this will also be escaped. Currently escapes space, "<", ">", and "&".
+#
+rule escape-html (
+ text + # The text to escape.
+ : space ? # What to replace spaces with, defaults to " ".
+ )
+{
+ local html-text = ;
+ while $(text)
+ {
+ local html = $(text[1]) ;
+ text = $(text[2-]) ;
+ html = [ regex.replace $(html) "&" "&" ] ;
+ html = [ regex.replace $(html) "<" "<" ] ;
+ html = [ regex.replace $(html) ">" ">" ] ;
+ if $(space)
+ {
+ html = [ regex.replace $(html) " " "$(space)" ] ;
+ }
+ html-text += $(html) ;
+ }
+ return $(html-text) ;
+}
+
+# Outputs the text strings collected by the text rule to the output
+# file.
+#
+actions quietly text-action
+{
+$(text-front)$(_)$(text-redirect-0)$(_)"$(<)"
+$(text-prefix)$(_)$(text-redirect-n)$(_)"$(<)"$(nl)
+$(text-body)$(_)$(text-redirect-n)$(_)"$(<)"$(nl)
+$(text-suffix)$(_)$(text-redirect-n)$(_)"$(<)"$(nl)
+}
+
+if [ modules.peek : NT ]
+{
+ rule echo-cmd ( string ? )
+ {
+ if $(string) || $(string) != ""
+ {
+ local escaped = [ regex.escape $(string) : "&|()<>^" : "^" ] ;
+ return "echo $(escaped)" ;
+ }
+ else
+ {
+ return "echo." ;
+ }
+ }
+}
+else
+{
+ rule echo-cmd ( string ? )
+ {
+ if $(string) || $(string) != ""
+ {
+ local escaped = [ regex.escape $(string) : "\\\"" : "\\" ] ;
+ return "echo \"$(escaped)\"" ;
+ }
+ else
+ {
+ return "echo" ;
+ }
+ }
+}
+
+local rule __test__ ( )
+{
+ import assert ;
+
+ assert.result one two three : split-at-words one two three : 5 ;
+ assert.result "one two" three : split-at-words one two three : 8 ;
+ assert.result "one two" three : split-at-words one two three : 9 ;
+ assert.result "one two three" : split-at-words one two three ;
+ assert.result "one two three" "&<>" :
+ escape-html "one two three" "&<>" ;
+}
Added: boost-jam/boost-build/branches/upstream/current/util/regex.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/regex.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/regex.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,172 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+#
+# Returns a list of the following substrings:
+# 1) from beginning till the first occurence of 'separator' or till the end,
+# 2) between each occurence of 'separator' and the next occurence,
+# 3) from the last occurence of 'separator' till the end.
+# If no separator is present, the result will contain only one element.
+#
+rule split ( string separator )
+{
+ local result ;
+ local s = $(string) ;
+
+ # Break pieaces off 's' until it has no separators left.
+ local match = 1 ;
+ while $(match)
+ {
+ match = [ MATCH ^(.*)($(separator))(.*) : $(s) ] ;
+ if $(match) {
+ match += "" ; # in case 3rd item was empty - works around MATCH bug
+ result = $(match[3]) $(result) ;
+ s = $(match[1]) ;
+ }
+ }
+ # Combine the remaining part at the beginning, which does not have
+ # separators, with the pieces broken off.
+ # Note that rule's signature does not allow initial s to be empty.
+ return $(s) $(result) ;
+}
+
+# Match string against pattern, and return the elements indicated by
+# indices.
+rule match ( pattern : string : indices * )
+{
+ indices ?= 1 2 3 4 5 6 7 8 9 ;
+ local x = [ MATCH $(pattern) : $(string) ] ;
+ return $(x[$(indices)]) ;
+}
+
+# Matches all elements of 'list' agains the 'pattern'
+# and returns a list of the elements indicated by indices of
+# all successfull matches. If 'indices' is omitted returns
+# a list of first paranthethised groups of all successfull
+# matches.
+#
+rule transform ( list * : pattern : indices * )
+{
+ indices ?= 1 ;
+ local result ;
+ for local e in $(list)
+ {
+ local m = [ MATCH $(pattern) : $(e) ] ;
+ if $(m)
+ {
+ result += $(m[$(indices)]) ;
+ }
+ }
+ return $(result) ;
+}
+
+# Commented out because of 'indices' parameter of 'transform' rule.
+#
+#NATIVE_RULE regex : transform ;
+
+# Escapes all of the characters in symbols using the escape symbol
+# escape-symbol for the given string, and returns the escaped string
+rule escape ( string : symbols : escape-symbol )
+{
+ local result = "" ;
+ local m = 1 ;
+ while $(m)
+ {
+ m = [ MATCH ^([^$(symbols)]*)([$(symbols)])(.*) : $(string) ] ;
+ if $(m)
+ {
+ m += "" ; # Supposedly a bug fix; borrowed from regex.split
+ result = "$(result)$(m[1])$(escape-symbol)$(m[2])" ;
+ string = $(m[3]) ;
+ }
+ }
+ string ?= "" ;
+ result = "$(result)$(string)" ;
+ return $(result) ;
+}
+
+# Replaces occurances of a match string in a given string. Returns the
+# new string. The match string can be a regex expression.
+#
+rule replace (
+ string # The string to modify.
+ match # The characters to replace.
+ replacement # The string to replace with.
+ )
+{
+ local result = "" ;
+ local parts = 1 ;
+ while $(parts)
+ {
+ parts = [ MATCH ^(.*)($(match))(.*) : $(string) ] ;
+ if $(parts)
+ {
+ parts += "" ;
+ result = "$(replacement)$(parts[3])$(result)" ;
+ string = $(parts[1]) ;
+ }
+ }
+ string ?= "" ;
+ result = "$(string)$(result)" ;
+ return $(result) ;
+}
+
+# Replaces occurances of a match string in a given list of strings.
+# Returns the list of new strings. The match string can be a regex
+# expression.
+#
+# list - the list of strings to modify.
+# match - the search expression.
+# replacement - the string to replace with.
+#
+rule replace-list ( list * : match : replacement )
+{
+ local result ;
+ for local e in $(list)
+ {
+ result += [ replace $(e) $(match) $(replacement) ] ;
+ }
+ return $(result) ;
+}
+
+rule __test__ ( )
+{
+ import assert ;
+
+ assert.result a b c : split "a/b/c" / ;
+ assert.result "" a b c : split "/a/b/c" / ;
+ assert.result "" "" a b c : split "//a/b/c" / ;
+ assert.result "" a "" b c : split "/a//b/c" / ;
+ assert.result "" a "" b c "" : split "/a//b/c/" / ;
+ assert.result "" a "" b c "" "" : split "/a//b/c//" / ;
+
+ assert.result a c b d
+ : match (.)(.)(.)(.) : abcd : 1 3 2 4 ;
+
+ assert.result a b c d
+ : match (.)(.)(.)(.) : abcd ;
+
+ assert.result ababab cddc
+ : match ((ab)*)([cd]+) : abababcddc : 1 3 ;
+
+ assert.result a.h c.h
+ : transform <a.h> \"b.h\" <c.h> : <(.*)> ;
+
+ assert.result a.h "" b.h c.h
+ : transform <a.h> \"b.h\" <c.h> : <([^>]*)>|\"([^\"]*)\" : 1 2 ;
+
+ assert.result "^<?xml version=\"1.0\"^>"
+ : escape "<?xml version=\"1.0\">" : "&|()<>^" : "^" ;
+
+ assert.result "<?xml version=\\\"1.0\\\">"
+ : escape "<?xml version=\"1.0\">" : "\\\"" : "\\" ;
+
+ assert.result "string string " : replace "string string " " " " " ;
+ assert.result " string string" : replace " string string" " " " " ;
+ assert.result "string string" : replace "string string" " " " " ;
+ assert.result "-" : replace "&" "&" "-" ;
+
+ assert.result "-" "a-b" : replace-list "&" "a&b" : "&" : "-" ;
+}
Added: boost-jam/boost-build/branches/upstream/current/util/sequence.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/sequence.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/sequence.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,319 @@
+# (C) Copyright David Abrahams 2002. 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.
+
+import assert ;
+import numbers ;
+import modules ;
+
+# Note that algorithms in this module execute largely in the caller's
+# module namespace, so that local rules can be used as function
+# objects. Also note that most predicates can be multi-element
+# lists. In that case, all but the first element are prepended to the
+# first argument which is passed to the rule named by the first
+# element.
+
+# Return the elements e of $(sequence) for which [ $(predicate) e ]
+# has a non-null value.
+rule filter ( predicate + : sequence * )
+{
+ local caller = [ CALLER_MODULE ] ;
+ local result ;
+
+ for local e in $(sequence)
+ {
+ if [ modules.call-in $(caller) : $(predicate) $(e) ]
+ {
+ result += $(e) ;
+ }
+ }
+ return $(result) ;
+}
+
+# return a new sequence consisting of [ $(function) $(e) ] for each
+# element e of $(sequence).
+rule transform ( function + : sequence * )
+{
+ local caller = [ CALLER_MODULE ] ;
+ local result ;
+
+ for local e in $(sequence)
+ {
+ result += [ modules.call-in $(caller) : $(function) $(e) ] ;
+ }
+ return $(result) ;
+}
+
+
+rule less ( a b )
+{
+ if $(a) < $(b)
+ {
+ return true ;
+ }
+}
+
+# insertion-sort s using the BinaryPredicate ordered.
+rule insertion-sort ( s * : ordered * )
+{
+ if ! $(ordered)
+ {
+ return [ SORT $(s) ] ;
+ }
+ else
+ {
+ local caller = [ CALLER_MODULE ] ;
+ ordered ?= sequence.less ;
+ local result = $(s[1]) ;
+ if $(ordered) = sequence.less
+ {
+ local head tail ;
+ for local x in $(s[2-])
+ {
+ head = ;
+ tail = $(result) ;
+ while $(tail) && ( $(tail[1]) < $(x) )
+ {
+ head += $(tail[1]) ;
+ tail = $(tail[2-]) ;
+ }
+ result = $(head) $(x) $(tail) ;
+ }
+ }
+ else
+ {
+ for local x in $(s[2-])
+ {
+ local head tail ;
+ tail = $(result) ;
+ while $(tail) && [ modules.call-in $(caller) : $(ordered) $(tail[1]) $(x) ]
+ {
+ head += $(tail[1]) ;
+ tail = $(tail[2-]) ;
+ }
+ result = $(head) $(x) $(tail) ;
+ }
+ }
+
+ return $(result) ;
+ }
+}
+
+# merge two ordered sequences using the BinaryPredicate ordered.
+rule merge ( s1 * : s2 * : ordered * )
+{
+ ordered ?= sequence.less ;
+ local result__ ;
+ local caller = [ CALLER_MODULE ] ;
+
+ while $(s1) && $(s2) {
+ if [ modules.call-in $(caller) : $(ordered) $(s1[1]) $(s2[1]) ]
+ {
+ result__ += $(s1[1]) ;
+ s1 = $(s1[2-]) ;
+ }
+ else if [ modules.call-in $(caller) : $(ordered) $(s2[1]) $(s1[1]) ]
+ {
+ result__ += $(s2[1]) ;
+ s2 = $(s2[2-]) ;
+ }
+ else
+ {
+ s2 = $(s2[2-]) ;
+ }
+
+ }
+ result__ += $(s1) ;
+ result__ += $(s2) ;
+
+ return $(result__) ;
+}
+
+# join the elements of s into one long string. If joint is supplied,
+# it is used as a separator.
+rule join ( s * : joint ? )
+{
+ joint ?= "" ;
+ return $(s:J=$(joint)) ;
+}
+
+# Find the length of any sequence in log(N) time.
+rule length ( s * )
+{
+ local length = "" ;
+ local zeros p10 d z ; # declared once for speed
+
+ # Find the power of 10 that is just less than length(s)
+ zeros = "" ;
+ p10 = 1 ;
+ while $(s[$(p10)0])
+ {
+ p10 = $(p10)0 ;
+ zeros = $(zeros[1])0 $(zeros) ;
+ }
+
+ # zeros is a list of the form ... 000 00 0 ""
+ for z in $(zeros) # for each digit in the result
+ {
+ # Find the next digit
+ d = 0 1 2 3 4 5 6 7 8 9 ;
+ while $(s[$(d[2])$(z)])
+ {
+ d = $(d[2-]) ;
+ }
+
+ # append it to the result
+ length = $(length)$(d[1]) ;
+
+ # Explanation: $(d[1])$(z) the largest number x of the form
+ # n000..., where n is a digit, such that x <= length(s). Here
+ # we're deleting x elements from the list. Since $(s[n]-)
+ # removes n - 1 elements from the list, we chop an additional
+ # one off the end.
+ s = $(s[$(d[1])$(z)--2]) ;
+ }
+ return $(length) ;
+}
+
+rule unique ( list * )
+{
+ local result ;
+ for local f in $(list)
+ {
+ if ! $(f) in $(result)
+ {
+ result += $(f) ;
+ }
+ }
+ return $(result) ;
+}
+
+# Returns the maximum number in 'elements'. Uses 'ordered' for comparisons,
+# or 'numbers.less' is none is provided.
+rule max-element ( elements + : ordered ? )
+{
+ ordered ?= numbers.less ;
+
+ local max = $(elements[1]) ;
+ for local e in $(elements[2-])
+ {
+ if [ $(ordered) $(max) $(e) ]
+ {
+ max = $(e) ;
+ }
+ }
+ return $(max) ;
+}
+
+# Returns all of 'elements' for which corresponding element in parallel
+# list 'rank' is equal to the maximum value in 'rank'.
+rule select-highest-ranked ( elements * : ranks * )
+{
+ if $(elements)
+ {
+ local max-rank = [ max-element $(ranks) ] ;
+ local result ;
+ while $(elements)
+ {
+ if $(ranks[1]) = $(max-rank)
+ {
+ result += $(elements[1]) ;
+ }
+ elements = $(elements[2-]) ;
+ ranks = $(ranks[2-]) ;
+ }
+ return $(result) ;
+ }
+}
+NATIVE_RULE sequence : select-highest-ranked ;
+
+
+local rule __test__ ( )
+{
+ # use a unique module so we can test the use of local rules.
+ module sequence.__test__
+ {
+ import assert ;
+ import sequence ;
+
+ local rule is-even ( n )
+ {
+ if $(n) in 0 2 4 6 8
+ {
+ return true ;
+ }
+ }
+
+ assert.result 4 6 4 2 8
+ : sequence.filter is-even : 1 4 6 3 4 7 2 3 8 ;
+
+ # test that argument binding works
+ local rule is-equal-test ( x y )
+ {
+ if $(x) = $(y)
+ {
+ return true ;
+ }
+ }
+
+ assert.result 3 3 3 : sequence.filter is-equal-test 3 : 1 2 3 4 3 5 3 5 7 ;
+
+ local rule append-x ( n )
+ {
+ return $(n)x ;
+ }
+
+ assert.result 1x 2x 3x : sequence.transform append-x : 1 2 3 ;
+
+ local rule repeat2 ( x )
+ {
+ return $(x) $(x) ;
+ }
+
+ assert.result 1 1 2 2 3 3 : sequence.transform repeat2 : 1 2 3 ;
+
+ local rule test-greater ( a b )
+ {
+ if $(a) > $(b)
+ {
+ return true ;
+ }
+ }
+ assert.result 1 2 3 4 5 6 7 8 9 : sequence.insertion-sort 9 6 5 3 8 7 1 2 4 ;
+ assert.result 9 8 7 6 5 4 3 2 1 : sequence.insertion-sort 9 6 5 3 8 7 1 2 4 : test-greater ;
+ assert.result 1 2 3 4 5 6 : sequence.merge 1 3 5 : 2 4 6 ;
+ assert.result 6 5 4 3 2 1 : sequence.merge 5 3 1 : 6 4 2 : test-greater ;
+ assert.result 1 2 3 : sequence.merge 1 2 3 : ;
+ assert.result 1 : sequence.merge 1 : 1 ;
+
+ assert.result foo-bar-baz : sequence.join foo bar baz : - ;
+ assert.result substandard : sequence.join sub stan dard ;
+ assert.result 3.0.1 : sequence.join 3.0.1 : - ;
+
+ assert.result 0 : sequence.length ;
+ assert.result 3 : sequence.length a b c ;
+ assert.result 17 : sequence.length 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 ;
+
+ assert.result 1 : sequence.length a ;
+ assert.result 10 : sequence.length a b c d e f g h i j ;
+ assert.result 11 : sequence.length a b c d e f g h i j k ;
+ assert.result 12 : sequence.length a b c d e f g h i j k l ;
+
+ local p2 = x ;
+ for local i in 1 2 3 4 5 6 7 8
+ {
+ p2 = $(p2) $(p2) ;
+ }
+ assert.result 256 : sequence.length $(p2) ;
+
+ assert.result 1 2 3 4 5
+ : sequence.unique 1 2 3 2 4 3 3 5 5 5 ;
+
+ assert.result 5
+ : sequence.max-element 1 3 5 0 4 ;
+
+ assert.result e-3 h-3
+ : sequence.select-highest-ranked e-1 e-3 h-3 m-2 : 1 3 3 2 ;
+ }
+}
Added: boost-jam/boost-build/branches/upstream/current/util/set.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/set.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/set.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,62 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+# difference
+# returns the elements of B that are not in A
+rule difference ( B * : A * )
+{
+ local result = ;
+ local element ;
+ for element in $(B)
+ {
+ if ! ( $(element) in $(A) )
+ {
+ result += $(element) ;
+ }
+ }
+ return $(result) ;
+}
+
+NATIVE_RULE set : difference ;
+
+# intersection set1 : set2
+#
+# Removes from set1 any items which don't appear in set2 and returns the result.
+rule intersection ( set1 * : set2 * )
+{
+ local result ;
+ for local v in $(set1)
+ {
+ if $(v) in $(set2)
+ {
+ result += $(v) ;
+ }
+ }
+ return $(result) ;
+}
+
+rule equal ( set1 * : set2 * )
+{
+ if $(set1) in $(set2) && ( $(set2) in $(set1) )
+ {
+ return true ;
+ }
+}
+
+rule __test__ ( )
+{
+ import assert ;
+
+ assert.result 0 1 4 6 8 9
+ : difference 0 1 2 3 4 5 6 7 8 9 : 2 3 5 7 ;
+
+ assert.result 2 5 7 : intersection 0 1 2 4 5 6 7 8 9 : 2 3 5 7 ;
+
+ assert.true equal 1 1 2 3 : 3 2 2 1 ;
+
+ assert.false equal 2 3 : 3 2 2 1 ;
+}
+
+
Added: boost-jam/boost-build/branches/upstream/current/util/string.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/string.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/string.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,122 @@
+# (C) Copyright David Abrahams, 2002.
+# (C) Copyright Rene Rivera, 2003.
+#
+# See accompanying license for terms and conditions of use.
+#
+
+import regex ;
+
+# Characters considered whitespace, as a list.
+.whitespace-chars = " " " " "
+" ;
+
+# Characters considered whitespace, as a single string.
+.whitespace = $(.whitespace-chars:J="") ;
+
+# Returns the canonical set of whitespace characters, as a list.
+#
+rule whitespace-chars ( )
+{
+ return $(.whitespace-chars) ;
+}
+
+# Returns the canonical set of whitespace characters, as a single string.
+#
+rule whitespace ( )
+{
+ return $(.whitespace) ;
+}
+
+# Splits the given string into a list of strings composed
+# of each character of the string in sequence.
+#
+rule chars (
+ string # The string to split.
+ )
+{
+ local result ;
+ while $(string)
+ {
+ local s = [ MATCH (.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.*) : $(string) ] ;
+ string = $(s[9]) ;
+ result += $(s[1-8]) ;
+ }
+
+ # trim off empty strings
+ while $(result[1]) && ! $(result[-1])
+ {
+ result = $(result[1--2]) ;
+ }
+
+ return $(result) ;
+}
+
+# Concatenates the given strings, inserting the given separator
+# between each string.
+#
+rule join (
+ strings * # The strings to join.
+ : separator ? # The optional separator.
+ )
+{
+ separator ?= "" ;
+ return $(strings:J=$(separator)) ;
+}
+
+# Split a string into whitespace separated words.
+#
+rule words (
+ string # The string to split.
+ : whitespace * # Optional, characters to consider as whitespace.
+ )
+{
+ whitespace = $(whitespace:J="") ;
+ whitespace ?= $(.whitespace) ;
+ local w = ;
+ while $(string)
+ {
+ string = [ MATCH "^[$(whitespace)]*([^$(whitespace)]*)(.*)" : $(string) ] ;
+ if $(string[1]) && $(string[1]) != ""
+ {
+ w += $(string[1]) ;
+ }
+ string = $(string[2]) ;
+ }
+ return $(w) ;
+}
+
+# Check that the given string is composed entirely of whitespace.
+#
+rule is-whitespace (
+ string ? # The string to test.
+ )
+{
+ if ! $(string) { return true ; }
+ else if $(string) = "" { return true ; }
+ else if [ MATCH "^([$(.whitespace)]+)$" : $(string) ] { return true ; }
+ else { return ; }
+}
+
+rule __test__ ( )
+{
+ import assert ;
+ assert.result a b c : chars abc ;
+
+ # check boundary cases
+ assert.result a : chars a ;
+ assert.result : chars "" ;
+ assert.result a b c d e f g h : chars abcdefgh ;
+ assert.result a b c d e f g h i : chars abcdefghi ;
+ assert.result a b c d e f g h i j : chars abcdefghij ;
+ assert.result a b c d e f g h i j k : chars abcdefghijk ;
+
+ assert.result a//b/c/d : join a "" b c d : / ;
+ assert.result abcd : join a "" b c d ;
+
+ assert.result a b c : words "a b c" ;
+
+ assert.true is-whitespace " " ;
+ assert.false is-whitespace " a b c " ;
+ assert.true is-whitespace "" ;
+ assert.true is-whitespace ;
+}
Added: boost-jam/boost-build/branches/upstream/current/util/utility.jam
===================================================================
--- boost-jam/boost-build/branches/upstream/current/util/utility.jam 2005-12-22 13:14:52 UTC (rev 13934)
+++ boost-jam/boost-build/branches/upstream/current/util/utility.jam 2005-12-22 14:00:13 UTC (rev 13935)
@@ -0,0 +1,141 @@
+# (C) Copyright David Abrahams 2001. 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.
+
+import "class" : is-instance ;
+import errors ;
+
+rule ungrist ( names * )
+{
+ local result ;
+ for local name in $(names)
+ {
+ local stripped = [ MATCH ^<(.*)>$ : $(name) ] ;
+ if ! $(stripped)
+ {
+ errors.error "in ungrist" $(names) : $(name) is not of the form <.*> ;
+ }
+ result += $(stripped) ;
+ }
+ return $(result) ;
+}
+
+# Return the file of the caller of the rule that called caller-file.
+rule caller-file ( )
+{
+ local bt = [ BACKTRACE ] ;
+ return $(bt[9]) ;
+}
+
+# Returns the textual representation of argument. If it is a class
+# instance, class its 'str' method. Otherwise, returns the argument.
+rule str ( value )
+{
+ if [ is-instance $(value) ]
+ {
+ return [ $(value).str ] ;
+ }
+ else
+ {
+ return $(value) ;
+ }
+}
+
+# Tests if 'a' is equal to 'b'. If 'a' is a class instance,
+# calls its 'equal' method. Uses ordinary jam's comparison otherwise.
+rule equal ( a b )
+{
+ if [ is-instance $(a) ]
+ {
+ return [ $(a).equal $(b) ] ;
+ }
+ else
+ {
+ if $(a) = $(b)
+ {
+ return true ;
+ }
+ }
+}
+
+# Tests if 'a' is less than 'b'. If 'a' is a class instance,
+# calls its 'less' method. Uses ordinary jam's comparison otherwise.
+rule less ( a b )
+{
+ if [ is-instance $(a) ]
+ {
+ return [ $(a).less $(b) ] ;
+ }
+ else
+ {
+ if $(a) < $(b)
+ {
+ return true ;
+ }
+ }
+}
+
+# For all elements of 'list' which do not already have 'suffix',
+# add 'suffix'.
+rule apply-default-suffix ( suffix : list * )
+{
+ local result ;
+ for local i in $(list)
+ {
+ if $(i:S) = $(suffix)
+ {
+ result += $(i) ;
+ }
+ else
+ {
+ result += $(i)$(suffix) ;
+ }
+ }
+ return $(result) ;
+}
+
+
+local rule __test__ ( )
+{
+ import assert ;
+ import "class" : new ;
+ assert.result foo bar : ungrist <foo> <bar> ;
+
+ assert.result 123 : str 123 ;
+
+ class test-class__
+ {
+ rule __init__ ( )
+ {
+ }
+
+ rule str ( )
+ {
+ return "str-test-class" ;
+ }
+
+ rule less ( a )
+ {
+ return "yes, of course!" ;
+ }
+
+ rule equal ( a )
+ {
+ return "not sure" ;
+ }
+ }
+
+ assert.result "str-test-class" : str [ new test-class__ ] ;
+ assert.true less 1 2 ;
+ assert.false less 2 1 ;
+ assert.result "yes, of course!" : less [ new test-class__ ] 1 ;
+ assert.true equal 1 1 ;
+ assert.false equal 1 2 ;
+ assert.result "not sure" : equal [ new test-class__ ] 1 ;
+
+ assert.result foo.lib foo.lib : apply-default-suffix .lib : foo.lib foo.lib ;
+}
+
+
+
More information about the pkg-boost-commits
mailing list