aboutsummaryrefslogtreecommitdiffstats
path: root/meson/test cases/common/117 shared module
diff options
context:
space:
mode:
Diffstat (limited to 'meson/test cases/common/117 shared module')
-rw-r--r--meson/test cases/common/117 shared module/meson.build40
-rw-r--r--meson/test cases/common/117 shared module/module.c96
-rw-r--r--meson/test cases/common/117 shared module/nosyms.c4
-rw-r--r--meson/test cases/common/117 shared module/prog.c103
-rw-r--r--meson/test cases/common/117 shared module/runtime.c19
-rw-r--r--meson/test cases/common/117 shared module/test.json7
6 files changed, 269 insertions, 0 deletions
diff --git a/meson/test cases/common/117 shared module/meson.build b/meson/test cases/common/117 shared module/meson.build
new file mode 100644
index 000000000..936c8396f
--- /dev/null
+++ b/meson/test cases/common/117 shared module/meson.build
@@ -0,0 +1,40 @@
+project('shared module', 'c')
+
+c = meson.get_compiler('c')
+
+# Windows UWP doesn't support the ToolHelp API we use in this test to emulate
+# runtime symbol resolution.
+if host_machine.system() == 'windows'
+ if not c.compiles('''
+#include <windows.h>
+#include <tlhelp32.h>
+
+HANDLE func(void)
+{
+ return CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
+}
+''')
+ error('MESON_SKIP_TEST Windows UWP does not support this test.')
+ endif
+endif
+
+dl = c.find_library('dl', required : false)
+l = shared_library('runtime', 'runtime.c')
+# Do NOT link the module with the runtime library. This
+# is a common approach for plugins that are only used
+# with dlopen. Any symbols are resolved dynamically
+# at runtime. This requires extra help on Windows, so
+# should be avoided unless really necessary.
+m = shared_module('mymodule', 'module.c')
+e = executable('prog', 'prog.c',
+ link_with : l, export_dynamic : true, dependencies : dl)
+test('import test', e, args : m)
+
+# Same as above, but module created with build_target()
+m2 = build_target('mymodule2', 'module.c', target_type: 'shared_module')
+test('import test 2', e, args : m2)
+
+# Shared module that does not export any symbols
+shared_module('nosyms', 'nosyms.c',
+ install : true,
+ install_dir : join_paths(get_option('libdir'), 'modules'))
diff --git a/meson/test cases/common/117 shared module/module.c b/meson/test cases/common/117 shared module/module.c
new file mode 100644
index 000000000..5dd26d7ef
--- /dev/null
+++ b/meson/test cases/common/117 shared module/module.c
@@ -0,0 +1,96 @@
+#if defined _WIN32 || defined __CYGWIN__
+ #define DLL_PUBLIC __declspec(dllexport)
+#else
+ #if defined __GNUC__
+ #define DLL_PUBLIC __attribute__ ((visibility("default")))
+ #else
+ #pragma message ("Compiler does not support symbol visibility.")
+ #define DLL_PUBLIC
+ #endif
+#endif
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+
+#include <stdio.h>
+
+typedef int (*fptr) (void);
+
+#ifdef __CYGWIN__
+
+#include <dlfcn.h>
+
+fptr find_any_f (const char *name) {
+ return (fptr) dlsym(RTLD_DEFAULT, name);
+}
+#else /* _WIN32 */
+
+#include <windows.h>
+#include <tlhelp32.h>
+
+static wchar_t*
+win32_get_last_error (void)
+{
+ wchar_t *msg = NULL;
+
+ FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_IGNORE_INSERTS
+ | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError (), 0,
+ (LPWSTR) &msg, 0, NULL);
+ return msg;
+}
+
+/* Unlike Linux and OS X, when a library is loaded, all the symbols aren't
+ * loaded into a single namespace. You must fetch the symbol by iterating over
+ * all loaded modules. Code for finding the function from any of the loaded
+ * modules is taken from gmodule.c in glib */
+fptr find_any_f (const char *name) {
+ fptr f;
+ HANDLE snapshot;
+ MODULEENTRY32 me32;
+
+ snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
+ if (snapshot == (HANDLE) -1) {
+ wchar_t *msg = win32_get_last_error();
+ printf("Could not get snapshot: %S\n", msg);
+ return 0;
+ }
+
+ me32.dwSize = sizeof (me32);
+
+ f = NULL;
+ if (Module32First (snapshot, &me32)) {
+ do {
+ if ((f = (fptr) GetProcAddress (me32.hModule, name)) != NULL)
+ break;
+ } while (Module32Next (snapshot, &me32));
+ }
+
+ CloseHandle (snapshot);
+ return f;
+}
+#endif
+
+int DLL_PUBLIC func(void) {
+ fptr f;
+
+ f = find_any_f ("func_from_language_runtime");
+ if (f != NULL)
+ return f();
+ printf ("Could not find function\n");
+ return 1;
+}
+
+#else
+/*
+ * Shared modules often have references to symbols that are not defined
+ * at link time, but which will be provided from deps of the executable that
+ * dlopens it. We need to make sure that this works, i.e. that we do
+ * not pass -Wl,--no-undefined when linking modules.
+ */
+int func_from_language_runtime(void);
+
+int DLL_PUBLIC func(void) {
+ return func_from_language_runtime();
+}
+#endif
diff --git a/meson/test cases/common/117 shared module/nosyms.c b/meson/test cases/common/117 shared module/nosyms.c
new file mode 100644
index 000000000..3432b1c46
--- /dev/null
+++ b/meson/test cases/common/117 shared module/nosyms.c
@@ -0,0 +1,4 @@
+static int
+func_not_exported (void) {
+ return 99;
+}
diff --git a/meson/test cases/common/117 shared module/prog.c b/meson/test cases/common/117 shared module/prog.c
new file mode 100644
index 000000000..47411856d
--- /dev/null
+++ b/meson/test cases/common/117 shared module/prog.c
@@ -0,0 +1,103 @@
+
+#include <stdio.h>
+
+int func_from_language_runtime(void);
+typedef int (*fptr) (void);
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+static wchar_t*
+win32_get_last_error (void)
+{
+ wchar_t *msg = NULL;
+
+ FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_IGNORE_INSERTS
+ | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError (), 0,
+ (LPWSTR) &msg, 0, NULL);
+ return msg;
+}
+
+int main(int argc, char **argv)
+{
+ HINSTANCE handle;
+ fptr importedfunc;
+ int expected, actual;
+ int ret = 1;
+ if(argc==0) {};
+
+ handle = LoadLibraryA (argv[1]);
+ if (!handle) {
+ wchar_t *msg = win32_get_last_error ();
+ printf ("Could not open %s: %S\n", argv[1], msg);
+ goto nohandle;
+ }
+
+ importedfunc = (fptr) GetProcAddress (handle, "func");
+ if (importedfunc == NULL) {
+ wchar_t *msg = win32_get_last_error ();
+ printf ("Could not find 'func': %S\n", msg);
+ goto out;
+ }
+
+ actual = importedfunc ();
+ expected = func_from_language_runtime ();
+ if (actual != expected) {
+ printf ("Got %i instead of %i\n", actual, expected);
+ goto out;
+ }
+
+ ret = 0;
+out:
+ FreeLibrary (handle);
+nohandle:
+ return ret;
+}
+
+#else
+
+#include<dlfcn.h>
+#include<assert.h>
+
+int main(int argc, char **argv) {
+ void *dl;
+ fptr importedfunc;
+ int expected, actual;
+ char *error;
+ int ret = 1;
+ if(argc==0) {};
+
+ dlerror();
+ dl = dlopen(argv[1], RTLD_LAZY);
+ error = dlerror();
+ if(error) {
+ printf("Could not open %s: %s\n", argv[1], error);
+ goto nodl;
+ }
+
+ importedfunc = (fptr) dlsym(dl, "func");
+ if (importedfunc == NULL) {
+ printf ("Could not find 'func'\n");
+ goto out;
+ }
+
+ assert(importedfunc != func_from_language_runtime);
+
+ actual = (*importedfunc)();
+ expected = func_from_language_runtime ();
+ if (actual != expected) {
+ printf ("Got %i instead of %i\n", actual, expected);
+ goto out;
+ }
+
+ ret = 0;
+out:
+ dlclose(dl);
+nodl:
+ return ret;
+}
+
+#endif
diff --git a/meson/test cases/common/117 shared module/runtime.c b/meson/test cases/common/117 shared module/runtime.c
new file mode 100644
index 000000000..03bde8614
--- /dev/null
+++ b/meson/test cases/common/117 shared module/runtime.c
@@ -0,0 +1,19 @@
+#if defined _WIN32 || defined __CYGWIN__
+ #define DLL_PUBLIC __declspec(dllexport)
+#else
+ #if defined __GNUC__
+ #define DLL_PUBLIC __attribute__ ((visibility("default")))
+ #else
+ #pragma message ("Compiler does not support symbol visibility.")
+ #define DLL_PUBLIC
+ #endif
+#endif
+
+/*
+ * This file pretends to be a language runtime that supports extension
+ * modules.
+ */
+
+int DLL_PUBLIC func_from_language_runtime(void) {
+ return 86;
+}
diff --git a/meson/test cases/common/117 shared module/test.json b/meson/test cases/common/117 shared module/test.json
new file mode 100644
index 000000000..33bfeff07
--- /dev/null
+++ b/meson/test cases/common/117 shared module/test.json
@@ -0,0 +1,7 @@
+{
+ "installed": [
+ {"type": "expr", "file": "usr/lib/modules/libnosyms?so"},
+ {"type": "implibempty", "file": "usr/lib/modules/libnosyms"},
+ {"type": "pdb", "file": "usr/lib/modules/nosyms"}
+ ]
+}