diff options
Diffstat (limited to 'Source/cmInstallTargetGenerator.cxx')
-rw-r--r-- | Source/cmInstallTargetGenerator.cxx | 780 |
1 files changed, 780 insertions, 0 deletions
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx new file mode 100644 index 0000000..448d278 --- /dev/null +++ b/Source/cmInstallTargetGenerator.cxx @@ -0,0 +1,780 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmInstallTargetGenerator.h" + +#include "cmComputeLinkInformation.h" +#include "cmGeneratorExpression.h" +#include "cmGeneratorTarget.h" +#include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmake.h" + +#include <assert.h> + +cmInstallTargetGenerator::cmInstallTargetGenerator( + const std::string& targetName, const char* dest, bool implib, + const char* file_permissions, std::vector<std::string> const& configurations, + const char* component, MessageLevel message, bool exclude_from_all, + bool optional) + : cmInstallGenerator(dest, configurations, component, message, + exclude_from_all) + , TargetName(targetName) + , Target(CM_NULLPTR) + , FilePermissions(file_permissions) + , ImportLibrary(implib) + , Optional(optional) +{ + this->ActionsPerConfig = true; + this->NamelinkMode = NamelinkModeNone; +} + +cmInstallTargetGenerator::~cmInstallTargetGenerator() +{ +} + +void cmInstallTargetGenerator::GenerateScript(std::ostream& os) +{ + // Warn if installing an exclude-from-all target. + if (this->Target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { + std::ostringstream msg; + msg << "WARNING: Target \"" << this->Target->GetName() + << "\" has EXCLUDE_FROM_ALL set and will not be built by default " + << "but an install rule has been provided for it. CMake does " + << "not define behavior for this case."; + cmSystemTools::Message(msg.str().c_str(), "Warning"); + } + + // Perform the main install script generation. + this->cmInstallGenerator::GenerateScript(os); +} + +void cmInstallTargetGenerator::GenerateScriptForConfig( + std::ostream& os, const std::string& config, Indent const& indent) +{ + // Compute the build tree directory from which to copy the target. + std::string fromDirConfig; + if (this->Target->NeedRelinkBeforeInstall(config)) { + fromDirConfig = + this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory(); + fromDirConfig += cmake::GetCMakeFilesDirectory(); + fromDirConfig += "/CMakeRelink.dir/"; + } else { + fromDirConfig = this->Target->GetDirectory(config, this->ImportLibrary); + fromDirConfig += "/"; + } + std::string toDir = + this->ConvertToAbsoluteDestination(this->GetDestination(config)); + toDir += "/"; + + // Compute the list of files to install for this target. + std::vector<std::string> filesFrom; + std::vector<std::string> filesTo; + std::string literal_args; + cmState::TargetType targetType = this->Target->GetType(); + cmInstallType type = cmInstallType(); + switch (targetType) { + case cmState::EXECUTABLE: + type = cmInstallType_EXECUTABLE; + break; + case cmState::STATIC_LIBRARY: + type = cmInstallType_STATIC_LIBRARY; + break; + case cmState::SHARED_LIBRARY: + type = cmInstallType_SHARED_LIBRARY; + break; + case cmState::MODULE_LIBRARY: + type = cmInstallType_MODULE_LIBRARY; + break; + case cmState::INTERFACE_LIBRARY: + // Not reachable. We never create a cmInstallTargetGenerator for + // an INTERFACE_LIBRARY. + assert(0 && "INTERFACE_LIBRARY targets have no installable outputs."); + break; + case cmState::OBJECT_LIBRARY: + case cmState::UTILITY: + case cmState::GLOBAL_TARGET: + case cmState::UNKNOWN_LIBRARY: + this->Target->GetLocalGenerator()->IssueMessage( + cmake::INTERNAL_ERROR, + "cmInstallTargetGenerator created with non-installable target."); + return; + } + if (targetType == cmState::EXECUTABLE) { + // There is a bug in cmInstallCommand if this fails. + assert(this->NamelinkMode == NamelinkModeNone); + + std::string targetName; + std::string targetNameReal; + std::string targetNameImport; + std::string targetNamePDB; + this->Target->GetExecutableNames(targetName, targetNameReal, + targetNameImport, targetNamePDB, config); + if (this->ImportLibrary) { + std::string from1 = fromDirConfig + targetNameImport; + std::string to1 = toDir + targetNameImport; + filesFrom.push_back(from1); + filesTo.push_back(to1); + std::string targetNameImportLib; + if (this->Target->GetImplibGNUtoMS(targetNameImport, + targetNameImportLib)) { + filesFrom.push_back(fromDirConfig + targetNameImportLib); + filesTo.push_back(toDir + targetNameImportLib); + } + + // An import library looks like a static library. + type = cmInstallType_STATIC_LIBRARY; + } else { + std::string from1 = fromDirConfig + targetName; + std::string to1 = toDir + targetName; + + // Handle OSX Bundles. + if (this->Target->IsAppBundleOnApple()) { + cmMakefile const* mf = this->Target->Target->GetMakefile(); + + // Install the whole app bundle directory. + type = cmInstallType_DIRECTORY; + literal_args += " USE_SOURCE_PERMISSIONS"; + from1 += ".app"; + + // Tweaks apply to the binary inside the bundle. + to1 += ".app/"; + if (!mf->PlatformIsAppleIos()) { + to1 += "Contents/MacOS/"; + } + to1 += targetName; + } else { + // Tweaks apply to the real file, so list it first. + if (targetNameReal != targetName) { + std::string from2 = fromDirConfig + targetNameReal; + std::string to2 = toDir += targetNameReal; + filesFrom.push_back(from2); + filesTo.push_back(to2); + } + } + + filesFrom.push_back(from1); + filesTo.push_back(to1); + } + } else { + std::string targetName; + std::string targetNameSO; + std::string targetNameReal; + std::string targetNameImport; + std::string targetNamePDB; + this->Target->GetLibraryNames(targetName, targetNameSO, targetNameReal, + targetNameImport, targetNamePDB, config); + if (this->ImportLibrary) { + // There is a bug in cmInstallCommand if this fails. + assert(this->NamelinkMode == NamelinkModeNone); + + std::string from1 = fromDirConfig + targetNameImport; + std::string to1 = toDir + targetNameImport; + filesFrom.push_back(from1); + filesTo.push_back(to1); + std::string targetNameImportLib; + if (this->Target->GetImplibGNUtoMS(targetNameImport, + targetNameImportLib)) { + filesFrom.push_back(fromDirConfig + targetNameImportLib); + filesTo.push_back(toDir + targetNameImportLib); + } + + // An import library looks like a static library. + type = cmInstallType_STATIC_LIBRARY; + } else if (this->Target->IsFrameworkOnApple()) { + // There is a bug in cmInstallCommand if this fails. + assert(this->NamelinkMode == NamelinkModeNone); + + // Install the whole framework directory. + type = cmInstallType_DIRECTORY; + literal_args += " USE_SOURCE_PERMISSIONS"; + + std::string from1 = fromDirConfig + targetName; + from1 = cmSystemTools::GetFilenamePath(from1); + + // Tweaks apply to the binary inside the bundle. + std::string to1 = toDir + targetNameReal; + + filesFrom.push_back(from1); + filesTo.push_back(to1); + } else if (this->Target->IsCFBundleOnApple()) { + // Install the whole app bundle directory. + type = cmInstallType_DIRECTORY; + literal_args += " USE_SOURCE_PERMISSIONS"; + + std::string targetNameBase = targetName.substr(0, targetName.find('/')); + + std::string from1 = fromDirConfig + targetNameBase; + std::string to1 = toDir + targetName; + + filesFrom.push_back(from1); + filesTo.push_back(to1); + } else { + bool haveNamelink = false; + + // Library link name. + std::string fromName = fromDirConfig + targetName; + std::string toName = toDir + targetName; + + // Library interface name. + std::string fromSOName; + std::string toSOName; + if (targetNameSO != targetName) { + haveNamelink = true; + fromSOName = fromDirConfig + targetNameSO; + toSOName = toDir + targetNameSO; + } + + // Library implementation name. + std::string fromRealName; + std::string toRealName; + if (targetNameReal != targetName && targetNameReal != targetNameSO) { + haveNamelink = true; + fromRealName = fromDirConfig + targetNameReal; + toRealName = toDir + targetNameReal; + } + + // Add the names based on the current namelink mode. + if (haveNamelink) { + // With a namelink we need to check the mode. + if (this->NamelinkMode == NamelinkModeOnly) { + // Install the namelink only. + filesFrom.push_back(fromName); + filesTo.push_back(toName); + } else { + // Install the real file if it has its own name. + if (!fromRealName.empty()) { + filesFrom.push_back(fromRealName); + filesTo.push_back(toRealName); + } + + // Install the soname link if it has its own name. + if (!fromSOName.empty()) { + filesFrom.push_back(fromSOName); + filesTo.push_back(toSOName); + } + + // Install the namelink if it is not to be skipped. + if (this->NamelinkMode != NamelinkModeSkip) { + filesFrom.push_back(fromName); + filesTo.push_back(toName); + } + } + } else { + // Without a namelink there will be only one file. Install it + // if this is not a namelink-only rule. + if (this->NamelinkMode != NamelinkModeOnly) { + filesFrom.push_back(fromName); + filesTo.push_back(toName); + } + } + } + } + + // If this fails the above code is buggy. + assert(filesFrom.size() == filesTo.size()); + + // Skip this rule if no files are to be installed for the target. + if (filesFrom.empty()) { + return; + } + + // Add pre-installation tweaks. + this->AddTweak(os, indent, config, filesTo, + &cmInstallTargetGenerator::PreReplacementTweaks); + + // Write code to install the target file. + const char* no_dir_permissions = CM_NULLPTR; + const char* no_rename = CM_NULLPTR; + bool optional = this->Optional || this->ImportLibrary; + this->AddInstallRule(os, this->GetDestination(config), type, filesFrom, + optional, this->FilePermissions.c_str(), + no_dir_permissions, no_rename, literal_args.c_str(), + indent); + + // Add post-installation tweaks. + this->AddTweak(os, indent, config, filesTo, + &cmInstallTargetGenerator::PostReplacementTweaks); +} + +std::string cmInstallTargetGenerator::GetDestination( + std::string const& config) const +{ + cmGeneratorExpression ge; + return ge.Parse(this->Destination) + ->Evaluate(this->Target->GetLocalGenerator(), config); +} + +std::string cmInstallTargetGenerator::GetInstallFilename( + const std::string& config) const +{ + NameType nameType = this->ImportLibrary ? NameImplib : NameNormal; + return cmInstallTargetGenerator::GetInstallFilename(this->Target, config, + nameType); +} + +std::string cmInstallTargetGenerator::GetInstallFilename( + cmGeneratorTarget const* target, const std::string& config, + NameType nameType) +{ + std::string fname; + // Compute the name of the library. + if (target->GetType() == cmState::EXECUTABLE) { + std::string targetName; + std::string targetNameReal; + std::string targetNameImport; + std::string targetNamePDB; + target->GetExecutableNames(targetName, targetNameReal, targetNameImport, + targetNamePDB, config); + if (nameType == NameImplib) { + // Use the import library name. + if (!target->GetImplibGNUtoMS(targetNameImport, fname, + "${CMAKE_IMPORT_LIBRARY_SUFFIX}")) { + fname = targetNameImport; + } + } else if (nameType == NameReal) { + // Use the canonical name. + fname = targetNameReal; + } else { + // Use the canonical name. + fname = targetName; + } + } else { + std::string targetName; + std::string targetNameSO; + std::string targetNameReal; + std::string targetNameImport; + std::string targetNamePDB; + target->GetLibraryNames(targetName, targetNameSO, targetNameReal, + targetNameImport, targetNamePDB, config); + if (nameType == NameImplib) { + // Use the import library name. + if (!target->GetImplibGNUtoMS(targetNameImport, fname, + "${CMAKE_IMPORT_LIBRARY_SUFFIX}")) { + fname = targetNameImport; + } + } else if (nameType == NameSO) { + // Use the soname. + fname = targetNameSO; + } else if (nameType == NameReal) { + // Use the real name. + fname = targetNameReal; + } else { + // Use the canonical name. + fname = targetName; + } + } + + return fname; +} + +void cmInstallTargetGenerator::Compute(cmLocalGenerator* lg) +{ + this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName); +} + +void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent const& indent, + const std::string& config, + std::string const& file, + TweakMethod tweak) +{ + std::ostringstream tw; + (this->*tweak)(tw, indent.Next(), config, file); + std::string tws = tw.str(); + if (!tws.empty()) { + os << indent << "if(EXISTS \"" << file << "\" AND\n" + << indent << " NOT IS_SYMLINK \"" << file << "\")\n"; + os << tws; + os << indent << "endif()\n"; + } +} + +void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent const& indent, + const std::string& config, + std::vector<std::string> const& files, + TweakMethod tweak) +{ + if (files.size() == 1) { + // Tweak a single file. + this->AddTweak(os, indent, config, this->GetDestDirPath(files[0]), tweak); + } else { + // Generate a foreach loop to tweak multiple files. + std::ostringstream tw; + this->AddTweak(tw, indent.Next(), config, "${file}", tweak); + std::string tws = tw.str(); + if (!tws.empty()) { + Indent indent2 = indent.Next().Next(); + os << indent << "foreach(file\n"; + for (std::vector<std::string>::const_iterator i = files.begin(); + i != files.end(); ++i) { + os << indent2 << "\"" << this->GetDestDirPath(*i) << "\"\n"; + } + os << indent2 << ")\n"; + os << tws; + os << indent << "endforeach()\n"; + } + } +} + +std::string cmInstallTargetGenerator::GetDestDirPath(std::string const& file) +{ + // Construct the path of the file on disk after installation on + // which tweaks may be performed. + std::string toDestDirPath = "$ENV{DESTDIR}"; + if (file[0] != '/' && file[0] != '$') { + toDestDirPath += "/"; + } + toDestDirPath += file; + return toDestDirPath; +} + +void cmInstallTargetGenerator::PreReplacementTweaks(std::ostream& os, + Indent const& indent, + const std::string& config, + std::string const& file) +{ + this->AddRPathCheckRule(os, indent, config, file); +} + +void cmInstallTargetGenerator::PostReplacementTweaks(std::ostream& os, + Indent const& indent, + const std::string& config, + std::string const& file) +{ + this->AddInstallNamePatchRule(os, indent, config, file); + this->AddChrpathPatchRule(os, indent, config, file); + this->AddUniversalInstallRule(os, indent, file); + this->AddRanlibRule(os, indent, file); + this->AddStripRule(os, indent, file); +} + +void cmInstallTargetGenerator::AddInstallNamePatchRule( + std::ostream& os, Indent const& indent, const std::string& config, + std::string const& toDestDirPath) +{ + if (this->ImportLibrary || + !(this->Target->GetType() == cmState::SHARED_LIBRARY || + this->Target->GetType() == cmState::MODULE_LIBRARY || + this->Target->GetType() == cmState::EXECUTABLE)) { + return; + } + + // Fix the install_name settings in installed binaries. + std::string installNameTool = + this->Target->Target->GetMakefile()->GetSafeDefinition( + "CMAKE_INSTALL_NAME_TOOL"); + + if (installNameTool.empty()) { + return; + } + + // Build a map of build-tree install_name to install-tree install_name for + // shared libraries linked to this target. + std::map<std::string, std::string> install_name_remap; + if (cmComputeLinkInformation* cli = + this->Target->GetLinkInformation(config)) { + std::set<cmGeneratorTarget const*> const& sharedLibs = + cli->GetSharedLibrariesLinked(); + for (std::set<cmGeneratorTarget const*>::const_iterator j = + sharedLibs.begin(); + j != sharedLibs.end(); ++j) { + cmGeneratorTarget const* tgt = *j; + + // The install_name of an imported target does not change. + if (tgt->IsImported()) { + continue; + } + + // If the build tree and install tree use different path + // components of the install_name field then we need to create a + // mapping to be applied after installation. + std::string for_build = tgt->GetInstallNameDirForBuildTree(config); + std::string for_install = tgt->GetInstallNameDirForInstallTree(); + if (for_build != for_install) { + // The directory portions differ. Append the filename to + // create the mapping. + std::string fname = this->GetInstallFilename(tgt, config, NameSO); + + // Map from the build-tree install_name. + for_build += fname; + + // Map to the install-tree install_name. + for_install += fname; + + // Store the mapping entry. + install_name_remap[for_build] = for_install; + } + } + } + + // Edit the install_name of the target itself if necessary. + std::string new_id; + if (this->Target->GetType() == cmState::SHARED_LIBRARY) { + std::string for_build = + this->Target->GetInstallNameDirForBuildTree(config); + std::string for_install = this->Target->GetInstallNameDirForInstallTree(); + + if (this->Target->IsFrameworkOnApple() && for_install.empty()) { + // Frameworks seem to have an id corresponding to their own full + // path. + // ... + // for_install = fullDestPath_without_DESTDIR_or_name; + } + + // If the install name will change on installation set the new id + // on the installed file. + if (for_build != for_install) { + // Prepare to refer to the install-tree install_name. + new_id = for_install; + new_id += this->GetInstallFilename(this->Target, config, NameSO); + } + } + + // Write a rule to run install_name_tool to set the install-tree + // install_name value and references. + if (!new_id.empty() || !install_name_remap.empty()) { + os << indent << "execute_process(COMMAND \"" << installNameTool; + os << "\""; + if (!new_id.empty()) { + os << "\n" << indent << " -id \"" << new_id << "\""; + } + for (std::map<std::string, std::string>::const_iterator i = + install_name_remap.begin(); + i != install_name_remap.end(); ++i) { + os << "\n" + << indent << " -change \"" << i->first << "\" \"" << i->second + << "\""; + } + os << "\n" << indent << " \"" << toDestDirPath << "\")\n"; + } +} + +void cmInstallTargetGenerator::AddRPathCheckRule( + std::ostream& os, Indent const& indent, const std::string& config, + std::string const& toDestDirPath) +{ + // Skip the chrpath if the target does not need it. + if (this->ImportLibrary || !this->Target->IsChrpathUsed(config)) { + return; + } + // Skip if on Apple + if (this->Target->Target->GetMakefile()->IsOn( + "CMAKE_PLATFORM_HAS_INSTALLNAME")) { + return; + } + + // Get the link information for this target. + // It can provide the RPATH. + cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config); + if (!cli) { + return; + } + + // Get the install RPATH from the link information. + std::string newRpath = cli->GetChrpathString(); + + // Write a rule to remove the installed file if its rpath is not the + // new rpath. This is needed for existing build/install trees when + // the installed rpath changes but the file is not rebuilt. + /* clang-format off */ + os << indent << "file(RPATH_CHECK\n" + << indent << " FILE \"" << toDestDirPath << "\"\n" + << indent << " RPATH \"" << newRpath << "\")\n"; + /* clang-format on */ +} + +void cmInstallTargetGenerator::AddChrpathPatchRule( + std::ostream& os, Indent const& indent, const std::string& config, + std::string const& toDestDirPath) +{ + // Skip the chrpath if the target does not need it. + if (this->ImportLibrary || !this->Target->IsChrpathUsed(config)) { + return; + } + + // Get the link information for this target. + // It can provide the RPATH. + cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config); + if (!cli) { + return; + } + + cmMakefile* mf = this->Target->Target->GetMakefile(); + + if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { + // If using install_name_tool, set up the rules to modify the rpaths. + std::string installNameTool = + mf->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL"); + + std::vector<std::string> oldRuntimeDirs, newRuntimeDirs; + cli->GetRPath(oldRuntimeDirs, false); + cli->GetRPath(newRuntimeDirs, true); + + std::string darwin_major_version_s = + mf->GetSafeDefinition("DARWIN_MAJOR_VERSION"); + + std::istringstream ss(darwin_major_version_s); + int darwin_major_version; + ss >> darwin_major_version; + if (!ss.fail() && darwin_major_version <= 9 && + (!oldRuntimeDirs.empty() || !newRuntimeDirs.empty())) { + std::ostringstream msg; + msg + << "WARNING: Target \"" << this->Target->GetName() + << "\" has runtime paths which cannot be changed during install. " + << "To change runtime paths, OS X version 10.6 or newer is required. " + << "Therefore, runtime paths will not be changed when installing. " + << "CMAKE_BUILD_WITH_INSTALL_RPATH may be used to work around" + " this limitation."; + mf->IssueMessage(cmake::WARNING, msg.str()); + } else { + // Note: These paths are kept unique to avoid + // install_name_tool corruption. + std::set<std::string> runpaths; + for (std::vector<std::string>::const_iterator i = oldRuntimeDirs.begin(); + i != oldRuntimeDirs.end(); ++i) { + std::string runpath = + mf->GetGlobalGenerator()->ExpandCFGIntDir(*i, config); + + if (runpaths.find(runpath) == runpaths.end()) { + runpaths.insert(runpath); + os << indent << "execute_process(COMMAND " << installNameTool + << "\n"; + os << indent << " -delete_rpath \"" << runpath << "\"\n"; + os << indent << " \"" << toDestDirPath << "\")\n"; + } + } + + runpaths.clear(); + for (std::vector<std::string>::const_iterator i = newRuntimeDirs.begin(); + i != newRuntimeDirs.end(); ++i) { + std::string runpath = + mf->GetGlobalGenerator()->ExpandCFGIntDir(*i, config); + + if (runpaths.find(runpath) == runpaths.end()) { + os << indent << "execute_process(COMMAND " << installNameTool + << "\n"; + os << indent << " -add_rpath \"" << runpath << "\"\n"; + os << indent << " \"" << toDestDirPath << "\")\n"; + } + } + } + } else { + // Construct the original rpath string to be replaced. + std::string oldRpath = cli->GetRPathString(false); + + // Get the install RPATH from the link information. + std::string newRpath = cli->GetChrpathString(); + + // Skip the rule if the paths are identical + if (oldRpath == newRpath) { + return; + } + + // Write a rule to run chrpath to set the install-tree RPATH + os << indent << "file(RPATH_CHANGE\n" + << indent << " FILE \"" << toDestDirPath << "\"\n" + << indent << " OLD_RPATH \"" << oldRpath << "\"\n" + << indent << " NEW_RPATH \"" << newRpath << "\")\n"; + } +} + +void cmInstallTargetGenerator::AddStripRule(std::ostream& os, + Indent const& indent, + const std::string& toDestDirPath) +{ + + // don't strip static and import libraries, because it removes the only + // symbol table they have so you can't link to them anymore + if (this->Target->GetType() == cmState::STATIC_LIBRARY || + this->ImportLibrary) { + return; + } + + // Don't handle OSX Bundles. + if (this->Target->Target->GetMakefile()->IsOn("APPLE") && + this->Target->GetPropertyAsBool("MACOSX_BUNDLE")) { + return; + } + + if (!this->Target->Target->GetMakefile()->IsSet("CMAKE_STRIP")) { + return; + } + + os << indent << "if(CMAKE_INSTALL_DO_STRIP)\n"; + os << indent << " execute_process(COMMAND \"" + << this->Target->Target->GetMakefile()->GetDefinition("CMAKE_STRIP") + << "\" \"" << toDestDirPath << "\")\n"; + os << indent << "endif()\n"; +} + +void cmInstallTargetGenerator::AddRanlibRule(std::ostream& os, + Indent const& indent, + const std::string& toDestDirPath) +{ + // Static libraries need ranlib on this platform. + if (this->Target->GetType() != cmState::STATIC_LIBRARY) { + return; + } + + // Perform post-installation processing on the file depending + // on its type. + if (!this->Target->Target->GetMakefile()->IsOn("APPLE")) { + return; + } + + std::string ranlib = + this->Target->Target->GetMakefile()->GetRequiredDefinition("CMAKE_RANLIB"); + if (ranlib.empty()) { + return; + } + + os << indent << "execute_process(COMMAND \"" << ranlib << "\" \"" + << toDestDirPath << "\")\n"; +} + +void cmInstallTargetGenerator::AddUniversalInstallRule( + std::ostream& os, Indent const& indent, const std::string& toDestDirPath) +{ + cmMakefile const* mf = this->Target->Target->GetMakefile(); + + if (!mf->PlatformIsAppleIos() || !mf->IsOn("XCODE")) { + return; + } + + const char* xcodeVersion = mf->GetDefinition("XCODE_VERSION"); + if (!xcodeVersion || + cmSystemTools::VersionCompareGreater("6", xcodeVersion)) { + return; + } + + switch (this->Target->GetType()) { + case cmState::EXECUTABLE: + case cmState::STATIC_LIBRARY: + case cmState::SHARED_LIBRARY: + case cmState::MODULE_LIBRARY: + break; + + default: + return; + } + + if (!this->Target->Target->GetPropertyAsBool("IOS_INSTALL_COMBINED")) { + return; + } + + os << indent << "include(CMakeIOSInstallCombined)\n"; + os << indent << "ios_install_combined(" + << "\"" << this->Target->Target->GetName() << "\" " + << "\"" << toDestDirPath << "\")\n"; +} |