|
Boost-Build : |
From: Francesco Gabbanini (f.gabbanini_at_[hidden])
Date: 2006-01-02 08:08:52
Hi Reece,
thanks to your help, it seems I have finally found a way to compile the
boost signals library for WINCE, using BBV2.
I modified some bbv2 configuration files as described in the message you
posted on December 10 2005, "[Boost-build] [BBv2] [msvc] Various
additions to the toolset".
I also had to make some other modifications to get things working, and
therefore I am attaching all the jam files I modified, in case someone
finds them helpful.
There are some points that I would like to highlight:
- I found that dll's with long names (>31 characters) cause problems
when WINCE tries to load them, so I modified the file stage.jam in order
not to include the toolset version in the dll name; this shortens the
names, but it is of course a "patch", I don't know how the problem could
be handled in a more elegant and systematic way...
- I had some problems creating static libraries, because I couldn't
obtain them with the appropriate "lib" prefix (instead of
libboost_signals-vc80-gd-1_34.lib I get boost_signals-vc80-gd-1_34.lib):
to correct this, I modified the add-prefix-and-suffix rule in the file
virtual-target.jam (you can see the change in the source file I am
attaching). Again, I am not an expert in boost-build configuration
files, so I don't know if this is the best way to correct the problem of
static library names generation.
- I modified Microsoft Visual Studio 8\VC\vcvarsall.bat in order to call
Microsoft Visual Studio 8\VC\bin\my_vcvars_arm.bat, which I wrote to
appropriately set VC environment variables.
That's all, I think (I hope I am not forgetting anything!).
Francesco.
@SET VSINSTALLDIR=C:\Programmi\Microsoft Visual Studio 8
@SET VCINSTALLDIR=C:\Programmi\Microsoft Visual Studio 8\VC
@SET FrameworkDir=C:\WINNT\Microsoft.NET\Framework
@SET FrameworkVersion=v2.0.50727
@SET FrameworkSDKDir=C:\Programmi\Microsoft Visual Studio 8\SDK\v2.0
@if "%VSINSTALLDIR%"=="" goto error_no_VSINSTALLDIR
@if "%VCINSTALLDIR%"=="" goto error_no_VCINSTALLDIR
@echo Setting environment for using Microsoft Visual Studio 2005 PocketPC 2003 ARM tools.
@rem
@rem Root of Visual Studio IDE installed files.
@rem
@set DevEnvDir=C:\Programmi\Microsoft Visual Studio 8\Common7\IDE
@set PATH=%VCINSTALLDIR%\ce\bin\x86_arm;%VCINSTALLDIR%\bin;%VCINSTALLDIR%\PlatformSDK\bin;%VSINSTALLDIR%\Common7\Tools;%VSINSTALLDIR%\Common7\IDE;%VSINSTALLDIR%\Common\Tools;%VSINSTALLDIR%\Common\IDE;%VSINSTALLDIR%;%FrameworkSDKDir%\Bin;%PATH%
@set INCLUDE=%VCINSTALLDIR%\ce\include;%VSINSTALLDIR%\SmartDevices\SDK\PocketPC2003\include;%VCINSTALLDIR%\ce\atlmfc\include;%VSINSTALLDIR%\SmartDevices\SDK\SQL Server\Mobile\v3.0;%INCLUDE%
@set LIB=%VSINSTALLDIR%\SmartDevices\SDK\PocketPC2003\lib\ARMV4;%VCINSTALLDIR%\ce\atlmfc\lib\ARMV4;%VCINSTALLDIR%\ce\lib\ARMV4;%LIB%
@set LIBPATH=%VCINSTALLDIR%\ce\atlmfc\src\atl\;%VCINSTALLDIR%\ce\atlmfc\src\mfc\;%VCINSTALLDIR%\ce\crt\src\;%LIBPATH%
@goto end
@rem set PATH=C:\Programmi\Microsoft Visual Studio 8\Common7\IDE;C:\Programmi\Microsoft Visual Studio 8\VC\BIN;C:\Programmi\Microsoft Visual Studio 8\Common7\Tools;C:\Programmi\Microsoft Visual Studio 8\Common7\Tools\bin;C:\Programmi\Microsoft Visual Studio 8\VC\PlatformSDK\bin;C:\Programmi\Microsoft Visual Studio 8\SDK\v2.0\bin;C:\WINNT\Microsoft.NET\Framework\v2.0.50727;C:\Programmi\Microsoft Visual Studio 8\VC\VCPackages;%PATH%
@rem set INCLUDE=C:\Programmi\Microsoft Visual Studio 8\VC\ATLMFC\INCLUDE;C:\Programmi\Microsoft Visual Studio 8\VC\INCLUDE;C:\Programmi\Microsoft Visual Studio 8\VC\PlatformSDK\include;C:\Programmi\Microsoft Visual Studio 8\SDK\v2.0\include;%INCLUDE%
@rem set LIB=C:\Programmi\Microsoft Visual Studio 8\VC\ATLMFC\LIB;C:\Programmi\Microsoft Visual Studio 8\VC\LIB;C:\Programmi\Microsoft Visual Studio 8\VC\PlatformSDK\lib;C:\Programmi\Microsoft Visual Studio 8\SDK\v2.0\lib;%LIB%
@rem set LIBPATH=C:\WINNT\Microsoft.NET\Framework\v2.0.50727;C:\Programmi\Microsoft Visual Studio 8\VC\ATLMFC\LIB
:error_no_VSINSTALLDIR
@echo ERROR: VSINSTALLDIR variable is not set.
@goto end
:error_no_VCINSTALLDIR
@echo ERROR: VCINSTALLDIR variable is not set.
@goto end
:end
@echo off
if "%1" == "" goto x86
if not "%2" == "" goto usage
if /i %1 == x86 goto x86
if /i %1 == amd64 goto amd64
if /i %1 == x64 goto amd64
if /i %1 == ia64 goto ia64
if /i %1 == x86_amd64 goto x86_amd64
if /i %1 == x86_ia64 goto x86_ia64
if /i %1 == arm goto arm
goto usage
:x86
if not exist "%~dp0bin\vcvars32.bat" goto missing
call "%~dp0bin\vcvars32.bat"
goto :eof
:amd64
if not exist "%~dp0bin\amd64\vcvarsamd64.bat" goto missing
call "%~dp0bin\amd64\vcvarsamd64.bat"
goto :eof
:ia64
if not exist "%~dp0bin\ia64\vcvarsia64.bat" goto missing
call "%~dp0bin\ia64\vcvarsia64.bat"
goto :eof
:x86_amd64
if not exist "%~dp0bin\x86_amd64\vcvarsx86_amd64.bat" goto missing
call "%~dp0bin\x86_amd64\vcvarsx86_amd64.bat"
goto :eof
:x86_ia64
if not exist "%~dp0bin\x86_ia64\vcvarsx86_ia64.bat" goto missing
call "%~dp0bin\x86_ia64\vcvarsx86_ia64.bat"
goto :eof
:arm
if not exist "%~dp0bin\my_vcvars_arm.bat" goto missing
call "%~dp0bin\my_vcvars_arm.bat"
goto :eof
:usage
echo Error in script usage. The correct usage is:
echo %0 [option]
echo where [option] is: x86 ^| ia64 ^| amd64 ^| x86_amd64 ^| x86_ia64
echo:
echo For example:
echo %0 x86_ia64
goto :eof
:missing
echo The specified configuration type is missing. The tools for the
echo configuration might not be installed.
goto :eof
# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears in
# all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
# Implements virtual targets, which correspond to actual files created during
# build, but are not yet targets in Jam sense. They are needed, for example,
# when searching for possible transormation sequences, when it's not known
# if particular target should be created at all.
import "class" : new ;
import path property-set utility sequence errors set type os ;
# +--------------------------+
# | virtual-target |
# +==========================+
# | actualize |
# +--------------------------+
# | actualize-action() = 0 |
# | actualize-location() = 0 |
# +----------------+---------+
# |
# ^
# / \
# +-+-+
# |
# +---------------------+ +-------+--------------+
# | action | | abstract-file-target |
# +=====================| * +======================+
# | action-name | +--+ action |
# | properties | | +----------------------+
# +---------------------+--+ | actualize-action() |
# | actualize() |0..1 +-----------+----------+
# | path() | |
# | adjust-properties() | sources |
# | actualize-sources() | targets |
# +------+--------------+ ^
# | / \
# ^ +-+-+
# / \ |
# +-+-+ +-------------+-------------+
# | | |
# | +------+---------------+ +--------+-------------+
# | | file-target | | searched-lib-target |
# | +======================+ +======================+
# | | actualize-location() | | actualize-location() |
# | +----------------------+ +----------------------+
# |
# +-+------------------------------+
# | |
# +----+----------------+ +---------+-----------+
# | compile-action | | link-action |
# +=====================+ +=====================+
# | adjust-properties() | | adjust-properties() |
# +---------------------+ | actualize-sources() |
# +---------------------+
#
# The 'compile-action' and 'link-action' classes are defined not here,
# but in builtin.jam modules. They are shown in the diagram to give
# the big picture.
# Potential target. It can be converted into jam target and used in
# building, if needed. However, it can be also dropped, which allows
# to search for different transformation and select only one.
#
class virtual-target
{
import virtual-target utility scanner ;
rule __init__ ( name # Name of this target -- specifies the name of
: project # Project to which this target belongs
)
{
self.name = $(name) ;
self.project = $(project) ;
self.dependencies = ;
}
# Name of this target.
rule name ( ) { return $(self.name) ; }
# Project of this target.
rule project ( ) { return $(self.project) ; }
# Adds additional instances of 'virtual-target' that this
# one depends on.
rule depends ( d + )
{
self.dependencies = [ sequence.merge $(self.dependencies)
: [ sequence.insertion-sort $(d) ] ] ;
}
rule dependencies ( )
{
return $(self.dependencies) ;
}
# Generates all the actual targets and sets up build actions for
# this target.
#
# If 'scanner' is specified, creates an additional target
# with the same location as actual target, which will depend on the
# actual target and be associated with 'scanner'. That additional
# target is returned. See the docs (#dependency_scanning) for rationale.
# Target must correspond to a file if 'scanner' is specified.
#
# If scanner is not specified, then actual target is returned.
rule actualize ( scanner ? )
{
local actual-name = [ actualize-no-scanner ] ;
if ! $(scanner)
{
return $(actual-name) ;
}
else
{
# Add the scanner instance to the grist for name.
local g = [ sequence.join
[ utility.ungrist $(actual-name:G) ] $(scanner) : - ] ;
local name = $(actual-name:G=$(g)) ;
if ! $(self.made.$(name)) {
self.made.$(name) = true ;
DEPENDS $(name) : $(actual-name) ;
actualize-location $(name) ;
scanner.install $(scanner) : $(name) $(__name__) ;
}
return $(name) ;
}
}
# private: (overridables)
# Sets up build actions for 'target'. Should call appropriate rules
# and set target variables.
rule actualize-action ( target )
{
errors.error "method should be defined in derived classes" ;
}
# Sets up variables on 'target' which specify its location.
rule actualize-location ( target )
{
errors.error "method should be defined in derived classes" ;
}
# If the target is generated one, returns the path where it will be
# generated. Otherwise, returns empty list.
rule path ( )
{
errors.error "method should be defined in derived classes" ;
}
# Return that actual target name that should be used
# (for the case where no scanner is involved)
rule actual-name ( )
{
errors.error "method should be defined in derived classes" ;
}
# implementation
rule actualize-no-scanner ( )
{
# In fact, we just need to merge virtual-target with
# abstract-virtual-target and the latter is the only class
# derived from the former. But that's for later.
errors.error "method should be defined in derived classes" ;
}
}
# Target which correspond to a file. The exact mapping for file
# is not yet specified in this class. (TODO: Actually, the class name
# could be better...)
#
# May be a source file (when no action is specified), or
# derived file (otherwise).
#
# The target's grist is concatenation of project's location,
# properties of action (for derived files), and, optionally,
# value identifying the main target.
class abstract-file-target : virtual-target
{
import project regex sequence path type ;
import property-set ;
import indirect ;
rule __init__ (
name # Name for this target
exact ? # If non-empty, the name is exactly the name
# created file should have. Otherwise, the '__init__'
# method will add suffix obtained from 'type' by
# calling 'type.generated-target-suffix'.
: type ? # The type of this target.
: project
: action ?
)
{
virtual-target.__init__ $(name) : $(project) ;
self.type = $(type) ;
self.action = $(action) ;
if $(action)
{
$(action).add-targets $(__name__) ;
if $(self.type) && ! $(exact)
{
_adjust-name $(name) ;
}
}
}
rule type ( ) { return $(self.type) ; }
# Sets the path. When generating target name, it will override any path
# computation from properties.
rule set-path ( path )
{
self.path = [ path.native $(path) ] ;
}
# If 'a' is supplied, sets action to 'a'.
# Returns the action currently set.
rule action ( )
{
return $(self.action) ;
}
# Sets/gets the 'root' flag. Target is root is it directly correspods to some
# variant of a main target.
rule root ( set ? )
{
if $(set)
{
self.root = true ;
}
return $(self.root) ;
}
# Gets or sets the subvariant which created this target. Subvariant
# is set when target is brought into existance, and is never changed
# after that. In particual, if target is shared by subvariant, only
# the first is stored.
rule creating-subvariant ( s ? # If specified, specified the value to set,
# which should be instance of 'subvariant'
# class.
)
{
if $(s) && ( ! $(self.creating-subvariant) && ! $(overwrite) )
{
if $(self.creating-subvariant)
{
errors.error "Attempt to change 'dg'" ;
}
else
{
self.creating-subvariant = $(s) ;
}
}
return $(self.creating-subvariant) ;
}
rule actualize-action ( target )
{
if $(self.action)
{
$(self.action).actualize ;
}
}
# Return a human-readable representation of this target
#
# If this target has an action, that's:
#
# { <action-name>-<self.name>.<self.type> <action-sources>... }
#
# otherwise, it's:
#
# { <self.name>.<self.type> }
#
rule str ( )
{
local action = [ action ] ;
local name-dot-type = [ sequence.join $(self.name) "." $(self.type) ] ;
if $(action)
{
local sources = [ $(action).sources ] ;
local action-name = [ $(action).action-name ] ;
local ss ;
for local s in $(sources)
{
ss += [ $(s).str ] ;
}
return "{" $(action-name)-$(name-dot-type) $(ss) "}" ;
}
else
{
return "{" $(name-dot-type) "}" ;
}
}
rule less ( a )
{
if [ str ] < [ $(a).str ]
{
return true ;
}
}
rule equal ( a )
{
if [ str ] = [ $(a).str ]
{
return true ;
}
}
# private:
rule actual-name ( )
{
if ! $(self.actual-name)
{
local grist = [ grist ] ;
local basename = [ path.native $(self.name) ] ;
self.actual-name = <$(grist)>$(basename) ;
}
return $(self.actual-name) ;
}
# Helper to 'actual-name', above. Compute unique prefix used to distinguish
# this target from other targets with the same name which create different
# file.
rule grist ( )
{
# Depending on target, there may be different approaches to generating
# unique prefixes. We'll generate prefixes in the form
# <one letter approach code> <the actual prefix>
local path = [ path ] ;
if $(path)
{
# The target will be generated to a known path. Just use the path
# for identification, since path is as unique as it can get.
return p$(path) ;
}
else
{
# File is either source, which will be searched for, or is not a file at
# all. Use the location of project for distinguishing.
local project-location = [ $(self.project).get location ] ;
local location-grist =
[ sequence.join [ regex.split $(project-location) "/" ] : "!" ] ;
if $(self.action)
{
local ps = [ $(self.action).properties ] ;
local property-grist = [ $(ps).as-path ] ;
# 'property-grist' can be empty when 'ps' is an empty
# property set.
if $(property-grist)
{
location-grist = $(location-grist)/$(property-grist) ;
}
}
return l$(location-grist) ;
}
}
# Given the target name specified in constructor, returns the
# name which should be really used, by looking at the <tag> properties.
# The tag properties come in two flavour:
# - <tag>value,
# - <tag>@rule-name
# In the first case, value is just added to name
# In the second case, the specified rule is called with specified name,
# target type and properties and should return the new name.
# If not <tag> property is specified, or the rule specified by
# <tag> returns nothing, returns the result of calling
# virtual-target.add-suffix
rule _adjust-name ( specified-name )
{
local ps ;
if $(self.action)
{
ps = [ $(self.action).properties ] ;
}
else
{
ps = [ property-set.empty ] ;
}
local tag = [ $(ps).get <tag> ] ;
if $(tag)
{
local rule-name = [ MATCH ^@(.*) : $(tag) ] ;
if $(rule-name)
{
if $(tag[2])
{
errors.error "<tag>@rulename is present but is not the only <tag> feature" ;
}
self.name = [ indirect.call $(rule-name) $(specified-name) :
$(self.type) : $(ps) ] ;
}
else
{
errors.error
"The value of the <tag> feature must be '@rule-nane'" ;
}
}
# If there's no tag or the tag rule returned nothing.
if ! $(tag) || ! $(self.name)
{
self.name = [ virtual-target.add-prefix-and-suffix
$(specified-name) : $(self.type) : $(ps) ] ;
}
}
rule actualize-no-scanner ( )
{
local name = [ actual-name ] ;
# Do anything only on the first invocation
if ! $(self.made.$(name)) {
self.made.$(name) = true ;
if $(self.action)
{
# For non-derived target, we don't care if there
# are several virtual targets that refer to the same name.
# One case when this is unavoidable is when file name is
# main.cpp and two targets have types CPP (for compiling)
# and MOCCABLE_CPP (for convertion to H via Qt tools).
virtual-target.register-actual-name $(name) : $(__name__) ;
}
for local i in $(self.dependencies) {
DEPENDS $(name) : [ $(i).actualize ] ;
}
actualize-location $(name) ;
actualize-action $(name) ;
}
return $(name) ;
}
}
# Appends the suffix appropriate to 'type/property-set' combination
# to the specified name and returns the result.
rule add-prefix-and-suffix ( specified-name : type ? : property-set )
{
local suffix = [ type.generated-target-suffix $(type) : $(property-set) ] ;
suffix = .$(suffix) ;
local prefix ;
#FRA ADDON
if [ type.is-derived $(type) STATIC_LIB ] && ! [ type.is-derived $(type) IMPORT_LIB ] && ! [ MATCH ^(lib) : $(specified-name) ]
#if [ type.is-derived $(type) LIB ] && [ os.on-unix ]
# && ! [ MATCH ^(lib) : $(specified-name) ]
#END
{
prefix = "lib" ;
}
return $(prefix:E="")$(specified-name)$(suffix:E="") ;
}
# File target with explicitly known location.
#
# The file path is determined as
# - value passed to the 'set-path' method, if any
# - for derived files, project's build dir, joined with components
# that describe action's properties. If the free properties
# are not equal to the project's reference properties
# an element with name of main target is added.
# - for source files, project's source dir
#
# The file suffix is
# - the value passed to the 'suffix' method, if any, or
# - the suffix which correspond to the target's type.
#
class file-target : abstract-file-target
{
import common ;
import errors ;
import "class" : new ;
rule __init__ (
name exact ?
: type ? # Optional type for this target
: project
: action ?
: path ?
)
{
abstract-file-target.__init__ $(name) $(exact) : $(type) : $(project)
: $(action) ;
self.path = $(path) ;
}
rule clone-with-different-type ( new-type )
{
return [ new file-target $(self.name) exact : $(new-type)
: $(self.project) : $(self.action) : $(self.path) ] ;
}
rule actualize-location ( target )
{
if $(self.action)
{
# This is a derived file.
local path = [ path ] ;
LOCATE on $(target) = $(path) ;
# Make sure the path exists.
DEPENDS $(target) : $(path) ;
common.MkDir $(path) ;
# It's possible that the target name includes a directory
# too, for example when installing headers. Create that
# directory.
if $(target:D)
{
local d = $(target:D) ;
d = $(d:R=$(path)) ;
DEPENDS $(target) : $(d) ;
common.MkDir $(d) ;
}
# For real file target, we create gristless target that
# depends on the real target. This allows to run
#
# bjam hello.o
#
# without trying to guess the name of the real target.
DEPENDS $(target:G=) : $(target) ;
}
else
{
SEARCH on $(target) = [ path.native $(self.path) ] ;
}
}
# Returns the directory for this target
rule path ( )
{
if ! $(self.path)
{
if $(self.action)
{
local p = [ $(self.action).properties ] ;
local path = [ $(p).target-path ] ;
if $(path[2]) = true
{
# Indicates that the path is relative to
# build dir.
path = [ path.join [ $(self.project).build-dir ]
$(path[1]) ] ;
}
# Store the computed path, so that it's not recomputed
# any more
self.path = [ path.native $(path) ] ;
}
}
return $(self.path) ;
}
}
class notfile-target : abstract-file-target
{
rule __init__ ( name : project : action ? )
{
abstract-file-target.__init__ $(name) : : $(project) : $(action) ;
}
# Returns nothing, to indicate that target path is not known.
rule path ( )
{
return ;
}
rule actualize-location ( target )
{
NOTFILE $(target) ;
ALWAYS $(target) ;
}
}
# Class which represents an action.
# Both 'targets' and 'sources' should list instances of 'virtual-target'.
# Action name should name a rule with this prototype
# rule action-name ( targets + : sources * : properties * )
# Targets and sources are passed as actual jam targets. The rule may
# not establish dependency relationship, but should do everything else.
class action
{
import type toolset property-set indirect class path assert ;
rule __init__ ( sources * : action-name + : property-set ? )
{
self.sources = $(sources) ;
self.action-name = [ indirect.make-qualified $(action-name) ] ;
if ! $(property-set)
{
property-set = [ property-set.empty ] ;
}
if ! [ class.is-instance $(property-set) ]
{
errors.error "Property set instance required" ;
}
self.properties = $(property-set) ;
}
rule add-targets ( targets * )
{
self.targets += $(targets) ;
}
rule targets ( )
{
return $(self.targets) ;
}
rule sources ( )
{
return $(self.sources) ;
}
rule action-name ( )
{
return $(self.action-name) ;
}
rule properties ( )
{
return $(self.properties) ;
}
# Generates actual build instructions.
rule actualize ( )
{
if ! $(self.actualized)
{
self.actualized = true ;
local ps = [ properties ] ;
local properties = [ adjust-properties $(ps) ] ;
local actual-targets ;
for local i in [ targets ]
{
actual-targets += [ $(i).actualize ] ;
}
actualize-sources [ sources ] : $(properties) ;
DEPENDS $(actual-targets) : $(self.actual-sources) $(self.dependency-only-sources) ;
# Action name can include additional argument to rule, which should not
# be passed to 'set-target-variables'
toolset.set-target-variables
[ indirect.get-rule $(self.action-name[1]) ] $(actual-targets)
: $(properties) ;
indirect.call $(self.action-name)
$(actual-targets) : $(self.actual-sources) : [ $(properties).raw ]
;
# Since we set up creating action here, we also set up
# action for cleaning up
common.Clean clean : $(actual-targets) ;
}
}
# Helper for 'actualize-sources'.
# For each passed source, actualizes it with the appropriate scanner.
# Returns the actualized virtual targets.
rule actualize-source-type ( sources * : property-set )
{
local result = ;
for local i in $(sources)
{
local scanner ;
if [ $(i).type ]
{
scanner =
[ type.get-scanner [ $(i).type ] : $(property-set) ] ;
}
result += [ $(i).actualize $(scanner) ] ;
}
return $(result) ;
}
# Creates actual jam targets for sources. Initialized two member
# variables:.
# 'self.actual-sources' -- sources which are passed to updating action
# 'self.dependency-only-sources' -- sources which are made dependencies, but
# are not used otherwise.
#
# New values will be *appended* to the variables. They may be non-empty,
# if caller wants it.
rule actualize-sources ( sources * : property-set )
{
local dependencies = [ $(self.properties).get <dependency> ] ;
self.dependency-only-sources += [
actualize-source-type $(dependencies) : $(property-set) ] ;
self.actual-sources += [
actualize-source-type $(sources) : $(property-set) ] ;
}
# Determined real properties when trying building with 'properties'.
# This is last chance to fix properties, for example to adjust includes
# to get generated headers correctly. Default implementation returns
# its argument.
rule adjust-properties ( property-set )
{
return $(property-set) ;
}
}
# Action class which does nothing --- it produces the targets with
# specific properties out of nowhere. It's needed to distinguish virtual
# targets with different properties that are known to exist, and have no
# actions which create them.
class null-action : action
{
rule __init__ ( property-set ? )
{
action.__init__ : .no-action : $(property-set) ;
}
rule actualize ( )
{
if ! $(self.actualized)
{
self.actualized = true ;
for local i in [ targets ]
{
$(i).actualize ;
}
}
}
}
# Class which acts exactly like 'action', except that the sources
# are not scanned for dependencies.
class non-scanning-action : action
{
rule __init__ ( sources * : action-name + : property-set ? )
{
action.__init__ $(sources) : $(action-name) : $(property-set) ;
}
rule actualize-source-type ( sources * : property-set )
{
local result ;
for local i in $(sources)
{
result += [ $(i).actualize ] ;
}
return $(result) ;
}
}
# Creates a virtual target with approariate name and type from 'file'.
# If a target with that name in that project was already created, returns that already
# created target.
# FIXME: more correct way would be to compute path to the file, based on name and source location
# for the project, and use that path to determine if the target was already created.
# TODO: passing project with all virtual targets starts to be annoying.
rule from-file ( file : file-loc : project )
{
import type ; # had to do this here to break a circular dependency
# Check if we've created a target corresponding to this file.
local path = [ path.root [ path.root $(file) $(file-loc) ]
[ path.pwd ] ] ;
if $(.files.$(path))
{
return $(.files.$(path)) ;
}
else
{
local name = [ path.make $(file) ] ;
local type = [ type.type $(file) ] ;
local result ;
result = [ new file-target $(file)
: $(type)
: $(project)
: #action
: $(file-loc) ] ;
.files.$(path) = $(result) ;
return $(result) ;
}
}
# Registers a new virtual target. Checks if there's already registered target, with the same
# name, type, project and subvariant properties, and also with the same sources
# and equal action. If such target is found it is retured and 'target' is not registers.
# Otherwise, 'target' is registered and returned.
rule register ( target )
{
local signature = [ sequence.join
[ $(target).path ] [ $(target).name ] : - ] ;
local result ;
for local t in $(.cache.$(signature))
{
local a1 = [ $(t).action ] ;
local a2 = [ $(target).action ] ;
if ! $(result)
{
if ! $(a1) && ! $(a2)
{
result = $(t) ;
}
else
{
if $(a1) && $(a2) && [ $(a1).action-name ] = [ $(a2).action-name ] &&
[ $(a1).sources ] = [ $(a2).sources ]
{
local ps1 = [ $(a1).properties ] ;
local ps2 = [ $(a2).properties ] ;
local p1 = [ $(ps1).base ] [ $(ps1).free ] [ $(ps1).dependency ] ;
local p2 = [ $(ps2).base ] [ $(ps2).free ] [ $(ps2).dependency ] ;
if $(p1) = $(p2)
{
result = $(t) ;
}
}
}
}
}
if ! $(result)
{
.cache.$(signature) += $(target) ;
result = $(target) ;
}
.recent-targets += $(result) ;
return $(result) ;
}
# Each target returned by 'register' is added to a list of
# 'recent-target', returned by this function. So, this allows
# us to find all targets created when building a given main
# target, even if the target
rule recent-targets ( )
{
return $(.recent-targets) ;
}
rule clear-recent-targets ( )
{
.recent-targets = ;
}
rule register-actual-name ( actual-name : virtual-target )
{
if $(.actual.$(actual-name))
{
local cs1 = [ $(.actual.$(actual-name)).creating-subvariant ] ;
local cs2 = [ $(virtual-target).creating-subvariant ] ;
local cmt1 = [ $(cs1).main-target ] ;
local cmt2 = [ $(cs2).main-target ] ;
local action1 = [ $(.actual.$(actual-name)).action ] ;
local action2 = [ $(virtual-target).action ] ;
local properties-added ;
local properties-removed ;
if $(action1) && $(action2)
{
local p1 = [ $(action1).properties ] ;
p1 = [ $(p1).raw ] ;
local p2 = [ $(action2).properties ] ;
p2 = [ $(p2).raw ] ;
properties-removed = [ set.difference $(p1) : $(p2) ] ;
properties-removed ?= "none" ;
properties-added = [ set.difference $(p2) : $(p1) ] ;
properties-added ?= "none" ;
}
errors.error "Duplicate name of actual target:" $(actual-name)
: "previous virtual target" [ $(.actual.$(actual-name)).str ]
: "created from" [ $(cmt1).full-name ]
: "another virtual target" [ $(virtual-target).str ]
: "created from" [ $(cmt2).full-name ]
: "added properties: " $(properties-added)
: "removed properties: " $(properties-removed) ;
}
else
{
.actual.$(actual-name) = $(virtual-target) ;
}
}
# Traverses the dependency graph of 'target' and return all targets that will
# be created before this one is created. If root of some dependency graph is
# found during traversal, it's either included or not, dependencing of the
# value of 'include-roots'. In either case, sources of root are not traversed.
rule traverse ( target : include-roots ? : include-sources ? )
{
local result ;
if [ $(target).action ]
{
local action = [ $(target).action ] ;
# This includes 'target' as well
result += [ $(action).targets ] ;
for local t in [ $(action).sources ]
{
if ! [ $(t).root ]
{
result += [ traverse $(t) : $(include-roots) : $(include-sources) ] ;
}
else if $(include-roots)
{
result += $(t) ;
}
}
}
else if $(include-sources)
{
result = $(target) ;
}
return $(result) ;
}
# Takes an 'action' instances and creates new instance of it
# and all produced target. The rule-name and properties are set
# to 'new-rule-name' and 'new-properties', if those are specified.
# Returns the cloned action.
rule clone-action ( action : new-project : new-action-name ? : new-properties ? )
{
if ! $(new-action-name)
{
new-action-name = [ $(action).action-name ] ;
}
if ! $(new-properties)
{
new-properties = [ $(action).properties ] ;
}
local action-class = [ modules.peek $(action) : __class__ ] ;
local cloned-action = [ class.new $(action-class)
[ $(action).sources ] : $(new-action-name) : $(new-properties) ] ;
local cloned-targets ;
for local target in [ $(action).targets ]
{
local n = [ $(target).name ] ;
# Don't modify the name of the produced targets.Strip the directory f
local cloned-target = [ class.new file-target $(n) exact : [ $(target).type ]
: $(new-project) : $(cloned-action) ] ;
local d = [ $(target).dependencies ] ;
if $(d)
{
$(cloned-target).depends $(d) ;
}
$(cloned-target).root [ $(target).root ] ;
$(cloned-target).creating-subvariant [ $(target).creating-subvariant ] ;
cloned-targets += $(cloned-target) ;
}
return $(cloned-action) ;
}
class subvariant
{
import sequence ;
import type ;
rule __init__ ( main-target # The instance of main-target class
: property-set # Properties requested for this target
: sources *
: build-properties # Actually used properties
: sources-usage-requirements # Properties propagated from sources
: created-targets * ) # Top-level created targets
{
self.main-target = $(main-target) ;
self.properties = $(property-set) ;
self.sources = $(sources) ;
self.build-properties = $(build-properties) ;
self.sources-usage-requirements = $(sources-usage-requirements) ;
self.created-targets = $(created-targets) ;
# Pre-compose the list of other dependency graphs, on which this one
# depends
local deps = [ $(build-properties).get <implicit-dependency> ] ;
for local d in $(deps)
{
self.other-dg += [ $(d:G=).creating-subvariant ] ;
}
self.other-dg = [ sequence.unique $(self.other-dg) ] ;
}
rule main-target ( )
{
return $(self.main-target) ;
}
rule created-targets ( )
{
return $(self.created-targets) ;
}
rule requested-properties ( )
{
return $(self.properties) ;
}
rule build-properties ( )
{
return $(self.build-properties) ;
}
rule sources-usage-requirements ( )
{
return $(self.sources-usage-requirements) ;
}
rule set-usage-requirements ( usage-requirements )
{
self.usage-requirements = $(usage-requirements) ;
}
rule usage-requirements ( )
{
return $(self.usage-requirements) ;
}
# Returns all targets referenced by this subvariant,
# either directly or indirectly, and
# either as sources, or as dependency properties.
# Targets referred with dependency property are returned a properties,
# not targets.
rule all-referenced-targets ( )
{
# Find directly referenced targets.
local deps = [ $(self.build-properties).dependency ] ;
local all-targets = $(self.sources) $(deps) ;
# Find other subvariants.
local r ;
for local t in $(all-targets)
{
r += [ $(t:G=).creating-subvariant ] ;
}
r = [ sequence.unique $(r) ] ;
for local s in $(r)
{
if $(s) != $(__name__)
{
all-targets += [ $(s).all-referenced-targets ] ;
}
}
return $(all-targets) ;
}
# Returns the properties which specify implicit include paths to
# generated headers. This traverses all targets in this subvariant,
# and subvariants referred by <implcit-dependecy>properties.
# For all targets which are of type 'target-type' (or for all targets,
# if 'target-type' is not specified), the result will contain
# <$(feature)>path-to-that-target.
rule implicit-includes ( feature : target-type ? )
{
local key = ii$(feature)-$(target-type:E="") ;
if ! $($(key))-is-nonempty
{
local target-paths = [ all-target-directories $(target-type) ] ;
target-paths = [ sequence.unique $(target-paths) ] ;
local result = $(target-paths:G=$(feature)) ;
if ! $(result)
{
result = "" ;
}
$(key) = $(result) ;
}
if $($(key)) = ""
{
return ;
}
else
{
return $($(key)) ;
}
}
rule all-target-directories ( target-type ? )
{
if ! $(self.target-directories)
{
compute-target-directories $(target-type) ;
}
return $(self.target-directories) ;
}
rule compute-target-directories ( target-type ? )
{
local result ;
for local t in $(self.created-targets)
{
if $(target-type) && ! [ type.is-derived [ $(t).type ] $(target-type) ]
{
# Skip target which is of wrong type.
}
else
{
result = [ sequence.merge $(result) : [ $(t).path ] ] ;
}
}
for local d in $(self.other-dg)
{
result += [ $(d).all-target-directories $(target-type) ] ;
}
self.target-directories = $(result) ;
}
}
# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears in
# all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
# This module defines the 'install' rule, used to copy a set of targets to
# a single location
import targets ;
import "class" : new ;
import property ;
import errors : error ;
import type : type ;
import type ;
import regex ;
import generators ;
import feature ;
import project ;
import property-set ;
import virtual-target ;
import path ;
feature.feature <install-dependencies> : off on : incidental ;
feature.feature <install-type> : : free incidental ;
feature.feature <install-source-root> : : free path ;
feature.feature <so-version> : : free incidental ;
class install-target-class : basic-target
{
import feature project type errors generators path stage ;
import "class" : new ;
rule __init__ ( name-and-dir : project : sources * : requirements * : default-build * )
{
basic-target.__init__ $(name-and-dir) : $(project) : $(sources) : $(requirements)
: $(default-build) ;
}
# If <location> is not set, sets it based on the project data.
rule update-location ( property-set )
{
local loc = [ $(property-set).get <location> ] ;
if ! $(loc)
{
loc = [ path.root $(self.name) [ $(self.project).get location ] ] ;
property-set = [ $(property-set).add-raw $(loc:G=<location>) ] ;
}
return $(property-set) ;
}
# Takes a target that is installed and property set which is
# used when installing.
rule adjust-properties ( target : build-property-set )
{
local ps-raw ;
local a = [ $(target).action ] ;
if $(a)
{
local ps = [ $(a).properties ] ;
ps-raw = [ $(ps).raw ] ;
# Unless <hardcode-dll-paths>true is in properties, which can
# happen only if the user has explicitly requested it, nuke all
# <dll-path> properties
if [ $(property-set).get <hardcode-dll-paths> ] != true
{
ps-raw = [ property.change $(ps-raw) : <dll-path> ] ;
}
# If any <dll-path> properties were specified for installing,
# add them.
local l = [ $(build-property-set).get <dll-path> ] ;
ps-raw += $(l:G=<dll-path>) ;
}
# Remove the <tag> feature on original targets.
ps-raw = [ property.change $(ps-raw) : <tag> ] ;
# And <location>. If stage target has another stage target
# in sources, then we'll get virtual targets with <location>
# property set.
ps-raw = [ property.change $(ps-raw) : <location> ] ;
local d = [ $(build-property-set).get <dependency> ] ;
ps-raw += $(d:G=<dependency>) ;
local d = [ $(build-property-set).get <location> ] ;
ps-raw += $(d:G=<location>) ;
local d = [ $(build-property-set).get <install-source-root> ] ;
# Make the path absolute: we'll use it to compute relative
# paths and making the path absolute will help.
if $(d)
{
d = [ path.root $(d) [ path.pwd ] ] ;
ps-raw += $(d:G=<install-source-root>) ;
}
if $(ps-raw)
{
return [ property-set.create $(ps-raw) ] ;
}
else
{
return [ property-set.empty ] ;
}
}
rule construct ( name : source-targets * : property-set )
{
source-targets = [
targets-to-stage $(source-targets) : $(property-set) ] ;
property-set = [ update-location $(property-set) ] ;
local result ;
for local i in $(source-targets)
{
local staged-targets ;
local new-properties =
[ adjust-properties $(i) : $(property-set) ] ;
# See if something special should be done when staging this
# type. It is indicated by presense of special "staged" type
local t = [ $(i).type ] ;
if $(t) && [ type.registered INSTALLED_$(t) ]
{
local targets = [ generators.construct $(self.project) $(name) :
INSTALLED_$(t) : $(new-properties) : $(i) : * ] ;
staged-targets += $(targets[2-]) ;
}
else
{
staged-targets = [ stage.copy-file $(self.project)
: $(i) : $(new-properties) ] ;
}
if ! $(staged-targets)
{
errors.error "Unable to generate staged version of " [ $(source).str ] ;
}
for t in $(staged-targets)
{
result += [ virtual-target.register $(t) ] ;
}
}
return [ property-set.empty ] $(result) ;
}
# Given the list of source targets explicitly passed to 'stage',
# returns the list of targets which must be staged.
rule targets-to-stage ( source-targets * : property-set )
{
local result ;
# Traverse the dependencies, if needed.
if [ $(property-set).get <install-dependencies> ] = "on"
{
source-targets = [ collect-targets $(source-targets) ] ;
}
# Filter the target types, if needed
local included-types = [ $(property-set).get <install-type> ] ;
for local r in $(source-targets)
{
local ty = [ $(r).type ] ;
if $(ty)
{
# Don't stage searched libs.
if $(ty) != SEARCHED_LIB
{
if $(included-types)
{
if [ include-type $(ty) : $(included-types) ]
{
result += $(r) ;
}
}
else
{
result += $(r) ;
}
}
}
else
{
result += $(r) ;
}
}
return $(result) ;
}
# CONSIDER: figure out why we can't use virtual-target.traverse here.
rule collect-targets ( targets * )
{
# Find subvariants
local s ;
for local t in $(targets)
{
s += [ $(t).creating-subvariant ] ;
}
s = [ sequence.unique $(s) ] ;
local result = $(targets) ;
for local i in $(s)
{
result += [ $(i).all-referenced-targets ] ;
}
local result2 ;
for local r in $(result)
{
if $(r:G) != <use>
{
result2 += $(r:G=) ;
}
}
result = [ sequence.unique $(result2) ] ;
}
# Returns true iff 'type' is subtype of some element of 'types-to-include'.
local rule include-type ( type : types-to-include * )
{
local found ;
while $(types-to-include) && ! $(found)
{
if [ type.is-subtype $(type) $(types-to-include[1]) ]
{
found = true ;
}
types-to-include = $(types-to-include[2-]) ;
}
return $(found) ;
}
}
# Creates a copy of target 'source'. The 'properties' object should
# have a <location> property which specifies where the target must
# be placed.
rule copy-file ( project : source : properties )
{
local targets ;
local name = [ $(source).name ] ;
new-a = [
new non-scanning-action $(source) : common.copy : $(properties) ] ;
local source-root = [ $(properties).get <install-source-root> ] ;
if $(source-root)
{
# Get the real path of the target. We probably need to strip
# relative path from the target name at construction...
local path = [ $(source).path ] ;
path = [ path.root $(name:D) $(path) ] ;
# Make the path absolute. Otherwise, it's hard to compute relative
# path. The 'source-root' is already absolute, see the
# 'adjust-properties' method above.
path = [ path.root $(path) [ path.pwd ] ] ;
relative = [ path.relative-to $(source-root) $(path) ] ;
targets = [ new file-target $(name:D=$(relative)) exact : [ $(source).type ]
: $(project) : $(new-a) ] ;
}
else
{
targets = [ new file-target $(name:D=) exact : [ $(source).type ]
: $(project) : $(new-a) ] ;
}
return $(targets) ;
}
rule symlink ( name : project : source : properties )
{
local a = [ new action $(source) : symlink.ln :
$(properties) ] ;
local targets = [
new file-target $(name) exact : [ $(source).type ] : $(project) : $(a) ] ;
return $(targets) ;
}
rule relink-file ( project : source : property-set )
{
local action = [ $(source).action ] ;
local cloned-action = [ virtual-target.clone-action $(action) : $(project) :
"" : $(property-set) ] ;
local result = [ $(cloned-action).targets ] ;
return $(result) ;
}
# Declare installed version of the EXE type. Generator for this type will
# cause relinking to the new location.
type.register INSTALLED_EXE : : EXE ;
class installed-exe-generator : generator
{
import type property-set modules stage ;
rule __init__ ( )
{
generator.__init__ install-exe : EXE : INSTALLED_EXE ;
}
rule run ( project name ? : property-set : source : multiple ? )
{
if [ $(property-set).get <os> ] in NT CYGWIN
{
# Relinking is never needed on NT
return [ stage.copy-file $(project)
: $(source) : $(property-set) ] ;
}
else
{
return [ stage.relink-file $(project)
: $(source) : $(property-set) ] ;
}
}
}
generators.register [ new installed-exe-generator ] ;
# Installing shared link on Unix might cause a creation of
# versioned symbolic links.
type.register INSTALLED_SHARED_LIB : : SHARED_LIB ;
class installed-shared-lib-generator : generator
{
import type property-set modules stage ;
rule __init__ ( )
{
generator.__init__ install-shared-lib : SHARED_LIB
: INSTALLED_SHARED_LIB ;
}
rule run ( project name ? : property-set : source : multiple ? )
{
if [ $(property-set).get <os> ] = NT
{
local copied = [ stage.copy-file $(project)
: $(source) : $(property-set) ] ;
copied = [ virtual-target.register $(copied) ] ;
return $(copied) ;
}
else
{
local a = [ $(source).action ] ;
local copied ;
if ! $(a)
{
# Non-derived file, just copy.
copied = [ stage.copy-file $(project)
: $(source) : $(property-set) ] ;
}
else
{
local cp = [ $(a).properties ] ;
local current-dll-path = [ $(cp).get <dll-path> ] ;
local new-dll-path = [ $(property-set).get <dll-path> ] ;
if $(current-dll-path) != $(new-dll-path)
{
# Rpath changed, need to relink.
copied = [ stage.relink-file
$(project) : $(source) : $(property-set) ] ;
}
else
{
copied = [ stage.copy-file $(project)
: $(source) : $(property-set) ] ;
}
}
copied = [ virtual-target.register $(copied) ] ;
local result = $(copied) ;
# If the name is in the form NNN.XXX.YYY.ZZZ, where all
# 'X', 'Y' and 'Z' are numbers, we need to create
# NNN.XXX and NNN.XXX.YYY symbolic links.
local m = [ MATCH (.*)\\.([0123456789]+)\\.([0123456789]+)\\.([0123456789]+)$
: [ $(copied).name ] ] ;
if $(m)
{
result += [ stage.symlink $(m[1]).$(m[2]) : $(project)
: $(copied) : $(property-set) ] ;
result += [ stage.symlink $(m[1]).$(m[2]).$(m[3]) : $(project)
: $(copied) : $(property-set) ] ;
}
return $(result) ;
}
}
}
generators.register [ new installed-shared-lib-generator ] ;
# Main target rule for 'install'
rule install ( name : sources * : requirements * : default-build * )
{
local project = [ project.current ] ;
# Unless the user has explicitly asked us to hardcode dll paths, add
# <hardcode-dll-paths>false in requirements, to override default
# value.
if ! <hardcode-dll-paths>true in $(requirements)
{
requirements += <hardcode-dll-paths>false ;
}
if <name> in $(requirements:G)
{
errors.user-error
"The <name> property is not allowed for the 'install' rule" ;
}
if <tag> in $(requirements:G)
{
errors.user-error
"The <tag> property is not allowed for the 'install' rule" ;
}
targets.main-target-alternative
[ new install-target-class $(name) : $(project)
: [ targets.main-target-sources $(sources) : $(name) ]
: [ targets.main-target-requirements $(requirements) : $(project) ]
: [ targets.main-target-default-build $(default-build) : $(project) ]
] ;
}
IMPORT $(__name__) : install : : install ;
IMPORT $(__name__) : install : : stage ;
rule add-variant-and-compiler ( name : type ? : property-set )
{
return [ rename $(name) : $(type) : $(property-set) ] ;
}
rule add-variant ( name : type ? : property-set )
{
return [ rename $(name) : $(type) : $(property-set) : unversioned ] ;
}
rule rename ( name : type ? : property-set : unversioned ? )
{
if [ type.is-derived $(type) LIB ]
{
local properties = [ $(property-set).raw ] ;
local tags = ;
local thread-tag ;
if <threading>multi in $(properties) { thread-tag = mt ; }
local runtime-tag = ;
if <runtime-link>static in $(properties) { runtime-tag += s ; }
#FRA ADDON (SUGGESTED BY Volodya)
#if <runtime-build>debug in $(properties) { runtime-tag += g ; }
if <runtime-debugging>on in $(properties) { runtime-tag += g ; }
#END
if <variant>debug-python in $(properties) { runtime-tag += y ; }
if <variant>debug in $(properties) { runtime-tag += d ; }
if <stdlib>stlport in $(properties) { runtime-tag += p ; }
if <stdlib-stlport:iostream>hostios in $(properties) { runtime-tag += n ; }
local toolset-tag = ;
# 'unversioned' should be a parameter.
if ! $(unversioned)
{
switch [ $(property-set).get <toolset> ]
{
case borland* : toolset-tag += bcb ;
case como* : toolset-tag += como ;
case cw : toolset-tag += cw ;
case darwin* : toolset-tag += ;
case edg* : toolset-tag += edg ;
case gcc* : toolset-tag += gcc ;
case intel-linux* : toolset-tag += il ;
case intel-win* : toolset-tag += iw ;
case kcc* : toolset-tag += kcc ;
case kylix* : toolset-tag += bck ;
#case metrowerks* : toolset-tag += cw ;
#case mingw* : toolset-tag += mgw ;
case mipspro* : toolset-tag += mp ;
case msvc* : toolset-tag += vc ;
case sun* : toolset-tag += sw ;
case tru64cxx* : toolset-tag += tru ;
case vacpp* : toolset-tag += xlc ;
}
local version = [ MATCH "<toolset.*version>([0123456789]+)[.]([0123456789]*)" : $(properties) ] ;
#FRA ADDON
toolset-tag = "" ;
#toolset-tag += $(version) ;
#END
}
# Note yet clear if this should be added on Linux (where we have
# version in soname) and how it should be done on Windows.
#local version-tag = ;
#if ! $(gUNVERSIONED_VARIANT_TAG)
#{
# local version-number = [ get-values <version> : $(properties) ] ;
# version-number ?= $(BOOST_VERSION) ;
# version-tag = [ MATCH "^([^.]+)[.]([^.]+)" : $(version-number[1]) ] ;
# version-tag = $(version-tag:J="_") ;
#}
tags += $(toolset-tag:J=) ;
tags += $(thread-tag:J=) ;
tags += $(runtime-tag:J=) ;
#tags += $(version-tag) ;
local result ;
if $(tags)
{
#FRA ADDON
#result = $(name)-$(tags:J=-) ;
result = $(name)$(tags:J=-) ;
#END
}
else
{
result = $(name) ;
}
return [ virtual-target.add-prefix-and-suffix $(result) : $(type)
: $(property-set) ] ;
}
}
# Copyright (c) 2003 David Abrahams.
# Copyright (c) 2005 Vladimir Prus.
# Copyright (c) 2005 Alexey Pakhunov.
#
# Use, modification and distribution is subject to the Boost Software
# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
# http://www.boost.org/LICENSE_1_0.txt)
import property ;
import generators ;
import os ;
import type ;
import toolset : flags ;
import errors : error ;
import feature : feature get-values ;
import path ;
import sequence : unique ;
import common ;
import "class" : new ;
import rc ;
import midl ;
import mc ;
import pch ;
import msplatformsdk ;
if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
{
.debug-configuration = true ;
}
feature.extend toolset : msvc ;
feature.subfeature toolset msvc : vendor
: intel
: propagated optional
# intel and msvc supposedly have link-compatible objects... remains
# to be seen, though ;-)
;
feature clr : default managed cppcli : propagated ;
feature pure-clr : no yes : propagated ;
feature safe-clr : no yes : propagated ;
feature have-assembly : yes no : propagated ;
feature initial-app-domain : no yes : propagated ;
feature resource-only : no yes : incidental ;
feature debug-store : object database edit-and-continue lines-only : propagated ;
feature improve-fp-consistency : no yes : propagated ;
feature fiber-safe-optimization : no yes : propagated ;
feature optimize-for-windows : no yes : propagated ;
feature function-hooks : none enter exit both : propagated ;
feature string-pooling : no yes : propagated ;
feature minimal-rebuild : no yes : propagated ;
feature security-checks : no yes : propagated ;
feature separate-functions : no yes : propagated ;
feature stack-checking : default force enable : propagated ;
feature addressable-sections : 16 32 : propagated ;
feature code-analysis : no yes : propagated ;
feature consider-fp-exceptions : no yes : propagated ;
feature fp-model : default fast precise strict : propagated ;
feature function-padding : default hotpatch : propagated ;
feature inheritance-model : virtual multiple single : propagated ;
feature pointer-to-member : default class-first : propagated ;
feature aliasing : default none cross-function : propagated ;
feature language-extensions : on off : incidental ;
feature smaller-checks : no yes : propagated ;
feature runtime-checking
:
none
fast
stack-frame
uninitialized-locals
: propagated ;
feature calling-convention : cdecl fastcall stdcall : propagated ;
# List of all registered configurations
.versions = [ new configurations ] ;
# Inherit MIDL flags
# Inherit flags
toolset.inherit-flags msvc : midl ;
# Inherit MC flags
toolset.inherit-flags msvc : mc ;
toolset.inherit-flags msvc : msplatformsdk ;
RM = [ common.rm-command ] ;
nl = "
" ;
# Initialize the toolset for a specific version. As the result, path to
# compiler and, possible, program names are set up, and will be used when
# that version of compiler is requested. For example, you might have:
#
# using msvc : 6.5 : cl.exe ;
# using msvc : 7.0 : Y:/foo/bar/cl.exe ;
#
# The version paramater can be ommited:
#
# using msvc : : Z:/foo/bar/cl.exe ;
#
# Two special version keywords may be supplied:
# - all - all detected versions will be registered;
# - default - this is an equivalent to an empty version.
#
# Depending on a supplied version, detected configurations and presence
# 'cl.exe' in the path different results may be achieved. The following
# table describes all possible cases:
#
# Nothing "x.y"
# Passed Nothing "x.y" detected, detected,
# version detected detected cl.exe in path cl.exe in path
#
# default Error Use "x.y" Create "default" Use "x.y"
# all None Use all None Use all
# x.y - Use "x.y" - Use "x.y"
# a.b Error Error Create "a.b" Create "a.b"
#
# "x.y" - refers to a detected version;
# "a.b" - refers to an undetected version.
#
# Note: for free VC7.1 tools, we don't correctly find vcvars32.bar when user
# explicitly provides a path.
rule init (
version ? # the msvc version which is being configured. When omitted
# the tools invoked when no explicit version is given will be configured.
: command *
# the command to invoke the compiler. If not specified:
# - if version is given, default location for that version will be searched
#
# - if version is not given, default locations for 7.1, 7.0 and 6.* will
# be searched
#
# - if compiler is not found in default locations, PATH will be searched.
: options *
# options can include <setup>, <compiler>, <assembler>, <linker> and <resource-compiler>
)
{
if $(command)
{
options += <command>$(command) ;
}
configure $(version) : $(options) ;
}
# 'configure' is a newer version of 'init'. The parameter 'command' is passed as
# a part of the 'options' list.
rule configure (
version ? :
options *
)
{
switch $(version)
{
case all :
if $(options)
{
error "msvc: options should be empty when 'all' is specified" ;
}
# use all detected versions
for local v in [ $(.versions).all ]
{
configure-really $(v) ;
}
case "default" :
configure-really : $(options) ;
case * :
configure-really $(version) : $(options) ;
}
}
# Supported CPU architectures
cpu-arch-i386 =
<architecture>/<address-model>
<architecture>/<address-model>32
<architecture>x86/<address-model>
<architecture>x86/<address-model>32 ;
cpu-arch-amd64 =
<architecture>/<address-model>64
<architecture>x86/<address-model>64 ;
cpu-arch-ia64 =
<architecture>ia64/<address-model>
<architecture>ia64/<address-model>64 ;
cpu-arch-arm =
<architecture>arm4
<architecture>arm4t
<architecture>arm5
<architecture>arm5t
;
cpu-arch-mips =
<architecture>mips4
;
cpu-arch-sh =
<architecture>sh3
<architecture>sh3dsp
<architecture>sh4
<architecture>sh5
;
local rule configure-really (
version ? :
options *
)
{
# If no version supplied use the default configuration. Note that condition
# remains versionless.
local v = $(version) ;
if ! $(v)
{
# take the first detected version
version = [ $(.versions).all ] ;
version = $(version[1]) ;
# Note: 'version' can still be empty at this point if no versions were
# detected.
version ?= "default" ;
}
# Version alias -> real version number
if $(.version-alias-$(version))
{
version = $(.version-alias-$(version)) ;
}
# Check whether selected configuration is used already
if $(version) in [ $(.versions).used ]
{
# Allow multiple 'toolset.usage' calls for the same configuration
# if the identical sets of options are used
if $(options) && ( $(options) != [ $(.versions).get $(version) : options ] )
{
error "msvc: the toolset version '$(version)' is configured already" ;
}
}
else
{
# Register a new configuration
$(.versions).register $(version) ;
# Set new options if any
if $(options)
{
$(.versions).set $(version) : options : $(options) ;
}
# Mark the configuration as 'used'.
$(.versions).use $(version) ;
# Get auto-detected or user-supplied options
options = [ $(.versions).get $(version) : options ] ;
# Generate condition and save it
local condition = [ common.check-init-parameters msvc :
version $(v) ] ;
$(.versions).set $(version) : condition : $(condition) ;
local command = [ get-values <command> : $(options) ] ;
# If version is specified, we try to search first in default paths,
# and only then in PATH.
command = [ common.get-invocation-command msvc : cl.exe : $(command)
: [ default-paths $(version) ] : $(version) ] ;
common.handle-options msvc : $(condition) : $(command) : $(options) ;
if ! $(version)
{
# Even if version is not explicitly specified, try to detect the version
# from the path.
if [ MATCH "(Microsoft Visual Studio 8)" : $(command) ]
{
version = 8.0 ;
}
else if [ MATCH "(NET 2003[\/\\]VC7)" : $(command) ]
{
version = 7.1 ;
}
else if [ MATCH "(Microsoft Visual C\\+\\+ Toolkit 2003)" : $(command) ]
{
version = 7.1toolkit ;
}
else if [ MATCH "(.NET[\/\\]VC7)" : $(command) ]
{
version = 7.0 ;
}
else
{
version = 6.0 ;
}
}
# Generate and register setup command
local below-8.0 = [ MATCH ^([67]\\.) : $(version) ] ;
local cpu = i386 ;
local setup ;
local setup-option ;
if $(command)
{
command = [ common.get-absolute-tool-path $(command[-1]) ] ;
local parent = [ path.make $(command) ] ;
parent = [ path.parent $(parent) ] ;
parent = [ path.native $(parent) ] ;
# setup will be used if the script name has been specified.
# If setup is not specified, a default script will be used instead.
setup = [ get-values <setup> : $(options) ] ;
if ! $(setup)
{
if $(below-8.0)
{
setup ?= vcvars32.bat ;
}
else
{
setup ?= vcvarsall.bat ;
}
# The vccars32.bat is actually in "bin" directory.
# (except for free VC7.1 tools)
setup = [ GLOB $(command) $(parent) : $(setup) ] ;
}
if $(setup)
{
# Note Cygwin to Windows translation
setup = "\""$(setup[1]:W)"\"" ;
if ! $(below-8.0)
{
#FRA ADDON
#cpu = i386 amd64 ia64 ;
#setup-option = x86 x86_amd64 x86_ia64 ;
cpu = i386 amd64 ia64 arm ;
setup-option = x86 x86_amd64 x86_ia64 arm ;
}
}
}
local prefix = "call " ;
local suffix = " >nul
" ;
if ! [ os.name ] in NT
{
prefix = "cmd.exe /S /C call " ;
suffix = " \"&&\" " ;
}
command = $(prefix)$(setup)" "$(setup-option:E="")$(suffix) ;
# Setup script is not required in some configurations
command ?= "" ;
# Get tool names (if any) and finish setup
compiler = [ get-values <compiler> : $(options) ] ;
compiler ?= cl ;
linker = [ get-values <linker> : $(options) ] ;
linker ?= link ;
resource-compiler = [ get-values <resource-compiler> : $(options) ] ;
resource-compiler ?= rc ;
assembler = [ get-values <assembler> : $(options) ] ;
assembler ?= ml ;
idl-compiler = [ get-values <idl-compiler> : $(options) ] ;
idl-compiler ?= midl ;
mc-compiler = [ get-values <mc-compiler> : $(options) ] ;
mc-compiler ?= mc ;
#FRA ADDON
#for local i in 1 2 3
for local i in 1 2 3 4
{
local c = $(cpu[$(i)]) ;
if $(c)
{
if $(.debug-configuration)
{
ECHO "msvc: condition:"
"'$(condition)/$(cond-$(c))',"
"command: '$(command[$(i)])'" ;
}
local cond = $(condition)/$(cpu-arch-$(c)) ;
flags msvc.compile .CC $(cond) : $(command[$(i)])$(compiler) ;
flags msvc.compile .RC $(cond) : $(command[$(i)])$(resource-compiler) ;
flags msvc.compile .ASM $(cond) : $(command[$(i)])$(assembler) ;
flags msvc.link .LD $(cond) : $(command[$(i)])$(linker) ;
flags msvc.archive .LD $(cond) : $(command[$(i)])$(linker) ;
flags msvc.compile .IDL $(cond) : $(command[$(i)])$(idl-compiler) ;
flags msvc.compile .MC $(cond) : $(command[$(i)])$(mc-compiler) ;
}
}
if ! $(below-8.0)
{
#flags msvc.link MANIFEST $(condition) : "mt -nologo -manifest " ;
#flags msvc.link OUTPUTRESOURCE $(condition) : "-outputresource:" ;
}
# Set version-specific flags
configure-version-specific $(version) : $(condition) ;
}
}
# Supported CPU types
cpu-type-g5 = i586 pentium pentium-mmx ;
cpu-type-g6 =
i686 pentiumpro pentium2 pentium3 pentium3m pentium-m k6 k6-2 k6-3
winchip-c6 winchip2 c3 c3-2 ;
cpu-type-em64t = prescott nocona ;
cpu-type-amd64 = k8 opteron athlon64 athlon-fx ;
cpu-type-g7 =
pentium4 pentium4m athlon athlon-tbird athlon-4 athlon-xp athlon-mp
$(cpu-type-em64t) $(cpu-type-amd64) ;
cpu-type-itanium = itanium itanium1 merced ;
cpu-type-itanium2 = itanium2 mckinley ;
local rule configure-version-specific ( version : condition )
{
# Starting with versions 7.0, the msvc compiler have the /Zc:forScope
# and /Zc:wchar_t options that improve C++ standard conformance, but
# those options are off by default.
# If we're sure that msvc version is at 7.*, add those options explicitly.
# We can be sure either if user specified version 7.* explicitly,
# or if the installation path contain 7.* (this is checked above).
if ! [ MATCH ^(6\\.) : $(version) ]
{
flags msvc.compile CFLAGS $(condition) : /Zc:forScope /Zc:wchar_t ;
flags msvc.compile.c++ C++FLAGS $(condition) : /wd4675 ;
flags msvc.compile CFLAGS $(condition)/<warnings>all : /Wp64 ; # 64-bit compatibility warning
flags msvc.compile CFLAGS <fiber-safe-optimization>yes : /GT ;
flags msvc.compile CFLAGS <function-hooks>enter : /Gh ;
flags msvc.compile CFLAGS <function-hooks>exit : /GH ;
flags msvc.compile CFLAGS <function-hooks>both : /Gh /GH ;
flags msvc.compile CFLAGS <security-checks>yes : /GS ;
flags msvc.compile CFLAGS <smaller-checks>yes : /RTCc ;
flags msvc.compile CFLAGS <runtime-checking>fast : /RTCsu ;
flags msvc.compile CFLAGS <runtime-checking>stack-frame : /RTCs ;
flags msvc.compile CFLAGS <runtime-checking>uninitialized-locals : /RTCu ;
flags msvc.compile CFLAGS <architecture>clr/<have-assembly>no : /clr:noAssembly ;
}
else # VC6
{
flags msvc.compile CFLAGS <function-hooks>enter : /Gh ;
flags msvc.compile CFLAGS <function-hooks>exit : /Gh ;
flags msvc.compile CFLAGS <function-hooks>both : /Gh ;
}
#
# Processor-specific optimization
#
if [ MATCH ^([67]\\.) : $(version) ]
{
# 8.0 deprecates some of the options
flags msvc.compile CFLAGS $(condition)/<optimization>speed $(condition)/<optimization>space : /Ogiy /Gs ;
flags msvc.compile CFLAGS $(condition)/<optimization>speed : /Ot ;
flags msvc.compile CFLAGS $(condition)/<optimization>space : /Os ;
flags msvc.compile CFLAGS <improve-fp-consistency>yes : /Op ;
flags msvc.compile CFLAGS <aliasing>none : /Oa ;
flags msvc.compile CFLAGS <aliasing>cross-function : /Ow ;
flags msvc.compile CFLAGS $(condition)/$(cpu-arch-i386)/<instruction-set> : /GB ;
flags msvc.compile CFLAGS $(condition)/$(cpu-arch-i386)/<instruction-set>i386 : /G3 ;
flags msvc.compile CFLAGS $(condition)/$(cpu-arch-i386)/<instruction-set>i486 : /G4 ;
flags msvc.compile CFLAGS $(condition)/$(cpu-arch-i386)/<instruction-set>$(cpu-type-g5) : /G5 ;
flags msvc.compile CFLAGS $(condition)/$(cpu-arch-i386)/<instruction-set>$(cpu-type-g6) : /G6 ;
flags msvc.compile CFLAGS $(condition)/$(cpu-arch-i386)/<instruction-set>$(cpu-type-g7) : /G7 ;
flags msvc.compile CFLAGS <architecture>clr : /clr ;
}
else # VC8+
{
flags msvc.compile CFLAGS <architecture>clr/<clr>default : /clr ;
flags msvc.compile CFLAGS <architecture>clr/<clr>cppcli : /clr ;
flags msvc.compile CFLAGS <architecture>clr/<clr>managed : /clr:oldSyntax ;
flags msvc.compile CFLAGS <architecture>clr/<pure-clr>yes : /clr:pure ;
flags msvc.compile CFLAGS <architecture>clr/<safe-clr>yes : /clr:safe ;
flags msvc.compile CFLAGS <architecture>clr/<initial-app-domain>yes : /clr:initialAppDomain ;
flags msvc.compile CFLAGS <consider-fp-exceptions>yes : /fp:except ;
flags msvc.compile CFLAGS <fp-model>fast : /fp:fast ;
flags msvc.compile CFLAGS <fp-model>precise : /fp:precise ;
flags msvc.compile CFLAGS <fp-model>strict : /fp:strict ;
flags msvc.compile CFLAGS <function-padding>hotpatch : /hotpatch ;
flags msvc.compile CFLAGS <code-analysis>yes : /analyse ;
flags msvc.compile CFLAGS <addressable-sections>32 : /bigobj ;
}
}
# Returns the default installation path for the given version.
local rule default-path ( version )
{
# Use auto-detected path if possible
local path = [ get-values <command> :
[ $(.versions).get $(version) : options ] ] ;
if $(path)
{
path = $(path:D) ;
}
else
{
# Check environment
if $(.version-$(version)-env)
{
local vc-path = [ os.environ $(.version-$(version)-env) ] ;
if $(vc-path)
{
vc-path = [ path.make $(vc-path) ] ;
vc-path = [ path.join $(vc-path) $(.version-$(version)-envpath) ] ;
vc-path = [ path.native $(vc-path) ] ;
path = $(vc-path) ;
}
}
# Check default path
if ! $(path) && $(.version-$(version)-path)
{
path = [ path.native [ path.join $(.ProgramFiles) $(.version-$(version)-path) ] ] ;
}
}
return $(path) ;
}
# Returns either the default installation path (if 'version' is not empty) or list of all
# known default paths (if no version is given)
rule default-paths ( version ? )
{
local possible-paths ;
if $(version)
{
default-path += [ default-path $(version) ] ;
}
else
{
for local i in $(.known-versions)
{
default-path += [ default-path $(i) ] ;
}
}
return $(possible-paths) ;
}
# Declare generators
# is it possible to combine these?
# make the generators non-composing, so that they don't convert each source
# into separate rsp file.
generators.register-linker msvc.link : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE : <toolset>msvc ;
generators.register-linker msvc.link.dll : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB : <toolset>msvc ;
generators.register-linker msvc.link.resource-dll : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB : <toolset>msvc <resource-only>yes ;
generators.override msvc.link.resource-dll : msvc.link.dll ;
generators.register-archiver msvc.archive : OBJ : STATIC_LIB : <toolset>msvc ;
generators.register-c-compiler msvc.compile.c++ : CPP : OBJ : <toolset>msvc ;
generators.register-c-compiler msvc.compile.c : C : OBJ : <toolset>msvc ;
# Using 'register-c-compiler' adds the build directory to INCLUDES
generators.register-c-compiler msvc.compile.rc : RC : OBJ(%_res) : <toolset>msvc ;
generators.override msvc.compile.rc : rc.resource-compile ;
generators.register-standard msvc.compile.asm : ASM : OBJ : <toolset>msvc ;
generators.register-c-compiler msvc.compile.idl : IDL : MSTYPELIB H C(%_i) C(%_proxy) C(%_dlldata) : <toolset>msvc ;
generators.override msvc.compile.idl : midl.compile.idl ;
generators.register-standard msvc.compile.mc : MC : H RC : <toolset>msvc ;
generators.override msvc.compile.mc : mc.compile ;
generators.register [ new pch-generator msvc.compile.pch : PCHEADER : OBJ PCH : <toolset>msvc ] ;
#
# Declare flags and action for compilation
#
#feature.feature debug-store : object database : propagated ;
flags msvc.compile CFLAGS <optimization>speed : /O2 ;
flags msvc.compile CFLAGS <optimization>space : /O1 ;
flags msvc.compile CFLAGS <optimize-for-windows>yes : /GA ;
flags msvc.compile CFLAGS <string-pooling>yes : /GF ;
flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>database/<minimal-rebuild>yes : /Gm ;
flags msvc.compile CFLAGS <stack-checking>force : /Ge ;
flags msvc.compile CFLAGS <stack-checking>enable : /Gs0 ;
flags msvc.compile CFLAGS <language-extensions>off : /Za ;
flags msvc.compile CFLAGS <calling-convention>cdecl : /Gd ;
flags msvc.compile CFLAGS <calling-convention>fastcall : /Gr ;
flags msvc.compile CFLAGS <calling-convention>stdcall : /Gz ;
flags msvc.compile CFLAGS <inheritance-model>virtual : /vmv ;
flags msvc.compile CFLAGS <inheritance-model>multiple : /vmm ;
flags msvc.compile CFLAGS <inheritance-model>single : /vms ;
flags msvc.compile CFLAGS <pointer-to-member>default : /vmg ;
flags msvc.compile CFLAGS <pointer-to-member>class-first : /vmb ;
flags msvc.compile CFLAGS $(cpu-arch-amd64)/<instruction-set> : /favor:blend ;
flags msvc.compile CFLAGS $(cpu-arch-amd64)/<instruction-set>$(cpu-type-em64t) : /favor:EM64T ;
flags msvc.compile CFLAGS $(cpu-arch-amd64)/<instruction-set>$(cpu-type-amd64) : /favor:AMD64 ;
flags msvc.compile CFLAGS $(cpu-arch-ia64)/<instruction-set>$(cpu-type-itanium) : /G1 ;
flags msvc.compile CFLAGS $(cpu-arch-ia64)/<instruction-set>$(cpu-type-itanium2) : /G2 ;
flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>object : /Z7 ;
flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>database : /Zi ;
flags msvc.compile CFLAGS $(cpu-arch-i386)/<debug-symbols>on/<debug-store>edit-and-continue : /ZI ;
flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>lines-only : /Zd ;
flags msvc.compile CFLAGS <optimization>off : /Od ;
flags msvc.compile CFLAGS <inlining>off : /Ob0 ;
flags msvc.compile CFLAGS <inlining>on : /Ob1 ;
flags msvc.compile CFLAGS <inlining>full : /Ob2 ;
flags msvc.compile CFLAGS <alignment>1 : /Zp1 ;
flags msvc.compile CFLAGS <alignment>2 : /Zp2 ;
flags msvc.compile CFLAGS <alignment>4 : /Zp4 ;
flags msvc.compile CFLAGS <alignment>8 : /Zp8 ;
flags msvc.compile CFLAGS <alignment>16 : /Zp16 ;
flags msvc.compile CFLAGS <warnings>on : /W3 ;
flags msvc.compile CFLAGS <warnings>off : /W0 ;
flags msvc.compile CFLAGS <warnings>all : /W4 ;
flags msvc.compile CFLAGS <warnings-as-errors>on : /WX ;
flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>off : /EHs ;
flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>on : /EHsc ;
flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>off : /EHa ;
flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>on : /EHac ;
flags msvc.compile CFLAGS <rtti>on : /GR ;
flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>shared : /MD ;
flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>shared : /MDd ;
flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>static/<threading>single : /ML ;
flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>static/<threading>single : /MLd ;
flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>static/<threading>multi : /MT ;
flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>static/<threading>multi : /MTd ;
flags msvc.compile USER_CFLAGS <cflags> : ;
flags msvc.compile.c++ USER_CFLAGS <cxxflags> : ;
flags msvc.compile PDB_CFLAG <debug-symbols>on/<debug-store>database : /Fd ; # not used yet
# CPU architecture and general windows version:
flags msvc.compile CFLAGS $(cpu-arch-i386) : /DWIN32 /DX86 /D_X86_ ;
flags msvc.compile CFLAGS $(cpu-arch-ia64) : /DWIN64 /DIA64 /D_IA64_ ;
flags msvc.compile CFLAGS $(cpu-arch-amd64) : /DWIN64 /DAMD64 /D_AMD64_ ;
#FRA ADDON
flags msvc.compile CFLAGS $(cpu-arch-arm) : /DBOOST_USE_WINDOWS_H /DWINCE /DARM /D_ARM_ /D_M_ARM /D_WIN32_WCE=0x420 /DUNDER_CE /DWIN32_PLATFORM_PSPC /DWINCE /D_UNICODE /DUNICODE /DTLS_OUT_OF_INDEXES=0xffffffff ;
#END
flags msvc.compile CFLAGS $(cpu-arch-sh) : /DWINCE ;
flags msvc.compile CFLAGS $(cpu-arch-mips) : /DWINCE ;
flags msvc.compile DEFINES <define> ;
flags msvc.compile UNDEFS <undef> ;
flags msvc.compile INCLUDES <include> ;
flags msvc.compile PCH_SOURCE <pch-source> ;
flags msvc.compile PCH_HEADER <pch>on : <pch-header> ;
flags msvc.compile PCH_FILE <pch>on : <pch-file> ;
rule compile.c ( targets + : sources * : properties * )
{
DEPENDS $(<) : [ on $(<) return $(PCH_HEADER) ] ;
DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ;
}
rule compile.c++ ( targets + : sources * : properties * )
{
DEPENDS $(<) : [ on $(<) return $(PCH_HEADER) ] ;
DEPENDS $(<) : [ on $(<) return $(PCH_FILE) ] ;
}
rule compile.pch ( targets + : sources * : properties * )
{
DEPENDS $(<) : [ on $(<) return $(PCH_SOURCE) ] ;
}
# The actions differ only by explicit selection of input language
actions compile.c bind PCH_HEADER PCH_FILE
{
$(.CC) /Zm800 -nologo -TC -U$(UNDEFS) $(CFLAGS) $(USER_CFLAGS) @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)-D$(DEFINES) $(nl)"-I$(INCLUDES)")" -c -Fo"$(<[1]:W)" -Yu"$(PCH_HEADER:D=)" -Fp"$(PCH_FILE:W)"
}
actions compile.c++ bind PCH_HEADER PCH_FILE
{
echo using the following compiler options (action compile.c++):
echo $(C++FLAGS)
echo $(CFLAGS)
echo end
$(.CC) /Zm800 -nologo -TP -U$(UNDEFS) $(CFLAGS) $(C++FLAGS) $(USER_CFLAGS) @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)-D$(DEFINES) $(nl)"-I$(INCLUDES)")" -c -Fo"$(<[1]:W)" -Yu"$(PCH_HEADER:D=)" -Fp"$(PCH_FILE:W)"
}
actions compile.pch bind PCH_SOURCE
{
$(.CC) /Zm800 -nologo -TP -U$(UNDEFS) $(CFLAGS) $(C++FLAGS) $(USER_CFLAGS) @"@($(<[1]:W).rsp:E=$(nl)"$(PCH_SOURCE:W)" $(nl)-D$(DEFINES) $(nl)"-I$(INCLUDES)")" -c -Fo"$(<[1]:W)" /Yc"$(>[1]:D=)" -Yl__bjam_pch_symbol -Fp"$(<[2]:W)"
}
actions compile.rc
{
$(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES)" -fo "$(<:W)" "$(>:W)"
}
TOUCH_FILE = [ midl.file-touch-command ] ;
actions compile.idl
{
$(.IDL) /nologo @"@($(<[1]:W).rsp:E=$(nl)"$(>:W)" $(nl)-D$(DEFINES) $(nl)"-I$(INCLUDES)" $(nl)-U$(UNDEFS) $(nl)$(MIDLFLAGS) $(nl)/tlb "$(<[1]:W)" $(nl)/h "$(<[2]:W)" $(nl)/iid "$(<[3]:W)" $(nl)/proxy "$(<[4]:W)" $(nl)/dlldata "$(<[5]:W)")"
$(TOUCH_FILE) "$(<[4]:W)"
$(TOUCH_FILE) "$(<[5]:W)"
}
# Declare flags and action for the assembler
flags msvc.compile.asm USER_ASMFLAGS <asmflags> : ;
#
# for the assembler the following options are turned on by default:
#
# -coff generate COFF format object file (compatible with cl.exe output)
# -Zp4 align structures to 4 bytes
# -Cp preserve case of user identifiers
# -Cx preserve case in publics, externs
flags msvc.compile ASMFLAGS <alignment>1 : /Zp1 ;
flags msvc.compile ASMFLAGS <alignment>2 : /Zp2 ;
flags msvc.compile ASMFLAGS <alignment>4 : /Zp4 ;
flags msvc.compile ASMFLAGS <alignment>8 : /Zp8 ;
flags msvc.compile ASMFLAGS <alignment>16 : /Zp16 ;
actions compile.asm
{
$(.ASM) -nologo -c -coff -Cp -Cx $(ASMFLAGS) $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)"
}
# Declare flags and action for linking
flags msvc.link PDB_LINKFLAG <debug-symbols>on/<debug-store>database : /PDB: ; # not used yet
flags msvc.link LINKFLAGS <debug-symbols>on : /DEBUG ;
flags msvc.link LINKFLAGS <debug-symbols>off : /RELEASE ;
flags msvc.link DEF_FILE <def-file> ;
# The linker disables the default optimizations when using /DEBUG. Whe have
# to enable them manually for release builds with debug symbols.
flags msvc LINKFLAGS <debug-symbols>on/<runtime-debugging>off : /OPT:REF,ICF ;
#FRA ADDON
flags msvc LINKFLAGS <user-interface>console : /subsystem:console ;
#END
flags msvc LINKFLAGS <user-interface>gui : /subsystem:windows ;
flags msvc LINKFLAGS <user-interface>wince : /subsystem:windowsce ;
flags msvc LINKFLAGS <user-interface>native : /subsystem:native ;
flags msvc LINKFLAGS <user-interface>auto : /subsystem:posix ;
flags msvc LINKFLAGS <main-target-type>LIB/<link>shared : /DLL ;
flags msvc LINKFLAGS <main-target-type>LIB/<link>shared/<resource-only>yes : /noentry ;
# CPU architecture:
flags msvc LINKFLAGS $(cpu-arch-i386) : -machine:x86 ;
flags msvc LINKFLAGS $(cpu-arch-ia64) : -machine:ia64 ;
flags msvc LINKFLAGS $(cpu-arch-amd64) : -machine:amd64 ;
#FRA ADDON
flags msvc LINKFLAGS $(cpu-arch-arm) : -machine:arm ccrtrtti.lib ;
#END
flags msvc LINKFLAGS $(cpu-arch-mips) : -machine:mips ;
flags msvc LINKFLAGS <architecture>sh3 : -machine:sh3 ;
flags msvc LINKFLAGS <architecture>sh3dsp : -machine:sh3dsp ;
flags msvc LINKFLAGS <architecture>sh4 : -machine:sh4 ;
flags msvc LINKFLAGS <architecture>sh5 : -machine:sh5 ;
flags msvc.link USER_LINKFLAGS <linkflags> ;
flags msvc.link LINKPATH <library-path> ;
flags msvc.link FINDLIBS_ST <find-static-library> ;
flags msvc.link FINDLIBS_SA <find-shared-library> ;
flags msvc.link LIBRARY_OPTION <toolset>msvc : "" : unchecked ;
flags msvc.link LIBRARIES_MENTIONED_BY_FILE : <library-file> ;
rule link.dll ( targets + : sources * : properties * )
{
DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
}
rule link.resource-dll ( targets + : sources * : properties * )
{
DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
}
# Declare action for creating static libraries
# If library exists, remove it before adding files. See
# http://article.gmane.org/gmane.comp.lib.boost.build/4241
# for rationale.
if [ os.name ] in NT
{
# The 'DEL' command would issue a message to stdout
# if the file does not exist, so need a check.
actions archive
{
if exist "$(<[1])" DEL "$(<[1])"
$(.LD) /lib /NOLOGO /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES_MENTIONED_BY_FILE) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")"
}
}
else
{
actions archive
{
$(RM) "$(<[1])"
$(.LD) /lib /NOLOGO /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES_MENTIONED_BY_FILE) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")"
}
}
# incremental linking a DLL causes no end of problems: if the
# actual exports don't change, the import .lib file is never
# updated. Therefore, the .lib is always out-of-date and gets
# rebuilt every time. I'm not sure that incremental linking is
# such a great idea in general, but in this case I'm sure we
# don't want it.
# Windows Manifests is a new way to specify dependencies
# on managed DotNet assemblies and Windows native DLLs. The
# manifests are embedded as resourses and are useful in
# any PE targets (both DLL and EXE)
actions link bind DEF_FILE
{
$(.LD) /NOLOGO $(LINKFLAGS) /out:"$(<[1]:W)" /INCREMENTAL:NO /LIBPATH:"$(LINKPATH:W)" $(USER_LINKFLAGS) @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES_MENTIONED_BY_FILE) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")"
$(MANIFEST)$(<[1]).manifest $(OUTPUTRESOURCE)$(<[1]);1
}
actions link.dll bind DEF_FILE
{
$(.LD) /NOLOGO $(LINKFLAGS) /out:"$(<[1]:W)" /INCREMENTAL:NO /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:$(DEF_FILE) $(USER_LINKFLAGS) @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES_MENTIONED_BY_FILE) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")"
$(MANIFEST)$(<[1]).manifest $(OUTPUTRESOURCE)$(<[1]);2
}
actions link.resource-dll bind DEF_FILE
{
$(.LD) /NOLOGO $(LINKFLAGS) /out:"$(<[1]:W)" /INCREMENTAL:NO /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:$(DEF_FILE) $(USER_LINKFLAGS) @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES_MENTIONED_BY_FILE) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")"
$(MANIFEST)$(<[1]).manifest $(OUTPUTRESOURCE)$(<[1]);2
}
actions compile.mc
{
$(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)"
}
#
# Autodetection code
# detects versions listed as '.known-versions' using registry, environment
# and checking default paths. Supports both native Windows and Cygwin.
#
.ProgramFiles = [ path.make [ common.get-program-files-dir ] ] ;
.known-versions = 8.0 8.0express 7.1 7.1toolkit 7.0 6.0 ;
# Version aliases
.version-alias-6 = 6.0 ;
.version-alias-7 = 7.0 ;
.version-alias-8 = 8.0 ;
# Name of the registry key that contains Visual C++ installation path
# (relative to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft"
.version-6.0-reg = "VisualStudio\\6.0\\Setup\\Microsoft Visual C++" ;
.version-7.0-reg = "VisualStudio\\7.0\\Setup\\VC" ;
.version-7.1-reg = "VisualStudio\\7.1\\Setup\\VC" ;
.version-8.0-reg = "VisualStudio\\8.0\\Setup\\VC" ;
.version-8.0express-reg = "VCExpress\\8.0\\Setup\\VC" ;
# Visual C++ Toolkit 2003 do not store its installation path in the registry.
# The environment variable 'VCToolkitInstallDir' and the default installation
# path will be checked instead.
.version-7.1toolkit-path = "Microsoft Visual C++ Toolkit 2003" "bin" ;
.version-7.1toolkit-env = VCToolkitInstallDir ;
# Path to the folder containing "cl.exe" relative to the value of the corresponding
# environment variable
.version-7.1toolkit-envpath = "bin" ;
# Validates given path, registers found configuration and prints debug information
# about it.
local rule register-configuration ( version : path ? )
{
if $(path)
{
local command = [ GLOB $(path) : cl.exe ] ;
if $(command)
{
if $(.debug-configuration)
{
ECHO "notice: msvc-$(version) detected, command: '$(command)'" ;
}
$(.versions).register $(version) ;
$(.versions).set $(version) : options : <command>$(command) ;
}
}
}
if [ os.name ] in NT CYGWIN
{
# Get installation paths from the registry
for local i in $(.known-versions)
{
if $(.version-$(i)-reg)
{
local vc-path = [ W32_GETREG
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"$(.version-$(i)-reg)
: "ProductDir" ] ;
if $(vc-path)
{
vc-path = [ path.native [ path.join [ path.make-NT $(vc-path) ] "bin" ] ] ;
register-configuration $(i) : $(vc-path) ;
}
}
}
}
# Check environment and default installation paths
for local i in $(.known-versions)
{
if ! $(i) in [ $(.versions).all ]
{
register-configuration $(i) : [ default-path $(i) ] ;
}
}
Boost-Build list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk