Changeset 1797 in kBuild for trunk/src/kmk
- Timestamp:
- Sep 21, 2008 1:05:36 AM (16 years ago)
- Location:
- trunk/src/kmk
- Files:
-
- 1 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/Makefile.am
r1778 r1797 48 48 \ 49 49 expreval.c \ 50 incdep.c \ 50 51 kbuild.c \ 51 52 electric.c \ -
trunk/src/kmk/Makefile.kmk
r1724 r1797 179 179 read.c \ 180 180 expreval.c \ 181 incdep.c \ 181 182 hash.c \ 182 183 strcache.c \ -
trunk/src/kmk/dep.h
r903 r1797 81 81 82 82 #ifdef CONFIG_WITH_INCLUDEDEP 83 void eval_include_dep (const char *name, struct floc *f); 83 /* incdep.c */ 84 enum incdep_op { incdep_read_it, incdep_queue, incdep_flush }; 85 void eval_include_dep (const char *name, struct floc *f, enum incdep_op op); 86 void incdep_flush_and_term (void); 87 88 /* read.c */ 89 void record_files (struct nameseq *filenames, const char *pattern, 90 const char *pattern_percent, struct dep *deps, 91 unsigned int cmds_started, char *commands, 92 unsigned int commands_idx, int two_colon, 93 const struct floc *flocp); 84 94 #endif 85 95 -
trunk/src/kmk/file.c
r1793 r1797 698 698 699 699 /* Disable second target expansion now since we won't expand files 700 entered after this point. ( saves CPU cycles in enter_file()). */700 entered after this point. (Saves CPU cycles in enter_file()). */ 701 701 second_target_expansion = 0; 702 702 } 703 703 #endif /* CONFIG_WITH_2ND_TARGET_EXPANSION */ 704 705 #ifdef CONFIG_WITH_INCLUDEDEP 706 /* Process any queued includedep files. Since includedep is supposed 707 to be *simple* stuff, we can do this after the second target expansion 708 and thereby save a little time. */ 709 incdep_flush_and_term (); 710 #endif 704 711 705 712 /* For every target that's not .SUFFIXES, expand its dependencies. -
trunk/src/kmk/kbuild.c
r1792 r1797 1704 1704 * was undefined and footer.kmk always passed an empty string. 1705 1705 * 1706 * Version 2, implemented in r1792, will delay the inclusion of the the 1707 * dependency file till the end of footer.kmk using _DEPFILES. 1706 * Version 2, as implemented in r1796, will make use of the async 1707 * includedep queue feature. This means the files will be read by one or 1708 * more background threads, leaving the eval'ing to be done later on by 1709 * the main thread (in snap_deps). 1708 1710 */ 1709 1711 if (!argv[0][0]) … … 1769 1771 if (!s_fNoCompileCmdsDepsDefined) 1770 1772 { 1771 1772 if (iVer >= 2) 1773 do_variable_definition(NILF, "_DEPFILES", pDep->value, o_file, f_append, 0 /* !target_var */); 1774 else 1775 { 1776 do_variable_definition(NILF, "_DEPFILES_INCLUDED", pDep->value, o_file, f_append, 0 /* !target_var */); 1777 eval_include_dep(pDep->value, NILF); 1778 } 1773 do_variable_definition(NILF, "_DEPFILES_INCLUDED", pDep->value, o_file, f_append, 0 /* !target_var */); 1774 eval_include_dep(pDep->value, NILF, iVer >= 2 ? incdep_queue : incdep_read_it); 1779 1775 } 1780 1776 -
trunk/src/kmk/read.c
r1776 r1797 34 34 # include "kbuild.h" 35 35 #endif 36 #ifdef CONFIG_WITH_INCLUDEDEP37 # ifdef HAVE_FCNTL_H38 # include <fcntl.h>39 # else40 # include <sys/file.h>41 #endif42 # ifdef WINDOWS3243 # include <io.h>44 # endif45 #endif46 36 47 37 #ifndef WINDOWS32 … … 147 137 enum variable_origin origin, struct ebuffer *ebuf); 148 138 static int conditional_line (char *line, int len, const struct floc *flocp); 139 #ifndef CONFIG_WITH_INCLUDEDEP 149 140 static void record_files (struct nameseq *filenames, const char *pattern, 150 141 const char *pattern_percent, struct dep *deps, … … 152 143 unsigned int commands_idx, int two_colon, 153 144 const struct floc *flocp); 145 #endif /* !KMK */ 154 146 static void record_target_var (struct nameseq *filenames, char *defn, 155 147 enum variable_origin origin, int enabled, … … 490 482 } 491 483 492 #ifdef CONFIG_WITH_INCLUDEDEP493 /* no nonsense dependency file including.494 495 Because nobody wants bogus dependency files to break their incremental496 builds with hard to comprehend error messages, this function does not497 use the normal eval routine but does all the parsing itself. This isn't,498 as much work as it sounds, because the necessary feature set is very499 limited.500 501 eval_include_dep groks:502 503 define var504 endef505 506 var [|:|?|>]= value [\]507 508 [\]509 file: [deps] [\]510 511 */512 void513 eval_include_dep (const char *name, struct floc *f)514 {515 int fd;516 char *file_base;517 const char *file_end, *cur, *endp;518 struct stat st;519 unsigned line_no;520 521 /* open and read it into memory. ignore non-existing dependency files522 or that we can't read. */523 errno = 0;524 #ifdef O_BINARY525 fd = open (name, O_RDONLY | O_BINARY, 0);526 #else527 fd = open (name, O_RDONLY, 0);528 #endif529 if (fd < 0)530 {531 int err = errno;532 if (err == ENOENT || !file_exists_p (name))533 return;534 error (f, "%s: %s", name, strerror (err));535 return;536 }537 if (fstat (fd, &st))538 {539 error (f, "%s: fstat: %s", name, strerror (errno));540 close (fd);541 return;542 }543 file_base = xmalloc (st.st_size + 1);544 if (read (fd, file_base, st.st_size) != st.st_size)545 {546 error (f, "%s: read: %s", name, strerror (errno));547 close (fd);548 free (file_base);549 return;550 }551 close (fd);552 file_end = file_base + st.st_size;553 file_base[st.st_size] = '\0';554 555 /* now parse the file. */556 line_no = 1;557 cur = file_base;558 while (cur < file_end)559 {560 /* skip empty lines */561 while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')562 ++cur;563 if (cur >= file_end)564 break;565 if (*cur == '#')566 {567 cur = memchr (cur, '\n', file_end - cur);568 if (!cur)569 break;570 }571 if (*cur == '\\')572 {573 unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2574 : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3575 : (file_end - cur == 1) ? 1 : 0;576 if (eol_len)577 {578 cur += eol_len;579 line_no++;580 continue;581 }582 }583 if (*cur == '\n')584 {585 cur++;586 line_no++;587 continue;588 }589 590 /* define var591 ...592 endef */593 if (strneq (cur, "define ", 7))594 {595 const char *var;596 unsigned var_len;597 const char *value_start;598 const char *value_end;599 char *value;600 unsigned value_len;601 int found_endef = 0;602 603 /* extract the variable name. */604 cur += 7;605 while (isblank ((unsigned char)*cur))606 ++cur;607 value_start = endp = memchr (cur, '\n', file_end - cur);608 if (!endp)609 endp = cur;610 while (endp > cur && isspace ((unsigned char)endp[-1]))611 --endp;612 var_len = endp - cur;613 if (!var_len)614 {615 error (f, "%s(%d): bogus define statement.", name, line_no);616 break;617 }618 var = strcache_add_len (cur, var_len);619 620 /* find the end of the variable. */621 cur = value_end = value_start = value_start + 1;622 ++line_no;623 while (cur < file_end)624 {625 /* check for endef, don't bother with skipping leading spaces. */626 if ( file_end - cur >= 5627 && strneq (cur, "endef", 5))628 {629 endp = cur + 5;630 while (endp < file_end && isspace ((unsigned char)*endp) && *endp != '\n')631 endp++;632 if (endp >= file_end || *endp == '\n')633 {634 found_endef = 1;635 cur = endp >= file_end ? file_end : endp + 1;636 break;637 }638 }639 640 /* skip a line ahead. */641 cur = value_end = memchr (cur, '\n', file_end - cur);642 if (cur != NULL)643 ++cur;644 else645 cur = value_end = file_end;646 ++line_no;647 }648 649 if (!found_endef)650 {651 error (f, "%s(%d): missing endef, dropping the rest of the file.", name, line_no);652 break;653 }654 value_len = value_end - value_start;655 if (memchr (value_start, '\0', value_len))656 {657 error (f, "%s(%d): '\\0' in define, dropping the rest of the file.", name, line_no);658 break;659 }660 661 /* make a copy of the value, converting \r\n to \n, and define it. */662 value = xmalloc (value_len + 1);663 endp = memchr (value_start, '\r', value_len);664 if (endp)665 {666 const char *src = value_start;667 char *dst = value;668 for (;;)669 {670 size_t len = endp - src;671 memcpy (dst, src, len);672 dst += len;673 src = endp;674 if (src + 1 < file_end && src[1] == '\n')675 src++; /* skip the '\r' */676 if (src >= value_end)677 break;678 endp = memchr (endp + 1, '\r', src - value_end);679 if (!endp)680 endp = value_end;681 }682 value_len = dst - value;683 }684 else685 memcpy (value, value_start, value_len);686 value [value_len] = '\0';687 688 define_variable_in_set (var, var_len, value, value_len,689 0 /* don't duplicate */, o_file,690 0 /* defines are recursive but this is faster */,691 NULL /* global set */, f);692 }693 694 /* file: deps695 OR696 variable [:]= value */697 else698 {699 const char *colonp;700 const char *equalp;701 702 /* Look for a colon and an equal sign, optimize for colon.703 Only one file is support and the colon / equal must be on704 the same line. */705 colonp = memchr (cur, ':', file_end - cur);706 #ifdef HAVE_DOS_PATHS707 while ( colonp708 && colonp + 1 < file_end709 && (colonp[1] == '/' || colonp[1] == '\\')710 && colonp > cur711 && isalpha ((unsigned char)colonp[-1])712 && ( colonp == cur + 1713 || strchr (" \t(", colonp[-2]) != 0))714 colonp = memchr (colonp + 1, ':', file_end - (colonp + 1));715 #endif716 endp = NULL;717 if ( !colonp718 || (endp = memchr (cur, '\n', colonp - cur)))719 {720 colonp = NULL;721 equalp = memchr (cur, '=', (endp ? endp : file_end) - cur);722 if ( !equalp723 || (!endp && memchr (cur, '\n', equalp - cur)))724 {725 error (f, "%s(%d): no colon.", name, line_no);726 break;727 }728 }729 else730 equalp = memchr (cur, '=', (colonp + 2 <= file_end731 ? colonp + 2 : file_end) - cur);732 if (equalp)733 {734 /* An assignment of some sort. */735 const char *var;736 unsigned var_len;737 const char *value_start;738 const char *value_end;739 char *value;740 unsigned value_len;741 unsigned multi_line = 0;742 enum variable_flavor flavor;743 744 /* figure the flavor first. */745 flavor = f_recursive;746 if (equalp > cur)747 {748 if (equalp[-1] == ':')749 flavor = f_simple;750 else if (equalp[-1] == '?')751 flavor = f_conditional;752 else if (equalp[-1] == '+')753 flavor = f_append;754 else if (equalp[-1] == '>')755 flavor = f_prepend;756 }757 758 /* extract the variable name. */759 endp = flavor == f_recursive ? equalp : equalp - 1;760 while (endp > cur && isblank ((unsigned char)endp[-1]))761 --endp;762 var_len = endp - cur;763 if (!var_len)764 {765 error (f, "%s(%d): empty variable. (includedep)", name, line_no);766 break;767 }768 if ( memchr (cur, '$', var_len)769 || memchr (cur, ' ', var_len)770 || memchr (cur, '\t', var_len))771 {772 error (f, "%s(%d): fancy variable name. (includedep)", name, line_no);773 break;774 }775 var = strcache_add_len (cur, var_len);776 777 /* find the start of the value. */778 cur = equalp + 1;779 while (cur < file_end && isblank ((unsigned char)*cur))780 cur++;781 value_start = cur;782 783 /* find the end of the value / line (this isn't 101% correct). */784 value_end = cur;785 while (cur < file_end)786 {787 endp = value_end = memchr (cur, '\n', file_end - cur);788 if (!value_end)789 value_end = file_end;790 if (value_end - 1 >= cur && value_end[-1] == '\r')791 --value_end;792 if (value_end - 1 < cur || value_end[-1] != '\\')793 {794 cur = endp ? endp + 1 : file_end;795 break;796 }797 --value_end;798 if (value_end - 1 >= cur && value_end[-1] == '\\')799 {800 error (f, "%s(%d): fancy escaping! (includedep)", name, line_no);801 cur = NULL;802 break;803 }804 if (!endp)805 {806 cur = file_end;807 break;808 }809 810 cur = endp + 1;811 ++multi_line;812 ++line_no;813 }814 if (!cur)815 break;816 ++line_no;817 818 /* make a copy of the value, converting \r\n to \n, and define it. */819 value_len = value_end - value_start;820 value = xmalloc (value_len + 1);821 if (!multi_line)822 memcpy (value, value_start, value_len);823 else824 {825 /* unescape it */826 const char *src = value_start;827 char *dst = value;828 while (src < value_end)829 {830 const char *nextp;831 832 endp = memchr (src, '\n', value_end - src);833 if (!endp)834 nextp = endp = value_end;835 else836 nextp = endp + 1;837 if (endp > src && endp[-1] == '\r')838 --endp;839 if (endp > src && endp[-1] == '\\')840 --endp;841 842 if (src != value_start)843 *dst++ = ' ';844 memcpy (dst, src, endp - src);845 dst += endp - src;846 src = nextp;847 }848 value_len = dst - value;849 }850 value [value_len] = '\0';851 852 /* do the definition */853 if (flavor == f_recursive854 || ( flavor == f_simple855 && !memchr (value, '$', value_len)))856 define_variable_in_set (var, var_len, value, value_len,857 0 /* don't duplicate */, o_file,858 flavor == f_recursive /* recursive */,859 NULL /* global set */, f);860 else861 {862 do_variable_definition (f, var, value, o_file, flavor,863 0 /* not target var */);864 free (value);865 }866 }867 else868 {869 /* file: dependencies */870 871 struct nameseq *filenames = 0;872 struct dep *deps = 0;873 struct dep **nextdep = &deps;874 struct dep *dep;875 int next_line = 1;876 877 /* extract the filename, ASSUME a single one. */878 endp = colonp;879 while (endp > cur && isblank ((unsigned char)endp[-1]))880 --endp;881 if (cur == endp)882 {883 error (f, "%s(%d): empty filename.", name, line_no);884 break;885 }886 if ( memchr (cur, '$', endp - cur)887 || memchr (cur, ' ', endp - cur)888 || memchr (cur, '\t', endp - cur))889 {890 error (f, "%s(%d): multiple / fancy file name. (includedep)", name, line_no);891 break;892 }893 filenames = xmalloc (sizeof (struct nameseq));894 memset (filenames, 0, sizeof (*filenames));895 filenames->name = strcache_add_len (cur, endp - cur);896 897 /* parse any dependencies. */898 cur = colonp + 1;899 while (cur < file_end)900 {901 /* skip blanks and count lines. */902 while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')903 ++cur;904 if (cur >= file_end)905 break;906 if (*cur == '\n')907 {908 cur++;909 line_no++;910 break;911 }912 913 /* continuation + eol? */914 if (*cur == '\\')915 {916 unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2917 : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3918 : (file_end - cur == 1) ? 1 : 0;919 if (eol_len)920 {921 cur += eol_len;922 line_no++;923 continue;924 }925 }926 927 /* find the end of the filename */928 endp = cur;929 while (endp < file_end && !isspace ((unsigned char)*endp))930 ++endp;931 932 /* add it to the list. */933 *nextdep = dep = alloc_dep ();934 dep->name = strcache_add_len (cur, endp - cur);935 nextdep = &dep->next;936 937 cur = endp;938 }939 940 /* enter the file with its dependencies. */941 record_files (filenames, NULL, NULL, deps, 0, NULL, 0, 0, f);942 }943 }944 }945 free (file_base);946 }947 #endif /* CONFIG_WITH_INCLUDEDEP */948 949 484 950 485 … … 1327 862 1328 863 #ifdef CONFIG_WITH_INCLUDEDEP 1329 if (word1eq ("includedep") )864 if (word1eq ("includedep") || word1eq ("includedep-queue") || word1eq ("includedep-flush")) 1330 865 { 1331 /* We have found an `includedep' line specifying a single makefile866 /* We have found an `includedep' line specifying one or more dep files 1332 867 to be read at this point. This include variation does no 1333 868 globbing and do not support multiple names. It's trying to save 1334 869 time by being dead simple as well as ignoring errors. */ 870 enum incdep_op op = p[wlen - 1] == 'p' 871 ? incdep_read_it 872 : p[wlen - 1] == 'e' 873 ? incdep_queue : incdep_flush; 1335 874 char *free_me = NULL; 1336 875 char *name = p2; … … 1350 889 saved = *end; /* not sure if this is required... */ 1351 890 *end = '\0'; 1352 eval_include_dep (name, fstart );891 eval_include_dep (name, fstart, op); 1353 892 *end = saved; 1354 893 … … 2493 2032 that are not incorporated into other data structures. */ 2494 2033 2034 #ifndef CONFIG_WITH_INCLUDEDEP 2495 2035 static void 2036 #else 2037 void 2038 #endif 2496 2039 record_files (struct nameseq *filenames, const char *pattern, 2497 2040 const char *pattern_percent, struct dep *deps, -
trunk/src/kmk/variable.c
r1793 r1797 1232 1232 && defined (KMK_HELPERS) 1233 1233 (void) define_variable ("KMK_FEATURES", 12, 1234 "append-dash-n abspath "1234 "append-dash-n abspath includedep-queue" 1235 1235 " rsort" 1236 1236 " abspathex" … … 1255 1255 # else /* MSC can't deal with strings mixed with #if/#endif, thus the slow way. */ 1256 1256 # error "All features should be enabled by default!" 1257 strcpy (buf, "append-dash-n abspath ");1257 strcpy (buf, "append-dash-n abspath includedep-queue"); 1258 1258 # if defined (CONFIG_WITH_RSORT) 1259 1259 strcat (buf, " rsort");
Note:
See TracChangeset
for help on using the changeset viewer.