处理弃用¶
弃用通常用于允许 API 随时间演进,通过逐步淘汰不再流行的 API 函数并用更新、更强大的替代方案替换它们。本页解释了 GNOME 堆栈中的库如何处理弃用,以及它们为应用程序开发者(也就是您)提供的处理弃用的机制。
需要记住的一点是,“已弃用”并不意味着“已损坏”或“不可用”。无需立即用其替代方案替换每个已弃用的函数。相关库的下一个主要版本(弃用 API 可能被删除的时间点)可能还有数年时间。在此之前,继续使用这些函数是完全可以的。
基础¶
如何识别一个函数已被弃用? 近几年来,GNOME 库在它们的头文件中以如下方式标注弃用:
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);
这些标注在 GLib 头文件中定义为宏,它们会扩展为函数属性,导致 C 编译器在使用这些函数时发出警告。
此外,已弃用函数的文档注释包含一个 Deprecated: 标签
/**
* 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.
*/
注意
如果您是库维护者:重要的是“Deprecated”标签不仅包含符号被弃用的版本,还包含如何用非弃用的 API 替换该符号的说明(如果存在替换方案)。
弃用警告¶
最终,GDK_DEPRECATED_IN_3_10 宏会扩展为一个编译器属性——例如 GCC 中的 __attribute__((__deprecated__))——这会导致现代编译器在编译程序时发出警告;例如
$ 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
请注意,这只是一个警告:程序仍然成功构建了。
提示
当您决定将代码移植到远离已弃用符号时,您可以要求编译器将弃用警告转换为错误;例如,使用 GCC,您可以将 -Werror=deprecated-declarations 添加到您的编译器标志中。
忽略所有弃用警告¶
如果您想忽略弃用警告,您可以告诉编译器不要发出警告——例如,使用 GCC,您可以将 -Wno-deprecated-declarations 添加到您的编译器标志中。或者,您可以禁用您正在使用的库的弃用警告——例如,通过将以下内容添加到您的 meson.build 文件中
add_project_arguments([
'-DGLIB_DISABLE_DEPRECATION_WARNINGS',
'-DGTK_DISABLE_DEPRECATION_WARNINGS',
],
language: 'c',
)
提供弃用标注的每个库都应提供禁用它们的方法。
选择性地忽略弃用警告¶
有时,即使您的代码在其他方面没有弃用,避免某些已弃用的函数也是不切实际的。在这种情况下,您可能不想禁用所有弃用警告,而是仅选择性地标记使用已弃用函数的代码部分
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
gtk_window_reshow_with_initial_size (window);
G_GNUC_END_IGNORE_DEPRECATIONS
针对特定库版本¶
如果您的应用程序是针对某个版本的库开发的,例如 GLib 2.56,并且您希望确保它继续适用于该版本的 GLib 以及更新版本,那么您需要担心两件事。
GLib 的新版本可能会弃用您正在使用的 API。您没有理由停止使用它,因为它在 2.56 中没有被弃用(并且替换方案可能在 2.56 中不可用),但您也希望在较新的 GLib 版本下构建您的应用程序而不会出现警告。
即使您的开发系统具有较新版本的 GLib,您也希望避免使用 GLib 在 2.56 之后引入的 API,以使您的应用程序在具有 GLib 2.56 的系统上正常工作。
GNOME 堆栈中的弃用和 API 添加都经过版本控制,这使您可以通过定义应用程序预期工作的 API 版本范围来实现这些目标。这通过一对宏来完成,这些宏通常在您的 meson.build 文件中定义
add_project_arguments([
'-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_56',
'-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_56',
],
language: 'c',
)
每个库都有自己的宏。对于 GLib,它们是 GLIB_VERSION_MIN_REQUIRED 和 GLIB_VERSION_MAX_ALLOWED。对于 GTK,它们是 GDK_VERSION_MIN_REQUIRED 和 GDK_VERSION_MAX_ALLOWED。
这些宏的定义必须以二进制格式编码主版本号和次版本号。您可以选择使用预定义的数值,例如 GLIB_VERSION_2_56、GDK_VERSION_3_10,或者使用 G_ENCODE_VERSION 宏,如下所示
#define GLIB_VERSION_MIN_REQUIRED G_ENCODE_VERSION(2,56)
重要提示
必须在包含相应库的头文件之前定义 MIN_REQUIRED 和 MAX_ALLOWED 宏。