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

Last change on this file since 1833 was 1832, checked in by bird, 17 years ago

kmk: starting to eliminate kbuild_get_variable_fmt*. Use sizeof() on constant strings where possible.

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