• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #ifndef BOOST_DLL_EXAMPLE_COMMON_B2_WORKAROUNDS_HPP
9 #define BOOST_DLL_EXAMPLE_COMMON_B2_WORKAROUNDS_HPP
10 
11 #include <boost/dll/config.hpp>
12 #include <boost/filesystem.hpp>
13 #include <boost/system/error_code.hpp>
14 #include <iostream>
15 #include <cctype>
16 
17 namespace b2_workarounds {
18 
19 
drop_version(const boost::filesystem::path & lhs)20 inline boost::filesystem::path drop_version(const boost::filesystem::path& lhs) {
21     boost::filesystem::path ext = lhs.filename().extension();
22     if (ext.native().size() > 1 && std::isdigit(ext.string()[1])) {
23         ext = lhs;
24         ext.replace_extension().replace_extension().replace_extension();
25         return ext;
26     }
27 
28     return lhs;
29 }
30 
is_shared_library(const std::string & s)31 inline bool is_shared_library(const std::string& s) {
32     return (s.find(".dll") != std::string::npos || s.find(".so") != std::string::npos || s.find(".dylib") != std::string::npos)
33             && s.find(".lib") == std::string::npos
34             && s.find(".exp") == std::string::npos
35             && s.find(".pdb") == std::string::npos
36             && s.find(".manifest") == std::string::npos
37             && s.find(".rsp") == std::string::npos
38             && s.find(".obj") == std::string::npos
39             && s.find(".a") == std::string::npos;
40 }
41 
is_shared_library(const char * p)42 inline bool is_shared_library(const char* p) {
43     return b2_workarounds::is_shared_library(std::string(p));
44 }
45 
is_shared_library(const boost::filesystem::path & p)46 inline bool is_shared_library(const boost::filesystem::path& p) {
47     return b2_workarounds::is_shared_library(p.string());
48 }
49 
first_lib_from_argv(int argc,char * argv[])50 inline boost::dll::fs::path first_lib_from_argv(int argc, char* argv[]) {
51     BOOST_ASSERT(argc > 1);
52     (void)argc;
53 
54     for (int i = 1; i < argc; ++i) {
55         if (b2_workarounds::is_shared_library(argv[i])) {
56             return argv[i];
57         }
58 
59         std::cout << "b2_workarounds::first_lib_from_argv(argc, argv): skipping '" << argv[i] << "'" << std::endl;
60     }
61 
62     BOOST_ASSERT(false);
63     return argv[1];
64 }
65 
66 // This ugly struct is required to drop library version from shared library generated by b2.
67 struct argv_to_path_guard {
68     const boost::filesystem::path original_;
69     const boost::filesystem::path version_dropped_;
70     const std::string just_path_;
71     const bool same_;
72 
73 
drop_b2_decob2_workarounds::argv_to_path_guard74     static inline boost::filesystem::path drop_b2_deco(const boost::filesystem::path& in) {
75         std::size_t pos = in.filename().string().find("-");
76         boost::filesystem::path res = in.parent_path() / in.filename().string().substr(0, in.filename().string().find("-"));
77         if (pos != std::string::npos) {
78             res += in.extension();
79         }
80         return res;
81     }
82 
argv_to_path_guardb2_workarounds::argv_to_path_guard83     inline explicit argv_to_path_guard(int argc, char* argv[])
84         : original_(first_lib_from_argv(argc, argv))
85         , version_dropped_( drop_b2_deco(drop_version(original_)) )
86         , just_path_( version_dropped_.parent_path().string() )
87         , same_(version_dropped_ == original_)
88     {
89         if (!same_) {
90             boost::system::error_code ignore;
91             boost::filesystem::remove(version_dropped_, ignore);
92             boost::filesystem::copy(original_, version_dropped_, ignore);
93         }
94 
95         argv[1] = const_cast<char*>(just_path_.c_str());
96     }
97 
~argv_to_path_guardb2_workarounds::argv_to_path_guard98     inline ~argv_to_path_guard() {
99         if (!same_) {
100             boost::system::error_code ignore;
101             boost::filesystem::remove(version_dropped_, ignore);
102         }
103     }
104 };
105 
106 } // namespace b2_workarounds
107 
108 #endif // BOOST_DLL_EXAMPLE_COMMON_B2_WORKAROUNDS_HPP
109 
110