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
17namespace b2_workarounds {
18
19
20inline 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
31inline 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
42inline bool is_shared_library(const char* p) {
43 return b2_workarounds::is_shared_library(s: std::string(p));
44}
45
46inline 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
51inline bool is_shared_library(const std::filesystem::path& p) {
52 return b2_workarounds::is_shared_library(p.string());
53}
54#endif
55
56inline 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.
73struct 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

source code of boost/libs/dll/example/b2_workarounds.hpp