VirtualBox

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

Last change on this file since 1946 was 1932, checked in by bird, 16 years ago

kmk: Made struct variable capable of holding read only variables to speed up set_file_variables.

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