Deprecations

Deprecations are commonly used to allow APIs to evolve over time, by phasing out no-longer-fashionable API functions and replacing them with newer, cooler replacements. This page explains how libraries in the GTK+ stack do deprecations, and what mechanisms they provide for an application developer - you - to deal with them.

One important thing to keep in mind is that 'deprecated' does not mean 'broken', or 'unusable'. There is no need to rush into replacing every deprecated function by its replacement right away. The next major release of the library in question (which is the point at which deprecated API may be dropped) may be years away. Until that happens, it is perfectly fine to keep using the functions.

Basics

How does one recognize that a function is deprecated ? Since a few years, the GTK+ stack annotates deprecations in their headers, like this:

GLIB_DEPRECATED_IN_2_26
void         g_completion_clear_items   (GCompletion*    cmp);

GLIB_DEPRECATED_IN_2_40_FOR(g_settings_schema_key_get_range)
GVariant *   g_settings_get_range        (GSettings   *settings,
                                          const gchar *key);

GDK_DEPRECATED_IN_3_10
void     gtk_window_reshow_with_initial_size (GtkWindow *window);

These annotations are defined as macros in the GLib headers, which expand to function attributes that cause the C compiler to warn when these functions are used.

In addition, the doc comments for deprecated functions contain a Deprecated: tag:

 /**
 * g_completion_clear_items:
 * @cmp: the #GCompletion.
 *
 * Removes all items from the #GCompletion. The items are not freed, so if the
 * memory was dynamically allocated, it should be freed after calling this
 * function.
 *
 * Deprecated:2.26: Rarely used API
 **/

/**
 * g_settings_get_range:
 * @settings: a #GSettings
 * @key: the key to query the range of
 *
 * Queries the range of a key.
 *
 * Since: 2.28
 *
 * Deprecated:2.40: Use g_settings_schema_key_get_range() instead.
 **/

/**
 * gtk_window_reshow_with_initial_size:
 * @window: a #GtkWindow
 * 
 * Hides @window, then reshows it, resetting the
 * default size and position of the window. Used
 * by GUI builders only.
 * 
 * Deprecated: 3.10: GUI builders can call gtk_widget_hide(),
 *   gtk_widget_unrealize() and then gtk_widget_show() on @window
 *   themselves, if they still need this functionality.
 **/

You can see here, here and here how these notes look in the formatted documentation.

Deprecation warnings

Ultimatively, the GDK_DEPRECATED_IN_3_10 expands to a compiler attribute — like __attribute__((__deprecated__)), in GCC — which causes a reasonably modern compiler to emit warnings when you compile your program; for instance:

$ make testheaderbar
  CC       testheaderbar.o
testheaderbar.c: In function ‘main’:
testheaderbar.c:192:3: warning: ‘gtk_window_reshow_with_initial_size’ is deprecated (declared at ../gtk/gtkwindow.h:419) [-Wdeprecated-declarations]
   gtk_window_reshow_with_initial_size (GTK_WINDOW (window));
   ^
  CCLD     testheaderbar

Note that this is just a warning — the program was successfully built. If you don't want to deal with deprecations right now, and the warnings annoy you, you can simply add -Wno-deprecated-declarations to CFLAGS to stop them.

Ignoring all deprecations

As already mentioned, adding -Wno-deprecated-declarations to CFLAGS is a quick way to get rid of all deprecation warnings. Another way to ignore all deprecations is to define GLIB_DISABLE_DEPRECATION_WARNINGS, which turns the deprecation annotations into no-ops. This is usually done in Makefile.am:

AM_CPPFLAGS = \
             -DGLIB_DISABLE_DEPRECATION_WARNINGS \
             ...

Selectively ignoring deprecations

Sometimes it is impractical to avoid certain deprecated functions, even though your code is otherwise deprecation-free. In this case, you probably don't want to disable all deprecation warnings, and instead just selectively mark the code sections in which the deprecated functions are used:

  G_GNUC_BEGIN_IGNORE_DEPRECATIONS
  
  gtk_window_reshow_with_initial_size (window);

  G_GNUC_END_IGNORE_DEPRECATIONS

Targeting specific library versions

If your application was developed against a certain version of a library, say GLib 2.26, and you want to ensure that it continues to work on systems with this version of GLib, as well as newer versions, there are two things you need to worry about.

Newer versions of GLib may deprecate API that you are using. There is no reason for you to stop using it, since it was not deprecated in 2.26 (and the replacements will probably not be available in 2.26), but you also want to build your application with newer versions of GLib without warnings.

Even if your development system has a newer version of GLib, you want avoid using GLib API that was introduced after 2.26, to keep your application working on systems with GLib 2.26.

The deprecations and API additions in the GTK+ stack are versioned, which lets you achieve these goals by defining the range of versions of the APIs that your application is expected to work with. This is done with a pair of macros, which are typically defined in configure.ac:

AC_DEFINE(GLIB_VERSION_MIN_REQUIRED, GLIB_VERSION_2_26, [Ignore post 2.26 deprecations])
AC_DEFINE(GLIB_VERSION_MAX_ALLOWED, GLIB_VERSION_2_26, [Prevent post 2.26 APIs])

Each library has their own macros. For GLib, they are GLIB_VERSION_MIN_REQUIRED and GLIB_VERSION_MAX_ALLOWED. For GTK+, they are GDK_VERSION_MIN_REQUIRED and GDK_VERSION_MAX_ALLOWED.

The definition for these macros must encode the major and minor version in a binary format. You can either use predefined values such as GLIB_VERSION_2_26, GDK_VERSION_3_10, or use the G_ENCODE_VERSION macro like this:

#define GLIB_VERSION_MIN_REQUIRED G_ENCODE_VERSION(2,26)

References

The GLib documentation contains a section about deprecations.