Index: contrib/boost.py =================================================================== --- contrib/boost.py (revision 0) +++ contrib/boost.py (working copy) @@ -0,0 +1,275 @@ +# $Id: boost.jam 62249 2010-05-26 19:05:19Z steven_watanabe $ +# Copyright 2008 Roland Schwarz +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# Boost library support module. +# +# This module allows to use the boost library from boost-build projects. +# The location of a boost source tree or the path to a pre-built +# version of the library can be configured from either site-config.jam +# or user-config.jam. If no location is configured the module looks for +# a BOOST_ROOT environment variable, which should point to a boost source +# tree. As a last resort it tries to use pre-built libraries from the standard +# search path of the compiler. +# +# If the location to a source tree is known, the module can be configured +# from the *-config.jam files: +# +# using boost : 1.35 : /path-to-boost-root ; +# +# If the location to a pre-built version is known: +# +# using boost : 1.34 +# : /usr/local/include/boost_1_34 +# /usr/local/lib +# ; +# +# It is legal to configure more than one boost library version in the config +# files. The version identifier is used to disambiguate between them. +# The first configured version becomes the default. +# +# To use a boost library you need to put a 'use' statement into your +# Jamfile: +# +# import boost ; +# +# boost.use-project 1.35 ; +# +# If you don't care about a specific version you just can omit the version +# part, in which case the default is picked up: +# +# boost.use-project ; +# +# The library can be referenced with the project identifier '/boost'. To +# reference the program_options you would specify: +# +# exe myexe : mysrc.cpp : /boost//program_options ; +# +# Note that the requirements are automatically transformed into suitable +# tags to find the correct pre-built library. +# + +import re + +import bjam + +from b2.build import alias, property, property_set, feature +from b2.manager import get_manager +from b2.tools import builtin, common +from b2.util import bjam_signature, regex + + +# TODO: This is currently necessary in Python Port, but was not in Jam. +feature.feature('layout', ['system', 'versioned', 'tag'], ['optional']) +feature.feature('root', [], ['optional', 'free']) +feature.feature('build-id', [], ['optional', 'free']) + +__initialized = None +__boost_auto_config = property_set.create([property.Property('layout', 'system')]) +__boost_configured = {} +__boost_default = None +__build_id = None + +__debug = None + +def debug(): + global __debug + if __debug is None: + __debug = "--debug-configuration" in bjam.variable("ARGV") + return __debug + + +# Configuration of the boost library to use. +# +# This can either be a boost source tree or +# pre-built libraries. The 'version' parameter must be a valid boost +# version number, e.g. 1.35, if specifying a pre-built version with +# versioned layout. It may be a symbolic name, e.g. 'trunk' if specifying +# a source tree. The options are specified as named parameters (like +# properties). The following paramters are available: +# +# /path-to-boost-root: Specify a source tree. +# +# /path-to-include: The include directory to search. +# +# /path-to-library: The library directory to search. +# +# system or versioned. +# +# my_build_id: The custom build id to use. +# +def init(version, options = None): + assert(isinstance(version,list)) + assert(len(version)==1) + version = version[0] + if version in __boost_configured: + get_manager().errors()("Boost {} already configured.".format(version)); + else: + global __boost_default + if debug(): + if not __boost_default: + print "notice: configuring default boost library {}".format(version) + print "notice: configuring boost library {}".format(version) + + if not __boost_default: + __boost_default = version + properties = [] + for option in options: + properties.append(property.create_from_string(option)) + __boost_configured[ version ] = property_set.PropertySet(properties) + +projects = get_manager().projects() +rules = projects.project_rules() + + +# Use a certain version of the library. +# +# The use-project rule causes the module to define a boost project of +# searchable pre-built boost libraries, or references a source tree +# of the boost library. If the 'version' parameter is omitted either +# the configured default (first in config files) is used or an auto +# configuration will be attempted. +# +@bjam_signature(([ "version", "?" ], )) +def use_project(version = None): + projects.push_current( projects.current() ) + if not version: + version = __boost_default + if not version: + version = "auto_config" + + global __initialized + if __initialized: + if __initialized != version: + get_manager().errors()('Attempt to use {} with different parameters'.format('boost')) + else: + if version in __boost_configured: + opts = __boost_configured[ version ] + root = opts.get('' ) + inc = opts.get('') + lib = opts.get('') + + if debug(): + print "notice: using boost library {} {}".format( version, opt.raw() ) + + global __layout + global __version_tag + __layout = opts.get('') + if not __layout: + __layout = 'versioned' + __build_id = opts.get('') + __version_tag = re.sub("[*\\/:.\"\' ]", "_", version) + __initialized = version + + if ( root and inc ) or \ + ( root and lib ) or \ + ( lib and not inc ) or \ + ( not lib and inc ): + get_manager().errors()("Ambiguous parameters, use either or with .") + elif not root and not inc: + root = bjam.variable("BOOST_ROOT") + + module = projects.current().project_module() + + if root: + bjam.call('call-in-module', module, 'use-project', ['boost', root]) + else: + projects.initialize(__name__) + if version == '0.0.1': + boost_0_0_1( inc, lib ) + else: + boost_std( inc, lib ) + else: + get_manager().errors()("Reference to unconfigured boost version.") + projects.pop_current() + + +rules._import_rule( projects.current().project_module(), 'boost.use-project', use_project ) + +def boost_std(inc = None, lib = None): + # The default definitions for pre-built libraries. + rules.project( + ['boost'], + ['usage-requirements'] + ['{}'.format(i) for i in inc] + ['BOOST_ALL_NO_LIB'], + ['requirements'] + ['{}'.format(l) for l in lib]) + + # TODO: There should be a better way to add a Python function into a + # project requirements property set. + tag_prop_set = property_set.create([property.Property('', tag_std)]) + attributes = projects.attributes(projects.current().project_module()) + attributes.requirements = attributes.requirements.refine(tag_prop_set) + + alias('headers') + + def boost_lib(lib_name, dyn_link_macro): + if (isinstance(lib_name,str)): + lib_name = [lib_name] + builtin.lib(lib_name, usage_requirements=['shared:{}'.format(dyn_link_macro)]) + + boost_lib('date_time' , 'BOOST_DATE_TIME_DYN_LINK' ) + boost_lib('filesystem' , 'BOOST_FILE_SYSTEM_DYN_LINK' ) + boost_lib('graph' , 'BOOST_GRAPH_DYN_LINK' ) + boost_lib('graph_parallel' , 'BOOST_GRAPH_DYN_LINK' ) + boost_lib('iostreams' , 'BOOST_IOSTREAMS_DYN_LINK' ) + boost_lib('math_tr1' , 'BOOST_MATH_TR1_DYN_LINK' ) + boost_lib('math_tr1f' , 'BOOST_MATH_TR1_DYN_LINK' ) + boost_lib('math_tr1l' , 'BOOST_MATH_TR1_DYN_LINK' ) + boost_lib('math_c99' , 'BOOST_MATH_TR1_DYN_LINK' ) + boost_lib('math_c99f' , 'BOOST_MATH_TR1_DYN_LINK' ) + boost_lib('math_c99l' , 'BOOST_MATH_TR1_DYN_LINK' ) + boost_lib('mpi' , 'BOOST_MPI_DYN_LINK' ) + boost_lib('program_options' , 'BOOST_PROGRAM_OPTIONS_DYN_LINK') + boost_lib('python' , 'BOOST_PYTHON_DYN_LINK' ) + boost_lib('random' , 'BOOST_RANDOM_DYN_LINK' ) + boost_lib('regex' , 'BOOST_REGEX_DYN_LINK' ) + boost_lib('serialization' , 'BOOST_SERIALIZATION_DYN_LINK' ) + boost_lib('wserialization' , 'BOOST_SERIALIZATION_DYN_LINK' ) + boost_lib('signals' , 'BOOST_SIGNALS_DYN_LINK' ) + boost_lib('system' , 'BOOST_SYSTEM_DYN_LINK' ) + boost_lib('unit_test_framework' , 'BOOST_TEST_DYN_LINK' ) + boost_lib('prg_exec_monitor' , 'BOOST_TEST_DYN_LINK' ) + boost_lib('test_exec_monitor' , 'BOOST_TEST_DYN_LINK' ) + boost_lib('thread' , 'BOOST_THREAD_DYN_DLL' ) + boost_lib('wave' , 'BOOST_WAVE_DYN_LINK' ) + +def boost_0_0_1( inc, lib ): + print "You are trying to use an example placeholder for boost libs." ; + # Copy this template to another place (in the file boost.jam) + # and define a project and libraries modelled after the + # boost_std rule. Please note that it is also possible to have + # a per version taging rule in case they are different between + # versions. + +def tag_std(name, type, prop_set): + name = 'boost_' + name + if 'static' in prop_set.get('') and 'windows' in prop_set.get(''): + name = 'lib' + name + result = None + + if __layout == 'system': + versionRe = re.search('^([0-9]+)_([0-9]+)', __version_tag) + if versionRe and versionRe.group(1) == '1' and int(versionRe.group(2)) < 39: + result = tag_tagged(name, type, prop_set) + else: + result = tag_system(name, type, prop_set) + elif __layout == 'tagged': + result = tag_tagged(name, type, prop_set) + elif __layout == 'versioned': + result = tag_versioned(name, type, prop_set) + else: + get_manager().errors()("Missing layout") + return result + +def tag_maybe(param): + return ['-{}'.format(param)] if param else [] + +def tag_system(name, type, prop_set): + return common.format_name([''] + tag_maybe(__build_id), name, type, prop_set) + +def tag_system(name, type, prop_set): + return common.format_name(['', '', ''] + tag_maybe(__build_id), name, type, prop_set) + +def tag_versioned(name, type, prop_set): + return common.format_name(['', '', '', ''] + tag_maybe(__version_tag) + tag_maybe(__build_id), + name, type, prop_set)