Boost Jam 3.1.16 Release

[SVN r41628]
This commit is contained in:
Rene Rivera 2007-12-03 03:17:01 +00:00
parent c9603dac14
commit a2aab13fac
488 changed files with 0 additions and 58837 deletions

View File

@ -1,65 +0,0 @@
/*
Copyright 2002 David Abrahams.
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)
*/
H1
{
FONT-SIZE: 200%
COLOR: #00007f
}
H2
{
FONT-SIZE: 150%;
}
H3
{
FONT-SIZE: 125%;
}
H4
{
FONT-SIZE: 108%;
}
BODY
{
FONT-SIZE: 100%;
BACKGROUND-COLOR: #ffffff
}
PRE
{
MARGIN-LEFT: 2pc;
FONT-SIZE: 80%;
BACKGROUND-COLOR: #dfffff
}
CODE
{
FONT-SIZE: 95%;
white-space: pre
}
.index
{
TEXT-ALIGN: left
}
.page-index
{
TEXT-ALIGN: left
}
.definition
{
TEXT-ALIGN: left
}
.footnote
{
FONT-SIZE: 66%;
VERTICAL-ALIGN: super;
TEXT-DECORATION: none
}
.function-semantics
{
CLEAR: left
}
.metafunction-semantics
{
CLEAR: left
}

0
historic/jam/build_dist.bat Normal file → Executable file
View File

View File

@ -1,21 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2003 Rene Rivera.
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)
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="refresh" content="0; URL=v2/index.html" />
<title></title>
</head>
<body>
Automatic redirection failed, please go to <a href=
"v2/index.html">v2/index.html</a>.
</body>
</html>

View File

@ -1,8 +0,0 @@
# Copyright 2001, 2002 Dave Abrahams
# Copyright 2002 Rene Rivera
# Copyright 2003 Vladimir Prus
# 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)
boost-build kernel ;

View File

@ -1,63 +0,0 @@
/* Copyright 2002 Dave 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) */
H1
{
FONT-SIZE: 200%
COLOR: #00007f
}
H2
{
FONT-SIZE: 150%;
}
H3
{
FONT-SIZE: 125%;
}
H4
{
FONT-SIZE: 108%;
}
BODY
{
FONT-SIZE: 100%;
BACKGROUND-COLOR: #ffffff
}
PRE
{
MARGIN-LEFT: 2pc;
FONT-SIZE: 80%;
BACKGROUND-COLOR: #dfffff
}
CODE
{
FONT-SIZE: 95%;
white-space: pre
}
.index
{
TEXT-ALIGN: left
}
.page-index
{
TEXT-ALIGN: left
}
.definition
{
TEXT-ALIGN: left
}
.footnote
{
FONT-SIZE: 66%;
VERTICAL-ALIGN: super;
TEXT-DECORATION: none
}
.function-semantics
{
CLEAR: left
}
.metafunction-semantics
{
CLEAR: left
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -1,18 +0,0 @@
# 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) ;

View File

@ -1,717 +0,0 @@
# Copyright 2003, 2005, 2007 Dave Abrahams
# Copyright 2006, 2007 Rene Rivera
# Copyright 2003, 2004, 2005, 2006 Vladimir Prus
# 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)
# 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 virtual-target ;
import "class" : new ;
import toolset ;
import regex ;
import builtin ;
import make ;
import os ;
import version ;
# Returns the location of the build system. The primary use case
# is building Boost, where it's sometimes needed to get location
# of other components (like BoostBook files), and it's convenient
# to use location relatively to Boost.Build path.
rule location ( )
{
local r = [ modules.binding build-system ] ;
return $(r:P) ;
}
# Returns the property set with the
# free features from the currently processed
# build request.
rule command-line-free-features ( )
{
return $(.command-line-free-features) ;
}
# Check if we can load 'test-config.jam'. If we can, load it and
# ignore user configs.
local argv = [ modules.peek : ARGV ] ;
local test-config = [ GLOB [ os.environ BOOST_BUILD_PATH ] : test-config.jam ] ;
local debug-config = [ MATCH ^(--debug-configuration)$ : [ modules.peek : ARGV ] ] ;
if $(test-config)
{
if $(debug-config)
{
ECHO "notice: loading test-config.jam from"
[ NORMALIZE_PATH $(test-config[1]) ] ;
ECHO "notice: user-config.jam and site-config.jam will be ignored" ;
}
module test-config
{
import toolset : using : using ;
}
import test-config ;
}
local ignore-config ;
if $(test-config) || --ignore-config in [ modules.peek : ARGV ]
{
ignore-config = true ;
}
local user-path = [ os.home-directories ] [ os.environ BOOST_BUILD_PATH ] ;
# Unless ignore-config is set, load the configuration file in
# $(path)/$(basename).jam
local rule load-config ( basename : path + )
{
if ! $(ignore-config)
{
if $(debug-config)
{
ECHO notice: searching \"$(path)\" for \"$(basename).jam\" ;
local where = [ GLOB $(path) : $(basename).jam ] ;
if $(where)
{
ECHO notice: loading $(basename).jam from
[ NORMALIZE_PATH $(where[1]) ] ;
}
}
modules.load $(basename) : : $(path) ;
project.load-used-projects $(basename) ;
}
}
#
# Load site-config.
#
module site-config
{
import project : initialize ;
initialize site-config ;
}
local site-path = /etc $(user-path) ;
if [ os.name ] in NT CYGWIN
{
site-path = [ modules.peek : SystemRoot ] $(user-path) ;
}
load-config site-config : $(site-path) ;
#
# Load user-config.
#
module user-config
{
import project : initialize ;
initialize user-config ;
}
local user-config-path = [ MATCH ^--user-config=(.*) : $(argv) ] ;
user-config-path ?= [ os.environ BOOST_BUILD_USER_CONFIG ] ;
if $(user-config-path)
{
if $(debug-config)
{
ECHO "Loading explicitly specifier user configuration file:" ;
ECHO " $(user-config-path)" ;
}
modules.load user-config : $(user-config-path:BS) : $(user-config-path:D) ;
project.load-used-projects user-config ;
}
else
{
load-config user-config : $(user-path) ;
}
#
# Autoconfigure toolsets based on any instances of --toolset=xx,yy,...zz or
# toolset=xx,yy,...zz in the command line
#
local option-toolsets = [ regex.split-list [ MATCH ^--toolset=(.*) : $(argv) ] : "," ] ;
local feature-toolsets = [ regex.split-list [ MATCH ^toolset=(.*) : $(argv) ] : "," ] ;
# if the user specified --toolset=..., we need to add toolset=... to
# the build request
local extra-build-request ;
if ! $(ignore-config)
{
for local t in $(option-toolsets) $(feature-toolsets)
{
# Parse toolset-version/properties
local (t-v,t,v) = [ MATCH (([^-/]+)-?([^/]+)?)/?.* : $(t) ] ;
local toolset-version = $((t-v,t,v)[1]) ;
local toolset = $((t-v,t,v)[2]) ;
local version = $((t-v,t,v)[3]) ;
if $(debug-config)
{
ECHO notice: [cmdline-cfg] Detected command-line request for
$(toolset-version): toolset= \"$(toolset)\" "version= \""$(version)\" ;
}
local known ;
# if the toolset isn't known, configure it now.
if $(toolset) in [ feature.values <toolset> ]
{
known = true ;
}
if $(known) && $(version)
&& ! [ feature.is-subvalue toolset : $(toolset) : version : $(version) ]
{
known = ;
}
if ! $(known)
{
if $(debug-config)
{
ECHO notice: [cmdline-cfg] toolset $(toolset-version)
not previously configured; configuring now ;
}
toolset.using $(toolset) : $(version) ;
}
else
{
if $(debug-config)
{
ECHO notice: [cmdline-cfg] toolset $(toolset-version) already configured ;
}
}
# make sure we get an appropriate property into the build request in
# case the user used the "--toolset=..." form
if ! $(t) in $(argv)
&& ! $(t) in $(feature-toolsets)
{
if $(debug-config)
{
ECHO notice: [cmdline-cfg] adding toolset=$(t) "to build request." ;
}
extra-build-request += toolset=$(t) ;
}
}
}
if USER_MODULE in [ RULENAMES ]
{
USER_MODULE site-config user-config ;
}
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.
if [ project.find "." : "." ]
{
current-project = [ project.target [ project.load "." ] ] ;
}
if ! [ feature.values <toolset> ]
{
local default-toolset = gcc ;
if [ os.name ] = NT
{
default-toolset = msvc ;
}
ECHO "warning: No toolsets are configured." ;
ECHO "warning: Configuring default toolset" \"$(default-toolset)\". ;
ECHO "warning: If the default is wrong, you may not be able to build C++ programs." ;
ECHO "warning: Use the \"--toolset=xxxxx\" option to override our guess." ;
ECHO "warning: For more configuration options, please consult" ;
ECHO "warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html" ;
if ! $(ignore-config)
{
toolset.using $(default-toolset) ;
}
}
build-request = [
build-request.from-command-line [
modules.peek : ARGV
] $(extra-build-request)
] ;
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) ;
}
else
{
expanded = [ property-set.empty ] ;
}
local target-ids = [ $(build-request).get-at 1 ] ;
local targets
local clean ;
if "--clean-all" in [ modules.peek : ARGV ]
{
cleanall = true ;
}
if "--clean" in [ modules.peek : ARGV ]
{
clean = true ;
}
local bjam-targets ;
# Given a target it, try to find and return corresponding target.
# This is only invoked when there's no Jamfile in "."
# This code somewhat duplicates code in project-target.find but we can't reuse
# that code without project-targets instance.
rule find-target ( target-id )
{
local split = [ MATCH (.*)//(.*) : $(target-id) ] ;
local pm ;
if $(split)
{
pm = [ project.find $(split[1]) : "." ] ;
}
else
{
pm = [ project.find $(target-id) : "." ] ;
}
local result ;
if $(pm)
{
result = [ project.target $(pm) ] ;
}
if $(split)
{
result = [ $(result).find $(split[2]) ] ;
}
return $(result) ;
}
if ! $(current-project)
{
if ! $(target-ids)
{
ECHO "error: no Jamfile in current directory found, and no target references specified." ;
EXIT ;
}
}
for local id in $(target-ids)
{
if $(id) = clean
{
clean = true ;
}
else
{
local t ;
if $(current-project)
{
t = [ $(current-project).find $(id) : no-error ] ;
}
else
{
t = [ find-target $(id) ] ;
}
if ! $(t)
{
ECHO "notice: could not find main target " $(id) ;
ECHO "notice: assuming it's a name of file to create " ;
bjam-targets += $(id) ;
}
else
{
targets += $(t) ;
}
}
}
if ! $(targets)
{
targets += [ project.target [ project.module-name "." ] ] ;
}
virtual-targets = ;
# Virtual targets obtained when building main targets references on
# the command line. When running
#
# bjam --clean main_target
#
# we want to clean the files that belong only to that main target,
# so we need to record which targets are produced.
local results-of-main-targets ;
for local p in $(expanded)
{
.command-line-free-features = [ property-set.create [ $(p).free ] ] ;
for local t in $(targets)
{
local g = [ $(t).generate $(p) ] ;
if ! [ class.is-a $(t) : project-target ]
{
results-of-main-targets += $(g[2-]) ;
}
virtual-targets += $(g[2-]) ;
}
}
# The cleaning is tricky. Say, if
# user says:
#
# bjam --clean foo
#
# where 'foo' is a directory, then we want to clean targets
# which are in 'foo' or in any children Jamfiles, but not in any
# unrelated Jamfiles. So, we collect the list of project under which
# cleaning is allowed.
#
local projects-to-clean ;
local targets-to-clean ;
if $(clean) || $(clean-all)
{
for local t in $(targets)
{
if [ class.is-a $(t) : project-target ]
{
projects-to-clean += [ $(t).project-module ] ;
}
}
local subvariants ;
for local t in $(results-of-main-targets)
{
# Don't include roots or sources.
targets-to-clean += [ virtual-target.traverse $(t) ] ;
}
targets-to-clean = [ sequence.unique $(targets-to-clean) ] ;
}
# Returns 'true' if 'project' is a child of 'current-project',
# possibly indirect, or is equal to 'project'.
# Returns 'false' otherwise.
rule is-child ( project )
{
if ! $(.is-child.$(project))
{
local r = false ;
if $(project) in $(projects-to-clean)
{
r = true ;
}
else
{
local parent = [ project.attribute $(project) parent-module ] ;
if $(parent) && $(parent) != user-config
{
r = [ is-child $(parent) ] ;
}
}
.is-child.$(project) = $(r) ;
}
return $(.is-child.$(project)) ;
}
actual-targets = ;
for t in $(virtual-targets)
{
actual-targets += [ $(t).actualize ] ;
}
# Was an XML dump requested?
.out-xml = [ MATCH --out-xml=(.*) : [ modules.peek : ARGV ] ] ;
if $(.out-xml)
{
# Get the qualified name of a virtual target.
rule full-target-name ( t )
{
local name = [ $(t).name ] ;
local project = [ $(t).project ] ;
local project-path = [ $(project).get location ] ;
return $(project-path)//$(name) ;
}
# Generate an XML file containing build statistics for each
# constituent
rule out-xml ( xml-file : constituents * )
{
# Prepare valid XML header and footer with some basic info
local nl = "
" ;
local jam = [ version.jam ] ;
local os = [ modules.peek : OS OSPLAT JAMUNAME ] "" ;
local timestamp = [ modules.peek : JAMDATE ] ;
local cwd = [ PWD ] ;
local command = [ modules.peek : ARGV ] ;
local bb-version = [ version.boost-build ] ;
.header on $(xml-file) =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"$(nl)<build format=\"1.0\" version=\"$(bb-version)\">"
"$(nl) <jam version=\"$(jam:J=.)\" />"
"$(nl) <os name=\"$(os[1])\" platform=\"$(os[2])\"><![CDATA[$(os[3-]:J= )]]></os>"
"$(nl) <timestamp><![CDATA[$(timestamp)]]></timestamp>"
"$(nl) <directory><![CDATA[$(cwd)]]></directory>"
"$(nl) <command><![CDATA[\"$(command:J=\" \")\"]]></command>"
;
.footer on $(xml-file) =
"$(nl)</build>" ;
# Generate target dependency graph
.contents on $(xml-file) +=
"$(nl) <targets>"
;
for local t in [ virtual-target.all-targets ]
{
local action = [ $(t).action ] ;
if $(action)
{
# If a target has no action, it has
# no dependencies.
local name = [ full-target-name $(t) ] ;
local sources = [ $(action).sources ] ;
local dependencies ;
for local s in $(sources)
{
dependencies += [ full-target-name $(s) ] ;
}
local path = [ $(t).path ] ;
local jam-target = [ $(t).actual-name ] ;
.contents on $(xml-file) +=
"$(nl) <target>"
"$(nl) <name><![CDATA[$(name)]]></name>"
"$(nl) <dependencies>"
"$(nl) <dependency><![CDATA[$(dependencies)]]></dependency>"
"$(nl) </dependencies>"
"$(nl) <path><![CDATA[$(path)]]></path>"
"$(nl) <jam-target><![CDATA[$(jam-target)]]></jam-target>"
"$(nl) </target>"
;
}
}
.contents on $(xml-file) +=
"$(nl) </targets>"
;
# Build $(xml-file) after $(constituents) and do so even if a
# constituent action fails, and regenerate the xml on every bjam run.
INCLUDES $(xml-file) : $(constituents) ;
ALWAYS $(xml-file) ;
__ACTION_RULE__ on $(xml-file) =
build-system.out-xml.generate-action ;
out-xml.generate $(xml-file) ;
}
# The actual build actions are here; if we did this work in the
# actions clause we would have to form a valid command line
# containing the result of @(...) below (the name of the XML file).
rule out-xml.generate-action (
args * : xml-file :
command status start end user system : output ? )
{
local contents =
[ on $(xml-file) return $(.header) $(.contents) $(.footer) ] ;
local f = @($(xml-file):E=$(contents)) ;
}
# Nothing to do here; the *real* actions happen in
# out-xml.generate-action
actions quietly out-xml.generate { }
# Define the out-xml file target, which depends on all the targets
# so that it runs the collection after the targets have run.
out-xml $(.out-xml) : $(actual-targets) ;
# Set up a global __ACTION_RULE__ that records all the available
# statistics about each actual target in a variable "on" the
# --out-xml target.
rule out-xml.collect (
xml-file : target :
command status start end user system : output ? )
{
local nl = "
" ;
# Open the action with some basic info.
.contents on $(xml-file) +=
"$(nl) <action status=\"$(status)\" start=\"$(start)\" end=\"$(end)\" user=\"$(user)\" system=\"$(system)\">"
;
# If we have an action object we can print out more detailed info.
local action = [ on $(target) return $(.action) ] ;
if $(action)
{
local action-name = [ $(action).action-name ] ;
local action-sources = [ $(action).sources ] ;
local action-props = [ $(action).properties ] ;
# The qualified name of the action which we created the target.
.contents on $(xml-file) +=
"$(nl) <name><![CDATA[$(action-name)]]></name>"
;
# The sources that made up the target.
.contents on $(xml-file) +=
"$(nl) <sources>"
;
for local source in $(action-sources)
{
local source-actual = [ $(source).actual-name ] ;
.contents on $(xml-file) +=
"$(nl) <source><![CDATA[$(source-actual)]]></source>"
;
}
.contents on $(xml-file) +=
"$(nl) </sources>"
;
# The properties that define the conditions under which the
# target was built.
.contents on $(xml-file) +=
"$(nl) <properties>"
;
for local prop in [ $(action-props).raw ]
{
local prop-name = [ MATCH ^<(.*)>$ : $(prop:G) ] ;
.contents on $(xml-file) +=
"$(nl) <property name=\"$(prop-name)\"><![CDATA[$(prop:G=)]]></property>"
;
}
.contents on $(xml-file) +=
"$(nl) </properties>"
;
}
local locate = [ on $(target) return $(LOCATE) ] ;
locate ?= "" ;
.contents on $(xml-file) +=
"$(nl) <jam-target><![CDATA[$(target)]]></jam-target>"
"$(nl) <path><![CDATA[$(target:G=:R=$(locate))]]></path>"
"$(nl) <command><![CDATA[$(command)]]></command>"
"$(nl) <output><![CDATA[$(output)]]></output>"
;
.contents on $(xml-file) +=
"$(nl) </action>"
;
}
# When no __ACTION_RULE__ is set "on" a target, the search falls
# back to the global module
module
{
__ACTION_RULE__ = build-system.out-xml.collect
[ modules.peek build-system : .out-xml ] ;
}
}
NOTFILE all ;
DEPENDS all : $(actual-targets) ;
if $(bjam-targets)
{
UPDATE $(bjam-targets:G=e) $(.out-xml) ;
}
else if $(cleanall)
{
UPDATE clean-all ;
}
else if $(clean)
{
local to-clean ;
for local t in [ virtual-target.all-targets ]
{
local p = [ $(t).project ] ;
# Remove only derived targets.
if [ $(t).action ]
{
if $(t) in $(targets-to-clean)
|| [ is-child [ $(p).project-module ] ] = true
{
to-clean += $(t) ;
}
}
}
local to-clean-actual ;
for local t in $(to-clean)
{
to-clean-actual += [ $(t).actualize ] ;
}
common.Clean clean : $(to-clean-actual) ;
UPDATE clean ;
}
else
{
UPDATE all $(.out-xml) ;
}

View File

@ -1,75 +0,0 @@
# Copyright 2003, 2004, 2006 Vladimir Prus
# 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)
# 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 ;
import property-set ;
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 ( name : source-targets * : property-set )
{
return [ property-set.empty ] $(source-targets) ;
}
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) : no-renaming ]
: [ 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 ;

View File

@ -1,300 +0,0 @@
# Copyright 2002 Dave 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)
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-]) ;
local skip-next = ;
for local e in $(command-line)
{
if $(skip-next)
{
skip-next = ;
}
else 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) ;
}
}
else if [ MATCH "^(-[-ldjfsto])$" : $(e) ]
{
skip-next = true ;
}
}
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 ;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,240 +0,0 @@
# Copyright 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)
# 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 ;
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.
#
class modifier : generator
{
rule __init__ (
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).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) ;
}
}
# 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).
#
class name-modifier : modifier
{
rule __init__ ( )
{
# 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 ;
}
}
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 ;

File diff suppressed because it is too large Load Diff

View File

@ -1,464 +0,0 @@
# Copyright 2003 Dave Abrahams
# Copyright 2003, 2004, 2005, 2006 Vladimir Prus
# 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)
import "class" : new ;
import feature ;
import property ;
import sequence ;
import set ;
# 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 ;
import path ;
import errors ;
rule __init__ ( raw-properties * )
{
self.raw = $(raw-properties) ;
for local p in $(raw-properties)
{
if ! $(p:G)
{
errors.error "Invalid property: '$(p)'" ;
}
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) ;
}
rule str ( )
{
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) ;
}
# Computes the target path that should be used for
# target with these properties.
# Returns a list of
# - the computed path
# - if the path is relative to build directory, a value of
# 'true'.
rule target-path ( )
{
if ! $(self.target-path)
{
# The <location> feature can be used to explicitly
# change the location of generated targetsv
local l = [ get <location> ] ;
if $(l)
{
self.target-path = $(l) ;
}
else
{
local p = [ 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 = [ get <location-prefix> ] ;
if $(prefix)
{
self.target-path = [ path.join $(prefix) $(p) ] ;
}
else
{
self.target-path = $(p) ;
}
if ! $(self.target-path)
{
self.target-path = . ;
}
# The path is relative to build dir.
self.target-path += true ;
}
}
return $(self.target-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 )
{
if ! $(self.map-built)
{
# For each feature, create member var and assign all
# values to it. Since all regular member vars start with
# 'self', there will be no conflicts between names.
self.map-built = true ;
for local v in $(self.raw)
{
$(v:G) += $(v:G=) ;
}
}
return $($(feature)) ;
}
}
# 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) ] ] ;
}
# Creates a property-set from the input given by the user, in the
# context of 'jamfile-module' at 'location'
rule create-from-user-input ( raw-properties * : jamfile-module location )
{
local specification = [ property.translate-paths $(raw-properties)
: $(location) ] ;
specification = [ property.translate-indirect $(specification)
: $(jamfile-module) ] ;
specification =
[ property.expand-subfeatures-in-conditions $(specification) ] ;
specification = [ property.make $(specification) ] ;
result = [ property-set.create $(specification) ] ;
return $(result) ;
}
# Refines requirements with requirements provided by the user.
# Specially handles "-<property>value" syntax in specification
# to remove given requirements.
# - parent-requirements -- property-set object with requirements
# to refine
# - specification -- string list of requirements provided by the use
# - project-module -- the module to which context indirect features
# will be bound.
# - location -- the path to which path features are relative.
#
#
rule refine-from-user-input ( parent-requirements : specification *
: project-module : location )
{
if ! $(specification)
{
return $(parent-requirements) ;
}
else
{
local add-requirements ;
local remove-requirements ;
for local r in $(specification)
{
local m = [ MATCH "^-(.*)" : $(r) ] ;
if $(m)
{
remove-requirements += $(m) ;
}
else
{
add-requirements += $(r) ;
}
}
if $(remove-requirements)
{
# Need to create property set, so that path features
# and indirect features are translated just like they
# are in project requirements.
local ps = [ property-set.create-from-user-input
$(remove-requirements) : $(project-module) $(location) ] ;
parent-requirements = [ property-set.create
[ set.difference [ $(parent-requirements).raw ]
: [ $(ps).raw ] ] ] ;
specification = $(add-requirements) ;
}
local requirements = [ property-set.create-from-user-input
$(specification) : $(project-module) $(location) ] ;
requirements = [ $(parent-requirements).refine $(requirements) ] ;
return $(requirements) ;
}
}
# Returns property-set with empty set of properties.
rule empty ( )
{
if ! $(.empty)
{
.empty = [ create ] ;
}
return $(.empty) ;
}

View File

@ -1,704 +0,0 @@
# Copyright 2001, 2002, 2003 Dave Abrahams
# Copyright 2006 Rene Rivera
# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
# 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)
import utility : ungrist ;
import sequence : unique ;
import errors : error ;
import feature ;
import regex ;
import string ;
import sequence ;
import set ;
import path ;
import assert ;
import indirect ;
# 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)
{
# 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 prevent
# validation by passing 'true' as second parameter.
e += [ feature.expand-subfeatures $(c) : true ] ;
}
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 ;
}
}
}
local rule abbreviate-dashed ( string )
{
local r ;
for local part in [ regex.split $(string) - ]
{
r += [ string.abbreviate $(part) ] ;
}
return $(r:J=-) ;
}
local rule identity ( string )
{
return $(string) ;
}
if --abbreviate-paths in [ modules.peek : ARGV ]
{
.abbrev = abbreviate-dashed ;
}
else
{
.abbrev = identity ;
}
# 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) ] ;
p = $(f)-$(p:G=) ;
}
components += [ $(.abbrev) $(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) || ( optional in [ feature.attributes $(feature) ] ) )
{
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]) ;
}
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) ;
}
# Assumes that all feature values that start with '@' are
# names of rules, used in 'context-module'. Such rules
# can be either local to the module or global. Converts such
# values into 'indirect-rule' format (see indirect.jam), so
# that they can be called from other modules.
rule translate-indirect ( specification * : context-module )
{
local result ;
for local p in $(specification)
{
local m = [ MATCH ^@(.+) : $(p:G=) ] ;
if $(m)
{
local v ;
if [ MATCH "^([^%]*)%([^%]+)$" : $(m) ]
{
# Rule is already in indirect format
v = $(m) ;
}
else
{
if ! [ MATCH ".*([.]).*" : $(m) ]
{
# This is unqualified rule name. The user might want
# to set flags on this rule name, and toolset.flag
# auto-qualifies the rule name. Need to do the same
# here so set flag setting work.
# We can arrange for toolset.flag to *not* auto-qualify
# the argument, but then two rules defined in two Jamfiles
# will conflict.
m = $(context-module).$(m) ;
}
v = [ indirect.make $(m) : $(context-module) ] ;
}
v = @$(v) ;
result += $(v:G=$(p:G)) ;
}
else
{
result += $(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 abbreviate-dashed ;
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-equal <toolset>gcc <rtti>off <define>FOO
: refine <toolset>gcc <rtti>off
: <define>FOO
: $(test-space)
;
assert.result-equal <toolset>gcc <optimization>on
: refine <toolset>gcc <optimization>off
: <optimization>on
: $(test-space)
;
assert.result-equal <toolset>gcc <rtti>off
: refine <toolset>gcc : <rtti>off : $(test-space)
;
assert.result-equal <toolset>gcc <rtti>off <rtti>off:<define>FOO
: refine <toolset>gcc : <rtti>off <rtti>off:<define>FOO
: $(test-space)
;
assert.result-equal <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)
;
assert.result optmz-off : abbreviate-dashed optimization-off ;
assert.result rntm-lnk-sttc : abbreviate-dashed runtime-link-static ;
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-equal <rtti>on
: remove free implicit : <toolset>gcc <define>foo <rtti>on : $(test-space) ;
assert.result-equal <include>a
: select include : <include>a <toolset>gcc ;
assert.result-equal <include>a
: select include bar : <include>a <toolset>gcc ;
assert.result-equal <include>a <toolset>gcc
: select include <bar> <toolset> : <include>a <toolset>gcc ;
assert.result-equal <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-equal <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 ;
}

View File

@ -1,13 +0,0 @@
Copyright 2001, 2002 Dave Abrahams
Copyright 2002 Vladimir Prus
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)
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

View File

@ -1,151 +0,0 @@
# Copyright 2003 Dave Abrahams
# Copyright 2002, 2003, 2004, 2005 Vladimir Prus
# 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)
# 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 property-set ;
# 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 : property-set )
{
if ! $(scanner-class) in $(.registered)
{
error "attempt to get unregisted scanner" ;
}
local r = $(.rv-cache.$(property-set)) ;
if ! $(r)
{
r = [ property-set.create
[ property.select $(.relevant-properties.$(scanner-class)) :
[ $(property-set).raw ] ] ] ;
.rv-cache.$(property-set) = $(r) ;
}
if ! $(scanner.$(scanner-class).$(r:J=-))
{
scanner.$(scanner-class).$(r:J=-) = [ new $(scanner-class) [ $(r).raw ] ] ;
}
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 ;

File diff suppressed because it is too large Load Diff

View File

@ -1,501 +0,0 @@
# Copyright 2003 Dave Abrahams
# Copyright 2005 Rene Rivera
# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
# 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)
# 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 ;
.ignore-requirements = ;
# This is used only for testing, to make sure
# we don't get random extra elements in paths.
if --ignore-toolset-requirements in [ modules.peek : ARGV ]
{
.ignore-requirements = 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) ;
$(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 if the 'flags' rule should do checking that
# the invoking module is the same as module we're setting
# flag for.
# 'v' can be either 'checked' or 'unchecked'.
# Subsequent call to 'pop-checking-for-flags-module'
# will restore the behaviour that was in effect before
# calling this rule.
rule push-checking-for-flags-module ( v )
{
.flags-module-checking = $(v) $(.flags-module-checking) ;
}
rule pop-checking-for-flags-module ( )
{
.flags-module-checking = $(.flags-module-checking[2-]) ;
}
# 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.
#
# Propery sets may use value-less properties
# ('<a>' vs. '<a>value') to match absent
# properties. This allows to separately match
#
# <architecture>/<address-model>64
# <architecture>ia64/<address-model>
#
# Where both features are optional. Without this
# syntax we'd be forced to define "default" value.
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.
: hack-hack ? # For
# flags rule OPTIONS <cxx-abi> : -model ansi
# Treak <cxx-abi> as condition
# FIXME: ugly hack.
)
{
local caller = [ CALLER_MODULE ] ;
if ! [ MATCH ".*([.]).*" : $(rule-or-module) ]
&& [ MATCH "(Jamfile<.*)" : $(caller) ]
{
# Unqualified rule name, used inside Jamfile.
# (most likely used with 'make' or 'notfile' rules.
# This prevents setting flags on entire Jamfile module
# (this will be considered as rule), but who cares?
# Probably, 'flags' rule should be split into 'flags' and
# 'flags-on-module'.
rule-or-module = $(caller).$(rule-or-module) ;
}
else
{
local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ;
if $(unchecked) != unchecked
&& $(.flags-module-checking[1]) != unchecked
&& $(module_) != $(caller)
{
errors.error "Module $(caller) attempted to set flags for module $(module_)" ;
}
}
if $(condition) && ! $(condition:G=) && ! $(hack-hack)
{
# 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.
rule find-property-subset ( property-sets * : properties * )
{
# cut property values off
local prop-keys = $(properties:G) ;
local result ;
for local s in $(property-sets)
{
if ! $(result)
{
# Handle value-less properties like '<architecture>' (compare with
# '<architecture>x86').
local set = [ feature.split $(s) ] ;
# Find the set of features that
# - have no property specified in required property set
# - are omitted in build property set
local default-props ;
for local i in $(set)
{
# If $(i) is a value-less property it should match default
# value of an optional property. See the first line in the
# example below:
#
# property set properties result
# <a> <b>foo <b>foo match
# <a> <b>foo <a>foo <b>foo no match
# <a>foo <b>foo <b>foo no match
# <a>foo <b>foo <a>foo <b>foo match
if ! ( $(i:G=) || ( $(i:G) in $(prop-keys) ) )
{
default-props += $(i) ;
}
}
if $(set) in $(properties) $(default-props)
{
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 += $(value) ;
}
return $(result) ;
}
# Given a rule name and a property set, returns a list of interleaved
# variables names and values which must be set on targets for that
# rule/property-set combination.
rule set-target-variables-aux ( rule-or-module : property-set )
{
local result ;
properties = [ $(property-set).raw ] ;
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)) ;
if ! $(condition) ||
[ find-property-subset $(condition) : $(properties) ]
{
local processed ;
for local v in $(values)
{
# The value might be <feature-name> so needs special
# treatment.
processed += [
handle-flag-value $(v) : $(properties) ] ;
}
for local r in $(processed)
{
result += $(variable) $(r) ;
}
}
}
# strip away last dot separated part and recurse.
local next = [ MATCH ^(.+)\\.([^\\.])* : $(rule-or-module) ] ;
if $(next)
{
result += [
set-target-variables-aux $(next[1]) : $(property-set) ] ;
}
return $(result) ;
}
rule set-target-variables ( rule-or-module targets + : property-set )
{
properties = [ $(property-set).raw ] ;
local key = $(rule-or-module).$(property-set) ;
local settings = $(.stv.$(key)) ;
if ! $(settings)
{
settings = [
set-target-variables-aux $(rule-or-module) : $(property-set) ] ;
if ! $(settings)
{
settings = none ;
}
.stv.$(key) = $(settings) ;
}
if $(settings) != none
{
local var-name = ;
for local name-or-value in $(settings)
{
if $(var-name)
{
$(var-name) on $(targets) += $(name-or-value) ;
var-name = ;
}
else
{
var-name = $(name-or-value) ;
}
}
}
}
# 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) ] ;
}
}
}
# Brings all flag definitions from 'base' toolset into
# other toolset 'toolset'. Flag definitions which
# condition make use of properties in 'prohibited-properties'
# are ignored. Don't confuse property and feature, for
# example <debug-symbols>on and <debug-symbols>off, so blocking
# one of them does not block the other one.
#
# The flag conditions are not altered at all, so if condition
# includes name, or version of base toolset, it won't ever match
# the inheriting toolset. When such flag settings must be
# inherited, define a rule in base toolset module and call it
# as needed.
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) ;
# Import the rules to the global scope
IMPORT $(toolset) : $(rules) : : $(toolset).$(rules) ;
}
# Return the list of global 'toolset requirements'.
# Those requirements will be automatically added to
# the requirements of any main target.
rule requirements ( )
{
return $(.requirements) ;
}
# Adds elements to the list of global 'toolset requirements'.
# The requirements will be automatically added to the requirements
# for all main targets, as if they were specified literally.
# For best results, all requirements added should be conditional or
# indirect conditional.
rule add-requirements ( requirements * )
{
if ! $(.ignore-requirements)
{
.requirements += $(requirements) ;
}
}
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) ;
local p-set = <a>/<b> <a>0/<b> <a>/<b>1 <a>0/<b>1 ;
assert.result <a>/<b> : find-property-subset $(p-set) : ;
assert.result <a>0/<b> : find-property-subset $(p-set) : <a>0 <c>2 ;
assert.result <a>/<b>1 : find-property-subset $(p-set) : <b>1 <c>2 ;
assert.result <a>0/<b>1 : find-property-subset $(p-set) : <a>0 <b>1 ;
}

View File

@ -1,370 +0,0 @@
# Copyright 2002, 2003 Dave Abrahams
# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
# 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)
# 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 ;
# 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'.
rule register ( type : suffixes * : base-type ? )
{
# 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) ;
.derived.$(base-type) += $(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) ;
# We used to declare main target rule only when 'main' parameter
# is specified. However, it's hard to decide that a type *never*
# will need a main target rule and so from time to time we needed
# to make yet another type 'main'. So, now main target rule is defined
# for each type.
main-rule-name = [ type-to-rule-name $(type) ] ;
.main-target-type.$(main-rule-name) = $(type) ;
IMPORT $(__name__) : main-target-rule : : $(main-rule-name) ;
}
}
# 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 : property-set )
{
if $(.scanner.$(type)) {
return [ scanner.get $(.scanner.$(type)) : $(property-set) ] ;
}
}
# 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) ;
}
rule all-derived ( type )
{
local result = $(type) ;
for local d in $(.derived.$(type))
{
result += [ all-derived $(d) ] ;
}
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) ] ;
}
}
# Store suffixes for generated targets
.suffixes = [ new property-map ] ;
# Store prefixes for generated targets (e.g. "lib" for library)
.prefixes = [ new property-map ] ;
# 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 )
{
set-generated-target-ps suffix : $(type) : $(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 )
{
change-generated-target-ps suffix : $(type) : $(properties) : $(suffix) ;
}
rule generated-target-suffix ( type : property-set )
{
return [ generated-target-ps suffix : $(type) : $(property-set) ] ;
}
# Sets a target prefix that should be used when generating target
# of 'type' with the specified properties. Can be called with
# empty properties if no prefix for 'type' was specified yet.
#
# The 'prefix' parameter can be empty string ("") to indicate that
# no prefix should be used.
#
# Example usage is for library names that have to have a "lib"
# prefix as in unix.
rule set-generated-target-prefix ( type : properties * : prefix )
{
set-generated-target-ps prefix : $(type) : $(properties) : $(prefix) ;
}
# Change the prefix previously registered for this type/properties
# combination. If prefix is not yet specified, sets it.
rule change-generated-target-prefix ( type : properties * : prefix )
{
change-generated-target-ps prefix : $(type) : $(properties) : $(prefix) ;
}
rule generated-target-prefix ( type : property-set )
{
return [ generated-target-ps prefix : $(type) : $(property-set) ] ;
}
# Common rules for prefix/suffix provisioning follow
rule set-generated-target-ps ( ps : type : properties * : psval )
{
properties = <target-type>$(type) $(properties) ;
$(.$(ps)es).insert $(properties) : $(psval) ;
}
rule change-generated-target-ps ( ps : type : properties * : psval )
{
properties = <target-type>$(type) $(properties) ;
local prev = [ $(.$(ps)es).find-replace $(properties) : $(psval) ] ;
if ! $(prev)
{
set-generated-target-ps $(ps) : $(type) : $(properties) : $(psval) ;
}
}
# Returns either prefix or suffix (as indicated by 'ps') that
# should be used when generating target of 'type' with the specified properties.
# Parameter 'ps' can be either "prefix" or "suffix". If no prefix/suffix is
# specified for 'type', returns prefix/suffix for base type, if any.
rule generated-target-ps-real ( ps : type : properties * )
{
local result ;
local found ;
while $(type) && ! $(found)
{
result = [ $(.$(ps)es).find <target-type>$(type) $(properties) ] ;
# If the prefix/suffix is explicitly set to empty string,
# we consider prefix/suffix to be found. If we did not compare with "",
# there would be no way for user to set empty prefix/suffix.
if $(result)-is-not-empty
{
found = true ;
}
type = $(.bases.$(type)) ;
}
if $(result) = ""
{
result = ;
}
return $(result) ;
}
rule generated-target-ps ( ps : type : property-set )
{
local key = .$(ps).$(type).$(property-set) ;
local v = $($(key)) ;
if ! $(v)
{
v = [ generated-target-ps-real $(ps) : $(type)
: [ $(property-set).raw ] ] ;
if ! $(v)
{
v = none ;
}
$(key) = $(v) ;
}
if $(v) != none
{
return $(v) ;
}
}
# 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]) ;
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) ] ;
}

View File

@ -1,20 +0,0 @@
# Copyright 2002, 2003, 2004, 2006 Vladimir Prus
# 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)
rule boost-build ( )
{
return "V2 (Milestone 12)" ;
}
rule jam ( )
{
local v = [ modules.peek : JAM_VERSION ] ;
return $(v:J=.) ;
}
rule print ( )
{
ECHO "Boost.Build" [ boost-build ] ;
ECHO "Boost.Jam" [ jam ] ;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,317 +0,0 @@
Copyright 2004-2007 Vladimir Prus
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)
Milestone 13 (in development)
Changes in this release:
The following bugs were fixed:
- gcc suport did not work on HP-UX systems
Milestone 12 (Oct 1, 2007)
Changes in this release:
- The Pathscale, PGI and mipspro compilers are now supported.
- Support for autoconfiguration of toolset based on command-line
toolset=xxxx request, and for default toolset
configuration as a fallback.
- Support for precompiled headers for gcc toolset,
and improvements for msvc.
- Mechanism for removing inherited requirements.
- The 'make' rule support specifying usage-requirements.
- New 'project.extension' rule for declaring standalone
projects.
- New 'conditional' convenience rule.
- New 'glob-tree' rule.
- The 'glob' rule accepts patterns to exclude.
- Inline targets are now marked explicit automatically.
- Toolsets can now implicitly add requirements to
all targets.
- New 'generate' rule.
- The executables produced by the 'run' rule are automatically
removed after run.
- The gcc toolset uses the version obtained by running
the compiler, if no explicit one is provided.
- The sun toolset now supports the 'address-model' feature,
and uses -KPIC for shared libraries.
- Free features on command line affect all targets, not
just 'directly requested' ones.
Documentation changes:
- Installation instructions for Linux distributors.
- Configuration options for all supported C++ compilers
are now documented.
The following bugs were fixed:
- The 'cflags' and 'linkflags' now work on Darwin.o
- The intel toolset now works on Windows.
- Fix library search options for CodeWarriour toolset.
- The <install-source-root> could cause duplicate
mkdir commands.
- Numerious fixes in Boost autolink support
- Numerious fixes in Boost.Python support.
- Indirect properties not evaluated in usage requirements.
- Generator that returns a property set but not target is
considered successful.
- On Darwin, when several compiler versions
are configured, -fcoalesce-templates is applied only to
versions that need it.
Milestone 11 (Jule 20, 2006)
Changes in this release:
- New C++ compilers: IBM xlf, HP aCC, HP CXX, Intel fortran compiler.
- New tools: Qt4 support, MS message compiler and IDL compiler.
- New main targets: 'notfile' and 'cast'.
- Core changes:
- Only one file required at top level of a project, named Jamroot.
- Jamfiles can now contain project-specific help messages.
- "Indirect conditional requirements" introduced
(http://tinyurl.com/mn3jp)
- Strip suffix in main target names when computing names of generated
files (URL)
- The 'source-location' project attribute can contain
several directories.
- Usage requirements are propagated not only direct dependents,
but to indirect dependents.
- Command line option changes (see http://tinyurl.com/zbycz)
- New option --build-dir
- The --clean option cleans only target below the current directory,
not globally.
- New --clean-all option was added.
- New option --debug-building
- Running "bjam some_directory" works even if there's no Jamfile
in the current directory.
- Toolset improvements:
- Assembling support with gcc, borland and msvc.
- Support amd64/ia64 cross-compiling with msvc.
- Improved, registry-based autodetection for msvc.
- Serialize execution of gcc.link actions
- Precompiled headers supported on MSVC
(Need documentation)
- New features <warnings> and <warnings-as-errors>
- The 'glob' rule accepts wildcards in directory names.
- The 'stage' rule was renamed to 'install'
(the old name still available for compatibility)
- The <tag> feature can accept user-defined function as value
(URL)
- The 'install' rule can install a directory hierarchy preserving relative
paths.
- The 'install' rule no longer allows to change library
name during install.
- The Jamfile referred via 'use-project' may declare project id different
from the one in 'use-project'.
- The 'using' rule now searches the directory of containing Jamfile.
The following bugs were fixed:
- The <library> feature was ignored for static linking
- Fix #include scanning for C files.
- Child projects were sometimes loaded before parent projects.
- Fix project references with absolute paths on Windows.
- The <dependency> feature was ignored for 'install' targets.
- A generator having the same type in sources and targets was causing hang.
- Use 'icpc' command for Intel, fixing errors with 8.1 and higher.
- Generation of PS files with the FOP tool really produces .PS files.
- No dependency scanning was done for C files.
- The 'constant' and 'path-constant' rules did not accept multi-element
value.
- Don't pass -fcoalesce-templates to gcc on OSX 10.4
- Fix static lib suffix on OSX.
- Fix rpath setting on Intel/Linux.
- The 'install' rule don't unnecessary scans #includes in installed
headers.
Developer visible changes:
- Ability to customize type's prefix depending on build properties.
- Generator's 'run' method can return usage-requirements.
- Main target rule is automatically declared for each new target type.
- 'Link incompatible' feature attribute was removed
- Generators no longer bypass unhandled sources, they just ignore them.
- If there are several applicable generators, immediately report ambiguity.
Provide a way to explicitly resolve conflicts between generators.
- The 'flags' rule can match absense of feature.
- Great improvement in response files handling
- The 'toolset.flags' rules allows value-less feature to signify
absense of this feature (fix hack-hack).
- Automatically declare main target rule for each declared target type.
- When inheriting types, inherit generators for the base type, as opposed
to using various hacks to invoke base generators when needed.
- Improve diagnostic for "duplicate actual target" and generator ambiguity.
Milestone 10 (October 29, 2004)
Changes in this release:
Many toolsets were added: Intel, Metrowerks, Comeau, aCC, vacpp.
Documentation was converted to BoostBook and improved.
Performance was improved.
- Toolsets initialization syntax is much more uniform. Compiler and linker
flags can now be specified.
- The algorithm for computing build properties was improved. Conditional
requirements can be chained, and a number of bugs were fixed.
- Specific order of properties can be specified.
- The main target rules can be called from everywhere, not necessary from
Jamfile.
- Check for "unused sources" removed.
- The <library> feature affects only linking now.
- The <file> feature now works only for libraries.
- Simpler syntax for "searched" libraries was added.
- New <dependency> feature.
Unix:
The right order of static libraries on Unix is automatically
computed.
The <hardcode-dll-paths> feature is the default.
gcc:
The -fPIC option is passed when creating shared libraries.
Problems with distcc were solved.
Sun:
It's now possible to use the sun linker (as opposed to gnu), and
to compile C files.
Darwin:
Shared libraries are now supported.
MSVC: Before resource files compilation, the setup script is invoked.
Options deprecated in 8.0 are not longer used.
The following bugs were fixed:
- The <unit-test> rule did not handle the <library> property (!!!!!!)
- Don't add "bin" to the build directory explicitly specified by the user.
- Allow <include-type> to select staged targets,
even with <traverse-dependencies>off.
- Includes for the form '# include <whatever>" did not work.
- (Qt) Add paths to all dependent libs to uic command
line, which helps if the UI files uses plugins.
- Using <toolset-msvc:version>xxx in requirements was broken.
- Error message printed when target can be found is much more clear.
- Inline targets in sources of 'stage' did not work.
- Don't produce 'independent target' warnings on Windows
- (gcc) The <link-runtime>static did not work.
- (gcc) Suppress warnings from the 'ar' tool on some systems.
- (gcc) Don't try to set soname on NT.
Developer visible changes:
- Generator priorities are gone, explicit overrides are used.
- 'Active' features were removed
- Support for VMS paths was added.
Thanks to Christopher Currie, Pedro Ferreira, Philipp Frauenfelder,
Andre Hentz, Jurgen Hunold, Toon Knapen, Johan Nilsson, Alexey Pakhunov,
Brock Peabody, Michael Stevens and Zbynek Winkler who contributed
code to this release.
Milestone 9.1 (Nov 6, 2003)
The following bugs were fixed:
- The 'unit-test' rule used to ignore <library> properties.
- The gcc toolset used to ignore <threading> property.
Milestone 9 (Nov 6, 2003)
Changes in this release
- Putting library in sources of other library now works even for static
linking, which makes expressing library->library dependency much
simpler.
- Performance was considerably improved.
- Regression testing framework now works on windows.
- The "alias" rule can have usage requirements and passes on usage
requirements of sources.
- The "stage" rule can traverse dependencies.
- Support for "def files" was implemented.
- Targets paths are now shorter.
- Darwin toolset was improved.
The following bugs were fixed:
- It was not possible to specify empty suffix for a target type derived
from other type.
- The stage rules used to generate incorrect suffix in some cases.
- It was possible to load Jamfile twice.
- The 'use-project' rule was broken when referring to a child project.
- Use of composite properties in requirements did not work.
Developer visible changes:
- New CALC builtin, which considerable improves performance.
- Source layout was reorganized.
- Handling of response file was simplified.
Thanks to Pedro Ferreira, Kirill Lapshin, Andre Hentz, Paul Lin,
Jurgen Hunold, Christopher Currie, and Brock Peabody, who contributed to
this release.
Milestone 8 (Oct 15, 2003)
Changes in this release:
- A regression testing framework was implemented.
- New <implicit-dependency> feature was added for better handling
of dependencies to generated headers.
- The link-compatibility checks not longer cause projects to be skipped,
and issue warning, not error, for main targets.
- Algorithm for selecting main target alternative was improved.
- The <dependency> feature was renamed to <use>.
- Project root constants were made available in project root itself.
The following bugs were fixed:
- failure to recognize shared libraries with version as such
- the 'path-constant' rule was mishandling absolute paths on Windows.
Milestone 7 (Sep 11, 2003)
Changes in this release:
- Performance was improved.
- Support for Sun and Darwin toolsets was added.
- <tag> feature, which changes the name of target depending of build
variant, was implemented.
- Old-style targets-ids are no longer supported.
- New 'glob' rule allows to easily perform wildcard matching in Jamfile.
- Improve bison/flex support to understand C++.
The following bugs were fixed:
- bogus error on use of project default-build attribute with several
main target alternatives.
- broken toolset inheritance
- hard error after skipping a target due to incompatible requirements
- incorrect behaviour of a generator when producing several targets of
the same type
- errors on use of the 'project-root' rule in Jamfile context
- inability to require specific compiler version for a main target.
- incorrect behaviour of "bjam msvc" when msvc is configured with explicit
version.
Thanks to Christopher Currie, Pedro Ferreira and Michael Stevens, who
contributed to this release.

View File

@ -1,4 +0,0 @@
boost_build_v2.html
index_v2.html
boost.png
doc

View File

@ -1 +0,0 @@
example/*

View File

@ -1,6 +0,0 @@
boost-build (2.0.m10-1) unstable; urgency=low
* Initial Release.
-- Vladimir Prus <ghost@cs.msu.su> Wed, 14 Aug 2002 14:08:00 +0400

View File

@ -1 +0,0 @@
/etc/site-config.jam

View File

@ -1,13 +0,0 @@
Source: boost-build
Section: devel
Priority: optional
Maintainer: Vladimir Prus <ghost@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.

View File

View File

@ -1,14 +0,0 @@
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

View File

@ -1,56 +0,0 @@
#!/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

View File

@ -1,29 +0,0 @@
# Copyright 2004,2006 Vladimir Prus
# 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)
import quickbook
;
project tools/build/v2/doc
;
boostbook userman : src/standalone.xml
: <xsl:param>toc.section.depth=1
<xsl:param>doc.standalone=true
<xsl:param>nav.layout=none
<implicit-dependency>jam_docs
<dependency>jam_docs
;
xml jam_docs : ../../../jam/doc/bjam.qbk ;
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 ] ;

View File

@ -1,130 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright 2004 Aleksey Gurtovoy -->
<!-- Copyright 2003, 2004 Vladimir Prus -->
<!-- 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) -->
<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: &dash;&dash;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>&copy; 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>

File diff suppressed because it is too large Load Diff

View File

@ -1,636 +0,0 @@
<?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 -- metatargets (abstract targets),
virtual targets, generators and properties.
<itemizedlist>
<listitem><para>Metatargets (see the "targets.jam" module) represent
all the user-defined entities which can be built. The "meta" prefix
signify that they don't really corrspond to files -- depending of
build request, they can produce different set of
files. Metatargets are created when Jamfiles are loaded. Each
metagarget has a <code>generate</code> method which is given a
property set and produces virtual targets for the passed properties.
</para></listitem>
<listitem><para>Virtual targets (see the "virtual-targets.jam"
module) correspond to the atomic things which can be updated --
most typically files.
</para></listitem>
<listitem><para>Properties are just (name, value) pairs, specified
by the user and describing how the targets should be
built. Properties are stored using the <code>property-set</code> class.
</para></listitem>
<listitem><para>Generators are the objects which encapsulate tools
-- they can take a list of source virtual targets and produce new
virtual targets from them.
</para></listitem>
</itemizedlist>
</para>
<para>The build process includes those steps:
<orderedlist>
<listitem><para>Top-level code calls the <code>generate</code>
method of a metatarget with some properties. </para></listitem>
<listitem><para>The metatarget combines the requested properties
with requirements and passes the result, together with the list
of sources, to the <code>generators.construct</code>
function</para></listitem>
<listitem><para>A generator appropriate for the build properties is
selected and its <code>run</code> method is
called. The method returns a list of virtual targets
</para></listitem>
<listitem><para>The targets are returned to the top level code. They
are converted into bjam targets (via
<code>virtual-target.actualize</code>) and passed to bjam for building.
</para></listitem>
</orderedlist>
</para>
<section id="bbv2.arch.metatargets">
<title>Metatargets</title>
<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 : &lt;toolset&gt;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>This means that a specific metatarget subclass may avoid using
generators at all. However, this is deprecated and we're trying to
eliminate all such subsclasses at the moment.
</para>
<para>Note that the <filename>build/targets.jam</filename> file contains
an UML diagram which might help.</para>
</section>
<section id="bbv2.arch.virtual">
<title>Virtual targets</title>
<para>Virtual targets correspond to the atomic things which can be
updated. Each virtual target can be assigned an updating action --
instance of the <code>action</code> class. The action class, in
turn, contains a list of source targets, properties, and a name of
bjam action block which should be executed.
</para>
<para>We try hard to never create equal instances of the
<code>virtual-target</code> class. Each code which creates virtual
targets passes them though the <code>virtual-target.register</code>
function, which detects if a target with the same name, sources, and
properties was created. In that case, existing target is returned.
</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 the
<code>virtual-target.actualize</code> method and the
<code>action.actualize</code> 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, &lt;debug-symbols&gt;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>Note that the <filename>build/virtual-targets.jam</filename> file
contains an UML diagram which might help.</para>
</section>
<section id="bbv2.arch.properties">
<para>Above, we noted that metatargets are built with a set of
properties. That set is represented with the
<code>property-set</code> class. An important point is that handling
of property sets can get very expensive. For that reason, we make
sure that for each set of (name, value) pairs only one
<code>property-set</code> instance is created. The
<code>property-set</code> uses extensive caching for all operation,
so most work is avoided. The <code>property-set.create</code> is the
factory function which should be used to create instances of the
<code>property-set</code> class.
</para>
</section>
</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" &#x2014; 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 &#x2014; 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 (&lt;toolset&gt;gcc) &lt;--(compile)-- a.cpp (scanner1) ----+
a.o (&lt;toolset&gt;msvc) &lt;--(compile)-- a.cpp (scanner2) ----|
a.cpp (installed copy) &lt;--(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 -----&gt; &lt;scanner1&gt;header.h [search path: d1, d2, d3]
&lt;d2&gt;header.h --------&gt; header.y
[generated in d2]
b.cpp -----&gt; &lt;scanner2&gt;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 ----
\
\
&gt;----&gt; &lt;d2&gt;header.h --------&gt; header.y
/ [generated in d2]
/
b.cpp ----
</programlisting>
or
<programlisting>
a.cpp -----&gt; &lt;scanner1&gt;header.h [search path: d1, d2, d3]
|
(includes)
V
&lt;d2&gt;header.h --------&gt; header.y
[generated in d2]
^
(includes)
|
b.cpp -----&gt; &lt;scanner2&gt;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
&lt;scanner1&gt;header.h will also depend on &lt;d2&gt;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 &#x2014; which some people consider a good
thing &#x2014; 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&amp;cd=//public/jam/src/&amp;ra=s&amp;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 -------&gt; C ----&gt; C.pro
/
B --/ C-includes ---&gt; 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 ---&gt; a.cpp
a.cpp-includes --&gt; a.h (scanned)
a.h-includes ------&gt; a.h (generated)
|
|
a.pro &lt;-------------------------------------------+
</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>&lt;feature-name&gt;-&lt;feature-value&gt;</literal> for
ordinary features and <literal>&lt;feature-value&gt;</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-&lt;name&gt;</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:
-->

View File

@ -1,9 +0,0 @@
<?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>

View File

@ -1,873 +0,0 @@
<?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 a simple but
realistic example.</para>
<para>Say you're writing an application that 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 that 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
that are just C++, except that the very first line of the file
contains the name of a variable that should be generated. A simple tool
is created that takes a verbatim file and creates a cpp file with
a single <code>char*</code> variable whose name is taken from the first line
of the verbatim file and whose value is the file's properly quoted content.</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 target type. The following code does
it:</para>
<programlisting>
import type ;
type.register VERBATIM : vrb ;
</programlisting>
<para>The first parameter to
<functionname>type.register</functionname> gives the name of the
declared type. By convention, it's uppercase. The second parameter
is the suffix for files of this type. So, if Boost.Build sees
<filename>code.vrb</filename> in a list of sources, it knows that it's of type
<code>VERBATIM</code>.</para>
<para>Next, you tell Boost.Build that the verbatim files can be
transformed into C++ files in one build step. A
<firstterm>generator</firstterm> is a template for a build step that
transforms targets of one type (or set of types) into another. Our
generator will be called <code>verbatim.inline-file</code>; it
transforms <code>VERBATIM</code> files into <code>CPP</code> files:
<programlisting>
import generators ;
generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
</programlisting>
</para>
<para>Lastly, you have to inform Boost.Build about the shell
commands used to make that transformation. That's done with an
<code>actions</code> declaration.
<programlisting>
actions inline-file
{
"./inline-file.py" $(&lt;) $(&gt;)
}
</programlisting>
<!-- You need to explain all the parameters to an "actions" and
describe the accompanying rule declaration: the user has no clue
what $(<) and $(>) are, and doesn't know about the third
parameter that gets passed to the rule. -->
<!-- We use verbatim.inline-file in one place and just inline-file in
another. Is this confusing for user?
-->
</para>
<para>Now, we're ready to tie it all together. Put all the code
above in file <filename>verbatim.jam</filename>, add <code>import verbatim ;</code>
to <filename>project-root.jam</filename>, 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 <filename>example/customization</filename>
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.
</para>
<para>Sometimes you want to change the suffix used for generated targets
depending on build properties, such as toolset. For example, some compiler
uses extension <literal>elf</literal> for executable files. You can use the
<code>type.set-generated-target-suffix</code> rule:
<programlisting>
type.set-generated-target-suffix EXE : &lt;toolset&gt;elf : elf ;
</programlisting>
</para>
<para>A new target type can be inherited from an existing one.
<programlisting>
type.register PLUGIN : : SHARED_LIB ;
</programlisting>
The above code defines a new type derived from
<code>SHARED_LIB</code>. Initially, the new type inherits all the
properties of the base type - in particular generators and suffix.
Typically, you'll change the new type in some way. For example, using
<code>type.set-generated-target-suffix</code> you can set the suffix for
the new type. Or you can write special a generator for the new type. For
example, it can generate additional metainformation for the plugin.
In either way, the <code>PLUGIN</code> type can be used whenever
<code>SHARED_LIB</code> can. For example, you can directly link plugins
to an application.
</para>
<para>A type can be defined as "main", in which case Boost.Build will
automatically declare a main target rule for building targets of that
type. More details can be found <link
linkend="bbv2.extending.rules.main-type">later</link>.
</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 that returns
the regular expression to be used for scanning. The
parentheses in the regular expression indicate which part
of the string is the name of the included file. Only the
first parenthesized group in the regular expression will be
recognized; if you can't express everything you want that
way, you can return multiple regular expressions, each of
which contains a parenthesized group to be matched.
</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 the properties that contain the list
of paths that should be searched for the included files.
</para>
<para>Finally, we assign the new scanner 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 that it
accepts and produces. Using that information, Boost.Build is able
to automatically invoke the generator. For example, if you declare a
generator that 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>.
<!-- Is the following supposed to be verbatim.jam? Tell the
user so. You also need to describe the meanings of $(<)
and $(>); this is the first time they're encountered. -->
<programlisting>
import generators ;
generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
actions inline-file
{
"./inline-file.py" $(&lt;) $(&gt;)
}
</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> with a 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 used 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>
Standard generators take 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 functions 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>
<!-- What kind of note? Either write the note or don't, but remove this dross. -->
<bridgehead>Custom generator classes</bridgehead>
<para>The standard generators allows you to specify source and target
types, an action, and a set of flags. If you need anything more complex,
<!-- What sort of flags? Command-line flags? What does the system do with them? -->
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) ;
}
<!-- What is the point of this __init__ function?? -->
}
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> method is
responsible for the overall process - it takes a number of source targets,
converts them to 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> <!-- Is it generated-target or generated-targets? -->
method can be overridden
when you want to add additional properties to the generated
targets or use additional sources. For a real-life example,
suppose you have a program analysis tool that 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-targets</code> method can find the list of
sources automatically:
<programlisting>
class itrace-generator : generator {
....
rule generated-targets ( sources + : property-set : project name ? )
{
local leaves ;
local temp = [ virtual-target.traverse $(sources[1]) : : include-sources ] ;<!-- You must explain include-sources! -->
for local t in $(temp)
{
if ! [ $(t).action<!-- In what namespace is this evaluated? --> ]
{
leaves += $(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> method will be called with a single
source target of type <literal>EXE</literal>. The call to
<code>virtual-target.traverse</code> will return all targets the
executable depends on, and we further find files that are not
produced from anything. <!-- What does "not produced from anything" mean? -->
The found targets are added to the sources.
</para>
<para>The <code>run</code> method can be overriden to completely
customize the way the 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 that 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, the Python
program will import itself, not the extension. Here's how it can be
done:
<programlisting>
rule run ( project name ? : property-set : sources * )
{
local python ;
for local s in $(sources)
{
if [ $(s).type ] = PY
{
python = $(s) ;
}
}
<!-- This is horrible code. Use a filter function, or at _least_ consolidate the two loops! -->
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 ] ; # get the target's basename
if $(name) = [ $(python).name ]
{
name = $(name)_ext ; # rename the target
}
new-sources += [ generators.construct $(project) $(name) :
PYTHON_EXTENSION : $(property-set) : $(s) $(libs) ] ;
}
}
result = [ construct-result $(python) $(new-sources) : $(project) $(name)
: $(property-set) ] ;
}
</programlisting>
<!-- Why are we doing this with a generator??? It seems
insane. We could just use a nice front-end rule that
calls some normal target-creation rules. No? -->
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 free 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 &lt;verbatim-options&gt; ;<!-- You must tell the reader what the syntax of the flags rule is -->
# Use the "OPTIONS" variable
actions inline-file
{
"./inline-file.py" $(OPTIONS) $(&lt;) $(&gt;)
}
</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, and 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.
<!-- It's been a while since I wrote these notes, so I don't
remember what I meant. But right here, I wrote "bad" and
circled it. Maybe you can figure out what I meant. ;-)
-->
</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 that 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>&lt;optimization&gt;speed</code> has the same meaning for
all C++ compilers and the user does not have to worry about the exact
options passed to the compiler's command line.
</para>
<para>
Besides such portable features there are special 'raw' features that
allow the user to pass any value to the command line parameters for a
particular tool, if so desired. For example, the
<code>&lt;cxxflags&gt;</code> feature allows you to pass any command line
options to a C++ compiler. The <code>&lt;include&gt;</code> feature
allows you to pass any string preceded by <code>-I</code> and the interpretation
is tool-specific. <!-- It's really tool-specific? That surprises me --> (See <xref
linkend="bbv2.faq.external"/> for an example of very smart usage of that
feature). Of course one should always strive to use portable
features, but these are still be provided as a backdoor just to make
sure Boost.Build does not take away any control from the user.
</para>
<para>
Using portable features is a good idea because:
<itemizedlist>
<listitem>
<para>When a portable feature is given a fixed set of
values, you can build your project with two different
settings of the feature and Boost.Build will automatically
use two different directories for generated files.
Boost.Build does not try to separate targets built with
different raw options.
<!-- It's a computer program. It doesn't "care" about options -->
</para>
</listitem>
<listitem>
<para>Unlike with “raw” features, you don't need to use
specific command-line flags in your Jamfile, and it will be
more likely to work with other tools.
</para>
</listitem>
</itemizedlist>
</para>
<bridgehead>Steps for adding a feauture</bridgehead>
<!-- This section is redundant with the previous one -->
<para>Adding a feature requires three steps:
<orderedlist>
<listitem><para>Declaring a feature. For that, the "feature.feature"
rule is used. You have to decide on the set of <link
linkend="bbv2.reference.features.attributes">feature
attributes</link>:
<itemizedlist>
<listitem><para>if a feature has several values<!-- what do you mean by that?? --> and
significantly affects the build, make it “propagated,” so that the
whole project is built 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.” For example, the
<code>include</code> feature is a free
feature.</para></listitem>
<listitem><para>if a feature is used to refer to a
path relative to the Jamfile, it must be a “path”
feature. <code>include</code> is also a path
feature.</para></listitem>
<listitem><para>if feature is used to refer to some target, it
must be a “dependency” feature. <!-- for example? --></para></listitem>
</itemizedlist>
</para>
</listitem>
<listitem><para>Representing the feature value in a
target-specific variable. Build actions are command
templates modified by Boost.Jam variable expansions. The
<code>toolset.flags</code> rule sets a target-specific
variable to the value of a feature.</para></listitem>
<listitem><para>Using the variable. The variable set in step 2 can
be used in a build action to form command parameters or
files.</para></listitem>
</orderedlist>
</para>
<bridgehead>Another example</bridgehead>
<para>Here's another example.
Let's see how we can make a feature that 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 : &lt;def-file&gt;a.def ;
</programlisting>
<!-- Why would that be nice? It seems to me that having a.def in the sources is the obvious and much nicer thing to do:
lib a : a.cpp a.def ;
-->
Actually, this feature is already supported, but anyway...
<!-- Something about saying that is very off-putting. I'm
sorry that I can't put my finger on it -->
</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 that cares about
<!-- The toolset doesn't "care." What do your really mean? -->
DEF files is msvc. The following line should be added to it.
<!-- Are you saying the msvc toolset is broken (or that it
doesn't use DEF files) as-shipped and the reader needs to
fix it? -->
<programlisting>
flags msvc.link DEF_FILE &lt;def-file&gt; ;
</programlisting>
<!-- And that line does... what? -->
</para></listitem>
<listitem><para>Since the DEF_FILE variable is not used by the
msvc.link action,
<!-- It's not? You just told us that MSVC "cares" about DEF files. I
presume that means that it uses them in some appropriate way? -->
we need to modify it to be:
<programlisting>
actions link bind DEF_FILE
{
$(.LD) .... /DEF:$(DEF_FILE) ....
}
</programlisting>
</para>
<para> Note the <code>bind DEF_FILE</code> part. It tells
bjam to translate the internal target name in
<varname>DEF_FILE</varname> to a corresponding filename in
the <code>link</code> action. Without it the expansion of
<code>$(DEF_FILE)</code> would be a strange symbol that is
not likely to make sense for the linker.
</para>
<!-- I have a note here that says: "none of this works for
targets in general, only source files." I'm not sure
what I meant by that; maybe you can figure it out. -->
<para>
We are almost done, but we should stop for a small workaround. Add the following
code to msvc.jam
<programlisting>
rule link
{
DEPENDS $(&lt;) : [ on $(&lt;) return $(DEF_FILE) ] ;
}
</programlisting>
<!-- You *must* explain the part in [...] above. It's completely opaque to the casual reader -->
This is needed to accomodate some bug in bjam, which hopefully
will be fixed one day.
<!-- This is *NOT* a bug!! Anyway, BBv2 shouild handle this automatically. Why doesn't it? -->
</para></listitem>
</orderedlist>
<bridgehead>Variants and composite features.</bridgehead>
<para>Sometimes you want to create a shortcut for some set of
features. For example, <code>release</code> is a value of
<code>&lt;variant&gt;</code> and is a shortcut for a set of features.
</para>
<para>It is possible to define your own build variants. For example:
<programlisting>
variant crazy : &lt;optimization&gt;speed &lt;inlining&gt;off
&lt;debug-symbols&gt;on &lt;profiling&gt;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 : &lt;define&gt;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.
<!-- What do you mean by that? How is defining a new feature related to what came before? -->
Here's example that defines a brand new feature:
<programlisting>
feature parallelism : mpi fake none : composite link-incompatible ;
feature.compose &lt;parallelism&gt;mpi : &lt;library&gt;/mpi//mpi/&lt;parallelism&gt;none ;
feature.compose &lt;parallelism&gt;fake : &lt;library&gt;/mpi//fake/&lt;parallelism&gt;none ;
</programlisting>
<!-- The use of the <library>/mpi//mpi/<parallelism>none construct
above is at best confusing and unexplained -->
This will allow you to specify the 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>
A main target rule (e.g “<functionname>exe</functionname>
Or “<functionname>lib</functionname>”) creates a top-level target. It's quite likely that you'll want to declare your own and
there are two ways to do that.
<!-- Why did "that" get changed to "this" above? -->
</para>
<para id="bbv2.extending.rules.main-type">The first way applies when
<!-- This is not a "way of defining a main target rule." Rephrase this and the previous sentence. -->
your target rule should just produce a target of specific type. In that case, a
rule is already defined for you! When you define a new type, Boost.Build
automatically defines a corresponding rule. The name of the rule is
obtained from the name of the type, by downcasing all letters and
replacing underscores with dashes.
<!-- This strikes me as needless complexity, and confusing. Why
do we have the uppercase-underscore convention for target
types? If we just dropped that, the rule names could be
the same as the type names. -->
For example, if you create a module
<filename>obfuscate.jam</filename> containing:
<programlisting>
import type ;
type.register OBFUSCATED_CPP : ocpp ;
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 second way is to write a wrapper rule that calls
any of the existing rules. For example, suppose you have only one library per
directory and want all cpp files in the directory to be compiled into that library. You
can achieve this effect with:
<programlisting>
lib codegen : [ glob *.cpp ] ;
</programlisting>
but if you want to make it even simpler, you could add the following
definition to the <filename>project-root.jam</filename> file:
<programlisting>
rule glib ( name : extra-sources * : requirements * )
{
lib $(name) : [ glob *.cpp ] $(extra-sources) : $(requirements) ;
}
</programlisting>
which would allow you to reduce the Jamfile to
<programlisting>
glib codegen ;
</programlisting>
</para>
<para>
Note that because you can associate a custom generator with a target
type, the logic of building can be rather compiler.
<!-- "compiler" is not an adjective. The logic can't be "rather
compiler." What you might mean here is completely
mysterious to me -->
For example, the
<code>boostbook</code> module declares a target type
<code>BOOSTBOOK_MAIN</code> and a custom generator for that
type. You can use that as example if your main target rule is
non-trivial.
</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 that will be
imported by your <filename>project-root.jam</filename>. If the
extensions will be used on many projects, users will thank you for
a finishing touch.
</para>
<para>The <code>using</code> rule provides a standard mechanism
for loading and configuring extensions. To make it work, your module
<!-- "module" hasn't been defined yet. Furthermore you haven't
said anything about where that module file must be
placed. -->
should provide an <code>init</code> rule. The rule will be called
with the same parameters that 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 versions, and other options.
<!-- But it's not entirely arbitrary. We have a standard
parameter order which you should describe here for
context. -->
</para>
<para>Here are some guidelines that help to make Boost.Build more
consistent:
<itemizedlist>
<listitem><para>The <code>init</code> rule should never fail. Even if
the user provided an incorrect 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.
<!-- So why shouldn't init fail on machines where it's wrong?? -->
</para></listitem>
<listitem><para>Prefer specifying the command to be executed
to specifying the tool's installation path. First of all, this
gives more control: it's possible to specify
<programlisting>
/usr/bin/g++-snapshot
time g++
<!-- Is this meant to be a single command? If not, insert "or" -->
</programlisting>
as the command. Second, while some tools have a logical
"installation root", it's better if the user doesn't have to remember whether
a specific tool requires a full command or a path.
<!-- But many tools are really collections: e.g. a
compiler, a linker, and others. The idea that the
"command to invoke" has any significance may be
completely bogus. Plus if you want to allow "time
/usr/bin/g++" the toolset may need to somehow parse
the command and find the path when it needs to invoke
some related executable. And in that case, will the
command be ignored? This scheme doesn't scale and
should be fixed. -->
</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.
<!-- Why should that be typical? -->
If the
tool's 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.
<!-- That would not be so terrible, and is much less harmful
than this restriction, IMO. It makes site-config
harder to maintain than necessary. -->
</para></listitem>
<listitem><para>If possible, <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:
sgml-indent-data: t
sgml-parent-document: ("userman.xml" "chapter")
sgml-set-face: t
End:
-->

View File

@ -1,400 +0,0 @@
<?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>
How do I get the current value of feature in Jamfile?
</title>
<para>
This is not possible, since Jamfile does not have "current" value of any
feature, be it toolset, build variant or anything else. For a single invocation of
<filename>bjam</filename>, any given main target can be built with several property sets.
For example, user can request two build variants on the command line. Or one library
is built as shared when used from one application, and as static when used from another.
Obviously, Jamfile is read only once, so generally, there's no single value of a feature
you can access in Jamfile.
</para>
<para>A feature has a specific value only when building a target, and there are two ways how you
can use that value:</para>
<itemizedlist>
<listitem><simpara>Use conditional requirements or indirect conditional requirements. See
<xref linkend="bbv2.advanced.targets.requirements.conditional"/>.</simpara>
</listitem>
<listitem>Define a custom generator and a custom main target type. The custom generator can do arbitrary processing
or properties. See the <xref linkend="bbv2.extender">extender manual</xref>.
</listitem>
</itemizedlist>
</section>
<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 : &lt;include&gt;/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 : &lt;include&gt;/usr/local/include ;
exe b : a.cpp : &lt;include&gt;/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 : &lt;include&gt;/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 ] : &lt;include&gt;/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 id="bbv2.faq.envar">
<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 os ;
local SOME_LIBRARY_PATH = [ os.environ SOME_LIBRARY_PATH ] ;
exe a : a.cpp : &lt;include&gt;$(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 : &lt;include&gt;b &lt;include&gt;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 : &lt;include&gt;a&amp;&amp;b ;
</programlisting>
</para>
<para>The <code>&amp;&amp;</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
&lt;use&gt; 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 : &lt;use&gt;b ;
</programlisting>
</para>
<para>
The same approach works for searched libraries, too:
<programlisting>
lib z ;
lib png : : &lt;use&gt;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>The <code>SHELL</code> builtin can be used for the purpose:
<programlisting>
local gtk_includes = [ SHELL "gtk-config --cflags" ] ;
</programlisting>
</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 : &lt;optimization&gt;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 : &lt;cflags&gt;-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 : &lt;variant&gt;release:&lt;optimization&gt;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 : &lt;dll-path&gt;/usr/lib/snake
&lt;location&gt;/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 your 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 declare the targets in site-config.jam:</para>
<programlisting>
project site-config ;
lib zlib : : &lt;name&gt;z ;
</programlisting>
<para>Recall that both <filename>site-config.jam</filename> and
<filename>user-config.jam</filename> are projects, and everything
you can do in a Jamfile you can do in those files. So, you declare
a project id and a target. Now, one can write:
<programlisting>
exe hello : hello.cpp /site-config//zlib ;
</programlisting>
in any Jamfile.</para>
</section>
<section id="bbv2.faq.header-only-libraries">
<title>Header-only libraries</title>
<para>In modern C++, libraries often consist of just header files, without
any source files to compile. To use such libraries, you need to add proper
includes and, maybe, defines, to your project. But with large number of
external libraries it becomes problematic to remember which libraries are
header only, and which are "real" ones. However, with Boost.Build a
header-only library can be declared as Boost.Build target and all
dependents can use such library without remebering if it's header-only or not.
</para>
<para>Header-only libraries are declared using the <code>alias</code> rule,
that specifies only usage requirements, for example:
<programlisting>
alias mylib
: # no sources
: # no build requirements
: # no default build
: &lt;include&gt;whatever
;
</programlisting>
The includes specified in usage requirements of <code>mylib</code> are
automatically added to build properties of all dependents. The dependents
need not care if <code>mylib</code> is header-only or not, and it's possible
to later make <code>mylib</code> into a regular compiled library.
</para>
<para>
If you already have proper usage requirements declared for project where
header-only library is defined, you don't need to duplicate them for
the <code>alias</code> target:
<programlisting>
project my : usage-requirements &lt;include&gt;whatever ;
alias mylib ;
</programlisting>
</para>
</section>
</chapter>
<!--
Local Variables:
mode: nxml
sgml-indent-data: t
sgml-parent-document: ("userman.xml" "chapter")
sgml-set-face: t
End:
-->

View File

@ -1,58 +0,0 @@
<?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>
<section id="root_option">
<varlistentry>
<term><literal>root</literal></term>
<!-- At present, this option is only used to set LD_LIBRARY_PATH
when running tests, and matters only if compiler's lib directory
is not in LD_LIBRARY_PATH -->
<listitem><para>Specifies root directory of the compiler
installation. This option is necessary only if it's not possible
to detect this information from the compiler command&#x2014;for
example if the specified compiler command is a user script. </para>
</listitem>
</varlistentry>
</section>
<section id="common_options">
<varlistentry>
<term><literal>cflags</literal></term>
<listitem><para>Specifies additional compiler flags that
will be used when compiling C sources.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>cxxflags</literal></term>
<listitem><para>Specifies additional compiler flags that
will be used when compiling C++ sources.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>compileflags</literal></term>
<listitem><para>Specifies additional compiler flags that
will be used when compiling both C and C++ sources.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>linkflags</literal></term>
<listitem><para>Specifies additional command line options
that will be passed to the linker.</para>
</listitem>
</varlistentry>
</section>
</chapter>

View File

@ -1,34 +0,0 @@
<?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 <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,
see <xref linkend="bbv2.installation"/> and then read about
<xref linkend="bbv2.reference.commandline"/>.
</para>
<para>
If you have questions, please post them to our mailing list (<ulink
url="http://boost.org/more/mailing_lists.htm#jamboost"/>). The mailing list is
also mirrowed to newsgroup <ulink url="news://news.gmane.org/gmane.comp.lib.boost.build"/>.
</para>
</chapter>

View File

@ -1,228 +0,0 @@
<?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 <ulink
url="http://sourceforge.net/project/showfiles.php?group_id=7586&amp;package_id=8041">Boost
source distribution</ulink>
or <ulink url="http://sourceforge.net/cvs/?group_id=7586">CVS
image</ulink>.
<footnote>
<para>Note that packages prepared for
Unix/Linux systems usually make their own choices about where to
put things and even which parts of Boost to include. When we
say &#x201C;released source distribution&#x201D; we mean a
distribution of Boost as released on its SourceForge
<ulink url="http://sourceforge.net/project/showfiles.php?group_id=7586&amp;package_id=8041">project
page</ulink>.
</para>
</footnote>
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 Boost <ulink url="http://sourceforge.net/project/showfiles.php?group_id=7586&amp;package_id=8041">distribution</ulink>.
<footnote>
<para>The Boost.Build subset of boost is also distributed
separately, for those who are only interested in getting a
build tool. The top-level directory of a <ulink
url="http://sourceforge.net/project/showfiles.php?group_id=7586&amp;package_id=80982">Boost.Build
distribution</ulink> contains all the subdirectories of the
<filename>tools/build/v2</filename> subdirectory from a full
Boost distribution, so it is itself a valid Boost.Build root
directory. It also contains the
<filename>tools/jam/src</filename> subdirectory of a
full Boost distribution, so you can rebuild Boost.Jam from
source.
</para>
</footnote>
</para>
<orderedlist>
<listitem>
<simpara>
Boost.Build uses <ulink
url= "../../tools/jam/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&amp;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 necessary to
<link linkend="jam.building">build <command>bjam</command>
from sources</link> 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 necessary, 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>
<bridgehead>Information for distributors</bridgehead>
<para>
If you're planning to package Boost.Build for a Linux distribution,
please follow these guidelines:
<itemizedlist>
<listitem><para>Create a separate package for Boost.Jam.</para></listitem>
<listitem>
<para>Create another package for Boost.Build, and make
this package install all Boost.Build files to
<filename>/usr/share/boost-build</filename> directory. After
install, that directory should contain everything you see in
Boost.Build release package, except for
<filename>jam_src</filename> directory. If you're using Boost CVS
to obtain Boost.Build, as opposed to release package, take
everything from the <filename>tools/build/v2</filename> directory.
For a check, make sure that
<filename>/usr/share/boost-build/boost-build.jam</filename> is installed.
</para>
<para>Placing Boost.Build into <filename>/usr/share/boost-build</filename>
will make sure that <command>bjam</command> will find Boost.Build
without any additional setup.</para>
</listitem>
<listitem><para>Provide a
<filename>/etc/site-config.jam</filename> configuration file that will
contain:
<programlisting>
using gcc ;
</programlisting>
You might want to add dependency from Boost.Build package to gcc,
to make sure that users can always build Boost.Build examples.
</para></listitem>
</itemizedlist>
</para>
<para>If those guidelines are met, users will be able to invoke
<command>bjam</command> without any explicit configuration.
</para>
</chapter>
<!--
Local Variables:
mode: nxml
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:
-->

View File

@ -1,11 +0,0 @@
<?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>

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<book xmlns:xi="http://www.w3.org/2001/XInclude"
id="bbv2" last-revision="$Date$">
<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="tasks.xml"/>
<xi:include href="extending.xml"/>
<xi:include href="reference.xml"/>
<xi:include href="faq.xml"/>
<!-- Appendicies -->
<!-- <xi:include href="architecture.xml"/> -->
<appendix id="bbv2.jam">
<title>Boost.Jam Documentation</title>
<xi:include href="jam_docs.xml" parse="xml"
xpointer="xpointer(id('jam.intro')|id('jam.intro')/following-sibling::*)"/>
</appendix>
<xi:include href="v1_vs_v2.xml"/>
<index/>
</book>

View File

@ -1,657 +0,0 @@
<?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">
<!-- Copyright 2006 Vladimir Prus -->
<!-- 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) -->
<chapter id="bbv2.tasks">
<title>Common tasks</title>
<para>This section describes main targets types that Boost.Build supports
of-of-the-box. Unless otherwise noted, all mentioned main target rules
have the common signature, described in <xref
linkend="bbv2.advanced.targets"/>.
</para>
<section id="bbv2.tasks.programs">
<title>Programs</title>
<indexterm><primary>exe</primary></indexterm>
<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
: &lt;threading&gt;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 that 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. See <xref linkend="bbv2.tasks.installing"/>.
</para>
<!-- We should be emphasizing the use of the built-in testing
rules rather than continually discussing these quirks of
running programs with dynamic libraries. -->
</tip>
</section>
<section id="bbv2.tasks.libraries">
<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 : &lt;include&gt;boost : : &lt;include&gt;. ;
</programlisting>
</para>
<!-- Add one sentence that says what the above does. -->
<para>In the most common case, the <code>lib</code> creates a library
from the specified sources. Depending on the value of
&lt;link&gt; 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.
<!-- But the first case is also prebuilt. This is confusingly phrased. -->
</para>
<para>
The syntax for these case is given below:
<programlisting>
lib z : : &lt;name&gt;z &lt;search&gt;/home/ghost ;
lib compress : : &lt;file&gt;/opt/libs/compress.a ;
</programlisting>
The <code>name</code> property specifies the name that should be
passed to the <option>-l</option> option, and the <code>file</code>
property specifies the file location. The <varname>search</varname> feature
specifies paths in which to search for the library. That feature can
be specified several times, or it can be omitted, in which case only
default compiler paths will be searched.
</para>
<para>The difference between using the <varname>file</varname> feature as
opposed to the <varname>name</varname> feature together with the
<varname>search</varname> feature is that <varname>file</varname> is more
precise. A specific file will be used. On the other hand, the
<varname>search</varname> feature only adds a library path, and the
<varname>name</varname> feature gives the basic name of the library. The
search rules are specific to the linker. For example, given these
definition:
<programlisting>
lib a : : &lt;variant&gt;release &lt;file&gt;/pool/release/a.so ;
lib a : : &lt;variant&gt;debug &lt;file&gt;/pool/debug/a.so ;
lib b : : &lt;variant&gt;release &lt;file&gt;/pool/release/b.so ;
lib b : : &lt;variant&gt;debug &lt;file&gt;/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 <varname>name</varname> and
<varname>search</varname> features, the linker would always pick either
release or debug versions.
<!-- explain -->
</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 : : &lt;name&gt;z ;
lib gui : : &lt;name&gt;gui ;
lib db : : &lt;name&gt;db ;
lib aux : : &lt;name&gt;aux ;
</programlisting>
</para>
<para>When a library uses another library you should put that other
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 : &lt;name&gt;png ;
</programlisting>
</para>
<note>
<para>When a library (say, <code>a</code>), that has another
library, (say, <code>b</code>)
<!-- how can a library "have" a library? -->
is linked dynamically, the <code>b</code>
library will be incorporated
<!-- Incorporated? Be precise. -->
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.)
<!-- Don't parenthesize a whole sentence. -->
When the <code>a</code>
library is linked statically, Boost.Build will assure that all
executables that link to <code>a</code> will also link to
<code>b</code>.
</para>
</note>
<para>One feature of Boost.Build that is very important for libraries
is usage requirements.
<!-- Rephrase that. But then, it's much too late for an
introduction of usage requirements - you've already
discussed them many times. -->
For example, if you write:
<programlisting>
lib helpers : helpers.cpp : : : &lt;include&gt;. ;
</programlisting>
then the compiler include path for all targets that use
<code>helpers</code> will contain the directory
<!-- The rest of this sentence is unintelligible -->
where the target is defined.path to "helpers.cpp". The user
only needs to add <code>helpers</code> to the list of sources,
and needn't consider the requirements its use imposes on a
dependent target. This feature greatly simplifies Jamfiles.
<!-- You can't say “allows to”—you need a noun. This error is
repeated throughout. -->
</para>
<note>
<para>If you don't want shared libraries to include all libraries
that are specified in sources (especially statically linked ones),
you'd need to use the following:
<programlisting>
lib b : a.cpp ;
lib a : a.cpp : &lt;use&gt;b : : &lt;library&gt;b ;
</programlisting>
This specifies that <code>a</code> uses <code>b</code>, and causes
all executables that 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.tasks.alias">
<title>Alias</title>
<para>
The <functionname>alias</functionname> rule gives alternative name to
a group of targets. For example, to give the name
<filename>core</filename> to a group of three other targets with the
following code:
<programlisting>
alias core : im reader writer ;</programlisting>
Using <filename>core</filename> on the command line, or in the source list
of any other target is the same as explicitly using
<filename>im</filename>, <filename>reader</filename>, and
<filename>writer</filename>, but it is just more convenient.
</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 threads : /boost/thread//boost_thread : &lt;link&gt;static ;
</programlisting>
and use only the <code>threads</code> alias in your Jamfiles.
<!-- changed name for clarity -->
</para>
<para>
You can also specify usage requirements for the
<code>alias</code> target. If you write the following:
<programlisting>
alias header_only_library : : : : &lt;include&gt;/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 : : : &lt;include&gt;. ;
alias lib_alias ; <!-- This line can't possibly be correct!?? -->
exe main : main.cpp lib_alias ;
</programlisting>
will compile <filename>main.cpp</filename> with the additional include.
</para>
</section>
<section id="bbv2.tasks.installing">
<title>Installing</title>
<para>This section describes various ways to install built target
and arbitrary files.</para>
<bridgehead>Basic install</bridgehead>
<para>For installing a built target you should use the
<code>install</code> rule, which follows the <link
linkend="bbv2.main-target-rule-syntax">common syntax</link>. For
example:
<programlisting>
install dist : hello helpers ;
</programlisting>
will cause the targets <code>hello</code> and <code>helpers</code> to
be moved to the <filename>dist</filename> directory, relative to
Jamfile's directory. The directory can
be changed with the <code>location</code> property:
<programlisting>
install dist : hello helpers : &lt;location&gt;/usr/bin ;
</programlisting>
While you can achieve the same effect by changing the target name to
<filename>/usr/bin</filename>, using the <code>location</code>
property is better, because it allows you to use a mnemonic target
name.
</para>
<para>The <code>location</code> property is especially handy when the location
is not fixed, but depends on build variant or environment variables:
<programlisting>
install dist : hello helpers : &lt;variant&gt;release:&lt;location&gt;dist/release
&lt;variant&gt;debug:&lt;location&gt;dist/debug ;
install dist2 : hello helpers : &lt;location&gt;$(DIST) ;
</programlisting>
See also <link linkend="bbv2.reference.variants.propcond">conditional
properties</link> and <link linkend="bbv2.faq.envar">environment variables</link>
</para>
<bridgehead>Installing with all dependencies</bridgehead>
<para>
Specifying the names of all libraries to install can be boring. The
<code>install</code> allows you to specify only the top-level executable
targets to install, and automatically install all dependencies:
<programlisting>
install dist : hello
: &lt;install-dependencies&gt;on &lt;install-type&gt;EXE
&lt;install-type&gt;LIB
;
</programlisting>
will find all targets that <code>hello</code> depends on, and install
all of those which are either executables or libraries. More
specifically, for each target, other targets that were specified as
sources or as dependency properties, will be recursively found. One
exception is that targets referred with the <link
linkend="bbv2.builtin.features.use"><code>use</code></link> feature
are not considered, because that feature is typically used to refer to
header-only libraries.
If the set of target types is specified, only targets of that type
will be installed, otherwise, all found target will be installed.
</para>
<bridgehead>Preserving Directory Hierarchy</bridgehead>
<indexterm><primary>install-source-root</primary></indexterm>
<para>By default, the <code>install</code> rules will stip paths from
it's sources. So, if sources include <filename>a/b/c.hpp</filename>,
the <filename>a/b</filename> part will be ignored. To make the
<code>install</code> rule preserve the directory hierarchy you need
to use the <code>install-source-root</code> feature to specify the
root of the hierarchy you are installing. Relative paths from that
root will be preserved. For example, if you write:
<programlisting>
install headers
: a/b/c.h
: &lt;location&gt;/tmp &lt;install-source-root&gt;a
;
</programlisting>
the a file named <filename>/tmp/b/c.h</filename> will be created.
</para>
<para>The <link linkend="bbv2.reference.glob-tree">glob-tree</link> rule
can be used to find all files below a given directory, making
it easy to install entire directory tree.</para>
<bridgehead>Installing into Several Directories</bridgehead>
<para>The <link linkend="bbv2.tasks.alias"><code>alias</code></link>
rule can be used when targets must be installed into several
directories:
<programlisting>
alias install : install-bin install-lib ;
install install-bin : applications : /usr/bin ;
install install-lib : helper : /usr/lib ;
</programlisting>
</para>
<para>Because the <code>install</code> rule just copies targets, most
free features <footnote><para>see the definition of "free" in <xref
linkend="bbv2.reference.features.attributes"/>.</para></footnote>
have no effect when used in requirements of the <code>install</code> rule.
The only two which matter are
<link linkend="bbv2.builtin.features.dependency">
<varname>dependency</varname></link> and, on Unix,
<link linkend="bbv2.reference.features.dll-path"><varname>dll-path</varname></link>.
</para>
<note>
<para>
(Unix specific). On Unix, executables built with Boost.Build typically
contain the list of paths to all used dynamic libraries. For
installing, this is not desired, so Boost.Build relinks the executable
with an empty list of paths. You can also specify additional paths for
installed executables with the <varname>dll-path</varname> feature.
</para>
</note>
</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 <functionname>unit-test</functionname> rule behaves like the
<functionname>exe</functionname> rule, but after the executable is created it is
run. If the executable returns an error code, the build system will also
return an 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>By default, the executable is run directly. Sometimes, it's
desirable to run the executable using some helper command. You should use the
<literal>testing.launcher</literal> property to specify the name of the
helper command. For example, if you write:
</para>
<programlisting>
unit-test helpers_test
: helpers_test.cpp helpers
: <emphasis role="bold">&lt;testing.launcher&gt;valgrind</emphasis>
;
</programlisting>
<para>The command used to run the executable will be:</para>
<screen>
<emphasis role="bold">valgrind</emphasis> bin/$toolset/debug/helpers_test
</screen>
<para>There are few specialized testing rules, listed below:
<programlisting>
rule compile ( sources : requirements * : target-name ? )
rule compile-fail ( sources : requirements * : target-name ? )
rule link ( sources + : requirements * : target-name ? )
rule link-fail ( sources + : requirements * : target-name ? )
</programlisting>
They are are given a list of sources and requirements.
If the target name is not provided, the name of the first
source file is used instead. The <literal>compile*</literal>
tests try to compile the passed source. The <literal>link*</literal>
rules try to compile and link an application from all the passed sources.
The <literal>compile</literal> and <literal>link</literal> rules expect
that compilation/linking succeeds. The <literal>compile-fail</literal>
and <literal>link-fail</literal> rules, on the opposite, expect that
the compilation/linking fails.
</para>
<para>There are two specialized rules for running applications, which
are more powerful than the <code>unit-test</code> rule. The
<code>run</code> rule has the following signature:
<programlisting>
rule run ( sources + : args * : input-files * : requirements * : target-name ?
: default-build * )
</programlisting>
The rule builds application from the provided sources and runs it,
passing <varname>args</varname> and <varname>input-files</varname>
as command-line arguments. The <varname>args</varname> parameter
is passed verbatim and the values of the <varname>input-files</varname>
parameter are treated as paths relative to containing Jamfile, and are
adjusted if <command>bjam</command> is invoked from a different
directory. The <code>run-fail</code> rule is identical to the
<code>run</code> rule, except that it expects that the run fails.
</para>
<para>All rules described in this section, if executed successfully,
create a special manifest file to indicate that the test passed.
For the <code>unit-test</code> rule the files is named
<filename><replaceable>target-name</replaceable>.passed</filename> and
for the other rules it is called
<filename><replaceable>target-name</replaceable>.test</filename>.
The <code>run*</code> rules also capture all output from the program,
and store it in a file named
<filename><replaceable>target-name</replaceable>.output</filename>.</para>
<para>The <code>run</code> and the <code>run-fail</code> rules, if
the test passes, automatically delete the linked executable, to
save space. This behaviour can be suppressed by passing the
<literal>--preserve-test-targets</literal> command line option.</para>
<para>It is possible to print the list of all test targets (except for
<code>unit-test</code>) declared in your project, by passing
the <literal>--dump-tests</literal> command-line option. The output
will consist of lines of the form:
<screen>
boost-test(<replaceable>test-type</replaceable>) <replaceable>path</replaceable> : <replaceable>sources</replaceable>
</screen>
</para>
<para>It is possible to process the list of tests, the output of
bjam during command run, and the presense/absense of the
<filename>*.test</filename> files created when test passes into
human-readable status table of tests. Such processing utilities
are not included in Boost.Build.</para>
</section>
<section id="bbv2.builtins.raw">
<title>Custom commands</title>
<para>When you use most of main target rules, Boost.Build automatically
figures what commands to run and it what order. As soon as you want
to use new file types, or support new tools, one approach is to
extend Boost.Build to smoothly support them, as documented in
<xref linkend="bbv2.extender"/>. However, if there's a single
place where the new tool is used, it might be easier to just
explicitly specify the commands to run.</para>
<para>Three main target rules can be used for that. The
<functionname>make</functionname> rule allows you to construct
a single file from any number of source file, by running a
command you specify. The <functionname>notfile</functionname> rule
allows you to run an arbitrary command, without creating any files.
Finaly, the <functionname>generate</functionname> rule allows you
to describe transformation using Boost.Build's virtual targets.
This is higher-level than file names that the make rule operates with,
and allows you to create more than one target, or create differently
named targets depending on properties, or use more than one
tool.</para>
<para>The <functionname>make</functionname> rule is used when you want to
create one file from a number of sources using some specific command.
The <functionname>notfile</functionname> is used to unconditionally run
a command.
</para>
<para>
Suppose you want to create file <filename>file.out</filename> from
file <filename>file.in</filename> by running command
<command>in2out</command>. Here's how you'd do this in Boost.Build:
<programlisting>
actions in2out
{
in2out $(&lt;) $(&gt;)
}
make file.out : file.in : @in2out ;
</programlisting>
If you run <command>bjam</command> and <filename>file.out</filename>
does not exist, Boost.Build will run the <command>in2out</command>
command to create that file. For more details on specifying actions,
see <xref linkend="bbv2.advanced.jam_language.actions"/>.
</para>
<para>
It could be that you just want to run some command unconditionally,
and that command does not create any specific files. The, you can use
the <functionname>notfile</functionname> rule. For example:
<programlisting>
notfile echo_something : @echo ;
actions echo
{
echo "something"
}
</programlisting>
The only difference from the <functionname>make</functionname> rule is
that the name of the target is not considered a name of a file, so
Boost.Build will unconditionally run the action.
</para>
<para>The <functionname>generate</functionname> rule is used when
you want to express transformations using Boost.Build's virtual targets,
as opposed to just filenames. The <functionname>generate</functionname>
rule has the standard main target rule signature, but you are required
to specify the <literal>generating-rule</literal> property. The value
of the property should be in the form
<literal>@<replaceable>rule-name</replaceable></literal> and the named
rule should have the following signature:
<programlisting>
rule generating-rule ( project name : property-set : sources * )
</programlisting>
and will be called with an instance of the <code>project-target</code>
class, the name of the main target, an instance of the
<code>property-set</code> class containing build properties,
and the list of instances of the <code>virtual-target</code> class
corresponding to sources.
The rule must return a list of <code>virtual-target</code> instances.
The interface of the <code>virtual-target</code> class can be learned
by looking at the <filename>build/virtual-target.jam</filename> file.
The <filename>generate</filename> example in Boost.Build distribution
illustrates how the <literal>generate</literal> rule can be used.
</para>
</section>
<section id="bbv2.reference.precompiled_headers">
<title>Precompiled Headers</title>
<para>Precompiled headers is a mechanism to speed up compilation
by creating a partially processed version of some header files,
and then using that version during compilations rather then
repeatedly parsing the original headers. Boost.Build supports
precompiled headers with gcc and msvc toolsets.</para>
<para>To use precompiled headers, follow these steps:</para>
<orderedlist>
<listitem><para>Create a header that includes big headers used by your project.
It's better to include only headers that are sufficiently stable &#x2014;
like headers from the compiler, and external libraries. Please wrap
the header in <code>#ifdef BOOST_BUILD_PCH_ENABLED</code>, so that
the potentially expensive inclusion of headers is not done
when PCH is not enabled. Include the new header at the top of your
source files.</para></listitem>
<listitem><para>Declare a new Boost.Build target for the precompiled header
and add that precompiled header to the sources of the target whose compilation
you want to speed up:
<programlisting>
cpp-pch pch : header.hpp ;
exe main : main.cpp pch ;</programlisting>
You can use the <code>c-pch</code> if you want to use the precompiled
header in C programs.
</para></listitem>
</orderedlist>
<para>The <filename>pch</filename> example in Boost.Build distribution
can be used as reference.</para>
<para>Please note the following:</para>
<itemizedlist>
<listitem><para>The inclusion of the precompiled header must be the
first thing in a source file, before any code or preprocessor directives.
</para></listitem>
<listitem><para>The build properties used to compile the source files
and the precompiled header must be the same. Consider using
project requirements to assure this.
</para></listitem>
<listitem><para>Precompiled headers must be used purely as a way to
improve compilation time, not to save the number of <code>#include</code>
statements. If a source file needs to include some header, explicitly include
it in the source file, even if the same header is included from
the precompiled header. This makes sure that your project will build
even if precompiled headers are not supported.</para></listitem>
</itemizedlist>
</section>
<section id="bbv2.reference.generated_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>&lt;implicit-dependency&gt;</literal> [ link ] feature must
be used, for example:</para>
<programlisting>
lib parser : parser.y ;
exe app : app.cpp : &lt;implicit-dependency&gt;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>
</chapter>
<!--
Local Variables:
mode: xml
sgml-indent-data: t
sgml-parent-document: ("userman.xml" "chapter")
sgml-set-face: t
End:
-->

View File

@ -1,716 +0,0 @@
<?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">
<title>Tutorial</title>
<!-- You can't launch into this stuff without describing how to configure -->
<!-- Boost.Build... unless of course you think it's likely to work with -->
<!-- no configuration. But even if you do you have to tell people how to -->
<!-- configure their installation in case it doesn't work. -->
<!--
VP: need also mention the examples which correspond to specific
sections.
-->
<para>This section will guide you though the most basic features of
Boost.Build V2. We will start with the &#x201C;Hello, world&#x201D; example,
learn how to use libraries, and finish with testing and installing features.
</para>
<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>Jamroot</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 <filename>hello</filename>
executable by compiling and
linking <filename>hello.cpp</filename>. By default, debug variant
is built. Now, to build the
release variant of <filename>hello</filename>, 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 unnecessary
recompilation. Let's extend the example by adding another line
to our project's <filename>Jamroot</filename>:
<programlisting>
exe hello2 : hello.cpp ;
</programlisting>
Now let us build both the debug and release variants of our project
again:
<screen>
bjam debug release
</screen>
Note that two variants of <filename>hello2</filename> are linked.
Since we have already built both variants
of <filename>hello</filename>, hello.cpp won't be recompiled;
instead the existing object files will just be linked into the
corresponding variants of <filename>hello2</filename>. 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 <filename>hello2</filename>.
<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 <code>debug-symbols</code> feature can have a value of <code>on</code> or
<code>off</code>. 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 <code>release</code> 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 <option>release</option> and <option>debug</option> that we've seen
in <command>bjam</command> invocations are just a shorthand way to
specify values of the <varname>variant</varname> 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> <varname>variant</varname> is so commonly-used that it has
been given special status as an <firstterm>implicit</firstterm>
feature&#x2014;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 in <xref linkend="bbv2.reference.features"/>.
</para>
<section id="bbv2.tutorial.properties.requirements">
<title>Build Requests and Target Requirements</title>
<para>
The set of properties specified on the command line constitute
a <firstterm>build request</firstterm>&#x2014;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 are typically a
combination of the build request and properties derived from
the project's <filename>Jamroot</filename> (and its other
Jamfiles, as described in <xref
linkend="bbv2.tutorial.hierarchy"/>). For example, the
locations of <code>#include</code>d header files are normally
not specified on the command-line, but described in
Jamfiles 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 Jamfile fragment below
illustrates how these requirements might be specified.
</para>
<programlisting>
exe hello
: hello.cpp
: &lt;include&gt;boost &lt;threading&gt;multi
;
</programlisting>
<para>
When <filename>hello</filename> is built, the two
requirements specified above will always be present.
If the build request given on the <command>bjam</command>
command-line explictly contradicts a target's requirements,
the target requirements usually override (or, in the case of
&#x201C;free&rdquo;&#x201D; features like
<varname>&lt;include&gt;</varname>,
<footnote>
<para>
See <xref linkend="bbv2.reference.features.attributes"/>
</para></footnote>
augments) the build request.
</para>
<tip>
<para>The value of the <varname>&lt;include&gt;</varname> feature is
relative to the location of <filename>Jamroot</filename> where it's
used.
</para>
</tip>
</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 can specify a
set of <firstterm>attributes</firstterm>, including
requirements:
<programlisting>
project
: requirements &lt;include&gt;/home/ghost/Work/boost &lt;threading&gt;multi
;
exe hello : hello.cpp ;
exe hello2 : hello.cpp ;
</programlisting>
The effect would be as if we specified the same requirement for
both <filename>hello</filename> and <filename>hello2</filename>.
</para>
</section>
</section>
<section id="bbv2.tutorial.hierarchy">
<title>Project Hierarchies</title>
<para>So far we've only considered examples with one project
&#x2014;a. with one user-written Boost.Jam file,
<filename>Jamroot</filename>). A typical large codebase would be
composed of many projects organized into a tree. The top of the
tree is called the <firstterm>project root</firstterm>. Every
subproject is defined by a file called
<filename>Jamfile</filename> in a descendant directory of the
project root. The parent project of a subproject is defined by
the nearest <filename>Jamfile</filename> or
<filename>Jamroot</filename> file in an ancestor directory. For
example, in the following directory layout:
<screen>
top/
|
+-- Jamroot
|
+-- app/
| |
| +-- Jamfile
| `-- app.cpp
|
`-- util/
|
+-- foo/
. |
. +-- Jamfile
. `-- bar.cpp
</screen>
the project root is <filename>top/</filename>. The projects in
<filename>top/app/</filename> and
<filename>top/util/foo/</filename> are immediate children of the
root project.
<note>
<para>
When we refer to a &#x201C;Jamfile,&#x201D; set in normal
type, we mean a file called either
<filename>Jamfile</filename> or
<filename>Jamroot</filename>. When we need to be more
specific, the filename will be set as
&#x201C;<filename>Jamfile</filename>&#x201D; or
&#x201C;<filename>Jamroot</filename>.&#x201D;
</para>
</note>
</para>
<para>
Projects inherit all attributes (such as requirements)
from their parents. Inherited requirements are combined with
any requirements specified by the subproject.
For example, if <filename>top/Jamroot</filename> has
<programlisting>
&lt;include&gt;/home/ghost/local
</programlisting>
in its requirements, then all of its subprojects will have it
in their requirements, too. Of course, any project can add
include paths to those specified by its parents. <footnote>
<para>Many
features will be overridden,
rather than added-to, in subprojects. See <xref
linkend="bbv2.reference.features.attributes"/> for more
information</para>
</footnote>
More details can be found in
<xref linkend= "bbv2.advanced.projects"/>.
</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 subprojects to be built unless the parent project's
Jamfile explicitly requests it. In our example,
<filename>top/Jamroot</filename> might contain:
<programlisting>
build-project app ;
</programlisting>
which would cause the project in <filename>top/app/</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/app/</filename>.
</para>
</section>
<section id="bbv2.tutorial.libs">
<title>Dependent Targets</title>
<para>
When a building a target <filename>X</filename> depends on first
building another target <filename>Y</filename> (such as a
library that must be linked with <firstterm>X</firstterm>),
<filename>Y</filename> is called a
<firstterm>dependency</firstterm> of <filename>X</filename> and
<filename>X</filename> is termed a
<firstterm>dependent</firstterm> of <filename>Y</filename>.
</para>
<para>To get a feeling of target dependencies, let's continue the
above example and see how <filename>top/app/Jamfile</filename> can
use libraries from <filename>top/util/foo</filename>. If
<filename>top/util/foo/Jamfile</filename> contains
<programlisting>
lib bar : bar.cpp ;
</programlisting>
then to use this library in <filename>top/app/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 <filename>bar</filename> declared in the Jamfile at
<filename>../util/foo</filename>.
</para>
<tip>
<para>Some other build system have special syntax for listing dependent
libraries, for example <varname>LIBS</varname> variable. In Boost.Build,
you just add the library to the list of sources.
</para>
</tip>
<para>Suppose we build <filename>app</filename> with:
<screen>
bjam app optimization=full define=USE_ASM
</screen>
Which properties will be used to build <code>foo</code>? The answer is
that some features are
<firstterm>propagated</firstterm>&#x2014;Boost.Build attempts to use
dependencies with the same value of propagated features. The
<varname>&lt;optimization&gt;</varname> feature is propagated, so both
<filename>app</filename> and <filename>foo</filename> will be compiled
with full optimization. But <varname>&lt;define&gt;</varname> is not
propagated: its value will be added as-is to the compiler flags for
<filename>a.cpp</filename>, but won't affect <filename>foo</filename>.
</para>
<para>Let's improve this project further.
The library
probably has some headers that must be used when compiling
<filename>app.cpp</filename>. We could manually add the necessary
<code>#include</code> paths to <filename>app</filename>'s
requirements as values of the
<varname>&lt;include&gt;</varname> feature, but then this work will
be repeated for all programs
that use <filename>foo</filename>. A better solution is to modify
<filename>util/foo/Jamfile</filename> in this way:
<programlisting>
project
: usage-requirements &lt;include&gt;.
;
lib foo : foo.cpp ;
</programlisting>
Usage requirements are applied not to the target being declared
but to its
dependents. In this case, <literal>&lt;include&gt;.</literal> will be applied to all
targets that directly depend on <filename>foo</filename>.
</para>
<para>Another improvement is using symbolic identifiers to refer to
the library, as opposed to <filename>Jamfile</filename> location.
In a large project, a library can be used by many targets, and if
they all use <filename>Jamfile</filename> location,
a change in directory organization entails much work.
The solution is to use project ids&#x2014;symbolic names
not tied to directory layout. First, we need to assign a project id by
adding this code to
<filename>Jamroot</filename>:</para>
<programlisting>
use-project /library-example/foo : util/foo ;
</programlisting>
<para>Second, we modify <filename>app/Jamfile</filename> to use the
project id:
<programlisting>
exe app : app.cpp /library-example/foo//bar ;
</programlisting>
The <filename>/library-example/foo//bar</filename> syntax is used
to refer to the target <filename>bar</filename> in
the project with id <filename>/library-example/foo</filename>.
We've achieved our goal&#x2014;if the library is moved to a different
directory, only <filename>Jamroot</filename> must be modified.
Note that project ids are global&#x2014;two Jamfiles are not
allowed to assign the same project id to different directories.
</para>
<tip>
<para>If you want all applications in some project to link
to a certain library, you can avoid having to specify it directly the sources of every
target by using the
<varname>&lt;library&gt;</varname> property. For example, if <filename>/boost/filesystem//fs</filename>
should be linked to all applications in your project, you can add
<code>&lt;library&gt;/boost/filesystem//fs</code> to the project's requirements, like this:</para>
<programlisting>
project
: requirements &lt;source&gt;/boost/filesystem//fs
;
</programlisting>
</tip>
</section>
<section id="bbv2.tutorial.testing">
<title>Testing</title>
</section>
<section id="bbv2.tutorial.linkage">
<title>Static and shared libaries</title>
<para>Libraries can be either
<emphasis>static</emphasis>, which means they are included in executable
files that 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 create and use both kinds.
</para>
<para>The kind of library produced from a <code>lib</code> target is
determined by the value of the <varname>link</varname> feature. Default
value is <literal>shared</literal>, and to build static library, the value
should be <literal>static</literal>. You can either requiest static build
on the command line:
<screen>
bjam link=static
</screen>
or in the library's requirements:
<programlisting>
lib l : l.cpp : &lt;link&gt;static ;
</programlisting>
</para>
<para>
We can also use the <varname>&lt;link&gt;</varname> property
to express linking requirements on a per-target basis.
For example, if a particular executable can be correctly built
only with the static version of a library, we can qualify the
executable's <link
linkend="bbv2.reference.targets.references">target
reference</link> to the library as follows:
<!-- There has been no earlier indication that target references can
contain properties. You can't assume that the reader will
recognize that strange incantation as a target reference, or that
she'll know what it means. You also can't assume that hyperlinks
will help the reader, because she may be working from a printout,
as I was.
VP: to be addressed when this section is moved. See comment
below.
-->
<programlisting>
exe important : main.cpp helpers/&lt;link&gt;static ;</programlisting>
No matter what arguments are specified on the <command>bjam</command>
command line, <filename>important</filename> will only be linked with
the static version of <filename>helpers</filename>.
</para>
<para>
Specifying properties in target references is especially useful if you
use a library defined in some other project (one you can't
change) but you still want static (or dynamic) linking to that library
in all cases. If that library is used by many targets,
you <emphasis>could</emphasis> use target references
everywhere:
<programlisting>
exe e1 : e1.cpp /other_project//bar/&lt;link&gt;static ;
exe e10 : e10.cpp /other_project//bar/&lt;link&gt;static ;</programlisting>
but that's far from being convenient. A better approach is
to introduce a level of indirection. Create a local
<type>alias</type> target that refers to the static (or
dynamic) version of <filename>foo</filename>:
<programlisting>
alias foo : /other_project//bar/&lt;link&gt;static ;
exe e1 : e1.cpp foo ;
exe e10 : e10.cpp foo ;</programlisting>
The <link linkend="bbv2.tasks.alias"><functionname>alias</functionname></link>
rule is specifically used to rename a reference to a target and possibly
change the properties.
<!-- You should introduce the alias rule in an earlier
section, before describing how it applies to this
specific use-case, and the foregoing sentence should
go there.
VP: we've agreed that this section should be moved further
in the docs, since it's more like advanced reading. When
I'll move it, I'll make sure 'alias' is already mentioned.
-->
</para>
<tip>
<para>
When one library uses another, you put the second library in
the source list of the first. For example:
<programlisting>
lib utils : utils.cpp /boost/filesystem//fs ;
lib core : core.cpp utils ;
exe app : app.cpp core ;</programlisting>
This works no matter what kind of linking is used. When
<filename>core</filename> is built as a shared library, it is linked
directly into <filename>utils</filename>. Static libraries can't
link to other libraries, so when <filename>core</filename> is built
as a static library, its dependency on <filename>utils</filename> is passed along to
<filename>core</filename>'s dependents, causing
<filename>app</filename> to be linked with both
<filename>core</filename> and <filename>utils</filename>.
</para>
</tip>
<note>
<para>(Note for non-UNIX system). Typically, shared libraries must be
installed to a directory in the dynamic linker's search
path. Otherwise, applications that use shared libraries can't be
started. On Windows, the dynamic linker's search path is given by the
<envar>PATH</envar> environment variable. This restriction is lifted
when you use Boost.Build testing facilities&#x2014;the
<envar>PATH</envar> variable will be automatically adjusted before
running executable.
<!-- Need ref here to 'testing facilities' -->
</para>
</note>
</section>
<section id="bbv2.tutorial.conditions">
<title>Conditions and alternatives</title>
<para>Sometimes, particular relationships need to be maintained
among a target's build properties. For example, you might want to set
specific <code>#define</code> when a library is built as shared,
or when a target's <code>release</code> variant is built.
This can be achieved with <firstterm>conditional requirements</firstterm>.
<programlisting>
lib network : network.cpp
: <emphasis role="bold">&lt;link&gt;shared:&lt;define&gt;NEWORK_LIB_SHARED</emphasis>
&lt;variant&gt;release:&lt;define&gt;EXTRA_FAST
;
</programlisting>
In the example above, whenever <filename>network</filename> is
built with <code>&lt;link&gt;shared</code>,
<code>&lt;define&gt;NEWORK_LIB_SHARED</code> will be in its
properties, too. Also, whenever its release variant is built,
<code>&lt;define&gt;EXTRA_FAST</code> will appear in its properties.
</para>
<para>
Sometimes the ways a target is built are so different that
describing them using conditional requirements would be
hard. For example, imagine that a library actually uses
different source files depending on the toolset used to build
it. We can express this situation using <firstterm>target
alternatives</firstterm>:
<programlisting>
lib demangler : dummy_demangler.cpp ; # alternative 1
lib demangler : demangler_gcc.cpp : &lt;toolset&gt;gcc ; # alternative 2
lib demangler : demangler_msvc.cpp : &lt;toolset&gt;msvc ; # alternative 3
</programlisting>
When building <filename>demangler</filename>, Boost.Build will compare
requirements for each alternative with build properties to find the best match.
For example, when building with with <code>&lt;toolset&gt;gcc</code>
alternative 2, will be selected, and when building with
<code>&lt;toolset&gt;msvc</code> alternative 3 will be selected. In all other
cases, the most generic alternative 1 will be built.
</para>
</section>
<section id="bbv2.tutorial.prebuilt">
<title>Prebuilt targets</title>
<para>
To link to libraries whose build instructions aren't given in a Jamfile,
you need to create <code>lib</code> targets with an appropriate
<varname>file</varname> property. Target alternatives can be used to
associate multiple library files with a single conceptual target. For
example:
<programlisting>
# util/lib2/Jamfile
lib lib2
:
: &lt;file&gt;lib2_release.a &lt;variant&gt;release
;
lib lib2
:
: &lt;file&gt;lib2_debug.a &lt;variant&gt;debug
;
</programlisting>
This example defines two alternatives for <filename>lib2</filename>, and
for each one names a prebuilt file. Naturally, there are no sources.
Instead, the <varname>&lt;file&gt;</varname> feature is used to specify
the file name.
</para>
<para>
Once a prebuilt target has been declared, it can be used just like any other target:
<programlisting>
exe app : app.cpp ../util/lib2//lib2 ;
</programlisting>
As with any target, the alternative selected depends on the
properties propagated from <filename>lib2</filename>'s dependents.
If we build the the release and debug versions of <filename>app</filename> will be linked
with <filename>lib2_release.a</filename> and <filename>lib2_debug.a</filename>, respectively.
</para>
<para>
System libraries&#x2014;those that are automatically found by
the toolset by searching through some set of predetermined
paths&#x2014;should be declared almost like regular ones:
<programlisting>
lib pythonlib : : &lt;name&gt;python22 ;
</programlisting>
We again don't specify any sources, but give a
<varname>name</varname> that should be passed to the
compiler. If the gcc toolset were used to link an executable
target to <filename>pythonlib</filename>, <option>-lpython22</option>
would appear in the command line (other compilers may use
different options).
</para>
<para>
We can also specify where the toolset should look for the library:
<programlisting>
lib pythonlib : : &lt;name&gt;python22 &lt;search&gt;/opt/lib ;
</programlisting>
And, of course, target alternatives can be used in the usual way:
<programlisting>
lib pythonlib : : &lt;name&gt;python22 &lt;variant&gt;release ;
lib pythonlib : : &lt;name&gt;python22_d &lt;variant&gt;debug ;
</programlisting>
</para>
<para>A more advanced use of prebuilt targets is described in <xref
linkend="bbv2.recipies.site-config"/>.
</para>
</section>
</chapter>
<!--
Local Variables:
mode: nxml
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:
-->

View File

@ -1,24 +0,0 @@
<?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$">
<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="tasks.xml"/>
<xi:include href="extending.xml"/>
<xi:include href="reference.xml"/>
<xi:include href="faq.xml"/>
<!-- Appendicies -->
<!-- <xi:include href="architecture.xml"/> -->
<xi:include href="v1_vs_v2.xml"/>
</part>

View File

@ -1,111 +0,0 @@
<?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">
<!-- Copyright 2006 Vladimir Prus -->
<!-- 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) -->
<appendix id="bbv2.vs_v1">
<title>Differences to Boost.Build V1</title>
<!-- "Differences to" is the British English usage. American
English is "differences from." You can use the former but be
sure you know what you're doing -->
<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, toolsets were configured by environment variables. If you
wanted to use two versions of the same toolset, you had to create a new
toolset module that would set the variables and then invoke the base
toolset. In V2, toolsets are configured by the
<functionname>using</functionname>, and you can easily configure several
versions of a toolset. See <xref
linkend="bbv2.advanced.configuration"/> 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 use of project requirements. In V1, if several targets had the same
requirements (for example, a common <code>#include</code> path), it was necessary to
manually write the requirements or use a helper rule or template target. In V2, the
common properties can be specified with the <code>requirements</code> project
attribute, as documented in <xref linkend="bbv2.advanced.projects"/>.
</para>
<para><link linkend="bbv2.tutorial.libs">Usage requirements</link>
also help to simplify Jamfiles.
<!-- Simplify, simplify, simplify! You could go through the
entire document several times and make changes like that
one -->
If a library requires
all clients to use specific <code>#include</code> paths or macros when compiling
code that depends on the library, that information can be cleanly
represented.</para>
<para>The difference between <code>lib</code> and <code>dll</code> targets in V1 is completely
eliminated in V2. There's only one library target type, <code>lib</code>, which can create
either static or shared libraries depending on the value of the
<link linkend="bbv2.advanced.builtins.features.link"><varname>&lt;link&gt;</varname>
feature</link>. If your target should be only built in one way<!--"variant" has a different meaning here-->, you
can add <code>&lt;link&gt;shared</code> or <code>&lt;link&gt;static</code> to its 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 &lt;lib&gt;../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 from the others by a double slash to indicate that
you're referring to target <filename>bar</filename> in project <filename>../foo</filename>, and not to
project <filename>../foo/bar</filename>.
</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 implicit features, just:
<programlisting>
bjam msvc release some_target
</programlisting>
See <link linkend="bbv2.reference.commandline">the reference</link> for a
complete description of the syntax.
</para>
</section>
</appendix>
<!--
Local Variables:
mode: xml
sgml-indent-data: t
sgml-parent-document: ("userman.xml" "chapter")
sgml-set-face: t
End:
-->

View File

@ -1,92 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright 2004 Aleksey Gurtovoy -->
<!-- Copyright 2003, 2004 Vladimir Prus -->
<!-- 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) -->
<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: &dash;&dash;tidy-mark false -i -wrap 78 !-->
<title>Boost Build System V2 &mdash; 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&amp;type=1" width="88"
height="31" border="0" alt="SourceForge.net Logo" align="right"></a>
<h1>Boost Build System V2 &mdash; 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.sourceforge.net">STLport</a> &mdash; 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 &mdash; 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>&copy; 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>

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +0,0 @@
# Copyright 2002, 2003 Vladimir Prus
# 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)
boost-build ../kernel ;

View File

@ -1,7 +0,0 @@
# Copyright 2003, 2004 Vladimir Prus
# 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)
exe codegen : codegen.cpp class.verbatim usage.verbatim
t1.verbatim ;

View File

@ -1,7 +0,0 @@
class_template
class %class_name% {
public:
%class_name%() {}
~%class_name%() {}
};

View File

@ -1,36 +0,0 @@
// (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;
}
}

View File

@ -1,44 +0,0 @@
#!/usr/bin/python
# Copyright 2003 Vladimir Prus
# 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)
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()

View File

@ -1,6 +0,0 @@
# Copyright 2003 Vladimir Prus
# 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)
import verbatim ;

View File

@ -1,11 +0,0 @@
Copyright 2003 Vladimir Prus
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)
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.

View File

@ -1,2 +0,0 @@
t1
//###include "t2.verbatim"

View File

@ -1,6 +0,0 @@
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.

View File

@ -1,51 +0,0 @@
# Copyright 2003, 2004 Vladimir Prus
# 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)
# 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" $(<) $(>)
}

View File

@ -1,35 +0,0 @@
# Copyright 2007 Vladimir Prus
# 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)
import common ;
import "class" : new ;
rule generate-example ( project name : property-set : sources * )
{
local result ;
for local s in $(sources)
{
#local ea = [ $(s).action ] ;
#local ep = [ $(ea).properties ] ;
# Create a new action, that takes the source target
# and runs 'common.copy' comamnd on it.
local a = [
new non-scanning-action $(s) : common.copy : $(property-set) ] ;
local source-name = [ $(s).name ] ;
# Create the target to represent the result of the action.
# The target has the name that was specified in Jamfile
# and passed here via the 'name' parameter,
# and the same type and project as the source.
result += [ new file-target $(name)
: [ $(s).type ]
: $(project)
: $(a) ] ;
}
return $(result) ;
}
generate a2 : a.cpp : <generating-rule>@generate-example ;

View File

@ -1,15 +0,0 @@
This example shows the 'generate' rule, that
allows you to construct target using any arbitrary
set of transformation and commands.
The rule is similar to 'make' and 'notfile', but
unlike those, you can operate in terms of
Boost.Build 'virtual targets', which is more
flexible.
Please consult the docs for more explanations.
# Copyright 2007 Vladimir Prus
# 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)

View File

@ -1,10 +0,0 @@
int main()
{
}
/*
Copyright 2007 Vladimir Prus
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)
*/

View File

@ -1,6 +0,0 @@
# Copyright 2006 Vladimir Prus
# 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)
import soap ;
exe foo : foo.gci : <server>on ;

View File

@ -1,7 +0,0 @@
This example shows how to declare a new generator class. It's necessary
when generator's logic is more complex that just running a single tool.
# Copyright 2006 Vladimir Prus
# 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)

View File

@ -1,10 +0,0 @@
int main()
{
return 0;
}
/*
Copyright 2006 Vladimir Prus
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)
*/

View File

@ -1,77 +0,0 @@
# Copyright 2006 Vladimir Prus
# 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)
# This is example of a fictional code generator tool.
# It accepts a single input of type '.gci' and produces
# either one or two outputs of type .cpp, depending
# on the value of the feature <server-mode>
#
# This example is loosely based on gSOAP code generator.
import type ;
import generators ;
import feature ;
import common ;
import "class" : new ;
type.register GCI : gci ;
feature.feature server : off on : incidental ;
class soap-generator : generator
{
import "class" : new ;
rule __init__ ( * : * )
{
generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
}
rule run ( project name ? : property-set : sources * )
{
if ! $(sources[2])
{
# Accept only single source.
local t = [ $(sources[1]).type ] ;
if $(t) = GCI
{
# The type is correct.
# If no output name is specified, guess it from sources.
if ! $(name)
{
name = [ generator.determine-output-name $(sources) ] ;
}
# Produce one output, using just copy.
local a = [ new action $(sources[1])
: common.copy : $(property-set) ] ;
local t = [ new file-target $(name) : CPP : $(project)
: $(a) ] ;
# If in server mode, create another output -- an
# empty file. If this were a real SOAP generator, we
# might have created a single action, and two targets
# both using that action.
local t2 ;
if [ $(property-set).get <server> ] = "on"
{
local a = [ new action : soap.touch : $(property-set) ] ;
t2 = [ new file-target $(name)_server : CPP : $(project)
: $(a) ] ;
}
return [ virtual-target.register $(t) ]
[ virtual-target.register $(t2) ] ;
}
}
}
}
generators.register [ new soap-generator soap.soap : GCI : CPP ] ;
TOUCH = [ common.file-touch-command ] ;
actions touch
{
$(TOUCH) $(<)
}

View File

@ -1,26 +0,0 @@
# Copyright 2003, 2006 Vladimir Prus
# 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)
# 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.mo
;

View File

@ -1,28 +0,0 @@
// 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;
}

View File

@ -1,6 +0,0 @@
# Copyright 2003 Vladimir Prus
# 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)
using gettext ;

View File

@ -1,25 +0,0 @@
Copyright 2003 Vladimir Prus
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)
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"

View File

@ -1,21 +0,0 @@
# 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@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@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@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"

View File

@ -1,2 +0,0 @@
exe hello : hello.cpp ;

View File

@ -1,16 +0,0 @@
// 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;
}

View File

@ -1,4 +0,0 @@
use-project /library-example/foo : util/foo ;
build-project app ;

View File

@ -1,9 +0,0 @@
# Copyright 2002, 2003, 2005 Vladimir Prus
# 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)
# 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 /library-example/foo//bar ;

View File

@ -1,15 +0,0 @@
// 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();
}

View File

@ -1,9 +0,0 @@
# Copyright 2005 Vladimir Prus
# 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)
project
: usage-requirements <include>include ;
lib bar : bar.cpp ;

View File

@ -1,13 +0,0 @@
// 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() {}

View File

@ -1,10 +0,0 @@
// 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();

View File

@ -1,23 +0,0 @@
import notfile ;
import common ;
exe main : main.cpp ;
# Create 'main.cpp' from 'main.cpp.pro' using action
# 'do-something' defined below.
#
make main.cpp : main_cpp.pro : @do-something ;
# In this example, we'll just copy a file.
# Need to find out the name of a command to copy a file.
CP = [ common.copy-command ] ;
# The action itself.
# The 'CP' variable is defined below
# $(>) is source
# $(<) is target
actions do-something
{
$(CP) $(>) $(<)
}

View File

@ -1,2 +0,0 @@
int main() { return 0; }

View File

@ -1,7 +0,0 @@
Copyright 2002, 2005 Vladimir Prus
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)
Example of using custom command to create one file from
another, using the builtin 'make' rule.

View File

@ -1,29 +0,0 @@
# Copyright 2006 Ilya Sokolov
#
# 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)
# pch ##########################################################################
import pch ;
cpp-pch pch
: # sources
include/pch.hpp
: # requirements
<include>include
;
explicit pch ;
# exe ##########################################################################
exe hello_world
: # sources
pch
source/hello_world.cpp
: # requirements
<include>include
: # default build
: # usage requirements
;

View File

@ -1,19 +0,0 @@
/* Copyright 2006 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)
*/
#ifdef BOOST_BUILD_PCH_ENABLED
#ifdef FOO2
int bar();
#endif
class TestClass {
public:
TestClass(int, int) {}
};
#endif

View File

@ -1,15 +0,0 @@
/* Copyright 2006 Ilya Sokolov
Copyright 2006 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)
*/
#include <pch.hpp>
int main()
{
TestClass c(1, 2);
return 0;
}

View File

@ -1,8 +0,0 @@
# Copyright 2006 Vladimir Prus
# 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)
import python_helpers ;
ECHO "test1:" [ python_helpers.test1 ] ;
ECHO "test2:" [ python_helpers.test2 1234 : 5678 ] ;

View File

@ -1,10 +0,0 @@
# Copyright 2006 Vladimir Prus
# 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)
# Import the Python rules to Boost.Build
PYTHON_IMPORT_RULE python_helpers : test1 : python_helpers : test1 ;
PYTHON_IMPORT_RULE python_helpers : test2 : python_helpers : test2 ;
# Make the new rules accessible to everybody who imports us.
EXPORT python_helpers : test1 test2 ;

View File

@ -1,18 +0,0 @@
# Copyright 2006 Vladimir Prus
# 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)
# Declare a couple of functions called from Boost.Build
#
# Each function will receive as many arguments as there ":"-separated
# arguments in bjam call. Each argument is a list of strings.
# As a special exception (aka bug), if no arguments are passed in bjam,
# Python function will be passed a single empty list.
#
# All Python functions must return a list of strings, which may be empty.
def test1(l):
return ["foo", "bar"]
def test2(l, l2):
return [l[0], l2[0]]

View File

@ -1,15 +0,0 @@
Copyright 2006 Vladimir Prus
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)
This example shows how you can use Python modules from Boost.Build.
In order to do this, you need to build bjam with Python support, by running:
./build.sh --with-python=/usr
in jam directory. (Replace /usr with the root of your Python installation.)
The integration between Python and bjam is very basic now, but enough to
be useful.

View File

@ -1,21 +0,0 @@
Copyright 2005 Vladimir Prus
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)
This directory contains Boost.Build examples for the Qt library
(http://www.trolltech.com/products/qt/index.html).
The current examples are:
1. Basic setup -- application with several sources and moccable header.
2. Using of .ui source file.
3. Running .cpp files via the moc tool.
For convenience, there are examples both for 3.* and 4.* version of Qt,
they are mostly identical and differ only in source code.
All examples assumes that you just installed Boost.Build and that QTDIR
environment variables is set (typical values can be /usr/share/qt3 and
/usr/share/qt4). After adding "using qt ..." to your user-config.jam, you'd
have to removing "using qt ; " statements from Jamroot file of examples.

View File

@ -1,13 +0,0 @@
# 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)
using qt ;
project
# built MT version, unless asked otherwise.
: default-build <threading>multi
;
exe canvas : main.cpp canvas.cpp canvas.h : <library>/qt//qt ;

View File

@ -1,73 +0,0 @@
// 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();
}

View File

@ -1,35 +0,0 @@
// 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

View File

@ -1,36 +0,0 @@
// 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();
}

View File

@ -1,11 +0,0 @@
using qt ;
import cast ;
project
: default-build <threading>multi
;
exe main : main.cpp [ cast _ moccable-cpp : main.cpp ]
/qt//qt
;

View File

@ -1,41 +0,0 @@
// Copyright Vladimir Prus 2005.
// 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 <qwidget.h>
#include <qpushbutton.h>
#include <qapplication.h>
#include <iostream>
class My_widget : public QWidget
{
Q_OBJECT
public:
My_widget() : QWidget()
{
QPushButton* b = new QPushButton("Push me", this);
connect(b, SIGNAL(clicked()), this, SLOT(theSlot()));
}
private slots:
void theSlot()
{
std::cout << "Clicked\n";
}
};
int main(int ac, char* av[])
{
QApplication app(ac, av);
My_widget mw;
mw.show();
app.setMainWidget(&mw);
app.exec();
}
#include "main.moc"

View File

@ -1,15 +0,0 @@
# 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)
# Tell that QT should be used. QTDIR will give installation
# prefix.
using qt ;
project
: default-build <threading>multi
;
exe hello : main.cpp hello_world_widget.ui : <library>/qt//qt ;

Some files were not shown because too many files have changed in this diff Show More