resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmGlobalNMakeMakefileGenerator.cxx
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
5 #include <ostream>
6
7 #include <cmext/algorithm>
8
9 #include "cmsys/RegularExpression.hxx"
10
11 #include "cmDocumentationEntry.h"
12 #include "cmDuration.h"
13 #include "cmGlobalGenerator.h"
14 #include "cmMakefile.h"
15 #include "cmMessageType.h"
16 #include "cmState.h"
17 #include "cmStringAlgorithms.h"
18 #include "cmSystemTools.h"
19 #include "cmake.h"
20
21 cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator(cmake* cm)
22   : cmGlobalUnixMakefileGenerator3(cm)
23 {
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;
32   this->UnixCD = false;
33   this->MakeSilentFlag = "/nologo";
34   // nmake breaks on '!' in long-line dependencies
35   this->ToolSupportsLongLineDependencies = false;
36 }
37
38 void cmGlobalNMakeMakefileGenerator::EnableLanguage(
39   std::vector<std::string> const& l, cmMakefile* mf, bool optional)
40 {
41   // pick a default
42   mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
43   mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
44   this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
45 }
46
47 bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf)
48 {
49   if (!this->cmGlobalGenerator::FindMakeProgram(mf)) {
50     return false;
51   }
52   if (cmValue nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
53     std::vector<std::string> command{ *nmakeCommand, "-?" };
54     std::string out;
55     std::string err;
56     if (!cmSystemTools::RunSingleCommand(command, &out, &err, nullptr, nullptr,
57                                          cmSystemTools::OUTPUT_NONE,
58                                          cmDuration(30))) {
59       mf->IssueMessage(MessageType::FATAL_ERROR,
60                        cmStrCat("Running\n '", cmJoin(command, "' '"),
61                                 "'\n"
62                                 "failed with:\n ",
63                                 err));
64       cmSystemTools::SetFatalErrorOccurred();
65       return false;
66     }
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();
72     }
73   }
74   return true;
75 }
76
77 void cmGlobalNMakeMakefileGenerator::CheckNMakeFeatures()
78 {
79   this->NMakeSupportsUTF8 = !cmSystemTools::VersionCompare(
80     cmSystemTools::OP_LESS, this->NMakeVersion, "9");
81 }
82
83 void cmGlobalNMakeMakefileGenerator::GetDocumentation(
84   cmDocumentationEntry& entry)
85 {
86   entry.Name = cmGlobalNMakeMakefileGenerator::GetActualName();
87   entry.Brief = "Generates NMake makefiles.";
88 }
89
90 void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(
91   std::ostream& os, std::string const& lang, cmValue envVar) const
92 {
93   if (lang == "CXX" || lang == "C") {
94     /* clang-format off */
95     os <<
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 */
101   }
102   this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
103 }
104
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)
112 {
113   std::vector<std::string> nmakeMakeOptions;
114
115   // Since we have full control over the invocation of nmake, let us
116   // make it quiet.
117   nmakeMakeOptions.push_back(this->MakeSilentFlag);
118   cm::append(nmakeMakeOptions, makeOptions);
119
120   return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
121     makeProgram, projectName, projectDir, targetNames, config,
122     cmake::NO_BUILD_PARALLEL_LEVEL, verbose, buildOptions, nmakeMakeOptions);
123 }
124
125 void cmGlobalNMakeMakefileGenerator::PrintBuildCommandAdvice(std::ostream& os,
126                                                              int jobs) const
127 {
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
131
132     /* clang-format off */
133     os <<
134       "Warning: NMake does not support parallel builds. "
135       "Ignoring parallel build command line option.\n";
136     /* clang-format on */
137   }
138
139   this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
140     os, cmake::NO_BUILD_PARALLEL_LEVEL);
141 }