summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2013-09-21 17:24:59 -0400
committerPaul Smith <psmith@gnu.org>2013-09-21 17:24:59 -0400
commit6c3e88e60f2c7d2bff3aa1967afcc59f27626c48 (patch)
tree2f5d702aa25de4f1815eed3f57b8b43cbf0dca35
parent9cd01958da86a68d0e47defcb9745ab373ef3d79 (diff)
downloadgunmake-6c3e88e60f2c7d2bff3aa1967afcc59f27626c48.tar.gz
Ensure that output generated while reading makefiles is synced.
-rw-r--r--ChangeLog10
-rw-r--r--main.c47
-rw-r--r--output.h2
-rw-r--r--tests/ChangeLog5
-rw-r--r--tests/scripts/features/output-sync60
5 files changed, 122 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index f4a897e..cc9ed4e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2013-09-21 Paul Smith <psmith@gnu.org>
+ Output generated while reading makefiles should be synced.
+
+ * main.c (make_sync): Define a context for syncing while reading
+ makefiles and other top-level operations.
+ (main): If we request syncing, enable it while we are parsing
+ options, reading makefiles, etc. to capture that output. Just
+ before we start to run rules, dump the output if any.
+ (die): Dump any output we've been syncing before we die
+ * output.h (OUTPUT_SET): Disable output_context if not syncout.
+
Stderr generated from shell functions in recipes should be synced.
* job.h (FD_STDIN, FD_STDOUT, FD_STDERR): Create new macros to
diff --git a/main.c b/main.c
index bd8b478..f0a7174 100644
--- a/main.c
+++ b/main.c
@@ -550,6 +550,11 @@ int clock_skew_detected;
#endif
unsigned short stopchar_map[UCHAR_MAX + 1] = {0};
+/* If output-sync is enabled we'll collect all the output generated due to
+ options, while reading makefiles, etc. */
+
+struct output make_sync;
+
/* Mask of signals that are being caught with fatal_error_signal. */
@@ -1041,6 +1046,7 @@ main (int argc, char **argv, char **envp)
struct dep *read_files;
PATH_VAR (current_directory);
unsigned int restarts = 0;
+ unsigned int syncing = 0;
#ifdef WINDOWS32
char *unix_path = NULL;
char *windows32_path = NULL;
@@ -1052,6 +1058,8 @@ main (int argc, char **argv, char **envp)
no_default_sh_exe = 1;
#endif
+ output_init (&make_sync);
+
initialize_stopchar_map();
#ifdef SET_STACK_SIZE
@@ -1390,6 +1398,13 @@ main (int argc, char **argv, char **envp)
decode_env_switches (STRING_SIZE_TUPLE ("GNUMAKEFLAGS"));
decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS"));
+ /* In output sync mode we need to sync any output generated by reading the
+ makefiles, such as in $(info ...) or stderr from $(shell ...) etc. */
+
+ syncing = make_sync.syncout = (output_sync == OUTPUT_SYNC_LINE
+ || output_sync == OUTPUT_SYNC_TARGET);
+ OUTPUT_SET (&make_sync);
+
#if 0
/* People write things like:
MFLAGS="CC=gcc -pipe" "CFLAGS=-g"
@@ -1399,6 +1414,16 @@ main (int argc, char **argv, char **envp)
decode_switches (argc, argv, 0);
+ /* Reset in case the switches changed our minds. */
+ syncing = (output_sync == OUTPUT_SYNC_LINE
+ || output_sync == OUTPUT_SYNC_TARGET);
+
+ if (make_sync.syncout && ! syncing)
+ output_close (&make_sync);
+
+ make_sync.syncout = syncing;
+ OUTPUT_SET (&make_sync);
+
/* Figure out the level of recursion. */
{
struct variable *v = lookup_variable (STRING_SIZE_TUPLE (MAKELEVEL_NAME));
@@ -1907,6 +1932,16 @@ main (int argc, char **argv, char **envp)
decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS"));
#endif
+ /* Reset in case the switches changed our minds. */
+ syncing = (output_sync == OUTPUT_SYNC_LINE
+ || output_sync == OUTPUT_SYNC_TARGET);
+
+ if (make_sync.syncout && ! syncing)
+ output_close (&make_sync);
+
+ make_sync.syncout = syncing;
+ OUTPUT_SET (&make_sync);
+
/* If we've disabled builtin rules, get rid of them. */
if (no_builtin_rules_flag && ! old_builtin_rules_flag)
{
@@ -2077,6 +2112,11 @@ main (int argc, char **argv, char **envp)
/* Initialize the remote job module. */
remote_setup ();
+ /* Dump any output we've collected. */
+
+ OUTPUT_UNSET ();
+ output_close (&make_sync);
+
if (read_files != 0)
{
/* Update any makefiles if necessary. */
@@ -3358,6 +3398,13 @@ die (int status)
clean_jobserver (status);
+ if (output_context)
+ {
+ assert (output_context == &make_sync);
+ OUTPUT_UNSET ();
+ output_close (&make_sync);
+ }
+
output_close (NULL);
/* Try to move back to the original directory. This is essential on
diff --git a/output.h b/output.h
index 1f0e2d7..5fef436 100644
--- a/output.h
+++ b/output.h
@@ -24,7 +24,7 @@ struct output
extern struct output *output_context;
extern unsigned int stdio_traced;
-#define OUTPUT_SET(_new) do{ if ((_new)->syncout) output_context = (_new); }while(0)
+#define OUTPUT_SET(_new) do{ output_context = (_new)->syncout ? (_new) : NULL; }while(0)
#define OUTPUT_UNSET() do{ output_context = NULL; }while(0)
#define OUTPUT_TRACED() do{ stdio_traced = 1; }while(0)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index e0e9475..cbcaa03 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,7 +1,10 @@
2013-09-21 Paul Smith <psmith@gnu.org>
* scripts/features/output-sync: Test shell functions writing to
- stderr in recipes: ensure it's captured via output-sync.
+ stderr in recipes: ensure it's captured via output-sync. Test
+ output generated while reading makefiles and make sure it's
+ captured via output-sync. Make sure that fatal errors dump the
+ output so it's not lost.
* scripts/options/dash-w: Add a test for -w flag.
diff --git a/tests/scripts/features/output-sync b/tests/scripts/features/output-sync
index e09505f..3bb9997 100644
--- a/tests/scripts/features/output-sync
+++ b/tests/scripts/features/output-sync
@@ -267,5 +267,65 @@ all: ; @: $(shell echo foo 1>&2)
!,
'-w -Oline', "#MAKE#: Entering directory '#PWD#'\nfoo\n#MAKE#: Leaving directory '#PWD#'\n");
+# Ensure that output generated while parsing makefiles is synced
+# when appropriate.
+run_make_test(q!
+$(shell echo foo 1>&2)
+all: ; echo bar
+!,
+ '-s -w -Otarget', "#MAKE#: Entering directory '#PWD#'\nfoo\n#MAKE#: Leaving directory '#PWD#'\n#MAKE#: Entering directory '#PWD#'\nbar\n#MAKE#: Leaving directory '#PWD#'\n");
+
+# Test recursion
+$m1 = get_tmpfile();
+$m2 = get_tmpfile();
+
+open(M1, "> $m1");
+print M1 <<'EOF';
+$(shell echo d1 stderr 1>&2)
+$(info d1 stdout)
+all:; @:
+EOF
+close(M1);
+
+open(M2, "> $m2");
+print M2 <<'EOF';
+$(shell echo d2 stderr 1>&2)
+$(info d2 stdout)
+all:; @:
+# Force an ordering on the output
+$(shell sleep 1)
+EOF
+close(M2);
+
+run_make_test(qq!
+all: t1 t2
+t1: ; \@\$(MAKE) -f $m1
+t2: ; \@\$(MAKE) -f $m2
+!,
+ "-j -Oline", "#MAKE#[1]: Entering directory '#PWD#'\nd1 stderr\nd1 stdout\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKE#[1]: Entering directory '#PWD#'\nd2 stderr\nd2 stdout\n#MAKE#[1]: Leaving directory '#PWD#'\n");
+
+rmfiles($m1, $m2);
+
+# Ensure that output generated while parsing makefiles is synced
+# when appropriate.
+$m1 = get_tmpfile();
+
+open(M1, "> $m1");
+print M1 <<'EOF';
+$(shell echo d1 stderr 1>&2)
+$(info d1 stdout)
+$(error d1 failed)
+all:; @:
+EOF
+close(M1);
+
+run_make_test(qq!
+all: t1
+t1: ; -\@\$(MAKE) -f $m1
+!,
+ "-j -Oline", "#MAKE#[1]: Entering directory '#PWD#'\nd1 stderr\nd1 stdout\n$m1:3: *** d1 failed. Stop.\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKEFILE#:3: recipe for target 't1' failed\n#MAKE#: [t1] Error 2 (ignored)\n");
+
+rmfiles($m1);
+
# This tells the test driver that the perl test script executed properly.
1;