Browse Source

Teach GenerateBuildCommand to find its own make program

Add a cmGlobalGenerator::SelectMakeProgram method to select a
caller-provided make program, the CMAKE_MAKE_PROGRAM cache entry, or a
generator-provided default.  Call it from all implementations of the
GenerateBuildCommand method with the corresponding generator's default,
if any.
Brad King 12 years ago
parent
commit
123a0608df

+ 20 - 0
Source/cmGlobalGenerator.cxx

@@ -88,6 +88,26 @@ bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts)
   return false;
 }
 
+std::string cmGlobalGenerator::SelectMakeProgram(const char* makeProgram,
+                                                 std::string makeDefault)
+{
+  if(cmSystemTools::IsOff(makeProgram))
+    {
+    makeProgram =
+      this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
+    if(cmSystemTools::IsOff(makeProgram))
+      {
+      makeProgram = makeDefault.c_str();
+      }
+    if(cmSystemTools::IsOff(makeProgram) &&
+       !(makeProgram && *makeProgram))
+      {
+      makeProgram = "CMAKE_MAKE_PROGRAM-NOTFOUND";
+      }
+    }
+  return makeProgram;
+}
+
 void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang,
                                                 cmMakefile *mf,
                                                 bool optional)

+ 2 - 0
Source/cmGlobalGenerator.h

@@ -334,6 +334,8 @@ protected:
   typedef std::vector<std::pair<cmQtAutoGenerators, cmTarget*> > AutogensType;
   void CreateQtAutoGeneratorsTargets(AutogensType& autogens);
 
+  std::string SelectMakeProgram(const char* makeProgram,
+                                std::string makeDefault = "");
 
   // Fill the ProjectMap, this must be called after LocalGenerators
   // has been populated.

+ 3 - 1
Source/cmGlobalNinjaGenerator.cxx

@@ -559,7 +559,9 @@ void cmGlobalNinjaGenerator
                        bool /*fast*/,
                        std::vector<std::string> const& makeOptions)
 {
-  makeCommand.push_back(makeProgram);
+  makeCommand.push_back(
+    this->SelectMakeProgram(makeProgram)
+    );
 
   makeCommand.insert(makeCommand.end(),
                      makeOptions.begin(), makeOptions.end());

+ 3 - 1
Source/cmGlobalUnixMakefileGenerator3.cxx

@@ -566,7 +566,9 @@ void cmGlobalUnixMakefileGenerator3
                        bool fast,
                        std::vector<std::string> const& makeOptions)
 {
-  makeCommand.push_back(makeProgram);
+  makeCommand.push_back(
+    this->SelectMakeProgram(makeProgram)
+    );
 
   // Since we have full control over the invocation of nmake, let us
   // make it quiet.

+ 47 - 31
Source/cmGlobalVisualStudio10Generator.cxx

@@ -311,23 +311,56 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
   bool fast,
   std::vector<std::string> const& makeOptions)
 {
-  // now build the test
-  std::string lowerCaseCommand = makeProgram;
-  cmSystemTools::LowerCase(lowerCaseCommand);
-
-  // If makeProgram is devenv, parent class knows how to generate command:
-  if (lowerCaseCommand.find("devenv") != std::string::npos ||
-      lowerCaseCommand.find("VCExpress") != std::string::npos)
+  // Select the caller- or user-preferred make program, else MSBuild.
+  std::string makeProgramSelected =
+    this->SelectMakeProgram(makeProgram, this->GetMSBuildCommand());
+
+  // Check if the caller explicitly requested a devenv tool.
+  std::string makeProgramLower = makeProgramSelected;
+  cmSystemTools::LowerCase(makeProgramLower);
+  bool useDevEnv =
+    (makeProgramLower.find("devenv") != std::string::npos ||
+     makeProgramLower.find("vcexpress") != std::string::npos);
+
+  // MSBuild is preferred (and required for VS Express), but if the .sln has
+  // an Intel Fortran .vfproj then we have to use devenv. Parse it to find out.
+  cmSlnData slnData;
+  {
+  std::string slnFile;
+  if(projectDir && *projectDir)
+    {
+    slnFile = projectDir;
+    slnFile += "/";
+    }
+  slnFile += projectName;
+  slnFile += ".sln";
+  cmVisualStudioSlnParser parser;
+  if(parser.ParseFile(slnFile, slnData,
+                      cmVisualStudioSlnParser::DataGroupProjects))
+    {
+    std::vector<cmSlnProjectEntry> slnProjects = slnData.GetProjects();
+    for(std::vector<cmSlnProjectEntry>::iterator i = slnProjects.begin();
+        !useDevEnv && i != slnProjects.end(); ++i)
+      {
+      std::string proj = i->GetRelativePath();
+      if(proj.size() > 7 &&
+         proj.substr(proj.size()-7) == ".vfproj")
+        {
+        useDevEnv = true;
+        }
+      }
+    }
+  }
+  if(useDevEnv)
     {
+    // Use devenv to build solutions containing Intel Fortran projects.
     cmGlobalVisualStudio7Generator::GenerateBuildCommand(
       makeCommand, makeProgram, projectName, projectDir,
       targetName, config, fast, makeOptions);
     return;
     }
 
-  // Otherwise, assume MSBuild command line, and construct accordingly.
-
-  makeCommand.push_back(makeProgram);
+  makeCommand.push_back(makeProgramSelected);
 
   // msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug /target:ALL_BUILD
   if(!targetName || strlen(targetName) == 0)
@@ -346,28 +379,11 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
     if (targetProject.find('/') == std::string::npos)
       {
       // it might be in a subdir
-      cmVisualStudioSlnParser parser;
-      cmSlnData slnData;
-      std::string slnFile;
-      if (projectDir && *projectDir)
-        {
-        slnFile = projectDir;
-        slnFile += '/';
-        slnFile += projectName;
-        }
-      else
-        {
-        slnFile = projectName;
-        }
-      if (parser.ParseFile(slnFile + ".sln", slnData,
-                           cmVisualStudioSlnParser::DataGroupProjects))
+      if (cmSlnProjectEntry const* proj =
+          slnData.GetProjectByName(targetName))
         {
-        if (cmSlnProjectEntry const* proj =
-            slnData.GetProjectByName(targetName))
-          {
-          targetProject = proj->GetRelativePath();
-          cmSystemTools::ConvertToUnixSlashes(targetProject);
-          }
+        targetProject = proj->GetRelativePath();
+        cmSystemTools::ConvertToUnixSlashes(targetProject);
         }
       }
     makeCommand.push_back(targetProject);

+ 3 - 18
Source/cmGlobalVisualStudio6Generator.cxx

@@ -118,24 +118,9 @@ cmGlobalVisualStudio6Generator::GenerateBuildCommand(
   )
 {
   // now build the test
-  std::vector<std::string> mp;
-  mp.push_back("[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio"
-               "\\6.0\\Setup;VsCommonDir]/MSDev98/Bin");
-  cmSystemTools::ExpandRegistryValues(mp[0]);
-  std::string originalCommand = makeProgram;
-  std::string makeCommandFound =
-    cmSystemTools::FindProgram(makeProgram, mp);
-  if(makeCommandFound.size() == 0)
-    {
-    std::string e = "Generator cannot find Visual Studio 6 msdev program \"";
-    e += originalCommand;
-    e += "\" specified by CMAKE_MAKE_PROGRAM cache entry.  ";
-    e += "Please fix the setting.";
-    cmSystemTools::Error(e.c_str());
-    return;
-    }
-
-  makeCommand.push_back(makeCommandFound);
+  makeCommand.push_back(
+    this->SelectMakeProgram(makeProgram, this->GetMSDevCommand())
+    );
 
   makeCommand.push_back(std::string(projectName)+".dsw");
   makeCommand.push_back("/MAKE");

+ 15 - 1
Source/cmGlobalVisualStudio7Generator.cxx

@@ -148,7 +148,21 @@ void cmGlobalVisualStudio7Generator::GenerateBuildCommand(
   bool /*fast*/,
   std::vector<std::string> const& makeOptions)
 {
-  makeCommand.push_back(makeProgram);
+  // Select the caller- or user-preferred make program, else devenv.
+  std::string makeProgramSelected =
+    this->SelectMakeProgram(makeProgram, this->GetDevEnvCommand());
+
+  // Ignore the above preference if it is msbuild.
+  // Assume any other value is either a devenv or
+  // command-line compatible with devenv.
+  std::string makeProgramLower = makeProgramSelected;
+  cmSystemTools::LowerCase(makeProgramLower);
+  if(makeProgramLower.find("msbuild") != std::string::npos)
+    {
+    makeProgramSelected = this->GetDevEnvCommand();
+    }
+
+  makeCommand.push_back(makeProgramSelected);
 
   makeCommand.push_back(std::string(projectName) + ".sln");
   bool clean = false;

+ 3 - 7
Source/cmGlobalXCodeGenerator.cxx

@@ -269,13 +269,9 @@ cmGlobalXCodeGenerator::GenerateBuildCommand(
   std::vector<std::string> const& makeOptions)
 {
   // now build the test
-  if(makeProgram == 0 || !strlen(makeProgram))
-    {
-    cmSystemTools::Error(
-      "Generator cannot find the appropriate make command.");
-    return;
-    }
-  makeCommand.push_back(makeProgram);
+  makeCommand.push_back(
+    this->SelectMakeProgram(makeProgram, "xcodebuild")
+    );
 
   makeCommand.push_back("-project");
   std::string projectArg = projectName;