cxx = g++
#cxx = /home/evanm/projects/src/llvm/Release+Asserts/bin/clang++
cflags = -g -Wall
+# needed for backtrace()
+ldflags = -g -rdynamic
# Here we declare a "rule" named "cxx", which knows how to compile
# C++ code. The variables indented below the rule are scoped to the
build @build.o: cxx build.cc
build @parsers.o: cxx parsers.cc
build @subprocess.o: cxx subprocess.cc
+build @util.o: cxx util.cc
build @ninja_jumble.o: cxx ninja_jumble.cc
-build @ninja.a: ar @build.o @parsers.o @subprocess.o @ninja_jumble.o
+build @ninja.a: ar @build.o @parsers.o @subprocess.o @util.o @ninja_jumble.o
build @ninja.o: cxx ninja.cc
build ninja: link @ninja.o @ninja.a
build @subprocess_test.o: cxx subprocess_test.cc
build ninja_test: link @build_test.o @ninja_test.o @parsers_test.o \
@subprocess_test.o @ninja.a
- ldflags = -lgtest -lgtest_main -lpthread
+ ldflags = -g -rdynamic -lgtest -lgtest_main -lpthread
# Generate a graph of the dependency tree (including the
#include <string.h>
#include <sys/wait.h>
+#include "util.h"
+
Subprocess::Stream::Stream() : fd_(-1) {}
Subprocess::Stream::~Stream() {
if (fd_ >= 0)
stream->buf_.append(buf, len);
} else {
if (len < 0)
- err_ = strerror(errno);
+ Fatal("read: %s", strerror(errno));
close(stream->fd_);
stream->fd_ = -1;
}
};
Stream stdout_, stderr_;
pid_t pid_;
- string err_;
};
// SubprocessSet runs a poll() loop around a set of Subprocesses.
--- /dev/null
+#include "util.h"
+
+#include <execinfo.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void DumpBacktrace(int skip_frames) {
+ void* stack[256];
+ int size = backtrace(stack, 256);
+ ++skip_frames; // Skip ourselves as well.
+ backtrace_symbols_fd(stack + skip_frames, size - skip_frames, 2);
+}
+
+void Fatal(const char* msg, ...) {
+ va_list ap;
+ fprintf(stderr, "FATAL: ");
+ va_start(ap, msg);
+ vfprintf(stderr, msg, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+ DumpBacktrace(1);
+ exit(1);
+}
--- /dev/null
+
+
+// Dump a backtrace to stderr.
+// |skip_frames| is how many frames to skip;
+// DumpBacktrace implicitly skips itself already.
+void DumpBacktrace(int skip_frames);
+
+// Log a fatal message, dump a backtrace, and exit.
+void Fatal(const char* msg, ...);