aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--authors.txt3
-rw-r--r--mesonbuild/dependencies.py40
-rw-r--r--mesonbuild/interpreter.py78
-rw-r--r--mesonbuild/modules/gnome.py99
-rw-r--r--mesonbuild/modules/i18n.py6
-rw-r--r--mesonbuild/modules/pkgconfig.py77
-rw-r--r--mesonbuild/scripts/gettext.py14
-rw-r--r--test cases/common/51 pkgconfig-gen/meson.build13
-rw-r--r--test cases/frameworks/7 gnome/meson.build1
-rw-r--r--test cases/frameworks/7 gnome/resources-data/meson.build16
-rw-r--r--test cases/frameworks/7 gnome/resources-data/res1.txt (renamed from test cases/frameworks/7 gnome/resources/data/res1.txt)0
-rw-r--r--test cases/frameworks/7 gnome/resources-data/res3.txt.in1
-rw-r--r--test cases/frameworks/7 gnome/resources-data/subdir/meson.build8
-rw-r--r--test cases/frameworks/7 gnome/resources-data/subdir/res2.txt1
-rw-r--r--test cases/frameworks/7 gnome/resources-data/subdir/res4.txt.in1
-rw-r--r--test cases/frameworks/7 gnome/resources/generated-main.c27
-rw-r--r--test cases/frameworks/7 gnome/resources/generated.gresource.xml9
-rw-r--r--test cases/frameworks/7 gnome/resources/meson.build34
-rw-r--r--test cases/frameworks/7 gnome/resources/myresource.gresource.xml3
-rw-r--r--test cases/frameworks/7 gnome/resources/simple-main.c (renamed from test cases/frameworks/7 gnome/resources/main.c)6
-rw-r--r--test cases/frameworks/7 gnome/resources/simple.gresource.xml7
-rw-r--r--test cases/linuxlike/5 dependency versions/meson.build6
-rw-r--r--test cases/linuxlike/5 dependency versions/subprojects/somelib/meson.build3
-rwxr-xr-xtools/cmake2meson.py8
24 files changed, 359 insertions, 102 deletions
diff --git a/authors.txt b/authors.txt
index 229a2ff..a51badd 100644
--- a/authors.txt
+++ b/authors.txt
@@ -47,3 +47,6 @@ Iain Lane
Daniel Brendle
Franz Zapata
Emanuele Aina
+Guillaume Poirier-Morency
+Scott D Phillips
+Gautier Pelloux-Prayer
diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py
index 6a4c32c..d0c7663 100644
--- a/mesonbuild/dependencies.py
+++ b/mesonbuild/dependencies.py
@@ -32,9 +32,10 @@ class DependencyException(MesonException):
MesonException.__init__(self, *args, **kwargs)
class Dependency():
- def __init__(self):
+ def __init__(self, type_name='unknown'):
self.name = "null"
self.is_found = False
+ self.type_name = type_name
def get_compile_args(self):
return []
@@ -59,9 +60,12 @@ class Dependency():
def need_threads(self):
return False
+ def type_name(self):
+ return self.type_name
+
class InternalDependency(Dependency):
def __init__(self, version, incdirs, compile_args, link_args, libraries, sources, ext_deps):
- super().__init__()
+ super().__init__('internal')
self.version = version
self.include_directories = incdirs
self.compile_args = compile_args
@@ -83,7 +87,7 @@ class PkgConfigDependency(Dependency):
pkgconfig_found = None
def __init__(self, name, environment, kwargs):
- Dependency.__init__(self)
+ Dependency.__init__(self, 'pkgconfig')
self.is_libtool = False
self.required = kwargs.get('required', True)
self.static = kwargs.get('static', False)
@@ -270,7 +274,7 @@ class WxDependency(Dependency):
wx_found = None
def __init__(self, environment, kwargs):
- Dependency.__init__(self)
+ Dependency.__init__(self, 'wx')
self.is_found = False
if WxDependency.wx_found is None:
self.check_wxconfig()
@@ -445,7 +449,7 @@ class ExternalProgram():
class ExternalLibrary(Dependency):
def __init__(self, name, link_args=None, silent=False):
- super().__init__()
+ super().__init__('external')
self.name = name
# Rename fullpath to link_args once standalone find_library() gets removed.
if link_args is not None:
@@ -476,7 +480,7 @@ class BoostDependency(Dependency):
name2lib = {'test' : 'unit_test_framework'}
def __init__(self, environment, kwargs):
- Dependency.__init__(self)
+ Dependency.__init__(self, 'boost')
self.name = 'boost'
self.environment = environment
self.libdir = ''
@@ -677,7 +681,7 @@ class BoostDependency(Dependency):
class GTestDependency(Dependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self)
+ Dependency.__init__(self, 'gtest')
self.main = kwargs.get('main', False)
self.name = 'gtest'
self.libname = 'libgtest.so'
@@ -744,7 +748,7 @@ class GTestDependency(Dependency):
class GMockDependency(Dependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self)
+ Dependency.__init__(self, 'gmock')
# GMock may be a library or just source.
# Work with both.
self.name = 'gmock'
@@ -798,7 +802,7 @@ class GMockDependency(Dependency):
class Qt5Dependency(Dependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self)
+ Dependency.__init__(self, 'qt5')
self.name = 'qt5'
self.root = '/usr'
mods = kwargs.get('modules', [])
@@ -909,7 +913,7 @@ class Qt5Dependency(Dependency):
class Qt4Dependency(Dependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self)
+ Dependency.__init__(self, 'qt4')
self.name = 'qt4'
self.root = '/usr'
self.modules = []
@@ -947,7 +951,7 @@ class Qt4Dependency(Dependency):
class GnuStepDependency(Dependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self)
+ Dependency.__init__(self, 'gnustep')
self.modules = kwargs.get('modules', [])
self.detect()
@@ -1019,7 +1023,7 @@ why. As a hack filter out everything that is not a flag."""
class AppleFrameworks(Dependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self)
+ Dependency.__init__(self, 'appleframeworks')
modules = kwargs.get('modules', [])
if isinstance(modules, str):
modules = [modules]
@@ -1039,13 +1043,14 @@ class AppleFrameworks(Dependency):
class GLDependency(Dependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self)
+ Dependency.__init__(self, 'gl')
self.is_found = False
self.cargs = []
self.linkargs = []
try:
pcdep = PkgConfigDependency('gl', environment, kwargs)
if pcdep.found():
+ self.type_name = 'pkgconfig'
self.is_found = True
self.cargs = pcdep.get_compile_args()
self.linkargs = pcdep.get_link_args()
@@ -1068,13 +1073,14 @@ class GLDependency(Dependency):
# sdl2-config, pkg-config and OSX framework
class SDL2Dependency(Dependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self)
+ Dependency.__init__(self, 'sdl2')
self.is_found = False
self.cargs = []
self.linkargs = []
try:
pcdep = PkgConfigDependency('sdl2', environment, kwargs)
if pcdep.found():
+ self.type_name = 'pkgconfig'
self.is_found = True
self.cargs = pcdep.get_compile_args()
self.linkargs = pcdep.get_link_args()
@@ -1124,7 +1130,7 @@ class SDL2Dependency(Dependency):
class ExtraFrameworkDependency(Dependency):
def __init__(self, name, required, path=None):
- Dependency.__init__(self)
+ Dependency.__init__(self, 'extraframeworks')
self.name = None
self.detect(name, path)
if self.found():
@@ -1165,7 +1171,7 @@ class ExtraFrameworkDependency(Dependency):
class ThreadDependency(Dependency):
def __init__(self, environment, kwargs):
- super().__init__()
+ super().__init__('threads')
self.name = 'threads'
self.is_found = True
mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES'))
@@ -1175,7 +1181,7 @@ class ThreadDependency(Dependency):
class Python3Dependency(Dependency):
def __init__(self, environment, kwargs):
- super().__init__()
+ super().__init__('python3')
self.name = 'python3'
self.is_found = False
self.version = "3.something_maybe"
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index e486ee9..6e57107 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -27,6 +27,7 @@ import os, sys, subprocess, shutil, uuid, re
from functools import wraps
import importlib
+import copy
run_depr_printed = False
@@ -188,6 +189,7 @@ class EnvironmentVariablesHolder(InterpreterObject):
self.methods.update({'set': self.set_method,
'append': self.append_method,
'prepend' : self.prepend_method,
+ 'copy' : self.copy_method,
})
@stringArgs
@@ -210,6 +212,9 @@ class EnvironmentVariablesHolder(InterpreterObject):
def prepend_method(self, args, kwargs):
self.add_var(self.held_object.prepend, args, kwargs)
+ def copy_method(self, args, kwargs):
+ return copy.deepcopy(self)
+
class ConfigurationDataHolder(InterpreterObject):
def __init__(self):
@@ -278,27 +283,21 @@ class DependencyHolder(InterpreterObject):
InterpreterObject.__init__(self)
self.held_object = dep
self.methods.update({'found' : self.found_method,
+ 'type_name': self.type_name_method,
'version': self.version_method})
+ def type_name_method(self, args, kwargs):
+ return self.held_object.type_name
+
def found_method(self, args, kwargs):
+ if self.held_object.type_name == 'internal':
+ return True
+
return self.held_object.found()
def version_method(self, args, kwargs):
return self.held_object.get_version()
-class InternalDependencyHolder(InterpreterObject):
- def __init__(self, dep):
- InterpreterObject.__init__(self)
- self.held_object = dep
- self.methods.update({'found' : self.found_method,
- 'version': self.version_method,
- })
-
- def found_method(self, args, kwargs):
- return True
-
- def version_method(self, args, kwargs):
- return self.held_object.get_version()
class ExternalProgramHolder(InterpreterObject):
def __init__(self, ep):
@@ -1394,7 +1393,7 @@ class Interpreter():
raise InterpreterException('Dependencies must be external deps')
final_deps.append(d)
dep = dependencies.InternalDependency(version, incs, compile_args, link_args, libs, sources, final_deps)
- return InternalDependencyHolder(dep)
+ return DependencyHolder(dep)
@noKwargs
def func_assert(self, node, args, kwargs):
@@ -1835,11 +1834,23 @@ class Interpreter():
# We need to actually search for this dep
exception = None
dep = None
- try:
- dep = dependencies.find_external_dependency(name, self.environment, kwargs)
- except dependencies.DependencyException as e:
- exception = e
- pass
+ # If the fallback has already been configured (possibly by a higher level project)
+ # try to use it before using the native version
+ if 'fallback' in kwargs:
+ dirname, varname = self.get_subproject_infos(kwargs)
+ if dirname in self.subprojects:
+ try:
+ dep = self.subprojects[dirname].get_variable_method([varname], {})
+ dep = dep.held_object
+ except KeyError:
+ pass
+
+ if not dep:
+ try:
+ dep = dependencies.find_external_dependency(name, self.environment, kwargs)
+ except dependencies.DependencyException as e:
+ exception = e
+ pass
if not dep or not dep.found():
if 'fallback' in kwargs:
@@ -1853,35 +1864,42 @@ class Interpreter():
self.coredata.deps[identifier] = dep
return DependencyHolder(dep)
- def dependency_fallback(self, name, kwargs):
+ def get_subproject_infos(self, kwargs):
fbinfo = kwargs['fallback']
check_stringlist(fbinfo)
if len(fbinfo) != 2:
raise InterpreterException('Fallback info must have exactly two items.')
- dirname, varname = fbinfo
+ return fbinfo
+
+ def dependency_fallback(self, name, kwargs):
+ dirname, varname = self.get_subproject_infos(kwargs)
try:
self.do_subproject(dirname, {})
except:
mlog.log('Also couldn\'t find a fallback subproject in',
mlog.bold(os.path.join(self.subproject_dir, dirname)),
'for the dependency', mlog.bold(name))
- if kwargs.get('required', True):
- raise
- else:
- return None
+ return None
try:
dep = self.subprojects[dirname].get_variable_method([varname], {})
except KeyError:
- raise InterpreterException('Fallback variable {!r} in the subproject {!r} does not exist'.format(varname, dirname))
- if not isinstance(dep, (DependencyHolder, InternalDependencyHolder)):
- raise InterpreterException('Fallback variable {!r} in the subproject {!r} is not a dependency object.'.format(varname, dirname))
+ mlog.log('Fallback variable', mlog.bold(varname),
+ 'in the subproject', mlog.bold(dirname), 'does not exist')
+ return None
+ if not isinstance(dep, DependencyHolder):
+ mlog.log('Fallback variable', mlog.bold(varname),
+ 'in the subproject', mlog.bold(dirname),
+ 'is not a dependency object.')
+ return None
# Check if the version of the declared dependency matches what we want
if 'version' in kwargs:
wanted = kwargs['version']
found = dep.version_method([], {})
if found == 'undefined' or not mesonlib.version_compare(found, wanted):
- m = 'Subproject "{0}" dependency "{1}" version is "{2}" but "{3}" is required.'
- raise InterpreterException(m.format(dirname, varname, found, wanted))
+ mlog.log('Subproject', mlog.bold(dirname), 'dependency',
+ mlog.bold(varname), 'version is', mlog.bold(found),
+ 'but', mlog.bold(wanted), 'is required.')
+ return None
mlog.log('Found a', mlog.green('fallback'), 'subproject',
mlog.bold(os.path.join(self.subproject_dir, dirname)), 'for',
mlog.bold(name))
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index be111ea..678ae82 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -22,22 +22,36 @@ from ..mesonlib import MesonException
from .. import dependencies
from .. import mlog
from .. import mesonlib
+from .. import interpreter
+native_glib_version = None
girwarning_printed = False
gresource_warning_printed = False
class GnomeModule:
+ def get_native_glib_version(self, state):
+ global native_glib_version
+ if native_glib_version is None:
+ glib_dep = dependencies.PkgConfigDependency(
+ 'glib-2.0', state.environment, {'native': True})
+ native_glib_version = glib_dep.get_modversion()
+ return native_glib_version
+
def __print_gresources_warning(self):
global gresource_warning_printed
if not gresource_warning_printed:
- mlog.log('Warning, glib compiled dependencies will not work reliably until this upstream issue is fixed:',
+ mlog.log('Warning, GLib compiled dependencies do not work fully '
+ 'with versions of GLib older than 2.50.0.\n'
+ 'See the following upstream issue:',
mlog.bold('https://bugzilla.gnome.org/show_bug.cgi?id=745754'))
gresource_warning_printed = True
return []
def compile_resources(self, state, args, kwargs):
- self.__print_gresources_warning()
+ if mesonlib.version_compare(self.get_native_glib_version(state),
+ '< 2.50.0'):
+ self.__print_gresources_warning()
cmd = ['glib-compile-resources', '@INPUT@']
@@ -51,6 +65,19 @@ class GnomeModule:
if len(args) < 2:
raise MesonException('Not enough arguments; The name of the resource and the path to the XML file are required')
+ dependencies = kwargs.pop('dependencies', [])
+ if not isinstance(dependencies, list):
+ dependencies = [dependencies]
+
+ if mesonlib.version_compare(self.get_native_glib_version(state),
+ '< 2.48.2'):
+ if len(dependencies) > 0:
+ raise MesonException(
+ 'The "dependencies" argument of gnome.compile_resources() '
+ 'can only be used with glib-compile-resources version '
+ '2.48.2 or newer, due to '
+ '<https://bugzilla.gnome.org/show_bug.cgi?id=673101>')
+
ifile = args[1]
if isinstance(ifile, mesonlib.File):
ifile = os.path.join(ifile.subdir, ifile.fname)
@@ -58,12 +85,20 @@ class GnomeModule:
ifile = os.path.join(state.subdir, ifile)
else:
raise RuntimeError('Unreachable code.')
- kwargs['depend_files'] = self.get_gresource_dependencies(state, ifile, source_dirs)
+
+ kwargs['depend_files'] = self.get_gresource_dependencies(
+ state, ifile, source_dirs, dependencies)
for source_dir in source_dirs:
sourcedir = os.path.join(state.build_to_src, state.subdir, source_dir)
cmd += ['--sourcedir', sourcedir]
+ if len(dependencies) > 0:
+ # Add the build variant of each sourcedir if we have any
+ # generated dependencies.
+ sourcedir = os.path.join(state.subdir, source_dir)
+ cmd += ['--sourcedir', sourcedir]
+
if 'c_name' in kwargs:
cmd += ['--c-name', kwargs.pop('c_name')]
cmd += ['--generate', '--target', '@OUTPUT@']
@@ -78,9 +113,17 @@ class GnomeModule:
target_h = build.CustomTarget(args[0] + '_h', state.subdir, kwargs)
return [target_c, target_h]
- def get_gresource_dependencies(self, state, input_file, source_dirs):
+ def get_gresource_dependencies(self, state, input_file, source_dirs, dependencies):
self.__print_gresources_warning()
+ for dep in dependencies:
+ if not isinstance(dep, interpreter.CustomTargetHolder) and not \
+ isinstance(dep, mesonlib.File):
+ raise MesonException(
+ 'Unexpected dependency type for gnome.compile_resources() '
+ '"dependencies" argument. Please pass the output of '
+ 'custom_target() or configure_file().')
+
cmd = ['glib-compile-resources',
input_file,
'--generate-dependencies']
@@ -95,7 +138,51 @@ class GnomeModule:
mlog.log(mlog.bold('Warning:'), 'glib-compile-resources has failed to get the dependencies for {}'.format(cmd[1]))
raise subprocess.CalledProcessError(pc.returncode, cmd)
- return stdout.split('\n')[:-1]
+ dep_files = stdout.split('\n')[:-1]
+
+ # In generate-dependencies mode, glib-compile-resources doesn't raise
+ # an error for missing resources but instead prints whatever filename
+ # was listed in the input file. That's good because it means we can
+ # handle resource files that get generated as part of the build, as
+ # follows.
+ #
+ # If there are multiple generated resource files with the same basename
+ # then this code will get confused.
+
+ def exists_in_srcdir(f):
+ return os.path.exists(os.path.join(state.environment.get_source_dir(), f))
+ missing_dep_files = [f for f in dep_files if not exists_in_srcdir(f)]
+
+ for missing in missing_dep_files:
+ found = False
+ missing_basename = os.path.basename(missing)
+
+ for dep in dependencies:
+ if isinstance(dep, mesonlib.File):
+ if dep.fname == missing_basename:
+ found = True
+ dep_files.remove(missing)
+ dep_files.append(dep)
+ break
+ elif isinstance(dep, interpreter.CustomTargetHolder):
+ if dep.held_object.get_basename() == missing_basename:
+ found = True
+ dep_files.remove(missing)
+ dep_files.append(
+ mesonlib.File(
+ is_built=True,
+ subdir=dep.held_object.get_subdir(),
+ fname=dep.held_object.get_basename()))
+ break
+
+ if not found:
+ raise MesonException(
+ 'Resource "%s" listed in "%s" was not found. If this is a '
+ 'generated file, pass the target that generates it to '
+ 'gnome.compile_resources() using the "dependencies" '
+ 'keyword argument.' % (missing, input_file))
+
+ return dep_files
def get_link_args(self, state, lib, depends=None):
link_command = ['-l%s' % lib.name]
@@ -158,7 +245,7 @@ class GnomeModule:
ldflags.update(extdepflags[1])
gi_includes.update(extdepflags[2])
for source in dep.sources:
- if isinstance(source.held_object, GirTarget):
+ if hasattr(source, 'held_object') and isinstance(source.held_object, GirTarget):
gi_includes.update([os.path.join(state.environment.get_build_dir(),
source.held_object.get_subdir())])
# This should be any dependency other than an internal one.
diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py
index 33874fa..00787f8 100644
--- a/mesonbuild/modules/i18n.py
+++ b/mesonbuild/modules/i18n.py
@@ -24,8 +24,12 @@ class I18nModule:
languages = mesonlib.stringlistify(kwargs.get('languages', []))
if len(languages) == 0:
raise coredata.MesonException('List of languages empty.')
+ datadirs = mesonlib.stringlistify(kwargs.get('data_dirs', []))
extra_args = mesonlib.stringlistify(kwargs.get('args', []))
- potargs = [state.environment.get_build_command(), '--internal', 'gettext', 'pot', packagename] + extra_args
+ potargs = [state.environment.get_build_command(), '--internal', 'gettext', 'pot', packagename]
+ if datadirs:
+ potargs.append('--datadirs=' + ':'.join(datadirs))
+ potargs += extra_args
pottarget = build.RunTarget(packagename + '-pot', sys.executable, potargs, [], state.subdir)
gmoargs = [state.environment.get_build_command(), '--internal', 'gettext', 'gen_gmo'] + languages
gmotarget = build.RunTarget(packagename + '-gmo', sys.executable, gmoargs, [], state.subdir)
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 9c235b5..0cfd309 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -37,8 +37,9 @@ class PkgConfigModule:
mlog.log(mlog.red('WARNING:'), msg.format(l.name, 'name_prefix', l.name, pcfile))
return l.name
- def generate_pkgconfig_file(self, state, libraries, subdirs, name, description, version, pcfile,
- pub_reqs, priv_reqs, priv_libs):
+ def generate_pkgconfig_file(self, state, libraries, subdirs, name, description,
+ url, version, pcfile, pub_reqs, priv_reqs,
+ conflicts, priv_libs):
coredata = state.environment.get_coredata()
outdir = state.environment.scratch_dir
fname = os.path.join(outdir, pcfile)
@@ -51,6 +52,8 @@ class PkgConfigModule:
ofile.write('Name: %s\n' % name)
if len(description) > 0:
ofile.write('Description: %s\n' % description)
+ if len(url) > 0:
+ ofile.write('URL: %s\n' % url)
if len(version) > 0:
ofile.write('Version: %s\n' % version)
if len(pub_reqs) > 0:
@@ -58,45 +61,55 @@ class PkgConfigModule:
if len(priv_reqs) > 0:
ofile.write(
'Requires.private: {}\n'.format(' '.join(priv_reqs)))
+ if len(conflicts) > 0:
+ ofile.write('Conflicts: {}\n'.format(' '.join(conflicts)))
+ def generate_libs_flags(libs):
+ msg = 'Library target {0!r} has {1!r} set. Compilers ' \
+ 'may not find it from its \'-l{2}\' linker flag in the ' \
+ '{3!r} pkg-config file.'
+ for l in libs:
+ if isinstance(l, str):
+ yield l
+ else:
+ if l.custom_install_dir:
+ yield '-L${prefix}/%s ' % l.custom_install_dir
+ else:
+ yield '-L${libdir}'
+ lname = self._get_lname(l, msg, pcfile)
+ # If using a custom suffix, the compiler may not be able to
+ # find the library
+ if l.name_suffix_set:
+ mlog.log(mlog.red('WARNING:'), msg.format(l.name, 'name_suffix', lname, pcfile))
+ yield '-l%s' % lname
+ if len(libraries) > 0:
+ ofile.write('Libs: {}\n'.format(' '.join(generate_libs_flags(libraries))))
if len(priv_libs) > 0:
- ofile.write(
- 'Libraries.private: {}\n'.format(' '.join(priv_libs)))
- ofile.write('Libs: -L${libdir} ')
- msg = 'Library target {0!r} has {1!r} set. Compilers ' \
- 'may not find it from its \'-l{2}\' linker flag in the ' \
- '{3!r} pkg-config file.'
- for l in libraries:
- if l.custom_install_dir:
- ofile.write('-L${prefix}/%s ' % l.custom_install_dir)
- lname = self._get_lname(l, msg, pcfile)
- # If using a custom suffix, the compiler may not be able to
- # find the library
- if l.name_suffix_set:
- mlog.log(mlog.red('WARNING:'), msg.format(l.name, 'name_suffix', lname, pcfile))
- ofile.write('-l{} '.format(lname))
- ofile.write('\n')
- ofile.write('CFlags: ')
+ ofile.write('Libs.private: {}\n'.format(' '.join(generate_libs_flags(priv_libs))))
+ ofile.write('Cflags:')
for h in subdirs:
if h == '.':
h = ''
- ofile.write(os.path.join('-I${includedir}', h))
ofile.write(' ')
+ ofile.write(os.path.join('-I${includedir}', h))
ofile.write('\n')
- def generate(self, state, args, kwargs):
- if len(args) > 0:
- raise mesonlib.MesonException('Pkgconfig_gen takes no positional arguments.')
- libs = kwargs.get('libraries', [])
+ def process_libs(self, libs):
if not isinstance(libs, list):
libs = [libs]
processed_libs = []
for l in libs:
if hasattr(l, 'held_object'):
l = l.held_object
- if not isinstance(l, (build.SharedLibrary, build.StaticLibrary)):
- raise mesonlib.MesonException('Library argument not a library object.')
+ if not isinstance(l, (build.SharedLibrary, build.StaticLibrary, str)):
+ raise mesonlib.MesonException('Library argument not a library object nor a string.')
processed_libs.append(l)
- libs = processed_libs
+ return processed_libs
+
+ def generate(self, state, args, kwargs):
+ if len(args) > 0:
+ raise mesonlib.MesonException('Pkgconfig_gen takes no positional arguments.')
+ libs = self.process_libs(kwargs.get('libraries', []))
+ priv_libs = self.process_libs(kwargs.get('libraries_private', []))
subdirs = mesonlib.stringlistify(kwargs.get('subdirs', ['.']))
version = kwargs.get('version', '')
if not isinstance(version, str):
@@ -110,17 +123,21 @@ class PkgConfigModule:
description = kwargs.get('description', None)
if not isinstance(description, str):
raise mesonlib.MesonException('Description is not a string.')
+ url = kwargs.get('url', '')
+ if not isinstance(url, str):
+ raise mesonlib.MesonException('URL is not a string.')
pub_reqs = mesonlib.stringlistify(kwargs.get('requires', []))
priv_reqs = mesonlib.stringlistify(kwargs.get('requires_private', []))
- priv_libs = mesonlib.stringlistify(kwargs.get('libraries_private', []))
+ conflicts = mesonlib.stringlistify(kwargs.get('conflicts', []))
pcfile = filebase + '.pc'
pkgroot = kwargs.get('install_dir',None)
if pkgroot is None:
pkgroot = os.path.join(state.environment.coredata.get_builtin_option('libdir'), 'pkgconfig')
if not isinstance(pkgroot, str):
raise mesonlib.MesonException('Install_dir must be a string.')
- self.generate_pkgconfig_file(state, libs, subdirs, name, description, version, pcfile,
- pub_reqs, priv_reqs, priv_libs)
+ self.generate_pkgconfig_file(state, libs, subdirs, name, description, url,
+ version, pcfile, pub_reqs, priv_reqs,
+ conflicts, priv_libs)
return build.Data(False, state.environment.get_scratch_dir(), [pcfile], pkgroot)
def initialize():
diff --git a/mesonbuild/scripts/gettext.py b/mesonbuild/scripts/gettext.py
index ba6b242..95fd45a 100644
--- a/mesonbuild/scripts/gettext.py
+++ b/mesonbuild/scripts/gettext.py
@@ -15,7 +15,7 @@
import os, subprocess, shutil
from mesonbuild.scripts import destdir_join
-def run_potgen(src_sub, pkgname, args):
+def run_potgen(src_sub, pkgname, datadirs, args):
listfile = os.path.join(src_sub, 'POTFILES')
if not os.path.exists(listfile):
listfile = os.path.join(src_sub, 'POTFILES.in')
@@ -23,9 +23,14 @@ def run_potgen(src_sub, pkgname, args):
print('Could not find file POTFILES in %s' % src_sub)
return 1
+ child_env = os.environ.copy()
+ if datadirs:
+ child_env['GETTEXTDATADIRS'] = datadirs
+
ofile = os.path.join(src_sub, pkgname + '.pot')
return subprocess.call(['xgettext', '--package-name=' + pkgname, '-p', src_sub, '-f', listfile,
- '-D', os.environ['MESON_SOURCE_ROOT'], '-k_', '-o', ofile] + args)
+ '-D', os.environ['MESON_SOURCE_ROOT'], '-k_', '-o', ofile] + args,
+ env=child_env)
def gen_gmo(src_sub, bld_sub, langs):
for l in langs:
@@ -47,9 +52,12 @@ def do_install(src_sub, bld_sub, dest, pkgname, langs):
def run(args):
subcmd = args[0]
if subcmd == 'pot':
+ pkgname = args[1]
+ datadirs = args[2][11:] if args[2].startswith('--datadirs=') else None
+ extra_args = args[3:] if datadirs is not None else args[2:]
src_sub = os.path.join(os.environ['MESON_SOURCE_ROOT'], os.environ['MESON_SUBDIR'])
bld_sub = os.path.join(os.environ['MESON_BUILD_ROOT'], os.environ['MESON_SUBDIR'])
- return run_potgen(src_sub, args[1], args[2:])
+ return run_potgen(src_sub, pkgname, datadirs, extra_args)
elif subcmd == 'gen_gmo':
src_sub = os.path.join(os.environ['MESON_SOURCE_ROOT'], os.environ['MESON_SUBDIR'])
bld_sub = os.path.join(os.environ['MESON_BUILD_ROOT'], os.environ['MESON_SUBDIR'])
diff --git a/test cases/common/51 pkgconfig-gen/meson.build b/test cases/common/51 pkgconfig-gen/meson.build
index e31bfe6..fa9439c 100644
--- a/test cases/common/51 pkgconfig-gen/meson.build
+++ b/test cases/common/51 pkgconfig-gen/meson.build
@@ -7,7 +7,7 @@ libver = '1.0'
h = install_headers('simple.h')
pkgg.generate(
- libraries : lib,
+ libraries : [lib, '-lz'],
subdirs : '.',
version : libver,
name : 'libsimple',
@@ -15,7 +15,16 @@ pkgg.generate(
description : 'A simple demo library.',
requires : 'glib-2.0', # Not really, but only here to test that this works.
requires_private : ['gio-2.0', 'gobject-2.0'],
- libraries_private : '-lz')
+ libraries_private : [lib, '-lz'],
+)
+
+pkgconfig = find_program('pkg-config', required: false)
+if pkgconfig.found()
+ test('pkgconfig-validation', pkgconfig,
+ args: ['--validate', 'simple'],
+ env: ['PKG_CONFIG_PATH=' + meson.current_build_dir() + '/meson-private' ],
+ )
+endif
# Test that name_prefix='' and name='libfoo' results in '-lfoo'
lib2 = shared_library('libfoo', 'simple.c',
diff --git a/test cases/frameworks/7 gnome/meson.build b/test cases/frameworks/7 gnome/meson.build
index 2c2e953..a771e71 100644
--- a/test cases/frameworks/7 gnome/meson.build
+++ b/test cases/frameworks/7 gnome/meson.build
@@ -9,6 +9,7 @@ gir = dependency('gobject-introspection-1.0')
gmod = dependency('gmodule-2.0')
add_global_arguments('-DMESON_TEST', language : 'c')
+subdir('resources-data')
subdir('resources')
subdir('gir')
subdir('schemas')
diff --git a/test cases/frameworks/7 gnome/resources-data/meson.build b/test cases/frameworks/7 gnome/resources-data/meson.build
new file mode 100644
index 0000000..6343c0e
--- /dev/null
+++ b/test cases/frameworks/7 gnome/resources-data/meson.build
@@ -0,0 +1,16 @@
+subdir('subdir')
+
+fake_generator_script = '''
+import os, sys
+assert os.path.exists(sys.argv[1]), "File %s not found" % sys.argv[1]
+print("This is a generated resource")
+'''
+
+# Generate file res3.txt from file res3.txt.in. This is then included
+# in a GResource file, driven by resources/meson.build.
+res3_txt = custom_target('res3.txt',
+ input: 'res3.txt.in',
+ output: 'res3.txt',
+ command: ['python3', '-c', fake_generator_script, '@INPUT@'],
+ capture: true,
+)
diff --git a/test cases/frameworks/7 gnome/resources/data/res1.txt b/test cases/frameworks/7 gnome/resources-data/res1.txt
index e10afea..e10afea 100644
--- a/test cases/frameworks/7 gnome/resources/data/res1.txt
+++ b/test cases/frameworks/7 gnome/resources-data/res1.txt
diff --git a/test cases/frameworks/7 gnome/resources-data/res3.txt.in b/test cases/frameworks/7 gnome/resources-data/res3.txt.in
new file mode 100644
index 0000000..077a8e3
--- /dev/null
+++ b/test cases/frameworks/7 gnome/resources-data/res3.txt.in
@@ -0,0 +1 @@
+This content is ignored, but Meson doesn't need to know that.
diff --git a/test cases/frameworks/7 gnome/resources-data/subdir/meson.build b/test cases/frameworks/7 gnome/resources-data/subdir/meson.build
new file mode 100644
index 0000000..b41300f
--- /dev/null
+++ b/test cases/frameworks/7 gnome/resources-data/subdir/meson.build
@@ -0,0 +1,8 @@
+cdata = configuration_data()
+cdata.set('NOISE', 'BARK')
+
+res4_txt = configure_file(
+ input: 'res4.txt.in',
+ output: 'res4.txt',
+ configuration: cdata
+)
diff --git a/test cases/frameworks/7 gnome/resources-data/subdir/res2.txt b/test cases/frameworks/7 gnome/resources-data/subdir/res2.txt
new file mode 100644
index 0000000..d297899
--- /dev/null
+++ b/test cases/frameworks/7 gnome/resources-data/subdir/res2.txt
@@ -0,0 +1 @@
+This is a resource in a subdirectory.
diff --git a/test cases/frameworks/7 gnome/resources-data/subdir/res4.txt.in b/test cases/frameworks/7 gnome/resources-data/subdir/res4.txt.in
new file mode 100644
index 0000000..c0ec6f2
--- /dev/null
+++ b/test cases/frameworks/7 gnome/resources-data/subdir/res4.txt.in
@@ -0,0 +1 @@
+@NOISE@ @NOISE@ @NOISE@
diff --git a/test cases/frameworks/7 gnome/resources/generated-main.c b/test cases/frameworks/7 gnome/resources/generated-main.c
new file mode 100644
index 0000000..fc9efbd
--- /dev/null
+++ b/test cases/frameworks/7 gnome/resources/generated-main.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<string.h>
+#include<gio/gio.h>
+#include"generated-resources.h"
+
+#define EXPECTED "This is a generated resource.\n"
+
+int main(int argc, char **argv) {
+ GResource *res = generated_resources_get_resource();
+ GError *err = NULL;
+ GBytes *data = g_resources_lookup_data("/com/example/myprog/res3.txt",
+ G_RESOURCE_LOOKUP_FLAGS_NONE, &err);
+
+ if(data == NULL) {
+ fprintf(stderr, "Data lookup failed: %s\n", err->message);
+ return 1;
+ }
+ if(strcmp(g_bytes_get_data(data, NULL), EXPECTED) != 0) {
+ fprintf(stderr, "Resource contents are wrong:\n %s\n",
+ (const char*)g_bytes_get_data(data, NULL));
+ return 1;
+ }
+ fprintf(stdout, "All ok.\n");
+ g_bytes_unref(data);
+ g_resource_unref(res);
+ return 0;
+}
diff --git a/test cases/frameworks/7 gnome/resources/generated.gresource.xml b/test cases/frameworks/7 gnome/resources/generated.gresource.xml
new file mode 100644
index 0000000..7a242d7
--- /dev/null
+++ b/test cases/frameworks/7 gnome/resources/generated.gresource.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/com/example/myprog">
+ <file>res1.txt</file>
+ <file>subdir/res2.txt</file>
+ <file>res3.txt</file>
+ <file>subdir/res4.txt</file>
+ </gresource>
+</gresources>
diff --git a/test cases/frameworks/7 gnome/resources/meson.build b/test cases/frameworks/7 gnome/resources/meson.build
index 937dc47..5762a8c 100644
--- a/test cases/frameworks/7 gnome/resources/meson.build
+++ b/test cases/frameworks/7 gnome/resources/meson.build
@@ -1,7 +1,29 @@
-myres = gnome.compile_resources('myresources', 'myresource.gresource.xml',
-source_dir : 'data',
-c_name : 'myres')
+# There are two tests here, because the 2nd one depends on a version of
+# GLib (2.48.2) that is very recent at the time of writing.
-resexe = executable('resprog', 'main.c', myres,
-dependencies : gio)
-test('resource test', resexe)
+simple_resources = gnome.compile_resources('simple-resources',
+ 'simple.gresource.xml',
+ source_dir : '../resources-data',
+ c_name : 'simple_resources')
+
+simple_res_exe = executable('simple-resources-test',
+ 'simple-main.c', simple_resources,
+ dependencies: gio)
+test('simple resource test', simple_res_exe)
+
+if glib.version() >= '2.48.2'
+ # This test cannot pass if GLib version is older than 2.48.2.
+ # Meson will raise an error if the user tries to use the 'dependencies'
+ # argument and the version of GLib is too old for generated resource
+ # dependencies to work correctly.
+ generated_resources = gnome.compile_resources('generated-resources',
+ 'generated.gresource.xml',
+ source_dir : '../resources-data',
+ c_name : 'generated_resources',
+ dependencies : [res3_txt, res4_txt])
+
+ generated_res_exe = executable('generated-resources-test',
+ 'generated-main.c', generated_resources,
+ dependencies: gio)
+ test('generated resource test', generated_res_exe)
+endif
diff --git a/test cases/frameworks/7 gnome/resources/myresource.gresource.xml b/test cases/frameworks/7 gnome/resources/myresource.gresource.xml
index b44c879..7a242d7 100644
--- a/test cases/frameworks/7 gnome/resources/myresource.gresource.xml
+++ b/test cases/frameworks/7 gnome/resources/myresource.gresource.xml
@@ -2,5 +2,8 @@
<gresources>
<gresource prefix="/com/example/myprog">
<file>res1.txt</file>
+ <file>subdir/res2.txt</file>
+ <file>res3.txt</file>
+ <file>subdir/res4.txt</file>
</gresource>
</gresources>
diff --git a/test cases/frameworks/7 gnome/resources/main.c b/test cases/frameworks/7 gnome/resources/simple-main.c
index 471f07e..3569901 100644
--- a/test cases/frameworks/7 gnome/resources/main.c
+++ b/test cases/frameworks/7 gnome/resources/simple-main.c
@@ -1,12 +1,12 @@
#include<stdio.h>
#include<string.h>
#include<gio/gio.h>
-#include"myresources.h"
+#include"simple-resources.h"
#define EXPECTED "This is a resource.\n"
int main(int argc, char **argv) {
- GResource *res = myres_get_resource();
+ GResource *res = simple_resources_get_resource();
GError *err = NULL;
GBytes *data = g_resources_lookup_data("/com/example/myprog/res1.txt",
G_RESOURCE_LOOKUP_FLAGS_NONE, &err);
@@ -20,7 +20,7 @@ int main(int argc, char **argv) {
(const char*)g_bytes_get_data(data, NULL));
return 1;
}
- fprintf(stderr, "All ok.\n");
+ fprintf(stdout, "All ok.\n");
g_bytes_unref(data);
g_resource_unref(res);
return 0;
diff --git a/test cases/frameworks/7 gnome/resources/simple.gresource.xml b/test cases/frameworks/7 gnome/resources/simple.gresource.xml
new file mode 100644
index 0000000..6e55910
--- /dev/null
+++ b/test cases/frameworks/7 gnome/resources/simple.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/com/example/myprog">
+ <file>res1.txt</file>
+ <file>subdir/res2.txt</file>
+ </gresource>
+</gresources>
diff --git a/test cases/linuxlike/5 dependency versions/meson.build b/test cases/linuxlike/5 dependency versions/meson.build
index a3ee335..1de87c8 100644
--- a/test cases/linuxlike/5 dependency versions/meson.build
+++ b/test cases/linuxlike/5 dependency versions/meson.build
@@ -6,6 +6,7 @@ zlib = dependency('zlib')
zlibver = dependency('zlib', version : '>1.0')
assert(zlib.version() == zlibver.version(), 'zlib versions did not match!')
# Find external dependency with conflicting version
+assert(zlib.type_name() == 'pkgconfig', 'zlib should be of type "pkgconfig" not ' + zlib.type_name())
zlibver = dependency('zlib', version : '<1.0', required : false)
assert(zlibver.found() == false, 'zlib <1.0 should not be found!')
@@ -16,6 +17,7 @@ dependency('somebrokenlib', version : '>=1.0', required : false)
# Find internal dependency without version
somelibver = dependency('somelib',
fallback : ['somelibnover', 'some_dep'])
+assert(somelibver.type_name() == 'internal', 'somelibver should be of type "internal", not ' + somelibver.type_name())
# Find an internal dependency again with the same name and a specific version
somelib = dependency('somelib',
version : '== 0.1',
@@ -30,3 +32,7 @@ somelibfail = dependency('somelib',
required : false,
fallback : ['somelibfail', 'some_dep'])
assert(somelibfail.found() == false, 'somelibfail found via wrong fallback')
+
+fakezlib_dep = dependency('zlib',
+ fallback : ['somelib', 'fakezlib_dep'])
+assert(fakezlib_dep.type_name() == 'internal', 'fakezlib_dep should be of type "internal", not ' + fakezlib_dep.type_name())
diff --git a/test cases/linuxlike/5 dependency versions/subprojects/somelib/meson.build b/test cases/linuxlike/5 dependency versions/subprojects/somelib/meson.build
index 049c58b..086e514 100644
--- a/test cases/linuxlike/5 dependency versions/subprojects/somelib/meson.build
+++ b/test cases/linuxlike/5 dependency versions/subprojects/somelib/meson.build
@@ -6,3 +6,6 @@ someinc = include_directories('.')
some_dep = declare_dependency(link_with : somelib,
include_directories : someinc)
+
+fakezlib_dep = declare_dependency(link_with : somelib,
+ include_directories : someinc)
diff --git a/tools/cmake2meson.py b/tools/cmake2meson.py
index 7465d45..a99ea50 100755
--- a/tools/cmake2meson.py
+++ b/tools/cmake2meson.py
@@ -279,15 +279,15 @@ class Converter:
defaultstr = ''
else:
if default == 'OFF':
- typestr = ' type : boolean,'
+ typestr = ' type : \'boolean\','
default = 'false'
elif default == 'ON':
default = 'true'
- typestr = ' type : boolean,'
+ typestr = ' type : \'boolean\','
else:
- typestr = ' type : string,'
+ typestr = ' type : \'string\','
defaultstr = ' value : %s,' % default
- line = "option(%s,%s%s description : '%s')\n" % (optname,
+ line = "option(%r,%s%s description : '%s')\n" % (optname,
typestr,
defaultstr,
description)