On 19 November 2010 03:16, Colomban Wendling lists.ban@herbesfolles.org wrote:
Le 18/11/2010 01:18, Lex Trotman a écrit :
On 18 November 2010 10:16, Colomban Wendling lists.ban@herbesfolles.org wrote:
Le 17/11/2010 23:09, Lex Trotman a écrit :
On 18 November 2010 03:36, Colomban Wendling lists.ban@herbesfolles.org wrote:
But does new API really matters? If a plugin writer wants to keep being compatible with old Geany versions, she just have not to use new API -- as far as the ABI hasn't changed.
But ATM how does a plugin check that without being re-compiled?
What what what? :D If a plugin compiles with version 0.18 and Geany doesn't detect a problem when comparing the ABI version it was built against, it IS compatible, no? And if the same plugin is compiled against Geany 0.19 (assuming the ABI hasn't changed), it will still work with Geany 0.18...
Yes, but ANY change to the API/ABI even in areas that the plugin doesn't use changes the version and makes the plugin incompatible with older Geany.
Okay, I think I got your point, reading this and some other mails in this thread: you want to prevent ABI bumps to break plugins that are not directly affected.
Yes, an ABI bump break every plugin that was compiled before it. If it isn't affected, it has to be rebuild.
But I'm with Enrico here: I don't think ABI bumps will/should happen often.
That means as soon as you expose something its frozen, you have to get it complete and exactly right the first time, no incremental development. I think thats setting a pretty large barrier for a small project like Geany.
And as more goes into plugins the difficulty increases, it doesn't decrease.
And finally, if you want to protect from ABI breakage, you have to protect every symbol, not only functions, but also structures and structure members (even enums values may need this then).
Each function in *Funcs in plugindata.h
Just structures (ie each pointer in GeanyData), no need to protect individual members because over time structures should be removed from the API because they expose implementation details that are then frozen. They should use accessors to read/write only the information the plugin needs and new fields should be exposed that way rather than in the structures.
Similarly types internal to Geany should not be exposed, except perhaps as an opaque typename needed for some functions (ie returned by one call and passed to another).
Enums don't need it since changing one changes the struct/function that uses it so they are protetcted that way. (if they are not used in a visible struct/function why are they exposed??)
So... while I'm not (and never was) against having a very flexible dependency mechanism, I still think it's overkill, and won't it to make everything complicated. If backbard compatibility is this important, I'd prefer to simply keep the whole ABI stable, even if it may cost some deprecated things and some "old and now useless stuff": it isn't really nice either, but still seems less bloated to me.
But I'd be curious to see how you would implement this :)
Well this is a first thought only :-)
Have a set of structs parallel to GeanyData and *Funcs structures, with same member names and all unsigned ints. Lets call them say GeanyDataVersion and *FuncsVersion. Collectively called the *Version structs.
Also have API and ABI numbers for GeanyData and *Funcs struct, that handles additions (changes API) and removals (changes ABI) to the struct itself. This needs only one struct with members named after the structures, lets call it the StructVersions struct.
plugindata.h has #defines for each value to go in the *Version structs eg #define GEANYAPPVERSION 12345 to use the first struct in GeanyData as the example and similar symbols for the StructVersions values. This allows plugins to still do static checks if they want to.
plugins.c has the *Version and StructVersions structs initialised with these symbols.
Each plugin has an array of:
struct detailed_versions_needed { size_t item_to_check; // offset of a member of GeanyDataVersion or *FuncsVersion, NULL to end unsigned int required_version; // version must equal this };
initialised with the required offsets and versions, and the plugin also has a StructVersion struct initialised as required.
A macro PLUGIN_DETAILED_VERSION_CHECK defines a function that runs through the array and the struct doing the checks.
Geany checks if the plugin has the plugin_detailed_version_check symbol and only calls it if it does, otherwise it calls the normal plugin_version_check.
Something like this approach does not force plugins to change immediately, it can happen over time. Also it allows a simple tool to check that a plugin dev has listed all the functions and structs she used.
We should not force immediate change on the plugins, but the plugins won't start changing until the facility is made available :-) and the sooner it is the easier for new plugin developers.
Cheers Lex
Regards, Colomban _______________________________________________ Geany-devel mailing list Geany-devel@uvena.de http://lists.uvena.de/cgi-bin/mailman/listinfo/geany-devel