]>
Commit | Line | Data |
---|---|---|
1e59de90 TL |
1 | # Copyright 2003 Dave Abrahams |
2 | # Copyright 2002, 2003 Rene Rivera | |
3 | # Copyright 2002, 2003, 2004, 2005 Vladimir Prus | |
4 | # Distributed under the Boost Software License, Version 1.0. | |
5 | # (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt) | |
7c673cae FG |
6 | |
7 | # Defines the "symlink" special target. 'symlink' targets make symbolic links | |
8 | # to the sources. | |
9 | ||
10 | import targets modules path class os feature project property-set ; | |
11 | ||
12 | .count = 0 ; | |
13 | ||
14 | feature.feature symlink-location : project-relative build-relative : incidental ; | |
15 | ||
16 | # The class representing "symlink" targets. | |
17 | # | |
18 | class symlink-targets : basic-target | |
19 | { | |
20 | import numbers modules class property project path ; | |
1e59de90 | 21 | |
7c673cae FG |
22 | rule __init__ ( |
23 | project | |
24 | : targets * | |
25 | : sources * | |
26 | ) | |
1e59de90 | 27 | { |
7c673cae FG |
28 | # Generate a fake name for now. Need unnamed targets eventually. |
29 | local c = [ modules.peek symlink : .count ] ; | |
30 | modules.poke symlink : .count : [ numbers.increment $(c) ] ; | |
31 | local fake-name = symlink#$(c) ; | |
1e59de90 | 32 | |
7c673cae | 33 | basic-target.__init__ $(fake-name) : $(project) : $(sources) ; |
1e59de90 | 34 | |
7c673cae FG |
35 | # Remember the targets to map the sources onto. Pad or truncate |
36 | # to fit the sources given. | |
37 | self.targets = ; | |
38 | for local source in $(sources) | |
39 | { | |
40 | if $(targets) | |
41 | { | |
42 | self.targets += $(targets[1]) ; | |
43 | targets = $(targets[2-]) ; | |
44 | } | |
45 | else | |
46 | { | |
47 | self.targets += $(source) ; | |
48 | } | |
49 | } | |
1e59de90 | 50 | |
7c673cae FG |
51 | # The virtual targets corresponding to the given targets. |
52 | self.virtual-targets = ; | |
1e59de90 TL |
53 | } |
54 | ||
7c673cae FG |
55 | rule construct ( name : source-targets * : property-set ) |
56 | { | |
57 | local i = 1 ; | |
58 | for local t in $(source-targets) | |
59 | { | |
60 | local s = $(self.targets[$(i)]) ; | |
61 | local a = [ class.new action $(t) : symlink.ln : $(property-set) ] ; | |
1e59de90 | 62 | local vt = [ class.new file-target $(s:D=) |
7c673cae | 63 | : [ $(t).type ] : $(self.project) : $(a) ] ; |
1e59de90 | 64 | |
7c673cae FG |
65 | # Place the symlink in the directory relative to the project |
66 | # location, instead of placing it in the build directory. | |
67 | if [ property.select <symlink-location> : [ $(property-set).raw ] ] = <symlink-location>project-relative | |
68 | { | |
69 | $(vt).set-path [ path.root $(s:D) [ $(self.project).get location ] ] ; | |
70 | } | |
1e59de90 | 71 | |
7c673cae FG |
72 | self.virtual-targets += $(vt) ; |
73 | i = [ numbers.increment $(i) ] ; | |
74 | } | |
75 | return [ property-set.empty ] $(self.virtual-targets) ; | |
76 | } | |
77 | } | |
78 | ||
79 | # Creates a symbolic link from a set of targets to a set of sources. | |
80 | # The targets and sources map one to one. The symlinks generated are | |
81 | # limited to be the ones given as the sources. That is, the targets | |
82 | # are either padded or trimmed to equate to the sources. The padding | |
83 | # is done with the name of the corresponding source. For example:: | |
84 | # | |
85 | # symlink : one two ; | |
86 | # | |
87 | # Is equal to:: | |
88 | # | |
89 | # symlink one two : one two ; | |
90 | # | |
91 | # Names for symlink are relative to the project location. They cannot | |
92 | # include ".." path components. | |
93 | rule symlink ( | |
94 | targets * | |
95 | : sources * | |
96 | ) | |
97 | { | |
98 | local project = [ project.current ] ; | |
1e59de90 | 99 | |
7c673cae | 100 | return [ targets.main-target-alternative |
1e59de90 | 101 | [ class.new symlink-targets $(project) : $(targets) : |
7c673cae FG |
102 | # Note: inline targets are not supported for symlink, intentionally, |
103 | # since it's used to linking existing non-local targets. | |
104 | $(sources) ] ] ; | |
105 | } | |
106 | ||
107 | rule ln | |
108 | { | |
109 | local os ; | |
110 | if [ modules.peek : UNIX ] { os = UNIX ; } | |
111 | else { os ?= [ os.name ] ; } | |
112 | # Remember the path to make the link relative to where the symlink is located. | |
113 | local path-to-source = [ path.relative-to | |
114 | [ path.make [ on $(<) return $(LOCATE) ] ] | |
115 | [ path.make [ on $(>) return $(LOCATE) ] ] ] ; | |
116 | if $(path-to-source) = . | |
117 | { | |
118 | PATH_TO_SOURCE on $(<) = "" ; | |
119 | } | |
120 | else | |
121 | { | |
122 | PATH_TO_SOURCE on $(<) = [ path.native $(path-to-source) ] ; | |
123 | } | |
124 | ln-$(os) $(<) : $(>) ; | |
125 | } | |
126 | ||
127 | actions ln-UNIX | |
128 | { | |
129 | ln -f -s '$(>:D=:R=$(PATH_TO_SOURCE))' '$(<)' | |
130 | } | |
131 | ||
132 | # there is a way to do this; we fall back to a copy for now | |
133 | actions ln-NT | |
134 | { | |
135 | echo "NT symlinks not supported yet, making copy" | |
136 | del /f /q "$(<)" 2>nul >nul | |
137 | copy "$(>)" "$(<)" $(NULL_OUT) | |
138 | } | |
139 | ||
140 | IMPORT $(__name__) : symlink : : symlink ; |