mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-13 07:56:17 +01:00
Merge branch 'gi_relocation' into 'main'
girepository: add support for relocations See merge request GNOME/glib!4088
This commit is contained in:
commit
b1e09794f4
@ -30,6 +30,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <glib-private.h>
|
||||||
#include <glib/gprintf.h>
|
#include <glib/gprintf.h>
|
||||||
#include <gmodule.h>
|
#include <gmodule.h>
|
||||||
#include "gibaseinfo-private.h"
|
#include "gibaseinfo-private.h"
|
||||||
@ -135,7 +136,6 @@ struct _GIRepository
|
|||||||
G_DEFINE_TYPE (GIRepository, gi_repository, G_TYPE_OBJECT);
|
G_DEFINE_TYPE (GIRepository, gi_repository, G_TYPE_OBJECT);
|
||||||
|
|
||||||
#ifdef G_PLATFORM_WIN32
|
#ifdef G_PLATFORM_WIN32
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
static HMODULE girepository_dll = NULL;
|
static HMODULE girepository_dll = NULL;
|
||||||
@ -155,19 +155,117 @@ DllMain (HINSTANCE hinstDLL,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* DLL_EXPORT */
|
||||||
|
#endif /* G_PLATFORM_WIN32 */
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <mach-o/dyld.h>
|
||||||
|
|
||||||
|
/* This function returns the file path of the loaded libgirepository1.0.dylib.
|
||||||
|
* It iterates over all the loaded images to find the one with the
|
||||||
|
* gi_repository_init symbol and returns its file path.
|
||||||
|
*/
|
||||||
|
static const char *
|
||||||
|
gi_repository_get_library_path_macos (void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Relevant documentation:
|
||||||
|
* https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/MachOTopics/0-Introduction/introduction.html
|
||||||
|
* https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dyld.3.html
|
||||||
|
* https://opensource.apple.com/source/xnu/xnu-2050.18.24/EXTERNAL_HEADERS/mach-o/loader.h
|
||||||
|
*/
|
||||||
|
const void *ptr = gi_repository_init;
|
||||||
|
const struct mach_header *header;
|
||||||
|
intptr_t offset;
|
||||||
|
uint32_t i, count;
|
||||||
|
|
||||||
|
/* Iterate over all the loaded images */
|
||||||
|
count = _dyld_image_count ();
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
header = _dyld_get_image_header (i);
|
||||||
|
offset = _dyld_get_image_vmaddr_slide (i);
|
||||||
|
|
||||||
|
/* Locate the first `load` command */
|
||||||
|
struct load_command *cmd = (struct load_command *) ((char *) header + sizeof (struct mach_header));
|
||||||
|
if (header->magic == MH_MAGIC_64)
|
||||||
|
cmd = (struct load_command *) ((char *) header + sizeof (struct mach_header_64));
|
||||||
|
|
||||||
|
/* Find the first `segment` command iterating over all the `load` commands.
|
||||||
|
* Then, check if the gi_repository_init symbol is in this image by checking
|
||||||
|
* if the pointer is in the segment's memory address range.
|
||||||
|
*/
|
||||||
|
uint32_t j = 0;
|
||||||
|
while (j < header->ncmds)
|
||||||
|
{
|
||||||
|
if (cmd->cmd == LC_SEGMENT)
|
||||||
|
{
|
||||||
|
struct segment_command *seg = (struct segment_command *) cmd;
|
||||||
|
if (((intptr_t) ptr >= (seg->vmaddr + offset)) && ((intptr_t) ptr < (seg->vmaddr + offset + seg->vmsize)))
|
||||||
|
return _dyld_get_image_name (i);
|
||||||
|
}
|
||||||
|
if (cmd->cmd == LC_SEGMENT_64)
|
||||||
|
{
|
||||||
|
struct segment_command_64 *seg = (struct segment_command_64 *) cmd;
|
||||||
|
if (((uintptr_t ) ptr >= (seg->vmaddr + offset)) && ((uintptr_t ) ptr < (seg->vmaddr + offset + seg->vmsize)))
|
||||||
|
return _dyld_get_image_name (i);
|
||||||
|
}
|
||||||
|
/* Jump to the next command */
|
||||||
|
j++;
|
||||||
|
cmd = (struct load_command *) ((char *) cmd + cmd->cmdsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif /* __APPLE__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gi_repository_get_libdir:
|
||||||
|
*
|
||||||
|
* Returns the directory where the typelib files are installed.
|
||||||
|
*
|
||||||
|
* In platforms without relocation support, this functions returns the
|
||||||
|
* `GOBJECT_INTROSPECTION_LIBDIR` directory defined at build time .
|
||||||
|
*
|
||||||
|
* On Windows and macOS this function returns the directory
|
||||||
|
* relative to the installation directory detected at runtime.
|
||||||
|
*
|
||||||
|
* On macOS, if the library is installed in
|
||||||
|
* `/Applications/MyApp.app/Contents/Home/lib/libgirepository-1.0.dylib`, it returns
|
||||||
|
* `/Applications/MyApp.app/Contents/Home/lib/girepository-1.0`
|
||||||
|
*
|
||||||
|
* On Windows, if the application is installed in
|
||||||
|
* `C:/Program Files/MyApp/bin/MyApp.exe`, it returns
|
||||||
|
* `C:/Program Files/MyApp/lib/girepository-1.0`
|
||||||
|
*/
|
||||||
|
static const gchar *
|
||||||
|
gi_repository_get_libdir (void)
|
||||||
|
{
|
||||||
|
static gchar *static_libdir;
|
||||||
|
|
||||||
|
if (g_once_init_enter_pointer (&static_libdir))
|
||||||
|
{
|
||||||
|
gchar *libdir;
|
||||||
|
#if defined(G_PLATFORM_WIN32)
|
||||||
|
const char *toplevel = g_win32_get_package_installation_directory_of_module (girepository_dll);
|
||||||
|
libdir = g_build_filename (toplevel, GOBJECT_INTROSPECTION_RELATIVE_LIBDIR, NULL);
|
||||||
|
g_ignore_leak (libdir);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
const char *libpath = gi_repository_get_library_path_macos ();
|
||||||
|
if (libpath != NULL)
|
||||||
|
{
|
||||||
|
libdir = g_path_get_dirname (libpath);
|
||||||
|
g_ignore_leak (libdir);
|
||||||
|
} else {
|
||||||
|
libdir = GOBJECT_INTROSPECTION_LIBDIR;
|
||||||
|
}
|
||||||
|
#else /* !G_PLATFORM_WIN32 && !__APPLE__ */
|
||||||
|
libdir = GOBJECT_INTROSPECTION_LIBDIR;
|
||||||
#endif
|
#endif
|
||||||
|
g_once_init_leave_pointer (&static_libdir, libdir);
|
||||||
#undef GOBJECT_INTROSPECTION_LIBDIR
|
}
|
||||||
|
return static_libdir;
|
||||||
/* GOBJECT_INTROSPECTION_LIBDIR is used only in code called just once,
|
}
|
||||||
* so no problem leaking this
|
|
||||||
*/
|
|
||||||
#define GOBJECT_INTROSPECTION_LIBDIR \
|
|
||||||
g_build_filename (g_win32_get_package_installation_directory_of_module (girepository_dll), \
|
|
||||||
"lib", \
|
|
||||||
NULL)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gi_repository_init (GIRepository *repository)
|
gi_repository_init (GIRepository *repository)
|
||||||
@ -197,7 +295,7 @@ gi_repository_init (GIRepository *repository)
|
|||||||
repository->typelib_search_path = g_ptr_array_new_null_terminated (1, g_free, TRUE);
|
repository->typelib_search_path = g_ptr_array_new_null_terminated (1, g_free, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
libdir = GOBJECT_INTROSPECTION_LIBDIR;
|
libdir = gi_repository_get_libdir ();
|
||||||
|
|
||||||
typelib_dir = g_build_filename (libdir, "girepository-1.0", NULL);
|
typelib_dir = g_build_filename (libdir, "girepository-1.0", NULL);
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ gir_c_args = [
|
|||||||
'-DGIR_DIR="@0@"'.format(glib_girdir),
|
'-DGIR_DIR="@0@"'.format(glib_girdir),
|
||||||
'-DGOBJECT_INTROSPECTION_LIBDIR="@0@"'.format(glib_libdir),
|
'-DGOBJECT_INTROSPECTION_LIBDIR="@0@"'.format(glib_libdir),
|
||||||
'-DGOBJECT_INTROSPECTION_DATADIR="@0@"'.format(glib_datadir),
|
'-DGOBJECT_INTROSPECTION_DATADIR="@0@"'.format(glib_datadir),
|
||||||
|
'-DGOBJECT_INTROSPECTION_RELATIVE_LIBDIR="@0@"'.format(get_option('libdir')),
|
||||||
]
|
]
|
||||||
|
|
||||||
custom_c_args = []
|
custom_c_args = []
|
||||||
|
@ -72,6 +72,7 @@ if enable_gir
|
|||||||
if cc.get_id() != 'msvc'
|
if cc.get_id() != 'msvc'
|
||||||
girepository_tests += {
|
girepository_tests += {
|
||||||
'autoptr-girepository' : {
|
'autoptr-girepository' : {
|
||||||
|
'dependencies': [libffi_dep],
|
||||||
'source' : 'autoptr.c',
|
'source' : 'autoptr.c',
|
||||||
'depends': gio_gir_testing_dep,
|
'depends': gio_gir_testing_dep,
|
||||||
},
|
},
|
||||||
|
@ -22,6 +22,23 @@
|
|||||||
#include "glib.h"
|
#include "glib.h"
|
||||||
#include "girepository.h"
|
#include "girepository.h"
|
||||||
|
|
||||||
|
static char *
|
||||||
|
test_repository_search_paths_get_expected_libdir_path (void)
|
||||||
|
{
|
||||||
|
#if defined(G_PLATFORM_WIN32)
|
||||||
|
const char *tests_build_dir = g_getenv ("G_TEST_BUILDDIR");
|
||||||
|
char *expected_rel_path = g_build_filename (tests_build_dir, "lib", "girepository-1.0", NULL);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
const char *tests_build_dir = g_getenv ("G_TEST_BUILDDIR");
|
||||||
|
char *expected_rel_path = g_build_filename (tests_build_dir, "..", "girepository-1.0", NULL);
|
||||||
|
#else /* !G_PLATFORM_WIN32 && !__APPLE__ */
|
||||||
|
char *expected_rel_path = g_build_filename (GOBJECT_INTROSPECTION_LIBDIR, "girepository-1.0", NULL);
|
||||||
|
#endif
|
||||||
|
char *expected_path = g_canonicalize_filename (expected_rel_path, NULL);
|
||||||
|
g_clear_pointer (&expected_rel_path, g_free);
|
||||||
|
return expected_path;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_repository_search_paths_default (void)
|
test_repository_search_paths_default (void)
|
||||||
{
|
{
|
||||||
@ -37,11 +54,9 @@ test_repository_search_paths_default (void)
|
|||||||
|
|
||||||
g_assert_cmpstr (search_paths[0], ==, g_get_tmp_dir ());
|
g_assert_cmpstr (search_paths[0], ==, g_get_tmp_dir ());
|
||||||
|
|
||||||
#ifndef G_PLATFORM_WIN32
|
char *expected_path = test_repository_search_paths_get_expected_libdir_path ();
|
||||||
char *expected_path = g_build_filename (GOBJECT_INTROSPECTION_LIBDIR, "girepository-1.0", NULL);
|
|
||||||
g_assert_cmpstr (search_paths[1], ==, expected_path);
|
g_assert_cmpstr (search_paths[1], ==, expected_path);
|
||||||
g_clear_pointer (&expected_path, g_free);
|
g_clear_pointer (&expected_path, g_free);
|
||||||
#endif
|
|
||||||
|
|
||||||
g_clear_object (&repository);
|
g_clear_object (&repository);
|
||||||
}
|
}
|
||||||
@ -63,11 +78,9 @@ test_repository_search_paths_prepend (void)
|
|||||||
g_assert_cmpstr (search_paths[0], ==, g_test_get_dir (G_TEST_BUILT));
|
g_assert_cmpstr (search_paths[0], ==, g_test_get_dir (G_TEST_BUILT));
|
||||||
g_assert_cmpstr (search_paths[1], ==, g_get_tmp_dir ());
|
g_assert_cmpstr (search_paths[1], ==, g_get_tmp_dir ());
|
||||||
|
|
||||||
#ifndef G_PLATFORM_WIN32
|
char *expected_path = test_repository_search_paths_get_expected_libdir_path ();
|
||||||
char *expected_path = g_build_filename (GOBJECT_INTROSPECTION_LIBDIR, "girepository-1.0", NULL);
|
|
||||||
g_assert_cmpstr (search_paths[2], ==, expected_path);
|
g_assert_cmpstr (search_paths[2], ==, expected_path);
|
||||||
g_clear_pointer (&expected_path, g_free);
|
g_clear_pointer (&expected_path, g_free);
|
||||||
#endif
|
|
||||||
|
|
||||||
gi_repository_prepend_search_path (repository, g_test_get_dir (G_TEST_DIST));
|
gi_repository_prepend_search_path (repository, g_test_get_dir (G_TEST_DIST));
|
||||||
search_paths = gi_repository_get_search_path (repository, &n_search_paths);
|
search_paths = gi_repository_get_search_path (repository, &n_search_paths);
|
||||||
@ -78,11 +91,9 @@ test_repository_search_paths_prepend (void)
|
|||||||
g_assert_cmpstr (search_paths[1], ==, g_test_get_dir (G_TEST_BUILT));
|
g_assert_cmpstr (search_paths[1], ==, g_test_get_dir (G_TEST_BUILT));
|
||||||
g_assert_cmpstr (search_paths[2], ==, g_get_tmp_dir ());
|
g_assert_cmpstr (search_paths[2], ==, g_get_tmp_dir ());
|
||||||
|
|
||||||
#ifndef G_PLATFORM_WIN32
|
expected_path = test_repository_search_paths_get_expected_libdir_path ();
|
||||||
expected_path = g_build_filename (GOBJECT_INTROSPECTION_LIBDIR, "girepository-1.0", NULL);
|
|
||||||
g_assert_cmpstr (search_paths[3], ==, expected_path);
|
g_assert_cmpstr (search_paths[3], ==, expected_path);
|
||||||
g_clear_pointer (&expected_path, g_free);
|
g_clear_pointer (&expected_path, g_free);
|
||||||
#endif
|
|
||||||
|
|
||||||
g_clear_object (&repository);
|
g_clear_object (&repository);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
#include "glib.h"
|
#include "glib.h"
|
||||||
#include "test-common.h"
|
#include "test-common.h"
|
||||||
|
|
||||||
#if defined(G_OS_UNIX)
|
#if defined(G_OS_UNIX) && !defined(__APPLE__)
|
||||||
#include "gio/gdesktopappinfo.h"
|
#include "gio/gdesktopappinfo.h"
|
||||||
#elif defined(G_OS_WIN32)
|
#elif defined(G_OS_WIN32)
|
||||||
#include "gio/gwin32inputstream.h"
|
#include "gio/gwin32inputstream.h"
|
||||||
@ -837,7 +837,7 @@ test_repository_find_by_gtype (RepositoryFixture *fx,
|
|||||||
GType platform_specific_type;
|
GType platform_specific_type;
|
||||||
const char *expected_name, *expected_namespace;
|
const char *expected_name, *expected_namespace;
|
||||||
|
|
||||||
#if defined(G_OS_UNIX)
|
#if defined(G_OS_UNIX) && !(__APPLE__)
|
||||||
platform_specific_type = G_TYPE_DESKTOP_APP_INFO;
|
platform_specific_type = G_TYPE_DESKTOP_APP_INFO;
|
||||||
expected_name = "DesktopAppInfo";
|
expected_name = "DesktopAppInfo";
|
||||||
expected_namespace = "GioUnix";
|
expected_namespace = "GioUnix";
|
||||||
|
Loading…
Reference in New Issue
Block a user