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

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

Partial implementation of a _PATH target property for resolving relative paths. It's primarily intended for sub-makefile mode where we apply it to all targets automatically. TODOs: INCS, DEPs (source level) and SUBDIRS*.

File size: 54.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 struct variable *pDefPath,
791 const char *pszProp, const char *pszVarName, int iDirection)
792{
793 struct variable *pVar;
794 unsigned iSdk, iSdkEnd;
795 int cVars, iVar, iVarEnd;
796 size_t cchTotal;
797 char *pszResult, *psz;
798 struct
799 {
800 struct variable *pVar;
801 size_t cchExp;
802 char *pszExp;
803 } *paVars;
804
805 struct variable Prop = {0};
806 Prop.value = (char *)pszProp;
807 Prop.value_length = strlen(pszProp);
808
809 assert(iDirection == 1 || iDirection == -1);
810
811 /*
812 * Get the variables.
813 */
814 cVars = 12 * (pSdks->c + 5);
815 paVars = alloca(cVars * sizeof(paVars[0]));
816
817 iVar = 0;
818 /* the tool (lowest priority) */
819 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%", pTool, &Prop);
820 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%.%", pTool, &Prop, pBldType);
821 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%.%", pTool, &Prop, pBldTrg);
822 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%.%", pTool, &Prop, pBldTrgArch);
823 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%.%.%", pTool, &Prop, pBldTrg, pBldTrgArch);
824 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%.%", pTool, &Prop, pBldTrgCpu);
825
826 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%%", pTool, pType, &Prop);
827 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%%.%", pTool, pType, &Prop, pBldType);
828 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%%.%", pTool, pType, &Prop, pBldTrg);
829 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%%.%", pTool, pType, &Prop, pBldTrgArch);
830 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%%.%.%", pTool, pType, &Prop, pBldTrg, pBldTrgArch);
831 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("TOOL_%_%%.%", pTool, pType, &Prop, pBldTrgCpu);
832
833 /* the global sdks */
834 iSdkEnd = iDirection == 1 ? pSdks->iGlobal + pSdks->cGlobal : pSdks->iGlobal - 1;
835 for (iSdk = iDirection == 1 ? pSdks->iGlobal : pSdks->iGlobal + pSdks->cGlobal - 1;
836 iSdk != iSdkEnd;
837 iSdk += iDirection)
838 {
839 struct variable *pSdk = &pSdks->pa[iSdk];
840 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%", pSdk, &Prop);
841 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldType);
842 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrg);
843 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
844 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
845 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
846
847 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%", pSdk, pType, &Prop);
848 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
849 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
850 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
851 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
852 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
853 }
854
855 /* the globals */
856 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%", &Prop);
857 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%.%", &Prop, pBldType);
858 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%.%", &Prop, pBldTrg);
859 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%.%", &Prop, pBldTrgArch);
860 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%.%.%", &Prop, pBldTrg, pBldTrgArch);
861 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%.%", &Prop, pBldTrgCpu);
862
863 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%%", pType, &Prop);
864 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%%.%", pType, &Prop, pBldType);
865 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%%.%", pType, &Prop, pBldTrg);
866 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%%.%", pType, &Prop, pBldTrgArch);
867 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%%.%.%", pType, &Prop, pBldTrg, pBldTrgArch);
868 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%%.%", pType, &Prop, pBldTrgCpu);
869
870 /* the target sdks */
871 iSdkEnd = iDirection == 1 ? pSdks->iTarget + pSdks->cTarget : pSdks->iTarget - 1;
872 for (iSdk = iDirection == 1 ? pSdks->iTarget : pSdks->iTarget + pSdks->cTarget - 1;
873 iSdk != iSdkEnd;
874 iSdk += iDirection)
875 {
876 struct variable *pSdk = &pSdks->pa[iSdk];
877 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%", pSdk, &Prop);
878 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldType);
879 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrg);
880 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
881 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
882 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
883
884 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%", pSdk, pType, &Prop);
885 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
886 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
887 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
888 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
889 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
890 }
891
892 /* the target */
893 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%", pTarget, &Prop);
894 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pTarget, &Prop, pBldType);
895 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pTarget, &Prop, pBldTrg);
896 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pTarget, &Prop, pBldTrgArch);
897 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%.%", pTarget, &Prop, pBldTrg, pBldTrgArch);
898 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pTarget, &Prop, pBldTrgCpu);
899
900 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%", pTarget, pType, &Prop);
901 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pTarget, pType, &Prop, pBldType);
902 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pTarget, pType, &Prop, pBldTrg);
903 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pTarget, pType, &Prop, pBldTrgArch);
904 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%.%", pTarget, pType, &Prop, pBldTrg, pBldTrgArch);
905 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pTarget, pType, &Prop, pBldTrgCpu);
906
907 /* the source sdks */
908 iSdkEnd = iDirection == 1 ? pSdks->iSource + pSdks->cSource : pSdks->iSource - 1;
909 for (iSdk = iDirection == 1 ? pSdks->iSource : pSdks->iSource + pSdks->cSource - 1;
910 iSdk != iSdkEnd;
911 iSdk += iDirection)
912 {
913 struct variable *pSdk = &pSdks->pa[iSdk];
914 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%", pSdk, &Prop);
915 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldType);
916 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrg);
917 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
918 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
919 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
920
921 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%", pSdk, pType, &Prop);
922 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
923 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
924 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
925 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
926 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
927 }
928
929 /* the source */
930 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%", pSource, &Prop);
931 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pSource, &Prop, pBldType);
932 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pSource, &Prop, pBldTrg);
933 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pSource, &Prop, pBldTrgArch);
934 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%.%", pSource, &Prop, pBldTrg, pBldTrgArch);
935 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%.%", pSource, &Prop, pBldTrgCpu);
936
937 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%", pSource, pType, &Prop);
938 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pSource, pType, &Prop, pBldType);
939 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pSource, pType, &Prop, pBldTrg);
940 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pSource, pType, &Prop, pBldTrgArch);
941 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%.%", pSource, pType, &Prop, pBldTrg, pBldTrgArch);
942 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%%.%", pSource, pType, &Prop, pBldTrgCpu);
943
944
945 /* the target + source sdks */
946 iSdkEnd = iDirection == 1 ? pSdks->iTargetSource + pSdks->cTargetSource : pSdks->iTargetSource - 1;
947 for (iSdk = iDirection == 1 ? pSdks->iTargetSource : pSdks->iTargetSource + pSdks->cTargetSource - 1;
948 iSdk != iSdkEnd;
949 iSdk += iDirection)
950 {
951 struct variable *pSdk = &pSdks->pa[iSdk];
952 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%", pSdk, &Prop);
953 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldType);
954 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrg);
955 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
956 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
957 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
958
959 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%", pSdk, pType, &Prop);
960 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
961 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
962 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
963 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
964 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
965 }
966
967 /* the target + source */
968 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%", pTarget, pSource, &Prop);
969 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%.%", pTarget, pSource, &Prop, pBldType);
970 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%.%", pTarget, pSource, &Prop, pBldTrg);
971 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%.%", pTarget, pSource, &Prop, pBldTrgArch);
972 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%.%.%", pTarget, pSource, &Prop, pBldTrg, pBldTrgArch);
973 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%.%", pTarget, pSource, &Prop, pBldTrgCpu);
974
975 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%%", pTarget, pSource, pType, &Prop);
976 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%%.%", pTarget, pSource, pType, &Prop, pBldType);
977 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrg);
978 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrgArch);
979 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%%.%.%", pTarget, pSource, pType, &Prop, pBldTrg, pBldTrgArch);
980 paVars[iVar++].pVar = kbuild_lookup_variable_fmt("%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrgCpu);
981
982 assert(cVars == iVar);
983
984 /*
985 * Expand the variables and calculate the total length.
986 */
987 cchTotal = 0;
988 iVarEnd = iDirection == 1 ? cVars : 0;
989 for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
990 {
991 paVars[iVar].cchExp = 0;
992 if (!paVars[iVar].pVar)
993 continue;
994 if ( paVars[iVar].pVar->flavor == f_simple
995 || !strchr(paVars[iVar].pVar->value, '$'))
996 {
997 paVars[iVar].pszExp = paVars[iVar].pVar->value;
998 paVars[iVar].cchExp = paVars[iVar].pVar->value_length;
999 }
1000 else
1001 {
1002 paVars[iVar].pszExp = allocated_variable_expand(paVars[iVar].pVar->value);
1003 paVars[iVar].cchExp = strlen(paVars[iVar].pszExp);
1004 }
1005 if (pDefPath)
1006 {
1007 /** @todo */
1008 }
1009 cchTotal += paVars[iVar].cchExp + 1;
1010 }
1011
1012 /*
1013 * Construct the result value.
1014 */
1015 psz = pszResult = xmalloc(cchTotal + 1);
1016 iVarEnd = iDirection == 1 ? cVars : 0;
1017 for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
1018 {
1019 if (!paVars[iVar].cchExp)
1020 continue;
1021 memcpy(psz, paVars[iVar].pszExp, paVars[iVar].cchExp);
1022 psz += paVars[iVar].cchExp;
1023 *psz++ = ' ';
1024 if (paVars[iVar].pszExp != paVars[iVar].pVar->value)
1025 free(paVars[iVar].pszExp);
1026 }
1027 if (psz != pszResult)
1028 psz--;
1029 *psz = '\0';
1030 cchTotal = psz - pszResult;
1031
1032 pVar = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cchTotal,
1033 0 /* take pszResult */ , o_file, 0 /* !recursive */);
1034 return pVar;
1035}
1036
1037/* get a source property. Doesn't respect the default path. */
1038char *
1039func_kbuild_source_prop(char *o, char **argv, const char *pszFuncName)
1040{
1041 struct variable *pTarget = kbuild_get_variable("target");
1042 struct variable *pSource = kbuild_get_variable("source");
1043 struct variable *pType = kbuild_get_variable("type");
1044 struct variable *pTool = kbuild_get_variable("tool");
1045 struct variable *pBldType = kbuild_get_variable("bld_type");
1046 struct variable *pBldTrg = kbuild_get_variable("bld_trg");
1047 struct variable *pBldTrgArch = kbuild_get_variable("bld_trg_arch");
1048 struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
1049 struct variable *pVar;
1050 struct kbuild_sdks Sdks;
1051 int iDirection;
1052 if (!strcmp(argv[2], "left-to-right"))
1053 iDirection = 1;
1054 else if (!strcmp(argv[2], "right-to-left"))
1055 iDirection = -1;
1056 else
1057 fatal(NILF, _("incorrect direction argument `%s'!"), argv[2]);
1058
1059 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
1060
1061 pVar = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType,
1062 pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
1063 NULL,
1064 argv[0], argv[1], iDirection);
1065 if (pVar)
1066 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1067
1068 kbuild_put_sdks(&Sdks);
1069 return o;
1070
1071}
1072
1073/*
1074dep := $(obj)$(SUFF_DEP)
1075obj := $(outbase)$(objsuff)
1076dirdep := $(call DIRDEP,$(dir $(outbase)))
1077PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1078*/
1079static struct variable *
1080kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(struct variable *pTarget, struct variable *pSource,
1081 struct variable *pOutBase, struct variable *pObjSuff,
1082 const char *pszVarName, struct variable **ppDep,
1083 struct variable **ppDirDep)
1084{
1085 struct variable *pDepSuff = kbuild_get_variable("SUFF_DEP");
1086 struct variable *pObj;
1087 size_t cch = pOutBase->value_length + pObjSuff->value_length + pDepSuff->value_length + 1;
1088 char *pszResult = alloca(cch);
1089 char *pszName, *psz;
1090
1091 /*
1092 * dep.
1093 */
1094 psz = pszResult;
1095 memcpy(psz, pOutBase->value, pOutBase->value_length); psz += pOutBase->value_length;
1096 memcpy(psz, pObjSuff->value, pObjSuff->value_length); psz += pObjSuff->value_length;
1097 memcpy(psz, pDepSuff->value, pDepSuff->value_length + 1);
1098 *ppDep = define_variable_vl("dep", 3, pszResult, cch - 1, 1 /*dup*/, o_file, 0 /* !recursive */);
1099
1100 /*
1101 * obj
1102 */
1103 *psz = '\0';
1104 pObj = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, psz - pszResult,
1105 1/* dup */, o_file, 0 /* !recursive */);
1106
1107 /*
1108 * PATH_$(target)_$(source) - this is global!
1109 */
1110 /* calc variable name. */
1111 cch = sizeof("PATH_")-1 + pTarget->value_length + sizeof("_")-1 + pSource->value_length;
1112 psz = pszName = alloca(cch + 1);
1113 memcpy(psz, "PATH_", sizeof("PATH_") - 1); psz += sizeof("PATH_") - 1;
1114 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1115 *psz++ = '_';
1116 memcpy(psz, pSource->value, pSource->value_length + 1);
1117
1118 /* strip off the filename. */
1119 psz = pszResult + pOutBase->value_length;
1120 for (;;)
1121 {
1122 psz--;
1123 if (psz <= pszResult)
1124 fatal(NULL, "whut!?! no path? result=`%s'", pszResult);
1125#ifdef HAVE_DOS_PATHS
1126 if (*psz == ':')
1127 {
1128 psz++;
1129 break;
1130 }
1131#endif
1132 if ( *psz == '/'
1133#ifdef HAVE_DOS_PATHS
1134 || *psz == '\\'
1135#endif
1136 )
1137 {
1138 while ( psz - 1 > pszResult
1139 && psz[-1] == '/'
1140#ifdef HAVE_DOS_PATHS
1141 || psz[-1] == '\\'
1142#endif
1143 )
1144 psz--;
1145#ifdef HAVE_DOS_PATHS
1146 if (psz == pszResult + 2 && pszResult[1] == ':')
1147 psz++;
1148#endif
1149 break;
1150 }
1151 }
1152 *psz = '\0';
1153
1154 /* set global variable */
1155 define_variable_vl_global(pszName, cch, pszResult, psz - pszResult, 1/*dup*/, o_file, 0 /* !recursive */, NILF);
1156
1157 /*
1158 * dirdep
1159 */
1160 if ( psz[-1] != '/'
1161#ifdef HAVE_DOS_PATHS
1162 && psz[-1] != '\\'
1163 && psz[-1] != ':'
1164#endif
1165 )
1166 {
1167 *psz++ = '/';
1168 *psz = '\0';
1169 }
1170 *ppDirDep = define_variable_vl("dirdep", 6, pszResult, psz - pszResult, 1/*dup*/, o_file, 0 /* !recursive */);
1171
1172 return pObj;
1173}
1174
1175
1176/* setup the base variables for def_target_source_c_cpp_asm_new:
1177
1178X := $(kb-src-tool tool)
1179x := $(kb-obj-base outbase)
1180x := $(kb-obj-suff objsuff)
1181obj := $(outbase)$(objsuff)
1182PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1183
1184x := $(kb-src-prop DEFS,defs,left-to-right)
1185x := $(kb-src-prop INCS,incs,right-to-left)
1186x := $(kb-src-prop FLAGS,flags,right-to-left)
1187
1188x := $(kb-src-prop DEPS,deps,left-to-right)
1189dirdep := $(call DIRDEP,$(dir $(outbase)))
1190dep := $(obj)$(SUFF_DEP)
1191*/
1192char *
1193func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
1194{
1195 static int s_fNoCompileCmdsDepsDefined = -1;
1196 struct variable *pTarget = kbuild_get_variable("target");
1197 struct variable *pSource = kbuild_get_variable("source");
1198 struct variable *pDefPath = kbuild_get_variable("defpath");
1199 struct variable *pType = kbuild_get_variable("type");
1200 struct variable *pBldType = kbuild_get_variable("bld_type");
1201 struct variable *pBldTrg = kbuild_get_variable("bld_trg");
1202 struct variable *pBldTrgArch= kbuild_get_variable("bld_trg_arch");
1203 struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
1204 struct variable *pTool = kbuild_get_source_tool(pTarget, pSource, pType, pBldTrg, pBldTrgArch, "tool");
1205 struct variable *pOutBase = kbuild_get_object_base(pTarget, pSource, "outbase");
1206 struct variable *pObjSuff = kbuild_get_object_suffix(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch, "objsuff");
1207 struct variable *pDefs, *pIncs, *pFlags, *pDeps, *pDirDep, *pDep, *pVar, *pOutput;
1208 struct variable *pObj = kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(pTarget, pSource, pOutBase, pObjSuff, "obj", &pDep, &pDirDep);
1209 char *pszDstVar, *pszDst, *pszSrcVar, *pszSrc, *pszVal, *psz;
1210 char *pszSavedVarBuf;
1211 unsigned cchSavedVarBuf;
1212 size_t cch;
1213 struct kbuild_sdks Sdks;
1214 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
1215
1216 if (pDefPath && !pDefPath->value_length)
1217 pDefPath = NULL;
1218 pDefs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
1219 "DEFS", "defs", 1/* left-to-right */);
1220 pIncs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
1221 "INCS", "incs", -1/* right-to-left */);
1222 pFlags = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
1223 "FLAGS", "flags", 1/* left-to-right */);
1224 pDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
1225 "DEPS", "deps", 1/* left-to-right */);
1226
1227 /*
1228 # dependencies
1229 ifndef NO_COMPILE_CMDS_DEPS
1230 _DEPFILES_INCLUDED += $(dep)
1231 $(if $(wildcard $(dep)),$(eval include $(dep)))
1232 endif
1233 */
1234 if (s_fNoCompileCmdsDepsDefined == -1)
1235 s_fNoCompileCmdsDepsDefined = kbuild_lookup_variable("NO_COMPILE_CMDS_DEPS") != NULL;
1236 if (!s_fNoCompileCmdsDepsDefined)
1237 {
1238 do_variable_definition(NILF, "_DEPFILES_INCLUDED", pDep->value, o_file, f_append, 0 /* !target_var */);
1239 eval_include_dep(pDep->value, NILF);
1240 }
1241
1242 /*
1243 # call the tool
1244 $(target)_$(source)_CMDS_ := $(TOOL_$(tool)_COMPILE_$(type)_CMDS)
1245 $(target)_$(source)_OUTPUT_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT)
1246 $(target)_$(source)_DEPEND_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPEND) $(deps) $(source)
1247 $(target)_$(source)_DEPORD_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPORD) $(dirdep)
1248 */
1249 cch = sizeof("TOOL_") + pTool->value_length + sizeof("_COMPILE_") + pType->value_length + sizeof("_OUTPUT");
1250 psz = pszSrcVar = alloca(cch);
1251 memcpy(psz, "TOOL_", sizeof("TOOL_") - 1); psz += sizeof("TOOL_") - 1;
1252 memcpy(psz, pTool->value, pTool->value_length); psz += pTool->value_length;
1253 memcpy(psz, "_COMPILE_", sizeof("_COMPILE_") - 1); psz += sizeof("_COMPILE_") - 1;
1254 memcpy(psz, pType->value, pType->value_length); psz += pType->value_length;
1255 pszSrc = psz;
1256
1257 cch = pTarget->value_length + 1 + pSource->value_length + sizeof("_OUTPUT_");
1258 psz = pszDstVar = alloca(cch);
1259 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1260 *psz++ = '_';
1261 memcpy(psz, pSource->value, pSource->value_length); psz += pSource->value_length;
1262 pszDst = psz;
1263
1264 memcpy(pszSrc, "_CMDS", sizeof("_CMDS"));
1265 memcpy(pszDst, "_CMDS_", sizeof("_CMDS_"));
1266 pVar = kbuild_get_recursive_variable(pszSrcVar);
1267 do_variable_definition(NILF, pszDstVar, pVar->value, o_file, f_simple, 0 /* !target_var */);
1268
1269 memcpy(pszSrc, "_OUTPUT", sizeof("_OUTPUT"));
1270 memcpy(pszDst, "_OUTPUT_", sizeof("_OUTPUT_"));
1271 pVar = kbuild_get_recursive_variable(pszSrcVar);
1272 pOutput = do_variable_definition(NILF, pszDstVar, pVar->value, o_file, f_simple, 0 /* !target_var */);
1273
1274 memcpy(pszSrc, "_DEPEND", sizeof("_DEPEND"));
1275 memcpy(pszDst, "_DEPEND_", sizeof("_DEPEND_"));
1276 pVar = kbuild_get_recursive_variable(pszSrcVar);
1277 psz = pszVal = xmalloc(pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length + 1);
1278 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1279 *psz++ = ' ';
1280 memcpy(psz, pDeps->value, pDeps->value_length); psz += pDeps->value_length;
1281 *psz++ = ' ';
1282 memcpy(psz, pSource->value, pSource->value_length + 1);
1283 do_variable_definition(NILF, pszDstVar, pszVal, o_file, f_simple, 0 /* !target_var */);
1284 free(pszVal);
1285
1286 memcpy(pszSrc, "_DEPORD", sizeof("_DEPORD"));
1287 memcpy(pszDst, "_DEPORD_", sizeof("_DEPORD_"));
1288 pVar = kbuild_get_recursive_variable(pszSrcVar);
1289 psz = pszVal = xmalloc(pVar->value_length + 1 + pDirDep->value_length + 1);
1290 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1291 *psz++ = ' ';
1292 memcpy(psz, pDirDep->value, pDirDep->value_length + 1);
1293 do_variable_definition(NILF, pszDstVar, pszVal, o_file, f_simple, 0 /* !target_var */);
1294 free(pszVal);
1295
1296 /*
1297 _OUT_FILES += $($(target)_$(source)_OUTPUT_)
1298 */
1299 pVar = kbuild_get_variable("_OUT_FILES");
1300 psz = pszVal = xmalloc(pVar->value_length + 1 + pOutput->value_length + 1);
1301 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1302 *psz++ = ' ';
1303 memcpy(psz, pOutput->value, pOutput->value_length + 1);
1304 do_variable_definition(NILF, "_OUT_FILES", pszVal, o_file, f_simple, 0 /* !target_var */);
1305 free(pszVal);
1306
1307 /*
1308 $(target)_OBJS_ += $(obj)
1309 */
1310 memcpy(pszDstVar + pTarget->value_length, "_OBJS_", sizeof("_OBJS_"));
1311 do_variable_definition(NILF, pszDstVar, pObj->value, o_file, f_append, 0 /* !target_var */);
1312
1313 /*
1314 $(eval $(def_target_source_rule))
1315 */
1316 pVar = kbuild_get_recursive_variable("def_target_source_rule");
1317 pszVal = allocated_variable_expand(pVar->value);
1318
1319 install_variable_buffer(&pszSavedVarBuf, &cchSavedVarBuf);
1320 eval_buffer(pszVal);
1321 restore_variable_buffer(pszSavedVarBuf, cchSavedVarBuf);
1322
1323 free(pszVal);
1324
1325 kbuild_put_sdks(&Sdks);
1326 return variable_buffer_output(o, "", 1);
1327}
1328
1329
1330#endif /* KMK_HELPERS */
Note: See TracBrowser for help on using the repository browser.