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

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

skip some unnecessary copies and allocations.

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