Merge pull request #1719 from jhasse/cmake-static-msvc

CMake: Use static MSVC runtime, fixes #1692
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..be1fc02
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,34 @@
+# How to successfully make changes to Ninja
+
+We're very wary of changes that increase the complexity of Ninja (in particular,
+new build file syntax or command-line flags) or increase the maintenance burden
+of Ninja. Ninja is already successfully used by hundreds of developers for large
+projects and it already achieves (most of) the goals we set out for it to do.
+It's probably best to discuss new feature ideas on the
+[mailing list](https://groups.google.com/forum/#!forum/ninja-build) or in an
+issue before creating a PR.
+
+## Coding guidelines
+
+Generally it's the
+[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) with
+a few additions:
+
+* Any code merged into the Ninja codebase which will be part of the main
+  executable must compile as C++03. You may use C++11 features in a test or an
+  unimportant tool if you guard your code with `#if __cplusplus >= 201103L`.
+* We have used `using namespace std;` a lot in the past. For new contributions,
+  please try to avoid relying on it and instead whenever possible use `std::`.
+  However, please do not change existing code simply to add `std::` unless your
+  contribution already needs to change that line of code anyway.
+* All source files should have the Google Inc. license header.
+* Use `///` for [Doxygen](http://www.doxygen.nl/) (use `\a` to refer to
+  arguments).
+* It's not necessary to document each argument, especially when they're
+  relatively self-evident (e.g. in
+  `CanonicalizePath(string* path, string* err)`, the arguments are hopefully
+  obvious).
+
+If you're unsure about code formatting, please use
+[clang-format](https://clang.llvm.org/docs/ClangFormat.html). However, please do
+not format code that is not otherwise part of your contribution.
diff --git a/HACKING.md b/HACKING.md
deleted file mode 100644
index bd6fec7..0000000
--- a/HACKING.md
+++ /dev/null
@@ -1,252 +0,0 @@
-## Basic overview
-
-`./configure.py` generates the `build.ninja` files used to build
-ninja.  It accepts various flags to adjust build parameters.
-Run './configure.py --help' for more configuration options.
-
-The primary build target of interest is `ninja`, but when hacking on
-Ninja your changes should be testable so it's more useful to build and
-run `ninja_test` when developing.
-
-### Bootstrapping
-
-Ninja is built using itself.  To bootstrap the first binary, run the
-configure script as `./configure.py --bootstrap`.  This first compiles
-all non-test source files together, then re-builds Ninja using itself.
-You should end up with a `ninja` binary (or `ninja.exe`) in the project root.
-
-#### Windows
-
-On Windows, you'll need to install Python to run `configure.py`, and
-run everything under a Visual Studio Tools Command Prompt (or after
-running `vcvarsall` in a normal command prompt).
-
-For other combinations such as gcc/clang you will need the compiler
-(gcc/cl) in your PATH and you will have to set the appropriate
-platform configuration script.
-
-See below if you want to use mingw or some other compiler instead of
-Visual Studio.
-
-##### Using Visual Studio
-Assuming that you now have Python installed, then the steps for building under
-Windows using Visual Studio are:
-
-Clone and checkout the latest release (or whatever branch you want). You
-can do this in either a command prompt or by opening a git bash prompt:
-
-```
-    $ git clone git://github.com/ninja-build/ninja.git && cd ninja
-    $ git checkout release
-```
-
-Then:
-
-1. Open a Windows command prompt in the folder where you checked out ninja.
-2. Select the Microsoft build environment by running
-`vcvarsall.bat` with the appropriate environment.
-3. Build ninja and test it.
-
-The steps for a Visual Studio 2015 64-bit build are outlined here:
-
-```
-    > "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
-    > python configure.py --bootstrap
-    > ninja --help
-```
-Copy the ninja executable to another location, if desired, e.g. C:\local\Ninja.
-
-Finally add the path where ninja.exe is to the PATH variable.
-
-### Adjusting build flags
-
-Build in "debug" mode while developing (disables optimizations and builds
-way faster on Windows):
-
-    ./configure.py --debug
-
-To use clang, set `CXX`:
-
-    CXX=clang++ ./configure.py
-
-## How to successfully make changes to Ninja
-
-Github pull requests are convenient for me to merge (I can just click
-a button and it's all handled server-side), but I'm also comfortable
-accepting pre-github git patches (via `send-email` etc.).
-
-Good pull requests have all of these attributes:
-
-* Are scoped to one specific issue
-* Include a test to demonstrate their correctness
-* Update the docs where relevant
-* Match the Ninja coding style (see below)
-* Don't include a mess of "oops, fix typo" commits
-
-These are typically merged without hesitation.  If a change is lacking
-any of the above I usually will ask you to fix it, though there are
-obvious exceptions (fixing typos in comments don't need tests).
-
-I am very wary of changes that increase the complexity of Ninja (in
-particular, new build file syntax or command-line flags) or increase
-the maintenance burden of Ninja.  Ninja is already successfully used
-by hundreds of developers for large projects and it already achieves
-(most of) the goals I set out for it to do.  It's probably best to
-discuss new feature ideas on the [mailing list](https://groups.google.com/forum/#!forum/ninja-build)
-before I shoot down your patch.
-
-## Testing
-
-### Test-driven development
-
-Set your build command to
-
-    ./ninja ninja_test && ./ninja_test --gtest_filter=MyTest.Name
-
-now you can repeatedly run that while developing until the tests pass
-(I frequently set it as my compilation command in Emacs).  Remember to
-build "all" before committing to verify the other source still works!
-
-## Testing performance impact of changes
-
-If you have a Chrome build handy, it's a good test case.  There's a
-script at `misc/measure.py` that repeatedly runs a command (to address
-variance) and summarizes its runtime.  E.g.
-
-    path/to/misc/measure.py path/to/my/ninja chrome
-
-For changing the depfile parser, you can also build `parser_perftest`
-and run that directly on some representative input files.
-
-## Coding guidelines
-
-Generally it's the [Google C++ coding style][], but in brief:
-
-* Function name are camelcase.
-* Member methods are camelcase, except for trivial getters which are
-  underscore separated.
-* Local variables are underscore separated.
-* Member variables are underscore separated and suffixed by an extra
-  underscore.
-* Two spaces indentation.
-* Opening braces is at the end of line.
-* Lines are 80 columns maximum.
-* All source files should have the Google Inc. license header.
-
-[Google C++ coding style]: https://google.github.io/styleguide/cppguide.html
-
-## Documentation
-
-### Style guidelines
-
-* Use `///` for doxygen.
-* Use `\a` to refer to arguments.
-* It's not necessary to document each argument, especially when they're
-  relatively self-evident (e.g. in `CanonicalizePath(string* path, string* err)`,
-  the arguments are hopefully obvious)
-
-### Building the manual
-
-    sudo apt-get install asciidoc --no-install-recommends
-    ./ninja manual
-
-### Building the code documentation
-
-    sudo apt-get install doxygen
-    ./ninja doxygen
-
-## Building for Windows
-
-While developing, it's helpful to copy `ninja.exe` to another name like
-`n.exe`; otherwise, rebuilds will be unable to write `ninja.exe` because
-it's locked while in use.
-
-### Via Visual Studio
-
-* Install Visual Studio (Express is fine), [Python for Windows][],
-  and (if making changes) googletest (see above instructions)
-* In a Visual Studio command prompt: `python configure.py --bootstrap`
-
-[Python for Windows]: http://www.python.org/getit/windows/
-
-### Via mingw on Windows (not well supported)
-
-* Install mingw, msys, and python
-* In the mingw shell, put Python in your path, and
-  `python configure.py --bootstrap`
-* To reconfigure, run `python configure.py`
-* Remember to strip the resulting executable if size matters to you
-
-### Via mingw on Linux (not well supported)
-
-Setup on Ubuntu Lucid:
-* `sudo apt-get install gcc-mingw32 wine`
-* `export CC=i586-mingw32msvc-cc CXX=i586-mingw32msvc-c++ AR=i586-mingw32msvc-ar`
-
-Setup on Ubuntu Precise:
-* `sudo apt-get install gcc-mingw-w64-i686 g++-mingw-w64-i686 wine`
-* `export CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ AR=i686-w64-mingw32-ar`
-
-Setup on Arch:
-* Uncomment the `[multilib]` section of `/etc/pacman.conf` and `sudo pacman -Sy`.
-* `sudo pacman -S mingw-w64-gcc wine`
-* `export CC=x86_64-w64-mingw32-cc CXX=x86_64-w64-mingw32-c++ AR=x86_64-w64-mingw32-ar`
-* `export CFLAGS=-I/usr/x86_64-w64-mingw32/include`
-
-Then run:
-* `./configure.py --platform=mingw --host=linux`
-* Build `ninja.exe` using a Linux ninja binary: `/path/to/linux/ninja`
-* Run: `./ninja.exe`  (implicitly runs through wine(!))
-
-### Using Microsoft compilers on Linux (extremely flaky)
-
-The trick is to install just the compilers, and not all of Visual Studio,
-by following [these instructions][win7sdk].
-
-[win7sdk]: http://www.kegel.com/wine/cl-howto-win7sdk.html
-
-### Using gcov
-
-Do a clean debug build with the right flags:
-
-    CFLAGS=-coverage LDFLAGS=-coverage ./configure.py --debug
-    ninja -t clean ninja_test && ninja ninja_test
-
-Run the test binary to generate `.gcda` and `.gcno` files in the build
-directory, then run gcov on the .o files to generate `.gcov` files in the
-root directory:
-
-    ./ninja_test
-    gcov build/*.o
-
-Look at the generated `.gcov` files directly, or use your favorite gcov viewer.
-
-### Using afl-fuzz
-
-Build with afl-clang++:
-
-    CXX=path/to/afl-1.20b/afl-clang++ ./configure.py
-    ninja
-
-Then run afl-fuzz like so:
-
-    afl-fuzz -i misc/afl-fuzz -o /tmp/afl-fuzz-out ./ninja -n -f @@
-
-You can pass `-x misc/afl-fuzz-tokens` to use the token dictionary. In my
-testing, that did not seem more effective though.
-
-#### Using afl-fuzz with asan
-
-If you want to use asan (the `isysroot` bit is only needed on OS X; if clang
-can't find C++ standard headers make sure your LLVM checkout includes a libc++
-checkout and has libc++ installed in the build directory):
-
-    CFLAGS="-fsanitize=address -isysroot $(xcrun -show-sdk-path)" \
-        LDFLAGS=-fsanitize=address CXX=path/to/afl-1.20b/afl-clang++ \
-        ./configure.py
-    AFL_CXX=path/to/clang++ ninja
-
-Make sure ninja can find the asan runtime:
-
-    DYLD_LIBRARY_PATH=path/to//lib/clang/3.7.0/lib/darwin/ \
-        afl-fuzz -i misc/afl-fuzz -o /tmp/afl-fuzz-out ./ninja -n -f @@
diff --git a/README b/README
deleted file mode 100644
index a1535ff..0000000
--- a/README
+++ /dev/null
@@ -1,21 +0,0 @@
-Ninja is a small build system with a focus on speed.
-https://ninja-build.org/
-
-See the manual -- https://ninja-build.org/manual.html or
-doc/manual.asciidoc included in the distribution -- for background
-and more details.
-
-Binaries for Linux, Mac, and Windows are available at
-  https://github.com/ninja-build/ninja/releases
-Run './ninja -h' for Ninja help.
-
-To build your own binary, on many platforms it should be sufficient to
-just run `./configure.py --bootstrap`; for more details see HACKING.md.
-(Also read that before making changes to Ninja, as it has advice.)
-
-Installation is not necessary because the only required file is the
-resulting ninja binary. However, to enable features like Bash
-completion and Emacs and Vim editing modes, some files in misc/ must be
-copied to appropriate locations.
-
-If you're interested in making changes to Ninja, read HACKING.md first.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3326f81
--- /dev/null
+++ b/README.md
@@ -0,0 +1,50 @@
+# Ninja
+
+Ninja is a small build system with a focus on speed.
+https://ninja-build.org/
+
+See [the manual](https://ninja-build.org/manual.html) or
+`doc/manual.asciidoc` included in the distribution for background
+and more details.
+
+Binaries for Linux, Mac, and Windows are available at
+  [GitHub](https://github.com/ninja-build/ninja/releases).
+Run `./ninja -h` for Ninja help.
+
+Installation is not necessary because the only required file is the
+resulting ninja binary. However, to enable features like Bash
+completion and Emacs and Vim editing modes, some files in misc/ must be
+copied to appropriate locations.
+
+If you're interested in making changes to Ninja, read CONTRIBUTING.md first.
+
+## Building Ninja itself
+
+You can either build Ninja via the custom generator script written in Python or
+via CMake. For more details see
+[the wiki](https://github.com/ninja-build/ninja/wiki).
+
+### Python
+
+```
+./configure.py --bootstrap
+```
+
+This will generate the `ninja` binary and a `build.ninja` file you can now use
+to built Ninja with itself.
+
+### CMake
+
+```
+cmake -Bbuild-cmake -H.
+cmake --build build-cmake
+```
+
+The `ninja` binary will now be inside the `build-cmake` directory (you can
+choose any other name you like).
+
+To run the unit tests:
+
+```
+./build-cmake/ninja_test
+```
diff --git a/RELEASING b/RELEASING
index da4dbdd..0b03341 100644
--- a/RELEASING
+++ b/RELEASING
@@ -1,7 +1,7 @@
 Notes to myself on all the steps to make for a Ninja release.
 
 Push new release branch:
-1. Run afl-fuzz for a day or so (see HACKING.md) and run ninja_test
+1. Run afl-fuzz for a day or so and run ninja_test
 2. Consider sending a heads-up to the ninja-build mailing list first
 3. Make sure branches 'master' and 'release' are synced up locally
 4. Update src/version.cc with new version (with ".git"), then
diff --git a/src/build_log.cc b/src/build_log.cc
index e2a9344..98543b6 100644
--- a/src/build_log.cc
+++ b/src/build_log.cc
@@ -422,6 +422,7 @@
 
 bool BuildLog::Restat(const StringPiece path,
                       const DiskInterface& disk_interface,
+                      const int output_count, char** outputs,
                       std::string* const err) {
   METRIC_RECORD(".ninja_log restat");
 
@@ -439,12 +440,21 @@
     return false;
   }
   for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) {
-    const TimeStamp mtime = disk_interface.Stat(i->second->output, err);
-    if (mtime == -1) {
-      fclose(f);
-      return false;
+    bool skip = output_count > 0;
+    for (int j = 0; j < output_count; ++j) {
+      if (i->second->output == outputs[j]) {
+        skip = false;
+        break;
+      }
     }
-    i->second->mtime = mtime;
+    if (!skip) {
+      const TimeStamp mtime = disk_interface.Stat(i->second->output, err);
+      if (mtime == -1) {
+        fclose(f);
+        return false;
+      }
+      i->second->mtime = mtime;
+    }
 
     if (!WriteEntry(f, *i->second)) {
       *err = strerror(errno);
diff --git a/src/build_log.h b/src/build_log.h
index ed59d79..ebe0530 100644
--- a/src/build_log.h
+++ b/src/build_log.h
@@ -85,7 +85,7 @@
 
   /// Restat all outputs in the log
   bool Restat(StringPiece path, const DiskInterface& disk_interface,
-              std::string* err);
+              int output_count, char** outputs, std::string* err);
 
   typedef ExternalStringHashMap<LogEntry*>::Type Entries;
   const Entries& entries() const { return entries_; }
diff --git a/src/build_log_test.cc b/src/build_log_test.cc
index 48ece23..a8b1733 100644
--- a/src/build_log_test.cc
+++ b/src/build_log_test.cc
@@ -252,7 +252,14 @@
   ASSERT_EQ(3, e->mtime);
 
   TestDiskInterface testDiskInterface;
-  EXPECT_TRUE(log.Restat(kTestFilename, testDiskInterface, &err));
+  char out2[] = { 'o', 'u', 't', '2' };
+  char* filter2[] = { out2 };
+  EXPECT_TRUE(log.Restat(kTestFilename, testDiskInterface, 1, filter2, &err));
+  ASSERT_EQ("", err);
+  e = log.LookupByOutput("out");
+  ASSERT_EQ(3, e->mtime); // unchanged, since the filter doesn't match
+
+  EXPECT_TRUE(log.Restat(kTestFilename, testDiskInterface, 0, NULL, &err));
   ASSERT_EQ("", err);
   e = log.LookupByOutput("out");
   ASSERT_EQ(4, e->mtime);
diff --git a/src/ninja.cc b/src/ninja.cc
index 08f717f..1429639 100644
--- a/src/ninja.cc
+++ b/src/ninja.cc
@@ -859,6 +859,24 @@
 }
 
 int NinjaMain::ToolRestat(const Options* options, int argc, char* argv[]) {
+  // The restat tool uses getopt, and expects argv[0] to contain the name of the
+  // tool, i.e. "restat"
+  argc++;
+  argv--;
+
+  optind = 1;
+  int opt;
+  while ((opt = getopt(argc, argv, const_cast<char*>("h"))) != -1) {
+    switch (opt) {
+    case 'h':
+    default:
+      printf("usage: ninja -t restat [outputs]\n");
+      return 1;
+    }
+  }
+  argv += optind;
+  argc -= optind;
+
   if (!EnsureBuildDirExists())
     return 1;
 
@@ -882,7 +900,7 @@
     err.clear();
   }
 
-  bool success = build_log_.Restat(log_path, disk_interface_, &err);
+  bool success = build_log_.Restat(log_path, disk_interface_, argc, argv, &err);
   if (!success) {
     Error("failed recompaction: %s", err.c_str());
     return EXIT_FAILURE;
@@ -951,7 +969,7 @@
     { "recompact",  "recompacts ninja-internal data structures",
       Tool::RUN_AFTER_LOAD, &NinjaMain::ToolRecompact },
     { "restat",  "restats all outputs in the build log",
-      Tool::RUN_AFTER_LOAD, &NinjaMain::ToolRestat },
+      Tool::RUN_AFTER_FLAGS, &NinjaMain::ToolRestat },
     { "rules",  "list all rules",
       Tool::RUN_AFTER_LOAD, &NinjaMain::ToolRules },
     { "cleandead",  "clean built files that are no longer produced by the manifest",