cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file LICENSE.rst or https://cmake.org/licensing for details. */
  3. #include "cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h"
  4. #include <sstream>
  5. #include <vector>
  6. #include <cmsys/RegularExpression.hxx>
  7. #include "cmRuntimeDependencyArchive.h"
  8. #include "cmUVProcessChain.h"
  9. #include "cmUVStream.h"
  10. cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::
  11. cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool(
  12. cmRuntimeDependencyArchive* archive)
  13. : cmBinUtilsMacOSMachOGetRuntimeDependenciesTool(archive)
  14. {
  15. }
  16. bool cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::GetFileInfo(
  17. std::string const& file, std::vector<std::string>& libs,
  18. std::vector<std::string>& rpaths)
  19. {
  20. std::vector<std::string> command;
  21. if (!this->Archive->GetGetRuntimeDependenciesCommand("otool", command)) {
  22. this->SetError("Could not find otool");
  23. return false;
  24. }
  25. command.emplace_back("-l");
  26. command.emplace_back(file);
  27. cmUVProcessChainBuilder builder;
  28. builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
  29. .AddCommand(command);
  30. auto process = builder.Start();
  31. if (!process.Valid() || process.GetStatus(0).SpawnResult != 0) {
  32. std::ostringstream e;
  33. e << "Failed to start otool process for:\n " << file;
  34. this->SetError(e.str());
  35. return false;
  36. }
  37. std::string line;
  38. static cmsys::RegularExpression const rpathRegex("^ *cmd LC_RPATH$");
  39. static cmsys::RegularExpression const loadDylibRegex(
  40. "^ *cmd LC_LOAD(_WEAK)?_DYLIB$");
  41. static cmsys::RegularExpression const pathRegex(
  42. "^ *path (.*) \\(offset [0-9]+\\)$");
  43. static cmsys::RegularExpression const nameRegex(
  44. "^ *name (.*) \\(offset [0-9]+\\)$");
  45. cmUVPipeIStream output(process.GetLoop(), process.OutputStream());
  46. while (std::getline(output, line)) {
  47. cmsys::RegularExpressionMatch cmdMatch;
  48. if (rpathRegex.find(line.c_str(), cmdMatch)) {
  49. // NOLINTNEXTLINE(misc-redundant-expression)
  50. if (!std::getline(output, line) || !std::getline(output, line)) {
  51. this->SetError("Invalid output from otool");
  52. return false;
  53. }
  54. cmsys::RegularExpressionMatch pathMatch;
  55. if (pathRegex.find(line.c_str(), pathMatch)) {
  56. rpaths.push_back(pathMatch.match(1));
  57. } else {
  58. this->SetError("Invalid output from otool");
  59. return false;
  60. }
  61. } else if (loadDylibRegex.find(line.c_str(), cmdMatch)) {
  62. // NOLINTNEXTLINE(misc-redundant-expression)
  63. if (!std::getline(output, line) || !std::getline(output, line)) {
  64. this->SetError("Invalid output from otool");
  65. return false;
  66. }
  67. cmsys::RegularExpressionMatch nameMatch;
  68. if (nameRegex.find(line.c_str(), nameMatch)) {
  69. libs.push_back(nameMatch.match(1));
  70. } else {
  71. this->SetError("Invalid output from otool");
  72. return false;
  73. }
  74. }
  75. }
  76. if (!process.Wait()) {
  77. std::ostringstream e;
  78. e << "Failed to wait on otool process for:\n " << file;
  79. this->SetError(e.str());
  80. return false;
  81. }
  82. if (process.GetStatus(0).ExitStatus != 0) {
  83. std::ostringstream e;
  84. e << "Failed to run otool on:\n " << file;
  85. this->SetError(e.str());
  86. return false;
  87. }
  88. return true;
  89. }