From 6d84b9b6468eca57763895efe51347047ca3088d Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Fri, 2 Dec 2016 21:55:56 +0200 Subject: Created new shared module build target type, and make sure -Wl,--no-undefined is not used when linking it. --- mesonbuild/backend/ninjabackend.py | 3 ++- mesonbuild/build.py | 10 ++++++++++ mesonbuild/compilers.py | 4 ++-- mesonbuild/interpreter.py | 10 ++++++++++ test cases/common/125 shared module/meson.build | 4 ++++ test cases/common/125 shared module/module.c | 22 ++++++++++++++++++++++ 6 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 test cases/common/125 shared module/meson.build create mode 100644 test cases/common/125 shared module/module.c diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 659a53d..6e2b1ee 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1927,7 +1927,8 @@ rule FORTRAN_DEP_HACK commands += linker.get_linker_always_args() if not isinstance(target, build.StaticLibrary): commands += compilers.get_base_link_args(self.environment.coredata.base_options, - linker) + linker, + isinstance(target, build.SharedModule)) commands += linker.get_buildtype_linker_args(self.environment.coredata.get_builtin_option('buildtype')) commands += linker.get_option_link_args(self.environment.coredata.compiler_options) commands += self.get_link_debugfile_args(linker, target, outname) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 39e215f..b5ca5aa 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1129,6 +1129,16 @@ class SharedLibrary(BuildTarget): def type_suffix(self): return "@sha" +# A shared library that is meant to be used with dlopen rather than linking +# into something else. +class SharedModule(SharedLibrary): + def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): + if 'version' in kwargs: + raise MesonException('Shared modules must not specify the version kwarg.') + if 'soversion' in kwargs: + raise MesonException('Shared modules must not specify the soversion kwarg.') + super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) + class CustomTarget: known_kwargs = {'input' : True, 'output' : True, diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 8f8851f..c603f37 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -248,7 +248,7 @@ def get_base_compile_args(options, compiler): pass return args -def get_base_link_args(options, linker): +def get_base_link_args(options, linker, is_shared_module): args = [] # FIXME, gcc/clang specific. try: @@ -269,7 +269,7 @@ def get_base_link_args(options, linker): except KeyError: pass try: - if options['b_lundef'].value: + if not is_shared_module and options['b_lundef'].value: args.append('-Wl,--no-undefined') except KeyError: pass diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index ef99511..fefc1ff 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -586,6 +586,10 @@ class SharedLibraryHolder(BuildTargetHolder): def __init__(self, target, interp): super().__init__(target, interp) +class SharedModuleHolder(BuildTargetHolder): + def __init__(self, target, interp): + super().__init__(target, interp) + class JarHolder(BuildTargetHolder): def __init__(self, target, interp): super().__init__(target, interp) @@ -1203,6 +1207,7 @@ class Interpreter(): 'dependency' : self.func_dependency, 'static_library' : self.func_static_lib, 'shared_library' : self.func_shared_lib, + 'shared_module' : self.func_shared_module, 'library' : self.func_library, 'jar' : self.func_jar, 'build_target': self.func_build_target, @@ -1961,6 +1966,9 @@ requirements use the version keyword argument instead.''') def func_shared_lib(self, node, args, kwargs): return self.build_target(node, args, kwargs, SharedLibraryHolder) + def func_shared_module(self, node, args, kwargs): + return self.build_target(node, args, kwargs, SharedModuleHolder) + def func_library(self, node, args, kwargs): if self.coredata.get_builtin_option('default_library') == 'shared': return self.func_shared_lib(node, args, kwargs) @@ -2448,6 +2456,8 @@ requirements use the version keyword argument instead.''') targetclass = build.Executable elif targetholder is SharedLibraryHolder: targetclass = build.SharedLibrary + elif targetholder is SharedModuleHolder: + targetclass = build.SharedModule elif targetholder is StaticLibraryHolder: targetclass = build.StaticLibrary elif targetholder is JarHolder: 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 0000000..70e954b --- /dev/null +++ b/test cases/common/125 shared module/meson.build @@ -0,0 +1,4 @@ +project('shared module', 'c') + +shared_module('mymodule', 'module.c') + 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 0000000..be0720d --- /dev/null +++ b/test cases/common/125 shared module/module.c @@ -0,0 +1,22 @@ +#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 + +/* + * Shared modules often have references to symbols that are not defined + * at link time, but which will be provided by 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 nonexisting_function(); + +int DLL_PUBLIC func() { + return nonexisting_function(); +} -- cgit v1.1 From 04a2e6ded33057adb7f93ef8f75df5d081411e3f Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Fri, 2 Dec 2016 22:26:50 +0200 Subject: Do not use -install_name or -shared when building modules on OSX, but do use -bundle. Closes #1112. --- mesonbuild/backend/ninjabackend.py | 8 ++++++-- mesonbuild/compilers.py | 39 ++++++++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 6e2b1ee..e5c430e 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1937,13 +1937,17 @@ rule FORTRAN_DEP_HACK if isinstance(target, build.Executable): commands += linker.get_std_exe_link_args() elif isinstance(target, build.SharedLibrary): - commands += linker.get_std_shared_lib_link_args() + if isinstance(target, build.SharedModule): + commands += linker.get_std_shared_module_link_args() + else: + commands += linker.get_std_shared_lib_link_args() commands += linker.get_pic_args() if hasattr(target, 'soversion'): soversion = target.soversion else: soversion = None - commands += linker.get_soname_args(target.prefix, target.name, target.suffix, abspath, soversion) + commands += linker.get_soname_args(target.prefix, target.name, target.suffix, + abspath, soversion, isinstance(target, build.SharedModule)) # This is only visited when using the Visual Studio toolchain if target.vs_module_defs and hasattr(linker, 'gen_vs_module_defs_args'): commands += linker.gen_vs_module_defs_args(target.vs_module_defs.rel_to_builddir(self.build_to_src)) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index c603f37..e012c55 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -486,6 +486,12 @@ class Compiler(): def get_link_debugfile_args(self, rel_obj): return [] + def get_std_shared_lib_link_args(self): + return [] + + def get_std_shared_module_link_args(self): + return self.get_std_shared_lib_link_args() + class CCompiler(Compiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None): # If a child ObjC or CPP class has already set it, don't set it ourselves @@ -1178,9 +1184,6 @@ class MonoCompiler(Compiler): def get_include_args(self, path): return [] - def get_std_shared_lib_link_args(self): - return [] - def get_pic_args(self): return [] @@ -1267,9 +1270,6 @@ class JavaCompiler(Compiler): def get_include_args(self, path): return [] - def get_std_shared_lib_link_args(self): - return [] - def get_pic_args(self): return [] @@ -1962,7 +1962,7 @@ CLANG_OSX = 1 CLANG_WIN = 2 # Possibly clang-cl? -def get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, path, soversion): +def get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module): if soversion is None: sostr = '' else: @@ -1972,6 +1972,8 @@ def get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, path, soversion): return ['-Wl,-soname,%s%s.%s%s' % (prefix, shlib_name, suffix, sostr)] return ['-Wl,-soname,%s%s' % (shlib_name, sostr)] elif gcc_type == GCC_OSX: + if is_shared_module: + return [] return ['-install_name', os.path.join(path, 'lib' + shlib_name + '.dylib')] else: raise RuntimeError('Not implemented yet.') @@ -2007,7 +2009,7 @@ class GnuCompiler: def get_define(self, define): if define in self.defines: - return defines[define] + return self.defines[define] def get_pic_args(self): if self.gcc_type in (GCC_MINGW, GCC_OSX): @@ -2029,8 +2031,13 @@ class GnuCompiler: def split_shlib_to_parts(self, fname): return (os.path.split(fname)[0], fname) - def get_soname_args(self, prefix, shlib_name, suffix, path, soversion): - return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion) + def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): + return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module) + + def get_std_shared_lib_link_args(self): + if self.gcc_type == GCC_OSX: + return ['-bundle'] + return ['-shared'] class GnuCCompiler(GnuCompiler, CCompiler): def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None): @@ -2066,6 +2073,9 @@ class GnuCCompiler(GnuCompiler, CCompiler): return options['c_winlibs'].value[:] return [] + def get_std_shared_lib_link_args(self): + return ['-shared'] + class GnuCPPCompiler(GnuCompiler, CPPCompiler): def __init__(self, exelist, version, gcc_type, is_cross, exe_wrap, defines): @@ -2193,6 +2203,11 @@ class ClangCompiler(): extra_args.append('-Wl,-no_weak_imports') return super().has_function(funcname, prefix, env, extra_args, dependencies) + def get_std_shared_module_link_args(self): + if self.clang_type == CLANG_OSX: + return ['-bundle'] + return ['-shared'] + class ClangCCompiler(ClangCompiler, CCompiler): def __init__(self, exelist, version, clang_type, is_cross, exe_wrapper=None): CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) @@ -2317,8 +2332,8 @@ end program prog def split_shlib_to_parts(self, fname): return (os.path.split(fname)[0], fname) - def get_soname_args(self, prefix, shlib_name, suffix, path, soversion): - return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion) + def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): + return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module) def get_dependency_gen_args(self, outtarget, outfile): # Disabled until this is fixed: -- cgit v1.1 From 023dc6953c6dda3825c7c04b465cee507f1ddcd9 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Fri, 2 Dec 2016 22:48:00 +0200 Subject: Arg fix. --- mesonbuild/compilers.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index e012c55..06f4f93 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -532,7 +532,7 @@ class CCompiler(Compiler): # Almost every compiler uses this for disabling warnings return ['-w'] - def get_soname_args(self, prefix, shlib_name, suffix, path, soversion): + def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): return [] def split_shlib_to_parts(self, fname): @@ -1148,7 +1148,7 @@ class MonoCompiler(Compiler): def get_link_args(self, fname): return ['-r:' + fname] - def get_soname_args(self, prefix, shlib_name, suffix, path, soversion): + def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): return [] def get_werror_args(self): @@ -1229,7 +1229,7 @@ class JavaCompiler(Compiler): self.id = 'unknown' self.javarunner = 'java' - def get_soname_args(self, prefix, shlib_name, suffix, path, soversion): + def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): return [] def get_werror_args(self): @@ -1528,7 +1528,7 @@ class DCompiler(Compiler): def get_std_shared_lib_link_args(self): return ['-shared'] - def get_soname_args(self, prefix, shlib_name, suffix, path, soversion): + def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): return [] def get_unittest_args(self): @@ -2178,7 +2178,7 @@ class ClangCompiler(): # so it might change semantics at any time. return ['-include-pch', os.path.join (pch_dir, self.get_pch_name (header))] - def get_soname_args(self, prefix, shlib_name, suffix, path, soversion): + def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): if self.clang_type == CLANG_STANDARD: gcc_type = GCC_STANDARD elif self.clang_type == CLANG_OSX: @@ -2187,7 +2187,7 @@ class ClangCompiler(): gcc_type = GCC_MINGW else: raise MesonException('Unreachable code when converting clang type to gcc type.') - return get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, path, soversion) + return get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module) def has_argument(self, arg, env): return super().has_argument(['-Werror=unknown-warning-option', arg], env) -- cgit v1.1 From 2dd7f3cb4762df06b43017b25c6c3b5eafec44c4 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sat, 3 Dec 2016 00:38:37 +0200 Subject: Tell msvc not to error out on missing symbols. --- mesonbuild/compilers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 06f4f93..3dc4340 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -1926,6 +1926,9 @@ class VisualStudioCCompiler(CCompiler): pdbarr += ['pdb'] return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)] + def get_std_shared_module_link_args(self): + return ['/DLL', '/FORCE:UNRESOLVED'] + class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): def __init__(self, exelist, version, is_cross, exe_wrap): self.language = 'cpp' -- cgit v1.1 From 49e0676ba932c3b4b9f7de290afc6d7b0d2d6b4c Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sat, 3 Dec 2016 01:11:07 +0200 Subject: Add a test that tests the module and symbol resolution with dlopen. --- test cases/common/125 shared module/meson.build | 6 +++- test cases/common/125 shared module/module.c | 6 ++-- test cases/common/125 shared module/prog.c | 38 +++++++++++++++++++++++++ test cases/common/125 shared module/runtime.c | 19 +++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 test cases/common/125 shared module/prog.c create mode 100644 test cases/common/125 shared module/runtime.c diff --git a/test cases/common/125 shared module/meson.build b/test cases/common/125 shared module/meson.build index 70e954b..5ca50c5 100644 --- a/test cases/common/125 shared module/meson.build +++ b/test cases/common/125 shared module/meson.build @@ -1,4 +1,8 @@ project('shared module', 'c') -shared_module('mymodule', 'module.c') +dl = meson.get_compiler('c').find_library('dl', required : false) +l = shared_library('runtime', 'runtime.c') +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 index be0720d..ed2712c 100644 --- a/test cases/common/125 shared module/module.c +++ b/test cases/common/125 shared module/module.c @@ -11,12 +11,12 @@ /* * Shared modules often have references to symbols that are not defined - * at link time, but which will be provided by the executable that + * 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 nonexisting_function(); +int func_from_language_runtime(); int DLL_PUBLIC func() { - return nonexisting_function(); + return func_from_language_runtime(); } 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 0000000..8397034 --- /dev/null +++ b/test cases/common/125 shared module/prog.c @@ -0,0 +1,38 @@ +#ifdef _WIN32 +// FIXME: add implementation using Winapi functions for dlopen. + +int main(int argc, char **argv) { + return 0; +} + +#else + +#include +#include +#include + +int func(); +int func_from_language_runtime(); + +int main(int argc, char **argv) { + void *dl; + int (*importedfunc)(); + int success; + char *error; + + dlerror(); + dl = dlopen(argv[1], RTLD_LAZY); + error = dlerror(); + if(error) { + printf("Could not open %s: %s\n", argv[1], error); + return 1; + } + importedfunc = (int (*)()) dlsym(dl, "func"); + assert(importedfunc); + assert(importedfunc != func_from_language_runtime); + success = (*importedfunc)() == func_from_language_runtime(); + dlclose(dl); + return !success; +} + +#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 0000000..f701171 --- /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 func_from_language_runtime() { + return 86; +} -- cgit v1.1 From a5dcb89410973f4bfa872cd58616272355638963 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sat, 3 Dec 2016 16:11:34 +0200 Subject: Link against runtime on OSX and Windows because they seem to insist on all symbols being present. --- test cases/common/125 shared module/meson.build | 13 ++++++++++++- test cases/common/125 shared module/runtime.c | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/test cases/common/125 shared module/meson.build b/test cases/common/125 shared module/meson.build index 5ca50c5..44abf55 100644 --- a/test cases/common/125 shared module/meson.build +++ b/test cases/common/125 shared module/meson.build @@ -2,7 +2,18 @@ project('shared module', 'c') dl = meson.get_compiler('c').find_library('dl', required : false) l = shared_library('runtime', 'runtime.c') -m = shared_module('mymodule', 'module.c') +if host_machine.system() == 'darwin' or host_machine.system() == 'windows' + # At least in OSX and seemingly also on Windows you must have + # all symbols present when linking a module. + # + # In Linux many projects build plugins without linking to + # the runtime so they have undefined symbols. We need to support + # both for ease of transitioning. + mlink = [l] +else + mlink = [] +endif +m = shared_module('mymodule', 'module.c', link_with : mlink) 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/runtime.c b/test cases/common/125 shared module/runtime.c index f701171..68c813a 100644 --- a/test cases/common/125 shared module/runtime.c +++ b/test cases/common/125 shared module/runtime.c @@ -14,6 +14,6 @@ * modules. */ -int func_from_language_runtime() { +int DLL_PUBLIC func_from_language_runtime() { return 86; } -- cgit v1.1 From b54fc1d00e5488e4dcc31f8f1a9f37226819ba24 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 4 Dec 2016 20:15:06 +0200 Subject: Apply magical flags to make OSX ignore missing symbols in plugins. --- mesonbuild/compilers.py | 2 +- test cases/common/125 shared module/meson.build | 17 +++++------------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 3dc4340..63117e8 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -2208,7 +2208,7 @@ class ClangCompiler(): def get_std_shared_module_link_args(self): if self.clang_type == CLANG_OSX: - return ['-bundle'] + return ['-bundle', '-Wl,-undefined,dynamic_lookup'] return ['-shared'] class ClangCCompiler(ClangCompiler, CCompiler): diff --git a/test cases/common/125 shared module/meson.build b/test cases/common/125 shared module/meson.build index 44abf55..6fd21c2 100644 --- a/test cases/common/125 shared module/meson.build +++ b/test cases/common/125 shared module/meson.build @@ -2,18 +2,11 @@ project('shared module', 'c') dl = meson.get_compiler('c').find_library('dl', required : false) l = shared_library('runtime', 'runtime.c') -if host_machine.system() == 'darwin' or host_machine.system() == 'windows' - # At least in OSX and seemingly also on Windows you must have - # all symbols present when linking a module. - # - # In Linux many projects build plugins without linking to - # the runtime so they have undefined symbols. We need to support - # both for ease of transitioning. - mlink = [l] -else - mlink = [] -endif -m = shared_module('mymodule', 'module.c', link_with : mlink) +# 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()]) -- cgit v1.1 From 59fdb1b9ff89e0d5d7073a05f59f161e286975a7 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Tue, 6 Dec 2016 19:44:05 +0200 Subject: Add unresolved symbol arg to link line in VS backends. For some reason VS does not pick it up even though it is visible in the linker option box. --- mesonbuild/backend/vs2010backend.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 15bebba..5be780c 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -783,6 +783,8 @@ class Vs2010Backend(backends.Backend): extra_link_args += l if not isinstance(target, build.StaticLibrary): extra_link_args += target.link_args + if isinstance(target, build.SharedModule): + extra_link_args += compiler.get_std_shared_module_link_args() # External deps must be last because target link libraries may depend on them. for dep in target.get_external_deps(): extra_link_args += dep.get_link_args() -- cgit v1.1 From dc1f537fb364833697406e7eb26f9a59d5d1d105 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Wed, 7 Dec 2016 00:30:28 +0200 Subject: Skip shared module test on VS because it fails for some reason nobody understands. --- mesonbuild/backend/ninjabackend.py | 1 + mesonbuild/backend/vs2010backend.py | 1 + mesonbuild/backend/vs2015backend.py | 1 + mesonbuild/backend/xcodebackend.py | 1 + mesonbuild/interpreter.py | 4 ++++ test cases/common/125 shared module/meson.build | 4 ++++ 6 files changed, 12 insertions(+) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index e5c430e..4792e96 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -139,6 +139,7 @@ class NinjaBackend(backends.Backend): def __init__(self, build): super().__init__(build) + self.name = 'ninja' self.ninja_filename = 'build.ninja' self.fortran_deps = {} self.all_outputs = {} diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 5be780c..eb62bd1 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -58,6 +58,7 @@ class RegenInfo(): class Vs2010Backend(backends.Backend): def __init__(self, build): super().__init__(build) + self.name = 'vs2010' self.project_file_version = '10.0.30319.1' self.sources_conflicts = {} self.platform_toolset = None diff --git a/mesonbuild/backend/vs2015backend.py b/mesonbuild/backend/vs2015backend.py index 8d4ff45..2c0efa7 100644 --- a/mesonbuild/backend/vs2015backend.py +++ b/mesonbuild/backend/vs2015backend.py @@ -19,6 +19,7 @@ from .vs2010backend import Vs2010Backend class Vs2015Backend(Vs2010Backend): def __init__(self, build): super().__init__(build) + self.name = 'vs2015' self.platform_toolset = 'v140' self.vs_version = '2015' diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index b157741..8133e0f 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -22,6 +22,7 @@ from ..mesonlib import MesonException class XCodeBackend(backends.Backend): def __init__(self, build): super().__init__(build) + self.name = 'xcode' self.project_uid = self.environment.coredata.guid.replace('-', '')[:24] self.project_conflist = self.gen_id() self.indent = ' ' diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index fefc1ff..502caff 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1027,6 +1027,7 @@ class MesonMain(InterpreterObject): 'version': self.version_method, 'project_name' : self.project_name_method, 'get_cross_property': self.get_cross_property_method, + 'backend' : self.backend_method, }) def add_install_script_method(self, args, kwargs): @@ -1065,6 +1066,9 @@ class MesonMain(InterpreterObject): return src return os.path.join(src, sub) + def backend_method(self, args, kwargs): + return self.interpreter.backend.name + def source_root_method(self, args, kwargs): return self.interpreter.environment.source_dir diff --git a/test cases/common/125 shared module/meson.build b/test cases/common/125 shared module/meson.build index 6fd21c2..ccb9c1a 100644 --- a/test cases/common/125 shared module/meson.build +++ b/test cases/common/125 shared module/meson.build @@ -1,5 +1,9 @@ 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 -- cgit v1.1 From f5a9b3b249efdafacbff1060999c60257c0ff72c Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Wed, 7 Dec 2016 05:24:38 +0530 Subject: Fix shared module support on Windows 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. So, we shouldn't use /FORCE:UNRESOLVED since that is not what modules do on Windows. Instead, we now do exactly what GModule does on Windows. Also use `void` for functions that take no arguments. --- mesonbuild/compilers.py | 3 - test cases/common/125 shared module/module.c | 51 ++++++++++++++- test cases/common/125 shared module/prog.c | 92 +++++++++++++++++++++++---- test cases/common/125 shared module/runtime.c | 2 +- 4 files changed, 129 insertions(+), 19 deletions(-) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 63117e8..b019e5f 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -1926,9 +1926,6 @@ class VisualStudioCCompiler(CCompiler): pdbarr += ['pdb'] return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)] - def get_std_shared_module_link_args(self): - return ['/DLL', '/FORCE:UNRESOLVED'] - class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): def __init__(self, exelist, version, is_cross, exe_wrap): self.language = 'cpp' diff --git a/test cases/common/125 shared module/module.c b/test cases/common/125 shared module/module.c index ed2712c..56078c5 100644 --- a/test cases/common/125 shared module/module.c +++ b/test cases/common/125 shared module/module.c @@ -9,6 +9,54 @@ #endif #endif +#ifdef _WIN32 + +#include +#include +#include + +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 @@ -17,6 +65,7 @@ */ int func_from_language_runtime(); -int DLL_PUBLIC func() { +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 index 8397034..2b63840 100644 --- a/test cases/common/125 shared module/prog.c +++ b/test cases/common/125 shared module/prog.c @@ -1,38 +1,102 @@ + +#include + +int func_from_language_runtime(void); +typedef int (*fptr) (void); + #ifdef _WIN32 -// FIXME: add implementation using Winapi functions for dlopen. -int main(int argc, char **argv) { - return 0; +#include + +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 #include -#include - -int func(); -int func_from_language_runtime(); int main(int argc, char **argv) { void *dl; - int (*importedfunc)(); - int success; + 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); - return 1; + goto nodl; } - importedfunc = (int (*)()) dlsym(dl, "func"); - assert(importedfunc); + + importedfunc = (fptr) dlsym(dl, "func"); + if (importedfunc == NULL) { + printf ("Could not find 'func'\n"); + goto out; + } + assert(importedfunc != func_from_language_runtime); - success = (*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); - return !success; +nodl: + return ret; } #endif diff --git a/test cases/common/125 shared module/runtime.c b/test cases/common/125 shared module/runtime.c index 68c813a..03bde86 100644 --- a/test cases/common/125 shared module/runtime.c +++ b/test cases/common/125 shared module/runtime.c @@ -14,6 +14,6 @@ * modules. */ -int DLL_PUBLIC func_from_language_runtime() { +int DLL_PUBLIC func_from_language_runtime(void) { return 86; } -- cgit v1.1