Browse Source

ENH: Cleanup cmake --build interface.

This cleans up the 'cmake --build' command-line interface:
  - Rename --clean to --clean-first to better describe it.
  - Replace --extra-options with a -- separator to simplify passing of
    multiple native build tool options.
  - Document the options in the main CMake man page description of the
    --build option, and shares this with the usage message.
  - Require --build to be the first argument when present.
  - Move implementation into cmakemain where it belongs.
Brad King 17 years ago
parent
commit
170febac52
4 changed files with 105 additions and 67 deletions
  1. 2 48
      Source/cmake.cxx
  2. 2 3
      Source/cmake.h
  3. 100 15
      Source/cmakemain.cxx
  4. 1 1
      Tests/CMakeBuildTest.cmake.in

+ 2 - 48
Source/cmake.cxx

@@ -4394,7 +4394,7 @@ std::vector<std::string> const& cmake::GetDebugConfigs()
 int cmake::Build(const std::string& dir,
                  const std::string& target,
                  const std::string& config,
-                 const std::string& extraBuildOptions,
+                 const std::vector<std::string>& nativeOptions,
                  bool clean)
 { 
   if(!cmSystemTools::FileIsDirectory(dir.c_str()))
@@ -4438,51 +4438,5 @@ int cmake::Build(const std::string& dir,
                     &output, 
                     makeProgram.c_str(),
                     config.c_str(), clean, false, 0, true,
-                    extraBuildOptions.c_str());
-}
-
-int cmake::DoBuild(int ac, char* av[])
-{
-#ifndef CMAKE_BUILD_WITH_CMAKE
-  std::cerr << "This cmake does not support --build\n";
-  return -1;
-#else
-  std::string target;
-  std::string config = "Debug";
-  std::string extraBuildOptions;
-  std::string dir;
-  bool clean = false;
-  cmsys::CommandLineArguments arg;
-  arg.Initialize(ac, av);
-  typedef cmsys::CommandLineArguments argT;
-  arg.AddArgument("--build", argT::SPACE_ARGUMENT, &dir, 
-                  "Build a configured cmake project --build dir.");
-  arg.AddArgument("--target", argT::SPACE_ARGUMENT, &target, 
-                  "Specifiy the target to build,"
-                  " if missing, all targets are built.");
-  arg.AddArgument("--config", argT::SPACE_ARGUMENT, &config, 
-                  "Specify configuration to build"
-                  " if missing Debug is built.");
-  arg.AddArgument("--extra-options", argT::SPACE_ARGUMENT, &extraBuildOptions, 
-                  "Specify extra options to pass to build program,"
-                  " for example with gmake -jN.");
-  arg.AddArgument("--clean", argT::NO_ARGUMENT, &clean, 
-                  "Clean before building.");
-  if ( !arg.Parse() )
-    {
-    std::cerr << "Problem parsing --build arguments:\n";
-    std::cerr << arg.GetHelp() << "\n";
-    return 1;
-    }
-
-  // Hack for vs6 that passes ".\Debug" as "$(IntDir)" value:
-  //
-  if (cmSystemTools::StringStartsWith(config.c_str(), ".\\"))
-    {
-    config = config.substr(2);
-    }
-
-  cmake cm;
-  return cm.Build(dir, target, config, extraBuildOptions, clean);
-#endif
+                    0, nativeOptions);
 }

+ 2 - 3
Source/cmake.h

@@ -357,13 +357,12 @@ class cmake
   void IssueMessage(cmake::MessageType t, std::string const& text,
                     cmListFileBacktrace const& backtrace);
   //  * run the --build option
-  static int DoBuild(int ac, char* av[]);
-protected:
   int Build(const std::string& dir,
             const std::string& target,
             const std::string& config,
-            const std::string& extraBuildOptions,
+            const std::vector<std::string>& nativeOptions,
             bool clean);
+protected:
   void InitializeProperties();
   int HandleDeleteCacheVariables(const char* var);
   cmPropertyMap Properties;

+ 100 - 15
Source/cmakemain.cxx

@@ -61,6 +61,14 @@ static const char * cmDocumentationDescription[][3] =
   {0,0,0}
 };
 
+#define CMAKE_BUILD_OPTIONS                                             \
+  "  <dir>          = Project binary directory to be built.\n"          \
+  "  --target <tgt> = Build <tgt> instead of default targets.\n"        \
+  "  --config <cfg> = For multi-configuration tools, choose <cfg>.\n"   \
+  "  --clean-first  = Build target 'clean' first, then build.\n"        \
+  "                   (To clean only, use --target 'clean'.)\n"         \
+  "  --             = Pass remaining options to the native tool.\n"
+
 //----------------------------------------------------------------------------
 static const char * cmDocumentationOptions[][3] =
 {
@@ -85,11 +93,11 @@ static const char * cmDocumentationOptions[][3] =
    "variables being created. If A is specified, then it will display also "
    "advanced variables. If H is specified, it will also display help for "
    "each variable."},
-  {"--build dir", "Build a configured cmake tree found in dir.",
-   "This option will use the native build tool from the command line to"
-   " build the project. Other options that can be specified with this one" 
-   " are --target, --config, --extra-options, and --clean.  For complete "
-   "help run --build with no options."},
+  {"--build <dir>", "Build a CMake-generated project binary tree.",
+   "This abstracts a native build tool's command-line interface with the "
+   "following options:\n"
+   CMAKE_BUILD_OPTIONS
+   "Run cmake --build with no options for quick help."},
   {"-N", "View mode only.",
    "Only load the cache. Do not actually run configure and generate steps."},
   {"-P <file>", "Process script mode.",
@@ -236,6 +244,7 @@ static const char * cmDocumentationNOTE[][3] =
 #endif
 
 int do_cmake(int ac, char** av);
+static int do_build(int ac, char** av);
 
 static cmMakefile* cmakemainGetMakefile(void *clientdata)
 {
@@ -307,6 +316,10 @@ int main(int ac, char** av)
 {
   cmSystemTools::EnableMSVCDebugHook();
   cmSystemTools::FindExecutableDirectory(av[0]);
+  if(ac > 1 && strcmp(av[1], "--build") == 0)
+    {
+    return do_build(ac, av);
+    }
   int ret = do_cmake(ac, av);
 #ifdef CMAKE_BUILD_WITH_CMAKE
   cmDynamicLoader::FlushCache();
@@ -412,7 +425,6 @@ int do_cmake(int ac, char** av)
   bool list_help = false;
   bool view_only = false;
   bool script_mode = false;
-  bool build = false;
   std::vector<std::string> args;
   for(int i =0; i < ac; ++i)
     {
@@ -420,10 +432,6 @@ int do_cmake(int ac, char** av)
       {
       wiz = true;
       }
-    else if(!command && strcmp(av[i], "--build") == 0)
-      {
-      return cmake::DoBuild(ac, av);
-      }
     else if(!command && strcmp(av[i], "--system-information") == 0)
       {
       sysinfo = true;
@@ -475,11 +483,6 @@ int do_cmake(int ac, char** av)
       args.push_back(av[i]);
       }
     }
-  if(build)
-    {
-    int ret = cmake::DoBuild(ac, av);
-    return ret;
-    }
   if(command)
     {
     int ret = cmake::ExecuteCMakeCommand(args);
@@ -544,3 +547,85 @@ int do_cmake(int ac, char** av)
     }
 }
 
+//----------------------------------------------------------------------------
+static int do_build(int ac, char** av)
+{
+#ifndef CMAKE_BUILD_WITH_CMAKE
+  std::cerr << "This cmake does not support --build\n";
+  return -1;
+#else
+  std::string target;
+  std::string config = "Debug";
+  std::string dir;
+  std::vector<std::string> nativeOptions;
+  bool clean = false;
+
+  enum Doing { DoingNone, DoingDir, DoingTarget, DoingConfig, DoingNative};
+  Doing doing = DoingDir;
+  for(int i=2; i < ac; ++i)
+    {
+    if(doing == DoingNative)
+      {
+      nativeOptions.push_back(av[i]);
+      }
+    else if(strcmp(av[i], "--target") == 0)
+      {
+      doing = DoingTarget;
+      }
+    else if(strcmp(av[i], "--config") == 0)
+      {
+      doing = DoingConfig;
+      }
+    else if(strcmp(av[i], "--clean-first") == 0)
+      {
+      clean = true;
+      doing = DoingNone;
+      }
+    else if(strcmp(av[i], "--") == 0)
+      {
+      doing = DoingNative;
+      }
+    else
+      {
+      switch (doing)
+        {
+        case DoingDir:
+          dir = av[i];
+          doing = DoingNone;
+          break;
+        case DoingTarget:
+          target = av[i];
+          doing = DoingNone;
+          break;
+        case DoingConfig:
+          config = av[i];
+          doing = DoingNone;
+          break;
+        default:
+          std::cerr << "Unknown argument " << av[i] << std::endl;
+          dir = "";
+          break;
+        }
+      }
+    }
+  if(dir.empty())
+    {
+    std::cerr <<
+      "Usage: cmake --build <dir> [options] [-- [native-options]]\n"
+      "Options:\n"
+      CMAKE_BUILD_OPTIONS
+      ;
+    return 1;
+    }
+
+  // Hack for vs6 that passes ".\Debug" as "$(IntDir)" value:
+  //
+  if (cmSystemTools::StringStartsWith(config.c_str(), ".\\"))
+    {
+    config = config.substr(2);
+    }
+
+  cmake cm;
+  return cm.Build(dir, target, config, nativeOptions, clean);
+#endif
+}

+ 1 - 1
Tests/CMakeBuildTest.cmake.in

@@ -46,7 +46,7 @@ endif(RESULT)
 # build it again with clean and only COnly target
 execute_process(COMMAND "${CMAKE_COMMAND}" 
   --build "@CMAKE_BUILD_TEST_BINARY_DIR@" --config Debug 
-  --clean --target COnly
+  --clean-first --target COnly
   RESULT_VARIABLE RESULT)
 if(RESULT)
   message(FATAL_ERROR "Error running cmake --build")