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

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

kmk: a bit more.

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