Compare commits

..

8 Commits

Author SHA1 Message Date
Paul Smith
b134da5505 * A few cleanups, and 3.77.94 release. 1999-08-25 21:39:28 +00:00
Paul Smith
d0b03e9355 * Terminology change in docs and code. 1999-08-24 04:49:39 +00:00
Paul Smith
5dc4b92b60 * Fix jobserver algorithm again.
* A couple of nits.
* Fix considered pruning for double-colon rules.
1999-08-23 22:15:17 +00:00
Paul Smith
b3fa4b3c7e * Start rewrite of jobserver to avoid unique tokens for debugging. 1999-08-23 05:35:14 +00:00
Paul Smith
6fa76a7d15 * Various changes. 1999-08-22 17:50:57 +00:00
Paul Smith
4ff6c62456 * Code cleanup. 1999-08-19 04:43:46 +00:00
Paul Smith
cbb9e38d10 * Rework jobserver yet one more time.
* Install the $(if ...) function and document it.  Still need some examples.
1999-08-13 07:36:26 +00:00
Paul Smith
9e79637ec3 * Some DOS fixes. 1999-08-12 23:16:42 +00:00
18 changed files with 981 additions and 694 deletions

View File

@@ -22,3 +22,5 @@ sun4 i386 i386-netbsd hp300-netbsd hp300 rs6000 sun3 news800 amiga
hp700 hp834 mips sol2 i486-linux
customs
install-sh mkinstalldirs

150
ChangeLog
View File

@@ -1,3 +1,153 @@
1999-08-25 Paul D. Smith <psmith@gnu.org>
* Version 3.77.94 released.
* main.c (main) [__MSDOS__]: If the user uses -j, warn that it's
not supported and reset it.
* make.h (ISDIGIT): Obtained this from the textutils distribution.
* main.c (decode_switches): Use it.
* function.c (is_numeric): Use it.
* main.c (struct command_switch): Store the switch char in an
unsigned char to shut up GCC about using it with ctype.h macros.
Besides, it _is_ always unsigned.
1999-08-24 Paul D. Smith <psmith@gnu.org>
* make.texinfo: Change "dependency" to "prerequisite" and
"dependencies" to "prerequisites". Various other cleanups related
to the terminology change.
* file.c: Change debugging and error messages to use
"prerequisite" instead of "dependency".
* implicit.c: Ditto.
* remake.c: Ditto.
* NEWS: Document it.
1999-08-23 Paul D. Smith <psmith@gnu.org>
* remake.c (update_file): Move the considered check into the
double-colon rule loop, so we consider double-colon rules
individually (otherwise after the first is pruned, the rest won't
get run).
* README.template: Minor changes.
Remove the debugging features of the jobserver, so it no longer
writes distinct tokens to the pipe. Thus, we don't need to store
the token we get. A side effect of this is to remove a potential
"unavailable token" situation: make-1 invokes make-2 with its
special token and make-3 with a normal token; make-2 completes.
Now we're waiting for make-3 but using 2 tokens; our special token
is idle. In the new version we don't have special tokens per se,
we merely decide if we already have a child or not. If we don't,
we don't need a token. If we do, we have to get one to run the
next child. Similar for putting tokens back: if we're cleaning up
the last child, we don't put a token back. Otherwise, we do.
* main.c: Add a new, internal flag --jobserver-fds instead of
overloading the meaning of -j. Remove job_slots_str and add the
stringlist jobserver_fds.
(struct command_switch): We don't need the int_string type.
(switches[]): Add a new option for --jobserver-fds and remove
conditions around -j. Make the description for the former 0 so it
doesn't print during "make --help".
(main): Rework jobserver parsing. If we got --jobserver-fds
make sure it's valid. We only get one and job_slots must be 0.
If we're the toplevel make (-jN without --jobserver-fds) create
the pipe and write generic tokens.
Create the stringlist struct for the submakes.
Clean up the stringlist where necessary.
(init_switches): Remove int_string handling.
(print_usage): Don't print internal flags (description ptr is 0).
(decode_switches): Remove int_string handling.
(define_makeflags): Remove int_string handling.
* job.c: Remove my_job_token flag and all references to the
child->job_token field.
(free_job_token): Remove this and merge it into free_child().
(reap_children): Rework the "reaped a child" logic slightly.
Don't call defunct free_job_token anymore. Always call
free_child, even if we're dying.
(free_child): If we're not freeing the only child, put a token
back in the pipe. Then, if we're dying, don't bother to free.
(new_job): If we are using the jobserver, loop checking to see if
a) there are no children or b) we get a token from the pipe.
* job.h (struct child): Remove the job_token field.
1999-08-20 Paul D. Smith <psmith@gnu.org>
* variable.c (try_variable_definition): Allocate for variable
expansion in f_append with a simple variable: if we're looking at
target-specific variables we don't want to trash the buffer.
Noticed by Reiner Beninga <Reiner.Beninga@mchp.siemens.de>.
1999-08-16 Eli Zaretskii <eliz@is.elta.co.il>
* main.c (main) [__MSDOS__]: Mirror any backslashes in argv[0], to
avoid problems in shell commands that use backslashes as escape
characters.
1999-08-16 Paul D. Smith <psmith@gnu.org>
* Version 3.77.93 released.
1999-08-13 Paul D. Smith <psmith@gnu.org
* function.c (func_if): New function $(if ...) based on the
original by Han-Wen but reworked quite a bit.
(function_table): Add it.
* NEWS: Introduce it.
* make.texinfo (If Function): Document it.
* job.c (free_job_token): Check for EINTR when writing tokens to
the jobserver pipe.
1999-08-12 Paul D. Smith <psmith@gnu.org>
Another jobserver algorithm change. We conveniently forgot that
the blocking bit is shared by all users of the pipe, it's not a
per-process setting. Since we have many make processes all
sharing the pipe we can't use the blocking bit as a signal handler
flag. Instead, we'll dup the pipe's read FD and have the SIGCHLD
handler close the dup'd FD. This will cause the read() to fail
with EBADF the next time we invoke it, so we know we need to reap
children. We then re-dup and reap.
* main.c (main): Define the job_rfd variable to hold the dup'd FD.
Actually dup the read side of the pipe. Don't bother setting the
blocking bit on the file descriptor.
* make.h: Declare the job_rfd variable.
* job.c (child_handler): If the dup'd jobserver pipe is open,
close it and assign -1 to job_rfd to notify the main program that
we got a SIGCHLD.
(start_job_command): Close the dup'd FD before exec'ing children.
Since we open and close this thing so often it doesn't seem
worth it to use the close-on-exec bit.
(new_job): Remove code for testing/setting the blocking bit.
Instead of EAGAIN, test for EBADF. If the dup'd FD has been
closed, re-dup it before we reap children.
* function.c (func_shell): Be a little more accurate about the
length of the error string to allocate.
* expand.c (variable_expand_for_file): If there's no filenm info
(say, from a builtin command) then reset reading_file to 0.
1999-08-09 Paul D. Smith <psmith@gnu.org>
* maintMakefile: Use g in sed (s///g) to replace >1 variable per
line.
* Makefile.DOS.template [__MSDOS__]: Fix mostlyclean-aminfo to
remove the right files.
1999-08-01 Eli Zaretskii <eliz@is.elta.co.il>
* function.c (msdos_openpipe) [__MSDOS__]: *Really* return a FILE
ptr.
1999-08-01 Paul D. Smith <psmith@gnu.org>
New jobserver algorithm to avoid a possible hole where we could

View File

@@ -224,7 +224,9 @@ dist-info: $(INFO_DEPS)
for base in $(INFO_DEPS); do d=$(srcdir); for file in `cd $$d && eval echo $$base*`; do test -f $(distdir)/$$file || ln $$d/$$file $(distdir)/$$file 2> /dev/null || cp -p $$d/$$file $(distdir)/$$file; done; done
mostlyclean-aminfo:
cd $(srcdir) && for i in $(INFO_DEPS) make.i; do rm -f `eval echo $$i*`; done
-rm -f make.aux make.cp make.cps make.dvi make.fn make.fns make.ky \
make.kys make.ps make.log make.pg make.toc make.tp make.tps \
make.vr make.vrs make.op make.tr make.cv make.cn
clean-aminfo:

14
NEWS
View File

@@ -12,17 +12,21 @@ Please send GNU make bug reports to bug-make@gnu.org.
Version 3.78
* Two new functions, $(error ...) and $(warning ...) are provided. The
* Two new functions, $(error ...) and $(warning ...) are available. The
former will cause make to fail and exit immediately upon expansion of
the function, with the text provided as the error message. The latter
causes the text provided to be printed as a warning message, but make
proceeds normally.
* A new function, $(call ...) is provided. This allows users to create
* A new function $(call ...) is available. This allows users to create
their own parameterized macros and invoke them later. Original
implementation of this feature was provided by Han-Wen Nienhuys
implementation of this function was provided by Han-Wen Nienhuys
<hanwen@cs.uu.nl>.
* A new function $(if ...) is available. It provides if-then-else
capabilities in a builtin function. Original implementation of this
function was provided by Han-Wen Nienhuys <hanwen@cs.uu.nl>.
* Make defines a new variable, .LIBPATTERNS. This variable controls how
library dependency expansion (dependencies like ``-lfoo'') is performed.
@@ -42,6 +46,10 @@ Version 3.78
each other to ensure that no more than N jobs are started across all
makes. To get the old behavior of -j back, you can configure make
with the --disable-job-server option.
* The confusing term "dependency" has been replaced by the more accurate
and standard term "prerequisite", both in the manual and in all GNU make
output.
Version 3.77

View File

@@ -1,6 +1,7 @@
This directory contains the %VERSION% release of GNU Make.
All bugs reported for previous releases have been fixed.
Some bugs surely remain.
See the file NEWS for the user-visible changes from previous releases.
In addition, there have been bugs fixed.
For general building and installation instructions, see the file INSTALL.
@@ -24,6 +25,8 @@ site. There is information there about ordering hardcopy documentation.
http://www.gnu.org/doc/doc.html
http://www.gnu.org/manual/manual.html
You can also find the latest versions of GNU Make from there.
Please send GNU make bug reports to bug-make@gnu.org. Please see the
section of the manual entitles `Problems and Bugs' for information on
submitting bug reports.
@@ -61,9 +64,5 @@ debug this code, you can do `make check-loadavg' to see if it works
properly on your system. (You must run `configure' beforehand, but you
need not build Make itself to run this test.)
See the file NEWS for what has changed since previous releases.
GNU Make is fully documented in make.texinfo. See the section entitled
`Problems and Bugs' for information on submitting bug reports.
GNU Make is free software. See the file COPYING for copying conditions.

View File

@@ -3,7 +3,7 @@ AC_REVISION([$Id$])
AC_PREREQ(2.13)dnl dnl Minimum Autoconf version required.
AC_INIT(vpath.c)dnl dnl A distinctive file to look for in srcdir.
AM_INIT_AUTOMAKE(make, 3.77.92)
AM_INIT_AUTOMAKE(make, 3.77.94)
AM_CONFIG_HEADER(config.h)
dnl Regular configure stuff

View File

@@ -442,7 +442,10 @@ variable_expand_for_file (line, file)
save = current_variable_set_list;
current_variable_set_list = file->variables;
reading_file = &file->cmds->fileinfo;
if (file->cmds && file->cmds->fileinfo.filenm)
reading_file = &file->cmds->fileinfo;
else
reading_file = 0;
fnext = file->variables->next;
/* See if there's a pattern-specific variable struct for this target. */
if (!file->pat_searched)

6
file.c
View File

@@ -620,9 +620,9 @@ print_file (f)
putchar ('\n');
if (f->precious)
puts (_("# Precious file (dependency of .PRECIOUS)."));
puts (_("# Precious file (prerequisite of .PRECIOUS)."));
if (f->phony)
puts (_("# Phony target (dependency of .PHONY)."));
puts (_("# Phony target (prerequisite of .PHONY)."));
if (f->cmd_target)
puts (_("# Command-line target."));
if (f->dontcare)
@@ -632,7 +632,7 @@ print_file (f)
if (f->stem != 0)
printf (_("# Implicit/static pattern stem: `%s'\n"), f->stem);
if (f->intermediate)
puts (_("# File is an intermediate dependency."));
puts (_("# File is an intermediate prerequisite."));
if (f->also_make != 0)
{
fputs (_("# Also makes:"), stdout);

View File

@@ -699,16 +699,13 @@ int
is_numeric (p)
char *p;
{
char *end = p + strlen (p) -1;
char *end = p + strlen (p) - 1;
char *beg = p;
strip_whitespace (&p, &end);
while (p <= end)
{
if (!isdigit (*p))
return 0;
p++;
}
while (p <= end)
if (!ISDIGIT (*(p++))) /* ISDIGIT only evals its arg once: see make.h. */
return 0;
return (end - beg >= 0);
}
@@ -817,9 +814,9 @@ func_foreach (o, argv, funcname)
const char *funcname;
{
/* expand only the first two. */
char *varname = expand_argument (argv[0], argv[1] -1);
char *varname = expand_argument (argv[0], argv[1] - 1);
char *list = expand_argument (argv[1], argv[2] -1);
char *body = savestring (argv[2], argv[3] - argv[2] -1 );
char *body = savestring (argv[2], argv[3] - argv[2] - 1);
int len =0;
char *list_iterator = list;
@@ -1075,6 +1072,68 @@ func_sort (o, argv, funcname)
return o;
}
/*
$(if condition,true-part[,false-part])
CONDITION is false iff it evaluates to an empty string. White
space before and after condition are stripped before evaluation.
If CONDITION is true, then TRUE-PART is evaluated, otherwise FALSE-PART is
evaluated (if it exists). Because only one of the two PARTs is evaluated,
you can use $(if ...) to create side-effects (with $(shell ...), for
example).
*/
static char *
func_if (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
{
char *begp = argv[0];
char *endp = argv[1]-1;
int result = 0;
/* Find the result of the condition: if we have a value, and it's not
empty, the condition is true. If we don't have a value, or it's the
empty string, then it's false. */
strip_whitespace (&begp, &endp);
if (begp < endp)
{
char *expansion = expand_argument (begp, endp);
result = strlen (expansion);
free (expansion);
}
/* If the result is true (1) we want to eval the first argument, and if
it's false (0) we want to eval the second. If the argument doesn't
exist we do nothing, otherwise expand it and add to the buffer. */
argv += 1 + !result;
if (argv[0] != NULL && argv[1] != NULL)
{
char *expansion;
char **endp = argv+1;
/* If we're doing the else-clause, make sure we concatenate any
potential extra arguments into the last argument. */
if (!result)
while (*endp && **endp != '\0')
++endp;
expansion = expand_argument (*argv, *endp-1);
o = variable_buffer_output (o, expansion, strlen (expansion));
free (expansion);
}
return o;
}
static char *
func_wildcard(o, argv, funcname)
char *o;
@@ -1203,7 +1262,7 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp)
#ifdef __MSDOS__
int
FILE *
msdos_openpipe (int* pipedes, int *pidp, char *text)
{
FILE *fpipe=0;
@@ -1307,7 +1366,7 @@ func_shell (o, argv, funcname)
/* For error messages. */
if (reading_file != 0)
{
error_prefix = (char *) alloca (strlen(reading_file->filenm)+100);
error_prefix = (char *) alloca (strlen(reading_file->filenm)+11+4);
sprintf (error_prefix,
"%s:%lu: ", reading_file->filenm, reading_file->lineno);
}
@@ -1546,54 +1605,6 @@ func_not (char* o, char **argv, char *funcname)
o = variable_buffer_output (o, result ? "1" : "", result);
return o;
}
/*
This is an experimental conditional function.
Syntax:
$(if condition, true-part, false-part)
This is fully not consistent with make's syntax, but more in line
with `normal' programming languages.
Semantics:
- CONDITION is false iff it evaluates to an empty string. White
space before and after condition are stripped before evaluation.
- If CONDITION is true, then TRUE-PART is evaluated, otherwise
FALSE-PART is evaluated. Because only one of the two PARTs is
evaluated, you can use $(if ) to create side-effects with the
$(shell ) function
*/
static char *
func_if (char* o, char **argv, char *funcname)
{
char *begp = argv[0];
char *endp = argv[1]-2;
char *expansion =0;
int result = 0;
strip_whitespace (&begp, &endp);
if(begp <= endp)
expansion = expand_argument (begp, endp + 1);
result = expansion
? strlen (expansion)
: 0;
result = !result;
free (expansion);
expansion = expand_argument (argv[1 + result], argv[2+result] -1);
o = variable_buffer_output (o, expansion, strlen (expansion));
return o;
}
#endif
@@ -1645,9 +1656,9 @@ static struct function_table_entry function_table[] =
{ STRING_SIZE_TUPLE("call"), -1, 1, func_call},
{ STRING_SIZE_TUPLE("error"), 1, 1, func_error},
{ STRING_SIZE_TUPLE("warning"), 1, 1, func_error},
{ STRING_SIZE_TUPLE("if"), -2, 0, func_if},
#ifdef EXPERIMENTAL
{ STRING_SIZE_TUPLE("eq"), 2, 1, func_eq},
{ STRING_SIZE_TUPLE("if"), 3, 0, func_if},
{ STRING_SIZE_TUPLE("not"), 1, 1, func_not},
#endif
{ 0 }

View File

@@ -376,7 +376,7 @@ pattern_search (file, archive, depth, recursions)
"impossible", then the rule fails and don't
bother trying it on the second pass either
since we know that will fail too. */
DEBUGP2 (_("Rejecting impossible %s dependency `%s'.\n"),
DEBUGP2 (_("Rejecting impossible %s prerequisite `%s'.\n"),
p == depname ? _("implicit") : _("rule"), p);
tryrules[i] = 0;
break;
@@ -384,7 +384,7 @@ pattern_search (file, archive, depth, recursions)
intermediate_files[deps_found] = 0;
DEBUGP2 (_("Trying %s dependency `%s'.\n"),
DEBUGP2 (_("Trying %s prerequisite `%s'.\n"),
p == depname ? _("implicit") : _("rule"), p);
/* The DEP->changed flag says that this dependency resides in a
@@ -408,8 +408,9 @@ pattern_search (file, archive, depth, recursions)
vp = p;
if (vpath_search (&vp, (FILE_TIMESTAMP *) 0))
{
DEBUGP2 (_("Found dependency `%s' as VPATH `%s'\n"), p, vp);
strcpy(vp, p);
DEBUGP2 (_("Found prerequisite `%s' as VPATH `%s'\n"),
p, vp);
strcpy (vp, p);
found_files[deps_found++] = vp;
continue;
}

247
job.c
View File

@@ -202,11 +202,6 @@ unsigned int job_slots_used = 0;
static int good_stdin_used = 0;
/* Specifies whether the current process's reserved job token is in use.
'+' means it's available, '-' means it isn't. */
static char my_job_token = '+';
/* Chain of children waiting to run until the load average goes down. */
static struct child *waiting_jobs = 0;
@@ -224,40 +219,11 @@ int unixy_shell = 1;
*/
int w32_kill(int pid, int sig)
{
return ((process_kill(pid, sig) == TRUE) ? 0 : -1);
return ((process_kill(pid, sig) == TRUE) ? 0 : -1);
}
#endif /* WINDOWS32 */
static void
free_job_token (child)
struct child *child;
{
switch (child->job_token)
{
case '-':
/* If this child doesn't have a token, punt. */
return;
case '+':
/* If this child has the reserved token, take it back. */
my_job_token = '+';
break;
default:
/* Write any other job tokens back to the pipe. */
write (job_fds[1], &child->job_token, 1);
break;
}
if (debug_flag)
printf (_("Released token `%c' for child 0x%08lx (%s).\n"),
child->job_token, (unsigned long int) child, child->file->name);
child->job_token = '-';
}
/* Write an error message describing the exit status given in
EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME.
Append "(ignored)" if IGNORED is nonzero. */
@@ -308,11 +274,10 @@ vmsWaitForChildren(int *status)
/* Handle a dead child. This handler may or may not ever be installed.
If we're using the jobserver blocking read, we need it. First, installing
it ensures the read will interrupt on SIGCHLD. Second, we reset the
blocking bit on the read side of the pipe to ensure we don't enter another
blocking read without reaping all the dead children. In this case we
don't need the dead_children count.
If we're using the jobserver feature, we need it. First, installing it
ensures the read will interrupt on SIGCHLD. Second, we close the dup'd
read FD to ensure we don't enter another blocking read without reaping all
the dead children. In this case we don't need the dead_children count.
If we don't have either waitpid or wait3, then make is unreliable, but we
use the dead_children count to reap children as best we can. */
@@ -325,15 +290,11 @@ child_handler (sig)
{
++dead_children;
#ifdef HAVE_JOBSERVER
if (job_fds[0] >= 0)
if (job_rfd >= 0)
{
int fl = fcntl(job_fds[0], F_GETFL, 0);
if (fl >= 0)
fcntl(job_fds[0], F_SETFL, fl | O_NONBLOCK);
close (job_rfd);
job_rfd = -1;
}
#endif
if (debug_flag)
printf (_("Got a SIGCHLD; %u unreaped children.\n"), dead_children);
@@ -354,14 +315,23 @@ reap_children (block, err)
int block, err;
{
WAIT_T status;
#ifdef WAIT_NOHANG
/* Initially, assume we have some. */
int reap_more = 1;
#ifdef WAIT_NOHANG
# define REAP_MORE reap_more
#else
# define REAP_MORE dead_children
#endif
/* As long as:
We have at least one child outstanding OR a shell function in progress,
AND
We're blocking for a complete child OR there are more children to reap
we'll keep reaping children. */
while ((children != 0 || shell_function_pid != 0) &&
(block || REAP_MORE))
{
@@ -406,10 +376,9 @@ reap_children (block, err)
any_remote |= c->remote;
any_local |= ! c->remote;
if (debug_flag)
printf (_("Live child 0x%08lx (%s) PID %ld token %c%s\n"),
printf (_("Live child 0x%08lx (%s) PID %ld %s\n"),
(unsigned long int) c, c->file->name,
(long) c->pid, c->job_token,
c->remote ? _(" (remote)") : "");
(long) c->pid, c->remote ? _(" (remote)") : "");
#ifdef VMS
break;
#endif
@@ -457,10 +426,11 @@ reap_children (block, err)
if (pid < 0)
{
/* The wait*() failed miserably. Punt. */
/* EINTR? Try again. */
if (EINTR_SET)
goto local_wait;
/* The wait*() failed miserably. Punt. */
pfatal_with_name ("wait");
}
else if (pid > 0)
@@ -473,26 +443,24 @@ reap_children (block, err)
else
{
/* No local children are dead. */
#ifdef WAIT_NOHANG
reap_more = 0;
#endif
if (block && any_remote)
{
/* Now try a blocking wait for a remote child. */
pid = remote_status (&exit_code, &exit_sig, &coredump, 1);
if (pid < 0)
goto remote_status_lose;
else if (pid == 0)
/* No remote children either. Finally give up. */
break;
else
/* We got a remote child. */
remote = 1;
}
else
break;
if (!block || !any_remote)
break;
/* Now try a blocking wait for a remote child. */
pid = remote_status (&exit_code, &exit_sig, &coredump, 1);
if (pid < 0)
goto remote_status_lose;
else if (pid == 0)
/* No remote children either. Finally give up. */
break;
/* We got a remote child. */
remote = 1;
}
#endif /* !__MSDOS__, !Amiga, !WINDOWS32. */
#ifdef __MSDOS__
/* Life is very different on MSDOS. */
pid = dos_pid - 1;
@@ -567,9 +535,9 @@ reap_children (block, err)
continue;
if (debug_flag)
printf (_("Reaping %s child 0x%08lx PID %ld token %c%s\n"),
printf (_("Reaping %s child 0x%08lx PID %ld %s\n"),
child_failed ? _("losing") : _("winning"),
(unsigned long int) c, (long) c->pid, c->job_token,
(unsigned long int) c, (long) c->pid,
c->remote ? _(" (remote)") : "");
if (c->sh_batch_file) {
@@ -667,8 +635,8 @@ reap_children (block, err)
notice_finished_file (c->file);
if (debug_flag)
printf (_("Removing child 0x%08lx PID %ld token %c%s from chain.\n"),
(unsigned long int) c, (long) c->pid, c->job_token,
printf (_("Removing child 0x%08lx PID %ld %s from chain.\n"),
(unsigned long int) c, (long) c->pid,
c->remote ? _(" (remote)") : "");
/* Block fatal signals while frobnicating the list, so that
@@ -678,9 +646,6 @@ reap_children (block, err)
live and call reap_children again. */
block_sigs ();
/* If this job has a token out, return it. */
free_job_token(c);
/* There is now another slot open. */
if (job_slots_used > 0)
--job_slots_used;
@@ -690,8 +655,8 @@ reap_children (block, err)
children = c->next;
else
lastc->next = c->next;
if (! handling_fatal_signal) /* Don't bother if about to die. */
free_child (c);
free_child (c);
unblock_sigs ();
@@ -715,6 +680,28 @@ static void
free_child (child)
register struct child *child;
{
/* If this child is the only one it was our "free" job, so don't put a
token back for it. This child has already been removed from the list,
so if there any left this wasn't the last one. */
if (job_fds[1] >= 0 && children)
{
char token = '+';
/* Write a job token back to the pipe. */
while (write (job_fds[1], &token, 1) != 1)
if (!EINTR_SET)
pfatal_with_name (_("write jobserver"));
if (debug_flag)
printf (_("Released token for child 0x%08lx (%s).\n"),
(unsigned long int) child, child->file->name);
}
if (handling_fatal_signal) /* Don't bother free'ing if about to die. */
return;
if (child->command_lines != 0)
{
register unsigned int i;
@@ -731,11 +718,6 @@ free_child (child)
free ((char *) child->environment);
}
/* If this child has a token it hasn't relinquished, give it up now.
This can happen if the job completes immediately, mainly because
all the command lines evaluated to empty strings. */
free_job_token(child);
free ((char *) child);
}
@@ -883,17 +865,18 @@ start_job_command (child)
? "%s" : (char *) 0, p);
/* Optimize an empty command. People use this for timestamp rules,
and forking a useless shell all the time leads to inefficiency. */
so avoid forking a useless shell. */
#if !defined(VMS) && !defined(_AMIGA)
if (
#ifdef __MSDOS__
unixy_shell /* the test is complicated and we already did it */
#else
(argv[0] && !strcmp(argv[0], "/bin/sh"))
(argv[0] && !strcmp (argv[0], "/bin/sh"))
#endif
&& (argv[1] && !strcmp(argv[1], "-c"))
&& (argv[2] && !strcmp(argv[2], ":"))
&& (argv[1]
&& argv[1][0] == '-' && argv[1][1] == 'c' && argv[1][2] == '\0')
&& (argv[2] && argv[2][0] == ':' && argv[2][1] == '\0')
&& argv[3] == NULL)
{
free (argv[0]);
@@ -1032,6 +1015,8 @@ start_job_command (child)
close (job_fds[0]);
close (job_fds[1]);
}
if (job_rfd >= 0)
close (job_rfd);
child_execute_job (child->good_stdin ? 0 : bad_stdin, 1,
argv, child->environment);
@@ -1202,10 +1187,9 @@ start_waiting_job (c)
case cs_running:
c->next = children;
if (debug_flag)
printf (_("Putting child 0x%08lx (%s) PID %ld token %c%s on the chain.\n"),
printf (_("Putting child 0x%08lx (%s) PID %ld%s on the chain.\n"),
(unsigned long int) c, c->file->name,
(long) c->pid, c->job_token,
c->remote ? _(" (remote)") : "");
(long) c->pid, c->remote ? _(" (remote)") : "");
children = c;
/* One more job slot is in use. */
++job_slots_used;
@@ -1362,62 +1346,69 @@ new_job (file)
c->command_ptr = 0;
c->environment = 0;
c->sh_batch_file = NULL;
c->job_token = '-';
/* Fetch the first command line to be run. */
job_next_command (c);
/* Wait for a job slot to be freed up. If we allow an infinite number
don't bother; also job_slots will == 0 if we're using the jobserver. */
if (job_slots != 0)
while (job_slots_used == job_slots)
reap_children (1, 0);
#ifdef MAKE_JOBSERVER
/* If we are controlling multiple jobs, and we don't yet have one,
obtain a token before starting the child. */
/* If we are controlling multiple jobs make sure we have a token before
starting the child. */
/* This can be inefficient. There's a decent chance that this job won't
actually have to run any subprocesses: the command script may be empty
or otherwise optimized away. It would be nice if we could defer
obtaining a token until just before we need it, in start_job_command.
To do that we'd need to keep track of whether we'd already obtained a
token (since start_job_command is called for each line of the job, not
just once). Also more thought needs to go into the entire algorithm;
this is where the old parallel job code waits, so... */
else if (job_fds[0] >= 0)
{
while (c->job_token == '-')
/* If the reserved token is available, just use that. */
if (my_job_token == '+')
{
c->job_token = my_job_token;
my_job_token = '-';
}
while (1)
{
char token;
/* If we don't already have a job started, use our "free" token. */
if (!children)
break;
/* Read a token. As long as there's no token available we'll block.
If we get a SIGCHLD we'll return with EINTR. If one happened
before we got here we'll return immediately with EAGAIN because
the signal handler unsets the blocking bit. */
else if (read (job_fds[0], &c->job_token, 1) < 1)
before we got here we'll return immediately with EBADF because
the signal handler closes the dup'd file descriptor. */
if (read (job_rfd, &token, 1) == 1)
{
int fl;
#if !defined(EAGAIN)
# define EAGAIN EWOULDBLOCK
#endif
if (errno != EINTR && errno != EAGAIN)
pfatal_with_name (_("read jobs pipe"));
/* Set the blocking bit on the read FD again, just in case. */
fl = fcntl(job_fds[0], F_GETFL, 0);
if (fl >= 0)
fcntl(job_fds[0], F_SETFL, fl & ~O_NONBLOCK);
/* Something's done. We don't want to block for a whole child,
just reap whatever's there. */
reap_children (0, 0);
if (debug_flag)
printf (_("Obtained token for child 0x%08lx (%s).\n"),
(unsigned long int) c, c->file->name);
break;
}
assert(c->job_token != '-');
if (debug_flag)
printf (_("Obtained token `%c' for child 0x%08lx (%s).\n"),
c->job_token, (unsigned long int) c, c->file->name);
}
if (errno != EINTR && errno != EBADF)
pfatal_with_name (_("read jobs pipe"));
/* Re-dup the read side of the pipe, so the signal handler can
notify us if we miss a child. */
if (job_rfd < 0)
job_rfd = dup (job_fds[0]);
/* Something's done. We don't want to block for a whole child,
just reap whatever's there. */
reap_children (0, 0);
}
#endif
/* The job is now primed. Start it running.
(This will notice if there are in fact no commands.) */
(void)start_waiting_job (c);
(void) start_waiting_job (c);
if (job_slots == 1)
/* Since there is only one job slot, make things run linearly.
@@ -2150,7 +2141,7 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
/* Note these overlap and strcpy() is undefined for
overlapping objects in ANSI C. The strlen() _IS_ right,
since we need to copy the nul byte too. */
bcopy (p + 1, p, strlen(p));
bcopy (p + 1, p, strlen (p));
if (instring)
goto string_char;
@@ -2318,7 +2309,7 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
}
*dptr = 0;
new_argv = (char **) xmalloc(2 * sizeof(char *));
new_argv = (char **) xmalloc (2 * sizeof (char *));
new_argv[0] = buffer;
new_argv[1] = 0;
}

1
job.h
View File

@@ -46,7 +46,6 @@ struct child
unsigned int good_stdin:1; /* Nonzero if this child has a good stdin. */
unsigned int deleted:1; /* Nonzero if targets have been deleted. */
char job_token; /* The token read from the job pipe. */
};
extern struct child *children;

240
main.c
View File

@@ -79,14 +79,13 @@ static char *quote_as_word PARAMS ((char *out, char *in, int double_dollars));
struct command_switch
{
char c; /* The switch character. */
unsigned char c; /* The switch character. */
enum /* Type of the value. */
{
flag, /* Turn int flag on. */
flag_off, /* Turn int flag off. */
string, /* One string per switch. */
int_string, /* One string. */
positive_int, /* A positive integer. */
floating, /* A floating-point number (double). */
ignore /* Ignored. */
@@ -104,6 +103,7 @@ struct command_switch
char *long_name; /* Long option name. */
char *argdesc; /* Descriptive word for argument. */
char *description; /* Description for usage message. */
/* 0 means internal; don't display help. */
};
@@ -195,16 +195,16 @@ static struct stringlist *makefiles = 0;
unsigned int job_slots = 1;
unsigned int default_job_slots = 1;
static char *job_slots_str = "1";
#ifndef MAKE_JOBSERVER
/* Value of job_slots that means no limit. */
static unsigned int inf_jobs = 0;
#endif
/* File descriptors for the jobs pipe. */
static struct stringlist *jobserver_fds = 0;
int job_fds[2] = { -1, -1 };
int job_rfd = -1;
/* Maximum load average at which multiple jobs will be run.
Negative values mean unlimited, while zero means limit to
@@ -277,14 +277,13 @@ static const struct command_switch switches[] =
"include-dir", _("DIRECTORY"),
_("Search DIRECTORY for included makefiles") },
{ 'j',
#ifndef MAKE_JOBSERVER
positive_int, (char *) &job_slots, 1, 1, 0,
(char *) &inf_jobs, (char *) &default_job_slots,
#else
int_string, (char *)&job_slots_str, 1, 1, 0, "0", "1",
#endif
"jobs", "N",
_("Allow N jobs at once; infinite jobs with no arg") },
{ 2, string, (char *) &jobserver_fds, 1, 1, 0, 0, 0,
"jobserver-fds", 0,
0 },
{ 'k', flag, (char *) &keep_going_flag, 1, 1, 0,
0, (char *) &default_keep_going_flag,
"keep-going", 0,
@@ -337,13 +336,13 @@ static const struct command_switch switches[] =
{ 'w', flag, (char *) &print_directory_flag, 1, 1, 0, 0, 0,
"print-directory", 0,
_("Print the current directory") },
{ 2, flag, (char *) &inhibit_print_directory_flag, 1, 1, 0, 0, 0,
{ 3, flag, (char *) &inhibit_print_directory_flag, 1, 1, 0, 0, 0,
"no-print-directory", 0,
_("Turn off -w, even if it was turned on implicitly") },
{ 'W', string, (char *) &new_files, 0, 0, 0, 0, 0,
"what-if", _("FILE"),
_("Consider FILE to be infinitely new") },
{ 3, flag, (char *) &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
{ 4, flag, (char *) &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
"warn-undefined-variables", 0,
_("Warn when an undefined variable is referenced") },
{ '\0', }
@@ -944,7 +943,7 @@ int main (int argc, char ** argv)
if (print_version_flag)
die (0);
#if !defined(__MSDOS__) && !defined(VMS)
#ifndef VMS
/* Set the "MAKE_COMMAND" variable to the name we were invoked with.
(If it is a relative pathname with a slash, prepend our directory name
so the result will run the same program regardless of the current dir.
@@ -962,9 +961,21 @@ int main (int argc, char ** argv)
strneq(argv[0], "//", 2))
argv[0] = xstrdup(w32ify(argv[0],1));
#else /* WINDOWS32 */
#ifdef __MSDOS__
if (strchr (argv[0], '\\'))
{
char *p;
argv[0] = xstrdup (argv[0]);
for (p = argv[0]; *p; p++)
if (*p == '\\')
*p = '/';
}
#else /* !__MSDOS__ */
if (current_directory[0] != '\0'
&& argv[0] != 0 && argv[0][0] != '/' && index (argv[0], '/') != 0)
argv[0] = concat (current_directory, "/", argv[0]);
#endif /* !__MSDOS__ */
#endif /* WINDOWS32 */
#endif
@@ -1138,7 +1149,7 @@ int main (int argc, char ** argv)
while (!feof (stdin))
{
char buf[2048];
unsigned int n = fread (buf, 1, sizeof(buf), stdin);
unsigned int n = fread (buf, 1, sizeof (buf), stdin);
if (n > 0 && fwrite (buf, 1, n, outfile) != n)
pfatal_with_name (_("fwrite (temporary file)"));
}
@@ -1155,7 +1166,7 @@ int main (int argc, char ** argv)
}
/* Make sure the temporary file will not be remade. */
stdin_nm = savestring (name, sizeof(name) -1);
stdin_nm = savestring (name, sizeof (name) -1);
f = enter_file (stdin_nm);
f->updated = 1;
f->update_status = 0;
@@ -1192,9 +1203,9 @@ int main (int argc, char ** argv)
/* This is supposed to be the default, but what the heck... */
sa.sa_flags = SA_INTERRUPT;
# endif
# define HANDLESIG(s) sigaction(s, &sa, NULL)
# define HANDLESIG(s) sigaction (s, &sa, NULL)
# else
# define HANDLESIG(s) signal(s, child_handler)
# define HANDLESIG(s) signal (s, child_handler)
# endif
/* OK, now actually install the handlers. */
@@ -1259,7 +1270,7 @@ int main (int argc, char ** argv)
/* We need to know what kind of shell we will be using. */
{
extern int _is_unixy_shell (const char *_path);
struct variable *shv = lookup_variable("SHELL", 5);
struct variable *shv = lookup_variable ("SHELL", 5);
extern int unixy_shell;
extern char *default_shell;
@@ -1283,81 +1294,90 @@ int main (int argc, char ** argv)
decode_env_switches ("MFLAGS", 6);
#endif
#ifdef __MSDOS__
if (job_slots != 1)
{
error (NILF, _("Parallel jobs (-j) are not supported on MS-DOS."));
error (NILF, _("Resetting to single job mode."));
job_slots = 1;
}
#endif
#ifdef MAKE_JOBSERVER
/* If extended jobs are available then the -j option can have one of 4
formats: (1) not specified: default is "1"; (2) specified with no value:
default is "0" (infinite); (3) specified with a single value: this means
the user wants N job slots; or (4) specified with 2 values separated by
a comma. The latter means we're a submake; the two values are the read
and write FDs, respectively, for the pipe. Note this last form is
undocumented for the user! */
/* If the jobserver-fds option is seen, make sure that -j is reasonable. */
sscanf (job_slots_str, "%d", &job_slots);
if (jobserver_fds)
{
char *cp = index (job_slots_str, ',');
char *cp;
/* In case #4, get the FDs. */
if (cp && sscanf (cp+1, "%d", &job_fds[1]) == 1)
if (jobserver_fds->idx > 1)
fatal (NILF, _("internal error: multiple --jobserver-fds options"));
/* The combination of a pipe + !job_slots means we're using the
jobserver. If !job_slots and we don't have a pipe, we can start
infinite jobs. */
if (job_slots != 0)
fatal (NILF, _("internal error: --jobserver-fds unexpected"));
/* Now parse the fds string and make sure it has the proper format. */
cp = jobserver_fds->list[0];
if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
fatal (NILF,
_("internal error: invalid --jobserver-fds string `%s'"), cp);
/* Create a duplicate pipe, that will be closed in the SIGCHLD
handler. If this fails with EBADF, the parent has closed the pipe
on us because it didn't think we were a submake. If so, print a
warning then default to -j1. */
if ((job_rfd = dup (job_fds[0])) < 0)
{
/* Set up the first FD and set job_slots to 0. The combination of a
pipe + !job_slots means we're using the jobserver. If !job_slots
and we don't have a pipe, we can start infinite jobs. */
job_fds[0] = job_slots;
job_slots = 0;
if (errno != EBADF)
pfatal_with_name (_("dup jobserver"));
/* Make sure the pipe is open! The parent might have closed it
because it didn't think we were a submake. If so, print a warning
then default to -j1. */
if (fcntl (job_fds[0], F_GETFL, 0) < 0
|| fcntl (job_fds[1], F_GETFL, 0) < 0)
{
error (NILF,
_("warning: jobserver unavailable (using -j1). Add `+' to parent make rule."));
job_slots = 1;
job_fds[0] = job_fds[1] = -1;
job_slots_str = "1";
}
error (NILF,
_("warning: jobserver unavailable (using -j1). Add `+' to parent make rule."));
job_slots = 1;
job_fds[0] = job_fds[1] = -1;
free (jobserver_fds->list);
free (jobserver_fds);
jobserver_fds = 0;
}
}
/* In case #3 above, set up the pipe and set up the submake options
properly. */
/* If we have >1 slot but no jobserver-fds, then we're a top-level make.
Set up the pipe and install the fds option for our children. */
if (job_slots > 1)
else if (job_slots > 1)
{
char buf[(sizeof("1024")*2)+1];
char c = '0';
char c = '+';
if (pipe (job_fds) < 0)
if (pipe (job_fds) < 0 || (job_rfd = dup (job_fds[0])) < 0)
pfatal_with_name (_("creating jobs pipe"));
/* Every make assumes that it always has one job it can run. For the
submakes it's the token they were given by their parent. For the
top make, we just subtract one from the number the user wants. */
top make, we just subtract one from the number the user wants. We
want job_slots to be 0 to indicate we're using the jobserver. */
while (--job_slots)
{
write(job_fds[1], &c, 1);
if (c == '9')
c = 'a';
else if (c == 'z')
c = 'A';
else if (c == 'Z')
c = '0'; /* Start over again!! */
else
++c;
}
while (write (job_fds[1], &c, 1) != 1)
if (!EINTR_SET)
pfatal_with_name (_("init jobserver pipe"));
sprintf(buf, "%d,%d", job_fds[0], job_fds[1]);
job_slots_str = xstrdup(buf);
}
/* Fill in the jobserver_fds struct for our children. */
/* Be sure the blocking bit on the read FD is set to start with. */
if (job_fds[0] >= 0)
{
int fl = fcntl(job_fds[0], F_GETFL, 0);
if (fl >= 0)
fcntl(job_fds[0], F_SETFL, fl & ~O_NONBLOCK);
jobserver_fds = (struct stringlist *)
xmalloc (sizeof (struct stringlist));
jobserver_fds->list = (char **) xmalloc (sizeof (char *));
jobserver_fds->list[0] = xmalloc ((sizeof ("1024")*2)+1);
sprintf (jobserver_fds->list[0], "%d,%d", job_fds[0], job_fds[1]);
jobserver_fds->idx = 1;
jobserver_fds->max = 1;
}
#endif
@@ -1594,9 +1614,9 @@ int main (int argc, char ** argv)
/* Add -o option for the stdin temporary file, if necessary. */
if (stdin_nm)
{
nargv = (char **)xmalloc((nargc + 2) * sizeof(char *));
bcopy((char *)argv, (char *)nargv, argc * sizeof(char *));
nargv[nargc++] = concat("-o", stdin_nm, "");
nargv = (char **) xmalloc ((nargc + 2) * sizeof (char *));
bcopy ((char *) argv, (char *) nargv, argc * sizeof (char *));
nargv[nargc++] = concat ("-o", stdin_nm, "");
nargv[nargc] = 0;
}
@@ -1674,8 +1694,8 @@ int main (int argc, char ** argv)
/* If there is a temp file from reading a makefile from stdin, get rid of
it now. */
if (stdin_nm && unlink(stdin_nm) < 0 && errno != ENOENT)
perror_with_name(_("unlink (temporary file): "), stdin_nm);
if (stdin_nm && unlink (stdin_nm) < 0 && errno != ENOENT)
perror_with_name (_("unlink (temporary file): "), stdin_nm);
{
int status;
@@ -1780,7 +1800,6 @@ init_switches ()
long_options[i].has_arg = no_argument;
break;
case int_string:
case string:
case positive_int:
case floating:
@@ -1841,8 +1860,7 @@ handle_non_switch_argument (arg, env)
}
else
{
lastgoal->next
= (struct dep *) xmalloc (sizeof (struct dep));
lastgoal->next = (struct dep *) xmalloc (sizeof (struct dep));
lastgoal = lastgoal->next;
}
lastgoal->name = 0;
@@ -1853,7 +1871,7 @@ handle_non_switch_argument (arg, env)
struct variable *v;
char *value;
v = lookup_variable("MAKECMDGOALS", 12);
v = lookup_variable ("MAKECMDGOALS", 12);
if (v == 0)
value = f->name;
else
@@ -1861,14 +1879,14 @@ handle_non_switch_argument (arg, env)
/* Paste the old and new values together */
unsigned int oldlen, newlen;
oldlen = strlen(v->value);
newlen = strlen(f->name);
value = (char *)alloca(oldlen + 1 + newlen + 1);
bcopy(v->value, value, oldlen);
oldlen = strlen (v->value);
newlen = strlen (f->name);
value = (char *) alloca (oldlen + 1 + newlen + 1);
bcopy (v->value, value, oldlen);
value[oldlen] = ' ';
bcopy(f->name, &value[oldlen + 1], newlen + 1);
bcopy (f->name, &value[oldlen + 1], newlen + 1);
}
define_variable("MAKECMDGOALS", 12, value, o_default, 0);
define_variable ("MAKECMDGOALS", 12, value, o_default, 0);
}
}
}
@@ -1894,7 +1912,7 @@ print_usage (bad)
{
char buf[1024], shortarg[50], longarg[50], *p;
if (cs->description[0] == '-')
if (!cs->description || cs->description[0] == '-')
continue;
switch (long_options[cs - switches].has_arg)
@@ -1939,8 +1957,9 @@ print_usage (bad)
{
const struct command_switch *ncs = cs;
while ((++ncs)->c != '\0')
if (ncs->description[0] == '-' &&
ncs->description[1] == cs->c)
if (ncs->description
&& ncs->description[0] == '-'
&& ncs->description[1] == cs->c)
{
/* This is another switch that does the same
one as the one we are processing. We want
@@ -2034,20 +2053,6 @@ decode_switches (argc, argv, env)
*(int *) cs->value_ptr = cs->type == flag;
break;
case int_string:
if (optarg == 0 && argc > optind
&& isdigit (argv[optind][0]))
optarg = argv[optind++];
if (!doit)
break;
if (optarg == 0)
optarg = cs->noarg_value;
*(char **)cs->value_ptr = optarg;
break;
case string:
if (!doit)
break;
@@ -2078,7 +2083,7 @@ decode_switches (argc, argv, env)
case positive_int:
if (optarg == 0 && argc > optind
&& isdigit (argv[optind][0]))
&& ISDIGIT (argv[optind][0]))
optarg = argv[optind++];
if (!doit)
@@ -2090,8 +2095,7 @@ decode_switches (argc, argv, env)
if (i < 1)
{
if (doit)
error (NILF, _("the `-%c' option requires a \
positive integral argument"),
error (NILF, _("the `-%c' option requires a positive integral argument"),
cs->c);
bad = 1;
}
@@ -2106,7 +2110,7 @@ positive integral argument"),
#ifndef NO_FLOAT
case floating:
if (optarg == 0 && optind < argc
&& (isdigit (argv[optind][0]) || argv[optind][0] == '.'))
&& (ISDIGIT (argv[optind][0]) || argv[optind][0] == '.'))
optarg = argv[optind++];
if (doit)
@@ -2133,7 +2137,7 @@ positive integral argument"),
if (!env && (bad || print_usage_flag))
{
print_usage(bad);
print_usage (bad);
die (bad ? 2 : 0);
}
}
@@ -2346,22 +2350,6 @@ define_makeflags (all, makefile)
break;
#endif
case int_string:
if (all)
{
char *vp = *(char **)cs->value_ptr;
if (cs->default_value != 0
&& streq(vp, cs->default_value))
break;
if (cs->noarg_value != 0
&& streq(vp, cs->noarg_value))
ADD_FLAG("", 0); /* Optional value omitted; see below. */
else
ADD_FLAG(vp, strlen(vp));
}
break;
case string:
if (all)
{

View File

@@ -18,29 +18,29 @@ MTEMPLATES = Makefile.DOS SMakefile
# General rule for turning a .template into a regular file.
#
$(TEMPLATES) : % : %.template configure.in
$(TEMPLATES) : % : %.template Makefile
rm -f $@
sed -e 's@%VERSION%@$(VERSION)@' \
-e 's@%PACKAGE%@$(PACKAGE)@' \
sed -e 's@%VERSION%@$(VERSION)@g' \
-e 's@%PACKAGE%@$(PACKAGE)@g' \
$< > $@
chmod a-w $@
# Construct Makefiles by adding on dependencies, etc.
#
$(MTEMPLATES) : % : %.template .dep_segment Makefile.am maintMakefile
$(MTEMPLATES) : % : %.template .dep_segment Makefile
rm -f $@
sed -e 's@%VERSION%@$(VERSION)@' \
-e 's@%PROGRAMS%@$(bin_PROGRAMS)@' \
-e 's@%SOURCES%@$(filter-out remote-%,$(make_SOURCES)) remote-$$(REMOTE).c@' \
-e 's@%OBJECTS%@$(filter-out remote-%,$(make_OBJECTS)) remote-$$(REMOTE).o@' \
-e 's@%GLOB_SOURCES%@$(globsrc) $(globhdr)@' \
-e 's@%GLOB_OBJECTS%@$(globsrc:glob/%.c=%.o)@' \
sed -e 's@%VERSION%@$(VERSION)@g' \
-e 's@%PROGRAMS%@$(bin_PROGRAMS)@g' \
-e 's@%SOURCES%@$(filter-out remote-%,$(make_SOURCES)) remote-$$(REMOTE).c@g' \
-e 's@%OBJECTS%@$(filter-out remote-%,$(make_OBJECTS)) remote-$$(REMOTE).o@g' \
-e 's@%GLOB_SOURCES%@$(globsrc) $(globhdr)@g' \
-e 's@%GLOB_OBJECTS%@$(globsrc:glob/%.c=%.o)@g' \
$< > $@
echo >>$@; echo '# --------------- DEPENDENCIES' >>$@; echo '#' >>$@; \
cat $(word 2,$^) >>$@
chmod a-w $@
NMakefile: NMakefile.template .dep_segment Makefile.am maintMakefile
NMakefile: NMakefile.template .dep_segment Makefile
rm -f $@
cp $< $@
echo >>$@; echo '# --------------- DEPENDENCIES' >>$@; echo '#' >>$@; \
@@ -49,10 +49,10 @@ NMakefile: NMakefile.template .dep_segment Makefile.am maintMakefile
# Construct build.sh.in
#
build.sh.in: build.template Makefile.am maintMakefile
build.sh.in: build.template Makefile
rm -f $@
sed -e 's@%objs%@$(filter-out remote-%, $(make_OBJECTS)@' \
-e 's@%globobjs%@$(patsubst %.c,%.o,$(globsrc)))@' \
sed -e 's@%objs%@$(filter-out remote-%, $(make_OBJECTS)@g' \
-e 's@%globobjs%@$(patsubst %.c,%.o,$(globsrc)))@g' \
$< > $@
chmod a-w+x $@

12
make.h
View File

@@ -299,6 +299,17 @@ extern char *alloca ();
# endif /* HAVE_ALLOCA_H. */
#endif /* GCC. */
/* ISDIGIT offers the following features:
- Its arg may be any int or unsigned int; it need not be an unsigned char.
- It's guaranteed to evaluate its argument exactly once.
NOTE! Make relies on this behavior, don't change it!
- It's typically faster.
Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
only '0' through '9' are digits. Prefer ISDIGIT to isdigit() unless
it's important to use the locale's definition of `digit' even when the
host does not conform to Posix. */
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
#ifndef iAPX286
# define streq(a, b) \
((a) == (b) || \
@@ -479,6 +490,7 @@ extern int batch_mode_shell;
extern unsigned int job_slots;
extern int job_fds[2];
extern int job_rfd;
#ifndef NO_FLOAT
extern double max_load_average;
#else

File diff suppressed because it is too large Load Diff

View File

@@ -316,19 +316,19 @@ update_file (file, depth)
register int status = 0;
register struct file *f;
/* Prune the dependency graph: if we've already been here on _this_ pass
through the dependency graph, we don't have to go any further. We won't
reap_children until we start the next pass, so no state change is
possible below here until then. */
if (file->considered == considered)
{
DEBUGPR (_("Pruning file `%s'.\n"));
return 0;
}
file->considered = considered;
for (f = file->double_colon ? file->double_colon : file; f != 0; f = f->prev)
{
/* Prune the dependency graph: if we've already been here on _this_
pass through the dependency graph, we don't have to go any further.
We won't reap_children until we start the next pass, so no state
change is possible below here until then. */
if (f->considered == considered)
{
DEBUGPR (_("Pruning file `%s'.\n"));
continue;
}
f->considered = considered;
status |= update_file_1 (f, depth);
check_renamed (f);
@@ -452,7 +452,7 @@ update_file_1 (file, depth)
if (d->file->updating)
{
error (NILF, _("Circular %s <- %s dependency dropped."),
error (NILF, _("Circular %s <- %s prerequisite dropped."),
file->name, d->file->name);
/* We cannot free D here because our the caller will still have
a reference to it when we were called recursively via
@@ -530,13 +530,13 @@ update_file_1 (file, depth)
file->updating = 0;
DEBUGPR (_("Finished dependencies of target file `%s'.\n"));
DEBUGPR (_("Finished prerequisites of target file `%s'.\n"));
if (running)
{
set_command_state (file, cs_deps_running);
--depth;
DEBUGPR (_("The dependencies of `%s' are being made.\n"));
DEBUGPR (_("The prerequisites of `%s' are being made.\n"));
return 0;
}
@@ -598,9 +598,9 @@ update_file_1 (file, depth)
{
print_spaces (depth);
if (d_mtime == (FILE_TIMESTAMP) -1)
printf (_("Dependency `%s' does not exist.\n"), dep_name (d));
printf (_("Prerequisite `%s' does not exist.\n"), dep_name (d));
else
printf (_("Dependency `%s' is %s than dependent `%s'.\n"),
printf (_("Prerequisite `%s' is %s than target `%s'.\n"),
dep_name (d), d->changed ? _("newer") : _("older"), file->name);
fflush (stdout);
}
@@ -612,12 +612,12 @@ update_file_1 (file, depth)
if (file->double_colon && file->deps == 0)
{
must_make = 1;
DEBUGPR (_("Target `%s' is double-colon and has no dependencies.\n"));
DEBUGPR (_("Target `%s' is double-colon and has no prerequisites.\n"));
}
else if (!noexist && file->is_target && !deps_changed && file->cmds == 0)
{
must_make = 0;
DEBUGPR (_("No commands for `%s' and no dependencies actually changed.\n"));
DEBUGPR (_("No commands for `%s' and no prerequisites actually changed.\n"));
}
if (!must_make)
@@ -851,7 +851,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
{
if (d->file->updating)
{
error (NILF, _("Circular %s <- %s dependency dropped."),
error (NILF, _("Circular %s <- %s prerequisite dropped."),
file->name, d->file->name);
if (lastd == 0)
{

View File

@@ -780,9 +780,9 @@ try_variable_definition (flocp, line, origin)
case f_simple:
/* A simple variable definition "var := value". Expand the value.
We have to allocate memory since otherwise it'll clobber the
variable buffer, and we still need that. */
alloc_value = allocated_variable_expand (p);
value = alloc_value;
variable buffer, and we may still need that if we're looking at a
target-specific variable. */
value = alloc_value = allocated_variable_expand (p);
break;
case f_conditional:
/* A conditional variable definition "var ?= value".
@@ -824,8 +824,10 @@ try_variable_definition (flocp, line, origin)
else
/* The previous definition of the variable was simple.
The new value comes from the old value, which was expanded
when it was set; and from the expanded new value. */
p = variable_expand (p);
when it was set; and from the expanded new value. Allocate
memory for the expansion as we may still need the rest of the
buffer if we're looking at a target-specific variable. */
p = alloc_value = allocated_variable_expand (p);
oldlen = strlen (v->value);
newlen = strlen (p);
@@ -952,7 +954,7 @@ print_variable (v, prefix)
register struct variable *v;
char *prefix;
{
char *origin;
const char *origin;
switch (v->origin)
{
@@ -980,7 +982,6 @@ print_variable (v, prefix)
case o_invalid:
default:
abort ();
break;
}
printf ("# %s\n", origin);