source: trunk/src/gmake/kbuild.c@ 644

Last change on this file since 644 was 644, checked in by bird, 19 years ago

Fixed bugs dealing with the order SDK properties was applied to sources.

File size: 53.8 KB
Line 
1/* $Id: $ */
2/** @file
3 *
4 * kBuild specific make functionality.
5 *
6 * Copyright (c) 2006 knut st. osmundsen <bird@innotek.de>
7 *
8 *
9 * This file is part of kBuild.
10 *
11 * kBuild is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kBuild is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kBuild; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27/* No GNU coding style here! */
28
29#ifdef KMK_HELPERS
30
31#include "make.h"
32#include "filedef.h"
33#include "variable.h"
34#include "dep.h"
35#include "debug.h"
36
37#include "kbuild.h"
38
39#include <assert.h>
40#include <stdarg.h>
41#ifndef va_copy
42# define va_copy(dst, src) do {(dst) = (src);} while (0)
43#endif
44
45
46/**
47 * Gets a variable that must exist.
48 * Will cause a fatal failure if the variable doesn't exist.
49 *
50 * @returns Pointer to the variable.
51 * @param pszName The variable name.
52 */
53static struct variable *
54kbuild_get_variable(const char *pszName)
55{
56#ifndef NDEBUG
57 unsigned i;
58#endif
59 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
60 if (!pVar)
61 fatal(NILF, _("variable `%s' isn't defined!"), pszName);
62 if (pVar->recursive)
63 fatal(NILF, _("variable `%s' is defined as `recursive' instead of `simple'!"), pszName);
64#ifndef NDEBUG
65 i = strlen(pVar->value);
66 if (i != pVar->value_length)
67 {
68 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
69# ifdef _MSC_VER
70 __asm int 3;
71# endif
72 assert(0);
73 }
74#endif
75 return pVar;
76}
77
78/**
79 * Gets a variable that must exist and can be recursive.
80 * Will cause a fatal failure if the variable doesn't exist.
81 *
82 * @returns Pointer to the variable.
83 * @param pszName The variable name.
84 */
85static struct variable *
86kbuild_get_recursive_variable(const char *pszName)
87{
88#ifndef NDEBUG
89 unsigned i;
90#endif
91 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
92 if (!pVar)
93 fatal(NILF, _("variable `%s' isn't defined!"), pszName);
94#ifndef NDEBUG
95 i = strlen(pVar->value);
96 if (i != pVar->value_length)
97 {
98 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
99# ifdef _MSC_VER
100 __asm int 3;
101# endif
102 assert(0);
103 }
104#endif
105 return pVar;
106}
107
108/**
109 * Converts the specified variable into a 'simple' one.
110 * @returns pVar.
111 * @param pVar The variable.
112 */
113static struct variable *
114kbuild_simplify_variable(struct variable *pVar)
115{
116 if (memchr(pVar->value, '$', pVar->value_length))
117 {
118 char *pszExpanded = allocated_variable_expand(pVar->value);
119 free(pVar->value);
120 pVar->value = pszExpanded;
121 pVar->value_length = strlen(pVar->value);
122 pVar->value_alloc_len = pVar->value_length + 1;
123 }
124 pVar->recursive = 0;
125 return pVar;
126}
127
128/**
129 * Looks up a variable.
130 * The value_length field is valid upon successful return.
131 *
132 * @returns Pointer to the variable. NULL if not found.
133 * @param pszName The variable name.
134 */
135static struct variable *
136kbuild_lookup_variable(const char *pszName)
137{
138 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
139 if (pVar)
140 {
141#ifndef NDEBUG
142 unsigned i = strlen(pVar->value);
143 if (i != pVar->value_length)
144 {
145 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
146# ifdef _MSC_VER
147 __asm int 3;
148# endif
149 assert(0);
150 }
151#endif
152 /* Make sure the variable is simple, convert it if necessary. */
153 if (pVar->recursive)
154 kbuild_simplify_variable(pVar);
155 }
156 return pVar;
157}
158
159/** Same as kbuild_lookup_variable except that a '%s' in the name string
160 * will be substituted with the values of the variables in the va list. */
161static struct variable *
162kbuild_lookup_variable_fmt_va(const char *pszNameFmt, va_list va)
163{
164 va_list va2;
165 size_t cchName;
166 const char *pszFmt;
167 char *pszName;
168 char *psz;
169
170 /* first pass, calc value name size and allocate stack buffer. */
171 va_copy(va2, va);
172
173 cchName = strlen(pszNameFmt) + 1;
174 pszFmt = strchr(pszNameFmt, '%');
175 while (pszFmt)
176 {
177 struct variable *pVar = va_arg(va, struct variable *);
178 if (pVar)
179 cchName += pVar->value_length;
180 pszFmt = strchr(pszFmt + 1, '%');
181 }
182 pszName = alloca(cchName);
183
184 /* second pass format it. */
185 pszFmt = pszNameFmt;
186 psz = pszName;
187 for (;;)
188 {
189 char ch = *pszFmt++;
190 if (ch != '%')
191 {
192 *psz++ = ch;
193 if (!ch)
194 break;
195 }
196 else
197 {
198 struct variable *pVar = va_arg(va2, struct variable *);
199 if (pVar)
200 {
201 memcpy(psz, pVar->value, pVar->value_length);
202 psz += pVar->value_length;
203 }
204 }
205 }
206 va_end(va2);
207
208 return kbuild_lookup_variable(pszName);
209}
210
211/** Same as kbuild_lookup_variable except that a '%s' in the name string
212 * will be substituted with the values of the variables in the ellipsis. */
213static struct variable *
214kbuild_lookup_variable_fmt(const char *pszNameFmt, ...)
215{
216 struct variable *pVar;
217 va_list va;
218 va_start(va, pszNameFmt);
219 pVar = kbuild_lookup_variable_fmt_va(pszNameFmt, va);
220 va_end(va);
221 return pVar;
222}
223
224/**
225 * Gets the first defined property variable.
226 */
227static struct variable *
228kbuild_first_prop(struct variable *pTarget, struct variable *pSource,
229 struct variable *pTool, struct variable *pType,
230 struct variable *pBldTrg, struct variable *pBldTrgArch,
231 const char *pszPropF1, const char *pszPropF2, const char *pszVarName)
232{
233 struct variable *pVar;
234 struct variable PropF1, PropF2;
235
236 PropF1.value = (char *)pszPropF1;
237 PropF1.value_length = strlen(pszPropF1);
238
239 PropF2.value = (char *)pszPropF2;
240 PropF2.value_length = strlen(pszPropF2);
241
242 if ( (pVar = kbuild_lookup_variable_fmt("%_%_%%.%.%",pTarget, pSource, pType, &PropF2, pBldTrg, pBldTrgArch))
243 || (pVar = kbuild_lookup_variable_fmt("%_%_%%.%", pTarget, pSource, pType, &PropF2, pBldTrg))
244 || (pVar = kbuild_lookup_variable_fmt("%_%_%%", pTarget, pSource, pType, &PropF2))
245 || (pVar = kbuild_lookup_variable_fmt("%_%_%.%.%", pTarget, pSource, &PropF2, pBldTrg, pBldTrgArch))
246 || (pVar = kbuild_lookup_variable_fmt("%_%_%.%", pTarget, pSource, &PropF2, pBldTrg))
247 || (pVar = kbuild_lookup_variable_fmt("%_%_%", pTarget, pSource, &PropF2))
248 || (pVar = kbuild_lookup_variable_fmt("%_%%.%.%", pSource, pType, &PropF2, pBldTrg, pBldTrgArch))
249 || (pVar = kbuild_lookup_variable_fmt("%_%%.%", pSource, pType, &PropF2, pBldTrg))
250 || (pVar = kbuild_lookup_variable_fmt("%_%%", pSource, pType, &PropF2))
251 || (pVar = kbuild_lookup_variable_fmt("%_%.%.%", pSource, &PropF2, pBldTrg, pBldTrgArch))
252 || (pVar = kbuild_lookup_variable_fmt("%_%.%", pSource, &PropF2, pBldTrg))
253 || (pVar = kbuild_lookup_variable_fmt("%_%", pSource, &PropF2))
254 || (pVar = kbuild_lookup_variable_fmt("%_%%.%.%", pTarget, pType, &PropF2, pBldTrg, pBldTrgArch))
255 || (pVar = kbuild_lookup_variable_fmt("%_%%.%", pTarget, pType, &PropF2, pBldTrg))
256 || (pVar = kbuild_lookup_variable_fmt("%_%%", pTarget, pType, &PropF2))
257 || (pVar = kbuild_lookup_variable_fmt("%_%.%.%", pTarget, &PropF2, pBldTrg, pBldTrgArch))
258 || (pVar = kbuild_lookup_variable_fmt("%_%.%", pTarget, &PropF2, pBldTrg))
259 || (pVar = kbuild_lookup_variable_fmt("%_%", pTarget, &PropF2))
260
261 || (pTool && (pVar = kbuild_lookup_variable_fmt("TOOL_%_%%.%.%", pTool, pType, &PropF2, pBldTrg, pBldTrgArch)))
262 || (pTool && (pVar = kbuild_lookup_variable_fmt("TOOL_%_%%.%", pTool, pType, &PropF2, pBldTrg)))
263 || (pTool && (pVar = kbuild_lookup_variable_fmt("TOOL_%_%%", pTool, pType, &PropF2)))
264 || (pTool && (pVar = kbuild_lookup_variable_fmt("TOOL_%_%.%.%", pTool, &PropF2, pBldTrg, pBldTrgArch)))
265 || (pTool && (pVar = kbuild_lookup_variable_fmt("TOOL_%_%.%", pTool, &PropF2, pBldTrg)))
266 || (pTool && (pVar = kbuild_lookup_variable_fmt("TOOL_%_%", pTool, &PropF2)))
267
268 || (pVar = kbuild_lookup_variable_fmt("%%.%.%", pType, &PropF1, pBldTrg, pBldTrgArch))
269 || (pVar = kbuild_lookup_variable_fmt("%%.%", pType, &PropF1, pBldTrg))
270 || (pVar = kbuild_lookup_variable_fmt("%%", pType, &PropF1))
271 || (pVar = kbuild_lookup_variable_fmt("%.%.%", &PropF1, pBldTrg, pBldTrgArch))
272 || (pVar = kbuild_lookup_variable_fmt("%.%", &PropF1, pBldTrg))
273 || (pVar = kbuild_lookup_variable(pszPropF1))
274 )
275 {
276 /* strip it */
277 char *psz = pVar->value;
278 char *pszEnd = psz + pVar->value_length;
279 while (isblank((unsigned char)*psz))
280 psz++;
281 while (pszEnd > psz && isblank((unsigned char)pszEnd[-1]))
282 pszEnd--;
283 if (pszEnd > psz)
284 {
285 char chSaved = *pszEnd;
286 *pszEnd = '\0';
287 pVar = define_variable_vl(pszVarName, strlen(pszVarName), psz, pszEnd - psz,
288 1 /* duplicate */, o_file, 0 /* !recursive */);
289 *pszEnd = chSaved;
290 if (pVar)
291 return pVar;
292 }
293 }
294 return NULL;
295}
296
297/*
298_SOURCE_TOOL = $(strip $(firstword \
299 $($(target)_$(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
300 $($(target)_$(source)_$(type)TOOL.$(bld_trg)) \
301 $($(target)_$(source)_$(type)TOOL) \
302 $($(target)_$(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
303 $($(target)_$(source)_TOOL.$(bld_trg)) \
304 $($(target)_$(source)_TOOL) \
305 $($(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
306 $($(source)_$(type)TOOL.$(bld_trg)) \
307 $($(source)_$(type)TOOL) \
308 $($(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
309 $($(source)_TOOL.$(bld_trg)) \
310 $($(source)_TOOL) \
311 $($(target)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
312 $($(target)_$(type)TOOL.$(bld_trg)) \
313 $($(target)_$(type)TOOL) \
314 $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \
315 $($(target)_TOOL.$(bld_trg)) \
316 $($(target)_TOOL) \
317 $($(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
318 $($(type)TOOL.$(bld_trg)) \
319 $($(type)TOOL) \
320 $(TOOL.$(bld_trg).$(bld_trg_arch)) \
321 $(TOOL.$(bld_trg)) \
322 $(TOOL) ))
323*/
324static struct variable *
325kbuild_get_source_tool(struct variable *pTarget, struct variable *pSource, struct variable *pType,
326 struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
327{
328 struct variable *pVar = kbuild_first_prop(pTarget, pSource, NULL, pType, pBldTrg, pBldTrgArch,
329 "TOOL", "TOOL", pszVarName);
330 if (!pVar)
331 fatal(NILF, _("no tool for source `%s' in target `%s'!"), pSource->value, pTarget->value);
332 return pVar;
333}
334
335/* Implements _SOURCE_TOOL. */
336char *
337func_kbuild_source_tool(char *o, char **argv, const char *pszFuncName)
338{
339 struct variable *pVar = kbuild_get_source_tool(kbuild_get_variable("target"),
340 kbuild_get_variable("source"),
341 kbuild_get_variable("type"),
342 kbuild_get_variable("bld_trg"),
343 kbuild_get_variable("bld_trg_arch"),
344 argv[0]);
345 if (pVar)
346 o = variable_buffer_output(o, pVar->value, pVar->value_length);
347 return o;
348
349}
350
351/* This has been extended a bit, it's now identical to _SOURCE_TOOL.
352$(firstword \
353 $($(target)_$(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
354 $($(target)_$(source)_OBJSUFF.$(bld_trg))\
355 $($(target)_$(source)_OBJSUFF)\
356 $($(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
357 $($(source)_OBJSUFF.$(bld_trg))\
358 $($(source)_OBJSUFF)\
359 $($(target)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
360 $($(target)_OBJSUFF.$(bld_trg))\
361 $($(target)_OBJSUFF)\
362 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg).$(bld_trg_arch))\
363 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg))\
364 $(TOOL_$(tool)_$(type)OBJSUFF)\
365 $(SUFF_OBJ))
366*/
367static struct variable *
368kbuild_get_object_suffix(struct variable *pTarget, struct variable *pSource,
369 struct variable *pTool, struct variable *pType,
370 struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
371{
372 struct variable *pVar = kbuild_first_prop(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch,
373 "SUFF_OBJ", "OBJSUFF", pszVarName);
374 if (!pVar)
375 fatal(NILF, _("no OBJSUFF attribute or SUFF_OBJ default for source `%s' in target `%s'!"), pSource->value, pTarget->value);
376 return pVar;
377}
378
379/* */
380char *
381func_kbuild_object_suffix(char *o, char **argv, const char *pszFuncName)
382{
383 struct variable *pVar = kbuild_get_object_suffix(kbuild_get_variable("target"),
384 kbuild_get_variable("source"),
385 kbuild_get_variable("tool"),
386 kbuild_get_variable("type"),
387 kbuild_get_variable("bld_trg"),
388 kbuild_get_variable("bld_trg_arch"),
389 argv[0]);
390 if (pVar)
391 o = variable_buffer_output(o, pVar->value, pVar->value_length);
392 return o;
393
394}
395
396
397/*
398## Figure out where to put object files.
399# @param $1 source file
400# @param $2 normalized main target
401# @remark There are two major hacks here:
402# 1. Source files in the output directory are translated into a gen/ subdir.
403# 2. Catch anyone specifying $(PATH_SUB_CURRENT)/sourcefile.c.
404_OBJECT_BASE = $(PATH_TARGET)/$(2)/$(call no-root-slash,$(call no-drive,$(basename \
405 $(patsubst $(PATH_ROOT)/%,%,$(patsubst $(PATH_SUB_CURRENT)/%,%,$(patsubst $(PATH_TARGET)/$(2)/%,gen/%,$(1)))))))
406*/
407static struct variable *
408kbuild_get_object_base(struct variable *pTarget, struct variable *pSource, const char *pszVarName)
409{
410 struct variable *pPathTarget = kbuild_get_variable("PATH_TARGET");
411 struct variable *pPathRoot = kbuild_get_variable("PATH_ROOT");
412 struct variable *pPathSubCur = kbuild_get_variable("PATH_SUB_CURRENT");
413 const char *pszSrcPrefix = NULL;
414 size_t cchSrcPrefix = 0;
415 const char *pszSrcEnd;
416 char *pszSrc;
417 char *pszResult;
418 char *psz;
419 size_t cch;
420
421 /*
422 * Strip the source filename of any uncessary leading path and root specs.
423 */
424 /* */
425 if ( pSource->value_length > pPathTarget->value_length
426 && !strncmp(pSource->value, pPathTarget->value, pPathTarget->value_length))
427 {
428 pszSrc = pSource->value + pPathTarget->value_length;
429 pszSrcPrefix = "gen/";
430 cchSrcPrefix = sizeof("gen/") - 1;
431 if ( *pszSrc == '/'
432 && !strncmp(pszSrc + 1, pTarget->value, pTarget->value_length)
433 && ( pszSrc[pTarget->value_length + 1] == '/'
434 || pszSrc[pTarget->value_length + 1] == '\0'))
435 pszSrc += 1 + pTarget->value_length;
436 }
437 else if ( pSource->value_length > pPathRoot->value_length
438 && !strncmp(pSource->value, pPathRoot->value, pPathRoot->value_length))
439 {
440 pszSrc = pSource->value + pPathRoot->value_length;
441 if ( *pszSrc == '/'
442 && !strncmp(pszSrc + 1, pPathSubCur->value, pPathSubCur->value_length)
443 && ( pszSrc[pPathSubCur->value_length + 1] == '/'
444 || pszSrc[pPathSubCur->value_length + 1] == '\0'))
445 pszSrc += 1 + pPathSubCur->value_length;
446 }
447 else
448 pszSrc = pSource->value;
449
450 /* skip root specification */
451#ifdef HAVE_DOS_PATHS
452 if (isalpha(pszSrc[0]) && pszSrc[1] == ':')
453 pszSrc += 2;
454#endif
455 while (*pszSrc == '/'
456#ifdef HAVE_DOS_PATHS
457 || *pszSrc == '\\'
458#endif
459 )
460 pszSrc++;
461
462 /* drop the source extension. */
463 pszSrcEnd = pSource->value + pSource->value_length;
464 for (;;)
465 {
466 pszSrcEnd--;
467 if ( pszSrcEnd <= pszSrc
468 || *pszSrcEnd == '/'
469#ifdef HAVE_DOS_PATHS
470 || *pszSrcEnd == '\\'
471 || *pszSrcEnd == ':'
472#endif
473 )
474 {
475 pszSrcEnd = pSource->value + pSource->value_length;
476 break;
477 }
478 if (*pszSrcEnd == '.')
479 break;
480 }
481
482 /*
483 * Assemble the string on the stack and define the objbase variable
484 * which we then return.
485 */
486 cch = pPathTarget->value_length
487 + 1 /* slash */
488 + pTarget->value_length
489 + 1 /* slash */
490 + cchSrcPrefix
491 + pszSrcEnd - pszSrc
492 + 1;
493 psz = pszResult = xmalloc(cch);
494
495 memcpy(psz, pPathTarget->value, pPathTarget->value_length); psz += pPathTarget->value_length;
496 *psz++ = '/';
497 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
498 *psz++ = '/';
499 if (pszSrcPrefix)
500 {
501 memcpy(psz, pszSrcPrefix, cchSrcPrefix);
502 psz += cchSrcPrefix;
503 }
504 memcpy(psz, pszSrc, pszSrcEnd - pszSrc); psz += pszSrcEnd - pszSrc;
505 *psz = '\0';
506
507 /*
508 * Define the variable in the current set and return it.
509 */
510 return define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cch - 1,
511 0 /* use pszResult */, o_file, 0 /* !recursive */);
512}
513
514/* Implements _OBJECT_BASE. */
515char *
516func_kbuild_object_base(char *o, char **argv, const char *pszFuncName)
517{
518 struct variable *pVar = kbuild_get_object_base(kbuild_lookup_variable("target"),
519 kbuild_lookup_variable("source"),
520 argv[0]);
521 if (pVar)
522 o = variable_buffer_output(o, pVar->value, pVar->value_length);
523 return o;
524
525}
526
527
528struct kbuild_sdks
529{
530 char *apsz[4];
531 struct variable *pa;
532 unsigned c;
533 unsigned iGlobal;
534 unsigned cGlobal;
535 unsigned iTarget;
536 unsigned cTarget;
537 unsigned iSource;
538 unsigned cSource;
539 unsigned iTargetSource;
540 unsigned cTargetSource;
541};
542
543/* Fills in the SDK struct (remember to free it). */
544static void
545kbuild_get_sdks(struct kbuild_sdks *pSdks, struct variable *pTarget, struct variable *pSource,
546 struct variable *pBldType, struct variable *pBldTrg, struct variable *pBldTrgArch)
547{
548 int i, j;
549 size_t cchTmp, cch;
550 char *pszTmp;
551 unsigned cchCur;
552 char *pszCur;
553 char *pszIterator;
554
555 /* basic init. */
556 pSdks->pa = NULL;
557 pSdks->c = 0;
558 i = 0;
559
560 /* determin required tmp variable name space. */
561 cchTmp = sizeof("$(__SDKS) $(__SDKS.) $(__SDKS.) $(__SDKS.) $(__SDKS..)")
562 + (pTarget->value_length + pSource->value_length) * 5
563 + pBldType->value_length
564 + pBldTrg->value_length
565 + pBldTrgArch->value_length
566 + pBldTrg->value_length + pBldTrgArch->value_length;
567 pszTmp = alloca(cchTmp);
568
569 /* the global sdks. */
570 pSdks->iGlobal = i;
571 pSdks->cGlobal = 0;
572 sprintf(pszTmp, "$(SDKS) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s.%s)",
573 pBldType->value,
574 pBldTrg->value,
575 pBldTrgArch->value,
576 pBldTrg->value, pBldTrgArch->value);
577 pszIterator = pSdks->apsz[0] = allocated_variable_expand(pszTmp);
578 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
579 pSdks->cGlobal++;
580 i += pSdks->cGlobal;
581
582 /* the target sdks.*/
583 pSdks->iTarget = i;
584 pSdks->cTarget = 0;
585 sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
586 pTarget->value,
587 pTarget->value, pBldType->value,
588 pTarget->value, pBldTrg->value,
589 pTarget->value, pBldTrgArch->value,
590 pTarget->value, pBldTrg->value, pBldTrgArch->value);
591 pszIterator = pSdks->apsz[1] = allocated_variable_expand(pszTmp);
592 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
593 pSdks->cTarget++;
594 i += pSdks->cTarget;
595
596 /* the source sdks.*/
597 pSdks->iSource = i;
598 pSdks->cSource = 0;
599 sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
600 pSource->value,
601 pSource->value, pBldType->value,
602 pSource->value, pBldTrg->value,
603 pSource->value, pBldTrgArch->value,
604 pSource->value, pBldTrg->value, pBldTrgArch->value);
605 pszIterator = pSdks->apsz[2] = allocated_variable_expand(pszTmp);
606 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
607 pSdks->cSource++;
608 i += pSdks->cSource;
609
610 /* the target + source sdks. */
611 pSdks->iTargetSource = i;
612 pSdks->cTargetSource = 0;
613 cch = sprintf(pszTmp, "$(%s_%s_SDKS) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s.%s)",
614 pTarget->value, pSource->value,
615 pTarget->value, pSource->value, pBldType->value,
616 pTarget->value, pSource->value, pBldTrg->value,
617 pTarget->value, pSource->value, pBldTrgArch->value,
618 pTarget->value, pSource->value, pBldTrg->value, pBldTrgArch->value);
619 assert(cch < cchTmp); (void)cch;
620 pszIterator = pSdks->apsz[3] = allocated_variable_expand(pszTmp);
621 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
622 pSdks->cTargetSource++;
623 i += pSdks->cTargetSource;
624
625 pSdks->c = i;
626 if (!i)
627 return;
628
629 /*
630 * Allocate the variable array and create the variables.
631 */
632 pSdks->pa = (struct variable *)xmalloc(sizeof(pSdks->pa[0]) * i);
633 memset(pSdks->pa, 0, sizeof(pSdks->pa[0]) * i);
634 for (i = j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
635 {
636 int k = i;
637 pszIterator = pSdks->apsz[j];
638 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
639 {
640 pSdks->pa[i].value = pszCur;
641 pSdks->pa[i].value_length = cchCur;
642 i++;
643 }
644 }
645 assert(i == pSdks->c);
646
647 /* terminate them (find_next_token won't work if we terminate them in the previous loop). */
648 while (i-- > 0)
649 pSdks->pa[i].value[pSdks->pa[i].value_length] = '\0';
650}
651
652/* releases resources allocated in the kbuild_get_sdks. */
653kbuild_put_sdks(struct kbuild_sdks *pSdks)
654{
655 unsigned j;
656 for (j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
657 free(pSdks->apsz[j]);
658 free(pSdks->pa);
659}
660
661/* this kind of stuff:
662
663defs := $(kb-src-exp defs)
664 $(TOOL_$(tool)_DEFS)\
665 $(TOOL_$(tool)_DEFS.$(bld_type))\
666 $(TOOL_$(tool)_DEFS.$(bld_trg))\
667 $(TOOL_$(tool)_DEFS.$(bld_trg_arch))\
668 $(TOOL_$(tool)_DEFS.$(bld_trg).$(bld_trg_arch))\
669 $(TOOL_$(tool)_DEFS.$(bld_trg_cpu))\
670 $(TOOL_$(tool)_$(type)DEFS)\
671 $(TOOL_$(tool)_$(type)DEFS.$(bld_type))\
672 $(foreach sdk, $(SDKS.$(bld_trg)) \
673 $(SDKS.$(bld_trg).$(bld_trg_arch)) \
674 $(SDKS.$(bld_type)) \
675 $(SDKS),\
676 $(SDK_$(sdk)_DEFS)\
677 $(SDK_$(sdk)_DEFS.$(bld_type))\
678 $(SDK_$(sdk)_DEFS.$(bld_trg))\
679 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
680 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
681 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
682 $(SDK_$(sdk)_$(type)DEFS)\
683 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
684 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
685 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
686 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
687 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
688 $(DEFS)\
689 $(DEFS.$(bld_type))\
690 $(DEFS.$(bld_trg))\
691 $(DEFS.$(bld_trg_arch))\
692 $(DEFS.$(bld_trg).$(bld_trg_arch))\
693 $(DEFS.$(bld_trg_cpu))\
694 $($(type)DEFS)\
695 $($(type)DEFS.$(bld_type))\
696 $($(type)DEFS.$(bld_trg))\
697 $($(type)DEFS.$(bld_trg_arch))\
698 $($(type)DEFS.$(bld_trg).$(bld_trg_arch))\
699 $($(type)DEFS.$(bld_trg_cpu))\
700 $(foreach sdk, $($(target)_SDKS.$(bld_trg)) \
701 $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \
702 $($(target)_SDKS.$(bld_type)) \
703 $($(target)_SDKS),\
704 $(SDK_$(sdk)_DEFS)\
705 $(SDK_$(sdk)_DEFS.$(bld_type))\
706 $(SDK_$(sdk)_DEFS.$(bld_trg))\
707 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
708 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
709 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
710 $(SDK_$(sdk)_$(type)DEFS)\
711 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
712 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
713 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
714 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
715 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
716 $($(target)_DEFS)\
717 $($(target)_DEFS.$(bld_type))\
718 $($(target)_DEFS.$(bld_trg))\
719 $($(target)_DEFS.$(bld_trg_arch))\
720 $($(target)_DEFS.$(bld_trg).$(bld_trg_arch))\
721 $($(target)_DEFS.$(bld_trg_cpu))\
722 $($(target)_$(type)DEFS)\
723 $($(target)_$(type)DEFS.$(bld_type))\
724 $($(target)_$(type)DEFS.$(bld_trg))\
725 $($(target)_$(type)DEFS.$(bld_trg_arch))\
726 $($(target)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
727 $($(target)_$(type)DEFS.$(bld_trg_cpu))\
728 $(foreach sdk, $($(source)_SDKS.$(bld_trg)) \
729 $($(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
730 $($(source)_SDKS.$(bld_type)) \
731 $($(source)_SDKS),\
732 $(SDK_$(sdk)_DEFS)\
733 $(SDK_$(sdk)_DEFS.$(bld_type))\
734 $(SDK_$(sdk)_DEFS.$(bld_trg))\
735 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
736 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
737 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
738 $(SDK_$(sdk)_$(type)DEFS)\
739 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
740 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
741 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
742 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
743 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
744 $($(source)_DEFS)\
745 $($(source)_DEFS.$(bld_type))\
746 $($(source)_DEFS.$(bld_trg))\
747 $($(source)_DEFS.$(bld_trg_arch))\
748 $($(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
749 $($(source)_DEFS.$(bld_trg_cpu))\
750 $($(source)_$(type)DEFS)\
751 $($(source)_$(type)DEFS.$(bld_type))\
752 $($(source)_$(type)DEFS.$(bld_trg))\
753 $($(source)_$(type)DEFS.$(bld_trg_arch))\
754 $($(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
755 $($(source)_$(type)DEFS.$(bld_trg_cpu))\
756 $(foreach sdk, $($(target)_$(source)_SDKS.$(bld_trg)) \
757 $($(target)_$(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
758 $($(target)_$(source)_SDKS.$(bld_type)) \
759 $($(target)_$(source)_SDKS),\
760 $(SDK_$(sdk)_DEFS)\
761 $(SDK_$(sdk)_DEFS.$(bld_type))\
762 $(SDK_$(sdk)_DEFS.$(bld_trg))\
763 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
764 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
765 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
766 $(SDK_$(sdk)_$(type)DEFS)\
767 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
768 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
769 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
770 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
771 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
772 $($(target)_$(source)_DEFS)\
773 $($(target)_$(source)_DEFS.$(bld_type))\
774 $($(target)_$(source)_DEFS.$(bld_trg))\
775 $($(target)_$(source)_DEFS.$(bld_trg_arch))\
776 $($(target)_$(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
777 $($(target)_$(source)_DEFS.$(bld_trg_cpu))\
778 $($(target)_$(source)_$(type)DEFS)\
779 $($(target)_$(source)_$(type)DEFS.$(bld_type))\
780 $($(target)_$(source)_$(type)DEFS.$(bld_trg))\
781 $($(target)_$(source)_$(type)DEFS.$(bld_trg_arch))\
782 $($(target)_$(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
783 $($(target)_$(source)_$(type)DEFS.$(bld_trg_cpu))
784*/
785static struct variable *
786kbuild_collect_source_prop(struct variable *pTarget, struct variable *pSource,
787 struct variable *pTool, struct kbuild_sdks *pSdks,
788 struct variable *pType, struct variable *pBldType,
789 struct variable *pBldTrg, struct variable *pBldTrgArch, struct variable *pBldTrgCpu,
790 const char *pszProp, const char *pszVarName, int iDirection)
791{
792 struct variable *pVar;
793 unsigned iSdk;
794 int cVars, iVar, iVarEnd;
795 size_t cchTotal;
796 char *pszResult, *psz;
797 struct
798 {
799 struct variable *pVar;
800 size_t cchExp;
801 char *pszExp;
802 } *paVars;
803
804 struct variable Prop = {0};
805 Prop.value = (char *)pszProp;
806 Prop.value_length = strlen(pszProp);
807
808 assert(iDirection == 1 || iDirection == -1);
809
810 /*
811 * Get the variables.
812 */
813 cVars = 12 * (pSdks->c + 5);
814 paVars = alloca(cVars * sizeof(paVars[0]));
815
816 iVar = 0;
817 /* the tool (lowest priority) */
818 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%", pTool, &Prop);
819 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%.%", pTool, &Prop, pBldType);
820 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%.%", pTool, &Prop, pBldTrg);
821 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%.%", pTool, &Prop, pBldTrgArch);
822 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%.%.%", pTool, &Prop, pBldTrg, pBldTrgArch);
823 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%.%", pTool, &Prop, pBldTrgCpu);
824
825 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%%", pTool, pType, &Prop);
826 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%%.%", pTool, pType, &Prop, pBldType);
827 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%%.%", pTool, pType, &Prop, pBldTrg);
828 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%%.%", pTool, pType, &Prop, pBldTrgArch);
829 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%%.%.%", pTool, pType, &Prop, pBldTrg, pBldTrgArch);
830 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%%.%", pTool, pType, &Prop, pBldTrgCpu);
831
832 /* the global sdks */
833 for (iSdk = pSdks->iGlobal; iSdk < pSdks->iGlobal + pSdks->cGlobal; iSdk++)
834 {
835 struct variable *pSdk = &pSdks->pa[iSdk];
836 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%", pSdk, &Prop);
837 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldType);
838 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrg);
839 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
840 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
841 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
842
843 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%", pSdk, pType, &Prop);
844 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
845 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
846 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
847 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
848 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
849 }
850
851 /* the globals */
852 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%", &Prop);
853 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%.%", &Prop, pBldType);
854 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%.%", &Prop, pBldTrg);
855 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%.%", &Prop, pBldTrgArch);
856 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%.%.%", &Prop, pBldTrg, pBldTrgArch);
857 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%.%", &Prop, pBldTrgCpu);
858
859 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%%", pType, &Prop);
860 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%%.%", pType, &Prop, pBldType);
861 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%%.%", pType, &Prop, pBldTrg);
862 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%%.%", pType, &Prop, pBldTrgArch);
863 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%%.%.%", pType, &Prop, pBldTrg, pBldTrgArch);
864 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%%.%", pType, &Prop, pBldTrgCpu);
865
866 /* the target sdks */
867 for (iSdk = pSdks->iTarget; iSdk < pSdks->iTarget + pSdks->cTarget; iSdk++)
868 {
869 struct variable *pSdk = &pSdks->pa[iSdk];
870 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%", pSdk, &Prop);
871 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldType);
872 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrg);
873 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
874 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
875 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
876
877 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%", pSdk, pType, &Prop);
878 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
879 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
880 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
881 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
882 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
883 }
884
885 /* the target */
886 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%", pTarget, &Prop);
887 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pTarget, &Prop, pBldType);
888 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pTarget, &Prop, pBldTrg);
889 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pTarget, &Prop, pBldTrgArch);
890 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%.%", pTarget, &Prop, pBldTrg, pBldTrgArch);
891 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pTarget, &Prop, pBldTrgCpu);
892
893 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%", pTarget, pType, &Prop);
894 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pTarget, pType, &Prop, pBldType);
895 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pTarget, pType, &Prop, pBldTrg);
896 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pTarget, pType, &Prop, pBldTrgArch);
897 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%.%", pTarget, pType, &Prop, pBldTrg, pBldTrgArch);
898 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pTarget, pType, &Prop, pBldTrgCpu);
899
900 /* the source sdks */
901 for (iSdk = pSdks->iSource; iSdk < pSdks->iSource + pSdks->cSource; iSdk++)
902 {
903 struct variable *pSdk = &pSdks->pa[iSdk];
904 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%", pSdk, &Prop);
905 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldType);
906 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrg);
907 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
908 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
909 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
910
911 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%", pSdk, pType, &Prop);
912 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
913 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
914 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
915 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
916 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
917 }
918
919 /* the source */
920 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%", pSource, &Prop);
921 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pSource, &Prop, pBldType);
922 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pSource, &Prop, pBldTrg);
923 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pSource, &Prop, pBldTrgArch);
924 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%.%", pSource, &Prop, pBldTrg, pBldTrgArch);
925 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pSource, &Prop, pBldTrgCpu);
926
927 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%", pSource, pType, &Prop);
928 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pSource, pType, &Prop, pBldType);
929 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pSource, pType, &Prop, pBldTrg);
930 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pSource, pType, &Prop, pBldTrgArch);
931 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%.%", pSource, pType, &Prop, pBldTrg, pBldTrgArch);
932 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pSource, pType, &Prop, pBldTrgCpu);
933
934
935 /* the target + source sdks */
936 for (iSdk = pSdks->iTargetSource; iSdk < pSdks->iTargetSource + pSdks->cTargetSource; iSdk++)
937 {
938 struct variable *pSdk = &pSdks->pa[iSdk];
939 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%", pSdk, &Prop);
940 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldType);
941 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrg);
942 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
943 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
944 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
945
946 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%", pSdk, pType, &Prop);
947 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
948 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
949 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
950 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
951 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
952 }
953
954 /* the target + source */
955 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%", pTarget, pSource, &Prop);
956 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%.%", pTarget, pSource, &Prop, pBldType);
957 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%.%", pTarget, pSource, &Prop, pBldTrg);
958 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%.%", pTarget, pSource, &Prop, pBldTrgArch);
959 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%.%.%", pTarget, pSource, &Prop, pBldTrg, pBldTrgArch);
960 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%.%", pTarget, pSource, &Prop, pBldTrgCpu);
961
962 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%%", pTarget, pSource, pType, &Prop);
963 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%%.%", pTarget, pSource, pType, &Prop, pBldType);
964 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrg);
965 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrgArch);
966 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%%.%.%", pTarget, pSource, pType, &Prop, pBldTrg, pBldTrgArch);
967 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrgCpu);
968
969 assert(cVars == iVar);
970
971 /*
972 * Expand the variables and calculate the total length.
973 */
974 cchTotal = 0;
975 iVarEnd = iDirection == 1 ? cVars : 0;
976 for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
977 {
978 paVars[iVar].cchExp = 0;
979 if (!paVars[iVar].pVar)
980 continue;
981 if ( paVars[iVar].pVar->flavor == f_simple
982 || !strchr(paVars[iVar].pVar->value, '$'))
983 {
984 paVars[iVar].pszExp = paVars[iVar].pVar->value;
985 paVars[iVar].cchExp = paVars[iVar].pVar->value_length;
986 }
987 else
988 {
989 paVars[iVar].pszExp = allocated_variable_expand(paVars[iVar].pVar->value);
990 paVars[iVar].cchExp = strlen(paVars[iVar].pszExp);
991 }
992 cchTotal += paVars[iVar].cchExp + 1;
993 }
994
995 /*
996 * Construct the result value.
997 */
998 psz = pszResult = xmalloc(cchTotal + 1);
999 iVarEnd = iDirection == 1 ? cVars : 0;
1000 for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
1001 {
1002 if (!paVars[iVar].cchExp)
1003 continue;
1004 memcpy(psz, paVars[iVar].pszExp, paVars[iVar].cchExp);
1005 psz += paVars[iVar].cchExp;
1006 *psz++ = ' ';
1007 if (paVars[iVar].pszExp != paVars[iVar].pVar->value)
1008 free(paVars[iVar].pszExp);
1009 }
1010 if (psz != pszResult)
1011 psz--;
1012 *psz = '\0';
1013 cchTotal = psz - pszResult;
1014
1015 pVar = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cchTotal,
1016 0 /* take pszResult */ , o_file, 0 /* !recursive */);
1017 return pVar;
1018}
1019
1020/* get a source property. */
1021char *
1022func_kbuild_source_prop(char *o, char **argv, const char *pszFuncName)
1023{
1024 struct variable *pTarget = kbuild_get_variable("target");
1025 struct variable *pSource = kbuild_get_variable("source");
1026 struct variable *pType = kbuild_get_variable("type");
1027 struct variable *pTool = kbuild_get_variable("tool");
1028 struct variable *pBldType = kbuild_get_variable("bld_type");
1029 struct variable *pBldTrg = kbuild_get_variable("bld_trg");
1030 struct variable *pBldTrgArch = kbuild_get_variable("bld_trg_arch");
1031 struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
1032 struct variable *pVar;
1033 struct kbuild_sdks Sdks;
1034 int iDirection;
1035 if (!strcmp(argv[2], "left-to-right"))
1036 iDirection = 1;
1037 else if (!strcmp(argv[2], "right-to-left"))
1038 iDirection = -1;
1039 else
1040 fatal(NILF, _("incorrect direction argument `%s'!"), argv[2]);
1041
1042 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
1043
1044 pVar = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType,
1045 pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
1046 argv[0], argv[1], iDirection);
1047 if (pVar)
1048 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1049
1050 kbuild_put_sdks(&Sdks);
1051 return o;
1052
1053}
1054
1055/*
1056dep := $(obj)$(SUFF_DEP)
1057obj := $(outbase)$(objsuff)
1058dirdep := $(call DIRDEP,$(dir $(outbase)))
1059PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1060*/
1061static struct variable *
1062kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(struct variable *pTarget, struct variable *pSource,
1063 struct variable *pOutBase, struct variable *pObjSuff,
1064 const char *pszVarName, struct variable **ppDep,
1065 struct variable **ppDirDep)
1066{
1067 struct variable *pDepSuff = kbuild_get_variable("SUFF_DEP");
1068 struct variable *pObj;
1069 size_t cch = pOutBase->value_length + pObjSuff->value_length + pDepSuff->value_length + 1;
1070 char *pszResult = alloca(cch);
1071 char *pszName, *psz;
1072
1073 /*
1074 * dep.
1075 */
1076 psz = pszResult;
1077 memcpy(psz, pOutBase->value, pOutBase->value_length); psz += pOutBase->value_length;
1078 memcpy(psz, pObjSuff->value, pObjSuff->value_length); psz += pObjSuff->value_length;
1079 memcpy(psz, pDepSuff->value, pDepSuff->value_length + 1);
1080 *ppDep = define_variable_vl("dep", 3, pszResult, cch - 1, 1 /*dup*/, o_file, 0 /* !recursive */);
1081
1082 /*
1083 * obj
1084 */
1085 *psz = '\0';
1086 pObj = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, psz - pszResult,
1087 1/* dup */, o_file, 0 /* !recursive */);
1088
1089 /*
1090 * PATH_$(target)_$(source) - this is global!
1091 */
1092 /* calc variable name. */
1093 cch = sizeof("PATH_")-1 + pTarget->value_length + sizeof("_")-1 + pSource->value_length;
1094 psz = pszName = alloca(cch + 1);
1095 memcpy(psz, "PATH_", sizeof("PATH_") - 1); psz += sizeof("PATH_") - 1;
1096 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1097 *psz++ = '_';
1098 memcpy(psz, pSource->value, pSource->value_length + 1);
1099
1100 /* strip off the filename. */
1101 psz = pszResult + pOutBase->value_length;
1102 for (;;)
1103 {
1104 psz--;
1105 if (psz <= pszResult)
1106 fatal(NULL, "whut!?! no path? result=`%s'", pszResult);
1107#ifdef HAVE_DOS_PATHS
1108 if (*psz == ':')
1109 {
1110 psz++;
1111 break;
1112 }
1113#endif
1114 if ( *psz == '/'
1115#ifdef HAVE_DOS_PATHS
1116 || *psz == '\\'
1117#endif
1118 )
1119 {
1120 while ( psz - 1 > pszResult
1121 && psz[-1] == '/'
1122#ifdef HAVE_DOS_PATHS
1123 || psz[-1] == '\\'
1124#endif
1125 )
1126 psz--;
1127#ifdef HAVE_DOS_PATHS
1128 if (psz == pszResult + 2 && pszResult[1] == ':')
1129 psz++;
1130#endif
1131 break;
1132 }
1133 }
1134 *psz = '\0';
1135
1136 /* set global variable */
1137 define_variable_vl_global(pszName, cch, pszResult, psz - pszResult, 1/*dup*/, o_file, 0 /* !recursive */, NILF);
1138
1139 /*
1140 * dirdep
1141 */
1142 if ( psz[-1] != '/'
1143#ifdef HAVE_DOS_PATHS
1144 && psz[-1] != '\\'
1145 && psz[-1] != ':'
1146#endif
1147 )
1148 {
1149 *psz++ = '/';
1150 *psz = '\0';
1151 }
1152 *ppDirDep = define_variable_vl("dirdep", 6, pszResult, psz - pszResult, 1/*dup*/, o_file, 0 /* !recursive */);
1153
1154 return pObj;
1155}
1156
1157
1158/* setup the base variables for def_target_source_c_cpp_asm_new:
1159
1160X := $(kb-src-tool tool)
1161x := $(kb-obj-base outbase)
1162x := $(kb-obj-suff objsuff)
1163obj := $(outbase)$(objsuff)
1164PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1165
1166x := $(kb-src-prop DEFS,defs,left-to-right)
1167x := $(kb-src-prop INCS,incs,right-to-left)
1168x := $(kb-src-prop FLAGS,flags,right-to-left)
1169
1170x := $(kb-src-prop DEPS,deps,left-to-right)
1171dirdep := $(call DIRDEP,$(dir $(outbase)))
1172dep := $(obj)$(SUFF_DEP)
1173*/
1174char *
1175func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
1176{
1177 static int s_fNoCompileCmdsDepsDefined = -1;
1178 struct variable *pTarget = kbuild_get_variable("target");
1179 struct variable *pSource = kbuild_get_variable("source");
1180 struct variable *pType = kbuild_get_variable("type");
1181 struct variable *pBldType = kbuild_get_variable("bld_type");
1182 struct variable *pBldTrg = kbuild_get_variable("bld_trg");
1183 struct variable *pBldTrgArch= kbuild_get_variable("bld_trg_arch");
1184 struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
1185 struct variable *pTool = kbuild_get_source_tool(pTarget, pSource, pType, pBldTrg, pBldTrgArch, "tool");
1186 struct variable *pOutBase = kbuild_get_object_base(pTarget, pSource, "outbase");
1187 struct variable *pObjSuff = kbuild_get_object_suffix(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch, "objsuff");
1188 struct variable *pDefs, *pIncs, *pFlags, *pDeps, *pDirDep, *pDep, *pVar, *pOutput;
1189 struct variable *pObj = kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(pTarget, pSource, pOutBase, pObjSuff, "obj", &pDep, &pDirDep);
1190 char *pszDstVar, *pszDst, *pszSrcVar, *pszSrc, *pszVal, *psz;
1191 char *pszSavedVarBuf;
1192 unsigned cchSavedVarBuf;
1193 size_t cch;
1194 struct kbuild_sdks Sdks;
1195 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
1196
1197 pDefs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
1198 "DEFS", "defs", 1/* left-to-right */);
1199 pIncs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
1200 "INCS", "incs", -1/* right-to-left */);
1201 pFlags = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
1202 "FLAGS", "flags", -1/* right-to-left */);
1203 pDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
1204 "DEPS", "deps", 1/* left-to-right */);
1205
1206 /*
1207 # dependencies
1208 ifndef NO_COMPILE_CMDS_DEPS
1209 _DEPFILES_INCLUDED += $(dep)
1210 $(if $(wildcard $(dep)),$(eval include $(dep)))
1211 endif
1212 */
1213 if (s_fNoCompileCmdsDepsDefined == -1)
1214 s_fNoCompileCmdsDepsDefined = kbuild_lookup_variable("NO_COMPILE_CMDS_DEPS") != NULL;
1215 if (!s_fNoCompileCmdsDepsDefined)
1216 {
1217 do_variable_definition(NILF, "_DEPFILES_INCLUDED", pDep->value, o_file, f_append, 0 /* !target_var */);
1218 eval_include_dep(pDep->value, NILF);
1219 }
1220
1221 /*
1222 # call the tool
1223 $(target)_$(source)_CMDS_ := $(TOOL_$(tool)_COMPILE_$(type)_CMDS)
1224 $(target)_$(source)_OUTPUT_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT)
1225 $(target)_$(source)_DEPEND_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPEND) $(deps) $(source)
1226 $(target)_$(source)_DEPORD_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPORD) $(dirdep)
1227 */
1228 cch = sizeof("TOOL_") + pTool->value_length + sizeof("_COMPILE_") + pType->value_length + sizeof("_OUTPUT");
1229 psz = pszSrcVar = alloca(cch);
1230 memcpy(psz, "TOOL_", sizeof("TOOL_") - 1); psz += sizeof("TOOL_") - 1;
1231 memcpy(psz, pTool->value, pTool->value_length); psz += pTool->value_length;
1232 memcpy(psz, "_COMPILE_", sizeof("_COMPILE_") - 1); psz += sizeof("_COMPILE_") - 1;
1233 memcpy(psz, pType->value, pType->value_length); psz += pType->value_length;
1234 pszSrc = psz;
1235
1236 cch = pTarget->value_length + 1 + pSource->value_length + sizeof("_OUTPUT_");
1237 psz = pszDstVar = alloca(cch);
1238 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1239 *psz++ = '_';
1240 memcpy(psz, pSource->value, pSource->value_length); psz += pSource->value_length;
1241 pszDst = psz;
1242
1243 memcpy(pszSrc, "_CMDS", sizeof("_CMDS"));
1244 memcpy(pszDst, "_CMDS_", sizeof("_CMDS_"));
1245 pVar = kbuild_get_recursive_variable(pszSrcVar);
1246 do_variable_definition(NILF, pszDstVar, pVar->value, o_file, f_simple, 0 /* !target_var */);
1247
1248 memcpy(pszSrc, "_OUTPUT", sizeof("_OUTPUT"));
1249 memcpy(pszDst, "_OUTPUT_", sizeof("_OUTPUT_"));
1250 pVar = kbuild_get_recursive_variable(pszSrcVar);
1251 pOutput = do_variable_definition(NILF, pszDstVar, pVar->value, o_file, f_simple, 0 /* !target_var */);
1252
1253 memcpy(pszSrc, "_DEPEND", sizeof("_DEPEND"));
1254 memcpy(pszDst, "_DEPEND_", sizeof("_DEPEND_"));
1255 pVar = kbuild_get_recursive_variable(pszSrcVar);
1256 psz = pszVal = xmalloc(pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length + 1);
1257 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1258 *psz++ = ' ';
1259 memcpy(psz, pDeps->value, pDeps->value_length); psz += pDeps->value_length;
1260 *psz++ = ' ';
1261 memcpy(psz, pSource->value, pSource->value_length + 1);
1262 do_variable_definition(NILF, pszDstVar, pszVal, o_file, f_simple, 0 /* !target_var */);
1263 free(pszVal);
1264
1265 memcpy(pszSrc, "_DEPORD", sizeof("_DEPORD"));
1266 memcpy(pszDst, "_DEPORD_", sizeof("_DEPORD_"));
1267 pVar = kbuild_get_recursive_variable(pszSrcVar);
1268 psz = pszVal = xmalloc(pVar->value_length + 1 + pDirDep->value_length + 1);
1269 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1270 *psz++ = ' ';
1271 memcpy(psz, pDirDep->value, pDirDep->value_length + 1);
1272 do_variable_definition(NILF, pszDstVar, pszVal, o_file, f_simple, 0 /* !target_var */);
1273 free(pszVal);
1274
1275 /*
1276 _OUT_FILES += $($(target)_$(source)_OUTPUT_)
1277 */
1278 pVar = kbuild_get_variable("_OUT_FILES");
1279 psz = pszVal = xmalloc(pVar->value_length + 1 + pOutput->value_length + 1);
1280 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1281 *psz++ = ' ';
1282 memcpy(psz, pOutput->value, pOutput->value_length + 1);
1283 do_variable_definition(NILF, "_OUT_FILES", pszVal, o_file, f_simple, 0 /* !target_var */);
1284 free(pszVal);
1285
1286 /*
1287 $(target)_OBJS_ += $(obj)
1288 */
1289 memcpy(pszDstVar + pTarget->value_length, "_OBJS_", sizeof("_OBJS_"));
1290 do_variable_definition(NILF, pszDstVar, pObj->value, o_file, f_append, 0 /* !target_var */);
1291
1292 /*
1293 $(eval $(def_target_source_rule))
1294 */
1295 pVar = kbuild_get_recursive_variable("def_target_source_rule");
1296 pszVal = allocated_variable_expand(pVar->value);
1297
1298 install_variable_buffer(&pszSavedVarBuf, &cchSavedVarBuf);
1299 eval_buffer(pszVal);
1300 restore_variable_buffer(pszSavedVarBuf, cchSavedVarBuf);
1301
1302 free(pszVal);
1303
1304 kbuild_put_sdks(&Sdks);
1305 return variable_buffer_output(o, "", 1);
1306}
1307
1308
1309#endif /* KMK_HELPERS */
Note: See TracBrowser for help on using the repository browser.