source: trunk/src/kmk/kbuild.c@ 1812

Last change on this file since 1812 was 1812, checked in by bird, 17 years ago

kmk: fixes for recusive variable mixup.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 72.2 KB
Line 
1/* $Id: kbuild.c 1812 2008-10-10 06:01:29Z bird $ */
2/** @file
3 *
4 * kBuild specific make functionality.
5 *
6 * Copyright (c) 2006-2007 knut st. osmundsen <bird-kBuild-spam@anduin.net>
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
30/*******************************************************************************
31* Header Files *
32*******************************************************************************/
33#include "make.h"
34#include "filedef.h"
35#include "variable.h"
36#include "dep.h"
37#include "debug.h"
38#ifdef WINDOWS32
39# include "pathstuff.h"
40# include <Windows.h>
41#endif
42#if defined(__APPLE__)
43# include <mach-o/dyld.h>
44#endif
45
46#include "kbuild.h"
47
48#include <assert.h>
49#include <stdarg.h>
50#ifndef va_copy
51# define va_copy(dst, src) do {(dst) = (src);} while (0)
52#endif
53
54
55/*******************************************************************************
56* Global Variables *
57*******************************************************************************/
58/** The argv[0] passed to main. */
59static const char *g_pszExeName;
60/** The initial working directory. */
61static char *g_pszInitialCwd;
62
63
64/**
65 * Initialize kBuild stuff.
66 *
67 * @param argc Number of arguments to main().
68 * @param argv The main() argument vector.
69 */
70void init_kbuild(int argc, char **argv)
71{
72 int rc;
73 PATH_VAR(szTmp);
74
75 /*
76 * Get the initial cwd for use in my_abspath.
77 */
78#ifdef WINDOWS32
79 if (getcwd_fs(szTmp, GET_PATH_MAX) != 0)
80#else
81 if (getcwd(szTmp, GET_PATH_MAX) != 0)
82#endif
83 g_pszInitialCwd = xstrdup(szTmp);
84 else
85 fatal(NILF, _("getcwd failed"));
86
87 /*
88 * Determin the executable name.
89 */
90 rc = -1;
91#if defined(__APPLE__)
92 {
93 const char *pszImageName = _dyld_get_image_name(0);
94 if (pszImageName)
95 {
96 size_t cchImageName = strlen(pszImageName);
97 if (cchImageName < GET_PATH_MAX)
98 {
99 memcpy(szTmp, pszImageName, cchImageName + 1);
100 rc = 0;
101 }
102 }
103 }
104
105#elif defined(__FreeBSD__)
106 rc = readlink("/proc/curproc/file", szTmp, GET_PATH_MAX - 1);
107 if (rc < 0 || rc == GET_PATH_MAX - 1)
108 rc = -1;
109 else
110 szTmp[rc] = '\0';
111
112#elif defined(__gnu_linux__) /** @todo find proper define... */
113 rc = readlink("/proc/self/exe", szTmp, GET_PATH_MAX - 1);
114 if (rc < 0 || rc == GET_PATH_MAX - 1)
115 rc = -1;
116 else
117 szTmp[rc] = '\0';
118
119#elif defined(__OS2__)
120 _execname(szTmp, GET_PATH_MAX);
121 rc = 0;
122
123#elif defined(__sun__)
124 {
125 char szTmp2[64];
126 snprintf(szTmp2, sizeof(szTmp2), "/proc/%d/path/a.out", getpid());
127 rc = readlink(szTmp2, szTmp, GET_PATH_MAX - 1);
128 if (rc < 0 || rc == GET_PATH_MAX - 1)
129 rc = -1;
130 else
131 szTmp[rc] = '\0';
132 }
133
134#elif defined(WINDOWS32)
135 if (GetModuleFileName(GetModuleHandle(NULL), szTmp, GET_PATH_MAX))
136 rc = 0;
137
138#endif
139
140#if !defined(__OS2__) && !defined(WINDOWS32)
141 /* fallback, try use the path to locate the binary. */
142 if ( rc < 0
143 && access(argv[0], X_OK))
144 {
145 size_t cchArgv0 = strlen(argv[0]);
146 const char *pszPath = getenv("PATH");
147 char *pszCopy = xstrdup(pszPath ? pszPath : ".");
148 char *psz = pszCopy;
149 while (*psz)
150 {
151 size_t cch;
152 char *pszEnd = strchr(psz, PATH_SEPARATOR_CHAR);
153 if (!pszEnd)
154 pszEnd = strchr(psz, '\0');
155 cch = pszEnd - psz;
156 if (cch + cchArgv0 + 2 <= GET_PATH_MAX)
157 {
158 memcpy(szTmp, psz, cch);
159 szTmp[cch] = '/';
160 memcpy(&szTmp[cch + 1], argv[0], cchArgv0 + 1);
161 if (!access(szTmp, X_OK))
162 {
163 rc = 0;
164 break;
165 }
166 }
167
168 /* next */
169 psz = pszEnd;
170 while (*psz == PATH_SEPARATOR_CHAR)
171 psz++;
172 }
173 free(pszCopy);
174 }
175#endif
176
177 if (rc < 0)
178 g_pszExeName = argv[0];
179 else
180 g_pszExeName = xstrdup(szTmp);
181
182 (void)argc;
183}
184
185
186/**
187 * Wrapper that ensures correct starting_directory.
188 */
189static char *my_abspath(const char *pszIn, char *pszOut)
190{
191 char *pszSaved, *pszRet;
192
193 pszSaved = starting_directory;
194 starting_directory = g_pszInitialCwd;
195 pszRet = abspath(pszIn, pszOut);
196 starting_directory = pszSaved;
197
198 return pszRet;
199}
200
201
202/**
203 * Determin the KBUILD_PATH value.
204 *
205 * @returns Pointer to static a buffer containing the value (consider it read-only).
206 */
207const char *get_kbuild_path(void)
208{
209 static const char *s_pszPath = NULL;
210 if (!s_pszPath)
211 {
212 PATH_VAR(szTmpPath);
213 const char *pszEnvVar = getenv("KBUILD_PATH");
214 if ( !pszEnvVar
215 || !my_abspath(pszEnvVar, szTmpPath))
216 {
217 const char *pszEnvVar = getenv("PATH_KBUILD");
218 if ( !pszEnvVar
219 || !my_abspath(pszEnvVar, szTmpPath))
220 {
221#ifdef KBUILD_PATH
222 return s_pszPath = KBUILD_PATH;
223#else
224 /* $(abspath $(KBUILD_BIN_PATH)/../..)*/
225 size_t cch = strlen(get_kbuild_bin_path());
226 char *pszTmp2 = alloca(cch + sizeof("/../.."));
227 strcat(strcpy(pszTmp2, get_kbuild_bin_path()), "/../..");
228 if (!my_abspath(pszTmp2, szTmpPath))
229 fatal(NILF, _("failed to determin KBUILD_PATH"));
230#endif
231 }
232 }
233 s_pszPath = xstrdup(szTmpPath);
234 }
235 return s_pszPath;
236}
237
238
239/**
240 * Determin the KBUILD_BIN_PATH value.
241 *
242 * @returns Pointer to static a buffer containing the value (consider it read-only).
243 */
244const char *get_kbuild_bin_path(void)
245{
246 static const char *s_pszPath = NULL;
247 if (!s_pszPath)
248 {
249 PATH_VAR(szTmpPath);
250
251 const char *pszEnvVar = getenv("KBUILD_BIN_PATH");
252 if ( !pszEnvVar
253 || !my_abspath(pszEnvVar, szTmpPath))
254 {
255 const char *pszEnvVar = getenv("PATH_KBUILD_BIN");
256 if ( !pszEnvVar
257 || !my_abspath(pszEnvVar, szTmpPath))
258 {
259#ifdef KBUILD_PATH
260 return s_pszPath = KBUILD_BIN_PATH;
261#else
262 /* $(abspath $(dir $(ARGV0)).) */
263 size_t cch = strlen(g_pszExeName);
264 char *pszTmp2 = alloca(cch + sizeof("."));
265 char *pszSep = pszTmp2 + cch - 1;
266 memcpy(pszTmp2, g_pszExeName, cch);
267# ifdef HAVE_DOS_PATHS
268 while (pszSep >= pszTmp2 && *pszSep != '/' && *pszSep != '\\' && *pszSep != ':')
269# else
270 while (pszSep >= pszTmp2 && *pszSep != '/')
271# endif
272 pszSep--;
273 if (pszSep >= pszTmp2)
274 strcpy(pszSep + 1, ".");
275 else
276 strcpy(pszTmp2, ".");
277
278 if (!my_abspath(pszTmp2, szTmpPath))
279 fatal(NILF, _("failed to determin KBUILD_BIN_PATH (pszTmp2=%s szTmpPath=%s)"), pszTmp2, szTmpPath);
280#endif /* !KBUILD_PATH */
281 }
282 }
283 s_pszPath = xstrdup(szTmpPath);
284 }
285 return s_pszPath;
286}
287
288
289/**
290 * Determin the location of default kBuild shell.
291 *
292 * @returns Pointer to static a buffer containing the location (consider it read-only).
293 */
294const char *get_default_kbuild_shell(void)
295{
296 static char *s_pszDefaultShell = NULL;
297 if (!s_pszDefaultShell)
298 {
299#if defined(__OS2__) || defined(_WIN32) || defined(WINDOWS32)
300 static const char s_szShellName[] = "/kmk_ash.exe";
301#else
302 static const char s_szShellName[] = "/kmk_ash";
303#endif
304 const char *pszBin = get_kbuild_bin_path();
305 size_t cchBin = strlen(pszBin);
306 s_pszDefaultShell = xmalloc(cchBin + sizeof(s_szShellName));
307 memcpy(s_pszDefaultShell, pszBin, cchBin);
308 memcpy(&s_pszDefaultShell[cchBin], s_szShellName, sizeof(s_szShellName));
309 }
310 return s_pszDefaultShell;
311}
312
313#ifdef KMK_HELPERS
314
315/**
316 * Applies the specified default path to any relative paths in *ppsz.
317 *
318 * @param pDefPath The default path.
319 * @param ppsz Pointer to the string pointer. If we expand anything, *ppsz
320 * will be replaced and the caller is responsible for calling free() on it.
321 * @param pcch IN: *pcch contains the current string length.
322 * OUT: *pcch contains the new string length.
323 * @param pcchAlloc *pcchAlloc contains the length allocated for the string. Can be NULL.
324 * @param fCanFree Whether *ppsz should be freed when we replace it.
325 */
326static void
327kbuild_apply_defpath(struct variable *pDefPath, char **ppsz, int *pcch, int *pcchAlloc, int fCanFree)
328{
329 const char *pszIterator;
330 const char *pszInCur;
331 unsigned int cchInCur;
332 unsigned int cRelativePaths;
333
334 /*
335 * The first pass, count the relative paths.
336 */
337 cRelativePaths = 0;
338 pszIterator = *ppsz;
339 while ((pszInCur = find_next_token(&pszIterator, &cchInCur)))
340 {
341 /* is relative? */
342#ifdef HAVE_DOS_PATHS
343 if (pszInCur[0] != '/' && pszInCur[0] != '\\' && (cchInCur < 2 || pszInCur[1] != ':'))
344#else
345 if (pszInCur[0] != '/')
346#endif
347 cRelativePaths++;
348 }
349
350 /*
351 * The second pass construct the new string.
352 */
353 if (cRelativePaths)
354 {
355 const size_t cchOut = *pcch + cRelativePaths * (pDefPath->value_length + 1) + 1;
356 char *pszOut = xmalloc(cchOut);
357 char *pszOutCur = pszOut;
358 const char *pszInNextCopy = *ppsz;
359
360 cRelativePaths = 0;
361 pszIterator = *ppsz;
362 while ((pszInCur = find_next_token(&pszIterator, &cchInCur)))
363 {
364 /* is relative? */
365#ifdef HAVE_DOS_PATHS
366 if (pszInCur[0] != '/' && pszInCur[0] != '\\' && (cchInCur < 2 || pszInCur[1] != ':'))
367#else
368 if (pszInCur[0] != '/')
369#endif
370 {
371 PATH_VAR(szAbsPathIn);
372 PATH_VAR(szAbsPathOut);
373
374 if (pDefPath->value_length + cchInCur + 1 >= GET_PATH_MAX)
375 continue;
376
377 /* Create the abspath input. */
378 memcpy(szAbsPathIn, pDefPath->value, pDefPath->value_length);
379 szAbsPathIn[pDefPath->value_length] = '/';
380 memcpy(&szAbsPathIn[pDefPath->value_length + 1], pszInCur, cchInCur);
381 szAbsPathIn[pDefPath->value_length + 1 + cchInCur] = '\0';
382
383 if (abspath(szAbsPathIn, szAbsPathOut) != NULL)
384 {
385 const size_t cchAbsPathOut = strlen(szAbsPathOut);
386 assert(cchAbsPathOut <= pDefPath->value_length + 1 + cchInCur);
387
388 /* copy leading input */
389 if (pszInCur != pszInNextCopy)
390 {
391 const size_t cchCopy = pszInCur - pszInNextCopy;
392 memcpy(pszOutCur, pszInNextCopy, cchCopy);
393 pszOutCur += cchCopy;
394 }
395 pszInNextCopy = pszInCur + cchInCur;
396
397 /* copy out the abspath. */
398 memcpy(pszOutCur, szAbsPathOut, cchAbsPathOut);
399 pszOutCur += cchAbsPathOut;
400 }
401 }
402 }
403 /* the final copy (includes the nil). */
404 cchInCur = *ppsz + *pcch - pszInNextCopy;
405 memcpy(pszOutCur, pszInNextCopy, cchInCur);
406 pszOutCur += cchInCur;
407 *pszOutCur = '\0';
408 assert((size_t)(pszOutCur - pszOut) < cchOut);
409
410 /* set return values */
411 if (fCanFree)
412 free(*ppsz);
413 *ppsz = pszOut;
414 *pcch = pszOutCur - pszOut;
415 if (pcchAlloc)
416 *pcchAlloc = cchOut;
417 }
418}
419
420
421/**
422 * Gets a variable that must exist.
423 * Will cause a fatal failure if the variable doesn't exist.
424 *
425 * @returns Pointer to the variable.
426 * @param pszName The variable name.
427 */
428static struct variable *
429kbuild_get_variable(const char *pszName)
430{
431#ifndef NDEBUG
432 int i;
433#endif
434 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
435 if (!pVar)
436 fatal(NILF, _("variable `%s' isn't defined!"), pszName);
437 if (pVar->recursive)
438 fatal(NILF, _("variable `%s' is defined as `recursive' instead of `simple'!"), pszName);
439#ifndef NDEBUG
440 i = strlen(pVar->value);
441 if (i != pVar->value_length)
442 {
443 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
444# ifdef _MSC_VER
445 __debugbreak();
446# endif
447 assert(0);
448 }
449#endif
450 return pVar;
451}
452
453
454/**
455 * Gets a variable that must exist and can be recursive.
456 * Will cause a fatal failure if the variable doesn't exist.
457 *
458 * @returns Pointer to the variable.
459 * @param pszName The variable name.
460 */
461static struct variable *
462kbuild_get_recursive_variable(const char *pszName)
463{
464#ifndef NDEBUG
465 int i;
466#endif
467 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
468 if (!pVar)
469 fatal(NILF, _("variable `%s' isn't defined!"), pszName);
470#ifndef NDEBUG
471 i = strlen(pVar->value);
472 if (i != pVar->value_length)
473 {
474 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
475# ifdef _MSC_VER
476 __debugbreak();
477# endif
478 assert(0);
479 }
480#endif
481 return pVar;
482}
483
484
485/**
486 * Gets a variable that doesn't have to exit, but if it does can be recursive.
487 *
488 * @returns Pointer to the variable.
489 * NULL if not found.
490 * @param pszName The variable name.
491 */
492static struct variable *
493kbuild_query_recursive_variable(const char *pszName)
494{
495#ifndef NDEBUG
496 int i;
497#endif
498 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
499 if (pVar)
500 {
501#ifndef NDEBUG
502 i = strlen(pVar->value);
503 if (i != pVar->value_length)
504 {
505 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
506# ifdef _MSC_VER
507 __debugbreak();
508# endif
509 assert(0);
510 }
511#endif
512 }
513 return pVar;
514}
515
516
517/**
518 * Converts the specified variable into a 'simple' one.
519 * @returns pVar.
520 * @param pVar The variable.
521 */
522static struct variable *
523kbuild_simplify_variable(struct variable *pVar)
524{
525 if (memchr(pVar->value, '$', pVar->value_length))
526 {
527 unsigned int value_len;
528 char *pszExpanded = allocated_variable_expand_2(pVar->value, pVar->value_length, &value_len);
529 free(pVar->value);
530 pVar->value = pszExpanded;
531 pVar->value_length = value_len;
532 pVar->value_alloc_len = value_len + 1;
533 }
534 pVar->recursive = 0;
535 return pVar;
536}
537
538
539/**
540 * Looks up a variable.
541 * The value_length field is valid upon successful return.
542 *
543 * @returns Pointer to the variable. NULL if not found.
544 * @param pszName The variable name.
545 */
546static struct variable *
547kbuild_lookup_variable(const char *pszName)
548{
549 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
550 if (pVar)
551 {
552#ifndef NDEBUG
553 int i = strlen(pVar->value);
554 if (i != pVar->value_length)
555 {
556 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
557# ifdef _MSC_VER
558 __debugbreak();
559# endif
560 assert(0);
561 }
562#endif
563 /* Make sure the variable is simple, convert it if necessary. */
564 if (pVar->recursive)
565 kbuild_simplify_variable(pVar);
566 }
567 return pVar;
568}
569
570
571/**
572 * Looks up a variable and applies default a path to all relative paths.
573 * The value_length field is valid upon successful return.
574 *
575 * @returns Pointer to the variable. NULL if not found.
576 * @param pDefPath The default path.
577 * @param pszName The variable name.
578 */
579static struct variable *
580kbuild_lookup_variable_defpath(struct variable *pDefPath, const char *pszName)
581{
582 struct variable *pVar = kbuild_lookup_variable(pszName);
583 if (pVar && pDefPath)
584 kbuild_apply_defpath(pDefPath, &pVar->value, &pVar->value_length, &pVar->value_alloc_len, 1);
585 return pVar;
586}
587
588
589/** Same as kbuild_lookup_variable except that a '%s' in the name string
590 * will be substituted with the values of the variables in the va list. */
591static struct variable *
592kbuild_lookup_variable_fmt_va(struct variable *pDefPath, const char *pszNameFmt, va_list va)
593{
594 va_list va2;
595 size_t cchName;
596 const char *pszFmt;
597 char *pszName;
598 char *psz;
599
600 /* first pass, calc value name size and allocate stack buffer. */
601 va_copy(va2, va);
602
603 cchName = strlen(pszNameFmt) + 1;
604 pszFmt = strchr(pszNameFmt, '%');
605 while (pszFmt)
606 {
607 struct variable *pVar = va_arg(va, struct variable *);
608 if (pVar)
609 cchName += pVar->value_length;
610 pszFmt = strchr(pszFmt + 1, '%');
611 }
612 pszName = alloca(cchName);
613
614 /* second pass format it. */
615 pszFmt = pszNameFmt;
616 psz = pszName;
617 for (;;)
618 {
619 char ch = *pszFmt++;
620 if (ch != '%')
621 {
622 *psz++ = ch;
623 if (!ch)
624 break;
625 }
626 else
627 {
628 struct variable *pVar = va_arg(va2, struct variable *);
629 if (pVar)
630 {
631 memcpy(psz, pVar->value, pVar->value_length);
632 psz += pVar->value_length;
633 }
634 }
635 }
636 va_end(va2);
637
638 if (pDefPath)
639 return kbuild_lookup_variable_defpath(pDefPath, pszName);
640 return kbuild_lookup_variable(pszName);
641}
642
643
644/** Same as kbuild_lookup_variable except that a '%s' in the name string
645 * will be substituted with the values of the variables in the ellipsis. */
646static struct variable *
647kbuild_lookup_variable_fmt(struct variable *pDefPath, const char *pszNameFmt, ...)
648{
649 struct variable *pVar;
650 va_list va;
651 va_start(va, pszNameFmt);
652 pVar = kbuild_lookup_variable_fmt_va(pDefPath, pszNameFmt, va);
653 va_end(va);
654 return pVar;
655}
656
657
658/**
659 * Gets the first defined property variable.
660 */
661static struct variable *
662kbuild_first_prop(struct variable *pTarget, struct variable *pSource,
663 struct variable *pTool, struct variable *pType,
664 struct variable *pBldTrg, struct variable *pBldTrgArch,
665 const char *pszPropF1, const char *pszPropF2, const char *pszVarName)
666{
667 struct variable *pVar;
668 struct variable PropF1, PropF2;
669
670 PropF1.value = (char *)pszPropF1;
671 PropF1.value_length = strlen(pszPropF1);
672
673 PropF2.value = (char *)pszPropF2;
674 PropF2.value_length = strlen(pszPropF2);
675
676 if ( (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%%.%.%",pTarget, pSource, pType, &PropF2, pBldTrg, pBldTrgArch))
677 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%%.%", pTarget, pSource, pType, &PropF2, pBldTrg))
678 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%%", pTarget, pSource, pType, &PropF2))
679 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%.%.%", pTarget, pSource, &PropF2, pBldTrg, pBldTrgArch))
680 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%.%", pTarget, pSource, &PropF2, pBldTrg))
681 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%", pTarget, pSource, &PropF2))
682 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%.%", pSource, pType, &PropF2, pBldTrg, pBldTrgArch))
683 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%", pSource, pType, &PropF2, pBldTrg))
684 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%", pSource, pType, &PropF2))
685 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%.%", pSource, &PropF2, pBldTrg, pBldTrgArch))
686 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%", pSource, &PropF2, pBldTrg))
687 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%", pSource, &PropF2))
688 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%.%", pTarget, pType, &PropF2, pBldTrg, pBldTrgArch))
689 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%", pTarget, pType, &PropF2, pBldTrg))
690 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%", pTarget, pType, &PropF2))
691 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%.%", pTarget, &PropF2, pBldTrg, pBldTrgArch))
692 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%", pTarget, &PropF2, pBldTrg))
693 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%", pTarget, &PropF2))
694
695 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%.%", pTool, pType, &PropF2, pBldTrg, pBldTrgArch)))
696 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &PropF2, pBldTrg)))
697 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%", pTool, pType, &PropF2)))
698 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%.%", pTool, &PropF2, pBldTrg, pBldTrgArch)))
699 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &PropF2, pBldTrg)))
700 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%", pTool, &PropF2)))
701
702 || (pVar = kbuild_lookup_variable_fmt(NULL, "%%.%.%", pType, &PropF1, pBldTrg, pBldTrgArch))
703 || (pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &PropF1, pBldTrg))
704 || (pVar = kbuild_lookup_variable_fmt(NULL, "%%", pType, &PropF1))
705 || (pVar = kbuild_lookup_variable_fmt(NULL, "%.%.%", &PropF1, pBldTrg, pBldTrgArch))
706 || (pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &PropF1, pBldTrg))
707 || (pVar = kbuild_lookup_variable(pszPropF1))
708 )
709 {
710 /* strip it */
711 char *psz = pVar->value;
712 char *pszEnd = psz + pVar->value_length;
713 while (isblank((unsigned char)*psz))
714 psz++;
715 while (pszEnd > psz && isblank((unsigned char)pszEnd[-1]))
716 pszEnd--;
717 if (pszEnd > psz)
718 {
719 char chSaved = *pszEnd;
720 *pszEnd = '\0';
721 pVar = define_variable_vl(pszVarName, strlen(pszVarName), psz, pszEnd - psz,
722 1 /* duplicate */, o_local, 0 /* !recursive */);
723 *pszEnd = chSaved;
724 if (pVar)
725 return pVar;
726 }
727 }
728 return NULL;
729}
730
731
732/*
733_SOURCE_TOOL = $(strip $(firstword \
734 $($(target)_$(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
735 $($(target)_$(source)_$(type)TOOL.$(bld_trg)) \
736 $($(target)_$(source)_$(type)TOOL) \
737 $($(target)_$(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
738 $($(target)_$(source)_TOOL.$(bld_trg)) \
739 $($(target)_$(source)_TOOL) \
740 $($(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
741 $($(source)_$(type)TOOL.$(bld_trg)) \
742 $($(source)_$(type)TOOL) \
743 $($(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
744 $($(source)_TOOL.$(bld_trg)) \
745 $($(source)_TOOL) \
746 $($(target)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
747 $($(target)_$(type)TOOL.$(bld_trg)) \
748 $($(target)_$(type)TOOL) \
749 $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \
750 $($(target)_TOOL.$(bld_trg)) \
751 $($(target)_TOOL) \
752 $($(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
753 $($(type)TOOL.$(bld_trg)) \
754 $($(type)TOOL) \
755 $(TOOL.$(bld_trg).$(bld_trg_arch)) \
756 $(TOOL.$(bld_trg)) \
757 $(TOOL) ))
758*/
759static struct variable *
760kbuild_get_source_tool(struct variable *pTarget, struct variable *pSource, struct variable *pType,
761 struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
762{
763 struct variable *pVar = kbuild_first_prop(pTarget, pSource, NULL, pType, pBldTrg, pBldTrgArch,
764 "TOOL", "TOOL", pszVarName);
765 if (!pVar)
766 fatal(NILF, _("no tool for source `%s' in target `%s'!"), pSource->value, pTarget->value);
767 return pVar;
768}
769
770
771/* Implements _SOURCE_TOOL. */
772char *
773func_kbuild_source_tool(char *o, char **argv, const char *pszFuncName)
774{
775 struct variable *pVar = kbuild_get_source_tool(kbuild_get_variable("target"),
776 kbuild_get_variable("source"),
777 kbuild_get_variable("type"),
778 kbuild_get_variable("bld_trg"),
779 kbuild_get_variable("bld_trg_arch"),
780 argv[0]);
781 if (pVar)
782 o = variable_buffer_output(o, pVar->value, pVar->value_length);
783 (void)pszFuncName;
784 return o;
785
786}
787
788
789/* This has been extended a bit, it's now identical to _SOURCE_TOOL.
790$(firstword \
791 $($(target)_$(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
792 $($(target)_$(source)_OBJSUFF.$(bld_trg))\
793 $($(target)_$(source)_OBJSUFF)\
794 $($(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
795 $($(source)_OBJSUFF.$(bld_trg))\
796 $($(source)_OBJSUFF)\
797 $($(target)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
798 $($(target)_OBJSUFF.$(bld_trg))\
799 $($(target)_OBJSUFF)\
800 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg).$(bld_trg_arch))\
801 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg))\
802 $(TOOL_$(tool)_$(type)OBJSUFF)\
803 $(SUFF_OBJ))
804*/
805static struct variable *
806kbuild_get_object_suffix(struct variable *pTarget, struct variable *pSource,
807 struct variable *pTool, struct variable *pType,
808 struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
809{
810 struct variable *pVar = kbuild_first_prop(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch,
811 "SUFF_OBJ", "OBJSUFF", pszVarName);
812 if (!pVar)
813 fatal(NILF, _("no OBJSUFF attribute or SUFF_OBJ default for source `%s' in target `%s'!"), pSource->value, pTarget->value);
814 return pVar;
815}
816
817
818/* */
819char *
820func_kbuild_object_suffix(char *o, char **argv, const char *pszFuncName)
821{
822 struct variable *pVar = kbuild_get_object_suffix(kbuild_get_variable("target"),
823 kbuild_get_variable("source"),
824 kbuild_get_variable("tool"),
825 kbuild_get_variable("type"),
826 kbuild_get_variable("bld_trg"),
827 kbuild_get_variable("bld_trg_arch"),
828 argv[0]);
829 if (pVar)
830 o = variable_buffer_output(o, pVar->value, pVar->value_length);
831 (void)pszFuncName;
832 return o;
833
834}
835
836
837/*
838## Figure out where to put object files.
839# @param $1 source file
840# @param $2 normalized main target
841# @remark There are two major hacks here:
842# 1. Source files in the output directory are translated into a gen/ subdir.
843# 2. Catch anyone specifying $(PATH_SUB_CURRENT)/sourcefile.c.
844_OBJECT_BASE = $(PATH_TARGET)/$(2)/$(call no-root-slash,$(call no-drive,$(basename \
845 $(patsubst $(PATH_ROOT)/%,%,$(patsubst $(PATH_SUB_CURRENT)/%,%,$(patsubst $(PATH_TARGET)/$(2)/%,gen/%,$(1)))))))
846*/
847static struct variable *
848kbuild_get_object_base(struct variable *pTarget, struct variable *pSource, const char *pszVarName)
849{
850 struct variable *pPathTarget = kbuild_get_variable("PATH_TARGET");
851 struct variable *pPathRoot = kbuild_get_variable("PATH_ROOT");
852 struct variable *pPathSubCur = kbuild_get_variable("PATH_SUB_CURRENT");
853 const char *pszSrcPrefix = NULL;
854 size_t cchSrcPrefix = 0;
855 size_t cchSrc = 0;
856 const char *pszSrcEnd;
857 char *pszSrc;
858 char *pszResult;
859 char *psz;
860 char *pszDot;
861 size_t cch;
862
863 /*
864 * Strip the source filename of any uncessary leading path and root specs.
865 */
866 /* */
867 if ( pSource->value_length > pPathTarget->value_length
868 && !strncmp(pSource->value, pPathTarget->value, pPathTarget->value_length))
869 {
870 pszSrc = pSource->value + pPathTarget->value_length;
871 pszSrcPrefix = "gen/";
872 cchSrcPrefix = sizeof("gen/") - 1;
873 if ( *pszSrc == '/'
874 && !strncmp(pszSrc + 1, pTarget->value, pTarget->value_length)
875 && ( pszSrc[pTarget->value_length + 1] == '/'
876 || pszSrc[pTarget->value_length + 1] == '\0'))
877 pszSrc += 1 + pTarget->value_length;
878 }
879 else if ( pSource->value_length > pPathRoot->value_length
880 && !strncmp(pSource->value, pPathRoot->value, pPathRoot->value_length))
881 {
882 pszSrc = pSource->value + pPathRoot->value_length;
883 if ( *pszSrc == '/'
884 && !strncmp(pszSrc + 1, pPathSubCur->value, pPathSubCur->value_length)
885 && ( pszSrc[pPathSubCur->value_length + 1] == '/'
886 || pszSrc[pPathSubCur->value_length + 1] == '\0'))
887 pszSrc += 1 + pPathSubCur->value_length;
888 }
889 else
890 pszSrc = pSource->value;
891
892 /* skip root specification */
893#ifdef HAVE_DOS_PATHS
894 if (isalpha(pszSrc[0]) && pszSrc[1] == ':')
895 pszSrc += 2;
896#endif
897 while (*pszSrc == '/'
898#ifdef HAVE_DOS_PATHS
899 || *pszSrc == '\\'
900#endif
901 )
902 pszSrc++;
903
904 /* drop the source extension. */
905 pszSrcEnd = pSource->value + pSource->value_length;
906 for (;;)
907 {
908 pszSrcEnd--;
909 if ( pszSrcEnd <= pszSrc
910 || *pszSrcEnd == '/'
911#ifdef HAVE_DOS_PATHS
912 || *pszSrcEnd == '\\'
913 || *pszSrcEnd == ':'
914#endif
915 )
916 {
917 pszSrcEnd = pSource->value + pSource->value_length;
918 break;
919 }
920 if (*pszSrcEnd == '.')
921 break;
922 }
923
924 /*
925 * Assemble the string on the heap and define the objbase variable
926 * which we then return.
927 */
928 cchSrc = pszSrcEnd - pszSrc;
929 cch = pPathTarget->value_length
930 + 1 /* slash */
931 + pTarget->value_length
932 + 1 /* slash */
933 + cchSrcPrefix
934 + cchSrc
935 + 1;
936 psz = pszResult = xmalloc(cch);
937
938 memcpy(psz, pPathTarget->value, pPathTarget->value_length); psz += pPathTarget->value_length;
939 *psz++ = '/';
940 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
941 *psz++ = '/';
942 if (pszSrcPrefix)
943 {
944 memcpy(psz, pszSrcPrefix, cchSrcPrefix);
945 psz += cchSrcPrefix;
946 }
947 pszDot = psz;
948 memcpy(psz, pszSrc, cchSrc); psz += cchSrc;
949 *psz = '\0';
950
951 /* convert '..' path elements in the source to 'dt'. */
952 while ((pszDot = memchr(pszDot, '.', psz - pszDot)) != NULL)
953 {
954 if ( pszDot[1] == '.'
955 && ( pszDot == psz
956 || pszDot[-1] == '/'
957#ifdef HAVE_DOS_PATHS
958 || pszDot[-1] == '\\'
959 || pszDot[-1] == ':'
960#endif
961 )
962 && ( !pszDot[2]
963 || pszDot[2] == '/'
964#ifdef HAVE_DOS_PATHS
965 || pszDot[2] == '\\'
966 || pszDot[2] == ':'
967#endif
968 )
969 )
970 {
971 *pszDot++ = 'd';
972 *pszDot++ = 't';
973 }
974 else
975 pszDot++;
976 }
977
978 /*
979 * Define the variable in the current set and return it.
980 */
981 return define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cch - 1,
982 0 /* use pszResult */, o_local, 0 /* !recursive */);
983}
984
985
986/* Implements _OBJECT_BASE. */
987char *
988func_kbuild_object_base(char *o, char **argv, const char *pszFuncName)
989{
990 struct variable *pVar = kbuild_get_object_base(kbuild_lookup_variable("target"),
991 kbuild_lookup_variable("source"),
992 argv[0]);
993 if (pVar)
994 o = variable_buffer_output(o, pVar->value, pVar->value_length);
995 (void)pszFuncName;
996 return o;
997
998}
999
1000
1001struct kbuild_sdks
1002{
1003 char *apsz[4];
1004 struct variable *pa;
1005 unsigned c;
1006 unsigned iGlobal;
1007 unsigned cGlobal;
1008 unsigned iTarget;
1009 unsigned cTarget;
1010 unsigned iSource;
1011 unsigned cSource;
1012 unsigned iTargetSource;
1013 unsigned cTargetSource;
1014};
1015
1016
1017/* Fills in the SDK struct (remember to free it). */
1018static void
1019kbuild_get_sdks(struct kbuild_sdks *pSdks, struct variable *pTarget, struct variable *pSource,
1020 struct variable *pBldType, struct variable *pBldTrg, struct variable *pBldTrgArch)
1021{
1022 unsigned i;
1023 unsigned j;
1024 size_t cchTmp, cch;
1025 char *pszTmp;
1026 unsigned cchCur;
1027 char *pszCur;
1028 const char *pszIterator;
1029
1030 /* basic init. */
1031 pSdks->pa = NULL;
1032 pSdks->c = 0;
1033 i = 0;
1034
1035 /* determin required tmp variable name space. */
1036 cchTmp = sizeof("$(__SDKS) $(__SDKS.) $(__SDKS.) $(__SDKS.) $(__SDKS..)")
1037 + (pTarget->value_length + pSource->value_length) * 5
1038 + pBldType->value_length
1039 + pBldTrg->value_length
1040 + pBldTrgArch->value_length
1041 + pBldTrg->value_length + pBldTrgArch->value_length;
1042 pszTmp = alloca(cchTmp);
1043
1044 /* the global sdks. */
1045 pSdks->iGlobal = i;
1046 pSdks->cGlobal = 0;
1047 cch = sprintf(pszTmp, "$(SDKS) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s.%s)",
1048 pBldType->value,
1049 pBldTrg->value,
1050 pBldTrgArch->value,
1051 pBldTrg->value, pBldTrgArch->value);
1052 pszIterator = pSdks->apsz[0] = allocated_variable_expand_2(pszTmp, cch, NULL);
1053 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1054 pSdks->cGlobal++;
1055 i += pSdks->cGlobal;
1056
1057 /* the target sdks.*/
1058 pSdks->iTarget = i;
1059 pSdks->cTarget = 0;
1060 cch = sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
1061 pTarget->value,
1062 pTarget->value, pBldType->value,
1063 pTarget->value, pBldTrg->value,
1064 pTarget->value, pBldTrgArch->value,
1065 pTarget->value, pBldTrg->value, pBldTrgArch->value);
1066 pszIterator = pSdks->apsz[1] = allocated_variable_expand_2(pszTmp, cch, NULL);
1067 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1068 pSdks->cTarget++;
1069 i += pSdks->cTarget;
1070
1071 /* the source sdks.*/
1072 pSdks->iSource = i;
1073 pSdks->cSource = 0;
1074 cch = sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
1075 pSource->value,
1076 pSource->value, pBldType->value,
1077 pSource->value, pBldTrg->value,
1078 pSource->value, pBldTrgArch->value,
1079 pSource->value, pBldTrg->value, pBldTrgArch->value);
1080 pszIterator = pSdks->apsz[2] = allocated_variable_expand_2(pszTmp, cch, NULL);
1081 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1082 pSdks->cSource++;
1083 i += pSdks->cSource;
1084
1085 /* the target + source sdks. */
1086 pSdks->iTargetSource = i;
1087 pSdks->cTargetSource = 0;
1088 cch = sprintf(pszTmp, "$(%s_%s_SDKS) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s.%s)",
1089 pTarget->value, pSource->value,
1090 pTarget->value, pSource->value, pBldType->value,
1091 pTarget->value, pSource->value, pBldTrg->value,
1092 pTarget->value, pSource->value, pBldTrgArch->value,
1093 pTarget->value, pSource->value, pBldTrg->value, pBldTrgArch->value);
1094 assert(cch < cchTmp); (void)cch;
1095 pszIterator = pSdks->apsz[3] = allocated_variable_expand_2(pszTmp, cch, NULL);
1096 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1097 pSdks->cTargetSource++;
1098 i += pSdks->cTargetSource;
1099
1100 pSdks->c = i;
1101 if (!i)
1102 return;
1103
1104 /*
1105 * Allocate the variable array and create the variables.
1106 */
1107 pSdks->pa = (struct variable *)xmalloc(sizeof(pSdks->pa[0]) * i);
1108 memset(pSdks->pa, 0, sizeof(pSdks->pa[0]) * i);
1109 for (i = j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
1110 {
1111 pszIterator = pSdks->apsz[j];
1112 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1113 {
1114 pSdks->pa[i].value = pszCur;
1115 pSdks->pa[i].value_length = cchCur;
1116 i++;
1117 }
1118 }
1119 assert(i == pSdks->c);
1120
1121 /* terminate them (find_next_token won't work if we terminate them in the previous loop). */
1122 while (i-- > 0)
1123 pSdks->pa[i].value[pSdks->pa[i].value_length] = '\0';
1124}
1125
1126
1127/* releases resources allocated in the kbuild_get_sdks. */
1128static void
1129kbuild_put_sdks(struct kbuild_sdks *pSdks)
1130{
1131 unsigned j;
1132 for (j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
1133 free(pSdks->apsz[j]);
1134 free(pSdks->pa);
1135}
1136
1137
1138/* this kind of stuff:
1139
1140defs := $(kb-src-exp defs)
1141 $(TOOL_$(tool)_DEFS)\
1142 $(TOOL_$(tool)_DEFS.$(bld_type))\
1143 $(TOOL_$(tool)_DEFS.$(bld_trg))\
1144 $(TOOL_$(tool)_DEFS.$(bld_trg_arch))\
1145 $(TOOL_$(tool)_DEFS.$(bld_trg).$(bld_trg_arch))\
1146 $(TOOL_$(tool)_DEFS.$(bld_trg_cpu))\
1147 $(TOOL_$(tool)_$(type)DEFS)\
1148 $(TOOL_$(tool)_$(type)DEFS.$(bld_type))\
1149 $(foreach sdk, $(SDKS.$(bld_trg)) \
1150 $(SDKS.$(bld_trg).$(bld_trg_arch)) \
1151 $(SDKS.$(bld_type)) \
1152 $(SDKS),\
1153 $(SDK_$(sdk)_DEFS)\
1154 $(SDK_$(sdk)_DEFS.$(bld_type))\
1155 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1156 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1157 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1158 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1159 $(SDK_$(sdk)_$(type)DEFS)\
1160 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1161 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1162 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1163 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1164 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1165 $(DEFS)\
1166 $(DEFS.$(bld_type))\
1167 $(DEFS.$(bld_trg))\
1168 $(DEFS.$(bld_trg_arch))\
1169 $(DEFS.$(bld_trg).$(bld_trg_arch))\
1170 $(DEFS.$(bld_trg_cpu))\
1171 $($(type)DEFS)\
1172 $($(type)DEFS.$(bld_type))\
1173 $($(type)DEFS.$(bld_trg))\
1174 $($(type)DEFS.$(bld_trg_arch))\
1175 $($(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1176 $($(type)DEFS.$(bld_trg_cpu))\
1177 $(foreach sdk, $($(target)_SDKS.$(bld_trg)) \
1178 $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1179 $($(target)_SDKS.$(bld_type)) \
1180 $($(target)_SDKS),\
1181 $(SDK_$(sdk)_DEFS)\
1182 $(SDK_$(sdk)_DEFS.$(bld_type))\
1183 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1184 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1185 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1186 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1187 $(SDK_$(sdk)_$(type)DEFS)\
1188 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1189 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1190 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1191 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1192 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1193 $($(target)_DEFS)\
1194 $($(target)_DEFS.$(bld_type))\
1195 $($(target)_DEFS.$(bld_trg))\
1196 $($(target)_DEFS.$(bld_trg_arch))\
1197 $($(target)_DEFS.$(bld_trg).$(bld_trg_arch))\
1198 $($(target)_DEFS.$(bld_trg_cpu))\
1199 $($(target)_$(type)DEFS)\
1200 $($(target)_$(type)DEFS.$(bld_type))\
1201 $($(target)_$(type)DEFS.$(bld_trg))\
1202 $($(target)_$(type)DEFS.$(bld_trg_arch))\
1203 $($(target)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1204 $($(target)_$(type)DEFS.$(bld_trg_cpu))\
1205 $(foreach sdk, $($(source)_SDKS.$(bld_trg)) \
1206 $($(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1207 $($(source)_SDKS.$(bld_type)) \
1208 $($(source)_SDKS),\
1209 $(SDK_$(sdk)_DEFS)\
1210 $(SDK_$(sdk)_DEFS.$(bld_type))\
1211 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1212 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1213 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1214 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1215 $(SDK_$(sdk)_$(type)DEFS)\
1216 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1217 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1218 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1219 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1220 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1221 $($(source)_DEFS)\
1222 $($(source)_DEFS.$(bld_type))\
1223 $($(source)_DEFS.$(bld_trg))\
1224 $($(source)_DEFS.$(bld_trg_arch))\
1225 $($(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
1226 $($(source)_DEFS.$(bld_trg_cpu))\
1227 $($(source)_$(type)DEFS)\
1228 $($(source)_$(type)DEFS.$(bld_type))\
1229 $($(source)_$(type)DEFS.$(bld_trg))\
1230 $($(source)_$(type)DEFS.$(bld_trg_arch))\
1231 $($(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1232 $($(source)_$(type)DEFS.$(bld_trg_cpu))\
1233 $(foreach sdk, $($(target)_$(source)_SDKS.$(bld_trg)) \
1234 $($(target)_$(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1235 $($(target)_$(source)_SDKS.$(bld_type)) \
1236 $($(target)_$(source)_SDKS),\
1237 $(SDK_$(sdk)_DEFS)\
1238 $(SDK_$(sdk)_DEFS.$(bld_type))\
1239 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1240 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1241 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1242 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1243 $(SDK_$(sdk)_$(type)DEFS)\
1244 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1245 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1246 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1247 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1248 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1249 $($(target)_$(source)_DEFS)\
1250 $($(target)_$(source)_DEFS.$(bld_type))\
1251 $($(target)_$(source)_DEFS.$(bld_trg))\
1252 $($(target)_$(source)_DEFS.$(bld_trg_arch))\
1253 $($(target)_$(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
1254 $($(target)_$(source)_DEFS.$(bld_trg_cpu))\
1255 $($(target)_$(source)_$(type)DEFS)\
1256 $($(target)_$(source)_$(type)DEFS.$(bld_type))\
1257 $($(target)_$(source)_$(type)DEFS.$(bld_trg))\
1258 $($(target)_$(source)_$(type)DEFS.$(bld_trg_arch))\
1259 $($(target)_$(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1260 $($(target)_$(source)_$(type)DEFS.$(bld_trg_cpu))
1261*/
1262static struct variable *
1263kbuild_collect_source_prop(struct variable *pTarget, struct variable *pSource,
1264 struct variable *pTool, struct kbuild_sdks *pSdks,
1265 struct variable *pType, struct variable *pBldType,
1266 struct variable *pBldTrg, struct variable *pBldTrgArch, struct variable *pBldTrgCpu,
1267 struct variable *pDefPath,
1268 const char *pszProp, const char *pszVarName, int iDirection)
1269{
1270 struct variable *pVar;
1271 unsigned iSdk, iSdkEnd;
1272 int cVars, iVar, iVarEnd;
1273 size_t cchTotal;
1274 char *pszResult, *psz;
1275 struct
1276 {
1277 struct variable *pVar;
1278 int cchExp;
1279 char *pszExp;
1280 } *paVars;
1281
1282 struct variable Prop = {0};
1283 Prop.value = (char *)pszProp;
1284 Prop.value_length = strlen(pszProp);
1285
1286 assert(iDirection == 1 || iDirection == -1);
1287
1288 /*
1289 * Get the variables.
1290 */
1291 cVars = 12 * (pSdks->c + 5);
1292 paVars = alloca(cVars * sizeof(paVars[0]));
1293
1294 iVar = 0;
1295 /* the tool (lowest priority) */
1296 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%", pTool, &Prop);
1297 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &Prop, pBldType);
1298 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &Prop, pBldTrg);
1299 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &Prop, pBldTrgArch);
1300 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%.%", pTool, &Prop, pBldTrg, pBldTrgArch);
1301 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &Prop, pBldTrgCpu);
1302
1303 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%", pTool, pType, &Prop);
1304 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &Prop, pBldType);
1305 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &Prop, pBldTrg);
1306 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &Prop, pBldTrgArch);
1307 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%.%", pTool, pType, &Prop, pBldTrg, pBldTrgArch);
1308 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &Prop, pBldTrgCpu);
1309
1310 /* the global sdks */
1311 iSdkEnd = iDirection == 1 ? pSdks->iGlobal + pSdks->cGlobal : pSdks->iGlobal - 1;
1312 for (iSdk = iDirection == 1 ? pSdks->iGlobal : pSdks->iGlobal + pSdks->cGlobal - 1;
1313 iSdk != iSdkEnd;
1314 iSdk += iDirection)
1315 {
1316 struct variable *pSdk = &pSdks->pa[iSdk];
1317 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%", pSdk, &Prop);
1318 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldType);
1319 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrg);
1320 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
1321 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
1322 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
1323
1324 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%", pSdk, pType, &Prop);
1325 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
1326 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
1327 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
1328 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
1329 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
1330 }
1331
1332 /* the globals */
1333 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%", &Prop);
1334 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &Prop, pBldType);
1335 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &Prop, pBldTrg);
1336 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &Prop, pBldTrgArch);
1337 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%.%", &Prop, pBldTrg, pBldTrgArch);
1338 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &Prop, pBldTrgCpu);
1339
1340 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%", pType, &Prop);
1341 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &Prop, pBldType);
1342 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &Prop, pBldTrg);
1343 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &Prop, pBldTrgArch);
1344 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%.%", pType, &Prop, pBldTrg, pBldTrgArch);
1345 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &Prop, pBldTrgCpu);
1346
1347 /* the target sdks */
1348 iSdkEnd = iDirection == 1 ? pSdks->iTarget + pSdks->cTarget : pSdks->iTarget - 1;
1349 for (iSdk = iDirection == 1 ? pSdks->iTarget : pSdks->iTarget + pSdks->cTarget - 1;
1350 iSdk != iSdkEnd;
1351 iSdk += iDirection)
1352 {
1353 struct variable *pSdk = &pSdks->pa[iSdk];
1354 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%", pSdk, &Prop);
1355 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldType);
1356 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrg);
1357 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
1358 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
1359 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
1360
1361 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%", pSdk, pType, &Prop);
1362 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
1363 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
1364 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
1365 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
1366 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
1367 }
1368
1369 /* the target */
1370 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%", pTarget, &Prop);
1371 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pTarget, &Prop, pBldType);
1372 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pTarget, &Prop, pBldTrg);
1373 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pTarget, &Prop, pBldTrgArch);
1374 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%.%", pTarget, &Prop, pBldTrg, pBldTrgArch);
1375 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pTarget, &Prop, pBldTrgCpu);
1376
1377 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%", pTarget, pType, &Prop);
1378 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pTarget, pType, &Prop, pBldType);
1379 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pTarget, pType, &Prop, pBldTrg);
1380 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pTarget, pType, &Prop, pBldTrgArch);
1381 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%.%", pTarget, pType, &Prop, pBldTrg, pBldTrgArch);
1382 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pTarget, pType, &Prop, pBldTrgCpu);
1383
1384 /* the source sdks */
1385 iSdkEnd = iDirection == 1 ? pSdks->iSource + pSdks->cSource : pSdks->iSource - 1;
1386 for (iSdk = iDirection == 1 ? pSdks->iSource : pSdks->iSource + pSdks->cSource - 1;
1387 iSdk != iSdkEnd;
1388 iSdk += iDirection)
1389 {
1390 struct variable *pSdk = &pSdks->pa[iSdk];
1391 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%", pSdk, &Prop);
1392 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldType);
1393 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrg);
1394 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
1395 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
1396 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
1397
1398 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%", pSdk, pType, &Prop);
1399 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
1400 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
1401 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
1402 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
1403 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
1404 }
1405
1406 /* the source */
1407 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%", pSource, &Prop);
1408 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pSource, &Prop, pBldType);
1409 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pSource, &Prop, pBldTrg);
1410 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pSource, &Prop, pBldTrgArch);
1411 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%.%", pSource, &Prop, pBldTrg, pBldTrgArch);
1412 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pSource, &Prop, pBldTrgCpu);
1413
1414 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%", pSource, pType, &Prop);
1415 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pSource, pType, &Prop, pBldType);
1416 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pSource, pType, &Prop, pBldTrg);
1417 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pSource, pType, &Prop, pBldTrgArch);
1418 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%.%", pSource, pType, &Prop, pBldTrg, pBldTrgArch);
1419 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pSource, pType, &Prop, pBldTrgCpu);
1420
1421
1422 /* the target + source sdks */
1423 iSdkEnd = iDirection == 1 ? pSdks->iTargetSource + pSdks->cTargetSource : pSdks->iTargetSource - 1;
1424 for (iSdk = iDirection == 1 ? pSdks->iTargetSource : pSdks->iTargetSource + pSdks->cTargetSource - 1;
1425 iSdk != iSdkEnd;
1426 iSdk += iDirection)
1427 {
1428 struct variable *pSdk = &pSdks->pa[iSdk];
1429 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%", pSdk, &Prop);
1430 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldType);
1431 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrg);
1432 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
1433 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
1434 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
1435
1436 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%", pSdk, pType, &Prop);
1437 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
1438 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
1439 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
1440 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
1441 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
1442 }
1443
1444 /* the target + source */
1445 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%", pTarget, pSource, &Prop);
1446 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%", pTarget, pSource, &Prop, pBldType);
1447 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%", pTarget, pSource, &Prop, pBldTrg);
1448 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%", pTarget, pSource, &Prop, pBldTrgArch);
1449 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%.%", pTarget, pSource, &Prop, pBldTrg, pBldTrgArch);
1450 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%", pTarget, pSource, &Prop, pBldTrgCpu);
1451
1452 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%", pTarget, pSource, pType, &Prop);
1453 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%", pTarget, pSource, pType, &Prop, pBldType);
1454 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrg);
1455 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrgArch);
1456 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%.%", pTarget, pSource, pType, &Prop, pBldTrg, pBldTrgArch);
1457 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrgCpu);
1458
1459 assert(cVars == iVar);
1460
1461 /*
1462 * Expand the variables and calculate the total length.
1463 */
1464 cchTotal = 0;
1465 iVarEnd = iDirection == 1 ? cVars : 0;
1466 for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
1467 {
1468 paVars[iVar].cchExp = 0;
1469 if (!paVars[iVar].pVar)
1470 continue;
1471 if ( !paVars[iVar].pVar->recursive
1472 || !memchr(paVars[iVar].pVar->value, '$', paVars[iVar].pVar->value_length))
1473 {
1474 paVars[iVar].pszExp = paVars[iVar].pVar->value;
1475 paVars[iVar].cchExp = paVars[iVar].pVar->value_length;
1476 }
1477 else
1478 {
1479 unsigned int cchExp;
1480 paVars[iVar].pszExp = allocated_variable_expand_2(paVars[iVar].pVar->value, paVars[iVar].pVar->value_length, &cchExp);
1481 paVars[iVar].cchExp = cchExp;
1482 }
1483 if (pDefPath)
1484 kbuild_apply_defpath(pDefPath, &paVars[iVar].pszExp, &paVars[iVar].cchExp, NULL,
1485 paVars[iVar].pszExp != paVars[iVar].pVar->value);
1486 cchTotal += paVars[iVar].cchExp + 1;
1487 }
1488
1489 /*
1490 * Construct the result value.
1491 */
1492 psz = pszResult = xmalloc(cchTotal + 1);
1493 iVarEnd = iDirection == 1 ? cVars : 0;
1494 for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
1495 {
1496 if (!paVars[iVar].cchExp)
1497 continue;
1498 memcpy(psz, paVars[iVar].pszExp, paVars[iVar].cchExp);
1499 psz += paVars[iVar].cchExp;
1500 *psz++ = ' ';
1501 if (paVars[iVar].pszExp != paVars[iVar].pVar->value)
1502 free(paVars[iVar].pszExp);
1503 }
1504 if (psz != pszResult)
1505 psz--;
1506 *psz = '\0';
1507 cchTotal = psz - pszResult;
1508
1509 pVar = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cchTotal,
1510 0 /* take pszResult */ , o_local, 0 /* !recursive */);
1511 return pVar;
1512}
1513
1514
1515/* get a source property. */
1516char *
1517func_kbuild_source_prop(char *o, char **argv, const char *pszFuncName)
1518{
1519 struct variable *pTarget = kbuild_get_variable("target");
1520 struct variable *pSource = kbuild_get_variable("source");
1521 struct variable *pDefPath = NULL;
1522 struct variable *pType = kbuild_get_variable("type");
1523 struct variable *pTool = kbuild_get_variable("tool");
1524 struct variable *pBldType = kbuild_get_variable("bld_type");
1525 struct variable *pBldTrg = kbuild_get_variable("bld_trg");
1526 struct variable *pBldTrgArch = kbuild_get_variable("bld_trg_arch");
1527 struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
1528 struct variable *pVar;
1529 struct kbuild_sdks Sdks;
1530 int iDirection;
1531 if (!strcmp(argv[2], "left-to-right"))
1532 iDirection = 1;
1533 else if (!strcmp(argv[2], "right-to-left"))
1534 iDirection = -1;
1535 else
1536 fatal(NILF, _("incorrect direction argument `%s'!"), argv[2]);
1537 if (argv[3])
1538 {
1539 const char *psz = argv[3];
1540 while (isspace(*psz))
1541 psz++;
1542 if (*psz)
1543 pDefPath = kbuild_get_variable("defpath");
1544 }
1545
1546 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
1547
1548 pVar = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType,
1549 pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
1550 pDefPath,
1551 argv[0], argv[1], iDirection);
1552 if (pVar)
1553 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1554
1555 kbuild_put_sdks(&Sdks);
1556 (void)pszFuncName;
1557 return o;
1558}
1559
1560
1561/*
1562dep := $(obj)$(SUFF_DEP)
1563obj := $(outbase)$(objsuff)
1564dirdep := $(call DIRDEP,$(dir $(outbase)))
1565PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1566*/
1567static struct variable *
1568kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(struct variable *pTarget, struct variable *pSource,
1569 struct variable *pOutBase, struct variable *pObjSuff,
1570 const char *pszVarName, struct variable **ppDep,
1571 struct variable **ppDirDep)
1572{
1573 struct variable *pDepSuff = kbuild_get_variable("SUFF_DEP");
1574 struct variable *pObj;
1575 size_t cch = pOutBase->value_length + pObjSuff->value_length + pDepSuff->value_length + 1;
1576 char *pszResult = alloca(cch);
1577 char *pszName, *psz;
1578
1579 /*
1580 * dep.
1581 */
1582 psz = pszResult;
1583 memcpy(psz, pOutBase->value, pOutBase->value_length); psz += pOutBase->value_length;
1584 memcpy(psz, pObjSuff->value, pObjSuff->value_length); psz += pObjSuff->value_length;
1585 memcpy(psz, pDepSuff->value, pDepSuff->value_length + 1);
1586 *ppDep = define_variable_vl("dep", 3, pszResult, cch - 1, 1 /*dup*/, o_local, 0 /* !recursive */);
1587
1588 /*
1589 * obj
1590 */
1591 *psz = '\0';
1592 pObj = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, psz - pszResult,
1593 1/* dup */, o_local, 0 /* !recursive */);
1594
1595 /*
1596 * PATH_$(target)_$(source) - this is global!
1597 */
1598 /* calc variable name. */
1599 cch = sizeof("PATH_")-1 + pTarget->value_length + sizeof("_")-1 + pSource->value_length;
1600 psz = pszName = alloca(cch + 1);
1601 memcpy(psz, "PATH_", sizeof("PATH_") - 1); psz += sizeof("PATH_") - 1;
1602 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1603 *psz++ = '_';
1604 memcpy(psz, pSource->value, pSource->value_length + 1);
1605
1606 /* strip off the filename. */
1607 psz = pszResult + pOutBase->value_length;
1608 for (;;)
1609 {
1610 psz--;
1611 if (psz <= pszResult)
1612 fatal(NULL, "whut!?! no path? result=`%s'", pszResult);
1613#ifdef HAVE_DOS_PATHS
1614 if (*psz == ':')
1615 {
1616 psz++;
1617 break;
1618 }
1619#endif
1620 if ( *psz == '/'
1621#ifdef HAVE_DOS_PATHS
1622 || *psz == '\\'
1623#endif
1624 )
1625 {
1626 while ( psz - 1 > pszResult
1627 && psz[-1] == '/'
1628#ifdef HAVE_DOS_PATHS
1629 || psz[-1] == '\\'
1630#endif
1631 )
1632 psz--;
1633#ifdef HAVE_DOS_PATHS
1634 if (psz == pszResult + 2 && pszResult[1] == ':')
1635 psz++;
1636#endif
1637 break;
1638 }
1639 }
1640 *psz = '\0';
1641
1642 /* set global variable */
1643 define_variable_vl_global(pszName, cch, pszResult, psz - pszResult, 1/*dup*/, o_file, 0 /* !recursive */, NILF);
1644
1645 /*
1646 * dirdep
1647 */
1648 if ( psz[-1] != '/'
1649#ifdef HAVE_DOS_PATHS
1650 && psz[-1] != '\\'
1651 && psz[-1] != ':'
1652#endif
1653 )
1654 {
1655 *psz++ = '/';
1656 *psz = '\0';
1657 }
1658 *ppDirDep = define_variable_vl("dirdep", 6, pszResult, psz - pszResult, 1/*dup*/, o_local, 0 /* !recursive */);
1659
1660 return pObj;
1661}
1662
1663
1664/* setup the base variables for def_target_source_c_cpp_asm_new:
1665
1666X := $(kb-src-tool tool)
1667x := $(kb-obj-base outbase)
1668x := $(kb-obj-suff objsuff)
1669obj := $(outbase)$(objsuff)
1670PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1671
1672x := $(kb-src-prop DEFS,defs,left-to-right)
1673x := $(kb-src-prop INCS,incs,right-to-left)
1674x := $(kb-src-prop FLAGS,flags,right-to-left)
1675
1676x := $(kb-src-prop DEPS,deps,left-to-right)
1677dirdep := $(call DIRDEP,$(dir $(outbase)))
1678dep := $(obj)$(SUFF_DEP)
1679*/
1680char *
1681func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
1682{
1683 static int s_fNoCompileCmdsDepsDefined = -1;
1684 struct variable *pTarget = kbuild_get_variable("target");
1685 struct variable *pSource = kbuild_get_variable("source");
1686 struct variable *pDefPath = kbuild_get_variable("defpath");
1687 struct variable *pType = kbuild_get_variable("type");
1688 struct variable *pBldType = kbuild_get_variable("bld_type");
1689 struct variable *pBldTrg = kbuild_get_variable("bld_trg");
1690 struct variable *pBldTrgArch= kbuild_get_variable("bld_trg_arch");
1691 struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
1692 struct variable *pTool = kbuild_get_source_tool(pTarget, pSource, pType, pBldTrg, pBldTrgArch, "tool");
1693 struct variable *pOutBase = kbuild_get_object_base(pTarget, pSource, "outbase");
1694 struct variable *pObjSuff = kbuild_get_object_suffix(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch, "objsuff");
1695 struct variable *pDefs, *pIncs, *pFlags, *pDeps, *pOrderDeps, *pDirDep, *pDep, *pVar, *pOutput, *pOutputMaybe;
1696 struct variable *pObj = kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(pTarget, pSource, pOutBase, pObjSuff, "obj", &pDep, &pDirDep);
1697 char *pszDstVar, *pszDst, *pszSrcVar, *pszSrc, *pszVal, *psz;
1698 char *pszSavedVarBuf;
1699 unsigned cchSavedVarBuf;
1700 size_t cch;
1701 struct kbuild_sdks Sdks;
1702 int iVer;
1703
1704 /*
1705 * argv[0] is the function version. Prior to r1792 (early 0.1.5) this
1706 * was undefined and footer.kmk always passed an empty string.
1707 *
1708 * Version 2, as implemented in r1797, will make use of the async
1709 * includedep queue feature. This means the files will be read by one or
1710 * more background threads, leaving the eval'ing to be done later on by
1711 * the main thread (in snap_deps).
1712 */
1713 if (!argv[0][0])
1714 iVer = 0;
1715 else
1716 switch (argv[0][0] | (argv[0][1] << 8))
1717 {
1718 case '2': iVer = 2; break;
1719 case '3': iVer = 3; break;
1720 case '4': iVer = 4; break;
1721 case '5': iVer = 5; break;
1722 case '6': iVer = 6; break;
1723 case '7': iVer = 7; break;
1724 case '8': iVer = 8; break;
1725 case '9': iVer = 9; break;
1726 case '0': iVer = 0; break;
1727 case '1': iVer = 1; break;
1728 default:
1729 iVer = 0;
1730 psz = argv[0];
1731 while (isblank((unsigned char)*psz))
1732 psz++;
1733 if (*psz)
1734 iVer = atoi(psz);
1735 break;
1736 }
1737
1738 /*
1739 * Gather properties.
1740 */
1741 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
1742
1743 if (pDefPath && !pDefPath->value_length)
1744 pDefPath = NULL;
1745 pDefs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
1746 "DEFS", "defs", 1/* left-to-right */);
1747 pIncs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
1748 "INCS", "incs", -1/* right-to-left */);
1749 pFlags = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
1750 "FLAGS", "flags", 1/* left-to-right */);
1751 pDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
1752 "DEPS", "deps", 1/* left-to-right */);
1753 pOrderDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
1754 "ORDERDEPS", "orderdeps", 1/* left-to-right */);
1755
1756 /*
1757 * If we've got a default path, we must expand the source now.
1758 * If we do this too early, "<source>_property = stuff" won't work becuase
1759 * our 'source' value isn't what the user expects.
1760 */
1761 if (pDefPath)
1762 kbuild_apply_defpath(pDefPath, &pSource->value, &pSource->value_length, &pSource->value_alloc_len, 1 /* can free */);
1763
1764 /*
1765 # dependencies
1766 ifndef NO_COMPILE_CMDS_DEPS
1767 _DEPFILES_INCLUDED += $(dep)
1768 $(if $(wildcard $(dep)),$(eval include $(dep)))
1769 endif
1770 */
1771 if (s_fNoCompileCmdsDepsDefined == -1)
1772 s_fNoCompileCmdsDepsDefined = kbuild_lookup_variable("NO_COMPILE_CMDS_DEPS") != NULL;
1773 if (!s_fNoCompileCmdsDepsDefined)
1774 {
1775 do_variable_definition_2(NILF, "_DEPFILES_INCLUDED", pDep->value, pDep->value_length,
1776 !pDep->recursive, 0, o_file, f_append, 0 /* !target_var */);
1777 eval_include_dep(pDep->value, NILF, iVer >= 2 ? incdep_queue : incdep_read_it);
1778 }
1779
1780 /*
1781 # call the tool
1782 $(target)_$(source)_CMDS_ := $(TOOL_$(tool)_COMPILE_$(type)_CMDS)
1783 $(target)_$(source)_OUTPUT_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT)
1784 $(target)_$(source)_OUTPUT_MAYBE_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT_MAYBE)
1785 $(target)_$(source)_DEPEND_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPEND) $(deps) $(source)
1786 $(target)_$(source)_DEPORD_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPORD) $(dirdep)
1787 */
1788 cch = sizeof("TOOL_") + pTool->value_length + sizeof("_COMPILE_") + pType->value_length + sizeof("_OUTPUT_MAYBE");
1789 psz = pszSrcVar = alloca(cch);
1790 memcpy(psz, "TOOL_", sizeof("TOOL_") - 1); psz += sizeof("TOOL_") - 1;
1791 memcpy(psz, pTool->value, pTool->value_length); psz += pTool->value_length;
1792 memcpy(psz, "_COMPILE_", sizeof("_COMPILE_") - 1); psz += sizeof("_COMPILE_") - 1;
1793 memcpy(psz, pType->value, pType->value_length); psz += pType->value_length;
1794 pszSrc = psz;
1795
1796 cch = pTarget->value_length + 1 + pSource->value_length + sizeof("_OUTPUT_MAYBE_");
1797 psz = pszDstVar = alloca(cch);
1798 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1799 *psz++ = '_';
1800 memcpy(psz, pSource->value, pSource->value_length); psz += pSource->value_length;
1801 pszDst = psz;
1802
1803 memcpy(pszSrc, "_CMDS", sizeof("_CMDS"));
1804 memcpy(pszDst, "_CMDS_", sizeof("_CMDS_"));
1805 pVar = kbuild_get_recursive_variable(pszSrcVar);
1806 do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length,
1807 !pVar->recursive, 0, o_file, f_simple, 0 /* !target_var */);
1808
1809 memcpy(pszSrc, "_OUTPUT", sizeof("_OUTPUT"));
1810 memcpy(pszDst, "_OUTPUT_", sizeof("_OUTPUT_"));
1811 pVar = kbuild_get_recursive_variable(pszSrcVar);
1812 pOutput = do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length,
1813 pVar->flavor == f_simple, 0, o_file, f_simple, 0 /* !target_var */);
1814
1815 memcpy(pszSrc, "_OUTPUT_MAYBE", sizeof("_OUTPUT_MAYBE"));
1816 memcpy(pszDst, "_OUTPUT_MAYBE_", sizeof("_OUTPUT_MAYBE_"));
1817 pVar = kbuild_query_recursive_variable(pszSrcVar);
1818 if (pVar)
1819 pOutputMaybe = do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length,
1820 pVar->flavor == f_simple, 0, o_file, f_simple, 0 /* !target_var */);
1821 else
1822 pOutputMaybe = do_variable_definition_2(NILF, pszDstVar, "", 0, 1, 0, o_file, f_simple, 0 /* !target_var */);
1823
1824 memcpy(pszSrc, "_DEPEND", sizeof("_DEPEND"));
1825 memcpy(pszDst, "_DEPEND_", sizeof("_DEPEND_"));
1826 pVar = kbuild_get_recursive_variable(pszSrcVar);
1827 psz = pszVal = xmalloc(pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length + 1);
1828 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1829 *psz++ = ' ';
1830 memcpy(psz, pDeps->value, pDeps->value_length); psz += pDeps->value_length;
1831 *psz++ = ' ';
1832 memcpy(psz, pSource->value, pSource->value_length + 1);
1833 do_variable_definition_2(NILF, pszDstVar, pszVal, pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length,
1834 !pVar->recursive && !pDeps->recursive && !pSource->recursive,
1835 pszVal, o_file, f_simple, 0 /* !target_var */);
1836
1837 memcpy(pszSrc, "_DEPORD", sizeof("_DEPORD"));
1838 memcpy(pszDst, "_DEPORD_", sizeof("_DEPORD_"));
1839 pVar = kbuild_get_recursive_variable(pszSrcVar);
1840 psz = pszVal = xmalloc(pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length + 1);
1841 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1842 *psz++ = ' ';
1843 memcpy(psz, pDirDep->value, pDirDep->value_length); psz += pDirDep->value_length;
1844 *psz++ = ' ';
1845 memcpy(psz, pOrderDeps->value, pOrderDeps->value_length + 1);
1846 do_variable_definition_2(NILF, pszDstVar, pszVal,
1847 pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length,
1848 !pVar->recursive && !pDirDep->recursive && !pOrderDeps->recursive,
1849 pszVal, o_file, f_simple, 0 /* !target_var */);
1850
1851 /*
1852 _OUT_FILES += $($(target)_$(source)_OUTPUT_) $($(target)_$(source)_OUTPUT_MAYBE_)
1853 */
1854 /** @todo use append? */
1855 pVar = kbuild_get_variable("_OUT_FILES");
1856 psz = pszVal = xmalloc(pVar->value_length + 1 + pOutput->value_length + 1 + pOutputMaybe->value_length + 1);
1857 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1858 *psz++ = ' ';
1859 memcpy(psz, pOutput->value, pOutput->value_length); psz += pOutput->value_length;
1860 *psz++ = ' ';
1861 memcpy(psz, pOutputMaybe->value, pOutputMaybe->value_length + 1);
1862 do_variable_definition_2(NILF, "_OUT_FILES", pszVal,
1863 pVar->value_length + 1 + pOutput->value_length + 1 + pOutputMaybe->value_length,
1864 !pVar->recursive && !pOutput->recursive && !pOutputMaybe->recursive,
1865 pszVal, o_file, f_simple, 0 /* !target_var */);
1866
1867 /*
1868 $(target)_OBJS_ += $(obj)
1869 */
1870 memcpy(pszDstVar + pTarget->value_length, "_OBJS_", sizeof("_OBJS_"));
1871 do_variable_definition_2(NILF, pszDstVar, pObj->value, pObj->value_length,
1872 !pObj->recursive, 0, o_file, f_append, 0 /* !target_var */);
1873
1874 /*
1875 $(eval $(def_target_source_rule))
1876 */
1877 pVar = kbuild_get_recursive_variable("def_target_source_rule");
1878 pszVal = allocated_variable_expand_2(pVar->value, pVar->value_length, NULL);
1879
1880 install_variable_buffer(&pszSavedVarBuf, &cchSavedVarBuf);
1881 eval_buffer(pszVal);
1882 restore_variable_buffer(pszSavedVarBuf, cchSavedVarBuf);
1883
1884 free(pszVal);
1885
1886 kbuild_put_sdks(&Sdks);
1887 (void)pszFuncName;
1888 return variable_buffer_output(o, "", 1);
1889}
1890
1891
1892#endif /* KMK_HELPERS */
1893
Note: See TracBrowser for help on using the repository browser.