source: trunk/src/gmakenew/kbuild.c@ 927

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

Fixed some PATH_KBUILD_BIN mess + the init warnings.

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