mirror of
https://github.com/boostorg/build.git
synced 2026-02-16 13:22:11 +00:00
744 lines
24 KiB
Plaintext
744 lines
24 KiB
Plaintext
# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and
|
|
# distribute this software is granted provided this copyright notice appears in
|
|
# all copies. This software is provided "as is" without express or implied
|
|
# warranty, and with no claim as to its suitability for any purpose.
|
|
|
|
# Defines standard features and rules.
|
|
|
|
import "class" : new ;
|
|
|
|
import feature : feature compose ;
|
|
import toolset : flags ;
|
|
import errors : error ;
|
|
import type ;
|
|
import scanner ;
|
|
import generators ;
|
|
import regex ;
|
|
import virtual-target ;
|
|
import os ;
|
|
import prebuilt ;
|
|
import symlink ;
|
|
import alias ;
|
|
import property ;
|
|
import print ;
|
|
import utility ;
|
|
import project ;
|
|
|
|
# This feature is used to determine which OS we're on.
|
|
# In future, this may become <target-os> and <host-os>
|
|
local os = [ modules.peek : OS ] ;
|
|
feature os : $(os) : propagated link-incompatible ;
|
|
|
|
feature toolset : : implicit propagated symmetric ;
|
|
|
|
feature stdlib : native : propagated link-incompatible composite ;
|
|
|
|
feature link : shared static : propagated ;
|
|
feature link-runtime : shared static : propagated ;
|
|
feature runtime-debugging : on off : propagated ;
|
|
|
|
|
|
feature optimization : off speed space : propagated ;
|
|
feature profiling : off on : propagated ;
|
|
feature inlining : off on full : propagated ;
|
|
|
|
feature threading : single multi : propagated ;
|
|
feature rtti : on off : propagated ;
|
|
feature exception-handling : on off : propagated ;
|
|
feature debug-symbols : on off : propagated ;
|
|
feature define : : free ;
|
|
feature "include" : : free path ; #order-sensitive ;
|
|
feature cflags : : free ;
|
|
feature cxxflags : : free ;
|
|
feature linkflags : : free ;
|
|
feature archiveflags : : free ;
|
|
feature version : : free ;
|
|
|
|
feature.feature location-prefix : : free ;
|
|
|
|
# The following features are incidental, since
|
|
# in themself they have no effect on build products.
|
|
# Not making them incidental will result in problems in corner
|
|
# cases, for example:
|
|
#
|
|
# unit-test a : a.cpp : <use>b ;
|
|
# lib b : a.cpp b ;
|
|
#
|
|
# Here, if <use> is not incidental, we'll decide we have two
|
|
# targets for a.obj with different properties, and will complain.
|
|
#
|
|
# Note that making feature incidental does not mean it's ignored. It may
|
|
# be ignored when creating the virtual target, but the rest of build process
|
|
# will use them.
|
|
feature use : : free dependency incidental ;
|
|
feature dependency : : free dependency incidental ;
|
|
feature implicit-dependency : : free dependency incidental ;
|
|
|
|
feature source : : free dependency incidental ;
|
|
feature library : : free dependency incidental ;
|
|
feature find-shared-library : : free ; #order-sensitive ;
|
|
feature find-static-library : : free ; #order-sensitive ;
|
|
feature library-path : : free path ; #order-sensitive ;
|
|
# Internal feature.
|
|
feature library-file : : free dependency ;
|
|
|
|
feature name : : free ;
|
|
feature tag : : free ;
|
|
feature search : : free path ; #order-sensitive ;
|
|
feature location : : free path ;
|
|
|
|
feature dll-path : : free path ;
|
|
feature hardcode-dll-paths : false true : incidental propagated ;
|
|
|
|
|
|
# This is internal feature which holds the paths of all dependency
|
|
# dynamic libraries. On Windows, it's needed so that we can all
|
|
# those paths to PATH, when running applications.
|
|
# On Linux, it's needed to add proper -rpath-link command line options.
|
|
feature xdll-path : : free path ;
|
|
|
|
#provides means to specify def-file for windows dlls.
|
|
feature def-file : : free dependency ;
|
|
|
|
# This feature is used to allow specific generators to run.
|
|
# For example, QT tools can only be invoked when QT library
|
|
# is used. In that case, <allow>qt will be in usage requirement
|
|
# of the library.
|
|
feature allow : : free ;
|
|
|
|
# Windows-specific features
|
|
|
|
feature user-interface : console gui wince native auto ;
|
|
|
|
feature variant : : implicit composite propagated symmetric ;
|
|
|
|
# Declares a new variant.
|
|
# First determines explicit properties for this variant, by
|
|
# refining parents' explicit properties with the passed explicit
|
|
# properties. The result is remembered and will be used if
|
|
# this variant is used as parent.
|
|
#
|
|
# Second, determines the full property set for this variant by
|
|
# adding to the explicit properties default values for all properties
|
|
# which neither present nor are symmetric.
|
|
#
|
|
# Lastly, makes appropriate value of 'variant' property expand
|
|
# to the full property set.
|
|
rule variant ( name # Name of the variant
|
|
: parents-or-properties * # Specifies parent variants, if
|
|
# 'explicit-properties' are given,
|
|
# and explicit-properties otherwise.
|
|
: explicit-properties * # Explicit properties.
|
|
)
|
|
{
|
|
local parents ;
|
|
if ! $(explicit-properties)
|
|
{
|
|
if $(parents-or-properties[1]:G)
|
|
{
|
|
explicit-properties = $(parents-or-properties) ;
|
|
}
|
|
else
|
|
{
|
|
parents = $(parents-or-properties) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
parents = $(parents-or-properties) ;
|
|
}
|
|
|
|
# The problem is that we have to check for conflicts
|
|
# between base variants.
|
|
if $(parents[2])
|
|
{
|
|
error "multiple base variants are not yet supported" ;
|
|
}
|
|
|
|
local inherited ;
|
|
# Add explicitly specified properties for parents
|
|
for local p in $(parents)
|
|
{
|
|
# TODO: the check may be sticter
|
|
if ! [ feature.is-implicit-value $(p) ]
|
|
{
|
|
error "Invalid base varaint" $(p) ;
|
|
}
|
|
|
|
inherited += $(.explicit-properties.$(p)) ;
|
|
}
|
|
property.validate $(explicit-properties) ;
|
|
explicit-properties = [ property.refine $(inherited) : $(explicit-properties) ] ;
|
|
|
|
# Record explicitly specified properties for this variant
|
|
# We do this after inheriting parents' properties, so that
|
|
# they affect other variants, derived from this one.
|
|
.explicit-properties.$(name) = $(explicit-properties) ;
|
|
|
|
feature.extend variant : $(name) ;
|
|
feature.compose <variant>$(name) : $(explicit-properties) ;
|
|
}
|
|
IMPORT $(__name__) : variant : : variant ;
|
|
|
|
variant debug : <optimization>off <debug-symbols>on <inlining>off <runtime-debugging>on ;
|
|
variant release : <optimization>speed <debug-symbols>off <inlining>full
|
|
<runtime-debugging>off <define>NDEBUG ;
|
|
variant profile : release : <profiling>on <debug-symbols>on ;
|
|
|
|
class searched-lib-target : abstract-file-target
|
|
{
|
|
rule __init__ ( name
|
|
: project
|
|
: shared ?
|
|
: real-name ?
|
|
: search *
|
|
)
|
|
{
|
|
abstract-file-target.__init__ $(name) : SEARCHED_LIB : $(project) ;
|
|
|
|
self.shared = $(shared) ;
|
|
self.real-name = $(real-name) ;
|
|
self.real-name ?= $(name) ;
|
|
self.search = $(search) ;
|
|
}
|
|
|
|
|
|
rule shared ( )
|
|
{
|
|
return $(self.shared) ;
|
|
}
|
|
|
|
rule real-name ( )
|
|
{
|
|
return $(self.real-name) ;
|
|
}
|
|
|
|
rule search ( )
|
|
{
|
|
return $(self.search) ;
|
|
}
|
|
|
|
rule actualize-location ( target )
|
|
{
|
|
NOTFILE $(target) ;
|
|
}
|
|
|
|
rule path ( )
|
|
{
|
|
}
|
|
}
|
|
|
|
type.register LIB : : : main ;
|
|
|
|
# register the given type on the specified OSes, or on remaining OSes
|
|
# if os is not specified.
|
|
local rule declare-type ( os * : type : suffixes * : base-type ? : main ? )
|
|
{
|
|
if ! [ type.registered $(type) ]
|
|
{
|
|
if ( ! $(os) ) || [ os.name ] in $(os)
|
|
{
|
|
type.register $(type) : $(suffixes) : $(base-type) : $(main) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
#
|
|
# Common target types.
|
|
#
|
|
|
|
declare-type NT CYGWIN : OBJ : obj : : main ;
|
|
declare-type : OBJ : o : : main ;
|
|
|
|
declare-type NT CYGWIN : STATIC_LIB : lib a : LIB : main ;
|
|
declare-type : STATIC_LIB : a : LIB : main ;
|
|
|
|
declare-type : IMPORT_LIB : : STATIC_LIB : main ;
|
|
type.set-generated-target-suffix IMPORT_LIB : : lib ;
|
|
|
|
declare-type NT CYGWIN : SHARED_LIB : dll : LIB : main ;
|
|
declare-type : SHARED_LIB : so : LIB : main ;
|
|
|
|
declare-type : SEARCHED_LIB : : LIB : main ;
|
|
|
|
declare-type NT CYGWIN : EXE : exe : : ;
|
|
declare-type : EXE : : : ;
|
|
|
|
declare-type : PYTHON_EXTENSION : : SHARED_LIB : main ;
|
|
# We can't give "dll" suffix to PYTHON_EXTENSION, because
|
|
# we would not know what "a.dll" is: python extenstion or
|
|
# ordinary library. Therefore, we specify only suffixes
|
|
# used for generation of targets.
|
|
type.set-generated-target-suffix PYTHON_EXTENSION : : so ;
|
|
type.set-generated-target-suffix PYTHON_EXTENSION : <os>NT : so ;
|
|
type.set-generated-target-suffix PYTHON_EXTENSION : <os>CYGWIN : dll ;
|
|
|
|
type.register CPP : cpp cxx cc ;
|
|
|
|
import stage ;
|
|
|
|
|
|
class c-scanner : scanner
|
|
{
|
|
import regex virtual-target path scanner ;
|
|
|
|
rule __init__ ( includes * )
|
|
{
|
|
scanner.__init__ ;
|
|
|
|
self.includes = $(includes) ;
|
|
}
|
|
|
|
rule pattern ( )
|
|
{
|
|
return "#[ \t]*include[ ]*(<(.*)>|\"(.*)\")" ;
|
|
}
|
|
|
|
rule process ( target : matches * : binding )
|
|
{
|
|
local angle = [ regex.transform $(matches) : "<(.*)>" ] ;
|
|
local quoted = [ regex.transform $(matches) : "\"(.*)\"" ] ;
|
|
|
|
# CONSIDER: the new scoping rule seem to defeat "on target" variables.
|
|
local g = [ on $(target) return $(HDRGRIST) ] ;
|
|
local b = [ NORMALIZE_PATH $(binding:D) ] ;
|
|
|
|
# Attach binding of including file to included targets.
|
|
# When target is directly created from virtual target
|
|
# this extra information is unnecessary. But in other
|
|
# cases, it allows to distinguish between two headers of the
|
|
# same name included from different places.
|
|
# We don't need this extra information for angle includes,
|
|
# since they should not depend on including file (we can't
|
|
# get literal "." in include path).
|
|
local g2 = $(g)"#"$(b) ;
|
|
|
|
angle = $(angle:G=$(g)) ;
|
|
quoted = $(quoted:G=$(g2)) ;
|
|
|
|
local all = $(angle) $(quoted) ;
|
|
|
|
INCLUDES $(target) : $(all) ;
|
|
NOCARE $(all) ;
|
|
SEARCH on $(angle) = $(self.includes:G=) ;
|
|
SEARCH on $(quoted) = $(b) $(self.includes:G=) ;
|
|
|
|
# Just propagate current scanner to includes, in a hope
|
|
# that includes do not change scanners.
|
|
scanner.propagate $(__name__) : $(angle) $(quoted) : $(target) ;
|
|
}
|
|
}
|
|
|
|
scanner.register c-scanner : include ;
|
|
|
|
type.set-scanner CPP : c-scanner ;
|
|
|
|
|
|
type.register H : h ;
|
|
type.register HPP : hpp : H ;
|
|
type.register C : c ;
|
|
|
|
class lib-target-class : basic-target
|
|
{
|
|
import generators : construct : generators.construct ;
|
|
import type ;
|
|
import path ;
|
|
|
|
rule __init__ ( name : project
|
|
: sources * : requirements * : default-build * : usage-requirements * )
|
|
{
|
|
basic-target.__init__ $(name) : $(project)
|
|
: $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ;
|
|
}
|
|
|
|
rule construct ( source-targets * : property-set )
|
|
{
|
|
local properties = [ $(property-set).raw ] ;
|
|
# Determine the needed target type
|
|
local actual-type ;
|
|
if <search> in $(properties:G) || <name> in $(properties:G)
|
|
{
|
|
actual-type = SEARCHED_LIB ;
|
|
}
|
|
else if <link>shared in $(properties)
|
|
{
|
|
actual-type = SHARED_LIB ;
|
|
}
|
|
else
|
|
{
|
|
actual-type = STATIC_LIB ;
|
|
}
|
|
property-set = [ $(property-set).add-raw <main-target-type>LIB ] ;
|
|
# Construct the target.
|
|
return [ generators.construct $(self.project) $(self.name) : $(actual-type)
|
|
: $(property-set) : $(source-targets) : LIB ] ;
|
|
}
|
|
|
|
rule compute-usage-requirements ( subvariant )
|
|
{
|
|
local rproperties = [ $(subvariant).build-properties ] ;
|
|
local created-targets = [ $(subvariant).created-targets ] ;
|
|
local result = [ basic-target.compute-usage-requirements $(subvariant) ] ;
|
|
|
|
# For lib targets with <search>, add the value of <search> as <library-path>
|
|
# usage requirement.
|
|
local search = [ $(rproperties).get <search> ] ;
|
|
if $(search)
|
|
{
|
|
result = [ $(result).add [
|
|
property-set.create $(search:G=<library-path>) ] ] ;
|
|
}
|
|
|
|
# Add appropricate <xdll-path> usage requirements.
|
|
local raw = [ $(rproperties).raw ] ;
|
|
if <link>shared in $(raw)
|
|
{
|
|
local paths ;
|
|
local pwd = [ path.pwd ] ;
|
|
for local t in $(created-targets)
|
|
{
|
|
if [ type.is-derived [ $(t).type ] SHARED_LIB ]
|
|
{
|
|
paths += [ path.root [ path.make [ $(t).path ] ] $(pwd) ] ;
|
|
}
|
|
}
|
|
if $(paths)
|
|
{
|
|
result = [ $(result).add
|
|
[ property-set.create $(paths:G=<xdll-path>) ] ] ;
|
|
}
|
|
}
|
|
|
|
# Pass <xdll-path> features that we've got from sources.
|
|
local u = [ $(subvariant).sources-usage-requirements ] ;
|
|
local values = [ $(u).get <xdll-path> ] ;
|
|
result = [ $(result).add-raw $(values:G=<xdll-path>) ] ;
|
|
|
|
# For libraries that we've failed to consume, we need to
|
|
# pass <library-path> usage requirements, if any.
|
|
# We look at all generated target, and if they are created in different
|
|
# subvariant, we add usage requirements.
|
|
for local t in [ $(subvariant).created-targets ]
|
|
{
|
|
local s = [ $(t).creating-subvariant ] ;
|
|
if $(s) != $(subvariant)
|
|
{
|
|
result = [ $(result).add [ $(s).usage-requirements ] ] ;
|
|
}
|
|
}
|
|
|
|
return $(result) ;
|
|
}
|
|
}
|
|
|
|
rule lib ( names + : sources * : requirements * : default-build *
|
|
: usage-requirements * )
|
|
{
|
|
local project = [ project.current ] ;
|
|
|
|
# This is a circular module dependency, so it must be imported here
|
|
import targets ;
|
|
|
|
local result ;
|
|
if $(sources) || <name> in $(requirements:G)
|
|
{
|
|
if $(names[2])
|
|
{
|
|
errors.user-error "When several names are given to the 'lib' rule" :
|
|
"it's not allows to specify either sources or <name> property " ;
|
|
}
|
|
|
|
local name = $(names[1]) ;
|
|
result = [ targets.main-target-alternative
|
|
[ new lib-target-class $(name) : $(project)
|
|
: [ targets.main-target-sources $(sources) : $(name) ]
|
|
: [ targets.main-target-requirements $(requirements) : $(project) ]
|
|
: [ targets.main-target-default-build $(default-build) : $(project) ]
|
|
: [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
|
|
] ] ;
|
|
}
|
|
else
|
|
{
|
|
for local name in $(names)
|
|
{
|
|
result += [
|
|
targets.main-target-alternative
|
|
[ new lib-target-class $(name) : $(project)
|
|
:
|
|
: [ targets.main-target-requirements $(requirements) <name>$(name) :
|
|
$(project) ]
|
|
: [ targets.main-target-default-build $(default-build) : $(project) ]
|
|
: [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
|
|
] ] ;
|
|
}
|
|
}
|
|
return $(result) ;
|
|
}
|
|
IMPORT $(__name__) : lib : : lib ;
|
|
|
|
|
|
class exe-target-class : typed-target
|
|
{
|
|
import type ;
|
|
|
|
rule __init__ ( name : project
|
|
: sources * : requirements * : default-build * : usage-requirements * )
|
|
{
|
|
typed-target.__init__ $(name) : $(project) : EXE
|
|
: $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ;
|
|
}
|
|
|
|
rule compute-usage-requirements ( subvariant )
|
|
{
|
|
local result = [ typed-target.compute-usage-requirements $(subvariant) ] ;
|
|
local p = [ $(subvariant).build-properties ] ;
|
|
|
|
local xdll-paths = [ $(p).get <xdll-path> ] ;
|
|
if $(xdll-paths)
|
|
{
|
|
result = [ $(result).add-raw $(xdll-paths:G=<xdll-path>) ] ;
|
|
}
|
|
|
|
return $(result) ;
|
|
}
|
|
|
|
rule check-for-unused-sources ( result * : sources * )
|
|
{
|
|
# For exes, we typically don't consume ignore DLL on windows.
|
|
# We also handle searched libraries via special properties
|
|
# on actions, so should not check for search libraries.
|
|
# As the result, we don't check for unused LIB sources
|
|
# at all.
|
|
|
|
local sources-to-check ;
|
|
for local s in $(sources)
|
|
{
|
|
if ! [ type.is-derived [ $(s).type ] LIB ]
|
|
{
|
|
sources-to-check += $(s) ;
|
|
}
|
|
}
|
|
basic-target.check-for-unused-sources $(result) : $(sources-to-check) ;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
rule exe ( name : sources * : requirements * : default-build *
|
|
: usage-requirements * )
|
|
{
|
|
local project = [ project.current ] ;
|
|
|
|
# This is a circular module dependency, so it must be imported here
|
|
import targets ;
|
|
targets.main-target-alternative
|
|
[ new exe-target-class $(name) : $(project)
|
|
: [ targets.main-target-sources $(sources) : $(name) ]
|
|
: [ targets.main-target-requirements $(requirements) : $(project) ]
|
|
: [ targets.main-target-default-build $(default-build) : $(project) ]
|
|
: [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
|
|
] ;
|
|
}
|
|
IMPORT $(__name__) : exe : : exe ;
|
|
|
|
|
|
|
|
class searched-lib-generator : generator
|
|
{
|
|
rule __init__ ( )
|
|
{
|
|
# The requirements cause the generators to be tried *only* when we're building
|
|
# lib target and there's 'search' feature. This seems ugly --- all we want
|
|
# is make sure searched-lib-generator is not invoced deep in transformation
|
|
# search.
|
|
generator.__init__ searched-lib-generator : : SEARCHED_LIB ;
|
|
}
|
|
|
|
rule run ( project name ? : property-set : sources * : multiple ? )
|
|
{
|
|
if $(name)
|
|
{
|
|
# If name is empty, it means we're called not from top-level.
|
|
# In this case, we just fail immediately, because searched-lib-generator
|
|
# cannot be used to produce intermediate targets.
|
|
|
|
local properties = [ $(property-set).raw ] ;
|
|
local shared ;
|
|
if <link>shared in $(properties)
|
|
{
|
|
shared = true ;
|
|
}
|
|
|
|
local t = [ new searched-lib-target $(name) : $(project) : $(shared)
|
|
: [ feature.get-values <name> : $(properties) ]
|
|
: [ feature.get-values <search> : $(properties) ]
|
|
] ;
|
|
# attach an action and properties to the target
|
|
a = [ new null-action $(t) : $(property-set) ] ;
|
|
$(t).action $(a) ;
|
|
return [ virtual-target.register $(t) ] ;
|
|
}
|
|
}
|
|
}
|
|
|
|
generators.register [ new searched-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 include path.
|
|
rule adjust-properties ( properties * )
|
|
{
|
|
local s = [ $(self.targets[1]).creating-subvariant ] ;
|
|
return $(properties) [ $(s).implicit-includes "include" : H ] ;
|
|
}
|
|
}
|
|
|
|
class C-compiling-generator : generator
|
|
{
|
|
rule __init__ ( id : source-types + : target-types + :
|
|
requirements * : optional-properties * )
|
|
{
|
|
generator.__init__ $(id) : $(source-types) : $(target-types) :
|
|
$(requirements) : $(optional-properties) ;
|
|
}
|
|
|
|
rule action-class ( )
|
|
{
|
|
return compile-action ;
|
|
}
|
|
}
|
|
|
|
rule register-c-compiler ( id : source-types + : target-types + :
|
|
requirements * : optional-properties * )
|
|
{
|
|
local g = [ new C-compiling-generator $(id) : $(source-types)
|
|
: $(target-types) : $(requirements) : $(optional-properties) ] ;
|
|
generators.register $(g) ;
|
|
}
|
|
|
|
# FIXME: this is ugly, should find a better way (we'd want client code to
|
|
# register all generators as "generator.some-rule", not with "some-module.some-rule".)
|
|
IMPORT $(__name__) : register-c-compiler : : generators.register-c-compiler ;
|
|
|
|
class linking-generator : generator
|
|
{
|
|
import property-set ;
|
|
import type ;
|
|
import path ;
|
|
import project ;
|
|
|
|
rule __init__ ( id
|
|
composing ? : # Specify if generator is composing. The generator will be
|
|
# composing if non-empty string is passed, or parameter is
|
|
# not given. To make generator non-composing, pass empty
|
|
# string ("")
|
|
source-types + : target-types + :
|
|
requirements * )
|
|
{
|
|
composing ?= true ;
|
|
generator.__init__ $(id) $(composing) : $(source-types) : $(target-types) :
|
|
$(requirements) ;
|
|
}
|
|
|
|
rule run ( project name ? : property-set : sources + : multiple ? )
|
|
{
|
|
if [ $(property-set).get <hardcode-dll-paths> ] = true
|
|
{
|
|
local xdll-path = [ $(property-set).get <xdll-path> ] ;
|
|
# It's possible that we have libraries in sources which did not came
|
|
# from 'lib' target. For example, libraries which are specified
|
|
# just as filenames as sources. We don't have xdll-path properties
|
|
# for such target, but still need to add proper dll-path properties.
|
|
for local s in $(sources)
|
|
{
|
|
if [ type.is-derived [ $(s).type ] SHARED_LIB ] && ! [ $(s).action ]
|
|
{
|
|
# Unfortunately, we don't have a good way to find the path
|
|
# to a file, so use this nasty approach.
|
|
local p = [ $(s).project ] ;
|
|
local location = [ path.root [ $(s).name ]
|
|
[ $(p).get source-location ] ] ;
|
|
xdll-path += [ path.parent $(location) ] ;
|
|
}
|
|
}
|
|
|
|
if $(xdll-path)
|
|
{
|
|
property-set = [ $(property-set).add-raw $(xdll-path:G=<dll-path>) ] ;
|
|
}
|
|
|
|
}
|
|
|
|
local result = [ generator.run $(project) $(name) : $(property-set)
|
|
: $(sources) : $(multiple) ] ;
|
|
|
|
return $(result) ;
|
|
}
|
|
|
|
rule generated-targets ( sources + : property-set : project name ? )
|
|
{
|
|
local sources2 ; # sources to pass to inherited rule
|
|
local properties2 ; # properties to pass to inherited rule
|
|
local libraries ; # sources which are libraries
|
|
|
|
# Searched libraries are not passed as argument to linker
|
|
# but via some option. So, we pass them to the action
|
|
# via property.
|
|
properties2 = [ $(property-set).raw ] ;
|
|
local fsa ;
|
|
local fst ;
|
|
for local s in $(sources)
|
|
{
|
|
if [ type.is-derived [ $(s).type ] LIB ] &&
|
|
[ class.is-a $(s) : searched-lib-target ]
|
|
{
|
|
local name = [ $(s).real-name ] ;
|
|
if [ $(s).shared ]
|
|
{
|
|
fsa += $(name) ;
|
|
}
|
|
else
|
|
{
|
|
fst += $(name) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sources2 += $(s) ;
|
|
}
|
|
}
|
|
properties2 += <find-shared-library>$(fsa:J=&&)
|
|
<find-static-library>$(fst:J=&&) ;
|
|
|
|
local spawn = [ generator.generated-targets $(sources2)
|
|
: [ property-set.create $(properties2) ] : $(project) $(name) ] ;
|
|
|
|
return $(spawn) ;
|
|
}
|
|
}
|
|
|
|
rule register-linker ( id composing ? : source-types + : target-types + :
|
|
requirements * )
|
|
{
|
|
local g = [ new linking-generator $(id) $(composing) : $(source-types)
|
|
: $(target-types) : $(requirements) ] ;
|
|
generators.register $(g) ;
|
|
}
|
|
|
|
IMPORT $(__name__) : register-linker : : generators.register-linker ;
|
|
|
|
declare-type : RSP : rsp ;
|
|
|
|
|