VirtualBox

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

Last change on this file since 1169 was 1128, checked in by bird, 17 years ago

OUTPUT_MAYBE support for compilers and assemblers.

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

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