]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/tools/build/src/tools/stage.jam
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / tools / build / src / tools / stage.jam
CommitLineData
7c673cae
FG
1# Copyright 2003 Dave Abrahams
2# Copyright 2005, 2006 Rene Rivera
3# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
20effc67 4# Copyright 2020 Dmitry Arkhipov
7c673cae
FG
5# Distributed under the Boost Software License, Version 1.0.
6# (See accompanying file LICENSE_1_0.txt or copy at
7# http://www.boost.org/LICENSE_1_0.txt)
8
20effc67
TL
9#| tag::doc[]
10
11[[bbv2.reference.modules.stage]]
12= stage
13This module defines the `install` rule, used to copy a set of targets to a
14single location.
15
16|# # end::doc[]
17
7c673cae
FG
18
19import "class" : new ;
20import feature ;
21import generators ;
20effc67 22import option ;
7c673cae
FG
23import path ;
24import project ;
20effc67 25import property ;
7c673cae
FG
26import targets ;
27import type ;
28import types/register ;
29import virtual-target ;
30
31
32feature.feature <install-dependencies> : off on : incidental ;
33feature.feature <install-type> : : free incidental ;
34feature.feature <install-source-root> : : free path ;
35feature.feature <so-version> : : free incidental ;
36
37# If 'on', version symlinks for shared libraries will not be created. Affects
38# Unix builds only.
39feature.feature <install-no-version-symlinks> : on : optional incidental ;
40
41
20effc67
TL
42#| tag::features-install-package-doc[]
43
44[[bbv2.builtin.features.install-package]]`install-package`::
45Specifies the name of the package to which installed files belong. This is
46used for default installation prefix on certain platforms.
47
48|# # end::features-install-package-doc[]
49
50feature.feature install-package : : free ;
51
52
53#| tag::doc[]
54
55[[bbv2.reference.modules.stage.add-install-dir]]
56. `rule add-install-dir ( name : suffix ? : parent ? : options * )`
57+
58Defines a named installation directory.
59+
60For example, `add-install-dir foo : bar : baz ;` creates feature
61<<bbv2.builtin.features.install-prefix,`<install-foo>`>> and adds support for
62named directory `(foo)` to `install` rule. The rule will try to use the value
63of `<install-foo>` property if present, otherwise will fallback to `(baz)/bar`.
64+
65Arguments:
66+
67* `name`: the name of the directory.
68* `suffix`: the path suffix appended to the parent named directory.
69* `parent`: the optional name of parent named directory.
70* `options`: special options that modify treatment of the directory.
71 Allowed options:
72+
73** `package-suffix`: append the package name to the default value. For example:
74+
75[source]
76----
77add-install-dir foo : bar : baz : package-suffix ;
78install (foo) : a : <install-package>xyz ;
79----
80+
81installs `a` into `(baz)/bar/xyz`.
82
83|# # end::doc[]
84
85.dirs = ;
86rule add-install-dir ( name : suffix ? : parent ? : options * )
87{
88 suffix ?= "" ;
89 if $(name) in $(.dirs)
90 {
91 import errors ;
92 errors.error Directory name $(name) is already registered. ;
93 }
94 feature.feature install-$(name) : : free ;
95 .dirs += $(name) ;
96 .dir.$(name) = $(suffix) $(parent) ;
97 .dir.$(name).options = $(options) ;
98}
99
100
101#| tag::doc[]
102
103. `rule install-dir-names ( )`
104+
105Returns names of all registered installation directories.
106
107|# # end::doc[]
108
109rule install-dir-names ( )
110{
111 return $(.dirs) ;
112}
113
114
115#| tag::features-install-prefix-doc[]
116
117[[bbv2.builtin.features.install-prefix]]`install-<name>`::
118Specifies installation prefix for <<bbv2.tasks.installing,`install`>> targets.
119These named installation prefixes are registered by default:
120+
121* `prefix`: `C:\<package name>` if `<target-os>windows` is in the property set,
122 `/usr/local` otherwise
123* `exec-prefix`: `(prefix)`
124* `bindir`: `(exec-prefix)/bin`
125* `sbindir`: `(exec-prefix)/sbin`
126* `libexecdir`: `(exec-prefix)/libexec`
127* `libdir`: `(exec-prefix)/lib`
128* `datarootdir`: `(prefix)/share`
129* `datadir`: `(datarootdir)`
130* `sysconfdir`: `(prefix)/etc`
131* `sharedstatedir`: `(prefix)/com`
132* `localstatedir`: `(prefix)/var`
133* `runstatedir`: `(localstatedir)/run`
134* `includedir`: `(prefix)/include`
135* `oldincludedir`: `/usr/include`
136* `docdir`: `(datarootdir)/doc/<package name>`
137* `infodir`: `(datarootdir)/info`
138* `htmldir`: `(docdir)`
139* `dvidir` : `(docdir)`
140* `pdfdir` : `(docdir)`
141* `psdir` : `(docdir)`
142* `lispdir`: `(datarootdir)/emacs/site-lisp`
143* `localedir`: `(datarootdir)/locale`
144* `mandir`: `(datarootdir)/man`
145
146If more are necessary, they could be added with
147<<bbv2.reference.modules.stage.add-install-dir,`stage.add-install-dir`>>.
148
149|# # end::features-install-prefix-doc[]
150
151feature.feature install-prefix : : free path ;
152add-install-dir exec-prefix : "" : prefix ;
153add-install-dir bindir : bin : exec-prefix ;
154add-install-dir sbindir : sbin : exec-prefix ;
155add-install-dir libexecdir : libexec : exec-prefix ;
156add-install-dir libdir : lib : exec-prefix ;
157add-install-dir datarootdir : share : prefix ;
158add-install-dir datadir : "" : datarootdir ;
159add-install-dir sysconfdir : etc : prefix ;
160add-install-dir sharedstatedir : com : prefix ;
161add-install-dir localstatedir : var : prefix ;
162add-install-dir runstatedir : run : localstatedir ;
163add-install-dir includedir : "include" : prefix ;
164add-install-dir oldincludedir : /usr/include ;
165add-install-dir docdir : doc : datarootdir : package-suffix ;
166add-install-dir infodir : info : datarootdir ;
167add-install-dir htmldir : "" : docdir ;
168add-install-dir dvidir : "" : docdir ;
169add-install-dir pdfdir : "" : docdir ;
170add-install-dir psdir : "" : docdir ;
171add-install-dir lispdir : emacs/site-lisp : datarootdir ;
172add-install-dir localedir : locale : datarootdir ;
173add-install-dir mandir : man : datarootdir ;
174
175
176#| tag::features-staging-prefix-doc[]
177
178[[bbv2.builtin.features.staging-prefix]]`staging-prefix`::
179Specifies staging prefix for <<bbv2.tasks.installing,`install`>> targets.
180If present, it will be used instead of the path to named directory `prefix`.
181Example:
182+
183[source]
184----
185project : requirements <install-prefix>x/y/z ;
186install a1 : a : <location>(bindir) ; # installs into x/y/z/bin
187install a2 : a : <location>(bindir) <staging-prefix>q ; # installs into q/bin
188----
189The feature is useful when you cannot (or don't want to) put build artfiacts
190into their intented locations during the build (such as when cross-compiling),
191but still need to communicate those intended locations to the build system,
192e.g. to generate configuration files.
193
194|# # end::features-staging-prefix-doc[]
195
196feature.feature staging-prefix : : free path ;
197
198
7c673cae
FG
199class install-target-class : basic-target
200{
201 import "class" : new ;
202 import feature ;
203 import generators ;
204 import path ;
205 import project ;
206 import property ;
207 import property-set ;
208 import stage ;
209 import type ;
210
211 rule __init__ ( name-and-dir : project : sources * : requirements * :
212 default-build * : usage-requirements * )
213 {
214 # The usage-requirements specified here are ignored but are taken as a
215 # parameter to have this metatarget class have the same standard
216 # instantiation interface as all the other Boost Build metatarget
217 # classes.
218 basic-target.__init__ $(name-and-dir) : $(project) : $(sources) :
219 $(requirements) : $(default-build) ;
220 }
221
222 # If <location> is not set, sets it based on the project data.
20effc67 223 # Either way, expands installation prefixes.
7c673cae
FG
224 rule update-location ( property-set )
225 {
20effc67
TL
226 local location = [ $(property-set).get <location> ] ;
227 local project-location = [ $(self.project).get location ] ;
228
229 local prefix ;
230 local suffix = $(location) ;
231 if $(suffix)
232 {
233 local rel = [ path.relative $(suffix) $(project-location)
234 : no-error ] ;
235 if not-a-child != $(rel)
236 {
237 suffix = $(rel) ;
238 }
239 }
240 suffix ?= $(self.name) ;
241 local matches = [ MATCH "^\\((.+)\\)(/(.*))?$" : $(suffix) ] ;
242
243 # if location can be split into named directory and optional trailing
244 # path, do the split and expand the name into path
245 if $(matches)
246 {
247 suffix = $(matches[3]) ;
248 suffix ?= "" ;
249 local package-name = [ stage.get-package-name $(property-set)
250 : [ $(self.project).project-module ] ] ;
251 prefix = [ stage.get-dir $(matches[1]) : $(property-set)
252 : $(package-name) : staged ] ;
253 }
254 # prefix location with the project's path
255 else if ! $(location)
7c673cae 256 {
20effc67
TL
257 prefix = $(project-location) ;
258 }
259
260 # only modify location if it's necessary
261 if $(prefix)
262 {
263 suffix = [ path.root $(suffix) $(prefix) ] ;
264 local properties = [ $(property-set).raw ] ;
265 properties = [ property.change $(properties) : <location> ] ;
266 property-set = [ property-set.create $(properties) <location>$(suffix) ] ;
7c673cae
FG
267 }
268
269 return $(property-set) ;
270 }
271
272 # Takes a target that is installed and a property set which is used when
273 # installing.
274 #
275 rule adjust-properties ( target : build-property-set )
276 {
277 local ps-raw ;
278 local a = [ $(target).action ] ;
279 if $(a)
280 {
281 local ps = [ $(a).properties ] ;
282 ps-raw = [ $(ps).raw ] ;
283
284 # Unless <hardcode-dll-paths>true is in properties, which can happen
285 # only if the user has explicitly requested it, nuke all <dll-path>
286 # properties.
287 if [ $(build-property-set).get <hardcode-dll-paths> ] != true
288 {
289 ps-raw = [ property.change $(ps-raw) : <dll-path> ] ;
290 }
291
292 # If any <dll-path> properties were specified for installing, add
293 # them.
294 local l = [ $(build-property-set).get <dll-path> ] ;
295 ps-raw += $(l:G=<dll-path>) ;
296
297 # Also copy <linkflags> feature from current build set, to be used
298 # for relinking.
299 local l = [ $(build-property-set).get <linkflags> ] ;
300 ps-raw += $(l:G=<linkflags>) ;
301
302 # Remove the <tag> feature on original targets.
303 ps-raw = [ property.change $(ps-raw) : <tag> ] ;
304
305 # And <location>. If stage target has another stage target in
306 # sources, then we shall get virtual targets with the <location>
307 # property set.
308 ps-raw = [ property.change $(ps-raw) : <location> ] ;
309 }
310
311 local d = [ $(build-property-set).get <dependency> ] ;
312 ps-raw += $(d:G=<dependency>) ;
313
314 local d = [ $(build-property-set).get <location> ] ;
315 ps-raw += $(d:G=<location>) ;
316
317 local ns = [ $(build-property-set).get <install-no-version-symlinks> ] ;
318 ps-raw += $(ns:G=<install-no-version-symlinks>) ;
319
320 local d = [ $(build-property-set).get <install-source-root> ] ;
321 # Make the path absolute: we shall use it to compute relative paths and
322 # making the path absolute will help.
323 if $(d)
324 {
325 d = [ path.root $(d) [ path.pwd ] ] ;
326 ps-raw += $(d:G=<install-source-root>) ;
327 }
328
329 if $(ps-raw)
330 {
331 return [ property-set.create $(ps-raw) ] ;
332 }
333 else
334 {
335 return [ property-set.empty ] ;
336 }
337 }
338
339 rule construct ( name : source-targets * : property-set )
340 {
341 source-targets = [ targets-to-stage $(source-targets) :
342 $(property-set) ] ;
343
344 property-set = [ update-location $(property-set) ] ;
345
346 local ename = [ $(property-set).get <name> ] ;
347
348 if $(ename) && $(source-targets[2])
349 {
350 import errors : error : $(__name__) : errors.error ;
351 errors.error When <name> property is used "in" 'install', only one
352 source is allowed. ;
353 }
354
355 local result ;
356 for local i in $(source-targets)
357 {
358 local staged-targets ;
359
360 local new-properties = [ adjust-properties $(i) :
361 $(property-set) ] ;
362
363 # See if something special should be done when staging this type. It
364 # is indicated by the presence of a special "INSTALLED_" type.
365 local t = [ $(i).type ] ;
366 if $(t) && [ type.registered INSTALLED_$(t) ]
367 {
368 if $(ename)
369 {
370 import errors : error : $(__name__) : errors.error ;
11fdf7f2 371 errors.error In "'install':" <name> property specified with
7c673cae
FG
372 target that requires relinking. ;
373 }
374 else
375 {
376 local targets = [ generators.construct $(self.project)
377 $(name) : INSTALLED_$(t) : $(new-properties) : $(i) ] ;
378 staged-targets += $(targets[2-]) ;
379 }
380 }
381 else
382 {
383 staged-targets = [ stage.copy-file $(self.project) $(ename) :
384 $(i) : $(new-properties) ] ;
385 }
386
387 if ! $(staged-targets)
388 {
389 import errors : error : $(__name__) : errors.error ;
390 errors.error Unable to generate staged version of
391 [ $(source).str ] ;
392 }
393
394 for t in $(staged-targets)
395 {
396 result += [ virtual-target.register $(t) ] ;
397 }
398 }
399
400 return [ property-set.empty ] $(result) ;
401 }
402
403 # Given the list of source targets explicitly passed to 'stage', returns the
404 # list of targets which must be staged.
405 #
406 rule targets-to-stage ( source-targets * : property-set )
407 {
408 local result ;
409
410 # Traverse the dependencies, if needed.
411 if [ $(property-set).get <install-dependencies> ] = "on"
412 {
413 source-targets = [ collect-targets $(source-targets) ] ;
414 }
415
416 # Filter the target types, if needed.
417 local included-types = [ $(property-set).get <install-type> ] ;
418 for local r in $(source-targets)
419 {
420 local ty = [ $(r).type ] ;
421 if $(ty)
422 {
423 # Do not stage searched libs.
424 if $(ty) != SEARCHED_LIB
425 {
426 if $(included-types)
427 {
428 if [ include-type $(ty) : $(included-types) ]
429 {
430 result += $(r) ;
431 }
432 }
433 else
434 {
435 result += $(r) ;
436 }
437 }
438 }
439 else if ! $(included-types)
440 {
441 # Do not install typeless targets if there is an explicit list
442 # of allowed types.
443 result += $(r) ;
444 }
445 }
446
447 return $(result) ;
448 }
449
450 # CONSIDER: figure out why we can not use virtual-target.traverse here.
451 #
452 rule collect-targets ( targets * )
453 {
454 # Find subvariants
455 local s ;
456 for local t in $(targets)
457 {
458 s += [ $(t).creating-subvariant ] ;
459 }
460 s = [ sequence.unique $(s) ] ;
461
462 local result = [ new set ] ;
463 $(result).add $(targets) ;
464
465 for local i in $(s)
466 {
467 $(i).all-referenced-targets $(result) ;
468 }
469 local result2 ;
470 for local r in [ $(result).list ]
471 {
472 if $(r:G) != <use>
473 {
474 result2 += $(r:G=) ;
475 }
476 }
477 DELETE_MODULE $(result) ;
478 return [ sequence.unique $(result2) ] ;
479 }
480
481 # Returns true iff 'type' is subtype of some element of 'types-to-include'.
482 #
483 local rule include-type ( type : types-to-include * )
484 {
485 local found ;
486 while $(types-to-include) && ! $(found)
487 {
488 if [ type.is-subtype $(type) $(types-to-include[1]) ]
489 {
490 found = true ;
491 }
492 types-to-include = $(types-to-include[2-]) ;
493 }
494
495 return $(found) ;
496 }
497}
498
499
500# Creates a copy of target 'source'. The 'properties' object should have a
501# <location> property which specifies where the target must be placed.
502#
503rule copy-file ( project name ? : source : properties )
504{
505 name ?= [ $(source).name ] ;
506 local relative ;
507
508 local new-a = [ new non-scanning-action $(source) : common.copy :
509 $(properties) ] ;
510 local source-root = [ $(properties).get <install-source-root> ] ;
511 if $(source-root)
512 {
513 # Get the real path of the target. We probably need to strip relative
514 # path from the target name at construction.
515 local path = [ $(source).path ] ;
516 path = [ path.root $(name:D) $(path) ] ;
517 # Make the path absolute. Otherwise, it would be hard to compute the
518 # relative path. The 'source-root' is already absolute, see the
519 # 'adjust-properties' method above.
520 path = [ path.root $(path) [ path.pwd ] ] ;
521
522 relative = [ path.relative-to $(source-root) $(path) ] ;
523 }
524
525 # Note: Using $(name:D=$(relative)) might be faster here, but then we would
526 # need to explicitly check that relative is not ".", otherwise we might get
527 # paths like '<prefix>/boost/.', try to create it and mkdir would obviously
528 # fail.
529 name = [ path.join $(relative) $(name:D=) ] ;
530
531 return [ new file-target $(name) exact : [ $(source).type ] : $(project) :
532 $(new-a) ] ;
533}
534
535
536rule symlink ( name : project : source : properties )
537{
538 local a = [ new action $(source) : symlink.ln : $(properties) ] ;
539 local t = [ new file-target $(name) exact : [ $(source).type ] : $(project)
540 : $(a) ] ;
541 return [ virtual-target.register $(t) ] ;
542}
543
544
545rule relink-file ( project : source : property-set )
546{
547 local action = [ $(source).action ] ;
548 local cloned-action = [ virtual-target.clone-action $(action) : $(project) :
549 "" : $(property-set) ] ;
550 return [ $(cloned-action).targets ] ;
551}
552
553
554# Declare installed version of the EXE type. Generator for this type will cause
555# relinking to the new location.
556type.register INSTALLED_EXE : : EXE ;
557
558
559class installed-exe-generator : generator
560{
561 import type ;
562 import property-set ;
563 import modules ;
564 import stage ;
565
566 rule __init__ ( )
567 {
568 generator.__init__ install-exe : EXE : INSTALLED_EXE ;
569 }
570
571 rule run ( project name ? : property-set : source : multiple ? )
572 {
573 local stage-rule = stage.copy-file ;
574
575 if ! [ $(property-set).get <os> ] in NT CYGWIN &&
576 ! [ $(property-set).get <target-os> ] in windows cygwin
577 {
578 # If dll-path properties have been changed for the stage target,
579 # relink instead of copying.
580 local a = [ $(source).action ] ;
581 local p = [ $(a).properties ] ;
582 local original = [ $(p).get <dll-path> ] ;
583 local current = [ $(property-set).get <dll-path> ] ;
584
585 if $(current) != $(original)
586 {
587 stage-rule = stage.relink-file ;
588 }
589 }
590
591 return [ $(stage-rule) $(project) : $(source) : $(property-set) ] ;
592 }
593}
594
595
596generators.register [ new installed-exe-generator ] ;
597
598
599# Installing a shared link on Unix might cause a creation of versioned symbolic
600# links.
601type.register INSTALLED_SHARED_LIB : : SHARED_LIB ;
602
603
604class installed-shared-lib-generator : generator
605{
606 import type ;
607 import property-set ;
608 import modules ;
609 import stage ;
610
611 rule __init__ ( )
612 {
613 generator.__init__ install-shared-lib : SHARED_LIB :
614 INSTALLED_SHARED_LIB ;
615 }
616
617 rule run ( project name ? : property-set : source : multiple ? )
618 {
619 if [ $(property-set).get <os> ] in NT CYGWIN ||
620 [ $(property-set).get <target-os> ] in windows cygwin
621 {
622 local copied = [ stage.copy-file $(project) : $(source) :
623 $(property-set) ] ;
624 return [ virtual-target.register $(copied) ] ;
625 }
626 else
627 {
628 local a = [ $(source).action ] ;
629 local copied ;
630 if ! $(a)
631 {
632 # Non-derived file, just copy.
633 copied = [ stage.copy-file $(project) : $(source) :
634 $(property-set) ] ;
635 }
636 else
637 {
638 local cp = [ $(a).properties ] ;
639 local current-dll-path = [ $(cp).get <dll-path> ] ;
640 local new-dll-path = [ $(property-set).get <dll-path> ] ;
641
642 if $(current-dll-path) != $(new-dll-path)
643 {
644 # Rpath changed, need to relink.
645 copied = [ stage.relink-file $(project) : $(source) :
646 $(property-set) ] ;
647 }
648 else
649 {
650 copied = [ stage.copy-file $(project) : $(source) :
651 $(property-set) ] ;
652 }
653 }
654
655 copied = [ virtual-target.register $(copied) ] ;
656
657 local result = $(copied) ;
658 # If the name is in the form NNN.XXX.YYY.ZZZ, where all 'X', 'Y' and
659 # 'Z' are numbers, we need to create NNN.XXX and NNN.XXX.YYY
660 # symbolic links.
661 local m = [ MATCH
11fdf7f2 662 "(.*)\\.([0123456789]+)\\.([0123456789]+)\\.([0123456789]+)$" :
7c673cae
FG
663 [ $(copied).name ] ] ;
664 if $(m)
665 {
666 # Symlink without version at all is used to make
667 # -lsome_library work.
668 result += [ stage.symlink $(m[1]) : $(project) : $(copied) :
669 $(property-set) ] ;
670
671 # Symlinks of some libfoo.N and libfoo.N.M are used so that
672 # library can found at runtime, if libfoo.N.M.X has soname of
673 # libfoo.N. That happens when the library makes some binary
674 # compatibility guarantees. If not, it is possible to skip those
675 # symlinks.
676 local suppress = [ $(property-set).get
677 <install-no-version-symlinks> ] ;
678
679 if $(suppress) != "on"
680 {
681 result += [ stage.symlink $(m[1]).$(m[2]) : $(project) :
682 $(copied) : $(property-set) ] ;
683 result += [ stage.symlink $(m[1]).$(m[2]).$(m[3]) :
684 $(project) : $(copied) : $(property-set) ] ;
685 }
686 }
687
688 return $(result) ;
689 }
690 }
691}
692
693generators.register [ new installed-shared-lib-generator ] ;
694
695
20effc67
TL
696#| tag::doc[]
697
698. `rule get-dir ( name : property-set : package-name : flags * )`
699+
700Returns the path to a named installation directory. For a given `name=xyz` the
701rule uses the value of `<install-xyz>` property if it is present in
702`property-set`. Otherwise it tries to construct the default value of the path
703recursively getting the path to ``name``'s registered base named directory and
704relative path. For example:
705+
706[source]
707----
708stage.add-install-dir foo : bar : baz ;
709
710local ps = [ property-set.create <install-foo>x/y/z ] ;
711echo [ stage.get-dir foo : $(ps) : $(__name__) ] ; # outputs x/y/z
712
713ps = [ property-set.create <install-baz>a/b/c/d ] ;
714echo [ stage.get-dir foo : $(ps) : $(__name__) ] ; # outputs a/b/c/d/bar
715----
716+
717The argument `package-name` is used to construct the path for named directories
718that were registered with `package-suffix` option and also to construct
719`install-prefix` when targeting Windows.
720+
721Available `flags`:
722+
723* `staged`: take <<bbv2.builtin.features.staging-prefix,`staging-prefix`>> into
724 account.
725* `relative`: return the path to `name` relative to its base directory.
726
727|# # end::doc[]
728
729rule get-dir ( name : property-set : package-name : flags * )
730{
731 local result ;
732
733 # We treat the 'prefix' directory in a special way, because it's default
734 # is based on the value of <target-os> property.
735 if $(name) = prefix
736 {
737 result = [ get-install-prefix $(property-set) : $(package-name)
738 : $(flags) ] ;
739 }
740 else
741 {
742 # First, try getting the path for requested directory from properties.
743 result = [ $(property-set).get <install-$(name)> ] ;
744 local info = [ get-dir-info $(name) : $(package-name) ] ;
745 # Otherwise, use the default path. In both cases, it could be a
746 # relative path.
747 result ?= $(info[1]) ;
748 if $(result)
749 {
750 result = [ path.make $(result) ] ;
751 }
752
753 # If there is a base directory, we may need to modify result further.
754 if $(info[2])
755 {
756 local base = [ get-dir $(info[2]) : $(property-set)
757 : $(package-name) : $(flags) ] ;
758 if relative in $(flags)
759 {
760 local rel = [ path.relative $(result) $(base) : no-error ] ;
761 if not-a-child != $(rel)
762 {
763 result = $(rel) ;
764 }
765 }
766 else
767 {
768 result = [ path.root $(result) $(base) ] ;
769 }
770 }
771 }
772
773 return $(result) ;
774}
775
776
777# For a given named directory returns its parent directory and relative path
778local rule get-dir-info ( name : package-name ) {
779 local path = $(.dir.$(name)[1]) ;
780 if ! x$(path)
781 {
782 import errors ;
783 errors.error $(name) is not an installation directory name. ;
784 }
785
786 if package-suffix in $(.dir.$(name).options)
787 {
788 path = [ path.join $(path) $(package-name) ] ;
789 }
790
791 return $(path) $(.dir.$(name)[2]) ;
792}
793
794
795local rule get-install-prefix ( property-set : package-name : flags * )
796{
797 local prefix ;
798 if staged in $(flags)
799 {
800 prefix = [ $(property-set).get <staging-prefix> ] ;
801 }
802 prefix ?= [ $(property-set).get <install-prefix> ] ;
803 prefix = $(prefix[0]) ;
804 prefix ?= [ option.get prefix ] ;
805 if ! $(prefix)
806 {
807 if windows = [ $(property-set).get <target-os> ]
808 {
809 prefix = C:\\$(package-name) ;
810 }
811 else
812 {
813 prefix = /usr/local ;
814 }
815 }
816 return [ path.make $(prefix) ] ;
817}
818
819
820#| tag::doc[]
821
822. `rule get-package-name ( property-set : project-module ? )`
823+
824Returns the package name that will be used for `install` targets when
825constructing installation location. The rule uses the value of
826<<bbv2.builtin.features.install-package,`<install-package>`>> property if it's
827present in `property-set`. Otherwise it deduces the package name using
828``project-module``'s attributes. It traverses the project hierarchy up to the
829root searching for the first project with an id. If none is found, the base
830name of the root project's location is used. If `project-module` is empty, the
831caller module is used (this allows invoking just `[ get-package-name $(ps) ]`
832in project jam files).
833
834|# # end::doc[]
835
836rule get-package-name ( property-set : project-module ? )
837{
838 local package = [ $(property-set).get <install-package> ] ;
839 if ! $(package)
840 {
841 project-module ?= [ CALLER_MODULE 1 ] ;
842
843 local m = $(project-module) ;
844 package = [ project.attribute $(m) id ] ;
845 while ! $(package)
846 {
847 m = [ project.attribute $(m) parent-module ] ;
848 if ! $(m) { break ; }
849
850 package = [ project.attribute $(m) id ] ;
851 }
852
853 if ! $(package)
854 {
855 local root = [ project.attribute $(project-module) project-root ] ;
856 package = [ path.root $(root) [ path.pwd ] ] ;
857 }
858
859 package = $(package:B) ;
860 }
861 return $(package) ;
862}
863
864
865rule stage-translate-path ( feature value : properties * : project-id : project-location )
866{
867 if $(feature) = <location> && [ MATCH "^\\((.+)\\)(/(.*))?$" : $(value) ]
868 {
869 return $(value) ;
870 }
871}
872
873
7c673cae
FG
874# Main target rule for 'install'.
875#
876rule install ( name : sources * : requirements * : default-build * )
877{
878 local project = [ project.current ] ;
879
880 # Unless the user has explicitly asked us to hardcode dll paths, add
881 # <hardcode-dll-paths>false in requirements, to override default value.
882 if ! <hardcode-dll-paths>true in $(requirements)
883 {
884 requirements += <hardcode-dll-paths>false ;
885 }
886
887 if <tag> in $(requirements:G)
888 {
889 import errors ;
890 errors.user-error The <tag> property is not allowed for the 'install'
891 rule. ;
892 }
893
894 targets.create-metatarget install-target-class : $(project) : $(name) :
20effc67 895 $(sources) : $(requirements) <translate-path>@stage-translate-path : $(default-build) ;
7c673cae
FG
896}
897
898
899IMPORT $(__name__) : install : : install ;
900IMPORT $(__name__) : install : : stage ;
20effc67 901IMPORT $(__name__) : stage-translate-path : : stage-translate-path ;