2011-09-16 19:38:03 +04:00
|
|
|
/* $NetBSD: main.c,v 1.198 2011/09/16 15:38:04 joerg Exp $ */
|
1995-06-14 19:18:37 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1996-11-06 20:58:58 +03:00
|
|
|
* Copyright (c) 1988, 1989, 1990, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
2003-08-07 15:13:06 +04:00
|
|
|
*
|
|
|
|
* This code is derived from software contributed to Berkeley by
|
|
|
|
* Adam de Boor.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
1993-03-21 12:45:37 +03:00
|
|
|
* Copyright (c) 1989 by Berkeley Softworks
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to Berkeley by
|
|
|
|
* Adam de Boor.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the University of
|
|
|
|
* California, Berkeley and its contributors.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2004-05-07 04:04:38 +04:00
|
|
|
#ifndef MAKE_NATIVE
|
2011-09-16 19:38:03 +04:00
|
|
|
static char rcsid[] = "$NetBSD: main.c,v 1.198 2011/09/16 15:38:04 joerg Exp $";
|
1997-09-28 07:30:58 +04:00
|
|
|
#else
|
1997-07-02 01:17:00 +04:00
|
|
|
#include <sys/cdefs.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#ifndef lint
|
2008-07-21 18:19:20 +04:00
|
|
|
__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\
|
|
|
|
The Regents of the University of California. All rights reserved.");
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
#ifndef lint
|
1995-06-14 19:18:37 +04:00
|
|
|
#if 0
|
1996-11-06 20:58:58 +03:00
|
|
|
static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
|
1995-06-14 19:18:37 +04:00
|
|
|
#else
|
2011-09-16 19:38:03 +04:00
|
|
|
__RCSID("$NetBSD: main.c,v 1.198 2011/09/16 15:38:04 joerg Exp $");
|
1995-06-14 19:18:37 +04:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif /* not lint */
|
1997-09-28 07:30:58 +04:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*-
|
|
|
|
* main.c --
|
|
|
|
* The main file for this entire program. Exit routines etc
|
|
|
|
* reside here.
|
|
|
|
*
|
|
|
|
* Utility functions defined in this file:
|
|
|
|
* Main_ParseArgLine Takes a line of arguments, breaks them and
|
|
|
|
* treats them as if they were given when first
|
|
|
|
* invoked. Used by the parse module to implement
|
|
|
|
* the .MFLAGS target.
|
|
|
|
*
|
|
|
|
* Error Print a tagged error message. The global
|
|
|
|
* MAKE variable must have been defined. This
|
|
|
|
* takes a format string and two optional
|
|
|
|
* arguments for it.
|
|
|
|
*
|
|
|
|
* Fatal Print an error message and exit. Also takes
|
|
|
|
* a format string and two arguments.
|
|
|
|
*
|
|
|
|
* Punt Aborts all jobs and exits with a message. Also
|
|
|
|
* takes a format string and two arguments.
|
|
|
|
*
|
|
|
|
* Finish Finish things up by printing the number of
|
2001-09-16 20:34:23 +04:00
|
|
|
* errors which occurred, as passed to it, and
|
1993-03-21 12:45:37 +03:00
|
|
|
* exiting.
|
|
|
|
*/
|
|
|
|
|
1994-03-05 03:34:29 +03:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/time.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <sys/param.h>
|
1994-03-05 03:34:29 +03:00
|
|
|
#include <sys/resource.h>
|
1995-11-03 02:54:35 +03:00
|
|
|
#include <sys/signal.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <sys/stat.h>
|
2004-05-07 04:04:38 +04:00
|
|
|
#ifdef MAKE_NATIVE
|
1994-09-30 06:14:21 +03:00
|
|
|
#include <sys/utsname.h>
|
1996-11-06 20:58:58 +03:00
|
|
|
#endif
|
1996-05-29 03:34:35 +04:00
|
|
|
#include <sys/wait.h>
|
2002-06-15 22:24:55 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
2002-06-15 22:24:55 +04:00
|
|
|
#include <stdarg.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <stdio.h>
|
1996-12-31 20:54:16 +03:00
|
|
|
#include <stdlib.h>
|
1998-04-02 14:33:17 +04:00
|
|
|
#include <time.h>
|
2002-06-15 22:24:55 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
#include "make.h"
|
1994-03-05 03:34:29 +03:00
|
|
|
#include "hash.h"
|
|
|
|
#include "dir.h"
|
|
|
|
#include "job.h"
|
1993-03-21 12:45:37 +03:00
|
|
|
#include "pathnames.h"
|
2000-12-30 05:05:20 +03:00
|
|
|
#include "trace.h"
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2001-05-29 21:37:51 +04:00
|
|
|
#ifdef USE_IOVEC
|
|
|
|
#include <sys/uio.h>
|
|
|
|
#endif
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
#ifndef DEFMAXLOCAL
|
|
|
|
#define DEFMAXLOCAL DEFMAXJOBS
|
1996-02-05 01:20:27 +03:00
|
|
|
#endif /* DEFMAXLOCAL */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
Lst create; /* Targets to be made */
|
|
|
|
time_t now; /* Time at start of make */
|
|
|
|
GNode *DEFAULT; /* .DEFAULT node */
|
|
|
|
Boolean allPrecious; /* .PRECIOUS given on line by itself */
|
|
|
|
|
|
|
|
static Boolean noBuiltins; /* -r flag */
|
|
|
|
static Lst makefiles; /* ordered list of makefiles to read */
|
1996-11-06 20:58:58 +03:00
|
|
|
static Boolean printVars; /* print value of one or more vars */
|
|
|
|
static Lst variables; /* list of variables to print */
|
1995-11-03 02:54:35 +03:00
|
|
|
int maxJobs; /* -j argument */
|
2006-10-11 11:01:44 +04:00
|
|
|
static int maxJobTokens; /* -j argument */
|
1994-03-05 03:34:29 +03:00
|
|
|
Boolean compatMake; /* -B argument */
|
2005-08-04 00:55:01 +04:00
|
|
|
int debug; /* -d argument */
|
1993-03-21 12:45:37 +03:00
|
|
|
Boolean noExecute; /* -n flag */
|
2001-01-01 18:47:37 +03:00
|
|
|
Boolean noRecursiveExecute; /* -N flag */
|
1993-03-21 12:45:37 +03:00
|
|
|
Boolean keepgoing; /* -k flag */
|
|
|
|
Boolean queryFlag; /* -q flag */
|
|
|
|
Boolean touchFlag; /* -t flag */
|
|
|
|
Boolean ignoreErrors; /* -i flag */
|
|
|
|
Boolean beSilent; /* -s flag */
|
|
|
|
Boolean oldVars; /* variable substitution style */
|
|
|
|
Boolean checkEnvFirst; /* -e flag */
|
2001-01-10 18:54:00 +03:00
|
|
|
Boolean parseWarnFatal; /* -W flag */
|
2000-12-30 05:05:20 +03:00
|
|
|
Boolean jobServer; /* -J flag */
|
2006-10-11 11:01:44 +04:00
|
|
|
static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */
|
2003-03-14 08:19:43 +03:00
|
|
|
Boolean varNoExportEnv; /* -X flag */
|
2007-12-21 23:32:24 +03:00
|
|
|
Boolean doing_depend; /* Set while reading .depend */
|
1993-03-21 12:45:37 +03:00
|
|
|
static Boolean jobsRunning; /* TRUE if the jobs might be running */
|
2000-12-30 05:05:20 +03:00
|
|
|
static const char * tracefile;
|
2008-02-16 00:29:50 +03:00
|
|
|
static char * Check_Cwd_av(int, char **, int);
|
|
|
|
static void MainParseArgs(int, char **);
|
2009-01-24 00:58:27 +03:00
|
|
|
static int ReadMakefile(const void *, const void *);
|
2011-09-16 19:38:03 +04:00
|
|
|
static void usage(void) __dead;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2009-09-09 21:09:49 +04:00
|
|
|
static Boolean ignorePWD; /* if we use -C, PWD is meaningless */
|
Overhaul the initialization and handling of .OBJDIR:
* Replace chdir_verify_path() with Main_SetObjdir(), which can be called
externally, and can take a "const char *". (There's a lot of non-const
"char *" passing around in var.c of what should be const strings....)
* Rewrite the initial "find my .OBJDIR" code to make use of the new
function. This still functions as it had in the past, but the comment
above this block was changed to reflect reality: if MAKEOBJDIRPREFIX
or MAKEOBJDIR are set in the environment, then *only that value* is
tried; make does not fall back to obj.MACHINE, obj, and /usr/obj/`pwd`
as it would without these env vars set.
* Add a new special target, .OBJDIR:, which when parsed will cause make to
change to a new object directory and reset .OBJDIR, and PWD in the
environment. This will allow some makefiles (mainly, src/tools)
to override the default objdir semantics in order to add custom logic.
2001-10-31 06:59:42 +03:00
|
|
|
static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
|
2011-02-21 02:12:09 +03:00
|
|
|
char curdir[MAXPATHLEN + 1]; /* Startup directory */
|
2001-01-10 18:54:00 +03:00
|
|
|
char *progname; /* the program name */
|
2010-04-07 04:11:27 +04:00
|
|
|
char *makeDependfile;
|
2010-04-23 04:18:50 +04:00
|
|
|
pid_t myPid;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2000-12-30 05:05:20 +03:00
|
|
|
Boolean forceJobs = FALSE;
|
|
|
|
|
2001-01-10 18:54:00 +03:00
|
|
|
extern Lst parseIncPath;
|
|
|
|
|
2006-10-15 12:38:21 +04:00
|
|
|
static void
|
|
|
|
parse_debug_options(const char *argvalue)
|
|
|
|
{
|
|
|
|
const char *modules;
|
2006-11-12 01:07:37 +03:00
|
|
|
const char *mode;
|
|
|
|
char *fname;
|
2008-02-16 00:29:50 +03:00
|
|
|
int len;
|
2006-10-15 12:38:21 +04:00
|
|
|
|
|
|
|
for (modules = argvalue; *modules; ++modules) {
|
|
|
|
switch (*modules) {
|
|
|
|
case 'A':
|
|
|
|
debug = ~0;
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
debug |= DEBUG_ARCH;
|
|
|
|
break;
|
2008-12-07 07:50:15 +03:00
|
|
|
case 'C':
|
|
|
|
debug |= DEBUG_CWD;
|
|
|
|
break;
|
2006-10-15 12:38:21 +04:00
|
|
|
case 'c':
|
|
|
|
debug |= DEBUG_COND;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
debug |= DEBUG_DIR;
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
debug |= DEBUG_ERROR;
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
debug |= DEBUG_FOR;
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
if (modules[1] == '1') {
|
|
|
|
debug |= DEBUG_GRAPH1;
|
|
|
|
++modules;
|
|
|
|
}
|
|
|
|
else if (modules[1] == '2') {
|
|
|
|
debug |= DEBUG_GRAPH2;
|
|
|
|
++modules;
|
|
|
|
}
|
|
|
|
else if (modules[1] == '3') {
|
|
|
|
debug |= DEBUG_GRAPH3;
|
|
|
|
++modules;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'j':
|
|
|
|
debug |= DEBUG_JOB;
|
|
|
|
break;
|
2008-01-19 09:52:13 +03:00
|
|
|
case 'l':
|
|
|
|
debug |= DEBUG_LOUD;
|
|
|
|
break;
|
2010-09-13 19:36:57 +04:00
|
|
|
case 'M':
|
|
|
|
debug |= DEBUG_META;
|
|
|
|
break;
|
2006-10-15 12:38:21 +04:00
|
|
|
case 'm':
|
|
|
|
debug |= DEBUG_MAKE;
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
debug |= DEBUG_SCRIPT;
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
debug |= DEBUG_PARSE;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
debug |= DEBUG_SUFF;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
debug |= DEBUG_TARG;
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
debug |= DEBUG_VAR;
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
debug |= DEBUG_SHELL;
|
|
|
|
break;
|
|
|
|
case 'F':
|
|
|
|
if (debug_file != stdout && debug_file != stderr)
|
|
|
|
fclose(debug_file);
|
|
|
|
if (*++modules == '+')
|
2006-11-12 01:07:37 +03:00
|
|
|
mode = "a";
|
2008-10-19 12:30:10 +04:00
|
|
|
else
|
2006-11-12 01:07:37 +03:00
|
|
|
mode = "w";
|
2008-10-19 12:30:10 +04:00
|
|
|
if (strcmp(modules, "stdout") == 0) {
|
2008-10-18 18:35:32 +04:00
|
|
|
debug_file = stdout;
|
2008-10-19 12:30:10 +04:00
|
|
|
goto debug_setbuf;
|
2008-10-18 18:35:32 +04:00
|
|
|
}
|
2008-10-19 12:30:10 +04:00
|
|
|
if (strcmp(modules, "stderr") == 0) {
|
2008-10-18 18:35:32 +04:00
|
|
|
debug_file = stderr;
|
2008-10-19 12:30:10 +04:00
|
|
|
goto debug_setbuf;
|
2008-10-18 18:35:32 +04:00
|
|
|
}
|
2006-11-12 01:07:37 +03:00
|
|
|
len = strlen(modules);
|
|
|
|
fname = malloc(len + 20);
|
|
|
|
memcpy(fname, modules, len + 1);
|
|
|
|
/* Let the filename be modified by the pid */
|
|
|
|
if (strcmp(fname + len - 3, ".%d") == 0)
|
2008-02-16 00:29:50 +03:00
|
|
|
snprintf(fname + len - 2, 20, "%d", getpid());
|
2006-11-12 01:07:37 +03:00
|
|
|
debug_file = fopen(fname, mode);
|
2006-10-15 12:38:21 +04:00
|
|
|
if (!debug_file) {
|
2006-12-06 23:38:21 +03:00
|
|
|
fprintf(stderr, "Cannot open debug file %s\n",
|
2006-11-12 01:07:37 +03:00
|
|
|
fname);
|
2006-10-15 12:38:21 +04:00
|
|
|
usage();
|
|
|
|
}
|
2006-11-12 01:07:37 +03:00
|
|
|
free(fname);
|
2008-10-19 12:30:10 +04:00
|
|
|
goto debug_setbuf;
|
2006-10-15 12:38:21 +04:00
|
|
|
default:
|
|
|
|
(void)fprintf(stderr,
|
|
|
|
"%s: illegal argument to d option -- %c\n",
|
|
|
|
progname, *modules);
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
}
|
2008-10-19 12:30:10 +04:00
|
|
|
debug_setbuf:
|
|
|
|
/*
|
|
|
|
* Make the debug_file unbuffered, and make
|
|
|
|
* stdout line buffered (unless debugfile == stdout).
|
|
|
|
*/
|
|
|
|
setvbuf(debug_file, NULL, _IONBF, 0);
|
|
|
|
if (debug_file != stdout) {
|
|
|
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
|
|
|
}
|
2006-10-15 12:38:21 +04:00
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*-
|
|
|
|
* MainParseArgs --
|
|
|
|
* Parse a given argument vector. Called from main() and from
|
|
|
|
* Main_ParseArgLine() when the .MAKEFLAGS target is used.
|
|
|
|
*
|
|
|
|
* XXX: Deal with command line overriding .MAKEFLAGS in makefile
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* Various global and local flags will be set depending on the flags
|
|
|
|
* given
|
|
|
|
*/
|
|
|
|
static void
|
2008-02-16 00:29:50 +03:00
|
|
|
MainParseArgs(int argc, char **argv)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1999-08-02 21:23:58 +04:00
|
|
|
char *p;
|
2006-03-17 18:39:44 +03:00
|
|
|
int c = '?';
|
2004-02-06 02:31:34 +03:00
|
|
|
int arginc;
|
2006-10-15 12:38:21 +04:00
|
|
|
char *argvalue;
|
2004-02-06 02:31:34 +03:00
|
|
|
const char *getopt_def;
|
|
|
|
char *optscan;
|
2004-04-23 01:19:02 +04:00
|
|
|
Boolean inOption, dashDash = FALSE;
|
2004-02-03 22:25:29 +03:00
|
|
|
char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2009-08-27 03:17:11 +04:00
|
|
|
#define OPTFLAGS "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrst"
|
2004-02-06 02:31:34 +03:00
|
|
|
/* Can't actually use getopt(3) because rescanning is not portable */
|
|
|
|
|
|
|
|
getopt_def = OPTFLAGS;
|
|
|
|
rearg:
|
|
|
|
inOption = FALSE;
|
2005-06-03 20:15:46 +04:00
|
|
|
optscan = NULL;
|
2004-02-06 02:31:34 +03:00
|
|
|
while(argc > 1) {
|
|
|
|
char *getopt_spec;
|
|
|
|
if(!inOption)
|
|
|
|
optscan = argv[1];
|
|
|
|
c = *optscan++;
|
|
|
|
arginc = 0;
|
|
|
|
if(inOption) {
|
|
|
|
if(c == '\0') {
|
|
|
|
++argv;
|
|
|
|
--argc;
|
|
|
|
inOption = FALSE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
2004-04-23 01:19:02 +04:00
|
|
|
if (c != '-' || dashDash)
|
2004-02-06 02:31:34 +03:00
|
|
|
break;
|
|
|
|
inOption = TRUE;
|
|
|
|
c = *optscan++;
|
|
|
|
}
|
|
|
|
/* '-' found at some earlier point */
|
|
|
|
getopt_spec = strchr(getopt_def, c);
|
|
|
|
if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') {
|
|
|
|
/* -<something> found, and <something> should have an arg */
|
|
|
|
inOption = FALSE;
|
|
|
|
arginc = 1;
|
|
|
|
argvalue = optscan;
|
|
|
|
if(*argvalue == '\0') {
|
2006-03-17 18:39:44 +03:00
|
|
|
if (argc < 3)
|
|
|
|
goto noarg;
|
2004-02-06 02:31:34 +03:00
|
|
|
argvalue = argv[2];
|
|
|
|
arginc = 2;
|
|
|
|
}
|
2005-06-03 20:15:46 +04:00
|
|
|
} else {
|
|
|
|
argvalue = NULL;
|
2004-02-06 02:31:34 +03:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
switch(c) {
|
2004-02-06 02:31:34 +03:00
|
|
|
case '\0':
|
|
|
|
arginc = 1;
|
|
|
|
inOption = FALSE;
|
|
|
|
break;
|
2003-09-05 10:52:11 +04:00
|
|
|
case 'B':
|
|
|
|
compatMake = TRUE;
|
|
|
|
Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
|
2010-04-22 23:11:17 +04:00
|
|
|
Var_Set(MAKE_MODE, "compat", VAR_GLOBAL, 0);
|
2003-09-05 10:52:11 +04:00
|
|
|
break;
|
2009-08-27 03:17:11 +04:00
|
|
|
case 'C':
|
|
|
|
if (chdir(argvalue) == -1) {
|
|
|
|
(void)fprintf(stderr,
|
|
|
|
"%s: chdir %s: %s\n",
|
|
|
|
progname, argvalue,
|
|
|
|
strerror(errno));
|
|
|
|
exit(1);
|
|
|
|
}
|
2010-01-04 20:05:25 +03:00
|
|
|
if (getcwd(curdir, MAXPATHLEN) == NULL) {
|
|
|
|
(void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
|
|
|
|
exit(2);
|
|
|
|
}
|
2009-09-09 21:09:49 +04:00
|
|
|
ignorePWD = TRUE;
|
2009-08-27 03:17:11 +04:00
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
case 'D':
|
2008-12-13 17:26:10 +03:00
|
|
|
if (argvalue == NULL || argvalue[0] == 0) goto noarg;
|
2006-03-17 18:39:44 +03:00
|
|
|
Var_Set(argvalue, "1", VAR_GLOBAL, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
|
2006-03-17 18:39:44 +03:00
|
|
|
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case 'I':
|
2006-03-17 18:39:44 +03:00
|
|
|
if (argvalue == NULL) goto noarg;
|
|
|
|
Parse_AddIncludeDir(argvalue);
|
1993-03-21 12:45:37 +03:00
|
|
|
Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
|
2006-03-17 18:39:44 +03:00
|
|
|
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
2000-12-30 05:05:20 +03:00
|
|
|
case 'J':
|
2006-03-17 18:39:44 +03:00
|
|
|
if (argvalue == NULL) goto noarg;
|
2006-10-11 11:01:44 +04:00
|
|
|
if (sscanf(argvalue, "%d,%d", &jp_0, &jp_1) != 2) {
|
2001-01-10 18:54:00 +03:00
|
|
|
(void)fprintf(stderr,
|
2006-10-11 11:01:44 +04:00
|
|
|
"%s: internal error -- J option malformed (%s)\n",
|
2006-03-17 18:39:44 +03:00
|
|
|
progname, argvalue);
|
2000-12-30 05:05:20 +03:00
|
|
|
usage();
|
|
|
|
}
|
2006-10-11 11:01:44 +04:00
|
|
|
if ((fcntl(jp_0, F_GETFD, 0) < 0) ||
|
|
|
|
(fcntl(jp_1, F_GETFD, 0) < 0)) {
|
2001-01-01 18:47:37 +03:00
|
|
|
#if 0
|
2000-12-30 05:05:20 +03:00
|
|
|
(void)fprintf(stderr,
|
2006-03-11 20:18:00 +03:00
|
|
|
"%s: ###### warning -- J descriptors were closed!\n",
|
2001-01-10 18:54:00 +03:00
|
|
|
progname);
|
2006-01-22 22:54:55 +03:00
|
|
|
exit(2);
|
2001-01-01 18:47:37 +03:00
|
|
|
#endif
|
2006-10-11 11:01:44 +04:00
|
|
|
jp_0 = -1;
|
|
|
|
jp_1 = -1;
|
2001-01-01 18:47:37 +03:00
|
|
|
compatMake = TRUE;
|
2000-12-30 05:05:20 +03:00
|
|
|
} else {
|
|
|
|
Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
|
2006-03-17 18:39:44 +03:00
|
|
|
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
|
2000-12-30 05:05:20 +03:00
|
|
|
jobServer = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
2001-01-01 18:47:37 +03:00
|
|
|
case 'N':
|
|
|
|
noExecute = TRUE;
|
|
|
|
noRecursiveExecute = TRUE;
|
|
|
|
Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL);
|
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
case 'S':
|
|
|
|
keepgoing = FALSE;
|
|
|
|
Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
|
|
|
|
break;
|
2000-12-30 05:05:20 +03:00
|
|
|
case 'T':
|
2006-03-17 18:39:44 +03:00
|
|
|
if (argvalue == NULL) goto noarg;
|
2008-10-07 02:09:21 +04:00
|
|
|
tracefile = bmake_strdup(argvalue);
|
2000-12-30 05:05:20 +03:00
|
|
|
Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL);
|
2006-03-17 18:39:44 +03:00
|
|
|
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
|
2000-12-30 05:05:20 +03:00
|
|
|
break;
|
2003-09-05 10:52:11 +04:00
|
|
|
case 'V':
|
2006-03-17 18:39:44 +03:00
|
|
|
if (argvalue == NULL) goto noarg;
|
2003-09-05 10:52:11 +04:00
|
|
|
printVars = TRUE;
|
2006-10-28 01:00:18 +04:00
|
|
|
(void)Lst_AtEnd(variables, argvalue);
|
2003-09-05 10:52:11 +04:00
|
|
|
Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
|
2006-03-17 18:39:44 +03:00
|
|
|
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
|
2003-09-05 10:52:11 +04:00
|
|
|
break;
|
2001-01-10 18:54:00 +03:00
|
|
|
case 'W':
|
|
|
|
parseWarnFatal = TRUE;
|
|
|
|
break;
|
2003-03-14 08:19:43 +03:00
|
|
|
case 'X':
|
|
|
|
varNoExportEnv = TRUE;
|
|
|
|
Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL);
|
|
|
|
break;
|
2006-10-15 12:38:21 +04:00
|
|
|
case 'd':
|
2006-03-17 18:39:44 +03:00
|
|
|
if (argvalue == NULL) goto noarg;
|
2006-10-15 12:38:21 +04:00
|
|
|
/* If '-d-opts' don't pass to children */
|
|
|
|
if (argvalue[0] == '-')
|
|
|
|
argvalue++;
|
|
|
|
else {
|
|
|
|
Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
|
|
|
|
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
|
|
|
|
}
|
|
|
|
parse_debug_options(argvalue);
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
checkEnvFirst = TRUE;
|
|
|
|
Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
|
|
|
|
break;
|
|
|
|
case 'f':
|
2006-03-17 18:39:44 +03:00
|
|
|
if (argvalue == NULL) goto noarg;
|
2006-10-28 01:00:18 +04:00
|
|
|
(void)Lst_AtEnd(makefiles, argvalue);
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
ignoreErrors = TRUE;
|
|
|
|
Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
|
|
|
|
break;
|
|
|
|
case 'j':
|
2006-03-17 18:39:44 +03:00
|
|
|
if (argvalue == NULL) goto noarg;
|
1995-11-08 05:30:53 +03:00
|
|
|
forceJobs = TRUE;
|
2006-03-17 18:39:44 +03:00
|
|
|
maxJobs = strtol(argvalue, &p, 0);
|
1999-08-02 21:23:58 +04:00
|
|
|
if (*p != '\0' || maxJobs < 1) {
|
2005-07-26 02:55:58 +04:00
|
|
|
(void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n",
|
2001-01-10 18:54:00 +03:00
|
|
|
progname);
|
1999-08-02 19:23:11 +04:00
|
|
|
exit(1);
|
|
|
|
}
|
1993-12-15 21:26:40 +03:00
|
|
|
Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
|
2006-03-17 18:39:44 +03:00
|
|
|
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
|
2010-04-22 23:11:17 +04:00
|
|
|
Var_Set(".MAKE.JOBS", argvalue, VAR_GLOBAL, 0);
|
2006-04-01 01:05:34 +04:00
|
|
|
maxJobTokens = maxJobs;
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case 'k':
|
|
|
|
keepgoing = TRUE;
|
|
|
|
Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
|
|
|
|
break;
|
1996-03-06 03:15:17 +03:00
|
|
|
case 'm':
|
2006-03-17 18:39:44 +03:00
|
|
|
if (argvalue == NULL) goto noarg;
|
2004-02-03 22:25:29 +03:00
|
|
|
/* look for magic parent directory search string */
|
2006-03-17 18:39:44 +03:00
|
|
|
if (strncmp(".../", argvalue, 4) == 0) {
|
|
|
|
if (!Dir_FindHereOrAbove(curdir, argvalue+4,
|
2004-02-03 22:25:29 +03:00
|
|
|
found_path, sizeof(found_path)))
|
|
|
|
break; /* nothing doing */
|
2005-07-26 02:55:58 +04:00
|
|
|
(void)Dir_AddDir(sysIncPath, found_path);
|
2004-02-03 22:25:29 +03:00
|
|
|
} else {
|
2006-03-17 18:39:44 +03:00
|
|
|
(void)Dir_AddDir(sysIncPath, argvalue);
|
2004-02-03 22:25:29 +03:00
|
|
|
}
|
1996-03-06 03:15:17 +03:00
|
|
|
Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
|
2006-03-17 18:39:44 +03:00
|
|
|
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
|
1996-03-06 03:15:17 +03:00
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
case 'n':
|
|
|
|
noExecute = TRUE;
|
|
|
|
Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
|
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
queryFlag = TRUE;
|
|
|
|
/* Kind of nonsensical, wot? */
|
|
|
|
Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
noBuiltins = TRUE;
|
|
|
|
Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
beSilent = TRUE;
|
|
|
|
Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
touchFlag = TRUE;
|
|
|
|
Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
|
|
|
|
break;
|
2004-04-23 01:19:02 +04:00
|
|
|
case '-':
|
|
|
|
dashDash = TRUE;
|
|
|
|
break;
|
1993-03-21 12:45:37 +03:00
|
|
|
default:
|
|
|
|
case '?':
|
|
|
|
usage();
|
|
|
|
}
|
2004-02-06 02:31:34 +03:00
|
|
|
argv += arginc;
|
|
|
|
argc -= arginc;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
oldVars = TRUE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* See if the rest of the arguments are variable assignments and
|
|
|
|
* perform them if so. Else take them to be targets and stuff them
|
|
|
|
* on the end of the "create" list.
|
|
|
|
*/
|
2004-02-06 02:31:34 +03:00
|
|
|
for (; argc > 1; ++argv, --argc)
|
|
|
|
if (Parse_IsVar(argv[1])) {
|
|
|
|
Parse_DoVar(argv[1], VAR_CMD);
|
2001-06-02 00:33:37 +04:00
|
|
|
} else {
|
2004-02-06 02:31:34 +03:00
|
|
|
if (!*argv[1])
|
1993-03-21 12:45:37 +03:00
|
|
|
Punt("illegal (null) argument.");
|
2004-04-23 01:19:02 +04:00
|
|
|
if (*argv[1] == '-' && !dashDash)
|
1993-03-21 12:45:37 +03:00
|
|
|
goto rearg;
|
2008-10-07 02:09:21 +04:00
|
|
|
(void)Lst_AtEnd(create, bmake_strdup(argv[1]));
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
2006-03-17 18:39:44 +03:00
|
|
|
|
|
|
|
return;
|
|
|
|
noarg:
|
|
|
|
(void)fprintf(stderr, "%s: option requires an argument -- %c\n",
|
|
|
|
progname, c);
|
|
|
|
usage();
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
* Main_ParseArgLine --
|
|
|
|
* Used by the parse module when a .MFLAGS or .MAKEFLAGS target
|
|
|
|
* is encountered and by main() when reading the .MAKEFLAGS envariable.
|
|
|
|
* Takes a line of arguments and breaks it into its
|
|
|
|
* component words and passes those words and the number of them to the
|
|
|
|
* MainParseArgs function.
|
|
|
|
* The line should have all its leading whitespace removed.
|
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
|
|
|
* line Line to fracture
|
|
|
|
*
|
1993-03-21 12:45:37 +03:00
|
|
|
* Results:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* Only those that come from the various arguments.
|
|
|
|
*/
|
|
|
|
void
|
2009-01-13 21:22:34 +03:00
|
|
|
Main_ParseArgLine(const char *line)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
char **argv; /* Manufactured argument vector */
|
2008-02-16 00:29:50 +03:00
|
|
|
int argc; /* Number of arguments in argv */
|
1998-03-26 22:20:36 +03:00
|
|
|
char *args; /* Space used by the args */
|
|
|
|
char *buf, *p1;
|
|
|
|
char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1);
|
1999-09-04 08:21:28 +04:00
|
|
|
size_t len;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
if (line == NULL)
|
|
|
|
return;
|
1994-03-05 03:34:29 +03:00
|
|
|
for (; *line == ' '; ++line)
|
|
|
|
continue;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (!*line)
|
|
|
|
return;
|
|
|
|
|
2008-10-07 02:09:21 +04:00
|
|
|
buf = bmake_malloc(len = strlen(line) + strlen(argv0) + 2);
|
1999-09-04 08:21:28 +04:00
|
|
|
(void)snprintf(buf, len, "%s %s", argv0, line);
|
1998-03-26 22:20:36 +03:00
|
|
|
if (p1)
|
|
|
|
free(p1);
|
|
|
|
|
1998-03-29 01:29:04 +03:00
|
|
|
argv = brk_string(buf, &argc, TRUE, &args);
|
2008-12-20 01:03:41 +03:00
|
|
|
if (argv == NULL) {
|
|
|
|
Error("Unterminated quoted string [%s]", buf);
|
|
|
|
free(buf);
|
|
|
|
return;
|
|
|
|
}
|
1998-11-01 06:07:33 +03:00
|
|
|
free(buf);
|
1993-03-21 12:45:37 +03:00
|
|
|
MainParseArgs(argc, argv);
|
1998-03-26 22:20:36 +03:00
|
|
|
|
|
|
|
free(args);
|
|
|
|
free(argv);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
Overhaul the initialization and handling of .OBJDIR:
* Replace chdir_verify_path() with Main_SetObjdir(), which can be called
externally, and can take a "const char *". (There's a lot of non-const
"char *" passing around in var.c of what should be const strings....)
* Rewrite the initial "find my .OBJDIR" code to make use of the new
function. This still functions as it had in the past, but the comment
above this block was changed to reflect reality: if MAKEOBJDIRPREFIX
or MAKEOBJDIR are set in the environment, then *only that value* is
tried; make does not fall back to obj.MACHINE, obj, and /usr/obj/`pwd`
as it would without these env vars set.
* Add a new special target, .OBJDIR:, which when parsed will cause make to
change to a new object directory and reset .OBJDIR, and PWD in the
environment. This will allow some makefiles (mainly, src/tools)
to override the default objdir semantics in order to add custom logic.
2001-10-31 06:59:42 +03:00
|
|
|
Boolean
|
2002-06-15 22:24:55 +04:00
|
|
|
Main_SetObjdir(const char *path)
|
1996-11-06 20:58:58 +03:00
|
|
|
{
|
|
|
|
struct stat sb;
|
Overhaul the initialization and handling of .OBJDIR:
* Replace chdir_verify_path() with Main_SetObjdir(), which can be called
externally, and can take a "const char *". (There's a lot of non-const
"char *" passing around in var.c of what should be const strings....)
* Rewrite the initial "find my .OBJDIR" code to make use of the new
function. This still functions as it had in the past, but the comment
above this block was changed to reflect reality: if MAKEOBJDIRPREFIX
or MAKEOBJDIR are set in the environment, then *only that value* is
tried; make does not fall back to obj.MACHINE, obj, and /usr/obj/`pwd`
as it would without these env vars set.
* Add a new special target, .OBJDIR:, which when parsed will cause make to
change to a new object directory and reset .OBJDIR, and PWD in the
environment. This will allow some makefiles (mainly, src/tools)
to override the default objdir semantics in order to add custom logic.
2001-10-31 06:59:42 +03:00
|
|
|
char *p = NULL;
|
|
|
|
char buf[MAXPATHLEN + 1];
|
2001-11-02 18:37:41 +03:00
|
|
|
Boolean rc = FALSE;
|
1996-11-06 20:58:58 +03:00
|
|
|
|
Overhaul the initialization and handling of .OBJDIR:
* Replace chdir_verify_path() with Main_SetObjdir(), which can be called
externally, and can take a "const char *". (There's a lot of non-const
"char *" passing around in var.c of what should be const strings....)
* Rewrite the initial "find my .OBJDIR" code to make use of the new
function. This still functions as it had in the past, but the comment
above this block was changed to reflect reality: if MAKEOBJDIRPREFIX
or MAKEOBJDIR are set in the environment, then *only that value* is
tried; make does not fall back to obj.MACHINE, obj, and /usr/obj/`pwd`
as it would without these env vars set.
* Add a new special target, .OBJDIR:, which when parsed will cause make to
change to a new object directory and reset .OBJDIR, and PWD in the
environment. This will allow some makefiles (mainly, src/tools)
to override the default objdir semantics in order to add custom logic.
2001-10-31 06:59:42 +03:00
|
|
|
/* expand variable substitutions */
|
2000-02-08 15:43:25 +03:00
|
|
|
if (strchr(path, '$') != 0) {
|
Overhaul the initialization and handling of .OBJDIR:
* Replace chdir_verify_path() with Main_SetObjdir(), which can be called
externally, and can take a "const char *". (There's a lot of non-const
"char *" passing around in var.c of what should be const strings....)
* Rewrite the initial "find my .OBJDIR" code to make use of the new
function. This still functions as it had in the past, but the comment
above this block was changed to reflect reality: if MAKEOBJDIRPREFIX
or MAKEOBJDIR are set in the environment, then *only that value* is
tried; make does not fall back to obj.MACHINE, obj, and /usr/obj/`pwd`
as it would without these env vars set.
* Add a new special target, .OBJDIR:, which when parsed will cause make to
change to a new object directory and reset .OBJDIR, and PWD in the
environment. This will allow some makefiles (mainly, src/tools)
to override the default objdir semantics in order to add custom logic.
2001-10-31 06:59:42 +03:00
|
|
|
snprintf(buf, MAXPATHLEN, "%s", path);
|
|
|
|
path = p = Var_Subst(NULL, buf, VAR_GLOBAL, 0);
|
2000-02-08 15:43:25 +03:00
|
|
|
}
|
Overhaul the initialization and handling of .OBJDIR:
* Replace chdir_verify_path() with Main_SetObjdir(), which can be called
externally, and can take a "const char *". (There's a lot of non-const
"char *" passing around in var.c of what should be const strings....)
* Rewrite the initial "find my .OBJDIR" code to make use of the new
function. This still functions as it had in the past, but the comment
above this block was changed to reflect reality: if MAKEOBJDIRPREFIX
or MAKEOBJDIR are set in the environment, then *only that value* is
tried; make does not fall back to obj.MACHINE, obj, and /usr/obj/`pwd`
as it would without these env vars set.
* Add a new special target, .OBJDIR:, which when parsed will cause make to
change to a new object directory and reset .OBJDIR, and PWD in the
environment. This will allow some makefiles (mainly, src/tools)
to override the default objdir semantics in order to add custom logic.
2001-10-31 06:59:42 +03:00
|
|
|
|
|
|
|
if (path[0] != '/') {
|
|
|
|
snprintf(buf, MAXPATHLEN, "%s/%s", curdir, path);
|
|
|
|
path = buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* look for the directory and try to chdir there */
|
1996-11-06 20:58:58 +03:00
|
|
|
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
|
|
|
if (chdir(path)) {
|
|
|
|
(void)fprintf(stderr, "make warning: %s: %s.\n",
|
|
|
|
path, strerror(errno));
|
Overhaul the initialization and handling of .OBJDIR:
* Replace chdir_verify_path() with Main_SetObjdir(), which can be called
externally, and can take a "const char *". (There's a lot of non-const
"char *" passing around in var.c of what should be const strings....)
* Rewrite the initial "find my .OBJDIR" code to make use of the new
function. This still functions as it had in the past, but the comment
above this block was changed to reflect reality: if MAKEOBJDIRPREFIX
or MAKEOBJDIR are set in the environment, then *only that value* is
tried; make does not fall back to obj.MACHINE, obj, and /usr/obj/`pwd`
as it would without these env vars set.
* Add a new special target, .OBJDIR:, which when parsed will cause make to
change to a new object directory and reset .OBJDIR, and PWD in the
environment. This will allow some makefiles (mainly, src/tools)
to override the default objdir semantics in order to add custom logic.
2001-10-31 06:59:42 +03:00
|
|
|
} else {
|
|
|
|
strncpy(objdir, path, MAXPATHLEN);
|
|
|
|
Var_Set(".OBJDIR", objdir, VAR_GLOBAL, 0);
|
|
|
|
setenv("PWD", objdir, 1);
|
2001-11-13 00:58:17 +03:00
|
|
|
Dir_InitDot();
|
Overhaul the initialization and handling of .OBJDIR:
* Replace chdir_verify_path() with Main_SetObjdir(), which can be called
externally, and can take a "const char *". (There's a lot of non-const
"char *" passing around in var.c of what should be const strings....)
* Rewrite the initial "find my .OBJDIR" code to make use of the new
function. This still functions as it had in the past, but the comment
above this block was changed to reflect reality: if MAKEOBJDIRPREFIX
or MAKEOBJDIR are set in the environment, then *only that value* is
tried; make does not fall back to obj.MACHINE, obj, and /usr/obj/`pwd`
as it would without these env vars set.
* Add a new special target, .OBJDIR:, which when parsed will cause make to
change to a new object directory and reset .OBJDIR, and PWD in the
environment. This will allow some makefiles (mainly, src/tools)
to override the default objdir semantics in order to add custom logic.
2001-10-31 06:59:42 +03:00
|
|
|
rc = TRUE;
|
1996-11-06 20:58:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Overhaul the initialization and handling of .OBJDIR:
* Replace chdir_verify_path() with Main_SetObjdir(), which can be called
externally, and can take a "const char *". (There's a lot of non-const
"char *" passing around in var.c of what should be const strings....)
* Rewrite the initial "find my .OBJDIR" code to make use of the new
function. This still functions as it had in the past, but the comment
above this block was changed to reflect reality: if MAKEOBJDIRPREFIX
or MAKEOBJDIR are set in the environment, then *only that value* is
tried; make does not fall back to obj.MACHINE, obj, and /usr/obj/`pwd`
as it would without these env vars set.
* Add a new special target, .OBJDIR:, which when parsed will cause make to
change to a new object directory and reset .OBJDIR, and PWD in the
environment. This will allow some makefiles (mainly, src/tools)
to override the default objdir semantics in order to add custom logic.
2001-10-31 06:59:42 +03:00
|
|
|
if (p)
|
|
|
|
free(p);
|
|
|
|
return rc;
|
1996-11-06 20:58:58 +03:00
|
|
|
}
|
|
|
|
|
2006-04-13 00:32:27 +04:00
|
|
|
/*-
|
|
|
|
* ReadAllMakefiles --
|
|
|
|
* wrapper around ReadMakefile() to read all.
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* TRUE if ok, FALSE on error
|
|
|
|
*/
|
|
|
|
static int
|
2009-01-24 00:58:27 +03:00
|
|
|
ReadAllMakefiles(const void *p, const void *q)
|
2006-04-13 00:32:27 +04:00
|
|
|
{
|
|
|
|
return (ReadMakefile(p, q) == 0);
|
|
|
|
}
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2011-05-05 00:38:31 +04:00
|
|
|
int
|
2010-04-07 04:11:27 +04:00
|
|
|
str2Lst_Append(Lst lp, char *str, const char *sep)
|
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
if (!sep)
|
|
|
|
sep = " \t";
|
|
|
|
|
|
|
|
for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) {
|
|
|
|
(void)Lst_AtEnd(lp, cp);
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
return (n);
|
|
|
|
}
|
|
|
|
|
2009-03-01 04:49:17 +03:00
|
|
|
#ifdef SIGINFO
|
|
|
|
/*ARGSUSED*/
|
|
|
|
static void
|
2011-02-14 00:24:42 +03:00
|
|
|
siginfo(int signo __unused)
|
2009-03-01 04:49:17 +03:00
|
|
|
{
|
|
|
|
char dir[MAXPATHLEN];
|
|
|
|
char str[2 * MAXPATHLEN];
|
|
|
|
int len;
|
|
|
|
if (getcwd(dir, sizeof(dir)) == NULL)
|
|
|
|
return;
|
2009-03-19 01:02:49 +03:00
|
|
|
len = snprintf(str, sizeof(str), "%s: Working in: %s\n", progname, dir);
|
2009-03-01 04:49:17 +03:00
|
|
|
if (len > 0)
|
|
|
|
(void)write(STDERR_FILENO, str, (size_t)len);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-04-07 04:11:27 +04:00
|
|
|
/*
|
|
|
|
* Allow makefiles some control over the mode we run in.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
MakeMode(const char *mode)
|
|
|
|
{
|
|
|
|
char *mp = NULL;
|
|
|
|
|
|
|
|
if (!mode)
|
|
|
|
mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}", VAR_GLOBAL, 0);
|
|
|
|
|
|
|
|
if (mode && *mode) {
|
|
|
|
if (strstr(mode, "compat")) {
|
|
|
|
compatMake = TRUE;
|
|
|
|
forceJobs = FALSE;
|
|
|
|
}
|
2010-09-13 19:36:57 +04:00
|
|
|
#if USE_META
|
|
|
|
if (strstr(mode, "meta"))
|
|
|
|
meta_init(mode);
|
|
|
|
#endif
|
2010-04-07 04:11:27 +04:00
|
|
|
}
|
|
|
|
if (mp)
|
|
|
|
free(mp);
|
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*-
|
|
|
|
* 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.
|
|
|
|
*/
|
1994-03-05 03:34:29 +03:00
|
|
|
int
|
2002-06-15 22:24:55 +04:00
|
|
|
main(int argc, char **argv)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
Lst targs; /* target nodes to create -- passed to Make_Init */
|
2006-11-18 01:07:39 +03:00
|
|
|
Boolean outOfDate = FALSE; /* FALSE if all targets up to date */
|
2001-11-12 00:40:05 +03:00
|
|
|
struct stat sb, sa;
|
|
|
|
char *p1, *path, *pwd;
|
Overhaul the initialization and handling of .OBJDIR:
* Replace chdir_verify_path() with Main_SetObjdir(), which can be called
externally, and can take a "const char *". (There's a lot of non-const
"char *" passing around in var.c of what should be const strings....)
* Rewrite the initial "find my .OBJDIR" code to make use of the new
function. This still functions as it had in the past, but the comment
above this block was changed to reflect reality: if MAKEOBJDIRPREFIX
or MAKEOBJDIR are set in the environment, then *only that value* is
tried; make does not fall back to obj.MACHINE, obj, and /usr/obj/`pwd`
as it would without these env vars set.
* Add a new special target, .OBJDIR:, which when parsed will cause make to
change to a new object directory and reset .OBJDIR, and PWD in the
environment. This will allow some makefiles (mainly, src/tools)
to override the default objdir semantics in order to add custom logic.
2001-10-31 06:59:42 +03:00
|
|
|
char mdpath[MAXPATHLEN];
|
2010-12-13 04:48:50 +03:00
|
|
|
const char *machine = getenv("MACHINE");
|
2003-07-14 22:19:11 +04:00
|
|
|
const char *machine_arch = getenv("MACHINE_ARCH");
|
2000-04-29 16:15:16 +04:00
|
|
|
char *syspath = getenv("MAKESYSPATH");
|
1996-03-06 03:15:17 +03:00
|
|
|
Lst sysMkPath; /* Path of sys.mk */
|
|
|
|
char *cp = NULL, *start;
|
|
|
|
/* avoid faults on read-only strings */
|
2000-04-29 16:15:16 +04:00
|
|
|
static char defsyspath[] = _PATH_DEFSYSPATH;
|
2004-02-03 22:25:29 +03:00
|
|
|
char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */
|
2005-06-01 21:17:34 +04:00
|
|
|
struct timeval rightnow; /* to initialize random seed */
|
2006-02-18 07:10:05 +03:00
|
|
|
#ifdef MAKE_NATIVE
|
|
|
|
struct utsname utsname;
|
|
|
|
#endif
|
2005-06-01 21:17:34 +04:00
|
|
|
|
2008-10-22 19:04:49 +04:00
|
|
|
/* default to writing debug to stderr */
|
|
|
|
debug_file = stderr;
|
2006-10-15 12:38:21 +04:00
|
|
|
|
2009-03-01 04:49:17 +03:00
|
|
|
#ifdef SIGINFO
|
2010-06-03 19:40:15 +04:00
|
|
|
(void)bmake_signal(SIGINFO, siginfo);
|
2009-03-01 04:49:17 +03:00
|
|
|
#endif
|
2005-06-01 21:17:34 +04:00
|
|
|
/*
|
2008-12-13 21:11:53 +03:00
|
|
|
* Set the seed to produce a different random sequence
|
2005-06-01 21:17:34 +04:00
|
|
|
* on each program execution.
|
|
|
|
*/
|
|
|
|
gettimeofday(&rightnow, NULL);
|
2008-02-16 00:29:50 +03:00
|
|
|
srandom(rightnow.tv_sec + rightnow.tv_usec);
|
2000-04-29 16:15:16 +04:00
|
|
|
|
2000-04-17 03:24:23 +04:00
|
|
|
if ((progname = strrchr(argv[0], '/')) != NULL)
|
|
|
|
progname++;
|
|
|
|
else
|
|
|
|
progname = argv[0];
|
1995-11-03 02:54:35 +03:00
|
|
|
#ifdef RLIMIT_NOFILE
|
|
|
|
/*
|
|
|
|
* get rid of resource limit on file descriptors
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
struct rlimit rl;
|
|
|
|
if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
|
|
|
|
rl.rlim_cur != rl.rlim_max) {
|
|
|
|
rl.rlim_cur = rl.rlim_max;
|
2005-07-26 02:55:58 +04:00
|
|
|
(void)setrlimit(RLIMIT_NOFILE, &rl);
|
1995-11-03 02:54:35 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2001-11-12 00:40:05 +03:00
|
|
|
|
1994-09-30 06:14:21 +03:00
|
|
|
/*
|
|
|
|
* 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, ...)
|
|
|
|
*
|
1997-01-29 02:58:00 +03:00
|
|
|
* Note that both MACHINE and MACHINE_ARCH are decided at
|
|
|
|
* run-time.
|
1994-09-30 06:14:21 +03:00
|
|
|
*/
|
1997-03-24 23:56:36 +03:00
|
|
|
if (!machine) {
|
2004-05-07 04:04:38 +04:00
|
|
|
#ifdef MAKE_NATIVE
|
1995-11-22 20:39:53 +03:00
|
|
|
if (uname(&utsname) == -1) {
|
2001-01-10 18:54:00 +03:00
|
|
|
(void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
|
|
|
|
strerror(errno));
|
|
|
|
exit(2);
|
1995-01-06 22:57:27 +03:00
|
|
|
}
|
|
|
|
machine = utsname.machine;
|
1996-03-11 16:45:31 +03:00
|
|
|
#else
|
2001-12-11 23:50:58 +03:00
|
|
|
#ifdef MAKE_MACHINE
|
2001-11-30 04:29:47 +03:00
|
|
|
machine = MAKE_MACHINE;
|
2001-12-11 23:50:58 +03:00
|
|
|
#else
|
|
|
|
machine = "unknown";
|
|
|
|
#endif
|
1996-03-11 16:45:31 +03:00
|
|
|
#endif
|
1994-09-30 06:14:21 +03:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1997-01-29 02:58:00 +03:00
|
|
|
if (!machine_arch) {
|
|
|
|
#ifndef MACHINE_ARCH
|
2001-11-30 04:29:47 +03:00
|
|
|
#ifdef MAKE_MACHINE_ARCH
|
|
|
|
machine_arch = MAKE_MACHINE_ARCH;
|
1998-10-13 21:08:34 +04:00
|
|
|
#else
|
2001-12-11 23:50:58 +03:00
|
|
|
machine_arch = "unknown";
|
1998-10-13 21:08:34 +04:00
|
|
|
#endif
|
1997-01-29 02:58:00 +03:00
|
|
|
#else
|
|
|
|
machine_arch = MACHINE_ARCH;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-04-23 04:18:50 +04:00
|
|
|
myPid = getpid(); /* remember this for vFork() */
|
|
|
|
|
2000-02-08 15:43:25 +03:00
|
|
|
/*
|
|
|
|
* Just in case MAKEOBJDIR wants us to do something tricky.
|
|
|
|
*/
|
|
|
|
Var_Init(); /* Initialize the lists of variables for
|
|
|
|
* parsing arguments */
|
2001-06-13 03:36:17 +04:00
|
|
|
Var_Set("MACHINE", machine, VAR_GLOBAL, 0);
|
|
|
|
Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL, 0);
|
2009-03-24 16:53:21 +03:00
|
|
|
#ifdef MAKE_VERSION
|
|
|
|
Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL, 0);
|
|
|
|
#endif
|
2001-06-13 03:36:17 +04:00
|
|
|
Var_Set(".newline", "\n", VAR_GLOBAL, 0); /* handy for :@ loops */
|
2010-04-07 04:11:27 +04:00
|
|
|
/*
|
|
|
|
* This is the traditional preference for makefiles.
|
|
|
|
*/
|
|
|
|
#ifndef MAKEFILE_PREFERENCE_LIST
|
|
|
|
# define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
|
|
|
|
#endif
|
|
|
|
Var_Set(MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST,
|
|
|
|
VAR_GLOBAL, 0);
|
|
|
|
Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL, 0);
|
2000-02-08 15:43:25 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
create = Lst_Init(FALSE);
|
|
|
|
makefiles = Lst_Init(FALSE);
|
1996-11-06 20:58:58 +03:00
|
|
|
printVars = FALSE;
|
|
|
|
variables = Lst_Init(FALSE);
|
1993-03-21 12:45:37 +03:00
|
|
|
beSilent = FALSE; /* Print commands as executed */
|
|
|
|
ignoreErrors = FALSE; /* Pay attention to non-zero returns */
|
|
|
|
noExecute = FALSE; /* Execute all commands */
|
2001-01-01 18:47:37 +03:00
|
|
|
noRecursiveExecute = FALSE; /* Execute all .MAKE targets */
|
1993-03-21 12:45:37 +03:00
|
|
|
keepgoing = FALSE; /* Stop on error */
|
|
|
|
allPrecious = FALSE; /* Remove targets when interrupted */
|
|
|
|
queryFlag = FALSE; /* This is not just a check-run */
|
|
|
|
noBuiltins = FALSE; /* Read the built-in rules */
|
|
|
|
touchFlag = FALSE; /* Actually update targets */
|
|
|
|
debug = 0; /* No debug verbosity, please. */
|
|
|
|
jobsRunning = FALSE;
|
|
|
|
|
2006-03-11 20:18:00 +03:00
|
|
|
maxJobs = DEFMAXLOCAL; /* Set default local max concurrency */
|
2006-04-01 01:05:34 +04:00
|
|
|
maxJobTokens = maxJobs;
|
1995-11-03 02:54:35 +03:00
|
|
|
compatMake = FALSE; /* No compat mode */
|
2009-09-09 21:09:49 +04:00
|
|
|
ignorePWD = FALSE;
|
1994-03-05 03:34:29 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Initialize the parsing, directory and variable modules to prepare
|
|
|
|
* for the reading of inclusion paths and variable settings on the
|
|
|
|
* command line
|
|
|
|
*/
|
1997-05-09 01:24:41 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Initialize various variables.
|
|
|
|
* MAKE also gets this name, for compatibility
|
|
|
|
* .MAKEFLAGS gets set to the empty string just in case.
|
|
|
|
* MFLAGS also gets initialized empty, for compatibility.
|
|
|
|
*/
|
2001-11-13 00:58:17 +03:00
|
|
|
Parse_Init();
|
2010-05-17 21:01:16 +04:00
|
|
|
if (argv[0][0] == '/' || strchr(argv[0], '/') == NULL) {
|
|
|
|
/*
|
|
|
|
* Leave alone if it is an absolute path, or if it does
|
|
|
|
* not contain a '/' in which case we need to find it in
|
|
|
|
* the path, like execvp(3) and the shells do.
|
|
|
|
*/
|
|
|
|
p1 = argv[0];
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* A relative path, canonicalize it.
|
|
|
|
*/
|
|
|
|
p1 = realpath(argv[0], mdpath);
|
|
|
|
if (!p1 || *p1 != '/' || stat(p1, &sb) < 0) {
|
|
|
|
p1 = argv[0]; /* realpath failed */
|
|
|
|
}
|
|
|
|
}
|
2010-04-14 20:16:17 +04:00
|
|
|
Var_Set("MAKE", p1, VAR_GLOBAL, 0);
|
|
|
|
Var_Set(".MAKE", p1, VAR_GLOBAL, 0);
|
2001-06-13 03:36:17 +04:00
|
|
|
Var_Set(MAKEFLAGS, "", VAR_GLOBAL, 0);
|
|
|
|
Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL, 0);
|
|
|
|
Var_Set("MFLAGS", "", VAR_GLOBAL, 0);
|
2001-11-12 04:33:48 +03:00
|
|
|
Var_Set(".ALLTARGETS", "", VAR_GLOBAL, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2007-10-02 02:14:09 +04:00
|
|
|
/*
|
|
|
|
* Set some other useful macros
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
char tmp[64];
|
2009-09-08 21:29:20 +04:00
|
|
|
const char *ep;
|
2007-10-02 02:14:09 +04:00
|
|
|
|
2009-09-08 21:29:20 +04:00
|
|
|
if (!(ep = getenv(MAKE_LEVEL))) {
|
|
|
|
ep = "0";
|
|
|
|
}
|
|
|
|
Var_Set(MAKE_LEVEL, ep, VAR_GLOBAL, 0);
|
2010-04-23 04:18:50 +04:00
|
|
|
snprintf(tmp, sizeof(tmp), "%u", myPid);
|
2007-10-02 02:14:09 +04:00
|
|
|
Var_Set(".MAKE.PID", tmp, VAR_GLOBAL, 0);
|
2008-02-16 00:29:50 +03:00
|
|
|
snprintf(tmp, sizeof(tmp), "%u", getppid());
|
2007-10-02 02:14:09 +04:00
|
|
|
Var_Set(".MAKE.PPID", tmp, VAR_GLOBAL, 0);
|
|
|
|
}
|
|
|
|
Job_SetPrefix();
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* First snag any flags out of the MAKE environment variable.
|
|
|
|
* (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
|
|
|
|
* in a different format).
|
|
|
|
*/
|
|
|
|
#ifdef POSIX
|
|
|
|
Main_ParseArgLine(getenv("MAKEFLAGS"));
|
|
|
|
#else
|
|
|
|
Main_ParseArgLine(getenv("MAKE"));
|
|
|
|
#endif
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2009-09-09 21:09:49 +04:00
|
|
|
/*
|
2010-01-04 20:05:25 +03:00
|
|
|
* Find where we are (now).
|
|
|
|
* We take care of PWD for the automounter below...
|
2009-09-09 21:09:49 +04:00
|
|
|
*/
|
|
|
|
if (getcwd(curdir, MAXPATHLEN) == NULL) {
|
2010-12-25 23:34:08 +03:00
|
|
|
(void)fprintf(stderr, "%s: getcwd: %s.\n",
|
|
|
|
progname, strerror(errno));
|
2009-09-09 21:09:49 +04:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
2010-01-04 20:05:25 +03:00
|
|
|
MainParseArgs(argc, argv);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Verify that cwd is sane.
|
|
|
|
*/
|
2009-09-09 21:09:49 +04:00
|
|
|
if (stat(curdir, &sa) == -1) {
|
|
|
|
(void)fprintf(stderr, "%s: %s: %s.\n",
|
|
|
|
progname, curdir, strerror(errno));
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-01-04 20:05:25 +03:00
|
|
|
* All this code is so that we know where we are when we start up
|
|
|
|
* on a different machine with pmake.
|
2009-09-09 21:09:49 +04:00
|
|
|
* Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
|
|
|
|
* since the value of curdir can vary depending on how we got
|
|
|
|
* here. Ie sitting at a shell prompt (shell that provides $PWD)
|
|
|
|
* or via subdir.mk in which case its likely a shell which does
|
|
|
|
* not provide it.
|
|
|
|
* So, to stop it breaking this case only, we ignore PWD if
|
|
|
|
* MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a transform.
|
|
|
|
*/
|
|
|
|
if (!ignorePWD &&
|
|
|
|
(pwd = getenv("PWD")) != NULL &&
|
|
|
|
getenv("MAKEOBJDIRPREFIX") == NULL) {
|
|
|
|
const char *makeobjdir = getenv("MAKEOBJDIR");
|
|
|
|
|
|
|
|
if (makeobjdir == NULL || !strchr(makeobjdir, '$')) {
|
|
|
|
if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
|
|
|
|
sa.st_dev == sb.st_dev)
|
|
|
|
(void)strncpy(curdir, pwd, MAXPATHLEN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Var_Set(".CURDIR", curdir, VAR_GLOBAL, 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the .OBJDIR. If MAKEOBJDIRPREFIX, or failing that,
|
|
|
|
* MAKEOBJDIR is set in the environment, try only that value
|
|
|
|
* and fall back to .CURDIR if it does not exist.
|
|
|
|
*
|
|
|
|
* Otherwise, try _PATH_OBJDIR.MACHINE, _PATH_OBJDIR, and
|
|
|
|
* finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none
|
|
|
|
* of these paths exist, just use .CURDIR.
|
|
|
|
*/
|
|
|
|
Dir_Init(curdir);
|
|
|
|
(void)Main_SetObjdir(curdir);
|
|
|
|
|
|
|
|
if ((path = getenv("MAKEOBJDIRPREFIX")) != NULL) {
|
|
|
|
(void)snprintf(mdpath, MAXPATHLEN, "%s%s", path, curdir);
|
|
|
|
(void)Main_SetObjdir(mdpath);
|
|
|
|
} else if ((path = getenv("MAKEOBJDIR")) != NULL) {
|
|
|
|
(void)Main_SetObjdir(path);
|
|
|
|
} else {
|
|
|
|
(void)snprintf(mdpath, MAXPATHLEN, "%s.%s", _PATH_OBJDIR, machine);
|
|
|
|
if (!Main_SetObjdir(mdpath) && !Main_SetObjdir(_PATH_OBJDIR)) {
|
|
|
|
(void)snprintf(mdpath, MAXPATHLEN, "%s%s",
|
|
|
|
_PATH_OBJDIRPREFIX, curdir);
|
|
|
|
(void)Main_SetObjdir(mdpath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-12-30 05:05:20 +03:00
|
|
|
/*
|
|
|
|
* Be compatible if user did not specify -j and did not explicitly
|
|
|
|
* turned compatibility on
|
|
|
|
*/
|
|
|
|
if (!compatMake && !forceJobs) {
|
|
|
|
compatMake = TRUE;
|
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Initialize archive, target and suffix modules in preparation for
|
|
|
|
* parsing the makefile(s)
|
|
|
|
*/
|
|
|
|
Arch_Init();
|
|
|
|
Targ_Init();
|
|
|
|
Suff_Init();
|
2000-12-30 05:05:20 +03:00
|
|
|
Trace_Init(tracefile);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2008-12-13 18:19:29 +03:00
|
|
|
DEFAULT = NULL;
|
1993-03-21 12:45:37 +03:00
|
|
|
(void)time(&now);
|
|
|
|
|
2000-12-30 05:05:20 +03:00
|
|
|
Trace_Log(MAKESTART, NULL);
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Set up the .TARGETS variable to contain the list of targets to be
|
|
|
|
* created. If none specified, make the variable empty -- the parser
|
|
|
|
* will fill the thing in with the default or .MAIN target.
|
|
|
|
*/
|
|
|
|
if (!Lst_IsEmpty(create)) {
|
|
|
|
LstNode ln;
|
|
|
|
|
2008-12-13 18:19:29 +03:00
|
|
|
for (ln = Lst_First(create); ln != NULL;
|
1993-03-21 12:45:37 +03:00
|
|
|
ln = Lst_Succ(ln)) {
|
|
|
|
char *name = (char *)Lst_Datum(ln);
|
|
|
|
|
|
|
|
Var_Append(".TARGETS", name, VAR_GLOBAL);
|
|
|
|
}
|
|
|
|
} else
|
2001-06-13 03:36:17 +04:00
|
|
|
Var_Set(".TARGETS", "", VAR_GLOBAL, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1996-03-06 03:15:17 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1996-03-06 03:15:17 +03:00
|
|
|
* If no user-supplied system path was given (through the -m option)
|
|
|
|
* add the directories from the DEFSYSPATH (more than one may be given
|
|
|
|
* as dir1:...:dirn) to the system include path.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2001-10-31 04:15:57 +03:00
|
|
|
if (syspath == NULL || *syspath == '\0')
|
|
|
|
syspath = defsyspath;
|
|
|
|
else
|
2008-10-07 02:09:21 +04:00
|
|
|
syspath = bmake_strdup(syspath);
|
2001-10-31 04:15:57 +03:00
|
|
|
|
|
|
|
for (start = syspath; *start != '\0'; start = cp) {
|
|
|
|
for (cp = start; *cp != '\0' && *cp != ':'; cp++)
|
|
|
|
continue;
|
2004-02-03 22:25:29 +03:00
|
|
|
if (*cp == ':') {
|
2001-10-31 04:15:57 +03:00
|
|
|
*cp++ = '\0';
|
2004-02-03 22:25:29 +03:00
|
|
|
}
|
|
|
|
/* look for magic parent directory search string */
|
|
|
|
if (strncmp(".../", start, 4) != 0) {
|
2005-07-26 02:55:58 +04:00
|
|
|
(void)Dir_AddDir(defIncPath, start);
|
2004-02-03 22:25:29 +03:00
|
|
|
} else {
|
|
|
|
if (Dir_FindHereOrAbove(curdir, start+4,
|
|
|
|
found_path, sizeof(found_path))) {
|
2005-07-26 02:55:58 +04:00
|
|
|
(void)Dir_AddDir(defIncPath, found_path);
|
2004-02-03 22:25:29 +03:00
|
|
|
}
|
1996-03-06 03:15:17 +03:00
|
|
|
}
|
|
|
|
}
|
2001-10-31 04:15:57 +03:00
|
|
|
if (syspath != defsyspath)
|
|
|
|
free(syspath);
|
1996-03-06 03:15:17 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Read in the built-in rules first, followed by the specified
|
2005-08-08 20:42:54 +04:00
|
|
|
* makefile, if it was (makefile != NULL), or the default
|
2004-03-24 03:59:40 +03:00
|
|
|
* makefile and Makefile, in that order, if it wasn't.
|
1996-03-06 03:15:17 +03:00
|
|
|
*/
|
|
|
|
if (!noBuiltins) {
|
|
|
|
LstNode ln;
|
|
|
|
|
2005-02-16 18:11:52 +03:00
|
|
|
sysMkPath = Lst_Init(FALSE);
|
2001-10-31 04:15:57 +03:00
|
|
|
Dir_Expand(_PATH_DEFSYSMK,
|
|
|
|
Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath,
|
|
|
|
sysMkPath);
|
1996-03-06 03:15:17 +03:00
|
|
|
if (Lst_IsEmpty(sysMkPath))
|
2001-01-10 18:54:00 +03:00
|
|
|
Fatal("%s: no system rules (%s).", progname,
|
|
|
|
_PATH_DEFSYSMK);
|
2006-10-28 01:00:18 +04:00
|
|
|
ln = Lst_Find(sysMkPath, NULL, ReadMakefile);
|
2008-12-13 18:19:29 +03:00
|
|
|
if (ln == NULL)
|
2001-01-10 18:54:00 +03:00
|
|
|
Fatal("%s: cannot open %s.", progname,
|
|
|
|
(char *)Lst_Datum(ln));
|
1996-03-06 03:15:17 +03:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
if (!Lst_IsEmpty(makefiles)) {
|
|
|
|
LstNode ln;
|
|
|
|
|
2006-10-28 01:00:18 +04:00
|
|
|
ln = Lst_Find(makefiles, NULL, ReadAllMakefiles);
|
2008-12-13 18:19:29 +03:00
|
|
|
if (ln != NULL)
|
2001-01-10 18:54:00 +03:00
|
|
|
Fatal("%s: cannot open %s.", progname,
|
|
|
|
(char *)Lst_Datum(ln));
|
2010-04-07 04:11:27 +04:00
|
|
|
} else {
|
|
|
|
p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}",
|
|
|
|
VAR_CMD, 0);
|
|
|
|
if (p1) {
|
|
|
|
(void)str2Lst_Append(makefiles, p1, NULL);
|
|
|
|
(void)Lst_Find(makefiles, NULL, ReadMakefile);
|
|
|
|
free(p1);
|
|
|
|
}
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2006-12-03 23:37:39 +03:00
|
|
|
/* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
|
2007-12-21 23:32:24 +03:00
|
|
|
if (!noBuiltins || !printVars) {
|
2010-04-07 04:11:27 +04:00
|
|
|
makeDependfile = Var_Subst(NULL, "${.MAKE.DEPENDFILE:T}",
|
|
|
|
VAR_CMD, 0);
|
|
|
|
doing_depend = TRUE;
|
|
|
|
(void)ReadMakefile(makeDependfile, NULL);
|
|
|
|
doing_depend = FALSE;
|
2007-12-21 23:32:24 +03:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2010-04-07 04:11:27 +04:00
|
|
|
MakeMode(NULL);
|
|
|
|
|
1994-06-07 02:45:17 +04:00
|
|
|
Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
|
|
|
|
if (p1)
|
|
|
|
free(p1);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2006-10-11 11:01:44 +04:00
|
|
|
if (!compatMake)
|
|
|
|
Job_ServerStart(maxJobTokens, jp_0, jp_1);
|
2000-12-30 05:05:20 +03:00
|
|
|
if (DEBUG(JOB))
|
2006-10-15 12:38:21 +04:00
|
|
|
fprintf(debug_file, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
|
2006-10-11 11:01:44 +04:00
|
|
|
jp_0, jp_1, maxJobs, maxJobTokens, compatMake);
|
2000-12-30 05:05:20 +03:00
|
|
|
|
2001-10-31 04:15:57 +03:00
|
|
|
Main_ExportMAKEFLAGS(TRUE); /* initial export */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2000-04-20 15:23:25 +04:00
|
|
|
Check_Cwd_av(0, NULL, 0); /* initialize it */
|
|
|
|
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* 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_Exists("VPATH", VAR_CMD)) {
|
2002-01-27 04:50:54 +03:00
|
|
|
char *vpath, savec;
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* GCC stores string constants in read-only memory, but
|
|
|
|
* Var_Subst will want to write this thing, so store it
|
|
|
|
* in an array
|
|
|
|
*/
|
|
|
|
static char VPATH[] = "${VPATH}";
|
|
|
|
|
1994-03-05 03:34:29 +03:00
|
|
|
vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
|
1993-03-21 12:45:37 +03:00
|
|
|
path = vpath;
|
|
|
|
do {
|
|
|
|
/* skip to end of directory */
|
1994-03-05 03:34:29 +03:00
|
|
|
for (cp = path; *cp != ':' && *cp != '\0'; cp++)
|
|
|
|
continue;
|
1993-03-21 12:45:37 +03:00
|
|
|
/* Save terminator character so know when to stop */
|
|
|
|
savec = *cp;
|
|
|
|
*cp = '\0';
|
|
|
|
/* Add directory to search path */
|
2005-07-26 02:55:58 +04:00
|
|
|
(void)Dir_AddDir(dirSearchPath, path);
|
1993-03-21 12:45:37 +03:00
|
|
|
*cp = savec;
|
|
|
|
path = cp + 1;
|
|
|
|
} while (savec == ':');
|
2005-08-05 04:53:18 +04:00
|
|
|
free(vpath);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now that all search paths have been read for suffixes et al, it's
|
|
|
|
* time to add the default search path to their lists...
|
|
|
|
*/
|
|
|
|
Suff_DoPaths();
|
|
|
|
|
1999-09-15 14:47:37 +04:00
|
|
|
/*
|
|
|
|
* Propagate attributes through :: dependency lists.
|
|
|
|
*/
|
|
|
|
Targ_Propagate();
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/* print the initial graph, if the user requested it */
|
|
|
|
if (DEBUG(GRAPH1))
|
|
|
|
Targ_PrintGraph(1);
|
|
|
|
|
1996-11-06 20:58:58 +03:00
|
|
|
/* print the values of any variables requested by the user */
|
|
|
|
if (printVars) {
|
|
|
|
LstNode ln;
|
|
|
|
|
2008-12-13 18:19:29 +03:00
|
|
|
for (ln = Lst_First(variables); ln != NULL;
|
1996-11-06 20:58:58 +03:00
|
|
|
ln = Lst_Succ(ln)) {
|
2003-09-05 10:52:11 +04:00
|
|
|
char *var = (char *)Lst_Datum(ln);
|
|
|
|
char *value;
|
|
|
|
|
|
|
|
if (strchr(var, '$')) {
|
|
|
|
value = p1 = Var_Subst(NULL, var, VAR_GLOBAL, 0);
|
|
|
|
} else {
|
|
|
|
value = Var_Value(var, VAR_GLOBAL, &p1);
|
|
|
|
}
|
1996-11-06 20:58:58 +03:00
|
|
|
printf("%s\n", value ? value : "");
|
|
|
|
if (p1)
|
|
|
|
free(p1);
|
|
|
|
}
|
2006-12-03 23:37:39 +03:00
|
|
|
} else {
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
2006-12-03 23:37:39 +03:00
|
|
|
* Have now read the entire graph and need to make a list of
|
|
|
|
* targets to create. If none was given on the command line,
|
|
|
|
* we consult the parsing module to find the main target(s)
|
|
|
|
* to create.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2006-12-03 23:37:39 +03:00
|
|
|
if (Lst_IsEmpty(create))
|
|
|
|
targs = Parse_MainName();
|
|
|
|
else
|
|
|
|
targs = Targ_FindList(create, TARG_CREATE);
|
|
|
|
|
|
|
|
if (!compatMake) {
|
|
|
|
/*
|
|
|
|
* Initialize job module before traversing the graph
|
|
|
|
* now that any .BEGIN and .END targets have been read.
|
|
|
|
* This is done only if the -q flag wasn't given
|
|
|
|
* (to prevent the .BEGIN from being executed should
|
|
|
|
* it exist).
|
|
|
|
*/
|
|
|
|
if (!queryFlag) {
|
|
|
|
Job_Init();
|
|
|
|
jobsRunning = TRUE;
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2006-12-03 23:37:39 +03:00
|
|
|
/* Traverse the graph, checking on all the targets */
|
|
|
|
outOfDate = Make_Run(targs);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Compat_Init will take care of creating all the
|
|
|
|
* targets as well as initializing the module.
|
|
|
|
*/
|
|
|
|
Compat_Run(targs);
|
|
|
|
}
|
1996-11-06 20:58:58 +03:00
|
|
|
}
|
|
|
|
|
1999-09-15 12:48:17 +04:00
|
|
|
#ifdef CLEANUP
|
2008-12-13 18:19:29 +03:00
|
|
|
Lst_Destroy(targs, NULL);
|
|
|
|
Lst_Destroy(variables, NULL);
|
|
|
|
Lst_Destroy(makefiles, NULL);
|
2005-08-10 01:36:42 +04:00
|
|
|
Lst_Destroy(create, (FreeProc *)free);
|
1999-09-15 12:48:17 +04:00
|
|
|
#endif
|
1994-06-07 02:45:17 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/* print the graph now it's been processed if the user requested it */
|
|
|
|
if (DEBUG(GRAPH2))
|
|
|
|
Targ_PrintGraph(2);
|
|
|
|
|
2000-12-30 05:05:20 +03:00
|
|
|
Trace_Log(MAKEEND, 0);
|
|
|
|
|
1994-06-07 02:45:17 +04:00
|
|
|
Suff_End();
|
|
|
|
Targ_End();
|
|
|
|
Arch_End();
|
|
|
|
Var_End();
|
|
|
|
Parse_End();
|
|
|
|
Dir_End();
|
1998-03-26 22:20:36 +03:00
|
|
|
Job_End();
|
2000-12-30 05:05:20 +03:00
|
|
|
Trace_End();
|
1994-06-07 02:45:17 +04:00
|
|
|
|
2006-11-18 01:07:39 +03:00
|
|
|
return outOfDate ? 1 : 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
* ReadMakefile --
|
|
|
|
* Open and parse the given makefile.
|
|
|
|
*
|
|
|
|
* Results:
|
2006-04-13 00:32:27 +04:00
|
|
|
* 0 if ok. -1 if couldn't open file.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* lots
|
|
|
|
*/
|
2006-04-13 00:32:27 +04:00
|
|
|
static int
|
2009-01-24 00:58:27 +03:00
|
|
|
ReadMakefile(const void *p, const void *q __unused)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2009-01-24 00:58:27 +03:00
|
|
|
const char *fname = p; /* makefile to read */
|
2006-12-16 11:59:29 +03:00
|
|
|
int fd;
|
1999-09-04 08:21:28 +04:00
|
|
|
size_t len = MAXPATHLEN;
|
2008-10-07 02:09:21 +04:00
|
|
|
char *name, *path = bmake_malloc(len);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
if (!strcmp(fname, "-")) {
|
2010-12-25 07:57:07 +03:00
|
|
|
Parse_File(NULL /*stdin*/, -1);
|
2001-06-13 03:36:17 +04:00
|
|
|
Var_Set("MAKEFILE", "", VAR_GLOBAL, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
} else {
|
|
|
|
/* if we've chdir'd, rebuild the path name */
|
Overhaul the initialization and handling of .OBJDIR:
* Replace chdir_verify_path() with Main_SetObjdir(), which can be called
externally, and can take a "const char *". (There's a lot of non-const
"char *" passing around in var.c of what should be const strings....)
* Rewrite the initial "find my .OBJDIR" code to make use of the new
function. This still functions as it had in the past, but the comment
above this block was changed to reflect reality: if MAKEOBJDIRPREFIX
or MAKEOBJDIR are set in the environment, then *only that value* is
tried; make does not fall back to obj.MACHINE, obj, and /usr/obj/`pwd`
as it would without these env vars set.
* Add a new special target, .OBJDIR:, which when parsed will cause make to
change to a new object directory and reset .OBJDIR, and PWD in the
environment. This will allow some makefiles (mainly, src/tools)
to override the default objdir semantics in order to add custom logic.
2001-10-31 06:59:42 +03:00
|
|
|
if (strcmp(curdir, objdir) && *fname != '/') {
|
1999-09-04 08:21:28 +04:00
|
|
|
size_t plen = strlen(curdir) + strlen(fname) + 2;
|
|
|
|
if (len < plen)
|
2008-10-07 02:09:21 +04:00
|
|
|
path = bmake_realloc(path, len = 2 * plen);
|
1999-09-04 08:21:28 +04:00
|
|
|
|
|
|
|
(void)snprintf(path, len, "%s/%s", curdir, fname);
|
2006-12-16 11:59:29 +03:00
|
|
|
fd = open(path, O_RDONLY);
|
|
|
|
if (fd != -1) {
|
1993-03-21 12:45:37 +03:00
|
|
|
fname = path;
|
|
|
|
goto found;
|
|
|
|
}
|
2003-12-19 01:36:18 +03:00
|
|
|
|
|
|
|
/* If curdir failed, try objdir (ala .depend) */
|
|
|
|
plen = strlen(objdir) + strlen(fname) + 2;
|
|
|
|
if (len < plen)
|
2008-10-07 02:09:21 +04:00
|
|
|
path = bmake_realloc(path, len = 2 * plen);
|
2003-12-19 01:36:18 +03:00
|
|
|
(void)snprintf(path, len, "%s/%s", objdir, fname);
|
2006-12-16 11:59:29 +03:00
|
|
|
fd = open(path, O_RDONLY);
|
|
|
|
if (fd != -1) {
|
2003-12-19 01:36:18 +03:00
|
|
|
fname = path;
|
|
|
|
goto found;
|
|
|
|
}
|
2006-12-16 11:59:29 +03:00
|
|
|
} else {
|
|
|
|
fd = open(fname, O_RDONLY);
|
|
|
|
if (fd != -1)
|
|
|
|
goto found;
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
/* look in -I and system include directories. */
|
|
|
|
name = Dir_FindFile(fname, parseIncPath);
|
|
|
|
if (!name)
|
2001-10-31 04:15:57 +03:00
|
|
|
name = Dir_FindFile(fname,
|
|
|
|
Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
|
2006-12-16 11:59:29 +03:00
|
|
|
if (!name || (fd = open(name, O_RDONLY)) == -1) {
|
2006-05-19 21:21:46 +04:00
|
|
|
if (name)
|
|
|
|
free(name);
|
1999-09-04 08:21:28 +04:00
|
|
|
free(path);
|
2006-04-13 00:32:27 +04:00
|
|
|
return(-1);
|
1999-09-04 08:21:28 +04:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
fname = name;
|
|
|
|
/*
|
|
|
|
* set the MAKEFILE variable desired by System V fans -- the
|
|
|
|
* placement of the setting here means it gets set to the last
|
|
|
|
* makefile specified, as it is set by SysV make.
|
|
|
|
*/
|
2001-06-02 00:33:37 +04:00
|
|
|
found:
|
2010-04-07 04:11:27 +04:00
|
|
|
if (!doing_depend)
|
2001-06-13 03:36:17 +04:00
|
|
|
Var_Set("MAKEFILE", fname, VAR_GLOBAL, 0);
|
2006-12-16 11:59:29 +03:00
|
|
|
Parse_File(fname, fd);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1999-09-04 08:21:28 +04:00
|
|
|
free(path);
|
2006-04-13 00:32:27 +04:00
|
|
|
return(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2000-04-20 15:23:25 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If MAKEOBJDIRPREFIX is in use, make ends up not in .CURDIR
|
|
|
|
* in situations that would not arrise with ./obj (links or not).
|
|
|
|
* This tends to break things like:
|
|
|
|
*
|
|
|
|
* build:
|
|
|
|
* ${MAKE} includes
|
|
|
|
*
|
|
|
|
* This function spots when ${.MAKE:T} or ${.MAKE} is a command (as
|
|
|
|
* opposed to an argument) in a command line and if so returns
|
|
|
|
* ${.CURDIR} so caller can chdir() so that the assumptions made by
|
|
|
|
* the Makefile hold true.
|
|
|
|
*
|
|
|
|
* If ${.MAKE} does not contain any '/', then ${.MAKE:T} is skipped.
|
|
|
|
*
|
|
|
|
* The chdir() only happens in the child process, and does nothing if
|
|
|
|
* MAKEOBJDIRPREFIX and MAKEOBJDIR are not in the environment so it
|
|
|
|
* should not break anything. Also if NOCHECKMAKECHDIR is set we
|
|
|
|
* do nothing - to ensure historic semantics can be retained.
|
|
|
|
*/
|
|
|
|
static int Check_Cwd_Off = 0;
|
|
|
|
|
|
|
|
static char *
|
2008-02-16 00:29:50 +03:00
|
|
|
Check_Cwd_av(int ac, char **av, int copy)
|
2000-04-20 15:23:25 +04:00
|
|
|
{
|
|
|
|
static char *make[4];
|
2002-01-27 04:50:54 +03:00
|
|
|
static char *cur_dir = NULL;
|
2003-07-14 22:19:11 +04:00
|
|
|
char **mp;
|
|
|
|
char *cp;
|
2000-04-20 15:23:25 +04:00
|
|
|
int is_cmd, next_cmd;
|
|
|
|
int i;
|
|
|
|
int n;
|
|
|
|
|
2008-12-07 07:50:15 +03:00
|
|
|
if (Check_Cwd_Off) {
|
|
|
|
if (DEBUG(CWD))
|
|
|
|
fprintf(debug_file, "check_cwd: check is off.\n");
|
2000-04-20 15:23:25 +04:00
|
|
|
return NULL;
|
2008-12-07 07:50:15 +03:00
|
|
|
}
|
2000-04-20 15:23:25 +04:00
|
|
|
|
|
|
|
if (make[0] == NULL) {
|
|
|
|
if (Var_Exists("NOCHECKMAKECHDIR", VAR_GLOBAL)) {
|
|
|
|
Check_Cwd_Off = 1;
|
2008-12-07 07:50:15 +03:00
|
|
|
if (DEBUG(CWD))
|
|
|
|
fprintf(debug_file, "check_cwd: turning check off.\n");
|
2000-04-20 15:23:25 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
make[1] = Var_Value(".MAKE", VAR_GLOBAL, &cp);
|
|
|
|
if ((make[0] = strrchr(make[1], '/')) == NULL) {
|
|
|
|
make[0] = make[1];
|
|
|
|
make[1] = NULL;
|
|
|
|
} else
|
|
|
|
++make[0];
|
|
|
|
make[2] = NULL;
|
2002-01-27 04:50:54 +03:00
|
|
|
cur_dir = Var_Value(".CURDIR", VAR_GLOBAL, &cp);
|
2000-04-20 15:23:25 +04:00
|
|
|
}
|
2008-12-07 07:50:15 +03:00
|
|
|
if (ac == 0 || av == NULL) {
|
|
|
|
if (DEBUG(CWD))
|
|
|
|
fprintf(debug_file, "check_cwd: empty command.\n");
|
2000-04-20 15:23:25 +04:00
|
|
|
return NULL; /* initialization only */
|
2008-12-07 07:50:15 +03:00
|
|
|
}
|
2000-04-20 15:23:25 +04:00
|
|
|
|
|
|
|
if (getenv("MAKEOBJDIR") == NULL &&
|
2008-12-07 07:50:15 +03:00
|
|
|
getenv("MAKEOBJDIRPREFIX") == NULL) {
|
|
|
|
if (DEBUG(CWD))
|
|
|
|
fprintf(debug_file, "check_cwd: no obj dirs.\n");
|
2000-04-20 15:23:25 +04:00
|
|
|
return NULL;
|
2008-12-07 07:50:15 +03:00
|
|
|
}
|
2000-04-20 15:23:25 +04:00
|
|
|
|
|
|
|
|
|
|
|
next_cmd = 1;
|
|
|
|
for (i = 0; i < ac; ++i) {
|
|
|
|
is_cmd = next_cmd;
|
|
|
|
|
|
|
|
n = strlen(av[i]);
|
|
|
|
cp = &(av[i])[n - 1];
|
2006-06-30 02:02:06 +04:00
|
|
|
if (strspn(av[i], "|&;") == (size_t)n) {
|
2000-04-20 15:23:25 +04:00
|
|
|
next_cmd = 1;
|
|
|
|
continue;
|
|
|
|
} else if (*cp == ';' || *cp == '&' || *cp == '|' || *cp == ')') {
|
|
|
|
next_cmd = 1;
|
|
|
|
if (copy) {
|
|
|
|
do {
|
|
|
|
*cp-- = '\0';
|
|
|
|
} while (*cp == ';' || *cp == '&' || *cp == '|' ||
|
|
|
|
*cp == ')' || *cp == '}') ;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* XXX this should not happen.
|
|
|
|
*/
|
2008-12-07 07:50:15 +03:00
|
|
|
fprintf(stderr, "%s: WARNING: raw arg ends in shell meta '%s'\n",
|
|
|
|
progname, av[i]);
|
2000-04-20 15:23:25 +04:00
|
|
|
}
|
|
|
|
} else
|
|
|
|
next_cmd = 0;
|
|
|
|
|
|
|
|
cp = av[i];
|
|
|
|
if (*cp == ';' || *cp == '&' || *cp == '|')
|
|
|
|
is_cmd = 1;
|
|
|
|
|
2008-12-07 07:50:15 +03:00
|
|
|
if (DEBUG(CWD))
|
|
|
|
fprintf(debug_file, "av[%d] == %s '%s'",
|
2000-04-20 15:23:25 +04:00
|
|
|
i, (is_cmd) ? "cmd" : "arg", av[i]);
|
|
|
|
if (is_cmd != 0) {
|
2000-06-06 07:00:11 +04:00
|
|
|
if (*cp == '(' || *cp == '{' ||
|
|
|
|
*cp == ';' || *cp == '&' || *cp == '|') {
|
|
|
|
do {
|
|
|
|
++cp;
|
|
|
|
} while (*cp == '(' || *cp == '{' ||
|
|
|
|
*cp == ';' || *cp == '&' || *cp == '|');
|
|
|
|
if (*cp == '\0') {
|
|
|
|
next_cmd = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2000-04-20 15:23:25 +04:00
|
|
|
if (strcmp(cp, "cd") == 0 || strcmp(cp, "chdir") == 0) {
|
2008-12-07 07:50:15 +03:00
|
|
|
if (DEBUG(CWD))
|
|
|
|
fprintf(debug_file, " == cd, done.\n");
|
2000-04-20 15:23:25 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
for (mp = make; *mp != NULL; ++mp) {
|
|
|
|
n = strlen(*mp);
|
|
|
|
if (strcmp(cp, *mp) == 0) {
|
2008-12-07 07:50:15 +03:00
|
|
|
if (DEBUG(CWD))
|
|
|
|
fprintf(debug_file, " %s == '%s', chdir(%s)\n",
|
2002-01-27 04:50:54 +03:00
|
|
|
cp, *mp, cur_dir);
|
|
|
|
return cur_dir;
|
2000-04-20 15:23:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-07 07:50:15 +03:00
|
|
|
if (DEBUG(CWD))
|
|
|
|
fprintf(debug_file, "\n");
|
2000-04-20 15:23:25 +04:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
2003-07-14 22:19:11 +04:00
|
|
|
Check_Cwd_Cmd(const char *cmd)
|
2000-04-20 15:23:25 +04:00
|
|
|
{
|
2003-07-14 22:19:11 +04:00
|
|
|
char *cp, *bp;
|
|
|
|
char **av;
|
2008-02-16 00:29:50 +03:00
|
|
|
int ac;
|
2000-04-20 15:23:25 +04:00
|
|
|
|
|
|
|
if (Check_Cwd_Off)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (cmd) {
|
|
|
|
av = brk_string(cmd, &ac, TRUE, &bp);
|
2008-12-07 07:50:15 +03:00
|
|
|
if (DEBUG(CWD))
|
|
|
|
fprintf(debug_file, "splitting: '%s' -> %d words\n",
|
2000-04-20 15:23:25 +04:00
|
|
|
cmd, ac);
|
|
|
|
} else {
|
|
|
|
ac = 0;
|
|
|
|
av = NULL;
|
|
|
|
bp = NULL;
|
|
|
|
}
|
|
|
|
cp = Check_Cwd_av(ac, av, 1);
|
2006-04-22 22:48:46 +04:00
|
|
|
if (bp)
|
2000-04-20 15:23:25 +04:00
|
|
|
free(bp);
|
2006-04-22 22:48:46 +04:00
|
|
|
if (av)
|
|
|
|
free(av);
|
2000-04-20 15:23:25 +04:00
|
|
|
return cp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2003-07-14 22:19:11 +04:00
|
|
|
Check_Cwd(const char **argv)
|
2000-04-20 15:23:25 +04:00
|
|
|
{
|
|
|
|
char *cp;
|
2008-02-16 00:29:50 +03:00
|
|
|
int ac;
|
2000-04-20 15:23:25 +04:00
|
|
|
|
|
|
|
if (Check_Cwd_Off)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (ac = 0; argv[ac] != NULL; ++ac)
|
|
|
|
/* NOTHING */;
|
|
|
|
if (ac == 3 && *argv[1] == '-') {
|
|
|
|
cp = Check_Cwd_Cmd(argv[2]);
|
|
|
|
} else {
|
2003-07-14 22:19:11 +04:00
|
|
|
cp = Check_Cwd_av(ac, UNCONST(argv), 0);
|
2000-04-20 15:23:25 +04:00
|
|
|
}
|
|
|
|
if (cp) {
|
|
|
|
chdir(cp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-05-29 03:34:35 +04:00
|
|
|
/*-
|
|
|
|
* Cmd_Exec --
|
|
|
|
* Execute the command in cmd, and return the output of that command
|
|
|
|
* in a string.
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* A string containing the output of the command, or the empty string
|
2006-08-26 22:17:41 +04:00
|
|
|
* If errnum is not NULL, it contains the reason for the command failure
|
1996-05-29 03:34:35 +04:00
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* The string must be freed by the caller.
|
|
|
|
*/
|
|
|
|
char *
|
2006-08-26 22:17:41 +04:00
|
|
|
Cmd_Exec(const char *cmd, const char **errnum)
|
1996-05-29 03:34:35 +04:00
|
|
|
{
|
2003-07-14 22:19:11 +04:00
|
|
|
const char *args[4]; /* Args for invoking the shell */
|
1996-05-29 03:34:35 +04:00
|
|
|
int fds[2]; /* Pipe streams */
|
2008-02-16 00:29:50 +03:00
|
|
|
int cpid; /* Child PID */
|
|
|
|
int pid; /* PID from wait() */
|
1996-05-29 03:34:35 +04:00
|
|
|
char *res; /* result */
|
|
|
|
int status; /* command exit status */
|
|
|
|
Buffer buf; /* buffer to store the result */
|
|
|
|
char *cp;
|
2008-02-16 00:29:50 +03:00
|
|
|
int cc;
|
1996-05-29 03:34:35 +04:00
|
|
|
|
|
|
|
|
2006-08-26 22:17:41 +04:00
|
|
|
*errnum = NULL;
|
1996-05-29 03:34:35 +04:00
|
|
|
|
2003-08-01 04:39:52 +04:00
|
|
|
if (!shellName)
|
|
|
|
Shell_Init();
|
1996-05-29 03:34:35 +04:00
|
|
|
/*
|
|
|
|
* Set up arguments for shell
|
|
|
|
*/
|
2003-08-01 04:39:52 +04:00
|
|
|
args[0] = shellName;
|
1996-05-29 03:34:35 +04:00
|
|
|
args[1] = "-c";
|
|
|
|
args[2] = cmd;
|
|
|
|
args[3] = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Open a pipe for fetching its output
|
|
|
|
*/
|
|
|
|
if (pipe(fds) == -1) {
|
2006-08-26 22:17:41 +04:00
|
|
|
*errnum = "Couldn't create pipe for \"%s\"";
|
1996-05-29 03:34:35 +04:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Fork
|
|
|
|
*/
|
2010-04-23 04:18:50 +04:00
|
|
|
switch (cpid = vFork()) {
|
1996-05-29 03:34:35 +04:00
|
|
|
case 0:
|
|
|
|
/*
|
|
|
|
* Close input side of pipe
|
|
|
|
*/
|
2005-07-26 02:55:58 +04:00
|
|
|
(void)close(fds[0]);
|
1996-05-29 03:34:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Duplicate the output stream to the shell's output, then
|
|
|
|
* shut the extra thing down. Note we don't fetch the error
|
|
|
|
* stream...why not? Why?
|
|
|
|
*/
|
2005-07-26 02:55:58 +04:00
|
|
|
(void)dup2(fds[1], 1);
|
|
|
|
(void)close(fds[1]);
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2007-10-05 19:27:45 +04:00
|
|
|
Var_ExportVars();
|
|
|
|
|
2005-07-26 02:55:58 +04:00
|
|
|
(void)execv(shellPath, UNCONST(args));
|
1996-05-29 03:34:35 +04:00
|
|
|
_exit(1);
|
|
|
|
/*NOTREACHED*/
|
|
|
|
|
|
|
|
case -1:
|
2006-08-26 22:17:41 +04:00
|
|
|
*errnum = "Couldn't exec \"%s\"";
|
1996-05-29 03:34:35 +04:00
|
|
|
goto bad;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* No need for the writing half
|
|
|
|
*/
|
2005-07-26 02:55:58 +04:00
|
|
|
(void)close(fds[1]);
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2009-01-17 16:29:37 +03:00
|
|
|
Buf_Init(&buf, 0);
|
1996-05-29 03:34:35 +04:00
|
|
|
|
|
|
|
do {
|
|
|
|
char result[BUFSIZ];
|
|
|
|
cc = read(fds[0], result, sizeof(result));
|
1996-11-06 20:58:58 +03:00
|
|
|
if (cc > 0)
|
2009-01-17 16:29:37 +03:00
|
|
|
Buf_AddBytes(&buf, cc, result);
|
1996-05-29 03:34:35 +04:00
|
|
|
}
|
|
|
|
while (cc > 0 || (cc == -1 && errno == EINTR));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Close the input side of the pipe.
|
|
|
|
*/
|
2005-07-26 02:55:58 +04:00
|
|
|
(void)close(fds[0]);
|
1996-05-29 03:34:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Wait for the process to exit.
|
|
|
|
*/
|
2010-08-07 10:44:08 +04:00
|
|
|
while(((pid = waitpid(cpid, &status, 0)) != cpid) && (pid >= 0)) {
|
|
|
|
JobReapChild(pid, status, FALSE);
|
1996-05-29 03:34:35 +04:00
|
|
|
continue;
|
2010-08-07 10:44:08 +04:00
|
|
|
}
|
2009-01-17 16:29:37 +03:00
|
|
|
cc = Buf_Size(&buf);
|
|
|
|
res = Buf_Destroy(&buf, FALSE);
|
1996-05-29 03:34:35 +04:00
|
|
|
|
2008-02-16 00:29:50 +03:00
|
|
|
if (cc == 0)
|
2006-08-26 22:17:41 +04:00
|
|
|
*errnum = "Couldn't read shell's output for \"%s\"";
|
1996-05-29 03:34:35 +04:00
|
|
|
|
2009-09-03 10:45:23 +04:00
|
|
|
if (WIFSIGNALED(status))
|
|
|
|
*errnum = "\"%s\" exited on a signal";
|
|
|
|
else if (WEXITSTATUS(status) != 0)
|
2006-08-26 22:17:41 +04:00
|
|
|
*errnum = "\"%s\" returned non-zero status";
|
1996-05-29 03:34:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Null-terminate the result, convert newlines to spaces and
|
|
|
|
* install it in the variable.
|
|
|
|
*/
|
2008-02-16 00:29:50 +03:00
|
|
|
res[cc] = '\0';
|
|
|
|
cp = &res[cc];
|
1996-05-29 03:34:35 +04:00
|
|
|
|
2008-02-16 00:29:50 +03:00
|
|
|
if (cc > 0 && *--cp == '\n') {
|
1996-05-29 03:34:35 +04:00
|
|
|
/*
|
|
|
|
* A final newline is just stripped
|
|
|
|
*/
|
|
|
|
*cp-- = '\0';
|
|
|
|
}
|
|
|
|
while (cp >= res) {
|
|
|
|
if (*cp == '\n') {
|
|
|
|
*cp = ' ';
|
|
|
|
}
|
|
|
|
cp--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
bad:
|
2008-10-07 02:09:21 +04:00
|
|
|
res = bmake_malloc(1);
|
1996-05-29 03:34:35 +04:00
|
|
|
*res = '\0';
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*-
|
|
|
|
* Error --
|
|
|
|
* Print an error message given its format.
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* None.
|
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* The message is printed.
|
|
|
|
*/
|
|
|
|
/* VARARGS */
|
|
|
|
void
|
2003-07-14 22:19:11 +04:00
|
|
|
Error(const char *fmt, ...)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
va_list ap;
|
2009-01-17 00:13:13 +03:00
|
|
|
FILE *err_file;
|
|
|
|
|
|
|
|
err_file = debug_file;
|
|
|
|
if (err_file == stdout)
|
|
|
|
err_file = stderr;
|
2010-04-30 03:12:21 +04:00
|
|
|
(void)fflush(stdout);
|
2009-01-17 00:13:13 +03:00
|
|
|
for (;;) {
|
|
|
|
va_start(ap, fmt);
|
|
|
|
fprintf(err_file, "%s: ", progname);
|
|
|
|
(void)vfprintf(err_file, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
(void)fprintf(err_file, "\n");
|
|
|
|
(void)fflush(err_file);
|
|
|
|
if (err_file == stderr)
|
|
|
|
break;
|
|
|
|
err_file = stderr;
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
* Fatal --
|
|
|
|
* Produce a Fatal error message. If jobs are running, waits for them
|
|
|
|
* to finish.
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* The program exits
|
|
|
|
*/
|
|
|
|
/* VARARGS */
|
|
|
|
void
|
2003-07-14 22:19:11 +04:00
|
|
|
Fatal(const char *fmt, ...)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
2002-06-15 22:24:55 +04:00
|
|
|
va_start(ap, fmt);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (jobsRunning)
|
|
|
|
Job_Wait();
|
|
|
|
|
2010-04-30 03:12:21 +04:00
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
(void)vfprintf(stderr, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
(void)fprintf(stderr, "\n");
|
|
|
|
(void)fflush(stderr);
|
|
|
|
|
2010-04-07 04:11:27 +04:00
|
|
|
PrintOnError(NULL, NULL);
|
2001-06-02 00:33:37 +04:00
|
|
|
|
2003-12-07 23:30:28 +03:00
|
|
|
if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
|
1993-03-21 12:45:37 +03:00
|
|
|
Targ_PrintGraph(2);
|
2000-12-30 05:05:20 +03:00
|
|
|
Trace_Log(MAKEERROR, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
exit(2); /* Not 1 so -q can distinguish error */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Punt --
|
|
|
|
* Major exception once jobs are being created. Kills all jobs, prints
|
|
|
|
* a message and exits.
|
|
|
|
*
|
|
|
|
* Results:
|
1996-11-06 20:58:58 +03:00
|
|
|
* None
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* All children are killed indiscriminately and the program Lib_Exits
|
|
|
|
*/
|
|
|
|
/* VARARGS */
|
|
|
|
void
|
2003-07-14 22:19:11 +04:00
|
|
|
Punt(const char *fmt, ...)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
va_list ap;
|
1994-03-05 03:34:29 +03:00
|
|
|
|
2002-06-15 22:24:55 +04:00
|
|
|
va_start(ap, fmt);
|
2010-04-30 03:12:21 +04:00
|
|
|
(void)fflush(stdout);
|
2001-01-10 18:54:00 +03:00
|
|
|
(void)fprintf(stderr, "%s: ", progname);
|
1993-03-21 12:45:37 +03:00
|
|
|
(void)vfprintf(stderr, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
(void)fprintf(stderr, "\n");
|
|
|
|
(void)fflush(stderr);
|
|
|
|
|
2010-04-07 04:11:27 +04:00
|
|
|
PrintOnError(NULL, NULL);
|
2001-06-02 00:33:37 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
DieHorribly();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
* DieHorribly --
|
|
|
|
* Exit without giving a message.
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* A big one...
|
|
|
|
*/
|
|
|
|
void
|
2002-06-15 22:24:55 +04:00
|
|
|
DieHorribly(void)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
if (jobsRunning)
|
|
|
|
Job_AbortAll();
|
|
|
|
if (DEBUG(GRAPH2))
|
|
|
|
Targ_PrintGraph(2);
|
2000-12-30 05:05:20 +03:00
|
|
|
Trace_Log(MAKEERROR, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
exit(2); /* Not 1, so -q can distinguish error */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Finish --
|
|
|
|
* Called when aborting due to errors in child shell to signal
|
1996-11-06 20:58:58 +03:00
|
|
|
* abnormal exit.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Results:
|
1996-11-06 20:58:58 +03:00
|
|
|
* None
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* The program exits
|
|
|
|
*/
|
|
|
|
void
|
2002-06-15 22:24:55 +04:00
|
|
|
Finish(int errors)
|
|
|
|
/* number of errors encountered in Make_Make */
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
Fatal("%d error%s", errors, errors == 1 ? "" : "s");
|
|
|
|
}
|
|
|
|
|
1995-11-03 02:54:35 +03:00
|
|
|
/*
|
|
|
|
* enunlink --
|
|
|
|
* Remove a file carefully, avoiding directories.
|
|
|
|
*/
|
|
|
|
int
|
2002-06-15 22:24:55 +04:00
|
|
|
eunlink(const char *file)
|
1995-11-03 02:54:35 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (lstat(file, &st) == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (S_ISDIR(st.st_mode)) {
|
|
|
|
errno = EISDIR;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return unlink(file);
|
|
|
|
}
|
|
|
|
|
2001-05-29 21:37:51 +04:00
|
|
|
/*
|
|
|
|
* execError --
|
|
|
|
* Print why exec failed, avoiding stdio.
|
|
|
|
*/
|
|
|
|
void
|
2002-06-15 22:24:55 +04:00
|
|
|
execError(const char *af, const char *av)
|
2001-05-29 21:37:51 +04:00
|
|
|
{
|
|
|
|
#ifdef USE_IOVEC
|
|
|
|
int i = 0;
|
2002-03-14 19:08:37 +03:00
|
|
|
struct iovec iov[8];
|
2001-05-29 21:37:51 +04:00
|
|
|
#define IOADD(s) \
|
2003-07-14 22:19:11 +04:00
|
|
|
(void)(iov[i].iov_base = UNCONST(s), \
|
2001-05-29 21:37:51 +04:00
|
|
|
iov[i].iov_len = strlen(iov[i].iov_base), \
|
|
|
|
i++)
|
|
|
|
#else
|
2005-07-26 02:55:58 +04:00
|
|
|
#define IOADD(void)write(2, s, strlen(s))
|
2001-05-29 21:37:51 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
IOADD(progname);
|
2002-03-14 19:08:37 +03:00
|
|
|
IOADD(": ");
|
2003-07-14 22:19:11 +04:00
|
|
|
IOADD(af);
|
2002-03-14 19:08:37 +03:00
|
|
|
IOADD("(");
|
2003-07-14 22:19:11 +04:00
|
|
|
IOADD(av);
|
2002-03-14 19:08:37 +03:00
|
|
|
IOADD(") failed (");
|
2001-05-29 21:37:51 +04:00
|
|
|
IOADD(strerror(errno));
|
|
|
|
IOADD(")\n");
|
|
|
|
|
|
|
|
#ifdef USE_IOVEC
|
2002-03-14 19:08:37 +03:00
|
|
|
(void)writev(2, iov, 8);
|
2001-05-29 21:37:51 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* usage --
|
|
|
|
* exit with usage message
|
|
|
|
*/
|
1994-03-05 03:34:29 +03:00
|
|
|
static void
|
2002-06-15 22:24:55 +04:00
|
|
|
usage(void)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
(void)fprintf(stderr,
|
2009-08-27 03:17:11 +04:00
|
|
|
"usage: %s [-BeikNnqrstWX] \n\
|
|
|
|
[-C directory] [-D variable] [-d flags] [-f makefile]\n\
|
2004-07-13 15:59:12 +04:00
|
|
|
[-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n\
|
|
|
|
[-V variable] [variable=value] [target ...]\n", progname);
|
1993-03-21 12:45:37 +03:00
|
|
|
exit(2);
|
|
|
|
}
|
1994-06-07 02:45:17 +04:00
|
|
|
|
|
|
|
|
|
|
|
int
|
2009-01-24 00:26:30 +03:00
|
|
|
PrintAddr(void *a, void *b)
|
1994-06-07 02:45:17 +04:00
|
|
|
{
|
|
|
|
printf("%lx ", (unsigned long) a);
|
|
|
|
return b ? 0 : 0;
|
|
|
|
}
|
2008-02-16 00:29:50 +03:00
|
|
|
|
2001-06-02 00:33:37 +04:00
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-04-07 04:11:27 +04:00
|
|
|
PrintOnError(GNode *gn, const char *s)
|
2001-06-02 00:33:37 +04:00
|
|
|
{
|
2010-04-08 21:41:29 +04:00
|
|
|
static GNode *en = NULL;
|
2001-06-02 00:33:37 +04:00
|
|
|
char tmp[64];
|
2006-07-28 21:06:14 +04:00
|
|
|
char *cp;
|
|
|
|
|
2001-06-02 00:33:37 +04:00
|
|
|
if (s)
|
2010-04-07 04:11:27 +04:00
|
|
|
printf("%s", s);
|
2001-06-02 00:33:37 +04:00
|
|
|
|
|
|
|
printf("\n%s: stopped in %s\n", progname, curdir);
|
2010-04-07 04:11:27 +04:00
|
|
|
|
2010-04-08 21:41:29 +04:00
|
|
|
if (en)
|
|
|
|
return; /* we've been here! */
|
2010-04-07 04:11:27 +04:00
|
|
|
if (gn) {
|
|
|
|
/*
|
|
|
|
* We can print this even if there is no .ERROR target.
|
|
|
|
*/
|
|
|
|
Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL, 0);
|
|
|
|
}
|
2010-05-10 19:54:21 +04:00
|
|
|
strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
|
|
|
|
sizeof(tmp) - 1);
|
|
|
|
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
|
|
|
|
if (cp) {
|
|
|
|
if (*cp)
|
|
|
|
printf("%s", cp);
|
|
|
|
free(cp);
|
|
|
|
}
|
2010-04-07 04:11:27 +04:00
|
|
|
/*
|
2010-05-10 19:54:21 +04:00
|
|
|
* Finally, see if there is a .ERROR target, and run it if so.
|
2010-04-07 04:11:27 +04:00
|
|
|
*/
|
|
|
|
en = Targ_FindNode(".ERROR", TARG_NOCREATE);
|
|
|
|
if (en) {
|
|
|
|
en->type |= OP_SPECIAL;
|
|
|
|
Compat_Make(en, en);
|
|
|
|
}
|
2001-06-02 00:33:37 +04:00
|
|
|
}
|
2001-06-09 09:22:47 +04:00
|
|
|
|
|
|
|
void
|
2002-06-15 22:24:55 +04:00
|
|
|
Main_ExportMAKEFLAGS(Boolean first)
|
2001-06-09 09:22:47 +04:00
|
|
|
{
|
|
|
|
static int once = 1;
|
|
|
|
char tmp[64];
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
if (once != first)
|
|
|
|
return;
|
|
|
|
once = 0;
|
|
|
|
|
2001-06-10 06:31:00 +04:00
|
|
|
strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
|
|
|
|
sizeof(tmp));
|
|
|
|
s = Var_Subst(NULL, tmp, VAR_CMD, 0);
|
2001-06-09 09:22:47 +04:00
|
|
|
if (s && *s) {
|
|
|
|
#ifdef POSIX
|
|
|
|
setenv("MAKEFLAGS", s, 1);
|
|
|
|
#else
|
|
|
|
setenv("MAKE", s, 1);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2010-04-22 23:11:17 +04:00
|
|
|
|
2010-12-10 01:30:16 +03:00
|
|
|
char *
|
|
|
|
getTmpdir(void)
|
2010-04-22 23:11:17 +04:00
|
|
|
{
|
|
|
|
static char *tmpdir = NULL;
|
|
|
|
|
|
|
|
if (!tmpdir) {
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Honor $TMPDIR but only if it is valid.
|
|
|
|
* Ensure it ends with /.
|
|
|
|
*/
|
2010-04-23 02:39:13 +04:00
|
|
|
tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, 0);
|
2010-04-22 23:11:17 +04:00
|
|
|
if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
|
|
|
|
free(tmpdir);
|
|
|
|
tmpdir = bmake_strdup(_PATH_TMP);
|
|
|
|
}
|
|
|
|
}
|
2010-12-10 01:30:16 +03:00
|
|
|
return tmpdir;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create and open a temp file using "pattern".
|
|
|
|
* If "fnamep" is provided set it to a copy of the filename created.
|
|
|
|
* Otherwise unlink the file once open.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
mkTempFile(const char *pattern, char **fnamep)
|
|
|
|
{
|
|
|
|
static char *tmpdir = NULL;
|
|
|
|
char tfile[MAXPATHLEN];
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
if (!pattern)
|
|
|
|
pattern = TMPPAT;
|
|
|
|
if (!tmpdir)
|
|
|
|
tmpdir = getTmpdir();
|
2010-04-22 23:11:17 +04:00
|
|
|
if (pattern[0] == '/') {
|
2010-04-23 00:25:16 +04:00
|
|
|
snprintf(tfile, sizeof(tfile), "%s", pattern);
|
2010-04-22 23:11:17 +04:00
|
|
|
} else {
|
|
|
|
snprintf(tfile, sizeof(tfile), "%s%s", tmpdir, pattern);
|
|
|
|
}
|
|
|
|
if ((fd = mkstemp(tfile)) < 0)
|
|
|
|
Punt("Could not create temporary file %s: %s", tfile, strerror(errno));
|
|
|
|
if (fnamep) {
|
|
|
|
*fnamep = bmake_strdup(tfile);
|
|
|
|
} else {
|
|
|
|
unlink(tfile); /* we just want the descriptor */
|
|
|
|
}
|
|
|
|
return fd;
|
|
|
|
}
|