Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmInstallTargetGenerator.cxx
blobdd6d6517c30bf260ea2330a02d41ead207d08aba
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmInstallTargetGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2009-03-16 14:39:49 $
7 Version: $Revision: 1.68 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmInstallTargetGenerator.h"
19 #include "cmComputeLinkInformation.h"
20 #include "cmGlobalGenerator.h"
21 #include "cmLocalGenerator.h"
22 #include "cmMakefile.h"
23 #include "cmake.h"
25 #include <assert.h>
27 //----------------------------------------------------------------------------
28 cmInstallTargetGenerator
29 ::cmInstallTargetGenerator(cmTarget& t, const char* dest, bool implib,
30 const char* file_permissions,
31 std::vector<std::string> const& configurations,
32 const char* component, bool optional):
33 cmInstallGenerator(dest, configurations, component), Target(&t),
34 ImportLibrary(implib), FilePermissions(file_permissions), Optional(optional)
36 this->ActionsPerConfig = true;
37 this->NamelinkMode = NamelinkModeNone;
38 this->Target->SetHaveInstallRule(true);
41 //----------------------------------------------------------------------------
42 cmInstallTargetGenerator
43 ::~cmInstallTargetGenerator()
47 //----------------------------------------------------------------------------
48 void cmInstallTargetGenerator::GenerateScript(std::ostream& os)
50 // Warn if installing an exclude-from-all target.
51 if(this->Target->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
53 cmOStringStream msg;
54 msg << "WARNING: Target \"" << this->Target->GetName()
55 << "\" has EXCLUDE_FROM_ALL set and will not be built by default "
56 << "but an install rule has been provided for it. CMake does "
57 << "not define behavior for this case.";
58 cmSystemTools::Message(msg.str().c_str(), "Warning");
61 // Compute the build tree directory from which to copy the target.
62 std::string& fromDir = this->FromDir;
63 if(this->Target->NeedRelinkBeforeInstall())
65 fromDir = this->Target->GetMakefile()->GetStartOutputDirectory();
66 fromDir += cmake::GetCMakeFilesDirectory();
67 fromDir += "/CMakeRelink.dir/";
69 else
71 fromDir = this->Target->GetDirectory(0, this->ImportLibrary);
72 fromDir += "/";
75 // Perform the main install script generation.
76 this->cmInstallGenerator::GenerateScript(os);
79 //----------------------------------------------------------------------------
80 void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
81 const char* config,
82 Indent const& indent)
84 // Compute the per-configuration directory containing the files.
85 std::string fromDirConfig = this->FromDir;
86 this->Target->GetMakefile()->GetLocalGenerator()->GetGlobalGenerator()
87 ->AppendDirectoryForConfig("", config, "/", fromDirConfig);
89 // Compute the full path to the main installed file for this target.
90 NameType nameType = this->ImportLibrary? NameImplib : NameNormal;
91 std::string toInstallPath = this->GetInstallDestination();
92 toInstallPath += "/";
93 toInstallPath += this->GetInstallFilename(this->Target, config, nameType);
95 // Track whether post-install operations should be added to the
96 // script.
97 bool tweakInstalledFile = true;
99 // Compute the list of files to install for this target.
100 std::vector<std::string> files;
101 std::string literal_args;
102 cmTarget::TargetType type = this->Target->GetType();
103 if(type == cmTarget::EXECUTABLE)
105 // There is a bug in cmInstallCommand if this fails.
106 assert(this->NamelinkMode == NamelinkModeNone);
108 std::string targetName;
109 std::string targetNameReal;
110 std::string targetNameImport;
111 std::string targetNamePDB;
112 this->Target->GetExecutableNames(targetName, targetNameReal,
113 targetNameImport, targetNamePDB,
114 config);
115 if(this->ImportLibrary)
117 std::string from1 = fromDirConfig;
118 from1 += targetNameImport;
119 files.push_back(from1);
121 // An import library looks like a static library.
122 type = cmTarget::STATIC_LIBRARY;
124 else
126 std::string from1 = fromDirConfig;
127 from1 += targetName;
129 // Handle OSX Bundles.
130 if(this->Target->IsAppBundleOnApple())
132 // Compute the source locations of the bundle executable and
133 // Info.plist file.
134 from1 += ".app";
135 files.push_back(from1);
136 type = cmTarget::INSTALL_DIRECTORY;
137 // Need to apply install_name_tool and stripping to binary
138 // inside bundle.
139 toInstallPath += ".app/Contents/MacOS/";
140 toInstallPath +=
141 this->GetInstallFilename(this->Target, config, nameType);
142 literal_args += " USE_SOURCE_PERMISSIONS";
144 else
146 // Operations done at install time on the installed file should
147 // be done on the real file and not any of the symlinks.
148 toInstallPath = this->GetInstallDestination();
149 toInstallPath += "/";
150 toInstallPath += targetNameReal;
152 files.push_back(from1);
153 if(targetNameReal != targetName)
155 std::string from2 = fromDirConfig;
156 from2 += targetNameReal;
157 files.push_back(from2);
162 else
164 std::string targetName;
165 std::string targetNameSO;
166 std::string targetNameReal;
167 std::string targetNameImport;
168 std::string targetNamePDB;
169 this->Target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
170 targetNameImport, targetNamePDB,
171 config);
172 if(this->ImportLibrary)
174 // There is a bug in cmInstallCommand if this fails.
175 assert(this->NamelinkMode == NamelinkModeNone);
177 std::string from1 = fromDirConfig;
178 from1 += targetNameImport;
179 files.push_back(from1);
181 // An import library looks like a static library.
182 type = cmTarget::STATIC_LIBRARY;
184 else if(this->Target->IsFrameworkOnApple())
186 // There is a bug in cmInstallCommand if this fails.
187 assert(this->NamelinkMode == NamelinkModeNone);
189 // Compute the build tree location of the framework directory
190 std::string from1 = fromDirConfig;
191 from1 += targetName;
192 from1 += ".framework";
193 files.push_back(from1);
195 type = cmTarget::INSTALL_DIRECTORY;
197 // Need to apply install_name_tool and stripping to binary
198 // inside framework.
199 toInstallPath += ".framework/Versions/";
200 toInstallPath += this->Target->GetFrameworkVersion();
201 toInstallPath += "/";
202 toInstallPath += this->GetInstallFilename(this->Target, config,
203 NameNormal);
205 literal_args += " USE_SOURCE_PERMISSIONS";
207 else
209 // Operations done at install time on the installed file should
210 // be done on the real file and not any of the symlinks.
211 toInstallPath = this->GetInstallDestination();
212 toInstallPath += "/";
213 toInstallPath += targetNameReal;
215 // Construct the list of file names to install for this library.
216 bool haveNamelink = false;
217 std::string fromName;
218 std::string fromSOName;
219 std::string fromRealName;
220 fromName = fromDirConfig;
221 fromName += targetName;
222 if(targetNameSO != targetName)
224 haveNamelink = true;
225 fromSOName = fromDirConfig;
226 fromSOName += targetNameSO;
228 if(targetNameReal != targetName &&
229 targetNameReal != targetNameSO)
231 haveNamelink = true;
232 fromRealName = fromDirConfig;
233 fromRealName += targetNameReal;
236 // Add the names based on the current namelink mode.
237 if(haveNamelink)
239 // With a namelink we need to check the mode.
240 if(this->NamelinkMode == NamelinkModeOnly)
242 // Install the namelink only.
243 files.push_back(fromName);
244 tweakInstalledFile = false;
246 else
248 // Install the real file if it has its own name.
249 if(!fromRealName.empty())
251 files.push_back(fromRealName);
254 // Install the soname link if it has its own name.
255 if(!fromSOName.empty())
257 files.push_back(fromSOName);
260 // Install the namelink if it is not to be skipped.
261 if(this->NamelinkMode != NamelinkModeSkip)
263 files.push_back(fromName);
267 else
269 // Without a namelink there will be only one file. Install it
270 // if this is not a namelink-only rule.
271 if(this->NamelinkMode != NamelinkModeOnly)
273 files.push_back(fromName);
279 // Skip this rule if no files are to be installed for the target.
280 if(files.empty())
282 return;
285 // Construct the path of the file on disk after installation on
286 // which tweaks may be performed.
287 std::string toDestDirPath = "$ENV{DESTDIR}";
288 if(toInstallPath[0] != '/' && toInstallPath[0] != '$')
290 toDestDirPath += "/";
292 toDestDirPath += toInstallPath;
294 // Add pre-installation tweaks.
295 if(tweakInstalledFile)
297 // Collect tweaking rules.
298 cmOStringStream tw;
299 this->AddRPathCheckRule(tw, indent.Next(), config, toDestDirPath);
300 std::string tws = tw.str();
302 // Add the rules, if any.
303 if(!tws.empty())
305 os << indent << "IF(EXISTS \"" << toDestDirPath << "\")\n";
306 os << tws;
307 os << indent << "ENDIF(EXISTS \"" << toDestDirPath << "\")\n";
311 // Write code to install the target file.
312 const char* no_dir_permissions = 0;
313 const char* no_rename = 0;
314 const char* no_properties = 0;
315 bool optional = this->Optional || this->ImportLibrary;
316 this->AddInstallRule(os, type, files,
317 optional, no_properties,
318 this->FilePermissions.c_str(), no_dir_permissions,
319 no_rename, literal_args.c_str(),
320 indent);
322 // Add post-installation tweaks.
323 if(tweakInstalledFile)
325 // Collect tweaking rules.
326 cmOStringStream tw;
327 this->AddInstallNamePatchRule(tw, indent.Next(), config, toDestDirPath);
328 this->AddChrpathPatchRule(tw, indent.Next(), config, toDestDirPath);
329 this->AddRanlibRule(tw, indent.Next(), type, toDestDirPath);
330 this->AddStripRule(tw, indent.Next(), type, toDestDirPath);
331 std::string tws = tw.str();
333 // Add the rules, if any.
334 if(!tws.empty())
336 os << indent << "IF(EXISTS \"" << toDestDirPath << "\")\n";
337 os << tws;
338 os << indent << "ENDIF(EXISTS \"" << toDestDirPath << "\")\n";
343 //----------------------------------------------------------------------------
344 std::string
345 cmInstallTargetGenerator::GetInstallFilename(const char* config) const
347 NameType nameType = this->ImportLibrary? NameImplib : NameNormal;
348 return
349 cmInstallTargetGenerator::GetInstallFilename(this->Target, config,
350 nameType);
353 //----------------------------------------------------------------------------
354 std::string cmInstallTargetGenerator::GetInstallFilename(cmTarget* target,
355 const char* config,
356 NameType nameType)
358 std::string fname;
359 // Compute the name of the library.
360 if(target->GetType() == cmTarget::EXECUTABLE)
362 std::string targetName;
363 std::string targetNameReal;
364 std::string targetNameImport;
365 std::string targetNamePDB;
366 target->GetExecutableNames(targetName, targetNameReal,
367 targetNameImport, targetNamePDB,
368 config);
369 if(nameType == NameImplib)
371 // Use the import library name.
372 fname = targetNameImport;
374 else if(nameType == NameReal)
376 // Use the canonical name.
377 fname = targetNameReal;
379 else
381 // Use the canonical name.
382 fname = targetName;
385 else
387 std::string targetName;
388 std::string targetNameSO;
389 std::string targetNameReal;
390 std::string targetNameImport;
391 std::string targetNamePDB;
392 target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
393 targetNameImport, targetNamePDB, config);
394 if(nameType == NameImplib)
396 // Use the import library name.
397 fname = targetNameImport;
399 else if(nameType == NameSO)
401 // Use the soname.
402 fname = targetNameSO;
404 else if(nameType == NameReal)
406 // Use the real name.
407 fname = targetNameReal;
409 else
411 // Use the canonical name.
412 fname = targetName;
416 return fname;
419 //----------------------------------------------------------------------------
420 void
421 cmInstallTargetGenerator
422 ::AddInstallNamePatchRule(std::ostream& os, Indent const& indent,
423 const char* config, std::string const& toDestDirPath)
425 if(this->ImportLibrary ||
426 !(this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
427 this->Target->GetType() == cmTarget::MODULE_LIBRARY ||
428 this->Target->GetType() == cmTarget::EXECUTABLE))
430 return;
433 // Fix the install_name settings in installed binaries.
434 std::string installNameTool =
435 this->Target->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL");
437 if(!installNameTool.size())
439 return;
442 // Build a map of build-tree install_name to install-tree install_name for
443 // shared libraries linked to this target.
444 std::map<cmStdString, cmStdString> install_name_remap;
445 if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config))
447 std::set<cmTarget*> const& sharedLibs = cli->GetSharedLibrariesLinked();
448 for(std::set<cmTarget*>::const_iterator j = sharedLibs.begin();
449 j != sharedLibs.end(); ++j)
451 cmTarget* tgt = *j;
453 // The install_name of an imported target does not change.
454 if(tgt->IsImported())
456 continue;
459 // If the build tree and install tree use different path
460 // components of the install_name field then we need to create a
461 // mapping to be applied after installation.
462 std::string for_build = tgt->GetInstallNameDirForBuildTree(config);
463 std::string for_install = tgt->GetInstallNameDirForInstallTree(config);
464 if(for_build != for_install)
466 // The directory portions differ. Append the filename to
467 // create the mapping.
468 std::string fname =
469 this->GetInstallFilename(tgt, config, NameSO);
471 // Map from the build-tree install_name.
472 for_build += fname;
474 // Map to the install-tree install_name.
475 for_install += fname;
477 // Store the mapping entry.
478 install_name_remap[for_build] = for_install;
483 // Edit the install_name of the target itself if necessary.
484 std::string new_id;
485 if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
487 std::string for_build =
488 this->Target->GetInstallNameDirForBuildTree(config);
489 std::string for_install =
490 this->Target->GetInstallNameDirForInstallTree(config);
492 if(this->Target->IsFrameworkOnApple() && for_install.empty())
494 // Frameworks seem to have an id corresponding to their own full
495 // path.
496 // ...
497 // for_install = fullDestPath_without_DESTDIR_or_name;
500 // If the install name will change on installation set the new id
501 // on the installed file.
502 if(for_build != for_install)
504 // Prepare to refer to the install-tree install_name.
505 new_id = for_install;
506 new_id += this->GetInstallFilename(this->Target, config, NameSO);
510 // Write a rule to run install_name_tool to set the install-tree
511 // install_name value and references.
512 if(!new_id.empty() || !install_name_remap.empty())
514 os << indent << "EXECUTE_PROCESS(COMMAND \"" << installNameTool;
515 os << "\"";
516 if(!new_id.empty())
518 os << "\n" << indent << " -id \"" << new_id << "\"";
520 for(std::map<cmStdString, cmStdString>::const_iterator
521 i = install_name_remap.begin();
522 i != install_name_remap.end(); ++i)
524 os << "\n" << indent << " -change \""
525 << i->first << "\" \"" << i->second << "\"";
527 os << "\n" << indent << " \"" << toDestDirPath << "\")\n";
531 //----------------------------------------------------------------------------
532 void
533 cmInstallTargetGenerator
534 ::AddRPathCheckRule(std::ostream& os, Indent const& indent,
535 const char* config, std::string const& toDestDirPath)
537 // Skip the chrpath if the target does not need it.
538 if(this->ImportLibrary || !this->Target->IsChrpathUsed())
540 return;
543 // Get the link information for this target.
544 // It can provide the RPATH.
545 cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config);
546 if(!cli)
548 return;
551 // Get the install RPATH from the link information.
552 std::string newRpath = cli->GetChrpathString();
554 // Write a rule to remove the installed file if its rpath is not the
555 // new rpath. This is needed for existing build/install trees when
556 // the installed rpath changes but the file is not rebuilt.
557 os << indent << "FILE(RPATH_CHECK\n"
558 << indent << " FILE \"" << toDestDirPath << "\"\n"
559 << indent << " RPATH \"" << newRpath << "\")\n";
562 //----------------------------------------------------------------------------
563 void
564 cmInstallTargetGenerator
565 ::AddChrpathPatchRule(std::ostream& os, Indent const& indent,
566 const char* config, std::string const& toDestDirPath)
568 // Skip the chrpath if the target does not need it.
569 if(this->ImportLibrary || !this->Target->IsChrpathUsed())
571 return;
574 // Get the link information for this target.
575 // It can provide the RPATH.
576 cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config);
577 if(!cli)
579 return;
582 // Construct the original rpath string to be replaced.
583 std::string oldRpath = cli->GetRPathString(false);
585 // Get the install RPATH from the link information.
586 std::string newRpath = cli->GetChrpathString();
588 // Skip the rule if the paths are identical
589 if(oldRpath == newRpath)
591 return;
594 // Write a rule to run chrpath to set the install-tree RPATH
595 if(newRpath.empty())
597 os << indent << "FILE(RPATH_REMOVE\n"
598 << indent << " FILE \"" << toDestDirPath << "\")\n";
600 else
602 os << indent << "FILE(RPATH_CHANGE\n"
603 << indent << " FILE \"" << toDestDirPath << "\"\n"
604 << indent << " OLD_RPATH \"" << oldRpath << "\"\n"
605 << indent << " NEW_RPATH \"" << newRpath << "\")\n";
609 //----------------------------------------------------------------------------
610 void
611 cmInstallTargetGenerator::AddStripRule(std::ostream& os,
612 Indent const& indent,
613 cmTarget::TargetType type,
614 const std::string& toDestDirPath)
617 // don't strip static libraries, because it removes the only symbol table
618 // they have so you can't link to them anymore
619 if(type == cmTarget::STATIC_LIBRARY)
621 return;
624 // Don't handle OSX Bundles.
625 if(this->Target->GetMakefile()->IsOn("APPLE") &&
626 this->Target->GetPropertyAsBool("MACOSX_BUNDLE"))
628 return;
631 if(! this->Target->GetMakefile()->IsSet("CMAKE_STRIP"))
633 return;
636 os << indent << "IF(CMAKE_INSTALL_DO_STRIP)\n";
637 os << indent << " EXECUTE_PROCESS(COMMAND \""
638 << this->Target->GetMakefile()->GetDefinition("CMAKE_STRIP")
639 << "\" \"" << toDestDirPath << "\")\n";
640 os << indent << "ENDIF(CMAKE_INSTALL_DO_STRIP)\n";
643 //----------------------------------------------------------------------------
644 void
645 cmInstallTargetGenerator::AddRanlibRule(std::ostream& os,
646 Indent const& indent,
647 cmTarget::TargetType type,
648 const std::string& toDestDirPath)
650 // Static libraries need ranlib on this platform.
651 if(type != cmTarget::STATIC_LIBRARY)
653 return;
656 // Perform post-installation processing on the file depending
657 // on its type.
658 if(!this->Target->GetMakefile()->IsOn("APPLE"))
660 return;
663 std::string ranlib =
664 this->Target->GetMakefile()->GetRequiredDefinition("CMAKE_RANLIB");
665 if(ranlib.empty())
667 return;
670 os << indent << "EXECUTE_PROCESS(COMMAND \""
671 << ranlib << "\" \"" << toDestDirPath << "\")\n";