#include <compilergcc.h>
void Dep_Plugin::OnAttach()
{
cbPlugin *plug = Manager::Get()->GetPluginManager()->FindPluginByName(_T("Compiler"));
if (plug)
{
cbCompilerPlugin *cplug = dynamic_cast<cbCompilerPlugin*>(plug);
bool attached = cplug->IsAttached();
Manager::Get()->GetLogManager()->Log(wxString::Format(_T("Dep plugin found compiler plugin instance %i"),attached));
}
}
At least on Linux It looks like it is possible to have a plugin compile against another plugin and use its plugin instance....This is because on linux we use -fvisibility=default and this will change in the future, when I have some free time to play with this.
Just need to include the relevant plugin headersThis is bloody dangerous. Nothing in this header is intended for external plugin access.Code#include <compilergcc.h>
On a separate topic:
Have you measured the time needed to load C::B with and without your patch.
Currently C::B loads pretty slow if all contrib plugins are installed, but disabled.
Does you patch improve the load time?
At least on Linux It looks like it is possible to have a plugin compile against another plugin and use its plugin instance....This is because on linux we use -fvisibility=default and this will change in the future, when I have some free time to play with this.
On windows the default is -fvisibility=hidden, so this won't work anyway.
Just need to include the relevant plugin headersThis is bloody dangerous. Nothing in this header is intended for external plugin access.Code#include <compilergcc.h>
If you want to access code from other plugins, you'll have to define a clear interface which can be guaranteed to be relatively stable.
I'm not sure also that it is a good idea to allow plugins to depend on other plugins
and I think if something should be accessed by more plugins it is better to provide a SDK API for it.
Not what you said in the other thread... ???I'm not sure what are you referring here. I've just said that if we need to have one plugin depend on another, then doing this as part of the plugin manager is the right way to do it.
... but I would still like some method of deploying this shared library using our existing plugin management mechanismsOne way is using static libraries. With -fvisibility=hidden plus some other useful options the linker is able to remove the unused code.
Another example is Tools+.I've always felt that the tools+ should have been written over the original code and thus the old code removed. And this is the reason I'm not using the Tools+.
Curious to hear what others think. I won't spend any more time on this if enough of you think this is a dead end.As I've said in the other topic: if you need this feature go on and implement it. Handling dependencies automatically is the only proper way to do this if you need it. Playing with the weights and so on is just a hack.
Curious to hear what others think. I won't spend any more time on this if enough of you think this is a dead end.
On a separate topic:
Have you measured the time needed to load C::B with and without your patch.
Currently C::B loads pretty slow if all contrib plugins are installed, but disabled.
Does you patch improve the load time?
Some, C::B still has to read all of the manifests, but no DLLs for disabled plugins get loaded. I will do some timings when I have time.
time codeblocks --safe-mode -ns -ni --multiple-instance (quitting immediately after)
before: ~10.0s first time*, ~5.8s subsequently
after: ~2.8s first time*, ~2.6s subsequently
time codeblocks -ns -ni --multiple-instance (quitting immediately after)
before: ~8.1s**
after: ~5.3s**
Not what you said in the other thread... ???I'm not sure what are you referring here. I've just said that if we need to have one plugin depend on another, then doing this as part of the plugin manager is the right way to do it.
... but I would still like some method of deploying this shared library using our existing plugin management mechanismsOne way is using static libraries. With -fvisibility=hidden plus some other useful options the linker is able to remove the unused code.
Another option is using -rpath, but I'm not sure if it is available on windows or osx.
Another example is Tools+.I've always felt that the tools+ should have been written over the original code and thus the old code removed. And this is the reason I'm not using the Tools+.
C::B has one very serious problem - it has tons of features that look like each other: tools/tools+, build-in search/threadsearch/incremental search.
We should try to do a better job in this regard - copy the good parts from all implementation and remove the bad once or at least extracting built-in tools and built-in search in plugins.
Curious to hear what others think. I won't spend any more time on this if enough of you think this is a dead end.As I've said in the other topic: if you need this feature go on and implement it. Handling dependencies automatically is the only proper way to do this if you need it. Playing with the weights and so on is just a hack.
Not sure what you mean, but probably because I don't sufficiently understand shared object linking. Suppose we have plugin A, plugin B and a library C that they both depend on. If I statically link A and C, how do I make sure B can find the stuff in C?A static lib is just an archive with object files, so if you link both A and B to C (which is static lib), then both A and B will have all the code in C.
In this case the data structures for A and B will be separate/duplicated in memory.
p.s. about the weights: I've mentioned it because it is another simpler approach to handle plugin deps.
Hm, I think I'm being misunderstood. I don't like the idea of having plugins for plugins, I'm relatively ok with the idea of plugin communications.
So, lets stop arguing and just do it if you need it.
Have you though of putting all of your python subplugins in a single binary? I think this is possible already in C::B and probably will be easier for the user. :)
As for linking one DLL (a plugin is just a DLL after all) against another DLL under Windows, this is something I've done many times in the past, without doing anything special (I heard of the visibility flag for the fist time too :P). Are you sure it's problematic? I think it might just work fine.dmoore's problem is that he doesn't want to place his so/dll file next to libcodeblocks.so/dll, but this is a requirement at the moment (I've not checked if this is really the case, but I suppose it is).
please spend another month or so thinking about it.
As for linking one DLL (a plugin is just a DLL after all) against another DLL under Windows, this is something I've done many times in the past, without doing anything special (I heard of the visibility flag for the fist time too :P). Are you sure it's problematic? I think it might just work fine.
It's almost as if the GCC devs think that's a security risk ;DGCC devs have nothing to do here. Its the dynamic linker devs (glibc) that think this way.
The visibility flag is something unrelated to this problem. What it will do is to change the defaults to be a bit more sane, aka windows like. This is something that will happen in the future, when I find the time to do it.
dmoore: I've never tried to place two plugins in a single binary, but I've thought it is supported... but I might be wrong.
Maybe this makes my first patch mostly redundant. If using visibility radically improves link time then it doesn't really matter that all libs get loaded.I don't think it is related to the load time. The only benefit might be smaller size plugins and of course no more symbol collisions (not really serious problem in c::b).
As for linking one DLL (a plugin is just a DLL after all) against another DLL under Windows, this is something I've done many times in the past, without doing anything special (I heard of the visibility flag for the fist time too :P). Are you sure it's problematic? I think it might just work fine.dmoore's problem is that he doesn't want to place his so/dll file next to libcodeblocks.so/dll, but this is a requirement at the moment (I've not checked if this is really the case, but I suppose it is).
On Linux, -rpath/-rpath-link adds some flexibility, but it means we can never have plugins that are depended on in users home (becasue we don't know where home is at compile time). Maybe that's a limitation we can live with?I found the following here (http://www.linuxquestions.org/questions/programming-9/how-to-change-add-to-library-search-path-at-runtime-on-linux-855278/#post4221331). It is not elegant, but it might work if needed.
On UNIXish sytem there is a notion of TMPDIR - if needed, you can first find all the needed libraries, then symlink them to a directory under TMPDIR, then use the the full path with that directory.
I found the following here (http://www.linuxquestions.org/questions/programming-9/how-to-change-add-to-library-search-path-at-runtime-on-linux-855278/#post4221331). It is not elegant, but it might work if needed.Hm, are you really proposing this solution? :)
And I really think we should get at least the first part of the patch in trunk.Probably, but please not the comment in this line:
+ cbPlugin* plugin = FindPluginByName(basename); // THIS DOESN'T WORK RIGHT...
I've just re-read the topic.I agree.
And I really think we should get at least the first part of the patch in trunk.
Does it change anything in the plugins (manifest/api/abi)? If no then it should be relatively safe to apply it. Hopefully it will improve the load time of cb, which is pretty bad at the moment.
It needs to be changed to handle enabling and disabling multiplugin bundles. Off the top of my head, I cannot recall what the issue was with the DOESN'T WORK RIGHT comment.
// extract plugin from bundle
if (!ExtractFile(actualName,
localName,
pluginFilename))
return false;
On my test, install a bundle(such as a file named ProjectsImporter-1.1.cbplugin which I exported from C::B) failed in function bool PluginManager::InstallPlugin(const wxString& pluginName, bool forAllUsers, bool askForConfirmation)CodeNot sure the reason.// extract plugin from bundle
if (!ExtractFile(actualName,
localName,
pluginFilename))
return false;
EDIT: uninstall an unenabled plugin also failed without any dialog or message box.
void PluginsConfigurationDlg::OnUninstall(cb_unused wxCommandEvent& event)
{
wxListCtrl* list = XRCCTRL(*this, "lstPlugins", wxListCtrl);
if (list->GetSelectedItemCount() == 0)
return;
wxBusyCursor busy;
long sel = -1;
wxString failure;
while (true)
{
sel = list->GetNextItem(sel, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (sel == -1)
break;
PluginElement* elem = (PluginElement*)list->GetItemData(sel);
if (elem && elem->plugin)
{
if (!Manager::Get()->GetPluginManager()->UninstallPlugin(elem))
failure << elem->info.title << _T('\n');
}
}
FillList();
if (!failure.IsEmpty())
cbMessageBox(_("One or more plugins were not un-installed successfully:\n\n") + failure, _("Warning"), wxICON_WARNING, this);
}
Patch updated to handle safemode:o, you have version 2 of your patch here, but I'm testing your version 1 patch...
But I still have an issue that I can't install an exported plugin bundle, reported in my previous posts.OK, I found the reason, I see that in my exported plugin bundle, the dll and zip file name are all in lowercase, but the bundle name is "ProjectsImporter-1.1.cbplugin", so that the name are not matched. I'm bulding C::B against wx trunk(wx31)
ScanForPlugins(pluginDir);
LoadAllPlugins();
cbPlugin* plugin = FindPluginByName(basename); //THIS DOESN'T WORK RIGHT...
const PluginInfo* info = GetPluginInfo(plugin);
void PluginsConfigurationDlg::OnToggle(wxCommandEvent& event)
{
wxListCtrl* list = XRCCTRL(*this, "lstPlugins", wxListCtrl);
if (list->GetSelectedItemCount() == 0)
return;
bool isEnable = event.GetId() == XRCID("btnEnable");
wxBusyCursor busy;
wxProgressDialog pd(wxString::Format(_("%s plugin(s)"), isEnable ? _("Enabling") : _("Disabling")),
_T("A description wide enough for the dialog ;)"),
list->GetSelectedItemCount(),
this,
wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
int count = 0;
long sel = -1;
bool skip = false;
while (true)
{
sel = list->GetNextItem(sel, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (sel == -1)
break;
PluginElement* elem = (PluginElement*)list->GetItemData(sel);
if (elem)
{
pd.Update(++count,
wxString::Format(_("%s \"%s\"..."), isEnable ? _("Enabling") : _("Disabling"), elem->info.title.c_str()),
&skip);
if (skip)
break;
if (!isEnable && elem->plugin && elem->plugin->IsAttached())
{
Manager::Get()->GetPluginManager()->DetachPlugin(elem->plugin);
Manager::Get()->GetPluginManager()->UnloadPlugin(elem->plugin);
}
else if (isEnable && !(elem->plugin && elem->plugin->IsAttached()))
{
if (!elem->plugin)
Manager::Get()->GetPluginManager()->LoadPlugin(elem->fileName, elem);
Manager::Get()->GetPluginManager()->AttachPlugin(elem->plugin, true); // ignore safe-mode here
}
else
continue;
if (!elem->plugin)
Manager::Get()->GetPluginManager()->LoadPlugin(elem->fileName, elem);
void PluginManager::AddUnloadedPluginElem(const wxString &path, const PluginInfo &info)
{
PluginElement *plugElem = new PluginElement;
plugElem->fileName = path;
plugElem->info = info;
plugElem->library = 0;
plugElem->freeProc = 0;
plugElem->plugin = 0;
m_Plugins.Add(plugElem);
}
static PluginElement PluginElement::unloaded(const wxString &path, const PluginInfo &info);
m_Plugins.Add( new PluginElement::unloaded(path, info));
I always shiver when I see naked new and delete.Welcome to the real world outside of the committee...