1 # Copyright (c) 2010 Vladimir Prus.
2 # Copyright (c) 2013 Steven Watanabe
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)
15 import virtual-target ;
21 project.initialize $(__name__) ;
22 .project = [ project.current ] ;
25 rule generate-include ( target : sources * : properties * )
27 local header = [ property.select <include> : $(properties) ] ;
28 print.output $(target) ;
29 print.text "#include <$(header:G=)>\n" : true ;
32 rule generate-main ( target : sources * : properties * )
34 print.output $(target) ;
35 print.text "int main() {}" : true ;
38 rule find-include-path ( properties : header : provided-path ? )
40 if $(provided-path) && [ path.exists [ path.root $(header) $(provided-path) ] ]
42 return $(provided-path) ;
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 ] ;
55 for t in $(result[2-])
57 jam-targets += [ $(t).actualize ] ;
59 if [ UPDATE_NOW $(jam-targets) : [ modules.peek configure : .log-fd ]
60 : ignore-minus-n : ignore-minus-q ]
67 rule construct-library ( name : property-set : provided-path ? )
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 ] ;
76 rule find-library ( properties : names + : provided-path ? )
79 if [ $(properties).get <link> ] = shared
81 link-opts = <link>shared <link>static ;
85 link-opts = <link>static <link>shared ;
89 local names-iter = $(names) ;
90 properties = [ $(properties).refine [ property-set.create $(link-opts[1]) ] ] ;
93 local name = $(names-iter[1]) ;
94 local lib = [ construct-library $(name) : $(properties) : $(provided-path) ] ;
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) ] ] ;
99 local test = [ generators.construct $(.project) $(name) : EXE
100 : [ $(properties).add $(lib[1]) ] : $(main.cpp) $(lib[2-])
105 jam-targets += [ $(t).actualize ] ;
107 if [ UPDATE_NOW $(jam-targets) : [ modules.peek configure : .log-fd ]
108 : ignore-minus-n : ignore-minus-q ]
110 result = $(name) $(link-opts[1]) ;
111 names-iter = ; link-opts = ; # break
113 names-iter = $(names-iter[2-]) ;
115 link-opts = $(link-opts[2-]) ;
120 class ac-library : basic-target
124 import virtual-target ;
127 import config-cache ;
129 rule __init__ ( name : project : requirements * : include-path ? : library-path ? : library-name ? )
131 basic-target.__init__ $(name) : $(project) : : $(requirements) ;
133 reconfigure $(include-path) : $(library-path) : $(library-name) ;
136 rule set-header ( header )
138 self.header = $(header) ;
141 rule set-default-names ( names + )
143 self.default-names = $(names) ;
146 rule reconfigure ( include-path ? : library-path ? : library-name ? )
148 if $(include-path) || $(library-path) || $(library-name)
150 check-not-configured ;
152 self.include-path = $(include-path) ;
153 self.library-path = $(library-path) ;
154 self.library-name = $(library-name) ;
158 rule set-target ( target )
160 check-not-configured ;
161 self.target = $(target) ;
164 rule check-not-configured ( )
166 if $(self.include-path) || $(self.library-path) || $(self.library-name) || $(self.target)
168 errors.user-error [ name ] "is already configured" ;
172 rule construct ( name : sources * : property-set )
176 return [ $(self.target).generate $(property-set) ] ;
180 local use-environment ;
181 if ! $(self.library-name) && ! $(self.include-path) && ! $(self.library-path)
183 use-environment = true ;
185 local libnames = $(self.library-name) ;
186 if ! $(libnames) && $(use-environment)
188 libnames = [ modules.peek : $(name:U)_NAME ] ;
189 # Backward compatibility only.
190 libnames ?= [ modules.peek : $(name:U)_BINARY ] ;
192 libnames ?= $(self.default-names) ;
194 local include-path = $(self.include-path) ;
195 if ! $(include-path) && $(use-environment)
197 include-path = [ modules.peek : $(name:U)_INCLUDE ] ;
200 local library-path = $(self.library-path) ;
201 if ! $(library-path) && $(use-environment)
203 library-path = [ modules.peek : $(name:U)_LIBRARY_PATH ] ;
204 # Backwards compatibility only
205 library-path ?= [ modules.peek : $(name:U)_LIBPATH ] ;
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 ] ] ;
214 local key = ac-library-$(name)-$(relevant:J=-) ;
215 local lookup = [ config-cache.get $(key) ] ;
219 if $(lookup) = missing
221 configure.log-library-search-result $(name) : "no (cached)" ;
222 return [ property-set.empty ] ;
226 local includes = $(lookup[1]) ;
227 if $(includes) = %default
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-]) ;
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)
243 config-cache.set $(key) : $(includes) $(library) ;
244 if $(includes) = %default
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-]) ;
255 config-cache.set $(key) : missing ;
256 configure.log-library-search-result $(name) : "no" ;
257 return [ property-set.empty ] ;
264 class check-library-worker
266 import property-set ;
270 rule __init__ ( target : true-properties * : false-properties * )
272 self.target = $(target) ;
273 self.true-properties = $(true-properties) ;
274 self.false-properties = $(false-properties) ;
277 rule check ( properties * )
280 local t = [ targets.current ] ;
281 local p = [ $(t).project ] ;
282 local ps = [ property-set.create $(properties) ] ;
283 ps = [ $(ps).propagated ] ;
285 [ targets.generate-from-reference $(self.target) : $(p) : $(ps) ] ;
288 choosen = $(self.true-properties) ;
292 choosen = $(self.false-properties) ;
294 return [ property.evaluate-conditionals-in-context $(choosen) :
299 rule check-library ( target : true-properties * : false-properties * )
301 local instance = [ class.new check-library-worker $(target) :
302 $(true-properties) : $(false-properties) ] ;
303 return <conditional>@$(instance).check ;