]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | # Copyright (c) 2010 Vladimir Prus. |
2 | # Copyright (c) 2013 Steven Watanabe | |
3 | # | |
4 | # Use, modification and distribution is subject to the Boost Software | |
5 | # License Version 1.0. (See accompanying file LICENSE_1_0.txt or | |
6 | # http://www.boost.org/LICENSE_1_0.txt) | |
7 | ||
8 | import property-set ; | |
9 | import path ; | |
10 | import modules ; | |
11 | import "class" ; | |
12 | import errors ; | |
13 | import configure ; | |
14 | import project ; | |
15 | import virtual-target ; | |
16 | import generators ; | |
17 | import property ; | |
18 | import print ; | |
19 | import regex ; | |
20 | ||
21 | project.initialize $(__name__) ; | |
22 | .project = [ project.current ] ; | |
23 | project ac ; | |
24 | ||
25 | rule generate-include ( target : sources * : properties * ) | |
26 | { | |
27 | local header = [ property.select <include> : $(properties) ] ; | |
28 | print.output $(target) ; | |
29 | print.text "#include <$(header:G=)>\n" : true ; | |
30 | } | |
31 | ||
32 | rule generate-main ( target : sources * : properties * ) | |
33 | { | |
34 | print.output $(target) ; | |
35 | print.text "int main() {}" : true ; | |
36 | } | |
37 | ||
38 | rule find-include-path ( properties : header : provided-path ? ) | |
39 | { | |
40 | if $(provided-path) && [ path.exists [ path.root $(header) $(provided-path) ] ] | |
41 | { | |
42 | return $(provided-path) ; | |
43 | } | |
44 | else | |
45 | { | |
46 | local a = [ class.new action : ac.generate-include : [ property-set.create <include>$(header) ] ] ; | |
47 | # Create a new CPP target named after the header. | |
48 | # Replace dots (".") in target basename for portability. | |
49 | local basename = [ regex.replace $(header:D=) "[.]" "_" ] ; | |
50 | local header-target = $(header:S=:B=$(basename)) ; | |
51 | local cpp = [ class.new file-target $(header-target:S=.cpp) exact : CPP : $(.project) : $(a) ] ; | |
52 | cpp = [ virtual-target.register $(cpp) ] ; | |
53 | local result = [ generators.construct $(.project) $(header-target) : OBJ : $(properties) : $(cpp) : true ] ; | |
54 | local jam-targets ; | |
55 | for t in $(result[2-]) | |
56 | { | |
57 | jam-targets += [ $(t).actualize ] ; | |
58 | } | |
59 | if [ UPDATE_NOW $(jam-targets) : [ modules.peek configure : .log-fd ] | |
60 | : ignore-minus-n : ignore-minus-q ] | |
61 | { | |
62 | return %default ; | |
63 | } | |
64 | } | |
65 | } | |
66 | ||
67 | rule construct-library ( name : property-set : provided-path ? ) | |
68 | { | |
69 | property-set = [ $(property-set).refine [ property-set.create $(link-opt) ] ] ; | |
70 | local lib-props = [ $(property-set).add-raw <name>$(name) <search>$(provided-path) ] ; | |
71 | return [ generators.construct $(.project) lib-$(name) | |
72 | : SEARCHED_LIB : $(lib-props) : : true ] ; | |
73 | } | |
74 | ||
75 | ||
76 | rule find-library ( properties : names + : provided-path ? ) | |
77 | { | |
78 | local result ; | |
7c673cae FG |
79 | if [ $(properties).get <link> ] = shared |
80 | { | |
81 | link-opts = <link>shared <link>static ; | |
82 | } | |
83 | else | |
84 | { | |
85 | link-opts = <link>static <link>shared ; | |
86 | } | |
87 | while $(link-opts) | |
88 | { | |
89 | local names-iter = $(names) ; | |
90 | properties = [ $(properties).refine [ property-set.create $(link-opts[1]) ] ] ; | |
91 | while $(names-iter) | |
92 | { | |
93 | local name = $(names-iter[1]) ; | |
94 | local lib = [ construct-library $(name) : $(properties) : $(provided-path) ] ; | |
b32b8144 FG |
95 | local a = [ class.new action : ac.generate-main : |
96 | [ property-set.empty ] ] ; | |
97 | local main.cpp = [ virtual-target.register | |
98 | [ class.new file-target main-$(name).cpp exact : CPP : $(.project) : $(a) ] ] ; | |
7c673cae | 99 | local test = [ generators.construct $(.project) $(name) : EXE |
b32b8144 | 100 | : [ $(properties).add $(lib[1]) ] : $(main.cpp) $(lib[2-]) |
7c673cae FG |
101 | : true ] ; |
102 | local jam-targets ; | |
103 | for t in $(test[2-]) | |
104 | { | |
105 | jam-targets += [ $(t).actualize ] ; | |
106 | } | |
107 | if [ UPDATE_NOW $(jam-targets) : [ modules.peek configure : .log-fd ] | |
108 | : ignore-minus-n : ignore-minus-q ] | |
109 | { | |
110 | result = $(name) $(link-opts[1]) ; | |
111 | names-iter = ; link-opts = ; # break | |
112 | } | |
113 | names-iter = $(names-iter[2-]) ; | |
114 | } | |
115 | link-opts = $(link-opts[2-]) ; | |
116 | } | |
117 | return $(result) ; | |
118 | } | |
119 | ||
120 | class ac-library : basic-target | |
121 | { | |
122 | import errors ; | |
123 | import indirect ; | |
124 | import virtual-target ; | |
125 | import ac ; | |
126 | import configure ; | |
127 | import config-cache ; | |
128 | ||
129 | rule __init__ ( name : project : requirements * : include-path ? : library-path ? : library-name ? ) | |
130 | { | |
131 | basic-target.__init__ $(name) : $(project) : : $(requirements) ; | |
132 | ||
133 | reconfigure $(include-path) : $(library-path) : $(library-name) ; | |
134 | } | |
135 | ||
136 | rule set-header ( header ) | |
137 | { | |
138 | self.header = $(header) ; | |
139 | } | |
140 | ||
141 | rule set-default-names ( names + ) | |
142 | { | |
143 | self.default-names = $(names) ; | |
144 | } | |
145 | ||
146 | rule reconfigure ( include-path ? : library-path ? : library-name ? ) | |
147 | { | |
148 | if $(include-path) || $(library-path) || $(library-name) | |
149 | { | |
150 | check-not-configured ; | |
151 | ||
152 | self.include-path = $(include-path) ; | |
153 | self.library-path = $(library-path) ; | |
154 | self.library-name = $(library-name) ; | |
155 | } | |
156 | } | |
157 | ||
158 | rule set-target ( target ) | |
159 | { | |
160 | check-not-configured ; | |
161 | self.target = $(target) ; | |
162 | } | |
163 | ||
164 | rule check-not-configured ( ) | |
165 | { | |
166 | if $(self.include-path) || $(self.library-path) || $(self.library-name) || $(self.target) | |
167 | { | |
168 | errors.user-error [ name ] "is already configured" ; | |
169 | } | |
170 | } | |
171 | ||
172 | rule construct ( name : sources * : property-set ) | |
173 | { | |
174 | if $(self.target) | |
175 | { | |
176 | return [ $(self.target).generate $(property-set) ] ; | |
177 | } | |
178 | else | |
179 | { | |
180 | local use-environment ; | |
181 | if ! $(self.library-name) && ! $(self.include-path) && ! $(self.library-path) | |
182 | { | |
183 | use-environment = true ; | |
184 | } | |
185 | local libnames = $(self.library-name) ; | |
186 | if ! $(libnames) && $(use-environment) | |
187 | { | |
188 | libnames = [ modules.peek : $(name:U)_NAME ] ; | |
189 | # Backward compatibility only. | |
190 | libnames ?= [ modules.peek : $(name:U)_BINARY ] ; | |
191 | } | |
192 | libnames ?= $(self.default-names) ; | |
193 | ||
194 | local include-path = $(self.include-path) ; | |
195 | if ! $(include-path) && $(use-environment) | |
196 | { | |
197 | include-path = [ modules.peek : $(name:U)_INCLUDE ] ; | |
198 | } | |
199 | ||
200 | local library-path = $(self.library-path) ; | |
201 | if ! $(library-path) && $(use-environment) | |
202 | { | |
203 | library-path = [ modules.peek : $(name:U)_LIBRARY_PATH ] ; | |
204 | # Backwards compatibility only | |
205 | library-path ?= [ modules.peek : $(name:U)_LIBPATH ] ; | |
206 | } | |
207 | ||
208 | local toolset = [ $(property-set).get <toolset> ] ; | |
209 | local toolset-version-property = "<toolset-$(toolset):version>" ; | |
210 | local relevant = [ property.select <target-os> <toolset> | |
211 | $(toolset-version-property) <link> <address-model> <architecture> : | |
212 | [ $(property-set).raw ] ] ; | |
213 | ||
214 | local key = ac-library-$(name)-$(relevant:J=-) ; | |
215 | local lookup = [ config-cache.get $(key) ] ; | |
216 | ||
217 | if $(lookup) | |
218 | { | |
219 | if $(lookup) = missing | |
220 | { | |
221 | configure.log-library-search-result $(name) : "no (cached)" ; | |
222 | return [ property-set.empty ] ; | |
223 | } | |
224 | else | |
225 | { | |
226 | local includes = $(lookup[1]) ; | |
227 | if $(includes) = %default | |
228 | { | |
229 | includes = ; | |
230 | } | |
231 | local library = [ ac.construct-library $(lookup[2]) : | |
232 | [ $(property-set).refine [ property-set.create $(lookup[3]) ] ] : $(library-path) ] ; | |
233 | configure.log-library-search-result $(name) : "yes (cached)" ; | |
234 | return [ $(library[1]).add-raw <include>$(includes) ] $(library[2-]) ; | |
235 | } | |
236 | } | |
237 | else | |
238 | { | |
239 | local includes = [ ac.find-include-path $(property-set) : $(self.header) : $(include-path) ] ; | |
240 | local library = [ ac.find-library $(property-set) : $(libnames) : $(library-path) ] ; | |
241 | if $(includes) && $(library) | |
242 | { | |
243 | config-cache.set $(key) : $(includes) $(library) ; | |
244 | if $(includes) = %default | |
245 | { | |
246 | includes = ; | |
247 | } | |
248 | library = [ ac.construct-library $(library[1]) : | |
249 | [ $(property-set).refine [ property-set.create $(library[2]) ] ] : $(library-path) ] ; | |
250 | configure.log-library-search-result $(name) : "yes" ; | |
251 | return [ $(library[1]).add-raw <include>$(includes) ] $(library[2-]) ; | |
252 | } | |
253 | else | |
254 | { | |
255 | config-cache.set $(key) : missing ; | |
256 | configure.log-library-search-result $(name) : "no" ; | |
257 | return [ property-set.empty ] ; | |
258 | } | |
259 | } | |
260 | } | |
261 | } | |
262 | } | |
263 | ||
264 | class check-library-worker | |
265 | { | |
266 | import property-set ; | |
267 | import targets ; | |
268 | import property ; | |
269 | ||
270 | rule __init__ ( target : true-properties * : false-properties * ) | |
271 | { | |
272 | self.target = $(target) ; | |
273 | self.true-properties = $(true-properties) ; | |
274 | self.false-properties = $(false-properties) ; | |
275 | } | |
276 | ||
277 | rule check ( properties * ) | |
278 | { | |
279 | local choosen ; | |
280 | local t = [ targets.current ] ; | |
281 | local p = [ $(t).project ] ; | |
282 | local ps = [ property-set.create $(properties) ] ; | |
283 | ps = [ $(ps).propagated ] ; | |
284 | local generated = | |
285 | [ targets.generate-from-reference $(self.target) : $(p) : $(ps) ] ; | |
286 | if $(generated[2]) | |
287 | { | |
288 | choosen = $(self.true-properties) ; | |
289 | } | |
290 | else | |
291 | { | |
292 | choosen = $(self.false-properties) ; | |
293 | } | |
294 | return [ property.evaluate-conditionals-in-context $(choosen) : | |
295 | $(properties) ] ; | |
296 | } | |
297 | } | |
298 | ||
299 | rule check-library ( target : true-properties * : false-properties * ) | |
300 | { | |
301 | local instance = [ class.new check-library-worker $(target) : | |
302 | $(true-properties) : $(false-properties) ] ; | |
303 | return <conditional>@$(instance).check ; | |
304 | } |