Le 18/11/2010 23:56, Lex Trotman a écrit : > On 19 November 2010 03:16, Colomban Wendling <lists....@herbesfolles.org> > wrote: >> Le 18/11/2010 01:18, Lex Trotman a écrit : >>> On 18 November 2010 10:16, Colomban Wendling <lists....@herbesfolles.org> >>> wrote: >>>> Le 17/11/2010 23:09, Lex Trotman a écrit : >>>>> On 18 November 2010 03:36, Colomban Wendling <lists....@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. Not exactly. You can still happen members to structs (but see below for thoughts about structs) without breaking the A[PB]I, and I think that this doesn't really apply for functions. In a library POV, I think that functions' signature should be got right the first time (it isn't easy, but…); and I still think that it'd be overkill to handle such changes from a plugin.
> 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. I agree, exposing members is generally a pain. > 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). Agreed. > 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??) Well, right. >> 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. Wouldn't manually checking for /everything/ be a PITA? Or at least, provide a trivial way to say "if this functions isn't present, I can't run". Or I miss something? > 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. Right. Regards, Colomban _______________________________________________ Geany-devel mailing list Geany-devel@uvena.de http://lists.uvena.de/cgi-bin/mailman/listinfo/geany-devel