VirtualBox

source: kBuild/trunk/src/kmk/kbuild.c@ 1728

Last change on this file since 1728 was 1725, checked in by bird, 16 years ago

kmk: shutting up warnings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 69.6 KB
Line 
1/* $Id: kbuild.c 1725 2008-09-05 01:43:19Z bird $ */
2/** @file
3 *
4 * kBuild specific make functionality.
5 *
6 * Copyright (c) 2006-2007 knut st. osmundsen <[email protected]>
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 char *pszExpanded = allocated_variable_expand(pVar->value);
528 free(pVar->value);
529 pVar->value = pszExpanded;
530 pVar->value_length = strlen(pVar->value);
531 pVar->value_alloc_len = pVar->value_length + 1;
532 }
533 pVar->recursive = 0;
534 return pVar;
535}
536
537
538/**
539 * Looks up a variable.
540 * The value_length field is valid upon successful return.
541 *
542 * @returns Pointer to the variable. NULL if not found.
543 * @param pszName The variable name.
544 */
545static struct variable *
546kbuild_lookup_variable(const char *pszName)
547{
548 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
549 if (pVar)
550 {
551#ifndef NDEBUG
552 int i = strlen(pVar->value);
553 if (i != pVar->value_length)
554 {
555 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
556# ifdef _MSC_VER
557 __debugbreak();
558# endif
559 assert(0);
560 }
561#endif
562 /* Make sure the variable is simple, convert it if necessary. */
563 if (pVar->recursive)
564 kbuild_simplify_variable(pVar);
565 }
566 return pVar;
567}
568
569
570/**
571 * Looks up a variable and applies default a path to all relative paths.
572 * The value_length field is valid upon successful return.
573 *
574 * @returns Pointer to the variable. NULL if not found.
575 * @param pDefPath The default path.
576 * @param pszName The variable name.
577 */
578static struct variable *
579kbuild_lookup_variable_defpath(struct variable *pDefPath, const char *pszName)
580{
581 struct variable *pVar = kbuild_lookup_variable(pszName);
582 if (pVar && pDefPath)
583 kbuild_apply_defpath(pDefPath, &pVar->value, &pVar->value_length, &pVar->value_alloc_len, 1);
584 return pVar;
585}
586
587
588/** Same as kbuild_lookup_variable except that a '%s' in the name string
589 * will be substituted with the values of the variables in the va list. */
590static struct variable *
591kbuild_lookup_variable_fmt_va(struct variable *pDefPath, const char *pszNameFmt, va_list va)
592{
593 va_list va2;
594 size_t cchName;
595 const char *pszFmt;
596 char *pszName;
597 char *psz;
598
599 /* first pass, calc value name size and allocate stack buffer. */
600 va_copy(va2, va);
601
602 cchName = strlen(pszNameFmt) + 1;
603 pszFmt = strchr(pszNameFmt, '%');
604 while (pszFmt)
605 {
606 struct variable *pVar = va_arg(va, struct variable *);
607 if (pVar)
608 cchName += pVar->value_length;
609 pszFmt = strchr(pszFmt + 1, '%');
610 }
611 pszName = alloca(cchName);
612
613 /* second pass format it. */
614 pszFmt = pszNameFmt;
615 psz = pszName;
616 for (;;)
617 {
618 char ch = *pszFmt++;
619 if (ch != '%')
620 {
621 *psz++ = ch;
622 if (!ch)
623 break;
624 }
625 else
626 {
627 struct variable *pVar = va_arg(va2, struct variable *);
628 if (pVar)
629 {
630 memcpy(psz, pVar->value, pVar->value_length);
631 psz += pVar->value_length;
632 }
633 }
634 }
635 va_end(va2);
636
637 if (pDefPath)
638 return kbuild_lookup_variable_defpath(pDefPath, pszName);
639 return kbuild_lookup_variable(pszName);
640}
641
642
643/** Same as kbuild_lookup_variable except that a '%s' in the name string
644 * will be substituted with the values of the variables in the ellipsis. */
645static struct variable *
646kbuild_lookup_variable_fmt(struct variable *pDefPath, const char *pszNameFmt, ...)
647{
648 struct variable *pVar;
649 va_list va;
650 va_start(va, pszNameFmt);
651 pVar = kbuild_lookup_variable_fmt_va(pDefPath, pszNameFmt, va);
652 va_end(va);
653 return pVar;
654}
655
656
657/**
658 * Gets the first defined property variable.
659 */
660static struct variable *
661kbuild_first_prop(struct variable *pTarget, struct variable *pSource,
662 struct variable *pTool, struct variable *pType,
663 struct variable *pBldTrg, struct variable *pBldTrgArch,
664 const char *pszPropF1, const char *pszPropF2, const char *pszVarName)
665{
666 struct variable *pVar;
667 struct variable PropF1, PropF2;
668
669 PropF1.value = (char *)pszPropF1;
670 PropF1.value_length = strlen(pszPropF1);
671
672 PropF2.value = (char *)pszPropF2;
673 PropF2.value_length = strlen(pszPropF2);
674
675 if ( (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%%.%.%",pTarget, pSource, pType, &PropF2, pBldTrg, pBldTrgArch))
676 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%%.%", pTarget, pSource, pType, &PropF2, pBldTrg))
677 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%%", pTarget, pSource, pType, &PropF2))
678 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%.%.%", pTarget, pSource, &PropF2, pBldTrg, pBldTrgArch))
679 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%.%", pTarget, pSource, &PropF2, pBldTrg))
680 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%", pTarget, pSource, &PropF2))
681 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%.%", pSource, pType, &PropF2, pBldTrg, pBldTrgArch))
682 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%", pSource, pType, &PropF2, pBldTrg))
683 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%", pSource, pType, &PropF2))
684 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%.%", pSource, &PropF2, pBldTrg, pBldTrgArch))
685 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%", pSource, &PropF2, pBldTrg))
686 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%", pSource, &PropF2))
687 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%.%", pTarget, pType, &PropF2, pBldTrg, pBldTrgArch))
688 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%", pTarget, pType, &PropF2, pBldTrg))
689 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%", pTarget, pType, &PropF2))
690 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%.%", pTarget, &PropF2, pBldTrg, pBldTrgArch))
691 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%", pTarget, &PropF2, pBldTrg))
692 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%", pTarget, &PropF2))
693
694 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%.%", pTool, pType, &PropF2, pBldTrg, pBldTrgArch)))
695 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &PropF2, pBldTrg)))
696 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%", pTool, pType, &PropF2)))
697 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%.%", pTool, &PropF2, pBldTrg, pBldTrgArch)))
698 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &PropF2, pBldTrg)))
699 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%", pTool, &PropF2)))
700
701 || (pVar = kbuild_lookup_variable_fmt(NULL, "%%.%.%", pType, &PropF1, pBldTrg, pBldTrgArch))
702 || (pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &PropF1, pBldTrg))
703 || (pVar = kbuild_lookup_variable_fmt(NULL, "%%", pType, &PropF1))
704 || (pVar = kbuild_lookup_variable_fmt(NULL, "%.%.%", &PropF1, pBldTrg, pBldTrgArch))
705 || (pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &PropF1, pBldTrg))
706 || (pVar = kbuild_lookup_variable(pszPropF1))
707 )
708 {
709 /* strip it */
710 char *psz = pVar->value;
711 char *pszEnd = psz + pVar->value_length;
712 while (isblank((unsigned char)*psz))
713 psz++;
714 while (pszEnd > psz && isblank((unsigned char)pszEnd[-1]))
715 pszEnd--;
716 if (pszEnd > psz)
717 {
718 char chSaved = *pszEnd;
719 *pszEnd = '\0';
720 pVar = define_variable_vl(pszVarName, strlen(pszVarName), psz, pszEnd - psz,
721 1 /* duplicate */, o_local, 0 /* !recursive */);
722 *pszEnd = chSaved;
723 if (pVar)
724 return pVar;
725 }
726 }
727 return NULL;
728}
729
730
731/*
732_SOURCE_TOOL = $(strip $(firstword \
733 $($(target)_$(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
734 $($(target)_$(source)_$(type)TOOL.$(bld_trg)) \
735 $($(target)_$(source)_$(type)TOOL) \
736 $($(target)_$(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
737 $($(target)_$(source)_TOOL.$(bld_trg)) \
738 $($(target)_$(source)_TOOL) \
739 $($(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
740 $($(source)_$(type)TOOL.$(bld_trg)) \
741 $($(source)_$(type)TOOL) \
742 $($(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
743 $($(source)_TOOL.$(bld_trg)) \
744 $($(source)_TOOL) \
745 $($(target)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
746 $($(target)_$(type)TOOL.$(bld_trg)) \
747 $($(target)_$(type)TOOL) \
748 $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \
749 $($(target)_TOOL.$(bld_trg)) \
750 $($(target)_TOOL) \
751 $($(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
752 $($(type)TOOL.$(bld_trg)) \
753 $($(type)TOOL) \
754 $(TOOL.$(bld_trg).$(bld_trg_arch)) \
755 $(TOOL.$(bld_trg)) \
756 $(TOOL) ))
757*/
758static struct variable *
759kbuild_get_source_tool(struct variable *pTarget, struct variable *pSource, struct variable *pType,
760 struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
761{
762 struct variable *pVar = kbuild_first_prop(pTarget, pSource, NULL, pType, pBldTrg, pBldTrgArch,
763 "TOOL", "TOOL", pszVarName);
764 if (!pVar)
765 fatal(NILF, _("no tool for source `%s' in target `%s'!"), pSource->value, pTarget->value);
766 return pVar;
767}
768
769
770/* Implements _SOURCE_TOOL. */
771char *
772func_kbuild_source_tool(char *o, char **argv, const char *pszFuncName)
773{
774 struct variable *pVar = kbuild_get_source_tool(kbuild_get_variable("target"),
775 kbuild_get_variable("source"),
776 kbuild_get_variable("type"),
777 kbuild_get_variable("bld_trg"),
778 kbuild_get_variable("bld_trg_arch"),
779 argv[0]);
780 if (pVar)
781 o = variable_buffer_output(o, pVar->value, pVar->value_length);
782 (void)pszFuncName;
783 return o;
784
785}
786
787
788/* This has been extended a bit, it's now identical to _SOURCE_TOOL.
789$(firstword \
790 $($(target)_$(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
791 $($(target)_$(source)_OBJSUFF.$(bld_trg))\
792 $($(target)_$(source)_OBJSUFF)\
793 $($(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
794 $($(source)_OBJSUFF.$(bld_trg))\
795 $($(source)_OBJSUFF)\
796 $($(target)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
797 $($(target)_OBJSUFF.$(bld_trg))\
798 $($(target)_OBJSUFF)\
799 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg).$(bld_trg_arch))\
800 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg))\
801 $(TOOL_$(tool)_$(type)OBJSUFF)\
802 $(SUFF_OBJ))
803*/
804static struct variable *
805kbuild_get_object_suffix(struct variable *pTarget, struct variable *pSource,
806 struct variable *pTool, struct variable *pType,
807 struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
808{
809 struct variable *pVar = kbuild_first_prop(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch,
810 "SUFF_OBJ", "OBJSUFF", pszVarName);
811 if (!pVar)
812 fatal(NILF, _("no OBJSUFF attribute or SUFF_OBJ default for source `%s' in target `%s'!"), pSource->value, pTarget->value);
813 return pVar;
814}
815
816
817/* */
818char *
819func_kbuild_object_suffix(char *o, char **argv, const char *pszFuncName)
820{
821 struct variable *pVar = kbuild_get_object_suffix(kbuild_get_variable("target"),
822 kbuild_get_variable("source"),
823 kbuild_get_variable("tool"),
824 kbuild_get_variable("type"),
825 kbuild_get_variable("bld_trg"),
826 kbuild_get_variable("bld_trg_arch"),
827 argv[0]);
828 if (pVar)
829 o = variable_buffer_output(o, pVar->value, pVar->value_length);
830 (void)pszFuncName;
831 return o;
832
833}
834
835
836/*
837## Figure out where to put object files.
838# @param $1 source file
839# @param $2 normalized main target
840# @remark There are two major hacks here:
841# 1. Source files in the output directory are translated into a gen/ subdir.
842# 2. Catch anyone specifying $(PATH_SUB_CURRENT)/sourcefile.c.
843_OBJECT_BASE = $(PATH_TARGET)/$(2)/$(call no-root-slash,$(call no-drive,$(basename \
844 $(patsubst $(PATH_ROOT)/%,%,$(patsubst $(PATH_SUB_CURRENT)/%,%,$(patsubst $(PATH_TARGET)/$(2)/%,gen/%,$(1)))))))
845*/
846static struct variable *
847kbuild_get_object_base(struct variable *pTarget, struct variable *pSource, const char *pszVarName)
848{
849 struct variable *pPathTarget = kbuild_get_variable("PATH_TARGET");
850 struct variable *pPathRoot = kbuild_get_variable("PATH_ROOT");
851 struct variable *pPathSubCur = kbuild_get_variable("PATH_SUB_CURRENT");
852 const char *pszSrcPrefix = NULL;
853 size_t cchSrcPrefix = 0;
854 size_t cchSrc = 0;
855 const char *pszSrcEnd;
856 char *pszSrc;
857 char *pszResult;
858 char *psz;
859 char *pszDot;
860 size_t cch;
861
862 /*
863 * Strip the source filename of any uncessary leading path and root specs.
864 */
865 /* */
866 if ( pSource->value_length > pPathTarget->value_length
867 && !strncmp(pSource->value, pPathTarget->value, pPathTarget->value_length))
868 {
869 pszSrc = pSource->value + pPathTarget->value_length;
870 pszSrcPrefix = "gen/";
871 cchSrcPrefix = sizeof("gen/") - 1;
872 if ( *pszSrc == '/'
873 && !strncmp(pszSrc + 1, pTarget->value, pTarget->value_length)
874 && ( pszSrc[pTarget->value_length + 1] == '/'
875 || pszSrc[pTarget->value_length + 1] == '\0'))
876 pszSrc += 1 + pTarget->value_length;
877 }
878 else if ( pSource->value_length > pPathRoot->value_length
879 && !strncmp(pSource->value, pPathRoot->value, pPathRoot->value_length))
880 {
881 pszSrc = pSource->value + pPathRoot->value_length;
882 if ( *pszSrc == '/'
883 && !strncmp(pszSrc + 1, pPathSubCur->value, pPathSubCur->value_length)
884 && ( pszSrc[pPathSubCur->value_length + 1] == '/'
885 || pszSrc[pPathSubCur->value_length + 1] == '\0'))
886 pszSrc += 1 + pPathSubCur->value_length;
887 }
888 else
889 pszSrc = pSource->value;
890
891 /* skip root specification */
892#ifdef HAVE_DOS_PATHS
893 if (isalpha(pszSrc[0]) && pszSrc[1] == ':')
894 pszSrc += 2;
895#endif
896 while (*pszSrc == '/'
897#ifdef HAVE_DOS_PATHS
898 || *pszSrc == '\\'
899#endif
900 )
901 pszSrc++;
902
903 /* drop the source extension. */
904 pszSrcEnd = pSource->value + pSource->value_length;
905 for (;;)
906 {
907 pszSrcEnd--;
908 if ( pszSrcEnd <= pszSrc
909 || *pszSrcEnd == '/'
910#ifdef HAVE_DOS_PATHS
911 || *pszSrcEnd == '\\'
912 || *pszSrcEnd == ':'
913#endif
914 )
915 {
916 pszSrcEnd = pSource->value + pSource->value_length;
917 break;
918 }
919 if (*pszSrcEnd == '.')
920 break;
921 }
922
923 /*
924 * Assemble the string on the heap and define the objbase variable
925 * which we then return.
926 */
927 cchSrc = pszSrcEnd - pszSrc;
928 cch = pPathTarget->value_length
929 + 1 /* slash */
930 + pTarget->value_length
931 + 1 /* slash */
932 + cchSrcPrefix
933 + cchSrc
934 + 1;
935 psz = pszResult = xmalloc(cch);
936
937 memcpy(psz, pPathTarget->value, pPathTarget->value_length); psz += pPathTarget->value_length;
938 *psz++ = '/';
939 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
940 *psz++ = '/';
941 if (pszSrcPrefix)
942 {
943 memcpy(psz, pszSrcPrefix, cchSrcPrefix);
944 psz += cchSrcPrefix;
945 }
946 pszDot = psz;
947 memcpy(psz, pszSrc, cchSrc); psz += cchSrc;
948 *psz = '\0';
949
950 /* convert '..' path elements in the source to 'dt'. */
951 while ((pszDot = memchr(pszDot, '.', psz - pszDot)) != NULL)
952 {
953 if ( pszDot[1] == '.'
954 && ( pszDot == psz
955 || pszDot[-1] == '/'
956#ifdef HAVE_DOS_PATHS
957 || pszDot[-1] == '\\'
958 || pszDot[-1] == ':'
959#endif
960 )
961 && ( !pszDot[2]
962 || pszDot[2] == '/'
963#ifdef HAVE_DOS_PATHS
964 || pszDot[2] == '\\'
965 || pszDot[2] == ':'
966#endif
967 )
968 )
969 {
970 *pszDot++ = 'd';
971 *pszDot++ = 't';
972 }
973 else
974 pszDot++;
975 }
976
977 /*
978 * Define the variable in the current set and return it.
979 */
980 return define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cch - 1,
981 0 /* use pszResult */, o_local, 0 /* !recursive */);
982}
983
984
985/* Implements _OBJECT_BASE. */
986char *
987func_kbuild_object_base(char *o, char **argv, const char *pszFuncName)
988{
989 struct variable *pVar = kbuild_get_object_base(kbuild_lookup_variable("target"),
990 kbuild_lookup_variable("source"),
991 argv[0]);
992 if (pVar)
993 o = variable_buffer_output(o, pVar->value, pVar->value_length);
994 (void)pszFuncName;
995 return o;
996
997}
998
999
1000struct kbuild_sdks
1001{
1002 char *apsz[4];
1003 struct variable *pa;
1004 unsigned c;
1005 unsigned iGlobal;
1006 unsigned cGlobal;
1007 unsigned iTarget;
1008 unsigned cTarget;
1009 unsigned iSource;
1010 unsigned cSource;
1011 unsigned iTargetSource;
1012 unsigned cTargetSource;
1013};
1014
1015
1016/* Fills in the SDK struct (remember to free it). */
1017static void
1018kbuild_get_sdks(struct kbuild_sdks *pSdks, struct variable *pTarget, struct variable *pSource,
1019 struct variable *pBldType, struct variable *pBldTrg, struct variable *pBldTrgArch)
1020{
1021 unsigned i;
1022 unsigned j;
1023 size_t cchTmp, cch;
1024 char *pszTmp;
1025 unsigned cchCur;
1026 char *pszCur;
1027 const char *pszIterator;
1028
1029 /* basic init. */
1030 pSdks->pa = NULL;
1031 pSdks->c = 0;
1032 i = 0;
1033
1034 /* determin required tmp variable name space. */
1035 cchTmp = sizeof("$(__SDKS) $(__SDKS.) $(__SDKS.) $(__SDKS.) $(__SDKS..)")
1036 + (pTarget->value_length + pSource->value_length) * 5
1037 + pBldType->value_length
1038 + pBldTrg->value_length
1039 + pBldTrgArch->value_length
1040 + pBldTrg->value_length + pBldTrgArch->value_length;
1041 pszTmp = alloca(cchTmp);
1042
1043 /* the global sdks. */
1044 pSdks->iGlobal = i;
1045 pSdks->cGlobal = 0;
1046 sprintf(pszTmp, "$(SDKS) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s.%s)",
1047 pBldType->value,
1048 pBldTrg->value,
1049 pBldTrgArch->value,
1050 pBldTrg->value, pBldTrgArch->value);
1051 pszIterator = pSdks->apsz[0] = allocated_variable_expand(pszTmp);
1052 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1053 pSdks->cGlobal++;
1054 i += pSdks->cGlobal;
1055
1056 /* the target sdks.*/
1057 pSdks->iTarget = i;
1058 pSdks->cTarget = 0;
1059 sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
1060 pTarget->value,
1061 pTarget->value, pBldType->value,
1062 pTarget->value, pBldTrg->value,
1063 pTarget->value, pBldTrgArch->value,
1064 pTarget->value, pBldTrg->value, pBldTrgArch->value);
1065 pszIterator = pSdks->apsz[1] = allocated_variable_expand(pszTmp);
1066 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1067 pSdks->cTarget++;
1068 i += pSdks->cTarget;
1069
1070 /* the source sdks.*/
1071 pSdks->iSource = i;
1072 pSdks->cSource = 0;
1073 sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
1074 pSource->value,
1075 pSource->value, pBldType->value,
1076 pSource->value, pBldTrg->value,
1077 pSource->value, pBldTrgArch->value,
1078 pSource->value, pBldTrg->value, pBldTrgArch->value);
1079 pszIterator = pSdks->apsz[2] = allocated_variable_expand(pszTmp);
1080 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1081 pSdks->cSource++;
1082 i += pSdks->cSource;
1083
1084 /* the target + source sdks. */
1085 pSdks->iTargetSource = i;
1086 pSdks->cTargetSource = 0;
1087 cch = sprintf(pszTmp, "$(%s_%s_SDKS) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s.%s)",
1088 pTarget->value, pSource->value,
1089 pTarget->value, pSource->value, pBldType->value,
1090 pTarget->value, pSource->value, pBldTrg->value,
1091 pTarget->value, pSource->value, pBldTrgArch->value,
1092 pTarget->value, pSource->value, pBldTrg->value, pBldTrgArch->value);
1093 assert(cch < cchTmp); (void)cch;
1094 pszIterator = pSdks->apsz[3] = allocated_variable_expand(pszTmp);
1095 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1096 pSdks->cTargetSource++;
1097 i += pSdks->cTargetSource;
1098
1099 pSdks->c = i;
1100 if (!i)
1101 return;
1102
1103 /*
1104 * Allocate the variable array and create the variables.
1105 */
1106 pSdks->pa = (struct variable *)xmalloc(sizeof(pSdks->pa[0]) * i);
1107 memset(pSdks->pa, 0, sizeof(pSdks->pa[0]) * i);
1108 for (i = j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
1109 {
1110 pszIterator = pSdks->apsz[j];
1111 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1112 {
1113 pSdks->pa[i].value = pszCur;
1114 pSdks->pa[i].value_length = cchCur;
1115 i++;
1116 }
1117 }
1118 assert(i == pSdks->c);
1119
1120 /* terminate them (find_next_token won't work if we terminate them in the previous loop). */
1121 while (i-- > 0)
1122 pSdks->pa[i].value[pSdks->pa[i].value_length] = '\0';
1123}
1124
1125
1126/* releases resources allocated in the kbuild_get_sdks. */
1127static void
1128kbuild_put_sdks(struct kbuild_sdks *pSdks)
1129{
1130 unsigned j;
1131 for (j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
1132 free(pSdks->apsz[j]);
1133 free(pSdks->pa);
1134}
1135
1136
1137/* this kind of stuff:
1138
1139defs := $(kb-src-exp defs)
1140 $(TOOL_$(tool)_DEFS)\
1141 $(TOOL_$(tool)_DEFS.$(bld_type))\
1142 $(TOOL_$(tool)_DEFS.$(bld_trg))\
1143 $(TOOL_$(tool)_DEFS.$(bld_trg_arch))\
1144 $(TOOL_$(tool)_DEFS.$(bld_trg).$(bld_trg_arch))\
1145 $(TOOL_$(tool)_DEFS.$(bld_trg_cpu))\
1146 $(TOOL_$(tool)_$(type)DEFS)\
1147 $(TOOL_$(tool)_$(type)DEFS.$(bld_type))\
1148 $(foreach sdk, $(SDKS.$(bld_trg)) \
1149 $(SDKS.$(bld_trg).$(bld_trg_arch)) \
1150 $(SDKS.$(bld_type)) \
1151 $(SDKS),\
1152 $(SDK_$(sdk)_DEFS)\
1153 $(SDK_$(sdk)_DEFS.$(bld_type))\
1154 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1155 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1156 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1157 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1158 $(SDK_$(sdk)_$(type)DEFS)\
1159 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1160 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1161 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1162 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1163 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1164 $(DEFS)\
1165 $(DEFS.$(bld_type))\
1166 $(DEFS.$(bld_trg))\
1167 $(DEFS.$(bld_trg_arch))\
1168 $(DEFS.$(bld_trg).$(bld_trg_arch))\
1169 $(DEFS.$(bld_trg_cpu))\
1170 $($(type)DEFS)\
1171 $($(type)DEFS.$(bld_type))\
1172 $($(type)DEFS.$(bld_trg))\
1173 $($(type)DEFS.$(bld_trg_arch))\
1174 $($(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1175 $($(type)DEFS.$(bld_trg_cpu))\
1176 $(foreach sdk, $($(target)_SDKS.$(bld_trg)) \
1177 $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1178 $($(target)_SDKS.$(bld_type)) \
1179 $($(target)_SDKS),\
1180 $(SDK_$(sdk)_DEFS)\
1181 $(SDK_$(sdk)_DEFS.$(bld_type))\
1182 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1183 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1184 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1185 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1186 $(SDK_$(sdk)_$(type)DEFS)\
1187 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1188 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1189 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1190 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1191 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1192 $($(target)_DEFS)\
1193 $($(target)_DEFS.$(bld_type))\
1194 $($(target)_DEFS.$(bld_trg))\
1195 $($(target)_DEFS.$(bld_trg_arch))\
1196 $($(target)_DEFS.$(bld_trg).$(bld_trg_arch))\
1197 $($(target)_DEFS.$(bld_trg_cpu))\
1198 $($(target)_$(type)DEFS)\
1199 $($(target)_$(type)DEFS.$(bld_type))\
1200 $($(target)_$(type)DEFS.$(bld_trg))\
1201 $($(target)_$(type)DEFS.$(bld_trg_arch))\
1202 $($(target)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1203 $($(target)_$(type)DEFS.$(bld_trg_cpu))\
1204 $(foreach sdk, $($(source)_SDKS.$(bld_trg)) \
1205 $($(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1206 $($(source)_SDKS.$(bld_type)) \
1207 $($(source)_SDKS),\
1208 $(SDK_$(sdk)_DEFS)\
1209 $(SDK_$(sdk)_DEFS.$(bld_type))\
1210 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1211 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1212 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1213 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1214 $(SDK_$(sdk)_$(type)DEFS)\
1215 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1216 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1217 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1218 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1219 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1220 $($(source)_DEFS)\
1221 $($(source)_DEFS.$(bld_type))\
1222 $($(source)_DEFS.$(bld_trg))\
1223 $($(source)_DEFS.$(bld_trg_arch))\
1224 $($(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
1225 $($(source)_DEFS.$(bld_trg_cpu))\
1226 $($(source)_$(type)DEFS)\
1227 $($(source)_$(type)DEFS.$(bld_type))\
1228 $($(source)_$(type)DEFS.$(bld_trg))\
1229 $($(source)_$(type)DEFS.$(bld_trg_arch))\
1230 $($(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1231 $($(source)_$(type)DEFS.$(bld_trg_cpu))\
1232 $(foreach sdk, $($(target)_$(source)_SDKS.$(bld_trg)) \
1233 $($(target)_$(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1234 $($(target)_$(source)_SDKS.$(bld_type)) \
1235 $($(target)_$(source)_SDKS),\
1236 $(SDK_$(sdk)_DEFS)\
1237 $(SDK_$(sdk)_DEFS.$(bld_type))\
1238 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1239 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1240 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1241 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1242 $(SDK_$(sdk)_$(type)DEFS)\
1243 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1244 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1245 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1246 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1247 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1248 $($(target)_$(source)_DEFS)\
1249 $($(target)_$(source)_DEFS.$(bld_type))\
1250 $($(target)_$(source)_DEFS.$(bld_trg))\
1251 $($(target)_$(source)_DEFS.$(bld_trg_arch))\
1252 $($(target)_$(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
1253 $($(target)_$(source)_DEFS.$(bld_trg_cpu))\
1254 $($(target)_$(source)_$(type)DEFS)\
1255 $($(target)_$(source)_$(type)DEFS.$(bld_type))\
1256 $($(target)_$(source)_$(type)DEFS.$(bld_trg))\
1257 $($(target)_$(source)_$(type)DEFS.$(bld_trg_arch))\
1258 $($(target)_$(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1259 $($(target)_$(source)_$(type)DEFS.$(bld_trg_cpu))
1260*/
1261static struct variable *
1262kbuild_collect_source_prop(struct variable *pTarget, struct variable *pSource,
1263 struct variable *pTool, struct kbuild_sdks *pSdks,
1264 struct variable *pType, struct variable *pBldType,
1265 struct variable *pBldTrg, struct variable *pBldTrgArch, struct variable *pBldTrgCpu,
1266 struct variable *pDefPath,
1267 const char *pszProp, const char *pszVarName, int iDirection)
1268{
1269 struct variable *pVar;
1270 unsigned iSdk, iSdkEnd;
1271 int cVars, iVar, iVarEnd;
1272 size_t cchTotal;
1273 char *pszResult, *psz;
1274 struct
1275 {
1276 struct variable *pVar;
1277 int cchExp;
1278 char *pszExp;
1279 } *paVars;
1280
1281 struct variable Prop = {0};
1282 Prop.value = (char *)pszProp;
1283 Prop.value_length = strlen(pszProp);
1284
1285 assert(iDirection == 1 || iDirection == -1);
1286
1287 /*
1288 * Get the variables.
1289 */
1290 cVars = 12 * (pSdks->c + 5);
1291 paVars = alloca(cVars * sizeof(paVars[0]));
1292
1293 iVar = 0;
1294 /* the tool (lowest priority) */
1295 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%", pTool, &Prop);
1296 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &Prop, pBldType);
1297 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &Prop, pBldTrg);
1298 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &Prop, pBldTrgArch);
1299 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%.%", pTool, &Prop, pBldTrg, pBldTrgArch);
1300 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &Prop, pBldTrgCpu);
1301
1302 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%", pTool, pType, &Prop);
1303 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &Prop, pBldType);
1304 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &Prop, pBldTrg);
1305 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &Prop, pBldTrgArch);
1306 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%.%", pTool, pType, &Prop, pBldTrg, pBldTrgArch);
1307 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &Prop, pBldTrgCpu);
1308
1309 /* the global sdks */
1310 iSdkEnd = iDirection == 1 ? pSdks->iGlobal + pSdks->cGlobal : pSdks->iGlobal - 1;
1311 for (iSdk = iDirection == 1 ? pSdks->iGlobal : pSdks->iGlobal + pSdks->cGlobal - 1;
1312 iSdk != iSdkEnd;
1313 iSdk += iDirection)
1314 {
1315 struct variable *pSdk = &pSdks->pa[iSdk];
1316 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%", pSdk, &Prop);
1317 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldType);
1318 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrg);
1319 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
1320 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
1321 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
1322
1323 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%", pSdk, pType, &Prop);
1324 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
1325 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
1326 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
1327 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
1328 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
1329 }
1330
1331 /* the globals */
1332 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%", &Prop);
1333 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &Prop, pBldType);
1334 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &Prop, pBldTrg);
1335 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &Prop, pBldTrgArch);
1336 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%.%", &Prop, pBldTrg, pBldTrgArch);
1337 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &Prop, pBldTrgCpu);
1338
1339 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%", pType, &Prop);
1340 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &Prop, pBldType);
1341 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &Prop, pBldTrg);
1342 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &Prop, pBldTrgArch);
1343 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%.%", pType, &Prop, pBldTrg, pBldTrgArch);
1344 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &Prop, pBldTrgCpu);
1345
1346 /* the target sdks */
1347 iSdkEnd = iDirection == 1 ? pSdks->iTarget + pSdks->cTarget : pSdks->iTarget - 1;
1348 for (iSdk = iDirection == 1 ? pSdks->iTarget : pSdks->iTarget + pSdks->cTarget - 1;
1349 iSdk != iSdkEnd;
1350 iSdk += iDirection)
1351 {
1352 struct variable *pSdk = &pSdks->pa[iSdk];
1353 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%", pSdk, &Prop);
1354 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldType);
1355 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrg);
1356 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
1357 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
1358 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
1359
1360 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%", pSdk, pType, &Prop);
1361 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
1362 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
1363 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
1364 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
1365 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
1366 }
1367
1368 /* the target */
1369 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%", pTarget, &Prop);
1370 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pTarget, &Prop, pBldType);
1371 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pTarget, &Prop, pBldTrg);
1372 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pTarget, &Prop, pBldTrgArch);
1373 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%.%", pTarget, &Prop, pBldTrg, pBldTrgArch);
1374 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pTarget, &Prop, pBldTrgCpu);
1375
1376 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%", pTarget, pType, &Prop);
1377 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pTarget, pType, &Prop, pBldType);
1378 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pTarget, pType, &Prop, pBldTrg);
1379 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pTarget, pType, &Prop, pBldTrgArch);
1380 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%.%", pTarget, pType, &Prop, pBldTrg, pBldTrgArch);
1381 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pTarget, pType, &Prop, pBldTrgCpu);
1382
1383 /* the source sdks */
1384 iSdkEnd = iDirection == 1 ? pSdks->iSource + pSdks->cSource : pSdks->iSource - 1;
1385 for (iSdk = iDirection == 1 ? pSdks->iSource : pSdks->iSource + pSdks->cSource - 1;
1386 iSdk != iSdkEnd;
1387 iSdk += iDirection)
1388 {
1389 struct variable *pSdk = &pSdks->pa[iSdk];
1390 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%", pSdk, &Prop);
1391 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldType);
1392 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrg);
1393 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
1394 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
1395 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
1396
1397 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%", pSdk, pType, &Prop);
1398 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
1399 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
1400 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
1401 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
1402 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
1403 }
1404
1405 /* the source */
1406 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%", pSource, &Prop);
1407 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pSource, &Prop, pBldType);
1408 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pSource, &Prop, pBldTrg);
1409 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pSource, &Prop, pBldTrgArch);
1410 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%.%", pSource, &Prop, pBldTrg, pBldTrgArch);
1411 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pSource, &Prop, pBldTrgCpu);
1412
1413 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%", pSource, pType, &Prop);
1414 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pSource, pType, &Prop, pBldType);
1415 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pSource, pType, &Prop, pBldTrg);
1416 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pSource, pType, &Prop, pBldTrgArch);
1417 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%.%", pSource, pType, &Prop, pBldTrg, pBldTrgArch);
1418 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pSource, pType, &Prop, pBldTrgCpu);
1419
1420
1421 /* the target + source sdks */
1422 iSdkEnd = iDirection == 1 ? pSdks->iTargetSource + pSdks->cTargetSource : pSdks->iTargetSource - 1;
1423 for (iSdk = iDirection == 1 ? pSdks->iTargetSource : pSdks->iTargetSource + pSdks->cTargetSource - 1;
1424 iSdk != iSdkEnd;
1425 iSdk += iDirection)
1426 {
1427 struct variable *pSdk = &pSdks->pa[iSdk];
1428 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%", pSdk, &Prop);
1429 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldType);
1430 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrg);
1431 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
1432 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
1433 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
1434
1435 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%", pSdk, pType, &Prop);
1436 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
1437 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
1438 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
1439 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
1440 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
1441 }
1442
1443 /* the target + source */
1444 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%", pTarget, pSource, &Prop);
1445 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%", pTarget, pSource, &Prop, pBldType);
1446 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%", pTarget, pSource, &Prop, pBldTrg);
1447 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%", pTarget, pSource, &Prop, pBldTrgArch);
1448 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%.%", pTarget, pSource, &Prop, pBldTrg, pBldTrgArch);
1449 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%", pTarget, pSource, &Prop, pBldTrgCpu);
1450
1451 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%", pTarget, pSource, pType, &Prop);
1452 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%", pTarget, pSource, pType, &Prop, pBldType);
1453 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrg);
1454 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrgArch);
1455 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%.%", pTarget, pSource, pType, &Prop, pBldTrg, pBldTrgArch);
1456 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrgCpu);
1457
1458 assert(cVars == iVar);
1459
1460 /*
1461 * Expand the variables and calculate the total length.
1462 */
1463 cchTotal = 0;
1464 iVarEnd = iDirection == 1 ? cVars : 0;
1465 for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
1466 {
1467 paVars[iVar].cchExp = 0;
1468 if (!paVars[iVar].pVar)
1469 continue;
1470 if ( paVars[iVar].pVar->flavor == f_simple
1471 || !strchr(paVars[iVar].pVar->value, '$'))
1472 {
1473 paVars[iVar].pszExp = paVars[iVar].pVar->value;
1474 paVars[iVar].cchExp = paVars[iVar].pVar->value_length;
1475 }
1476 else
1477 {
1478 paVars[iVar].pszExp = allocated_variable_expand(paVars[iVar].pVar->value);
1479 paVars[iVar].cchExp = strlen(paVars[iVar].pszExp);
1480 }
1481 if (pDefPath)
1482 kbuild_apply_defpath(pDefPath, &paVars[iVar].pszExp, &paVars[iVar].cchExp, NULL,
1483 paVars[iVar].pszExp != paVars[iVar].pVar->value);
1484 cchTotal += paVars[iVar].cchExp + 1;
1485 }
1486
1487 /*
1488 * Construct the result value.
1489 */
1490 psz = pszResult = xmalloc(cchTotal + 1);
1491 iVarEnd = iDirection == 1 ? cVars : 0;
1492 for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
1493 {
1494 if (!paVars[iVar].cchExp)
1495 continue;
1496 memcpy(psz, paVars[iVar].pszExp, paVars[iVar].cchExp);
1497 psz += paVars[iVar].cchExp;
1498 *psz++ = ' ';
1499 if (paVars[iVar].pszExp != paVars[iVar].pVar->value)
1500 free(paVars[iVar].pszExp);
1501 }
1502 if (psz != pszResult)
1503 psz--;
1504 *psz = '\0';
1505 cchTotal = psz - pszResult;
1506
1507 pVar = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cchTotal,
1508 0 /* take pszResult */ , o_local, 0 /* !recursive */);
1509 return pVar;
1510}
1511
1512
1513/* get a source property. */
1514char *
1515func_kbuild_source_prop(char *o, char **argv, const char *pszFuncName)
1516{
1517 struct variable *pTarget = kbuild_get_variable("target");
1518 struct variable *pSource = kbuild_get_variable("source");
1519 struct variable *pDefPath = NULL;
1520 struct variable *pType = kbuild_get_variable("type");
1521 struct variable *pTool = kbuild_get_variable("tool");
1522 struct variable *pBldType = kbuild_get_variable("bld_type");
1523 struct variable *pBldTrg = kbuild_get_variable("bld_trg");
1524 struct variable *pBldTrgArch = kbuild_get_variable("bld_trg_arch");
1525 struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
1526 struct variable *pVar;
1527 struct kbuild_sdks Sdks;
1528 int iDirection;
1529 if (!strcmp(argv[2], "left-to-right"))
1530 iDirection = 1;
1531 else if (!strcmp(argv[2], "right-to-left"))
1532 iDirection = -1;
1533 else
1534 fatal(NILF, _("incorrect direction argument `%s'!"), argv[2]);
1535 if (argv[3])
1536 {
1537 const char *psz = argv[3];
1538 while (isspace(*psz))
1539 psz++;
1540 if (*psz)
1541 pDefPath = kbuild_get_variable("defpath");
1542 }
1543
1544 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
1545
1546 pVar = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType,
1547 pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
1548 pDefPath,
1549 argv[0], argv[1], iDirection);
1550 if (pVar)
1551 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1552
1553 kbuild_put_sdks(&Sdks);
1554 (void)pszFuncName;
1555 return o;
1556}
1557
1558
1559/*
1560dep := $(obj)$(SUFF_DEP)
1561obj := $(outbase)$(objsuff)
1562dirdep := $(call DIRDEP,$(dir $(outbase)))
1563PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1564*/
1565static struct variable *
1566kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(struct variable *pTarget, struct variable *pSource,
1567 struct variable *pOutBase, struct variable *pObjSuff,
1568 const char *pszVarName, struct variable **ppDep,
1569 struct variable **ppDirDep)
1570{
1571 struct variable *pDepSuff = kbuild_get_variable("SUFF_DEP");
1572 struct variable *pObj;
1573 size_t cch = pOutBase->value_length + pObjSuff->value_length + pDepSuff->value_length + 1;
1574 char *pszResult = alloca(cch);
1575 char *pszName, *psz;
1576
1577 /*
1578 * dep.
1579 */
1580 psz = pszResult;
1581 memcpy(psz, pOutBase->value, pOutBase->value_length); psz += pOutBase->value_length;
1582 memcpy(psz, pObjSuff->value, pObjSuff->value_length); psz += pObjSuff->value_length;
1583 memcpy(psz, pDepSuff->value, pDepSuff->value_length + 1);
1584 *ppDep = define_variable_vl("dep", 3, pszResult, cch - 1, 1 /*dup*/, o_local, 0 /* !recursive */);
1585
1586 /*
1587 * obj
1588 */
1589 *psz = '\0';
1590 pObj = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, psz - pszResult,
1591 1/* dup */, o_local, 0 /* !recursive */);
1592
1593 /*
1594 * PATH_$(target)_$(source) - this is global!
1595 */
1596 /* calc variable name. */
1597 cch = sizeof("PATH_")-1 + pTarget->value_length + sizeof("_")-1 + pSource->value_length;
1598 psz = pszName = alloca(cch + 1);
1599 memcpy(psz, "PATH_", sizeof("PATH_") - 1); psz += sizeof("PATH_") - 1;
1600 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1601 *psz++ = '_';
1602 memcpy(psz, pSource->value, pSource->value_length + 1);
1603
1604 /* strip off the filename. */
1605 psz = pszResult + pOutBase->value_length;
1606 for (;;)
1607 {
1608 psz--;
1609 if (psz <= pszResult)
1610 fatal(NULL, "whut!?! no path? result=`%s'", pszResult);
1611#ifdef HAVE_DOS_PATHS
1612 if (*psz == ':')
1613 {
1614 psz++;
1615 break;
1616 }
1617#endif
1618 if ( *psz == '/'
1619#ifdef HAVE_DOS_PATHS
1620 || *psz == '\\'
1621#endif
1622 )
1623 {
1624 while ( psz - 1 > pszResult
1625 && psz[-1] == '/'
1626#ifdef HAVE_DOS_PATHS
1627 || psz[-1] == '\\'
1628#endif
1629 )
1630 psz--;
1631#ifdef HAVE_DOS_PATHS
1632 if (psz == pszResult + 2 && pszResult[1] == ':')
1633 psz++;
1634#endif
1635 break;
1636 }
1637 }
1638 *psz = '\0';
1639
1640 /* set global variable */
1641 define_variable_vl_global(pszName, cch, pszResult, psz - pszResult, 1/*dup*/, o_file, 0 /* !recursive */, NILF);
1642
1643 /*
1644 * dirdep
1645 */
1646 if ( psz[-1] != '/'
1647#ifdef HAVE_DOS_PATHS
1648 && psz[-1] != '\\'
1649 && psz[-1] != ':'
1650#endif
1651 )
1652 {
1653 *psz++ = '/';
1654 *psz = '\0';
1655 }
1656 *ppDirDep = define_variable_vl("dirdep", 6, pszResult, psz - pszResult, 1/*dup*/, o_local, 0 /* !recursive */);
1657
1658 return pObj;
1659}
1660
1661
1662/* setup the base variables for def_target_source_c_cpp_asm_new:
1663
1664X := $(kb-src-tool tool)
1665x := $(kb-obj-base outbase)
1666x := $(kb-obj-suff objsuff)
1667obj := $(outbase)$(objsuff)
1668PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1669
1670x := $(kb-src-prop DEFS,defs,left-to-right)
1671x := $(kb-src-prop INCS,incs,right-to-left)
1672x := $(kb-src-prop FLAGS,flags,right-to-left)
1673
1674x := $(kb-src-prop DEPS,deps,left-to-right)
1675dirdep := $(call DIRDEP,$(dir $(outbase)))
1676dep := $(obj)$(SUFF_DEP)
1677*/
1678char *
1679func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
1680{
1681 static int s_fNoCompileCmdsDepsDefined = -1;
1682 struct variable *pTarget = kbuild_get_variable("target");
1683 struct variable *pSource = kbuild_get_variable("source");
1684 struct variable *pDefPath = kbuild_get_variable("defpath");
1685 struct variable *pType = kbuild_get_variable("type");
1686 struct variable *pBldType = kbuild_get_variable("bld_type");
1687 struct variable *pBldTrg = kbuild_get_variable("bld_trg");
1688 struct variable *pBldTrgArch= kbuild_get_variable("bld_trg_arch");
1689 struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
1690 struct variable *pTool = kbuild_get_source_tool(pTarget, pSource, pType, pBldTrg, pBldTrgArch, "tool");
1691 struct variable *pOutBase = kbuild_get_object_base(pTarget, pSource, "outbase");
1692 struct variable *pObjSuff = kbuild_get_object_suffix(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch, "objsuff");
1693 struct variable *pDefs, *pIncs, *pFlags, *pDeps, *pOrderDeps, *pDirDep, *pDep, *pVar, *pOutput, *pOutputMaybe;
1694 struct variable *pObj = kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(pTarget, pSource, pOutBase, pObjSuff, "obj", &pDep, &pDirDep);
1695 char *pszDstVar, *pszDst, *pszSrcVar, *pszSrc, *pszVal, *psz;
1696 char *pszSavedVarBuf;
1697 unsigned cchSavedVarBuf;
1698 size_t cch;
1699 struct kbuild_sdks Sdks;
1700
1701 /*
1702 * Gather properties.
1703 */
1704 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
1705
1706 if (pDefPath && !pDefPath->value_length)
1707 pDefPath = NULL;
1708 pDefs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
1709 "DEFS", "defs", 1/* left-to-right */);
1710 pIncs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
1711 "INCS", "incs", -1/* right-to-left */);
1712 pFlags = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
1713 "FLAGS", "flags", 1/* left-to-right */);
1714 pDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
1715 "DEPS", "deps", 1/* left-to-right */);
1716 pOrderDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
1717 "ORDERDEPS", "orderdeps", 1/* left-to-right */);
1718
1719 /*
1720 * If we've got a default path, we must expand the source now.
1721 * If we do this too early, "<source>_property = stuff" won't work becuase
1722 * our 'source' value isn't what the user expects.
1723 */
1724 if (pDefPath)
1725 kbuild_apply_defpath(pDefPath, &pSource->value, &pSource->value_length, &pSource->value_alloc_len, 1 /* can free */);
1726
1727 /*
1728 # dependencies
1729 ifndef NO_COMPILE_CMDS_DEPS
1730 _DEPFILES_INCLUDED += $(dep)
1731 $(if $(wildcard $(dep)),$(eval include $(dep)))
1732 endif
1733 */
1734 if (s_fNoCompileCmdsDepsDefined == -1)
1735 s_fNoCompileCmdsDepsDefined = kbuild_lookup_variable("NO_COMPILE_CMDS_DEPS") != NULL;
1736 if (!s_fNoCompileCmdsDepsDefined)
1737 {
1738 do_variable_definition(NILF, "_DEPFILES_INCLUDED", pDep->value, o_file, f_append, 0 /* !target_var */);
1739 eval_include_dep(pDep->value, NILF);
1740 }
1741
1742 /*
1743 # call the tool
1744 $(target)_$(source)_CMDS_ := $(TOOL_$(tool)_COMPILE_$(type)_CMDS)
1745 $(target)_$(source)_OUTPUT_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT)
1746 $(target)_$(source)_OUTPUT_MAYBE_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT_MAYBE)
1747 $(target)_$(source)_DEPEND_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPEND) $(deps) $(source)
1748 $(target)_$(source)_DEPORD_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPORD) $(dirdep)
1749 */
1750 cch = sizeof("TOOL_") + pTool->value_length + sizeof("_COMPILE_") + pType->value_length + sizeof("_OUTPUT_MAYBE");
1751 psz = pszSrcVar = alloca(cch);
1752 memcpy(psz, "TOOL_", sizeof("TOOL_") - 1); psz += sizeof("TOOL_") - 1;
1753 memcpy(psz, pTool->value, pTool->value_length); psz += pTool->value_length;
1754 memcpy(psz, "_COMPILE_", sizeof("_COMPILE_") - 1); psz += sizeof("_COMPILE_") - 1;
1755 memcpy(psz, pType->value, pType->value_length); psz += pType->value_length;
1756 pszSrc = psz;
1757
1758 cch = pTarget->value_length + 1 + pSource->value_length + sizeof("_OUTPUT_MAYBE_");
1759 psz = pszDstVar = alloca(cch);
1760 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1761 *psz++ = '_';
1762 memcpy(psz, pSource->value, pSource->value_length); psz += pSource->value_length;
1763 pszDst = psz;
1764
1765 memcpy(pszSrc, "_CMDS", sizeof("_CMDS"));
1766 memcpy(pszDst, "_CMDS_", sizeof("_CMDS_"));
1767 pVar = kbuild_get_recursive_variable(pszSrcVar);
1768 do_variable_definition(NILF, pszDstVar, pVar->value, o_file, f_simple, 0 /* !target_var */);
1769
1770 memcpy(pszSrc, "_OUTPUT", sizeof("_OUTPUT"));
1771 memcpy(pszDst, "_OUTPUT_", sizeof("_OUTPUT_"));
1772 pVar = kbuild_get_recursive_variable(pszSrcVar);
1773 pOutput = do_variable_definition(NILF, pszDstVar, pVar->value, o_file, f_simple, 0 /* !target_var */);
1774
1775 memcpy(pszSrc, "_OUTPUT_MAYBE", sizeof("_OUTPUT_MAYBE"));
1776 memcpy(pszDst, "_OUTPUT_MAYBE_", sizeof("_OUTPUT_MAYBE_"));
1777 pVar = kbuild_query_recursive_variable(pszSrcVar);
1778 pOutputMaybe = do_variable_definition(NILF, pszDstVar, pVar ? pVar->value : "", o_file, f_simple, 0 /* !target_var */);
1779
1780 memcpy(pszSrc, "_DEPEND", sizeof("_DEPEND"));
1781 memcpy(pszDst, "_DEPEND_", sizeof("_DEPEND_"));
1782 pVar = kbuild_get_recursive_variable(pszSrcVar);
1783 psz = pszVal = xmalloc(pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length + 1);
1784 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1785 *psz++ = ' ';
1786 memcpy(psz, pDeps->value, pDeps->value_length); psz += pDeps->value_length;
1787 *psz++ = ' ';
1788 memcpy(psz, pSource->value, pSource->value_length + 1);
1789 do_variable_definition(NILF, pszDstVar, pszVal, o_file, f_simple, 0 /* !target_var */);
1790 free(pszVal);
1791
1792 memcpy(pszSrc, "_DEPORD", sizeof("_DEPORD"));
1793 memcpy(pszDst, "_DEPORD_", sizeof("_DEPORD_"));
1794 pVar = kbuild_get_recursive_variable(pszSrcVar);
1795 psz = pszVal = xmalloc(pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length + 1);
1796 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1797 *psz++ = ' ';
1798 memcpy(psz, pDirDep->value, pDirDep->value_length); psz += pDirDep->value_length;
1799 *psz++ = ' ';
1800 memcpy(psz, pOrderDeps->value, pOrderDeps->value_length + 1);
1801 do_variable_definition(NILF, pszDstVar, pszVal, o_file, f_simple, 0 /* !target_var */);
1802 free(pszVal);
1803
1804 /*
1805 _OUT_FILES += $($(target)_$(source)_OUTPUT_) $($(target)_$(source)_OUTPUT_MAYBE_)
1806 */
1807 pVar = kbuild_get_variable("_OUT_FILES");
1808 psz = pszVal = xmalloc(pVar->value_length + 1 + pOutput->value_length + 1 + pOutputMaybe->value_length + 1);
1809 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1810 *psz++ = ' ';
1811 memcpy(psz, pOutput->value, pOutput->value_length); psz += pOutput->value_length;
1812 *psz++ = ' ';
1813 memcpy(psz, pOutputMaybe->value, pOutputMaybe->value_length + 1);
1814 do_variable_definition(NILF, "_OUT_FILES", pszVal, o_file, f_simple, 0 /* !target_var */);
1815 free(pszVal);
1816
1817 /*
1818 $(target)_OBJS_ += $(obj)
1819 */
1820 memcpy(pszDstVar + pTarget->value_length, "_OBJS_", sizeof("_OBJS_"));
1821 do_variable_definition(NILF, pszDstVar, pObj->value, o_file, f_append, 0 /* !target_var */);
1822
1823 /*
1824 $(eval $(def_target_source_rule))
1825 */
1826 pVar = kbuild_get_recursive_variable("def_target_source_rule");
1827 pszVal = allocated_variable_expand(pVar->value);
1828
1829 install_variable_buffer(&pszSavedVarBuf, &cchSavedVarBuf);
1830 eval_buffer(pszVal);
1831 restore_variable_buffer(pszSavedVarBuf, cchSavedVarBuf);
1832
1833 free(pszVal);
1834
1835 kbuild_put_sdks(&Sdks);
1836 (void)pszFuncName;
1837 (void)argv;
1838 return variable_buffer_output(o, "", 1);
1839}
1840
1841
1842#endif /* KMK_HELPERS */
1843
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette