b2_workarounds.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Copyright 2014 Renato Tegon Forti, Antony Polukhin.
  2. // Copyright 2015-2019 Antony Polukhin.
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt
  6. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_DLL_EXAMPLE_COMMON_B2_WORKAROUNDS_HPP
  8. #define BOOST_DLL_EXAMPLE_COMMON_B2_WORKAROUNDS_HPP
  9. #include <boost/dll/config.hpp>
  10. #include <boost/filesystem.hpp>
  11. #include <boost/system/error_code.hpp>
  12. #include <iostream>
  13. #include <cctype>
  14. namespace b2_workarounds {
  15. inline boost::filesystem::path drop_version(const boost::filesystem::path& lhs) {
  16. boost::filesystem::path ext = lhs.filename().extension();
  17. if (ext.native().size() > 1 && std::isdigit(ext.string()[1])) {
  18. ext = lhs;
  19. ext.replace_extension().replace_extension().replace_extension();
  20. return ext;
  21. }
  22. return lhs;
  23. }
  24. inline bool is_shared_library(const std::string& s) {
  25. return (s.find(".dll") != std::string::npos || s.find(".so") != std::string::npos || s.find(".dylib") != std::string::npos)
  26. && s.find(".lib") == std::string::npos
  27. && s.find(".exp") == std::string::npos
  28. && s.find(".pdb") == std::string::npos
  29. && s.find(".manifest") == std::string::npos
  30. && s.find(".rsp") == std::string::npos
  31. && s.find(".obj") == std::string::npos
  32. && s.find(".a") == std::string::npos;
  33. }
  34. inline bool is_shared_library(const char* p) {
  35. return b2_workarounds::is_shared_library(std::string(p));
  36. }
  37. inline bool is_shared_library(const boost::filesystem::path& p) {
  38. return b2_workarounds::is_shared_library(p.string());
  39. }
  40. inline boost::dll::fs::path first_lib_from_argv(int argc, char* argv[]) {
  41. BOOST_ASSERT(argc > 1);
  42. (void)argc;
  43. for (int i = 1; i < argc; ++i) {
  44. if (b2_workarounds::is_shared_library(argv[i])) {
  45. return argv[i];
  46. }
  47. std::cout << "b2_workarounds::first_lib_from_argv(argc, argv): skipping '" << argv[i] << "'" << std::endl;
  48. }
  49. BOOST_ASSERT(false);
  50. return argv[1];
  51. }
  52. // This ugly struct is required to drop library version from shared library generated by b2.
  53. struct argv_to_path_guard {
  54. const boost::filesystem::path original_;
  55. const boost::filesystem::path version_dropped_;
  56. const std::string just_path_;
  57. const bool same_;
  58. static inline boost::filesystem::path drop_b2_deco(const boost::filesystem::path& in) {
  59. std::size_t pos = in.filename().string().find("-");
  60. boost::filesystem::path res = in.parent_path() / in.filename().string().substr(0, in.filename().string().find("-"));
  61. if (pos != std::string::npos) {
  62. res += in.extension();
  63. }
  64. return res;
  65. }
  66. inline explicit argv_to_path_guard(int argc, char* argv[])
  67. : original_(first_lib_from_argv(argc, argv))
  68. , version_dropped_( drop_b2_deco(drop_version(original_)) )
  69. , just_path_( version_dropped_.parent_path().string() )
  70. , same_(version_dropped_ == original_)
  71. {
  72. if (!same_) {
  73. boost::system::error_code ignore;
  74. boost::filesystem::remove(version_dropped_, ignore);
  75. boost::filesystem::copy(original_, version_dropped_, ignore);
  76. }
  77. argv[1] = const_cast<char*>(just_path_.c_str());
  78. }
  79. inline ~argv_to_path_guard() {
  80. if (!same_) {
  81. boost::system::error_code ignore;
  82. boost::filesystem::remove(version_dropped_, ignore);
  83. }
  84. }
  85. };
  86. } // namespace b2_workarounds
  87. #endif // BOOST_DLL_EXAMPLE_COMMON_B2_WORKAROUNDS_HPP