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 "cmInstallCommand.h"
4
5 #include <algorithm>
6 #include <cassert>
7 #include <cstddef>
8 #include <iterator>
9 #include <set>
10 #include <sstream>
11 #include <utility>
12
13 #include <cm/memory>
14 #include <cmext/string_view>
15
16 #include "cmsys/Glob.hxx"
17
18 #include "cmArgumentParser.h"
19 #include "cmExecutionStatus.h"
20 #include "cmExportSet.h"
21 #include "cmGeneratorExpression.h"
22 #include "cmGlobalGenerator.h"
23 #include "cmInstallCommandArguments.h"
24 #include "cmInstallDirectoryGenerator.h"
25 #include "cmInstallExportGenerator.h"
26 #include "cmInstallFilesGenerator.h"
27 #include "cmInstallGenerator.h"
28 #include "cmInstallGetRuntimeDependenciesGenerator.h"
29 #include "cmInstallImportedRuntimeArtifactsGenerator.h"
30 #include "cmInstallRuntimeDependencySet.h"
31 #include "cmInstallRuntimeDependencySetGenerator.h"
32 #include "cmInstallScriptGenerator.h"
33 #include "cmInstallTargetGenerator.h"
34 #include "cmListFileCache.h"
35 #include "cmMakefile.h"
36 #include "cmMessageType.h"
37 #include "cmPolicies.h"
38 #include "cmRange.h"
39 #include "cmRuntimeDependencyArchive.h"
40 #include "cmStateTypes.h"
41 #include "cmStringAlgorithms.h"
42 #include "cmSubcommandTable.h"
43 #include "cmSystemTools.h"
44 #include "cmTarget.h"
45 #include "cmTargetExport.h"
46 #include "cmValue.h"
47
48 namespace {
49
50 struct RuntimeDependenciesArgs
51 {
52 std::vector<std::string> Directories;
53 std::vector<std::string> PreIncludeRegexes;
54 std::vector<std::string> PreExcludeRegexes;
55 std::vector<std::string> PostIncludeRegexes;
56 std::vector<std::string> PostExcludeRegexes;
57 std::vector<std::string> PostIncludeFiles;
58 std::vector<std::string> PostExcludeFiles;
59 };
60
61 auto const RuntimeDependenciesArgHelper =
62 cmArgumentParser<RuntimeDependenciesArgs>{}
63 .Bind("DIRECTORIES"_s, &RuntimeDependenciesArgs::Directories)
64 .Bind("PRE_INCLUDE_REGEXES"_s, &RuntimeDependenciesArgs::PreIncludeRegexes)
65 .Bind("PRE_EXCLUDE_REGEXES"_s, &RuntimeDependenciesArgs::PreExcludeRegexes)
66 .Bind("POST_INCLUDE_REGEXES"_s,
67 &RuntimeDependenciesArgs::PostIncludeRegexes)
68 .Bind("POST_EXCLUDE_REGEXES"_s,
69 &RuntimeDependenciesArgs::PostExcludeRegexes)
70 .Bind("POST_INCLUDE_FILES"_s, &RuntimeDependenciesArgs::PostIncludeFiles)
71 .Bind("POST_EXCLUDE_FILES"_s, &RuntimeDependenciesArgs::PostExcludeFiles);
72
73 class Helper
74 {
75 public:
Helper(cmExecutionStatus & status)76 Helper(cmExecutionStatus& status)
77 : Status(status)
78 , Makefile(&status.GetMakefile())
79 {
80 this->DefaultComponentName = this->Makefile->GetSafeDefinition(
81 "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
82 if (this->DefaultComponentName.empty()) {
83 this->DefaultComponentName = "Unspecified";
84 }
85 }
86
SetError(std::string const & err)87 void SetError(std::string const& err) { this->Status.SetError(err); }
88
89 bool MakeFilesFullPath(const char* modeName,
90 const std::vector<std::string>& relFiles,
91 std::vector<std::string>& absFiles);
92 bool CheckCMP0006(bool& failure) const;
93
94 std::string GetDestination(const cmInstallCommandArguments* args,
95 const std::string& varName,
96 const std::string& guess) const;
97 std::string GetRuntimeDestination(
98 const cmInstallCommandArguments* args) const;
99 std::string GetSbinDestination(const cmInstallCommandArguments* args) const;
100 std::string GetArchiveDestination(
101 const cmInstallCommandArguments* args) const;
102 std::string GetLibraryDestination(
103 const cmInstallCommandArguments* args) const;
104 std::string GetIncludeDestination(
105 const cmInstallCommandArguments* args) const;
106 std::string GetSysconfDestination(
107 const cmInstallCommandArguments* args) const;
108 std::string GetSharedStateDestination(
109 const cmInstallCommandArguments* args) const;
110 std::string GetLocalStateDestination(
111 const cmInstallCommandArguments* args) const;
112 std::string GetRunStateDestination(
113 const cmInstallCommandArguments* args) const;
114 std::string GetDataRootDestination(
115 const cmInstallCommandArguments* args) const;
116 std::string GetDataDestination(const cmInstallCommandArguments* args) const;
117 std::string GetInfoDestination(const cmInstallCommandArguments* args) const;
118 std::string GetLocaleDestination(
119 const cmInstallCommandArguments* args) const;
120 std::string GetManDestination(const cmInstallCommandArguments* args) const;
121 std::string GetDocDestination(const cmInstallCommandArguments* args) const;
122 std::string GetDestinationForType(const cmInstallCommandArguments* args,
123 const std::string& type) const;
124
125 cmExecutionStatus& Status;
126 cmMakefile* Makefile;
127 std::string DefaultComponentName;
128 };
129
CreateInstallTargetGenerator(cmTarget & target,const cmInstallCommandArguments & args,bool impLib,cmListFileBacktrace const & backtrace,const std::string & destination,bool forceOpt=false,bool namelink=false)130 std::unique_ptr<cmInstallTargetGenerator> CreateInstallTargetGenerator(
131 cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
132 cmListFileBacktrace const& backtrace, const std::string& destination,
133 bool forceOpt = false, bool namelink = false)
134 {
135 cmInstallGenerator::MessageLevel message =
136 cmInstallGenerator::SelectMessageLevel(target.GetMakefile());
137 target.SetHaveInstallRule(true);
138 const std::string& component =
139 namelink ? args.GetNamelinkComponent() : args.GetComponent();
140 auto g = cm::make_unique<cmInstallTargetGenerator>(
141 target.GetName(), destination, impLib, args.GetPermissions(),
142 args.GetConfigurations(), component, message, args.GetExcludeFromAll(),
143 args.GetOptional() || forceOpt, backtrace);
144 target.AddInstallGenerator(g.get());
145 return g;
146 }
147
CreateInstallTargetGenerator(cmTarget & target,const cmInstallCommandArguments & args,bool impLib,cmListFileBacktrace const & backtrace,bool forceOpt=false,bool namelink=false)148 std::unique_ptr<cmInstallTargetGenerator> CreateInstallTargetGenerator(
149 cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
150 cmListFileBacktrace const& backtrace, bool forceOpt = false,
151 bool namelink = false)
152 {
153 return CreateInstallTargetGenerator(target, args, impLib, backtrace,
154 args.GetDestination(), forceOpt,
155 namelink);
156 }
157
CreateInstallFilesGenerator(cmMakefile * mf,const std::vector<std::string> & absFiles,const cmInstallCommandArguments & args,bool programs,const std::string & destination)158 std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator(
159 cmMakefile* mf, const std::vector<std::string>& absFiles,
160 const cmInstallCommandArguments& args, bool programs,
161 const std::string& destination)
162 {
163 cmInstallGenerator::MessageLevel message =
164 cmInstallGenerator::SelectMessageLevel(mf);
165 return cm::make_unique<cmInstallFilesGenerator>(
166 absFiles, destination, programs, args.GetPermissions(),
167 args.GetConfigurations(), args.GetComponent(), message,
168 args.GetExcludeFromAll(), args.GetRename(), args.GetOptional(),
169 mf->GetBacktrace());
170 }
171
CreateInstallFilesGenerator(cmMakefile * mf,const std::vector<std::string> & absFiles,const cmInstallCommandArguments & args,bool programs)172 std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator(
173 cmMakefile* mf, const std::vector<std::string>& absFiles,
174 const cmInstallCommandArguments& args, bool programs)
175 {
176 return CreateInstallFilesGenerator(mf, absFiles, args, programs,
177 args.GetDestination());
178 }
179
AddInstallRuntimeDependenciesGenerator(Helper & helper,cmInstallRuntimeDependencySet * runtimeDependencySet,const cmInstallCommandArguments & runtimeArgs,const cmInstallCommandArguments & libraryArgs,const cmInstallCommandArguments & frameworkArgs,RuntimeDependenciesArgs runtimeDependenciesArgs,bool & installsRuntime,bool & installsLibrary,bool & installsFramework)180 void AddInstallRuntimeDependenciesGenerator(
181 Helper& helper, cmInstallRuntimeDependencySet* runtimeDependencySet,
182 const cmInstallCommandArguments& runtimeArgs,
183 const cmInstallCommandArguments& libraryArgs,
184 const cmInstallCommandArguments& frameworkArgs,
185 RuntimeDependenciesArgs runtimeDependenciesArgs, bool& installsRuntime,
186 bool& installsLibrary, bool& installsFramework)
187 {
188 bool dllPlatform =
189 !helper.Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
190 bool apple =
191 helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME") == "Darwin";
192 auto const& runtimeDependenciesArgsRef =
193 dllPlatform ? runtimeArgs : libraryArgs;
194 std::vector<std::string> configurations =
195 runtimeDependenciesArgsRef.GetConfigurations();
196 if (apple) {
197 std::copy(frameworkArgs.GetConfigurations().begin(),
198 frameworkArgs.GetConfigurations().end(),
199 std::back_inserter(configurations));
200 }
201
202 // Create file(GET_RUNTIME_DEPENDENCIES) generator.
203 auto getRuntimeDependenciesGenerator =
204 cm::make_unique<cmInstallGetRuntimeDependenciesGenerator>(
205 runtimeDependencySet, std::move(runtimeDependenciesArgs.Directories),
206 std::move(runtimeDependenciesArgs.PreIncludeRegexes),
207 std::move(runtimeDependenciesArgs.PreExcludeRegexes),
208 std::move(runtimeDependenciesArgs.PostIncludeRegexes),
209 std::move(runtimeDependenciesArgs.PostExcludeRegexes),
210 std::move(runtimeDependenciesArgs.PostIncludeFiles),
211 std::move(runtimeDependenciesArgs.PostExcludeFiles),
212 runtimeDependenciesArgsRef.GetComponent(),
213 apple ? frameworkArgs.GetComponent() : "", true, "_CMAKE_DEPS",
214 "_CMAKE_RPATH", configurations,
215 cmInstallGenerator::SelectMessageLevel(helper.Makefile),
216 runtimeDependenciesArgsRef.GetExcludeFromAll() &&
217 (apple ? frameworkArgs.GetExcludeFromAll() : true),
218 helper.Makefile->GetBacktrace());
219 helper.Makefile->AddInstallGenerator(
220 std::move(getRuntimeDependenciesGenerator));
221
222 // Create the library dependencies generator.
223 auto libraryRuntimeDependenciesGenerator =
224 cm::make_unique<cmInstallRuntimeDependencySetGenerator>(
225 cmInstallRuntimeDependencySetGenerator::DependencyType::Library,
226 runtimeDependencySet, std::vector<std::string>{}, true, std::string{},
227 true, "_CMAKE_DEPS", "_CMAKE_RPATH", "_CMAKE_TMP",
228 dllPlatform ? helper.GetRuntimeDestination(&runtimeArgs)
229 : helper.GetLibraryDestination(&libraryArgs),
230 runtimeDependenciesArgsRef.GetConfigurations(),
231 runtimeDependenciesArgsRef.GetComponent(),
232 runtimeDependenciesArgsRef.GetPermissions(),
233 cmInstallGenerator::SelectMessageLevel(helper.Makefile),
234 runtimeDependenciesArgsRef.GetExcludeFromAll(),
235 helper.Makefile->GetBacktrace());
236 helper.Makefile->AddInstallGenerator(
237 std::move(libraryRuntimeDependenciesGenerator));
238 if (dllPlatform) {
239 installsRuntime = true;
240 } else {
241 installsLibrary = true;
242 }
243
244 if (apple) {
245 // Create the framework dependencies generator.
246 auto frameworkRuntimeDependenciesGenerator =
247 cm::make_unique<cmInstallRuntimeDependencySetGenerator>(
248 cmInstallRuntimeDependencySetGenerator::DependencyType::Framework,
249 runtimeDependencySet, std::vector<std::string>{}, true, std::string{},
250 true, "_CMAKE_DEPS", "_CMAKE_RPATH", "_CMAKE_TMP",
251 frameworkArgs.GetDestination(), frameworkArgs.GetConfigurations(),
252 frameworkArgs.GetComponent(), frameworkArgs.GetPermissions(),
253 cmInstallGenerator::SelectMessageLevel(helper.Makefile),
254 frameworkArgs.GetExcludeFromAll(), helper.Makefile->GetBacktrace());
255 helper.Makefile->AddInstallGenerator(
256 std::move(frameworkRuntimeDependenciesGenerator));
257 installsFramework = true;
258 }
259 }
260
261 std::set<std::string> const allowedTypes{
262 "BIN", "SBIN", "LIB", "INCLUDE", "SYSCONF",
263 "SHAREDSTATE", "LOCALSTATE", "RUNSTATE", "DATA", "INFO",
264 "LOCALE", "MAN", "DOC",
265 };
266
267 template <typename T>
AddBundleExecutable(Helper & helper,cmInstallRuntimeDependencySet * runtimeDependencySet,T && bundleExecutable)268 bool AddBundleExecutable(Helper& helper,
269 cmInstallRuntimeDependencySet* runtimeDependencySet,
270 T&& bundleExecutable)
271 {
272 if (!runtimeDependencySet->AddBundleExecutable(bundleExecutable)) {
273 helper.SetError(
274 "A runtime dependency set may only have one bundle executable.");
275 return false;
276 }
277 return true;
278 }
279
HandleScriptMode(std::vector<std::string> const & args,cmExecutionStatus & status)280 bool HandleScriptMode(std::vector<std::string> const& args,
281 cmExecutionStatus& status)
282 {
283 Helper helper(status);
284
285 std::string component = helper.DefaultComponentName;
286 int componentCount = 0;
287 bool doing_script = false;
288 bool doing_code = false;
289 bool exclude_from_all = false;
290 bool all_components = false;
291
292 // Scan the args once for COMPONENT. Only allow one.
293 //
294 for (size_t i = 0; i < args.size(); ++i) {
295 if (args[i] == "COMPONENT" && i + 1 < args.size()) {
296 ++componentCount;
297 ++i;
298 component = args[i];
299 }
300 if (args[i] == "EXCLUDE_FROM_ALL") {
301 exclude_from_all = true;
302 } else if (args[i] == "ALL_COMPONENTS") {
303 all_components = true;
304 }
305 }
306
307 if (componentCount > 1) {
308 status.SetError("given more than one COMPONENT for the SCRIPT or CODE "
309 "signature of the INSTALL command. "
310 "Use multiple INSTALL commands with one COMPONENT each.");
311 return false;
312 }
313
314 if (all_components && componentCount == 1) {
315 status.SetError("ALL_COMPONENTS and COMPONENT are mutually exclusive");
316 return false;
317 }
318
319 // Scan the args again, this time adding install generators each time we
320 // encounter a SCRIPT or CODE arg:
321 //
322 for (std::string const& arg : args) {
323 if (arg == "SCRIPT") {
324 doing_script = true;
325 doing_code = false;
326 } else if (arg == "CODE") {
327 doing_script = false;
328 doing_code = true;
329 } else if (arg == "COMPONENT") {
330 doing_script = false;
331 doing_code = false;
332 } else if (doing_script) {
333 doing_script = false;
334 std::string script = arg;
335 if (!cmSystemTools::FileIsFullPath(script)) {
336 script =
337 cmStrCat(helper.Makefile->GetCurrentSourceDirectory(), '/', arg);
338 }
339 if (cmSystemTools::FileIsDirectory(script)) {
340 status.SetError("given a directory as value of SCRIPT argument.");
341 return false;
342 }
343 helper.Makefile->AddInstallGenerator(
344 cm::make_unique<cmInstallScriptGenerator>(
345 script, false, component, exclude_from_all, all_components,
346 helper.Makefile->GetBacktrace()));
347 } else if (doing_code) {
348 doing_code = false;
349 std::string const& code = arg;
350 helper.Makefile->AddInstallGenerator(
351 cm::make_unique<cmInstallScriptGenerator>(
352 code, true, component, exclude_from_all, all_components,
353 helper.Makefile->GetBacktrace()));
354 }
355 }
356
357 if (doing_script) {
358 status.SetError("given no value for SCRIPT argument.");
359 return false;
360 }
361 if (doing_code) {
362 status.SetError("given no value for CODE argument.");
363 return false;
364 }
365
366 // Tell the global generator about any installation component names
367 // specified.
368 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(component);
369
370 return true;
371 }
372
HandleTargetsMode(std::vector<std::string> const & args,cmExecutionStatus & status)373 bool HandleTargetsMode(std::vector<std::string> const& args,
374 cmExecutionStatus& status)
375 {
376 Helper helper(status);
377
378 // This is the TARGETS mode.
379 std::vector<cmTarget*> targets;
380
381 struct ArgVectors
382 {
383 std::vector<std::string> Archive;
384 std::vector<std::string> Library;
385 std::vector<std::string> Runtime;
386 std::vector<std::string> Object;
387 std::vector<std::string> Framework;
388 std::vector<std::string> Bundle;
389 std::vector<std::string> Includes;
390 std::vector<std::string> PrivateHeader;
391 std::vector<std::string> PublicHeader;
392 std::vector<std::string> Resource;
393 };
394
395 static auto const argHelper =
396 cmArgumentParser<ArgVectors>{}
397 .Bind("ARCHIVE"_s, &ArgVectors::Archive)
398 .Bind("LIBRARY"_s, &ArgVectors::Library)
399 .Bind("RUNTIME"_s, &ArgVectors::Runtime)
400 .Bind("OBJECTS"_s, &ArgVectors::Object)
401 .Bind("FRAMEWORK"_s, &ArgVectors::Framework)
402 .Bind("BUNDLE"_s, &ArgVectors::Bundle)
403 .Bind("INCLUDES"_s, &ArgVectors::Includes)
404 .Bind("PRIVATE_HEADER"_s, &ArgVectors::PrivateHeader)
405 .Bind("PUBLIC_HEADER"_s, &ArgVectors::PublicHeader)
406 .Bind("RESOURCE"_s, &ArgVectors::Resource);
407
408 std::vector<std::string> genericArgVector;
409 ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
410
411 // now parse the generic args (i.e. the ones not specialized on LIBRARY/
412 // ARCHIVE, RUNTIME etc. (see above)
413 // These generic args also contain the targets and the export stuff
414 std::vector<std::string> targetList;
415 std::string exports;
416 std::vector<std::string> runtimeDependenciesArgVector;
417 std::string runtimeDependencySetArg;
418 std::vector<std::string> unknownArgs;
419 std::vector<std::string> parsedArgs;
420 cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
421 genericArgs.Bind("TARGETS"_s, targetList);
422 genericArgs.Bind("EXPORT"_s, exports);
423 genericArgs.Bind("RUNTIME_DEPENDENCIES"_s, runtimeDependenciesArgVector);
424 genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
425 genericArgs.Parse(genericArgVector, &unknownArgs, nullptr, &parsedArgs);
426 bool success = genericArgs.Finalize();
427
428 bool withRuntimeDependencies =
429 std::find(parsedArgs.begin(), parsedArgs.end(), "RUNTIME_DEPENDENCIES") !=
430 parsedArgs.end();
431 RuntimeDependenciesArgs runtimeDependenciesArgs =
432 RuntimeDependenciesArgHelper.Parse(runtimeDependenciesArgVector,
433 &unknownArgs);
434
435 cmInstallCommandArguments archiveArgs(helper.DefaultComponentName);
436 cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
437 cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
438 cmInstallCommandArguments objectArgs(helper.DefaultComponentName);
439 cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
440 cmInstallCommandArguments bundleArgs(helper.DefaultComponentName);
441 cmInstallCommandArguments privateHeaderArgs(helper.DefaultComponentName);
442 cmInstallCommandArguments publicHeaderArgs(helper.DefaultComponentName);
443 cmInstallCommandArguments resourceArgs(helper.DefaultComponentName);
444 cmInstallCommandIncludesArgument includesArgs;
445
446 // now parse the args for specific parts of the target (e.g. LIBRARY,
447 // RUNTIME, ARCHIVE etc.
448 archiveArgs.Parse(argVectors.Archive, &unknownArgs);
449 libraryArgs.Parse(argVectors.Library, &unknownArgs);
450 runtimeArgs.Parse(argVectors.Runtime, &unknownArgs);
451 objectArgs.Parse(argVectors.Object, &unknownArgs);
452 frameworkArgs.Parse(argVectors.Framework, &unknownArgs);
453 bundleArgs.Parse(argVectors.Bundle, &unknownArgs);
454 privateHeaderArgs.Parse(argVectors.PrivateHeader, &unknownArgs);
455 publicHeaderArgs.Parse(argVectors.PublicHeader, &unknownArgs);
456 resourceArgs.Parse(argVectors.Resource, &unknownArgs);
457 includesArgs.Parse(&argVectors.Includes, &unknownArgs);
458
459 if (!unknownArgs.empty()) {
460 // Unknown argument.
461 status.SetError(
462 cmStrCat("TARGETS given unknown argument \"", unknownArgs[0], "\"."));
463 return false;
464 }
465
466 // apply generic args
467 archiveArgs.SetGenericArguments(&genericArgs);
468 libraryArgs.SetGenericArguments(&genericArgs);
469 runtimeArgs.SetGenericArguments(&genericArgs);
470 objectArgs.SetGenericArguments(&genericArgs);
471 frameworkArgs.SetGenericArguments(&genericArgs);
472 bundleArgs.SetGenericArguments(&genericArgs);
473 privateHeaderArgs.SetGenericArguments(&genericArgs);
474 publicHeaderArgs.SetGenericArguments(&genericArgs);
475 resourceArgs.SetGenericArguments(&genericArgs);
476
477 success = success && archiveArgs.Finalize();
478 success = success && libraryArgs.Finalize();
479 success = success && runtimeArgs.Finalize();
480 success = success && objectArgs.Finalize();
481 success = success && frameworkArgs.Finalize();
482 success = success && bundleArgs.Finalize();
483 success = success && privateHeaderArgs.Finalize();
484 success = success && publicHeaderArgs.Finalize();
485 success = success && resourceArgs.Finalize();
486
487 if (!success) {
488 return false;
489 }
490
491 // Enforce argument rules too complex to specify for the
492 // general-purpose parser.
493 if (archiveArgs.GetNamelinkOnly() || runtimeArgs.GetNamelinkOnly() ||
494 objectArgs.GetNamelinkOnly() || frameworkArgs.GetNamelinkOnly() ||
495 bundleArgs.GetNamelinkOnly() || privateHeaderArgs.GetNamelinkOnly() ||
496 publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly()) {
497 status.SetError(
498 "TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
499 "The NAMELINK_ONLY option may be specified only following LIBRARY.");
500 return false;
501 }
502 if (archiveArgs.GetNamelinkSkip() || runtimeArgs.GetNamelinkSkip() ||
503 objectArgs.GetNamelinkSkip() || frameworkArgs.GetNamelinkSkip() ||
504 bundleArgs.GetNamelinkSkip() || privateHeaderArgs.GetNamelinkSkip() ||
505 publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip()) {
506 status.SetError(
507 "TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
508 "The NAMELINK_SKIP option may be specified only following LIBRARY.");
509 return false;
510 }
511 if (archiveArgs.HasNamelinkComponent() ||
512 runtimeArgs.HasNamelinkComponent() ||
513 objectArgs.HasNamelinkComponent() ||
514 frameworkArgs.HasNamelinkComponent() ||
515 bundleArgs.HasNamelinkComponent() ||
516 privateHeaderArgs.HasNamelinkComponent() ||
517 publicHeaderArgs.HasNamelinkComponent() ||
518 resourceArgs.HasNamelinkComponent()) {
519 status.SetError(
520 "TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. "
521 "The NAMELINK_COMPONENT option may be specified only following "
522 "LIBRARY.");
523 return false;
524 }
525 if (libraryArgs.GetNamelinkOnly() && libraryArgs.GetNamelinkSkip()) {
526 status.SetError("TARGETS given NAMELINK_ONLY and NAMELINK_SKIP. "
527 "At most one of these two options may be specified.");
528 return false;
529 }
530 if (!genericArgs.GetType().empty() || !archiveArgs.GetType().empty() ||
531 !libraryArgs.GetType().empty() || !runtimeArgs.GetType().empty() ||
532 !objectArgs.GetType().empty() || !frameworkArgs.GetType().empty() ||
533 !bundleArgs.GetType().empty() || !privateHeaderArgs.GetType().empty() ||
534 !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty()) {
535 status.SetError(
536 "TARGETS given TYPE option. The TYPE option may only be specified in "
537 " install(FILES) and install(DIRECTORIES).");
538 return false;
539 }
540
541 cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr;
542 if (withRuntimeDependencies) {
543 if (!runtimeDependencySetArg.empty()) {
544 status.SetError("TARGETS cannot have both RUNTIME_DEPENDENCIES and "
545 "RUNTIME_DEPENDENCY_SET.");
546 return false;
547 }
548 auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
549 if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
550 system)) {
551 status.SetError(
552 cmStrCat("TARGETS RUNTIME_DEPENDENCIES is not supported on system \"",
553 system, '"'));
554 return false;
555 }
556 if (helper.Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
557 status.SetError("TARGETS RUNTIME_DEPENDENCIES is not supported "
558 "when cross-compiling.");
559 return false;
560 }
561 if (helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME") ==
562 "Darwin" &&
563 frameworkArgs.GetDestination().empty()) {
564 status.SetError(
565 "TARGETS RUNTIME_DEPENDENCIES given no FRAMEWORK DESTINATION");
566 return false;
567 }
568 runtimeDependencySet = helper.Makefile->GetGlobalGenerator()
569 ->CreateAnonymousRuntimeDependencySet();
570 } else if (!runtimeDependencySetArg.empty()) {
571 auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
572 if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
573 system)) {
574 status.SetError(cmStrCat(
575 "TARGETS RUNTIME_DEPENDENCY_SET is not supported on system \"", system,
576 '"'));
577 return false;
578 }
579 runtimeDependencySet =
580 helper.Makefile->GetGlobalGenerator()->GetNamedRuntimeDependencySet(
581 runtimeDependencySetArg);
582 }
583
584 // Select the mode for installing symlinks to versioned shared libraries.
585 cmInstallTargetGenerator::NamelinkModeType namelinkMode =
586 cmInstallTargetGenerator::NamelinkModeNone;
587 if (libraryArgs.GetNamelinkOnly()) {
588 namelinkMode = cmInstallTargetGenerator::NamelinkModeOnly;
589 } else if (libraryArgs.GetNamelinkSkip()) {
590 namelinkMode = cmInstallTargetGenerator::NamelinkModeSkip;
591 }
592
593 // Check if there is something to do.
594 if (targetList.empty()) {
595 return true;
596 }
597
598 for (std::string const& tgt : targetList) {
599
600 if (helper.Makefile->IsAlias(tgt)) {
601 status.SetError(
602 cmStrCat("TARGETS given target \"", tgt, "\" which is an alias."));
603 return false;
604 }
605 // Lookup this target in the current directory.
606 cmTarget* target = helper.Makefile->FindLocalNonAliasTarget(tgt);
607 if (!target) {
608 // If no local target has been found, find it in the global scope.
609 cmTarget* const global_target =
610 helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true);
611 if (global_target && !global_target->IsImported()) {
612 target = global_target;
613 }
614 }
615 if (target) {
616 // Found the target. Check its type.
617 if (target->GetType() != cmStateEnums::EXECUTABLE &&
618 target->GetType() != cmStateEnums::STATIC_LIBRARY &&
619 target->GetType() != cmStateEnums::SHARED_LIBRARY &&
620 target->GetType() != cmStateEnums::MODULE_LIBRARY &&
621 target->GetType() != cmStateEnums::OBJECT_LIBRARY &&
622 target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
623 status.SetError(
624 cmStrCat("TARGETS given target \"", tgt,
625 "\" which is not an executable, library, or module."));
626 return false;
627 }
628 // Store the target in the list to be installed.
629 targets.push_back(target);
630 } else {
631 // Did not find the target.
632 status.SetError(
633 cmStrCat("TARGETS given target \"", tgt, "\" which does not exist."));
634 return false;
635 }
636 }
637
638 // Keep track of whether we will be performing an installation of
639 // any files of the given type.
640 bool installsArchive = false;
641 bool installsLibrary = false;
642 bool installsNamelink = false;
643 bool installsRuntime = false;
644 bool installsObject = false;
645 bool installsFramework = false;
646 bool installsBundle = false;
647 bool installsPrivateHeader = false;
648 bool installsPublicHeader = false;
649 bool installsResource = false;
650
651 // Generate install script code to install the given targets.
652 for (cmTarget* ti : targets) {
653 // Handle each target type.
654 cmTarget& target = *ti;
655 std::unique_ptr<cmInstallTargetGenerator> archiveGenerator;
656 std::unique_ptr<cmInstallTargetGenerator> libraryGenerator;
657 std::unique_ptr<cmInstallTargetGenerator> namelinkGenerator;
658 std::unique_ptr<cmInstallTargetGenerator> runtimeGenerator;
659 std::unique_ptr<cmInstallTargetGenerator> objectGenerator;
660 std::unique_ptr<cmInstallTargetGenerator> frameworkGenerator;
661 std::unique_ptr<cmInstallTargetGenerator> bundleGenerator;
662 std::unique_ptr<cmInstallFilesGenerator> privateHeaderGenerator;
663 std::unique_ptr<cmInstallFilesGenerator> publicHeaderGenerator;
664 std::unique_ptr<cmInstallFilesGenerator> resourceGenerator;
665
666 // Avoid selecting default destinations for PUBLIC_HEADER and
667 // PRIVATE_HEADER if any artifacts are specified.
668 bool artifactsSpecified = false;
669
670 // Track whether this is a namelink-only rule.
671 bool namelinkOnly = false;
672
673 auto addTargetExport = [&]() {
674 // Add this install rule to an export if one was specified.
675 if (!exports.empty()) {
676 auto te = cm::make_unique<cmTargetExport>();
677 te->TargetName = target.GetName();
678 te->ArchiveGenerator = archiveGenerator.get();
679 te->BundleGenerator = bundleGenerator.get();
680 te->FrameworkGenerator = frameworkGenerator.get();
681 te->HeaderGenerator = publicHeaderGenerator.get();
682 te->LibraryGenerator = libraryGenerator.get();
683 te->RuntimeGenerator = runtimeGenerator.get();
684 te->ObjectsGenerator = objectGenerator.get();
685 target.AddInstallIncludeDirectories(
686 cmMakeRange(includesArgs.GetIncludeDirs()));
687 te->NamelinkOnly = namelinkOnly;
688 helper.Makefile->GetGlobalGenerator()
689 ->GetExportSets()[exports]
690 .AddTargetExport(std::move(te));
691 }
692 };
693
694 switch (target.GetType()) {
695 case cmStateEnums::SHARED_LIBRARY: {
696 // Shared libraries are handled differently on DLL and non-DLL
697 // platforms. All windows platforms are DLL platforms including
698 // cygwin. Currently no other platform is a DLL platform.
699 if (target.IsDLLPlatform()) {
700 // When in namelink only mode skip all libraries on Windows.
701 if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
702 namelinkOnly = true;
703 addTargetExport();
704 continue;
705 }
706
707 // This is a DLL platform.
708 if (!archiveArgs.GetDestination().empty()) {
709 // The import library uses the ARCHIVE properties.
710 archiveGenerator = CreateInstallTargetGenerator(
711 target, archiveArgs, true, helper.Makefile->GetBacktrace());
712 artifactsSpecified = true;
713 }
714 if (!runtimeArgs.GetDestination().empty()) {
715 // The DLL uses the RUNTIME properties.
716 runtimeGenerator = CreateInstallTargetGenerator(
717 target, runtimeArgs, false, helper.Makefile->GetBacktrace());
718 artifactsSpecified = true;
719 }
720 if (!archiveGenerator && !runtimeGenerator) {
721 archiveGenerator = CreateInstallTargetGenerator(
722 target, archiveArgs, true, helper.Makefile->GetBacktrace(),
723 helper.GetArchiveDestination(nullptr));
724 runtimeGenerator = CreateInstallTargetGenerator(
725 target, runtimeArgs, false, helper.Makefile->GetBacktrace(),
726 helper.GetRuntimeDestination(nullptr));
727 }
728 if (runtimeDependencySet && runtimeGenerator) {
729 runtimeDependencySet->AddLibrary(runtimeGenerator.get());
730 }
731 } else {
732 // This is a non-DLL platform.
733 // If it is marked with FRAMEWORK property use the FRAMEWORK set of
734 // INSTALL properties. Otherwise, use the LIBRARY properties.
735 if (target.IsFrameworkOnApple()) {
736 // When in namelink only mode skip frameworks.
737 if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
738 namelinkOnly = true;
739 addTargetExport();
740 continue;
741 }
742
743 // Use the FRAMEWORK properties.
744 if (!frameworkArgs.GetDestination().empty()) {
745 frameworkGenerator = CreateInstallTargetGenerator(
746 target, frameworkArgs, false, helper.Makefile->GetBacktrace());
747 } else {
748 status.SetError(
749 cmStrCat("TARGETS given no FRAMEWORK DESTINATION for shared "
750 "library FRAMEWORK target \"",
751 target.GetName(), "\"."));
752 return false;
753 }
754 } else {
755 // The shared library uses the LIBRARY properties.
756 if (!libraryArgs.GetDestination().empty()) {
757 artifactsSpecified = true;
758 }
759 if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) {
760 libraryGenerator = CreateInstallTargetGenerator(
761 target, libraryArgs, false, helper.Makefile->GetBacktrace(),
762 helper.GetLibraryDestination(&libraryArgs));
763 libraryGenerator->SetNamelinkMode(
764 cmInstallTargetGenerator::NamelinkModeSkip);
765 }
766 if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) {
767 namelinkGenerator = CreateInstallTargetGenerator(
768 target, libraryArgs, false, helper.Makefile->GetBacktrace(),
769 helper.GetLibraryDestination(&libraryArgs), false, true);
770 namelinkGenerator->SetNamelinkMode(
771 cmInstallTargetGenerator::NamelinkModeOnly);
772 }
773 namelinkOnly =
774 (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
775 }
776 if (runtimeDependencySet && libraryGenerator) {
777 runtimeDependencySet->AddLibrary(libraryGenerator.get());
778 }
779 }
780 } break;
781 case cmStateEnums::STATIC_LIBRARY: {
782 // If it is marked with FRAMEWORK property use the FRAMEWORK set of
783 // INSTALL properties. Otherwise, use the LIBRARY properties.
784 if (target.IsFrameworkOnApple()) {
785 // When in namelink only mode skip frameworks.
786 if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
787 namelinkOnly = true;
788 addTargetExport();
789 continue;
790 }
791
792 // Use the FRAMEWORK properties.
793 if (!frameworkArgs.GetDestination().empty()) {
794 frameworkGenerator = CreateInstallTargetGenerator(
795 target, frameworkArgs, false, helper.Makefile->GetBacktrace());
796 } else {
797 status.SetError(
798 cmStrCat("TARGETS given no FRAMEWORK DESTINATION for static "
799 "library FRAMEWORK target \"",
800 target.GetName(), "\"."));
801 return false;
802 }
803 } else {
804 // Static libraries use ARCHIVE properties.
805 if (!archiveArgs.GetDestination().empty()) {
806 artifactsSpecified = true;
807 }
808 archiveGenerator = CreateInstallTargetGenerator(
809 target, archiveArgs, false, helper.Makefile->GetBacktrace(),
810 helper.GetArchiveDestination(&archiveArgs));
811 }
812 } break;
813 case cmStateEnums::MODULE_LIBRARY: {
814 // Modules use LIBRARY properties.
815 if (!libraryArgs.GetDestination().empty()) {
816 libraryGenerator = CreateInstallTargetGenerator(
817 target, libraryArgs, false, helper.Makefile->GetBacktrace());
818 libraryGenerator->SetNamelinkMode(namelinkMode);
819 namelinkOnly =
820 (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
821 if (runtimeDependencySet) {
822 runtimeDependencySet->AddModule(libraryGenerator.get());
823 }
824 } else {
825 status.SetError(
826 cmStrCat("TARGETS given no LIBRARY DESTINATION for module "
827 "target \"",
828 target.GetName(), "\"."));
829 return false;
830 }
831 } break;
832 case cmStateEnums::OBJECT_LIBRARY: {
833 // Objects use OBJECT properties.
834 if (!objectArgs.GetDestination().empty()) {
835 // Verify that we know where the objects are to install them.
836 std::string reason;
837 if (!helper.Makefile->GetGlobalGenerator()
838 ->HasKnownObjectFileLocation(&reason)) {
839 status.SetError(
840 cmStrCat("TARGETS given OBJECT library \"", target.GetName(),
841 "\" whose objects may not be installed", reason, "."));
842 return false;
843 }
844
845 objectGenerator = CreateInstallTargetGenerator(
846 target, objectArgs, false, helper.Makefile->GetBacktrace());
847 } else {
848 // Installing an OBJECT library without a destination transforms
849 // it to an INTERFACE library. It installs no files but can be
850 // exported.
851 }
852 } break;
853 case cmStateEnums::EXECUTABLE: {
854 if (target.IsAppBundleOnApple()) {
855 // Application bundles use the BUNDLE properties.
856 if (!bundleArgs.GetDestination().empty()) {
857 bundleGenerator = CreateInstallTargetGenerator(
858 target, bundleArgs, false, helper.Makefile->GetBacktrace());
859 } else if (!runtimeArgs.GetDestination().empty()) {
860 bool failure = false;
861 if (helper.CheckCMP0006(failure)) {
862 // For CMake 2.4 compatibility fallback to the RUNTIME
863 // properties.
864 bundleGenerator = CreateInstallTargetGenerator(
865 target, runtimeArgs, false, helper.Makefile->GetBacktrace());
866 } else if (failure) {
867 return false;
868 }
869 }
870 if (!bundleGenerator) {
871 status.SetError(cmStrCat("TARGETS given no BUNDLE DESTINATION for "
872 "MACOSX_BUNDLE executable target \"",
873 target.GetName(), "\"."));
874 return false;
875 }
876 if (runtimeDependencySet) {
877 if (!AddBundleExecutable(helper, runtimeDependencySet,
878 bundleGenerator.get())) {
879 return false;
880 }
881 }
882 } else {
883 // Executables use the RUNTIME properties.
884 if (!runtimeArgs.GetDestination().empty()) {
885 artifactsSpecified = true;
886 }
887 runtimeGenerator = CreateInstallTargetGenerator(
888 target, runtimeArgs, false, helper.Makefile->GetBacktrace(),
889 helper.GetRuntimeDestination(&runtimeArgs));
890 if (runtimeDependencySet) {
891 runtimeDependencySet->AddExecutable(runtimeGenerator.get());
892 }
893 }
894
895 // On DLL platforms an executable may also have an import
896 // library. Install it to the archive destination if it
897 // exists.
898 if ((target.IsDLLPlatform() || target.IsAIX()) &&
899 !archiveArgs.GetDestination().empty() &&
900 target.IsExecutableWithExports()) {
901 // The import library uses the ARCHIVE properties.
902 artifactsSpecified = true;
903 archiveGenerator = CreateInstallTargetGenerator(
904 target, archiveArgs, true, helper.Makefile->GetBacktrace(), true);
905 }
906 } break;
907 case cmStateEnums::INTERFACE_LIBRARY:
908 // Nothing to do. An INTERFACE_LIBRARY can be installed, but the
909 // only effect of that is to make it exportable. It installs no
910 // other files itself.
911 default:
912 // This should never happen due to the above type check.
913 // Ignore the case.
914 break;
915 }
916
917 // These well-known sets of files are installed *automatically* for
918 // FRAMEWORK SHARED library targets on the Mac as part of installing the
919 // FRAMEWORK. For other target types or on other platforms, they are not
920 // installed automatically and so we need to create install files
921 // generators for them.
922 bool createInstallGeneratorsForTargetFileSets = true;
923
924 if (target.IsFrameworkOnApple()) {
925 createInstallGeneratorsForTargetFileSets = false;
926 }
927
928 if (createInstallGeneratorsForTargetFileSets && !namelinkOnly) {
929 cmValue files = target.GetProperty("PRIVATE_HEADER");
930 if (cmNonempty(files)) {
931 std::vector<std::string> relFiles = cmExpandedList(*files);
932 std::vector<std::string> absFiles;
933 if (!helper.MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) {
934 return false;
935 }
936
937 // Create the files install generator.
938 if (!artifactsSpecified ||
939 !privateHeaderArgs.GetDestination().empty()) {
940 privateHeaderGenerator = CreateInstallFilesGenerator(
941 helper.Makefile, absFiles, privateHeaderArgs, false,
942 helper.GetIncludeDestination(&privateHeaderArgs));
943 } else {
944 std::ostringstream e;
945 e << "INSTALL TARGETS - target " << target.GetName() << " has "
946 << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
947 cmSystemTools::Message(e.str(), "Warning");
948 }
949 }
950
951 files = target.GetProperty("PUBLIC_HEADER");
952 if (cmNonempty(files)) {
953 std::vector<std::string> relFiles = cmExpandedList(*files);
954 std::vector<std::string> absFiles;
955 if (!helper.MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) {
956 return false;
957 }
958
959 // Create the files install generator.
960 if (!artifactsSpecified ||
961 !publicHeaderArgs.GetDestination().empty()) {
962 publicHeaderGenerator = CreateInstallFilesGenerator(
963 helper.Makefile, absFiles, publicHeaderArgs, false,
964 helper.GetIncludeDestination(&publicHeaderArgs));
965 } else {
966 std::ostringstream e;
967 e << "INSTALL TARGETS - target " << target.GetName() << " has "
968 << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION.";
969 cmSystemTools::Message(e.str(), "Warning");
970 }
971 }
972
973 files = target.GetProperty("RESOURCE");
974 if (cmNonempty(files)) {
975 std::vector<std::string> relFiles = cmExpandedList(*files);
976 std::vector<std::string> absFiles;
977 if (!helper.MakeFilesFullPath("RESOURCE", relFiles, absFiles)) {
978 return false;
979 }
980
981 // Create the files install generator.
982 if (!resourceArgs.GetDestination().empty()) {
983 resourceGenerator = CreateInstallFilesGenerator(
984 helper.Makefile, absFiles, resourceArgs, false);
985 } else if (!target.IsAppBundleOnApple()) {
986 cmSystemTools::Message(
987 cmStrCat("INSTALL TARGETS - target ", target.GetName(),
988 " has RESOURCE files but no RESOURCE DESTINATION."),
989 "Warning");
990 }
991 }
992 }
993
994 // Add this install rule to an export if one was specified.
995 addTargetExport();
996
997 // Keep track of whether we're installing anything in each category
998 installsArchive = installsArchive || archiveGenerator;
999 installsLibrary = installsLibrary || libraryGenerator;
1000 installsNamelink = installsNamelink || namelinkGenerator;
1001 installsRuntime = installsRuntime || runtimeGenerator;
1002 installsObject = installsObject || objectGenerator;
1003 installsFramework = installsFramework || frameworkGenerator;
1004 installsBundle = installsBundle || bundleGenerator;
1005 installsPrivateHeader = installsPrivateHeader || privateHeaderGenerator;
1006 installsPublicHeader = installsPublicHeader || publicHeaderGenerator;
1007 installsResource = installsResource || resourceGenerator;
1008
1009 helper.Makefile->AddInstallGenerator(std::move(archiveGenerator));
1010 helper.Makefile->AddInstallGenerator(std::move(libraryGenerator));
1011 helper.Makefile->AddInstallGenerator(std::move(namelinkGenerator));
1012 helper.Makefile->AddInstallGenerator(std::move(runtimeGenerator));
1013 helper.Makefile->AddInstallGenerator(std::move(objectGenerator));
1014 helper.Makefile->AddInstallGenerator(std::move(frameworkGenerator));
1015 helper.Makefile->AddInstallGenerator(std::move(bundleGenerator));
1016 helper.Makefile->AddInstallGenerator(std::move(privateHeaderGenerator));
1017 helper.Makefile->AddInstallGenerator(std::move(publicHeaderGenerator));
1018 helper.Makefile->AddInstallGenerator(std::move(resourceGenerator));
1019 }
1020
1021 if (withRuntimeDependencies && !runtimeDependencySet->Empty()) {
1022 AddInstallRuntimeDependenciesGenerator(
1023 helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs,
1024 std::move(runtimeDependenciesArgs), installsRuntime, installsLibrary,
1025 installsFramework);
1026 }
1027
1028 // Tell the global generator about any installation component names
1029 // specified
1030 if (installsArchive) {
1031 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1032 archiveArgs.GetComponent());
1033 }
1034 if (installsLibrary) {
1035 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1036 libraryArgs.GetComponent());
1037 }
1038 if (installsNamelink) {
1039 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1040 libraryArgs.GetNamelinkComponent());
1041 }
1042 if (installsRuntime) {
1043 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1044 runtimeArgs.GetComponent());
1045 }
1046 if (installsObject) {
1047 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1048 objectArgs.GetComponent());
1049 }
1050 if (installsFramework) {
1051 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1052 frameworkArgs.GetComponent());
1053 }
1054 if (installsBundle) {
1055 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1056 bundleArgs.GetComponent());
1057 }
1058 if (installsPrivateHeader) {
1059 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1060 privateHeaderArgs.GetComponent());
1061 }
1062 if (installsPublicHeader) {
1063 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1064 publicHeaderArgs.GetComponent());
1065 }
1066 if (installsResource) {
1067 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1068 resourceArgs.GetComponent());
1069 }
1070
1071 return true;
1072 }
1073
HandleImportedRuntimeArtifactsMode(std::vector<std::string> const & args,cmExecutionStatus & status)1074 bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args,
1075 cmExecutionStatus& status)
1076 {
1077 Helper helper(status);
1078
1079 // This is the IMPORTED_RUNTIME_ARTIFACTS mode.
1080 std::vector<cmTarget*> targets;
1081
1082 struct ArgVectors
1083 {
1084 std::vector<std::string> Library;
1085 std::vector<std::string> Runtime;
1086 std::vector<std::string> Framework;
1087 std::vector<std::string> Bundle;
1088 };
1089
1090 static auto const argHelper = cmArgumentParser<ArgVectors>{}
1091 .Bind("LIBRARY"_s, &ArgVectors::Library)
1092 .Bind("RUNTIME"_s, &ArgVectors::Runtime)
1093 .Bind("FRAMEWORK"_s, &ArgVectors::Framework)
1094 .Bind("BUNDLE"_s, &ArgVectors::Bundle);
1095
1096 std::vector<std::string> genericArgVector;
1097 ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
1098
1099 // now parse the generic args (i.e. the ones not specialized on LIBRARY,
1100 // RUNTIME etc. (see above)
1101 std::vector<std::string> targetList;
1102 std::string runtimeDependencySetArg;
1103 std::vector<std::string> unknownArgs;
1104 cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
1105 genericArgs.Bind("IMPORTED_RUNTIME_ARTIFACTS"_s, targetList)
1106 .Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
1107 genericArgs.Parse(genericArgVector, &unknownArgs);
1108 bool success = genericArgs.Finalize();
1109
1110 cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
1111 cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
1112 cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
1113 cmInstallCommandArguments bundleArgs(helper.DefaultComponentName);
1114
1115 // now parse the args for specific parts of the target (e.g. LIBRARY,
1116 // RUNTIME etc.
1117 libraryArgs.Parse(argVectors.Library, &unknownArgs);
1118 runtimeArgs.Parse(argVectors.Runtime, &unknownArgs);
1119 frameworkArgs.Parse(argVectors.Framework, &unknownArgs);
1120 bundleArgs.Parse(argVectors.Bundle, &unknownArgs);
1121
1122 if (!unknownArgs.empty()) {
1123 // Unknown argument.
1124 status.SetError(
1125 cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given unknown argument \"",
1126 unknownArgs[0], "\"."));
1127 return false;
1128 }
1129
1130 // apply generic args
1131 libraryArgs.SetGenericArguments(&genericArgs);
1132 runtimeArgs.SetGenericArguments(&genericArgs);
1133 frameworkArgs.SetGenericArguments(&genericArgs);
1134 bundleArgs.SetGenericArguments(&genericArgs);
1135
1136 success = success && libraryArgs.Finalize();
1137 success = success && runtimeArgs.Finalize();
1138 success = success && frameworkArgs.Finalize();
1139 success = success && bundleArgs.Finalize();
1140
1141 if (!success) {
1142 return false;
1143 }
1144
1145 cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr;
1146 if (!runtimeDependencySetArg.empty()) {
1147 auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
1148 if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
1149 system)) {
1150 status.SetError(
1151 cmStrCat("IMPORTED_RUNTIME_ARTIFACTS RUNTIME_DEPENDENCY_SET is not "
1152 "supported on system \"",
1153 system, '"'));
1154 return false;
1155 }
1156 runtimeDependencySet =
1157 helper.Makefile->GetGlobalGenerator()->GetNamedRuntimeDependencySet(
1158 runtimeDependencySetArg);
1159 }
1160
1161 // Check if there is something to do.
1162 if (targetList.empty()) {
1163 return true;
1164 }
1165
1166 for (std::string const& tgt : targetList) {
1167 if (helper.Makefile->IsAlias(tgt)) {
1168 status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"",
1169 tgt, "\" which is an alias."));
1170 return false;
1171 }
1172 // Lookup this target in the current directory.
1173 cmTarget* target = helper.Makefile->FindTargetToUse(tgt);
1174 if (!target || !target->IsImported()) {
1175 // If no local target has been found, find it in the global scope.
1176 cmTarget* const global_target =
1177 helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true);
1178 if (global_target && global_target->IsImported()) {
1179 target = global_target;
1180 }
1181 }
1182 if (target) {
1183 // Found the target. Check its type.
1184 if (target->GetType() != cmStateEnums::EXECUTABLE &&
1185 target->GetType() != cmStateEnums::SHARED_LIBRARY &&
1186 target->GetType() != cmStateEnums::MODULE_LIBRARY) {
1187 status.SetError(
1188 cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"", tgt,
1189 "\" which is not an executable, library, or module."));
1190 return false;
1191 }
1192 // Store the target in the list to be installed.
1193 targets.push_back(target);
1194 } else {
1195 // Did not find the target.
1196 status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"",
1197 tgt, "\" which does not exist."));
1198 return false;
1199 }
1200 }
1201
1202 // Keep track of whether we will be performing an installation of
1203 // any files of the given type.
1204 bool installsLibrary = false;
1205 bool installsRuntime = false;
1206 bool installsFramework = false;
1207 bool installsBundle = false;
1208
1209 auto const createInstallGenerator =
1210 [helper](cmTarget& target, const cmInstallCommandArguments& typeArgs,
1211 const std::string& destination)
1212 -> std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator> {
1213 return cm::make_unique<cmInstallImportedRuntimeArtifactsGenerator>(
1214 target.GetName(), destination, typeArgs.GetPermissions(),
1215 typeArgs.GetConfigurations(), typeArgs.GetComponent(),
1216 cmInstallGenerator::SelectMessageLevel(helper.Makefile),
1217 typeArgs.GetExcludeFromAll(), typeArgs.GetOptional(),
1218 helper.Makefile->GetBacktrace());
1219 };
1220
1221 // Generate install script code to install the given targets.
1222 for (cmTarget* ti : targets) {
1223 // Handle each target type.
1224 cmTarget& target = *ti;
1225 std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
1226 libraryGenerator;
1227 std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
1228 runtimeGenerator;
1229 std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
1230 frameworkGenerator;
1231 std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
1232 bundleGenerator;
1233
1234 switch (target.GetType()) {
1235 case cmStateEnums::SHARED_LIBRARY:
1236 if (target.IsDLLPlatform()) {
1237 runtimeGenerator = createInstallGenerator(
1238 target, runtimeArgs, helper.GetRuntimeDestination(&runtimeArgs));
1239 if (runtimeDependencySet) {
1240 runtimeDependencySet->AddLibrary(runtimeGenerator.get());
1241 }
1242 } else if (target.IsFrameworkOnApple()) {
1243 if (frameworkArgs.GetDestination().empty()) {
1244 status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given no "
1245 "FRAMEWORK DESTINATION for shared "
1246 "library FRAMEWORK target \"",
1247 target.GetName(), "\"."));
1248 return false;
1249 }
1250 frameworkGenerator = createInstallGenerator(
1251 target, frameworkArgs, frameworkArgs.GetDestination());
1252 if (runtimeDependencySet) {
1253 runtimeDependencySet->AddLibrary(frameworkGenerator.get());
1254 }
1255 } else {
1256 libraryGenerator = createInstallGenerator(
1257 target, libraryArgs, helper.GetLibraryDestination(&libraryArgs));
1258 if (runtimeDependencySet) {
1259 runtimeDependencySet->AddLibrary(libraryGenerator.get());
1260 }
1261 }
1262 break;
1263 case cmStateEnums::MODULE_LIBRARY:
1264 libraryGenerator = createInstallGenerator(
1265 target, libraryArgs, helper.GetLibraryDestination(&libraryArgs));
1266 if (runtimeDependencySet) {
1267 runtimeDependencySet->AddModule(libraryGenerator.get());
1268 }
1269 break;
1270 case cmStateEnums::EXECUTABLE:
1271 if (target.IsAppBundleOnApple()) {
1272 if (bundleArgs.GetDestination().empty()) {
1273 status.SetError(
1274 cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given no BUNDLE "
1275 "DESTINATION for MACOSX_BUNDLE executable target \"",
1276 target.GetName(), "\"."));
1277 return false;
1278 }
1279 bundleGenerator = createInstallGenerator(
1280 target, bundleArgs, bundleArgs.GetDestination());
1281 if (runtimeDependencySet) {
1282 if (!AddBundleExecutable(helper, runtimeDependencySet,
1283 bundleGenerator.get())) {
1284 return false;
1285 }
1286 }
1287 } else {
1288 runtimeGenerator = createInstallGenerator(
1289 target, runtimeArgs, helper.GetRuntimeDestination(&runtimeArgs));
1290 if (runtimeDependencySet) {
1291 runtimeDependencySet->AddExecutable(runtimeGenerator.get());
1292 }
1293 }
1294 break;
1295 default:
1296 assert(false && "This should never happen");
1297 break;
1298 }
1299
1300 // Keep track of whether we're installing anything in each category
1301 installsLibrary = installsLibrary || libraryGenerator;
1302 installsRuntime = installsRuntime || runtimeGenerator;
1303 installsFramework = installsFramework || frameworkGenerator;
1304 installsBundle = installsBundle || bundleGenerator;
1305
1306 helper.Makefile->AddInstallGenerator(std::move(libraryGenerator));
1307 helper.Makefile->AddInstallGenerator(std::move(runtimeGenerator));
1308 helper.Makefile->AddInstallGenerator(std::move(frameworkGenerator));
1309 helper.Makefile->AddInstallGenerator(std::move(bundleGenerator));
1310 }
1311
1312 // Tell the global generator about any installation component names
1313 // specified
1314 if (installsLibrary) {
1315 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1316 libraryArgs.GetComponent());
1317 }
1318 if (installsRuntime) {
1319 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1320 runtimeArgs.GetComponent());
1321 }
1322 if (installsFramework) {
1323 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1324 frameworkArgs.GetComponent());
1325 }
1326 if (installsBundle) {
1327 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1328 bundleArgs.GetComponent());
1329 }
1330
1331 return true;
1332 }
1333
HandleFilesMode(std::vector<std::string> const & args,cmExecutionStatus & status)1334 bool HandleFilesMode(std::vector<std::string> const& args,
1335 cmExecutionStatus& status)
1336 {
1337 Helper helper(status);
1338
1339 // This is the FILES mode.
1340 bool programs = (args[0] == "PROGRAMS");
1341 cmInstallCommandArguments ica(helper.DefaultComponentName);
1342 std::vector<std::string> files;
1343 ica.Bind(programs ? "PROGRAMS"_s : "FILES"_s, files);
1344 std::vector<std::string> unknownArgs;
1345 ica.Parse(args, &unknownArgs);
1346
1347 if (!unknownArgs.empty()) {
1348 // Unknown argument.
1349 status.SetError(
1350 cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\"."));
1351 return false;
1352 }
1353
1354 std::string type = ica.GetType();
1355 if (!type.empty() && allowedTypes.count(type) == 0) {
1356 status.SetError(
1357 cmStrCat(args[0], " given non-type \"", type, "\" with TYPE argument."));
1358 return false;
1359 }
1360
1361 const std::vector<std::string>& filesVector = files;
1362
1363 // Check if there is something to do.
1364 if (filesVector.empty()) {
1365 return true;
1366 }
1367
1368 if (!ica.GetRename().empty() && filesVector.size() > 1) {
1369 // The rename option works only with one file.
1370 status.SetError(
1371 cmStrCat(args[0], " given RENAME option with more than one file."));
1372 return false;
1373 }
1374
1375 std::vector<std::string> absFiles;
1376 if (!helper.MakeFilesFullPath(args[0].c_str(), filesVector, absFiles)) {
1377 return false;
1378 }
1379
1380 cmPolicies::PolicyStatus policyStatus =
1381 helper.Makefile->GetPolicyStatus(cmPolicies::CMP0062);
1382
1383 cmGlobalGenerator* gg = helper.Makefile->GetGlobalGenerator();
1384 for (std::string const& file : filesVector) {
1385 if (gg->IsExportedTargetsFile(file)) {
1386 const char* modal = nullptr;
1387 std::ostringstream e;
1388 MessageType messageType = MessageType::AUTHOR_WARNING;
1389
1390 switch (policyStatus) {
1391 case cmPolicies::WARN:
1392 e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0062) << "\n";
1393 modal = "should";
1394 CM_FALLTHROUGH;
1395 case cmPolicies::OLD:
1396 break;
1397 case cmPolicies::REQUIRED_IF_USED:
1398 case cmPolicies::REQUIRED_ALWAYS:
1399 case cmPolicies::NEW:
1400 modal = "may";
1401 messageType = MessageType::FATAL_ERROR;
1402 break;
1403 }
1404 if (modal) {
1405 e << "The file\n " << file
1406 << "\nwas generated by the export() "
1407 "command. It "
1408 << modal
1409 << " not be installed with the "
1410 "install() command. Use the install(EXPORT) mechanism "
1411 "instead. See the cmake-packages(7) manual for more.\n";
1412 helper.Makefile->IssueMessage(messageType, e.str());
1413 if (messageType == MessageType::FATAL_ERROR) {
1414 return false;
1415 }
1416 }
1417 }
1418 }
1419
1420 if (!ica.Finalize()) {
1421 return false;
1422 }
1423
1424 if (!type.empty() && !ica.GetDestination().empty()) {
1425 status.SetError(cmStrCat(args[0],
1426 " given both TYPE and DESTINATION arguments. "
1427 "You may only specify one."));
1428 return false;
1429 }
1430
1431 std::string destination = helper.GetDestinationForType(&ica, type);
1432 if (destination.empty()) {
1433 // A destination is required.
1434 status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
1435 return false;
1436 }
1437
1438 // Create the files install generator.
1439 helper.Makefile->AddInstallGenerator(CreateInstallFilesGenerator(
1440 helper.Makefile, absFiles, ica, programs, destination));
1441
1442 // Tell the global generator about any installation component names
1443 // specified.
1444 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1445 ica.GetComponent());
1446
1447 return true;
1448 }
1449
HandleDirectoryMode(std::vector<std::string> const & args,cmExecutionStatus & status)1450 bool HandleDirectoryMode(std::vector<std::string> const& args,
1451 cmExecutionStatus& status)
1452 {
1453 Helper helper(status);
1454
1455 enum Doing
1456 {
1457 DoingNone,
1458 DoingDirs,
1459 DoingDestination,
1460 DoingPattern,
1461 DoingRegex,
1462 DoingPermsFile,
1463 DoingPermsDir,
1464 DoingPermsMatch,
1465 DoingConfigurations,
1466 DoingComponent,
1467 DoingType
1468 };
1469 Doing doing = DoingDirs;
1470 bool in_match_mode = false;
1471 bool optional = false;
1472 bool exclude_from_all = false;
1473 bool message_never = false;
1474 std::vector<std::string> dirs;
1475 const std::string* destination = nullptr;
1476 std::string permissions_file;
1477 std::string permissions_dir;
1478 std::vector<std::string> configurations;
1479 std::string component = helper.DefaultComponentName;
1480 std::string literal_args;
1481 std::string type;
1482 for (unsigned int i = 1; i < args.size(); ++i) {
1483 if (args[i] == "DESTINATION") {
1484 if (in_match_mode) {
1485 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1486 "\" after PATTERN or REGEX."));
1487 return false;
1488 }
1489
1490 // Switch to setting the destination property.
1491 doing = DoingDestination;
1492 } else if (args[i] == "TYPE") {
1493 if (in_match_mode) {
1494 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1495 "\" after PATTERN or REGEX."));
1496 return false;
1497 }
1498
1499 // Switch to setting the type.
1500 doing = DoingType;
1501 } else if (args[i] == "OPTIONAL") {
1502 if (in_match_mode) {
1503 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1504 "\" after PATTERN or REGEX."));
1505 return false;
1506 }
1507
1508 // Mark the rule as optional.
1509 optional = true;
1510 doing = DoingNone;
1511 } else if (args[i] == "MESSAGE_NEVER") {
1512 if (in_match_mode) {
1513 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1514 "\" after PATTERN or REGEX."));
1515 return false;
1516 }
1517
1518 // Mark the rule as quiet.
1519 message_never = true;
1520 doing = DoingNone;
1521 } else if (args[i] == "PATTERN") {
1522 // Switch to a new pattern match rule.
1523 doing = DoingPattern;
1524 in_match_mode = true;
1525 } else if (args[i] == "REGEX") {
1526 // Switch to a new regex match rule.
1527 doing = DoingRegex;
1528 in_match_mode = true;
1529 } else if (args[i] == "EXCLUDE") {
1530 // Add this property to the current match rule.
1531 if (!in_match_mode || doing == DoingPattern || doing == DoingRegex) {
1532 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1533 "\" before a PATTERN or REGEX is given."));
1534 return false;
1535 }
1536 literal_args += " EXCLUDE";
1537 doing = DoingNone;
1538 } else if (args[i] == "PERMISSIONS") {
1539 if (!in_match_mode) {
1540 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1541 "\" before a PATTERN or REGEX is given."));
1542 return false;
1543 }
1544
1545 // Switch to setting the current match permissions property.
1546 literal_args += " PERMISSIONS";
1547 doing = DoingPermsMatch;
1548 } else if (args[i] == "FILE_PERMISSIONS") {
1549 if (in_match_mode) {
1550 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1551 "\" after PATTERN or REGEX."));
1552 return false;
1553 }
1554
1555 // Switch to setting the file permissions property.
1556 doing = DoingPermsFile;
1557 } else if (args[i] == "DIRECTORY_PERMISSIONS") {
1558 if (in_match_mode) {
1559 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1560 "\" after PATTERN or REGEX."));
1561 return false;
1562 }
1563
1564 // Switch to setting the directory permissions property.
1565 doing = DoingPermsDir;
1566 } else if (args[i] == "USE_SOURCE_PERMISSIONS") {
1567 if (in_match_mode) {
1568 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1569 "\" after PATTERN or REGEX."));
1570 return false;
1571 }
1572
1573 // Add this option literally.
1574 literal_args += " USE_SOURCE_PERMISSIONS";
1575 doing = DoingNone;
1576 } else if (args[i] == "FILES_MATCHING") {
1577 if (in_match_mode) {
1578 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1579 "\" after PATTERN or REGEX."));
1580 return false;
1581 }
1582
1583 // Add this option literally.
1584 literal_args += " FILES_MATCHING";
1585 doing = DoingNone;
1586 } else if (args[i] == "CONFIGURATIONS") {
1587 if (in_match_mode) {
1588 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1589 "\" after PATTERN or REGEX."));
1590 return false;
1591 }
1592
1593 // Switch to setting the configurations property.
1594 doing = DoingConfigurations;
1595 } else if (args[i] == "COMPONENT") {
1596 if (in_match_mode) {
1597 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1598 "\" after PATTERN or REGEX."));
1599 return false;
1600 }
1601
1602 // Switch to setting the component property.
1603 doing = DoingComponent;
1604 } else if (args[i] == "EXCLUDE_FROM_ALL") {
1605 if (in_match_mode) {
1606 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1607 "\" after PATTERN or REGEX."));
1608 return false;
1609 }
1610 exclude_from_all = true;
1611 doing = DoingNone;
1612 } else if (doing == DoingDirs) {
1613 // Convert this directory to a full path.
1614 std::string dir = args[i];
1615 std::string::size_type gpos = cmGeneratorExpression::Find(dir);
1616 if (gpos != 0 && !cmSystemTools::FileIsFullPath(dir)) {
1617 dir =
1618 cmStrCat(helper.Makefile->GetCurrentSourceDirectory(), '/', args[i]);
1619 }
1620
1621 // Make sure the name is a directory.
1622 if (cmSystemTools::FileExists(dir) &&
1623 !cmSystemTools::FileIsDirectory(dir)) {
1624 status.SetError(cmStrCat(args[0], " given non-directory \"", args[i],
1625 "\" to install."));
1626 return false;
1627 }
1628
1629 // Store the directory for installation.
1630 dirs.push_back(std::move(dir));
1631 } else if (doing == DoingConfigurations) {
1632 configurations.push_back(args[i]);
1633 } else if (doing == DoingDestination) {
1634 destination = &args[i];
1635 doing = DoingNone;
1636 } else if (doing == DoingType) {
1637 if (allowedTypes.count(args[i]) == 0) {
1638 status.SetError(cmStrCat(args[0], " given non-type \"", args[i],
1639 "\" with TYPE argument."));
1640 return false;
1641 }
1642
1643 type = args[i];
1644 doing = DoingNone;
1645 } else if (doing == DoingPattern) {
1646 // Convert the pattern to a regular expression. Require a
1647 // leading slash and trailing end-of-string in the matched
1648 // string to make sure the pattern matches only whole file
1649 // names.
1650 literal_args += " REGEX \"/";
1651 std::string regex = cmsys::Glob::PatternToRegex(args[i], false);
1652 cmSystemTools::ReplaceString(regex, "\\", "\\\\");
1653 literal_args += regex;
1654 literal_args += "$\"";
1655 doing = DoingNone;
1656 } else if (doing == DoingRegex) {
1657 literal_args += " REGEX \"";
1658 // Match rules are case-insensitive on some platforms.
1659 #if defined(_WIN32) || defined(__APPLE__)
1660 std::string regex = cmSystemTools::LowerCase(args[i]);
1661 #else
1662 std::string regex = args[i];
1663 #endif
1664 cmSystemTools::ReplaceString(regex, "\\", "\\\\");
1665 literal_args += regex;
1666 literal_args += "\"";
1667 doing = DoingNone;
1668 } else if (doing == DoingComponent) {
1669 component = args[i];
1670 doing = DoingNone;
1671 } else if (doing == DoingPermsFile) {
1672 // Check the requested permission.
1673 if (!cmInstallCommandArguments::CheckPermissions(args[i],
1674 permissions_file)) {
1675 status.SetError(cmStrCat(args[0], " given invalid file permission \"",
1676 args[i], "\"."));
1677 return false;
1678 }
1679 } else if (doing == DoingPermsDir) {
1680 // Check the requested permission.
1681 if (!cmInstallCommandArguments::CheckPermissions(args[i],
1682 permissions_dir)) {
1683 status.SetError(cmStrCat(
1684 args[0], " given invalid directory permission \"", args[i], "\"."));
1685 return false;
1686 }
1687 } else if (doing == DoingPermsMatch) {
1688 // Check the requested permission.
1689 if (!cmInstallCommandArguments::CheckPermissions(args[i],
1690 literal_args)) {
1691 status.SetError(
1692 cmStrCat(args[0], " given invalid permission \"", args[i], "\"."));
1693 return false;
1694 }
1695 } else {
1696 // Unknown argument.
1697 status.SetError(
1698 cmStrCat(args[0], " given unknown argument \"", args[i], "\"."));
1699 return false;
1700 }
1701 }
1702
1703 // Support installing an empty directory.
1704 if (dirs.empty() && destination) {
1705 dirs.emplace_back();
1706 }
1707
1708 // Check if there is something to do.
1709 if (dirs.empty()) {
1710 return true;
1711 }
1712 std::string destinationStr;
1713 if (!destination) {
1714 if (type.empty()) {
1715 // A destination is required.
1716 status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
1717 return false;
1718 }
1719 destinationStr = helper.GetDestinationForType(nullptr, type);
1720 destination = &destinationStr;
1721 } else if (!type.empty()) {
1722 status.SetError(cmStrCat(args[0],
1723 " given both TYPE and DESTINATION "
1724 "arguments. You may only specify one."));
1725 return false;
1726 }
1727
1728 cmInstallGenerator::MessageLevel message =
1729 cmInstallGenerator::SelectMessageLevel(helper.Makefile, message_never);
1730
1731 // Create the directory install generator.
1732 helper.Makefile->AddInstallGenerator(
1733 cm::make_unique<cmInstallDirectoryGenerator>(
1734 dirs, *destination, permissions_file, permissions_dir, configurations,
1735 component, message, exclude_from_all, literal_args, optional,
1736 helper.Makefile->GetBacktrace()));
1737
1738 // Tell the global generator about any installation component names
1739 // specified.
1740 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(component);
1741
1742 return true;
1743 }
1744
HandleExportAndroidMKMode(std::vector<std::string> const & args,cmExecutionStatus & status)1745 bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
1746 cmExecutionStatus& status)
1747 {
1748 #ifndef CMAKE_BOOTSTRAP
1749 Helper helper(status);
1750
1751 // This is the EXPORT mode.
1752 cmInstallCommandArguments ica(helper.DefaultComponentName);
1753
1754 std::string exp;
1755 std::string name_space;
1756 bool exportOld = false;
1757 std::string filename;
1758
1759 ica.Bind("EXPORT_ANDROID_MK"_s, exp);
1760 ica.Bind("NAMESPACE"_s, name_space);
1761 ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld);
1762 ica.Bind("FILE"_s, filename);
1763
1764 std::vector<std::string> unknownArgs;
1765 ica.Parse(args, &unknownArgs);
1766
1767 if (!unknownArgs.empty()) {
1768 // Unknown argument.
1769 status.SetError(
1770 cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\"."));
1771 return false;
1772 }
1773
1774 if (!ica.Finalize()) {
1775 return false;
1776 }
1777
1778 // Make sure there is a destination.
1779 if (ica.GetDestination().empty()) {
1780 // A destination is required.
1781 status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
1782 return false;
1783 }
1784
1785 // Check the file name.
1786 std::string fname = filename;
1787 if (fname.find_first_of(":/\\") != std::string::npos) {
1788 status.SetError(cmStrCat(args[0], " given invalid export file name \"",
1789 fname,
1790 "\". The FILE argument may not contain a path. "
1791 "Specify the path in the DESTINATION argument."));
1792 return false;
1793 }
1794
1795 // Check the file extension.
1796 if (!fname.empty() &&
1797 cmSystemTools::GetFilenameLastExtension(fname) != ".mk") {
1798 status.SetError(cmStrCat(
1799 args[0], " given invalid export file name \"", fname,
1800 R"(". The FILE argument must specify a name ending in ".mk".)"));
1801 return false;
1802 }
1803 if (fname.find_first_of(":/\\") != std::string::npos) {
1804 status.SetError(
1805 cmStrCat(args[0], " given export name \"", exp,
1806 "\". "
1807 "This name cannot be safely converted to a file name. "
1808 "Specify a different export name or use the FILE option to set "
1809 "a file name explicitly."));
1810 return false;
1811 }
1812 // Use the default name
1813 if (fname.empty()) {
1814 fname = "Android.mk";
1815 }
1816
1817 cmExportSet& exportSet =
1818 helper.Makefile->GetGlobalGenerator()->GetExportSets()[exp];
1819
1820 cmInstallGenerator::MessageLevel message =
1821 cmInstallGenerator::SelectMessageLevel(helper.Makefile);
1822
1823 // Create the export install generator.
1824 helper.Makefile->AddInstallGenerator(
1825 cm::make_unique<cmInstallExportGenerator>(
1826 &exportSet, ica.GetDestination(), ica.GetPermissions(),
1827 ica.GetConfigurations(), ica.GetComponent(), message,
1828 ica.GetExcludeFromAll(), fname, name_space, exportOld, true,
1829 helper.Makefile->GetBacktrace()));
1830
1831 return true;
1832 #else
1833 static_cast<void>(args);
1834 status.SetError("EXPORT_ANDROID_MK not supported in bootstrap cmake");
1835 return false;
1836 #endif
1837 }
1838
HandleExportMode(std::vector<std::string> const & args,cmExecutionStatus & status)1839 bool HandleExportMode(std::vector<std::string> const& args,
1840 cmExecutionStatus& status)
1841 {
1842 Helper helper(status);
1843
1844 // This is the EXPORT mode.
1845 cmInstallCommandArguments ica(helper.DefaultComponentName);
1846
1847 std::string exp;
1848 std::string name_space;
1849 bool exportOld = false;
1850 std::string filename;
1851
1852 ica.Bind("EXPORT"_s, exp);
1853 ica.Bind("NAMESPACE"_s, name_space);
1854 ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld);
1855 ica.Bind("FILE"_s, filename);
1856
1857 std::vector<std::string> unknownArgs;
1858 ica.Parse(args, &unknownArgs);
1859
1860 if (!unknownArgs.empty()) {
1861 // Unknown argument.
1862 status.SetError(
1863 cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\"."));
1864 return false;
1865 }
1866
1867 if (!ica.Finalize()) {
1868 return false;
1869 }
1870
1871 // Make sure there is a destination.
1872 if (ica.GetDestination().empty()) {
1873 // A destination is required.
1874 status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
1875 return false;
1876 }
1877
1878 // Check the file name.
1879 std::string fname = filename;
1880 if (fname.find_first_of(":/\\") != std::string::npos) {
1881 status.SetError(cmStrCat(args[0], " given invalid export file name \"",
1882 fname,
1883 "\". "
1884 "The FILE argument may not contain a path. "
1885 "Specify the path in the DESTINATION argument."));
1886 return false;
1887 }
1888
1889 // Check the file extension.
1890 if (!fname.empty() &&
1891 cmSystemTools::GetFilenameLastExtension(fname) != ".cmake") {
1892 status.SetError(
1893 cmStrCat(args[0], " given invalid export file name \"", fname,
1894 "\". "
1895 "The FILE argument must specify a name ending in \".cmake\"."));
1896 return false;
1897 }
1898
1899 // Construct the file name.
1900 if (fname.empty()) {
1901 fname = cmStrCat(exp, ".cmake");
1902
1903 if (fname.find_first_of(":/\\") != std::string::npos) {
1904 status.SetError(cmStrCat(
1905 args[0], " given export name \"", exp,
1906 "\". "
1907 "This name cannot be safely converted to a file name. "
1908 "Specify a different export name or use the FILE option to set "
1909 "a file name explicitly."));
1910 return false;
1911 }
1912 }
1913
1914 cmExportSet& exportSet =
1915 helper.Makefile->GetGlobalGenerator()->GetExportSets()[exp];
1916 if (exportOld) {
1917 for (auto const& te : exportSet.GetTargetExports()) {
1918 cmTarget* tgt =
1919 helper.Makefile->GetGlobalGenerator()->FindTarget(te->TargetName);
1920 const bool newCMP0022Behavior =
1921 (tgt && tgt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
1922 tgt->GetPolicyStatusCMP0022() != cmPolicies::OLD);
1923
1924 if (!newCMP0022Behavior) {
1925 status.SetError(cmStrCat(
1926 "INSTALL(EXPORT) given keyword \""
1927 "EXPORT_LINK_INTERFACE_LIBRARIES\", but target \"",
1928 te->TargetName, "\" does not have policy CMP0022 set to NEW."));
1929 return false;
1930 }
1931 }
1932 }
1933
1934 cmInstallGenerator::MessageLevel message =
1935 cmInstallGenerator::SelectMessageLevel(helper.Makefile);
1936
1937 // Create the export install generator.
1938 helper.Makefile->AddInstallGenerator(
1939 cm::make_unique<cmInstallExportGenerator>(
1940 &exportSet, ica.GetDestination(), ica.GetPermissions(),
1941 ica.GetConfigurations(), ica.GetComponent(), message,
1942 ica.GetExcludeFromAll(), fname, name_space, exportOld, false,
1943 helper.Makefile->GetBacktrace()));
1944
1945 return true;
1946 }
1947
HandleRuntimeDependencySetMode(std::vector<std::string> const & args,cmExecutionStatus & status)1948 bool HandleRuntimeDependencySetMode(std::vector<std::string> const& args,
1949 cmExecutionStatus& status)
1950 {
1951 Helper helper(status);
1952
1953 auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
1954 if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
1955 system)) {
1956 status.SetError(cmStrCat(
1957 "RUNTIME_DEPENDENCY_SET is not supported on system \"", system, '"'));
1958 return false;
1959 }
1960
1961 // This is the RUNTIME_DEPENDENCY_SET mode.
1962 cmInstallRuntimeDependencySet* runtimeDependencySet;
1963
1964 struct ArgVectors
1965 {
1966 std::vector<std::string> Library;
1967 std::vector<std::string> Runtime;
1968 std::vector<std::string> Framework;
1969 };
1970
1971 static auto const argHelper = cmArgumentParser<ArgVectors>{}
1972 .Bind("LIBRARY"_s, &ArgVectors::Library)
1973 .Bind("RUNTIME"_s, &ArgVectors::Runtime)
1974 .Bind("FRAMEWORK"_s, &ArgVectors::Framework);
1975
1976 std::vector<std::string> genericArgVector;
1977 ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
1978
1979 // now parse the generic args (i.e. the ones not specialized on LIBRARY,
1980 // RUNTIME, FRAMEWORK etc. (see above)
1981 // These generic args also contain the runtime dependency set
1982 std::string runtimeDependencySetArg;
1983 std::vector<std::string> runtimeDependencyArgVector;
1984 std::vector<std::string> parsedArgs;
1985 cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
1986 genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
1987 genericArgs.Parse(genericArgVector, &runtimeDependencyArgVector, nullptr,
1988 &parsedArgs);
1989 bool success = genericArgs.Finalize();
1990
1991 cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
1992 cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
1993 cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
1994
1995 // Now also parse the file(GET_RUNTIME_DEPENDENCY) args
1996 std::vector<std::string> unknownArgs;
1997 auto runtimeDependencyArgs = RuntimeDependenciesArgHelper.Parse(
1998 runtimeDependencyArgVector, &unknownArgs);
1999
2000 // now parse the args for specific parts of the target (e.g. LIBRARY,
2001 // RUNTIME, FRAMEWORK etc.
2002 libraryArgs.Parse(argVectors.Library, &unknownArgs);
2003 runtimeArgs.Parse(argVectors.Runtime, &unknownArgs);
2004 frameworkArgs.Parse(argVectors.Framework, &unknownArgs);
2005
2006 libraryArgs.SetGenericArguments(&genericArgs);
2007 runtimeArgs.SetGenericArguments(&genericArgs);
2008 frameworkArgs.SetGenericArguments(&genericArgs);
2009
2010 success = success && libraryArgs.Finalize();
2011 success = success && runtimeArgs.Finalize();
2012 success = success && frameworkArgs.Finalize();
2013
2014 if (!success) {
2015 return false;
2016 }
2017
2018 if (!unknownArgs.empty()) {
2019 helper.SetError(
2020 cmStrCat("RUNTIME_DEPENDENCY_SET given unknown argument \"",
2021 unknownArgs.front(), "\"."));
2022 return false;
2023 }
2024
2025 if (runtimeDependencySetArg.empty()) {
2026 helper.SetError(
2027 "RUNTIME_DEPENDENCY_SET not given a runtime dependency set.");
2028 return false;
2029 }
2030
2031 runtimeDependencySet =
2032 helper.Makefile->GetGlobalGenerator()->GetNamedRuntimeDependencySet(
2033 runtimeDependencySetArg);
2034
2035 bool installsRuntime = false;
2036 bool installsLibrary = false;
2037 bool installsFramework = false;
2038
2039 AddInstallRuntimeDependenciesGenerator(
2040 helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs,
2041 std::move(runtimeDependencyArgs), installsRuntime, installsLibrary,
2042 installsFramework);
2043
2044 // Tell the global generator about any installation component names
2045 // specified
2046 if (installsLibrary) {
2047 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
2048 libraryArgs.GetComponent());
2049 }
2050 if (installsRuntime) {
2051 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
2052 runtimeArgs.GetComponent());
2053 }
2054 if (installsFramework) {
2055 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
2056 frameworkArgs.GetComponent());
2057 }
2058
2059 return true;
2060 }
2061
MakeFilesFullPath(const char * modeName,const std::vector<std::string> & relFiles,std::vector<std::string> & absFiles)2062 bool Helper::MakeFilesFullPath(const char* modeName,
2063 const std::vector<std::string>& relFiles,
2064 std::vector<std::string>& absFiles)
2065 {
2066 for (std::string const& relFile : relFiles) {
2067 std::string file = relFile;
2068 std::string::size_type gpos = cmGeneratorExpression::Find(file);
2069 if (gpos != 0 && !cmSystemTools::FileIsFullPath(file)) {
2070 file =
2071 cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', relFile);
2072 }
2073
2074 // Make sure the file is not a directory.
2075 if (gpos == std::string::npos && !cmSystemTools::FileIsSymlink(file) &&
2076 cmSystemTools::FileIsDirectory(file)) {
2077 this->SetError(
2078 cmStrCat(modeName, " given directory \"", relFile, "\" to install."));
2079 return false;
2080 }
2081 // Store the file for installation.
2082 absFiles.push_back(std::move(file));
2083 }
2084 return true;
2085 }
2086
CheckCMP0006(bool & failure) const2087 bool Helper::CheckCMP0006(bool& failure) const
2088 {
2089 switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0006)) {
2090 case cmPolicies::WARN:
2091 this->Makefile->IssueMessage(
2092 MessageType::AUTHOR_WARNING,
2093 cmPolicies::GetPolicyWarning(cmPolicies::CMP0006));
2094 CM_FALLTHROUGH;
2095 case cmPolicies::OLD:
2096 // OLD behavior is to allow compatibility
2097 return true;
2098 case cmPolicies::NEW:
2099 // NEW behavior is to disallow compatibility
2100 break;
2101 case cmPolicies::REQUIRED_IF_USED:
2102 case cmPolicies::REQUIRED_ALWAYS:
2103 failure = true;
2104 this->Makefile->IssueMessage(
2105 MessageType::FATAL_ERROR,
2106 cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0006));
2107 break;
2108 }
2109 return false;
2110 }
2111
GetDestination(const cmInstallCommandArguments * args,const std::string & varName,const std::string & guess) const2112 std::string Helper::GetDestination(const cmInstallCommandArguments* args,
2113 const std::string& varName,
2114 const std::string& guess) const
2115 {
2116 if (args && !args->GetDestination().empty()) {
2117 return args->GetDestination();
2118 }
2119 std::string val = this->Makefile->GetSafeDefinition(varName);
2120 if (!val.empty()) {
2121 return val;
2122 }
2123 return guess;
2124 }
2125
GetRuntimeDestination(const cmInstallCommandArguments * args) const2126 std::string Helper::GetRuntimeDestination(
2127 const cmInstallCommandArguments* args) const
2128 {
2129 return this->GetDestination(args, "CMAKE_INSTALL_BINDIR", "bin");
2130 }
2131
GetSbinDestination(const cmInstallCommandArguments * args) const2132 std::string Helper::GetSbinDestination(
2133 const cmInstallCommandArguments* args) const
2134 {
2135 return this->GetDestination(args, "CMAKE_INSTALL_SBINDIR", "sbin");
2136 }
2137
GetArchiveDestination(const cmInstallCommandArguments * args) const2138 std::string Helper::GetArchiveDestination(
2139 const cmInstallCommandArguments* args) const
2140 {
2141 return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
2142 }
2143
GetLibraryDestination(const cmInstallCommandArguments * args) const2144 std::string Helper::GetLibraryDestination(
2145 const cmInstallCommandArguments* args) const
2146 {
2147 return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
2148 }
2149
GetIncludeDestination(const cmInstallCommandArguments * args) const2150 std::string Helper::GetIncludeDestination(
2151 const cmInstallCommandArguments* args) const
2152 {
2153 return this->GetDestination(args, "CMAKE_INSTALL_INCLUDEDIR", "include");
2154 }
2155
GetSysconfDestination(const cmInstallCommandArguments * args) const2156 std::string Helper::GetSysconfDestination(
2157 const cmInstallCommandArguments* args) const
2158 {
2159 return this->GetDestination(args, "CMAKE_INSTALL_SYSCONFDIR", "etc");
2160 }
2161
GetSharedStateDestination(const cmInstallCommandArguments * args) const2162 std::string Helper::GetSharedStateDestination(
2163 const cmInstallCommandArguments* args) const
2164 {
2165 return this->GetDestination(args, "CMAKE_INSTALL_SHAREDSTATEDIR", "com");
2166 }
2167
GetLocalStateDestination(const cmInstallCommandArguments * args) const2168 std::string Helper::GetLocalStateDestination(
2169 const cmInstallCommandArguments* args) const
2170 {
2171 return this->GetDestination(args, "CMAKE_INSTALL_LOCALSTATEDIR", "var");
2172 }
2173
GetRunStateDestination(const cmInstallCommandArguments * args) const2174 std::string Helper::GetRunStateDestination(
2175 const cmInstallCommandArguments* args) const
2176 {
2177 return this->GetDestination(args, "CMAKE_INSTALL_RUNSTATEDIR",
2178 this->GetLocalStateDestination(nullptr) +
2179 "/run");
2180 }
2181
GetDataRootDestination(const cmInstallCommandArguments * args) const2182 std::string Helper::GetDataRootDestination(
2183 const cmInstallCommandArguments* args) const
2184 {
2185 return this->GetDestination(args, "CMAKE_INSTALL_DATAROOTDIR", "share");
2186 }
2187
GetDataDestination(const cmInstallCommandArguments * args) const2188 std::string Helper::GetDataDestination(
2189 const cmInstallCommandArguments* args) const
2190 {
2191 return this->GetDestination(args, "CMAKE_INSTALL_DATADIR",
2192 this->GetDataRootDestination(nullptr));
2193 }
2194
GetInfoDestination(const cmInstallCommandArguments * args) const2195 std::string Helper::GetInfoDestination(
2196 const cmInstallCommandArguments* args) const
2197 {
2198 return this->GetDestination(args, "CMAKE_INSTALL_INFODIR",
2199 this->GetDataRootDestination(nullptr) + "/info");
2200 }
2201
GetLocaleDestination(const cmInstallCommandArguments * args) const2202 std::string Helper::GetLocaleDestination(
2203 const cmInstallCommandArguments* args) const
2204 {
2205 return this->GetDestination(args, "CMAKE_INSTALL_LOCALEDIR",
2206 this->GetDataRootDestination(nullptr) +
2207 "/locale");
2208 }
2209
GetManDestination(const cmInstallCommandArguments * args) const2210 std::string Helper::GetManDestination(
2211 const cmInstallCommandArguments* args) const
2212 {
2213 return this->GetDestination(args, "CMAKE_INSTALL_MANDIR",
2214 this->GetDataRootDestination(nullptr) + "/man");
2215 }
2216
GetDocDestination(const cmInstallCommandArguments * args) const2217 std::string Helper::GetDocDestination(
2218 const cmInstallCommandArguments* args) const
2219 {
2220 return this->GetDestination(args, "CMAKE_INSTALL_DOCDIR",
2221 this->GetDataRootDestination(nullptr) + "/doc");
2222 }
2223
GetDestinationForType(const cmInstallCommandArguments * args,const std::string & type) const2224 std::string Helper::GetDestinationForType(
2225 const cmInstallCommandArguments* args, const std::string& type) const
2226 {
2227 if (args && !args->GetDestination().empty()) {
2228 return args->GetDestination();
2229 }
2230 if (type == "BIN") {
2231 return this->GetRuntimeDestination(nullptr);
2232 }
2233 if (type == "SBIN") {
2234 return this->GetSbinDestination(nullptr);
2235 }
2236 if (type == "SYSCONF") {
2237 return this->GetSysconfDestination(nullptr);
2238 }
2239 if (type == "SHAREDSTATE") {
2240 return this->GetSharedStateDestination(nullptr);
2241 }
2242 if (type == "LOCALSTATE") {
2243 return this->GetLocalStateDestination(nullptr);
2244 }
2245 if (type == "RUNSTATE") {
2246 return this->GetRunStateDestination(nullptr);
2247 }
2248 if (type == "LIB") {
2249 return this->GetLibraryDestination(nullptr);
2250 }
2251 if (type == "INCLUDE") {
2252 return this->GetIncludeDestination(nullptr);
2253 }
2254 if (type == "DATA") {
2255 return this->GetDataDestination(nullptr);
2256 }
2257 if (type == "INFO") {
2258 return this->GetInfoDestination(nullptr);
2259 }
2260 if (type == "LOCALE") {
2261 return this->GetLocaleDestination(nullptr);
2262 }
2263 if (type == "MAN") {
2264 return this->GetManDestination(nullptr);
2265 }
2266 if (type == "DOC") {
2267 return this->GetDocDestination(nullptr);
2268 }
2269 return "";
2270 }
2271
2272 } // namespace
2273
cmInstallCommand(std::vector<std::string> const & args,cmExecutionStatus & status)2274 bool cmInstallCommand(std::vector<std::string> const& args,
2275 cmExecutionStatus& status)
2276 {
2277 // Allow calling with no arguments so that arguments may be built up
2278 // using a variable that may be left empty.
2279 if (args.empty()) {
2280 return true;
2281 }
2282
2283 // Enable the install target.
2284 status.GetMakefile().GetGlobalGenerator()->EnableInstallTarget();
2285
2286 static cmSubcommandTable const subcommand{
2287 { "SCRIPT"_s, HandleScriptMode },
2288 { "CODE"_s, HandleScriptMode },
2289 { "TARGETS"_s, HandleTargetsMode },
2290 { "IMPORTED_RUNTIME_ARTIFACTS"_s, HandleImportedRuntimeArtifactsMode },
2291 { "FILES"_s, HandleFilesMode },
2292 { "PROGRAMS"_s, HandleFilesMode },
2293 { "DIRECTORY"_s, HandleDirectoryMode },
2294 { "EXPORT"_s, HandleExportMode },
2295 { "EXPORT_ANDROID_MK"_s, HandleExportAndroidMKMode },
2296 { "RUNTIME_DEPENDENCY_SET"_s, HandleRuntimeDependencySetMode },
2297 };
2298
2299 return subcommand(args[0], args, status);
2300 }
2301