VirtualBox

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

Last change on this file since 1021 was 961, checked in by bird, 18 years ago

find the executable on solaris. fixed bugs in the linux and freebsd code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 65.3 KB
Line 
1/* $Id: kbuild.c 961 2007-05-27 13:30:41Z bird $ */
2/** @file
3 *
4 * kBuild specific make functionality.
5 *
6 * Copyright (c) 2006-2007 knut st. osmundsen <[email protected]>
7 *
8 *
9 * This file is part of kBuild.
10 *
11 * kBuild is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kBuild is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kBuild; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27/* No GNU coding style here! */
28
29
30/*******************************************************************************
31* Header Files *
32*******************************************************************************/
33#include "make.h"
34#include "filedef.h"
35#include "variable.h"
36#include "dep.h"
37#include "debug.h"
38#ifdef WINDOWS32
39# include "pathstuff.h"
40# include <Windows.h>
41#endif
42
43#include "kbuild.h"
44
45#include <assert.h>
46#include <stdarg.h>
47#ifndef va_copy
48# define va_copy(dst, src) do {(dst) = (src);} while (0)
49#endif
50
51
52/*******************************************************************************
53* Internal Functions *
54*******************************************************************************/
55/* function.c */
56char * abspath(const char *name, char *apath);
57
58/*******************************************************************************
59* Global Variables *
60*******************************************************************************/
61/** The argv[0] passed to main. */
62static const char *g_pszExeName;
63/** The initial working directory. */
64static char *g_pszInitialCwd;
65
66
67/**
68 * Initialize kBuild stuff.
69 *
70 * @param argc Number of arguments to main().
71 * @param argv The main() argument vector.
72 */
73void init_kbuild(int argc, char **argv)
74{
75 int rc;
76 PATH_VAR(szTmp);
77
78 /*
79 * Get the initial cwd for use in my_abspath.
80 */
81#ifdef WINDOWS32
82 if (getcwd_fs(szTmp, GET_PATH_MAX) != 0)
83#else
84 if (getcwd(szTmp, GET_PATH_MAX) != 0)
85#endif
86 g_pszInitialCwd = xstrdup(szTmp);
87 else
88 fatal(NILF, _("getcwd failed"));
89
90 /*
91 * Determin the executable name.
92 */
93 rc = -1;
94#if defined(__APPLE__)
95 {
96 const char *pszImageName = _dyld_get_image_name(0);
97 if (pszImageName)
98 {
99 size_t cchImageName = strlen(pszImageName);
100 if (cchImageName < GET_PATH_MAX)
101 {
102 memcpy(szTmp, pszImageName, cchImageName + 1);
103 rc = 0;
104 }
105 }
106 }
107
108#elif defined(__FreeBSD__)
109 rc = readlink("/proc/curproc/file", szTmp, GET_PATH_MAX - 1);
110 if (rc < 0 || rc == GET_PATH_MAX - 1)
111 rc = -1;
112 else
113 szTmp[rc] = '\0';
114
115#elif defined(__gnu_linux__) /** @todo find proper define... */
116 rc = readlink("/proc/self/exe", szTmp, GET_PATH_MAX - 1);
117 if (rc < 0 || rc == GET_PATH_MAX - 1)
118 rc = -1;
119 else
120 szTmp[rc] = '\0';
121
122#elif defined(__OS2__)
123 _execname(szTmp, GET_PATH_MAX);
124 rc = 0;
125
126#elif defined(__sun__)
127 {
128 char szTmp2[64];
129 snprintf(szTmp2, sizeof(szTmp2), "/proc/%d/path/a.out", getpid());
130 rc = readlink(szTmp2, szTmp, GET_PATH_MAX - 1);
131 if (rc < 0 || rc == GET_PATH_MAX - 1)
132 rc = -1;
133 else
134 szTmp[rc] = '\0';
135 }
136
137#elif defined(WINDOWS32)
138 if (GetModuleFileName(GetModuleHandle(NULL), szTmp, GET_PATH_MAX))
139 rc = 0;
140
141#endif
142 if (rc < 0)
143 g_pszExeName = argv[0];
144 else
145 g_pszExeName = xstrdup(szTmp);
146}
147
148
149/**
150 * Wrapper that ensures correct starting_directory.
151 */
152static char *my_abspath(const char *pszIn, char *pszOut)
153{
154 char *pszSaved, *pszRet;
155
156 pszSaved = starting_directory;
157 starting_directory = g_pszInitialCwd;
158 pszRet = abspath(pszIn, pszOut);
159 starting_directory = pszSaved;
160
161 return pszRet;
162}
163
164
165/**
166 * Determin the PATH_KBUILD value.
167 *
168 * @returns Pointer to static buffer to be treated as read only!
169 */
170const char *get_path_kbuild(void)
171{
172 static const char *s_pszPath = NULL;
173 if (!s_pszPath)
174 {
175 PATH_VAR(szTmpPath);
176 const char *pszEnvVar = getenv("PATH_KBUILD");
177 if ( !pszEnvVar
178 || !my_abspath(pszEnvVar, szTmpPath))
179 {
180#ifdef PATH_KBUILD
181 return s_pszPath = PATH_KBUILD;
182#else
183 /* $(abspath $(PATH_KBUILD_BIN)/../..)*/
184 size_t cch = strlen(get_path_kbuild_bin());
185 char *pszTmp2 = alloca(cch + sizeof("/../.."));
186 strcat(strcpy(pszTmp2, get_path_kbuild_bin()), "/../..");
187 if (!my_abspath(pszTmp2, szTmpPath))
188 fatal(NILF, _("failed to determin PATH_KBUILD"));
189#endif
190 }
191 s_pszPath = xstrdup(szTmpPath);
192 }
193 return s_pszPath;
194}
195
196
197/**
198 * Determin the PATH_KBUILD_BIN value.
199 *
200 * @returns Pointer to static buffer to be treated as read only!
201 */
202const char *get_path_kbuild_bin(void)
203{
204 static const char *s_pszPath = NULL;
205 if (!s_pszPath)
206 {
207 PATH_VAR(szTmpPath);
208 const char *pszEnvVar = getenv("PATH_KBUILD_BIN");
209 if ( !pszEnvVar
210 || !my_abspath(pszEnvVar, szTmpPath))
211 {
212#ifdef PATH_KBUILD
213 return s_pszPath = PATH_KBUILD_BIN;
214#else
215 /* $(abspath $(dir $(ARGV0)).) */
216 size_t cch = strlen(g_pszExeName);
217 char *pszTmp2 = alloca(cch + sizeof("."));
218 char *pszSep = pszTmp2 + cch - 1;
219 memcpy(pszTmp2, g_pszExeName, cch);
220#ifdef HAVE_DOS_PATHS
221 while (pszSep >= pszTmp2 && *pszSep != '/' && *pszSep != '\\' && *pszSep != ':')
222#else
223 while (pszSep >= pszTmp2 && *pszSep != '/')
224#endif
225 pszSep--;
226 if (pszSep >= pszTmp2)
227 strcpy(pszSep + 1, ".");
228 else
229 strcpy(pszTmp2, ".");
230
231 if (!my_abspath(pszTmp2, szTmpPath))
232 fatal(NILF, _("failed to determin PATH_KBUILD_BIN (pszTmp2=%s szTmpPath=%s)"), pszTmp2, szTmpPath);
233#endif
234 }
235 s_pszPath = xstrdup(szTmpPath);
236 }
237 return s_pszPath;
238}
239
240
241#ifdef KMK_HELPERS
242
243/**
244 * Applies the specified default path to any relative paths in *ppsz.
245 *
246 * @param pDefPath The default path.
247 * @param ppsz Pointer to the string pointer. If we expand anything, *ppsz
248 * will be replaced and the caller is responsible for calling free() on it.
249 * @param pcch IN: *pcch contains the current string length.
250 * OUT: *pcch contains the new string length.
251 * @param pcchAlloc *pcchAlloc contains the length allocated for the string. Can be NULL.
252 * @param fCanFree Whether *ppsz should be freed when we replace it.
253 */
254static void
255kbuild_apply_defpath(struct variable *pDefPath, char **ppsz, int *pcch, int *pcchAlloc, int fCanFree)
256{
257 const char *pszIterator;
258 const char *pszInCur;
259 unsigned int cchInCur;
260 unsigned int cRelativePaths;
261
262 /*
263 * The first pass, count the relative paths.
264 */
265 cRelativePaths = 0;
266 pszIterator = *ppsz;
267 while ((pszInCur = find_next_token(&pszIterator, &cchInCur)))
268 {
269 /* is relative? */
270#ifdef HAVE_DOS_PATHS
271 if (pszInCur[0] != '/' && pszInCur[0] != '\\' && (cchInCur < 2 || pszInCur[1] != ':'))
272#else
273 if (pszInCur[0] != '/')
274#endif
275 cRelativePaths++;
276 }
277
278 /*
279 * The second pass construct the new string.
280 */
281 if (cRelativePaths)
282 {
283 const size_t cchOut = *pcch + cRelativePaths * (pDefPath->value_length + 1) + 1;
284 char *pszOut = xmalloc(cchOut);
285 char *pszOutCur = pszOut;
286 const char *pszInNextCopy = *ppsz;
287
288 cRelativePaths = 0;
289 pszIterator = *ppsz;
290 while ((pszInCur = find_next_token(&pszIterator, &cchInCur)))
291 {
292 /* is relative? */
293#ifdef HAVE_DOS_PATHS
294 if (pszInCur[0] != '/' && pszInCur[0] != '\\' && (cchInCur < 2 || pszInCur[1] != ':'))
295#else
296 if (pszInCur[0] != '/')
297#endif
298 {
299 PATH_VAR(szAbsPathIn);
300 PATH_VAR(szAbsPathOut);
301
302 if (pDefPath->value_length + cchInCur + 1 >= GET_PATH_MAX)
303 continue;
304
305 /* Create the abspath input. */
306 memcpy(szAbsPathIn, pDefPath->value, pDefPath->value_length);
307 szAbsPathIn[pDefPath->value_length] = '/';
308 memcpy(&szAbsPathIn[pDefPath->value_length + 1], pszInCur, cchInCur);
309 szAbsPathIn[pDefPath->value_length + 1 + cchInCur] = '\0';
310
311 if (abspath(szAbsPathIn, szAbsPathOut) != NULL)
312 {
313 const size_t cchAbsPathOut = strlen(szAbsPathOut);
314 assert(cchAbsPathOut <= pDefPath->value_length + 1 + cchInCur);
315
316 /* copy leading input */
317 if (pszInCur != pszInNextCopy)
318 {
319 const size_t cchCopy = pszInCur - pszInNextCopy;
320 memcpy(pszOutCur, pszInNextCopy, cchCopy);
321 pszOutCur += cchCopy;
322 }
323 pszInNextCopy = pszInCur + cchInCur;
324
325 /* copy out the abspath. */
326 memcpy(pszOutCur, szAbsPathOut, cchAbsPathOut);
327 pszOutCur += cchAbsPathOut;
328 }
329 }
330 }
331 /* the final copy (includes the nil). */
332 cchInCur = *ppsz + *pcch - pszInNextCopy;
333 memcpy(pszOutCur, pszInNextCopy, cchInCur);
334 pszOutCur += cchInCur;
335 *pszOutCur = '\0';
336 assert((size_t)(pszOutCur - pszOut) < cchOut);
337
338 /* set return values */
339 if (fCanFree)
340 free(*ppsz);
341 *ppsz = pszOut;
342 *pcch = pszOutCur - pszOut;
343 if (pcchAlloc)
344 *pcchAlloc = cchOut;
345 }
346}
347
348
349/**
350 * Gets a variable that must exist.
351 * Will cause a fatal failure if the variable doesn't exist.
352 *
353 * @returns Pointer to the variable.
354 * @param pszName The variable name.
355 */
356static struct variable *
357kbuild_get_variable(const char *pszName)
358{
359#ifndef NDEBUG
360 unsigned i;
361#endif
362 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
363 if (!pVar)
364 fatal(NILF, _("variable `%s' isn't defined!"), pszName);
365 if (pVar->recursive)
366 fatal(NILF, _("variable `%s' is defined as `recursive' instead of `simple'!"), pszName);
367#ifndef NDEBUG
368 i = strlen(pVar->value);
369 if (i != pVar->value_length)
370 {
371 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
372# ifdef _MSC_VER
373 __debugbreak();
374# endif
375 assert(0);
376 }
377#endif
378 return pVar;
379}
380
381/**
382 * Gets a variable that must exist and can be recursive.
383 * Will cause a fatal failure if the variable doesn't exist.
384 *
385 * @returns Pointer to the variable.
386 * @param pszName The variable name.
387 */
388static struct variable *
389kbuild_get_recursive_variable(const char *pszName)
390{
391#ifndef NDEBUG
392 unsigned i;
393#endif
394 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
395 if (!pVar)
396 fatal(NILF, _("variable `%s' isn't defined!"), pszName);
397#ifndef NDEBUG
398 i = strlen(pVar->value);
399 if (i != pVar->value_length)
400 {
401 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
402# ifdef _MSC_VER
403 __debugbreak();
404# endif
405 assert(0);
406 }
407#endif
408 return pVar;
409}
410
411/**
412 * Converts the specified variable into a 'simple' one.
413 * @returns pVar.
414 * @param pVar The variable.
415 */
416static struct variable *
417kbuild_simplify_variable(struct variable *pVar)
418{
419 if (memchr(pVar->value, '$', pVar->value_length))
420 {
421 char *pszExpanded = allocated_variable_expand(pVar->value);
422 free(pVar->value);
423 pVar->value = pszExpanded;
424 pVar->value_length = strlen(pVar->value);
425 pVar->value_alloc_len = pVar->value_length + 1;
426 }
427 pVar->recursive = 0;
428 return pVar;
429}
430
431/**
432 * Looks up a variable.
433 * The value_length field is valid upon successful return.
434 *
435 * @returns Pointer to the variable. NULL if not found.
436 * @param pszName The variable name.
437 */
438static struct variable *
439kbuild_lookup_variable(const char *pszName)
440{
441 struct variable *pVar = lookup_variable(pszName, strlen(pszName));
442 if (pVar)
443 {
444#ifndef NDEBUG
445 unsigned i = strlen(pVar->value);
446 if (i != pVar->value_length)
447 {
448 printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
449# ifdef _MSC_VER
450 __debugbreak();
451# endif
452 assert(0);
453 }
454#endif
455 /* Make sure the variable is simple, convert it if necessary. */
456 if (pVar->recursive)
457 kbuild_simplify_variable(pVar);
458 }
459 return pVar;
460}
461
462/**
463 * Looks up a variable and applies default a path to all relative paths.
464 * The value_length field is valid upon successful return.
465 *
466 * @returns Pointer to the variable. NULL if not found.
467 * @param pDefPath The default path.
468 * @param pszName The variable name.
469 */
470static struct variable *
471kbuild_lookup_variable_defpath(struct variable *pDefPath, const char *pszName)
472{
473 struct variable *pVar = kbuild_lookup_variable(pszName);
474 if (pVar && pDefPath)
475 kbuild_apply_defpath(pDefPath, &pVar->value, &pVar->value_length, &pVar->value_alloc_len, 1);
476 return pVar;
477}
478
479/** Same as kbuild_lookup_variable except that a '%s' in the name string
480 * will be substituted with the values of the variables in the va list. */
481static struct variable *
482kbuild_lookup_variable_fmt_va(struct variable *pDefPath, const char *pszNameFmt, va_list va)
483{
484 va_list va2;
485 size_t cchName;
486 const char *pszFmt;
487 char *pszName;
488 char *psz;
489
490 /* first pass, calc value name size and allocate stack buffer. */
491 va_copy(va2, va);
492
493 cchName = strlen(pszNameFmt) + 1;
494 pszFmt = strchr(pszNameFmt, '%');
495 while (pszFmt)
496 {
497 struct variable *pVar = va_arg(va, struct variable *);
498 if (pVar)
499 cchName += pVar->value_length;
500 pszFmt = strchr(pszFmt + 1, '%');
501 }
502 pszName = alloca(cchName);
503
504 /* second pass format it. */
505 pszFmt = pszNameFmt;
506 psz = pszName;
507 for (;;)
508 {
509 char ch = *pszFmt++;
510 if (ch != '%')
511 {
512 *psz++ = ch;
513 if (!ch)
514 break;
515 }
516 else
517 {
518 struct variable *pVar = va_arg(va2, struct variable *);
519 if (pVar)
520 {
521 memcpy(psz, pVar->value, pVar->value_length);
522 psz += pVar->value_length;
523 }
524 }
525 }
526 va_end(va2);
527
528 if (pDefPath)
529 return kbuild_lookup_variable_defpath(pDefPath, pszName);
530 return kbuild_lookup_variable(pszName);
531}
532
533/** Same as kbuild_lookup_variable except that a '%s' in the name string
534 * will be substituted with the values of the variables in the ellipsis. */
535static struct variable *
536kbuild_lookup_variable_fmt(struct variable *pDefPath, const char *pszNameFmt, ...)
537{
538 struct variable *pVar;
539 va_list va;
540 va_start(va, pszNameFmt);
541 pVar = kbuild_lookup_variable_fmt_va(pDefPath, pszNameFmt, va);
542 va_end(va);
543 return pVar;
544}
545
546/**
547 * Gets the first defined property variable.
548 */
549static struct variable *
550kbuild_first_prop(struct variable *pTarget, struct variable *pSource,
551 struct variable *pTool, struct variable *pType,
552 struct variable *pBldTrg, struct variable *pBldTrgArch,
553 const char *pszPropF1, const char *pszPropF2, const char *pszVarName)
554{
555 struct variable *pVar;
556 struct variable PropF1, PropF2;
557
558 PropF1.value = (char *)pszPropF1;
559 PropF1.value_length = strlen(pszPropF1);
560
561 PropF2.value = (char *)pszPropF2;
562 PropF2.value_length = strlen(pszPropF2);
563
564 if ( (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%%.%.%",pTarget, pSource, pType, &PropF2, pBldTrg, pBldTrgArch))
565 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%%.%", pTarget, pSource, pType, &PropF2, pBldTrg))
566 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%%", pTarget, pSource, pType, &PropF2))
567 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%.%.%", pTarget, pSource, &PropF2, pBldTrg, pBldTrgArch))
568 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%.%", pTarget, pSource, &PropF2, pBldTrg))
569 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%_%", pTarget, pSource, &PropF2))
570 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%.%", pSource, pType, &PropF2, pBldTrg, pBldTrgArch))
571 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%", pSource, pType, &PropF2, pBldTrg))
572 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%", pSource, pType, &PropF2))
573 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%.%", pSource, &PropF2, pBldTrg, pBldTrgArch))
574 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%", pSource, &PropF2, pBldTrg))
575 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%", pSource, &PropF2))
576 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%.%", pTarget, pType, &PropF2, pBldTrg, pBldTrgArch))
577 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%.%", pTarget, pType, &PropF2, pBldTrg))
578 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%%", pTarget, pType, &PropF2))
579 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%.%", pTarget, &PropF2, pBldTrg, pBldTrgArch))
580 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%.%", pTarget, &PropF2, pBldTrg))
581 || (pVar = kbuild_lookup_variable_fmt(NULL, "%_%", pTarget, &PropF2))
582
583 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%.%", pTool, pType, &PropF2, pBldTrg, pBldTrgArch)))
584 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &PropF2, pBldTrg)))
585 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%", pTool, pType, &PropF2)))
586 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%.%", pTool, &PropF2, pBldTrg, pBldTrgArch)))
587 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &PropF2, pBldTrg)))
588 || (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%", pTool, &PropF2)))
589
590 || (pVar = kbuild_lookup_variable_fmt(NULL, "%%.%.%", pType, &PropF1, pBldTrg, pBldTrgArch))
591 || (pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &PropF1, pBldTrg))
592 || (pVar = kbuild_lookup_variable_fmt(NULL, "%%", pType, &PropF1))
593 || (pVar = kbuild_lookup_variable_fmt(NULL, "%.%.%", &PropF1, pBldTrg, pBldTrgArch))
594 || (pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &PropF1, pBldTrg))
595 || (pVar = kbuild_lookup_variable(pszPropF1))
596 )
597 {
598 /* strip it */
599 char *psz = pVar->value;
600 char *pszEnd = psz + pVar->value_length;
601 while (isblank((unsigned char)*psz))
602 psz++;
603 while (pszEnd > psz && isblank((unsigned char)pszEnd[-1]))
604 pszEnd--;
605 if (pszEnd > psz)
606 {
607 char chSaved = *pszEnd;
608 *pszEnd = '\0';
609 pVar = define_variable_vl(pszVarName, strlen(pszVarName), psz, pszEnd - psz,
610 1 /* duplicate */, o_file, 0 /* !recursive */);
611 *pszEnd = chSaved;
612 if (pVar)
613 return pVar;
614 }
615 }
616 return NULL;
617}
618
619/*
620_SOURCE_TOOL = $(strip $(firstword \
621 $($(target)_$(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
622 $($(target)_$(source)_$(type)TOOL.$(bld_trg)) \
623 $($(target)_$(source)_$(type)TOOL) \
624 $($(target)_$(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
625 $($(target)_$(source)_TOOL.$(bld_trg)) \
626 $($(target)_$(source)_TOOL) \
627 $($(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
628 $($(source)_$(type)TOOL.$(bld_trg)) \
629 $($(source)_$(type)TOOL) \
630 $($(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
631 $($(source)_TOOL.$(bld_trg)) \
632 $($(source)_TOOL) \
633 $($(target)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
634 $($(target)_$(type)TOOL.$(bld_trg)) \
635 $($(target)_$(type)TOOL) \
636 $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \
637 $($(target)_TOOL.$(bld_trg)) \
638 $($(target)_TOOL) \
639 $($(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
640 $($(type)TOOL.$(bld_trg)) \
641 $($(type)TOOL) \
642 $(TOOL.$(bld_trg).$(bld_trg_arch)) \
643 $(TOOL.$(bld_trg)) \
644 $(TOOL) ))
645*/
646static struct variable *
647kbuild_get_source_tool(struct variable *pTarget, struct variable *pSource, struct variable *pType,
648 struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
649{
650 struct variable *pVar = kbuild_first_prop(pTarget, pSource, NULL, pType, pBldTrg, pBldTrgArch,
651 "TOOL", "TOOL", pszVarName);
652 if (!pVar)
653 fatal(NILF, _("no tool for source `%s' in target `%s'!"), pSource->value, pTarget->value);
654 return pVar;
655}
656
657/* Implements _SOURCE_TOOL. */
658char *
659func_kbuild_source_tool(char *o, char **argv, const char *pszFuncName)
660{
661 struct variable *pVar = kbuild_get_source_tool(kbuild_get_variable("target"),
662 kbuild_get_variable("source"),
663 kbuild_get_variable("type"),
664 kbuild_get_variable("bld_trg"),
665 kbuild_get_variable("bld_trg_arch"),
666 argv[0]);
667 if (pVar)
668 o = variable_buffer_output(o, pVar->value, pVar->value_length);
669 return o;
670
671}
672
673/* This has been extended a bit, it's now identical to _SOURCE_TOOL.
674$(firstword \
675 $($(target)_$(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
676 $($(target)_$(source)_OBJSUFF.$(bld_trg))\
677 $($(target)_$(source)_OBJSUFF)\
678 $($(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
679 $($(source)_OBJSUFF.$(bld_trg))\
680 $($(source)_OBJSUFF)\
681 $($(target)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
682 $($(target)_OBJSUFF.$(bld_trg))\
683 $($(target)_OBJSUFF)\
684 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg).$(bld_trg_arch))\
685 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg))\
686 $(TOOL_$(tool)_$(type)OBJSUFF)\
687 $(SUFF_OBJ))
688*/
689static struct variable *
690kbuild_get_object_suffix(struct variable *pTarget, struct variable *pSource,
691 struct variable *pTool, struct variable *pType,
692 struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName)
693{
694 struct variable *pVar = kbuild_first_prop(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch,
695 "SUFF_OBJ", "OBJSUFF", pszVarName);
696 if (!pVar)
697 fatal(NILF, _("no OBJSUFF attribute or SUFF_OBJ default for source `%s' in target `%s'!"), pSource->value, pTarget->value);
698 return pVar;
699}
700
701/* */
702char *
703func_kbuild_object_suffix(char *o, char **argv, const char *pszFuncName)
704{
705 struct variable *pVar = kbuild_get_object_suffix(kbuild_get_variable("target"),
706 kbuild_get_variable("source"),
707 kbuild_get_variable("tool"),
708 kbuild_get_variable("type"),
709 kbuild_get_variable("bld_trg"),
710 kbuild_get_variable("bld_trg_arch"),
711 argv[0]);
712 if (pVar)
713 o = variable_buffer_output(o, pVar->value, pVar->value_length);
714 return o;
715
716}
717
718
719/*
720## Figure out where to put object files.
721# @param $1 source file
722# @param $2 normalized main target
723# @remark There are two major hacks here:
724# 1. Source files in the output directory are translated into a gen/ subdir.
725# 2. Catch anyone specifying $(PATH_SUB_CURRENT)/sourcefile.c.
726_OBJECT_BASE = $(PATH_TARGET)/$(2)/$(call no-root-slash,$(call no-drive,$(basename \
727 $(patsubst $(PATH_ROOT)/%,%,$(patsubst $(PATH_SUB_CURRENT)/%,%,$(patsubst $(PATH_TARGET)/$(2)/%,gen/%,$(1)))))))
728*/
729static struct variable *
730kbuild_get_object_base(struct variable *pTarget, struct variable *pSource, const char *pszVarName)
731{
732 struct variable *pPathTarget = kbuild_get_variable("PATH_TARGET");
733 struct variable *pPathRoot = kbuild_get_variable("PATH_ROOT");
734 struct variable *pPathSubCur = kbuild_get_variable("PATH_SUB_CURRENT");
735 const char *pszSrcPrefix = NULL;
736 size_t cchSrcPrefix = 0;
737 const char *pszSrcEnd;
738 char *pszSrc;
739 char *pszResult;
740 char *psz;
741 size_t cch;
742
743 /*
744 * Strip the source filename of any uncessary leading path and root specs.
745 */
746 /* */
747 if ( pSource->value_length > pPathTarget->value_length
748 && !strncmp(pSource->value, pPathTarget->value, pPathTarget->value_length))
749 {
750 pszSrc = pSource->value + pPathTarget->value_length;
751 pszSrcPrefix = "gen/";
752 cchSrcPrefix = sizeof("gen/") - 1;
753 if ( *pszSrc == '/'
754 && !strncmp(pszSrc + 1, pTarget->value, pTarget->value_length)
755 && ( pszSrc[pTarget->value_length + 1] == '/'
756 || pszSrc[pTarget->value_length + 1] == '\0'))
757 pszSrc += 1 + pTarget->value_length;
758 }
759 else if ( pSource->value_length > pPathRoot->value_length
760 && !strncmp(pSource->value, pPathRoot->value, pPathRoot->value_length))
761 {
762 pszSrc = pSource->value + pPathRoot->value_length;
763 if ( *pszSrc == '/'
764 && !strncmp(pszSrc + 1, pPathSubCur->value, pPathSubCur->value_length)
765 && ( pszSrc[pPathSubCur->value_length + 1] == '/'
766 || pszSrc[pPathSubCur->value_length + 1] == '\0'))
767 pszSrc += 1 + pPathSubCur->value_length;
768 }
769 else
770 pszSrc = pSource->value;
771
772 /* skip root specification */
773#ifdef HAVE_DOS_PATHS
774 if (isalpha(pszSrc[0]) && pszSrc[1] == ':')
775 pszSrc += 2;
776#endif
777 while (*pszSrc == '/'
778#ifdef HAVE_DOS_PATHS
779 || *pszSrc == '\\'
780#endif
781 )
782 pszSrc++;
783
784 /* drop the source extension. */
785 pszSrcEnd = pSource->value + pSource->value_length;
786 for (;;)
787 {
788 pszSrcEnd--;
789 if ( pszSrcEnd <= pszSrc
790 || *pszSrcEnd == '/'
791#ifdef HAVE_DOS_PATHS
792 || *pszSrcEnd == '\\'
793 || *pszSrcEnd == ':'
794#endif
795 )
796 {
797 pszSrcEnd = pSource->value + pSource->value_length;
798 break;
799 }
800 if (*pszSrcEnd == '.')
801 break;
802 }
803
804 /*
805 * Assemble the string on the stack and define the objbase variable
806 * which we then return.
807 */
808 cch = pPathTarget->value_length
809 + 1 /* slash */
810 + pTarget->value_length
811 + 1 /* slash */
812 + cchSrcPrefix
813 + pszSrcEnd - pszSrc
814 + 1;
815 psz = pszResult = xmalloc(cch);
816
817 memcpy(psz, pPathTarget->value, pPathTarget->value_length); psz += pPathTarget->value_length;
818 *psz++ = '/';
819 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
820 *psz++ = '/';
821 if (pszSrcPrefix)
822 {
823 memcpy(psz, pszSrcPrefix, cchSrcPrefix);
824 psz += cchSrcPrefix;
825 }
826 memcpy(psz, pszSrc, pszSrcEnd - pszSrc); psz += pszSrcEnd - pszSrc;
827 *psz = '\0';
828
829 /*
830 * Define the variable in the current set and return it.
831 */
832 return define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cch - 1,
833 0 /* use pszResult */, o_file, 0 /* !recursive */);
834}
835
836/* Implements _OBJECT_BASE. */
837char *
838func_kbuild_object_base(char *o, char **argv, const char *pszFuncName)
839{
840 struct variable *pVar = kbuild_get_object_base(kbuild_lookup_variable("target"),
841 kbuild_lookup_variable("source"),
842 argv[0]);
843 if (pVar)
844 o = variable_buffer_output(o, pVar->value, pVar->value_length);
845 return o;
846
847}
848
849
850struct kbuild_sdks
851{
852 char *apsz[4];
853 struct variable *pa;
854 unsigned c;
855 unsigned iGlobal;
856 unsigned cGlobal;
857 unsigned iTarget;
858 unsigned cTarget;
859 unsigned iSource;
860 unsigned cSource;
861 unsigned iTargetSource;
862 unsigned cTargetSource;
863};
864
865/* Fills in the SDK struct (remember to free it). */
866static void
867kbuild_get_sdks(struct kbuild_sdks *pSdks, struct variable *pTarget, struct variable *pSource,
868 struct variable *pBldType, struct variable *pBldTrg, struct variable *pBldTrgArch)
869{
870 int i, j;
871 size_t cchTmp, cch;
872 char *pszTmp;
873 unsigned cchCur;
874 char *pszCur;
875 const char *pszIterator;
876
877 /* basic init. */
878 pSdks->pa = NULL;
879 pSdks->c = 0;
880 i = 0;
881
882 /* determin required tmp variable name space. */
883 cchTmp = sizeof("$(__SDKS) $(__SDKS.) $(__SDKS.) $(__SDKS.) $(__SDKS..)")
884 + (pTarget->value_length + pSource->value_length) * 5
885 + pBldType->value_length
886 + pBldTrg->value_length
887 + pBldTrgArch->value_length
888 + pBldTrg->value_length + pBldTrgArch->value_length;
889 pszTmp = alloca(cchTmp);
890
891 /* the global sdks. */
892 pSdks->iGlobal = i;
893 pSdks->cGlobal = 0;
894 sprintf(pszTmp, "$(SDKS) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s.%s)",
895 pBldType->value,
896 pBldTrg->value,
897 pBldTrgArch->value,
898 pBldTrg->value, pBldTrgArch->value);
899 pszIterator = pSdks->apsz[0] = allocated_variable_expand(pszTmp);
900 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
901 pSdks->cGlobal++;
902 i += pSdks->cGlobal;
903
904 /* the target sdks.*/
905 pSdks->iTarget = i;
906 pSdks->cTarget = 0;
907 sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
908 pTarget->value,
909 pTarget->value, pBldType->value,
910 pTarget->value, pBldTrg->value,
911 pTarget->value, pBldTrgArch->value,
912 pTarget->value, pBldTrg->value, pBldTrgArch->value);
913 pszIterator = pSdks->apsz[1] = allocated_variable_expand(pszTmp);
914 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
915 pSdks->cTarget++;
916 i += pSdks->cTarget;
917
918 /* the source sdks.*/
919 pSdks->iSource = i;
920 pSdks->cSource = 0;
921 sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
922 pSource->value,
923 pSource->value, pBldType->value,
924 pSource->value, pBldTrg->value,
925 pSource->value, pBldTrgArch->value,
926 pSource->value, pBldTrg->value, pBldTrgArch->value);
927 pszIterator = pSdks->apsz[2] = allocated_variable_expand(pszTmp);
928 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
929 pSdks->cSource++;
930 i += pSdks->cSource;
931
932 /* the target + source sdks. */
933 pSdks->iTargetSource = i;
934 pSdks->cTargetSource = 0;
935 cch = sprintf(pszTmp, "$(%s_%s_SDKS) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s.%s)",
936 pTarget->value, pSource->value,
937 pTarget->value, pSource->value, pBldType->value,
938 pTarget->value, pSource->value, pBldTrg->value,
939 pTarget->value, pSource->value, pBldTrgArch->value,
940 pTarget->value, pSource->value, pBldTrg->value, pBldTrgArch->value);
941 assert(cch < cchTmp); (void)cch;
942 pszIterator = pSdks->apsz[3] = allocated_variable_expand(pszTmp);
943 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
944 pSdks->cTargetSource++;
945 i += pSdks->cTargetSource;
946
947 pSdks->c = i;
948 if (!i)
949 return;
950
951 /*
952 * Allocate the variable array and create the variables.
953 */
954 pSdks->pa = (struct variable *)xmalloc(sizeof(pSdks->pa[0]) * i);
955 memset(pSdks->pa, 0, sizeof(pSdks->pa[0]) * i);
956 for (i = j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
957 {
958 int k = i;
959 pszIterator = pSdks->apsz[j];
960 while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0)
961 {
962 pSdks->pa[i].value = pszCur;
963 pSdks->pa[i].value_length = cchCur;
964 i++;
965 }
966 }
967 assert(i == pSdks->c);
968
969 /* terminate them (find_next_token won't work if we terminate them in the previous loop). */
970 while (i-- > 0)
971 pSdks->pa[i].value[pSdks->pa[i].value_length] = '\0';
972}
973
974/* releases resources allocated in the kbuild_get_sdks. */
975static void
976kbuild_put_sdks(struct kbuild_sdks *pSdks)
977{
978 unsigned j;
979 for (j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++)
980 free(pSdks->apsz[j]);
981 free(pSdks->pa);
982}
983
984/* this kind of stuff:
985
986defs := $(kb-src-exp defs)
987 $(TOOL_$(tool)_DEFS)\
988 $(TOOL_$(tool)_DEFS.$(bld_type))\
989 $(TOOL_$(tool)_DEFS.$(bld_trg))\
990 $(TOOL_$(tool)_DEFS.$(bld_trg_arch))\
991 $(TOOL_$(tool)_DEFS.$(bld_trg).$(bld_trg_arch))\
992 $(TOOL_$(tool)_DEFS.$(bld_trg_cpu))\
993 $(TOOL_$(tool)_$(type)DEFS)\
994 $(TOOL_$(tool)_$(type)DEFS.$(bld_type))\
995 $(foreach sdk, $(SDKS.$(bld_trg)) \
996 $(SDKS.$(bld_trg).$(bld_trg_arch)) \
997 $(SDKS.$(bld_type)) \
998 $(SDKS),\
999 $(SDK_$(sdk)_DEFS)\
1000 $(SDK_$(sdk)_DEFS.$(bld_type))\
1001 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1002 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1003 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1004 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1005 $(SDK_$(sdk)_$(type)DEFS)\
1006 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1007 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1008 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1009 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1010 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1011 $(DEFS)\
1012 $(DEFS.$(bld_type))\
1013 $(DEFS.$(bld_trg))\
1014 $(DEFS.$(bld_trg_arch))\
1015 $(DEFS.$(bld_trg).$(bld_trg_arch))\
1016 $(DEFS.$(bld_trg_cpu))\
1017 $($(type)DEFS)\
1018 $($(type)DEFS.$(bld_type))\
1019 $($(type)DEFS.$(bld_trg))\
1020 $($(type)DEFS.$(bld_trg_arch))\
1021 $($(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1022 $($(type)DEFS.$(bld_trg_cpu))\
1023 $(foreach sdk, $($(target)_SDKS.$(bld_trg)) \
1024 $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1025 $($(target)_SDKS.$(bld_type)) \
1026 $($(target)_SDKS),\
1027 $(SDK_$(sdk)_DEFS)\
1028 $(SDK_$(sdk)_DEFS.$(bld_type))\
1029 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1030 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1031 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1032 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1033 $(SDK_$(sdk)_$(type)DEFS)\
1034 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1035 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1036 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1037 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1038 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1039 $($(target)_DEFS)\
1040 $($(target)_DEFS.$(bld_type))\
1041 $($(target)_DEFS.$(bld_trg))\
1042 $($(target)_DEFS.$(bld_trg_arch))\
1043 $($(target)_DEFS.$(bld_trg).$(bld_trg_arch))\
1044 $($(target)_DEFS.$(bld_trg_cpu))\
1045 $($(target)_$(type)DEFS)\
1046 $($(target)_$(type)DEFS.$(bld_type))\
1047 $($(target)_$(type)DEFS.$(bld_trg))\
1048 $($(target)_$(type)DEFS.$(bld_trg_arch))\
1049 $($(target)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1050 $($(target)_$(type)DEFS.$(bld_trg_cpu))\
1051 $(foreach sdk, $($(source)_SDKS.$(bld_trg)) \
1052 $($(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1053 $($(source)_SDKS.$(bld_type)) \
1054 $($(source)_SDKS),\
1055 $(SDK_$(sdk)_DEFS)\
1056 $(SDK_$(sdk)_DEFS.$(bld_type))\
1057 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1058 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1059 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1060 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1061 $(SDK_$(sdk)_$(type)DEFS)\
1062 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1063 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1064 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1065 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1066 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1067 $($(source)_DEFS)\
1068 $($(source)_DEFS.$(bld_type))\
1069 $($(source)_DEFS.$(bld_trg))\
1070 $($(source)_DEFS.$(bld_trg_arch))\
1071 $($(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
1072 $($(source)_DEFS.$(bld_trg_cpu))\
1073 $($(source)_$(type)DEFS)\
1074 $($(source)_$(type)DEFS.$(bld_type))\
1075 $($(source)_$(type)DEFS.$(bld_trg))\
1076 $($(source)_$(type)DEFS.$(bld_trg_arch))\
1077 $($(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1078 $($(source)_$(type)DEFS.$(bld_trg_cpu))\
1079 $(foreach sdk, $($(target)_$(source)_SDKS.$(bld_trg)) \
1080 $($(target)_$(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1081 $($(target)_$(source)_SDKS.$(bld_type)) \
1082 $($(target)_$(source)_SDKS),\
1083 $(SDK_$(sdk)_DEFS)\
1084 $(SDK_$(sdk)_DEFS.$(bld_type))\
1085 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1086 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1087 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1088 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1089 $(SDK_$(sdk)_$(type)DEFS)\
1090 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1091 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1092 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1093 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1094 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1095 $($(target)_$(source)_DEFS)\
1096 $($(target)_$(source)_DEFS.$(bld_type))\
1097 $($(target)_$(source)_DEFS.$(bld_trg))\
1098 $($(target)_$(source)_DEFS.$(bld_trg_arch))\
1099 $($(target)_$(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
1100 $($(target)_$(source)_DEFS.$(bld_trg_cpu))\
1101 $($(target)_$(source)_$(type)DEFS)\
1102 $($(target)_$(source)_$(type)DEFS.$(bld_type))\
1103 $($(target)_$(source)_$(type)DEFS.$(bld_trg))\
1104 $($(target)_$(source)_$(type)DEFS.$(bld_trg_arch))\
1105 $($(target)_$(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1106 $($(target)_$(source)_$(type)DEFS.$(bld_trg_cpu))
1107*/
1108static struct variable *
1109kbuild_collect_source_prop(struct variable *pTarget, struct variable *pSource,
1110 struct variable *pTool, struct kbuild_sdks *pSdks,
1111 struct variable *pType, struct variable *pBldType,
1112 struct variable *pBldTrg, struct variable *pBldTrgArch, struct variable *pBldTrgCpu,
1113 struct variable *pDefPath,
1114 const char *pszProp, const char *pszVarName, int iDirection)
1115{
1116 struct variable *pVar;
1117 unsigned iSdk, iSdkEnd;
1118 int cVars, iVar, iVarEnd;
1119 size_t cchTotal;
1120 char *pszResult, *psz;
1121 struct
1122 {
1123 struct variable *pVar;
1124 int cchExp;
1125 char *pszExp;
1126 } *paVars;
1127
1128 struct variable Prop = {0};
1129 Prop.value = (char *)pszProp;
1130 Prop.value_length = strlen(pszProp);
1131
1132 assert(iDirection == 1 || iDirection == -1);
1133
1134 /*
1135 * Get the variables.
1136 */
1137 cVars = 12 * (pSdks->c + 5);
1138 paVars = alloca(cVars * sizeof(paVars[0]));
1139
1140 iVar = 0;
1141 /* the tool (lowest priority) */
1142 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%", pTool, &Prop);
1143 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &Prop, pBldType);
1144 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &Prop, pBldTrg);
1145 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &Prop, pBldTrgArch);
1146 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%.%", pTool, &Prop, pBldTrg, pBldTrgArch);
1147 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%.%", pTool, &Prop, pBldTrgCpu);
1148
1149 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%", pTool, pType, &Prop);
1150 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &Prop, pBldType);
1151 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &Prop, pBldTrg);
1152 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &Prop, pBldTrgArch);
1153 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%.%", pTool, pType, &Prop, pBldTrg, pBldTrgArch);
1154 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "TOOL_%_%%.%", pTool, pType, &Prop, pBldTrgCpu);
1155
1156 /* the global sdks */
1157 iSdkEnd = iDirection == 1 ? pSdks->iGlobal + pSdks->cGlobal : pSdks->iGlobal - 1;
1158 for (iSdk = iDirection == 1 ? pSdks->iGlobal : pSdks->iGlobal + pSdks->cGlobal - 1;
1159 iSdk != iSdkEnd;
1160 iSdk += iDirection)
1161 {
1162 struct variable *pSdk = &pSdks->pa[iSdk];
1163 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%", pSdk, &Prop);
1164 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldType);
1165 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrg);
1166 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
1167 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
1168 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
1169
1170 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%", pSdk, pType, &Prop);
1171 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
1172 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
1173 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
1174 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
1175 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
1176 }
1177
1178 /* the globals */
1179 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%", &Prop);
1180 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &Prop, pBldType);
1181 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &Prop, pBldTrg);
1182 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &Prop, pBldTrgArch);
1183 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%.%", &Prop, pBldTrg, pBldTrgArch);
1184 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%.%", &Prop, pBldTrgCpu);
1185
1186 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%", pType, &Prop);
1187 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &Prop, pBldType);
1188 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &Prop, pBldTrg);
1189 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &Prop, pBldTrgArch);
1190 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%.%", pType, &Prop, pBldTrg, pBldTrgArch);
1191 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "%%.%", pType, &Prop, pBldTrgCpu);
1192
1193 /* the target sdks */
1194 iSdkEnd = iDirection == 1 ? pSdks->iTarget + pSdks->cTarget : pSdks->iTarget - 1;
1195 for (iSdk = iDirection == 1 ? pSdks->iTarget : pSdks->iTarget + pSdks->cTarget - 1;
1196 iSdk != iSdkEnd;
1197 iSdk += iDirection)
1198 {
1199 struct variable *pSdk = &pSdks->pa[iSdk];
1200 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%", pSdk, &Prop);
1201 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldType);
1202 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrg);
1203 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
1204 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
1205 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
1206
1207 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%", pSdk, pType, &Prop);
1208 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
1209 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
1210 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
1211 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
1212 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
1213 }
1214
1215 /* the target */
1216 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%", pTarget, &Prop);
1217 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pTarget, &Prop, pBldType);
1218 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pTarget, &Prop, pBldTrg);
1219 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pTarget, &Prop, pBldTrgArch);
1220 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%.%", pTarget, &Prop, pBldTrg, pBldTrgArch);
1221 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pTarget, &Prop, pBldTrgCpu);
1222
1223 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%", pTarget, pType, &Prop);
1224 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pTarget, pType, &Prop, pBldType);
1225 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pTarget, pType, &Prop, pBldTrg);
1226 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pTarget, pType, &Prop, pBldTrgArch);
1227 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%.%", pTarget, pType, &Prop, pBldTrg, pBldTrgArch);
1228 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pTarget, pType, &Prop, pBldTrgCpu);
1229
1230 /* the source sdks */
1231 iSdkEnd = iDirection == 1 ? pSdks->iSource + pSdks->cSource : pSdks->iSource - 1;
1232 for (iSdk = iDirection == 1 ? pSdks->iSource : pSdks->iSource + pSdks->cSource - 1;
1233 iSdk != iSdkEnd;
1234 iSdk += iDirection)
1235 {
1236 struct variable *pSdk = &pSdks->pa[iSdk];
1237 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%", pSdk, &Prop);
1238 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldType);
1239 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrg);
1240 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
1241 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
1242 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
1243
1244 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%", pSdk, pType, &Prop);
1245 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
1246 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
1247 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
1248 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
1249 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
1250 }
1251
1252 /* the source */
1253 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%", pSource, &Prop);
1254 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pSource, &Prop, pBldType);
1255 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pSource, &Prop, pBldTrg);
1256 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pSource, &Prop, pBldTrgArch);
1257 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%.%", pSource, &Prop, pBldTrg, pBldTrgArch);
1258 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%.%", pSource, &Prop, pBldTrgCpu);
1259
1260 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%", pSource, pType, &Prop);
1261 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pSource, pType, &Prop, pBldType);
1262 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pSource, pType, &Prop, pBldTrg);
1263 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pSource, pType, &Prop, pBldTrgArch);
1264 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%.%", pSource, pType, &Prop, pBldTrg, pBldTrgArch);
1265 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%%.%", pSource, pType, &Prop, pBldTrgCpu);
1266
1267
1268 /* the target + source sdks */
1269 iSdkEnd = iDirection == 1 ? pSdks->iTargetSource + pSdks->cTargetSource : pSdks->iTargetSource - 1;
1270 for (iSdk = iDirection == 1 ? pSdks->iTargetSource : pSdks->iTargetSource + pSdks->cTargetSource - 1;
1271 iSdk != iSdkEnd;
1272 iSdk += iDirection)
1273 {
1274 struct variable *pSdk = &pSdks->pa[iSdk];
1275 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%", pSdk, &Prop);
1276 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldType);
1277 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrg);
1278 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgArch);
1279 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%.%", pSdk, &Prop, pBldTrg, pBldTrgArch);
1280 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%.%", pSdk, &Prop, pBldTrgCpu);
1281
1282 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%", pSdk, pType, &Prop);
1283 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldType);
1284 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrg);
1285 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgArch);
1286 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%.%", pSdk, pType, &Prop, pBldTrg, pBldTrgArch);
1287 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(NULL, "SDK_%_%%.%", pSdk, pType, &Prop, pBldTrgCpu);
1288 }
1289
1290 /* the target + source */
1291 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%", pTarget, pSource, &Prop);
1292 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%", pTarget, pSource, &Prop, pBldType);
1293 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%", pTarget, pSource, &Prop, pBldTrg);
1294 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%", pTarget, pSource, &Prop, pBldTrgArch);
1295 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%.%", pTarget, pSource, &Prop, pBldTrg, pBldTrgArch);
1296 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%.%", pTarget, pSource, &Prop, pBldTrgCpu);
1297
1298 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%", pTarget, pSource, pType, &Prop);
1299 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%", pTarget, pSource, pType, &Prop, pBldType);
1300 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrg);
1301 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrgArch);
1302 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%.%", pTarget, pSource, pType, &Prop, pBldTrg, pBldTrgArch);
1303 paVars[iVar++].pVar = kbuild_lookup_variable_fmt(pDefPath, "%_%_%%.%", pTarget, pSource, pType, &Prop, pBldTrgCpu);
1304
1305 assert(cVars == iVar);
1306
1307 /*
1308 * Expand the variables and calculate the total length.
1309 */
1310 cchTotal = 0;
1311 iVarEnd = iDirection == 1 ? cVars : 0;
1312 for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
1313 {
1314 paVars[iVar].cchExp = 0;
1315 if (!paVars[iVar].pVar)
1316 continue;
1317 if ( paVars[iVar].pVar->flavor == f_simple
1318 || !strchr(paVars[iVar].pVar->value, '$'))
1319 {
1320 paVars[iVar].pszExp = paVars[iVar].pVar->value;
1321 paVars[iVar].cchExp = paVars[iVar].pVar->value_length;
1322 }
1323 else
1324 {
1325 paVars[iVar].pszExp = allocated_variable_expand(paVars[iVar].pVar->value);
1326 paVars[iVar].cchExp = strlen(paVars[iVar].pszExp);
1327 }
1328 if (pDefPath)
1329 kbuild_apply_defpath(pDefPath, &paVars[iVar].pszExp, &paVars[iVar].cchExp, NULL,
1330 paVars[iVar].pszExp != paVars[iVar].pVar->value);
1331 cchTotal += paVars[iVar].cchExp + 1;
1332 }
1333
1334 /*
1335 * Construct the result value.
1336 */
1337 psz = pszResult = xmalloc(cchTotal + 1);
1338 iVarEnd = iDirection == 1 ? cVars : 0;
1339 for (iVar = iDirection == 1 ? 0 : cVars - 1; iVar != iVarEnd; iVar += iDirection)
1340 {
1341 if (!paVars[iVar].cchExp)
1342 continue;
1343 memcpy(psz, paVars[iVar].pszExp, paVars[iVar].cchExp);
1344 psz += paVars[iVar].cchExp;
1345 *psz++ = ' ';
1346 if (paVars[iVar].pszExp != paVars[iVar].pVar->value)
1347 free(paVars[iVar].pszExp);
1348 }
1349 if (psz != pszResult)
1350 psz--;
1351 *psz = '\0';
1352 cchTotal = psz - pszResult;
1353
1354 pVar = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cchTotal,
1355 0 /* take pszResult */ , o_file, 0 /* !recursive */);
1356 return pVar;
1357}
1358
1359/* get a source property. Doesn't respect the default path. */
1360char *
1361func_kbuild_source_prop(char *o, char **argv, const char *pszFuncName)
1362{
1363 struct variable *pTarget = kbuild_get_variable("target");
1364 struct variable *pSource = kbuild_get_variable("source");
1365 struct variable *pDefPath = NULL;
1366 struct variable *pType = kbuild_get_variable("type");
1367 struct variable *pTool = kbuild_get_variable("tool");
1368 struct variable *pBldType = kbuild_get_variable("bld_type");
1369 struct variable *pBldTrg = kbuild_get_variable("bld_trg");
1370 struct variable *pBldTrgArch = kbuild_get_variable("bld_trg_arch");
1371 struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
1372 struct variable *pVar;
1373 struct kbuild_sdks Sdks;
1374 int iDirection;
1375 if (!strcmp(argv[2], "left-to-right"))
1376 iDirection = 1;
1377 else if (!strcmp(argv[2], "right-to-left"))
1378 iDirection = -1;
1379 else
1380 fatal(NILF, _("incorrect direction argument `%s'!"), argv[2]);
1381 if (argv[3])
1382 pDefPath = kbuild_get_variable("defpath");
1383
1384 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
1385
1386 pVar = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType,
1387 pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
1388 pDefPath,
1389 argv[0], argv[1], iDirection);
1390 if (pVar)
1391 o = variable_buffer_output(o, pVar->value, pVar->value_length);
1392
1393 kbuild_put_sdks(&Sdks);
1394 return o;
1395
1396}
1397
1398/*
1399dep := $(obj)$(SUFF_DEP)
1400obj := $(outbase)$(objsuff)
1401dirdep := $(call DIRDEP,$(dir $(outbase)))
1402PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1403*/
1404static struct variable *
1405kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(struct variable *pTarget, struct variable *pSource,
1406 struct variable *pOutBase, struct variable *pObjSuff,
1407 const char *pszVarName, struct variable **ppDep,
1408 struct variable **ppDirDep)
1409{
1410 struct variable *pDepSuff = kbuild_get_variable("SUFF_DEP");
1411 struct variable *pObj;
1412 size_t cch = pOutBase->value_length + pObjSuff->value_length + pDepSuff->value_length + 1;
1413 char *pszResult = alloca(cch);
1414 char *pszName, *psz;
1415
1416 /*
1417 * dep.
1418 */
1419 psz = pszResult;
1420 memcpy(psz, pOutBase->value, pOutBase->value_length); psz += pOutBase->value_length;
1421 memcpy(psz, pObjSuff->value, pObjSuff->value_length); psz += pObjSuff->value_length;
1422 memcpy(psz, pDepSuff->value, pDepSuff->value_length + 1);
1423 *ppDep = define_variable_vl("dep", 3, pszResult, cch - 1, 1 /*dup*/, o_file, 0 /* !recursive */);
1424
1425 /*
1426 * obj
1427 */
1428 *psz = '\0';
1429 pObj = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, psz - pszResult,
1430 1/* dup */, o_file, 0 /* !recursive */);
1431
1432 /*
1433 * PATH_$(target)_$(source) - this is global!
1434 */
1435 /* calc variable name. */
1436 cch = sizeof("PATH_")-1 + pTarget->value_length + sizeof("_")-1 + pSource->value_length;
1437 psz = pszName = alloca(cch + 1);
1438 memcpy(psz, "PATH_", sizeof("PATH_") - 1); psz += sizeof("PATH_") - 1;
1439 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1440 *psz++ = '_';
1441 memcpy(psz, pSource->value, pSource->value_length + 1);
1442
1443 /* strip off the filename. */
1444 psz = pszResult + pOutBase->value_length;
1445 for (;;)
1446 {
1447 psz--;
1448 if (psz <= pszResult)
1449 fatal(NULL, "whut!?! no path? result=`%s'", pszResult);
1450#ifdef HAVE_DOS_PATHS
1451 if (*psz == ':')
1452 {
1453 psz++;
1454 break;
1455 }
1456#endif
1457 if ( *psz == '/'
1458#ifdef HAVE_DOS_PATHS
1459 || *psz == '\\'
1460#endif
1461 )
1462 {
1463 while ( psz - 1 > pszResult
1464 && psz[-1] == '/'
1465#ifdef HAVE_DOS_PATHS
1466 || psz[-1] == '\\'
1467#endif
1468 )
1469 psz--;
1470#ifdef HAVE_DOS_PATHS
1471 if (psz == pszResult + 2 && pszResult[1] == ':')
1472 psz++;
1473#endif
1474 break;
1475 }
1476 }
1477 *psz = '\0';
1478
1479 /* set global variable */
1480 define_variable_vl_global(pszName, cch, pszResult, psz - pszResult, 1/*dup*/, o_file, 0 /* !recursive */, NILF);
1481
1482 /*
1483 * dirdep
1484 */
1485 if ( psz[-1] != '/'
1486#ifdef HAVE_DOS_PATHS
1487 && psz[-1] != '\\'
1488 && psz[-1] != ':'
1489#endif
1490 )
1491 {
1492 *psz++ = '/';
1493 *psz = '\0';
1494 }
1495 *ppDirDep = define_variable_vl("dirdep", 6, pszResult, psz - pszResult, 1/*dup*/, o_file, 0 /* !recursive */);
1496
1497 return pObj;
1498}
1499
1500
1501/* setup the base variables for def_target_source_c_cpp_asm_new:
1502
1503X := $(kb-src-tool tool)
1504x := $(kb-obj-base outbase)
1505x := $(kb-obj-suff objsuff)
1506obj := $(outbase)$(objsuff)
1507PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1508
1509x := $(kb-src-prop DEFS,defs,left-to-right)
1510x := $(kb-src-prop INCS,incs,right-to-left)
1511x := $(kb-src-prop FLAGS,flags,right-to-left)
1512
1513x := $(kb-src-prop DEPS,deps,left-to-right)
1514dirdep := $(call DIRDEP,$(dir $(outbase)))
1515dep := $(obj)$(SUFF_DEP)
1516*/
1517char *
1518func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
1519{
1520 static int s_fNoCompileCmdsDepsDefined = -1;
1521 struct variable *pTarget = kbuild_get_variable("target");
1522 struct variable *pSource = kbuild_get_variable("source");
1523 struct variable *pDefPath = kbuild_get_variable("defpath");
1524 struct variable *pType = kbuild_get_variable("type");
1525 struct variable *pBldType = kbuild_get_variable("bld_type");
1526 struct variable *pBldTrg = kbuild_get_variable("bld_trg");
1527 struct variable *pBldTrgArch= kbuild_get_variable("bld_trg_arch");
1528 struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
1529 struct variable *pTool = kbuild_get_source_tool(pTarget, pSource, pType, pBldTrg, pBldTrgArch, "tool");
1530 struct variable *pOutBase = kbuild_get_object_base(pTarget, pSource, "outbase");
1531 struct variable *pObjSuff = kbuild_get_object_suffix(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch, "objsuff");
1532 struct variable *pDefs, *pIncs, *pFlags, *pDeps, *pOrderDeps, *pDirDep, *pDep, *pVar, *pOutput;
1533 struct variable *pObj = kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(pTarget, pSource, pOutBase, pObjSuff, "obj", &pDep, &pDirDep);
1534 char *pszDstVar, *pszDst, *pszSrcVar, *pszSrc, *pszVal, *psz;
1535 char *pszSavedVarBuf;
1536 unsigned cchSavedVarBuf;
1537 size_t cch;
1538 struct kbuild_sdks Sdks;
1539
1540 /*
1541 * Gather properties.
1542 */
1543 kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch);
1544
1545 if (pDefPath && !pDefPath->value_length)
1546 pDefPath = NULL;
1547 pDefs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
1548 "DEFS", "defs", 1/* left-to-right */);
1549 pIncs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
1550 "INCS", "incs", -1/* right-to-left */);
1551 pFlags = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
1552 "FLAGS", "flags", 1/* left-to-right */);
1553 pDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
1554 "DEPS", "deps", 1/* left-to-right */);
1555 pOrderDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
1556 "ORDERDEPS", "orderdeps", 1/* left-to-right */);
1557
1558 /*
1559 * If we've got a default path, we must expand the source now.
1560 * If we do this too early, "<source>_property = stuff" won't work becuase
1561 * our 'source' value isn't what the user expects.
1562 */
1563 if (pDefPath)
1564 kbuild_apply_defpath(pDefPath, &pSource->value, &pSource->value_length, &pSource->value_alloc_len, 1 /* can free */);
1565
1566 /*
1567 # dependencies
1568 ifndef NO_COMPILE_CMDS_DEPS
1569 _DEPFILES_INCLUDED += $(dep)
1570 $(if $(wildcard $(dep)),$(eval include $(dep)))
1571 endif
1572 */
1573 if (s_fNoCompileCmdsDepsDefined == -1)
1574 s_fNoCompileCmdsDepsDefined = kbuild_lookup_variable("NO_COMPILE_CMDS_DEPS") != NULL;
1575 if (!s_fNoCompileCmdsDepsDefined)
1576 {
1577 do_variable_definition(NILF, "_DEPFILES_INCLUDED", pDep->value, o_file, f_append, 0 /* !target_var */);
1578 eval_include_dep(pDep->value, NILF);
1579 }
1580
1581 /*
1582 # call the tool
1583 $(target)_$(source)_CMDS_ := $(TOOL_$(tool)_COMPILE_$(type)_CMDS)
1584 $(target)_$(source)_OUTPUT_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT)
1585 $(target)_$(source)_DEPEND_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPEND) $(deps) $(source)
1586 $(target)_$(source)_DEPORD_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPORD) $(dirdep)
1587 */
1588 cch = sizeof("TOOL_") + pTool->value_length + sizeof("_COMPILE_") + pType->value_length + sizeof("_OUTPUT");
1589 psz = pszSrcVar = alloca(cch);
1590 memcpy(psz, "TOOL_", sizeof("TOOL_") - 1); psz += sizeof("TOOL_") - 1;
1591 memcpy(psz, pTool->value, pTool->value_length); psz += pTool->value_length;
1592 memcpy(psz, "_COMPILE_", sizeof("_COMPILE_") - 1); psz += sizeof("_COMPILE_") - 1;
1593 memcpy(psz, pType->value, pType->value_length); psz += pType->value_length;
1594 pszSrc = psz;
1595
1596 cch = pTarget->value_length + 1 + pSource->value_length + sizeof("_OUTPUT_");
1597 psz = pszDstVar = alloca(cch);
1598 memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length;
1599 *psz++ = '_';
1600 memcpy(psz, pSource->value, pSource->value_length); psz += pSource->value_length;
1601 pszDst = psz;
1602
1603 memcpy(pszSrc, "_CMDS", sizeof("_CMDS"));
1604 memcpy(pszDst, "_CMDS_", sizeof("_CMDS_"));
1605 pVar = kbuild_get_recursive_variable(pszSrcVar);
1606 do_variable_definition(NILF, pszDstVar, pVar->value, o_file, f_simple, 0 /* !target_var */);
1607
1608 memcpy(pszSrc, "_OUTPUT", sizeof("_OUTPUT"));
1609 memcpy(pszDst, "_OUTPUT_", sizeof("_OUTPUT_"));
1610 pVar = kbuild_get_recursive_variable(pszSrcVar);
1611 pOutput = do_variable_definition(NILF, pszDstVar, pVar->value, o_file, f_simple, 0 /* !target_var */);
1612
1613 memcpy(pszSrc, "_DEPEND", sizeof("_DEPEND"));
1614 memcpy(pszDst, "_DEPEND_", sizeof("_DEPEND_"));
1615 pVar = kbuild_get_recursive_variable(pszSrcVar);
1616 psz = pszVal = xmalloc(pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length + 1);
1617 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1618 *psz++ = ' ';
1619 memcpy(psz, pDeps->value, pDeps->value_length); psz += pDeps->value_length;
1620 *psz++ = ' ';
1621 memcpy(psz, pSource->value, pSource->value_length + 1);
1622 do_variable_definition(NILF, pszDstVar, pszVal, o_file, f_simple, 0 /* !target_var */);
1623 free(pszVal);
1624
1625 memcpy(pszSrc, "_DEPORD", sizeof("_DEPORD"));
1626 memcpy(pszDst, "_DEPORD_", sizeof("_DEPORD_"));
1627 pVar = kbuild_get_recursive_variable(pszSrcVar);
1628 psz = pszVal = xmalloc(pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length + 1);
1629 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1630 *psz++ = ' ';
1631 memcpy(psz, pDirDep->value, pDirDep->value_length); psz += pDirDep->value_length;
1632 *psz++ = ' ';
1633 memcpy(psz, pOrderDeps->value, pOrderDeps->value_length + 1);
1634 do_variable_definition(NILF, pszDstVar, pszVal, o_file, f_simple, 0 /* !target_var */);
1635 free(pszVal);
1636
1637 /*
1638 _OUT_FILES += $($(target)_$(source)_OUTPUT_)
1639 */
1640 pVar = kbuild_get_variable("_OUT_FILES");
1641 psz = pszVal = xmalloc(pVar->value_length + 1 + pOutput->value_length + 1);
1642 memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
1643 *psz++ = ' ';
1644 memcpy(psz, pOutput->value, pOutput->value_length + 1);
1645 do_variable_definition(NILF, "_OUT_FILES", pszVal, o_file, f_simple, 0 /* !target_var */);
1646 free(pszVal);
1647
1648 /*
1649 $(target)_OBJS_ += $(obj)
1650 */
1651 memcpy(pszDstVar + pTarget->value_length, "_OBJS_", sizeof("_OBJS_"));
1652 do_variable_definition(NILF, pszDstVar, pObj->value, o_file, f_append, 0 /* !target_var */);
1653
1654 /*
1655 $(eval $(def_target_source_rule))
1656 */
1657 pVar = kbuild_get_recursive_variable("def_target_source_rule");
1658 pszVal = allocated_variable_expand(pVar->value);
1659
1660 install_variable_buffer(&pszSavedVarBuf, &cchSavedVarBuf);
1661 eval_buffer(pszVal);
1662 restore_variable_buffer(pszSavedVarBuf, cchSavedVarBuf);
1663
1664 free(pszVal);
1665
1666 kbuild_put_sdks(&Sdks);
1667 return variable_buffer_output(o, "", 1);
1668}
1669
1670
1671#endif /* KMK_HELPERS */
1672
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