cmake: fix shared_module dependency (fixes #7715)
parent
4c2d0eb9bc
commit
4cef45af21
7 changed files with 250 additions and 0 deletions
@ -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) |
@ -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 |
@ -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; |
||||||
|
} |
@ -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") |
@ -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 |
@ -0,0 +1,3 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#define SPECIAL_MAGIC_DEFINE 42 |
Loading…
Reference in new issue