-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathPluginHelper.cpp
181 lines (151 loc) · 6.93 KB
/
PluginHelper.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include "PluginHelper.hpp"
#include <rtt/types/TypekitPlugin.hpp>
#include <boost/filesystem.hpp>
#include <boost/tokenizer.hpp>
#include <rtt/plugin/PluginLoader.hpp>
#include <base/Time.hpp>
#include "PkgConfigRegistry.hpp"
#include "PkgConfigHelper.hpp"
#include <iostream>
#include <base-logging/Logging.hpp>
#define xstr(s) str(s)
#define str(s) #s
using namespace orocos_cpp;
/**
* Cache for the needed typekits.
*/
std::map<std::string, std::vector<std::string> > PluginHelper::componentToTypeKitsMap;
std::vector< std::string > PluginHelper::getNeededTypekits(const std::string& componentName)
{
auto it = componentToTypeKitsMap.find(componentName);
if(it != componentToTypeKitsMap.end())
return it->second;
PkgConfigRegistryPtr pkgreg = PkgConfigRegistry::get();
OrogenPkgConfig pkg;
if(!pkgreg->getOrogen(componentName, pkg)){
throw std::runtime_error("Could not load pkgConfig file for typekit for component " + componentName);
}
std::string neededTypekitsString;
if(!pkg.tasks.getVariable("typekits", neededTypekitsString)){
std::cerr << "Tasks-PkgConfig file for component "+ componentName + " ("+pkg.tasks.sourceFile+") is expected to define the 'typekits' variable, but it does not. Trying to load self-named typekit" << std::endl;
neededTypekitsString = componentName;
}
std::vector<std::string> ret = PkgConfigHelper::vectorizeTokenSeparatedString(neededTypekitsString, " ");
// Name of orocos-rtt typekit in RTT::types::TypekitRepository is 'rtt-types', but the rock pkg
// config files call it as 'orocos'
// Result is that RTT::types::TypekitRepository::hasTypekit(tk=orocos) always returns false and
// the loading process is triggered
// The following loop works around this naming inconsistency
//
// Note: It is not clear 'why' oroGen generates the tpekit name as 'orocos'. Maybe because of
// orocos.rb specific things? Maybe becausen there was a renaming somewhen in the past?
for(std::string& tk : ret){
if(tk == "orocos")
tk = "rtt-types";
}
componentToTypeKitsMap.insert(std::make_pair(componentName, ret));
return ret;
}
void PluginHelper::loadAllPluginsInDir(const std::string& path)
{
base::Time start = base::Time::now();
boost::filesystem::path pluginDir(path);
int cnt = 0;
boost::shared_ptr<RTT::plugin::PluginLoader> loader = RTT::plugin::PluginLoader::Instance();
boost::filesystem::directory_iterator end_it; // default construction yields past-the-end
for (boost::filesystem::directory_iterator it( pluginDir );
it != end_it; it++ )
{
if(boost::filesystem::is_regular_file(*it))
{
// std::cout << "Found library " << *it << std::endl;
loader->loadLibrary(it->path().string());
cnt++;
}
}
base::Time end = base::Time::now();
std::cout << "Loaded " << cnt << " typekits in " << (end - start).toSeconds() << " Seconds " << std::endl;
}
bool PluginHelper::loadAllTypekitAndTransports()
{
//Create 'own' PkgconfigRegistry to ensure that all installed packages
//are loaded.
PkgConfigRegistry pkgreg({}, true);
bool all_okay=true;
for(std::string tk_name : pkgreg.getRegisteredTypekitNames()){
all_okay &= PluginHelper::loadTypekitAndTransports(tk_name);
}
return all_okay;
}
bool PluginHelper::loadTypekitAndTransports(const std::string& typekitName)
{
//already loaded, we can just exit
if(RTT::types::TypekitRepository::hasTypekit(typekitName)){
LOG_DEBUG_S << "Typekit and transport for " << typekitName << " was already laoded earlier";
return true;
}
LOG_INFO_S << "Loading Typekit and Transport for " << typekitName;
//Supported transport types
static const std::vector<std::string> knownTransports = {"corba", "mqueue", "typelib"};
PkgConfigRegistryPtr pkgreg = PkgConfigRegistry::get();
RTT::plugin::PluginLoader &loader(*RTT::plugin::PluginLoader::Instance());
PkgConfig pkg;
if(typekitName == "rtt-types" || typekitName == "orocos" || typekitName == "rtt")
{
LOG_DEBUG_S << "Loading RTT typekit";
//special case, rtt does not follow the convention below
if(!pkgreg->getOrocosRTT(pkg)){
throw std::runtime_error("PkgConfig for OROCOS RTT package was not loaded");
}
std::string libdir;
pkg.getVariable("libdir", libdir);
if(!loader.loadTypekits(libdir + "/orocos/gnulinux/"))
throw std::runtime_error("Error, failed to load rtt basis typekits");
if(!loader.loadPlugins(libdir + "/orocos/gnulinux/"))
throw std::runtime_error("Error, failed to load rtt basis plugins");
return true;
}
TypekitPkgConfig tpkg;
if(!pkgreg->getTypekit(typekitName, tpkg))
throw std::runtime_error("No PkgConfig file for typekit of component " + typekitName + " was loaded.");
if(!tpkg.typekit.isLoaded()){
throw std::runtime_error("No Typekit PkgConfig file for component " + typekitName + " was loaded.");
}
std::string libDir;
tpkg.typekit.getVariable("libdir", libDir);
//Library of typekit is named after a specific file pattern
std::string fname = libDir + "/lib" + typekitName + "-typekit-" xstr(OROCOS_TARGET) ".so";
LOG_DEBUG_S << "Loading typekit from " << fname;
if(!loader.loadLibrary(fname))
throw std::runtime_error("Error, could not load typekit for component " + typekitName);
//Load transports for typekit
for(const std::string &transport: knownTransports)
{
std::map<std::string, PkgConfig>::iterator it = tpkg.transports.find(transport);
if(it == tpkg.transports.end())
throw std::runtime_error("No PkgConfig file was loaded for transport " + transport + " for component " + typekitName);
pkg = it->second;
if(!pkg.getVariable("libdir", libDir)){
throw(std::runtime_error("PkgConfig file for transport "+transport+" of typekit "+typekitName+" does not define a 'libdir'."));
}
//Library of transport for a typekit is named after a specific file pattern
fname = libDir + "/lib" + typekitName + "-transport-" + transport + "-" xstr(OROCOS_TARGET) ".so";
LOG_DEBUG_S << "Loading typekit from " << fname;
if(!loader.loadLibrary(fname))
throw std::runtime_error("Error, could not load transport " + transport + " for component " + typekitName);
}
return true;
}
bool PluginHelper::loadAllTypekitsForModel(const std::string &modelName){
std::string componentName = modelName.substr(0, modelName.find_first_of(':'));
std::vector<std::string> neededTks = PluginHelper::getNeededTypekits(componentName);
bool retVal = false;
for(const std::string &tk: neededTks)
{
if(RTT::types::TypekitRepository::hasTypekit(tk))
continue;
retVal = true;
PluginHelper::loadTypekitAndTransports(tk);
}
return retVal;
}