Skip to content

Commit

Permalink
Refactor the built-in generators into independent generator files.
Browse files Browse the repository at this point in the history
  • Loading branch information
grafikrobot committed Aug 24, 2017
1 parent b487b1b commit f9c88a6
Show file tree
Hide file tree
Showing 10 changed files with 621 additions and 541 deletions.
540 changes: 5 additions & 535 deletions src/tools/builtin.jam

Large diffs are not rendered by default.

Expand Up @@ -3,19 +3,21 @@
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

# Here we automatically define any feature modules in this directory.
# Here we automatically define any "feature" modules in this directory.

local key = feature ;

import os path modules ;

.this-module's-file = [ modules.binding $(__name__) ] ;
.this-module's-dir = [ path.parent [ path.make $(.this-module's-file) ] ] ;
.feature-jamfiles = [ path.glob $(.this-module's-dir) : *-feature.jam ] ;
.feature-modules = [ MATCH ^(.*)\.jam$ : $(.feature-jamfiles) ] ;
.to-load-jamfiles = [ path.glob $(.this-module's-dir) : *-$(key).jam ] ;
.to-load-modules = [ MATCH ^(.*)\.jam$ : $(.to-load-jamfiles) ] ;

# A loop over all feature modules in this directory
for local m in $(.feature-modules)
# A loop over all matched modules in this directory
for local m in $(.to-load-modules)
{
m = [ path.basename $(m) ] ;
m = features/$(m) ;
m = $(key)s/$(m) ;
import $(m) ;
}
23 changes: 23 additions & 0 deletions src/tools/generators/__init_generators__.jam
@@ -0,0 +1,23 @@
# Copyright 2017 Rene Rivera
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

# Here we automatically define any "generator" modules in this directory.

local key = generator ;

import os path modules ;

.this-module's-file = [ modules.binding $(__name__) ] ;
.this-module's-dir = [ path.parent [ path.make $(.this-module's-file) ] ] ;
.to-load-jamfiles = [ path.glob $(.this-module's-dir) : *-$(key).jam ] ;
.to-load-modules = [ MATCH ^(.*)\.jam$ : $(.to-load-jamfiles) ] ;

# A loop over all matched modules in this directory
for local m in $(.to-load-modules)
{
m = [ path.basename $(m) ] ;
m = $(key)s/$(m) ;
import $(m) ;
}
73 changes: 73 additions & 0 deletions src/tools/generators/archive-generator.jam
@@ -0,0 +1,73 @@
# Copyright 2002-2017 Rene Rivera
# Copyright 2002-2017 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

import "class" : new ;
import generators ;

# 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) ] ;
}

IMPORT $(__name__) : register-archiver : : generators.register-archiver ;
70 changes: 70 additions & 0 deletions src/tools/generators/c-compiling-generator.jam
@@ -0,0 +1,70 @@
# Copyright 2002-2017 Rene Rivera
# Copyright 2002-2017 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

import "class" : new ;
import generators ;
import virtual-target ;

# 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 ;

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 ] ;
if $(s)
{
return [ $(property-set).add-raw
[ $(s).implicit-includes "include" : H ] ] ;
}
else
{
return $(property-set) ;
}
}
}
20 changes: 20 additions & 0 deletions src/tools/generators/dummy-generator.jam
@@ -0,0 +1,20 @@
# Copyright 2002-2017 Rene Rivera
# Copyright 2002-2017 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

import generators ;

# 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 ] ;
}
}
115 changes: 115 additions & 0 deletions src/tools/generators/lib-generator.jam
@@ -0,0 +1,115 @@
# Copyright 2002-2017 Rene Rivera
# Copyright 2002-2017 Vladimir Prus
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

import "class" : new ;
import generators ;
import project ;
import targets ;

# 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) : $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : $(16) :
$(17) : $(18) : $(19) ;
}

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 ;

0 comments on commit f9c88a6

Please sign in to comment.