cmGlobalNMakeMakefileGenerator.cxx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmGlobalNMakeMakefileGenerator.h"
  4. #include "cmsys/RegularExpression.hxx"
  5. #include "cmDocumentationEntry.h"
  6. #include "cmDuration.h"
  7. #include "cmLocalUnixMakefileGenerator3.h"
  8. #include "cmMakefile.h"
  9. #include "cmState.h"
  10. #include "cmake.h"
  11. cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator(cmake* cm)
  12. : cmGlobalUnixMakefileGenerator3(cm)
  13. {
  14. this->FindMakeProgramFile = "CMakeNMakeFindMake.cmake";
  15. this->ForceUnixPaths = false;
  16. this->ToolSupportsColor = true;
  17. this->UseLinkScript = false;
  18. cm->GetState()->SetWindowsShell(true);
  19. cm->GetState()->SetNMake(true);
  20. this->DefineWindowsNULL = true;
  21. this->PassMakeflags = true;
  22. this->UnixCD = false;
  23. this->MakeSilentFlag = "/nologo";
  24. // nmake breaks on '!' in long-line dependencies
  25. this->ToolSupportsLongLineDependencies = false;
  26. }
  27. void cmGlobalNMakeMakefileGenerator::EnableLanguage(
  28. std::vector<std::string> const& l, cmMakefile* mf, bool optional)
  29. {
  30. // pick a default
  31. mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
  32. mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
  33. this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
  34. }
  35. bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf)
  36. {
  37. if (!this->cmGlobalGenerator::FindMakeProgram(mf)) {
  38. return false;
  39. }
  40. if (cmProp nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
  41. std::vector<std::string> command{ *nmakeCommand, "-?" };
  42. std::string out;
  43. std::string err;
  44. if (!cmSystemTools::RunSingleCommand(command, &out, &err, nullptr, nullptr,
  45. cmSystemTools::OUTPUT_NONE,
  46. cmDuration(30))) {
  47. mf->IssueMessage(MessageType::FATAL_ERROR,
  48. cmStrCat("Running\n '", cmJoin(command, "' '"),
  49. "'\n"
  50. "failed with:\n ",
  51. err));
  52. cmSystemTools::SetFatalErrorOccured();
  53. return false;
  54. }
  55. cmsys::RegularExpression regex(
  56. "Program Maintenance Utility Version ([1-9][0-9.]+)");
  57. if (regex.find(err)) {
  58. this->NMakeVersion = regex.match(1);
  59. this->CheckNMakeFeatures();
  60. }
  61. }
  62. return true;
  63. }
  64. void cmGlobalNMakeMakefileGenerator::CheckNMakeFeatures()
  65. {
  66. this->NMakeSupportsUTF8 = !cmSystemTools::VersionCompare(
  67. cmSystemTools::OP_LESS, this->NMakeVersion.c_str(), "9");
  68. }
  69. void cmGlobalNMakeMakefileGenerator::GetDocumentation(
  70. cmDocumentationEntry& entry)
  71. {
  72. entry.Name = cmGlobalNMakeMakefileGenerator::GetActualName();
  73. entry.Brief = "Generates NMake makefiles.";
  74. }
  75. void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(
  76. std::ostream& os, std::string const& lang, const char* envVar) const
  77. {
  78. if (lang == "CXX" || lang == "C") {
  79. /* clang-format off */
  80. os <<
  81. "To use the NMake generator with Visual C++, cmake must be run from a "
  82. "shell that can use the compiler cl from the command line. This "
  83. "environment is unable to invoke the cl compiler. To fix this problem, "
  84. "run cmake from the Visual Studio Command Prompt (vcvarsall.bat).\n";
  85. /* clang-format on */
  86. }
  87. this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
  88. }
  89. std::vector<cmGlobalGenerator::GeneratedMakeCommand>
  90. cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
  91. const std::string& makeProgram, const std::string& projectName,
  92. const std::string& projectDir, std::vector<std::string> const& targetNames,
  93. const std::string& config, bool fast, int /*jobs*/, bool verbose,
  94. std::vector<std::string> const& makeOptions)
  95. {
  96. std::vector<std::string> nmakeMakeOptions;
  97. // Since we have full control over the invocation of nmake, let us
  98. // make it quiet.
  99. nmakeMakeOptions.push_back(this->MakeSilentFlag);
  100. cm::append(nmakeMakeOptions, makeOptions);
  101. return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
  102. makeProgram, projectName, projectDir, targetNames, config, fast,
  103. cmake::NO_BUILD_PARALLEL_LEVEL, verbose, nmakeMakeOptions);
  104. }
  105. void cmGlobalNMakeMakefileGenerator::PrintBuildCommandAdvice(std::ostream& os,
  106. int jobs) const
  107. {
  108. if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
  109. // nmake does not support parallel build level
  110. // see https://msdn.microsoft.com/en-us/library/afyyse50.aspx
  111. /* clang-format off */
  112. os <<
  113. "Warning: NMake does not support parallel builds. "
  114. "Ignoring parallel build command line option.\n";
  115. /* clang-format on */
  116. }
  117. this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
  118. os, cmake::NO_BUILD_PARALLEL_LEVEL);
  119. }