[BACK]Return to main.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Diff for /src/usr.bin/make/main.c between version 1.74 and 1.75

version 1.74, 2007/07/24 18:58:48 version 1.75, 2007/07/30 09:39:18
Line 100 
Line 100 
 bool            ignoreErrors;   /* -i flag */  bool            ignoreErrors;   /* -i flag */
 bool            beSilent;       /* -s flag */  bool            beSilent;       /* -s flag */
   
 static void             MainParseArgs(int, char **);  struct dirs {
 static char *           chdir_verify_path(const char *);          char *current;
 static int              ReadMakefile(void *, void *);          char *object;
 static void             add_dirpath(Lst, const char *);  };
 static void             usage(void);  
 static void             posixParseOptLetter(int);  
 static void             record_option(int, const char *);  
   
 static char *curdir;                    /* startup directory */  static void MainParseArgs(int, char **);
 static char *objdir;                    /* where we chdir'ed to */  static void add_dirpath(Lst, const char *);
   static void usage(void);
   static void posixParseOptLetter(int);
   static void record_option(int, const char *);
   
   static char *figure_out_MACHINE(void);
   static char *figure_out_MACHINE_ARCH(void);
   static void no_fd_limits(void);
   
   static char *chdir_verify_path(const char *, struct dirs *);
   static char *concat_verify(const char *, const char *, char, struct dirs *);
   static char *figure_out_CURDIR(void);
   static void setup_CURDIR_OBJDIR(struct dirs *, const char *);
   
   static void setup_VPATH(void);
   
   static void read_all_make_rules(bool, Lst, struct dirs *);
   static void read_makefile_list(Lst, struct dirs *);
   static int ReadMakefile(void *, void *);
   
   
 static void record_option(int c, const char *arg)  static void record_option(int c, const char *arg)
 {  {
     char opt[3];      char opt[3];
   
     opt[0] = '-';          opt[0] = '-';
     opt[1] = c;          opt[1] = c;
     opt[2] = '\0';          opt[2] = '\0';
     Var_Append(MAKEFLAGS, opt, VAR_GLOBAL);          Var_Append(MAKEFLAGS, opt, VAR_GLOBAL);
     if (arg != NULL)          if (arg != NULL)
         Var_Append(MAKEFLAGS, arg, VAR_GLOBAL);                  Var_Append(MAKEFLAGS, arg, VAR_GLOBAL);
 }  }
   
 static void  static void
Line 373 
Line 388 
         free(argv);          free(argv);
 }  }
   
 char *  
 chdir_verify_path(const char *path)  
 {  
     struct stat sb;  
   
     if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {  
         if (chdir(path)) {  
             (void)fprintf(stderr, "make warning: %s: %s.\n",  
                   path, strerror(errno));  
             return NULL;  
         } else {  
             if (path[0] != '/')  
                 return Str_concat(curdir, path, '/');  
             else  
                 return estrdup(path);  
         }  
     }  
   
     return NULL;  
 }  
   
   
 /* Add a :-separated path to a Lst of directories.  */  /* Add a :-separated path to a Lst of directories.  */
 static void  static void
 add_dirpath(Lst l, const char *n)  add_dirpath(Lst l, const char *n)
 {  {
     const char *start;          const char *start;
     const char *cp;          const char *cp;
   
     for (start = n;;) {          for (start = n;;) {
         for (cp = start; *cp != '\0' && *cp != ':';)                  for (cp = start; *cp != '\0' && *cp != ':';)
             cp++;                          cp++;
         Dir_AddDiri(l, start, cp);                  Dir_AddDiri(l, start, cp);
         if (*cp == '\0')                  if (*cp == '\0')
             break;                          break;
         else                  else
             start= cp+1;                          start= cp+1;
     }          }
 }  }
   
 int main(int, char **);  /*
 /*-   * Get the name of this type of MACHINE from utsname so we can share an
  * main --   * executable for similar machines. (i.e. m68k: amiga hp300, mac68k, sun3, ...)
  *      The main function, for obvious reasons. Initializes variables  
  *      and a few modules, then parses the arguments give it in the  
  *      environment and on the command line. Reads the system makefile  
  *      followed by either Makefile, makefile or the file given by the  
  *      -f argument. Sets the .MAKEFLAGS PMake variable based on all the  
  *      flags it has received by then uses either the Make or the Compat  
  *      module to create the initial list of targets.  
  *   *
  * Results:   * Note that both MACHINE and MACHINE_ARCH are decided at
  *      If -q was given, exits -1 if anything was out-of-date. Else it exits   * run-time.
  *      0.  
  *  
  * Side Effects:  
  *      The program exits when done. Targets are created. etc. etc. etc.  
  */   */
 int  static char *
 main(int argc, char **argv)  figure_out_MACHINE()
 {  {
         static LIST targs;      /* target nodes to create */          char *r = getenv("MACHINE");
         bool outOfDate = true;  /* false if all targets up to date */          if (r == NULL) {
         struct stat sb, sa;  #ifndef MAKE_BOOTSTRAP
         char *p, *path, *pathp, *pwd;                  static struct utsname utsname;
         char *mdpath;  
         char *machine = getenv("MACHINE");  
         char *machine_arch = getenv("MACHINE_ARCH");  
         const char *syspath = _PATH_DEFSYSPATH;  
   
 #ifdef RLIMIT_NOFILE                  if (uname(&utsname) == -1) {
         /*                          perror("make: uname");
          * get rid of resource limit on file descriptors                          exit(2);
          */  
         {  
                 struct rlimit rl;  
                 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&  
                     rl.rlim_cur != rl.rlim_max) {  
                         rl.rlim_cur = rl.rlim_max;  
                         (void)setrlimit(RLIMIT_NOFILE, &rl);  
                 }                  }
                   r = utsname.machine;
   #else
                   r = MACHINE;
   #endif
         }          }
           return r;
   }
   
   static char *
   figure_out_MACHINE_ARCH()
   {
           char *r = getenv("MACHINE_ARCH");
           if (r == NULL) {
   #ifndef MACHINE_ARCH
                   r = "unknown";  /* XXX: no uname -p yet */
   #else
                   r = MACHINE_ARCH;
 #endif  #endif
         /*          }
          * Find where we are and take care of PWD for the automounter...          return r;
          * All this code is so that we know where we are when we start up  }
          * on a different machine with pmake.  
          */  /* get rid of resource limit on file descriptors */
         if ((curdir = dogetcwd()) == NULL) {  static void
   no_fd_limits()
   {
   #ifdef RLIMIT_NOFILE
           struct rlimit rl;
           if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
               rl.rlim_cur != rl.rlim_max) {
                   rl.rlim_cur = rl.rlim_max;
                   (void)setrlimit(RLIMIT_NOFILE, &rl);
           }
   #endif
   }
   
   static char *
   figure_out_CURDIR()
   {
           char *dir, *cwd;
           struct stat sa, sb;
   
           /* curdir is cwd... */
           cwd = dogetcwd();
           if (cwd == NULL) {
                 (void)fprintf(stderr, "make: %s.\n", strerror(errno));                  (void)fprintf(stderr, "make: %s.\n", strerror(errno));
                 exit(2);                  exit(2);
         }          }
   
         if (stat(curdir, &sa) == -1) {          if (stat(cwd, &sa) == -1) {
             (void)fprintf(stderr, "make: %s: %s.\n",                  (void)fprintf(stderr, "make: %s: %s.\n", cwd, strerror(errno));
                           curdir, strerror(errno));                  exit(2);
             exit(2);  
         }          }
   
         if ((pwd = getenv("PWD")) != NULL) {          /* ...but we can use the alias $PWD if we can prove it is the same
             if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&           * directory */
                 sa.st_dev == sb.st_dev) {          if ((dir = getenv("PWD")) != NULL) {
                     free(curdir);                  if (stat(dir, &sb) == 0 && sa.st_ino == sb.st_ino &&
                     curdir = estrdup(pwd);                      sa.st_dev == sb.st_dev)
             }                          free(cwd);
                           return estrdup(dir);
         }          }
   
         /*          return cwd;
          * Get the name of this type of MACHINE from utsname  }
          * so we can share an executable for similar machines.  
          * (i.e. m68k: amiga hp300, mac68k, sun3, ...)  
          *  
          * Note that both MACHINE and MACHINE_ARCH are decided at  
          * run-time.  
          */  
         if (!machine) {  
 #ifndef MAKE_BOOTSTRAP  
             static struct utsname utsname;  
   
             if (uname(&utsname) == -1) {  static char *
                     perror("make: uname");  chdir_verify_path(const char *path, struct dirs *d)
                     exit(2);  {
             }          struct stat sb;
             machine = utsname.machine;  
 #else  
             machine = MACHINE;  
 #endif  
         }  
   
         if (!machine_arch) {          if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
 #ifndef MACHINE_ARCH                  if (chdir(path)) {
             machine_arch = "unknown";   /* XXX: no uname -p yet */                          (void)fprintf(stderr, "make warning: %s: %s.\n",
 #else                                path, strerror(errno));
             machine_arch = MACHINE_ARCH;                          return NULL;
 #endif                  } else {
                           if (path[0] != '/')
                                   return Str_concat(d->current, path, '/');
                           else
                                   return estrdup(path);
                   }
         }          }
   
           return NULL;
   }
   
   static char *
   concat_verify(const char *p1, const char *p2, char c, struct dirs *d)
   {
           char *tmp = Str_concat(p1, p2, c);
           char *result = chdir_verify_path(tmp, d);
           free(tmp);
           return result;
   }
   
   static void
   setup_CURDIR_OBJDIR(struct dirs *d, const char *machine)
   {
           char *path, *prefix;
   
           d->current = figure_out_CURDIR();
           d->object = NULL;
         /*          /*
          * If the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory           * If the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory
          * exists, change into it and build there.  (If a .${MACHINE} suffix           * exists, change into it and build there.  (If a .${MACHINE} suffix
Line 523 
Line 541 
          * and modify the paths for the Makefiles appropriately.  The           * and modify the paths for the Makefiles appropriately.  The
          * current directory is also placed as a variable for make scripts.           * current directory is also placed as a variable for make scripts.
          */           */
         mdpath = NULL;          if ((prefix = getenv("MAKEOBJDIRPREFIX")) != NULL) {
         if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {                  d->object = concat_verify(prefix, d->current, 0, d);
                 if (!(path = getenv("MAKEOBJDIR"))) {          } else if ((path = getenv("MAKEOBJDIR")) != NULL) {
                         path = _PATH_OBJDIR;                  d->object = chdir_verify_path(path, d);
                         pathp = _PATH_OBJDIRPREFIX;          } else {
                         mdpath = Str_concat(path, machine, '.');                  path = _PATH_OBJDIR;
                         if (!(objdir = chdir_verify_path(mdpath)))                  prefix = _PATH_OBJDIRPREFIX;
                                 if (!(objdir=chdir_verify_path(path))) {                  d->object = concat_verify(path, machine, '.', d);
                                         free(mdpath);                  if (!d->object)
                                         mdpath = Str_concat(pathp, curdir, 0);                          d->object=chdir_verify_path(path, d);
                                         if (!(objdir=chdir_verify_path(mdpath)))                  if (!d->object)
                                                 objdir = curdir;                          d->object = concat_verify(prefix, d->current, 0, d);
                                 }  
                 }  
                 else if (!(objdir = chdir_verify_path(path)))  
                         objdir = curdir;  
         }          }
         else {          if (d->object == NULL)
                 mdpath = Str_concat(pathp, curdir, 0);                  d->object = d->current;
                 if (!(objdir = chdir_verify_path(mdpath)))  }
                         objdir = curdir;  
   #ifdef CLEANUP
   static void
   free_CURDIR_OBJDIR(struct dirs *d)
   {
           if (d->object != d->current)
                   free(d->object);
           free(d->current);
   }
   #endif
   
   
   /*
    * if the VPATH variable is defined, add its contents to the search path.
    * Uses the same format as the PATH env variable, i.e.,
    * <directory>:<directory>:<directory>...
    */
   static void
   setup_VPATH()
   {
           if (Var_Value("VPATH") != NULL) {
                   char *vpath;
   
                   vpath = Var_Subst("${VPATH}", NULL, false);
                   add_dirpath(dirSearchPath, vpath);
                   (void)free(vpath);
         }          }
         free(mdpath);  }
   
         esetenv("PWD", objdir);  static void
   read_makefile_list(Lst mk, struct dirs *d)
   {
           LstNode ln;
           ln = Lst_Find(mk, ReadMakefile, d);
           if (ln != NULL)
                   Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
   }
   
   static void
   read_all_make_rules(bool noBuiltins, Lst makefiles, struct dirs *d)
   {
           /*
            * Read in the built-in rules first, followed by the specified
            * makefile(s), or the default BSDmakefile, Makefile or
            * makefile, in that order.
            */
           if (!noBuiltins) {
                   LIST sysMkPath;                 /* Path of sys.mk */
   
                   Lst_Init(&sysMkPath);
                   Dir_Expand(_PATH_DEFSYSMK, sysIncPath, &sysMkPath);
                   if (Lst_IsEmpty(&sysMkPath))
                           Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
   
                   read_makefile_list(&sysMkPath, d);
   #ifdef CLEANUP
                   Lst_Destroy(&sysMkPath, (SimpleProc)free);
   #endif
           }
   
           if (!Lst_IsEmpty(makefiles)) {
                   read_makefile_list(makefiles, d);
           } else if (!ReadMakefile("BSDmakefile", d))
                   if (!ReadMakefile("makefile", d))
                           (void)ReadMakefile("Makefile", d);
   
           /* Always read a .depend file, if it exists. */
           (void)ReadMakefile(".depend", d);
   }
   
   
   int main(int, char **);
   /*-
    * main --
    *      The main function, for obvious reasons. Initializes variables
    *      and a few modules, then parses the arguments give it in the
    *      environment and on the command line. Reads the system makefile
    *      followed by either Makefile, makefile or the file given by the
    *      -f argument. Sets the .MAKEFLAGS PMake variable based on all the
    *      flags it has received by then uses either the Make or the Compat
    *      module to create the initial list of targets.
    *
    * Results:
    *      If -q was given, exits -1 if anything was out-of-date. Else it exits
    *      0.
    *
    * Side Effects:
    *      The program exits when done. Targets are created. etc. etc. etc.
    */
   int
   main(int argc, char **argv)
   {
           static LIST targs;      /* target nodes to create */
           bool outOfDate = true;  /* false if all targets up to date */
           char *machine = figure_out_MACHINE();
           char *machine_arch = figure_out_MACHINE_ARCH();
           const char *syspath = _PATH_DEFSYSPATH;
           char *p;
           static struct dirs d;
   
           no_fd_limits();
           setup_CURDIR_OBJDIR(&d, machine);
   
           esetenv("PWD", d.object);
         unsetenv("CDPATH");          unsetenv("CDPATH");
   
         Static_Lst_Init(create);          Static_Lst_Init(create);
Line 576 
Line 689 
          */           */
         Init();          Init();
   
         if (objdir != curdir)          if (d.object != d.current)
                 Dir_AddDir(dirSearchPath, curdir);                  Dir_AddDir(dirSearchPath, d.current);
         Var_Set(".CURDIR", curdir, VAR_GLOBAL);          Var_Set(".CURDIR", d.current, VAR_GLOBAL);
         Var_Set(".OBJDIR", objdir, VAR_GLOBAL);          Var_Set(".OBJDIR", d.object, VAR_GLOBAL);
   
         /*          /*
          * Initialize various variables.           * Initialize various variables.
Line 632 
Line 745 
         if (Lst_IsEmpty(sysIncPath))          if (Lst_IsEmpty(sysIncPath))
             add_dirpath(sysIncPath, syspath);              add_dirpath(sysIncPath, syspath);
   
         /*          read_all_make_rules(noBuiltins, &makefiles, &d);
          * Read in the built-in rules first, followed by the specified  
          * makefile(s), or the default BSDmakefile, Makefile or  
          * makefile, in that order.  
          */  
         if (!noBuiltins) {  
                 LstNode ln;  
                 LIST sysMkPath;                 /* Path of sys.mk */  
   
                 Lst_Init(&sysMkPath);          Var_Append("MFLAGS", Var_Value(MAKEFLAGS), VAR_GLOBAL);
                 Dir_Expand(_PATH_DEFSYSMK, sysIncPath, &sysMkPath);  
                 if (Lst_IsEmpty(&sysMkPath))  
                         Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);  
                 ln = Lst_Find(&sysMkPath, ReadMakefile, NULL);  
                 if (ln != NULL)  
                         Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));  
 #ifdef CLEANUP  
                 Lst_Destroy(&sysMkPath, (SimpleProc)free);  
 #endif  
         }  
   
         if (!Lst_IsEmpty(&makefiles)) {  
                 LstNode ln;  
   
                 ln = Lst_Find(&makefiles, ReadMakefile, NULL);  
                 if (ln != NULL)  
                         Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));  
         } else if (!ReadMakefile("BSDmakefile", NULL))  
                 if (!ReadMakefile("makefile", NULL))  
                         (void)ReadMakefile("Makefile", NULL);  
   
         /* Always read a .depend file, if it exists. */  
         (void)ReadMakefile(".depend", NULL);  
   
         Var_Append("MFLAGS", Var_Value(MAKEFLAGS),  
             VAR_GLOBAL);  
   
         /* Install all the flags into the MAKEFLAGS env variable. */          /* Install all the flags into the MAKEFLAGS env variable. */
         if (((p = Var_Value(MAKEFLAGS)) != NULL) && *p)          if (((p = Var_Value(MAKEFLAGS)) != NULL) && *p)
                 esetenv("MAKEFLAGS", p);                  esetenv("MAKEFLAGS", p);
   
         /*          setup_VPATH();
          * For compatibility, look at the directories in the VPATH variable  
          * and add them to the search path, if the variable is defined. The  
          * variable's value is in the same format as the PATH envariable, i.e.  
          * <directory>:<directory>:<directory>...  
          */  
         if (Var_Value("VPATH") != NULL) {  
             char *vpath;  
   
             vpath = Var_Subst("${VPATH}", NULL, false);  
             add_dirpath(dirSearchPath, vpath);  
             (void)free(vpath);  
         }  
   
         /* Now that all search paths have been read for suffixes et al, it's          /* Now that all search paths have been read for suffixes et al, it's
          * time to add the default search path to their lists...  */           * time to add the default search path to their lists...  */
         Suff_DoPaths();          Suff_DoPaths();
Line 697 
Line 765 
   
         /* Print the values of any variables requested by the user.  */          /* Print the values of any variables requested by the user.  */
         if (!Lst_IsEmpty(&varstoprint)) {          if (!Lst_IsEmpty(&varstoprint)) {
             LstNode ln;                  LstNode ln;
   
             for (ln = Lst_First(&varstoprint); ln != NULL; ln = Lst_Adv(ln)) {                  for (ln = Lst_First(&varstoprint); ln != NULL;
                     char *value = Var_Value((char *)Lst_Datum(ln));                      ln = Lst_Adv(ln)) {
                           char *value = Var_Value((char *)Lst_Datum(ln));
   
                     printf("%s\n", value ? value : "");                          printf("%s\n", value ? value : "");
             }                  }
         } else {          } else {
             /* Have now read the entire graph and need to make a list of targets                  /* Have now read the entire graph and need to make a list
              * to create. If none was given on the command line, we consult the                   * of targets to create. If none was given on the command
              * parsing module to find the main target(s) to create.  */                   * line, we consult the parsing module to find the main
             if (Lst_IsEmpty(create))                   * target(s) to create.  */
                 Parse_MainName(&targs);                  if (Lst_IsEmpty(create))
             else                          Parse_MainName(&targs);
                 Targ_FindList(&targs, create);                  else
                           Targ_FindList(&targs, create);
   
             if (compatMake)                  if (compatMake)
                 /* Compat_Init will take care of creating all the targets as                          /* Compat_Init will take care of creating all the
                  * well as initializing the module.  */                           * targets as well as initializing the module.  */
                 Compat_Run(&targs);                          Compat_Run(&targs);
             else {                  else {
                 /* Initialize job module before traversing the graph, now that                          /* Initialize job module before traversing the graph,
                  * any .BEGIN and .END targets have been read.  This is done                           * now that any .BEGIN and .END targets have been
                  * only if the -q flag wasn't given (to prevent the .BEGIN from                           * read. This is done only if the -q flag wasn't given
                  * being executed should it exist).  */                           * (to prevent the .BEGIN from being executed should
                 if (!queryFlag) {                           * it exist).  */
                         if (maxLocal == -1)                          if (!queryFlag) {
                                 maxLocal = maxJobs;                                  if (maxLocal == -1)
                         Job_Init(maxJobs, maxLocal);                                          maxLocal = maxJobs;
                 }                                  Job_Init(maxJobs, maxLocal);
                           }
   
                 /* Traverse the graph, checking on all the targets.  */                          /* Traverse the graph, checking on all the targets.  */
                 outOfDate = Make_Run(&targs);                          outOfDate = Make_Run(&targs);
             }                  }
         }          }
   
 #ifdef CLEANUP  #ifdef CLEANUP
Line 745 
Line 816 
                 Targ_PrintGraph(2);                  Targ_PrintGraph(2);
   
 #ifdef CLEANUP  #ifdef CLEANUP
         if (objdir != curdir)          free_CURDIR_OBJDIR(&d);
             free(objdir);  
         free(curdir);  
         End();          End();
 #endif  #endif
         if (queryFlag && outOfDate)          if (queryFlag && outOfDate)
Line 767 
Line 836 
  *      lots   *      lots
  */   */
 static bool  static bool
 ReadMakefile(void *p, void *q UNUSED)  ReadMakefile(void *p, void *q)
 {  {
         char *fname = (char *)p;        /* makefile to read */          char *fname = (char *)p;        /* makefile to read */
           struct dirs *d = (struct dirs *)q;
         FILE *stream;          FILE *stream;
         char *name;          char *name;
   
Line 780 
Line 850 
                 if ((stream = fopen(fname, "r")) != NULL)                  if ((stream = fopen(fname, "r")) != NULL)
                         goto found;                          goto found;
                 /* if we've chdir'd, rebuild the path name */                  /* if we've chdir'd, rebuild the path name */
                 if (curdir != objdir && *fname != '/') {                  if (d->current != d->object && *fname != '/') {
                         char *path;                          char *path;
   
                         path = Str_concat(curdir, fname, '/');                          path = Str_concat(d->current, fname, '/');
                         if ((stream = fopen(path, "r")) == NULL)                          if ((stream = fopen(path, "r")) == NULL)
                             free(path);                                  free(path);
                         else {                          else {
                             fname = path;                                  fname = path;
                             goto found;                                  goto found;
                         }                          }
                 }                  }
                 /* look in -I and system include directories. */                  /* look in -I and system include directories. */

Legend:
Removed from v.1.74  
changed lines
  Added in v.1.75