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"
7 #include <cmext/algorithm>
9 #include "cmsys/RegularExpression.hxx"
11 #include "cmDocumentationEntry.h"
12 #include "cmDuration.h"
13 #include "cmGlobalGenerator.h"
14 #include "cmMakefile.h"
15 #include "cmMessageType.h"
17 #include "cmStringAlgorithms.h"
18 #include "cmSystemTools.h"
21 cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator(cmake* cm)
22 : cmGlobalUnixMakefileGenerator3(cm)
24 this->FindMakeProgramFile = "CMakeNMakeFindMake.cmake";
25 this->ForceUnixPaths = false;
26 this->ToolSupportsColor = true;
27 this->UseLinkScript = false;
28 cm->GetState()->SetWindowsShell(true);
29 cm->GetState()->SetNMake(true);
30 this->DefineWindowsNULL = true;
31 this->PassMakeflags = true;
33 this->MakeSilentFlag = "/nologo";
34 // nmake breaks on '!' in long-line dependencies
35 this->ToolSupportsLongLineDependencies = false;
38 void cmGlobalNMakeMakefileGenerator::EnableLanguage(
39 std::vector<std::string> const& l, cmMakefile* mf, bool optional)
42 mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
43 mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
44 this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
47 bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf)
49 if (!this->cmGlobalGenerator::FindMakeProgram(mf)) {
52 if (cmValue nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
53 std::vector<std::string> command{ *nmakeCommand, "-?" };
56 if (!cmSystemTools::RunSingleCommand(command, &out, &err, nullptr, nullptr,
57 cmSystemTools::OUTPUT_NONE,
59 mf->IssueMessage(MessageType::FATAL_ERROR,
60 cmStrCat("Running\n '", cmJoin(command, "' '"),
64 cmSystemTools::SetFatalErrorOccurred();
67 cmsys::RegularExpression regex(
68 "Program Maintenance Utility Version ([1-9][0-9.]+)");
69 if (regex.find(err)) {
70 this->NMakeVersion = regex.match(1);
71 this->CheckNMakeFeatures();
77 void cmGlobalNMakeMakefileGenerator::CheckNMakeFeatures()
79 this->NMakeSupportsUTF8 = !cmSystemTools::VersionCompare(
80 cmSystemTools::OP_LESS, this->NMakeVersion, "9");
83 void cmGlobalNMakeMakefileGenerator::GetDocumentation(
84 cmDocumentationEntry& entry)
86 entry.Name = cmGlobalNMakeMakefileGenerator::GetActualName();
87 entry.Brief = "Generates NMake makefiles.";
90 void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(
91 std::ostream& os, std::string const& lang, cmValue envVar) const
93 if (lang == "CXX" || lang == "C") {
94 /* clang-format off */
96 "To use the NMake generator with Visual C++, cmake must be run from a "
97 "shell that can use the compiler cl from the command line. This "
98 "environment is unable to invoke the cl compiler. To fix this problem, "
99 "run cmake from the Visual Studio Command Prompt (vcvarsall.bat).\n";
100 /* clang-format on */
102 this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
105 std::vector<cmGlobalGenerator::GeneratedMakeCommand>
106 cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
107 const std::string& makeProgram, const std::string& projectName,
108 const std::string& projectDir, std::vector<std::string> const& targetNames,
109 const std::string& config, int /*jobs*/, bool verbose,
110 const cmBuildOptions& buildOptions,
111 std::vector<std::string> const& makeOptions)
113 std::vector<std::string> nmakeMakeOptions;
115 // Since we have full control over the invocation of nmake, let us
117 nmakeMakeOptions.push_back(this->MakeSilentFlag);
118 cm::append(nmakeMakeOptions, makeOptions);
120 return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
121 makeProgram, projectName, projectDir, targetNames, config,
122 cmake::NO_BUILD_PARALLEL_LEVEL, verbose, buildOptions, nmakeMakeOptions);
125 void cmGlobalNMakeMakefileGenerator::PrintBuildCommandAdvice(std::ostream& os,
128 if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
129 // nmake does not support parallel build level
130 // see https://msdn.microsoft.com/en-us/library/afyyse50.aspx
132 /* clang-format off */
134 "Warning: NMake does not support parallel builds. "
135 "Ignoring parallel build command line option.\n";
136 /* clang-format on */
139 this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
140 os, cmake::NO_BUILD_PARALLEL_LEVEL);