aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/backend/ninjabackend.py37
-rw-r--r--mesonbuild/backend/vs2010backend.py9
-rw-r--r--mesonbuild/build.py49
-rw-r--r--mesonbuild/compilers/c.py33
-rw-r--r--mesonbuild/compilers/compilers.py2
-rw-r--r--mesonbuild/dependencies/misc.py19
-rw-r--r--mesonbuild/interpreter.py87
-rw-r--r--mesonbuild/interpreterbase.py27
-rw-r--r--mesonbuild/mesonmain.py10
-rw-r--r--mesonbuild/modules/__init__.py1
-rw-r--r--mesonbuild/modules/gnome.py25
-rw-r--r--mesonbuild/modules/i18n.py36
-rw-r--r--mesonbuild/modules/modtest.py2
-rw-r--r--mesonbuild/modules/pkgconfig.py2
-rw-r--r--mesonbuild/modules/python3.py3
-rw-r--r--mesonbuild/modules/qt4.py2
-rw-r--r--mesonbuild/modules/qt5.py2
-rw-r--r--mesonbuild/modules/rpm.py2
-rw-r--r--mesonbuild/modules/windows.py2
-rw-r--r--[-rwxr-xr-x]mesonbuild/rewriter.py0
-rw-r--r--mesonbuild/scripts/meson_install.py4
-rw-r--r--mesonbuild/wrap/wrap.py74
22 files changed, 267 insertions, 161 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 7088c1e..41b93cb 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import os, pickle, re, shlex, shutil, subprocess, sys
+import os, pickle, re, shlex, subprocess, sys
from collections import OrderedDict
from . import backends
@@ -83,10 +83,9 @@ class NinjaBuildElement:
def write(self, outfile):
self.check_outputs()
- line = 'build %s: %s %s' % (
- ' '.join([ninja_quote(i) for i in self.outfilenames]),
- self.rule,
- ' '.join([ninja_quote(i) for i in self.infilenames]))
+ line = 'build %s: %s %s' % (' '.join([ninja_quote(i) for i in self.outfilenames]),
+ self.rule,
+ ' '.join([ninja_quote(i) for i in self.infilenames]))
if len(self.deps) > 0:
line += ' | ' + ' '.join([ninja_quote(x) for x in self.deps])
if len(self.orderdeps) > 0:
@@ -721,8 +720,7 @@ int dummy;
# On toolchains/platforms that use an import library for
# linking (separate from the shared library with all the
# code), we need to install that too (dll.a/.lib).
- if (isinstance(t, build.SharedLibrary) or
- isinstance(t, build.Executable)) and t.get_import_filename():
+ if (isinstance(t, build.SharedLibrary) or isinstance(t, build.Executable)) and t.get_import_filename():
if custom_install_dir:
# If the DLL is installed into a custom directory,
# install the import library into the same place so
@@ -856,8 +854,9 @@ int dummy;
self.create_target_alias('meson-test', outfile)
# And then benchmarks.
- cmd = self.environment.get_build_command(True) + ['test', '--benchmark', '--logbase',
- 'benchmarklog', '--num-processes=1', '--no-rebuild']
+ cmd = self.environment.get_build_command(True) + [
+ 'test', '--benchmark', '--logbase',
+ 'benchmarklog', '--num-processes=1', '--no-rebuild']
elem = NinjaBuildElement(self.all_outputs, 'meson-benchmark', 'CUSTOM_COMMAND', ['all', 'PHONY'])
elem.add_item('COMMAND', cmd)
elem.add_item('DESC', 'Running benchmark suite.')
@@ -1576,9 +1575,10 @@ int dummy;
def generate_swift_compile_rules(self, compiler, outfile):
rule = 'rule %s_COMPILER\n' % compiler.get_language()
full_exe = [ninja_quote(x) for x in self.environment.get_build_command()] + [
- '--internal',
- 'dirchanger',
- '$RUNDIR']
+ '--internal',
+ 'dirchanger',
+ '$RUNDIR',
+ ]
invoc = (' '.join(full_exe) + ' ' +
' '.join(ninja_quote(i) for i in compiler.get_exelist()))
command = ' command = %s $ARGS $in\n' % invoc
@@ -1784,7 +1784,6 @@ rule FORTRAN_DEP_HACK
exe_arr = self.exe_object_to_cmd_array(exe)
infilelist = genlist.get_inputs()
outfilelist = genlist.get_outputs()
- base_args = generator.get_arglist()
extra_dependencies = [os.path.join(self.build_to_src, i) for i in genlist.extra_depends]
source_target_dir = self.get_target_source_dir(target)
for i in range(len(infilelist)):
@@ -1794,6 +1793,7 @@ rule FORTRAN_DEP_HACK
sole_output = ''
curfile = infilelist[i]
infilename = curfile.rel_to_builddir(self.build_to_src)
+ base_args = generator.get_arglist(infilename)
outfiles = genlist.get_outputs_for(curfile)
outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles]
if generator.depfile is None:
@@ -1818,7 +1818,7 @@ rule FORTRAN_DEP_HACK
elem.add_item('DEPFILE', depfile)
if len(extra_dependencies) > 0:
elem.add_dep(extra_dependencies)
- elem.add_item('DESC', 'Generating $out')
+ elem.add_item('DESC', 'Generating {!r}.'.format(sole_output))
if isinstance(exe, build.BuildTarget):
elem.add_dep(self.get_target_filename(exe))
elem.add_item('COMMAND', cmdlist)
@@ -2527,10 +2527,11 @@ rule FORTRAN_DEP_HACK
def generate_dist(self, outfile):
elem = NinjaBuildElement(self.all_outputs, 'meson-dist', 'CUSTOM_COMMAND', 'PHONY')
elem.add_item('DESC', 'Creating source packages')
- elem.add_item('COMMAND', self.environment.get_build_command() +
- ['--internal', 'dist',
- self.environment.source_dir,
- self.environment.build_dir] + self.environment.get_build_command())
+ elem.add_item('COMMAND', self.environment.get_build_command() + [
+ '--internal', 'dist',
+ self.environment.source_dir,
+ self.environment.build_dir,
+ ] + self.environment.get_build_command())
elem.add_item('pool', 'console')
elem.write(outfile)
# Alias that runs the target defined above
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 0bbc17c..22c1779 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -22,7 +22,6 @@ from .. import build
from .. import dependencies
from .. import mlog
from .. import compilers
-from ..build import BuildTarget
from ..compilers import CompilerArgs
from ..mesonlib import MesonException, File
from ..environment import Environment
@@ -106,7 +105,6 @@ class Vs2010Backend(backends.Backend):
infilelist = genlist.get_inputs()
outfilelist = genlist.get_outputs()
exe_arr = self.exe_object_to_cmd_array(exe)
- base_args = generator.get_arglist()
idgroup = ET.SubElement(parent_node, 'ItemGroup')
for i in range(len(infilelist)):
if len(infilelist) == len(outfilelist):
@@ -115,6 +113,7 @@ class Vs2010Backend(backends.Backend):
sole_output = ''
curfile = infilelist[i]
infilename = os.path.join(down, curfile.rel_to_builddir(self.build_to_src))
+ base_args = generator.get_arglist(infilename)
outfiles_rel = genlist.get_outputs_for(curfile)
outfiles = [os.path.join(target_private_dir, of) for of in outfiles_rel]
generator_output_files += outfiles
@@ -383,8 +382,7 @@ class Vs2010Backend(backends.Backend):
cmd = [sys.executable, os.path.join(self.environment.get_script_dir(), 'commandrunner.py'),
self.environment.get_build_dir(),
self.environment.get_source_dir(),
- self.get_target_dir(target)] + \
- self.environment.get_build_command()
+ self.get_target_dir(target)] + self.environment.get_build_command()
for i in cmd_raw:
if isinstance(i, build.BuildTarget):
cmd.append(os.path.join(self.environment.get_build_dir(), self.get_target_filename(i)))
@@ -926,8 +924,7 @@ class Vs2010Backend(backends.Backend):
ofile.text = '$(OutDir)%s' % target.get_filename()
subsys = ET.SubElement(link, 'SubSystem')
subsys.text = subsystem
- if (isinstance(target, build.SharedLibrary) or
- isinstance(target, build.Executable)) and target.get_import_filename():
+ if (isinstance(target, build.SharedLibrary) or isinstance(target, build.Executable)) and target.get_import_filename():
# DLLs built with MSVC always have an import library except when
# they're data-only DLLs, but we don't support those yet.
ET.SubElement(link, 'ImportLibrary').text = target.get_import_filename()
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 281b060..c54abbd 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -359,6 +359,7 @@ class BuildTarget(Target):
self.check_unknown_kwargs(kwargs)
if not self.sources and not self.generated and not self.objects:
raise InvalidArguments('Build target %s has no sources.' % name)
+ self.process_compilers_late()
self.validate_sources()
self.validate_cross_install(environment)
@@ -439,6 +440,39 @@ class BuildTarget(Target):
removed = True
return removed
+ def process_compilers_late(self):
+ """Processes additional compilers after kwargs have been evaluated.
+
+ This can add extra compilers that might be required by keyword
+ arguments, such as link_with or dependencies. It will also try to guess
+ which compiler to use if one hasn't been selected already.
+ """
+ # Populate list of compilers
+ if self.is_cross:
+ compilers = self.environment.coredata.cross_compilers
+ else:
+ compilers = self.environment.coredata.compilers
+
+ # If this library is linked against another library we need to consider
+ # the languages of those libraries as well.
+ if self.link_targets or self.link_whole_targets:
+ extra = set()
+ for t in itertools.chain(self.link_targets, self.link_whole_targets):
+ for name, compiler in t.compilers.items():
+ if name in clike_langs:
+ extra.add((name, compiler))
+ for name, compiler in sorted(extra, key=lambda p: sort_clike(p[0])):
+ self.compilers[name] = compiler
+
+ if not self.compilers:
+ # No source files or parent targets, target consists of only object
+ # files of unknown origin. Just add the first clike compiler
+ # that we have and hope that it can link these objects
+ for lang in clike_langs:
+ if lang in compilers:
+ self.compilers[lang] = compilers[lang]
+ break
+
def process_compilers(self):
'''
Populate self.compilers, which is the list of compilers that this
@@ -487,14 +521,7 @@ class BuildTarget(Target):
# Re-sort according to clike_langs
self.compilers = OrderedDict(sorted(self.compilers.items(),
key=lambda t: sort_clike(t[0])))
- else:
- # No source files, target consists of only object files of unknown
- # origin. Just add the first clike compiler that we have and hope
- # that it can link these objects
- for lang in clike_langs:
- if lang in compilers:
- self.compilers[lang] = compilers[lang]
- break
+
# If all our sources are Vala, our target also needs the C compiler but
# it won't get added above.
if 'vala' in self.compilers and 'c' not in self.compilers:
@@ -1048,8 +1075,10 @@ class Generator:
basename = os.path.splitext(plainname)[0]
return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname)
- def get_arglist(self):
- return self.arglist
+ def get_arglist(self, inname):
+ plainname = os.path.split(inname)[1]
+ basename = os.path.splitext(plainname)[0]
+ return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.arglist]
def process_files(self, name, files, state, extra_args=[]):
output = GeneratedList(self, extra_args=extra_args)
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 255a506..82b1ef0 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -482,6 +482,34 @@ class CCompiler(Compiler):
# minus the extra newline at the end
return p.stdo.split(delim + '\n')[-1][:-1]
+ def get_return_value(self, fname, rtype, prefix, env, extra_args, dependencies):
+ if rtype == 'string':
+ fmt = '%s'
+ cast = '(char*)'
+ elif rtype == 'int':
+ fmt = '%lli'
+ cast = '(long long int)'
+ else:
+ raise AssertionError('BUG: Unknown return type {!r}'.format(rtype))
+ fargs = {'prefix': prefix, 'f': fname, 'cast': cast, 'fmt': fmt}
+ code = '''{prefix}
+ #include <stdio.h>
+ int main(int argc, char *argv[]) {{
+ printf ("{fmt}", {cast} {f}());
+ }}'''.format(**fargs)
+ res = self.run(code, env, extra_args, dependencies)
+ if not res.compiled:
+ m = 'Could not get return value of {}()'
+ raise EnvironmentException(m.format(fname))
+ if rtype == 'string':
+ return res.stdout
+ elif rtype == 'int':
+ try:
+ return int(res.stdout.strip())
+ except:
+ m = 'Return value of {}() is not an int'
+ raise EnvironmentException(m.format(fname))
+
@staticmethod
def _no_prototype_templ():
"""
@@ -896,6 +924,9 @@ class VisualStudioCCompiler(CCompiler):
def get_linker_search_args(self, dirname):
return ['/LIBPATH:' + dirname]
+ def get_gui_app_args(self):
+ return ['/SUBSYSTEM:WINDOWS']
+
def get_pic_args(self):
return [] # PIC is handled by the loader on Windows
@@ -1025,5 +1056,3 @@ class VisualStudioCCompiler(CCompiler):
# and the can not be called.
return None
return vs32_instruction_set_args.get(instruction_set, None)
-
-
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index c431194..89208e0 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -252,7 +252,7 @@ vs32_instruction_set_args = {'mmx': ['/arch:SSE'], # There does not seem to be a
'avx': ['/arch:AVX'],
'avx2': ['/arch:AVX2'],
'neon': None,
-}
+ }
# The 64 bit compiler defaults to /arch:avx.
vs64_instruction_set_args = {'mmx': ['/arch:AVX'],
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index c0ac5a8..c2b6dbd 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -575,6 +575,7 @@ class Python3Dependency(ExternalDependency):
else:
return [DependencyMethods.PKGCONFIG]
+
class PcapDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('pcap', environment, None, kwargs)
@@ -598,23 +599,12 @@ class PcapDependency(ExternalDependency):
self.compile_args = stdo.strip().split()
stdo = Popen_safe(['pcap-config', '--libs'])[1]
self.link_args = stdo.strip().split()
- self.version = '0'
+ self.version = self.get_pcap_lib_version()
self.is_found = True
mlog.log('Dependency', mlog.bold('pcap'), 'found:',
mlog.green('YES'), '(%s)' % pcapconf)
return
mlog.debug('Could not find pcap-config binary, trying next.')
- if DependencyMethods.EXTRAFRAMEWORK in self.methods:
- if mesonlib.is_osx():
- fwdep = ExtraFrameworkDependency('pcap', False, None, self.env,
- self.language, kwargs)
- if fwdep.found():
- self.is_found = True
- self.compile_args = fwdep.get_compile_args()
- self.link_args = fwdep.get_link_args()
- self.version = '2' # FIXME
- return
- mlog.log('Dependency', mlog.bold('pcap'), 'found:', mlog.red('NO'))
def get_methods(self):
if mesonlib.is_osx():
@@ -622,6 +612,11 @@ class PcapDependency(ExternalDependency):
else:
return [DependencyMethods.PKGCONFIG, DependencyMethods.PCAPCONFIG]
+ def get_pcap_lib_version(self):
+ return self.compiler.get_return_value('pcap_lib_version', 'string',
+ '#include <pcap.h>', self.env, [], [self])
+
+
class CupsDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('cups', environment, None, kwargs)
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 69c49c2..2148bed 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -881,7 +881,7 @@ class CompilerHolder(InterpreterObject):
extra_args = self.determine_args(kwargs)
deps = self.determine_dependencies(kwargs)
value = self.compiler.get_define(element, prefix, self.environment, extra_args, deps)
- mlog.log('Checking for value of define "%s": %s' % (element, value))
+ mlog.log('Fetching value of define "%s": %s' % (element, value))
return value
def compiles_method(self, args, kwargs):
@@ -1028,7 +1028,6 @@ class CompilerHolder(InterpreterObject):
h)
return result
-
def first_supported_argument_method(self, args, kwargs):
for i in mesonlib.stringlistify(args):
if self.compiler.has_argument(i, self.environment):
@@ -1245,48 +1244,50 @@ class MesonMain(InterpreterObject):
pch_kwargs = set(['c_pch', 'cpp_pch'])
-lang_arg_kwargs = set(['c_args',
- 'cpp_args',
- 'd_args',
- 'd_import_dirs',
- 'd_unittest',
- 'd_module_versions',
- 'fortran_args',
- 'java_args',
- 'objc_args',
- 'objcpp_args',
- 'rust_args',
- 'vala_args',
- 'cs_args',
- ])
+lang_arg_kwargs = set([
+ 'c_args',
+ 'cpp_args',
+ 'd_args',
+ 'd_import_dirs',
+ 'd_unittest',
+ 'd_module_versions',
+ 'fortran_args',
+ 'java_args',
+ 'objc_args',
+ 'objcpp_args',
+ 'rust_args',
+ 'vala_args',
+ 'cs_args',
+])
vala_kwargs = set(['vala_header', 'vala_gir', 'vala_vapi'])
rust_kwargs = set(['rust_crate_type'])
-cs_kwargs = set(['resources'])
-
-buildtarget_kwargs = set(['build_by_default',
- 'build_rpath',
- 'dependencies',
- 'extra_files',
- 'gui_app',
- 'link_with',
- 'link_whole',
- 'link_args',
- 'link_depends',
- 'implicit_include_directories',
- 'include_directories',
- 'install',
- 'install_rpath',
- 'install_dir',
- 'name_prefix',
- 'name_suffix',
- 'native',
- 'objects',
- 'override_options',
- 'pic',
- 'sources',
- 'vs_module_defs',
- ])
+cs_kwargs = set(['resources', 'cs_args'])
+
+buildtarget_kwargs = set([
+ 'build_by_default',
+ 'build_rpath',
+ 'dependencies',
+ 'extra_files',
+ 'gui_app',
+ 'link_with',
+ 'link_whole',
+ 'link_args',
+ 'link_depends',
+ 'implicit_include_directories',
+ 'include_directories',
+ 'install',
+ 'install_rpath',
+ 'install_dir',
+ 'name_prefix',
+ 'name_suffix',
+ 'native',
+ 'objects',
+ 'override_options',
+ 'pic',
+ 'sources',
+ 'vs_module_defs',
+])
build_target_common_kwargs = (
buildtarget_kwargs |
@@ -2013,11 +2014,11 @@ class Interpreter(InterpreterBase):
if not isinstance(use_native, bool):
raise InvalidArguments('Argument to "native" must be a boolean.')
if not use_native:
- progobj = self.program_from_cross_file(args)
+ progobj = self.program_from_cross_file(args)
if progobj is None:
progobj = self.program_from_system(args)
if required and (progobj is None or not progobj.found()):
- raise InvalidArguments('Program "%s" not found or not executable' % exename)
+ raise InvalidArguments('Program "%s" not found or not executable' % args[0])
if progobj is None:
return ExternalProgramHolder(dependencies.ExternalProgram('nonexistingprogram'))
return progobj
diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py
index d2e2ab3..1dd2f02 100644
--- a/mesonbuild/interpreterbase.py
+++ b/mesonbuild/interpreterbase.py
@@ -450,9 +450,25 @@ class InterpreterBase:
else:
raise InterpreterException('Unknown method "%s" for an integer.' % method_name)
+ @staticmethod
+ def _get_one_string_posarg(posargs, method_name):
+ if len(posargs) > 1:
+ m = '{}() must have zero or one arguments'
+ raise InterpreterException(m.format(method_name))
+ elif len(posargs) == 1:
+ s = posargs[0]
+ if not isinstance(s, str):
+ m = '{}() argument must be a string'
+ raise InterpreterException(m.format(method_name))
+ return s
+ return None
+
def string_method_call(self, obj, method_name, args):
(posargs, _) = self.reduce_arguments(args)
if method_name == 'strip':
+ s = self._get_one_string_posarg(posargs, 'strip')
+ if s is not None:
+ return obj.strip(s)
return obj.strip()
elif method_name == 'format':
return self.format_string(obj, args)
@@ -463,15 +479,10 @@ class InterpreterBase:
elif method_name == 'underscorify':
return re.sub(r'[^a-zA-Z0-9]', '_', obj)
elif method_name == 'split':
- if len(posargs) > 1:
- raise InterpreterException('Split() must have at most one argument.')
- elif len(posargs) == 1:
- s = posargs[0]
- if not isinstance(s, str):
- raise InterpreterException('Split() argument must be a string')
+ s = self._get_one_string_posarg(posargs, 'split')
+ if s is not None:
return obj.split(s)
- else:
- return obj.split()
+ return obj.split()
elif method_name == 'startswith' or method_name == 'contains' or method_name == 'endswith':
s = posargs[0]
if not isinstance(s, str):
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index 1657ddd..45e6026 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -122,11 +122,11 @@ class MesonApp:
if os.path.exists(priv_dir):
if not handshake:
print('Directory already configured, exiting Meson. Just run your build command\n'
- '(e.g. ninja) and Meson will regenerate as necessary. If ninja fails, run ninja\n'
- 'reconfigure to force Meson to regenerate.\n'
- '\nIf build failures persist, manually wipe your build directory to clear any\n'
- 'stored system data.\n'
- '\nTo change option values, run meson configure instead.')
+ '(e.g. ninja) and Meson will regenerate as necessary. If ninja fails, run ninja\n'
+ 'reconfigure to force Meson to regenerate.\n'
+ '\nIf build failures persist, manually wipe your build directory to clear any\n'
+ 'stored system data.\n'
+ '\nTo change option values, run meson configure instead.')
sys.exit(0)
else:
if handshake:
diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py
index 8b5b210..364bc45 100644
--- a/mesonbuild/modules/__init__.py
+++ b/mesonbuild/modules/__init__.py
@@ -4,7 +4,6 @@ from .. import build
from .. import dependencies
from .. import mlog
from ..mesonlib import MesonException
-from ..interpreterbase import permittedKwargs, noKwargs
class permittedSnippetKwargs:
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index 137d380..1ab075b 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -17,7 +17,6 @@ functionality such as gobject-introspection, gresources and gtk-doc'''
from .. import build
import os
-import sys
import copy
import subprocess
from . import ModuleReturnValue
@@ -30,7 +29,7 @@ from .. import interpreter
from . import GResourceTarget, GResourceHeaderTarget, GirTarget, TypelibTarget, VapiTarget
from . import find_program, get_include_args
from . import ExtensionModule
-from . import noKwargs, permittedKwargs
+from ..interpreterbase import noKwargs, permittedKwargs
# gresource compilation is broken due to the way
# the resource compiler and Ninja clash about it
@@ -697,18 +696,22 @@ This will become a hard error in the future.''')
args.append('--langs=' + '@@'.join(langs))
inscript = build.RunScript(script, args)
- potargs = state.environment.get_build_command() + ['--internal', 'yelphelper', 'pot',
- '--subdir=' + state.subdir,
- '--id=' + project_id,
- '--sources=' + source_str]
+ potargs = state.environment.get_build_command() + [
+ '--internal', 'yelphelper', 'pot',
+ '--subdir=' + state.subdir,
+ '--id=' + project_id,
+ '--sources=' + source_str,
+ ]
pottarget = build.RunTarget('help-' + project_id + '-pot', potargs[0],
potargs[1:], [], state.subdir)
- poargs = state.environment.get_build_command() + ['--internal', 'yelphelper', 'update-po',
- '--subdir=' + state.subdir,
- '--id=' + project_id,
- '--sources=' + source_str,
- '--langs=' + '@@'.join(langs)]
+ poargs = state.environment.get_build_command() + [
+ '--internal', 'yelphelper', 'update-po',
+ '--subdir=' + state.subdir,
+ '--id=' + project_id,
+ '--sources=' + source_str,
+ '--langs=' + '@@'.join(langs),
+ ]
potarget = build.RunTarget('help-' + project_id + '-update-po', poargs[0],
poargs[1:], [], state.subdir)
diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py
index 2af09de..c1dd837 100644
--- a/mesonbuild/modules/i18n.py
+++ b/mesonbuild/modules/i18n.py
@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import sys
import shutil
from os import path
@@ -20,7 +19,7 @@ from .. import coredata, mesonlib, build
from ..mesonlib import MesonException
from . import ModuleReturnValue
from . import ExtensionModule
-from . import permittedKwargs
+from ..interpreterbase import permittedKwargs
PRESET_ARGS = {
'glib': [
@@ -72,8 +71,10 @@ class I18nModule(ExtensionModule):
datadirs = self._get_data_dirs(state, mesonlib.stringlistify(kwargs.pop('data_dirs', [])))
datadirs = '--datadirs=' + ':'.join(datadirs) if datadirs else None
- command = state.environment.get_build_command() + ['--internal', 'msgfmthelper',
- '@INPUT@', '@OUTPUT@', file_type, podir]
+ command = state.environment.get_build_command() + [
+ '--internal', 'msgfmthelper',
+ '@INPUT@', '@OUTPUT@', file_type, podir
+ ]
if datadirs:
command.append(datadirs)
@@ -81,7 +82,7 @@ class I18nModule(ExtensionModule):
ct = build.CustomTarget(kwargs['output'] + '_merge', state.subdir, kwargs)
return ModuleReturnValue(ct, [ct])
- @permittedKwargs({'po_dir', 'data_dirs', 'type', 'languages', 'args', 'preset'})
+ @permittedKwargs({'po_dir', 'data_dirs', 'type', 'languages', 'args', 'preset', 'install'})
def gettext(self, state, args, kwargs):
if len(args) != 1:
raise coredata.MesonException('Gettext requires one positional argument (package name).')
@@ -126,16 +127,21 @@ class I18nModule(ExtensionModule):
updatepoargs.append(extra_args)
updatepotarget = build.RunTarget(packagename + '-update-po', updatepoargs[0], updatepoargs[1:], [], state.subdir)
- script = state.environment.get_build_command()
- args = ['--internal', 'gettext', 'install',
- '--subdir=' + state.subdir,
- '--localedir=' + state.environment.coredata.get_builtin_option('localedir'),
- pkg_arg]
- if lang_arg:
- args.append(lang_arg)
- iscript = build.RunScript(script, args)
-
- return ModuleReturnValue(None, [pottarget, gmotarget, iscript, updatepotarget])
+ targets = [pottarget, gmotarget, updatepotarget]
+
+ install = kwargs.get('install', True)
+ if install:
+ script = state.environment.get_build_command()
+ args = ['--internal', 'gettext', 'install',
+ '--subdir=' + state.subdir,
+ '--localedir=' + state.environment.coredata.get_builtin_option('localedir'),
+ pkg_arg]
+ if lang_arg:
+ args.append(lang_arg)
+ iscript = build.RunScript(script, args)
+ targets.append(iscript)
+
+ return ModuleReturnValue(None, targets)
def initialize():
return I18nModule()
diff --git a/mesonbuild/modules/modtest.py b/mesonbuild/modules/modtest.py
index dd2f215..758eeae 100644
--- a/mesonbuild/modules/modtest.py
+++ b/mesonbuild/modules/modtest.py
@@ -14,7 +14,7 @@
from . import ModuleReturnValue
from . import ExtensionModule
-from . import noKwargs
+from ..interpreterbase import noKwargs
class TestModule(ExtensionModule):
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 824ba78..aaed820 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -19,7 +19,7 @@ from .. import mesonlib
from .. import mlog
from . import ModuleReturnValue
from . import ExtensionModule
-from . import permittedKwargs
+from ..interpreterbase import permittedKwargs
class PkgConfigModule(ExtensionModule):
diff --git a/mesonbuild/modules/python3.py b/mesonbuild/modules/python3.py
index 94db75c..4fae88b 100644
--- a/mesonbuild/modules/python3.py
+++ b/mesonbuild/modules/python3.py
@@ -18,7 +18,8 @@ from .. import mesonlib, dependencies
from . import ExtensionModule
from mesonbuild.modules import ModuleReturnValue
-from . import noKwargs, permittedSnippetKwargs
+from . import permittedSnippetKwargs
+from ..interpreterbase import noKwargs
from ..interpreter import shlib_kwargs
mod_kwargs = set()
diff --git a/mesonbuild/modules/qt4.py b/mesonbuild/modules/qt4.py
index 37e630b..a63aff8 100644
--- a/mesonbuild/modules/qt4.py
+++ b/mesonbuild/modules/qt4.py
@@ -20,7 +20,7 @@ from ..dependencies import Qt4Dependency
from . import ExtensionModule
import xml.etree.ElementTree as ET
from . import ModuleReturnValue
-from . import permittedKwargs
+from ..interpreterbase import permittedKwargs
class Qt4Module(ExtensionModule):
tools_detected = False
diff --git a/mesonbuild/modules/qt5.py b/mesonbuild/modules/qt5.py
index ef3d52f..08ce662 100644
--- a/mesonbuild/modules/qt5.py
+++ b/mesonbuild/modules/qt5.py
@@ -20,7 +20,7 @@ from ..dependencies import Qt5Dependency
from . import ExtensionModule
import xml.etree.ElementTree as ET
from . import ModuleReturnValue
-from . import permittedKwargs
+from ..interpreterbase import permittedKwargs
class Qt5Module(ExtensionModule):
tools_detected = False
diff --git a/mesonbuild/modules/rpm.py b/mesonbuild/modules/rpm.py
index b0a8db9..dbb01f7 100644
--- a/mesonbuild/modules/rpm.py
+++ b/mesonbuild/modules/rpm.py
@@ -22,7 +22,7 @@ from .. import mlog
from . import GirTarget, TypelibTarget
from . import ModuleReturnValue
from . import ExtensionModule
-from . import noKwargs
+from ..interpreterbase import noKwargs
import os
diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py
index ab215dc..c16d7a8 100644
--- a/mesonbuild/modules/windows.py
+++ b/mesonbuild/modules/windows.py
@@ -20,7 +20,7 @@ from ..mesonlib import MesonException, extract_as_list
from . import get_include_args
from . import ModuleReturnValue
from . import ExtensionModule
-from . import permittedKwargs
+from ..interpreterbase import permittedKwargs
class WindowsModule(ExtensionModule):
diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py
index b88c5ef..b88c5ef 100755..100644
--- a/mesonbuild/rewriter.py
+++ b/mesonbuild/rewriter.py
diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py
index f978be4..985b0e9 100644
--- a/mesonbuild/scripts/meson_install.py
+++ b/mesonbuild/scripts/meson_install.py
@@ -227,7 +227,9 @@ def install_man(d):
if outfilename.endswith('.gz') and not full_source_filename.endswith('.gz'):
with open(outfilename, 'wb') as of:
with open(full_source_filename, 'rb') as sf:
- of.write(gzip.compress(sf.read()))
+ # Set mtime and filename for reproducibility.
+ with gzip.GzipFile(fileobj=of, mode='wb', filename='', mtime=0) as gz:
+ gz.write(sf.read())
shutil.copystat(full_source_filename, outfilename)
append_to_log(outfilename)
else:
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index ac84d0e..14529ab 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -14,7 +14,7 @@
from .. import mlog
import contextlib
-import urllib.request, os, hashlib, shutil
+import urllib.request, os, hashlib, shutil, tempfile, stat
import subprocess
import sys
from pathlib import Path
@@ -230,6 +230,8 @@ class Resolver:
def get_data(self, url):
blocksize = 10 * 1024
+ h = hashlib.sha256()
+ tmpfile = tempfile.NamedTemporaryFile(mode='wb', dir=self.cachedir, delete=False)
if url.startswith('https://wrapdb.mesonbuild.com'):
resp = open_wrapdburl(url)
else:
@@ -241,26 +243,34 @@ class Resolver:
dlsize = None
if dlsize is None:
print('Downloading file of unknown size.')
- return resp.read()
+ while True:
+ block = resp.read(blocksize)
+ if block == b'':
+ break
+ h.update(block)
+ tmpfile.write(block)
+ hashvalue = h.hexdigest()
+ return hashvalue, tmpfile.name
print('Download size:', dlsize)
print('Downloading: ', end='')
sys.stdout.flush()
printed_dots = 0
- blocks = []
downloaded = 0
while True:
block = resp.read(blocksize)
if block == b'':
break
downloaded += len(block)
- blocks.append(block)
+ h.update(block)
+ tmpfile.write(block)
ratio = int(downloaded / dlsize * 10)
while printed_dots < ratio:
print('.', end='')
sys.stdout.flush()
printed_dots += 1
print('')
- return b''.join(blocks)
+ hashvalue = h.hexdigest()
+ return hashvalue, tmpfile.name
def get_hash(self, data):
h = hashlib.sha256()
@@ -272,34 +282,51 @@ class Resolver:
ofname = os.path.join(self.cachedir, p.get('source_filename'))
if os.path.exists(ofname):
mlog.log('Using', mlog.bold(packagename), 'from cache.')
- return
- srcurl = p.get('source_url')
- mlog.log('Downloading', mlog.bold(packagename), 'from', mlog.bold(srcurl))
- srcdata = self.get_data(srcurl)
- dhash = self.get_hash(srcdata)
- expected = p.get('source_hash')
- if dhash != expected:
- raise RuntimeError('Incorrect hash for source %s:\n %s expected\n %s actual.' % (packagename, expected, dhash))
- with open(ofname, 'wb') as f:
- f.write(srcdata)
+ else:
+ srcurl = p.get('source_url')
+ mlog.log('Downloading', mlog.bold(packagename), 'from', mlog.bold(srcurl))
+ dhash, tmpfile = self.get_data(srcurl)
+ expected = p.get('source_hash')
+ if dhash != expected:
+ os.remove(tmpfile)
+ raise RuntimeError('Incorrect hash for source %s:\n %s expected\n %s actual.' % (packagename, expected, dhash))
+ os.rename(tmpfile, ofname)
if p.has_patch():
purl = p.get('patch_url')
mlog.log('Downloading patch from', mlog.bold(purl))
- pdata = self.get_data(purl)
- phash = self.get_hash(pdata)
+ phash, tmpfile = self.get_data(purl)
expected = p.get('patch_hash')
if phash != expected:
+ os.remove(tmpfile)
raise RuntimeError('Incorrect hash for patch %s:\n %s expected\n %s actual' % (packagename, expected, phash))
filename = os.path.join(self.cachedir, p.get('patch_filename'))
- with open(filename, 'wb') as f:
- f.write(pdata)
+ os.rename(tmpfile, filename)
else:
mlog.log('Package does not require patch.')
+ def copy_tree(self, root_src_dir, root_dst_dir):
+ """
+ Copy directory tree. Overwrites also read only files.
+ """
+ for src_dir, dirs, files in os.walk(root_src_dir):
+ dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1)
+ if not os.path.exists(dst_dir):
+ os.makedirs(dst_dir)
+ for file_ in files:
+ src_file = os.path.join(src_dir, file_)
+ dst_file = os.path.join(dst_dir, file_)
+ if os.path.exists(dst_file):
+ try:
+ os.remove(dst_file)
+ except PermissionError as exc:
+ os.chmod(dst_file, stat.S_IWUSR)
+ os.remove(dst_file)
+ shutil.copy2(src_file, dst_dir)
+
def extract_package(self, package):
if sys.version_info < (3, 5):
try:
- import lzma
+ import lzma # noqa: F401
del lzma
except ImportError:
pass
@@ -322,4 +349,9 @@ class Resolver:
pass
shutil.unpack_archive(os.path.join(self.cachedir, package.get('source_filename')), extract_dir)
if package.has_patch():
- shutil.unpack_archive(os.path.join(self.cachedir, package.get('patch_filename')), self.subdir_root)
+ try:
+ shutil.unpack_archive(os.path.join(self.cachedir, package.get('patch_filename')), self.subdir_root)
+ except Exception:
+ with tempfile.TemporaryDirectory() as workdir:
+ shutil.unpack_archive(os.path.join(self.cachedir, package.get('patch_filename')), workdir)
+ self.copy_tree(workdir, self.subdir_root)