📄 builtin.jam
字号:
{
errors.user-error "When several names are given to the 'lib' rule" :
"it's not allowed to specify sources. " ;
}
}
for local name in $(names)
{
local r = $(requirements) ;
if $(names[2])
{
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
# 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 * )
{
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 ;
}
a = [ new null-action $(property-set) ] ;
local t = [ new searched-lib-target $(name) : $(project) : $(shared)
: [ feature.get-values <name> : $(properties) ]
: [ feature.get-values <search> : $(properties) ]
: $(a)
] ;
# We return sources for a simple reason. If there's
# lib png : z : <name>png ;
# the 'z' target should be returned, so that apps linking to
# 'png' will link to 'z', too.
return [ virtual-target.register $(t) ] $(sources) ;
}
}
}
generators.register [ new searched-lib-generator ] ;
class prebuilt-lib-generator : generator
{
rule __init__ ( * : * )
{
generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
}
rule run ( project name ? : property-set : sources * )
{
local f = [ $(property-set).get <file> ] ;
return $(f) $(sources) ;
}
}
generators.register
[ new prebuilt-lib-generator builtin.prebuilt : : LIB : <file> ] ;
generators.override builtin.lib-generator : builtin.prebuilt ;
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 ( 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 a case
# when a source file includes headers which are generated themselfs.
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 ;
# The generator class for handling EXE and SHARED_LIB creation.
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 + )
{
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) ;
}
}
# Hardcode dll paths only when linking executables.
# Pros: don't need to relinking libraries when installing.
# Cons: "standalone" libraries (plugins, python extensions)
# can't 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> ] ;
# 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) ] ;
}
}
extra += <dll-path>$(xdll-path) ;
}
if $(extra)
{
property-set = [ $(property-set).add-raw $(extra) ] ;
}
local result = [ generator.run $(project) $(name) : $(property-set)
: $(sources) ] ;
return [ extra-usage-requirements $(result) : $(property-set) ]
$(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 shared library is built, exe which uses it must know paths
# to other shared libraries this one depends on, to be able to find them
# all at runtime.
# Just pass all features in property-set, it's theorically possible
# that we'll propagate <xdll-path> features explicitly specified by
# the user, but then the user's to blaim for using 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 ; # 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 ] SEARCHED_LIB ]
{
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) ;
}
# 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't
# 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'll try to install 'a1', even though it's not necessary in
# the general case.
# With the second approaches, even indirect dependents will link to
# the library, but it should not cause any harm.
# So, return all LIB sources together with created targets,
# so that dependents 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 * )
{
local g = [ new archive-generator $(id) $(composing) : $(source-types)
: $(target-types) : $(requirements) ] ;
generators.register $(g) ;
}
IMPORT $(__name__) : register-linker register-archiver
: : generators.register-linker generators.register-archiver ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -