* New handling of += in target-specific variables.
+1999-11-17 Paul D. Smith <psmith@gnu.org>
+
+ * function.c (func_if): Find the end of the arg list by testing
+ the next item for NULL; any other test is not correct.
+ Reported by Graham Reed <grahamr@algorithmics.com> (PR/1429).
+
+ Fix += when used in a target-specific variable context.
+
+ * variable.h: New bitfield APPEND set if we have a +=
+ target-specific variable.
+
+ * variable.c (try_variable_definition): Add an argument to specify
+ if we're trying a target-specific variable. If we are and it's an
+ append style, don't append it, record it as normal recursive, but
+ set the APPEND flag so it'll be expanded later.
+ * main.c (handle_non_switch_argument): Use new
+ try_variable_definition() signature.
+ * read.c (read_makefile,record_target_var): Ditto.
+
+ * expand.c (allocated_variable_append): New function: like
+ allocated_variable_expand(), but we expand the same variable name
+ in the context of the ``next'' variable set, then we append this
+ expanded value.
+ (recursively_expand): Invoke it, if the APPEND bit is set.
+
+1999-11-10 Paul D. Smith <psmith@gnu.org>
+
+ * file.c (snap_deps): If the .NOTPARALLEL target is defined, turn
+ off parallel builds for this make only (still allow submakes to be
+ run in parallel).
+ * main.c: New variable, ``not_parallel''.
+ * make.h: Add an extern for it.
+ * job.c (new_job): Test NOT_PARALLEL as well as JOB_SLOTS.
+ * NEWS: Add info on .NOTPARALLEL.
+ * make.texinfo (Special Targets): Document it.
+
+ * configure.in (GLOBDIR): Set to "glob" if we need to build the
+ glob library.
+ * Makefile.am (SUBDIRS): Use the GLOBDIR variable instead of
+ "glob" so we don't try to build glob if we don't need to (if we
+ have GLIBC glob). Reported by Lars Hecking <lhecking@nmrc.ucc.ie>.
+
+ * main.c (main): Don't put "***" in the clock skew warning
+ message. Reported by karl@gnu.org.
+
+ * make.h: Remove unneeded signal setup.
+
+ * signame.c: Remove extraneous #includes; some versions of Ultrix
+ don't protect against multiple inclusions and it causes compile
+ errors. Reported by Simon Burge <simonb@thistledown.com.au>.
+
1999-10-15 Paul D. Smith <psmith@gnu.org>
* main.c (quote_for_env): Rename from quote_as_word().
commands.h dep.h filedef.h job.h make.h rule.h variable.h \
signame.c signame.h \
getopt.c getopt1.c getopt.h
-make_LDADD = @LIBOBJS@ @ALLOCA@ @GLOBLIB@
+make_LDADD = $(LIBOBJS) @ALLOCA@ $(GLOBLIB)
info_TEXINFOS = make.texinfo
man_MANS = make.1
-INCLUDES = @GLOBINC@ -DLIBDIR=\"$(libdir)\" -DINCLUDEDIR=\"$(includedir)\"
+INCLUDES = $(GLOBINC) -DLIBDIR=\"$(libdir)\" -DINCLUDEDIR=\"$(includedir)\"
EXTRA_DIST = README build.sh.in $(man_MANS) README.customs remote-cstms.c\
make-stds.texi texinfo.tex SCOPTIONS SMakefile\
readme.vms makefile.vms makefile.com config.h-vms vmsdir.h\
vmsfunctions.c vmsify.c
-SUBDIRS = glob
+SUBDIRS = $(GLOBDIR)
MOSTLYCLEANFILES = loadavg.c
CLEANFILES = loadavg
-MAKE_HOST = @MAKE_HOST@
+MAKE_HOST = @MAKE_HOST@
# --------------- Local INSTALL Section
GNU make NEWS -*-indented-text-*-
History of user-visible changes.
- 17 Sep 1999
+ 10 Nov 1999
Copyright (C) 1992,93,94,95,96,97,98,1999 Free Software Foundation, Inc.
See the end for copying conditions.
See the README file and the GNU make manual for details on sending bug
reports.
\f
-Version 3.78.2
+Version 3.79
* Previously, GNU make quoted variables such as MAKEFLAGS and
MAKEOVERRIDES for proper parsing by the shell. This allowed them to
explicitly within a make rule you may need to re-examine your use for
correctness given this change.
+* A new psuedo-target, .NOTPARALLEL, is defined. If set the current
+ makefile is always run serially regardless of the value of -j. Any
+ submakes will still be run in parallel if -j was specified.
+\f
Version 3.78
* Two new functions, $(error ...) and $(warning ...) are available. The
case "$make_cv_sys_gnu_glob" in
yes) AC_MSG_RESULT(yes) ;;
no) AC_MSG_RESULT([no; using local copy])
+ AC_SUBST(GLOBDIR) GLOBDIR=glob
AC_SUBST(GLOBINC) GLOBINC='-I$(srcdir)/glob'
AC_SUBST(GLOBLIB) GLOBLIB=glob/libglob.a
;;
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include <assert.h>
+
#include "make.h"
#include "filedef.h"
#include "job.h"
\f
/* Recursively expand V. The returned string is malloc'd. */
+static char *allocated_variable_append PARAMS ((struct variable *v));
+
char *
recursively_expand (v)
register struct variable *v;
v->name);
v->expanding = 1;
- value = allocated_variable_expand (v->value);
+ if (v->append)
+ value = allocated_variable_append (v);
+ else
+ value = allocated_variable_expand (v->value);
v->expanding = 0;
return value;
unsigned int length;
{
register struct variable *v = lookup_variable (name, length);
+ char *value;
if (v == 0)
warn_undefined (name, length);
- if (v != 0 && *v->value != '\0')
- {
- char *value = (v->recursive ? recursively_expand (v) : v->value);
- o = variable_buffer_output (o, value, strlen (value));
- if (v->recursive)
- free (value);
- }
+ if (v == 0 || *v->value == '\0')
+ return o;
+
+ value = (v->recursive ? recursively_expand (v) : v->value);
+
+ o = variable_buffer_output (o, value, strlen (value));
+
+ if (v->recursive)
+ free (value);
return o;
}
return result;
}
\f
+/* Like allocated_variable_expand, but we first expand this variable in the
+ context of the next variable set, then we append the expanded value. */
+
+static char *
+allocated_variable_append (v)
+ struct variable *v;
+{
+ struct variable_set_list *save;
+ int len = strlen (v->name);
+ char *var = alloca (len + 4);
+ char *value;
+
+ char *obuf = variable_buffer;
+ unsigned int olen = variable_buffer_length;
+
+ variable_buffer = 0;
+
+ assert(current_variable_set_list->next != 0);
+ save = current_variable_set_list;
+ current_variable_set_list = current_variable_set_list->next;
+
+ var[0] = '$';
+ var[1] = '(';
+ strcpy (&var[2], v->name);
+ var[len+2] = ')';
+ var[len+3] = '\0';
+
+ value = variable_expand_for_file (var, 0);
+
+ current_variable_set_list = save;
+
+ value += strlen (value);
+ value = variable_buffer_output (value, " ", 1);
+ value = variable_expand_string (value, v->value, (long)-1);
+
+ value = variable_buffer;
+
+#if 0
+ /* Waste a little memory and save time. */
+ value = xrealloc (value, strlen (value))
+#endif
+
+ variable_buffer = obuf;
+ variable_buffer_length = olen;
+
+ return value;
+}
+
/* Like variable_expand_for_file, but the returned string is malloc'd.
This function is called a lot. It wants to be efficient. */
f = lookup_file (".POSIX");
if (f != 0 && f->is_target)
posix_pedantic = 1;
+
+ f = lookup_file (".NOTPARALLEL");
+ if (f != 0 && f->is_target)
+ not_parallel = 1;
}
\f
/* Set the `command_state' member of FILE and all its `also_make's. */
if (argv[0] != NULL && argv[1] != NULL)
{
char *expansion;
- char **endp = argv+1;
+ char **argend = 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;
+ while (argend[1])
+ ++argend;
- expansion = expand_argument (*argv, *endp-1);
+ expansion = expand_argument (*argv, *argend-1);
o = variable_buffer_output (o, expansion, strlen (expansion));
free (expansion);
(This will notice if there are in fact no commands.) */
(void) start_waiting_job (c);
- if (job_slots == 1)
+ if (job_slots == 1 || not_parallel)
/* Since there is only one job slot, make things run linearly.
Wait for the child to die, setting the state to `cs_finished'. */
while (file->command_state == cs_running)
int posix_pedantic;
+/* Nonzero if we have seen the `.NOTPARALLEL' target.
+ This turns off parallel builds for this invocation of make. */
+
+int not_parallel;
+
/* Nonzero if some rule detected clock skew; we keep track so (a) we only
print one warning about it during the run, and (b) we can print a final
warning at the end of the run. */
/* If we detected some clock skew, generate one last warning */
if (clock_skew_detected)
- error (NILF, _("*** Warning: Clock skew detected. Your build may be incomplete."));
+ error (NILF,
+ _("warning: Clock skew detected. Your build may be incomplete."));
/* Exit. */
die (status);
if (arg[0] == '-' && arg[1] == '\0')
/* Ignore plain `-' for compatibility. */
return;
- v = try_variable_definition (0, arg, o_command);
+ v = try_variable_definition (0, arg, o_command, 0);
if (v != 0)
{
/* It is indeed a variable definition. Record a pointer to
# define POSIX 1
#endif
-#if defined (HAVE_SYS_SIGLIST) && !defined (SYS_SIGLIST_DECLARED)
-extern char *sys_siglist[];
-#endif
-
-#if !defined (HAVE_SYS_SIGLIST) || !defined (HAVE_STRSIGNAL)
-# include "signame.h"
-#endif
-
-/* Some systems do not define NSIG in <signal.h>. */
-#ifndef NSIG
-# ifdef _NSIG
-# define NSIG _NSIG
-# else
-# define NSIG 32
-# endif
-#endif
-
#ifndef RETSIGTYPE
# define RETSIGTYPE void
#endif
extern int debug_flag, print_data_base_flag, question_flag, touch_flag;
extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag;
extern int print_version_flag, print_directory_flag;
-extern int warn_undefined_variables_flag, posix_pedantic;
+extern int warn_undefined_variables_flag, posix_pedantic, not_parallel;
extern int clock_skew_detected;
/* can we run commands via 'sh -c xxx' or must we use batch files? */
export all variables to child processes by default.
@xref{Variables/Recursion, ,Communicating Variables to a
Sub-@code{make}}.
+
+@findex .NOTPARALLEL
+@item .NOTPARALLEL
+@cindex parallel execution, overriding
+
+If @code{.NOTPARALLEL} is mentioned as a target, then this invocation of
+@code{make} will be run serially, even if the @samp{-j} option is
+given. Any recursively invoked @code{make} command will still be run in
+parallel if its makefile doesn't contain this target. Any prerequisites
+on this target are ignored.
@end table
Any defined implicit rule suffix also counts as a special target if it
}
}
else if (!ignoring
- && !try_variable_definition (&fileinfo, p2, o_override))
+ && !try_variable_definition (&fileinfo, p2, o_override, 0))
error (&fileinfo, _("invalid `override' directive"));
continue;
p2 = next_token (p + 6);
if (*p2 == '\0')
export_all_variables = 1;
- v = try_variable_definition (&fileinfo, p2, o_file);
+ v = try_variable_definition (&fileinfo, p2, o_file, 0);
if (v != 0)
v->export = v_export;
else
reading_file = &fileinfo;
}
#undef word1eq
- else if (try_variable_definition (&fileinfo, p, o_file))
+ else if (try_variable_definition (&fileinfo, p, o_file, 0))
/* This line has been dealt with. */
;
else if (lb.buffer[0] == '\t')
global = current_variable_set_list;
+ /* If the variable is an append version, store that but treat it as a
+ normal recursive variable. */
+
for (; filenames != 0; filenames = nextf)
{
struct variable *v;
/* Make the new variable context current and define the variable. */
current_variable_set_list = vlist;
- v = try_variable_definition (flocp, defn, origin);
+ v = try_variable_definition (flocp, defn, origin, 1);
if (!v)
error (flocp, _("Malformed per-target variable definition"));
v->per_target = 1;
/* Convert between signal names and numbers.
- Copyright (C) 1990, 1992, 1993, 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1990,92,93,95,96,99 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "make.h"
-
-#include <stdio.h>
-#include <sys/types.h> /* Some systems need this for <signal.h>. */
-#include <signal.h>
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-/* Some systems declare `sys_siglist in <unistd.h>; if
- configure defined SYS_SIGLIST_DECLARED, it may expect
- to find the declaration there. */
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
+/* In the GNU make version, all the headers we need are provided by make.h. */
+#include "make.h"
/* Some systems do not define NSIG in <signal.h>. */
+1999-11-17 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/if: Add a test for PR/1429: put some text
+ after an if-statement to make sure it works.
+
+ * scripts/features/targetvars: Add a test for PR/1380: handling +=
+ in target-specific variable definitions correctly.
+
1999-10-15 Paul D. Smith <psmith@gnu.org>
* scripts/variables/MAKEFILES: This was really broken: it didn't
$answer = "foo bar\n";
&compare_output($answer, &get_logfile(1));
+# TEST #9
+# For PR/1380: Using += assignment in target-specific variables sometimes fails
+
+$makefile3 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile3");
+print MAKEFILE <<'EOF';
+.PHONY: all one
+all: FOO += baz
+all: one; @echo $(FOO)
+
+FOO = bar
+
+one: FOO += biz
+one: ; @echo $(FOO)
+EOF
+close(MAKEFILE);
+
+&run_make_with_options("$makefile3", "", &get_logfile);
+$answer = "bar baz biz\nbar baz\n";
+&compare_output($answer, &get_logfile(1));
+
+&run_make_with_options("$makefile3", "one", &get_logfile);
+$answer = "bar biz\n";
+&compare_output($answer, &get_logfile(1));
+
1;
\t\@echo \$(if ,\$(shell echo hi),false)
\t\@echo \$(if \$(call NEQ,a,b),true,false)
\t\@echo \$(if \$(call NEQ,a,a),true,false)
-\t\@echo \$(if z,true,fal,se)
-\t\@echo \$(if ,true,fal,se)
+\t\@echo \$(if z,true,fal,se) hi
+\t\@echo \$(if ,true,fal,se)there
EOMAKE
close(MAKEFILE);
&run_make_with_options($makefile, "", &get_logfile);
-$answer = "false\n\n\ntrue\ntrue\nfalse\ntrue\nfalse\ntrue\nfal,se\n";
+$answer = "false\n\n\ntrue\ntrue\nfalse\ntrue\nfalse\ntrue hi\nfal,sethere\n";
&compare_output($answer, &get_logfile(1));
1;
returned. */
struct variable *
-try_variable_definition (flocp, line, origin)
+try_variable_definition (flocp, line, origin, target_var)
const struct floc *flocp;
char *line;
enum variable_origin origin;
+ int target_var;
{
register int c;
register char *p = line;
f_simple, f_recursive, f_append, f_conditional } flavor = f_bogus;
char *name, *expanded_name, *value, *alloc_value=NULL;
struct variable *v;
+ int append = 0;
while (1)
{
value = p;
break;
case f_append:
+ /* If we have += but we're in a target variable context, defer the
+ append until the context expansion. */
+ if (target_var)
+ {
+ append = 1;
+ flavor = f_recursive;
+ value = p;
+ break;
+ }
+
/* An appending variable definition "var += value".
Extract the old value and append the new one. */
v = lookup_variable (expanded_name, strlen (expanded_name));
v = define_variable (expanded_name, strlen (expanded_name),
value, origin, flavor == f_recursive);
+ v->append = append;
+
if (alloc_value)
free (alloc_value);
free (expanded_name);
unsigned int recursive:1; /* Gets recursively re-evaluated. */
unsigned int expanding:1; /* Nonzero if currently being expanded. */
unsigned int per_target:1; /* Nonzero if a target-specific variable. */
+ unsigned int append:1; /* Nonzero if an appending target-specific
+ variable. */
enum variable_export
{
v_export, /* Export this variable. */
extern void print_file_variables PARAMS ((struct file *file));
extern void print_variable_set PARAMS ((struct variable_set *set, char *prefix));
extern void merge_variable_set_lists PARAMS ((struct variable_set_list **setlist0, struct variable_set_list *setlist1));
-extern struct variable *try_variable_definition PARAMS ((const struct floc *flocp, char *line, enum variable_origin origin));
+extern struct variable *try_variable_definition PARAMS ((const struct floc *flocp, char *line, enum variable_origin origin, int target_var));
extern struct variable *lookup_variable PARAMS ((char *name, unsigned int length));
extern struct variable *define_variable PARAMS ((char *name, unsigned int length, char *value,