how to handle "undefined symbol" errors for mismatched shared objects
I developed an application using a recent Glade, so I need it to load the UI from XML at runtime, using the GtkBuilder. If I try to run this on a distro which has too old a Gtk (e.g. RHEL 5), it will fail like this
undefined symbol: gtk_builder_new
which is normal and expected. But I wonder if there is a way to catch that error and 开发者_如何学Pythoninstead display a GUI error dialog saying something like "your version of Gtk is not new enough"? This is an error that happens before my main() starts, so really the question is, is there a way to handle runtime linking errors? While googling, I found a mention of the concept of a linker plugin but I didn't find details about that yet. It sounds like something which would have to exist outside my application anyway, so maybe that's going a bit far.
I could use dlopen() to load Gtk, but that's ridiculous because I'd have to give the full path to it, and then I'd have to call dlsym() a lot to link every function that I need. ld-linux.so does the search for me. Is there a way I can use ld-linux.so to tell me the path to libgtk without actually loading it, then I check whether the version is new enough (or just whether gtk_builder_new exists), then finish the runtime linking if it's OK?
Well, it doesn't work that way on a Linux distro. What you're basically doing is bypassing the package manager.
The good way is to build your software on the target distro. At configuration time (call to ./configure) you will see that the requirements to use your software are not met. Or if you have no configure script, the compiler will yell at link time.
Then, it's the packager's job to fill in the requirement of the package. If in the .spec file of your RPM package you require gtk >= 2.16, then at installation time, the user will be shown the dialog telling him that some dependencies are missing, and he will see that his GTK version is too old.
You seem to be talking about the situation where you have compiled against headers with a recent enough version, but are running on a system where your library is not recent enough.
GTK provides a facility for checking that you have linked against a new enough version of the library. For example, if you need at least GTK 2.12 (which is the version in which GtkBuilder was introduced) you can use this code which will even display a nice GUI error dialog:
if (gtk_major_version < 2 || gtk_minor_version < 12) {
GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
"Your version of GTK is too old to run this program.");
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
"You need at least version 2.12.0; your version is %d.%d.%d.",
gtk_major_version, gtk_minor_version, gtk_micro_version);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
exit(-1);
}
Here is a workaround which might help: Rename your exe and create a bash script which calls it.
Now you can do this:
EXE=...name-of-your-real-executable...
LOG=logfile
$EXE > "$LOG" 2>&1 || {
if grep "undefined symbol: gtk_builder_new" "$LOG" ; then
... show error message ...
fi
}
[EDIT] Alternatively, you can create a really small test program which just contains a call to gtk_builder_new
and run that during installation or in the test script.
That way, you don't need to check for a specific error message (which might get translated on non-English systems). If this small test program fails, you can be sure it's because of this missing symbol and nothing else.
精彩评论