diff --git a/.gitignore b/.gitignore index 29b973fc47..6ea9a326f4 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ TAGS .*.swp .*~ *~ +/gtest-1.6.0 diff --git a/GNUmakefile b/GNUmakefile index e079ee3ab9..0c079157b4 100755 --- a/GNUmakefile +++ b/GNUmakefile @@ -92,7 +92,7 @@ help: ninja ./ninja -t targets clean: build.ninja - -$(RM) build/*.o ###XXX build.ninja + -$(RM) build/*.o build.ninja distclean: ###XXX clean find . \( -name '*~' -o -name '.*~' -o -name '*.pyc' \) -delete diff --git a/configure.py b/configure.py index 505f9b5863..553132c12d 100755 --- a/configure.py +++ b/configure.py @@ -411,7 +411,7 @@ def shell_escape(str): options.with_python, generator=True) n.build('build.ninja', 'configure', - implicit=['configure.py', 'misc/ninja_syntax.py']) + implicit=['configure.py', os.path.normpath('misc/ninja_syntax.py')]) n.newline() n.comment('Build only the main binary by default.') diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc index e7983be19e..4db0565f02 100644 --- a/doc/manual.asciidoc +++ b/doc/manual.asciidoc @@ -278,9 +278,9 @@ built for them. If used like +ninja -t clean -r _rules_+ it removes all files built using the given rules. + -depfiles are not removed. Files created but not referenced in the -graph are not removed. This tool takes in account the +-v+ and the -+-n+ options (note that +-n+ implies +-v+). +Files created but not referenced in the graph are not removed. This +tool takes in account the +-v+ and the +-n+ options (note that +-n+ +implies +-v+). diff --git a/misc/ninja_syntax.py b/misc/ninja_syntax.py index 3ecbcee25d..66babbe84f 100755 --- a/misc/ninja_syntax.py +++ b/misc/ninja_syntax.py @@ -10,8 +10,8 @@ import textwrap import re -def escape_spaces(word): - return word.replace('$ ','$$ ').replace(' ','$ ') +def escape_path(word): + return word.replace('$ ','$$ ').replace(' ','$ ').replace(':', '$:') class Writer(object): def __init__(self, output, width=78): @@ -53,15 +53,15 @@ def build(self, outputs, rule, inputs=None, implicit=None, order_only=None, variables=None): outputs = self._as_list(outputs) all_inputs = self._as_list(inputs)[:] - out_outputs = list(map(escape_spaces, outputs)) - all_inputs = list(map(escape_spaces, all_inputs)) + out_outputs = list(map(escape_path, outputs)) + all_inputs = list(map(escape_path, all_inputs)) if implicit: - implicit = map(escape_spaces, self._as_list(implicit)) + implicit = map(escape_path, self._as_list(implicit)) all_inputs.append('|') all_inputs.extend(implicit) if order_only: - order_only = map(escape_spaces, self._as_list(order_only)) + order_only = map(escape_path, self._as_list(order_only)) all_inputs.append('||') all_inputs.extend(order_only) diff --git a/src/build_log.cc b/src/build_log.cc index 1fec7ef8cd..a59b34f93e 100644 --- a/src/build_log.cc +++ b/src/build_log.cc @@ -229,6 +229,7 @@ bool BuildLog::Load(const string& path, string* err) { if (log_version < kOldestSupportedVersion) { *err = "unable to extract version from build log, perhaps due to " "being too old; you must clobber your build output and rebuild"; + fclose(file); return false; } } diff --git a/src/clean.h b/src/clean.h index 4d9b4e631c..5938dffb4e 100644 --- a/src/clean.h +++ b/src/clean.h @@ -14,7 +14,6 @@ #ifndef NINJA_CLEAN_H_ #define NINJA_CLEAN_H_ -#pragma once #include #include diff --git a/src/graph.cc b/src/graph.cc index 361f7befba..05498abc03 100644 --- a/src/graph.cc +++ b/src/graph.cc @@ -140,11 +140,14 @@ bool Edge::RecomputeOutputDirty(BuildLog* build_log, if (rule_->restat() && build_log && (entry = build_log->LookupByOutput(output->path()))) { if (entry->restat_mtime < most_recent_input) { - EXPLAIN("restat of output %s older than inputs", output->path().c_str()); + EXPLAIN("restat of output %s older than most recent input %s (0x%016" PRIx64 " vs 0x%016" PRIx64 ")", + output->path().c_str(), + most_recent_node ? most_recent_node->path().c_str() : "", + entry->restat_mtime, most_recent_input); return true; } } else { - EXPLAIN("output %s older than most recent input %s (%016" PRIx64 " vs %016" PRIx64 ")", + EXPLAIN("output %s older than most recent input %s (0x%016" PRIx64 " vs 0x%016" PRIx64 ")", output->path().c_str(), most_recent_node ? most_recent_node->path().c_str() : "", output->mtime(), most_recent_input); @@ -171,7 +174,7 @@ bool Edge::RecomputeOutputDirty(BuildLog* build_log, // FIXME: The FS time may not have ns resolution, so round to sec! ck if (((entry->restat_mtime / 10000000LL)) != ((most_recent_node->mtime() / 10000000LL))) { - EXPLAIN("generator: mtime %"PRIx64" != %"PRIx64" of file %s changed", + EXPLAIN("generator: mtime 0x%016"PRIx64" != 0x%016"PRIx64" of file %s changed", entry->restat_mtime, most_recent_node->mtime(), most_recent_node->path().c_str()); return true; @@ -355,7 +358,7 @@ bool Edge::is_phony() const { } void Node::Dump(const char* prefix) const { - printf("%s <%s 0x%p> mtime: %" PRIx64 "%s, (:%s), ", + printf("%s <%s 0x%p> mtime: 0x%016" PRIx64 "%s, (:%s), ", prefix, path().c_str(), this, mtime(), mtime()?"":" (:missing)", dirty()?" dirty":" clean"); diff --git a/src/lexer.cc b/src/lexer.cc index b3efe22c54..ca6f367f0a 100644 --- a/src/lexer.cc +++ b/src/lexer.cc @@ -127,7 +127,7 @@ Lexer::Token Lexer::ReadToken() { unsigned int yyaccept = 0; static const unsigned char yybm[] = { 0, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 0, 64, 64, 64, 64, 64, + 64, 64, 0, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 64, 64, 64, 64, 64, 64, 64, @@ -216,7 +216,8 @@ Lexer::Token Lexer::ReadToken() { yy4: yyaccept = 1; yych = *(q = ++p); - if (yych >= 0x01) goto yy60; + if (yych <= 0x00) goto yy5; + if (yych != '\r') goto yy60; yy5: { token = ERROR; break; } yy6: @@ -354,7 +355,9 @@ Lexer::Token Lexer::ReadToken() { if (yybm[0+yych] & 64) { goto yy59; } - if (yych >= 0x01) goto yy62; + if (yych <= 0x00) goto yy61; + if (yych <= '\f') goto yy62; +yy61: p = q; if (yyaccept <= 0) { goto yy3; @@ -576,7 +579,7 @@ bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) { unsigned char yych; static const unsigned char yybm[] = { 0, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 0, 128, 128, 128, 128, 128, + 128, 128, 0, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 16, 128, 128, 128, 0, 128, 128, 128, @@ -609,24 +612,25 @@ bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) { 128, 128, 128, 128, 128, 128, 128, 128, }; yych = *p; - if (yych <= '#') { + if (yych <= ' ') { if (yych <= '\n') { if (yych <= 0x00) goto yy96; if (yych >= '\n') goto yy92; } else { - if (yych == ' ') goto yy92; + if (yych == '\r') goto yy98; + if (yych >= ' ') goto yy92; } } else { - if (yych <= ':') { - if (yych <= '$') goto yy94; - if (yych >= ':') goto yy92; + if (yych <= '9') { + if (yych == '$') goto yy94; } else { + if (yych <= ':') goto yy92; if (yych == '|') goto yy92; } } ++p; yych = *p; - goto yy120; + goto yy121; yy91: { eval->AddText(StringPiece(start, p - start)); @@ -649,39 +653,40 @@ bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) { ++p; if ((yych = *p) <= '/') { if (yych <= ' ') { - if (yych == '\n') goto yy109; - if (yych <= 0x1F) goto yy98; - goto yy100; + if (yych == '\n') goto yy110; + if (yych <= 0x1F) goto yy99; + goto yy101; } else { if (yych <= '$') { - if (yych <= '#') goto yy98; - goto yy102; + if (yych <= '#') goto yy99; + goto yy103; } else { - if (yych == '-') goto yy104; - goto yy98; + if (yych == '-') goto yy105; + goto yy99; } } } else { if (yych <= '^') { if (yych <= ':') { - if (yych <= '9') goto yy104; - goto yy106; + if (yych <= '9') goto yy105; + goto yy107; } else { - if (yych <= '@') goto yy98; - if (yych <= 'Z') goto yy104; - goto yy98; + if (yych <= '@') goto yy99; + if (yych <= 'Z') goto yy105; + goto yy99; } } else { if (yych <= '`') { - if (yych <= '_') goto yy104; - goto yy98; + if (yych <= '_') goto yy105; + goto yy99; } else { - if (yych <= 'z') goto yy104; - if (yych <= '{') goto yy108; - goto yy98; + if (yych <= 'z') goto yy105; + if (yych <= '{') goto yy109; + goto yy99; } } } +yy95: { last_token_ = start; return Error("lexing error", err); @@ -693,83 +698,86 @@ bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) { return Error("unexpected EOF", err); } yy98: - ++p; + yych = *++p; + goto yy95; yy99: + ++p; +yy100: { last_token_ = start; return Error("bad $-escape (literal $ must be written as $$)", err); } -yy100: +yy101: ++p; { eval->AddText(StringPiece(" ", 1)); continue; } -yy102: +yy103: ++p; { eval->AddText(StringPiece("$", 1)); continue; } -yy104: +yy105: ++p; yych = *p; - goto yy118; -yy105: + goto yy119; +yy106: { eval->AddSpecial(StringPiece(start + 1, p - start - 1)); continue; } -yy106: +yy107: ++p; { eval->AddText(StringPiece(":", 1)); continue; } -yy108: +yy109: yych = *(q = ++p); if (yybm[0+yych] & 32) { - goto yy112; + goto yy113; } - goto yy99; -yy109: + goto yy100; +yy110: ++p; yych = *p; if (yybm[0+yych] & 16) { - goto yy109; + goto yy110; } { continue; } -yy112: +yy113: ++p; yych = *p; if (yybm[0+yych] & 32) { - goto yy112; + goto yy113; } - if (yych == '}') goto yy115; + if (yych == '}') goto yy116; p = q; - goto yy99; -yy115: + goto yy100; +yy116: ++p; { eval->AddSpecial(StringPiece(start + 2, p - start - 3)); continue; } -yy117: +yy118: ++p; yych = *p; -yy118: +yy119: if (yybm[0+yych] & 64) { - goto yy117; + goto yy118; } - goto yy105; -yy119: + goto yy106; +yy120: ++p; yych = *p; -yy120: +yy121: if (yybm[0+yych] & 128) { - goto yy119; + goto yy120; } goto yy91; } diff --git a/src/lexer.in.cc b/src/lexer.in.cc index e4789215ad..852d6e983b 100644 --- a/src/lexer.in.cc +++ b/src/lexer.in.cc @@ -130,7 +130,7 @@ Lexer::Token Lexer::ReadToken() { simple_varname = [a-zA-Z0-9_-]+; varname = [a-zA-Z0-9_.-]+; - [ ]*"#"[^\000\n]*"\n" { continue; } + [ ]*"#"[^\000\r\n]*"\n" { continue; } [ ]*[\n] { token = NEWLINE; break; } [ ]+ { token = INDENT; break; } "build" { token = BUILD; break; } @@ -200,7 +200,7 @@ bool Lexer::ReadEvalString(EvalString* eval, bool path, string* err) { for (;;) { start = p; /*!re2c - [^$ :\n|\000]+ { + [^$ :\r\n|\000]+ { eval->AddText(StringPiece(start, p - start)); continue; } diff --git a/src/manifest_parser_test.cc b/src/manifest_parser_test.cc index 9c6644c29e..3261d39e2f 100644 --- a/src/manifest_parser_test.cc +++ b/src/manifest_parser_test.cc @@ -682,3 +682,23 @@ TEST_F(ParserTest, UTF8) { " command = true\n" " description = compilaci\xC3\xB3\n")); } + +// We might want to eventually allow CRLF to be nice to Windows developers, +// but for now just verify we error out with a nice message. +TEST_F(ParserTest, CRLF) { + State state; + ManifestParser parser(&state, NULL); + string err; + + EXPECT_FALSE(parser.ParseTest("# comment with crlf\r\n", + &err)); + EXPECT_EQ("input:1: lexing error\n", + err); + + EXPECT_FALSE(parser.ParseTest("foo = foo\nbar = bar\r\n", + &err)); + EXPECT_EQ("input:2: lexing error\n" + "bar = bar\r\n" + " ^ near here", + err); +} diff --git a/src/state.h b/src/state.h index 23ca12b398..9197ef8199 100644 --- a/src/state.h +++ b/src/state.h @@ -14,7 +14,6 @@ #ifndef NINJA_STATE_H_ #define NINJA_STATE_H_ -#pragma once #include #include diff --git a/src/subprocess_test.cc b/src/subprocess_test.cc index c155012e8c..b7a99697d3 100644 --- a/src/subprocess_test.cc +++ b/src/subprocess_test.cc @@ -16,6 +16,13 @@ #include "test.h" +#ifndef _WIN32 +// SetWithLots need setrlimit. +#include +#include +#include +#endif + namespace { #ifdef _WIN32 @@ -142,7 +149,7 @@ TEST_F(SubprocessTest, SetWithMulti) { } } -#ifdef linux +#if !defined(_WIN32) && !defined(__APPLE__) TEST_F(SubprocessTest, SetWithLots) { // Arbitrary big number; needs to be over 1024 to confirm we're no longer // hostage to pselect. @@ -169,4 +176,4 @@ TEST_F(SubprocessTest, SetWithLots) { } ASSERT_EQ(kNumProcs, subprocs_.finished_.size()); } -#endif // linux +#endif // _WIN32 || __APPLE__ diff --git a/src/util.h b/src/util.h index 65ce094649..6858c03781 100644 --- a/src/util.h +++ b/src/util.h @@ -14,7 +14,6 @@ #ifndef NINJA_UTIL_H_ #define NINJA_UTIL_H_ -#pragma once #ifdef _WIN32 #include "win32port.h" diff --git a/src/version.h b/src/version.h index 09dca53ebd..d47658c37b 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -const char* kVersion = "## develop-b33ff36"; +const char* kVersion = "## develop-69e055c"; diff --git a/src/win32port.h b/src/win32port.h index 5a02ed953c..4c25e12324 100644 --- a/src/win32port.h +++ b/src/win32port.h @@ -14,8 +14,9 @@ #ifndef NINJA_WIN32PORT_H_ #define NINJA_WIN32PORT_H_ -#pragma once +typedef signed short int16_t; +typedef unsigned short uint16_t; /// A 64-bit integer type typedef signed long long int64_t; typedef unsigned long long uint64_t;