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"
15 #include <cm/string_view>
16 #include <cmext/string_view>
18 #include "cmsys/Glob.hxx"
20 #include "cmArgumentParser.h"
21 #include "cmExecutionStatus.h"
22 #include "cmExportSet.h"
23 #include "cmFileSet.h"
24 #include "cmGeneratorExpression.h"
25 #include "cmGlobalGenerator.h"
26 #include "cmInstallCommandArguments.h"
27 #include "cmInstallDirectoryGenerator.h"
28 #include "cmInstallExportGenerator.h"
29 #include "cmInstallFileSetGenerator.h"
30 #include "cmInstallFilesGenerator.h"
31 #include "cmInstallGenerator.h"
32 #include "cmInstallGetRuntimeDependenciesGenerator.h"
33 #include "cmInstallImportedRuntimeArtifactsGenerator.h"
34 #include "cmInstallRuntimeDependencySet.h"
35 #include "cmInstallRuntimeDependencySetGenerator.h"
36 #include "cmInstallScriptGenerator.h"
37 #include "cmInstallTargetGenerator.h"
38 #include "cmMakefile.h"
39 #include "cmMessageType.h"
40 #include "cmPolicies.h"
42 #include "cmRuntimeDependencyArchive.h"
43 #include "cmStateTypes.h"
44 #include "cmStringAlgorithms.h"
45 #include "cmSubcommandTable.h"
46 #include "cmSystemTools.h"
48 #include "cmTargetExport.h"
51 class cmListFileBacktrace;
55 struct RuntimeDependenciesArgs
57 std::vector<std::string> Directories;
58 std::vector<std::string> PreIncludeRegexes;
59 std::vector<std::string> PreExcludeRegexes;
60 std::vector<std::string> PostIncludeRegexes;
61 std::vector<std::string> PostExcludeRegexes;
62 std::vector<std::string> PostIncludeFiles;
63 std::vector<std::string> PostExcludeFiles;
66 auto const RuntimeDependenciesArgHelper =
67 cmArgumentParser<RuntimeDependenciesArgs>{}
68 .Bind("DIRECTORIES"_s, &RuntimeDependenciesArgs::Directories)
69 .Bind("PRE_INCLUDE_REGEXES"_s, &RuntimeDependenciesArgs::PreIncludeRegexes)
70 .Bind("PRE_EXCLUDE_REGEXES"_s, &RuntimeDependenciesArgs::PreExcludeRegexes)
71 .Bind("POST_INCLUDE_REGEXES"_s,
72 &RuntimeDependenciesArgs::PostIncludeRegexes)
73 .Bind("POST_EXCLUDE_REGEXES"_s,
74 &RuntimeDependenciesArgs::PostExcludeRegexes)
75 .Bind("POST_INCLUDE_FILES"_s, &RuntimeDependenciesArgs::PostIncludeFiles)
76 .Bind("POST_EXCLUDE_FILES"_s, &RuntimeDependenciesArgs::PostExcludeFiles);
81 Helper(cmExecutionStatus& status)
83 , Makefile(&status.GetMakefile())
85 this->DefaultComponentName = this->Makefile->GetSafeDefinition(
86 "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
87 if (this->DefaultComponentName.empty()) {
88 this->DefaultComponentName = "Unspecified";
92 void SetError(std::string const& err) { this->Status.SetError(err); }
94 bool MakeFilesFullPath(const char* modeName,
95 const std::vector<std::string>& relFiles,
96 std::vector<std::string>& absFiles);
97 bool MakeFilesFullPath(const char* modeName, const std::string& basePath,
98 const std::vector<std::string>& relFiles,
99 std::vector<std::string>& absFiles);
100 bool CheckCMP0006(bool& failure) const;
102 std::string GetDestination(const cmInstallCommandArguments* args,
103 const std::string& varName,
104 const std::string& guess) const;
105 std::string GetRuntimeDestination(
106 const cmInstallCommandArguments* args) const;
107 std::string GetSbinDestination(const cmInstallCommandArguments* args) const;
108 std::string GetArchiveDestination(
109 const cmInstallCommandArguments* args) const;
110 std::string GetLibraryDestination(
111 const cmInstallCommandArguments* args) const;
112 std::string GetIncludeDestination(
113 const cmInstallCommandArguments* args) const;
114 std::string GetSysconfDestination(
115 const cmInstallCommandArguments* args) const;
116 std::string GetSharedStateDestination(
117 const cmInstallCommandArguments* args) const;
118 std::string GetLocalStateDestination(
119 const cmInstallCommandArguments* args) const;
120 std::string GetRunStateDestination(
121 const cmInstallCommandArguments* args) const;
122 std::string GetDataRootDestination(
123 const cmInstallCommandArguments* args) const;
124 std::string GetDataDestination(const cmInstallCommandArguments* args) const;
125 std::string GetInfoDestination(const cmInstallCommandArguments* args) const;
126 std::string GetLocaleDestination(
127 const cmInstallCommandArguments* args) const;
128 std::string GetManDestination(const cmInstallCommandArguments* args) const;
129 std::string GetDocDestination(const cmInstallCommandArguments* args) const;
130 std::string GetDestinationForType(const cmInstallCommandArguments* args,
131 const std::string& type) const;
133 cmExecutionStatus& Status;
134 cmMakefile* Makefile;
135 std::string DefaultComponentName;
138 std::unique_ptr<cmInstallTargetGenerator> CreateInstallTargetGenerator(
139 cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
140 cmListFileBacktrace const& backtrace, const std::string& destination,
141 bool forceOpt = false, bool namelink = false)
143 cmInstallGenerator::MessageLevel message =
144 cmInstallGenerator::SelectMessageLevel(target.GetMakefile());
145 target.SetHaveInstallRule(true);
146 const std::string& component =
147 namelink ? args.GetNamelinkComponent() : args.GetComponent();
148 auto g = cm::make_unique<cmInstallTargetGenerator>(
149 target.GetName(), destination, impLib, args.GetPermissions(),
150 args.GetConfigurations(), component, message, args.GetExcludeFromAll(),
151 args.GetOptional() || forceOpt, backtrace);
152 target.AddInstallGenerator(g.get());
156 std::unique_ptr<cmInstallTargetGenerator> CreateInstallTargetGenerator(
157 cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
158 cmListFileBacktrace const& backtrace, bool forceOpt = false,
159 bool namelink = false)
161 return CreateInstallTargetGenerator(target, args, impLib, backtrace,
162 args.GetDestination(), forceOpt,
166 std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator(
167 cmMakefile* mf, const std::vector<std::string>& absFiles,
168 const cmInstallCommandArguments& args, bool programs,
169 const std::string& destination)
171 cmInstallGenerator::MessageLevel message =
172 cmInstallGenerator::SelectMessageLevel(mf);
173 return cm::make_unique<cmInstallFilesGenerator>(
174 absFiles, destination, programs, args.GetPermissions(),
175 args.GetConfigurations(), args.GetComponent(), message,
176 args.GetExcludeFromAll(), args.GetRename(), args.GetOptional(),
180 std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator(
181 cmMakefile* mf, const std::vector<std::string>& absFiles,
182 const cmInstallCommandArguments& args, bool programs)
184 return CreateInstallFilesGenerator(mf, absFiles, args, programs,
185 args.GetDestination());
188 std::unique_ptr<cmInstallFileSetGenerator> CreateInstallFileSetGenerator(
189 Helper& helper, cmTarget& target, cmFileSet* fileSet,
190 const std::string& destination, const cmInstallCommandArguments& args)
192 cmInstallGenerator::MessageLevel message =
193 cmInstallGenerator::SelectMessageLevel(helper.Makefile);
194 return cm::make_unique<cmInstallFileSetGenerator>(
195 target.GetName(), fileSet, destination, args.GetPermissions(),
196 args.GetConfigurations(), args.GetComponent(), message,
197 args.GetExcludeFromAll(), args.GetOptional(),
198 helper.Makefile->GetBacktrace());
201 void AddInstallRuntimeDependenciesGenerator(
202 Helper& helper, cmInstallRuntimeDependencySet* runtimeDependencySet,
203 const cmInstallCommandArguments& runtimeArgs,
204 const cmInstallCommandArguments& libraryArgs,
205 const cmInstallCommandArguments& frameworkArgs,
206 RuntimeDependenciesArgs runtimeDependenciesArgs, bool& installsRuntime,
207 bool& installsLibrary, bool& installsFramework)
210 !helper.Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
212 helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME") == "Darwin";
213 auto const& runtimeDependenciesArgsRef =
214 dllPlatform ? runtimeArgs : libraryArgs;
215 std::vector<std::string> configurations =
216 runtimeDependenciesArgsRef.GetConfigurations();
218 std::copy(frameworkArgs.GetConfigurations().begin(),
219 frameworkArgs.GetConfigurations().end(),
220 std::back_inserter(configurations));
223 // Create file(GET_RUNTIME_DEPENDENCIES) generator.
224 auto getRuntimeDependenciesGenerator =
225 cm::make_unique<cmInstallGetRuntimeDependenciesGenerator>(
226 runtimeDependencySet, std::move(runtimeDependenciesArgs.Directories),
227 std::move(runtimeDependenciesArgs.PreIncludeRegexes),
228 std::move(runtimeDependenciesArgs.PreExcludeRegexes),
229 std::move(runtimeDependenciesArgs.PostIncludeRegexes),
230 std::move(runtimeDependenciesArgs.PostExcludeRegexes),
231 std::move(runtimeDependenciesArgs.PostIncludeFiles),
232 std::move(runtimeDependenciesArgs.PostExcludeFiles),
233 runtimeDependenciesArgsRef.GetComponent(),
234 apple ? frameworkArgs.GetComponent() : "", true, "_CMAKE_DEPS",
235 "_CMAKE_RPATH", configurations,
236 cmInstallGenerator::SelectMessageLevel(helper.Makefile),
237 runtimeDependenciesArgsRef.GetExcludeFromAll() &&
238 (apple ? frameworkArgs.GetExcludeFromAll() : true),
239 helper.Makefile->GetBacktrace());
240 helper.Makefile->AddInstallGenerator(
241 std::move(getRuntimeDependenciesGenerator));
243 // Create the library dependencies generator.
244 auto libraryRuntimeDependenciesGenerator =
245 cm::make_unique<cmInstallRuntimeDependencySetGenerator>(
246 cmInstallRuntimeDependencySetGenerator::DependencyType::Library,
247 runtimeDependencySet, std::vector<std::string>{}, true, std::string{},
248 true, "_CMAKE_DEPS", "_CMAKE_RPATH", "_CMAKE_TMP",
249 dllPlatform ? helper.GetRuntimeDestination(&runtimeArgs)
250 : helper.GetLibraryDestination(&libraryArgs),
251 runtimeDependenciesArgsRef.GetConfigurations(),
252 runtimeDependenciesArgsRef.GetComponent(),
253 runtimeDependenciesArgsRef.GetPermissions(),
254 cmInstallGenerator::SelectMessageLevel(helper.Makefile),
255 runtimeDependenciesArgsRef.GetExcludeFromAll(),
256 helper.Makefile->GetBacktrace());
257 helper.Makefile->AddInstallGenerator(
258 std::move(libraryRuntimeDependenciesGenerator));
260 installsRuntime = true;
262 installsLibrary = true;
266 // Create the framework dependencies generator.
267 auto frameworkRuntimeDependenciesGenerator =
268 cm::make_unique<cmInstallRuntimeDependencySetGenerator>(
269 cmInstallRuntimeDependencySetGenerator::DependencyType::Framework,
270 runtimeDependencySet, std::vector<std::string>{}, true, std::string{},
271 true, "_CMAKE_DEPS", "_CMAKE_RPATH", "_CMAKE_TMP",
272 frameworkArgs.GetDestination(), frameworkArgs.GetConfigurations(),
273 frameworkArgs.GetComponent(), frameworkArgs.GetPermissions(),
274 cmInstallGenerator::SelectMessageLevel(helper.Makefile),
275 frameworkArgs.GetExcludeFromAll(), helper.Makefile->GetBacktrace());
276 helper.Makefile->AddInstallGenerator(
277 std::move(frameworkRuntimeDependenciesGenerator));
278 installsFramework = true;
282 std::set<std::string> const allowedTypes{
283 "BIN", "SBIN", "LIB", "INCLUDE", "SYSCONF",
284 "SHAREDSTATE", "LOCALSTATE", "RUNSTATE", "DATA", "INFO",
285 "LOCALE", "MAN", "DOC",
288 template <typename T>
289 bool AddBundleExecutable(Helper& helper,
290 cmInstallRuntimeDependencySet* runtimeDependencySet,
291 T&& bundleExecutable)
293 if (!runtimeDependencySet->AddBundleExecutable(bundleExecutable)) {
295 "A runtime dependency set may only have one bundle executable.");
301 bool HandleScriptMode(std::vector<std::string> const& args,
302 cmExecutionStatus& status)
304 Helper helper(status);
306 std::string component = helper.DefaultComponentName;
307 int componentCount = 0;
308 bool doing_script = false;
309 bool doing_code = false;
310 bool exclude_from_all = false;
311 bool all_components = false;
313 // Scan the args once for COMPONENT. Only allow one.
315 for (size_t i = 0; i < args.size(); ++i) {
316 if (args[i] == "COMPONENT" && i + 1 < args.size()) {
321 if (args[i] == "EXCLUDE_FROM_ALL") {
322 exclude_from_all = true;
323 } else if (args[i] == "ALL_COMPONENTS") {
324 all_components = true;
328 if (componentCount > 1) {
329 status.SetError("given more than one COMPONENT for the SCRIPT or CODE "
330 "signature of the INSTALL command. "
331 "Use multiple INSTALL commands with one COMPONENT each.");
335 if (all_components && componentCount == 1) {
336 status.SetError("ALL_COMPONENTS and COMPONENT are mutually exclusive");
340 // Scan the args again, this time adding install generators each time we
341 // encounter a SCRIPT or CODE arg:
343 for (std::string const& arg : args) {
344 if (arg == "SCRIPT") {
347 } else if (arg == "CODE") {
348 doing_script = false;
350 } else if (arg == "COMPONENT") {
351 doing_script = false;
353 } else if (doing_script) {
354 doing_script = false;
355 std::string script = arg;
356 if (!cmSystemTools::FileIsFullPath(script)) {
358 cmStrCat(helper.Makefile->GetCurrentSourceDirectory(), '/', arg);
360 if (cmSystemTools::FileIsDirectory(script)) {
361 status.SetError("given a directory as value of SCRIPT argument.");
364 helper.Makefile->AddInstallGenerator(
365 cm::make_unique<cmInstallScriptGenerator>(
366 script, false, component, exclude_from_all, all_components,
367 helper.Makefile->GetBacktrace()));
368 } else if (doing_code) {
370 std::string const& code = arg;
371 helper.Makefile->AddInstallGenerator(
372 cm::make_unique<cmInstallScriptGenerator>(
373 code, true, component, exclude_from_all, all_components,
374 helper.Makefile->GetBacktrace()));
379 status.SetError("given no value for SCRIPT argument.");
383 status.SetError("given no value for CODE argument.");
387 // Tell the global generator about any installation component names
389 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(component);
394 bool HandleTargetsMode(std::vector<std::string> const& args,
395 cmExecutionStatus& status)
397 Helper helper(status);
399 // This is the TARGETS mode.
400 std::vector<cmTarget*> targets;
404 std::vector<std::string> Archive;
405 std::vector<std::string> Library;
406 std::vector<std::string> Runtime;
407 std::vector<std::string> Object;
408 std::vector<std::string> Framework;
409 std::vector<std::string> Bundle;
410 std::vector<std::string> Includes;
411 std::vector<std::string> PrivateHeader;
412 std::vector<std::string> PublicHeader;
413 std::vector<std::string> Resource;
414 std::vector<std::vector<std::string>> FileSets;
417 static auto const argHelper =
418 cmArgumentParser<ArgVectors>{}
419 .Bind("ARCHIVE"_s, &ArgVectors::Archive)
420 .Bind("LIBRARY"_s, &ArgVectors::Library)
421 .Bind("RUNTIME"_s, &ArgVectors::Runtime)
422 .Bind("OBJECTS"_s, &ArgVectors::Object)
423 .Bind("FRAMEWORK"_s, &ArgVectors::Framework)
424 .Bind("BUNDLE"_s, &ArgVectors::Bundle)
425 .Bind("INCLUDES"_s, &ArgVectors::Includes)
426 .Bind("PRIVATE_HEADER"_s, &ArgVectors::PrivateHeader)
427 .Bind("PUBLIC_HEADER"_s, &ArgVectors::PublicHeader)
428 .Bind("RESOURCE"_s, &ArgVectors::Resource)
429 .Bind("FILE_SET"_s, &ArgVectors::FileSets);
431 std::vector<std::string> genericArgVector;
432 ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
434 // now parse the generic args (i.e. the ones not specialized on LIBRARY/
435 // ARCHIVE, RUNTIME etc. (see above)
436 // These generic args also contain the targets and the export stuff
437 std::vector<std::string> targetList;
439 std::vector<std::string> runtimeDependenciesArgVector;
440 std::string runtimeDependencySetArg;
441 std::vector<std::string> unknownArgs;
442 std::vector<std::string> parsedArgs;
443 cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
444 genericArgs.Bind("TARGETS"_s, targetList);
445 genericArgs.Bind("EXPORT"_s, exports);
446 genericArgs.Bind("RUNTIME_DEPENDENCIES"_s, runtimeDependenciesArgVector);
447 genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
448 genericArgs.Parse(genericArgVector, &unknownArgs, nullptr, &parsedArgs);
449 bool success = genericArgs.Finalize();
451 bool withRuntimeDependencies =
452 std::find(parsedArgs.begin(), parsedArgs.end(), "RUNTIME_DEPENDENCIES") !=
454 RuntimeDependenciesArgs runtimeDependenciesArgs =
455 RuntimeDependenciesArgHelper.Parse(runtimeDependenciesArgVector,
458 cmInstallCommandArguments archiveArgs(helper.DefaultComponentName);
459 cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
460 cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
461 cmInstallCommandArguments objectArgs(helper.DefaultComponentName);
462 cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
463 cmInstallCommandArguments bundleArgs(helper.DefaultComponentName);
464 cmInstallCommandArguments privateHeaderArgs(helper.DefaultComponentName);
465 cmInstallCommandArguments publicHeaderArgs(helper.DefaultComponentName);
466 cmInstallCommandArguments resourceArgs(helper.DefaultComponentName);
467 cmInstallCommandIncludesArgument includesArgs;
468 std::vector<cmInstallCommandFileSetArguments> fileSetArgs(
469 argVectors.FileSets.size(), { helper.DefaultComponentName });
471 // now parse the args for specific parts of the target (e.g. LIBRARY,
472 // RUNTIME, ARCHIVE etc.
473 archiveArgs.Parse(argVectors.Archive, &unknownArgs);
474 libraryArgs.Parse(argVectors.Library, &unknownArgs);
475 runtimeArgs.Parse(argVectors.Runtime, &unknownArgs);
476 objectArgs.Parse(argVectors.Object, &unknownArgs);
477 frameworkArgs.Parse(argVectors.Framework, &unknownArgs);
478 bundleArgs.Parse(argVectors.Bundle, &unknownArgs);
479 privateHeaderArgs.Parse(argVectors.PrivateHeader, &unknownArgs);
480 publicHeaderArgs.Parse(argVectors.PublicHeader, &unknownArgs);
481 resourceArgs.Parse(argVectors.Resource, &unknownArgs);
482 includesArgs.Parse(&argVectors.Includes, &unknownArgs);
483 for (std::size_t i = 0; i < argVectors.FileSets.size(); i++) {
484 // We have to create a separate object for the parsing because
485 // cmArgumentParser<void>::Bind() binds to a specific address, but the
486 // objects in the vector can move around. So we parse in an object with a
487 // fixed address and then copy the data into the vector.
488 cmInstallCommandFileSetArguments fileSetArg(helper.DefaultComponentName);
489 fileSetArg.Parse(argVectors.FileSets[i], &unknownArgs);
490 fileSetArgs[i] = std::move(fileSetArg);
493 if (!unknownArgs.empty()) {
496 cmStrCat("TARGETS given unknown argument \"", unknownArgs[0], "\"."));
500 // apply generic args
501 archiveArgs.SetGenericArguments(&genericArgs);
502 libraryArgs.SetGenericArguments(&genericArgs);
503 runtimeArgs.SetGenericArguments(&genericArgs);
504 objectArgs.SetGenericArguments(&genericArgs);
505 frameworkArgs.SetGenericArguments(&genericArgs);
506 bundleArgs.SetGenericArguments(&genericArgs);
507 privateHeaderArgs.SetGenericArguments(&genericArgs);
508 publicHeaderArgs.SetGenericArguments(&genericArgs);
509 resourceArgs.SetGenericArguments(&genericArgs);
510 for (auto& fileSetArg : fileSetArgs) {
511 fileSetArg.SetGenericArguments(&genericArgs);
514 success = success && archiveArgs.Finalize();
515 success = success && libraryArgs.Finalize();
516 success = success && runtimeArgs.Finalize();
517 success = success && objectArgs.Finalize();
518 success = success && frameworkArgs.Finalize();
519 success = success && bundleArgs.Finalize();
520 success = success && privateHeaderArgs.Finalize();
521 success = success && publicHeaderArgs.Finalize();
522 success = success && resourceArgs.Finalize();
523 for (auto& fileSetArg : fileSetArgs) {
524 success = success && fileSetArg.Finalize();
531 // Enforce argument rules too complex to specify for the
532 // general-purpose parser.
533 if (archiveArgs.GetNamelinkOnly() || runtimeArgs.GetNamelinkOnly() ||
534 objectArgs.GetNamelinkOnly() || frameworkArgs.GetNamelinkOnly() ||
535 bundleArgs.GetNamelinkOnly() || privateHeaderArgs.GetNamelinkOnly() ||
536 publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly() ||
537 std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
538 [](const cmInstallCommandFileSetArguments& fileSetArg)
539 -> bool { return fileSetArg.GetNamelinkOnly(); })) {
541 "TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
542 "The NAMELINK_ONLY option may be specified only following LIBRARY.");
545 if (archiveArgs.GetNamelinkSkip() || runtimeArgs.GetNamelinkSkip() ||
546 objectArgs.GetNamelinkSkip() || frameworkArgs.GetNamelinkSkip() ||
547 bundleArgs.GetNamelinkSkip() || privateHeaderArgs.GetNamelinkSkip() ||
548 publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip() ||
549 std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
550 [](const cmInstallCommandFileSetArguments& fileSetArg)
551 -> bool { return fileSetArg.GetNamelinkSkip(); })) {
553 "TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
554 "The NAMELINK_SKIP option may be specified only following LIBRARY.");
557 if (archiveArgs.HasNamelinkComponent() ||
558 runtimeArgs.HasNamelinkComponent() ||
559 objectArgs.HasNamelinkComponent() ||
560 frameworkArgs.HasNamelinkComponent() ||
561 bundleArgs.HasNamelinkComponent() ||
562 privateHeaderArgs.HasNamelinkComponent() ||
563 publicHeaderArgs.HasNamelinkComponent() ||
564 resourceArgs.HasNamelinkComponent() ||
565 std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
566 [](const cmInstallCommandFileSetArguments& fileSetArg)
567 -> bool { return fileSetArg.HasNamelinkComponent(); })) {
569 "TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. "
570 "The NAMELINK_COMPONENT option may be specified only following "
574 if (libraryArgs.GetNamelinkOnly() && libraryArgs.GetNamelinkSkip()) {
575 status.SetError("TARGETS given NAMELINK_ONLY and NAMELINK_SKIP. "
576 "At most one of these two options may be specified.");
579 if (!genericArgs.GetType().empty() || !archiveArgs.GetType().empty() ||
580 !libraryArgs.GetType().empty() || !runtimeArgs.GetType().empty() ||
581 !objectArgs.GetType().empty() || !frameworkArgs.GetType().empty() ||
582 !bundleArgs.GetType().empty() || !privateHeaderArgs.GetType().empty() ||
583 !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty() ||
584 std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
585 [](const cmInstallCommandFileSetArguments& fileSetArg)
586 -> bool { return !fileSetArg.GetType().empty(); })) {
588 "TARGETS given TYPE option. The TYPE option may only be specified in "
589 " install(FILES) and install(DIRECTORIES).");
592 if (std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
593 [](const cmInstallCommandFileSetArguments& fileSetArg)
594 -> bool { return fileSetArg.GetFileSet().empty(); })) {
595 status.SetError("TARGETS given FILE_SET option without file set name.");
599 cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr;
600 if (withRuntimeDependencies) {
601 if (!runtimeDependencySetArg.empty()) {
602 status.SetError("TARGETS cannot have both RUNTIME_DEPENDENCIES and "
603 "RUNTIME_DEPENDENCY_SET.");
606 auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
607 if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
610 cmStrCat("TARGETS RUNTIME_DEPENDENCIES is not supported on system \"",
614 if (helper.Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
615 status.SetError("TARGETS RUNTIME_DEPENDENCIES is not supported "
616 "when cross-compiling.");
619 if (helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME") ==
621 frameworkArgs.GetDestination().empty()) {
623 "TARGETS RUNTIME_DEPENDENCIES given no FRAMEWORK DESTINATION");
626 runtimeDependencySet = helper.Makefile->GetGlobalGenerator()
627 ->CreateAnonymousRuntimeDependencySet();
628 } else if (!runtimeDependencySetArg.empty()) {
629 auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
630 if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
632 status.SetError(cmStrCat(
633 "TARGETS RUNTIME_DEPENDENCY_SET is not supported on system \"", system,
637 runtimeDependencySet =
638 helper.Makefile->GetGlobalGenerator()->GetNamedRuntimeDependencySet(
639 runtimeDependencySetArg);
642 // Select the mode for installing symlinks to versioned shared libraries.
643 cmInstallTargetGenerator::NamelinkModeType namelinkMode =
644 cmInstallTargetGenerator::NamelinkModeNone;
645 if (libraryArgs.GetNamelinkOnly()) {
646 namelinkMode = cmInstallTargetGenerator::NamelinkModeOnly;
647 } else if (libraryArgs.GetNamelinkSkip()) {
648 namelinkMode = cmInstallTargetGenerator::NamelinkModeSkip;
651 // Check if there is something to do.
652 if (targetList.empty()) {
656 for (std::string const& tgt : targetList) {
658 if (helper.Makefile->IsAlias(tgt)) {
660 cmStrCat("TARGETS given target \"", tgt, "\" which is an alias."));
663 // Lookup this target in the current directory.
664 cmTarget* target = helper.Makefile->FindLocalNonAliasTarget(tgt);
666 // If no local target has been found, find it in the global scope.
667 cmTarget* const global_target =
668 helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true);
669 if (global_target && !global_target->IsImported()) {
670 target = global_target;
674 // Found the target. Check its type.
675 if (target->GetType() != cmStateEnums::EXECUTABLE &&
676 target->GetType() != cmStateEnums::STATIC_LIBRARY &&
677 target->GetType() != cmStateEnums::SHARED_LIBRARY &&
678 target->GetType() != cmStateEnums::MODULE_LIBRARY &&
679 target->GetType() != cmStateEnums::OBJECT_LIBRARY &&
680 target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
682 cmStrCat("TARGETS given target \"", tgt,
683 "\" which is not an executable, library, or module."));
686 // Store the target in the list to be installed.
687 targets.push_back(target);
689 // Did not find the target.
691 cmStrCat("TARGETS given target \"", tgt, "\" which does not exist."));
696 // Keep track of whether we will be performing an installation of
697 // any files of the given type.
698 bool installsArchive = false;
699 bool installsLibrary = false;
700 bool installsNamelink = false;
701 bool installsRuntime = false;
702 bool installsObject = false;
703 bool installsFramework = false;
704 bool installsBundle = false;
705 bool installsPrivateHeader = false;
706 bool installsPublicHeader = false;
707 bool installsResource = false;
708 std::vector<bool> installsFileSet(fileSetArgs.size(), false);
710 // Generate install script code to install the given targets.
711 for (cmTarget* ti : targets) {
712 // Handle each target type.
713 cmTarget& target = *ti;
714 std::unique_ptr<cmInstallTargetGenerator> archiveGenerator;
715 std::unique_ptr<cmInstallTargetGenerator> libraryGenerator;
716 std::unique_ptr<cmInstallTargetGenerator> namelinkGenerator;
717 std::unique_ptr<cmInstallTargetGenerator> runtimeGenerator;
718 std::unique_ptr<cmInstallTargetGenerator> objectGenerator;
719 std::unique_ptr<cmInstallTargetGenerator> frameworkGenerator;
720 std::unique_ptr<cmInstallTargetGenerator> bundleGenerator;
721 std::unique_ptr<cmInstallFilesGenerator> privateHeaderGenerator;
722 std::unique_ptr<cmInstallFilesGenerator> publicHeaderGenerator;
723 std::unique_ptr<cmInstallFilesGenerator> resourceGenerator;
724 std::vector<std::unique_ptr<cmInstallFileSetGenerator>> fileSetGenerators;
726 // Avoid selecting default destinations for PUBLIC_HEADER and
727 // PRIVATE_HEADER if any artifacts are specified.
728 bool artifactsSpecified = false;
730 // Track whether this is a namelink-only rule.
731 bool namelinkOnly = false;
733 auto addTargetExport = [&]() -> bool {
734 // Add this install rule to an export if one was specified.
735 if (!exports.empty()) {
736 auto interfaceFileSets = target.GetAllInterfaceFileSets();
738 interfaceFileSets.begin(), interfaceFileSets.end(),
739 [=](const std::string& name) -> bool {
741 fileSetArgs.begin(), fileSetArgs.end(),
742 [=](const cmInstallCommandFileSetArguments& fileSetArg)
743 -> bool { return fileSetArg.GetFileSet() == name; });
745 status.SetError(cmStrCat("TARGETS target ", target.GetName(),
746 " is exported but not all of its interface "
747 "file sets are installed"));
751 auto te = cm::make_unique<cmTargetExport>();
752 te->TargetName = target.GetName();
753 te->ArchiveGenerator = archiveGenerator.get();
754 te->BundleGenerator = bundleGenerator.get();
755 te->FrameworkGenerator = frameworkGenerator.get();
756 te->HeaderGenerator = publicHeaderGenerator.get();
757 te->LibraryGenerator = libraryGenerator.get();
758 te->RuntimeGenerator = runtimeGenerator.get();
759 te->ObjectsGenerator = objectGenerator.get();
760 for (auto const& gen : fileSetGenerators) {
761 te->FileSetGenerators[gen->GetFileSet()] = gen.get();
763 target.AddInstallIncludeDirectories(
764 *te, cmMakeRange(includesArgs.GetIncludeDirs()));
765 te->NamelinkOnly = namelinkOnly;
766 helper.Makefile->GetGlobalGenerator()
767 ->GetExportSets()[exports]
768 .AddTargetExport(std::move(te));
773 switch (target.GetType()) {
774 case cmStateEnums::SHARED_LIBRARY: {
775 // Shared libraries are handled differently on DLL and non-DLL
776 // platforms. All windows platforms are DLL platforms including
777 // cygwin. Currently no other platform is a DLL platform.
778 if (target.IsDLLPlatform()) {
779 // When in namelink only mode skip all libraries on Windows.
780 if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
782 if (!addTargetExport()) {
788 // This is a DLL platform.
789 if (!archiveArgs.GetDestination().empty()) {
790 // The import library uses the ARCHIVE properties.
791 archiveGenerator = CreateInstallTargetGenerator(
792 target, archiveArgs, true, helper.Makefile->GetBacktrace());
793 artifactsSpecified = true;
795 if (!runtimeArgs.GetDestination().empty()) {
796 // The DLL uses the RUNTIME properties.
797 runtimeGenerator = CreateInstallTargetGenerator(
798 target, runtimeArgs, false, helper.Makefile->GetBacktrace());
799 artifactsSpecified = true;
801 if (!archiveGenerator && !runtimeGenerator) {
802 archiveGenerator = CreateInstallTargetGenerator(
803 target, archiveArgs, true, helper.Makefile->GetBacktrace(),
804 helper.GetArchiveDestination(nullptr));
805 runtimeGenerator = CreateInstallTargetGenerator(
806 target, runtimeArgs, false, helper.Makefile->GetBacktrace(),
807 helper.GetRuntimeDestination(nullptr));
809 if (runtimeDependencySet && runtimeGenerator) {
810 runtimeDependencySet->AddLibrary(runtimeGenerator.get());
813 // This is a non-DLL platform.
814 // If it is marked with FRAMEWORK property use the FRAMEWORK set of
815 // INSTALL properties. Otherwise, use the LIBRARY properties.
816 if (target.IsFrameworkOnApple()) {
817 // When in namelink only mode skip frameworks.
818 if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
820 if (!addTargetExport()) {
826 // Use the FRAMEWORK properties.
827 if (!frameworkArgs.GetDestination().empty()) {
828 frameworkGenerator = CreateInstallTargetGenerator(
829 target, frameworkArgs, false, helper.Makefile->GetBacktrace());
832 cmStrCat("TARGETS given no FRAMEWORK DESTINATION for shared "
833 "library FRAMEWORK target \"",
834 target.GetName(), "\"."));
838 // The shared library uses the LIBRARY properties.
839 if (!libraryArgs.GetDestination().empty()) {
840 artifactsSpecified = true;
842 if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) {
843 libraryGenerator = CreateInstallTargetGenerator(
844 target, libraryArgs, false, helper.Makefile->GetBacktrace(),
845 helper.GetLibraryDestination(&libraryArgs));
846 libraryGenerator->SetNamelinkMode(
847 cmInstallTargetGenerator::NamelinkModeSkip);
849 if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) {
850 namelinkGenerator = CreateInstallTargetGenerator(
851 target, libraryArgs, false, helper.Makefile->GetBacktrace(),
852 helper.GetLibraryDestination(&libraryArgs), false, true);
853 namelinkGenerator->SetNamelinkMode(
854 cmInstallTargetGenerator::NamelinkModeOnly);
857 (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
859 if (runtimeDependencySet && libraryGenerator) {
860 runtimeDependencySet->AddLibrary(libraryGenerator.get());
864 case cmStateEnums::STATIC_LIBRARY: {
865 // If it is marked with FRAMEWORK property use the FRAMEWORK set of
866 // INSTALL properties. Otherwise, use the LIBRARY properties.
867 if (target.IsFrameworkOnApple()) {
868 // When in namelink only mode skip frameworks.
869 if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
871 if (!addTargetExport()) {
877 // Use the FRAMEWORK properties.
878 if (!frameworkArgs.GetDestination().empty()) {
879 frameworkGenerator = CreateInstallTargetGenerator(
880 target, frameworkArgs, false, helper.Makefile->GetBacktrace());
883 cmStrCat("TARGETS given no FRAMEWORK DESTINATION for static "
884 "library FRAMEWORK target \"",
885 target.GetName(), "\"."));
889 // Static libraries use ARCHIVE properties.
890 if (!archiveArgs.GetDestination().empty()) {
891 artifactsSpecified = true;
893 archiveGenerator = CreateInstallTargetGenerator(
894 target, archiveArgs, false, helper.Makefile->GetBacktrace(),
895 helper.GetArchiveDestination(&archiveArgs));
898 case cmStateEnums::MODULE_LIBRARY: {
899 // Modules use LIBRARY properties.
900 if (!libraryArgs.GetDestination().empty()) {
901 libraryGenerator = CreateInstallTargetGenerator(
902 target, libraryArgs, false, helper.Makefile->GetBacktrace());
903 libraryGenerator->SetNamelinkMode(namelinkMode);
905 (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
906 if (runtimeDependencySet) {
907 runtimeDependencySet->AddModule(libraryGenerator.get());
911 cmStrCat("TARGETS given no LIBRARY DESTINATION for module "
913 target.GetName(), "\"."));
917 case cmStateEnums::OBJECT_LIBRARY: {
918 // Objects use OBJECT properties.
919 if (!objectArgs.GetDestination().empty()) {
920 // Verify that we know where the objects are to install them.
922 if (!target.HasKnownObjectFileLocation(&reason)) {
924 cmStrCat("TARGETS given OBJECT library \"", target.GetName(),
925 "\" whose objects may not be installed", reason, "."));
929 objectGenerator = CreateInstallTargetGenerator(
930 target, objectArgs, false, helper.Makefile->GetBacktrace());
932 // Installing an OBJECT library without a destination transforms
933 // it to an INTERFACE library. It installs no files but can be
937 case cmStateEnums::EXECUTABLE: {
938 if (target.IsAppBundleOnApple()) {
939 // Application bundles use the BUNDLE properties.
940 if (!bundleArgs.GetDestination().empty()) {
941 bundleGenerator = CreateInstallTargetGenerator(
942 target, bundleArgs, false, helper.Makefile->GetBacktrace());
943 } else if (!runtimeArgs.GetDestination().empty()) {
944 bool failure = false;
945 if (helper.CheckCMP0006(failure)) {
946 // For CMake 2.4 compatibility fallback to the RUNTIME
948 bundleGenerator = CreateInstallTargetGenerator(
949 target, runtimeArgs, false, helper.Makefile->GetBacktrace());
950 } else if (failure) {
954 if (!bundleGenerator) {
955 status.SetError(cmStrCat("TARGETS given no BUNDLE DESTINATION for "
956 "MACOSX_BUNDLE executable target \"",
957 target.GetName(), "\"."));
960 if (runtimeDependencySet) {
961 if (!AddBundleExecutable(helper, runtimeDependencySet,
962 bundleGenerator.get())) {
967 // Executables use the RUNTIME properties.
968 if (!runtimeArgs.GetDestination().empty()) {
969 artifactsSpecified = true;
971 runtimeGenerator = CreateInstallTargetGenerator(
972 target, runtimeArgs, false, helper.Makefile->GetBacktrace(),
973 helper.GetRuntimeDestination(&runtimeArgs));
974 if (runtimeDependencySet) {
975 runtimeDependencySet->AddExecutable(runtimeGenerator.get());
979 // On DLL platforms an executable may also have an import
980 // library. Install it to the archive destination if it
982 if ((target.IsDLLPlatform() || target.IsAIX()) &&
983 !archiveArgs.GetDestination().empty() &&
984 target.IsExecutableWithExports()) {
985 // The import library uses the ARCHIVE properties.
986 artifactsSpecified = true;
987 archiveGenerator = CreateInstallTargetGenerator(
988 target, archiveArgs, true, helper.Makefile->GetBacktrace(), true);
991 case cmStateEnums::INTERFACE_LIBRARY:
992 // Nothing to do. An INTERFACE_LIBRARY can be installed, but the
993 // only effect of that is to make it exportable. It installs no
994 // other files itself.
996 // This should never happen due to the above type check.
1001 // These well-known sets of files are installed *automatically* for
1002 // FRAMEWORK SHARED library targets on the Mac as part of installing the
1003 // FRAMEWORK. For other target types or on other platforms, they are not
1004 // installed automatically and so we need to create install files
1005 // generators for them.
1006 bool createInstallGeneratorsForTargetFileSets = true;
1008 if (target.IsFrameworkOnApple()) {
1009 createInstallGeneratorsForTargetFileSets = false;
1012 if (createInstallGeneratorsForTargetFileSets && !namelinkOnly) {
1013 cmValue files = target.GetProperty("PRIVATE_HEADER");
1014 if (cmNonempty(files)) {
1015 std::vector<std::string> relFiles = cmExpandedList(*files);
1016 std::vector<std::string> absFiles;
1017 if (!helper.MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) {
1021 // Create the files install generator.
1022 if (!artifactsSpecified ||
1023 !privateHeaderArgs.GetDestination().empty()) {
1024 privateHeaderGenerator = CreateInstallFilesGenerator(
1025 helper.Makefile, absFiles, privateHeaderArgs, false,
1026 helper.GetIncludeDestination(&privateHeaderArgs));
1028 std::ostringstream e;
1029 e << "Target " << target.GetName() << " has "
1030 << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
1031 helper.Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
1035 files = target.GetProperty("PUBLIC_HEADER");
1036 if (cmNonempty(files)) {
1037 std::vector<std::string> relFiles = cmExpandedList(*files);
1038 std::vector<std::string> absFiles;
1039 if (!helper.MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) {
1043 // Create the files install generator.
1044 if (!artifactsSpecified ||
1045 !publicHeaderArgs.GetDestination().empty()) {
1046 publicHeaderGenerator = CreateInstallFilesGenerator(
1047 helper.Makefile, absFiles, publicHeaderArgs, false,
1048 helper.GetIncludeDestination(&publicHeaderArgs));
1050 std::ostringstream e;
1051 e << "Target " << target.GetName() << " has "
1052 << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION.";
1053 helper.Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
1057 files = target.GetProperty("RESOURCE");
1058 if (cmNonempty(files)) {
1059 std::vector<std::string> relFiles = cmExpandedList(*files);
1060 std::vector<std::string> absFiles;
1061 if (!helper.MakeFilesFullPath("RESOURCE", relFiles, absFiles)) {
1065 // Create the files install generator.
1066 if (!resourceArgs.GetDestination().empty()) {
1067 resourceGenerator = CreateInstallFilesGenerator(
1068 helper.Makefile, absFiles, resourceArgs, false);
1069 } else if (!target.IsAppBundleOnApple()) {
1070 helper.Makefile->IssueMessage(
1071 MessageType::AUTHOR_WARNING,
1072 cmStrCat("Target ", target.GetName(),
1073 " has RESOURCE files but no RESOURCE DESTINATION."));
1078 if (!namelinkOnly) {
1079 for (std::size_t i = 0; i < fileSetArgs.size(); i++) {
1080 if (auto* fileSet = target.GetFileSet(fileSetArgs[i].GetFileSet())) {
1081 auto interfaceFileSetEntries = cmExpandedList(target.GetSafeProperty(
1082 cmTarget::GetInterfaceFileSetsPropertyName(fileSet->GetType())));
1083 if (std::find(interfaceFileSetEntries.begin(),
1084 interfaceFileSetEntries.end(),
1085 fileSetArgs[i].GetFileSet()) !=
1086 interfaceFileSetEntries.end()) {
1087 std::string destination;
1088 if (fileSet->GetType() == "HEADERS"_s) {
1089 destination = helper.GetIncludeDestination(&fileSetArgs[i]);
1091 destination = fileSetArgs[i].GetDestination();
1092 if (destination.empty()) {
1093 status.SetError(cmStrCat(
1094 "TARGETS given no FILE_SET DESTINATION for target \"",
1095 target.GetName(), "\" file set \"", fileSet->GetName(),
1100 fileSetGenerators.push_back(CreateInstallFileSetGenerator(
1101 helper, target, fileSet, destination, fileSetArgs[i]));
1102 installsFileSet[i] = true;
1108 // Add this install rule to an export if one was specified.
1109 if (!addTargetExport()) {
1113 // Keep track of whether we're installing anything in each category
1114 installsArchive = installsArchive || archiveGenerator;
1115 installsLibrary = installsLibrary || libraryGenerator;
1116 installsNamelink = installsNamelink || namelinkGenerator;
1117 installsRuntime = installsRuntime || runtimeGenerator;
1118 installsObject = installsObject || objectGenerator;
1119 installsFramework = installsFramework || frameworkGenerator;
1120 installsBundle = installsBundle || bundleGenerator;
1121 installsPrivateHeader = installsPrivateHeader || privateHeaderGenerator;
1122 installsPublicHeader = installsPublicHeader || publicHeaderGenerator;
1123 installsResource = installsResource || resourceGenerator;
1125 helper.Makefile->AddInstallGenerator(std::move(archiveGenerator));
1126 helper.Makefile->AddInstallGenerator(std::move(libraryGenerator));
1127 helper.Makefile->AddInstallGenerator(std::move(namelinkGenerator));
1128 helper.Makefile->AddInstallGenerator(std::move(runtimeGenerator));
1129 helper.Makefile->AddInstallGenerator(std::move(objectGenerator));
1130 helper.Makefile->AddInstallGenerator(std::move(frameworkGenerator));
1131 helper.Makefile->AddInstallGenerator(std::move(bundleGenerator));
1132 helper.Makefile->AddInstallGenerator(std::move(privateHeaderGenerator));
1133 helper.Makefile->AddInstallGenerator(std::move(publicHeaderGenerator));
1134 helper.Makefile->AddInstallGenerator(std::move(resourceGenerator));
1135 for (auto& gen : fileSetGenerators) {
1136 helper.Makefile->AddInstallGenerator(std::move(gen));
1140 if (withRuntimeDependencies && !runtimeDependencySet->Empty()) {
1141 AddInstallRuntimeDependenciesGenerator(
1142 helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs,
1143 std::move(runtimeDependenciesArgs), installsRuntime, installsLibrary,
1147 // Tell the global generator about any installation component names
1149 if (installsArchive) {
1150 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1151 archiveArgs.GetComponent());
1153 if (installsLibrary) {
1154 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1155 libraryArgs.GetComponent());
1157 if (installsNamelink) {
1158 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1159 libraryArgs.GetNamelinkComponent());
1161 if (installsRuntime) {
1162 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1163 runtimeArgs.GetComponent());
1165 if (installsObject) {
1166 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1167 objectArgs.GetComponent());
1169 if (installsFramework) {
1170 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1171 frameworkArgs.GetComponent());
1173 if (installsBundle) {
1174 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1175 bundleArgs.GetComponent());
1177 if (installsPrivateHeader) {
1178 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1179 privateHeaderArgs.GetComponent());
1181 if (installsPublicHeader) {
1182 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1183 publicHeaderArgs.GetComponent());
1185 if (installsResource) {
1186 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1187 resourceArgs.GetComponent());
1189 for (std::size_t i = 0; i < fileSetArgs.size(); i++) {
1190 if (installsFileSet[i]) {
1191 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1192 fileSetArgs[i].GetComponent());
1199 bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args,
1200 cmExecutionStatus& status)
1202 Helper helper(status);
1204 // This is the IMPORTED_RUNTIME_ARTIFACTS mode.
1205 std::vector<cmTarget*> targets;
1209 std::vector<std::string> Library;
1210 std::vector<std::string> Runtime;
1211 std::vector<std::string> Framework;
1212 std::vector<std::string> Bundle;
1215 static auto const argHelper = cmArgumentParser<ArgVectors>{}
1216 .Bind("LIBRARY"_s, &ArgVectors::Library)
1217 .Bind("RUNTIME"_s, &ArgVectors::Runtime)
1218 .Bind("FRAMEWORK"_s, &ArgVectors::Framework)
1219 .Bind("BUNDLE"_s, &ArgVectors::Bundle);
1221 std::vector<std::string> genericArgVector;
1222 ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
1224 // now parse the generic args (i.e. the ones not specialized on LIBRARY,
1225 // RUNTIME etc. (see above)
1226 std::vector<std::string> targetList;
1227 std::string runtimeDependencySetArg;
1228 std::vector<std::string> unknownArgs;
1229 cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
1230 genericArgs.Bind("IMPORTED_RUNTIME_ARTIFACTS"_s, targetList)
1231 .Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
1232 genericArgs.Parse(genericArgVector, &unknownArgs);
1233 bool success = genericArgs.Finalize();
1235 cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
1236 cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
1237 cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
1238 cmInstallCommandArguments bundleArgs(helper.DefaultComponentName);
1240 // now parse the args for specific parts of the target (e.g. LIBRARY,
1242 libraryArgs.Parse(argVectors.Library, &unknownArgs);
1243 runtimeArgs.Parse(argVectors.Runtime, &unknownArgs);
1244 frameworkArgs.Parse(argVectors.Framework, &unknownArgs);
1245 bundleArgs.Parse(argVectors.Bundle, &unknownArgs);
1247 if (!unknownArgs.empty()) {
1248 // Unknown argument.
1250 cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given unknown argument \"",
1251 unknownArgs[0], "\"."));
1255 // apply generic args
1256 libraryArgs.SetGenericArguments(&genericArgs);
1257 runtimeArgs.SetGenericArguments(&genericArgs);
1258 frameworkArgs.SetGenericArguments(&genericArgs);
1259 bundleArgs.SetGenericArguments(&genericArgs);
1261 success = success && libraryArgs.Finalize();
1262 success = success && runtimeArgs.Finalize();
1263 success = success && frameworkArgs.Finalize();
1264 success = success && bundleArgs.Finalize();
1270 cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr;
1271 if (!runtimeDependencySetArg.empty()) {
1272 auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
1273 if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
1276 cmStrCat("IMPORTED_RUNTIME_ARTIFACTS RUNTIME_DEPENDENCY_SET is not "
1277 "supported on system \"",
1281 runtimeDependencySet =
1282 helper.Makefile->GetGlobalGenerator()->GetNamedRuntimeDependencySet(
1283 runtimeDependencySetArg);
1286 // Check if there is something to do.
1287 if (targetList.empty()) {
1291 for (std::string const& tgt : targetList) {
1292 if (helper.Makefile->IsAlias(tgt)) {
1293 status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"",
1294 tgt, "\" which is an alias."));
1297 // Lookup this target in the current directory.
1298 cmTarget* target = helper.Makefile->FindTargetToUse(tgt);
1299 if (!target || !target->IsImported()) {
1300 // If no local target has been found, find it in the global scope.
1301 cmTarget* const global_target =
1302 helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true);
1303 if (global_target && global_target->IsImported()) {
1304 target = global_target;
1308 // Found the target. Check its type.
1309 if (target->GetType() != cmStateEnums::EXECUTABLE &&
1310 target->GetType() != cmStateEnums::SHARED_LIBRARY &&
1311 target->GetType() != cmStateEnums::MODULE_LIBRARY) {
1313 cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"", tgt,
1314 "\" which is not an executable, library, or module."));
1317 // Store the target in the list to be installed.
1318 targets.push_back(target);
1320 // Did not find the target.
1321 status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"",
1322 tgt, "\" which does not exist."));
1327 // Keep track of whether we will be performing an installation of
1328 // any files of the given type.
1329 bool installsLibrary = false;
1330 bool installsRuntime = false;
1331 bool installsFramework = false;
1332 bool installsBundle = false;
1334 auto const createInstallGenerator =
1335 [helper](cmTarget& target, const cmInstallCommandArguments& typeArgs,
1336 const std::string& destination)
1337 -> std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator> {
1338 return cm::make_unique<cmInstallImportedRuntimeArtifactsGenerator>(
1339 target.GetName(), destination, typeArgs.GetPermissions(),
1340 typeArgs.GetConfigurations(), typeArgs.GetComponent(),
1341 cmInstallGenerator::SelectMessageLevel(helper.Makefile),
1342 typeArgs.GetExcludeFromAll(), typeArgs.GetOptional(),
1343 helper.Makefile->GetBacktrace());
1346 // Generate install script code to install the given targets.
1347 for (cmTarget* ti : targets) {
1348 // Handle each target type.
1349 cmTarget& target = *ti;
1350 std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
1352 std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
1354 std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
1356 std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
1359 switch (target.GetType()) {
1360 case cmStateEnums::SHARED_LIBRARY:
1361 if (target.IsDLLPlatform()) {
1362 runtimeGenerator = createInstallGenerator(
1363 target, runtimeArgs, helper.GetRuntimeDestination(&runtimeArgs));
1364 if (runtimeDependencySet) {
1365 runtimeDependencySet->AddLibrary(runtimeGenerator.get());
1367 } else if (target.IsFrameworkOnApple()) {
1368 if (frameworkArgs.GetDestination().empty()) {
1369 status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given no "
1370 "FRAMEWORK DESTINATION for shared "
1371 "library FRAMEWORK target \"",
1372 target.GetName(), "\"."));
1375 frameworkGenerator = createInstallGenerator(
1376 target, frameworkArgs, frameworkArgs.GetDestination());
1377 if (runtimeDependencySet) {
1378 runtimeDependencySet->AddLibrary(frameworkGenerator.get());
1381 libraryGenerator = createInstallGenerator(
1382 target, libraryArgs, helper.GetLibraryDestination(&libraryArgs));
1383 if (runtimeDependencySet) {
1384 runtimeDependencySet->AddLibrary(libraryGenerator.get());
1388 case cmStateEnums::MODULE_LIBRARY:
1389 libraryGenerator = createInstallGenerator(
1390 target, libraryArgs, helper.GetLibraryDestination(&libraryArgs));
1391 if (runtimeDependencySet) {
1392 runtimeDependencySet->AddModule(libraryGenerator.get());
1395 case cmStateEnums::EXECUTABLE:
1396 if (target.IsAppBundleOnApple()) {
1397 if (bundleArgs.GetDestination().empty()) {
1399 cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given no BUNDLE "
1400 "DESTINATION for MACOSX_BUNDLE executable target \"",
1401 target.GetName(), "\"."));
1404 bundleGenerator = createInstallGenerator(
1405 target, bundleArgs, bundleArgs.GetDestination());
1406 if (runtimeDependencySet) {
1407 if (!AddBundleExecutable(helper, runtimeDependencySet,
1408 bundleGenerator.get())) {
1413 runtimeGenerator = createInstallGenerator(
1414 target, runtimeArgs, helper.GetRuntimeDestination(&runtimeArgs));
1415 if (runtimeDependencySet) {
1416 runtimeDependencySet->AddExecutable(runtimeGenerator.get());
1421 assert(false && "This should never happen");
1425 // Keep track of whether we're installing anything in each category
1426 installsLibrary = installsLibrary || libraryGenerator;
1427 installsRuntime = installsRuntime || runtimeGenerator;
1428 installsFramework = installsFramework || frameworkGenerator;
1429 installsBundle = installsBundle || bundleGenerator;
1431 helper.Makefile->AddInstallGenerator(std::move(libraryGenerator));
1432 helper.Makefile->AddInstallGenerator(std::move(runtimeGenerator));
1433 helper.Makefile->AddInstallGenerator(std::move(frameworkGenerator));
1434 helper.Makefile->AddInstallGenerator(std::move(bundleGenerator));
1437 // Tell the global generator about any installation component names
1439 if (installsLibrary) {
1440 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1441 libraryArgs.GetComponent());
1443 if (installsRuntime) {
1444 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1445 runtimeArgs.GetComponent());
1447 if (installsFramework) {
1448 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1449 frameworkArgs.GetComponent());
1451 if (installsBundle) {
1452 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1453 bundleArgs.GetComponent());
1459 bool HandleFilesMode(std::vector<std::string> const& args,
1460 cmExecutionStatus& status)
1462 Helper helper(status);
1464 // This is the FILES mode.
1465 bool programs = (args[0] == "PROGRAMS");
1466 cmInstallCommandArguments ica(helper.DefaultComponentName);
1467 std::vector<std::string> files;
1468 ica.Bind(programs ? "PROGRAMS"_s : "FILES"_s, files);
1469 std::vector<std::string> unknownArgs;
1470 ica.Parse(args, &unknownArgs);
1472 if (!unknownArgs.empty()) {
1473 // Unknown argument.
1475 cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\"."));
1479 std::string type = ica.GetType();
1480 if (!type.empty() && allowedTypes.count(type) == 0) {
1482 cmStrCat(args[0], " given non-type \"", type, "\" with TYPE argument."));
1486 const std::vector<std::string>& filesVector = files;
1488 // Check if there is something to do.
1489 if (filesVector.empty()) {
1493 if (!ica.GetRename().empty() && filesVector.size() > 1) {
1494 // The rename option works only with one file.
1496 cmStrCat(args[0], " given RENAME option with more than one file."));
1500 std::vector<std::string> absFiles;
1501 if (!helper.MakeFilesFullPath(args[0].c_str(), filesVector, absFiles)) {
1505 cmPolicies::PolicyStatus policyStatus =
1506 helper.Makefile->GetPolicyStatus(cmPolicies::CMP0062);
1508 cmGlobalGenerator* gg = helper.Makefile->GetGlobalGenerator();
1509 for (std::string const& file : filesVector) {
1510 if (gg->IsExportedTargetsFile(file)) {
1511 const char* modal = nullptr;
1512 std::ostringstream e;
1513 MessageType messageType = MessageType::AUTHOR_WARNING;
1515 switch (policyStatus) {
1516 case cmPolicies::WARN:
1517 e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0062) << "\n";
1520 case cmPolicies::OLD:
1522 case cmPolicies::REQUIRED_IF_USED:
1523 case cmPolicies::REQUIRED_ALWAYS:
1524 case cmPolicies::NEW:
1526 messageType = MessageType::FATAL_ERROR;
1530 e << "The file\n " << file
1531 << "\nwas generated by the export() "
1534 << " not be installed with the "
1535 "install() command. Use the install(EXPORT) mechanism "
1536 "instead. See the cmake-packages(7) manual for more.\n";
1537 helper.Makefile->IssueMessage(messageType, e.str());
1538 if (messageType == MessageType::FATAL_ERROR) {
1545 if (!ica.Finalize()) {
1549 if (!type.empty() && !ica.GetDestination().empty()) {
1550 status.SetError(cmStrCat(args[0],
1551 " given both TYPE and DESTINATION arguments. "
1552 "You may only specify one."));
1556 std::string destination = helper.GetDestinationForType(&ica, type);
1557 if (destination.empty()) {
1558 // A destination is required.
1559 status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
1563 // Create the files install generator.
1564 helper.Makefile->AddInstallGenerator(CreateInstallFilesGenerator(
1565 helper.Makefile, absFiles, ica, programs, destination));
1567 // Tell the global generator about any installation component names
1569 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
1570 ica.GetComponent());
1575 bool HandleDirectoryMode(std::vector<std::string> const& args,
1576 cmExecutionStatus& status)
1578 Helper helper(status);
1590 DoingConfigurations,
1594 Doing doing = DoingDirs;
1595 bool in_match_mode = false;
1596 bool optional = false;
1597 bool exclude_from_all = false;
1598 bool message_never = false;
1599 std::vector<std::string> dirs;
1600 const std::string* destination = nullptr;
1601 std::string permissions_file;
1602 std::string permissions_dir;
1603 std::vector<std::string> configurations;
1604 std::string component = helper.DefaultComponentName;
1605 std::string literal_args;
1607 for (unsigned int i = 1; i < args.size(); ++i) {
1608 if (args[i] == "DESTINATION") {
1609 if (in_match_mode) {
1610 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1611 "\" after PATTERN or REGEX."));
1615 // Switch to setting the destination property.
1616 doing = DoingDestination;
1617 } else if (args[i] == "TYPE") {
1618 if (in_match_mode) {
1619 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1620 "\" after PATTERN or REGEX."));
1624 // Switch to setting the type.
1626 } else if (args[i] == "OPTIONAL") {
1627 if (in_match_mode) {
1628 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1629 "\" after PATTERN or REGEX."));
1633 // Mark the rule as optional.
1636 } else if (args[i] == "MESSAGE_NEVER") {
1637 if (in_match_mode) {
1638 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1639 "\" after PATTERN or REGEX."));
1643 // Mark the rule as quiet.
1644 message_never = true;
1646 } else if (args[i] == "PATTERN") {
1647 // Switch to a new pattern match rule.
1648 doing = DoingPattern;
1649 in_match_mode = true;
1650 } else if (args[i] == "REGEX") {
1651 // Switch to a new regex match rule.
1653 in_match_mode = true;
1654 } else if (args[i] == "EXCLUDE") {
1655 // Add this property to the current match rule.
1656 if (!in_match_mode || doing == DoingPattern || doing == DoingRegex) {
1657 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1658 "\" before a PATTERN or REGEX is given."));
1661 literal_args += " EXCLUDE";
1663 } else if (args[i] == "PERMISSIONS") {
1664 if (!in_match_mode) {
1665 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1666 "\" before a PATTERN or REGEX is given."));
1670 // Switch to setting the current match permissions property.
1671 literal_args += " PERMISSIONS";
1672 doing = DoingPermsMatch;
1673 } else if (args[i] == "FILE_PERMISSIONS") {
1674 if (in_match_mode) {
1675 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1676 "\" after PATTERN or REGEX."));
1680 // Switch to setting the file permissions property.
1681 doing = DoingPermsFile;
1682 } else if (args[i] == "DIRECTORY_PERMISSIONS") {
1683 if (in_match_mode) {
1684 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1685 "\" after PATTERN or REGEX."));
1689 // Switch to setting the directory permissions property.
1690 doing = DoingPermsDir;
1691 } else if (args[i] == "USE_SOURCE_PERMISSIONS") {
1692 if (in_match_mode) {
1693 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1694 "\" after PATTERN or REGEX."));
1698 // Add this option literally.
1699 literal_args += " USE_SOURCE_PERMISSIONS";
1701 } else if (args[i] == "FILES_MATCHING") {
1702 if (in_match_mode) {
1703 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1704 "\" after PATTERN or REGEX."));
1708 // Add this option literally.
1709 literal_args += " FILES_MATCHING";
1711 } else if (args[i] == "CONFIGURATIONS") {
1712 if (in_match_mode) {
1713 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1714 "\" after PATTERN or REGEX."));
1718 // Switch to setting the configurations property.
1719 doing = DoingConfigurations;
1720 } else if (args[i] == "COMPONENT") {
1721 if (in_match_mode) {
1722 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1723 "\" after PATTERN or REGEX."));
1727 // Switch to setting the component property.
1728 doing = DoingComponent;
1729 } else if (args[i] == "EXCLUDE_FROM_ALL") {
1730 if (in_match_mode) {
1731 status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
1732 "\" after PATTERN or REGEX."));
1735 exclude_from_all = true;
1737 } else if (doing == DoingDirs) {
1738 // Convert this directory to a full path.
1739 std::string dir = args[i];
1740 std::string::size_type gpos = cmGeneratorExpression::Find(dir);
1741 if (gpos != 0 && !cmSystemTools::FileIsFullPath(dir)) {
1743 cmStrCat(helper.Makefile->GetCurrentSourceDirectory(), '/', args[i]);
1746 // Make sure the name is a directory.
1747 if (cmSystemTools::FileExists(dir) &&
1748 !cmSystemTools::FileIsDirectory(dir)) {
1749 status.SetError(cmStrCat(args[0], " given non-directory \"", args[i],
1754 // Store the directory for installation.
1755 dirs.push_back(std::move(dir));
1756 } else if (doing == DoingConfigurations) {
1757 configurations.push_back(args[i]);
1758 } else if (doing == DoingDestination) {
1759 destination = &args[i];
1761 } else if (doing == DoingType) {
1762 if (allowedTypes.count(args[i]) == 0) {
1763 status.SetError(cmStrCat(args[0], " given non-type \"", args[i],
1764 "\" with TYPE argument."));
1770 } else if (doing == DoingPattern) {
1771 // Convert the pattern to a regular expression. Require a
1772 // leading slash and trailing end-of-string in the matched
1773 // string to make sure the pattern matches only whole file
1775 literal_args += " REGEX \"/";
1776 std::string regex = cmsys::Glob::PatternToRegex(args[i], false);
1777 cmSystemTools::ReplaceString(regex, "\\", "\\\\");
1778 literal_args += regex;
1779 literal_args += "$\"";
1781 } else if (doing == DoingRegex) {
1782 literal_args += " REGEX \"";
1783 // Match rules are case-insensitive on some platforms.
1784 #if defined(_WIN32) || defined(__APPLE__)
1785 std::string regex = cmSystemTools::LowerCase(args[i]);
1787 std::string regex = args[i];
1789 cmSystemTools::ReplaceString(regex, "\\", "\\\\");
1790 literal_args += regex;
1791 literal_args += "\"";
1793 } else if (doing == DoingComponent) {
1794 component = args[i];
1796 } else if (doing == DoingPermsFile) {
1797 // Check the requested permission.
1798 if (!cmInstallCommandArguments::CheckPermissions(args[i],
1799 permissions_file)) {
1800 status.SetError(cmStrCat(args[0], " given invalid file permission \"",
1804 } else if (doing == DoingPermsDir) {
1805 // Check the requested permission.
1806 if (!cmInstallCommandArguments::CheckPermissions(args[i],
1808 status.SetError(cmStrCat(
1809 args[0], " given invalid directory permission \"", args[i], "\"."));
1812 } else if (doing == DoingPermsMatch) {
1813 // Check the requested permission.
1814 if (!cmInstallCommandArguments::CheckPermissions(args[i],
1817 cmStrCat(args[0], " given invalid permission \"", args[i], "\"."));
1821 // Unknown argument.
1823 cmStrCat(args[0], " given unknown argument \"", args[i], "\"."));
1828 // Support installing an empty directory.
1829 if (dirs.empty() && destination) {
1830 dirs.emplace_back();
1833 // Check if there is something to do.
1837 std::string destinationStr;
1840 // A destination is required.
1841 status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
1844 destinationStr = helper.GetDestinationForType(nullptr, type);
1845 destination = &destinationStr;
1846 } else if (!type.empty()) {
1847 status.SetError(cmStrCat(args[0],
1848 " given both TYPE and DESTINATION "
1849 "arguments. You may only specify one."));
1853 cmInstallGenerator::MessageLevel message =
1854 cmInstallGenerator::SelectMessageLevel(helper.Makefile, message_never);
1856 // Create the directory install generator.
1857 helper.Makefile->AddInstallGenerator(
1858 cm::make_unique<cmInstallDirectoryGenerator>(
1859 dirs, *destination, permissions_file, permissions_dir, configurations,
1860 component, message, exclude_from_all, literal_args, optional,
1861 helper.Makefile->GetBacktrace()));
1863 // Tell the global generator about any installation component names
1865 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(component);
1870 bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
1871 cmExecutionStatus& status)
1873 #ifndef CMAKE_BOOTSTRAP
1874 Helper helper(status);
1876 // This is the EXPORT mode.
1877 cmInstallCommandArguments ica(helper.DefaultComponentName);
1880 std::string name_space;
1881 bool exportOld = false;
1882 std::string filename;
1884 ica.Bind("EXPORT_ANDROID_MK"_s, exp);
1885 ica.Bind("NAMESPACE"_s, name_space);
1886 ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld);
1887 ica.Bind("FILE"_s, filename);
1889 std::vector<std::string> unknownArgs;
1890 ica.Parse(args, &unknownArgs);
1892 if (!unknownArgs.empty()) {
1893 // Unknown argument.
1895 cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\"."));
1899 if (!ica.Finalize()) {
1903 // Make sure there is a destination.
1904 if (ica.GetDestination().empty()) {
1905 // A destination is required.
1906 status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
1910 // Check the file name.
1911 std::string fname = filename;
1912 if (fname.find_first_of(":/\\") != std::string::npos) {
1913 status.SetError(cmStrCat(args[0], " given invalid export file name \"",
1915 "\". The FILE argument may not contain a path. "
1916 "Specify the path in the DESTINATION argument."));
1920 // Check the file extension.
1921 if (!fname.empty() &&
1922 cmSystemTools::GetFilenameLastExtension(fname) != ".mk") {
1923 status.SetError(cmStrCat(
1924 args[0], " given invalid export file name \"", fname,
1925 R"(". The FILE argument must specify a name ending in ".mk".)"));
1928 if (fname.find_first_of(":/\\") != std::string::npos) {
1930 cmStrCat(args[0], " given export name \"", exp,
1932 "This name cannot be safely converted to a file name. "
1933 "Specify a different export name or use the FILE option to set "
1934 "a file name explicitly."));
1937 // Use the default name
1938 if (fname.empty()) {
1939 fname = "Android.mk";
1942 cmExportSet& exportSet =
1943 helper.Makefile->GetGlobalGenerator()->GetExportSets()[exp];
1945 cmInstallGenerator::MessageLevel message =
1946 cmInstallGenerator::SelectMessageLevel(helper.Makefile);
1948 // Create the export install generator.
1949 helper.Makefile->AddInstallGenerator(
1950 cm::make_unique<cmInstallExportGenerator>(
1951 &exportSet, ica.GetDestination(), ica.GetPermissions(),
1952 ica.GetConfigurations(), ica.GetComponent(), message,
1953 ica.GetExcludeFromAll(), fname, name_space, exportOld, true,
1954 helper.Makefile->GetBacktrace()));
1958 static_cast<void>(args);
1959 status.SetError("EXPORT_ANDROID_MK not supported in bootstrap cmake");
1964 bool HandleExportMode(std::vector<std::string> const& args,
1965 cmExecutionStatus& status)
1967 Helper helper(status);
1969 // This is the EXPORT mode.
1970 cmInstallCommandArguments ica(helper.DefaultComponentName);
1973 std::string name_space;
1974 bool exportOld = false;
1975 std::string filename;
1977 ica.Bind("EXPORT"_s, exp);
1978 ica.Bind("NAMESPACE"_s, name_space);
1979 ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld);
1980 ica.Bind("FILE"_s, filename);
1982 std::vector<std::string> unknownArgs;
1983 ica.Parse(args, &unknownArgs);
1985 if (!unknownArgs.empty()) {
1986 // Unknown argument.
1988 cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\"."));
1992 if (!ica.Finalize()) {
1996 // Make sure there is a destination.
1997 if (ica.GetDestination().empty()) {
1998 // A destination is required.
1999 status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
2003 // Check the file name.
2004 std::string fname = filename;
2005 if (fname.find_first_of(":/\\") != std::string::npos) {
2006 status.SetError(cmStrCat(args[0], " given invalid export file name \"",
2009 "The FILE argument may not contain a path. "
2010 "Specify the path in the DESTINATION argument."));
2014 // Check the file extension.
2015 if (!fname.empty() &&
2016 cmSystemTools::GetFilenameLastExtension(fname) != ".cmake") {
2018 cmStrCat(args[0], " given invalid export file name \"", fname,
2020 "The FILE argument must specify a name ending in \".cmake\"."));
2024 // Construct the file name.
2025 if (fname.empty()) {
2026 fname = cmStrCat(exp, ".cmake");
2028 if (fname.find_first_of(":/\\") != std::string::npos) {
2029 status.SetError(cmStrCat(
2030 args[0], " given export name \"", exp,
2032 "This name cannot be safely converted to a file name. "
2033 "Specify a different export name or use the FILE option to set "
2034 "a file name explicitly."));
2039 cmExportSet& exportSet =
2040 helper.Makefile->GetGlobalGenerator()->GetExportSets()[exp];
2042 for (auto const& te : exportSet.GetTargetExports()) {
2044 helper.Makefile->GetGlobalGenerator()->FindTarget(te->TargetName);
2045 const bool newCMP0022Behavior =
2046 (tgt && tgt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
2047 tgt->GetPolicyStatusCMP0022() != cmPolicies::OLD);
2049 if (!newCMP0022Behavior) {
2050 status.SetError(cmStrCat(
2051 "INSTALL(EXPORT) given keyword \""
2052 "EXPORT_LINK_INTERFACE_LIBRARIES\", but target \"",
2053 te->TargetName, "\" does not have policy CMP0022 set to NEW."));
2059 cmInstallGenerator::MessageLevel message =
2060 cmInstallGenerator::SelectMessageLevel(helper.Makefile);
2062 // Create the export install generator.
2063 helper.Makefile->AddInstallGenerator(
2064 cm::make_unique<cmInstallExportGenerator>(
2065 &exportSet, ica.GetDestination(), ica.GetPermissions(),
2066 ica.GetConfigurations(), ica.GetComponent(), message,
2067 ica.GetExcludeFromAll(), fname, name_space, exportOld, false,
2068 helper.Makefile->GetBacktrace()));
2073 bool HandleRuntimeDependencySetMode(std::vector<std::string> const& args,
2074 cmExecutionStatus& status)
2076 Helper helper(status);
2078 auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
2079 if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
2081 status.SetError(cmStrCat(
2082 "RUNTIME_DEPENDENCY_SET is not supported on system \"", system, '"'));
2086 // This is the RUNTIME_DEPENDENCY_SET mode.
2087 cmInstallRuntimeDependencySet* runtimeDependencySet;
2091 std::vector<std::string> Library;
2092 std::vector<std::string> Runtime;
2093 std::vector<std::string> Framework;
2096 static auto const argHelper = cmArgumentParser<ArgVectors>{}
2097 .Bind("LIBRARY"_s, &ArgVectors::Library)
2098 .Bind("RUNTIME"_s, &ArgVectors::Runtime)
2099 .Bind("FRAMEWORK"_s, &ArgVectors::Framework);
2101 std::vector<std::string> genericArgVector;
2102 ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
2104 // now parse the generic args (i.e. the ones not specialized on LIBRARY,
2105 // RUNTIME, FRAMEWORK etc. (see above)
2106 // These generic args also contain the runtime dependency set
2107 std::string runtimeDependencySetArg;
2108 std::vector<std::string> runtimeDependencyArgVector;
2109 std::vector<std::string> parsedArgs;
2110 cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
2111 genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
2112 genericArgs.Parse(genericArgVector, &runtimeDependencyArgVector, nullptr,
2114 bool success = genericArgs.Finalize();
2116 cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
2117 cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
2118 cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
2120 // Now also parse the file(GET_RUNTIME_DEPENDENCY) args
2121 std::vector<std::string> unknownArgs;
2122 auto runtimeDependencyArgs = RuntimeDependenciesArgHelper.Parse(
2123 runtimeDependencyArgVector, &unknownArgs);
2125 // now parse the args for specific parts of the target (e.g. LIBRARY,
2126 // RUNTIME, FRAMEWORK etc.
2127 libraryArgs.Parse(argVectors.Library, &unknownArgs);
2128 runtimeArgs.Parse(argVectors.Runtime, &unknownArgs);
2129 frameworkArgs.Parse(argVectors.Framework, &unknownArgs);
2131 libraryArgs.SetGenericArguments(&genericArgs);
2132 runtimeArgs.SetGenericArguments(&genericArgs);
2133 frameworkArgs.SetGenericArguments(&genericArgs);
2135 success = success && libraryArgs.Finalize();
2136 success = success && runtimeArgs.Finalize();
2137 success = success && frameworkArgs.Finalize();
2143 if (!unknownArgs.empty()) {
2145 cmStrCat("RUNTIME_DEPENDENCY_SET given unknown argument \"",
2146 unknownArgs.front(), "\"."));
2150 if (runtimeDependencySetArg.empty()) {
2152 "RUNTIME_DEPENDENCY_SET not given a runtime dependency set.");
2156 runtimeDependencySet =
2157 helper.Makefile->GetGlobalGenerator()->GetNamedRuntimeDependencySet(
2158 runtimeDependencySetArg);
2160 bool installsRuntime = false;
2161 bool installsLibrary = false;
2162 bool installsFramework = false;
2164 AddInstallRuntimeDependenciesGenerator(
2165 helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs,
2166 std::move(runtimeDependencyArgs), installsRuntime, installsLibrary,
2169 // Tell the global generator about any installation component names
2171 if (installsLibrary) {
2172 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
2173 libraryArgs.GetComponent());
2175 if (installsRuntime) {
2176 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
2177 runtimeArgs.GetComponent());
2179 if (installsFramework) {
2180 helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
2181 frameworkArgs.GetComponent());
2187 bool Helper::MakeFilesFullPath(const char* modeName,
2188 const std::vector<std::string>& relFiles,
2189 std::vector<std::string>& absFiles)
2191 return this->MakeFilesFullPath(
2192 modeName, this->Makefile->GetCurrentSourceDirectory(), relFiles, absFiles);
2195 bool Helper::MakeFilesFullPath(const char* modeName,
2196 const std::string& basePath,
2197 const std::vector<std::string>& relFiles,
2198 std::vector<std::string>& absFiles)
2200 for (std::string const& relFile : relFiles) {
2201 std::string file = relFile;
2202 std::string::size_type gpos = cmGeneratorExpression::Find(file);
2203 if (gpos != 0 && !cmSystemTools::FileIsFullPath(file)) {
2204 file = cmStrCat(basePath, '/', relFile);
2207 // Make sure the file is not a directory.
2208 if (gpos == std::string::npos && !cmSystemTools::FileIsSymlink(file) &&
2209 cmSystemTools::FileIsDirectory(file)) {
2211 cmStrCat(modeName, " given directory \"", relFile, "\" to install."));
2214 // Store the file for installation.
2215 absFiles.push_back(std::move(file));
2220 bool Helper::CheckCMP0006(bool& failure) const
2222 switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0006)) {
2223 case cmPolicies::WARN:
2224 this->Makefile->IssueMessage(
2225 MessageType::AUTHOR_WARNING,
2226 cmPolicies::GetPolicyWarning(cmPolicies::CMP0006));
2228 case cmPolicies::OLD:
2229 // OLD behavior is to allow compatibility
2231 case cmPolicies::NEW:
2232 // NEW behavior is to disallow compatibility
2234 case cmPolicies::REQUIRED_IF_USED:
2235 case cmPolicies::REQUIRED_ALWAYS:
2237 this->Makefile->IssueMessage(
2238 MessageType::FATAL_ERROR,
2239 cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0006));
2245 std::string Helper::GetDestination(const cmInstallCommandArguments* args,
2246 const std::string& varName,
2247 const std::string& guess) const
2249 if (args && !args->GetDestination().empty()) {
2250 return args->GetDestination();
2252 std::string val = this->Makefile->GetSafeDefinition(varName);
2259 std::string Helper::GetRuntimeDestination(
2260 const cmInstallCommandArguments* args) const
2262 return this->GetDestination(args, "CMAKE_INSTALL_BINDIR", "bin");
2265 std::string Helper::GetSbinDestination(
2266 const cmInstallCommandArguments* args) const
2268 return this->GetDestination(args, "CMAKE_INSTALL_SBINDIR", "sbin");
2271 std::string Helper::GetArchiveDestination(
2272 const cmInstallCommandArguments* args) const
2274 return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
2277 std::string Helper::GetLibraryDestination(
2278 const cmInstallCommandArguments* args) const
2280 return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
2283 std::string Helper::GetIncludeDestination(
2284 const cmInstallCommandArguments* args) const
2286 return this->GetDestination(args, "CMAKE_INSTALL_INCLUDEDIR", "include");
2289 std::string Helper::GetSysconfDestination(
2290 const cmInstallCommandArguments* args) const
2292 return this->GetDestination(args, "CMAKE_INSTALL_SYSCONFDIR", "etc");
2295 std::string Helper::GetSharedStateDestination(
2296 const cmInstallCommandArguments* args) const
2298 return this->GetDestination(args, "CMAKE_INSTALL_SHAREDSTATEDIR", "com");
2301 std::string Helper::GetLocalStateDestination(
2302 const cmInstallCommandArguments* args) const
2304 return this->GetDestination(args, "CMAKE_INSTALL_LOCALSTATEDIR", "var");
2307 std::string Helper::GetRunStateDestination(
2308 const cmInstallCommandArguments* args) const
2310 return this->GetDestination(args, "CMAKE_INSTALL_RUNSTATEDIR",
2311 this->GetLocalStateDestination(nullptr) +
2315 std::string Helper::GetDataRootDestination(
2316 const cmInstallCommandArguments* args) const
2318 return this->GetDestination(args, "CMAKE_INSTALL_DATAROOTDIR", "share");
2321 std::string Helper::GetDataDestination(
2322 const cmInstallCommandArguments* args) const
2324 return this->GetDestination(args, "CMAKE_INSTALL_DATADIR",
2325 this->GetDataRootDestination(nullptr));
2328 std::string Helper::GetInfoDestination(
2329 const cmInstallCommandArguments* args) const
2331 return this->GetDestination(args, "CMAKE_INSTALL_INFODIR",
2332 this->GetDataRootDestination(nullptr) + "/info");
2335 std::string Helper::GetLocaleDestination(
2336 const cmInstallCommandArguments* args) const
2338 return this->GetDestination(args, "CMAKE_INSTALL_LOCALEDIR",
2339 this->GetDataRootDestination(nullptr) +
2343 std::string Helper::GetManDestination(
2344 const cmInstallCommandArguments* args) const
2346 return this->GetDestination(args, "CMAKE_INSTALL_MANDIR",
2347 this->GetDataRootDestination(nullptr) + "/man");
2350 std::string Helper::GetDocDestination(
2351 const cmInstallCommandArguments* args) const
2353 return this->GetDestination(args, "CMAKE_INSTALL_DOCDIR",
2354 this->GetDataRootDestination(nullptr) + "/doc");
2357 std::string Helper::GetDestinationForType(
2358 const cmInstallCommandArguments* args, const std::string& type) const
2360 if (args && !args->GetDestination().empty()) {
2361 return args->GetDestination();
2363 if (type == "BIN") {
2364 return this->GetRuntimeDestination(nullptr);
2366 if (type == "SBIN") {
2367 return this->GetSbinDestination(nullptr);
2369 if (type == "SYSCONF") {
2370 return this->GetSysconfDestination(nullptr);
2372 if (type == "SHAREDSTATE") {
2373 return this->GetSharedStateDestination(nullptr);
2375 if (type == "LOCALSTATE") {
2376 return this->GetLocalStateDestination(nullptr);
2378 if (type == "RUNSTATE") {
2379 return this->GetRunStateDestination(nullptr);
2381 if (type == "LIB") {
2382 return this->GetLibraryDestination(nullptr);
2384 if (type == "INCLUDE") {
2385 return this->GetIncludeDestination(nullptr);
2387 if (type == "DATA") {
2388 return this->GetDataDestination(nullptr);
2390 if (type == "INFO") {
2391 return this->GetInfoDestination(nullptr);
2393 if (type == "LOCALE") {
2394 return this->GetLocaleDestination(nullptr);
2396 if (type == "MAN") {
2397 return this->GetManDestination(nullptr);
2399 if (type == "DOC") {
2400 return this->GetDocDestination(nullptr);
2407 bool cmInstallCommand(std::vector<std::string> const& args,
2408 cmExecutionStatus& status)
2410 // Allow calling with no arguments so that arguments may be built up
2411 // using a variable that may be left empty.
2416 // Enable the install target.
2417 status.GetMakefile().GetGlobalGenerator()->EnableInstallTarget();
2419 static cmSubcommandTable const subcommand{
2420 { "SCRIPT"_s, HandleScriptMode },
2421 { "CODE"_s, HandleScriptMode },
2422 { "TARGETS"_s, HandleTargetsMode },
2423 { "IMPORTED_RUNTIME_ARTIFACTS"_s, HandleImportedRuntimeArtifactsMode },
2424 { "FILES"_s, HandleFilesMode },
2425 { "PROGRAMS"_s, HandleFilesMode },
2426 { "DIRECTORY"_s, HandleDirectoryMode },
2427 { "EXPORT"_s, HandleExportMode },
2428 { "EXPORT_ANDROID_MK"_s, HandleExportAndroidMKMode },
2429 { "RUNTIME_DEPENDENCY_SET"_s, HandleRuntimeDependencySetMode },
2432 return subcommand(args[0], args, status);