mirror of
https://github.com/boostorg/build.git
synced 2026-02-14 00:32:11 +00:00
Can now fully specify modular libs externally. Only tested for building
Boost System and Filesystem.
This commit is contained in:
@@ -3,108 +3,11 @@
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#alias library
|
||||
# :
|
||||
# : : : <include>include
|
||||
# ;
|
||||
|
||||
import path ;
|
||||
import project ;
|
||||
import modules ;
|
||||
import regex ;
|
||||
|
||||
rule find ( target-refs + )
|
||||
{
|
||||
process-args ;
|
||||
|
||||
local caller-mod = [ CALLER_MODULE ] ;
|
||||
local caller-dir = [ modules.peek $(caller-mod) : __file__ ] ;
|
||||
caller-dir = $(caller-dir:D) ;
|
||||
caller-dir = [ path.root $(caller-dir) [ path.pwd ] ] ;
|
||||
|
||||
for local target-ref in $(target-refs)
|
||||
{
|
||||
local ref = [ MATCH ^(.*)//.* : $(target-ref:G=) ] ;
|
||||
local search-prefix ;
|
||||
local search-sub ;
|
||||
for local prefix in $(.search-path-prefix)
|
||||
{
|
||||
if ! $(search-prefix)
|
||||
{
|
||||
local search-match = [ MATCH ^($(prefix))/(.*)$ : $(ref) ] ;
|
||||
search-prefix = $(search-match[1]) ;
|
||||
search-sub = $(search-match[2]) ;
|
||||
}
|
||||
}
|
||||
local found = [ path.glob $(.search-path.$(search-prefix)) : $(search-sub) ] ;
|
||||
found = $(found[1]) ;
|
||||
if $(found)
|
||||
{
|
||||
local lib-ref = [ regex.split $(search-sub) / ] ;
|
||||
lib-ref = $(search-prefix)/$(lib-ref[1]) ;
|
||||
local lib-path = [ path.relative-to $(caller-dir) $(found) ] ;
|
||||
library $(lib-ref) $(caller-mod) : $(lib-path) ;
|
||||
}
|
||||
}
|
||||
|
||||
return $(target-refs) ;
|
||||
}
|
||||
|
||||
rule library ( name caller-module ? : root )
|
||||
{
|
||||
process-args ;
|
||||
|
||||
# Dir path of caller to base paths from.
|
||||
caller-module ?= [ CALLER_MODULE ] ;
|
||||
local caller-dir = [ modules.peek $(caller-module) : __file__ ] ;
|
||||
caller-dir = $(caller-dir:D) ;
|
||||
|
||||
# Find the various parts of the library.
|
||||
local lib-dir = [ path.root [ path.root $(root) $(caller-dir) ] [ path.pwd ] ] ;
|
||||
local lib-contents = [ path.glob $(lib-dir) : "include" "build" ] ;
|
||||
lib-contents = $(lib-contents:D=) ;
|
||||
# "include" dir for library..
|
||||
local include-dir ;
|
||||
if "include" in $(lib-contents)
|
||||
{
|
||||
include-dir = include ;
|
||||
}
|
||||
|
||||
# Does it look like a library?
|
||||
if $(include-dir)
|
||||
{
|
||||
# Load/create/declare library project.
|
||||
local lib-module = [ project.find $(root) : $(caller-dir) ] ;
|
||||
if ! $(lib-module)
|
||||
{
|
||||
lib-module = [ project.load
|
||||
[ path.root [ path.make $(root) ] $(caller-dir) ] : synthesize ] ;
|
||||
}
|
||||
local lib-target = [ project.target $(lib-module) ] ;
|
||||
|
||||
# We move to the library project module to define the various
|
||||
# targets others use for the library.
|
||||
if ! [ modules.peek $(lib-module) : __library__ ]
|
||||
{
|
||||
modules.poke $(lib-module) : __library__ : $(name) ;
|
||||
project.push-current $(lib-target) ;
|
||||
|
||||
# Declare the library alias.
|
||||
modules.call-in $(lib-module) : alias library
|
||||
: # Sources
|
||||
: # Requirements
|
||||
: # Default Build
|
||||
: # Usage Requirements
|
||||
<include>$(include-dir)
|
||||
;
|
||||
|
||||
project.pop-current ;
|
||||
}
|
||||
|
||||
# Declare project alternate ID.
|
||||
modules.call-in $(caller-module) : use-project $(name) : $(root) ;
|
||||
}
|
||||
}
|
||||
import type ;
|
||||
|
||||
# Add a location, i.e. directory, where to search for libraries.
|
||||
# The optional 'prefix' indicates which rooted-prefixes the new
|
||||
@@ -126,6 +29,167 @@ rule add-location ( dir prefix ? : base-dir ? )
|
||||
.search-path.$(prefix) += [ path.root [ path.root $(dir) $(base-dir) ] [ path.pwd ] ] ;
|
||||
}
|
||||
|
||||
# Declares additional definitions of a modular library target external
|
||||
# to the modular library build itself. This makes it possible to externally
|
||||
# define modular libraries without modifying the library. The passed in
|
||||
# values are added on demand when the named library is first declared.
|
||||
rule external (
|
||||
name : sources * : requirements * : default-build * :
|
||||
usage-requirements * )
|
||||
{
|
||||
.external.($(name)).sources = $(sources) ;
|
||||
.external.($(name)).requirements = $(requirements) ;
|
||||
.external.($(name)).default-build = $(default-build) ;
|
||||
.external.($(name)).usage-requirements = $(usage-requirements) ;
|
||||
}
|
||||
|
||||
# Find, and declare, any modular libraries referenced in the target-refs.
|
||||
# This will both load the modular libraries, and declare/manufacture
|
||||
# the modular libraries as needed.
|
||||
rule find ( target-refs + )
|
||||
{
|
||||
process-args ;
|
||||
|
||||
local caller-mod = [ CALLER_MODULE ] ;
|
||||
local caller-dir = [ modules.peek $(caller-mod) : __file__ ] ;
|
||||
caller-dir = $(caller-dir:D) ;
|
||||
caller-dir = [ path.root $(caller-dir) [ path.pwd ] ] ;
|
||||
|
||||
local result-refs ;
|
||||
for local target-ref in $(target-refs)
|
||||
{
|
||||
result-refs += [ resolve-reference $(target-ref)
|
||||
: $(caller-mod) $(caller-dir) ] ;
|
||||
}
|
||||
|
||||
return $(result-refs) ;
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
|
||||
local rule resolve-reference ( target-ref : caller-mod caller-dir ? )
|
||||
{
|
||||
# ECHO %%% modular.resolve-target-ref $(target-ref) :: $(caller-mod) $(caller-dir) ;
|
||||
if ! $(caller-dir)
|
||||
{
|
||||
caller-dir = [ modules.peek $(caller-mod) : __file__ ] ;
|
||||
caller-dir = $(caller-dir:D) ;
|
||||
caller-dir = [ path.root $(caller-dir) [ path.pwd ] ] ;
|
||||
}
|
||||
local result-ref = $(target-ref) ;
|
||||
local ref = [ MATCH ^(.*)//.* : $(target-ref:G=) ] ;
|
||||
# if ! ( $(ref) in $(.target-refs) )
|
||||
{
|
||||
# .target-refs += $(ref) ;
|
||||
local search-prefix ;
|
||||
local search-sub ;
|
||||
for local prefix in $(.search-path-prefix)
|
||||
{
|
||||
if ! $(search-prefix)
|
||||
{
|
||||
local search-match = [ MATCH ^($(prefix))/(.*)$ : $(ref) ] ;
|
||||
search-prefix = $(search-match[1]) ;
|
||||
search-sub = $(search-match[2]) ;
|
||||
}
|
||||
}
|
||||
|
||||
if $(search-prefix)
|
||||
{
|
||||
local found = [ path.glob $(.search-path.$(search-prefix)) : $(search-sub) ] ;
|
||||
found = $(found[1]) ;
|
||||
if $(found)
|
||||
{
|
||||
local lib-ref = [ regex.split $(search-sub) / ] ;
|
||||
lib-ref = $(search-prefix)/$(lib-ref[1]) ;
|
||||
local lib-path = [ path.relative-to $(caller-dir) $(found) ] ;
|
||||
define-library $(lib-ref) $(caller-mod) : $(lib-path) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $(result-ref) ;
|
||||
}
|
||||
|
||||
local rule define-library ( name caller-module ? : root )
|
||||
{
|
||||
# ECHO ~~~ modular.library $(name) $(caller-module) :: $(root) :: $(depends) ;
|
||||
|
||||
process-args ;
|
||||
|
||||
# Dir path of caller to base paths from.
|
||||
caller-module ?= [ CALLER_MODULE ] ;
|
||||
local caller-dir = [ modules.peek $(caller-module) : __file__ ] ;
|
||||
caller-dir = $(caller-dir:D) ;
|
||||
|
||||
# Find the various parts of the library.
|
||||
local lib-dir = [ path.root [ path.root $(root) $(caller-dir) ] [ path.pwd ] ] ;
|
||||
local lib-contents = [ path.glob $(lib-dir) : "include" "build" ] ;
|
||||
lib-contents = $(lib-contents:D=) ;
|
||||
|
||||
# "include" dir for library..
|
||||
local include-dir ;
|
||||
if "include" in $(lib-contents)
|
||||
{
|
||||
include-dir = $(root)/include ;
|
||||
}
|
||||
|
||||
# If it has a build dir, i.e. it has targets to build,
|
||||
# we root the project at the build dir to make it easy
|
||||
# to refer to the build targets. This mirrors the regular
|
||||
# Boost organization of the project aliases.
|
||||
if "build" in $(lib-contents)
|
||||
{
|
||||
root = $(root)/build ;
|
||||
build-dir = "." ;
|
||||
}
|
||||
|
||||
# Shadow target declarations so that we can alter build targets
|
||||
# to work in the standalone modular structure.
|
||||
local lib-location = [ path.root [ path.make $(root) ] $(caller-dir) ] ;
|
||||
local lib-module-name = [ project.module-name $(lib-location) ] ;
|
||||
local modular-rules = [ RULENAMES modular-rules ] ;
|
||||
IMPORT modular-rules : $(modular-rules) : $(lib-module-name) : $(modular-rules) ;
|
||||
|
||||
# Load/create/declare library project.
|
||||
local lib-module = [ project.find $(root) : $(caller-dir) ] ;
|
||||
if ! $(lib-module)
|
||||
{
|
||||
# If the find was unable to load the project we synthesize it.
|
||||
lib-module = [ project.load $(lib-location) : synthesize ] ;
|
||||
}
|
||||
local lib-target = [ project.target $(lib-module) ] ;
|
||||
if ! [ modules.peek $(lib-module) : __library__ ]
|
||||
{
|
||||
modules.poke $(lib-module) : __library__ : $(name) ;
|
||||
for local type in [ modules.peek type : .types ]
|
||||
{
|
||||
main-rule-name = [ type.type-to-rule-name $(type) ] ;
|
||||
IMPORT modular-rules : main-target-rule : $(lib-module-name) : $(main-rule-name) ;
|
||||
}
|
||||
}
|
||||
|
||||
# Declare project alternate ID.
|
||||
modules.call-in $(caller-module) : use-project $(name) : $(root) ;
|
||||
|
||||
# Create a "library" target that has basic usage info if needed.
|
||||
if ! [ $(lib-target).has-alternative-for-target library ]
|
||||
{
|
||||
include-dir = [ path.relative-to $(root) $(include-dir) ] ;
|
||||
|
||||
project.push-current $(lib-target) ;
|
||||
|
||||
# Declare the library alias.
|
||||
modules.call-in $(lib-module) : library
|
||||
: # Sources
|
||||
: # Requirements
|
||||
: # Default Build
|
||||
: # Usage Requirements
|
||||
<include>$(include-dir)
|
||||
;
|
||||
|
||||
project.pop-current ;
|
||||
}
|
||||
}
|
||||
|
||||
local rule process-args ( )
|
||||
{
|
||||
if ! $(.did-process-args)
|
||||
@@ -139,3 +203,86 @@ local rule process-args ( )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rule apply-external (
|
||||
mod : field : values * )
|
||||
{
|
||||
local result ;
|
||||
local name = [ modules.peek $(mod) : __library__ ] ;
|
||||
values += $(.external.($(name)).$(field)) ;
|
||||
for local value in $(values)
|
||||
{
|
||||
result += [ resolve-reference $(value) : $(mod) ] ;
|
||||
}
|
||||
return $(result) ;
|
||||
}
|
||||
|
||||
module modular-rules
|
||||
{
|
||||
import type ;
|
||||
import targets ;
|
||||
import builtin ;
|
||||
import alias ;
|
||||
|
||||
# Avoids any form of installation for Boost modules.
|
||||
rule boost-install ( libraries * ) { }
|
||||
|
||||
# Generic typed target rule to pre-process main target
|
||||
# declarations to make them work within the standalone
|
||||
# modular structure.
|
||||
rule main-target-rule (
|
||||
name : sources * : requirements * : default-build * :
|
||||
usage-requirements * )
|
||||
{
|
||||
local mod = [ CALLER_MODULE ] ;
|
||||
|
||||
# ECHO @@@ [[$(mod)]] modular-rules.main-target-rule $(name) :: $(sources) :: $(requirements) :: $(default-build) :: $(usage-requirements) ;
|
||||
|
||||
# First discover the required target type based on the exact alias used to
|
||||
# invoke this rule.
|
||||
local bt = [ BACKTRACE 1 ] ;
|
||||
local rulename = $(bt[4]) ;
|
||||
local target-type = [ type.type-from-rule-name $(rulename) ] ;
|
||||
return [ targets.create-typed-target $(target-type) : [ project.current ] :
|
||||
$(name) : $(sources) : $(requirements) : $(default-build) :
|
||||
$(usage-requirements) ] ;
|
||||
}
|
||||
|
||||
rule lib ( names + : sources * : requirements * : default-build * :
|
||||
usage-requirements * )
|
||||
{
|
||||
local mod = [ CALLER_MODULE ] ;
|
||||
requirements += <use>library ;
|
||||
usage-requirements += <use>library ;
|
||||
|
||||
# ECHO @@@ [[$(mod)]] modular-rules.lib $(names) :: $(sources) :: $(requirements) :: $(default-build) :: $(usage-requirements) ;
|
||||
return [ builtin.lib $(names) : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ] ;
|
||||
}
|
||||
|
||||
rule alias ( name : sources * : requirements * : default-build * :
|
||||
usage-requirements * )
|
||||
{
|
||||
local mod = [ CALLER_MODULE ] ;
|
||||
|
||||
# ECHO @@@ [[$(mod)]] modular-rules.alias $(name) :: $(sources) :: $(requirements) :: $(default-build) :: $(usage-requirements) ;
|
||||
return [ alias.alias $(name) : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ] ;
|
||||
}
|
||||
|
||||
rule library ( name ? : sources * : requirements * : default-build * :
|
||||
usage-requirements * )
|
||||
{
|
||||
import modular ;
|
||||
|
||||
local mod = [ CALLER_MODULE ] ;
|
||||
sources = [ modular.apply-external $(mod) : sources : $(sources) ] ;
|
||||
requirements = [ modular.apply-external $(mod) : requirements : $(requirements) ] ;
|
||||
default-build = [ modular.apply-external $(mod) : default-build : $(default-build) ] ;
|
||||
usage-requirements = [ modular.apply-external $(mod) : usage-requirements : $(usage-requirements) ] ;
|
||||
|
||||
name ?= library ;
|
||||
|
||||
# ECHO @@@ [[$(mod)]] modular-rules.library $(name) :: $(sources) :: $(requirements) :: $(default-build) :: $(usage-requirements) ;
|
||||
return [ alias.alias $(name) : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ] ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user