# Project directory tree:
#
# trunk/
# |
# +-- bld/
# |
# +-- ...
# |
# +-- res/
# |
# +-- libs/
# |
# +-- json/
# |
# +-- ...
# |
# +-- src/
# |
# +-- foo/
# |
# +-- build/
# |
# +-- jamfile.jam
# |
# +-- foo.cc
# +-- bar/
# |
# +-- build/
# |
# +-- jamfile.jam
# |
# +-- bar.cc
# import modules ;
#
# modules.poke .ENVIRON : BOOST_PATH : /path/to/boost ;
# modules.poke .ENVIRON : BOOST_VERSION : 1_51 ;
#
# dep = [ new dependencies ] ;
# $(dep).push boost : thread ;
# $(dep).push Poco : Foundation ;
# $(dep).push luascript : : ;
#
# exe/lib foo : foo.cpp : @$(dep).get
#
class dependencies
{
import os ;
import type ;
import path ;
import common ;
#import string ;
import property-set ;
rule __init__ ( )
{
# Searches for res directory
self.res-dir = res ;
while ! [ path.exists $(self.res-dir) ]
{
self.res-dir = ../$(self.res-dir) ;
}
self.res-dir = [ path.join [ path.pwd ] $(self.res-dir) ] ;
}
# basename: library name
# names: sub library name (e.g. boost thread)
# format: configurations used to format final name
rule push ( basename : names * : format * )
{
# If format not specified, use default
format ?= ;
self.basenames += $(basename) ;
self.$(basename).names = $(names) ;
self.$(basename).format = $(format) ;
}
rule get ( properties * )
{
# I don't know why, but this rule is called even when it self is not configured for
# so we check if there is a conditional in properties
local property-set = [ property-set.create $(properties) ] ;
if [ $(property-set).get ]
{
local dependencies ;
for local basename in $(self.basenames)
{
local library-dir = [ get-library-dir $(basename) ] ;
local format = $(self.$(basename).format) ;
local names = $(self.$(basename).names) ;
if $(names)
{
# If has sub libraries, process them all
for local name in $(names)
{
dependencies += [ path.join $(library-dir) [ resolve-name $(basename) : $(name) : $(format) : $(property-set) ] ] ;
}
}
else
{
dependencies += [ path.join $(library-dir) [ resolve-name $(basename) : : $(format) : $(property-set) ] ] ;
}
}
return $(dependencies) ;
}
}
# private:
# Search for the library dir
rule get-library-dir ( basename )
{
# Here we check if library is on res/libs dir
local library-dir = [ path.join $(self.res-dir) libs $(basename) ] ;
library-dir = [ path.glob $(library-dir) : lib ] ;
# If it's not, check for environment variable LIBNAME_PATH
library-dir ?= [ path.join [ os.environ $(basename:U)_PATH ] lib ] ;
if ! $(library-dir)
{
exit Unable to find library $(basename) ;
}
return $(library-dir) ;
}
rule resolve-name ( basename : name ? : format * : property-set )
{
local dependency ;
# Here we may treat diferents libraries names
switch $(basename)
{
# For example Poco, it does not follow boost naming
case Poco :
local extension = [ type.generated-target-suffix STATIC_LIB : $(property-set) ] ;
dependency = $(basename)$(name) ;
if multi in [ $(property-set).raw ]
{
if shared in [ $(property-set).raw ]
{
dependency = $(dependency)md ;
}
else
{
dependency = $(dependency)mt ;
}
}
if debug in [ $(property-set).raw ] { dependency = $(dependency)d ; }
dependency = $(dependency).$(extension) ;
# Another example is xulrunner
case xulrunner :
local extension = [ type.generated-target-suffix STATIC_LIB : $(property-set) ] ;
dependency = $(name).$(extension) ;
# Everything else drops here, this rule follow boost naming convension
case * :
# If LIBNAME_VERSION environment variable exists, use it appending it in format
local version = [ os.environ $(basename:U)_VERSION ] ;
if $(version)
{
#if $(version) { version = [ string.words $(version) : _ ] ; }
format += -$(version) ;
}
if $(name)
{
dependency = [ common.format-name $(basename)_ $(format) : $(name) : STATIC_LIB : $(property-set) ] ;
}
dependency ?= [ common.format-name $(format) : $(basename) : STATIC_LIB : $(property-set) ] ;
}
return $(dependency) ;
}
}