windows: merge msvc-helper into ninja.exe itself
authorEvan Martin <martine@danga.com>
Thu, 13 Sep 2012 18:07:45 +0000 (11:07 -0700)
committerEvan Martin <martine@danga.com>
Thu, 13 Sep 2012 18:11:47 +0000 (11:11 -0700)
Now "ninja -t msvc ..." passes the "..." to the msvc helper main.
This drastically simplifies bootstrap and makes ninja a single
binary again.

bootstrap.py
configure.py
src/msvc_helper_main-win32.cc
src/ninja.cc

index abd2528..3032a9b 100755 (executable)
@@ -19,6 +19,7 @@ import os
 import glob
 import errno
 import shlex
+import shutil
 import subprocess
 
 os.chdir(os.path.dirname(os.path.abspath(__file__)))
@@ -68,8 +69,6 @@ for src in glob.glob('src/*.cc'):
     else:
         if src.endswith('-win32.cc'):
             continue
-    if '_main' in src:
-        continue
 
     sources.append(src)
 
@@ -113,25 +112,14 @@ if options.verbose:
     verbose = ['-v']
 
 if sys.platform.startswith('win32'):
-    # Build ninja-msvc-helper using ninja without an msvc-helper.
-    print 'Building ninja-msvc-helper...'
-    run([sys.executable, 'configure.py', '--with-msvc-helper='] + conf_args)
-    run(['./' + binary] + verbose + ['ninja-msvc-helper'])
-
-    # Rename the helper to the same name + .bootstrap.
-    helper_binary = 'ninja-msvc-helper.bootstrap.exe'
-    try:
-        os.unlink(helper_binary)
-    except:
-        pass
-    os.rename('ninja-msvc-helper.exe', helper_binary)
-
-    # Build ninja using the newly-built msvc-helper.
     print 'Building ninja using itself...'
-    run([sys.executable, 'configure.py',
-         '--with-msvc-helper=%s' % helper_binary] + conf_args)
+    run([sys.executable, 'configure.py', '--with-ninja=%s' % binary] +
+        conf_args)
     run(['./' + binary] + verbose)
 
+    # Copy the new executable over the bootstrap one.
+    shutil.copyfile('ninja.exe', binary)
+
     # Clean up.
     for obj in glob.glob('*.obj'):
         os.unlink(obj)
@@ -142,8 +130,8 @@ Done!
 Note: to work around Windows file locking, where you can't rebuild an
 in-use binary, to run ninja after making any changes to build ninja itself
 you should run ninja.bootstrap instead.  Your build is also configured to
-use ninja-msvc-helper.bootstrap.exe instead of the ninja-msvc-helper.exe
-that it builds; see the --help output of configure.py."""
+use ninja.bootstrap.exe as the MSVC helper; see the --with-ninja flag of
+the --help output of configure.py."""
 else:
     print 'Building ninja using itself...'
     run([sys.executable, 'configure.py'] + conf_args)
index ca6615c..98274e6 100755 (executable)
@@ -45,8 +45,9 @@ parser.add_option('--with-gtest', metavar='PATH',
 parser.add_option('--with-python', metavar='EXE',
                   help='use EXE as the Python interpreter',
                   default=os.path.basename(sys.executable))
-parser.add_option('--with-msvc-helper', metavar='NAME',
-                  help="name for ninja-msvc-helper binary (MSVC only)")
+parser.add_option('--with-ninja', metavar='NAME',
+                  help="name for ninja binary for -t msvc (MSVC only)",
+                  default="ninja")
 (options, args) = parser.parse_args()
 if args:
     print 'ERROR: extra unparsed command-line arguments:', args
@@ -185,8 +186,9 @@ n.newline()
 
 if platform == 'windows':
     compiler = '$cxx'
-    if options.with_msvc_helper:
-        compiler = '%s -o $out -- $cxx /showIncludes' % options.with_msvc_helper
+    if options.with_ninja:
+        compiler = ('%s -t msvc -o $out -- $cxx /showIncludes' %
+                    options.with_ninja)
     n.rule('cxx',
         command='%s $cflags -c $in /Fo$out' % compiler,
         depfile='$out.d',
@@ -279,6 +281,7 @@ if platform in ('mingw', 'windows'):
     if platform == 'windows':
         objs += cxx('includes_normalize-win32')
         objs += cxx('msvc_helper-win32')
+        objs += cxx('msvc_helper_main-win32')
         objs += cxx('minidump-win32')
     objs += cc('getopt')
 else:
@@ -303,16 +306,6 @@ ninja = n.build(binary('ninja'), 'link', objs, implicit=ninja_lib,
 n.newline()
 all_targets += ninja
 
-if platform == 'windows':
-    n.comment('Helper for working with MSVC.')
-    msvc_helper = n.build(binary('ninja-msvc-helper'), 'link',
-                          cxx('msvc_helper_main-win32'),
-                          implicit=ninja_lib,
-                          variables=[('libs', libs)])
-    n.default(msvc_helper)
-    n.newline()
-    all_targets += msvc_helper
-
 n.comment('Tests all build into ninja_test executable.')
 
 variables = []
index f265010..0c8db37 100644 (file)
@@ -24,9 +24,7 @@ namespace {
 
 void Usage() {
   printf(
-"ninja-msvc-helper: adjust msvc command-line tools for use by ninja.\n"
-"\n"
-"usage: ninja-mvsc-helper [options] -- command args\n"
+"usage: ninja -t msvc [options] -- cl.exe /showIncludes /otherArgs\n"
 "options:\n"
 "  -e ENVFILE load environment block from ENVFILE as environment\n"
 "  -r BASE    normalize paths and make relative to BASE before output\n"
@@ -48,7 +46,7 @@ void PushPathIntoEnvironment(const string& env_block) {
 
 }  // anonymous namespace
 
-int main(int argc, char** argv) {
+int MSVCHelperMain(int argc, char** argv) {
   const char* output_filename = NULL;
   const char* relative_to = NULL;
   const char* envfile = NULL;
@@ -76,8 +74,10 @@ int main(int argc, char** argv) {
     }
   }
 
-  if (!output_filename)
+  if (!output_filename) {
+    Usage();
     Fatal("-o required");
+  }
 
   string env;
   if (envfile) {
index fb273be..089dbc1 100644 (file)
@@ -42,6 +42,9 @@
 #include "state.h"
 #include "util.h"
 
+// Defined in msvc_helper_main-win32.cc.
+int MSVCHelperMain(int argc, char** argv);
+
 namespace {
 
 /// The version number of the current Ninja release.  This will always
@@ -289,6 +292,16 @@ int ToolBrowse(Globals* globals, int argc, char* argv[]) {
 }
 #endif  // _WIN32
 
+#if defined(WIN32)
+int ToolMSVC(Globals* globals, int argc, char* argv[]) {
+  // Reset getopt: push one argument onto the front of argv, reset optind.
+  argc++;
+  argv--;
+  optind = 0;
+  return MSVCHelperMain(argc, argv);
+}
+#endif
+
 int ToolTargetsList(const vector<Node*>& nodes, int depth, int indent) {
   for (vector<Node*>::const_iterator n = nodes.begin();
        n != nodes.end();
@@ -524,6 +537,10 @@ int ChooseTool(const string& tool_name, const Tool** tool_out) {
     { "browse", "browse dependency graph in a web browser",
       Tool::RUN_AFTER_LOAD, ToolBrowse },
 #endif
+#if defined(WIN32)
+    { "msvc", "build helper for MSVC cl.exe",
+      Tool::RUN_AFTER_FLAGS, ToolMSVC },
+#endif
     { "clean", "clean built files",
       Tool::RUN_AFTER_LOAD, ToolClean },
     { "commands", "list all commands required to rebuild given targets",