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

Last change on this file since 1499 was 1484, checked in by bird, 17 years ago

Fixed memchr crash in kbuild_get_object_base. A recent regression caused by the '..' -> 'dt' change.

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