On 07.01.2012 20:39, Greg Ercolano wrote:
> On 01/07/12 02:29, Albrecht Schlosser wrote:
...
>> IMO config.h would be the wrong place, this is only used in the FLTK
>> lib and not available to end users. However, the developer may need
>> a way to tell if a particular feature is available (if the ABI feature
>> is also an API extension or modification, which should be allowed as
>> well). Hence, it would probably have to be in FL/Enumerations.H ?
>
>       Yes, where ever's best. I'm not fully knowledegable about
>       FLTK's release stuff.
>
>> Well, here's an idea: we can tell the users to define the feature
>> macro when compiling the FLTK lib *and* the application as the
>> *same* value, and then FL/Enumerations.H could contain:
>>
>> #ifndef FLTK_ABI_VERSION
>> # define FLTK_ABI_VERSION 010300
>> #endif
>>
>> However, if someone would compile his app with another value than
>> the FLTK library (.dll, or .so), then this would be a big problem,
>> because then you *would* have ABI differences. Better ideas, anybody?
>
>       My idea was (in a previous post I think) that if this macro
>       is enabled, there'd be a compiler #warning if anyone tried
>       to build dynamically against FLTK built with this flag enabled.

This is *not* dependent on linking statically or dynamically! If your
version of the FLTK lib is compiled with another ABI version macro than
you define in your application, then you *have* different ABI versions
in your application. For an example look at your fl_tree.patch [1,2]
that enables additional member variables. The header file is included
in both the library (i.e. the .o files for static linking) and in the
application's code.

I believe we would need a function call to return the runtime library
version number, just like many other libraries have. I suggest
int fl_abi_version().

>       Or, perhaps the macro would affect the file naming of the .dll's
>       we generate, so that it has a special suffix (eg. 
> fltk_images_1_3_0_AF.dll
>       or some such) that indicates is a special feature release of 1.3.0.
>       This would prevent accidental inclusion of the wrong dll/so's at 
> runtime..?

This would maybe work with configure etc., but we wouldn't be able to
do this with the Windows (and Xcode) IDE projects, and I don't know
whether we could do it easily with CMake (I believe, probably yes).

>> IMHO this would be too much work, and since all these ABI features
>> will be included in later versions anyway, we'd have to maintain this
>> also when we switch to the next ABI release (minor or major version).
>> And, BTW, configure is not used by IDE users and CMake etc.
>
>       Right, though whatever features we do supply in configure
>       probably have similar techniques in those.. I don't know what
>       those are.
>
>       It seems like VS options are minimal; DEBUG/RELEASE and CAIRO
>       are the only options I've ever seen (or needed).. if there's more,
>       I guess I don't know about them.

You can define your own macros for the entire project, hence you could
do it with a #define FLTK_ABI_VERSION macro.

Okay, here are some more thoughts about this. I'd like to keep it as
simple as possible, but still protect it from being used wrong. We'd
have to make sure that no user overrides the internal ABI version
with a lower value than the official release uses, so I suggest to
use something like the following. The correct place to put the ABI
version in would obviously be FL/Enumerations.H, since we define the
other version numbers (FL_VERSION, FL_MAJOR_VERSION, etc.) in this
file. I suggest to use *another* macro to override the ABI version,
like FL_ABI_OVERRIDE, so that we can check if this is lower than the
given FL_ABI_VERSION. Note that we don't use leading zeroes, since
this would make the constant octal (thanks to Bill for the hint).

#if defined(FL_ABI_OVERRIDE) && FL_ABI_OVERRIDE > 10300
# define FL_ABI_VERSION FL_ABI_OVERRIDE
#else
# define FL_ABI_VERSION 10300
#endif

This would be unchanged for all versions in the 1.3.x series, since
we don't change ABI versions in patch versions.

Then we add a function in one of the .c(xx) files, so that it will
be part of the library:

int fl_abi_version() {
   return FL_ABI_VERSION;
}

Users are encouraged to do something like this in their main program
or wherever they have potential ABI differences:

if (fl_abi_version() != FL_ABI_VERSION)
   fl_abort ("FLTK ABI version mismatch: %d != %d",
     fl_abi_version(), FL_ABI_VERSION);

We could also add this to check the version and abort the program
if it doesn't match:

void fl_check_abi_version(int version) {
   if (fl_abi_version() != version)
     Fl::fatal ("FLTK ABI version mismatch: %d != %d",
       fl_abi_version(), version);
   return;
}


To support detecting and using the correct ABI version in application
development, we could add an option to configure that would be
propagated to fltk-config, so that fltk-config would define the
correct compiler option (e.g. "-DFL_ABI_OVERRIDE=10302") when called
with --compile or --c(xx)flags:

  --enable-abi-override=10302   (note: syntax not checked)

As an alternative, this is already possible today (running configure
with CFLAGS and CXXFLAGS defined:

CFLAGS="-DFL_ABI_OVERRIDE=10302" \
  CXXFLAGS="-DFL_ABI_OVERRIDE=10302" \
  ./configure

This results in (output may wrap):

$ ./fltk-config --cxxflags
-I. -I./png -I./zlib -I./jpeg -mwindows -DWIN32 -DUSE_OPENGL32 
-DFL_ABI_OVERRIDE=10302 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE

Note that "-DFL_ABI_OVERRIDE=10302" is shown above.

For simplicity and testing I put all this in one file, and it works
as expected (see below). This is expected to call Fl::error() with
the ABI mismatch message like this:
   "FLTK ABI version mismatch: 10302 != 10300"
for the 2nd call of fl_check_abi_version(), if compiled with
   -D-DFL_ABI_OVERRIDE=10302

Thoughts?

Albrecht

// modified test/hello.cxx:

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>

#include <stdio.h>

#if defined(FL_ABI_OVERRIDE) && FL_ABI_OVERRIDE > 10300
# define FL_ABI_VERSION FL_ABI_OVERRIDE
#else
# define FL_ABI_VERSION 10300
#endif

int fl_abi_version() {
   return FL_ABI_VERSION;
}

void fl_check_abi_version(int version) {
   if (fl_abi_version() != version)
     Fl::fatal ("FLTK ABI version mismatch: %d != %d",
       fl_abi_version(), version);
   return;
}

int main(int argc, char **argv) {
   Fl_Window *window = new Fl_Window(340,180);
   Fl_Box *box = new Fl_Box(20,40,300,100,"Hello, World!");
   box->box(FL_UP_BOX);
   box->labelfont(FL_BOLD+FL_ITALIC);
   box->labelsize(36);
   box->labeltype(FL_SHADOW_LABEL);
   window->end();
   window->show(argc, argv);
#ifdef FL_ABI_OVERRIDE
   printf ("FL_ABI_OVERRIDE = %d\n",FL_ABI_OVERRIDE);
   fflush(stdout);
#endif
   fl_check_abi_version(FL_ABI_VERSION);
   fl_check_abi_version(10300);
   return Fl::run();
}
_______________________________________________
fltk-dev mailing list
fltk-dev@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk-dev

Reply via email to