cmBinUtilsWindowsPELinker.cxx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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 "cmBinUtilsWindowsPELinker.h"
  4. #include "cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h"
  5. #include "cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h"
  6. #include "cmRuntimeDependencyArchive.h"
  7. #include "cmSystemTools.h"
  8. #include <sstream>
  9. #include <vector>
  10. #include "cm_memory.hxx"
  11. #ifdef _WIN32
  12. # include <windows.h>
  13. #endif
  14. cmBinUtilsWindowsPELinker::cmBinUtilsWindowsPELinker(
  15. cmRuntimeDependencyArchive* archive)
  16. : cmBinUtilsLinker(archive)
  17. {
  18. }
  19. bool cmBinUtilsWindowsPELinker::Prepare()
  20. {
  21. std::string tool = this->Archive->GetGetRuntimeDependenciesTool();
  22. if (tool.empty()) {
  23. std::vector<std::string> command;
  24. if (this->Archive->GetGetRuntimeDependenciesCommand("dumpbin", command)) {
  25. tool = "dumpbin";
  26. } else {
  27. tool = "objdump";
  28. }
  29. }
  30. if (tool == "dumpbin") {
  31. this->Tool =
  32. cm::make_unique<cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool>(
  33. this->Archive);
  34. } else if (tool == "objdump") {
  35. this->Tool =
  36. cm::make_unique<cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool>(
  37. this->Archive);
  38. } else {
  39. std::ostringstream e;
  40. e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool;
  41. this->SetError(e.str());
  42. return false;
  43. }
  44. return true;
  45. }
  46. bool cmBinUtilsWindowsPELinker::ScanDependencies(
  47. std::string const& file, cmStateEnums::TargetType /* unused */)
  48. {
  49. std::vector<std::string> needed;
  50. if (!this->Tool->GetFileInfo(file, needed)) {
  51. return false;
  52. }
  53. for (auto& n : needed) {
  54. n = cmSystemTools::LowerCase(n);
  55. }
  56. std::string origin = cmSystemTools::GetFilenamePath(file);
  57. for (auto const& lib : needed) {
  58. if (!this->Archive->IsPreExcluded(lib)) {
  59. std::string path;
  60. bool resolved = false;
  61. if (!this->ResolveDependency(lib, origin, path, resolved)) {
  62. return false;
  63. }
  64. if (resolved) {
  65. if (!this->Archive->IsPostExcluded(path)) {
  66. bool unique;
  67. this->Archive->AddResolvedPath(lib, path, unique);
  68. if (unique &&
  69. !this->ScanDependencies(path, cmStateEnums::SHARED_LIBRARY)) {
  70. return false;
  71. }
  72. }
  73. } else {
  74. this->Archive->AddUnresolvedPath(lib);
  75. }
  76. }
  77. }
  78. return true;
  79. }
  80. bool cmBinUtilsWindowsPELinker::ResolveDependency(std::string const& name,
  81. std::string const& origin,
  82. std::string& path,
  83. bool& resolved)
  84. {
  85. auto dirs = this->Archive->GetSearchDirectories();
  86. #ifdef _WIN32
  87. char buf[MAX_PATH];
  88. unsigned int len;
  89. if ((len = GetWindowsDirectoryA(buf, MAX_PATH)) > 0) {
  90. dirs.insert(dirs.begin(), std::string(buf, len));
  91. }
  92. if ((len = GetSystemDirectoryA(buf, MAX_PATH)) > 0) {
  93. dirs.insert(dirs.begin(), std::string(buf, len));
  94. }
  95. #endif
  96. dirs.insert(dirs.begin(), origin);
  97. for (auto const& searchPath : dirs) {
  98. path = searchPath + '/' + name;
  99. if (cmSystemTools::PathExists(path)) {
  100. resolved = true;
  101. return true;
  102. }
  103. }
  104. resolved = false;
  105. return true;
  106. }