VirtualBox

Changeset 1797 in kBuild for trunk/src/kmk


Ignore:
Timestamp:
Sep 21, 2008 1:05:36 AM (16 years ago)
Author:
bird
Message:

kmk: moved eval_include_dep into incdep.c (was in read.c) and implemented background file reading. 'includedep-queue' and 'includedep-flush' are new directives, which along with 'includedep', all take a list of dependency files (used to only take a single file).

Location:
trunk/src/kmk
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/Makefile.am

    r1778 r1797  
    4848                \
    4949                expreval.c \
     50                incdep.c \
    5051                kbuild.c \
    5152                electric.c \
  • trunk/src/kmk/Makefile.kmk

    r1724 r1797  
    179179        read.c \
    180180        expreval.c \
     181        incdep.c \
    181182        hash.c \
    182183        strcache.c \
  • trunk/src/kmk/dep.h

    r903 r1797  
    8181
    8282#ifdef CONFIG_WITH_INCLUDEDEP
    83 void eval_include_dep (const char *name, struct floc *f);
     83/* incdep.c */
     84enum incdep_op { incdep_read_it, incdep_queue, incdep_flush };
     85void eval_include_dep (const char *name, struct floc *f, enum incdep_op op);
     86void incdep_flush_and_term (void);
     87
     88/* read.c */
     89void 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);
    8494#endif
    8595
  • trunk/src/kmk/file.c

    r1793 r1797  
    698698
    699699      /* 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()). */
    701701      second_target_expansion = 0;
    702702    }
    703703#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
    704711
    705712  /* For every target that's not .SUFFIXES, expand its dependencies.
  • trunk/src/kmk/kbuild.c

    r1792 r1797  
    17041704     * was undefined and footer.kmk always passed an empty string.
    17051705     *
    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).
    17081710     */
    17091711    if (!argv[0][0])
     
    17691771    if (!s_fNoCompileCmdsDepsDefined)
    17701772    {
    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);
    17791775    }
    17801776
  • trunk/src/kmk/read.c

    r1776 r1797  
    3434# include "kbuild.h"
    3535#endif
    36 #ifdef CONFIG_WITH_INCLUDEDEP
    37 # ifdef HAVE_FCNTL_H
    38 #  include <fcntl.h>
    39 # else
    40 #  include <sys/file.h>
    41 #endif
    42 # ifdef WINDOWS32
    43 #  include <io.h>
    44 # endif
    45 #endif
    4636
    4737#ifndef WINDOWS32
     
    147137                       enum variable_origin origin, struct ebuffer *ebuf);
    148138static int conditional_line (char *line, int len, const struct floc *flocp);
     139#ifndef CONFIG_WITH_INCLUDEDEP
    149140static void record_files (struct nameseq *filenames, const char *pattern,
    150141                          const char *pattern_percent, struct dep *deps,
     
    152143                          unsigned int commands_idx, int two_colon,
    153144                          const struct floc *flocp);
     145#endif /* !KMK */
    154146static void record_target_var (struct nameseq *filenames, char *defn,
    155147                               enum variable_origin origin, int enabled,
     
    490482}
    491483
    492 #ifdef CONFIG_WITH_INCLUDEDEP
    493 /* no nonsense dependency file including.
    494 
    495    Because nobody wants bogus dependency files to break their incremental
    496    builds with hard to comprehend error messages, this function does not
    497    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 very
    499    limited.
    500 
    501    eval_include_dep groks:
    502 
    503    define var
    504    endef
    505 
    506    var [|:|?|>]= value [\]
    507 
    508    [\]
    509    file: [deps] [\]
    510 
    511    */
    512 void
    513 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 files
    522      or that we can't read. */
    523   errno = 0;
    524 #ifdef O_BINARY
    525   fd = open (name, O_RDONLY | O_BINARY, 0);
    526 #else
    527   fd = open (name, O_RDONLY, 0);
    528 #endif
    529   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') ? 2
    574                            : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
    575                            : (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 var
    591          ...
    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 >= 5
    627                   && 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               else
    645                 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           else
    685             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: deps
    695          OR
    696          variable [:]= value */
    697       else
    698         {
    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 on
    704              the same line. */
    705           colonp = memchr (cur, ':', file_end - cur);
    706 #ifdef HAVE_DOS_PATHS
    707           while (   colonp
    708                  && colonp + 1 < file_end
    709                  && (colonp[1] == '/' || colonp[1] == '\\')
    710                  && colonp > cur
    711                  && isalpha ((unsigned char)colonp[-1])
    712                  && (   colonp == cur + 1
    713                      || strchr (" \t(", colonp[-2]) != 0))
    714               colonp = memchr (colonp + 1, ':', file_end - (colonp + 1));
    715 #endif
    716           endp = NULL;
    717           if (   !colonp
    718               ||  (endp = memchr (cur, '\n', colonp - cur)))
    719             {
    720               colonp = NULL;
    721               equalp = memchr (cur, '=', (endp ? endp : file_end) - cur);
    722               if (   !equalp
    723                   || (!endp && memchr (cur, '\n', equalp - cur)))
    724                 {
    725                   error (f, "%s(%d): no colon.", name, line_no);
    726                   break;
    727                 }
    728             }
    729           else
    730             equalp = memchr (cur, '=', (colonp + 2 <= file_end
    731                                         ? 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               else
    824                 {
    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                       else
    836                         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_recursive
    854                || (   flavor == f_simple
    855                    && !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               else
    861                 {
    862                   do_variable_definition (f, var, value, o_file, flavor,
    863                                           0 /* not target var */);
    864                   free (value);
    865                 }
    866             }
    867           else
    868             {
    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') ? 2
    917                                        : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
    918                                        : (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 
    949484
    950485
     
    1327862
    1328863#ifdef CONFIG_WITH_INCLUDEDEP
    1329       if (word1eq ("includedep"))
     864      if (word1eq ("includedep") || word1eq ("includedep-queue") || word1eq ("includedep-flush"))
    1330865        {
    1331           /* We have found an `includedep' line specifying a single makefile
     866          /* We have found an `includedep' line specifying one or more dep files
    1332867             to be read at this point. This include variation does no
    1333868             globbing and do not support multiple names. It's trying to save
    1334869             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;
    1335874          char *free_me = NULL;
    1336875          char *name = p2;
     
    1350889          saved = *end; /* not sure if this is required... */
    1351890          *end = '\0';
    1352           eval_include_dep (name, fstart);
     891          eval_include_dep (name, fstart, op);
    1353892          *end = saved;
    1354893
     
    24932032   that are not incorporated into other data structures.  */
    24942033
     2034#ifndef CONFIG_WITH_INCLUDEDEP
    24952035static void
     2036#else
     2037void
     2038#endif
    24962039record_files (struct nameseq *filenames, const char *pattern,
    24972040              const char *pattern_percent, struct dep *deps,
  • trunk/src/kmk/variable.c

    r1793 r1797  
    12321232  && defined (KMK_HELPERS)
    12331233  (void) define_variable ("KMK_FEATURES", 12,
    1234                           "append-dash-n abspath"
     1234                          "append-dash-n abspath includedep-queue"
    12351235                          " rsort"
    12361236                          " abspathex"
     
    12551255# else /* MSC can't deal with strings mixed with #if/#endif, thus the slow way. */
    12561256#  error "All features should be enabled by default!"
    1257   strcpy (buf, "append-dash-n abspath");
     1257  strcpy (buf, "append-dash-n abspath includedep-queue");
    12581258#  if defined (CONFIG_WITH_RSORT)
    12591259  strcat (buf, " rsort");
Note: See TracChangeset for help on using the changeset viewer.

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