cmLinkLineDeviceComputer.cxx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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 "cmLinkLineDeviceComputer.h"
  4. #include <set>
  5. #include <sstream>
  6. #include <utility>
  7. #include "cmAlgorithms.h"
  8. #include "cmComputeLinkInformation.h"
  9. #include "cmGeneratorTarget.h"
  10. #include "cmGlobalNinjaGenerator.h"
  11. #include "cmStateTypes.h"
  12. class cmOutputConverter;
  13. cmLinkLineDeviceComputer::cmLinkLineDeviceComputer(
  14. cmOutputConverter* outputConverter, cmStateDirectory const& stateDir)
  15. : cmLinkLineComputer(outputConverter, stateDir)
  16. {
  17. }
  18. cmLinkLineDeviceComputer::~cmLinkLineDeviceComputer() = default;
  19. static bool cmLinkItemValidForDevice(std::string const& item)
  20. {
  21. // Valid items are:
  22. // * Non-flags (does not start in '-')
  23. // * Specific flags --library, --library-path, -l, -L
  24. // For example:
  25. // * 'cublas_device' => pass-along
  26. // * '--library pthread' => pass-along
  27. // * '-lpthread' => pass-along
  28. // * '-pthread' => drop
  29. // * '-a' => drop
  30. // * '-framework Name' (as one string) => drop
  31. return (!cmHasLiteralPrefix(item, "-") || //
  32. cmHasLiteralPrefix(item, "-l") || //
  33. cmHasLiteralPrefix(item, "-L") || //
  34. cmHasLiteralPrefix(item, "--library"));
  35. }
  36. std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
  37. cmComputeLinkInformation& cli, std::string const& stdLibString)
  38. {
  39. // Write the library flags to the build rule.
  40. std::ostringstream fout;
  41. // Generate the unique set of link items when device linking.
  42. // The nvcc device linker is designed so that each static library
  43. // with device symbols only needs to be listed once as it doesn't
  44. // care about link order.
  45. std::set<std::string> emitted;
  46. typedef cmComputeLinkInformation::ItemVector ItemVector;
  47. ItemVector const& items = cli.GetItems();
  48. std::string config = cli.GetConfig();
  49. bool skipItemAfterFramework = false;
  50. for (auto const& item : items) {
  51. if (skipItemAfterFramework) {
  52. skipItemAfterFramework = false;
  53. continue;
  54. }
  55. if (item.Target) {
  56. bool skip = false;
  57. switch (item.Target->GetType()) {
  58. case cmStateEnums::MODULE_LIBRARY:
  59. case cmStateEnums::INTERFACE_LIBRARY:
  60. skip = true;
  61. break;
  62. case cmStateEnums::STATIC_LIBRARY:
  63. skip = item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
  64. break;
  65. default:
  66. break;
  67. }
  68. if (skip) {
  69. continue;
  70. }
  71. }
  72. std::string out;
  73. if (item.IsPath) {
  74. // nvcc understands absolute paths to libraries ending in '.a' or '.lib'.
  75. // These should be passed to nvlink. Other extensions need to be left
  76. // out because nvlink may not understand or need them. Even though it
  77. // can tolerate '.so' or '.dylib' it cannot tolerate '.so.1'.
  78. if (cmHasLiteralSuffix(item.Value, ".a") ||
  79. cmHasLiteralSuffix(item.Value, ".lib")) {
  80. out += this->ConvertToOutputFormat(
  81. this->ConvertToLinkReference(item.Value));
  82. }
  83. } else if (item.Value == "-framework") {
  84. // This is the first part of '-framework Name' where the framework
  85. // name is specified as a following item. Ignore both.
  86. skipItemAfterFramework = true;
  87. continue;
  88. } else if (cmLinkItemValidForDevice(item.Value)) {
  89. out += item.Value;
  90. }
  91. if (emitted.insert(out).second) {
  92. fout << out << " ";
  93. }
  94. }
  95. if (!stdLibString.empty()) {
  96. fout << stdLibString << " ";
  97. }
  98. return fout.str();
  99. }
  100. std::string cmLinkLineDeviceComputer::GetLinkerLanguage(cmGeneratorTarget*,
  101. std::string const&)
  102. {
  103. return "CUDA";
  104. }
  105. cmNinjaLinkLineDeviceComputer::cmNinjaLinkLineDeviceComputer(
  106. cmOutputConverter* outputConverter, cmStateDirectory const& stateDir,
  107. cmGlobalNinjaGenerator const* gg)
  108. : cmLinkLineDeviceComputer(outputConverter, stateDir)
  109. , GG(gg)
  110. {
  111. }
  112. std::string cmNinjaLinkLineDeviceComputer::ConvertToLinkReference(
  113. std::string const& lib) const
  114. {
  115. return GG->ConvertToNinjaPath(lib);
  116. }