VirtualBox

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

Last change on this file since 1116 was 1071, checked in by bird, 17 years ago

Implemented PATH fallback for locating the executable. (FreeBSD doesn't necessarily have /proc mounted.)

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