summaryrefslogtreecommitdiff
path: root/gmodule
diff options
context:
space:
mode:
Diffstat (limited to 'gmodule')
-rw-r--r--gmodule/gmodule-ar.c15
-rw-r--r--gmodule/gmodule-deprecated.c29
-rw-r--r--gmodule/gmodule-dl.c15
-rw-r--r--gmodule/gmodule.c127
-rw-r--r--gmodule/gmodule.h2
-rw-r--r--gmodule/meson.build5
-rw-r--r--gmodule/tests/max-version.c46
-rw-r--r--gmodule/tests/meson.build12
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