VirtualBox

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

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

kbuild.c: some more cleanup.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 71.4 KB
Line 
1/* $Id: kbuild.c 1924 2008-10-24 02:41:34Z 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
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 free(pVar->value);
575 pVar->value = pszExpanded;
576 pVar->value_length = value_len;
577 pVar->value_alloc_len = value_len + 1;
578 }
579 pVar->recursive = 0;
580 return pVar;
581}
582
583
584/**
585 * Looks up a variable.
586 * The value_length field is valid upon successful return.
587 *
588 * @returns Pointer to the variable. NULL if not found.
589 * @param pszName The variable name.
590 * @param cchName The name length.
591 */
592MY_INLINE struct variable *
593kbuild_lookup_variable_n(const char *pszName, size_t cchName)
594{
595 struct variable *pVar = lookup_variable(pszName, cchName);
596 if (pVar)
597 {
598#ifndef NDEBUG
599 int i = strlen(pVar->value);
600 if (i != pVar->value_length)
601 {
602 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
603# ifdef _MSC_VER
604 __debugbreak();
605# endif
606 assert(0);
607 }
608#endif
609 /* Make sure the variable is simple, convert it if necessary. */
610 if (pVar->recursive)
611 kbuild_simplify_variable(pVar);
612 }
613 return pVar;
614}
615
616
617/**
618 * Looks up a variable.
619 * The value_length field is valid upon successful return.
620 *
621 * @returns Pointer to the variable. NULL if not found.
622 * @param pszName The variable name.
623 */
624MY_INLINE struct variable *
625kbuild_lookup_variable(const char *pszName)
626{
627 return kbuild_lookup_variable_n(pszName, strlen(pszName));
628}
629
630
631/**
632 * Looks up a variable and applies default a path to all relative paths.
633 * The value_length field is valid upon successful return.
634 *
635 * @returns Pointer to the variable. NULL if not found.
636 * @param pDefPath The default path.
637 * @param pszName The variable name.
638 * @param cchName The name length.
639 */
640MY_INLINE struct variable *
641kbuild_lookup_variable_defpath_n(struct variable *pDefPath, const char *pszName, size_t cchName)
642{
643 struct variable *pVar = kbuild_lookup_variable_n(pszName, cchName);
644 if (pVar && pDefPath)
645 kbuild_apply_defpath(pDefPath, &pVar->value, (unsigned int *)&pVar->value_length, &pVar->value_alloc_len, 1);
646 return pVar;
647}
648
649
650/**
651 * Looks up a variable and applies default a path to all relative paths.
652 * The value_length field is valid upon successful return.
653 *
654 * @returns Pointer to the variable. NULL if not found.
655 * @param pDefPath The default path.
656 * @param pszName The variable name.
657 */
658MY_INLINE struct variable *
659kbuild_lookup_variable_defpath(struct variable *pDefPath, const char *pszName)
660{
661 struct variable *pVar = kbuild_lookup_variable(pszName);
662 if (pVar && pDefPath)
663 kbuild_apply_defpath(pDefPath, &pVar->value, (unsigned int *)&pVar->value_length, &pVar->value_alloc_len, 1);
664 return pVar;
665}
666
667
668/**
669 * Gets the first defined property variable.
670 */
671static struct variable *
672kbuild_first_prop(struct variable *pTarget, struct variable *pSource,
673 struct variable *pTool, struct variable *pType,
674 struct variable *pBldTrg, struct variable *pBldTrgArch,
675 const char *pszPropF1, char cchPropF1,
676 const char *pszPropF2, char cchPropF2,
677 const char *pszVarName)
678{
679 struct variable *pVar;
680 size_t cchBuf;
681 char *pszBuf;
682 char *psz, *psz1, *psz2, *psz3, *psz4;
683
684 /* calc and allocate a too big name buffer. */
685 cchBuf = cchPropF2 + 1
686 + cchPropF1 + 1
687 + pTarget->value_length + 1
688 + pSource->value_length + 1
689 + (pTool ? pTool->value_length + 1 : 0)
690 + pType->value_length + 1
691 + pBldTrg->value_length + 1
692 + pBldTrgArch->value_length + 1;
693 pszBuf = xmalloc(cchBuf);
694
695#define ADD_VAR(pVar) do { my_memcpy(psz, (pVar)->value, (pVar)->value_length); psz += (pVar)->value_length; } while (0)
696#define ADD_STR(pszStr, cchStr) do { my_memcpy(psz, (pszStr), (cchStr)); psz += (cchStr); } while (0)
697#define ADD_CSTR(pszStr) do { my_memcpy(psz, pszStr, sizeof(pszStr) - 1); psz += sizeof(pszStr) - 1; } while (0)
698#define ADD_CH(ch) do { *psz++ = (ch); } while (0)
699
700 /*
701 * $(target)_$(source)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
702 */
703 psz = pszBuf;
704 ADD_VAR(pTarget);
705 ADD_CH('_');
706 ADD_VAR(pSource);
707 ADD_CH('_');
708 psz2 = psz;
709 ADD_VAR(pType);
710 ADD_STR(pszPropF2, cchPropF2);
711 psz3 = psz;
712 ADD_CH('.');
713 ADD_VAR(pBldTrg);
714 psz4 = psz;
715 ADD_CH('.');
716 ADD_VAR(pBldTrgArch);
717 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
718
719 /* $(target)_$(source)_$(type)$(propf2).$(bld_trg) */
720 if (!pVar)
721 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
722
723 /* $(target)_$(source)_$(type)$(propf2) */
724 if (!pVar)
725 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
726
727 /*
728 * $(target)_$(source)_$(propf2).$(bld_trg).$(bld_trg_arch)
729 */
730 if (!pVar)
731 {
732 psz = psz2;
733 ADD_STR(pszPropF2, cchPropF2);
734 psz3 = psz;
735 ADD_CH('.');
736 ADD_VAR(pBldTrg);
737 psz4 = psz;
738 ADD_CH('.');
739 ADD_VAR(pBldTrgArch);
740 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
741
742 /* $(target)_$(source)_$(propf2).$(bld_trg) */
743 if (!pVar)
744 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
745
746 /* $(target)_$(source)_$(propf2) */
747 if (!pVar)
748 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
749 }
750
751
752 /*
753 * $(source)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
754 */
755 if (!pVar)
756 {
757 psz = pszBuf;
758 ADD_VAR(pSource);
759 ADD_CH('_');
760 psz2 = psz;
761 ADD_VAR(pType);
762 ADD_STR(pszPropF2, cchPropF2);
763 psz3 = psz;
764 ADD_CH('.');
765 ADD_VAR(pBldTrg);
766 psz4 = psz;
767 ADD_CH('.');
768 ADD_VAR(pBldTrgArch);
769 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
770
771 /* $(source)_$(type)$(propf2).$(bld_trg) */
772 if (!pVar)
773 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
774
775 /* $(source)_$(type)$(propf2) */
776 if (!pVar)
777 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
778
779 /*
780 * $(source)_$(propf2).$(bld_trg).$(bld_trg_arch)
781 */
782 if (!pVar)
783 {
784 psz = psz2;
785 ADD_STR(pszPropF2, cchPropF2);
786 psz3 = psz;
787 ADD_CH('.');
788 ADD_VAR(pBldTrg);
789 psz4 = psz;
790 ADD_CH('.');
791 ADD_VAR(pBldTrgArch);
792 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
793
794 /* $(source)_$(propf2).$(bld_trg) */
795 if (!pVar)
796 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
797
798 /* $(source)_$(propf2) */
799 if (!pVar)
800 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
801 }
802 }
803
804 /*
805 * $(target)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
806 */
807 if (!pVar)
808 {
809 psz = pszBuf;
810 ADD_VAR(pTarget);
811 ADD_CH('_');
812 psz2 = psz;
813 ADD_VAR(pType);
814 ADD_STR(pszPropF2, cchPropF2);
815 psz3 = psz;
816 ADD_CH('.');
817 ADD_VAR(pBldTrg);
818 psz4 = psz;
819 ADD_CH('.');
820 ADD_VAR(pBldTrgArch);
821 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
822
823 /* $(target)_$(type)$(propf2).$(bld_trg) */
824 if (!pVar)
825 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
826
827 /* $(target)_$(type)$(propf2) */
828 if (!pVar)
829 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
830
831 /* $(target)_$(propf2).$(bld_trg).$(bld_trg_arch) */
832 if (!pVar)
833 {
834 psz = psz2;
835 ADD_STR(pszPropF2, cchPropF2);
836 psz3 = psz;
837 ADD_CH('.');
838 ADD_VAR(pBldTrg);
839 psz4 = psz;
840 ADD_CH('.');
841 ADD_VAR(pBldTrgArch);
842 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
843 }
844
845 /* $(target)_$(propf2).$(bld_trg) */
846 if (!pVar)
847 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
848
849 /* $(target)_$(propf2) */
850 if (!pVar)
851 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
852 }
853
854 /*
855 * TOOL_$(tool)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
856 */
857 if (!pVar && pTool)
858 {
859 psz = pszBuf;
860 ADD_CSTR("TOOL_");
861 ADD_VAR(pTool);
862 ADD_CH('_');
863 psz2 = psz;
864 ADD_VAR(pType);
865 ADD_STR(pszPropF2, cchPropF2);
866 psz3 = psz;
867 ADD_CH('.');
868 ADD_VAR(pBldTrg);
869 psz4 = psz;
870 ADD_CH('.');
871 ADD_VAR(pBldTrgArch);
872 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
873
874 /* TOOL_$(tool)_$(type)$(propf2).$(bld_trg) */
875 if (!pVar)
876 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
877
878 /* TOOL_$(tool)_$(type)$(propf2) */
879 if (!pVar)
880 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
881
882 /* TOOL_$(tool)_$(propf2).$(bld_trg).$(bld_trg_arch) */
883 if (!pVar)
884 {
885 psz = psz2;
886 ADD_STR(pszPropF2, cchPropF2);
887 psz3 = psz;
888 ADD_CH('.');
889 ADD_VAR(pBldTrg);
890 psz4 = psz;
891 ADD_CH('.');
892 ADD_VAR(pBldTrgArch);
893 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
894
895 /* TOOL_$(tool)_$(propf2).$(bld_trg) */
896 if (!pVar)
897 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
898
899 /* TOOL_$(tool)_$(propf2) */
900 if (!pVar)
901 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
902 }
903 }
904
905 /*
906 * $(type)$(propf1).$(bld_trg).$(bld_trg_arch)
907 */
908 if (!pVar)
909 {
910 psz = pszBuf;
911 ADD_VAR(pType);
912 ADD_STR(pszPropF1, cchPropF1);
913 psz3 = psz;
914 ADD_CH('.');
915 ADD_VAR(pBldTrg);
916 psz4 = psz;
917 ADD_CH('.');
918 ADD_VAR(pBldTrgArch);
919 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
920
921 /* $(type)$(propf1).$(bld_trg) */
922 if (!pVar)
923 pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
924
925 /* $(type)$(propf1) */
926 if (!pVar)
927 pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
928
929 /*
930 * $(propf1).$(bld_trg).$(bld_trg_arch)
931 */
932 if (!pVar)
933 {
934 psz1 = pszBuf + pType->value_length;
935 pVar = kbuild_lookup_variable_n(psz1, psz - psz1);
936
937 /* $(propf1).$(bld_trg) */
938 if (!pVar)
939 pVar = kbuild_lookup_variable_n(psz1, psz4 - psz1);
940
941 /* $(propf1) */
942 if (!pVar)
943 pVar = kbuild_lookup_variable_n(pszPropF1, cchPropF1);
944 }
945 }
946 free(pszBuf);
947#undef ADD_VAR
948#undef ADD_STR
949#undef ADD_CSTR
950#undef ADD_CH
951
952 if (pVar)
953 {
954 /* strip it */
955 char *psz = pVar->value;
956 char *pszEnd = psz + pVar->value_length;
957 while (isblank((unsigned char)*psz))
958 psz++;
959 while (pszEnd > psz && isblank((unsigned char)pszEnd[-1]))
960 pszEnd--;
961 if (pszEnd > psz)
962 {
963 char chSaved = *pszEnd;
964 *pszEnd = '\0';
965 pVar = define_variable_vl(pszVarName, strlen(pszVarName), psz, pszEnd - psz,
966 1 /* duplicate */, o_local, 0 /* !recursive */);
967 *pszEnd = chSaved;
968 if (pVar)
969 return pVar;
970 }
971 }
972 return NULL;
973}
974
975
976/*
977_SOURCE_TOOL = $(strip $(firstword \
978 $($(target)_$(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
979 $($(target)_$(source)_$(type)TOOL.$(bld_trg)) \
980 $($(target)_$(source)_$(type)TOOL) \
981 $($(target)_$(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
982 $($(target)_$(source)_TOOL.$(bld_trg)) \
983 $($(target)_$(source)_TOOL) \
984 $($(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
985 $($(source)_$(type)TOOL.$(bld_trg)) \
986 $($(source)_$(type)TOOL) \
987 $($(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
988 $($(source)_TOOL.$(bld_trg)) \
989 $($(source)_TOOL) \
990 $($(target)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
991 $($(target)_$(type)TOOL.$(bld_trg)) \
992 $($(target)_$(type)TOOL) \
993 $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \
994 $($(target)_TOOL.$(bld_trg)) \
995 $($(target)_TOOL) \
996 $($(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
997 $($(type)TOOL.$(bld_trg)) \
998 $($(type)TOOL) \
999 $(TOOL.$(bld_trg).$(bld_trg_arch)) \
1000 $(TOOL.$(bld_trg)) \
1001 $(TOOL) ))
1002*/
1003static struct variable *
1004kbuild_get_source_tool(struct variable *pTarget, struct variable *pSource, struct variable *pType,
1005 struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
1006{
1007 struct variable *pVar = kbuild_first_prop(pTarget, pSource, NULL, pType, pBldTrg, pBldTrgArch,
1008 "TOOL", sizeof("TOOL") - 1,
1009 "TOOL", sizeof("TOOL") - 1,
1010 pszVarName);
1011 if (!pVar)
1012 fatal(NILF, _("no tool for source `%s' in target `%s'!"), pSource->value, pTarget->value);
1013 return pVar;
1014}
1015
1016
1017/* Implements _SOURCE_TOOL. */
1018char *
1019func_kbuild_source_tool(char *o, char **argv, const char *pszFuncName)
1020{
1021 struct variable *pVar = kbuild_get_source_tool(kbuild_get_variable_n(ST("target")),
1022 kbuild_get_variable_n(ST("source")),
1023 kbuild_get_variable_n(ST("type")),
1024 kbuild_get_variable_n(ST("bld_trg")),
1025 kbuild_get_variable_n(ST("bld_trg_arch")),
1026 argv[0]);
1027 if (pVar)
1028 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1029 (void)pszFuncName;
1030 return o;
1031
1032}
1033
1034
1035/* This has been extended a bit, it's now identical to _SOURCE_TOOL.
1036$(firstword \
1037 $($(target)_$(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
1038 $($(target)_$(source)_OBJSUFF.$(bld_trg))\
1039 $($(target)_$(source)_OBJSUFF)\
1040 $($(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
1041 $($(source)_OBJSUFF.$(bld_trg))\
1042 $($(source)_OBJSUFF)\
1043 $($(target)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
1044 $($(target)_OBJSUFF.$(bld_trg))\
1045 $($(target)_OBJSUFF)\
1046 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg).$(bld_trg_arch))\
1047 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg))\
1048 $(TOOL_$(tool)_$(type)OBJSUFF)\
1049 $(SUFF_OBJ))
1050*/
1051static struct variable *
1052kbuild_get_object_suffix(struct variable *pTarget, struct variable *pSource,
1053 struct variable *pTool, struct variable *pType,
1054 struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
1055{
1056 struct variable *pVar = kbuild_first_prop(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch,
1057 "SUFF_OBJ", sizeof("SUFF_OBJ") - 1,
1058 "OBJSUFF", sizeof("OBJSUFF") - 1,
1059 pszVarName);
1060 if (!pVar)
1061 fatal(NILF, _("no OBJSUFF attribute or SUFF_OBJ default for source `%s' in target `%s'!"), pSource->value, pTarget->value);
1062 return pVar;
1063}
1064
1065
1066/* */
1067char *
1068func_kbuild_object_suffix(char *o, char **argv, const char *pszFuncName)
1069{
1070 struct variable *pVar = kbuild_get_object_suffix(kbuild_get_variable_n(ST("target")),
1071 kbuild_get_variable_n(ST("source")),
1072 kbuild_get_variable_n(ST("tool")),
1073 kbuild_get_variable_n(ST("type")),
1074 kbuild_get_variable_n(ST("bld_trg")),
1075 kbuild_get_variable_n(ST("bld_trg_arch")),
1076 argv[0]);
1077 if (pVar)
1078 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1079 (void)pszFuncName;
1080 return o;
1081
1082}
1083
1084
1085/*
1086## Figure out where to put object files.
1087# @param $1 source file
1088# @param $2 normalized main target
1089# @remark There are two major hacks here:
1090# 1. Source files in the output directory are translated into a gen/ subdir.
1091# 2. Catch anyone specifying $(PATH_SUB_CURRENT)/sourcefile.c.
1092_OBJECT_BASE = $(PATH_TARGET)/$(2)/$(call no-root-slash,$(call no-drive,$(basename \
1093 $(patsubst $(PATH_ROOT)/%,%,$(patsubst $(PATH_SUB_CURRENT)/%,%,$(patsubst $(PATH_TARGET)/$(2)/%,gen/%,$(1)))))))
1094*/
1095static struct variable *
1096kbuild_get_object_base(struct variable *pTarget, struct variable *pSource, const char *pszVarName)
1097{
1098 struct variable *pPathTarget = kbuild_get_variable_n(ST("PATH_TARGET"));
1099 struct variable *pPathRoot = kbuild_get_variable_n(ST("PATH_ROOT"));
1100 struct variable *pPathSubCur = kbuild_get_variable_n(ST("PATH_SUB_CURRENT"));
1101 const char *pszSrcPrefix = NULL;
1102 size_t cchSrcPrefix = 0;
1103 size_t cchSrc = 0;
1104 const char *pszSrcEnd;
1105 char *pszSrc;
1106 char *pszResult;
1107 char *psz;
1108 char *pszDot;
1109 size_t cch;
1110
1111 /*
1112 * Strip the source filename of any uncessary leading path and root specs.
1113 */
1114 /* */
1115 if ( pSource->value_length > pPathTarget->value_length
1116 && !strncmp(pSource->value, pPathTarget->value, pPathTarget->value_length))
1117 {
1118 pszSrc = pSource->value + pPathTarget->value_length;
1119 pszSrcPrefix = "gen/";
1120 cchSrcPrefix = sizeof("gen/") - 1;
1121 if ( *pszSrc == '/'
1122 && !strncmp(pszSrc + 1, pTarget->value, pTarget->value_length)
1123 && ( pszSrc[pTarget->value_length + 1] == '/'
1124 || pszSrc[pTarget->value_length + 1] == '\0'))
1125 pszSrc += 1 + pTarget->value_length;
1126 }
1127 else if ( pSource->value_length > pPathRoot->value_length
1128 && !strncmp(pSource->value, pPathRoot->value, pPathRoot->value_length))
1129 {
1130 pszSrc = pSource->value + pPathRoot->value_length;
1131 if ( *pszSrc == '/'
1132 && !strncmp(pszSrc + 1, pPathSubCur->value, pPathSubCur->value_length)
1133 && ( pszSrc[pPathSubCur->value_length + 1] == '/'
1134 || pszSrc[pPathSubCur->value_length + 1] == '\0'))
1135 pszSrc += 1 + pPathSubCur->value_length;
1136 }
1137 else
1138 pszSrc = pSource->value;
1139
1140 /* skip root specification */
1141#ifdef HAVE_DOS_PATHS
1142 if (isalpha(pszSrc[0]) && pszSrc[1] == ':')
1143 pszSrc += 2;
1144#endif
1145 while (*pszSrc == '/'
1146#ifdef HAVE_DOS_PATHS
1147 || *pszSrc == '\\'
1148#endif
1149 )
1150 pszSrc++;
1151
1152 /* drop the source extension. */
1153 pszSrcEnd = pSource->value + pSource->value_length;
1154 for (;;)
1155 {
1156 pszSrcEnd--;
1157 if ( pszSrcEnd <= pszSrc
1158 || *pszSrcEnd == '/'
1159#ifdef HAVE_DOS_PATHS
1160 || *pszSrcEnd == '\\'
1161 || *pszSrcEnd == ':'
1162#endif
1163 )
1164 {
1165 pszSrcEnd = pSource->value + pSource->value_length;
1166 break;
1167 }
1168 if (*pszSrcEnd == '.')
1169 break;
1170 }
1171
1172 /*
1173 * Assemble the string on the heap and define the objbase variable
1174 * which we then return.
1175 */
1176 cchSrc = pszSrcEnd - pszSrc;
1177 cch = pPathTarget->value_length
1178 + 1 /* slash */
1179 + pTarget->value_length
1180 + 1 /* slash */
1181 + cchSrcPrefix
1182 + cchSrc
1183 + 1;
1184 psz = pszResult = xmalloc(cch);
1185
1186 memcpy(psz, pPathTarget->value, pPathTarget->value_length); psz += pPathTarget->value_length;
1187 *psz++ = '/';
1188 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1189 *psz++ = '/';
1190 if (pszSrcPrefix)
1191 {
1192 memcpy(psz, pszSrcPrefix, cchSrcPrefix);
1193 psz += cchSrcPrefix;
1194 }
1195 pszDot = psz;
1196 memcpy(psz, pszSrc, cchSrc); psz += cchSrc;
1197 *psz = '\0';
1198
1199 /* convert '..' path elements in the source to 'dt'. */
1200 while ((pszDot = memchr(pszDot, '.', psz - pszDot)) != NULL)
1201 {
1202 if ( pszDot[1] == '.'
1203 && ( pszDot == psz
1204 || pszDot[-1] == '/'
1205#ifdef HAVE_DOS_PATHS
1206 || pszDot[-1] == '\\'
1207 || pszDot[-1] == ':'
1208#endif
1209 )
1210 && ( !pszDot[2]
1211 || pszDot[2] == '/'
1212#ifdef HAVE_DOS_PATHS
1213 || pszDot[2] == '\\'
1214 || pszDot[2] == ':'
1215#endif
1216 )
1217 )
1218 {
1219 *pszDot++ = 'd';
1220 *pszDot++ = 't';
1221 }
1222 else
1223 pszDot++;
1224 }
1225
1226 /*
1227 * Define the variable in the current set and return it.
1228 */
1229 return define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cch - 1,
1230 0 /* use pszResult */, o_local, 0 /* !recursive */);
1231}
1232
1233
1234/* Implements _OBJECT_BASE. */
1235char *
1236func_kbuild_object_base(char *o, char **argv, const char *pszFuncName)
1237{
1238 struct variable *pVar = kbuild_get_object_base(kbuild_lookup_variable("target"),
1239 kbuild_lookup_variable("source"),
1240 argv[0]);
1241 if (pVar)
1242 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1243 (void)pszFuncName;
1244 return o;
1245
1246}
1247
1248
1249struct kbuild_sdks
1250{
1251 char *apsz[4];
1252 struct variable *pa;
1253 unsigned c;
1254 unsigned iGlobal;
1255 unsigned cGlobal;
1256 unsigned iTarget;
1257 unsigned cTarget;
1258 unsigned iSource;
1259 unsigned cSource;
1260 unsigned iTargetSource;
1261 unsigned cTargetSource;
1262 unsigned int cchMax;
1263};
1264
1265
1266/* Fills in the SDK struct (remember to free it). */
1267static void
1268kbuild_get_sdks(struct kbuild_sdks *pSdks, struct variable *pTarget, struct variable *pSource,
1269 struct variable *pBldType, struct variable *pBldTrg, struct variable *pBldTrgArch)
1270{
1271 unsigned i;
1272 unsigned j;
1273 size_t cchTmp, cch;
1274 char *pszTmp;
1275 unsigned cchCur;
1276 char *pszCur;
1277 const char *pszIterator;
1278
1279 /** @todo rewrite this to avoid sprintf and allocated_varaible_expand_2. */
1280
1281 /* basic init. */
1282 pSdks->cchMax = 0;
1283 pSdks->pa = NULL;
1284 pSdks->c = 0;
1285 i = 0;
1286
1287 /* determin required tmp variable name space. */
1288 cchTmp = sizeof("$(__SDKS) $(__SDKS.) $(__SDKS.) $(__SDKS.) $(__SDKS..)")
1289 + (pTarget->value_length + pSource->value_length) * 5
1290 + pBldType->value_length
1291 + pBldTrg->value_length
1292 + pBldTrgArch->value_length
1293 + pBldTrg->value_length + pBldTrgArch->value_length;
1294 pszTmp = alloca(cchTmp);
1295
1296 /* the global sdks. */
1297 pSdks->iGlobal = i;
1298 pSdks->cGlobal = 0;
1299 cch = sprintf(pszTmp, "$(SDKS) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s.%s)",
1300 pBldType->value,
1301 pBldTrg->value,
1302 pBldTrgArch->value,
1303 pBldTrg->value, pBldTrgArch->value);
1304 pszIterator = pSdks->apsz[0] = allocated_variable_expand_2(pszTmp, cch, NULL);
1305 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1306 pSdks->cGlobal++;
1307 i += pSdks->cGlobal;
1308
1309 /* the target sdks.*/
1310 pSdks->iTarget = i;
1311 pSdks->cTarget = 0;
1312 cch = sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
1313 pTarget->value,
1314 pTarget->value, pBldType->value,
1315 pTarget->value, pBldTrg->value,
1316 pTarget->value, pBldTrgArch->value,
1317 pTarget->value, pBldTrg->value, pBldTrgArch->value);
1318 pszIterator = pSdks->apsz[1] = allocated_variable_expand_2(pszTmp, cch, NULL);
1319 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1320 pSdks->cTarget++;
1321 i += pSdks->cTarget;
1322
1323 /* the source sdks.*/
1324 pSdks->iSource = i;
1325 pSdks->cSource = 0;
1326 cch = sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
1327 pSource->value,
1328 pSource->value, pBldType->value,
1329 pSource->value, pBldTrg->value,
1330 pSource->value, pBldTrgArch->value,
1331 pSource->value, pBldTrg->value, pBldTrgArch->value);
1332 pszIterator = pSdks->apsz[2] = allocated_variable_expand_2(pszTmp, cch, NULL);
1333 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1334 pSdks->cSource++;
1335 i += pSdks->cSource;
1336
1337 /* the target + source sdks. */
1338 pSdks->iTargetSource = i;
1339 pSdks->cTargetSource = 0;
1340 cch = sprintf(pszTmp, "$(%s_%s_SDKS) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s.%s)",
1341 pTarget->value, pSource->value,
1342 pTarget->value, pSource->value, pBldType->value,
1343 pTarget->value, pSource->value, pBldTrg->value,
1344 pTarget->value, pSource->value, pBldTrgArch->value,
1345 pTarget->value, pSource->value, pBldTrg->value, pBldTrgArch->value);
1346 assert(cch < cchTmp); (void)cch;
1347 pszIterator = pSdks->apsz[3] = allocated_variable_expand_2(pszTmp, cch, NULL);
1348 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1349 pSdks->cTargetSource++;
1350 i += pSdks->cTargetSource;
1351
1352 pSdks->c = i;
1353 if (!i)
1354 return;
1355
1356 /*
1357 * Allocate the variable array and create the variables.
1358 */
1359 pSdks->pa = (struct variable *)xmalloc(sizeof(pSdks->pa[0]) * i);
1360 memset(pSdks->pa, 0, sizeof(pSdks->pa[0]) * i);
1361 for (i = j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
1362 {
1363 pszIterator = pSdks->apsz[j];
1364 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
1365 {
1366 pSdks->pa[i].value = pszCur;
1367 pSdks->pa[i].value_length = cchCur;
1368 i++;
1369 }
1370 }
1371 assert(i == pSdks->c);
1372
1373 /* terminate them (find_next_token won't work if we terminate them in the previous loop). */
1374 while (i-- > 0)
1375 {
1376 pSdks->pa[i].value[pSdks->pa[i].value_length] = '\0';
1377
1378 /* calc the max variable length too. */
1379 if (pSdks->cchMax < (unsigned int)pSdks->pa[i].value_length)
1380 pSdks->cchMax = pSdks->pa[i].value_length;
1381 }
1382}
1383
1384
1385/* releases resources allocated in the kbuild_get_sdks. */
1386static void
1387kbuild_put_sdks(struct kbuild_sdks *pSdks)
1388{
1389 unsigned j;
1390 for (j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
1391 free(pSdks->apsz[j]);
1392 free(pSdks->pa);
1393}
1394
1395
1396/* this kind of stuff:
1397
1398defs := $(kb-src-exp defs)
1399 $(TOOL_$(tool)_DEFS)\
1400 $(TOOL_$(tool)_DEFS.$(bld_type))\
1401 $(TOOL_$(tool)_DEFS.$(bld_trg))\
1402 $(TOOL_$(tool)_DEFS.$(bld_trg_arch))\
1403 $(TOOL_$(tool)_DEFS.$(bld_trg).$(bld_trg_arch))\
1404 $(TOOL_$(tool)_DEFS.$(bld_trg_cpu))\
1405 $(TOOL_$(tool)_$(type)DEFS)\
1406 $(TOOL_$(tool)_$(type)DEFS.$(bld_type))\
1407 $(foreach sdk, $(SDKS.$(bld_trg)) \
1408 $(SDKS.$(bld_trg).$(bld_trg_arch)) \
1409 $(SDKS.$(bld_type)) \
1410 $(SDKS),\
1411 $(SDK_$(sdk)_DEFS)\
1412 $(SDK_$(sdk)_DEFS.$(bld_type))\
1413 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1414 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1415 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1416 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1417 $(SDK_$(sdk)_$(type)DEFS)\
1418 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1419 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1420 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1421 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1422 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1423 $(DEFS)\
1424 $(DEFS.$(bld_type))\
1425 $(DEFS.$(bld_trg))\
1426 $(DEFS.$(bld_trg_arch))\
1427 $(DEFS.$(bld_trg).$(bld_trg_arch))\
1428 $(DEFS.$(bld_trg_cpu))\
1429 $($(type)DEFS)\
1430 $($(type)DEFS.$(bld_type))\
1431 $($(type)DEFS.$(bld_trg))\
1432 $($(type)DEFS.$(bld_trg_arch))\
1433 $($(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1434 $($(type)DEFS.$(bld_trg_cpu))\
1435 $(foreach sdk, $($(target)_SDKS.$(bld_trg)) \
1436 $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1437 $($(target)_SDKS.$(bld_type)) \
1438 $($(target)_SDKS),\
1439 $(SDK_$(sdk)_DEFS)\
1440 $(SDK_$(sdk)_DEFS.$(bld_type))\
1441 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1442 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1443 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1444 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1445 $(SDK_$(sdk)_$(type)DEFS)\
1446 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1447 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1448 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1449 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1450 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1451 $($(target)_DEFS)\
1452 $($(target)_DEFS.$(bld_type))\
1453 $($(target)_DEFS.$(bld_trg))\
1454 $($(target)_DEFS.$(bld_trg_arch))\
1455 $($(target)_DEFS.$(bld_trg).$(bld_trg_arch))\
1456 $($(target)_DEFS.$(bld_trg_cpu))\
1457 $($(target)_$(type)DEFS)\
1458 $($(target)_$(type)DEFS.$(bld_type))\
1459 $($(target)_$(type)DEFS.$(bld_trg))\
1460 $($(target)_$(type)DEFS.$(bld_trg_arch))\
1461 $($(target)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1462 $($(target)_$(type)DEFS.$(bld_trg_cpu))\
1463 $(foreach sdk, $($(source)_SDKS.$(bld_trg)) \
1464 $($(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1465 $($(source)_SDKS.$(bld_type)) \
1466 $($(source)_SDKS),\
1467 $(SDK_$(sdk)_DEFS)\
1468 $(SDK_$(sdk)_DEFS.$(bld_type))\
1469 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1470 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1471 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1472 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1473 $(SDK_$(sdk)_$(type)DEFS)\
1474 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1475 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1476 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1477 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1478 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1479 $($(source)_DEFS)\
1480 $($(source)_DEFS.$(bld_type))\
1481 $($(source)_DEFS.$(bld_trg))\
1482 $($(source)_DEFS.$(bld_trg_arch))\
1483 $($(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
1484 $($(source)_DEFS.$(bld_trg_cpu))\
1485 $($(source)_$(type)DEFS)\
1486 $($(source)_$(type)DEFS.$(bld_type))\
1487 $($(source)_$(type)DEFS.$(bld_trg))\
1488 $($(source)_$(type)DEFS.$(bld_trg_arch))\
1489 $($(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1490 $($(source)_$(type)DEFS.$(bld_trg_cpu))\
1491 $(foreach sdk, $($(target)_$(source)_SDKS.$(bld_trg)) \
1492 $($(target)_$(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1493 $($(target)_$(source)_SDKS.$(bld_type)) \
1494 $($(target)_$(source)_SDKS),\
1495 $(SDK_$(sdk)_DEFS)\
1496 $(SDK_$(sdk)_DEFS.$(bld_type))\
1497 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1498 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1499 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1500 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1501 $(SDK_$(sdk)_$(type)DEFS)\
1502 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1503 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1504 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1505 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1506 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1507 $($(target)_$(source)_DEFS)\
1508 $($(target)_$(source)_DEFS.$(bld_type))\
1509 $($(target)_$(source)_DEFS.$(bld_trg))\
1510 $($(target)_$(source)_DEFS.$(bld_trg_arch))\
1511 $($(target)_$(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
1512 $($(target)_$(source)_DEFS.$(bld_trg_cpu))\
1513 $($(target)_$(source)_$(type)DEFS)\
1514 $($(target)_$(source)_$(type)DEFS.$(bld_type))\
1515 $($(target)_$(source)_$(type)DEFS.$(bld_trg))\
1516 $($(target)_$(source)_$(type)DEFS.$(bld_trg_arch))\
1517 $($(target)_$(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1518 $($(target)_$(source)_$(type)DEFS.$(bld_trg_cpu))
1519*/
1520static struct variable *
1521kbuild_collect_source_prop(struct variable *pTarget, struct variable *pSource,
1522 struct variable *pTool, struct kbuild_sdks *pSdks,
1523 struct variable *pType, struct variable *pBldType,
1524 struct variable *pBldTrg, struct variable *pBldTrgArch, struct variable *pBldTrgCpu,
1525 struct variable *pDefPath,
1526 const char *pszProp, size_t cchProp,
1527 const char *pszVarName, size_t cchVarName,
1528 int iDirection)
1529{
1530 struct variable *pVar;
1531 unsigned iSdk, iSdkEnd;
1532 int cVars, iVar;
1533 size_t cchTotal, cchBuf;
1534 char *pszResult, *pszBuf, *psz, *psz2, *psz3;
1535 struct
1536 {
1537 struct variable *pVar;
1538 unsigned int cchExp;
1539 char *pszExp;
1540 } *paVars;
1541
1542 assert(iDirection == 1 || iDirection == -1);
1543
1544 /*
1545 * Calc and allocate a too big name buffer.
1546 */
1547 cchBuf = cchProp + 1
1548 + pTarget->value_length + 1
1549 + pSource->value_length + 1
1550 + pSdks->cchMax + 1
1551 + (pTool ? pTool->value_length + 1 : 0)
1552 + pType->value_length + 1
1553 + pBldTrg->value_length + 1
1554 + pBldTrgArch->value_length + 1
1555 + pBldTrgCpu->value_length + 1
1556 + pBldType->value_length + 1;
1557 pszBuf = xmalloc(cchBuf);
1558
1559 /*
1560 * Get the variables.
1561 *
1562 * The compiler will get a heart attack when it sees this code ... ;-)
1563 */
1564 cVars = 12 * (pSdks->c + 5);
1565 paVars = alloca(cVars * sizeof(paVars[0]));
1566
1567 iVar = 0;
1568 cchTotal = 0;
1569
1570#define ADD_VAR(pVar) do { my_memcpy(psz, (pVar)->value, (pVar)->value_length); psz += (pVar)->value_length; } while (0)
1571#define ADD_STR(pszStr, cchStr) do { my_memcpy(psz, (pszStr), (cchStr)); psz += (cchStr); } while (0)
1572#define ADD_CSTR(pszStr) do { my_memcpy(psz, pszStr, sizeof(pszStr) - 1); psz += sizeof(pszStr) - 1; } while (0)
1573#define ADD_CH(ch) do { *psz++ = (ch); } while (0)
1574#define DO_VAR_LOOKUP() \
1575 do { \
1576 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); \
1577 if (pVar) \
1578 { \
1579 paVars[iVar].pVar = pVar; \
1580 if ( !pVar->recursive \
1581 || !memchr(pVar->value, '$', pVar->value_length)) \
1582 { \
1583 paVars[iVar].pszExp = pVar->value; \
1584 paVars[iVar].cchExp = pVar->value_length; \
1585 if (pDefPath && paVars[iVar].cchExp) \
1586 kbuild_apply_defpath(pDefPath, &paVars[iVar].pszExp, &paVars[iVar].cchExp, NULL, 0); \
1587 if (paVars[iVar].cchExp) \
1588 { \
1589 cchTotal += paVars[iVar].cchExp + 1; \
1590 iVar++; \
1591 } \
1592 } \
1593 else \
1594 { \
1595 paVars[iVar].pszExp = allocated_variable_expand_2(pVar->value, pVar->value_length, &paVars[iVar].cchExp); \
1596 if (pDefPath && paVars[iVar].cchExp) \
1597 kbuild_apply_defpath(pDefPath, &paVars[iVar].pszExp, &paVars[iVar].cchExp, NULL, 1); \
1598 if (paVars[iVar].cchExp) \
1599 { \
1600 cchTotal += paVars[iVar].cchExp + 1; \
1601 iVar++; \
1602 } \
1603 else \
1604 free(paVars[iVar].pszExp); \
1605 } \
1606 } \
1607 } while (0)
1608#define DO_SINGLE_PSZ3_VARIATION() \
1609 do { \
1610 DO_VAR_LOOKUP(); \
1611 \
1612 ADD_CH('.'); \
1613 psz3 = psz; \
1614 ADD_VAR(pBldType); \
1615 DO_VAR_LOOKUP(); \
1616 \
1617 psz = psz3; \
1618 ADD_VAR(pBldTrg); \
1619 DO_VAR_LOOKUP(); \
1620 \
1621 psz = psz3; \
1622 ADD_VAR(pBldTrgArch); \
1623 DO_VAR_LOOKUP(); \
1624 \
1625 psz = psz3; \
1626 ADD_VAR(pBldTrg); \
1627 ADD_CH('.'); \
1628 ADD_VAR(pBldTrgArch); \
1629 DO_VAR_LOOKUP(); \
1630 \
1631 psz = psz3; \
1632 ADD_VAR(pBldTrgCpu); \
1633 DO_VAR_LOOKUP(); \
1634 } while (0)
1635
1636#define DO_DOUBLE_PSZ2_VARIATION() \
1637 do { \
1638 psz2 = psz; \
1639 ADD_STR(pszProp, cchProp); \
1640 DO_SINGLE_PSZ3_VARIATION(); \
1641 \
1642 /* add prop before type */ \
1643 psz = psz2; \
1644 ADD_VAR(pType); \
1645 ADD_STR(pszProp, cchProp); \
1646 DO_SINGLE_PSZ3_VARIATION(); \
1647 } while (0)
1648
1649 /* the tool (lowest priority). */
1650 psz = pszBuf;
1651 ADD_CSTR("TOOL_");
1652 ADD_VAR(pTool);
1653 ADD_CH('_');
1654 DO_DOUBLE_PSZ2_VARIATION();
1655
1656
1657 /* the global sdks. */
1658 iSdkEnd = iDirection == 1 ? pSdks->iGlobal + pSdks->cGlobal : pSdks->iGlobal - 1;
1659 for (iSdk = iDirection == 1 ? pSdks->iGlobal : pSdks->iGlobal + pSdks->cGlobal - 1;
1660 iSdk != iSdkEnd;
1661 iSdk += iDirection)
1662 {
1663 struct variable *pSdk = &pSdks->pa[iSdk];
1664 psz = pszBuf;
1665 ADD_CSTR("SDK_");
1666 ADD_VAR(pSdk);
1667 ADD_CH('_');
1668 DO_DOUBLE_PSZ2_VARIATION();
1669 }
1670
1671 /* the globals. */
1672 psz = pszBuf;
1673 DO_DOUBLE_PSZ2_VARIATION();
1674
1675
1676 /* the target sdks. */
1677 iSdkEnd = iDirection == 1 ? pSdks->iTarget + pSdks->cTarget : pSdks->iTarget - 1;
1678 for (iSdk = iDirection == 1 ? pSdks->iTarget : pSdks->iTarget + pSdks->cTarget - 1;
1679 iSdk != iSdkEnd;
1680 iSdk += iDirection)
1681 {
1682 struct variable *pSdk = &pSdks->pa[iSdk];
1683 psz = pszBuf;
1684 ADD_CSTR("SDK_");
1685 ADD_VAR(pSdk);
1686 ADD_CH('_');
1687 DO_DOUBLE_PSZ2_VARIATION();
1688 }
1689
1690 /* the target. */
1691 psz = pszBuf;
1692 ADD_VAR(pTarget);
1693 ADD_CH('_');
1694 DO_DOUBLE_PSZ2_VARIATION();
1695
1696 /* the source sdks. */
1697 iSdkEnd = iDirection == 1 ? pSdks->iSource + pSdks->cSource : pSdks->iSource - 1;
1698 for (iSdk = iDirection == 1 ? pSdks->iSource : pSdks->iSource + pSdks->cSource - 1;
1699 iSdk != iSdkEnd;
1700 iSdk += iDirection)
1701 {
1702 struct variable *pSdk = &pSdks->pa[iSdk];
1703 psz = pszBuf;
1704 ADD_CSTR("SDK_");
1705 ADD_VAR(pSdk);
1706 ADD_CH('_');
1707 DO_DOUBLE_PSZ2_VARIATION();
1708 }
1709
1710 /* the source. */
1711 psz = pszBuf;
1712 ADD_VAR(pSource);
1713 ADD_CH('_');
1714 DO_DOUBLE_PSZ2_VARIATION();
1715
1716 /* the target + source sdks. */
1717 iSdkEnd = iDirection == 1 ? pSdks->iTargetSource + pSdks->cTargetSource : pSdks->iTargetSource - 1;
1718 for (iSdk = iDirection == 1 ? pSdks->iTargetSource : pSdks->iTargetSource + pSdks->cTargetSource - 1;
1719 iSdk != iSdkEnd;
1720 iSdk += iDirection)
1721 {
1722 struct variable *pSdk = &pSdks->pa[iSdk];
1723 psz = pszBuf;
1724 ADD_CSTR("SDK_");
1725 ADD_VAR(pSdk);
1726 ADD_CH('_');
1727 DO_DOUBLE_PSZ2_VARIATION();
1728 }
1729
1730 /* the target + source. */
1731 psz = pszBuf;
1732 ADD_VAR(pTarget);
1733 ADD_CH('_');
1734 ADD_VAR(pSource);
1735 ADD_CH('_');
1736 DO_DOUBLE_PSZ2_VARIATION();
1737
1738 free(pszBuf);
1739
1740 assert(iVar <= cVars);
1741 cVars = iVar;
1742
1743 /*
1744 * Construct the result value.
1745 */
1746 if (!cVars || !cchTotal)
1747 pVar = define_variable_vl(pszVarName, cchVarName, "", 0,
1748 1 /* duplicate value */ , o_local, 0 /* !recursive */);
1749 else
1750 {
1751 psz = pszResult = xmalloc(cchTotal + 1);
1752 if (iDirection == 1)
1753 {
1754 for (iVar = 0; iVar < cVars; iVar++)
1755 {
1756 my_memcpy(psz, paVars[iVar].pszExp, paVars[iVar].cchExp);
1757 psz += paVars[iVar].cchExp;
1758 *psz++ = ' ';
1759 if (paVars[iVar].pszExp != paVars[iVar].pVar->value)
1760 free(paVars[iVar].pszExp);
1761 }
1762 }
1763 else
1764 {
1765 iVar = cVars;
1766 while (iVar-- > 0)
1767 {
1768 my_memcpy(psz, paVars[iVar].pszExp, paVars[iVar].cchExp);
1769 psz += paVars[iVar].cchExp;
1770 *psz++ = ' ';
1771 if (paVars[iVar].pszExp != paVars[iVar].pVar->value)
1772 free(paVars[iVar].pszExp);
1773 }
1774
1775 }
1776 assert(psz != pszResult);
1777 assert(cchTotal == (size_t)(psz - pszResult));
1778 psz[-1] = '\0';
1779 cchTotal--;
1780
1781 pVar = define_variable_vl(pszVarName, cchVarName, pszResult, cchTotal,
1782 0 /* take pszResult */ , o_local, 0 /* !recursive */);
1783 }
1784
1785 return pVar;
1786
1787#undef ADD_VAR
1788#undef ADD_STR
1789#undef ADD_CSTR
1790#undef ADD_CH
1791#undef DO_VAR_LOOKUP
1792#undef DO_DOUBLE_PSZ2_VARIATION
1793#undef DO_SINGLE_PSZ3_VARIATION
1794}
1795
1796
1797/* get a source property. */
1798char *
1799func_kbuild_source_prop(char *o, char **argv, const char *pszFuncName)
1800{
1801 struct variable *pTarget = kbuild_get_variable_n(ST("target"));
1802 struct variable *pSource = kbuild_get_variable_n(ST("source"));
1803 struct variable *pDefPath = NULL;
1804 struct variable *pType = kbuild_get_variable_n(ST("type"));
1805 struct variable *pTool = kbuild_get_variable_n(ST("tool"));
1806 struct variable *pBldType = kbuild_get_variable_n(ST("bld_type"));
1807 struct variable *pBldTrg = kbuild_get_variable_n(ST("bld_trg"));
1808 struct variable *pBldTrgArch = kbuild_get_variable_n(ST("bld_trg_arch"));
1809 struct variable *pBldTrgCpu = kbuild_get_variable_n(ST("bld_trg_cpu"));
1810 struct variable *pVar;
1811 struct kbuild_sdks Sdks;
1812 int iDirection;
1813 if (!strcmp(argv[2], "left-to-right"))
1814 iDirection = 1;
1815 else if (!strcmp(argv[2], "right-to-left"))
1816 iDirection = -1;
1817 else
1818 fatal(NILF, _("incorrect direction argument `%s'!"), argv[2]);
1819 if (argv[3])
1820 {
1821 const char *psz = argv[3];
1822 while (isspace(*psz))
1823 psz++;
1824 if (*psz)
1825 pDefPath = kbuild_get_variable_n(ST("defpath"));
1826 }
1827
1828 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
1829
1830 pVar = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType,
1831 pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
1832 pDefPath,
1833 argv[0], strlen(argv[0]),
1834 argv[1], strlen(argv[1]),
1835 iDirection);
1836 if (pVar)
1837 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1838
1839 kbuild_put_sdks(&Sdks);
1840 (void)pszFuncName;
1841 return o;
1842}
1843
1844
1845/*
1846dep := $(obj)$(SUFF_DEP)
1847obj := $(outbase)$(objsuff)
1848dirdep := $(call DIRDEP,$(dir $(outbase)))
1849PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1850*/
1851static struct variable *
1852kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(struct variable *pTarget, struct variable *pSource,
1853 struct variable *pOutBase, struct variable *pObjSuff,
1854 const char *pszVarName, struct variable **ppDep,
1855 struct variable **ppDirDep)
1856{
1857 struct variable *pDepSuff = kbuild_get_variable_n(ST("SUFF_DEP"));
1858 struct variable *pObj;
1859 size_t cch = pOutBase->value_length + pObjSuff->value_length + pDepSuff->value_length + 1;
1860 char *pszResult = alloca(cch);
1861 char *pszName, *psz;
1862
1863 /*
1864 * dep.
1865 */
1866 psz = pszResult;
1867 memcpy(psz, pOutBase->value, pOutBase->value_length); psz += pOutBase->value_length;
1868 memcpy(psz, pObjSuff->value, pObjSuff->value_length); psz += pObjSuff->value_length;
1869 memcpy(psz, pDepSuff->value, pDepSuff->value_length + 1);
1870 *ppDep = define_variable_vl("dep", 3, pszResult, cch - 1, 1 /*dup*/, o_local, 0 /* !recursive */);
1871
1872 /*
1873 * obj
1874 */
1875 *psz = '\0';
1876 pObj = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, psz - pszResult,
1877 1/* dup */, o_local, 0 /* !recursive */);
1878
1879 /*
1880 * PATH_$(target)_$(source) - this is global!
1881 */
1882 /* calc variable name. */
1883 cch = sizeof("PATH_")-1 + pTarget->value_length + sizeof("_")-1 + pSource->value_length;
1884 psz = pszName = alloca(cch + 1);
1885 memcpy(psz, "PATH_", sizeof("PATH_") - 1); psz += sizeof("PATH_") - 1;
1886 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1887 *psz++ = '_';
1888 memcpy(psz, pSource->value, pSource->value_length + 1);
1889
1890 /* strip off the filename. */
1891 psz = pszResult + pOutBase->value_length;
1892 for (;;)
1893 {
1894 psz--;
1895 if (psz <= pszResult)
1896 fatal(NULL, "whut!?! no path? result=`%s'", pszResult);
1897#ifdef HAVE_DOS_PATHS
1898 if (*psz == ':')
1899 {
1900 psz++;
1901 break;
1902 }
1903#endif
1904 if ( *psz == '/'
1905#ifdef HAVE_DOS_PATHS
1906 || *psz == '\\'
1907#endif
1908 )
1909 {
1910 while ( psz - 1 > pszResult
1911 && psz[-1] == '/'
1912#ifdef HAVE_DOS_PATHS
1913 || psz[-1] == '\\'
1914#endif
1915 )
1916 psz--;
1917#ifdef HAVE_DOS_PATHS
1918 if (psz == pszResult + 2 && pszResult[1] == ':')
1919 psz++;
1920#endif
1921 break;
1922 }
1923 }
1924 *psz = '\0';
1925
1926 /* set global variable */
1927 define_variable_vl_global(pszName, cch, pszResult, psz - pszResult, 1/*dup*/, o_file, 0 /* !recursive */, NILF);
1928
1929 /*
1930 * dirdep
1931 */
1932 if ( psz[-1] != '/'
1933#ifdef HAVE_DOS_PATHS
1934 && psz[-1] != '\\'
1935 && psz[-1] != ':'
1936#endif
1937 )
1938 {
1939 *psz++ = '/';
1940 *psz = '\0';
1941 }
1942 *ppDirDep = define_variable_vl("dirdep", 6, pszResult, psz - pszResult, 1/*dup*/, o_local, 0 /* !recursive */);
1943
1944 return pObj;
1945}
1946
1947
1948/* setup the base variables for def_target_source_c_cpp_asm_new:
1949
1950X := $(kb-src-tool tool)
1951x := $(kb-obj-base outbase)
1952x := $(kb-obj-suff objsuff)
1953obj := $(outbase)$(objsuff)
1954PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1955
1956x := $(kb-src-prop DEFS,defs,left-to-right)
1957x := $(kb-src-prop INCS,incs,right-to-left)
1958x := $(kb-src-prop FLAGS,flags,right-to-left)
1959
1960x := $(kb-src-prop DEPS,deps,left-to-right)
1961dirdep := $(call DIRDEP,$(dir $(outbase)))
1962dep := $(obj)$(SUFF_DEP)
1963*/
1964char *
1965func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
1966{
1967 static int s_fNoCompileCmdsDepsDefined = -1;
1968 struct variable *pTarget = kbuild_get_variable_n(ST("target"));
1969 struct variable *pSource = kbuild_get_variable_n(ST("source"));
1970 struct variable *pDefPath = kbuild_get_variable_n(ST("defpath"));
1971 struct variable *pType = kbuild_get_variable_n(ST("type"));
1972 struct variable *pBldType = kbuild_get_variable_n(ST("bld_type"));
1973 struct variable *pBldTrg = kbuild_get_variable_n(ST("bld_trg"));
1974 struct variable *pBldTrgArch= kbuild_get_variable_n(ST("bld_trg_arch"));
1975 struct variable *pBldTrgCpu = kbuild_get_variable_n(ST("bld_trg_cpu"));
1976 struct variable *pTool = kbuild_get_source_tool(pTarget, pSource, pType, pBldTrg, pBldTrgArch, "tool");
1977 struct variable *pOutBase = kbuild_get_object_base(pTarget, pSource, "outbase");
1978 struct variable *pObjSuff = kbuild_get_object_suffix(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch, "objsuff");
1979 struct variable *pDefs, *pIncs, *pFlags, *pDeps, *pOrderDeps, *pDirDep, *pDep, *pVar, *pOutput, *pOutputMaybe;
1980 struct variable *pObj = kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(pTarget, pSource, pOutBase, pObjSuff, "obj", &pDep, &pDirDep);
1981 char *pszDstVar, *pszDst, *pszSrcVar, *pszSrc, *pszVal, *psz;
1982 char *pszSavedVarBuf;
1983 unsigned cchSavedVarBuf;
1984 size_t cch;
1985 struct kbuild_sdks Sdks;
1986 int iVer;
1987
1988 /*
1989 * argv[0] is the function version. Prior to r1792 (early 0.1.5) this
1990 * was undefined and footer.kmk always passed an empty string.
1991 *
1992 * Version 2, as implemented in r1797, will make use of the async
1993 * includedep queue feature. This means the files will be read by one or
1994 * more background threads, leaving the eval'ing to be done later on by
1995 * the main thread (in snap_deps).
1996 */
1997 if (!argv[0][0])
1998 iVer = 0;
1999 else
2000 switch (argv[0][0] | (argv[0][1] << 8))
2001 {
2002 case '2': iVer = 2; break;
2003 case '3': iVer = 3; break;
2004 case '4': iVer = 4; break;
2005 case '5': iVer = 5; break;
2006 case '6': iVer = 6; break;
2007 case '7': iVer = 7; break;
2008 case '8': iVer = 8; break;
2009 case '9': iVer = 9; break;
2010 case '0': iVer = 0; break;
2011 case '1': iVer = 1; break;
2012 default:
2013 iVer = 0;
2014 psz = argv[0];
2015 while (isblank((unsigned char)*psz))
2016 psz++;
2017 if (*psz)
2018 iVer = atoi(psz);
2019 break;
2020 }
2021
2022 /*
2023 * Gather properties.
2024 */
2025 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
2026
2027 if (pDefPath && !pDefPath->value_length)
2028 pDefPath = NULL;
2029 pDefs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
2030 ST("DEFS"), ST("defs"), 1/* left-to-right */);
2031 pIncs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
2032 ST("INCS"), ST("incs"), -1/* right-to-left */);
2033 pFlags = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
2034 ST("FLAGS"), ST("flags"), 1/* left-to-right */);
2035 pDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
2036 ST("DEPS"), ST("deps"), 1/* left-to-right */);
2037 pOrderDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
2038 ST("ORDERDEPS"), ST("orderdeps"), 1/* left-to-right */);
2039
2040 /*
2041 * If we've got a default path, we must expand the source now.
2042 * If we do this too early, "<source>_property = stuff" won't work becuase
2043 * our 'source' value isn't what the user expects.
2044 */
2045 if (pDefPath)
2046 kbuild_apply_defpath(pDefPath, &pSource->value, (unsigned int *)&pSource->value_length, &pSource->value_alloc_len, 1 /* can free */);
2047
2048 /*
2049 # dependencies
2050 ifndef NO_COMPILE_CMDS_DEPS
2051 _DEPFILES_INCLUDED += $(dep)
2052 $(if $(wildcard $(dep)),$(eval include $(dep)))
2053 endif
2054 */
2055 if (s_fNoCompileCmdsDepsDefined == -1)
2056 s_fNoCompileCmdsDepsDefined = kbuild_lookup_variable_n(ST("NO_COMPILE_CMDS_DEPS")) != NULL;
2057 if (!s_fNoCompileCmdsDepsDefined)
2058 {
2059 do_variable_definition_2(NILF, "_DEPFILES_INCLUDED", pDep->value, pDep->value_length,
2060 !pDep->recursive, 0, o_file, f_append, 0 /* !target_var */);
2061 eval_include_dep(pDep->value, NILF, iVer >= 2 ? incdep_queue : incdep_read_it);
2062 }
2063
2064 /*
2065 # call the tool
2066 $(target)_$(source)_CMDS_ := $(TOOL_$(tool)_COMPILE_$(type)_CMDS)
2067 $(target)_$(source)_OUTPUT_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT)
2068 $(target)_$(source)_OUTPUT_MAYBE_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT_MAYBE)
2069 $(target)_$(source)_DEPEND_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPEND) $(deps) $(source)
2070 $(target)_$(source)_DEPORD_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPORD) $(dirdep)
2071 */
2072 cch = sizeof("TOOL_") + pTool->value_length + sizeof("_COMPILE_") + pType->value_length + sizeof("_OUTPUT_MAYBE");
2073 psz = pszSrcVar = alloca(cch);
2074 memcpy(psz, "TOOL_", sizeof("TOOL_") - 1); psz += sizeof("TOOL_") - 1;
2075 memcpy(psz, pTool->value, pTool->value_length); psz += pTool->value_length;
2076 memcpy(psz, "_COMPILE_", sizeof("_COMPILE_") - 1); psz += sizeof("_COMPILE_") - 1;
2077 memcpy(psz, pType->value, pType->value_length); psz += pType->value_length;
2078 pszSrc = psz;
2079
2080 cch = pTarget->value_length + 1 + pSource->value_length + sizeof("_OUTPUT_MAYBE_");
2081 psz = pszDstVar = alloca(cch);
2082 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
2083 *psz++ = '_';
2084 memcpy(psz, pSource->value, pSource->value_length); psz += pSource->value_length;
2085 pszDst = psz;
2086
2087 memcpy(pszSrc, "_CMDS", sizeof("_CMDS"));
2088 memcpy(pszDst, "_CMDS_", sizeof("_CMDS_"));
2089 pVar = kbuild_get_recursive_variable(pszSrcVar);
2090 do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length,
2091 !pVar->recursive, 0, o_file, f_simple, 0 /* !target_var */);
2092
2093 memcpy(pszSrc, "_OUTPUT", sizeof("_OUTPUT"));
2094 memcpy(pszDst, "_OUTPUT_", sizeof("_OUTPUT_"));
2095 pVar = kbuild_get_recursive_variable(pszSrcVar);
2096 pOutput = do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length,
2097 !pVar->recursive, 0, o_file, f_simple, 0 /* !target_var */);
2098
2099 memcpy(pszSrc, "_OUTPUT_MAYBE", sizeof("_OUTPUT_MAYBE"));
2100 memcpy(pszDst, "_OUTPUT_MAYBE_", sizeof("_OUTPUT_MAYBE_"));
2101 pVar = kbuild_query_recursive_variable(pszSrcVar);
2102 if (pVar)
2103 pOutputMaybe = do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length,
2104 !pVar->recursive, 0, o_file, f_simple, 0 /* !target_var */);
2105 else
2106 pOutputMaybe = do_variable_definition_2(NILF, pszDstVar, "", 0, 1, 0, o_file, f_simple, 0 /* !target_var */);
2107
2108 memcpy(pszSrc, "_DEPEND", sizeof("_DEPEND"));
2109 memcpy(pszDst, "_DEPEND_", sizeof("_DEPEND_"));
2110 pVar = kbuild_get_recursive_variable(pszSrcVar);
2111 psz = pszVal = xmalloc(pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length + 1);
2112 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
2113 *psz++ = ' ';
2114 memcpy(psz, pDeps->value, pDeps->value_length); psz += pDeps->value_length;
2115 *psz++ = ' ';
2116 memcpy(psz, pSource->value, pSource->value_length + 1);
2117 do_variable_definition_2(NILF, pszDstVar, pszVal, pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length,
2118 !pVar->recursive && !pDeps->recursive && !pSource->recursive,
2119 pszVal, o_file, f_simple, 0 /* !target_var */);
2120
2121 memcpy(pszSrc, "_DEPORD", sizeof("_DEPORD"));
2122 memcpy(pszDst, "_DEPORD_", sizeof("_DEPORD_"));
2123 pVar = kbuild_get_recursive_variable(pszSrcVar);
2124 psz = pszVal = xmalloc(pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length + 1);
2125 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
2126 *psz++ = ' ';
2127 memcpy(psz, pDirDep->value, pDirDep->value_length); psz += pDirDep->value_length;
2128 *psz++ = ' ';
2129 memcpy(psz, pOrderDeps->value, pOrderDeps->value_length + 1);
2130 do_variable_definition_2(NILF, pszDstVar, pszVal,
2131 pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length,
2132 !pVar->recursive && !pDirDep->recursive && !pOrderDeps->recursive,
2133 pszVal, o_file, f_simple, 0 /* !target_var */);
2134
2135 /*
2136 _OUT_FILES += $($(target)_$(source)_OUTPUT_) $($(target)_$(source)_OUTPUT_MAYBE_)
2137 */
2138 /** @todo use append? */
2139 pVar = kbuild_get_variable_n(ST("_OUT_FILES"));
2140 psz = pszVal = xmalloc(pVar->value_length + 1 + pOutput->value_length + 1 + pOutputMaybe->value_length + 1);
2141 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
2142 *psz++ = ' ';
2143 memcpy(psz, pOutput->value, pOutput->value_length); psz += pOutput->value_length;
2144 *psz++ = ' ';
2145 memcpy(psz, pOutputMaybe->value, pOutputMaybe->value_length + 1);
2146 do_variable_definition_2(NILF, "_OUT_FILES", pszVal,
2147 pVar->value_length + 1 + pOutput->value_length + 1 + pOutputMaybe->value_length,
2148 !pVar->recursive && !pOutput->recursive && !pOutputMaybe->recursive,
2149 pszVal, o_file, f_simple, 0 /* !target_var */);
2150
2151 /*
2152 $(target)_OBJS_ += $(obj)
2153 */
2154 memcpy(pszDstVar + pTarget->value_length, "_OBJS_", sizeof("_OBJS_"));
2155 do_variable_definition_2(NILF, pszDstVar, pObj->value, pObj->value_length,
2156 !pObj->recursive, 0, o_file, f_append, 0 /* !target_var */);
2157
2158 /*
2159 $(eval $(def_target_source_rule))
2160 */
2161 pVar = kbuild_get_recursive_variable("def_target_source_rule");
2162 pszVal = variable_expand_string_2 (o, pVar->value, pVar->value_length, &psz);
2163 assert (!((size_t)pszVal & 3));
2164
2165 install_variable_buffer(&pszSavedVarBuf, &cchSavedVarBuf);
2166 eval_buffer(pszVal, psz);
2167 restore_variable_buffer(pszSavedVarBuf, cchSavedVarBuf);
2168
2169 kbuild_put_sdks(&Sdks);
2170 (void)pszFuncName;
2171
2172 *pszVal = '\0';
2173 return pszVal;
2174}
2175
2176
2177#endif /* KMK_HELPERS */
2178
Note: See TracBrowser for help on using the repository browser.

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