1# $Id: boost.jam 62249 2010-05-26 19:05:19Z steven_watanabe $ 2# Copyright 2008 Roland Schwarz 3# Distributed under the Boost Software License, Version 1.0. 4# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) 5 6# Boost library support module. 7# 8# This module allows to use the boost library from boost-build projects. 9# The location of a boost source tree or the path to a pre-built 10# version of the library can be configured from either site-config.jam 11# or user-config.jam. If no location is configured the module looks for 12# a BOOST_ROOT environment variable, which should point to a boost source 13# tree. As a last resort it tries to use pre-built libraries from the standard 14# search path of the compiler. 15# 16# If the location to a source tree is known, the module can be configured 17# from the *-config.jam files: 18# 19# using boost : 1.35 : <root>/path-to-boost-root ; 20# 21# If the location to a pre-built version is known: 22# 23# using boost : 1.34 24# : <include>/usr/local/include/boost_1_34 25# <library>/usr/local/lib 26# ; 27# 28# It is legal to configure more than one boost library version in the config 29# files. The version identifier is used to disambiguate between them. 30# The first configured version becomes the default. 31# 32# To use a boost library you need to put a 'use' statement into your 33# Jamfile: 34# 35# import boost ; 36# 37# boost.use-project 1.35 ; 38# 39# If you don't care about a specific version you just can omit the version 40# part, in which case the default is picked up: 41# 42# boost.use-project ; 43# 44# The library can be referenced with the project identifier '/boost'. To 45# reference the program_options you would specify: 46# 47# exe myexe : mysrc.cpp : <library>/boost//program_options ; 48# 49# Note that the requirements are automatically transformed into suitable 50# tags to find the correct pre-built library. 51# 52 53import re 54 55import bjam 56 57from b2.build import alias, property, property_set, feature 58from b2.manager import get_manager 59from b2.tools import builtin, common 60from b2.util import bjam_signature, regex 61 62 63# TODO: This is currently necessary in Python Port, but was not in Jam. 64feature.feature('layout', ['system', 'versioned', 'tag'], ['optional']) 65feature.feature('root', [], ['optional', 'free']) 66feature.feature('build-id', [], ['optional', 'free']) 67 68__initialized = None 69__boost_auto_config = property_set.create([property.Property('layout', 'system')]) 70__boost_configured = {} 71__boost_default = None 72__build_id = None 73 74__debug = None 75 76def debug(): 77 global __debug 78 if __debug is None: 79 __debug = "--debug-configuration" in bjam.variable("ARGV") 80 return __debug 81 82 83# Configuration of the boost library to use. 84# 85# This can either be a boost source tree or 86# pre-built libraries. The 'version' parameter must be a valid boost 87# version number, e.g. 1.35, if specifying a pre-built version with 88# versioned layout. It may be a symbolic name, e.g. 'trunk' if specifying 89# a source tree. The options are specified as named parameters (like 90# properties). The following parameters are available: 91# 92# <root>/path-to-boost-root: Specify a source tree. 93# 94# <include>/path-to-include: The include directory to search. 95# 96# <library>/path-to-library: The library directory to search. 97# 98# <layout>system or <layout>versioned. 99# 100# <build-id>my_build_id: The custom build id to use. 101# 102def init(version, options = None): 103 assert(isinstance(version,list)) 104 assert(len(version)==1) 105 version = version[0] 106 if version in __boost_configured: 107 get_manager().errors()("Boost {} already configured.".format(version)); 108 else: 109 global __boost_default 110 if debug(): 111 if not __boost_default: 112 print "notice: configuring default boost library {}".format(version) 113 print "notice: configuring boost library {}".format(version) 114 115 if not __boost_default: 116 __boost_default = version 117 properties = [] 118 for option in options: 119 properties.append(property.create_from_string(option)) 120 __boost_configured[ version ] = property_set.PropertySet(properties) 121 122projects = get_manager().projects() 123rules = projects.project_rules() 124 125 126# Use a certain version of the library. 127# 128# The use-project rule causes the module to define a boost project of 129# searchable pre-built boost libraries, or references a source tree 130# of the boost library. If the 'version' parameter is omitted either 131# the configured default (first in config files) is used or an auto 132# configuration will be attempted. 133# 134@bjam_signature(([ "version", "?" ], )) 135def use_project(version = None): 136 projects.push_current( projects.current() ) 137 if not version: 138 version = __boost_default 139 if not version: 140 version = "auto_config" 141 142 global __initialized 143 if __initialized: 144 if __initialized != version: 145 get_manager().errors()('Attempt to use {} with different parameters'.format('boost')) 146 else: 147 if version in __boost_configured: 148 opts = __boost_configured[ version ] 149 root = opts.get('<root>' ) 150 inc = opts.get('<include>') 151 lib = opts.get('<library>') 152 153 if debug(): 154 print "notice: using boost library {} {}".format( version, opt.raw() ) 155 156 global __layout 157 global __version_tag 158 __layout = opts.get('<layout>') 159 if not __layout: 160 __layout = 'versioned' 161 __build_id = opts.get('<build-id>') 162 __version_tag = re.sub("[*\\/:.\"\' ]", "_", version) 163 __initialized = version 164 165 if ( root and inc ) or \ 166 ( root and lib ) or \ 167 ( lib and not inc ) or \ 168 ( not lib and inc ): 169 get_manager().errors()("Ambiguous parameters, use either <root> or <include> with <library>.") 170 elif not root and not inc: 171 root = bjam.variable("BOOST_ROOT") 172 173 module = projects.current().project_module() 174 175 if root: 176 bjam.call('call-in-module', module, 'use-project', ['boost', root]) 177 else: 178 projects.initialize(__name__) 179 if version == '0.0.1': 180 boost_0_0_1( inc, lib ) 181 else: 182 boost_std( inc, lib ) 183 else: 184 get_manager().errors()("Reference to unconfigured boost version.") 185 projects.pop_current() 186 187 188rules.add_rule( 'boost.use-project', use_project ) 189 190def boost_std(inc = None, lib = None): 191 # The default definitions for pre-built libraries. 192 rules.project( 193 ['boost'], 194 ['usage-requirements'] + ['<include>{}'.format(i) for i in inc] + ['<define>BOOST_ALL_NO_LIB'], 195 ['requirements'] + ['<search>{}'.format(l) for l in lib]) 196 197 # TODO: There should be a better way to add a Python function into a 198 # project requirements property set. 199 tag_prop_set = property_set.create([property.Property('<tag>', tag_std)]) 200 attributes = projects.attributes(projects.current().project_module()) 201 attributes.requirements = attributes.requirements.refine(tag_prop_set) 202 203 alias('headers') 204 205 def boost_lib(lib_name, dyn_link_macro): 206 if (isinstance(lib_name,str)): 207 lib_name = [lib_name] 208 builtin.lib(lib_name, usage_requirements=['<link>shared:<define>{}'.format(dyn_link_macro)]) 209 210 boost_lib('container' , 'BOOST_CONTAINER_DYN_LINK' ) 211 boost_lib('date_time' , 'BOOST_DATE_TIME_DYN_LINK' ) 212 boost_lib('filesystem' , 'BOOST_FILE_SYSTEM_DYN_LINK' ) 213 boost_lib('graph' , 'BOOST_GRAPH_DYN_LINK' ) 214 boost_lib('graph_parallel' , 'BOOST_GRAPH_DYN_LINK' ) 215 boost_lib('iostreams' , 'BOOST_IOSTREAMS_DYN_LINK' ) 216 boost_lib('locale' , 'BOOST_LOG_DYN_LINK' ) 217 boost_lib('log' , 'BOOST_LOG_DYN_LINK' ) 218 boost_lib('log_setup' , 'BOOST_LOG_DYN_LINK' ) 219 boost_lib('math_tr1' , 'BOOST_MATH_TR1_DYN_LINK' ) 220 boost_lib('math_tr1f' , 'BOOST_MATH_TR1_DYN_LINK' ) 221 boost_lib('math_tr1l' , 'BOOST_MATH_TR1_DYN_LINK' ) 222 boost_lib('math_c99' , 'BOOST_MATH_TR1_DYN_LINK' ) 223 boost_lib('math_c99f' , 'BOOST_MATH_TR1_DYN_LINK' ) 224 boost_lib('math_c99l' , 'BOOST_MATH_TR1_DYN_LINK' ) 225 boost_lib('mpi' , 'BOOST_MPI_DYN_LINK' ) 226 boost_lib('program_options' , 'BOOST_PROGRAM_OPTIONS_DYN_LINK') 227 boost_lib('python' , 'BOOST_PYTHON_DYN_LINK' ) 228 boost_lib('python3' , 'BOOST_PYTHON_DYN_LINK' ) 229 boost_lib('random' , 'BOOST_RANDOM_DYN_LINK' ) 230 boost_lib('regex' , 'BOOST_REGEX_DYN_LINK' ) 231 boost_lib('serialization' , 'BOOST_SERIALIZATION_DYN_LINK' ) 232 boost_lib('wserialization' , 'BOOST_SERIALIZATION_DYN_LINK' ) 233 boost_lib('signals' , 'BOOST_SIGNALS_DYN_LINK' ) 234 boost_lib('system' , 'BOOST_SYSTEM_DYN_LINK' ) 235 boost_lib('unit_test_framework' , 'BOOST_TEST_DYN_LINK' ) 236 boost_lib('prg_exec_monitor' , 'BOOST_TEST_DYN_LINK' ) 237 boost_lib('test_exec_monitor' , 'BOOST_TEST_DYN_LINK' ) 238 boost_lib('thread' , 'BOOST_THREAD_DYN_DLL' ) 239 boost_lib('wave' , 'BOOST_WAVE_DYN_LINK' ) 240 241def boost_0_0_1( inc, lib ): 242 print "You are trying to use an example placeholder for boost libs." ; 243 # Copy this template to another place (in the file boost.jam) 244 # and define a project and libraries modelled after the 245 # boost_std rule. Please note that it is also possible to have 246 # a per version taging rule in case they are different between 247 # versions. 248 249def tag_std(name, type, prop_set): 250 name = 'boost_' + name 251 if 'static' in prop_set.get('<link>') and 'windows' in prop_set.get('<target-os>'): 252 name = 'lib' + name 253 result = None 254 255 if __layout == 'system': 256 versionRe = re.search('^([0-9]+)_([0-9]+)', __version_tag) 257 if versionRe and versionRe.group(1) == '1' and int(versionRe.group(2)) < 39: 258 result = tag_tagged(name, type, prop_set) 259 else: 260 result = tag_system(name, type, prop_set) 261 elif __layout == 'tagged': 262 result = tag_tagged(name, type, prop_set) 263 elif __layout == 'versioned': 264 result = tag_versioned(name, type, prop_set) 265 else: 266 get_manager().errors()("Missing layout") 267 return result 268 269def tag_maybe(param): 270 return ['-{}'.format(param)] if param else [] 271 272def tag_system(name, type, prop_set): 273 return common.format_name(['<base>'] + tag_maybe(__build_id), name, type, prop_set) 274 275def tag_tagged(name, type, prop_set): 276 return common.format_name(['<base>', '<threading>', '<runtime>'] + tag_maybe(__build_id), name, type, prop_set) 277 278def tag_versioned(name, type, prop_set): 279 return common.format_name(['<base>', '<toolset>', '<threading>', '<runtime>'] + tag_maybe(__version_tag) + tag_maybe(__build_id), 280 name, type, prop_set) 281