From 123a0608dfe6cf155f0fc095cf389ae7b3d4ebb0 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 13 Nov 2013 15:12:06 -0500 Subject: 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. --- Source/cmGlobalGenerator.cxx | 20 ++++++++ Source/cmGlobalGenerator.h | 2 + Source/cmGlobalNinjaGenerator.cxx | 4 +- Source/cmGlobalUnixMakefileGenerator3.cxx | 4 +- Source/cmGlobalVisualStudio10Generator.cxx | 78 ++++++++++++++++++------------ Source/cmGlobalVisualStudio6Generator.cxx | 21 ++------ Source/cmGlobalVisualStudio7Generator.cxx | 16 +++++- Source/cmGlobalXCodeGenerator.cxx | 10 ++-- 8 files changed, 96 insertions(+), 59 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index b653aff..9609497 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/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) diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 37e12ff..74d88f3 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -334,6 +334,8 @@ protected: typedef std::vector > 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. diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 24bfdc3..77571b2 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -559,7 +559,9 @@ void cmGlobalNinjaGenerator bool /*fast*/, std::vector const& makeOptions) { - makeCommand.push_back(makeProgram); + makeCommand.push_back( + this->SelectMakeProgram(makeProgram) + ); makeCommand.insert(makeCommand.end(), makeOptions.begin(), makeOptions.end()); diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 3aa1f5f..e1af2f9 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -566,7 +566,9 @@ void cmGlobalUnixMakefileGenerator3 bool fast, std::vector 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. diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index d4d67d0..741d591 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -311,23 +311,56 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand( bool fast, std::vector 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 slnProjects = slnData.GetProjects(); + for(std::vector::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); diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx index 51f38c2..08ea249 100644 --- a/Source/cmGlobalVisualStudio6Generator.cxx +++ b/Source/cmGlobalVisualStudio6Generator.cxx @@ -118,24 +118,9 @@ cmGlobalVisualStudio6Generator::GenerateBuildCommand( ) { // now build the test - std::vector 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"); diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 2602f83..08eff31 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -148,7 +148,21 @@ void cmGlobalVisualStudio7Generator::GenerateBuildCommand( bool /*fast*/, std::vector 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; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index f8ec8a0..be0459d 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -269,13 +269,9 @@ cmGlobalXCodeGenerator::GenerateBuildCommand( std::vector 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; -- cgit v0.12