| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 | 
							- /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
-    file Copyright.txt or https://cmake.org/licensing for details.  */
 
- #include "cmLinkLineDeviceComputer.h"
 
- #include <algorithm>
 
- #include <set>
 
- #include <utility>
 
- #include <cmext/algorithm>
 
- #include "cmComputeLinkInformation.h"
 
- #include "cmGeneratorTarget.h"
 
- #include "cmGlobalGenerator.h"
 
- #include "cmLinkItem.h"
 
- #include "cmListFileCache.h"
 
- #include "cmLocalGenerator.h"
 
- #include "cmMakefile.h"
 
- #include "cmStateDirectory.h"
 
- #include "cmStateSnapshot.h"
 
- #include "cmStateTypes.h"
 
- #include "cmStringAlgorithms.h"
 
- #include "cmValue.h"
 
- class cmOutputConverter;
 
- cmLinkLineDeviceComputer::cmLinkLineDeviceComputer(
 
-   cmOutputConverter* outputConverter, cmStateDirectory const& stateDir)
 
-   : cmLinkLineComputer(outputConverter, stateDir)
 
- {
 
- }
 
- cmLinkLineDeviceComputer::~cmLinkLineDeviceComputer() = default;
 
- static bool cmLinkItemValidForDevice(std::string const& item)
 
- {
 
-   // Valid items are:
 
-   // * Non-flags (does not start in '-')
 
-   // * Specific flags --library, --library-path, -l, -L
 
-   // For example:
 
-   // * 'cublas_device' => pass-along
 
-   // * '--library pthread' => pass-along
 
-   // * '-lpthread' => pass-along
 
-   // * '-pthread' => drop
 
-   // * '-a' => drop
 
-   // * '-framework Name' (as one string) => drop
 
-   return (!cmHasLiteralPrefix(item, "-") || //
 
-           cmHasLiteralPrefix(item, "-l") || //
 
-           cmHasLiteralPrefix(item, "-L") || //
 
-           cmHasLiteralPrefix(item, "--library"));
 
- }
 
- bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinking(
 
-   cmComputeLinkInformation& cli)
 
- {
 
-   // Determine if this item might requires device linking.
 
-   // For this we only consider targets
 
-   using ItemVector = cmComputeLinkInformation::ItemVector;
 
-   ItemVector const& items = cli.GetItems();
 
-   return std::any_of(
 
-     items.begin(), items.end(),
 
-     [](cmComputeLinkInformation::Item const& item) -> bool {
 
-       return item.Target &&
 
-         item.Target->GetType() == cmStateEnums::STATIC_LIBRARY &&
 
-         // this dependency requires us to device link it
 
-         !item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS") &&
 
-         item.Target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION");
 
-     });
 
- }
 
- bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinkingIPOFlag(
 
-   cmComputeLinkInformation& cli)
 
- {
 
-   // Determine if this item might requires device linking.
 
-   // For this we only consider targets
 
-   using ItemVector = cmComputeLinkInformation::ItemVector;
 
-   ItemVector const& items = cli.GetItems();
 
-   std::string config = cli.GetConfig();
 
-   return std::any_of(
 
-     items.begin(), items.end(),
 
-     [config](cmComputeLinkInformation::Item const& item) -> bool {
 
-       return item.Target &&
 
-         item.Target->GetType() == cmStateEnums::STATIC_LIBRARY &&
 
-         // this dependency requires us to device link it
 
-         !item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS") &&
 
-         item.Target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION") &&
 
-         item.Target->IsIPOEnabled("CUDA", config);
 
-     });
 
- }
 
- void cmLinkLineDeviceComputer::ComputeLinkLibraries(
 
-   cmComputeLinkInformation& cli, std::string const& stdLibString,
 
-   std::vector<BT<std::string>>& linkLibraries)
 
- {
 
-   // Generate the unique set of link items when device linking.
 
-   // The nvcc device linker is designed so that each static library
 
-   // with device symbols only needs to be listed once as it doesn't
 
-   // care about link order.
 
-   std::set<std::string> emitted;
 
-   using ItemVector = cmComputeLinkInformation::ItemVector;
 
-   ItemVector const& items = cli.GetItems();
 
-   std::string config = cli.GetConfig();
 
-   bool skipItemAfterFramework = false;
 
-   // Note:
 
-   // Any modification of this algorithm should be reflected also in
 
-   // cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions
 
-   for (auto const& item : items) {
 
-     if (skipItemAfterFramework) {
 
-       skipItemAfterFramework = false;
 
-       continue;
 
-     }
 
-     if (item.Target) {
 
-       bool skip = false;
 
-       switch (item.Target->GetType()) {
 
-         case cmStateEnums::SHARED_LIBRARY:
 
-         case cmStateEnums::MODULE_LIBRARY:
 
-         case cmStateEnums::OBJECT_LIBRARY:
 
-         case cmStateEnums::INTERFACE_LIBRARY:
 
-           skip = true;
 
-           break;
 
-         case cmStateEnums::STATIC_LIBRARY:
 
-           skip = item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
 
-           break;
 
-         default:
 
-           break;
 
-       }
 
-       if (skip) {
 
-         continue;
 
-       }
 
-     }
 
-     BT<std::string> linkLib;
 
-     if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
 
-       // nvcc understands absolute paths to libraries ending in '.a' or '.lib'.
 
-       // These should be passed to nvlink.  Other extensions need to be left
 
-       // out because nvlink may not understand or need them.  Even though it
 
-       // can tolerate '.so' or '.dylib' it cannot tolerate '.so.1'.
 
-       if (cmHasLiteralSuffix(item.Value.Value, ".a") ||
 
-           cmHasLiteralSuffix(item.Value.Value, ".lib")) {
 
-         linkLib.Value = item
 
-                           .GetFormattedItem(this->ConvertToOutputFormat(
 
-                             this->ConvertToLinkReference(item.Value.Value)))
 
-                           .Value;
 
-       }
 
-     } else if (item.Value == "-framework") {
 
-       // This is the first part of '-framework Name' where the framework
 
-       // name is specified as a following item.  Ignore both.
 
-       skipItemAfterFramework = true;
 
-       continue;
 
-     } else if (cmLinkItemValidForDevice(item.Value.Value)) {
 
-       linkLib.Value = item.Value.Value;
 
-     }
 
-     if (emitted.insert(linkLib.Value).second) {
 
-       linkLib.Value += " ";
 
-       const cmLinkImplementation* linkImpl =
 
-         cli.GetTarget()->GetLinkImplementation(
 
-           cli.GetConfig(), cmGeneratorTarget::LinkInterfaceFor::Link);
 
-       for (const cmLinkImplItem& iter : linkImpl->Libraries) {
 
-         if (iter.Target != nullptr &&
 
-             iter.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
 
-           std::string libPath = iter.Target->GetLocation(cli.GetConfig());
 
-           if (item.Value == libPath) {
 
-             linkLib.Backtrace = iter.Backtrace;
 
-             break;
 
-           }
 
-         }
 
-       }
 
-       linkLibraries.emplace_back(linkLib);
 
-     }
 
-   }
 
-   if (!stdLibString.empty()) {
 
-     linkLibraries.emplace_back(cmStrCat(stdLibString, ' '));
 
-   }
 
- }
 
- std::string cmLinkLineDeviceComputer::GetLinkerLanguage(cmGeneratorTarget*,
 
-                                                         std::string const&)
 
- {
 
-   return "CUDA";
 
- }
 
- bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg,
 
-                           const std::string& config)
 
- {
 
-   if (!target.GetGlobalGenerator()->GetLanguageEnabled("CUDA")) {
 
-     return false;
 
-   }
 
-   if (target.GetType() == cmStateEnums::OBJECT_LIBRARY) {
 
-     return false;
 
-   }
 
-   if (!lg.GetMakefile()->IsOn("CMAKE_CUDA_COMPILER_HAS_DEVICE_LINK_PHASE")) {
 
-     return false;
 
-   }
 
-   if (cmValue resolveDeviceSymbols =
 
-         target.GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) {
 
-     // If CUDA_RESOLVE_DEVICE_SYMBOLS has been explicitly set we need
 
-     // to honor the value no matter what it is.
 
-     return cmIsOn(*resolveDeviceSymbols);
 
-   }
 
-   // Determine if we have any dependencies that require
 
-   // us to do a device link step
 
-   cmGeneratorTarget::LinkClosure const* closure =
 
-     target.GetLinkClosure(config);
 
-   if (cm::contains(closure->Languages, "CUDA")) {
 
-     if (cmIsOn(target.GetProperty("CUDA_SEPARABLE_COMPILATION"))) {
 
-       bool doDeviceLinking = false;
 
-       switch (target.GetType()) {
 
-         case cmStateEnums::SHARED_LIBRARY:
 
-         case cmStateEnums::MODULE_LIBRARY:
 
-         case cmStateEnums::EXECUTABLE:
 
-           doDeviceLinking = true;
 
-           break;
 
-         default:
 
-           break;
 
-       }
 
-       return doDeviceLinking;
 
-     }
 
-     cmComputeLinkInformation* pcli = target.GetLinkInformation(config);
 
-     if (pcli) {
 
-       cmLinkLineDeviceComputer deviceLinkComputer(
 
-         &lg, lg.GetStateSnapshot().GetDirectory());
 
-       return deviceLinkComputer.ComputeRequiresDeviceLinking(*pcli);
 
-     }
 
-     return true;
 
-   }
 
-   return false;
 
- }
 
 
  |