1 | // Copyright 2014 Renato Tegon Forti, Antony Polukhin. |
2 | // Copyright Antony Polukhin, 2015-2024. |
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 | |
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 | |
31 | inline bool is_shared_library(const std::string& s) { |
32 | return (s.find(s: ".dll" ) != std::string::npos || s.find(s: ".so" ) != std::string::npos || s.find(s: ".dylib" ) != std::string::npos) |
33 | && s.find(s: ".lib" ) == std::string::npos |
34 | && s.find(s: ".exp" ) == std::string::npos |
35 | && s.find(s: ".pdb" ) == std::string::npos |
36 | && s.find(s: ".manifest" ) == std::string::npos |
37 | && s.find(s: ".rsp" ) == std::string::npos |
38 | && s.find(s: ".obj" ) == std::string::npos |
39 | && s.find(s: ".a" ) == std::string::npos; |
40 | } |
41 | |
42 | inline bool is_shared_library(const char* p) { |
43 | return b2_workarounds::is_shared_library(s: std::string(p)); |
44 | } |
45 | |
46 | inline bool is_shared_library(const boost::filesystem::path& p) { |
47 | return b2_workarounds::is_shared_library(s: p.string()); |
48 | } |
49 | |
50 | #ifdef BOOST_DLL_USE_STD_FS |
51 | inline bool is_shared_library(const std::filesystem::path& p) { |
52 | return b2_workarounds::is_shared_library(p.string()); |
53 | } |
54 | #endif |
55 | |
56 | inline boost::dll::fs::path first_lib_from_argv(int argc, char* argv[]) { |
57 | BOOST_ASSERT(argc > 1); |
58 | (void)argc; |
59 | |
60 | for (int i = 1; i < argc; ++i) { |
61 | if (b2_workarounds::is_shared_library(p: argv[i])) { |
62 | return argv[i]; |
63 | } |
64 | |
65 | std::cout << "b2_workarounds::first_lib_from_argv(argc, argv): skipping '" << argv[i] << "'" << std::endl; |
66 | } |
67 | |
68 | BOOST_ASSERT(false); |
69 | return argv[1]; |
70 | } |
71 | |
72 | // This ugly struct is required to drop library version from shared library generated by b2. |
73 | struct argv_to_path_guard { |
74 | const boost::filesystem::path original_; |
75 | const boost::filesystem::path version_dropped_; |
76 | const std::string just_path_; |
77 | const bool same_; |
78 | |
79 | |
80 | static inline boost::filesystem::path drop_b2_deco(const boost::filesystem::path& in) { |
81 | std::size_t pos = in.filename().string().find(s: "-" ); |
82 | boost::filesystem::path res = in.parent_path() / in.filename().string().substr(pos: 0, n: in.filename().string().find(s: "-" )); |
83 | if (pos != std::string::npos) { |
84 | res += in.extension(); |
85 | } |
86 | return res; |
87 | } |
88 | |
89 | inline explicit argv_to_path_guard(int argc, char* argv[]) |
90 | : original_(first_lib_from_argv(argc, argv)) |
91 | , version_dropped_( drop_b2_deco(in: drop_version(lhs: original_)) ) |
92 | , just_path_( version_dropped_.parent_path().string() ) |
93 | , same_(version_dropped_ == original_) |
94 | { |
95 | if (!same_) { |
96 | boost::system::error_code ignore; |
97 | boost::filesystem::remove(p: version_dropped_, ec&: ignore); |
98 | boost::filesystem::copy(from: original_, to: version_dropped_, ec&: ignore); |
99 | } |
100 | |
101 | argv[1] = const_cast<char*>(just_path_.c_str()); |
102 | } |
103 | |
104 | inline ~argv_to_path_guard() { |
105 | if (!same_) { |
106 | boost::system::error_code ignore; |
107 | boost::filesystem::remove(p: version_dropped_, ec&: ignore); |
108 | } |
109 | } |
110 | }; |
111 | |
112 | } // namespace b2_workarounds |
113 | |
114 | #endif // BOOST_DLL_EXAMPLE_COMMON_B2_WORKAROUNDS_HPP |
115 | |
116 | |