1# Copyright Gennadiy Rozental
2# Copyright 2006 Rene Rivera
3# Copyright 2003, 2004, 2006 Vladimir Prus
4# Distributed under the Boost Software License, Version 1.0.
5# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
6
7# The STLPort is usable by means of 'stdlib' feature. When
8# stdlib=stlport is specified, default version of STLPort will be used,
9# while stdlib=stlport-4.5 will use specific version.
10# The subfeature value 'hostios' means to use host compiler's iostreams.
11#
12# The specific version of stlport is selected by features:
13# The <runtime-link> feature selects between static and shared library
14# The <runtime-debugging>on selects STLPort with debug symbols
15# and stl debugging.
16# There's no way to use STLPort with debug symbols but without
17# stl debugging.
18
19# TODO: must implement selection of different STLPort installations based
20# on used toolset.
21# Also, finish various flags:
22#
23# This is copied from V1 toolset, "+" means "implemented"
24#+flags $(CURR_TOOLSET) DEFINES <stlport-iostream>off : _STLP_NO_OWN_IOSTREAMS=1 _STLP_HAS_NO_NEW_IOSTREAMS=1 ;
25#+flags $(CURR_TOOLSET) DEFINES <stlport-extensions>off : _STLP_NO_EXTENSIONS=1 ;
26# flags $(CURR_TOOLSET) DEFINES <stlport-anachronisms>off : _STLP_NO_ANACHRONISMS=1 ;
27# flags $(CURR_TOOLSET) DEFINES <stlport-cstd-namespace>global : _STLP_VENDOR_GLOBAL_CSTD=1 ;
28# flags $(CURR_TOOLSET) DEFINES <exception-handling>off : _STLP_NO_EXCEPTIONS=1 ;
29# flags $(CURR_TOOLSET) DEFINES <stlport-debug-alloc>on : _STLP_DEBUG_ALLOC=1 ;
30#+flags $(CURR_TOOLSET) DEFINES <runtime-build>debug : _STLP_DEBUG=1 _STLP_DEBUG_UNINITIALIZED=1 ;
31#+flags $(CURR_TOOLSET) DEFINES <runtime-link>dynamic : _STLP_USE_DYNAMIC_LIB=1 ;
32
33
34import feature : feature subfeature ;
35import project ;
36import "class" : new ;
37import targets ;
38import property-set ;
39import common ;
40import type ;
41
42# Make this module into a project.
43project.initialize $(__name__) ;
44project stlport ;
45
46# The problem: how to request to use host compiler's iostreams?
47#
48# Solution 1: Global 'stlport-iostream' feature.
49#    That's ugly. Subfeature make more sense for stlport-specific thing.
50# Solution 2: Use subfeature with two values, one of which ("use STLPort iostream")
51#     is default.
52#    The problem is that such subfeature will appear in target paths, and that's ugly
53# Solution 3: Use optional subfeature with only one value.
54
55feature.extend stdlib : stlport ;
56feature.compose <stdlib>stlport : <library>/stlport//stlport ;
57
58# STLport iostreams or native iostreams
59subfeature stdlib stlport : iostream : hostios : optional propagated  ;
60
61# STLport extensions
62subfeature stdlib stlport : extensions : noext : optional propagated ;
63
64# STLport anachronisms -- NOT YET SUPPORTED
65# subfeature stdlib stlport : anachronisms : on off ;
66
67# STLport debug allocation -- NOT YET SUPPORTED
68#subfeature stdlib stlport : debug-alloc : off on ;
69
70# Declare a special target class to handle the creation of search-lib-target
71# instances for STLport. We need a special class, because otherwise we'll have
72# - declare prebuilt targets for all possible toolsets. And by the time 'init'
73#   is called we don't even know the list of toolsets that are registered
74# - when host iostreams are used, we really should produce nothing. It would
75#   be hard/impossible to achieve this using prebuilt targets.
76
77class stlport-target-class : basic-target
78{
79    import feature project type errors generators ;
80    import set : difference ;
81
82    rule __init__ ( project : headers ? : libraries * :  version ? )
83    {
84        basic-target.__init__ stlport : $(project) ;
85        self.headers = $(headers) ;
86        self.libraries = $(libraries) ;
87        self.version = $(version) ;
88        self.version.5 = [ MATCH "^(5[.][0123456789]+).*" : $(version) ] ;
89
90        local requirements ;
91        requirements += <stdlib-stlport:version>$(self.version) ;
92        self.requirements = [ property-set.create $(requirements) ] ;
93    }
94
95    rule generate ( property-set )
96    {
97        # Since this target is built with <stdlib>stlport, it will also
98        # have <library>/stlport//stlport in requirements, which will
99        # cause a loop in main target references. Remove that property
100        # manually.
101
102        property-set = [ property-set.create
103            [ difference
104                [ $(property-set).raw ] :
105                <library>/stlport//stlport
106                <stdlib>stlport
107                ]
108            ] ;
109        return [ basic-target.generate $(property-set) ] ;
110    }
111
112    rule construct ( name : source-targets * : property-set )
113    {
114        # Deduce the name of stlport library, based on toolset and
115        # debug setting.
116        local raw = [ $(property-set).raw ] ;
117        local hostios = [ feature.get-values <stdlib-stlport:iostream> : $(raw) ] ;
118        local toolset = [ feature.get-values <toolset> : $(raw) ] ;
119
120        if $(self.version.5)
121        {
122            # Version 5.x
123
124            # STLport host IO streams no longer supported. So we always
125            # need libraries.
126
127            # name: stlport(stl)?[dg]?(_static)?.M.R
128            local name = stlport ;
129            if [ feature.get-values <runtime-debugging> : $(raw) ] = "on"
130            {
131                name += stl ;
132                switch $(toolset)
133                {
134                    case gcc* : name += g ;
135                    case darwin* : name += g ;
136                    case * : name += d ;
137                }
138            }
139
140            if [ feature.get-values <runtime-link> : $(raw) ] = "static"
141            {
142                name += _static ;
143            }
144
145            # Starting with version 5.2.0, the STLport static libraries no
146            # longer include a version number in their name
147            local version.pre.5.2 = [ MATCH "^(5[.][01]+).*" : $(version) ] ;
148            if $(version.pre.5.2) || [ feature.get-values <runtime-link> :
149                $(raw) ] != "static"
150            {
151                name += .$(self.version.5) ;
152            }
153
154            name = $(name:J=) ;
155
156            if [ feature.get-values <install-dependencies> : $(raw) ] = "on"
157            {
158                #~ Allow explicitly asking to install the STLport lib by
159                #~ referring to it directly:
160                #~   /stlport//stlport/<install-dependencies>on
161                #~ This allows for install packaging of all libs one might need
162                #~ for a standalone distribution.
163                import path : make : path-make ;
164                local runtime-link
165                    = [ feature.get-values <runtime-link> : $(raw) ] ;
166                local lib-file.props
167                    = [ property-set.create $(raw) <link>$(runtime-link) ] ;
168                local lib-file.prefix
169                    = [ type.generated-target-prefix $(runtime-link:U)_LIB :
170                        $(lib-file.props) ] ;
171                local lib-file.suffix
172                    = [ type.generated-target-suffix $(runtime-link:U)_LIB :
173                        $(lib-file.props) ] ;
174                lib-file.prefix
175                    ?= "" "lib" ;
176                lib-file.suffix
177                    ?= "" ;
178                local lib-file
179                    = [ GLOB $(self.libraries) [ modules.peek : PATH ] :
180                        $(lib-file.prefix)$(name).$(lib-file.suffix) ] ;
181                lib-file
182                    = [ new file-reference [ path-make $(lib-file[1]) ] :
183                        $(self.project) ] ;
184                lib-file
185                    = [ $(lib-file).generate "" ] ;
186                local lib-file.requirements
187                    = [ targets.main-target-requirements
188                        [ $(lib-file.props).raw ] <file>$(lib-file[-1])
189                        : $(self.project) ] ;
190                return [ generators.construct $(self.project) $(name) : LIB :
191                    $(lib-file.requirements) ] ;
192            }
193            else
194            {
195                #~ Otherwise, it is just regular library usage.
196                return [ generators.construct
197                    $(self.project) $(name) : SEARCHED_LIB : $(property-set) ] ;
198            }
199        }
200        else if ! $(hostios) && $(toolset) != msvc
201        {
202            # We don't need libraries if host istreams are used. For
203            # msvc, automatic library selection will be used.
204
205            # name: stlport_<toolset>(_stldebug)?
206            local name = stlport ;
207            name = $(name)_$(toolset) ;
208            if [ feature.get-values <runtime-debugging> : $(raw) ] = "on"
209            {
210                name = $(name)_stldebug ;
211            }
212
213            return [ generators.construct
214                $(self.project) $(name) : SEARCHED_LIB : $(property-set) ] ;
215        }
216        else
217        {
218            return [ property-set.empty ] ;
219        }
220    }
221
222    rule compute-usage-requirements ( subvariant )
223    {
224        local usage-requirements =
225            <include>$(self.headers)
226            <dll-path>$(self.libraries)
227            <library-path>$(self.libraries)
228            ;
229
230        local rproperties = [ $(subvariant).build-properties ] ;
231        # CONSIDER: should this "if" sequence be replaced with
232        # some use of 'property-map' class?
233        if [ $(rproperties).get <runtime-debugging> ] = "on"
234        {
235            usage-requirements +=
236                <define>_STLP_DEBUG=1
237                <define>_STLP_DEBUG_UNINITIALIZED=1 ;
238        }
239        if [ $(rproperties).get <runtime-link> ] = "shared"
240        {
241            usage-requirements +=
242                <define>_STLP_USE_DYNAMIC_LIB=1 ;
243        }
244        if [ $(rproperties).get <stdlib-stlport:extensions> ] = noext
245        {
246            usage-requirements +=
247                <define>_STLP_NO_EXTENSIONS=1 ;
248        }
249        if [ $(rproperties).get <stdlib-stlport:iostream> ] = hostios
250        {
251            usage-requirements +=
252                <define>_STLP_NO_OWN_IOSTREAMS=1
253                <define>_STLP_HAS_NO_NEW_IOSTREAMS=1 ;
254        }
255        if $(self.version.5)
256        {
257            # Version 5.x
258            if [ $(rproperties).get <threading> ] = "single"
259            {
260                # Since STLport5 doesn't normally support single-thread
261                # we force STLport5 into the multi-thread mode. Hence
262                # getting what other libs provide of single-thread code
263                # linking against a multi-thread lib.
264                usage-requirements +=
265                    <define>_STLP_THREADS=1 ;
266            }
267        }
268
269        return [ property-set.create $(usage-requirements) ] ;
270    }
271}
272
273rule stlport-target ( headers ? : libraries * : version ? )
274{
275    local project = [ project.current ] ;
276
277    targets.main-target-alternative
278      [ new stlport-target-class  $(project) : $(headers) : $(libraries)
279        : $(version)
280      ] ;
281}
282
283local .version-subfeature-defined ;
284
285# Initialize stlport support.
286rule init (
287    version ? :
288    headers   :     # Location of header files
289    libraries *     # Location of libraries, lib and bin subdirs of STLport.
290    )
291{
292    # FIXME: need to use common.check-init-parameters here.
293    # At the moment, that rule always tries to define subfeature
294    # of the 'toolset' feature, while we need to define subfeature
295    # of <stdlib>stlport, so tweaks to check-init-parameters are needed.
296    if $(version)
297    {
298        if ! $(.version-subfeature-defined)
299        {
300            feature.subfeature stdlib stlport : version : : propagated ;
301            .version-subfeature-defined = true ;
302        }
303        feature.extend-subfeature stdlib stlport : version : $(version) ;
304    }
305
306    # Declare the main target for this STLPort version.
307    stlport-target $(headers) : $(libraries) : $(version) ;
308}
309
310