diff options
Diffstat (limited to 'gmodule')
-rw-r--r-- | gmodule/gmodule-ar.c | 15 | ||||
-rw-r--r-- | gmodule/gmodule-deprecated.c | 29 | ||||
-rw-r--r-- | gmodule/gmodule-dl.c | 15 | ||||
-rw-r--r-- | gmodule/gmodule.c | 127 | ||||
-rw-r--r-- | gmodule/gmodule.h | 2 | ||||
-rw-r--r-- | gmodule/meson.build | 5 | ||||
-rw-r--r-- | gmodule/tests/max-version.c | 46 | ||||
-rw-r--r-- | gmodule/tests/meson.build | 12 |
8 files changed, 191 insertions, 60 deletions
diff --git a/gmodule/gmodule-ar.c b/gmodule/gmodule-ar.c index a3966decb..8289f529f 100644 --- a/gmodule/gmodule-ar.c +++ b/gmodule/gmodule-ar.c @@ -167,18 +167,3 @@ _g_module_symbol (gpointer handle, return p; } - -static gchar* -_g_module_build_path (const gchar *directory, - const gchar *module_name) -{ - if (directory && *directory) { - if (strncmp (module_name, "lib", 3) == 0) - return g_strconcat (directory, "/", module_name, NULL); - else - return g_strconcat (directory, "/lib", module_name, "." G_MODULE_SUFFIX, NULL); - } else if (strncmp (module_name, "lib", 3) == 0) - return g_strdup (module_name); - else - return g_strconcat ("lib", module_name, "." G_MODULE_SUFFIX, NULL); -} diff --git a/gmodule/gmodule-deprecated.c b/gmodule/gmodule-deprecated.c new file mode 100644 index 000000000..e3f1fada7 --- /dev/null +++ b/gmodule/gmodule-deprecated.c @@ -0,0 +1,29 @@ +#include "config.h" + +/* + * This is the only way to disable deprecation warnings for macros, and we need + * to continue using G_MODULE_SUFFIX in the implementation of + * g_module_build_path() which is also deprecated API. + */ +#define GLIB_DISABLE_DEPRECATION_WARNINGS +#include <glib.h> + +#if (G_MODULE_IMPL == G_MODULE_IMPL_AR) || (G_MODULE_IMPL == G_MODULE_IMPL_DL) +G_GNUC_INTERNAL gchar* _g_module_build_path (const gchar *directory, + const gchar *module_name); + +gchar* +_g_module_build_path (const gchar *directory, + const gchar *module_name) +{ + if (directory && *directory) { + if (strncmp (module_name, "lib", 3) == 0) + return g_strconcat (directory, "/", module_name, NULL); + else + return g_strconcat (directory, "/lib", module_name, "." G_MODULE_SUFFIX, NULL); + } else if (strncmp (module_name, "lib", 3) == 0) + return g_strdup (module_name); + else + return g_strconcat ("lib", module_name, "." G_MODULE_SUFFIX, NULL); +} +#endif diff --git a/gmodule/gmodule-dl.c b/gmodule/gmodule-dl.c index 1ae90aa12..81b1b9f6b 100644 --- a/gmodule/gmodule-dl.c +++ b/gmodule/gmodule-dl.c @@ -210,18 +210,3 @@ _g_module_symbol (gpointer handle, return p; } - -static gchar* -_g_module_build_path (const gchar *directory, - const gchar *module_name) -{ - if (directory && *directory) { - if (strncmp (module_name, "lib", 3) == 0) - return g_strconcat (directory, "/", module_name, NULL); - else - return g_strconcat (directory, "/lib", module_name, "." G_MODULE_SUFFIX, NULL); - } else if (strncmp (module_name, "lib", 3) == 0) - return g_strdup (module_name); - else - return g_strconcat ("lib", module_name, "." G_MODULE_SUFFIX, NULL); -} diff --git a/gmodule/gmodule.c b/gmodule/gmodule.c index 49fc39664..9f9e1a042 100644 --- a/gmodule/gmodule.c +++ b/gmodule/gmodule.c @@ -161,9 +161,24 @@ /** * G_MODULE_SUFFIX: * - * Expands to the proper shared library suffix for the current platform - * without the leading dot. For most Unices and Linux this is "so", and - * for Windows this is "dll". + * Expands to a shared library suffix for the current platform without the + * leading dot. On Unixes this is "so", and on Windows this is "dll". + * + * Deprecated: 2.76: Use g_module_open() instead with @module_name as the + * basename of the file_name argument. You will get the wrong results using + * this macro most of the time: + * + * 1. The suffix on macOS is usually 'dylib', but it's 'so' when using + * Autotools, so there's no way to get the suffix correct using + * a pre-processor macro. + * 2. Prefixes also vary in a platform-specific way. You may or may not have + * a 'lib' prefix for the name on Windows and on Cygwin the prefix is + * 'cyg'. + * 3. The library name itself can vary per platform. For instance, you may + * want to load foo-1.dll on Windows and libfoo.1.dylib on macOS. + * + * g_module_open() takes care of all this by searching the filesystem for + * combinations of possible suffixes and prefixes. */ /** @@ -219,8 +234,14 @@ static void _g_module_close (gpointer handle); static gpointer _g_module_self (void); static gpointer _g_module_symbol (gpointer handle, const gchar *symbol_name); +#if (G_MODULE_IMPL != G_MODULE_IMPL_DL) && (G_MODULE_IMPL != G_MODULE_IMPL_AR) static gchar* _g_module_build_path (const gchar *directory, const gchar *module_name); +#else +/* Implementation is in gmodule-deprecated.c */ +gchar* _g_module_build_path (const gchar *directory, + const gchar *module_name); +#endif static inline void g_module_set_error (const gchar *error); static inline GModule* g_module_find_by_handle (gpointer handle); static inline GModule* g_module_find_by_name (const gchar *name); @@ -481,24 +502,28 @@ static GRecMutex g_module_global_lock; /** * g_module_open_full: - * @file_name: (nullable): the name of the file containing the module, or %NULL - * to obtain a #GModule representing the main program itself + * @file_name: (nullable): the name or path to the file containing the module, + * or %NULL to obtain a #GModule representing the main program itself * @flags: the flags used for opening the module. This can be the * logical OR of any of the #GModuleFlags * @error: #GError. * - * Opens a module. If the module has already been opened, - * its reference count is incremented. + * Opens a module. If the module has already been opened, its reference count + * is incremented. If not, the module is searched in the following order: * - * First of all g_module_open_full() tries to open @file_name as a module. - * If that fails and @file_name has the ".la"-suffix (and is a libtool - * archive) it tries to open the corresponding module. If that fails - * and it doesn't have the proper module suffix for the platform - * (%G_MODULE_SUFFIX), this suffix will be appended and the corresponding - * module will be opened. If that fails and @file_name doesn't have the - * ".la"-suffix, this suffix is appended and g_module_open_full() tries to open - * the corresponding module. If eventually that fails as well, %NULL is - * returned. + * 1. If @file_name exists as a regular file, it is used as-is; else + * 2. If @file_name doesn't have the correct suffix and/or prefix for the + * platform, then possible suffixes and prefixes will be added to the + * basename till a file is found and whatever is found will be used; else + * 3. If @file_name doesn't have the ".la"-suffix, ".la" is appended. Either + * way, if a matching .la file exists (and is a libtool archive) the + * libtool archive is parsed to find the actual file name, and that is + * used. + * + * At the end of all this, we would have a file path that we can access on + * disk, and it is opened as a module. If not, @file_name is opened as + * a module verbatim in the hopes that the system implementation will somehow + * be able to access it. * * Returns: a #GModule on success, or %NULL on failure * @@ -568,12 +593,58 @@ g_module_open_full (const gchar *file_name, /* try completing file name with standard library suffix */ if (!name) { - name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL); - if (!g_file_test (name, G_FILE_TEST_IS_REGULAR)) - { - g_free (name); - name = NULL; - } + char *basename, *dirname; + size_t prefix_idx = 0, suffix_idx = 0; + const char *prefixes[2] = {0}, *suffixes[2] = {0}; + + basename = g_path_get_basename (file_name); + dirname = g_path_get_dirname (file_name); +#ifdef G_OS_WIN32 + if (!g_str_has_prefix (basename, "lib")) + prefixes[prefix_idx++] = "lib"; + prefixes[prefix_idx++] = ""; + if (!g_str_has_suffix (basename, ".dll")) + suffixes[suffix_idx++] = ".dll"; +#else + #ifdef __CYGWIN__ + if (!g_str_has_prefix (basename, "cyg")) + prefixes[prefix_idx++] = "cyg"; + #else + if (!g_str_has_prefix (basename, "lib")) + prefixes[prefix_idx++] = "lib"; + else + /* People commonly pass `libfoo` as the file_name and want us to + * auto-detect the suffix as .la or .so, etc. We need to also find + * .dylib and .dll in those cases. */ + prefixes[prefix_idx++] = ""; + #endif + #ifdef G_OS_DARWIN + if (!g_str_has_suffix (basename, ".dylib") && + !g_str_has_suffix (basename, ".so")) + { + suffixes[suffix_idx++] = ".dylib"; + suffixes[suffix_idx++] = ".so"; + } + #else + if (!g_str_has_suffix (basename, ".so")) + suffixes[suffix_idx++] = ".so"; + #endif +#endif + for (guint i = 0; i < prefix_idx; i++) + { + for (guint j = 0; j < suffix_idx; j++) + { + name = g_strconcat (dirname, G_DIR_SEPARATOR_S, prefixes[i], + basename, suffixes[j], NULL); + if (g_file_test (name, G_FILE_TEST_IS_REGULAR)) + goto name_found; + g_free (name); + name = NULL; + } + } + name_found: + g_free (basename); + g_free (dirname); } /* try completing by appending libtool suffix */ if (!name) @@ -592,8 +663,9 @@ g_module_open_full (const gchar *file_name, { gchar *dot = strrchr (file_name, '.'); gchar *slash = strrchr (file_name, G_DIR_SEPARATOR); - - /* make sure the name has a suffix */ + + /* we make sure the name has a suffix using the deprecated + * G_MODULE_SUFFIX for backward-compat */ if (!dot || dot < slash) name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL); else @@ -687,8 +759,8 @@ g_module_open_full (const gchar *file_name, /** * g_module_open: - * @file_name: (nullable): the name of the file containing the module, or %NULL - * to obtain a #GModule representing the main program itself + * @file_name: (nullable): the name or path to the file containing the module, + * or %NULL to obtain a #GModule representing the main program itself * @flags: the flags used for opening the module. This can be the * logical OR of any of the #GModuleFlags. * @@ -891,6 +963,9 @@ g_module_name (GModule *module) * * Returns: the complete path of the module, including the standard library * prefix and suffix. This should be freed when no longer needed + * + * Deprecated: 2.76: Use g_module_open() instead with @module_name as the + * basename of the file_name argument. See %G_MODULE_SUFFIX for why. */ gchar * g_module_build_path (const gchar *directory, diff --git a/gmodule/gmodule.h b/gmodule/gmodule.h index 664d8bbaa..5330a08e7 100644 --- a/gmodule/gmodule.h +++ b/gmodule/gmodule.h @@ -138,7 +138,7 @@ const gchar * g_module_name (GModule *module); * * No checks are made that the file exists, or is of correct type. */ -GMODULE_AVAILABLE_IN_ALL +GMODULE_DEPRECATED_IN_2_76 gchar* g_module_build_path (const gchar *directory, const gchar *module_name); diff --git a/gmodule/meson.build b/gmodule/meson.build index 3195fdc29..5119e0be0 100644 --- a/gmodule/meson.build +++ b/gmodule/meson.build @@ -73,9 +73,12 @@ gvisibility_h = custom_target( command: [gen_visibility_macros, meson.project_version(), 'visibility-macros', 'GMODULE', '@OUTPUT@'], install: true, install_dir: g_module_includedir, + # FIXME: Not needed with Meson >= 0.64.0 + install_tag: 'devel', ) -gmodule_sources = [gmodule_c, gvisibility_h] +gmodule_sources = [gmodule_c, gvisibility_h, 'gmodule-deprecated.c'] + if host_system == 'windows' gmodule_win_rc = configure_file( input: 'gmodule.rc.in', diff --git a/gmodule/tests/max-version.c b/gmodule/tests/max-version.c new file mode 100644 index 000000000..bae63b7bb --- /dev/null +++ b/gmodule/tests/max-version.c @@ -0,0 +1,46 @@ +/* + * Copyright 2022 Collabora Ltd. + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef GLIB_VERSION_MAX_ALLOWED +/* This is the oldest version macro available */ +#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_26 +#define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_26 +#endif + +#include <glib.h> + +#include <gmodule.h> + +static void +nothing (void) +{ + /* This doesn't really do anything: the real "test" is at compile time. + * Just make sure the GModule library gets linked. */ + g_debug ("GModule supported: %s", g_module_supported () ? "yes" : "no"); +} + +int +main (int argc, + char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/max-version/tested-at-compile-time", nothing); + return g_test_run (); +} diff --git a/gmodule/tests/meson.build b/gmodule/tests/meson.build index a751f3185..b9a0ee6f4 100644 --- a/gmodule/tests/meson.build +++ b/gmodule/tests/meson.build @@ -1,13 +1,16 @@ gmodule_tests = { + 'max-version' : {'install': false}, 'module-test-library' : { 'export_dynamic' : true, 'source': 'module-test.c', 'c_args': ['-DMODULE_TYPE="library"'], + 'can_fail': glib_build_static and host_system == 'windows', }, 'module-test-plugin' : { 'export_dynamic' : true, 'source': 'module-test.c', 'c_args': ['-DMODULE_TYPE="plugin"'], + 'can_fail': glib_build_static and host_system == 'windows', }, } @@ -37,7 +40,7 @@ if ['darwin', 'ios'].contains(host_machine.system()) module_suffix = 'so' endif -if get_option('default_library') != 'static' +if glib_build_shared foreach module : ['moduletestplugin_a', 'moduletestplugin_b'] shared_module(module + '_plugin', 'lib@0@.c'.format(module), dependencies : [libglib_dep, libgmodule_dep], @@ -56,7 +59,7 @@ if get_option('default_library') != 'static' endforeach endif -test_env = environment(common_test_env) +test_env = environment() test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) @@ -95,5 +98,10 @@ foreach test_name, extra_args : gmodule_tests suite = ['gmodule'] + extra_args.get('suite', []) timeout = suite.contains('slow') ? test_timeout_slow : test_timeout + + if extra_args.get('can_fail', false) + suite += 'failing' + endif + test(test_name, exe, env : test_env, timeout : timeout, suite : suite) endforeach |