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

Last change on this file since 1303 was 1298, checked in by bird, 18 years ago

better check for the kmk shell. don't freak out and use the shell on double-quote (probably a bug).

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