Merge pull request #1955 from jon-turney/exe-implib
Support implibs for executables on Windowspull/2104/head
commit
979efce04a
26 changed files with 253 additions and 111 deletions
@ -0,0 +1,21 @@ |
||||
project('shared module resolving symbol in executable', 'c') |
||||
|
||||
# The shared module contains a reference to the symbol 'func_from_executable', |
||||
# which is always provided by the executable which loads it. This symbol can be |
||||
# resolved at run-time by an ELF loader. But when building PE/COFF objects, all |
||||
# symbols must be resolved at link-time, so an implib is generated for the |
||||
# executable, and the shared module linked with it. |
||||
# |
||||
# See testcase 125 for an example of the more complex portability gymnastics |
||||
# required if we do not know (at link-time) what provides the symbol. |
||||
|
||||
link_flags = [] |
||||
if host_machine.system() != 'windows' |
||||
# Needed to export dynamic symbols from the executable |
||||
link_flags += ['-rdynamic'] |
||||
endif |
||||
|
||||
dl = meson.get_compiler('c').find_library('dl', required: false) |
||||
e = executable('prog', 'prog.c', dependencies: dl, implib: true, link_args: link_flags) |
||||
m = shared_module('module', 'module.c', link_with: e) |
||||
test('test', e, args: m.full_path()) |
@ -0,0 +1,16 @@ |
||||
#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 |
||||
|
||||
extern int func_from_executable(void); |
||||
|
||||
int DLL_PUBLIC func(void) { |
||||
return func_from_executable(); |
||||
} |
@ -0,0 +1,60 @@ |
||||
#include <stdio.h> |
||||
#include <assert.h> |
||||
#ifdef _WIN32 |
||||
#include <windows.h> |
||||
#else |
||||
#include <dlfcn.h> |
||||
#endif |
||||
|
||||
#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 |
||||
|
||||
typedef int (*fptr) (void); |
||||
|
||||
int DLL_PUBLIC |
||||
func_from_executable(void) |
||||
{ |
||||
return 42; |
||||
} |
||||
|
||||
int |
||||
main (int argc, char **argv) |
||||
{ |
||||
int expected, actual; |
||||
fptr importedfunc; |
||||
|
||||
#ifdef _WIN32 |
||||
HMODULE h = LoadLibraryA(argv[1]); |
||||
#else |
||||
void *h = dlopen(argv[1], RTLD_NOW); |
||||
#endif |
||||
assert(h != NULL); |
||||
|
||||
#ifdef _WIN32 |
||||
importedfunc = (fptr) GetProcAddress (h, "func"); |
||||
#else |
||||
importedfunc = (fptr) dlsym(h, "func"); |
||||
#endif |
||||
assert(importedfunc != NULL); |
||||
assert(importedfunc != func_from_executable); |
||||
|
||||
actual = (*importedfunc)(); |
||||
expected = func_from_executable(); |
||||
assert(actual == expected); |
||||
|
||||
#ifdef _WIN32 |
||||
FreeLibrary(h); |
||||
#else |
||||
dlclose(h); |
||||
#endif |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,4 @@ |
||||
project('link with exe', 'c') |
||||
|
||||
e = executable('prog', 'prog.c') |
||||
m = shared_module('module', 'module.c', link_with: e) |
@ -0,0 +1,4 @@ |
||||
|
||||
int func(void) { |
||||
return 42; |
||||
} |
@ -0,0 +1,5 @@ |
||||
int |
||||
main (int argc, char **argv) |
||||
{ |
||||
return 0; |
||||
} |
@ -0,0 +1,8 @@ |
||||
usr/bin/prog.exe |
||||
usr/bin/prog.pdb |
||||
usr/bin/prog2.exe |
||||
usr/bin/prog2.pdb |
||||
?gcc:usr/lib/libprog.exe.a |
||||
?gcc:usr/lib/libburble.a |
||||
?msvc:usr/lib/prog.exe.lib |
||||
?msvc:usr/lib/burble.lib |
@ -0,0 +1,7 @@ |
||||
project('wintest', 'c') |
||||
|
||||
# Test that we can produce an implib for an executable on Windows, and that it's |
||||
# name can be set, and that it is installed along with the executable |
||||
|
||||
executable('prog', 'prog.c', install: true, implib: true) |
||||
executable('prog2', 'prog.c', install: true, implib: 'burble') |
@ -0,0 +1,6 @@ |
||||
#include <windows.h> |
||||
|
||||
int __declspec(dllexport) |
||||
main(int argc, char **argv) { |
||||
return 0; |
||||
} |
@ -1,11 +0,0 @@ |
||||
usr/bin/?libsome-0.dll |
||||
usr/lib/libsome.dll.a |
||||
usr/bin/?libnoversion.dll |
||||
usr/lib/libnoversion.dll.a |
||||
usr/bin/?libonlyversion-1.dll |
||||
usr/lib/libonlyversion.dll.a |
||||
usr/bin/?libonlysoversion-5.dll |
||||
usr/lib/libonlysoversion.dll.a |
||||
usr/libexec/?libcustomdir.dll |
||||
usr/libexec/libcustomdir.dll.a |
||||
usr/lib/?libmodule.dll |
@ -1,55 +0,0 @@ |
||||
project('mingw dll versioning', 'c') |
||||
|
||||
cc = meson.get_compiler('c') |
||||
|
||||
if cc.get_id() == 'msvc' |
||||
error('MESON_SKIP_TEST: test is only for MinGW') |
||||
endif |
||||
|
||||
# Test that MinGW/GCC creates correctly-named dll files and dll.a files, |
||||
# and also installs them in the right place |
||||
some = shared_library('some', 'lib.c', |
||||
version : '1.2.3', |
||||
soversion : '0', |
||||
install : true) |
||||
|
||||
noversion = shared_library('noversion', 'lib.c', |
||||
install : true) |
||||
|
||||
onlyversion = shared_library('onlyversion', 'lib.c', |
||||
version : '1.4.5', |
||||
install : true) |
||||
|
||||
onlysoversion = shared_library('onlysoversion', 'lib.c', |
||||
# Also test that int soversion is acceptable |
||||
soversion : 5, |
||||
install : true) |
||||
|
||||
# Hack to make the executables below depend on the shared libraries above |
||||
# without actually adding them as `link_with` dependencies since we want to try |
||||
# linking to them with -lfoo linker arguments. |
||||
out = custom_target('library-dependency-hack', |
||||
input : 'exe.orig.c', |
||||
output : 'exe.c', |
||||
depends : [some, noversion, onlyversion, onlysoversion], |
||||
command : ['cp', '@INPUT@', '@OUTPUT@']) |
||||
|
||||
# Manually test if the linker can find the above libraries |
||||
# i.e., whether they were generated with the right naming scheme |
||||
test('manually linked 1', executable('manuallink1', out, |
||||
link_args : ['-L.', '-lsome'])) |
||||
|
||||
test('manually linked 2', executable('manuallink2', out, |
||||
link_args : ['-L.', '-lnoversion'])) |
||||
|
||||
test('manually linked 3', executable('manuallink3', out, |
||||
link_args : ['-L.', '-lonlyversion'])) |
||||
|
||||
test('manually linked 4', executable('manuallink4', out, |
||||
link_args : ['-L.', '-lonlysoversion'])) |
||||
|
||||
shared_library('customdir', 'lib.c', |
||||
install : true, |
||||
install_dir : get_option('libexecdir')) |
||||
|
||||
shared_module('module', 'lib.c', install : true) |
@ -0,0 +1,24 @@ |
||||
?msvc:usr/bin/some-0.dll |
||||
?msvc:usr/bin/some-0.pdb |
||||
?msvc:usr/lib/some.lib |
||||
?msvc:usr/bin/noversion.dll |
||||
?msvc:usr/bin/noversion.pdb |
||||
?msvc:usr/lib/noversion.lib |
||||
?msvc:usr/bin/onlyversion-1.dll |
||||
?msvc:usr/lib/onlyversion.lib |
||||
?msvc:usr/bin/onlysoversion-5.dll |
||||
?msvc:usr/lib/onlysoversion.lib |
||||
?msvc:usr/libexec/customdir.dll |
||||
?msvc:usr/libexec/customdir.lib |
||||
?msvc:usr/lib/module.dll |
||||
?gcc:usr/bin/?libsome-0.dll |
||||
?gcc:usr/lib/libsome.dll.a |
||||
?gcc:usr/bin/?libnoversion.dll |
||||
?gcc:usr/lib/libnoversion.dll.a |
||||
?gcc:usr/bin/?libonlyversion-1.dll |
||||
?gcc:usr/lib/libonlyversion.dll.a |
||||
?gcc:usr/bin/?libonlysoversion-5.dll |
||||
?gcc:usr/lib/libonlysoversion.dll.a |
||||
?gcc:usr/libexec/?libcustomdir.dll |
||||
?gcc:usr/libexec/libcustomdir.dll.a |
||||
?gcc:usr/lib/?libmodule.dll |
@ -1,9 +0,0 @@ |
||||
int myFunc (void); |
||||
|
||||
int |
||||
main (int argc, char *argv[]) |
||||
{ |
||||
if (myFunc() == 55) |
||||
return 0; |
||||
return 1; |
||||
} |
@ -1,13 +0,0 @@ |
||||
usr/bin/some-0.dll |
||||
usr/bin/some-0.pdb |
||||
usr/lib/some.lib |
||||
usr/bin/noversion.dll |
||||
usr/bin/noversion.pdb |
||||
usr/lib/noversion.lib |
||||
usr/bin/onlyversion-1.dll |
||||
usr/lib/onlyversion.lib |
||||
usr/bin/onlysoversion-5.dll |
||||
usr/lib/onlysoversion.lib |
||||
usr/libexec/customdir.dll |
||||
usr/libexec/customdir.lib |
||||
usr/lib/module.dll |
@ -1,6 +0,0 @@ |
||||
#ifdef _WIN32 |
||||
__declspec(dllexport) |
||||
#endif |
||||
int myFunc() { |
||||
return 55; |
||||
} |
Loading…
Reference in new issue