]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/build/build-request.jam
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / tools / build / src / build / build-request.jam
1 # Copyright 2002 Dave Abrahams
2 # Distributed under the Boost Software License, Version 1.0.
3 # (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt)
4
5 import "class" : new ;
6 import sequence ;
7 import set ;
8 import regex ;
9 import feature ;
10 import property ;
11 import container ;
12 import string ;
13
14
15 # Transform property-set by applying f to each component property.
16 #
17 local rule apply-to-property-set ( f property-set )
18 {
19 local properties = [ feature.split $(property-set) ] ;
20 return [ string.join [ $(f) $(properties) ] : / ] ;
21 }
22
23
24 # Expand the given build request by combining all property-sets which do not
25 # specify conflicting non-free features. Expects all the project files to
26 # already be loaded.
27 #
28 rule expand-no-defaults ( property-sets * )
29 {
30 # First make all features and subfeatures explicit.
31 local expanded-property-sets = [ sequence.transform apply-to-property-set
32 feature.expand-subfeatures : $(property-sets) ] ;
33
34 # Now combine all of the expanded property-sets
35 local product = [ x-product $(expanded-property-sets) : $(feature-space) ] ;
36
37 return $(product) ;
38 }
39
40
41 # Update the list of expected conflicts based on the new
42 # features.
43 #
44 local rule remove-conflicts ( conflicts * : features * )
45 {
46 local result ;
47 for local c in $(conflicts)
48 {
49 if ! [ set.intersection [ regex.split $(c) "/" ] : $(features) ]
50 {
51 result += $(c) ;
52 }
53 }
54 return $(result) ;
55 }
56
57
58 # Implementation of x-product, below. Expects all the project files to already
59 # be loaded.
60 #
61 local rule x-product-aux ( property-sets + )
62 {
63 local result ;
64 local p = [ feature.split $(property-sets[1]) ] ;
65 local f = [ set.difference $(p:G) : [ feature.free-features ] ] ;
66 local seen ;
67 local extra-conflicts ;
68
69 # No conflict with things used at a higher level?
70 if ! [ set.intersection $(f) : $(x-product-used) ]
71 {
72 local x-product-seen ;
73 local x-product-conflicts =
74 [ remove-conflicts $(x-product-conflicts) : $(f) ] ;
75 {
76 # Do not mix in any conflicting features.
77 local x-product-used = $(x-product-used) $(f) ;
78
79 if $(property-sets[2])
80 {
81 local rest = [ x-product-aux $(property-sets[2-]) ] ;
82 result = $(property-sets[1])/$(rest) ;
83 }
84 if ! $(x-product-conflicts)
85 {
86 result ?= $(property-sets[1]) ;
87 }
88 }
89
90 # If we did not encounter a conflicting feature lower down, do not
91 # recurse again.
92 if ! [ set.intersection $(f) : $(x-product-seen) ]
93 || [ remove-conflicts $(x-product-conflicts) : $(x-product-seen) ]
94 {
95 property-sets = ;
96 }
97 else
98 {
99 # A property is only allowed to be absent if it conflicts
100 # with either a higher or lower layer. We don't need to
101 # bother setting this if we already know that we don't need
102 # to recurse again.
103 extra-conflicts = $(f:J=/) ;
104 }
105
106 seen = $(x-product-seen) ;
107 }
108
109 if $(property-sets[2])
110 {
111 # Lower layers expansion must conflict with this
112 local x-product-conflicts = $(x-product-conflicts) $(extra-conflicts) ;
113
114 result += [ x-product-aux $(property-sets[2-]) ] ;
115 }
116
117 # Note that we have seen these features so that higher levels will recurse
118 # again without them set.
119 x-product-seen += $(f) $(seen) ;
120 return $(result) ;
121 }
122
123
124 # Return the cross-product of all elements of property-sets, less any that would
125 # contain conflicting values for single-valued features. Expects all the project
126 # files to already be loaded.
127 #
128 # Formal definition:
129 # Returns all maximum non-conflicting subsets of property-sets.
130 # The result is a list of all property-sets p such that
131 # 1. p is composed by joining a subset of property-sets without removing
132 # duplicates
133 # 2. p contains at most one instance of every single-valued feature
134 # 3. Adding any additional element of property-sets to p be would
135 # violate (2)
136 local rule x-product ( property-sets * )
137 {
138 if $(property-sets).non-empty
139 {
140 # Prepare some "scoped globals" that can be used by the implementation
141 # function, x-product-aux.
142 local x-product-seen x-product-used x-product-conflicts ;
143 return [ x-product-aux $(property-sets) : $(feature-space) ] ;
144 }
145 # Otherwise return empty.
146 }
147
148
149 # Returns true if either 'v' or the part of 'v' before the first '-' symbol is
150 # an implicit value. Expects all the project files to already be loaded.
151 #
152 local rule looks-like-implicit-value ( v )
153 {
154 if [ feature.is-implicit-value $(v) ]
155 {
156 return true ;
157 }
158 else
159 {
160 local split = [ regex.split $(v) - ] ;
161 if [ feature.is-implicit-value $(split[1]) ]
162 {
163 return true ;
164 }
165 }
166 }
167
168
169 # Takes the command line tokens (such as taken from the ARGV rule) and
170 # constructs a build request from them. Returns a vector of two vectors (where
171 # "vector" means container.jam's "vector"). First is the set of targets
172 # specified in the command line, and second is the set of requested build
173 # properties. Expects all the project files to already be loaded.
174 #
175 rule from-command-line ( command-line * )
176 {
177 local targets ;
178 local properties ;
179
180 command-line = $(command-line[2-]) ;
181 local skip-next = ;
182 for local e in $(command-line)
183 {
184 if $(skip-next)
185 {
186 skip-next = ;
187 }
188 else if ! [ MATCH ^(-) : $(e) ]
189 {
190 # Build request spec either has "=" in it or completely consists of
191 # implicit feature values.
192 local fs = feature-space ;
193 if [ MATCH "(.*=.*)" : $(e) ]
194 || [ looks-like-implicit-value $(e:D=) : $(feature-space) ]
195 {
196 properties += $(e) ;
197 }
198 else if $(e)
199 {
200 targets += $(e) ;
201 }
202 }
203 else if [ MATCH "^(-[-ldjfsto])$" : $(e) ]
204 {
205 skip-next = true ;
206 }
207 }
208 return [ new vector
209 [ new vector $(targets) ]
210 [ new vector $(properties) ] ] ;
211 }
212
213
214 # Converts a list of elements of command line build request specification into internal
215 # form. Expects all the project files to already be loaded.
216 #
217 rule convert-command-line-elements ( elements * )
218 {
219 local result ;
220 for local e in $(elements)
221 {
222 result += [ convert-command-line-element $(e) ] ;
223 }
224 return $(result) ;
225 }
226
227
228 # Converts one element of command line build request specification into internal
229 # form.
230 local rule convert-command-line-element ( e )
231 {
232 local result ;
233 local parts = [ regex.split $(e) "/" ] ;
234 while $(parts)
235 {
236 local p = $(parts[1]) ;
237 local m = [ MATCH "([^=]*)=(.*)" : $(p) ] ;
238 local lresult ;
239 local feature ;
240 local values ;
241 if $(m)
242 {
243 feature = $(m[1]) ;
244 values = [ regex.split $(m[2]) "," ] ;
245 lresult = <$(feature)>$(values) ;
246 }
247 else
248 {
249 lresult = [ regex.split $(p) "," ] ;
250 }
251
252 if $(feature) && free in [ feature.attributes <$(feature)> ]
253 {
254 # If we have free feature, then the value is everything
255 # until the end of the command line token. Slashes in
256 # the following string are not taked to mean separation
257 # of properties. Commas are also not interpreted specially.
258 values = $(values:J=,) ;
259 values = $(values) $(parts[2-]) ;
260 values = $(values:J=/) ;
261 lresult = ;
262 # Optional free features will ignore empty value arguments.
263 if optional in [ feature.attributes <$(feature)> ]
264 {
265 for local v in $(values)
266 {
267 if $(v)
268 {
269 lresult += <$(feature)>$(v) ;
270 }
271 }
272 }
273 else
274 {
275 lresult = <$(feature)>$(values) ;
276 }
277 parts = ;
278 }
279
280 if ! [ MATCH (.*-.*) : $(p) ]
281 {
282 # property.validate cannot handle subfeatures, so we avoid the check
283 # here.
284 for local p in $(lresult)
285 {
286 property.validate $(p) : $(feature-space) ;
287 }
288 }
289
290 if $(lresult)
291 {
292 if ! $(result)
293 {
294 result = $(lresult) ;
295 }
296 else
297 {
298 result = $(result)/$(lresult) ;
299 }
300 }
301
302 parts = $(parts[2-]) ;
303 }
304
305 return $(result) ;
306 }
307
308
309 rule __test__ ( )
310 {
311 import assert ;
312 import feature ;
313
314 feature.prepare-test build-request-test-temp ;
315
316 import build-request ;
317 import build-request : expand-no-defaults : build-request.expand-no-defaults ;
318 import errors : try catch ;
319 import feature : feature subfeature ;
320
321 feature toolset : gcc msvc borland : implicit ;
322 subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4
323 3.0 3.0.1 3.0.2 : optional ;
324
325 feature variant : debug release : implicit composite ;
326 feature inlining : on off ;
327 feature "include" : : free ;
328
329 feature stdlib : native stlport : implicit ;
330
331 feature runtime-link : dynamic static : symmetric ;
332
333 # Empty build requests should expand to empty.
334 assert.result
335 : build-request.expand-no-defaults ;
336
337 assert.result
338 <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug
339 <toolset>msvc/<stdlib>stlport/<variant>debug
340 <toolset>msvc/<variant>debug
341 : build-request.expand-no-defaults gcc-3.0.1/stlport msvc/stlport msvc debug ;
342
343 assert.result
344 <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug
345 <toolset>msvc/<variant>debug
346 <variant>debug/<toolset>msvc/<stdlib>stlport
347 : build-request.expand-no-defaults gcc-3.0.1/stlport msvc debug msvc/stlport ;
348
349 assert.result
350 <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug/<inlining>off
351 <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>release/<inlining>off
352 : build-request.expand-no-defaults gcc-3.0.1/stlport debug release <inlining>off ;
353
354 assert.result
355 <include>a/b/c/<toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug/<include>x/y/z
356 <include>a/b/c/<toolset>msvc/<stdlib>stlport/<variant>debug/<include>x/y/z
357 <include>a/b/c/<toolset>msvc/<variant>debug/<include>x/y/z
358 : build-request.expand-no-defaults <include>a/b/c gcc-3.0.1/stlport msvc/stlport msvc debug <include>x/y/z ;
359
360 local r ;
361
362 try ;
363 {
364 r = [ build-request.from-command-line bjam gcc/debug runtime-link=dynamic/static ] ;
365 build-request.convert-command-line-elements [ $(r).get-at 2 ] ;
366 }
367 catch \"static\" is not an implicit feature value ;
368
369 r = [ build-request.from-command-line bjam debug runtime-link=dynamic ] ;
370 assert.equal [ $(r).get-at 1 ] : ;
371 assert.equal [ $(r).get-at 2 ] : debug runtime-link=dynamic ;
372
373 assert.equal
374 [ build-request.convert-command-line-elements debug runtime-link=dynamic ]
375 : debug <runtime-link>dynamic ;
376
377 r = [ build-request.from-command-line bjam -d2 --debug debug target runtime-link=dynamic ] ;
378 assert.equal [ $(r).get-at 1 ] : target ;
379 assert.equal [ $(r).get-at 2 ] : debug runtime-link=dynamic ;
380
381 assert.equal
382 [ build-request.convert-command-line-elements debug runtime-link=dynamic ]
383 : debug <runtime-link>dynamic ;
384
385 r = [ build-request.from-command-line bjam debug runtime-link=dynamic,static ] ;
386 assert.equal [ $(r).get-at 1 ] : ;
387 assert.equal [ $(r).get-at 2 ] : debug runtime-link=dynamic,static ;
388
389 assert.equal
390 [ build-request.convert-command-line-elements debug runtime-link=dynamic,static ]
391 : debug <runtime-link>dynamic <runtime-link>static ;
392
393 r = [ build-request.from-command-line bjam debug gcc/runtime-link=dynamic,static ] ;
394 assert.equal [ $(r).get-at 1 ] : ;
395 assert.equal [ $(r).get-at 2 ] : debug gcc/runtime-link=dynamic,static ;
396
397 assert.equal
398 [ build-request.convert-command-line-elements debug gcc/runtime-link=dynamic,static ]
399 : debug gcc/<runtime-link>dynamic gcc/<runtime-link>static ;
400
401 r = [ build-request.from-command-line bjam msvc gcc,borland/runtime-link=static ] ;
402 assert.equal [ $(r).get-at 1 ] : ;
403 assert.equal [ $(r).get-at 2 ] : msvc gcc,borland/runtime-link=static ;
404
405 assert.equal
406 [ build-request.convert-command-line-elements msvc gcc,borland/runtime-link=static ]
407 : msvc gcc/<runtime-link>static borland/<runtime-link>static ;
408
409 r = [ build-request.from-command-line bjam gcc-3.0 ] ;
410 assert.equal [ $(r).get-at 1 ] : ;
411 assert.equal [ $(r).get-at 2 ] : gcc-3.0 ;
412
413 assert.equal
414 [ build-request.convert-command-line-elements gcc-3.0 ]
415 : gcc-3.0 ;
416
417 feature.finish-test build-request-test-temp ;
418 }