aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mensinger <daniel@mensinger-ka.de>2020-09-09 22:00:19 +0200
committerNirbheek Chauhan <nirbheek.chauhan@gmail.com>2020-09-10 06:41:24 +0000
commit4cef45af21465f4c860dbd467796b1c768f556f4 (patch)
tree37441f17511e0f0f314d146c142def7c7db7d1e9
parent4c2d0eb9bcedefa3ef06a237a0502afbc581268b (diff)
downloadmeson-4cef45af21465f4c860dbd467796b1c768f556f4.zip
meson-4cef45af21465f4c860dbd467796b1c768f556f4.tar.gz
meson-4cef45af21465f4c860dbd467796b1c768f556f4.tar.bz2
cmake: fix shared_module dependency (fixes #7715)
-rw-r--r--mesonbuild/cmake/interpreter.py4
-rw-r--r--test cases/cmake/21 shared module/meson.build13
-rw-r--r--test cases/cmake/21 shared module/prog.c108
-rw-r--r--test cases/cmake/21 shared module/runtime.c19
-rw-r--r--test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt7
-rw-r--r--test cases/cmake/21 shared module/subprojects/cmMod/module/module.c96
-rw-r--r--test cases/cmake/21 shared module/subprojects/cmMod/module/module.h3
7 files changed, 250 insertions, 0 deletions
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index ef353e1..2fdb328 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -1235,6 +1235,10 @@ class CMakeInterpreter:
if tgt_func in ['static_library', 'shared_library']:
dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs))
node_list += [dep_node]
+ elif tgt_func in ['shared_module']:
+ del dep_kwargs['link_with']
+ dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs))
+ node_list += [dep_node]
else:
dep_var = None
diff --git a/test cases/cmake/21 shared module/meson.build b/test cases/cmake/21 shared module/meson.build
new file mode 100644
index 0000000..c6ff957
--- /dev/null
+++ b/test cases/cmake/21 shared module/meson.build
@@ -0,0 +1,13 @@
+project('cmakeSharedModule', ['c', 'cpp'])
+
+cm = import('cmake')
+
+sub_pro = cm.subproject('cmMod')
+sub_dep = sub_pro.dependency('myMod')
+
+dl = meson.get_compiler('c').find_library('dl', required: false)
+
+l = shared_library('runtime', 'runtime.c')
+e = executable('prog', ['prog.c'], link_with: l, dependencies: [sub_dep, dl])
+m = sub_pro.target('myMod')
+test('test1', e, args : m)
diff --git a/test cases/cmake/21 shared module/prog.c b/test cases/cmake/21 shared module/prog.c
new file mode 100644
index 0000000..228a976
--- /dev/null
+++ b/test cases/cmake/21 shared module/prog.c
@@ -0,0 +1,108 @@
+
+#include <stdio.h>
+#include "module.h"
+
+#if SPECIAL_MAGIC_DEFINE != 42
+#error "SPECIAL_MAGIC_DEFINE is not defined"
+#endif
+
+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/test cases/cmake/21 shared module/runtime.c b/test cases/cmake/21 shared module/runtime.c
new file mode 100644
index 0000000..03bde86
--- /dev/null
+++ b/test cases/cmake/21 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/test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt b/test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt
new file mode 100644
index 0000000..d2fcfe3
--- /dev/null
+++ b/test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(cmModule)
+
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/module")
+
+add_library(myMod MODULE "${CMAKE_CURRENT_SOURCE_DIR}/module/module.c")
diff --git a/test cases/cmake/21 shared module/subprojects/cmMod/module/module.c b/test cases/cmake/21 shared module/subprojects/cmMod/module/module.c
new file mode 100644
index 0000000..5dd26d7
--- /dev/null
+++ b/test cases/cmake/21 shared module/subprojects/cmMod/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/test cases/cmake/21 shared module/subprojects/cmMod/module/module.h b/test cases/cmake/21 shared module/subprojects/cmMod/module/module.h
new file mode 100644
index 0000000..e1d9c13
--- /dev/null
+++ b/test cases/cmake/21 shared module/subprojects/cmMod/module/module.h
@@ -0,0 +1,3 @@
+#pragma once
+
+#define SPECIAL_MAGIC_DEFINE 42