main.c revision 17193
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1988, 1989, 1990, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * Copyright (c) 1989 by Berkeley Softworks 51590Srgrimes * All rights reserved. 61590Srgrimes * 71590Srgrimes * This code is derived from software contributed to Berkeley by 81590Srgrimes * Adam de Boor. 91590Srgrimes * 101590Srgrimes * Redistribution and use in source and binary forms, with or without 111590Srgrimes * modification, are permitted provided that the following conditions 121590Srgrimes * are met: 131590Srgrimes * 1. Redistributions of source code must retain the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer. 151590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161590Srgrimes * notice, this list of conditions and the following disclaimer in the 171590Srgrimes * documentation and/or other materials provided with the distribution. 181590Srgrimes * 3. All advertising materials mentioning features or use of this software 191590Srgrimes * must display the following acknowledgement: 201590Srgrimes * This product includes software developed by the University of 211590Srgrimes * California, Berkeley and its contributors. 221590Srgrimes * 4. Neither the name of the University nor the names of its contributors 231590Srgrimes * may be used to endorse or promote products derived from this software 241590Srgrimes * without specific prior written permission. 251590Srgrimes * 261590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 271590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 281590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 291590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 301590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 311590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 321590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 331590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 341590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 351590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 361590Srgrimes * SUCH DAMAGE. 371590Srgrimes */ 381590Srgrimes 391590Srgrimes#ifndef lint 401590Srgrimesstatic char copyright[] = 411590Srgrimes"@(#) Copyright (c) 1988, 1989, 1990, 1993\n\ 421590Srgrimes The Regents of the University of California. All rights reserved.\n"; 431590Srgrimes#endif /* not lint */ 441590Srgrimes 451590Srgrimes#ifndef lint 461590Srgrimesstatic char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; 471590Srgrimes#endif /* not lint */ 481590Srgrimes 491590Srgrimes/*- 501590Srgrimes * main.c -- 511590Srgrimes * The main file for this entire program. Exit routines etc 521590Srgrimes * reside here. 531590Srgrimes * 541590Srgrimes * Utility functions defined in this file: 551590Srgrimes * Main_ParseArgLine Takes a line of arguments, breaks them and 561590Srgrimes * treats them as if they were given when first 571590Srgrimes * invoked. Used by the parse module to implement 581590Srgrimes * the .MFLAGS target. 591590Srgrimes * 601590Srgrimes * Error Print a tagged error message. The global 611590Srgrimes * MAKE variable must have been defined. This 621590Srgrimes * takes a format string and two optional 631590Srgrimes * arguments for it. 641590Srgrimes * 651590Srgrimes * Fatal Print an error message and exit. Also takes 661590Srgrimes * a format string and two arguments. 671590Srgrimes * 681590Srgrimes * Punt Aborts all jobs and exits with a message. Also 691590Srgrimes * takes a format string and two arguments. 701590Srgrimes * 711590Srgrimes * Finish Finish things up by printing the number of 721590Srgrimes * errors which occured, as passed to it, and 731590Srgrimes * exiting. 741590Srgrimes */ 751590Srgrimes 761590Srgrimes#include <sys/types.h> 771590Srgrimes#include <sys/time.h> 781590Srgrimes#include <sys/param.h> 791590Srgrimes#include <sys/resource.h> 801590Srgrimes#include <sys/signal.h> 811590Srgrimes#include <sys/stat.h> 825814Sjkh#include <sys/utsname.h> 831590Srgrimes#include <errno.h> 841590Srgrimes#include <fcntl.h> 851590Srgrimes#include <stdio.h> 861590Srgrimes#if __STDC__ 871590Srgrimes#include <stdarg.h> 881590Srgrimes#else 891590Srgrimes#include <varargs.h> 901590Srgrimes#endif 911590Srgrimes#include "make.h" 921590Srgrimes#include "hash.h" 931590Srgrimes#include "dir.h" 941590Srgrimes#include "job.h" 951590Srgrimes#include "pathnames.h" 961590Srgrimes 971590Srgrimes#ifndef DEFMAXLOCAL 981590Srgrimes#define DEFMAXLOCAL DEFMAXJOBS 991590Srgrimes#endif DEFMAXLOCAL 1001590Srgrimes 1011590Srgrimes#define MAKEFLAGS ".MAKEFLAGS" 1021590Srgrimes 1031590SrgrimesLst create; /* Targets to be made */ 1041590Srgrimestime_t now; /* Time at start of make */ 1051590SrgrimesGNode *DEFAULT; /* .DEFAULT node */ 1061590SrgrimesBoolean allPrecious; /* .PRECIOUS given on line by itself */ 1071590Srgrimes 1081590Srgrimesstatic Boolean noBuiltins; /* -r flag */ 1091590Srgrimesstatic Lst makefiles; /* ordered list of makefiles to read */ 11017193Sbdestatic Boolean printVars; /* print value of one or more vars */ 11117193Sbdestatic Lst variables; /* list of variables to print */ 1121590Srgrimesint maxJobs; /* -J argument */ 1131590Srgrimesstatic int maxLocal; /* -L argument */ 1141590SrgrimesBoolean compatMake; /* -B argument */ 1151590SrgrimesBoolean debug; /* -d flag */ 1161590SrgrimesBoolean noExecute; /* -n flag */ 1171590SrgrimesBoolean keepgoing; /* -k flag */ 1181590SrgrimesBoolean queryFlag; /* -q flag */ 1191590SrgrimesBoolean touchFlag; /* -t flag */ 1201590SrgrimesBoolean usePipes; /* !-P flag */ 1211590SrgrimesBoolean ignoreErrors; /* -i flag */ 1221590SrgrimesBoolean beSilent; /* -s flag */ 1231590SrgrimesBoolean oldVars; /* variable substitution style */ 1241590SrgrimesBoolean checkEnvFirst; /* -e flag */ 1251590Srgrimesstatic Boolean jobsRunning; /* TRUE if the jobs might be running */ 1261590Srgrimes 1271590Srgrimesstatic Boolean ReadMakefile(); 1281590Srgrimesstatic void usage(); 1291590Srgrimes 1301590Srgrimesstatic char *curdir; /* startup directory */ 1311590Srgrimesstatic char *objdir; /* where we chdir'ed to */ 1321590Srgrimes 1331590Srgrimes/*- 1341590Srgrimes * MainParseArgs -- 1351590Srgrimes * Parse a given argument vector. Called from main() and from 1361590Srgrimes * Main_ParseArgLine() when the .MAKEFLAGS target is used. 1371590Srgrimes * 1381590Srgrimes * XXX: Deal with command line overriding .MAKEFLAGS in makefile 1391590Srgrimes * 1401590Srgrimes * Results: 1411590Srgrimes * None 1421590Srgrimes * 1431590Srgrimes * Side Effects: 1441590Srgrimes * Various global and local flags will be set depending on the flags 1451590Srgrimes * given 1461590Srgrimes */ 1471590Srgrimesstatic void 1481590SrgrimesMainParseArgs(argc, argv) 1491590Srgrimes int argc; 1501590Srgrimes char **argv; 1511590Srgrimes{ 1521590Srgrimes extern int optind; 1531590Srgrimes extern char *optarg; 1545814Sjkh int c; 1551590Srgrimes 1561590Srgrimes optind = 1; /* since we're called more than once */ 1571590Srgrimes#ifdef notyet 15817193Sbde# define OPTFLAGS "BD:I:L:PSVd:ef:ij:knqrst" 1591590Srgrimes#else 16017193Sbde# define OPTFLAGS "D:I:V:d:ef:ij:knqrst" 1611590Srgrimes#endif 1625814Sjkhrearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) { 1631590Srgrimes switch(c) { 1641590Srgrimes case 'D': 1651590Srgrimes Var_Set(optarg, "1", VAR_GLOBAL); 1661590Srgrimes Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); 1671590Srgrimes Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 1681590Srgrimes break; 1691590Srgrimes case 'I': 1701590Srgrimes Parse_AddIncludeDir(optarg); 1711590Srgrimes Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); 1721590Srgrimes Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 1731590Srgrimes break; 17417193Sbde case 'V': 17517193Sbde printVars = TRUE; 17617193Sbde (void)Lst_AtEnd(variables, (ClientData)optarg); 17717193Sbde Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); 17817193Sbde Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 17917193Sbde break; 1801590Srgrimes#ifdef notyet 1811590Srgrimes case 'B': 1821590Srgrimes compatMake = TRUE; 1831590Srgrimes break; 1841590Srgrimes case 'L': 1851590Srgrimes maxLocal = atoi(optarg); 1861590Srgrimes Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL); 1871590Srgrimes Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 1881590Srgrimes break; 1891590Srgrimes case 'P': 1901590Srgrimes usePipes = FALSE; 1911590Srgrimes Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL); 1921590Srgrimes break; 1931590Srgrimes case 'S': 1941590Srgrimes keepgoing = FALSE; 1951590Srgrimes Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); 1961590Srgrimes break; 1971590Srgrimes#endif 1981590Srgrimes case 'd': { 1991590Srgrimes char *modules = optarg; 2001590Srgrimes 2011590Srgrimes for (; *modules; ++modules) 2021590Srgrimes switch (*modules) { 2031590Srgrimes case 'A': 2041590Srgrimes debug = ~0; 2051590Srgrimes break; 2061590Srgrimes case 'a': 2071590Srgrimes debug |= DEBUG_ARCH; 2081590Srgrimes break; 2091590Srgrimes case 'c': 2101590Srgrimes debug |= DEBUG_COND; 2111590Srgrimes break; 2121590Srgrimes case 'd': 2131590Srgrimes debug |= DEBUG_DIR; 2141590Srgrimes break; 2151590Srgrimes case 'f': 2161590Srgrimes debug |= DEBUG_FOR; 2171590Srgrimes break; 2181590Srgrimes case 'g': 2191590Srgrimes if (modules[1] == '1') { 2201590Srgrimes debug |= DEBUG_GRAPH1; 2211590Srgrimes ++modules; 2221590Srgrimes } 2231590Srgrimes else if (modules[1] == '2') { 2241590Srgrimes debug |= DEBUG_GRAPH2; 2251590Srgrimes ++modules; 2261590Srgrimes } 2271590Srgrimes break; 2281590Srgrimes case 'j': 2291590Srgrimes debug |= DEBUG_JOB; 2301590Srgrimes break; 2311590Srgrimes case 'm': 2321590Srgrimes debug |= DEBUG_MAKE; 2331590Srgrimes break; 2341590Srgrimes case 's': 2351590Srgrimes debug |= DEBUG_SUFF; 2361590Srgrimes break; 2371590Srgrimes case 't': 2381590Srgrimes debug |= DEBUG_TARG; 2391590Srgrimes break; 2401590Srgrimes case 'v': 2411590Srgrimes debug |= DEBUG_VAR; 2421590Srgrimes break; 2431590Srgrimes default: 2441590Srgrimes (void)fprintf(stderr, 2451590Srgrimes "make: illegal argument to d option -- %c\n", 2461590Srgrimes *modules); 2471590Srgrimes usage(); 2481590Srgrimes } 2491590Srgrimes Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); 2501590Srgrimes Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 2511590Srgrimes break; 2521590Srgrimes } 2531590Srgrimes case 'e': 2541590Srgrimes checkEnvFirst = TRUE; 2551590Srgrimes Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); 2561590Srgrimes break; 2571590Srgrimes case 'f': 2581590Srgrimes (void)Lst_AtEnd(makefiles, (ClientData)optarg); 2591590Srgrimes break; 2601590Srgrimes case 'i': 2611590Srgrimes ignoreErrors = TRUE; 2621590Srgrimes Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); 2631590Srgrimes break; 2641590Srgrimes case 'j': 2651590Srgrimes maxJobs = atoi(optarg); 2661590Srgrimes Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); 2671590Srgrimes Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 2681590Srgrimes break; 2691590Srgrimes case 'k': 2701590Srgrimes keepgoing = TRUE; 2711590Srgrimes Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); 2721590Srgrimes break; 2731590Srgrimes case 'n': 2741590Srgrimes noExecute = TRUE; 2751590Srgrimes Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); 2761590Srgrimes break; 2771590Srgrimes case 'q': 2781590Srgrimes queryFlag = TRUE; 2791590Srgrimes /* Kind of nonsensical, wot? */ 2801590Srgrimes Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); 2811590Srgrimes break; 2821590Srgrimes case 'r': 2831590Srgrimes noBuiltins = TRUE; 2841590Srgrimes Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); 2851590Srgrimes break; 2861590Srgrimes case 's': 2871590Srgrimes beSilent = TRUE; 2881590Srgrimes Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); 2891590Srgrimes break; 2901590Srgrimes case 't': 2911590Srgrimes touchFlag = TRUE; 2921590Srgrimes Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); 2931590Srgrimes break; 2941590Srgrimes default: 2951590Srgrimes case '?': 2961590Srgrimes usage(); 2971590Srgrimes } 2981590Srgrimes } 2991590Srgrimes 3001590Srgrimes oldVars = TRUE; 3011590Srgrimes 3021590Srgrimes /* 3031590Srgrimes * See if the rest of the arguments are variable assignments and 3041590Srgrimes * perform them if so. Else take them to be targets and stuff them 3051590Srgrimes * on the end of the "create" list. 3061590Srgrimes */ 3071590Srgrimes for (argv += optind, argc -= optind; *argv; ++argv, --argc) 3081590Srgrimes if (Parse_IsVar(*argv)) 3091590Srgrimes Parse_DoVar(*argv, VAR_CMD); 3101590Srgrimes else { 3111590Srgrimes if (!**argv) 3121590Srgrimes Punt("illegal (null) argument."); 3131590Srgrimes if (**argv == '-') { 3141590Srgrimes if ((*argv)[1]) 3151590Srgrimes optind = 0; /* -flag... */ 3161590Srgrimes else 3171590Srgrimes optind = 1; /* - */ 3181590Srgrimes goto rearg; 3191590Srgrimes } 3205814Sjkh (void)Lst_AtEnd(create, (ClientData)strdup(*argv)); 3211590Srgrimes } 3221590Srgrimes} 3231590Srgrimes 3241590Srgrimes/*- 3251590Srgrimes * Main_ParseArgLine -- 3261590Srgrimes * Used by the parse module when a .MFLAGS or .MAKEFLAGS target 3271590Srgrimes * is encountered and by main() when reading the .MAKEFLAGS envariable. 3281590Srgrimes * Takes a line of arguments and breaks it into its 3291590Srgrimes * component words and passes those words and the number of them to the 3301590Srgrimes * MainParseArgs function. 3311590Srgrimes * The line should have all its leading whitespace removed. 3321590Srgrimes * 3331590Srgrimes * Results: 3341590Srgrimes * None 3351590Srgrimes * 3361590Srgrimes * Side Effects: 3371590Srgrimes * Only those that come from the various arguments. 3381590Srgrimes */ 3391590Srgrimesvoid 3401590SrgrimesMain_ParseArgLine(line) 3411590Srgrimes char *line; /* Line to fracture */ 3421590Srgrimes{ 3431590Srgrimes char **argv; /* Manufactured argument vector */ 3441590Srgrimes int argc; /* Number of arguments in argv */ 3451590Srgrimes 3461590Srgrimes if (line == NULL) 3471590Srgrimes return; 3481590Srgrimes for (; *line == ' '; ++line) 3491590Srgrimes continue; 3501590Srgrimes if (!*line) 3511590Srgrimes return; 3521590Srgrimes 3535814Sjkh argv = brk_string(line, &argc, TRUE); 3541590Srgrimes MainParseArgs(argc, argv); 3551590Srgrimes} 3561590Srgrimes 3571590Srgrimes/*- 3581590Srgrimes * main -- 3591590Srgrimes * The main function, for obvious reasons. Initializes variables 3601590Srgrimes * and a few modules, then parses the arguments give it in the 3611590Srgrimes * environment and on the command line. Reads the system makefile 3621590Srgrimes * followed by either Makefile, makefile or the file given by the 3631590Srgrimes * -f argument. Sets the .MAKEFLAGS PMake variable based on all the 3641590Srgrimes * flags it has received by then uses either the Make or the Compat 3651590Srgrimes * module to create the initial list of targets. 3661590Srgrimes * 3671590Srgrimes * Results: 3681590Srgrimes * If -q was given, exits -1 if anything was out-of-date. Else it exits 3691590Srgrimes * 0. 3701590Srgrimes * 3711590Srgrimes * Side Effects: 3721590Srgrimes * The program exits when done. Targets are created. etc. etc. etc. 3731590Srgrimes */ 3741590Srgrimesint 3751590Srgrimesmain(argc, argv) 3761590Srgrimes int argc; 3771590Srgrimes char **argv; 3781590Srgrimes{ 3791590Srgrimes Lst targs; /* target nodes to create -- passed to Make_Init */ 3801590Srgrimes Boolean outOfDate = TRUE; /* FALSE if all targets up to date */ 3811590Srgrimes struct stat sb, sa; 3825814Sjkh char *p, *p1, *path, *pwd, *getenv(), *getwd(); 3831590Srgrimes char mdpath[MAXPATHLEN + 1]; 3841590Srgrimes char obpath[MAXPATHLEN + 1]; 3851590Srgrimes char cdpath[MAXPATHLEN + 1]; 38616663Sjkh char *realobjdir; /* Where we'd like to go */ 3875814Sjkh struct utsname utsname; 3885814Sjkh char *machine = getenv("MACHINE"); 3891590Srgrimes 3901590Srgrimes /* 3911590Srgrimes * Find where we are and take care of PWD for the automounter... 3921590Srgrimes * All this code is so that we know where we are when we start up 3931590Srgrimes * on a different machine with pmake. 3941590Srgrimes */ 3951590Srgrimes curdir = cdpath; 3965814Sjkh if (getcwd(curdir, MAXPATHLEN) == NULL) { 3975814Sjkh (void)fprintf(stderr, "make: %s.\n", strerror(errno)); 3981590Srgrimes exit(2); 3991590Srgrimes } 4001590Srgrimes 4011590Srgrimes if (stat(curdir, &sa) == -1) { 4021590Srgrimes (void)fprintf(stderr, "make: %s: %s.\n", 4031590Srgrimes curdir, strerror(errno)); 4041590Srgrimes exit(2); 4051590Srgrimes } 4061590Srgrimes 40716885Sjkh if ((pwd = getenv("PWD")) != NULL) { 40816885Sjkh if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino && 40916885Sjkh sa.st_dev == sb.st_dev) 41016885Sjkh (void) strcpy(curdir, pwd); 41116885Sjkh } 41216885Sjkh 4135814Sjkh /* 4145814Sjkh * Get the name of this type of MACHINE from utsname 4155814Sjkh * so we can share an executable for similar machines. 4165814Sjkh * (i.e. m68k: amiga hp300, mac68k, sun3, ...) 4175814Sjkh * 4185814Sjkh * Note that while MACHINE is decided at run-time, 4195814Sjkh * MACHINE_ARCH is always known at compile time. 4205814Sjkh */ 4215814Sjkh if (!machine) { 4225814Sjkh if (uname(&utsname)) { 4235814Sjkh perror("make: uname"); 4245814Sjkh exit(2); 4255814Sjkh } 4265814Sjkh machine = utsname.machine; 4275814Sjkh } 4281590Srgrimes 4291590Srgrimes /* 4301590Srgrimes * if the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory 4311590Srgrimes * exists, change into it and build there. Once things are 4321590Srgrimes * initted, have to add the original directory to the search path, 4331590Srgrimes * and modify the paths for the Makefiles apropriately. The 4341590Srgrimes * current directory is also placed as a variable for make scripts. 4351590Srgrimes */ 43616663Sjkh if (!(path = getenv("MAKEOBJDIR"))) 4371590Srgrimes path = _PATH_OBJDIR; 43816663Sjkh (void) snprintf(mdpath, MAXPATHLEN, "%s%s", path, curdir); 43916663Sjkh realobjdir = mdpath; /* This is where we'd _like_ to be, anyway */ 4408874Srgrimes 4411590Srgrimes if (stat(mdpath, &sb) == 0 && S_ISDIR(sb.st_mode)) { 4421590Srgrimes 4431590Srgrimes if (chdir(mdpath)) { 4441590Srgrimes (void)fprintf(stderr, "make warning: %s: %s.\n", 4451590Srgrimes mdpath, strerror(errno)); 4461590Srgrimes objdir = curdir; 4471590Srgrimes } 4481590Srgrimes else { 4491590Srgrimes if (mdpath[0] != '/') { 4501590Srgrimes (void) sprintf(obpath, "%s/%s", curdir, mdpath); 4511590Srgrimes objdir = obpath; 4521590Srgrimes } 4531590Srgrimes else 4541590Srgrimes objdir = mdpath; 4551590Srgrimes } 4561590Srgrimes } 45716663Sjkh else 45816663Sjkh objdir = curdir; 4591590Srgrimes 4601590Srgrimes setenv("PWD", objdir, 1); 4611590Srgrimes 4621590Srgrimes create = Lst_Init(FALSE); 4631590Srgrimes makefiles = Lst_Init(FALSE); 46417193Sbde printVars = FALSE; 46517193Sbde variables = Lst_Init(FALSE); 4661590Srgrimes beSilent = FALSE; /* Print commands as executed */ 4671590Srgrimes ignoreErrors = FALSE; /* Pay attention to non-zero returns */ 4681590Srgrimes noExecute = FALSE; /* Execute all commands */ 4691590Srgrimes keepgoing = FALSE; /* Stop on error */ 4701590Srgrimes allPrecious = FALSE; /* Remove targets when interrupted */ 4711590Srgrimes queryFlag = FALSE; /* This is not just a check-run */ 4721590Srgrimes noBuiltins = FALSE; /* Read the built-in rules */ 4731590Srgrimes touchFlag = FALSE; /* Actually update targets */ 4741590Srgrimes usePipes = TRUE; /* Catch child output in pipes */ 4751590Srgrimes debug = 0; /* No debug verbosity, please. */ 4761590Srgrimes jobsRunning = FALSE; 4771590Srgrimes 4781590Srgrimes maxJobs = DEFMAXJOBS; /* Set default max concurrency */ 4791590Srgrimes maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */ 4801590Srgrimes#ifdef notyet 4811590Srgrimes compatMake = FALSE; /* No compat mode */ 4821590Srgrimes#else 4831590Srgrimes compatMake = TRUE; /* No compat mode */ 4841590Srgrimes#endif 4851590Srgrimes 4868874Srgrimes 4871590Srgrimes /* 4881590Srgrimes * Initialize the parsing, directory and variable modules to prepare 4891590Srgrimes * for the reading of inclusion paths and variable settings on the 4901590Srgrimes * command line 4911590Srgrimes */ 4921590Srgrimes Dir_Init(); /* Initialize directory structures so -I flags 4931590Srgrimes * can be processed correctly */ 4941590Srgrimes Parse_Init(); /* Need to initialize the paths of #include 4951590Srgrimes * directories */ 4961590Srgrimes Var_Init(); /* As well as the lists of variables for 4971590Srgrimes * parsing arguments */ 4985814Sjkh str_init(); 4991590Srgrimes if (objdir != curdir) 5001590Srgrimes Dir_AddDir(dirSearchPath, curdir); 5011590Srgrimes Var_Set(".CURDIR", curdir, VAR_GLOBAL); 50216663Sjkh Var_Set(".TARGETOBJDIR", realobjdir, VAR_GLOBAL); 5031590Srgrimes Var_Set(".OBJDIR", objdir, VAR_GLOBAL); 5041590Srgrimes 5051590Srgrimes /* 5061590Srgrimes * Initialize various variables. 5071590Srgrimes * MAKE also gets this name, for compatibility 5081590Srgrimes * .MAKEFLAGS gets set to the empty string just in case. 5091590Srgrimes * MFLAGS also gets initialized empty, for compatibility. 5101590Srgrimes */ 5111590Srgrimes Var_Set("MAKE", argv[0], VAR_GLOBAL); 5121590Srgrimes Var_Set(MAKEFLAGS, "", VAR_GLOBAL); 5131590Srgrimes Var_Set("MFLAGS", "", VAR_GLOBAL); 5145814Sjkh Var_Set("MACHINE", machine, VAR_GLOBAL); 5151590Srgrimes#ifdef MACHINE_ARCH 5161590Srgrimes Var_Set("MACHINE_ARCH", MACHINE_ARCH, VAR_GLOBAL); 5171590Srgrimes#endif 5181590Srgrimes 5191590Srgrimes /* 5201590Srgrimes * First snag any flags out of the MAKE environment variable. 5211590Srgrimes * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's 5221590Srgrimes * in a different format). 5231590Srgrimes */ 5241590Srgrimes#ifdef POSIX 5251590Srgrimes Main_ParseArgLine(getenv("MAKEFLAGS")); 5261590Srgrimes#else 5271590Srgrimes Main_ParseArgLine(getenv("MAKE")); 5281590Srgrimes#endif 5298874Srgrimes 5301590Srgrimes MainParseArgs(argc, argv); 5311590Srgrimes 5321590Srgrimes /* 5331590Srgrimes * Initialize archive, target and suffix modules in preparation for 5341590Srgrimes * parsing the makefile(s) 5351590Srgrimes */ 5361590Srgrimes Arch_Init(); 5371590Srgrimes Targ_Init(); 5381590Srgrimes Suff_Init(); 5391590Srgrimes 5401590Srgrimes DEFAULT = NILGNODE; 5411590Srgrimes (void)time(&now); 5421590Srgrimes 5431590Srgrimes /* 5441590Srgrimes * Set up the .TARGETS variable to contain the list of targets to be 5451590Srgrimes * created. If none specified, make the variable empty -- the parser 5461590Srgrimes * will fill the thing in with the default or .MAIN target. 5471590Srgrimes */ 5481590Srgrimes if (!Lst_IsEmpty(create)) { 5491590Srgrimes LstNode ln; 5501590Srgrimes 5511590Srgrimes for (ln = Lst_First(create); ln != NILLNODE; 5521590Srgrimes ln = Lst_Succ(ln)) { 5531590Srgrimes char *name = (char *)Lst_Datum(ln); 5541590Srgrimes 5551590Srgrimes Var_Append(".TARGETS", name, VAR_GLOBAL); 5561590Srgrimes } 5571590Srgrimes } else 5581590Srgrimes Var_Set(".TARGETS", "", VAR_GLOBAL); 5591590Srgrimes 5601590Srgrimes /* 5611590Srgrimes * Read in the built-in rules first, followed by the specified makefile, 5621590Srgrimes * if it was (makefile != (char *) NULL), or the default Makefile and 5631590Srgrimes * makefile, in that order, if it wasn't. 5641590Srgrimes */ 5651590Srgrimes if (!noBuiltins && !ReadMakefile(_PATH_DEFSYSMK)) 5661590Srgrimes Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); 5671590Srgrimes 5681590Srgrimes if (!Lst_IsEmpty(makefiles)) { 5691590Srgrimes LstNode ln; 5701590Srgrimes 5711590Srgrimes ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile); 5721590Srgrimes if (ln != NILLNODE) 5731590Srgrimes Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); 5741590Srgrimes } else if (!ReadMakefile("makefile")) 5751590Srgrimes (void)ReadMakefile("Makefile"); 5761590Srgrimes 5771590Srgrimes (void)ReadMakefile(".depend"); 5781590Srgrimes 5795814Sjkh Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL); 5805814Sjkh if (p1) 5815814Sjkh free(p1); 5821590Srgrimes 5831590Srgrimes /* Install all the flags into the MAKE envariable. */ 5845814Sjkh if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p) 5851590Srgrimes#ifdef POSIX 5861590Srgrimes setenv("MAKEFLAGS", p, 1); 5871590Srgrimes#else 5881590Srgrimes setenv("MAKE", p, 1); 5891590Srgrimes#endif 5905814Sjkh if (p1) 5915814Sjkh free(p1); 5921590Srgrimes 5931590Srgrimes /* 5941590Srgrimes * For compatibility, look at the directories in the VPATH variable 5951590Srgrimes * and add them to the search path, if the variable is defined. The 5961590Srgrimes * variable's value is in the same format as the PATH envariable, i.e. 5971590Srgrimes * <directory>:<directory>:<directory>... 5981590Srgrimes */ 5991590Srgrimes if (Var_Exists("VPATH", VAR_CMD)) { 6001590Srgrimes char *vpath, *path, *cp, savec; 6011590Srgrimes /* 6021590Srgrimes * GCC stores string constants in read-only memory, but 6031590Srgrimes * Var_Subst will want to write this thing, so store it 6041590Srgrimes * in an array 6051590Srgrimes */ 6061590Srgrimes static char VPATH[] = "${VPATH}"; 6071590Srgrimes 6081590Srgrimes vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE); 6091590Srgrimes path = vpath; 6101590Srgrimes do { 6111590Srgrimes /* skip to end of directory */ 6121590Srgrimes for (cp = path; *cp != ':' && *cp != '\0'; cp++) 6131590Srgrimes continue; 6141590Srgrimes /* Save terminator character so know when to stop */ 6151590Srgrimes savec = *cp; 6161590Srgrimes *cp = '\0'; 6171590Srgrimes /* Add directory to search path */ 6181590Srgrimes Dir_AddDir(dirSearchPath, path); 6191590Srgrimes *cp = savec; 6201590Srgrimes path = cp + 1; 6211590Srgrimes } while (savec == ':'); 6221590Srgrimes (void)free((Address)vpath); 6231590Srgrimes } 6241590Srgrimes 6251590Srgrimes /* 6261590Srgrimes * Now that all search paths have been read for suffixes et al, it's 6271590Srgrimes * time to add the default search path to their lists... 6281590Srgrimes */ 6291590Srgrimes Suff_DoPaths(); 6301590Srgrimes 6311590Srgrimes /* print the initial graph, if the user requested it */ 6321590Srgrimes if (DEBUG(GRAPH1)) 6331590Srgrimes Targ_PrintGraph(1); 6341590Srgrimes 63517193Sbde /* print the values of any variables requested by the user */ 63617193Sbde if (printVars) { 63717193Sbde LstNode ln; 63817193Sbde 63917193Sbde for (ln = Lst_First(variables); ln != NILLNODE; 64017193Sbde ln = Lst_Succ(ln)) { 64117193Sbde char *value = Var_Value((char *)Lst_Datum(ln), 64217193Sbde VAR_GLOBAL, &p1); 64317193Sbde 64417193Sbde printf("%s\n", value ? value : ""); 64517193Sbde if (p1) 64617193Sbde free(p1); 64717193Sbde } 64817193Sbde } 64917193Sbde 6501590Srgrimes /* 6511590Srgrimes * Have now read the entire graph and need to make a list of targets 6521590Srgrimes * to create. If none was given on the command line, we consult the 6531590Srgrimes * parsing module to find the main target(s) to create. 6541590Srgrimes */ 6551590Srgrimes if (Lst_IsEmpty(create)) 6561590Srgrimes targs = Parse_MainName(); 6571590Srgrimes else 6581590Srgrimes targs = Targ_FindList(create, TARG_CREATE); 6591590Srgrimes 6601590Srgrimes/* 6611590Srgrimes * this was original amMake -- want to allow parallelism, so put this 6621590Srgrimes * back in, eventually. 6631590Srgrimes */ 66417193Sbde if (!compatMake && !printVars) { 6651590Srgrimes /* 6661590Srgrimes * Initialize job module before traversing the graph, now that 6671590Srgrimes * any .BEGIN and .END targets have been read. This is done 6681590Srgrimes * only if the -q flag wasn't given (to prevent the .BEGIN from 6691590Srgrimes * being executed should it exist). 6701590Srgrimes */ 6711590Srgrimes if (!queryFlag) { 6721590Srgrimes if (maxLocal == -1) 6731590Srgrimes maxLocal = maxJobs; 6741590Srgrimes Job_Init(maxJobs, maxLocal); 6751590Srgrimes jobsRunning = TRUE; 6761590Srgrimes } 6771590Srgrimes 6781590Srgrimes /* Traverse the graph, checking on all the targets */ 6791590Srgrimes outOfDate = Make_Run(targs); 68017193Sbde } else if (!printVars) { 6811590Srgrimes /* 6821590Srgrimes * Compat_Init will take care of creating all the targets as 6831590Srgrimes * well as initializing the module. 6841590Srgrimes */ 6851590Srgrimes Compat_Run(targs); 68617193Sbde } 6878874Srgrimes 6885814Sjkh Lst_Destroy(targs, NOFREE); 68917193Sbde Lst_Destroy(variables, NOFREE); 6905814Sjkh Lst_Destroy(makefiles, NOFREE); 6915814Sjkh Lst_Destroy(create, (void (*) __P((ClientData))) free); 6925814Sjkh 6931590Srgrimes /* print the graph now it's been processed if the user requested it */ 6941590Srgrimes if (DEBUG(GRAPH2)) 6951590Srgrimes Targ_PrintGraph(2); 6961590Srgrimes 6975814Sjkh Suff_End(); 6985814Sjkh Targ_End(); 6995814Sjkh Arch_End(); 7005814Sjkh str_end(); 7015814Sjkh Var_End(); 7025814Sjkh Parse_End(); 7035814Sjkh Dir_End(); 7045814Sjkh 7051590Srgrimes if (queryFlag && outOfDate) 7061590Srgrimes return(1); 7071590Srgrimes else 7081590Srgrimes return(0); 7091590Srgrimes} 7101590Srgrimes 7111590Srgrimes/*- 7121590Srgrimes * ReadMakefile -- 7131590Srgrimes * Open and parse the given makefile. 7141590Srgrimes * 7151590Srgrimes * Results: 7161590Srgrimes * TRUE if ok. FALSE if couldn't open file. 7171590Srgrimes * 7181590Srgrimes * Side Effects: 7191590Srgrimes * lots 7201590Srgrimes */ 7211590Srgrimesstatic Boolean 7221590SrgrimesReadMakefile(fname) 7231590Srgrimes char *fname; /* makefile to read */ 7241590Srgrimes{ 7251590Srgrimes extern Lst parseIncPath, sysIncPath; 7261590Srgrimes FILE *stream; 7271590Srgrimes char *name, path[MAXPATHLEN + 1]; 7281590Srgrimes 7291590Srgrimes if (!strcmp(fname, "-")) { 7301590Srgrimes Parse_File("(stdin)", stdin); 7311590Srgrimes Var_Set("MAKEFILE", "", VAR_GLOBAL); 7321590Srgrimes } else { 7331590Srgrimes if ((stream = fopen(fname, "r")) != NULL) 7341590Srgrimes goto found; 7351590Srgrimes /* if we've chdir'd, rebuild the path name */ 7361590Srgrimes if (curdir != objdir && *fname != '/') { 7371590Srgrimes (void)sprintf(path, "%s/%s", curdir, fname); 7381590Srgrimes if ((stream = fopen(path, "r")) != NULL) { 7391590Srgrimes fname = path; 7401590Srgrimes goto found; 7411590Srgrimes } 7421590Srgrimes } 7431590Srgrimes /* look in -I and system include directories. */ 7441590Srgrimes name = Dir_FindFile(fname, parseIncPath); 7451590Srgrimes if (!name) 7461590Srgrimes name = Dir_FindFile(fname, sysIncPath); 7471590Srgrimes if (!name || !(stream = fopen(name, "r"))) 7481590Srgrimes return(FALSE); 7491590Srgrimes fname = name; 7501590Srgrimes /* 7511590Srgrimes * set the MAKEFILE variable desired by System V fans -- the 7521590Srgrimes * placement of the setting here means it gets set to the last 7531590Srgrimes * makefile specified, as it is set by SysV make. 7541590Srgrimes */ 7551590Srgrimesfound: Var_Set("MAKEFILE", fname, VAR_GLOBAL); 7561590Srgrimes Parse_File(fname, stream); 7571590Srgrimes (void)fclose(stream); 7581590Srgrimes } 7591590Srgrimes return(TRUE); 7601590Srgrimes} 7611590Srgrimes 7621590Srgrimes/*- 7631590Srgrimes * Error -- 7641590Srgrimes * Print an error message given its format. 7651590Srgrimes * 7661590Srgrimes * Results: 7671590Srgrimes * None. 7681590Srgrimes * 7691590Srgrimes * Side Effects: 7701590Srgrimes * The message is printed. 7711590Srgrimes */ 7721590Srgrimes/* VARARGS */ 7731590Srgrimesvoid 7741590Srgrimes#if __STDC__ 7755814SjkhError(char *fmt, ...) 7761590Srgrimes#else 7771590SrgrimesError(va_alist) 7781590Srgrimes va_dcl 7791590Srgrimes#endif 7801590Srgrimes{ 7811590Srgrimes va_list ap; 7821590Srgrimes#if __STDC__ 7831590Srgrimes va_start(ap, fmt); 7841590Srgrimes#else 7851590Srgrimes char *fmt; 7861590Srgrimes 7871590Srgrimes va_start(ap); 7881590Srgrimes fmt = va_arg(ap, char *); 7891590Srgrimes#endif 7901590Srgrimes (void)vfprintf(stderr, fmt, ap); 7911590Srgrimes va_end(ap); 7921590Srgrimes (void)fprintf(stderr, "\n"); 7931590Srgrimes (void)fflush(stderr); 7941590Srgrimes} 7951590Srgrimes 7961590Srgrimes/*- 7971590Srgrimes * Fatal -- 7981590Srgrimes * Produce a Fatal error message. If jobs are running, waits for them 7991590Srgrimes * to finish. 8001590Srgrimes * 8011590Srgrimes * Results: 8021590Srgrimes * None 8031590Srgrimes * 8041590Srgrimes * Side Effects: 8051590Srgrimes * The program exits 8061590Srgrimes */ 8071590Srgrimes/* VARARGS */ 8081590Srgrimesvoid 8091590Srgrimes#if __STDC__ 8105814SjkhFatal(char *fmt, ...) 8111590Srgrimes#else 8121590SrgrimesFatal(va_alist) 8131590Srgrimes va_dcl 8141590Srgrimes#endif 8151590Srgrimes{ 8161590Srgrimes va_list ap; 8171590Srgrimes#if __STDC__ 8181590Srgrimes va_start(ap, fmt); 8191590Srgrimes#else 8201590Srgrimes char *fmt; 8211590Srgrimes 8221590Srgrimes va_start(ap); 8231590Srgrimes fmt = va_arg(ap, char *); 8241590Srgrimes#endif 8251590Srgrimes if (jobsRunning) 8261590Srgrimes Job_Wait(); 8271590Srgrimes 8281590Srgrimes (void)vfprintf(stderr, fmt, ap); 8291590Srgrimes va_end(ap); 8301590Srgrimes (void)fprintf(stderr, "\n"); 8311590Srgrimes (void)fflush(stderr); 8321590Srgrimes 8331590Srgrimes if (DEBUG(GRAPH2)) 8341590Srgrimes Targ_PrintGraph(2); 8351590Srgrimes exit(2); /* Not 1 so -q can distinguish error */ 8361590Srgrimes} 8371590Srgrimes 8381590Srgrimes/* 8391590Srgrimes * Punt -- 8401590Srgrimes * Major exception once jobs are being created. Kills all jobs, prints 8411590Srgrimes * a message and exits. 8421590Srgrimes * 8431590Srgrimes * Results: 8448874Srgrimes * None 8451590Srgrimes * 8461590Srgrimes * Side Effects: 8471590Srgrimes * All children are killed indiscriminately and the program Lib_Exits 8481590Srgrimes */ 8491590Srgrimes/* VARARGS */ 8501590Srgrimesvoid 8511590Srgrimes#if __STDC__ 8525814SjkhPunt(char *fmt, ...) 8531590Srgrimes#else 8541590SrgrimesPunt(va_alist) 8551590Srgrimes va_dcl 8561590Srgrimes#endif 8571590Srgrimes{ 8581590Srgrimes va_list ap; 8591590Srgrimes#if __STDC__ 8601590Srgrimes va_start(ap, fmt); 8611590Srgrimes#else 8621590Srgrimes char *fmt; 8631590Srgrimes 8641590Srgrimes va_start(ap); 8651590Srgrimes fmt = va_arg(ap, char *); 8661590Srgrimes#endif 8671590Srgrimes 8681590Srgrimes (void)fprintf(stderr, "make: "); 8691590Srgrimes (void)vfprintf(stderr, fmt, ap); 8701590Srgrimes va_end(ap); 8711590Srgrimes (void)fprintf(stderr, "\n"); 8721590Srgrimes (void)fflush(stderr); 8731590Srgrimes 8741590Srgrimes DieHorribly(); 8751590Srgrimes} 8761590Srgrimes 8771590Srgrimes/*- 8781590Srgrimes * DieHorribly -- 8791590Srgrimes * Exit without giving a message. 8801590Srgrimes * 8811590Srgrimes * Results: 8821590Srgrimes * None 8831590Srgrimes * 8841590Srgrimes * Side Effects: 8851590Srgrimes * A big one... 8861590Srgrimes */ 8871590Srgrimesvoid 8881590SrgrimesDieHorribly() 8891590Srgrimes{ 8901590Srgrimes if (jobsRunning) 8911590Srgrimes Job_AbortAll(); 8921590Srgrimes if (DEBUG(GRAPH2)) 8931590Srgrimes Targ_PrintGraph(2); 8941590Srgrimes exit(2); /* Not 1, so -q can distinguish error */ 8951590Srgrimes} 8961590Srgrimes 8971590Srgrimes/* 8981590Srgrimes * Finish -- 8991590Srgrimes * Called when aborting due to errors in child shell to signal 9008874Srgrimes * abnormal exit. 9011590Srgrimes * 9021590Srgrimes * Results: 9038874Srgrimes * None 9041590Srgrimes * 9051590Srgrimes * Side Effects: 9061590Srgrimes * The program exits 9071590Srgrimes */ 9081590Srgrimesvoid 9091590SrgrimesFinish(errors) 9101590Srgrimes int errors; /* number of errors encountered in Make_Make */ 9111590Srgrimes{ 9121590Srgrimes Fatal("%d error%s", errors, errors == 1 ? "" : "s"); 9131590Srgrimes} 9141590Srgrimes 9151590Srgrimes/* 9161590Srgrimes * emalloc -- 9171590Srgrimes * malloc, but die on error. 9181590Srgrimes */ 9191590Srgrimeschar * 9201590Srgrimesemalloc(len) 9215814Sjkh size_t len; 9221590Srgrimes{ 9231590Srgrimes char *p; 9241590Srgrimes 9255814Sjkh if ((p = (char *) malloc(len)) == NULL) 9261590Srgrimes enomem(); 9271590Srgrimes return(p); 9281590Srgrimes} 9291590Srgrimes 9301590Srgrimes/* 9311590Srgrimes * enomem -- 9321590Srgrimes * die when out of memory. 9331590Srgrimes */ 9341590Srgrimesvoid 9351590Srgrimesenomem() 9361590Srgrimes{ 9371590Srgrimes (void)fprintf(stderr, "make: %s.\n", strerror(errno)); 9381590Srgrimes exit(2); 9391590Srgrimes} 9401590Srgrimes 9411590Srgrimes/* 9421590Srgrimes * usage -- 9431590Srgrimes * exit with usage message 9441590Srgrimes */ 9451590Srgrimesstatic void 9461590Srgrimesusage() 9471590Srgrimes{ 9481590Srgrimes (void)fprintf(stderr, 94917193Sbde"usage: make [-eiknqrst] [-D variable] [-d flags] [-f makefile] [-I directory]\n\ 95017193Sbde [-j max_jobs] [-V variable] [variable=value] [target ...]\n"); 9511590Srgrimes exit(2); 9521590Srgrimes} 9535814Sjkh 9545814Sjkh 9555814Sjkhint 9565814SjkhPrintAddr(a, b) 9575814Sjkh ClientData a; 9585814Sjkh ClientData b; 9595814Sjkh{ 9605814Sjkh printf("%lx ", (unsigned long) a); 9615814Sjkh return b ? 0 : 0; 9625814Sjkh} 963