CMake Nightly Date Stamp
[kiteware-cmake.git] / Source / cmInstallGenerator.cxx
blob93abd456933f713d82a5d5d95bbcc2b9bbef3089
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 "cmInstallGenerator.h"
5 #include <sstream>
6 #include <utility>
8 #include "cmMakefile.h"
9 #include "cmStringAlgorithms.h"
10 #include "cmSystemTools.h"
12 cmInstallGenerator::cmInstallGenerator(
13 std::string destination, std::vector<std::string> const& configurations,
14 std::string component, MessageLevel message, bool exclude_from_all,
15 bool all_components, cmListFileBacktrace backtrace)
16 : cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations)
17 , Destination(std::move(destination))
18 , Component(std::move(component))
19 , Message(message)
20 , ExcludeFromAll(exclude_from_all)
21 , AllComponents(all_components)
22 , Backtrace(std::move(backtrace))
26 cmInstallGenerator::~cmInstallGenerator() = default;
28 bool cmInstallGenerator::HaveInstall()
30 return true;
33 void cmInstallGenerator::CheckCMP0082(bool& haveSubdirectoryInstall,
34 bool& haveInstallAfterSubdirectory)
36 if (haveSubdirectoryInstall) {
37 haveInstallAfterSubdirectory = true;
41 void cmInstallGenerator::AddInstallRule(
42 std::ostream& os, std::string const& dest, cmInstallType type,
43 std::vector<std::string> const& files, bool optional /* = false */,
44 const char* permissions_file /* = nullptr */,
45 const char* permissions_dir /* = nullptr */,
46 const char* rename /* = nullptr */, const char* literal_args /* = nullptr */,
47 Indent indent, const char* files_var /* = nullptr */)
49 // Use the FILE command to install the file.
50 std::string stype;
51 switch (type) {
52 case cmInstallType_DIRECTORY:
53 stype = "DIRECTORY";
54 break;
55 case cmInstallType_PROGRAMS:
56 stype = "PROGRAM";
57 break;
58 case cmInstallType_EXECUTABLE:
59 stype = "EXECUTABLE";
60 break;
61 case cmInstallType_STATIC_LIBRARY:
62 stype = "STATIC_LIBRARY";
63 break;
64 case cmInstallType_SHARED_LIBRARY:
65 stype = "SHARED_LIBRARY";
66 break;
67 case cmInstallType_MODULE_LIBRARY:
68 stype = "MODULE";
69 break;
70 case cmInstallType_FILES:
71 stype = "FILE";
72 break;
74 if (cmSystemTools::FileIsFullPath(dest)) {
75 if (!files.empty()) {
76 os << indent << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n";
77 os << indent << " \"";
78 bool firstIteration = true;
79 for (std::string const& file : files) {
80 if (!firstIteration) {
81 os << ";";
83 os << dest << "/";
84 if (rename && *rename) {
85 os << rename;
86 } else {
87 os << cmSystemTools::GetFilenameName(file);
89 firstIteration = false;
91 os << "\")\n";
93 if (files_var) {
94 os << indent << "foreach(_cmake_abs_file IN LISTS " << files_var
95 << ")\n";
96 os << indent.Next()
97 << "get_filename_component(_cmake_abs_file_name "
98 "\"${_cmake_abs_file}\" NAME)\n";
99 os << indent.Next() << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES \""
100 << dest << "/${_cmake_abs_file_name}\")\n";
101 os << indent << "endforeach()\n";
102 os << indent << "unset(_cmake_abs_file_name)\n";
103 os << indent << "unset(_cmake_abs_file)\n";
105 os << indent << "if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
106 os << indent.Next()
107 << "message(WARNING \"ABSOLUTE path INSTALL "
108 "DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
109 os << indent << "endif()\n";
111 os << indent << "if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
112 os << indent.Next()
113 << "message(FATAL_ERROR \"ABSOLUTE path INSTALL "
114 "DESTINATION forbidden (by caller): "
115 "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
116 os << indent << "endif()\n";
118 std::string absDest = ConvertToAbsoluteDestination(dest);
119 os << indent << "file(INSTALL DESTINATION \"" << absDest << "\" TYPE "
120 << stype;
121 if (optional) {
122 os << " OPTIONAL";
124 switch (this->Message) {
125 case MessageDefault:
126 break;
127 case MessageAlways:
128 os << " MESSAGE_ALWAYS";
129 break;
130 case MessageLazy:
131 os << " MESSAGE_LAZY";
132 break;
133 case MessageNever:
134 os << " MESSAGE_NEVER";
135 break;
137 if (permissions_file && *permissions_file) {
138 os << " PERMISSIONS" << permissions_file;
140 if (permissions_dir && *permissions_dir) {
141 os << " DIR_PERMISSIONS" << permissions_dir;
143 if (rename && *rename) {
144 os << " RENAME \"" << rename << "\"";
146 os << " FILES";
147 if (files.size() == 1) {
148 os << " \"" << files[0] << "\"";
149 } else {
150 for (std::string const& f : files) {
151 os << "\n" << indent << " \"" << f << "\"";
153 if (files_var) {
154 os << " ${" << files_var << "}";
156 os << "\n" << indent << " ";
157 if (!(literal_args && *literal_args)) {
158 os << " ";
161 if (literal_args && *literal_args) {
162 os << literal_args;
164 os << ")\n";
167 std::string cmInstallGenerator::CreateComponentTest(
168 const std::string& component, bool exclude_from_all, bool all_components)
170 if (all_components) {
171 if (exclude_from_all) {
172 return "CMAKE_INSTALL_COMPONENT";
174 return {};
177 std::string result = "CMAKE_INSTALL_COMPONENT STREQUAL \"";
178 result += component;
179 result += "\"";
180 if (!exclude_from_all) {
181 result += " OR NOT CMAKE_INSTALL_COMPONENT";
184 return result;
187 void cmInstallGenerator::GenerateScript(std::ostream& os)
189 // Track indentation.
190 Indent indent;
192 std::string component_test = this->CreateComponentTest(
193 this->Component, this->ExcludeFromAll, this->AllComponents);
195 // Begin this block of installation.
196 if (!component_test.empty()) {
197 os << indent << "if(" << component_test << ")\n";
200 // Generate the script possibly with per-configuration code.
201 this->GenerateScriptConfigs(os,
202 this->AllComponents ? indent : indent.Next());
204 // End this block of installation.
205 if (!component_test.empty()) {
206 os << indent << "endif()\n\n";
210 bool cmInstallGenerator::InstallsForConfig(const std::string& config)
212 return this->GeneratesForConfig(config);
215 std::string cmInstallGenerator::ConvertToAbsoluteDestination(
216 std::string const& dest)
218 std::string result;
219 if (!dest.empty() && !cmSystemTools::FileIsFullPath(dest)) {
220 result = "${CMAKE_INSTALL_PREFIX}/";
222 result += dest;
223 return result;
226 cmInstallGenerator::MessageLevel cmInstallGenerator::SelectMessageLevel(
227 cmMakefile* mf, bool never)
229 if (never) {
230 return MessageNever;
232 std::string m = mf->GetSafeDefinition("CMAKE_INSTALL_MESSAGE");
233 if (m == "ALWAYS") {
234 return MessageAlways;
236 if (m == "LAZY") {
237 return MessageLazy;
239 if (m == "NEVER") {
240 return MessageNever;
242 return MessageDefault;
245 std::string cmInstallGenerator::GetDestDirPath(std::string const& file)
247 // Construct the path of the file on disk after installation on
248 // which tweaks may be performed.
249 std::string toDestDirPath = "$ENV{DESTDIR}";
250 if (file[0] != '/' && file[0] != '$') {
251 toDestDirPath += "/";
253 toDestDirPath += file;
254 return toDestDirPath;
257 void cmInstallGenerator::AddTweak(std::ostream& os, Indent indent,
258 const std::string& config,
259 std::string const& file,
260 const TweakMethod& tweak)
262 std::ostringstream tw;
263 tweak(tw, indent.Next(), config, file);
264 std::string tws = tw.str();
265 if (!tws.empty()) {
266 os << indent << "if(EXISTS \"" << file << "\" AND\n"
267 << indent << " NOT IS_SYMLINK \"" << file << "\")\n";
268 os << tws;
269 os << indent << "endif()\n";
273 void cmInstallGenerator::AddTweak(std::ostream& os, Indent indent,
274 const std::string& config,
275 std::string const& dir,
276 std::vector<std::string> const& files,
277 const TweakMethod& tweak)
279 if (files.size() == 1) {
280 // Tweak a single file.
281 AddTweak(os, indent, config, GetDestDirPath(cmStrCat(dir, files[0])),
282 tweak);
283 } else {
284 // Generate a foreach loop to tweak multiple files.
285 std::ostringstream tw;
286 AddTweak(tw, indent.Next(), config, "${file}", tweak);
287 std::string tws = tw.str();
288 if (!tws.empty()) {
289 Indent indent2 = indent.Next().Next();
290 os << indent << "foreach(file\n";
291 for (std::string const& f : files) {
292 os << indent2 << "\"" << GetDestDirPath(cmStrCat(dir, f)) << "\"\n";
294 os << indent2 << ")\n";
295 os << tws;
296 os << indent << "endforeach()\n";