VirtualBox

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

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

Environment / globals cleanup. The new policy is to use KBUILD_ and KMK_ prefixes for things that is put into or/and picked from the environment. This will take a good while to complete.

Renamed (old still valid for some versions):
PATH_KBUILD -> KBUILD_PATH
PATH_KBUILD_BIN -> KBUILD_BIN_PATH
BUILD_PLATFORM -> KBUILD_HOST
BUILD_PLATFORM_ARCH -> KBUILD_HOST_ARCH
BUILD_PLATFORM_CPU -> KBUILD_HOST_CPU

Renamed - old not checked:
MAKELEVEL -> KMK_LEVEL
KMKFLAGS -> KMK_FLAGS
MAKEFLAGS -> KMK_FLAGS
MAKEOVERRIDES -> KMK_OVERRIDES

Removed:
MAKE_VERSION
MFLAGS

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

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