summaryrefslogtreecommitdiff
path: root/test cases
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2016-12-07 21:49:16 +0200
committerGitHub <noreply@github.com>2016-12-07 21:49:16 +0200
commitf62f73082178644d25a480d93609e6a8866b5d74 (patch)
tree046780d0d2abf4e09e2c0f1a10e38268ff457246 /test cases
parent344231d336339c0ea4c1eb072ef37ba5e15ff901 (diff)
parentf5a9b3b249efdafacbff1060999c60257c0ff72c (diff)
downloadmeson-f62f73082178644d25a480d93609e6a8866b5d74.tar.gz
Merge pull request #1126 from mesonbuild/sharedmodule
Support for shared modules
Diffstat (limited to 'test cases')
-rw-r--r--test cases/common/125 shared module/meson.build16
-rw-r--r--test cases/common/125 shared module/module.c71
-rw-r--r--test cases/common/125 shared module/prog.c102
-rw-r--r--test cases/common/125 shared module/runtime.c19
4 files changed, 208 insertions, 0 deletions
diff --git a/test cases/common/125 shared module/meson.build b/test cases/common/125 shared module/meson.build
new file mode 100644
index 000000000..ccb9c1a04
--- /dev/null
+++ b/test cases/common/125 shared module/meson.build
@@ -0,0 +1,16 @@
+project('shared module', 'c')
+
+if meson.backend().startswith('vs')
+ error('MESON_SKIP_TEST for some reason /FORCE does not work in the VS backend.')
+endif
+
+dl = meson.get_compiler('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
+m = shared_module('mymodule', 'module.c')
+e = executable('prog', 'prog.c', link_with : l, dependencies : dl)
+test('import test', e, args : [m.full_path()])
+
diff --git a/test cases/common/125 shared module/module.c b/test cases/common/125 shared module/module.c
new file mode 100644
index 000000000..56078c565
--- /dev/null
+++ b/test cases/common/125 shared module/module.c
@@ -0,0 +1,71 @@
+#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
+
+#ifdef _WIN32
+
+#include <stdio.h>
+#include <windows.h>
+#include <tlhelp32.h>
+
+typedef int (*fptr) (void);
+
+/* 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) {
+ printf("Could not get snapshot\n");
+ 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;
+}
+
+int DLL_PUBLIC func() {
+ 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();
+
+int DLL_PUBLIC func(void) {
+ return func_from_language_runtime();
+}
+#endif
diff --git a/test cases/common/125 shared module/prog.c b/test cases/common/125 shared module/prog.c
new file mode 100644
index 000000000..2b638409b
--- /dev/null
+++ b/test cases/common/125 shared module/prog.c
@@ -0,0 +1,102 @@
+
+#include <stdio.h>
+
+int func_from_language_runtime(void);
+typedef int (*fptr) (void);
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+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;
+
+ 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;
+
+ 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/test cases/common/125 shared module/runtime.c b/test cases/common/125 shared module/runtime.c
new file mode 100644
index 000000000..03bde8614
--- /dev/null
+++ b/test cases/common/125 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;
+}