diff options
-rw-r--r-- | mesonbuild/backend/backends.py | 2 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 14 | ||||
-rw-r--r-- | mesonbuild/build.py | 9 | ||||
-rw-r--r-- | mesonbuild/compilers.py | 68 | ||||
-rw-r--r-- | mesonbuild/environment.py | 36 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 4 | ||||
-rw-r--r-- | mesonbuild/modules/rpm.py | 4 | ||||
-rw-r--r-- | test cases/failing/28 no vs module defs/meson.build | 9 | ||||
-rw-r--r-- | test cases/failing/28 no vs module defs/prog.c | 5 | ||||
-rw-r--r-- | test cases/failing/28 no vs module defs/subdir/meson.build | 1 | ||||
-rw-r--r-- | test cases/failing/28 no vs module defs/subdir/somedll.c | 7 | ||||
-rw-r--r-- | test cases/windows/6 vs module defs/meson.build | 7 | ||||
-rw-r--r-- | test cases/windows/6 vs module defs/prog.c | 5 | ||||
-rw-r--r-- | test cases/windows/6 vs module defs/subdir/meson.build | 1 | ||||
-rw-r--r-- | test cases/windows/6 vs module defs/subdir/somedll.c | 5 | ||||
-rw-r--r-- | test cases/windows/6 vs module defs/subdir/somedll.def | 3 |
16 files changed, 134 insertions, 46 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 313580b..c9d6197 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -251,8 +251,6 @@ class Backend(): commands += self.environment.coredata.external_args[compiler.get_language()] commands += target.get_extra_args(compiler.get_language()) commands += compiler.get_buildtype_args(self.environment.coredata.get_builtin_option('buildtype')) - if self.environment.coredata.base_options.get('b_coverage', False): - commands += compiler.get_coverage_args() if self.environment.coredata.get_builtin_option('werror'): commands += compiler.get_werror_args() if isinstance(target, build.SharedLibrary): diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index dfd792b..5263d86 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -184,7 +184,8 @@ int dummy; self.generate_tests(outfile) outfile.write('# Install rules\n\n') self.generate_install(outfile) - if self.environment.coredata.base_options.get('b_coverage', False): + if 'b_coverage' in self.environment.coredata.base_options and \ + self.environment.coredata.base_options['b_coverage'].value: outfile.write('# Coverage rules\n\n') self.generate_coverage_rules(outfile) outfile.write('# Suffix\n\n') @@ -446,10 +447,11 @@ int dummy; phony_elem.write(outfile) elem = NinjaBuildElement(self.all_outputs, 'coveragereport/index.html', 'CUSTOM_COMMAND', '') + htmloutdir = os.path.join(self.environment.get_log_dir(), 'coveragereport') command = [lcov_exe, '--directory', self.environment.get_build_dir(),\ '--capture', '--output-file', 'coverage.info', '--no-checksum',\ '&&', genhtml_exe, '--prefix', self.environment.get_build_dir(),\ - '--output-directory', self.environment.get_log_dir(), '--title', 'Code coverage',\ + '--output-directory', htmloutdir, '--title', 'Code coverage',\ '--legend', '--show-details', 'coverage.info'] elem.add_item('COMMAND', command) elem.add_item('DESC', 'Generating HTML coverage report.') @@ -813,6 +815,7 @@ int dummy; outputs = [vapiname] args = [] args += self.build.get_global_args(compiler) + args += compiler.get_buildtype_args(self.environment.coredata.get_builtin_option('buildtype')) args += ['-d', self.get_target_private_dir(target)] args += ['-C']#, '-o', cname] if not isinstance(target, build.Executable): @@ -1655,6 +1658,8 @@ rule FORTRAN_DEP_HACK else: soversion = None commands += linker.get_soname_args(target.name, abspath, soversion) + 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)) elif isinstance(target, build.StaticLibrary): commands += linker.get_std_link_args() else: @@ -1682,8 +1687,6 @@ rule FORTRAN_DEP_HACK commands += dep.get_link_args() commands += linker.build_rpath_args(self.environment.get_build_dir(),\ self.determine_rpath_dirs(target), target.install_rpath) - if self.environment.coredata.base_options.get('b_coverage', False): - commands += linker.get_coverage_link_args() custom_target_libraries = self.get_custom_target_provided_libraries(target) commands += extra_args commands += custom_target_libraries @@ -1797,7 +1800,8 @@ rule FORTRAN_DEP_HACK elem = NinjaBuildElement(self.all_outputs, 'clean', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', [ninja_command, '-t', 'clean']) elem.add_item('description', 'Cleaning') - if self.environment.coredata.base_options.get('b_coverage', False): + if 'b_coverage' in self.environment.coredata.base_options and \ + self.environment.coredata.base_options['b_coverage'].value: self.generate_gcov_clean(outfile) elem.add_dep('clean-gcda') elem.add_dep('clean-gcno') diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 3f480e8..2a91aa3 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -47,7 +47,7 @@ known_shlib_kwargs.update({'version' : True, 'soversion' : True, 'name_prefix' : True, 'name_suffix' : True, - }) + 'vs_module_defs' : True}) backslash_explanation = \ '''Compiler arguments have a backslash "\\" character. This is unfortunately not @@ -703,6 +703,7 @@ class SharedLibrary(BuildTarget): def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): self.version = None self.soversion = None + self.vs_module_defs = None super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs); if len(self.sources) > 0 and self.sources[0].endswith('.cs'): prefix = 'lib' @@ -726,6 +727,12 @@ class SharedLibrary(BuildTarget): self.set_version(kwargs['version']) if 'soversion' in kwargs: self.set_soversion(kwargs['soversion']) + if 'vs_module_defs' in kwargs: + path = kwargs['vs_module_defs'] + if (os.path.isabs(path)): + self.vs_module_defs = File.from_absolute_file(path) + else: + self.vs_module_defs = File.from_source_file(environment.source_dir, self.subdir, path) def check_unknown_kwargs(self, kwargs): self.check_unknown_kwargs_int(kwargs, known_shlib_kwargs) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 3079c5e..880113d 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -126,7 +126,7 @@ base_options = { 'off'), 'b_coverage': coredata.UserBooleanOption('b_coverage', 'Enable coverage tracking.', - True), + False), } def sanitizer_compile_args(value): @@ -285,6 +285,9 @@ class Compiler(): def find_library(self, libname, extra_dirs): raise EnvironmentException('Language {} does not support library finding.'.format(self.language)) + def get_library_dirs(self): + return [] + class CCompiler(Compiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None): super().__init__(exelist, version) @@ -372,6 +375,16 @@ class CCompiler(Compiler): def get_std_shared_lib_link_args(self): return ['-shared'] + def get_library_dirs(self): + output = subprocess.Popen(self.exelist + ['--print-search-dirs'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) + (stdo, _) = output.communicate() + stdo = stdo.decode('utf-8') + for line in stdo.split('\n'): + if line.startswith('libraries:'): + libstr = line.split('=', 1)[1] + return libstr.split(':') + return [] + def can_compile(self, filename): suffix = filename.split('.')[-1] if suffix == 'c' or suffix == 'h': @@ -484,7 +497,6 @@ int someSymbolHereJustForFun; return p.returncode == 0 def links(self, code, extra_args = []): - suflen = len(self.default_suffix) (fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix) os.close(fd) (fd, dstname) = tempfile.mkstemp() @@ -662,16 +674,28 @@ void bar() { return self.compiles(templ % (prefix, typename), extra_args) def find_library(self, libname, extra_dirs): + # First try if we can just add the library as -l. code = '''int main(int argc, char **argv) { return 0; } ''' - args = [] - for i in extra_dirs: - args += self.get_linker_search_args(i) - args.append('-l' + libname) - if self.links(code, extra_args=args): - return args + # Gcc + co seem to prefer builtin lib dirs to -L dirs. + # Only try to find std libs if no extra dirs specified. + if len(extra_dirs) == 0: + args = ['-l' + libname] + if self.links(code, extra_args=args): + return args + # Not found? Try to find the library file itself. + extra_dirs += self.get_library_dirs() + suffixes = ['so', 'dylib', 'lib', 'dll', 'a'] + for d in extra_dirs: + for suffix in suffixes: + trial = os.path.join(d, 'lib' + libname + '.' + suffix) + if os.path.isfile(trial): + return trial + trial2 = os.path.join(d, libname + '.' + suffix) + if os.path.isfile(trial2): + return trial2 return None def thread_flags(self): @@ -1044,6 +1068,11 @@ class ValaCompiler(Compiler): suffix = filename.split('.')[-1] return suffix in ('vala', 'vapi') + def get_buildtype_args(self, buildtype): + if buildtype == 'debug' or buildtype == 'debugoptimized': + return ['--debug'] + return [] + class RustCompiler(Compiler): def __init__(self, exelist, version): super().__init__(exelist, version) @@ -1252,6 +1281,13 @@ class VisualStudioCCompiler(CCompiler): def get_std_shared_lib_link_args(self): return ['/DLL'] + def gen_vs_module_defs_args(self, defsfile): + if not isinstance(defsfile, str): + raise RuntimeError('Module definitions file should be str') + # With MSVC, DLLs only export symbols that are explicitly exported, + # so if a module defs file is specified, we use that to export symbols + return ['/DEF:' + defsfile] + def gen_pch_args(self, header, source, pchname): objname = os.path.splitext(pchname)[0] + '.obj' return (objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname ]) @@ -1420,7 +1456,7 @@ class GnuCCompiler(CCompiler): self.warn_args = {'1': ['-Wall', '-Winvalid-pch'], '2': ['-Wall', '-Wextra', '-Winvalid-pch'], '3' : ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch']} - self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize'] + self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] if self.gcc_type != GCC_OSX: self.base_options.append('b_lundef') @@ -1485,7 +1521,7 @@ class GnuObjCCompiler(ObjCCompiler): self.warn_args = {'1': ['-Wall', '-Winvalid-pch'], '2': ['-Wall', '-Wextra', '-Winvalid-pch'], '3' : ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch']} - self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize'] + self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] if self.gcc_type != GCC_OSX: self.base_options.append('b_lundef') @@ -1513,7 +1549,7 @@ class GnuObjCPPCompiler(ObjCPPCompiler): self.warn_args = {'1': ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'], '2': ['-Wall', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor'], '3' : ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor']} - self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize'] + self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] if self.gcc_type != GCC_OSX: self.base_options.append('b_lundef') @@ -1533,7 +1569,7 @@ class ClangObjCCompiler(GnuObjCCompiler): def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None): super().__init__(exelist, version, is_cross, exe_wrapper) self.id = 'clang' - self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize'] + self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] self.clang_type = cltype if self.clang_type != CLANG_OSX: self.base_options.append('b_lundef') @@ -1543,7 +1579,7 @@ class ClangObjCPPCompiler(GnuObjCPPCompiler): super().__init__(exelist, version, is_cross, exe_wrapper) self.id = 'clang' self.clang_type = cltype - self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize'] + self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] if self.clang_type != CLANG_OSX: self.base_options.append('b_lundef') @@ -1555,7 +1591,7 @@ class ClangCCompiler(CCompiler): self.warn_args = {'1': ['-Wall', '-Winvalid-pch'], '2': ['-Wall', '-Wextra', '-Winvalid-pch'], '3' : ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch']} - self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize'] + self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] if self.clang_type != CLANG_OSX: self.base_options.append('b_lundef') @@ -1603,7 +1639,7 @@ class GnuCPPCompiler(CPPCompiler): self.warn_args = {'1': ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'], '2': ['-Wall', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor'], '3': ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor']} - self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize'] + self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] if self.gcc_type != GCC_OSX: self.base_options.append('b_lundef') @@ -1653,7 +1689,7 @@ class ClangCPPCompiler(CPPCompiler): '2': ['-Wall', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor'], '3': ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor']} self.clang_type = cltype - self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize'] + self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] if self.clang_type != CLANG_OSX: self.base_options.append('b_lundef') diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 8db0b0c..bfd1c35 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -252,11 +252,11 @@ class Environment(): for compiler in compilers: for arg in ['--version', '-V']: try: - p = subprocess.Popen([compiler] + [arg], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + p = subprocess.Popen([compiler] + [arg], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) except OSError: - continue + continue (out, err) = p.communicate() out = out.decode(errors='ignore') err = err.decode(errors='ignore') @@ -267,32 +267,32 @@ class Environment(): version = vmatch.group(0) if 'GNU Fortran' in out: - return GnuFortranCompiler([compiler], version, GCC_STANDARD, is_cross, exe_wrap) + return GnuFortranCompiler([compiler], version, GCC_STANDARD, is_cross, exe_wrap) if 'G95' in out: - return G95FortranCompiler([compiler], version, is_cross, exe_wrap) + return G95FortranCompiler([compiler], version, is_cross, exe_wrap) if 'Sun Fortran' in err: - version = 'unknown version' - vmatch = re.search(Environment.version_regex, err) - if vmatch: - version = vmatch.group(0) - return SunFortranCompiler([compiler], version, is_cross, exe_wrap) + version = 'unknown version' + vmatch = re.search(Environment.version_regex, err) + if vmatch: + version = vmatch.group(0) + return SunFortranCompiler([compiler], version, is_cross, exe_wrap) if 'ifort (IFORT)' in out: - return IntelFortranCompiler([compiler], version, is_cross, exe_wrap) - + return IntelFortranCompiler([compiler], version, is_cross, exe_wrap) + if 'PathScale EKOPath(tm)' in err: - return PathScaleFortranCompiler([compiler], version, is_cross, exe_wrap) + return PathScaleFortranCompiler([compiler], version, is_cross, exe_wrap) if 'pgf90' in out: - return PGIFortranCompiler([compiler], version, is_cross, exe_wrap) + return PGIFortranCompiler([compiler], version, is_cross, exe_wrap) if 'Open64 Compiler Suite' in err: - return Open64FortranCompiler([compiler], version, is_cross, exe_wrap) + return Open64FortranCompiler([compiler], version, is_cross, exe_wrap) if 'NAG Fortran' in err: - return NAGFortranCompiler([compiler], version, is_cross, exe_wrap) + return NAGFortranCompiler([compiler], version, is_cross, exe_wrap) raise EnvironmentException('Unknown compiler(s): "' + ', '.join(compilers) + '"') @@ -515,7 +515,7 @@ class Environment(): evar = 'AR' if evar in os.environ: linker = os.environ[evar].strip() - if isinstance(compiler, VisualStudioCCompiler): + elif isinstance(compiler, VisualStudioCCompiler): linker= self.vs_static_linker else: linker = self.default_static_linker diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index ef6f3c1..90a0a13 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -761,13 +761,13 @@ class CompilerHolder(InterpreterObject): required = kwargs.get('required', True) if not isinstance(required, bool): raise InterpreterException('required must be boolean.') - search_dirs = kwargs.get('dirs', []) + search_dirs = mesonlib.stringlistify(kwargs.get('dirs', [])) for i in search_dirs: if not os.path.isabs(i): raise InvalidCode('Search directory %s is not an absolute path.' % i) linkargs = self.compiler.find_library(libname, search_dirs) if required and linkargs is None: - raise InterpreterException('Library %s not found'.format(libname)) + raise InterpreterException('Library {} not found'.format(libname)) lib = dependencies.ExternalLibrary(libname, linkargs) return ExternalLibraryHolder(lib) diff --git a/mesonbuild/modules/rpm.py b/mesonbuild/modules/rpm.py index c8035ec..262c1d9 100644 --- a/mesonbuild/modules/rpm.py +++ b/mesonbuild/modules/rpm.py @@ -65,9 +65,9 @@ class RPMModule: to_delete.add('%%{buildroot}%%{_libdir}/%s' % target.get_filename()) mlog.log('Warning, removing', mlog.bold(target.get_filename()), 'from package because packaging static libs not recommended') - elif isinstance(target, modules.gnome.GirTarget) and target.should_install(): + elif isinstance(target, gnome.GirTarget) and target.should_install(): files_devel.add('%%{_datadir}/gir-1.0/%s' % target.get_filename()[0]) - elif isinstance(target, modules.gnome.TypelibTarget) and target.should_install(): + elif isinstance(target, gnome.TypelibTarget) and target.should_install(): files.add('%%{_libdir}/girepository-1.0/%s' % target.get_filename()[0]) for header in state.headers: if len(header.get_install_subdir()) > 0: diff --git a/test cases/failing/28 no vs module defs/meson.build b/test cases/failing/28 no vs module defs/meson.build new file mode 100644 index 0000000..7864daa --- /dev/null +++ b/test cases/failing/28 no vs module defs/meson.build @@ -0,0 +1,9 @@ +project('dll_no_module_def', 'c') + +if meson.get_compiler('c').get_id() != 'msvc' + error('Need to use the Visual Studio compiler') +endif + +subdir('subdir') +exe = executable('prog', 'prog.c', link_with : shlib) +test('runtest', exe) diff --git a/test cases/failing/28 no vs module defs/prog.c b/test cases/failing/28 no vs module defs/prog.c new file mode 100644 index 0000000..f35f4a0 --- /dev/null +++ b/test cases/failing/28 no vs module defs/prog.c @@ -0,0 +1,5 @@ +int somedllfunc(); + +int main(int argc, char **argv) { + return somedllfunc() == 42 ? 0 : 1; +} diff --git a/test cases/failing/28 no vs module defs/subdir/meson.build b/test cases/failing/28 no vs module defs/subdir/meson.build new file mode 100644 index 0000000..8395d59 --- /dev/null +++ b/test cases/failing/28 no vs module defs/subdir/meson.build @@ -0,0 +1 @@ +shlib = shared_library('somedll', 'somedll.c') diff --git a/test cases/failing/28 no vs module defs/subdir/somedll.c b/test cases/failing/28 no vs module defs/subdir/somedll.c new file mode 100644 index 0000000..5c469b1 --- /dev/null +++ b/test cases/failing/28 no vs module defs/subdir/somedll.c @@ -0,0 +1,7 @@ +/* With MSVC, the DLL created from this will not export any symbols + * without a module definitions file specified while linking */ +#ifdef _MSC_VER +int somedllfunc() { + return 42; +} +#endif diff --git a/test cases/windows/6 vs module defs/meson.build b/test cases/windows/6 vs module defs/meson.build new file mode 100644 index 0000000..4b9e735 --- /dev/null +++ b/test cases/windows/6 vs module defs/meson.build @@ -0,0 +1,7 @@ +project('dll_module_defs', 'c') + +if meson.get_compiler('c').get_id() == 'msvc' + subdir('subdir') + exe = executable('prog', 'prog.c', link_with : shlib) + test('runtest', exe) +endif diff --git a/test cases/windows/6 vs module defs/prog.c b/test cases/windows/6 vs module defs/prog.c new file mode 100644 index 0000000..f35f4a0 --- /dev/null +++ b/test cases/windows/6 vs module defs/prog.c @@ -0,0 +1,5 @@ +int somedllfunc(); + +int main(int argc, char **argv) { + return somedllfunc() == 42 ? 0 : 1; +} diff --git a/test cases/windows/6 vs module defs/subdir/meson.build b/test cases/windows/6 vs module defs/subdir/meson.build new file mode 100644 index 0000000..60633c3 --- /dev/null +++ b/test cases/windows/6 vs module defs/subdir/meson.build @@ -0,0 +1 @@ +shlib = shared_library('somedll', 'somedll.c', vs_module_defs : 'somedll.def') diff --git a/test cases/windows/6 vs module defs/subdir/somedll.c b/test cases/windows/6 vs module defs/subdir/somedll.c new file mode 100644 index 0000000..df255e3 --- /dev/null +++ b/test cases/windows/6 vs module defs/subdir/somedll.c @@ -0,0 +1,5 @@ +#ifdef _MSC_VER +int somedllfunc() { + return 42; +} +#endif diff --git a/test cases/windows/6 vs module defs/subdir/somedll.def b/test cases/windows/6 vs module defs/subdir/somedll.def new file mode 100644 index 0000000..217801b --- /dev/null +++ b/test cases/windows/6 vs module defs/subdir/somedll.def @@ -0,0 +1,3 @@ +EXPORTS + somedllfunc + |