3 * kBuild specific make functionality.
7 * Copyright (c) 2006-2008 knut st. osmundsen <bird-src-spam@anduin.net>
9 * This file is part of kBuild.
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 3 of the License, or
14 * (at your option) any later version.
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.
21 * You should have received a copy of the GNU General Public License
22 * along with kBuild. If not, see <http://www.gnu.org/licenses/>
26 /* No GNU coding style here! */
28 /*******************************************************************************
30 *******************************************************************************/
37 # include "pathstuff.h"
40 #if defined(__APPLE__)
41 # include <mach-o/dyld.h>
49 /*******************************************************************************
50 * Defined Constants And Macros *
51 *******************************************************************************/
52 /** Helper for passing a string constant to kbuild_get_variable_n. */
53 #define ST(strconst) strconst, sizeof(strconst) - 1
56 # define my_memcpy(dst, src, len) \
59 memcpy(dst, src, len); \
63 case 8: dst[7] = src[7]; \
64 case 7: dst[6] = src[6]; \
65 case 6: dst[5] = src[5]; \
66 case 5: dst[4] = src[4]; \
67 case 4: dst[3] = src[3]; \
68 case 3: dst[2] = src[2]; \
69 case 2: dst[1] = src[1]; \
70 case 1: dst[0] = src[0]; \
74 #elif defined(__GNUC__)
75 # define my_memcpy __builtin_memcpy
76 #elif defined(_MSC_VER)
77 # pragma instrinic(memcpy)
78 # define my_memcpy memcpy
82 /*******************************************************************************
84 *******************************************************************************/
85 /** The argv[0] passed to main. */
86 static const char *g_pszExeName
;
87 /** The initial working directory. */
88 static char *g_pszInitialCwd
;
92 * Initialize kBuild stuff.
94 * @param argc Number of arguments to main().
95 * @param argv The main() argument vector.
97 void init_kbuild(int argc
, char **argv
)
103 * Get the initial cwd for use in my_abspath.
106 if (getcwd_fs(szTmp
, GET_PATH_MAX
) != 0)
108 if (getcwd(szTmp
, GET_PATH_MAX
) != 0)
110 g_pszInitialCwd
= xstrdup(szTmp
);
112 fatal(NILF
, _("getcwd failed"));
115 * Determin the executable name.
118 #if defined(__APPLE__)
120 const char *pszImageName
= _dyld_get_image_name(0);
123 size_t cchImageName
= strlen(pszImageName
);
124 if (cchImageName
< GET_PATH_MAX
)
126 memcpy(szTmp
, pszImageName
, cchImageName
+ 1);
132 #elif defined(__FreeBSD__)
133 rc
= readlink("/proc/curproc/file", szTmp
, GET_PATH_MAX
- 1);
134 if (rc
< 0 || rc
== GET_PATH_MAX
- 1)
139 #elif defined(__gnu_linux__) /** @todo find proper define... */
140 rc
= readlink("/proc/self/exe", szTmp
, GET_PATH_MAX
- 1);
141 if (rc
< 0 || rc
== GET_PATH_MAX
- 1)
146 #elif defined(__OS2__)
147 _execname(szTmp
, GET_PATH_MAX
);
150 #elif defined(__sun__)
153 snprintf(szTmp2
, sizeof(szTmp2
), "/proc/%ld/path/a.out", (long)getpid());
154 rc
= readlink(szTmp2
, szTmp
, GET_PATH_MAX
- 1);
155 if (rc
< 0 || rc
== GET_PATH_MAX
- 1)
161 #elif defined(WINDOWS32)
162 if (GetModuleFileName(GetModuleHandle(NULL
), szTmp
, GET_PATH_MAX
))
167 #if !defined(__OS2__) && !defined(WINDOWS32)
168 /* fallback, try use the path to locate the binary. */
170 && access(argv
[0], X_OK
))
172 size_t cchArgv0
= strlen(argv
[0]);
173 const char *pszPath
= getenv("PATH");
174 char *pszCopy
= xstrdup(pszPath
? pszPath
: ".");
179 char *pszEnd
= strchr(psz
, PATH_SEPARATOR_CHAR
);
181 pszEnd
= strchr(psz
, '\0');
183 if (cch
+ cchArgv0
+ 2 <= GET_PATH_MAX
)
185 memcpy(szTmp
, psz
, cch
);
187 memcpy(&szTmp
[cch
+ 1], argv
[0], cchArgv0
+ 1);
188 if (!access(szTmp
, X_OK
))
197 while (*psz
== PATH_SEPARATOR_CHAR
)
205 g_pszExeName
= argv
[0];
207 g_pszExeName
= xstrdup(szTmp
);
214 * Wrapper that ensures correct starting_directory.
216 static char *my_abspath(const char *pszIn
, char *pszOut
)
218 char *pszSaved
, *pszRet
;
220 pszSaved
= starting_directory
;
221 starting_directory
= g_pszInitialCwd
;
222 pszRet
= abspath(pszIn
, pszOut
);
223 starting_directory
= pszSaved
;
230 * Determin the KBUILD_PATH value.
232 * @returns Pointer to static a buffer containing the value (consider it read-only).
234 const char *get_kbuild_path(void)
236 static const char *s_pszPath
= NULL
;
240 const char *pszEnvVar
= getenv("KBUILD_PATH");
242 || !my_abspath(pszEnvVar
, szTmpPath
))
244 pszEnvVar
= getenv("PATH_KBUILD");
246 || !my_abspath(pszEnvVar
, szTmpPath
))
249 return s_pszPath
= KBUILD_PATH
;
251 /* $(abspath $(KBUILD_BIN_PATH)/../..)*/
252 size_t cch
= strlen(get_kbuild_bin_path());
253 char *pszTmp2
= alloca(cch
+ sizeof("/../.."));
254 strcat(strcpy(pszTmp2
, get_kbuild_bin_path()), "/../..");
255 if (!my_abspath(pszTmp2
, szTmpPath
))
256 fatal(NILF
, _("failed to determin KBUILD_PATH"));
260 s_pszPath
= xstrdup(szTmpPath
);
267 * Determin the KBUILD_BIN_PATH value.
269 * @returns Pointer to static a buffer containing the value (consider it read-only).
271 const char *get_kbuild_bin_path(void)
273 static const char *s_pszPath
= NULL
;
278 const char *pszEnvVar
= getenv("KBUILD_BIN_PATH");
280 || !my_abspath(pszEnvVar
, szTmpPath
))
282 pszEnvVar
= getenv("PATH_KBUILD_BIN");
284 || !my_abspath(pszEnvVar
, szTmpPath
))
287 return s_pszPath
= KBUILD_BIN_PATH
;
289 /* $(abspath $(dir $(ARGV0)).) */
290 size_t cch
= strlen(g_pszExeName
);
291 char *pszTmp2
= alloca(cch
+ sizeof("."));
292 char *pszSep
= pszTmp2
+ cch
- 1;
293 memcpy(pszTmp2
, g_pszExeName
, cch
);
294 # ifdef HAVE_DOS_PATHS
295 while (pszSep
>= pszTmp2
&& *pszSep
!= '/' && *pszSep
!= '\\' && *pszSep
!= ':')
297 while (pszSep
>= pszTmp2
&& *pszSep
!= '/')
300 if (pszSep
>= pszTmp2
)
301 strcpy(pszSep
+ 1, ".");
303 strcpy(pszTmp2
, ".");
305 if (!my_abspath(pszTmp2
, szTmpPath
))
306 fatal(NILF
, _("failed to determin KBUILD_BIN_PATH (pszTmp2=%s szTmpPath=%s)"), pszTmp2
, szTmpPath
);
307 #endif /* !KBUILD_PATH */
310 s_pszPath
= xstrdup(szTmpPath
);
317 * Determin the location of default kBuild shell.
319 * @returns Pointer to static a buffer containing the location (consider it read-only).
321 const char *get_default_kbuild_shell(void)
323 static char *s_pszDefaultShell
= NULL
;
324 if (!s_pszDefaultShell
)
326 #if defined(__OS2__) || defined(_WIN32) || defined(WINDOWS32)
327 static const char s_szShellName
[] = "/kmk_ash.exe";
329 static const char s_szShellName
[] = "/kmk_ash";
331 const char *pszBin
= get_kbuild_bin_path();
332 size_t cchBin
= strlen(pszBin
);
333 s_pszDefaultShell
= xmalloc(cchBin
+ sizeof(s_szShellName
));
334 memcpy(s_pszDefaultShell
, pszBin
, cchBin
);
335 memcpy(&s_pszDefaultShell
[cchBin
], s_szShellName
, sizeof(s_szShellName
));
337 return s_pszDefaultShell
;
343 * Applies the specified default path to any relative paths in *ppsz.
345 * @param pDefPath The default path.
346 * @param ppsz Pointer to the string pointer. If we expand anything, *ppsz
347 * will be replaced and the caller is responsible for calling free() on it.
348 * @param pcch IN: *pcch contains the current string length.
349 * OUT: *pcch contains the new string length.
350 * @param pcchAlloc *pcchAlloc contains the length allocated for the string. Can be NULL.
351 * @param fCanFree Whether *ppsz should be freed when we replace it.
354 kbuild_apply_defpath(struct variable
*pDefPath
, char **ppsz
, unsigned int *pcch
, unsigned int *pcchAlloc
, int fCanFree
)
356 const char *pszIterator
;
357 const char *pszInCur
;
358 unsigned int cchInCur
;
359 unsigned int cRelativePaths
;
362 * The first pass, count the relative paths.
366 while ((pszInCur
= find_next_token(&pszIterator
, &cchInCur
)))
369 #ifdef HAVE_DOS_PATHS
370 if (pszInCur
[0] != '/' && pszInCur
[0] != '\\' && (cchInCur
< 2 || pszInCur
[1] != ':'))
372 if (pszInCur
[0] != '/')
378 * The second pass construct the new string.
382 const size_t cchOut
= *pcch
+ cRelativePaths
* (pDefPath
->value_length
+ 1) + 1;
383 char *pszOut
= xmalloc(cchOut
);
384 char *pszOutCur
= pszOut
;
385 const char *pszInNextCopy
= *ppsz
;
389 while ((pszInCur
= find_next_token(&pszIterator
, &cchInCur
)))
392 #ifdef HAVE_DOS_PATHS
393 if (pszInCur
[0] != '/' && pszInCur
[0] != '\\' && (cchInCur
< 2 || pszInCur
[1] != ':'))
395 if (pszInCur
[0] != '/')
398 PATH_VAR(szAbsPathIn
);
399 PATH_VAR(szAbsPathOut
);
401 if (pDefPath
->value_length
+ cchInCur
+ 1 >= GET_PATH_MAX
)
404 /* Create the abspath input. */
405 memcpy(szAbsPathIn
, pDefPath
->value
, pDefPath
->value_length
);
406 szAbsPathIn
[pDefPath
->value_length
] = '/';
407 memcpy(&szAbsPathIn
[pDefPath
->value_length
+ 1], pszInCur
, cchInCur
);
408 szAbsPathIn
[pDefPath
->value_length
+ 1 + cchInCur
] = '\0';
410 if (abspath(szAbsPathIn
, szAbsPathOut
) != NULL
)
412 const size_t cchAbsPathOut
= strlen(szAbsPathOut
);
413 assert(cchAbsPathOut
<= pDefPath
->value_length
+ 1 + cchInCur
);
415 /* copy leading input */
416 if (pszInCur
!= pszInNextCopy
)
418 const size_t cchCopy
= pszInCur
- pszInNextCopy
;
419 memcpy(pszOutCur
, pszInNextCopy
, cchCopy
);
420 pszOutCur
+= cchCopy
;
422 pszInNextCopy
= pszInCur
+ cchInCur
;
424 /* copy out the abspath. */
425 memcpy(pszOutCur
, szAbsPathOut
, cchAbsPathOut
);
426 pszOutCur
+= cchAbsPathOut
;
430 /* the final copy (includes the nil). */
431 cchInCur
= *ppsz
+ *pcch
- pszInNextCopy
;
432 memcpy(pszOutCur
, pszInNextCopy
, cchInCur
);
433 pszOutCur
+= cchInCur
;
435 assert((size_t)(pszOutCur
- pszOut
) < cchOut
);
437 /* set return values */
441 *pcch
= pszOutCur
- pszOut
;
448 * Gets a variable that must exist.
449 * Will cause a fatal failure if the variable doesn't exist.
451 * @returns Pointer to the variable.
452 * @param pszName The variable name.
453 * @param cchName The name length.
455 MY_INLINE
struct variable
*
456 kbuild_get_variable_n(const char *pszName
, size_t cchName
)
458 struct variable
*pVar
= lookup_variable(pszName
, cchName
);
460 fatal(NILF
, _("variable `%.*s' isn't defined!"), (int)cchName
, pszName
);
462 fatal(NILF
, _("variable `%.*s' is defined as `recursive' instead of `simple'!"), (int)cchName
, pszName
);
464 MY_ASSERT_MSG(strlen(pVar
->value
) == pVar
->value_length
,
465 ("%u != %u %.*s\n", pVar
->value_length
, (unsigned int)strlen(pVar
->value
), (int)cchName
, pVar
->name
));
471 * Gets a variable that must exist and can be recursive.
472 * Will cause a fatal failure if the variable doesn't exist.
474 * @returns Pointer to the variable.
475 * @param pszName The variable name.
477 static struct variable
*
478 kbuild_get_recursive_variable(const char *pszName
)
480 struct variable
*pVar
= lookup_variable(pszName
, strlen(pszName
));
482 fatal(NILF
, _("variable `%s' isn't defined!"), pszName
);
484 MY_ASSERT_MSG(strlen(pVar
->value
) == pVar
->value_length
,
485 ("%u != %u %s\n", pVar
->value_length
, (unsigned int)strlen(pVar
->value
), pVar
->name
));
491 * Gets a variable that doesn't have to exit, but if it does can be recursive.
493 * @returns Pointer to the variable.
495 * @param pszName The variable name. Doesn't need to be terminated.
496 * @param cchName The name length.
498 static struct variable
*
499 kbuild_query_recursive_variable_n(const char *pszName
, size_t cchName
)
501 struct variable
*pVar
= lookup_variable(pszName
, cchName
);
502 MY_ASSERT_MSG(!pVar
|| strlen(pVar
->value
) == pVar
->value_length
,
503 ("%u != %u %.*s\n", pVar
->value_length
, (unsigned int)strlen(pVar
->value
), (int)cchName
, pVar
->name
));
509 * Gets a variable that doesn't have to exit, but if it does can be recursive.
511 * @returns Pointer to the variable.
513 * @param pszName The variable name.
515 static struct variable
*
516 kbuild_query_recursive_variable(const char *pszName
)
518 return kbuild_query_recursive_variable_n(pszName
, strlen(pszName
));
523 * Converts the specified variable into a 'simple' one.
525 * @param pVar The variable.
527 static struct variable
*
528 kbuild_simplify_variable(struct variable
*pVar
)
530 if (memchr(pVar
->value
, '$', pVar
->value_length
))
532 unsigned int value_len
;
533 char *pszExpanded
= allocated_variable_expand_2(pVar
->value
, pVar
->value_length
, &value_len
);
534 #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE
535 if (pVar
->rdonly_val
)
536 pVar
->rdonly_val
= 0;
540 assert(pVar
->origin
!= o_automatic
);
541 pVar
->value
= pszExpanded
;
542 pVar
->value_length
= value_len
;
543 pVar
->value_alloc_len
= value_len
+ 1;
551 * Looks up a variable.
552 * The value_length field is valid upon successful return.
554 * @returns Pointer to the variable. NULL if not found.
555 * @param pszName The variable name.
556 * @param cchName The name length.
558 MY_INLINE
struct variable
*
559 kbuild_lookup_variable_n(const char *pszName
, size_t cchName
)
561 struct variable
*pVar
= lookup_variable(pszName
, cchName
);
564 MY_ASSERT_MSG(strlen(pVar
->value
) == pVar
->value_length
,
565 ("%u != %u %.*s\n", pVar
->value_length
, (unsigned int)strlen(pVar
->value
), (int)cchName
, pVar
->name
));
567 /* Make sure the variable is simple, convert it if necessary. */
569 kbuild_simplify_variable(pVar
);
576 * Looks up a variable.
577 * The value_length field is valid upon successful return.
579 * @returns Pointer to the variable. NULL if not found.
580 * @param pszName The variable name.
582 MY_INLINE
struct variable
*
583 kbuild_lookup_variable(const char *pszName
)
585 return kbuild_lookup_variable_n(pszName
, strlen(pszName
));
590 * Looks up a variable and applies default a path to all relative paths.
591 * The value_length field is valid upon successful return.
593 * @returns Pointer to the variable. NULL if not found.
594 * @param pDefPath The default path.
595 * @param pszName The variable name.
596 * @param cchName The name length.
598 MY_INLINE
struct variable
*
599 kbuild_lookup_variable_defpath_n(struct variable
*pDefPath
, const char *pszName
, size_t cchName
)
601 struct variable
*pVar
= kbuild_lookup_variable_n(pszName
, cchName
);
602 if (pVar
&& pDefPath
)
604 assert(pVar
->origin
!= o_automatic
);
605 #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE
606 assert(!pVar
->rdonly_val
);
608 kbuild_apply_defpath(pDefPath
, &pVar
->value
, &pVar
->value_length
, &pVar
->value_alloc_len
, 1);
615 * Looks up a variable and applies default a path to all relative paths.
616 * The value_length field is valid upon successful return.
618 * @returns Pointer to the variable. NULL if not found.
619 * @param pDefPath The default path.
620 * @param pszName The variable name.
622 MY_INLINE
struct variable
*
623 kbuild_lookup_variable_defpath(struct variable
*pDefPath
, const char *pszName
)
625 struct variable
*pVar
= kbuild_lookup_variable(pszName
);
626 if (pVar
&& pDefPath
)
628 assert(pVar
->origin
!= o_automatic
);
629 #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE
630 assert(!pVar
->rdonly_val
);
632 kbuild_apply_defpath(pDefPath
, &pVar
->value
, &pVar
->value_length
, &pVar
->value_alloc_len
, 1);
639 * Gets the first defined property variable.
641 static struct variable
*
642 kbuild_first_prop(struct variable
*pTarget
, struct variable
*pSource
,
643 struct variable
*pTool
, struct variable
*pType
,
644 struct variable
*pBldTrg
, struct variable
*pBldTrgArch
,
645 const char *pszPropF1
, char cchPropF1
,
646 const char *pszPropF2
, char cchPropF2
,
647 const char *pszVarName
)
649 struct variable
*pVar
;
652 char *psz
, *psz1
, *psz2
, *psz3
, *psz4
, *pszEnd
;
654 /* calc and allocate a too big name buffer. */
655 cchBuf
= cchPropF2
+ 1
657 + pTarget
->value_length
+ 1
658 + pSource
->value_length
+ 1
659 + (pTool
? pTool
->value_length
+ 1 : 0)
660 + pType
->value_length
+ 1
661 + pBldTrg
->value_length
+ 1
662 + pBldTrgArch
->value_length
+ 1;
663 pszBuf
= xmalloc(cchBuf
);
665 #define ADD_VAR(pVar) do { my_memcpy(psz, (pVar)->value, (pVar)->value_length); psz += (pVar)->value_length; } while (0)
666 #define ADD_STR(pszStr, cchStr) do { my_memcpy(psz, (pszStr), (cchStr)); psz += (cchStr); } while (0)
667 #define ADD_CSTR(pszStr) do { my_memcpy(psz, pszStr, sizeof(pszStr) - 1); psz += sizeof(pszStr) - 1; } while (0)
668 #define ADD_CH(ch) do { *psz++ = (ch); } while (0)
671 * $(target)_$(source)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
680 ADD_STR(pszPropF2
, cchPropF2
);
686 ADD_VAR(pBldTrgArch
);
687 pVar
= kbuild_lookup_variable_n(pszBuf
, psz
- pszBuf
);
689 /* $(target)_$(source)_$(type)$(propf2).$(bld_trg) */
691 pVar
= kbuild_lookup_variable_n(pszBuf
, psz4
- pszBuf
);
693 /* $(target)_$(source)_$(type)$(propf2) */
695 pVar
= kbuild_lookup_variable_n(pszBuf
, psz3
- pszBuf
);
698 * $(target)_$(source)_$(propf2).$(bld_trg).$(bld_trg_arch)
703 ADD_STR(pszPropF2
, cchPropF2
);
709 ADD_VAR(pBldTrgArch
);
710 pVar
= kbuild_lookup_variable_n(pszBuf
, psz
- pszBuf
);
712 /* $(target)_$(source)_$(propf2).$(bld_trg) */
714 pVar
= kbuild_lookup_variable_n(pszBuf
, psz4
- pszBuf
);
716 /* $(target)_$(source)_$(propf2) */
718 pVar
= kbuild_lookup_variable_n(pszBuf
, psz3
- pszBuf
);
723 * $(source)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
732 ADD_STR(pszPropF2
, cchPropF2
);
738 ADD_VAR(pBldTrgArch
);
739 pVar
= kbuild_lookup_variable_n(pszBuf
, psz
- pszBuf
);
741 /* $(source)_$(type)$(propf2).$(bld_trg) */
743 pVar
= kbuild_lookup_variable_n(pszBuf
, psz4
- pszBuf
);
745 /* $(source)_$(type)$(propf2) */
747 pVar
= kbuild_lookup_variable_n(pszBuf
, psz3
- pszBuf
);
750 * $(source)_$(propf2).$(bld_trg).$(bld_trg_arch)
755 ADD_STR(pszPropF2
, cchPropF2
);
761 ADD_VAR(pBldTrgArch
);
762 pVar
= kbuild_lookup_variable_n(pszBuf
, psz
- pszBuf
);
764 /* $(source)_$(propf2).$(bld_trg) */
766 pVar
= kbuild_lookup_variable_n(pszBuf
, psz4
- pszBuf
);
768 /* $(source)_$(propf2) */
770 pVar
= kbuild_lookup_variable_n(pszBuf
, psz3
- pszBuf
);
775 * $(target)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
784 ADD_STR(pszPropF2
, cchPropF2
);
790 ADD_VAR(pBldTrgArch
);
791 pVar
= kbuild_lookup_variable_n(pszBuf
, psz
- pszBuf
);
793 /* $(target)_$(type)$(propf2).$(bld_trg) */
795 pVar
= kbuild_lookup_variable_n(pszBuf
, psz4
- pszBuf
);
797 /* $(target)_$(type)$(propf2) */
799 pVar
= kbuild_lookup_variable_n(pszBuf
, psz3
- pszBuf
);
801 /* $(target)_$(propf2).$(bld_trg).$(bld_trg_arch) */
805 ADD_STR(pszPropF2
, cchPropF2
);
811 ADD_VAR(pBldTrgArch
);
812 pVar
= kbuild_lookup_variable_n(pszBuf
, psz
- pszBuf
);
815 /* $(target)_$(propf2).$(bld_trg) */
817 pVar
= kbuild_lookup_variable_n(pszBuf
, psz4
- pszBuf
);
819 /* $(target)_$(propf2) */
821 pVar
= kbuild_lookup_variable_n(pszBuf
, psz3
- pszBuf
);
825 * TOOL_$(tool)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
835 ADD_STR(pszPropF2
, cchPropF2
);
841 ADD_VAR(pBldTrgArch
);
842 pVar
= kbuild_lookup_variable_n(pszBuf
, psz
- pszBuf
);
844 /* TOOL_$(tool)_$(type)$(propf2).$(bld_trg) */
846 pVar
= kbuild_lookup_variable_n(pszBuf
, psz4
- pszBuf
);
848 /* TOOL_$(tool)_$(type)$(propf2) */
850 pVar
= kbuild_lookup_variable_n(pszBuf
, psz3
- pszBuf
);
852 /* TOOL_$(tool)_$(propf2).$(bld_trg).$(bld_trg_arch) */
856 ADD_STR(pszPropF2
, cchPropF2
);
862 ADD_VAR(pBldTrgArch
);
863 pVar
= kbuild_lookup_variable_n(pszBuf
, psz
- pszBuf
);
865 /* TOOL_$(tool)_$(propf2).$(bld_trg) */
867 pVar
= kbuild_lookup_variable_n(pszBuf
, psz4
- pszBuf
);
869 /* TOOL_$(tool)_$(propf2) */
871 pVar
= kbuild_lookup_variable_n(pszBuf
, psz3
- pszBuf
);
876 * $(type)$(propf1).$(bld_trg).$(bld_trg_arch)
882 ADD_STR(pszPropF1
, cchPropF1
);
888 ADD_VAR(pBldTrgArch
);
889 pVar
= kbuild_lookup_variable_n(pszBuf
, psz
- pszBuf
);
891 /* $(type)$(propf1).$(bld_trg) */
893 pVar
= kbuild_lookup_variable_n(pszBuf
, psz4
- pszBuf
);
895 /* $(type)$(propf1) */
897 pVar
= kbuild_lookup_variable_n(pszBuf
, psz3
- pszBuf
);
900 * $(propf1).$(bld_trg).$(bld_trg_arch)
904 psz1
= pszBuf
+ pType
->value_length
;
905 pVar
= kbuild_lookup_variable_n(psz1
, psz
- psz1
);
907 /* $(propf1).$(bld_trg) */
909 pVar
= kbuild_lookup_variable_n(psz1
, psz4
- psz1
);
913 pVar
= kbuild_lookup_variable_n(pszPropF1
, cchPropF1
);
926 pszEnd
= psz
+ pVar
->value_length
;
927 while (isblank((unsigned char)*psz
))
929 while (pszEnd
> psz
&& isblank((unsigned char)pszEnd
[-1]))
933 char chSaved
= *pszEnd
;
935 pVar
= define_variable_vl(pszVarName
, strlen(pszVarName
), psz
, pszEnd
- psz
,
936 1 /* duplicate */, o_local
, 0 /* !recursive */);
947 _SOURCE_TOOL = $(strip $(firstword \
948 $($(target)_$(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
949 $($(target)_$(source)_$(type)TOOL.$(bld_trg)) \
950 $($(target)_$(source)_$(type)TOOL) \
951 $($(target)_$(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
952 $($(target)_$(source)_TOOL.$(bld_trg)) \
953 $($(target)_$(source)_TOOL) \
954 $($(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
955 $($(source)_$(type)TOOL.$(bld_trg)) \
956 $($(source)_$(type)TOOL) \
957 $($(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \
958 $($(source)_TOOL.$(bld_trg)) \
960 $($(target)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
961 $($(target)_$(type)TOOL.$(bld_trg)) \
962 $($(target)_$(type)TOOL) \
963 $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \
964 $($(target)_TOOL.$(bld_trg)) \
966 $($(type)TOOL.$(bld_trg).$(bld_trg_arch)) \
967 $($(type)TOOL.$(bld_trg)) \
969 $(TOOL.$(bld_trg).$(bld_trg_arch)) \
973 static struct variable
*
974 kbuild_get_source_tool(struct variable
*pTarget
, struct variable
*pSource
, struct variable
*pType
,
975 struct variable
*pBldTrg
, struct variable
*pBldTrgArch
, const char *pszVarName
)
977 struct variable
*pVar
= kbuild_first_prop(pTarget
, pSource
, NULL
, pType
, pBldTrg
, pBldTrgArch
,
978 "TOOL", sizeof("TOOL") - 1,
979 "TOOL", sizeof("TOOL") - 1,
982 fatal(NILF
, _("no tool for source `%s' in target `%s'!"), pSource
->value
, pTarget
->value
);
987 /* Implements _SOURCE_TOOL. */
989 func_kbuild_source_tool(char *o
, char **argv
, const char *pszFuncName
)
991 struct variable
*pVar
= kbuild_get_source_tool(kbuild_get_variable_n(ST("target")),
992 kbuild_get_variable_n(ST("source")),
993 kbuild_get_variable_n(ST("type")),
994 kbuild_get_variable_n(ST("bld_trg")),
995 kbuild_get_variable_n(ST("bld_trg_arch")),
998 o
= variable_buffer_output(o
, pVar
->value
, pVar
->value_length
);
1005 /* This has been extended a bit, it's now identical to _SOURCE_TOOL.
1007 $($(target)_$(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
1008 $($(target)_$(source)_OBJSUFF.$(bld_trg))\
1009 $($(target)_$(source)_OBJSUFF)\
1010 $($(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
1011 $($(source)_OBJSUFF.$(bld_trg))\
1012 $($(source)_OBJSUFF)\
1013 $($(target)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\
1014 $($(target)_OBJSUFF.$(bld_trg))\
1015 $($(target)_OBJSUFF)\
1016 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg).$(bld_trg_arch))\
1017 $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg))\
1018 $(TOOL_$(tool)_$(type)OBJSUFF)\
1021 static struct variable
*
1022 kbuild_get_object_suffix(struct variable
*pTarget
, struct variable
*pSource
,
1023 struct variable
*pTool
, struct variable
*pType
,
1024 struct variable
*pBldTrg
, struct variable
*pBldTrgArch
, const char *pszVarName
)
1026 struct variable
*pVar
= kbuild_first_prop(pTarget
, pSource
, pTool
, pType
, pBldTrg
, pBldTrgArch
,
1027 "SUFF_OBJ", sizeof("SUFF_OBJ") - 1,
1028 "OBJSUFF", sizeof("OBJSUFF") - 1,
1031 fatal(NILF
, _("no OBJSUFF attribute or SUFF_OBJ default for source `%s' in target `%s'!"), pSource
->value
, pTarget
->value
);
1038 func_kbuild_object_suffix(char *o
, char **argv
, const char *pszFuncName
)
1040 struct variable
*pVar
= kbuild_get_object_suffix(kbuild_get_variable_n(ST("target")),
1041 kbuild_get_variable_n(ST("source")),
1042 kbuild_get_variable_n(ST("tool")),
1043 kbuild_get_variable_n(ST("type")),
1044 kbuild_get_variable_n(ST("bld_trg")),
1045 kbuild_get_variable_n(ST("bld_trg_arch")),
1048 o
= variable_buffer_output(o
, pVar
->value
, pVar
->value_length
);
1056 ## Figure out where to put object files.
1057 # @param $1 source file
1058 # @param $2 normalized main target
1059 # @remark There are two major hacks here:
1060 # 1. Source files in the output directory are translated into a gen/ subdir.
1061 # 2. Catch anyone specifying $(PATH_SUB_CURRENT)/sourcefile.c.
1062 _OBJECT_BASE = $(PATH_TARGET)/$(2)/$(call no-root-slash,$(call no-drive,$(basename \
1063 $(patsubst $(PATH_ROOT)/%,%,$(patsubst $(PATH_SUB_CURRENT)/%,%,$(patsubst $(PATH_TARGET)/$(2)/%,gen/%,$(1)))))))
1065 static struct variable
*
1066 kbuild_get_object_base(struct variable
*pTarget
, struct variable
*pSource
, const char *pszVarName
)
1068 struct variable
*pPathTarget
= kbuild_get_variable_n(ST("PATH_TARGET"));
1069 struct variable
*pPathRoot
= kbuild_get_variable_n(ST("PATH_ROOT"));
1070 struct variable
*pPathSubCur
= kbuild_get_variable_n(ST("PATH_SUB_CURRENT"));
1071 const char *pszSrcPrefix
= NULL
;
1072 size_t cchSrcPrefix
= 0;
1074 const char *pszSrcEnd
;
1082 * Strip the source filename of any uncessary leading path and root specs.
1085 if ( pSource
->value_length
> pPathTarget
->value_length
1086 && !strncmp(pSource
->value
, pPathTarget
->value
, pPathTarget
->value_length
))
1088 pszSrc
= pSource
->value
+ pPathTarget
->value_length
;
1089 pszSrcPrefix
= "gen/";
1090 cchSrcPrefix
= sizeof("gen/") - 1;
1092 && !strncmp(pszSrc
+ 1, pTarget
->value
, pTarget
->value_length
)
1093 && ( pszSrc
[pTarget
->value_length
+ 1] == '/'
1094 || pszSrc
[pTarget
->value_length
+ 1] == '\0'))
1095 pszSrc
+= 1 + pTarget
->value_length
;
1097 else if ( pSource
->value_length
> pPathRoot
->value_length
1098 && !strncmp(pSource
->value
, pPathRoot
->value
, pPathRoot
->value_length
))
1100 pszSrc
= pSource
->value
+ pPathRoot
->value_length
;
1102 && !strncmp(pszSrc
+ 1, pPathSubCur
->value
, pPathSubCur
->value_length
)
1103 && ( pszSrc
[pPathSubCur
->value_length
+ 1] == '/'
1104 || pszSrc
[pPathSubCur
->value_length
+ 1] == '\0'))
1105 pszSrc
+= 1 + pPathSubCur
->value_length
;
1108 pszSrc
= pSource
->value
;
1110 /* skip root specification */
1111 #ifdef HAVE_DOS_PATHS
1112 if (isalpha(pszSrc
[0]) && pszSrc
[1] == ':')
1115 while (*pszSrc
== '/'
1116 #ifdef HAVE_DOS_PATHS
1122 /* drop the source extension. */
1123 pszSrcEnd
= pSource
->value
+ pSource
->value_length
;
1127 if ( pszSrcEnd
<= pszSrc
1128 || *pszSrcEnd
== '/'
1129 #ifdef HAVE_DOS_PATHS
1130 || *pszSrcEnd
== '\\'
1131 || *pszSrcEnd
== ':'
1135 pszSrcEnd
= pSource
->value
+ pSource
->value_length
;
1138 if (*pszSrcEnd
== '.')
1143 * Assemble the string on the heap and define the objbase variable
1144 * which we then return.
1146 cchSrc
= pszSrcEnd
- pszSrc
;
1147 cch
= pPathTarget
->value_length
1149 + pTarget
->value_length
1154 psz
= pszResult
= xmalloc(cch
);
1156 memcpy(psz
, pPathTarget
->value
, pPathTarget
->value_length
); psz
+= pPathTarget
->value_length
;
1158 memcpy(psz
, pTarget
->value
, pTarget
->value_length
); psz
+= pTarget
->value_length
;
1162 memcpy(psz
, pszSrcPrefix
, cchSrcPrefix
);
1163 psz
+= cchSrcPrefix
;
1166 memcpy(psz
, pszSrc
, cchSrc
); psz
+= cchSrc
;
1169 /* convert '..' path elements in the source to 'dt'. */
1170 while ((pszDot
= memchr(pszDot
, '.', psz
- pszDot
)) != NULL
)
1172 if ( pszDot
[1] == '.'
1174 || pszDot
[-1] == '/'
1175 #ifdef HAVE_DOS_PATHS
1176 || pszDot
[-1] == '\\'
1177 || pszDot
[-1] == ':'
1182 #ifdef HAVE_DOS_PATHS
1183 || pszDot
[2] == '\\'
1197 * Define the variable in the current set and return it.
1199 return define_variable_vl(pszVarName
, strlen(pszVarName
), pszResult
, cch
- 1,
1200 0 /* use pszResult */, o_local
, 0 /* !recursive */);
1204 /* Implements _OBJECT_BASE. */
1206 func_kbuild_object_base(char *o
, char **argv
, const char *pszFuncName
)
1208 struct variable
*pVar
= kbuild_get_object_base(kbuild_lookup_variable("target"),
1209 kbuild_lookup_variable("source"),
1212 o
= variable_buffer_output(o
, pVar
->value
, pVar
->value_length
);
1222 struct variable
*pa
;
1230 unsigned iTargetSource
;
1231 unsigned cTargetSource
;
1232 unsigned int cchMax
;
1236 /* Fills in the SDK struct (remember to free it). */
1238 kbuild_get_sdks(struct kbuild_sdks
*pSdks
, struct variable
*pTarget
, struct variable
*pSource
,
1239 struct variable
*pBldType
, struct variable
*pBldTrg
, struct variable
*pBldTrgArch
)
1247 const char *pszIterator
;
1249 /** @todo rewrite this to avoid sprintf and allocated_varaible_expand_2. */
1257 /* determin required tmp variable name space. */
1258 cchTmp
= sizeof("$(__SDKS) $(__SDKS.) $(__SDKS.) $(__SDKS.) $(__SDKS..)")
1259 + (pTarget
->value_length
+ pSource
->value_length
) * 5
1260 + pBldType
->value_length
1261 + pBldTrg
->value_length
1262 + pBldTrgArch
->value_length
1263 + pBldTrg
->value_length
+ pBldTrgArch
->value_length
;
1264 pszTmp
= alloca(cchTmp
);
1266 /* the global sdks. */
1269 cch
= sprintf(pszTmp
, "$(SDKS) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s.%s)",
1273 pBldTrg
->value
, pBldTrgArch
->value
);
1274 pszIterator
= pSdks
->apsz
[0] = allocated_variable_expand_2(pszTmp
, cch
, NULL
);
1275 while ((pszCur
= find_next_token(&pszIterator
, &cchCur
)) != 0)
1277 i
+= pSdks
->cGlobal
;
1279 /* the target sdks.*/
1282 cch
= sprintf(pszTmp
, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
1284 pTarget
->value
, pBldType
->value
,
1285 pTarget
->value
, pBldTrg
->value
,
1286 pTarget
->value
, pBldTrgArch
->value
,
1287 pTarget
->value
, pBldTrg
->value
, pBldTrgArch
->value
);
1288 pszIterator
= pSdks
->apsz
[1] = allocated_variable_expand_2(pszTmp
, cch
, NULL
);
1289 while ((pszCur
= find_next_token(&pszIterator
, &cchCur
)) != 0)
1291 i
+= pSdks
->cTarget
;
1293 /* the source sdks.*/
1296 cch
= sprintf(pszTmp
, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)",
1298 pSource
->value
, pBldType
->value
,
1299 pSource
->value
, pBldTrg
->value
,
1300 pSource
->value
, pBldTrgArch
->value
,
1301 pSource
->value
, pBldTrg
->value
, pBldTrgArch
->value
);
1302 pszIterator
= pSdks
->apsz
[2] = allocated_variable_expand_2(pszTmp
, cch
, NULL
);
1303 while ((pszCur
= find_next_token(&pszIterator
, &cchCur
)) != 0)
1305 i
+= pSdks
->cSource
;
1307 /* the target + source sdks. */
1308 pSdks
->iTargetSource
= i
;
1309 pSdks
->cTargetSource
= 0;
1310 cch
= sprintf(pszTmp
, "$(%s_%s_SDKS) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s.%s)",
1311 pTarget
->value
, pSource
->value
,
1312 pTarget
->value
, pSource
->value
, pBldType
->value
,
1313 pTarget
->value
, pSource
->value
, pBldTrg
->value
,
1314 pTarget
->value
, pSource
->value
, pBldTrgArch
->value
,
1315 pTarget
->value
, pSource
->value
, pBldTrg
->value
, pBldTrgArch
->value
);
1316 assert(cch
< cchTmp
); (void)cch
;
1317 pszIterator
= pSdks
->apsz
[3] = allocated_variable_expand_2(pszTmp
, cch
, NULL
);
1318 while ((pszCur
= find_next_token(&pszIterator
, &cchCur
)) != 0)
1319 pSdks
->cTargetSource
++;
1320 i
+= pSdks
->cTargetSource
;
1327 * Allocate the variable array and create the variables.
1329 pSdks
->pa
= (struct variable
*)xmalloc(sizeof(pSdks
->pa
[0]) * i
);
1330 memset(pSdks
->pa
, 0, sizeof(pSdks
->pa
[0]) * i
);
1331 for (i
= j
= 0; j
< sizeof(pSdks
->apsz
) / sizeof(pSdks
->apsz
[0]); j
++)
1333 pszIterator
= pSdks
->apsz
[j
];
1334 while ((pszCur
= find_next_token(&pszIterator
, &cchCur
)) != 0)
1336 pSdks
->pa
[i
].value
= pszCur
;
1337 pSdks
->pa
[i
].value_length
= cchCur
;
1341 assert(i
== pSdks
->c
);
1343 /* terminate them (find_next_token won't work if we terminate them in the previous loop). */
1346 pSdks
->pa
[i
].value
[pSdks
->pa
[i
].value_length
] = '\0';
1348 /* calc the max variable length too. */
1349 if (pSdks
->cchMax
< (unsigned int)pSdks
->pa
[i
].value_length
)
1350 pSdks
->cchMax
= pSdks
->pa
[i
].value_length
;
1355 /* releases resources allocated in the kbuild_get_sdks. */
1357 kbuild_put_sdks(struct kbuild_sdks
*pSdks
)
1360 for (j
= 0; j
< sizeof(pSdks
->apsz
) / sizeof(pSdks
->apsz
[0]); j
++)
1361 free(pSdks
->apsz
[j
]);
1366 /* this kind of stuff:
1368 defs := $(kb-src-exp defs)
1369 $(TOOL_$(tool)_DEFS)\
1370 $(TOOL_$(tool)_DEFS.$(bld_type))\
1371 $(TOOL_$(tool)_DEFS.$(bld_trg))\
1372 $(TOOL_$(tool)_DEFS.$(bld_trg_arch))\
1373 $(TOOL_$(tool)_DEFS.$(bld_trg).$(bld_trg_arch))\
1374 $(TOOL_$(tool)_DEFS.$(bld_trg_cpu))\
1375 $(TOOL_$(tool)_$(type)DEFS)\
1376 $(TOOL_$(tool)_$(type)DEFS.$(bld_type))\
1377 $(foreach sdk, $(SDKS.$(bld_trg)) \
1378 $(SDKS.$(bld_trg).$(bld_trg_arch)) \
1379 $(SDKS.$(bld_type)) \
1382 $(SDK_$(sdk)_DEFS.$(bld_type))\
1383 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1384 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1385 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1386 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1387 $(SDK_$(sdk)_$(type)DEFS)\
1388 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1389 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1390 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1391 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1392 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1394 $(DEFS.$(bld_type))\
1396 $(DEFS.$(bld_trg_arch))\
1397 $(DEFS.$(bld_trg).$(bld_trg_arch))\
1398 $(DEFS.$(bld_trg_cpu))\
1400 $($(type)DEFS.$(bld_type))\
1401 $($(type)DEFS.$(bld_trg))\
1402 $($(type)DEFS.$(bld_trg_arch))\
1403 $($(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1404 $($(type)DEFS.$(bld_trg_cpu))\
1405 $(foreach sdk, $($(target)_SDKS.$(bld_trg)) \
1406 $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1407 $($(target)_SDKS.$(bld_type)) \
1410 $(SDK_$(sdk)_DEFS.$(bld_type))\
1411 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1412 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1413 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1414 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1415 $(SDK_$(sdk)_$(type)DEFS)\
1416 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1417 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1418 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1419 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1420 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1422 $($(target)_DEFS.$(bld_type))\
1423 $($(target)_DEFS.$(bld_trg))\
1424 $($(target)_DEFS.$(bld_trg_arch))\
1425 $($(target)_DEFS.$(bld_trg).$(bld_trg_arch))\
1426 $($(target)_DEFS.$(bld_trg_cpu))\
1427 $($(target)_$(type)DEFS)\
1428 $($(target)_$(type)DEFS.$(bld_type))\
1429 $($(target)_$(type)DEFS.$(bld_trg))\
1430 $($(target)_$(type)DEFS.$(bld_trg_arch))\
1431 $($(target)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1432 $($(target)_$(type)DEFS.$(bld_trg_cpu))\
1433 $(foreach sdk, $($(source)_SDKS.$(bld_trg)) \
1434 $($(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1435 $($(source)_SDKS.$(bld_type)) \
1438 $(SDK_$(sdk)_DEFS.$(bld_type))\
1439 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1440 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1441 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1442 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1443 $(SDK_$(sdk)_$(type)DEFS)\
1444 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1445 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1446 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1447 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1448 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1450 $($(source)_DEFS.$(bld_type))\
1451 $($(source)_DEFS.$(bld_trg))\
1452 $($(source)_DEFS.$(bld_trg_arch))\
1453 $($(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
1454 $($(source)_DEFS.$(bld_trg_cpu))\
1455 $($(source)_$(type)DEFS)\
1456 $($(source)_$(type)DEFS.$(bld_type))\
1457 $($(source)_$(type)DEFS.$(bld_trg))\
1458 $($(source)_$(type)DEFS.$(bld_trg_arch))\
1459 $($(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1460 $($(source)_$(type)DEFS.$(bld_trg_cpu))\
1461 $(foreach sdk, $($(target)_$(source)_SDKS.$(bld_trg)) \
1462 $($(target)_$(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \
1463 $($(target)_$(source)_SDKS.$(bld_type)) \
1464 $($(target)_$(source)_SDKS),\
1466 $(SDK_$(sdk)_DEFS.$(bld_type))\
1467 $(SDK_$(sdk)_DEFS.$(bld_trg))\
1468 $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\
1469 $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\
1470 $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\
1471 $(SDK_$(sdk)_$(type)DEFS)\
1472 $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\
1473 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\
1474 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\
1475 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1476 $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\
1477 $($(target)_$(source)_DEFS)\
1478 $($(target)_$(source)_DEFS.$(bld_type))\
1479 $($(target)_$(source)_DEFS.$(bld_trg))\
1480 $($(target)_$(source)_DEFS.$(bld_trg_arch))\
1481 $($(target)_$(source)_DEFS.$(bld_trg).$(bld_trg_arch))\
1482 $($(target)_$(source)_DEFS.$(bld_trg_cpu))\
1483 $($(target)_$(source)_$(type)DEFS)\
1484 $($(target)_$(source)_$(type)DEFS.$(bld_type))\
1485 $($(target)_$(source)_$(type)DEFS.$(bld_trg))\
1486 $($(target)_$(source)_$(type)DEFS.$(bld_trg_arch))\
1487 $($(target)_$(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\
1488 $($(target)_$(source)_$(type)DEFS.$(bld_trg_cpu))
1490 static struct variable
*
1491 kbuild_collect_source_prop(struct variable
*pTarget
, struct variable
*pSource
,
1492 struct variable
*pTool
, struct kbuild_sdks
*pSdks
,
1493 struct variable
*pType
, struct variable
*pBldType
,
1494 struct variable
*pBldTrg
, struct variable
*pBldTrgArch
, struct variable
*pBldTrgCpu
,
1495 struct variable
*pDefPath
,
1496 const char *pszProp
, size_t cchProp
,
1497 const char *pszVarName
, size_t cchVarName
,
1500 struct variable
*pVar
;
1501 unsigned iSdk
, iSdkEnd
;
1503 size_t cchTotal
, cchBuf
;
1504 char *pszResult
, *pszBuf
, *psz
, *psz2
, *psz3
;
1507 struct variable
*pVar
;
1508 unsigned int cchExp
;
1512 assert(iDirection
== 1 || iDirection
== -1);
1515 * Calc and allocate a too big name buffer.
1517 cchBuf
= cchProp
+ 1
1518 + pTarget
->value_length
+ 1
1519 + pSource
->value_length
+ 1
1521 + (pTool
? pTool
->value_length
+ 1 : 0)
1522 + pType
->value_length
+ 1
1523 + pBldTrg
->value_length
+ 1
1524 + pBldTrgArch
->value_length
+ 1
1525 + pBldTrgCpu
->value_length
+ 1
1526 + pBldType
->value_length
+ 1;
1527 pszBuf
= xmalloc(cchBuf
);
1530 * Get the variables.
1532 * The compiler will get a heart attack when it sees this code ... ;-)
1534 cVars
= 12 * (pSdks
->c
+ 5);
1535 paVars
= alloca(cVars
* sizeof(paVars
[0]));
1540 #define ADD_VAR(pVar) do { my_memcpy(psz, (pVar)->value, (pVar)->value_length); psz += (pVar)->value_length; } while (0)
1541 #define ADD_STR(pszStr, cchStr) do { my_memcpy(psz, (pszStr), (cchStr)); psz += (cchStr); } while (0)
1542 #define ADD_CSTR(pszStr) do { my_memcpy(psz, pszStr, sizeof(pszStr) - 1); psz += sizeof(pszStr) - 1; } while (0)
1543 #define ADD_CH(ch) do { *psz++ = (ch); } while (0)
1544 #define DO_VAR_LOOKUP() \
1546 pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); \
1549 paVars[iVar].pVar = pVar; \
1550 if ( !pVar->recursive \
1551 || !memchr(pVar->value, '$', pVar->value_length)) \
1553 paVars[iVar].pszExp = pVar->value; \
1554 paVars[iVar].cchExp = pVar->value_length; \
1555 if (pDefPath && paVars[iVar].cchExp) \
1556 kbuild_apply_defpath(pDefPath, &paVars[iVar].pszExp, &paVars[iVar].cchExp, NULL, 0); \
1557 if (paVars[iVar].cchExp) \
1559 cchTotal += paVars[iVar].cchExp + 1; \
1565 paVars[iVar].pszExp = allocated_variable_expand_2(pVar->value, pVar->value_length, &paVars[iVar].cchExp); \
1566 if (pDefPath && paVars[iVar].cchExp) \
1567 kbuild_apply_defpath(pDefPath, &paVars[iVar].pszExp, &paVars[iVar].cchExp, NULL, 1); \
1568 if (paVars[iVar].cchExp) \
1570 cchTotal += paVars[iVar].cchExp + 1; \
1574 free(paVars[iVar].pszExp); \
1578 #define DO_SINGLE_PSZ3_VARIATION() \
1584 ADD_VAR(pBldType); \
1592 ADD_VAR(pBldTrgArch); \
1598 ADD_VAR(pBldTrgArch); \
1602 ADD_VAR(pBldTrgCpu); \
1606 #define DO_DOUBLE_PSZ2_VARIATION() \
1609 ADD_STR(pszProp, cchProp); \
1610 DO_SINGLE_PSZ3_VARIATION(); \
1612 /* add prop before type */ \
1615 ADD_STR(pszProp, cchProp); \
1616 DO_SINGLE_PSZ3_VARIATION(); \
1619 /* the tool (lowest priority). */
1624 DO_DOUBLE_PSZ2_VARIATION();
1627 /* the global sdks. */
1628 iSdkEnd
= iDirection
== 1 ? pSdks
->iGlobal
+ pSdks
->cGlobal
: pSdks
->iGlobal
- 1;
1629 for (iSdk
= iDirection
== 1 ? pSdks
->iGlobal
: pSdks
->iGlobal
+ pSdks
->cGlobal
- 1;
1633 struct variable
*pSdk
= &pSdks
->pa
[iSdk
];
1638 DO_DOUBLE_PSZ2_VARIATION();
1643 DO_DOUBLE_PSZ2_VARIATION();
1646 /* the target sdks. */
1647 iSdkEnd
= iDirection
== 1 ? pSdks
->iTarget
+ pSdks
->cTarget
: pSdks
->iTarget
- 1;
1648 for (iSdk
= iDirection
== 1 ? pSdks
->iTarget
: pSdks
->iTarget
+ pSdks
->cTarget
- 1;
1652 struct variable
*pSdk
= &pSdks
->pa
[iSdk
];
1657 DO_DOUBLE_PSZ2_VARIATION();
1664 DO_DOUBLE_PSZ2_VARIATION();
1666 /* the source sdks. */
1667 iSdkEnd
= iDirection
== 1 ? pSdks
->iSource
+ pSdks
->cSource
: pSdks
->iSource
- 1;
1668 for (iSdk
= iDirection
== 1 ? pSdks
->iSource
: pSdks
->iSource
+ pSdks
->cSource
- 1;
1672 struct variable
*pSdk
= &pSdks
->pa
[iSdk
];
1677 DO_DOUBLE_PSZ2_VARIATION();
1684 DO_DOUBLE_PSZ2_VARIATION();
1686 /* the target + source sdks. */
1687 iSdkEnd
= iDirection
== 1 ? pSdks
->iTargetSource
+ pSdks
->cTargetSource
: pSdks
->iTargetSource
- 1;
1688 for (iSdk
= iDirection
== 1 ? pSdks
->iTargetSource
: pSdks
->iTargetSource
+ pSdks
->cTargetSource
- 1;
1692 struct variable
*pSdk
= &pSdks
->pa
[iSdk
];
1697 DO_DOUBLE_PSZ2_VARIATION();
1700 /* the target + source. */
1706 DO_DOUBLE_PSZ2_VARIATION();
1710 assert(iVar
<= cVars
);
1714 * Construct the result value.
1716 if (!cVars
|| !cchTotal
)
1717 pVar
= define_variable_vl(pszVarName
, cchVarName
, "", 0,
1718 1 /* duplicate value */ , o_local
, 0 /* !recursive */);
1721 psz
= pszResult
= xmalloc(cchTotal
+ 1);
1722 if (iDirection
== 1)
1724 for (iVar
= 0; iVar
< cVars
; iVar
++)
1726 my_memcpy(psz
, paVars
[iVar
].pszExp
, paVars
[iVar
].cchExp
);
1727 psz
+= paVars
[iVar
].cchExp
;
1729 if (paVars
[iVar
].pszExp
!= paVars
[iVar
].pVar
->value
)
1730 free(paVars
[iVar
].pszExp
);
1738 my_memcpy(psz
, paVars
[iVar
].pszExp
, paVars
[iVar
].cchExp
);
1739 psz
+= paVars
[iVar
].cchExp
;
1741 if (paVars
[iVar
].pszExp
!= paVars
[iVar
].pVar
->value
)
1742 free(paVars
[iVar
].pszExp
);
1746 assert(psz
!= pszResult
);
1747 assert(cchTotal
== (size_t)(psz
- pszResult
));
1751 pVar
= define_variable_vl(pszVarName
, cchVarName
, pszResult
, cchTotal
,
1752 0 /* take pszResult */ , o_local
, 0 /* !recursive */);
1761 #undef DO_VAR_LOOKUP
1762 #undef DO_DOUBLE_PSZ2_VARIATION
1763 #undef DO_SINGLE_PSZ3_VARIATION
1767 /* get a source property. */
1769 func_kbuild_source_prop(char *o
, char **argv
, const char *pszFuncName
)
1771 struct variable
*pTarget
= kbuild_get_variable_n(ST("target"));
1772 struct variable
*pSource
= kbuild_get_variable_n(ST("source"));
1773 struct variable
*pDefPath
= NULL
;
1774 struct variable
*pType
= kbuild_get_variable_n(ST("type"));
1775 struct variable
*pTool
= kbuild_get_variable_n(ST("tool"));
1776 struct variable
*pBldType
= kbuild_get_variable_n(ST("bld_type"));
1777 struct variable
*pBldTrg
= kbuild_get_variable_n(ST("bld_trg"));
1778 struct variable
*pBldTrgArch
= kbuild_get_variable_n(ST("bld_trg_arch"));
1779 struct variable
*pBldTrgCpu
= kbuild_get_variable_n(ST("bld_trg_cpu"));
1780 struct variable
*pVar
;
1781 struct kbuild_sdks Sdks
;
1783 if (!strcmp(argv
[2], "left-to-right"))
1785 else if (!strcmp(argv
[2], "right-to-left"))
1788 fatal(NILF
, _("incorrect direction argument `%s'!"), argv
[2]);
1791 const char *psz
= argv
[3];
1792 while (isspace(*psz
))
1795 pDefPath
= kbuild_get_variable_n(ST("defpath"));
1798 kbuild_get_sdks(&Sdks
, pTarget
, pSource
, pBldType
, pBldTrg
, pBldTrgArch
);
1800 pVar
= kbuild_collect_source_prop(pTarget
, pSource
, pTool
, &Sdks
, pType
,
1801 pBldType
, pBldTrg
, pBldTrgArch
, pBldTrgCpu
,
1803 argv
[0], strlen(argv
[0]),
1804 argv
[1], strlen(argv
[1]),
1807 o
= variable_buffer_output(o
, pVar
->value
, pVar
->value_length
);
1809 kbuild_put_sdks(&Sdks
);
1816 dep := $(obj)$(SUFF_DEP)
1817 obj := $(outbase)$(objsuff)
1818 dirdep := $(call DIRDEP,$(dir $(outbase)))
1819 PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1821 static struct variable
*
1822 kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(struct variable
*pTarget
, struct variable
*pSource
,
1823 struct variable
*pOutBase
, struct variable
*pObjSuff
,
1824 const char *pszVarName
, struct variable
**ppDep
,
1825 struct variable
**ppDirDep
)
1827 struct variable
*pDepSuff
= kbuild_get_variable_n(ST("SUFF_DEP"));
1828 struct variable
*pObj
;
1829 size_t cch
= pOutBase
->value_length
+ pObjSuff
->value_length
+ pDepSuff
->value_length
+ 1;
1830 char *pszResult
= alloca(cch
);
1831 char *pszName
, *psz
;
1837 memcpy(psz
, pOutBase
->value
, pOutBase
->value_length
); psz
+= pOutBase
->value_length
;
1838 memcpy(psz
, pObjSuff
->value
, pObjSuff
->value_length
); psz
+= pObjSuff
->value_length
;
1839 memcpy(psz
, pDepSuff
->value
, pDepSuff
->value_length
+ 1);
1840 *ppDep
= define_variable_vl("dep", 3, pszResult
, cch
- 1, 1 /*dup*/, o_local
, 0 /* !recursive */);
1846 pObj
= define_variable_vl(pszVarName
, strlen(pszVarName
), pszResult
, psz
- pszResult
,
1847 1/* dup */, o_local
, 0 /* !recursive */);
1850 * PATH_$(target)_$(source) - this is global!
1852 /* calc variable name. */
1853 cch
= sizeof("PATH_")-1 + pTarget
->value_length
+ sizeof("_")-1 + pSource
->value_length
;
1854 psz
= pszName
= alloca(cch
+ 1);
1855 memcpy(psz
, "PATH_", sizeof("PATH_") - 1); psz
+= sizeof("PATH_") - 1;
1856 memcpy(psz
, pTarget
->value
, pTarget
->value_length
); psz
+= pTarget
->value_length
;
1858 memcpy(psz
, pSource
->value
, pSource
->value_length
+ 1);
1860 /* strip off the filename. */
1861 psz
= pszResult
+ pOutBase
->value_length
;
1865 if (psz
<= pszResult
)
1866 fatal(NULL
, "whut!?! no path? result=`%s'", pszResult
);
1867 #ifdef HAVE_DOS_PATHS
1875 #ifdef HAVE_DOS_PATHS
1880 while ( psz
- 1 > pszResult
1882 #ifdef HAVE_DOS_PATHS
1887 #ifdef HAVE_DOS_PATHS
1888 if (psz
== pszResult
+ 2 && pszResult
[1] == ':')
1896 /* set global variable */
1897 define_variable_vl_global(pszName
, cch
, pszResult
, psz
- pszResult
, 1/*dup*/, o_file
, 0 /* !recursive */, NILF
);
1903 #ifdef HAVE_DOS_PATHS
1912 *ppDirDep
= define_variable_vl("dirdep", 6, pszResult
, psz
- pszResult
, 1/*dup*/, o_local
, 0 /* !recursive */);
1918 /* setup the base variables for def_target_source_c_cpp_asm_new:
1920 X := $(kb-src-tool tool)
1921 x := $(kb-obj-base outbase)
1922 x := $(kb-obj-suff objsuff)
1923 obj := $(outbase)$(objsuff)
1924 PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase)))
1926 x := $(kb-src-prop DEFS,defs,left-to-right)
1927 x := $(kb-src-prop INCS,incs,right-to-left)
1928 x := $(kb-src-prop FLAGS,flags,right-to-left)
1930 x := $(kb-src-prop DEPS,deps,left-to-right)
1931 dirdep := $(call DIRDEP,$(dir $(outbase)))
1932 dep := $(obj)$(SUFF_DEP)
1935 func_kbuild_source_one(char *o
, char **argv
, const char *pszFuncName
)
1937 static int s_fNoCompileCmdsDepsDefined
= -1;
1938 struct variable
*pTarget
= kbuild_get_variable_n(ST("target"));
1939 struct variable
*pSource
= kbuild_get_variable_n(ST("source"));
1940 struct variable
*pDefPath
= kbuild_get_variable_n(ST("defpath"));
1941 struct variable
*pType
= kbuild_get_variable_n(ST("type"));
1942 struct variable
*pBldType
= kbuild_get_variable_n(ST("bld_type"));
1943 struct variable
*pBldTrg
= kbuild_get_variable_n(ST("bld_trg"));
1944 struct variable
*pBldTrgArch
= kbuild_get_variable_n(ST("bld_trg_arch"));
1945 struct variable
*pBldTrgCpu
= kbuild_get_variable_n(ST("bld_trg_cpu"));
1946 struct variable
*pTool
= kbuild_get_source_tool(pTarget
, pSource
, pType
, pBldTrg
, pBldTrgArch
, "tool");
1947 struct variable
*pOutBase
= kbuild_get_object_base(pTarget
, pSource
, "outbase");
1948 struct variable
*pObjSuff
= kbuild_get_object_suffix(pTarget
, pSource
, pTool
, pType
, pBldTrg
, pBldTrgArch
, "objsuff");
1949 struct variable
*pDefs
, *pIncs
, *pFlags
, *pDeps
, *pOrderDeps
, *pDirDep
, *pDep
, *pVar
, *pOutput
, *pOutputMaybe
;
1950 struct variable
*pObj
= kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(pTarget
, pSource
, pOutBase
, pObjSuff
, "obj", &pDep
, &pDirDep
);
1951 int fInstallOldVars
= 0;
1952 char *pszDstVar
, *pszDst
, *pszSrcVar
, *pszSrc
, *pszVal
, *psz
;
1953 char *pszSavedVarBuf
;
1954 unsigned cchSavedVarBuf
;
1956 struct kbuild_sdks Sdks
;
1960 * argv[0] is the function version. Prior to r1792 (early 0.1.5) this
1961 * was undefined and footer.kmk always passed an empty string.
1963 * Version 2, as implemented in r1797, will make use of the async
1964 * includedep queue feature. This means the files will be read by one or
1965 * more background threads, leaving the eval'ing to be done later on by
1966 * the main thread (in snap_deps).
1971 switch (argv
[0][0] | (argv
[0][1] << 8))
1973 case '2': iVer
= 2; break;
1974 case '3': iVer
= 3; break;
1975 case '4': iVer
= 4; break;
1976 case '5': iVer
= 5; break;
1977 case '6': iVer
= 6; break;
1978 case '7': iVer
= 7; break;
1979 case '8': iVer
= 8; break;
1980 case '9': iVer
= 9; break;
1981 case '0': iVer
= 0; break;
1982 case '1': iVer
= 1; break;
1986 while (isblank((unsigned char)*psz
))
1994 * Gather properties.
1996 kbuild_get_sdks(&Sdks
, pTarget
, pSource
, pBldType
, pBldTrg
, pBldTrgArch
);
1998 if (pDefPath
&& !pDefPath
->value_length
)
2000 pDefs
= kbuild_collect_source_prop(pTarget
, pSource
, pTool
, &Sdks
, pType
, pBldType
, pBldTrg
, pBldTrgArch
, pBldTrgCpu
, NULL
,
2001 ST("DEFS"), ST("defs"), 1/* left-to-right */);
2002 pIncs
= kbuild_collect_source_prop(pTarget
, pSource
, pTool
, &Sdks
, pType
, pBldType
, pBldTrg
, pBldTrgArch
, pBldTrgCpu
, pDefPath
,
2003 ST("INCS"), ST("incs"), -1/* right-to-left */);
2004 pFlags
= kbuild_collect_source_prop(pTarget
, pSource
, pTool
, &Sdks
, pType
, pBldType
, pBldTrg
, pBldTrgArch
, pBldTrgCpu
, NULL
,
2005 ST("FLAGS"), ST("flags"), 1/* left-to-right */);
2006 pDeps
= kbuild_collect_source_prop(pTarget
, pSource
, pTool
, &Sdks
, pType
, pBldType
, pBldTrg
, pBldTrgArch
, pBldTrgCpu
, pDefPath
,
2007 ST("DEPS"), ST("deps"), 1/* left-to-right */);
2008 pOrderDeps
= kbuild_collect_source_prop(pTarget
, pSource
, pTool
, &Sdks
, pType
, pBldType
, pBldTrg
, pBldTrgArch
, pBldTrgCpu
, pDefPath
,
2009 ST("ORDERDEPS"), ST("orderdeps"), 1/* left-to-right */);
2012 * If we've got a default path, we must expand the source now.
2013 * If we do this too early, "<source>_property = stuff" won't work becuase
2014 * our 'source' value isn't what the user expects.
2018 /** @todo assert(pSource->origin != o_automatic); We're changing 'source'
2019 * from the foreach loop! */
2020 #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE
2021 assert(!pSource
->rdonly_val
);
2023 kbuild_apply_defpath(pDefPath
, &pSource
->value
, &pSource
->value_length
, &pSource
->value_alloc_len
, 1 /* can free */);
2028 ifndef NO_COMPILE_CMDS_DEPS
2029 _DEPFILES_INCLUDED += $(dep)
2030 $(if $(wildcard $(dep)),$(eval include $(dep)))
2033 if (s_fNoCompileCmdsDepsDefined
== -1)
2034 s_fNoCompileCmdsDepsDefined
= kbuild_lookup_variable_n(ST("NO_COMPILE_CMDS_DEPS")) != NULL
;
2035 if (!s_fNoCompileCmdsDepsDefined
)
2037 pVar
= kbuild_query_recursive_variable_n("_DEPFILES_INCLUDED", sizeof("_DEPFILES_INCLUDED") - 1);
2040 if (pVar
->recursive
)
2041 pVar
= kbuild_simplify_variable(pVar
);
2042 append_string_to_variable(pVar
, pDep
->value
, pDep
->value_length
, 1 /* append */);
2045 define_variable_vl_global("_DEPFILES_INCLUDED", sizeof("_DEPFILES_INCLUDED") - 1,
2046 pDep
->value
, pDep
->value_length
,
2047 1 /* duplicate_value */,
2052 eval_include_dep(pDep
->value
, NILF
, iVer
>= 2 ? incdep_queue
: incdep_read_it
);
2057 $(target)_$(source)_CMDS_ := $(TOOL_$(tool)_COMPILE_$(type)_CMDS)
2058 $(target)_$(source)_OUTPUT_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT)
2059 $(target)_$(source)_OUTPUT_MAYBE_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT_MAYBE)
2060 $(target)_$(source)_DEPEND_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPEND) $(deps) $(source)
2061 $(target)_$(source)_DEPORD_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPORD) $(dirdep)
2063 /** @todo Make all these local variables, if someone needs the info later it
2064 * can be recalculated. (Ticket #80.) */
2065 cch
= sizeof("TOOL_") + pTool
->value_length
+ sizeof("_COMPILE_") + pType
->value_length
+ sizeof("_OUTPUT_MAYBE");
2066 if (cch
< pTarget
->value_length
+ sizeof("$(_2_OBJS)"))
2067 cch
= pTarget
->value_length
+ sizeof("$(_2_OBJS)");
2068 psz
= pszSrcVar
= alloca(cch
);
2069 memcpy(psz
, "TOOL_", sizeof("TOOL_") - 1); psz
+= sizeof("TOOL_") - 1;
2070 memcpy(psz
, pTool
->value
, pTool
->value_length
); psz
+= pTool
->value_length
;
2071 memcpy(psz
, "_COMPILE_", sizeof("_COMPILE_") - 1); psz
+= sizeof("_COMPILE_") - 1;
2072 memcpy(psz
, pType
->value
, pType
->value_length
); psz
+= pType
->value_length
;
2075 cch
= pTarget
->value_length
+ 1 + pSource
->value_length
+ sizeof("_OUTPUT_MAYBE_");
2076 psz
= pszDstVar
= alloca(cch
);
2077 memcpy(psz
, pTarget
->value
, pTarget
->value_length
); psz
+= pTarget
->value_length
;
2079 memcpy(psz
, pSource
->value
, pSource
->value_length
); psz
+= pSource
->value_length
;
2082 memcpy(pszSrc
, "_CMDS", sizeof("_CMDS"));
2083 memcpy(pszDst
, "_CMDS_", sizeof("_CMDS_"));
2084 pVar
= kbuild_get_recursive_variable(pszSrcVar
);
2085 do_variable_definition_2(NILF
, pszDstVar
, pVar
->value
, pVar
->value_length
,
2086 !pVar
->recursive
, 0, o_file
, f_simple
, 0 /* !target_var */);
2088 memcpy(pszSrc
, "_OUTPUT", sizeof("_OUTPUT"));
2089 memcpy(pszDst
, "_OUTPUT_", sizeof("_OUTPUT_"));
2090 pVar
= kbuild_get_recursive_variable(pszSrcVar
);
2091 pOutput
= do_variable_definition_2(NILF
, pszDstVar
, pVar
->value
, pVar
->value_length
,
2092 !pVar
->recursive
, 0, o_file
, f_simple
, 0 /* !target_var */);
2094 memcpy(pszSrc
, "_OUTPUT_MAYBE", sizeof("_OUTPUT_MAYBE"));
2095 memcpy(pszDst
, "_OUTPUT_MAYBE_", sizeof("_OUTPUT_MAYBE_"));
2096 pVar
= kbuild_query_recursive_variable(pszSrcVar
);
2098 pOutputMaybe
= do_variable_definition_2(NILF
, pszDstVar
, pVar
->value
, pVar
->value_length
,
2099 !pVar
->recursive
, 0, o_file
, f_simple
, 0 /* !target_var */);
2101 pOutputMaybe
= do_variable_definition_2(NILF
, pszDstVar
, "", 0, 1, 0, o_file
, f_simple
, 0 /* !target_var */);
2103 memcpy(pszSrc
, "_DEPEND", sizeof("_DEPEND"));
2104 memcpy(pszDst
, "_DEPEND_", sizeof("_DEPEND_"));
2105 pVar
= kbuild_get_recursive_variable(pszSrcVar
);
2106 psz
= pszVal
= xmalloc(pVar
->value_length
+ 1 + pDeps
->value_length
+ 1 + pSource
->value_length
+ 1);
2107 memcpy(psz
, pVar
->value
, pVar
->value_length
); psz
+= pVar
->value_length
;
2109 memcpy(psz
, pDeps
->value
, pDeps
->value_length
); psz
+= pDeps
->value_length
;
2111 memcpy(psz
, pSource
->value
, pSource
->value_length
+ 1);
2112 do_variable_definition_2(NILF
, pszDstVar
, pszVal
, pVar
->value_length
+ 1 + pDeps
->value_length
+ 1 + pSource
->value_length
,
2113 !pVar
->recursive
&& !pDeps
->recursive
&& !pSource
->recursive
,
2114 pszVal
, o_file
, f_simple
, 0 /* !target_var */);
2116 memcpy(pszSrc
, "_DEPORD", sizeof("_DEPORD"));
2117 memcpy(pszDst
, "_DEPORD_", sizeof("_DEPORD_"));
2118 pVar
= kbuild_get_recursive_variable(pszSrcVar
);
2119 psz
= pszVal
= xmalloc(pVar
->value_length
+ 1 + pDirDep
->value_length
+ 1 + pOrderDeps
->value_length
+ 1);
2120 memcpy(psz
, pVar
->value
, pVar
->value_length
); psz
+= pVar
->value_length
;
2122 memcpy(psz
, pDirDep
->value
, pDirDep
->value_length
); psz
+= pDirDep
->value_length
;
2124 memcpy(psz
, pOrderDeps
->value
, pOrderDeps
->value_length
+ 1);
2125 do_variable_definition_2(NILF
, pszDstVar
, pszVal
,
2126 pVar
->value_length
+ 1 + pDirDep
->value_length
+ 1 + pOrderDeps
->value_length
,
2127 !pVar
->recursive
&& !pDirDep
->recursive
&& !pOrderDeps
->recursive
,
2128 pszVal
, o_file
, f_simple
, 0 /* !target_var */);
2131 _OUT_FILES += $($(target)_$(source)_OUTPUT_) $($(target)_$(source)_OUTPUT_MAYBE_)
2133 pVar
= kbuild_get_variable_n(ST("_OUT_FILES"));
2134 append_string_to_variable(pVar
, pOutput
->value
, pOutput
->value_length
, 1 /* append */);
2135 if (pOutputMaybe
->value_length
)
2136 append_string_to_variable(pVar
, pOutputMaybe
->value
, pOutputMaybe
->value_length
, 1 /* append */);
2139 $(target)_2_OBJS += $(obj)
2141 memcpy(pszDstVar
+ pTarget
->value_length
, "_2_OBJS", sizeof("_2_OBJS"));
2142 pVar
= kbuild_query_recursive_variable_n(pszDstVar
, pTarget
->value_length
+ sizeof("_2_OBJS") - 1);
2143 fInstallOldVars
|= iVer
<= 2 && (!pVar
|| !pVar
->value_length
);
2146 if (pVar
->recursive
)
2147 pVar
= kbuild_simplify_variable(pVar
);
2148 append_string_to_variable(pVar
, pObj
->value
, pObj
->value_length
, 1 /* append */);
2151 define_variable_vl_global(pszDstVar
, pTarget
->value_length
+ sizeof("_2_OBJS") - 1,
2152 pObj
->value
, pObj
->value_length
,
2153 1 /* duplicate_value */,
2159 * Install legacy variables.
2161 if (fInstallOldVars
)
2163 /* $(target)_OBJS_ = $($(target)_2_OBJS)*/
2164 memcpy(pszDstVar
+ pTarget
->value_length
, "_OBJS_", sizeof("_OBJS_"));
2168 memcpy(pszSrcVar
+ 2, pTarget
->value
, pTarget
->value_length
);
2169 psz
= pszSrcVar
+ 2 + pTarget
->value_length
;
2170 memcpy(psz
, "_2_OBJS)", sizeof("_2_OBJS)"));
2172 define_variable_vl_global(pszDstVar
, pTarget
->value_length
+ sizeof("_OBJS_") - 1,
2173 pszSrcVar
, pTarget
->value_length
+ sizeof("$(_2_OBJS)") - 1,
2174 1 /* duplicate_value */,
2181 $(eval $(def_target_source_rule))
2183 pVar
= kbuild_get_recursive_variable("def_target_source_rule");
2184 pszVal
= variable_expand_string_2 (o
, pVar
->value
, pVar
->value_length
, &psz
);
2185 assert(!((size_t)pszVal
& 3));
2187 install_variable_buffer(&pszSavedVarBuf
, &cchSavedVarBuf
);
2188 eval_buffer(pszVal
, psz
);
2189 restore_variable_buffer(pszSavedVarBuf
, cchSavedVarBuf
);
2191 kbuild_put_sdks(&Sdks
);
2200 ## Inherit one template property in a non-accumulative manner.
2201 # @param $(prop) Property name
2202 # @param $(target) Target name
2203 # @todo fix the precedence order for some properties.
2204 define def_inherit_template_one
2205 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop)
2206 ifndef $(target)_$(prop)
2207 $(target)_$(prop) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop))
2210 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)
2211 ifndef $(target)_$(prop).$(bld_trg)
2212 $(target)_$(prop).$(bld_trg) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg))
2215 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)
2216 ifndef $(target)_$(prop).$(bld_trg).$(bld_trg_arch)
2217 $(target)_$(prop).$(bld_trg).$(bld_trg_arch) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch))
2220 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)
2221 ifndef $(target)_$(prop).$(bld_trg_arch)
2222 $(target)_$(prop).$(bld_trg_arch) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch))
2225 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)
2226 ifndef $(target)_$(prop).$(bld_trg_cpu)
2227 $(target)_$(prop).$(bld_trg_cpu) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu))
2232 ## Inherit one template property in a non-accumulative manner, deferred expansion.
2233 # @param 1: $(prop) Property name
2234 # @param 2: $(target) Target name
2235 # @todo fix the precedence order for some properties.
2236 # @remark this define relies on double evaluation
2237 define def_inherit_template_one_deferred
2238 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop)
2239 ifndef $(target)_$(prop)
2240 $(target)_$(prop) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop))
2243 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)
2244 ifndef $(target)_$(prop).$(bld_trg)
2245 $(target)_$(prop).$(bld_trg) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg))
2248 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)
2249 ifndef $(target)_$(prop).$(bld_trg).$(bld_trg_arch)
2250 $(target)_$(prop).$(bld_trg).$(bld_trg_arch) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch))
2253 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)
2254 ifndef $(target)_$(prop).$(bld_trg_arch)
2255 $(target)_$(prop).$(bld_trg_arch) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch))
2258 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)
2259 ifndef $(target)_$(prop).$(bld_trg_cpu)
2260 $(target)_$(prop).$(bld_trg_cpu) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu))
2265 ## Inherit one acculumlative template property where the 'most significant' items are at the left end.
2266 # @param $(prop) Property name
2267 # @param $(target) Target name
2268 define def_inherit_template_one_accumulate_l
2269 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop)
2270 ifeq ($$(flavor $(target)_$(prop)),simple)
2271 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop))
2273 $(target)_$(prop) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop))
2275 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE)
2276 ifeq ($$(flavor $(target)_$(prop).$(KBUILD_TYPE)),simple)
2277 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(KBUILD_TYPE))
2279 $(target)_$(prop).$(KBUILD_TYPE) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE))
2281 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)
2282 ifeq ($$(flavor $(target)_$(prop).$(bld_trg)),simple)
2283 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg))
2285 $(target)_$(prop).$(bld_trg) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg))
2287 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)
2288 ifeq ($$(flavor $(target)_$(prop).$(bld_trg).$(bld_trg_arch)),simple)
2289 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg).$(bld_trg_arch))
2291 $(target)_$(prop).$(bld_trg).$(bld_trg_arch) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch))
2293 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)
2294 ifeq ($$(flavor $(target)_$(prop).$(bld_trg_cpu)),simple)
2295 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg_cpu))
2297 $(target)_$(prop).$(bld_trg_cpu) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu))
2299 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)
2300 ifeq ($$(flavor $(target)_$(prop).$(bld_trg_arch)),simple)
2301 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg_arch))
2303 $(target)_$(prop).$(bld_trg_arch) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch))
2307 ## Inherit one acculumlative template property where the 'most significant' items are at the right end.
2308 # @param $(prop) Property name
2309 # @param $(target) Target name
2310 define def_inherit_template_one_accumulate_r
2311 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop)
2312 ifeq ($$(flavor $(target)_$(prop)),simple)
2313 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop))
2315 $(target)_$(prop) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop))
2317 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE)
2318 ifeq ($$(flavor $(target)_$(prop).$(KBUILD_TYPE)),simple)
2319 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(KBUILD_TYPE))
2321 $(target)_$(prop).$(KBUILD_TYPE) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE))
2323 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)
2324 ifeq ($$(flavor $(target)_$(prop).$(bld_trg)),simple)
2325 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg))
2327 $(target)_$(prop).$(bld_trg) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg))
2329 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)
2330 ifeq ($$(flavor $(target)_$(prop).$(bld_trg).$(bld_trg_arch)),simple)
2331 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg).$(bld_trg_arch))
2333 $(target)_$(prop).$(bld_trg).$(bld_trg_arch) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch))
2335 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)
2336 ifeq ($$(flavor $(target)_$(prop).$(bld_trg_cpu)),simple)
2337 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg_cpu))
2339 $(target)_$(prop).$(bld_trg_cpu) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu))
2341 ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)
2342 ifeq ($$(flavor $(target)_$(prop).$(bld_trg_arch)),simple)
2343 $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg_arch))
2345 $(target)_$(prop).$(bld_trg_arch) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch))
2350 ## Inherit template properties for on target.
2351 # @param $(target) Target name.
2352 define def_inherit_template
2354 ifdef _$(target)_ALREADY_PROCESSED
2355 $(error kBuild: The target $(target) appears more than once in the target lists! Please correct the makefile(s))
2357 _$(target)_ALREADY_PROCESSED := 1
2359 # Inherit any default template.
2361 ifeq ($($(target)_TEMPLATE),)
2362 $(eval $(target)_TEMPLATE:=$(TEMPLATE))
2365 # Expand the template if specified.
2366 ifneq ($($(target)_TEMPLATE),)
2367 $(foreach prop,$(PROPS_SINGLE),$(evalval def_inherit_template_one))
2368 $(foreach prop,$(PROPS_DEFERRED),$(eval $(def_inherit_template_one_deferred))) # exploits the 2 evaluation, so no value!
2369 $(foreach prop,$(PROPS_ACCUMULATE_L),$(eval $(def_inherit_template_one_accumulate_l))) # += works fine without value
2370 $(foreach prop,$(PROPS_ACCUMULATE_R),$(eval $(def_inherit_template_one_accumulate_r))) # use <= (kmk addition)
2376 $(kb-exp-tmpl 1,$(_ALL_TARGET_TARGETS),$(KBUILD_TARGET),$(KBUILD_TARGET_ARCH),$(KBUILD_TARGET_CPU),$(KBUILD_TYPE))
2379 func_kbuild_expand_template(char *o
, char **argv
, const char *pszFuncName
)
2381 const char *pszVersion
= argv
[0];
2382 const char *pszBldTrg
= argv
[2];
2383 const char *pszBldTrgArch
= argv
[3];
2384 const char *pszBldTrgCpu
= argv
[4];
2385 const char *pszBldType
= argv
[5];
2386 size_t cchBldTrg
= strlen(pszBldTrg
);
2387 size_t cchBldTrgArch
= strlen(pszBldTrgArch
);
2388 size_t cchBldTrgCpu
= strlen(pszBldTrgCpu
);
2389 size_t cchBldType
= strlen(pszBldType
);
2390 size_t cchMaxBld
= cchBldTrg
+ cchBldTrgArch
+ cchBldTrgCpu
+ cchBldType
; /* too big, but so what. */
2396 unsigned int const cKeys
= 6;
2398 struct variable
*pDefTemplate
;
2399 struct variable
*pProps
;
2404 enum kbet_prop_enum
{ kPropSingle
, kPropDeferred
, kPropAccumulateL
, kPropAccumulateR
}
2407 unsigned int cProps
;
2410 struct variable
*pVarTrg
;
2411 struct variable
*pVarSrc
;
2412 const char *pszIter
;
2413 const char *pszTarget
;
2414 unsigned int cchTarget
;
2416 char *pszSrcRef
= 0;
2417 char *pszSrcBuf
= 0;
2418 size_t cchSrcBuf
= 0;
2425 if (pszVersion
[0] != '1' || pszVersion
[1])
2426 fatal(NULL
, "%s: Unsupported version `%s'", pszFuncName
, pszVersion
);
2429 fatal(NULL
, "%s: missing bldtrg", pszFuncName
);
2432 fatal(NULL
, "%s: missing bld_trg_arch", pszFuncName
);
2435 fatal(NULL
, "%s: missing bld_trg_cpu", pszFuncName
);
2438 fatal(NULL
, "%s: missing bld_type", pszFuncName
);
2441 * Prepare the keywords, prepending dots for quicker copying.
2442 * This allows for an inner loop when processing properties, saving code
2443 * at the expense of a few xmallocs.
2445 /* the first entry is empty. */
2447 aKeys
[0].psz
= NULL
;
2449 aKeys
[1].cch
= cchBldType
+ 1;
2450 aKeys
[1].psz
= xmalloc (aKeys
[1].cch
+ 1);
2451 aKeys
[1].psz
[0] = '.';
2452 memcpy(aKeys
[1].psz
+ 1, pszBldType
, cchBldType
+ 1);
2454 aKeys
[2].cch
= cchBldTrg
+ 1;
2455 aKeys
[2].psz
= xmalloc (aKeys
[2].cch
+ 1);
2456 aKeys
[2].psz
[0] = '.';
2457 memcpy(aKeys
[2].psz
+ 1, pszBldTrg
, cchBldTrg
+ 1);
2459 aKeys
[3].cch
= cchBldTrg
+ 1 + cchBldTrgArch
+ 1;
2460 aKeys
[3].psz
= xmalloc (aKeys
[3].cch
+ 1);
2461 aKeys
[3].psz
[0] = '.';
2462 memcpy(aKeys
[3].psz
+ 1, pszBldTrg
, cchBldTrg
);
2463 aKeys
[3].psz
[1 + cchBldTrg
] = '.';
2464 memcpy(aKeys
[3].psz
+ 1 + cchBldTrg
+ 1, pszBldTrgArch
, cchBldTrgArch
+ 1);
2466 aKeys
[4].cch
= cchBldTrgCpu
+ 1;
2467 aKeys
[4].psz
= xmalloc (aKeys
[4].cch
+ 1);
2468 aKeys
[4].psz
[0] = '.';
2469 memcpy(aKeys
[4].psz
+ 1, pszBldTrgCpu
, cchBldTrgCpu
+ 1);
2471 aKeys
[5].cch
= cchBldTrgArch
+ 1;
2472 aKeys
[5].psz
= xmalloc (aKeys
[5].cch
+ 1);
2473 aKeys
[5].psz
[0] = '.';
2474 memcpy(aKeys
[5].psz
+ 1, pszBldTrgArch
, cchBldTrgArch
+ 1);
2478 * Prepare the properties, folding them into an array.
2479 * This way we won't have to reparse them for each an every target, though
2480 * it comes at the expense of one or more heap calls.
2482 #define PROP_ALLOC_INC 128
2484 cProps
= PROP_ALLOC_INC
;
2485 paProps
= xmalloc(sizeof(*pProps
) * cProps
);
2487 pProps
= kbuild_get_variable_n(ST("PROPS_SINGLE"));
2488 pszIter
= pProps
->value
;
2489 while ((paProps
[iProp
].pch
= find_next_token(&pszIter
, &paProps
[iProp
].cch
)))
2491 paProps
[iProp
].enmType
= kPropSingle
;
2492 if (++iProp
>= cProps
)
2494 cProps
+= PROP_ALLOC_INC
;
2495 paProps
= xrealloc(paProps
, sizeof(*paProps
) * cProps
);
2500 pProps
= kbuild_get_variable_n(ST("PROPS_DEFERRED"));
2501 pszIter
= pProps
->value
;
2502 while ((paProps
[iProp
].pch
= find_next_token(&pszIter
, &paProps
[iProp
].cch
)))
2504 paProps
[iProp
].enmType
= kPropDeferred
;
2505 if (++iProp
>= cProps
)
2507 cProps
+= PROP_ALLOC_INC
;
2508 paProps
= xrealloc(paProps
, sizeof(*paProps
) * cProps
);
2512 pProps
= kbuild_get_variable_n(ST("PROPS_ACCUMULATE_L"));
2513 pszIter
= pProps
->value
;
2514 while ((paProps
[iProp
].pch
= find_next_token(&pszIter
, &paProps
[iProp
].cch
)))
2516 paProps
[iProp
].enmType
= kPropAccumulateL
;
2517 if (++iProp
>= cProps
)
2519 cProps
+= PROP_ALLOC_INC
;
2520 paProps
= xrealloc(paProps
, sizeof(*paProps
) * cProps
);
2524 pProps
= kbuild_get_variable_n(ST("PROPS_ACCUMULATE_R"));
2525 pszIter
= pProps
->value
;
2526 while ((paProps
[iProp
].pch
= find_next_token(&pszIter
, &paProps
[iProp
].cch
)))
2528 paProps
[iProp
].enmType
= kPropAccumulateR
;
2529 if (++iProp
>= cProps
)
2531 cProps
+= PROP_ALLOC_INC
;
2532 paProps
= xrealloc(paProps
, sizeof(*paProps
) * cProps
);
2535 #undef PROP_ALLOC_INC
2538 /* find the max prop length. */
2539 cchMaxProp
= paProps
[0].cch
;
2541 if (paProps
[iProp
].cch
> cchMaxProp
)
2542 cchMaxProp
= paProps
[iProp
].cch
;
2545 * Query and prepare (strip) the default template
2546 * (given by the TEMPLATE variable).
2548 pDefTemplate
= kbuild_lookup_variable_n(ST("TEMPLATE"));
2551 if ( pDefTemplate
->value_length
2552 && ( isspace(pDefTemplate
->value
[0])
2553 || isspace(pDefTemplate
->value
[pDefTemplate
->value_length
- 1])))
2556 if (pDefTemplate
->rdonly_val
)
2557 fatal(NULL
, "%s: TEMPLATE is read-only", pszFuncName
);
2560 for (off
= 0; isspace(pDefTemplate
->value
[off
]); off
++)
2564 pDefTemplate
->value_length
-= off
;
2565 memmove(pDefTemplate
->value
, pDefTemplate
->value
+ off
, pDefTemplate
->value_length
+ 1);
2569 off
= pDefTemplate
->value_length
;
2570 while (off
> 0 && isspace(pDefTemplate
->value
[off
- 1]))
2572 pDefTemplate
->value_length
= off
;
2573 pDefTemplate
->value
[off
] = '\0';
2576 if (!pDefTemplate
->value_length
)
2577 pDefTemplate
= NULL
;
2581 * Iterate the target list.
2584 while ((pszTarget
= find_next_token(&pszIter
, &cchTarget
)))
2586 char *pszTrgProp
, *pszSrcProp
;
2587 char *pszTrgKey
, *pszSrcKey
;
2588 struct variable
*pTmpl
;
2589 const char *pszTmpl
;
2590 size_t cchTmpl
, cchMax
;
2592 /* resize the target buffer. */
2593 cchMax
= cchTarget
+ cchMaxProp
+ cchMaxBld
+ 10;
2594 if (cchTrg
< cchMax
)
2596 cchTrg
= (cchMax
+ 31U) & ~(size_t)31;
2597 pszTrg
= xrealloc(pszTrg
, cchTrg
);
2601 * Query the TEMPLATE property, if not found or zero-length fall back on the default.
2603 memcpy(pszTrg
, pszTarget
, cchTarget
);
2604 pszTrgProp
= pszTrg
+ cchTarget
;
2605 memcpy(pszTrgProp
, "_TEMPLATE", sizeof("_TEMPLATE"));
2606 pszTrgProp
++; /* after '_'. */
2608 /** @todo Change this to a recursive lookup with simplification below. That
2609 * will allow target_TEMPLATE = $(NO_SUCH_TEMPLATE) instead of having
2610 * to use target_TEMPLATE = DUMMY */
2611 pTmpl
= kbuild_lookup_variable_n(pszTrg
, cchTarget
+ sizeof("_TEMPLATE") - 1);
2612 if (!pTmpl
|| !pTmpl
->value_length
)
2615 continue; /* no template */
2616 pszTmpl
= pDefTemplate
->value
;
2617 cchTmpl
= pDefTemplate
->value_length
;
2621 pszTmpl
= pTmpl
->value
;
2622 cchTmpl
= pTmpl
->value_length
;
2623 while (isspace(*pszTmpl
))
2624 cchTmpl
--, pszTmpl
++;
2626 continue; /* no template */
2629 /* resize the source buffer. */
2630 cchMax
= sizeof("TEMPLATE_") + cchTmpl
+ cchMaxProp
+ cchMaxBld
+ 10 + sizeof(void *);
2631 if (cchSrcBuf
< cchMax
)
2633 cchSrcBuf
= (cchMax
+ 31U) & ~(size_t)31;
2634 pszSrcBuf
= xrealloc(pszSrcBuf
, cchSrcBuf
);
2635 pszSrc
= pszSrcBuf
+ sizeof(void *); assert(sizeof(void *) >= 2);
2636 pszSrcRef
= pszSrc
- 2;
2641 /* prepare the source buffer */
2642 memcpy(pszSrc
, "TEMPLATE_", sizeof("TEMPLATE_") - 1);
2643 pszSrcProp
= pszSrc
+ sizeof("TEMPLATE_") - 1;
2644 memcpy(pszSrcProp
, pszTmpl
, cchTmpl
);
2645 pszSrcProp
+= cchTmpl
;
2646 *pszSrcProp
++ = '_';
2649 * Process properties.
2650 * Note! The single and deferred are handled in the same way now.
2652 #define BY_REF_LIMIT 64 /*(cchSrcVar * 4 > 64 ? cchSrcVar * 4 : 64)*/
2654 for (iProp
= 0; iProp
< cProps
; iProp
++)
2656 memcpy(pszTrgProp
, paProps
[iProp
].pch
, paProps
[iProp
].cch
);
2657 pszTrgKey
= pszTrgProp
+ paProps
[iProp
].cch
;
2659 memcpy(pszSrcProp
, paProps
[iProp
].pch
, paProps
[iProp
].cch
);
2660 pszSrcKey
= pszSrcProp
+ paProps
[iProp
].cch
;
2662 for (iKey
= 0; iKey
< cKeys
; iKey
++)
2667 /* lookup source, skip ahead if it doesn't exist. */
2668 memcpy(pszSrcKey
, aKeys
[iKey
].psz
, aKeys
[iKey
].cch
);
2669 cchSrcVar
= pszSrcKey
- pszSrc
+ aKeys
[iKey
].cch
;
2670 pszSrc
[cchSrcVar
] = '\0';
2671 pVarSrc
= kbuild_query_recursive_variable_n(pszSrc
, cchSrcVar
);
2675 /* lookup target, skip ahead if it exists. */
2676 memcpy(pszTrgKey
, aKeys
[iKey
].psz
, aKeys
[iKey
].cch
);
2677 pszTrgEnd
= pszTrgKey
+ aKeys
[iKey
].cch
;
2679 pVarTrg
= kbuild_query_recursive_variable_n(pszTrg
, pszTrgEnd
- pszTrg
);
2681 switch (paProps
[iProp
].enmType
)
2683 case kPropAccumulateL
:
2684 case kPropAccumulateR
:
2687 /* Append to existing variable. If the source is recursive,
2688 or we append by reference, we'll have to make sure the
2689 target is recusive as well. */
2690 if ( !pVarTrg
->recursive
2691 && ( pVarSrc
->value_length
>= BY_REF_LIMIT
2692 || pVarSrc
->recursive
))
2693 pVarTrg
->recursive
= 1;
2695 if (pVarSrc
->value_length
< BY_REF_LIMIT
)
2696 append_string_to_variable(pVarTrg
, pVarSrc
->value
, pVarSrc
->value_length
,
2697 paProps
[iProp
].enmType
== kPropAccumulateL
/* append */);
2700 pszSrc
[cchSrcVar
] = ')';
2701 pszSrc
[cchSrcVar
+ 1] = '\0';
2702 append_string_to_variable(pVarTrg
, pszSrcRef
, 2 + cchSrcVar
+ 1,
2703 paProps
[iProp
].enmType
== kPropAccumulateL
/* append */);
2707 /* else: the target variable doesn't exist, create it. */
2713 continue; /* skip ahead if it already exists. */
2715 /* copy the variable if its short, otherwise reference it. */
2716 if (pVarSrc
->value_length
< BY_REF_LIMIT
)
2717 define_variable_vl_global(pszTrg
, pszTrgEnd
- pszTrg
,
2718 pVarSrc
->value
, pVarSrc
->value_length
,
2719 1 /* duplicate_value */,
2725 pszSrc
[cchSrcVar
] = ')';
2726 pszSrc
[cchSrcVar
+ 1] = '\0';
2727 define_variable_vl_global(pszTrg
, pszTrgEnd
- pszTrg
,
2728 pszSrcRef
, 2 + cchSrcVar
+ 1,
2729 1 /* duplicate_value */,
2739 } /* foreach prop */
2741 } /* foreach target */
2749 for (iKey
= 1; iKey
< cKeys
; iKey
++)
2750 free(aKeys
[iKey
].psz
);
2755 #endif /* KMK_HELPERS */