blob: 5ad05b311306828f7de9aaaf5403c40bd670b02b [file] [log] [blame]
# Copyright 2002, 2003, 2004, 2005 Dave Abrahams
# Copyright 2002, 2005, 2006, 2007, 2010 Rene Rivera
# Copyright 2006 Juergen Hunold
# Copyright 2005 Toon Knapen
# 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)
# Defines standard features and rules.
import alias ;
import "class" : new ;
import errors ;
import feature ;
import generators ;
import numbers ;
import os ;
import path ;
import print ;
import project ;
import property ;
import regex ;
import scanner ;
import sequence ;
import stage ;
import symlink ;
import toolset ;
import type ;
import types/register ;
import utility ;
import virtual-target ;
import message ;
import convert ;
# FIXME: the following generate module import is not needed here but removing it
# too hastly will break using code (e.g. the main Boost library Jamroot file)
# that forgot to import the generate module before calling the generate rule.
import generate ;
.os-names = aix bsd cygwin darwin freebsd hpux iphone linux netbsd
openbsd osf qnx qnxnto sgi solaris unix unixware windows
elf # Not actually an OS -- used for targeting bare metal where
# object format is ELF. This catches both -elf and -eabi gcc
# targets and well as other compilers targeting ELF. It is not
# clear how often do we need to key of ELF specifically as opposed
# to other bare metal targets, but let's stick with gcc naming.
;
# Feature used to determine which OS we're on. New <target-os> and <host-os>
# features should be used instead.
local os = [ modules.peek : OS ] ;
feature.feature os : $(os) : propagated link-incompatible ;
# Translates from bjam current OS to the os tags used in host-os and target-os,
# i.e. returns the running host-os.
#
local rule default-host-os ( )
{
local host-os ;
if [ os.name ] in $(.os-names:U)
{
host-os = [ os.name ] ;
}
else
{
switch [ os.name ]
{
case NT : host-os = windows ;
case AS400 : host-os = unix ;
case MINGW : host-os = windows ;
case BSDI : host-os = bsd ;
case COHERENT : host-os = unix ;
case DRAGONFLYBSD : host-os = bsd ;
case IRIX : host-os = sgi ;
case MACOSX : host-os = darwin ;
case KFREEBSD : host-os = freebsd ;
case LINUX : host-os = linux ;
case SUNOS :
ECHO "SunOS is not a supported operating system." ;
ECHO "We believe last version of SunOS was released in 1992, " ;
ECHO "so if you get this message, something is very wrong with configuration logic. " ;
ECHO "Please report this as a bug. " ;
EXIT ;
case * : host-os = unix ;
}
}
return $(host-os:L) ;
}
# The two OS features define a known set of abstract OS names. The host-os is
# the OS under which bjam is running. Even though this should really be a fixed
# property we need to list all the values to prevent unknown value errors. Both
# set the default value to the current OS to account for the default use case of
# building on the target OS.
feature.feature host-os : $(.os-names) ;
feature.set-default host-os : [ default-host-os ] ;
feature.feature target-os : $(.os-names) : propagated link-incompatible ;
feature.set-default target-os : [ default-host-os ] ;
feature.feature toolset : : implicit propagated symmetric ;
feature.feature stdlib : native : propagated composite ;
feature.feature link : shared static : propagated ;
feature.feature runtime-link : shared static : propagated ;
feature.feature runtime-debugging : on off : propagated ;
feature.feature optimization : off speed space : propagated ;
feature.feature profiling : off on : propagated ;
feature.feature inlining : off on full : propagated ;
feature.feature threading : single multi : propagated ;
feature.feature rtti : on off : propagated ;
feature.feature exception-handling : on off : propagated ;
# Whether there is support for asynchronous EH (e.g. catching SEGVs).
feature.feature asynch-exceptions : off on : propagated ;
# Whether all extern "C" functions are considered nothrow by default.
feature.feature extern-c-nothrow : off on : propagated ;
feature.feature debug-symbols : on off : propagated ;
# Controls whether the binary should be stripped -- that is have
# everything not necessary to running removed. This option should
# not be very often needed. Also, this feature will show up in
# target paths of everything, not just binaries. Should fix that
# when impelementing feature relevance.
feature.feature strip : off on : propagated ;
feature.feature define : : free ;
feature.feature undef : : free ;
feature.feature "include" : : free path ; #order-sensitive ;
feature.feature cflags : : free ;
feature.feature cxxflags : : free ;
feature.feature fflags : : free ;
feature.feature asmflags : : free ;
feature.feature linkflags : : free ;
feature.feature archiveflags : : free ;
feature.feature version : : free ;
# Generic, i.e. non-language specific, flags for tools.
feature.feature flags : : free ;
feature.feature location-prefix : : free ;
# The following features are incidental since they have no effect on built
# products. Not making them incidental will result in problems in corner cases,
# e.g.:
#
# unit-test a : a.cpp : <use>b ;
# lib b : a.cpp b ;
#
# Here, if <use> is not incidental, we would decide we have two targets for
# a.obj with different properties and complain about it.
#
# Note that making a feature incidental does not mean it is ignored. It may be
# ignored when creating a virtual target, but the rest of build process will use
# them.
feature.feature use : : free dependency incidental ;
feature.feature dependency : : free dependency incidental ;
feature.feature implicit-dependency : : free dependency incidental ;
feature.feature warnings :
on # Enable default/"reasonable" warning level for the tool.
all # Enable all possible warnings issued by the tool.
off # Disable all warnings issued by the tool.
: incidental propagated ;
feature.feature warnings-as-errors :
off # Do not fail the compilation if there are warnings.
on # Fail the compilation if there are warnings.
: incidental propagated ;
# Feature that allows us to configure the maximal template instantiation depth
# level allowed by a C++ compiler. Applies only to C++ toolsets whose compilers
# actually support this configuration setting.
#
# Note that Boost Build currently does not allow defining features that take any
# positive integral value as a parameter, which is what we need here, so we just
# define some of the values here and leave it up to the user to extend this set
# as he needs using the feature.extend rule.
#
# TODO: This should be upgraded as soon as Boost Build adds support for custom
# validated feature values or at least features allowing any positive integral
# value. See related Boost Build related trac ticket #194.
#
feature.feature c++-template-depth
:
[ numbers.range 64 1024 : 64 ]
[ numbers.range 20 1000 : 10 ]
# Maximum template instantiation depth guaranteed for ANSI/ISO C++
# conforming programs.
17
:
incidental optional propagated ;
feature.feature source : : free dependency incidental ;
feature.feature library : : free dependency incidental ;
feature.feature file : : free dependency incidental ;
feature.feature find-shared-library : : free ; #order-sensitive ;
feature.feature find-static-library : : free ; #order-sensitive ;
feature.feature library-path : : free path ; #order-sensitive ;
# Internal feature.
feature.feature library-file : : free dependency ;
feature.feature name : : free ;
feature.feature tag : : free ;
feature.feature search : : free path ; #order-sensitive ;
feature.feature location : : free path ;
feature.feature dll-path : : free path ;
feature.feature hardcode-dll-paths : true false : incidental ;
# An internal feature that holds the paths of all dependency shared libraries.
# On Windows, it is needed so that we can add all those paths to PATH when
# running applications. On Linux, it is needed to add proper -rpath-link command
# line options.
feature.feature xdll-path : : free path ;
# Provides means to specify def-file for windows DLLs.
feature.feature def-file : : free dependency ;
feature.feature suppress-import-lib : false true : incidental ;
# Internal feature used to store the name of a bjam action to call when building
# a target.
feature.feature action : : free ;
# This feature is used to allow specific generators to run. For example, QT
# tools can only be invoked when QT library is used. In that case, <allow>qt
# will be in usage requirement of the library.
feature.feature allow : : free ;
# The addressing model to generate code for. Currently a limited set only
# specifying the bit size of pointers.
feature.feature address-model : 16 32 64 32_64 : propagated optional ;
# Type of CPU architecture to compile for.
feature.feature architecture :
# x86 and x86-64
x86
# ia64
ia64
# Sparc
sparc
# RS/6000 & PowerPC
power
# MIPS/SGI
mips1 mips2 mips3 mips4 mips32 mips32r2 mips64
# HP/PA-RISC
parisc
# Advanced RISC Machines
arm
# Combined architectures for platforms/toolsets that support building for
# multiple architectures at once. "combined" would be the default multi-arch
# for the toolset.
combined
combined-x86-power
: propagated optional ;
# The specific instruction set in an architecture to compile.
feature.feature instruction-set :
# x86 and x86-64
native i386 i486 i586 i686 pentium pentium-mmx pentiumpro pentium2 pentium3
pentium3m pentium-m pentium4 pentium4m prescott nocona core2 conroe conroe-xe
conroe-l allendale mermon mermon-xe kentsfield kentsfield-xe penryn wolfdale
yorksfield nehalem k6 k6-2 k6-3 athlon athlon-tbird athlon-4 athlon-xp
athlon-mp k8 opteron athlon64 athlon-fx winchip-c6 winchip2 c3 c3-2
# ia64
itanium itanium1 merced itanium2 mckinley
# Sparc
v7 cypress v8 supersparc sparclite hypersparc sparclite86x f930 f934
sparclet tsc701 v9 ultrasparc ultrasparc3
# RS/6000 & PowerPC
401 403 405 405fp 440 440fp 505 601 602 603 603e 604 604e 620 630 740 7400
7450 750 801 821 823 860 970 8540 power-common ec603e g3 g4 g5 power power2
power3 power4 power5 powerpc powerpc64 rios rios1 rsc rios2 rs64a
# MIPS
4kc 4kp 5kc 20kc m4k r2000 r3000 r3900 r4000 r4100 r4300 r4400 r4600 r4650
r6000 r8000 rm7000 rm9000 orion sb1 vr4100 vr4111 vr4120 vr4130 vr4300
vr5000 vr5400 vr5500
# HP/PA-RISC
700 7100 7100lc 7200 7300 8000
# Advanced RISC Machines
armv2 armv2a armv3 armv3m armv4 armv4t armv5 armv5t armv5te armv6 armv6j iwmmxt ep9312
: propagated optional ;
# Used to select a specific variant of C++ ABI if the compiler supports several.
feature.feature c++abi : : propagated optional ;
feature.feature conditional : : incidental free ;
# The value of 'no' prevents building of a target.
feature.feature build : yes no : optional ;
# Windows-specific features
feature.feature user-interface : console gui wince native auto ;
feature.feature variant : : implicit composite propagated symmetric ;
# Declares a new variant.
#
# First determines explicit properties for this variant, by refining parents'
# explicit properties with the passed explicit properties. The result is
# remembered and will be used if this variant is used as parent.
#
# Second, determines the full property set for this variant by adding to the
# explicit properties default values for all missing non-symmetric properties.
#
# Lastly, makes appropriate value of 'variant' property expand to the full
# property set.
#
rule variant ( name # Name of the variant
: parents-or-properties * # Specifies parent variants, if
# 'explicit-properties' are given, and
# explicit-properties or parents otherwise.
: explicit-properties * # Explicit properties.
)
{
local parents ;
if ! $(explicit-properties)
{
if $(parents-or-properties[1]:G)
{
explicit-properties = $(parents-or-properties) ;
}
else
{
parents = $(parents-or-properties) ;
}
}
else
{
parents = $(parents-or-properties) ;
}
# The problem is that we have to check for conflicts between base variants.
if $(parents[2])
{
errors.error "multiple base variants are not yet supported" ;
}
local inherited ;
# Add explicitly specified properties for parents.
for local p in $(parents)
{
# TODO: This check may be made stricter.
if ! [ feature.is-implicit-value $(p) ]
{
errors.error "Invalid base variant" $(p) ;
}
inherited += $(.explicit-properties.$(p)) ;
}
property.validate $(explicit-properties) ;
explicit-properties = [ property.refine $(inherited)
: $(explicit-properties) ] ;
# Record explicitly specified properties for this variant. We do this after
# inheriting parents' properties so they affect other variants derived from
# this one.
.explicit-properties.$(name) = $(explicit-properties) ;
feature.extend variant : $(name) ;
feature.compose <variant>$(name) : $(explicit-properties) ;
}
IMPORT $(__name__) : variant : : variant ;
variant debug : <optimization>off <debug-symbols>on <inlining>off
<runtime-debugging>on ;
variant release : <optimization>speed <debug-symbols>off <inlining>full
<runtime-debugging>off <define>NDEBUG ;
variant profile : release : <profiling>on <debug-symbols>on ;
class searched-lib-target : abstract-file-target
{
rule __init__ ( name
: project
: shared ?
: search *
: action
)
{
abstract-file-target.__init__ $(name) : SEARCHED_LIB : $(project)
: $(action) : ;
self.shared = $(shared) ;
self.search = $(search) ;
}
rule shared ( )
{
return $(self.shared) ;
}
rule search ( )
{
return $(self.search) ;
}
rule actualize-location ( target )
{
NOTFILE $(target) ;
}
rule path ( )
{
}
}
# The generator class for libraries (target type LIB). Depending on properties
# it will request building of the appropriate specific library type --
# -- SHARED_LIB, STATIC_LIB or SHARED_LIB.
#
class lib-generator : generator
{
rule __init__ ( * : * )
{
generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
}
rule run ( project name ? : property-set : sources * )
{
# The lib generator is composing, and can be only invoked with an
# explicit name. This check is present in generator.run (and so in
# builtin.linking-generator) but duplicated here to avoid doing extra
# work.
if $(name)
{
local properties = [ $(property-set).raw ] ;
# Determine the needed target type.
local actual-type ;
# <source>files can be generated by <conditional>@rule feature
# in which case we do not consider it a SEARCHED_LIB type.
if ! <source> in $(properties:G) &&
( <search> in $(properties:G) || <name> in $(properties:G) )
{
actual-type = SEARCHED_LIB ;
}
else if <file> in $(properties:G)
{
actual-type = LIB ;
}
else if <link>shared in $(properties)
{
actual-type = SHARED_LIB ;
}
else
{
actual-type = STATIC_LIB ;
}
property-set = [ $(property-set).add-raw <main-target-type>LIB ] ;
# Construct the target.
return [ generators.construct $(project) $(name) : $(actual-type)
: $(property-set) : $(sources) ] ;
}
}
rule viable-source-types ( )
{
return * ;
}
}
generators.register [ new lib-generator builtin.lib-generator : : LIB ] ;
# The implementation of the 'lib' rule. Beyond standard syntax that rule allows
# simplified: "lib a b c ;".
#
rule lib ( names + : sources * : requirements * : default-build * :
usage-requirements * )
{
if $(names[2])
{
if <name> in $(requirements:G)
{
errors.user-error "When several names are given to the 'lib' rule" :
"it is not allowed to specify the <name> feature." ;
}
if $(sources)
{
errors.user-error "When several names are given to the 'lib' rule" :
"it is not allowed to specify sources." ;
}
}
# This is a circular module dependency so it must be imported here.
import targets ;
local project = [ project.current ] ;
local result ;
for local name in $(names)
{
local r = $(requirements) ;
# Support " lib a ; " and " lib a b c ; " syntax.
if ! $(sources) && ! <name> in $(requirements:G)
&& ! <file> in $(requirements:G)
{
r += <name>$(name) ;
}
result += [ targets.main-target-alternative
[ new typed-target $(name) : $(project) : LIB
: [ targets.main-target-sources $(sources) : $(name) ]
: [ targets.main-target-requirements $(r) : $(project) ]
: [ targets.main-target-default-build $(default-build) : $(project) ]
: [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
] ] ;
}
return $(result) ;
}
IMPORT $(__name__) : lib : : lib ;
class searched-lib-generator : generator
{
import property-set ;
rule __init__ ( )
{
# The requirements cause the generators to be tried *only* when we're
# building a lib target with a 'search' feature. This seems ugly --- all
# we want is to make sure searched-lib-generator is not invoked deep
# inside transformation search to produce intermediate targets.
generator.__init__ searched-lib-generator : : SEARCHED_LIB ;
}
rule run ( project name ? : property-set : sources * )
{
if $(name)
{
# If 'name' is empty, it means we have not been called to build a
# top-level target. In this case, we just fail immediately, because
# searched-lib-generator cannot be used to produce intermediate
# targets.
local properties = [ $(property-set).raw ] ;
local shared ;
if <link>shared in $(properties)
{
shared = true ;
}
local search = [ feature.get-values <search> : $(properties) ] ;
local a = [ new null-action $(property-set) ] ;
local lib-name = [ feature.get-values <name> : $(properties) ] ;
lib-name ?= $(name) ;
local t = [ new searched-lib-target $(lib-name) : $(project)
: $(shared) : $(search) : $(a) ] ;
# We return sources for a simple reason. If there is
# lib png : z : <name>png ;
# the 'z' target should be returned, so that apps linking to 'png'
# will link to 'z', too.
return [ property-set.create <xdll-path>$(search) ]
[ virtual-target.register $(t) ] $(sources) ;
}
}
}
generators.register [ new searched-lib-generator ] ;
class prebuilt-lib-generator : generator
{
rule __init__ ( * : * )
{
generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
}
rule run ( project name ? : property-set : sources * )
{
local f = [ $(property-set).get <file> ] ;
return $(f) $(sources) ;
}
}
generators.register
[ new prebuilt-lib-generator builtin.prebuilt : : LIB : <file> ] ;
generators.override builtin.prebuilt : builtin.lib-generator ;
class compile-action : action
{
import sequence ;
rule __init__ ( targets * : sources * : action-name : properties * )
{
action.__init__ $(targets) : $(sources) : $(action-name) : $(properties) ;
}
# For all virtual targets for the same dependency graph as self, i.e. which
# belong to the same main target, add their directories to the include path.
#
rule adjust-properties ( property-set )
{
local s = [ $(self.targets[1]).creating-subvariant ] ;
return [ $(property-set).add-raw
[ $(s).implicit-includes "include" : H ] ] ;
}
}
# Declare a special compiler generator. The only thing it does is changing the
# type used to represent 'action' in the constructed dependency graph to
# 'compile-action'. That class in turn adds additional include paths to handle
# cases when a source file includes headers which are generated themselves.
#
class C-compiling-generator : generator
{
rule __init__ ( id : source-types + : target-types + : requirements *
: optional-properties * )
{
generator.__init__ $(id) : $(source-types) : $(target-types) :
$(requirements) : $(optional-properties) ;
}
rule action-class ( )
{
return compile-action ;
}
}
rule register-c-compiler ( id : source-types + : target-types + : requirements *
: optional-properties * )
{
generators.register [ new C-compiling-generator $(id) : $(source-types) :
$(target-types) : $(requirements) : $(optional-properties) ] ;
}
# FIXME: this is ugly, should find a better way (we would like client code to
# register all generators as "generators.some-rule" instead of
# "some-module.some-rule".)
#
IMPORT $(__name__) : register-c-compiler : : generators.register-c-compiler ;
# The generator class for handling EXE and SHARED_LIB creation.
#
class linking-generator : generator
{
import path ;
import project ;
import property-set ;
import type ;
rule __init__ ( id
composing ? : # The generator will be composing if a non-empty
# string is passed or the parameter is not given. To
# make the generator non-composing, pass an empty
# string ("").
source-types + :
target-types + :
requirements * )
{
composing ?= true ;
generator.__init__ $(id) $(composing) : $(source-types)
: $(target-types) : $(requirements) ;
}
rule run ( project name ? : property-set : sources + )
{
sources += [ $(property-set).get <library> ] ;
# Add <library-path> properties for all searched libraries.
local extra ;
for local s in $(sources)
{
if [ $(s).type ] = SEARCHED_LIB
{
local search = [ $(s).search ] ;
extra += <library-path>$(search) ;
}
}
# It is possible that sources include shared libraries that did not came
# from 'lib' targets, e.g. .so files specified as sources. In this case
# we have to add extra dll-path properties and propagate extra xdll-path
# properties so that application linking to us will get xdll-path to
# those libraries.
local extra-xdll-paths ;
for local s in $(sources)
{
if [ type.is-derived [ $(s).type ] SHARED_LIB ] && ! [ $(s).action ]
{
# Unfortunately, we do not have a good way to find the path to a
# file, so use this nasty approach.
#
# TODO: This needs to be done better. One thing that is really
# broken with this is that it does not work correctly with
# projects having multiple source locations.
local p = [ $(s).project ] ;
local location = [ path.root [ $(s).name ]
[ $(p).get source-location ] ] ;
extra-xdll-paths += [ path.parent $(location) ] ;
}
}
# Hardcode DLL paths only when linking executables.
# Pros: do not need to relink libraries when installing.
# Cons: "standalone" libraries (plugins, python extensions) can not
# hardcode paths to dependent libraries.
if [ $(property-set).get <hardcode-dll-paths> ] = true
&& [ type.is-derived $(self.target-types[1]) EXE ]
{
local xdll-path = [ $(property-set).get <xdll-path> ] ;
extra += <dll-path>$(xdll-path) <dll-path>$(extra-xdll-paths) ;
}
if $(extra)
{
property-set = [ $(property-set).add-raw $(extra) ] ;
}
local result = [ generator.run $(project) $(name) : $(property-set)
: $(sources) ] ;
local ur ;
if $(result)
{
ur = [ extra-usage-requirements $(result) : $(property-set) ] ;
ur = [ $(ur).add
[ property-set.create <xdll-path>$(extra-xdll-paths) ] ] ;
}
return $(ur) $(result) ;
}
rule extra-usage-requirements ( created-targets * : property-set )
{
local result = [ property-set.empty ] ;
local extra ;
# Add appropricate <xdll-path> usage requirements.
local raw = [ $(property-set).raw ] ;
if <link>shared in $(raw)
{
local paths ;
local pwd = [ path.pwd ] ;
for local t in $(created-targets)
{
if [ type.is-derived [ $(t).type ] SHARED_LIB ]
{
paths += [ path.root [ path.make [ $(t).path ] ] $(pwd) ] ;
}
}
extra += $(paths:G=<xdll-path>) ;
}
# We need to pass <xdll-path> features that we've got from sources,
# because if a shared library is built, exe using it needs to know paths
# to other shared libraries this one depends on in order to be able to
# find them all at runtime.
# Just pass all features in property-set, it is theorically possible
# that we will propagate <xdll-path> features explicitly specified by
# the user, but then the user is to blaim for using an internal feature.
local values = [ $(property-set).get <xdll-path> ] ;
extra += $(values:G=<xdll-path>) ;
if $(extra)
{
result = [ property-set.create $(extra) ] ;
}
return $(result) ;
}
rule generated-targets ( sources + : property-set : project name ? )
{
local sources2 ; # Sources to pass to inherited rule.
local properties2 ; # Properties to pass to inherited rule.
local libraries ; # Library sources.
# Searched libraries are not passed as arguments to the linker but via
# some option. So, we pass them to the action using a property.
properties2 = [ $(property-set).raw ] ;
local fsa ;
local fst ;
for local s in $(sources)
{
if [ type.is-derived [ $(s).type ] SEARCHED_LIB ]
{
local name = [ $(s).name ] ;
if [ $(s).shared ]
{
fsa += $(name) ;
}
else
{
fst += $(name) ;
}
}
else
{
sources2 += $(s) ;
}
}
properties2 += <find-shared-library>$(fsa:J=&&)
<find-static-library>$(fst:J=&&) ;
return [ generator.generated-targets $(sources2)
: [ property-set.create $(properties2) ] : $(project) $(name) ] ;
}
}
rule register-linker ( id composing ? : source-types + : target-types +
: requirements * )
{
generators.register [ new linking-generator $(id) $(composing)
: $(source-types) : $(target-types) : $(requirements) ] ;
}
# The generator class for handling STATIC_LIB creation.
#
class archive-generator : generator
{
import property-set ;
rule __init__ ( id composing ? : source-types + : target-types +
: requirements * )
{
composing ?= true ;
generator.__init__ $(id) $(composing) : $(source-types)
: $(target-types) : $(requirements) ;
}
rule run ( project name ? : property-set : sources + )
{
sources += [ $(property-set).get <library> ] ;
local result = [ generator.run $(project) $(name) : $(property-set)
: $(sources) ] ;
# For static linking, if we get a library in source, we can not directly
# link to it so we need to cause our dependencies to link to that
# library. There are two approaches:
# - adding the library to the list of returned targets.
# - using the <library> usage requirements.
# The problem with the first is:
#
# lib a1 : : <file>liba1.a ;
# lib a2 : a2.cpp a1 : <link>static ;
# install dist : a2 ;
#
# here we will try to install 'a1', even though it is not necessary in
# the general case. With the second approach, even indirect dependants
# will link to the library, but it should not cause any harm. So, return
# all LIB sources together with created targets, so that dependants link
# to them.
local usage-requirements ;
if [ $(property-set).get <link> ] = static
{
for local t in $(sources)
{
if [ type.is-derived [ $(t).type ] LIB ]
{
usage-requirements += <library>$(t) ;
}
}
}
usage-requirements = [ property-set.create $(usage-requirements) ] ;
return $(usage-requirements) $(result) ;
}
}
rule register-archiver ( id composing ? : source-types + : target-types +
: requirements * )
{
generators.register [ new archive-generator $(id) $(composing)
: $(source-types) : $(target-types) : $(requirements) ] ;
}
# Generator that accepts everything and produces nothing. Useful as a general
# fallback for toolset-specific actions like PCH generation.
#
class dummy-generator : generator
{
import property-set ;
rule run ( project name ? : property-set : sources + )
{
return [ property-set.empty ] ;
}
}
IMPORT $(__name__) : register-linker register-archiver
: : generators.register-linker generators.register-archiver ;