/* Authorization for the jobserver. */
-static char *jobserver_auth = NULL;
+char *jobserver_auth = NULL;
/* Shuffle mode for goals and prerequisites. */
/* Handle for the mutex used on Windows to synchronize output of our
children under -O. */
-char *sync_mutex = NULL;
+static char *sync_mutex = NULL;
/* Maximum load average at which multiple jobs will be run.
Negative values mean unlimited, while zero means limit to
/* These are long-style options. */
{ CHAR_MAX+1, strlist, &db_flags, 1, 1, 0, "basic", 0, "debug" },
- { CHAR_MAX+2, string, &jobserver_auth, 1, 1, 0, 0, 0, "jobserver-auth" },
+ { CHAR_MAX+2, string, &jobserver_auth, 1, 1, 0, 0, 0, JOBSERVER_AUTH_OPT },
{ CHAR_MAX+3, flag, &trace_flag, 1, 1, 0, 0, 0, "trace" },
{ CHAR_MAX+4, flag_off, &print_directory_flag, 1, 1, 0, 0,
&default_print_directory_flag, "no-print-directory" },
#include "job.h"
#include "commands.h"
#include "variable.h"
+#include "os.h"
#include "rule.h"
#ifdef WINDOWS32
#include "pathstuff.h"
{
static unsigned long last_changenum = 0;
-
/* This one actually turns out to be very hard, due to the way the parser
records targets. The way it works is that target information is collected
internally until make knows the target is completely specified. Only when
/* Create a new environment for FILE's commands.
If FILE is nil, this is for the 'shell' function.
- The child's MAKELEVEL variable is incremented. */
+ The child's MAKELEVEL variable is incremented.
+ If recursive is true then we're running a recursive make, else not. */
char **
-target_environment (struct file *file)
+target_environment (struct file *file, int recursive)
{
struct variable_set_list *set_list;
struct variable_set_list *s;
struct hash_table table;
struct variable **v_slot;
struct variable **v_end;
- struct variable makelevel_key;
char **result_0;
char **result;
+ const char *invalid = NULL;
/* If we got no value from the environment then never add the default. */
int added_SHELL = shell_var.value == 0;
+ int found_makelevel = 0;
+ int found_mflags = 0;
+ int found_makeflags = 0;
+
+ /* We need to update makeflags if (a) we're not recurive, (b) jobserver_auth
+ is enabled, and (c) we need to add invalidation. */
+ if (!recursive && jobserver_auth)
+ invalid = jobserver_get_invalid_auth ();
if (file == 0)
set_list = current_variable_set_list;
hash_insert_at (&table, v, evslot);
}
else if ((*evslot)->export == v_default)
- {
- /* We already have a variable but we don't know its status. */
- (*evslot)->export = v->export;
- }
+ /* We already have a variable but we don't know its status. */
+ (*evslot)->export = v->export;
}
}
- makelevel_key.name = (char *)MAKELEVEL_NAME;
- makelevel_key.length = MAKELEVEL_LENGTH;
- hash_delete (&table, &makelevel_key);
-
result = result_0 = xmalloc ((table.ht_fill + 3) * sizeof (char *));
v_slot = (struct variable **) table.ht_vec;
if (! HASH_VACANT (*v_slot))
{
struct variable *v = *v_slot;
+ char *value = v->value;
+ char *cp = NULL;
/* This might be here because it was a target-specific variable that
we didn't know the status of when we added it. */
if (! should_export (v))
continue;
- /* If this is the SHELL variable remember we already added it. */
- if (!added_SHELL && streq (v->name, "SHELL"))
- added_SHELL = 1;
-
/* If V is recursively expanded and didn't come from the environment,
expand its value. If it came from the environment, it should
go back into the environment unchanged. */
/* If V is being recursively expanded and this is for a shell
function, just skip it. */
if (v->expanding && file == NULL)
- DB (DB_VERBOSE, (_("%s:%lu: Skipping export of %s to shell function due to recursive expansion"),
- v->fileinfo.filenm, v->fileinfo.lineno, v->name));
- else
{
- char *value = recursively_expand_for_file (v, file);
-#ifdef WINDOWS32
- if (strcmp (v->name, "Path") == 0 ||
- strcmp (v->name, "PATH") == 0)
- convert_Path_to_windows32 (value, ';');
-#endif
- *result++ = xstrdup (concat (3, v->name, "=", value));
- free (value);
+ DB (DB_VERBOSE, (_("%s:%lu: Skipping export of %s to shell function due to recursive expansion"),
+ v->fileinfo.filenm, v->fileinfo.lineno, v->name));
+ continue;
}
+
+ value = cp = recursively_expand_for_file (v, file);
}
- else
+
+ /* If this is the SHELL variable remember we already added it. */
+ if (!added_SHELL && streq (v->name, "SHELL"))
+ {
+ added_SHELL = 1;
+ goto setit;
+ }
+
+ /* If this is MAKELEVEL, update it. */
+ if (!found_makelevel && streq (v->name, MAKELEVEL_NAME))
+ {
+ char val[INTSTR_LENGTH + 1];
+ sprintf (val, "%u", makelevel + 1);
+ free (cp);
+ value = cp = xstrdup (val);
+ found_makelevel = 1;
+ goto setit;
+ }
+
+ /* If we need to reset jobserver, check for MAKEFLAGS / MFLAGS. */
+ if (invalid)
{
+ if (!found_makeflags && streq (v->name, MAKEFLAGS_NAME))
+ {
+ char *mf;
+ char *vars;
+ found_makeflags = 1;
+
+ if (!strstr (value, " --" JOBSERVER_AUTH_OPT "="))
+ goto setit;
+
+ /* The invalid option must come before variable overrides. */
+ vars = strstr (value, " -- ");
+ if (!vars)
+ mf = xstrdup (concat (2, value, invalid));
+ else
+ {
+ size_t lf = vars - value;
+ size_t li = strlen (invalid);
+ mf = xmalloc (strlen (value) + li + 1);
+ strcpy (mempcpy (mempcpy (mf, value, lf), invalid, li),
+ vars);
+ }
+ free (cp);
+ value = cp = mf;
+ if (found_mflags)
+ invalid = NULL;
+ goto setit;
+ }
+
+ if (!found_mflags && streq (v->name, "MFLAGS"))
+ {
+ const char *mf;
+ found_mflags = 1;
+
+ if (!strstr (value, " --" JOBSERVER_AUTH_OPT "="))
+ goto setit;
+
+ if (v->origin != o_env)
+ goto setit;
+ mf = concat (2, value, invalid);
+ free (cp);
+ value = cp = xstrdup (mf);
+ if (found_makeflags)
+ invalid = NULL;
+ goto setit;
+ }
+ }
+
#ifdef WINDOWS32
- if (strcmp (v->name, "Path") == 0 ||
- strcmp (v->name, "PATH") == 0)
- convert_Path_to_windows32 (v->value, ';');
-#endif
- *result++ = xstrdup (concat (3, v->name, "=", v->value));
+ if (streq (v->name, "Path") || streq (v->name, "PATH"))
+ {
+ if (!cp)
+ cp = xstrdup (value);
+ value = convert_Path_to_windows32 (cp, ';');
+ goto setit;
}
+#endif
+
+ setit:
+ *result++ = xstrdup (concat (3, v->name, "=", value));
+ free (cp);
}
if (!added_SHELL)
*result++ = xstrdup (concat (3, shell_var.name, "=", shell_var.value));
- *result = xmalloc (100);
- sprintf (*result, "%s=%u", MAKELEVEL_NAME, makelevel + 1);
- *++result = 0;
+ if (!found_makelevel)
+ {
+ char val[MAKELEVEL_LENGTH + 1 + INTSTR_LENGTH + 1];
+ sprintf (val, "%s=%u", MAKELEVEL_NAME, makelevel + 1);
+ *result++ = xstrdup (val);
+ }
+
+ *result = NULL;
hash_free (&table, 0);
# Normal flags aren't prefixed with "-"
run_make_test(q!
-all: ; @echo $(MAKEFLAGS)
+all: ; @echo /$(MAKEFLAGS)/
!,
- '-e -r -R', 'erR');
+ '-e -r -R', '/erR/');
# Long arguments mean everything is prefixed with "-"
run_make_test(q!
-all: ; @echo $(MAKEFLAGS)
+all: ; @echo /$(MAKEFLAGS)/
!,
'--no-print-directory -e -r -R --trace', "#MAKEFILE#:2: update target 'all' due to: target does not exist
-echo erR --trace --no-print-directory
-erR --trace --no-print-directory");
+echo /erR --trace --no-print-directory/
+/erR --trace --no-print-directory/");
# Recursive invocations of make should accumulate MAKEFLAGS values.
'-Onone -l2.5 -l2.5 -Onone -I/tmp -iknqrs -i -n -s -k -I/tmp',
"makeflags='iknqrsw -I/tmp -I/tmp -Onone -Onone -l2.5 -l2.5 --no-print-directory'");
+# Verify that command line arguments are included in MAKEFLAGS
+run_make_test(q!
+all: ; @echo $(MAKEFLAGS)
+!,
+ '-e FOO=bar -r -R', 'erR -- FOO=bar');
+
+# Long arguments mean everything is prefixed with "-"
+run_make_test(q!
+all: ; @echo /$(MAKEFLAGS)/
+!,
+ '--no-print-directory -e -r -R --trace FOO=bar',
+ "#MAKEFILE#:2: update target 'all' due to: target does not exist
+echo /erR --trace --no-print-directory -- FOO=bar/
+/erR --trace --no-print-directory -- FOO=bar/");
+
+
1;