cmBinUtilsWindowsPELinker.cxx 3.3 KB

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