• 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 // MinGW related workaround
9 #define BOOST_DLL_FORCE_ALIAS_INSTANTIATION
10 
11 #include "../b2_workarounds.hpp"
12 #include "../tutorial4/static_plugin.hpp"
13 #include <boost/dll/runtime_symbol_info.hpp> // for program_location()
14 #include <boost/dll/shared_library.hpp>
15 #include <boost/make_shared.hpp>
16 #include <boost/container/map.hpp>
17 #include <boost/filesystem.hpp>
18 #include <iostream>
19 
20 //[plugcpp_plugins_collector_def
21 namespace dll = boost::dll;
22 
23 class plugins_collector {
24     // Name => plugin
25     typedef boost::container::map<std::string, dll::shared_library> plugins_t;
26 
27     boost::dll::fs::path            plugins_directory_;
28     plugins_t                       plugins_;
29 
30     // loads all plugins in plugins_directory_
31     void load_all();
32 
33     // Gets `my_plugin_api` instance using "create_plugin" or "plugin" imports,
34     // stores plugin with its name in the `plugins_` map.
35     void insert_plugin(BOOST_RV_REF(dll::shared_library) lib);
36 
37 public:
plugins_collector(const boost::dll::fs::path & plugins_directory)38     plugins_collector(const boost::dll::fs::path& plugins_directory)
39         : plugins_directory_(plugins_directory)
40     {
41         load_all();
42     }
43 
44     void print_plugins() const;
45 
46     std::size_t count() const;
47     // ...
48 };
49 //]
50 
51 
52 //[plugcpp_plugins_collector_load_all
load_all()53 void plugins_collector::load_all() {
54     namespace fs = ::boost::dll::fs;
55     typedef fs::path::string_type string_type;
56     const string_type extension = dll::shared_library::suffix().native();
57 
58     // Searching a folder for files with '.so' or '.dll' extension
59     fs::recursive_directory_iterator endit;
60     for (fs::recursive_directory_iterator it(plugins_directory_); it != endit; ++it) {
61         if (!fs::is_regular_file(*it)) {
62             continue;
63         }
64         /*<-*/
65         if ( !b2_workarounds::is_shared_library((*it).path()) ) {
66             continue;
67         }
68         /*->*/
69         // We found a file. Trying to load it
70         boost::dll::fs::error_code error;
71         dll::shared_library plugin(it->path(), error);
72         if (error) {
73             continue;
74         }
75         std::cout << "Loaded (" << plugin.native() << "):" << it->path() << '\n';
76 
77         // Gets plugin using "create_plugin" or "plugin" function
78         insert_plugin(boost::move(plugin));
79     }
80 
81     dll::shared_library plugin(dll::program_location());
82     std::cout << "Loaded self\n";
83     insert_plugin(boost::move(plugin));
84 }
85 //]
86 
87 //[plugcpp_plugins_collector_insert_plugin
insert_plugin(BOOST_RV_REF (dll::shared_library)lib)88 void plugins_collector::insert_plugin(BOOST_RV_REF(dll::shared_library) lib) {
89     std::string plugin_name;
90     if (lib.has("create_plugin")) {
91         plugin_name = lib.get_alias<boost::shared_ptr<my_plugin_api>()>("create_plugin")()->name();
92     } else if (lib.has("plugin")) {
93         plugin_name = lib.get<my_plugin_api>("plugin").name();
94     } else {
95         return;
96     }
97 
98     if (plugins_.find(plugin_name) == plugins_.cend()) {
99         plugins_[plugin_name] = boost::move(lib);
100     }
101 }
102 //]
103 
print_plugins() const104 void plugins_collector::print_plugins() const {
105     plugins_t::const_iterator const end = plugins_.cend();
106     for (plugins_t::const_iterator it = plugins_.cbegin(); it != end; ++it) {
107         std::cout << '(' << it->second.native() << "): " << it->first << '\n';
108     }
109 }
110 
count() const111 std::size_t plugins_collector::count() const {
112     return plugins_.size();
113 }
114 
115 
116 //[plugcpp_load_all
main(int argc,char * argv[])117 int main(int argc, char* argv[]) {
118     /*<-*/
119     BOOST_ASSERT(argc >= 3);
120     boost::dll::fs::path path1(argv[1]);
121     for (int i = 2; i < argc; ++i) {
122         boost::dll::fs::path path2(argv[i]);
123         boost::dll::fs::path res;
124         for (boost::dll::fs::path::iterator it1 = path1.begin(), it2 = path2.begin();
125             it1 != path1.end() && it2 != path2.end() && *it1 == *it2;
126             ++it1, ++it2)
127         {
128             res /= *it1;
129         }
130 
131         path1 = res;
132     }
133 
134     std::string new_argv = path1.string();
135     std::cout << "\nPlugins path: " << new_argv << ":\n";
136     argv[1] = &new_argv[0];
137     /*->*/
138     plugins_collector plugins(argv[1]);
139 
140     std::cout << "\n\nUnique plugins " << plugins.count() << ":\n";
141     plugins.print_plugins();
142     // ...
143 //]
144     BOOST_ASSERT(plugins.count() >= 3);
145 }
146 
147