VirtualBox

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

Last change on this file since 1882 was 1834, checked in by bird, 16 years ago

kmk: assertions.

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