]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | # Copyright Rene Rivera 2015 |
2 | # Distributed under the Boost Software License, Version 1.0. | |
1e59de90 TL |
3 | # (See accompanying file LICENSE.txt or copy at |
4 | # https://www.bfgroup.xyz/b2/LICENSE.txt) | |
7c673cae FG |
5 | |
6 | import path ; | |
7 | import project ; | |
8 | import modules ; | |
9 | import regex ; | |
10 | import type ; | |
11 | ||
12 | # Add a location, i.e. directory, where to search for libraries. | |
13 | # The optional 'prefix' indicates which rooted-prefixes the new | |
14 | # search dir applies to. The prefix defaults to '/'. | |
15 | rule add-location ( dir prefix ? : base-dir ? ) | |
16 | { | |
17 | process-args ; | |
1e59de90 | 18 | |
7c673cae | 19 | prefix ?= "/" ; |
1e59de90 | 20 | |
7c673cae FG |
21 | # Dir path of caller to base paths from. |
22 | caller-module ?= [ CALLER_MODULE ] ; | |
23 | local caller-dir = [ modules.peek $(caller-module) : __file__ ] ; | |
24 | caller-dir = $(caller-dir:D) ; | |
1e59de90 | 25 | |
7c673cae | 26 | base-dir ?= $(caller-dir) ; |
1e59de90 | 27 | |
7c673cae FG |
28 | .search-path-prefix += $(prefix) ; |
29 | .search-path.$(prefix) += [ path.root [ path.root $(dir) $(base-dir) ] [ path.pwd ] ] ; | |
30 | } | |
31 | ||
32 | # Declares additional definitions of a modular library target external | |
33 | # to the modular library build itself. This makes it possible to externally | |
34 | # define modular libraries without modifying the library. The passed in | |
35 | # values are added on demand when the named library is first declared. | |
36 | rule external ( | |
37 | name : sources * : requirements * : default-build * : | |
38 | usage-requirements * ) | |
39 | { | |
40 | .external.($(name)).sources = $(sources) ; | |
41 | .external.($(name)).requirements = $(requirements) ; | |
42 | .external.($(name)).default-build = $(default-build) ; | |
43 | .external.($(name)).usage-requirements = $(usage-requirements) ; | |
44 | } | |
45 | ||
46 | # Find, and declare, any modular libraries referenced in the target-refs. | |
47 | # This will both load the modular libraries, and declare/manufacture | |
48 | # the modular libraries as needed. | |
49 | rule find ( target-refs + ) | |
50 | { | |
51 | process-args ; | |
1e59de90 | 52 | |
7c673cae FG |
53 | local caller-mod = [ CALLER_MODULE ] ; |
54 | local caller-dir = [ modules.peek $(caller-mod) : __file__ ] ; | |
55 | caller-dir = $(caller-dir:D) ; | |
56 | caller-dir = [ path.root $(caller-dir) [ path.pwd ] ] ; | |
1e59de90 | 57 | |
7c673cae FG |
58 | local result-refs ; |
59 | for local target-ref in $(target-refs) | |
60 | { | |
61 | result-refs += [ resolve-reference $(target-ref) | |
62 | : $(caller-mod) $(caller-dir) ] ; | |
63 | } | |
1e59de90 | 64 | |
7c673cae FG |
65 | return $(result-refs) ; |
66 | } | |
67 | ||
68 | ############################################################################## | |
69 | ||
70 | local rule resolve-reference ( target-ref : caller-mod caller-dir ? ) | |
71 | { | |
72 | # ECHO %%% modular.resolve-target-ref $(target-ref) :: $(caller-mod) $(caller-dir) ; | |
73 | if ! $(caller-dir) | |
74 | { | |
75 | caller-dir = [ modules.peek $(caller-mod) : __file__ ] ; | |
76 | caller-dir = $(caller-dir:D) ; | |
77 | caller-dir = [ path.root $(caller-dir) [ path.pwd ] ] ; | |
78 | } | |
79 | local result-ref = $(target-ref) ; | |
80 | local ref = [ MATCH ^(.*)//.* : $(target-ref:G=) ] ; | |
81 | # if ! ( $(ref) in $(.target-refs) ) | |
82 | { | |
83 | # .target-refs += $(ref) ; | |
84 | local search-prefix ; | |
85 | local search-sub ; | |
86 | for local prefix in $(.search-path-prefix) | |
87 | { | |
88 | if ! $(search-prefix) | |
89 | { | |
90 | local search-match = [ MATCH ^($(prefix))/(.*)$ : $(ref) ] ; | |
91 | search-prefix = $(search-match[1]) ; | |
92 | search-sub = $(search-match[2]) ; | |
93 | } | |
94 | } | |
1e59de90 | 95 | |
7c673cae FG |
96 | if $(search-prefix) |
97 | { | |
98 | local found = [ path.glob $(.search-path.$(search-prefix)) : $(search-sub) ] ; | |
99 | found = $(found[1]) ; | |
100 | if $(found) | |
101 | { | |
102 | local lib-ref = [ regex.split $(search-sub) / ] ; | |
103 | lib-ref = $(search-prefix)/$(lib-ref[1]) ; | |
104 | local lib-path = [ path.relative-to $(caller-dir) $(found) ] ; | |
105 | define-library $(lib-ref) $(caller-mod) : $(lib-path) ; | |
106 | } | |
107 | } | |
108 | } | |
109 | return $(result-ref) ; | |
110 | } | |
111 | ||
112 | local rule define-library ( name caller-module ? : root ) | |
113 | { | |
114 | # ECHO ~~~ modular.library $(name) $(caller-module) :: $(root) :: $(depends) ; | |
115 | ||
116 | process-args ; | |
1e59de90 | 117 | |
7c673cae FG |
118 | # Dir path of caller to base paths from. |
119 | caller-module ?= [ CALLER_MODULE ] ; | |
120 | local caller-dir = [ modules.peek $(caller-module) : __file__ ] ; | |
121 | caller-dir = $(caller-dir:D) ; | |
1e59de90 | 122 | |
7c673cae FG |
123 | # Find the various parts of the library. |
124 | local lib-dir = [ path.root [ path.root $(root) $(caller-dir) ] [ path.pwd ] ] ; | |
125 | local lib-contents = [ path.glob $(lib-dir) : "include" "build" ] ; | |
126 | lib-contents = $(lib-contents:D=) ; | |
1e59de90 | 127 | |
7c673cae FG |
128 | # "include" dir for library.. |
129 | local include-dir ; | |
130 | if "include" in $(lib-contents) | |
131 | { | |
132 | include-dir = $(root)/include ; | |
133 | } | |
1e59de90 | 134 | |
7c673cae FG |
135 | # If it has a build dir, i.e. it has targets to build, |
136 | # we root the project at the build dir to make it easy | |
137 | # to refer to the build targets. This mirrors the regular | |
138 | # Boost organization of the project aliases. | |
139 | if "build" in $(lib-contents) | |
140 | { | |
141 | root = $(root)/build ; | |
142 | build-dir = "." ; | |
143 | } | |
1e59de90 | 144 | |
7c673cae FG |
145 | # Shadow target declarations so that we can alter build targets |
146 | # to work in the standalone modular structure. | |
147 | local lib-location = [ path.root [ path.make $(root) ] $(caller-dir) ] ; | |
148 | local lib-module-name = [ project.module-name $(lib-location) ] ; | |
149 | local modular-rules = [ RULENAMES modular-rules ] ; | |
150 | IMPORT modular-rules : $(modular-rules) : $(lib-module-name) : $(modular-rules) ; | |
1e59de90 | 151 | |
7c673cae FG |
152 | # Load/create/declare library project. |
153 | local lib-module = [ project.find $(root) : $(caller-dir) ] ; | |
154 | if ! $(lib-module) | |
155 | { | |
156 | # If the find was unable to load the project we synthesize it. | |
157 | lib-module = [ project.load $(lib-location) : synthesize ] ; | |
158 | } | |
159 | local lib-target = [ project.target $(lib-module) ] ; | |
160 | if ! [ modules.peek $(lib-module) : __library__ ] | |
161 | { | |
162 | modules.poke $(lib-module) : __library__ : $(name) ; | |
163 | for local type in [ modules.peek type : .types ] | |
164 | { | |
165 | main-rule-name = [ type.type-to-rule-name $(type) ] ; | |
166 | IMPORT modular-rules : main-target-rule : $(lib-module-name) : $(main-rule-name) ; | |
167 | } | |
168 | } | |
1e59de90 | 169 | |
7c673cae FG |
170 | # Declare project alternate ID. |
171 | modules.call-in $(caller-module) : use-project $(name) : $(root) ; | |
1e59de90 | 172 | |
7c673cae FG |
173 | # Create a "library" target that has basic usage info if needed. |
174 | if ! [ $(lib-target).has-alternative-for-target library ] | |
175 | { | |
176 | include-dir = [ path.relative-to $(root) $(include-dir) ] ; | |
1e59de90 | 177 | |
7c673cae | 178 | project.push-current $(lib-target) ; |
1e59de90 | 179 | |
7c673cae FG |
180 | # Declare the library alias. |
181 | modules.call-in $(lib-module) : library | |
182 | : # Sources | |
183 | : # Requirements | |
184 | : # Default Build | |
185 | : # Usage Requirements | |
186 | <include>$(include-dir) | |
187 | ; | |
1e59de90 | 188 | |
7c673cae FG |
189 | project.pop-current ; |
190 | } | |
191 | } | |
192 | ||
193 | local rule process-args ( ) | |
194 | { | |
195 | if ! $(.did-process-args) | |
196 | { | |
197 | .did-process-args = yes ; | |
198 | local argv = [ modules.peek : ARGV ] ; | |
199 | local dirs = [ MATCH ^--modular-search-dir=(.*)$ : $(argv) ] ; | |
200 | for local dir in $(dirs) | |
201 | { | |
202 | add-location $(dir) : [ path.pwd ] ; | |
203 | } | |
204 | } | |
205 | } | |
206 | ||
207 | rule apply-external ( | |
208 | mod : field : values * ) | |
209 | { | |
210 | local result ; | |
211 | local name = [ modules.peek $(mod) : __library__ ] ; | |
212 | values += $(.external.($(name)).$(field)) ; | |
213 | for local value in $(values) | |
214 | { | |
215 | result += [ resolve-reference $(value) : $(mod) ] ; | |
216 | } | |
217 | return $(result) ; | |
218 | } | |
219 | ||
220 | module modular-rules | |
221 | { | |
222 | import type ; | |
223 | import targets ; | |
224 | import builtin ; | |
225 | import alias ; | |
1e59de90 | 226 | |
7c673cae FG |
227 | # Avoids any form of installation for Boost modules. |
228 | rule boost-install ( libraries * ) { } | |
1e59de90 | 229 | |
7c673cae FG |
230 | # Generic typed target rule to pre-process main target |
231 | # declarations to make them work within the standalone | |
232 | # modular structure. | |
233 | rule main-target-rule ( | |
234 | name : sources * : requirements * : default-build * : | |
235 | usage-requirements * ) | |
236 | { | |
237 | local mod = [ CALLER_MODULE ] ; | |
1e59de90 | 238 | |
7c673cae | 239 | # ECHO @@@ [[$(mod)]] modular-rules.main-target-rule $(name) :: $(sources) :: $(requirements) :: $(default-build) :: $(usage-requirements) ; |
1e59de90 | 240 | |
7c673cae FG |
241 | # First discover the required target type based on the exact alias used to |
242 | # invoke this rule. | |
243 | local bt = [ BACKTRACE 1 ] ; | |
244 | local rulename = $(bt[4]) ; | |
245 | local target-type = [ type.type-from-rule-name $(rulename) ] ; | |
246 | return [ targets.create-typed-target $(target-type) : [ project.current ] : | |
247 | $(name) : $(sources) : $(requirements) : $(default-build) : | |
248 | $(usage-requirements) ] ; | |
249 | } | |
1e59de90 | 250 | |
7c673cae FG |
251 | rule lib ( names + : sources * : requirements * : default-build * : |
252 | usage-requirements * ) | |
253 | { | |
254 | local mod = [ CALLER_MODULE ] ; | |
255 | requirements += <use>library ; | |
256 | usage-requirements += <use>library ; | |
1e59de90 | 257 | |
7c673cae FG |
258 | # ECHO @@@ [[$(mod)]] modular-rules.lib $(names) :: $(sources) :: $(requirements) :: $(default-build) :: $(usage-requirements) ; |
259 | return [ builtin.lib $(names) : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ] ; | |
260 | } | |
1e59de90 | 261 | |
7c673cae FG |
262 | rule alias ( name : sources * : requirements * : default-build * : |
263 | usage-requirements * ) | |
264 | { | |
265 | local mod = [ CALLER_MODULE ] ; | |
1e59de90 | 266 | |
7c673cae FG |
267 | # ECHO @@@ [[$(mod)]] modular-rules.alias $(name) :: $(sources) :: $(requirements) :: $(default-build) :: $(usage-requirements) ; |
268 | return [ alias.alias $(name) : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ] ; | |
269 | } | |
1e59de90 | 270 | |
7c673cae FG |
271 | rule library ( name ? : sources * : requirements * : default-build * : |
272 | usage-requirements * ) | |
273 | { | |
274 | import modular ; | |
1e59de90 | 275 | |
7c673cae FG |
276 | local mod = [ CALLER_MODULE ] ; |
277 | sources = [ modular.apply-external $(mod) : sources : $(sources) ] ; | |
278 | requirements = [ modular.apply-external $(mod) : requirements : $(requirements) ] ; | |
279 | default-build = [ modular.apply-external $(mod) : default-build : $(default-build) ] ; | |
280 | usage-requirements = [ modular.apply-external $(mod) : usage-requirements : $(usage-requirements) ] ; | |
1e59de90 | 281 | |
7c673cae | 282 | name ?= library ; |
1e59de90 | 283 | |
7c673cae FG |
284 | # ECHO @@@ [[$(mod)]] modular-rules.library $(name) :: $(sources) :: $(requirements) :: $(default-build) :: $(usage-requirements) ; |
285 | return [ alias.alias $(name) : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ] ; | |
286 | } | |
287 | } | |
288 |