VirtualBox

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

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

Seems '_.' is a bad idea, use 'dt'.

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