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"
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
))
20 , ExcludeFromAll(exclude_from_all
)
21 , AllComponents(all_components
)
22 , Backtrace(std::move(backtrace
))
26 cmInstallGenerator::~cmInstallGenerator() = default;
28 bool cmInstallGenerator::HaveInstall()
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.
52 case cmInstallType_DIRECTORY
:
55 case cmInstallType_PROGRAMS
:
58 case cmInstallType_EXECUTABLE
:
61 case cmInstallType_STATIC_LIBRARY
:
62 stype
= "STATIC_LIBRARY";
64 case cmInstallType_SHARED_LIBRARY
:
65 stype
= "SHARED_LIBRARY";
67 case cmInstallType_MODULE_LIBRARY
:
70 case cmInstallType_FILES
:
74 if (cmSystemTools::FileIsFullPath(dest
)) {
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
) {
84 if (rename
&& *rename
) {
87 os
<< cmSystemTools::GetFilenameName(file
);
89 firstIteration
= false;
94 os
<< indent
<< "foreach(_cmake_abs_file IN LISTS " << files_var
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";
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";
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 "
124 switch (this->Message
) {
128 os
<< " MESSAGE_ALWAYS";
131 os
<< " MESSAGE_LAZY";
134 os
<< " MESSAGE_NEVER";
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
<< "\"";
147 if (files
.size() == 1) {
148 os
<< " \"" << files
[0] << "\"";
150 for (std::string
const& f
: files
) {
151 os
<< "\n" << indent
<< " \"" << f
<< "\"";
154 os
<< " ${" << files_var
<< "}";
156 os
<< "\n" << indent
<< " ";
157 if (!(literal_args
&& *literal_args
)) {
161 if (literal_args
&& *literal_args
) {
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";
177 std::string result
= "CMAKE_INSTALL_COMPONENT STREQUAL \"";
180 if (!exclude_from_all
) {
181 result
+= " OR NOT CMAKE_INSTALL_COMPONENT";
187 void cmInstallGenerator::GenerateScript(std::ostream
& os
)
189 // Track indentation.
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
)
219 if (!dest
.empty() && !cmSystemTools::FileIsFullPath(dest
)) {
220 result
= "${CMAKE_INSTALL_PREFIX}/";
226 cmInstallGenerator::MessageLevel
cmInstallGenerator::SelectMessageLevel(
227 cmMakefile
* mf
, bool never
)
232 std::string m
= mf
->GetSafeDefinition("CMAKE_INSTALL_MESSAGE");
234 return MessageAlways
;
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();
266 os
<< indent
<< "if(EXISTS \"" << file
<< "\" AND\n"
267 << indent
<< " NOT IS_SYMLINK \"" << file
<< "\")\n";
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])),
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();
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";
296 os
<< indent
<< "endforeach()\n";