aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ci/azure-steps.yml3
-rw-r--r--docs/markdown/Kconfig-module.md52
-rw-r--r--docs/markdown/snippets/kconfig.md5
-rw-r--r--docs/markdown/snippets/multiple-cross-files.md3
-rw-r--r--docs/sitemap.txt1
-rw-r--r--mesonbuild/backend/backends.py3
-rw-r--r--mesonbuild/backend/ninjabackend.py6
-rw-r--r--mesonbuild/compilers/c.py34
-rw-r--r--mesonbuild/compilers/fortran.py4
-rw-r--r--mesonbuild/coredata.py58
-rw-r--r--mesonbuild/dependencies/base.py10
-rw-r--r--mesonbuild/envconfig.py10
-rw-r--r--mesonbuild/environment.py9
-rw-r--r--mesonbuild/interpreter.py7
-rw-r--r--mesonbuild/linkers.py9
-rw-r--r--mesonbuild/mesonlib.py10
-rw-r--r--mesonbuild/modules/unstable_kconfig.py72
-rw-r--r--mesonbuild/msetup.py4
-rw-r--r--mesonbuild/munstable_coredata.py5
-rw-r--r--mesonbuild/optinterpreter.py4
-rwxr-xr-xrun_project_tests.py1
-rwxr-xr-xrun_unittests.py35
-rw-r--r--test cases/kconfig/1 basic/.config3
-rw-r--r--test cases/kconfig/1 basic/meson.build16
-rw-r--r--test cases/kconfig/2 subdir/.config2
-rw-r--r--test cases/kconfig/2 subdir/dir/meson.build13
-rw-r--r--test cases/kconfig/2 subdir/meson.build4
-rw-r--r--test cases/kconfig/3 load_config files/dir/config2
-rw-r--r--test cases/kconfig/3 load_config files/dir/meson.build13
-rw-r--r--test cases/kconfig/3 load_config files/meson.build4
-rw-r--r--test cases/kconfig/4 load_config builddir/config2
-rw-r--r--test cases/kconfig/4 load_config builddir/meson.build14
-rw-r--r--test cases/unit/57 native file override/crossfile24
-rw-r--r--test cases/windows/5 resources/res/dummy.c0
-rw-r--r--test cases/windows/5 resources/res/meson.build4
35 files changed, 324 insertions, 102 deletions
diff --git a/ci/azure-steps.yml b/ci/azure-steps.yml
index 7e0f6fe..d0f6d09 100644
--- a/ci/azure-steps.yml
+++ b/ci/azure-steps.yml
@@ -172,5 +172,4 @@ steps:
- task: PublishBuildArtifacts@1
inputs:
artifactName: $(System.JobName)
- # publishing artifacts from PRs from a fork is currently blocked
- condition: eq(variables['system.pullrequest.isfork'], false)
+ condition: not(canceled())
diff --git a/docs/markdown/Kconfig-module.md b/docs/markdown/Kconfig-module.md
new file mode 100644
index 0000000..c361b5b
--- /dev/null
+++ b/docs/markdown/Kconfig-module.md
@@ -0,0 +1,52 @@
+---
+short-description: Unstable kconfig module
+authors:
+ - name: Mark Schulte, Paolo Bonzini
+ years: [2017, 2019]
+ has-copyright: false
+...
+
+# Unstable kconfig module
+
+This module parses Kconfig output files to allow use of kconfig
+configurations in meson projects.
+
+**Note**: this does not provide kconfig frontend tooling to generate a
+configuration. You still need something such as kconfig frontends (see
+link below) to parse your Kconfig files, and then (after you've
+choosen the configuration options), output a ".config" file.
+
+ [kconfig-frontends]: http://ymorin.is-a-geek.org/projects/kconfig-frontends
+
+## Usage
+
+The module may be imported as follows:
+
+``` meson
+kconfig = import('unstable-kconfig')
+```
+
+The following functions will then be available as methods on the object
+with the name `kconfig`. You can, of course, replace the name
+`kconfig` with anything else.
+
+### kconfig.load()
+
+This function loads a kconfig output file and returns a dictionary object.
+
+`kconfig.load()` makes no attempt at parsing the values in the
+file. Therefore, true boolean values will be represented as the string "y"
+and integer values will have to be converted with `.to_int()`.
+
+Kconfig frontends usually have ".config" as the default name for the
+configuration file. However, placing the configuration file in the source
+directory limits the user to one configuration per source directory.
+In order to allow separate configurations for each build directory, as is
+the Meson standard, `meson.build` should not hardcode ".config" as the
+argument to `kconfig.load()`, and should instead make the argument to
+`kconfig.load()` a [project build option](Build-options.md).
+
+* The first (and only) argument is the path to the configuration file to
+ load (usually ".config").
+
+**Returns**: a [dictionary object](Reference-manual.md#dictionary-object).
diff --git a/docs/markdown/snippets/kconfig.md b/docs/markdown/snippets/kconfig.md
new file mode 100644
index 0000000..d4d5c9b
--- /dev/null
+++ b/docs/markdown/snippets/kconfig.md
@@ -0,0 +1,5 @@
+## New module to parse kconfig output files
+
+The new module `unstable-kconfig` adds the ability to parse and use kconfig output
+files from `meson.build`.
+
diff --git a/docs/markdown/snippets/multiple-cross-files.md b/docs/markdown/snippets/multiple-cross-files.md
new file mode 100644
index 0000000..de229be
--- /dev/null
+++ b/docs/markdown/snippets/multiple-cross-files.md
@@ -0,0 +1,3 @@
+## Multipe cross files can be specified
+
+`--cross-file` can be passed multiple times, with the configuration files overlaying the same way as `--native-file`.
diff --git a/docs/sitemap.txt b/docs/sitemap.txt
index bea2a31..2e6eb68 100644
--- a/docs/sitemap.txt
+++ b/docs/sitemap.txt
@@ -45,6 +45,7 @@ index.md
Simd-module.md
Windows-module.md
Cuda-module.md
+ Kconfig-module.md
Java.md
Vala.md
D.md
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 3ca2f99..d69091b 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -786,8 +786,7 @@ class Backend:
deps = [os.path.join(self.build_to_src, df)
for df in self.interpreter.get_build_def_files()]
if self.environment.is_cross_build():
- deps.append(os.path.join(self.build_to_src,
- self.environment.coredata.cross_file))
+ deps.extend(self.environment.coredata.cross_files)
deps.append('meson-private/coredata.dat')
if os.path.exists(os.path.join(self.environment.get_source_dir(), 'meson_options.txt')):
deps.append(os.path.join(self.build_to_src, 'meson_options.txt'))
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 9e4ba0f..7f36b7b 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -31,7 +31,7 @@ from .. import dependencies
from .. import compilers
from ..compilers import CompilerArgs, CCompiler, VisualStudioCCompiler, FortranCompiler
from ..linkers import ArLinker
-from ..mesonlib import File, MachineChoice, MesonException, OrderedSet
+from ..mesonlib import File, MachineChoice, MesonException, OrderedSet, LibType
from ..mesonlib import get_compiler_for_source, has_path_sep
from .backends import CleanTrees
from ..build import InvalidArguments
@@ -2401,8 +2401,8 @@ rule FORTRAN_DEP_HACK%s
# TODO The get_library_naming requirement currently excludes link targets that use d or fortran as their main linker
if hasattr(linker, 'get_library_naming'):
search_dirs = tuple(search_dirs) + linker.get_library_dirs(self.environment)
- static_patterns = linker.get_library_naming(self.environment, 'static', strict=True)
- shared_patterns = linker.get_library_naming(self.environment, 'shared', strict=True)
+ static_patterns = linker.get_library_naming(self.environment, LibType.STATIC, strict=True)
+ shared_patterns = linker.get_library_naming(self.environment, LibType.SHARED, strict=True)
for libname in libs:
# be conservative and record most likely shared and static resolution, because we don't know exactly
# which one the linker will prefer
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 2983ce7..4294bb1 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -27,7 +27,7 @@ from . import compilers
from ..mesonlib import (
EnvironmentException, MachineChoice, MesonException, Popen_safe, listify,
version_compare, for_windows, for_darwin, for_cygwin, for_haiku,
- for_openbsd, darwin_get_object_archs
+ for_openbsd, darwin_get_object_archs, LibType
)
from .c_function_attributes import C_FUNC_ATTRIBUTES
@@ -903,7 +903,7 @@ class CCompiler(Compiler):
patterns.append(p + '{}.so.[0-9]*.[0-9]*')
return patterns
- def get_library_naming(self, env, libtype, strict=False):
+ def get_library_naming(self, env, libtype: LibType, strict=False):
'''
Get library prefixes and suffixes for the target platform ordered by
priority
@@ -936,18 +936,17 @@ class CCompiler(Compiler):
# Linux/BSDs
shlibext = ['so']
# Search priority
- if libtype == 'shared-static':
+ if libtype is LibType.PREFER_SHARED:
patterns = self._get_patterns(env, prefixes, shlibext, True)
patterns.extend([x for x in self._get_patterns(env, prefixes, stlibext, False) if x not in patterns])
- elif libtype == 'static-shared':
+ elif libtype is LibType.PREFER_STATIC:
patterns = self._get_patterns(env, prefixes, stlibext, False)
patterns.extend([x for x in self._get_patterns(env, prefixes, shlibext, True) if x not in patterns])
- elif libtype == 'shared':
+ elif libtype is LibType.SHARED:
patterns = self._get_patterns(env, prefixes, shlibext, True)
- elif libtype == 'static':
- patterns = self._get_patterns(env, prefixes, stlibext, False)
else:
- raise AssertionError('BUG: unknown libtype {!r}'.format(libtype))
+ assert libtype is LibType.STATIC
+ patterns = self._get_patterns(env, prefixes, stlibext, False)
return tuple(patterns)
@staticmethod
@@ -1009,13 +1008,13 @@ class CCompiler(Compiler):
'''
return self.sizeof('void *', '', env) == 8
- def find_library_real(self, libname, env, extra_dirs, code, libtype):
+ def find_library_real(self, libname, env, extra_dirs, code, libtype: LibType):
# First try if we can just add the library as -l.
# Gcc + co seem to prefer builtin lib dirs to -L dirs.
# Only try to find std libs if no extra dirs specified.
# The built-in search procedure will always favour .so and then always
- # search for .a. This is only allowed if libtype is 'shared-static'
- if ((not extra_dirs and libtype == 'shared-static') or
+ # search for .a. This is only allowed if libtype is LibType.PREFER_SHARED
+ if ((not extra_dirs and libtype is LibType.PREFER_SHARED) or
libname in self.internal_libs):
args = ['-l' + libname]
largs = self.linker_to_compiler_args(self.get_allow_undefined_link_args())
@@ -1049,7 +1048,7 @@ class CCompiler(Compiler):
return [trial.as_posix()]
return None
- def find_library_impl(self, libname, env, extra_dirs, code, libtype):
+ def find_library_impl(self, libname, env, extra_dirs, code, libtype: LibType):
# These libraries are either built-in or invalid
if libname in self.ignore_libs:
return []
@@ -1065,7 +1064,7 @@ class CCompiler(Compiler):
return None
return value[:]
- def find_library(self, libname, env, extra_dirs, libtype='shared-static'):
+ def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED):
code = 'int main(int argc, char **argv) { return 0; }'
return self.find_library_impl(libname, env, extra_dirs, code, libtype)
@@ -1397,6 +1396,13 @@ class VisualStudioCCompiler(CCompiler):
self.base_options = ['b_pch', 'b_ndebug', 'b_vscrt'] # FIXME add lto, pgo and the like
self.target = target
self.is_64 = ('x64' in target) or ('x86_64' in target)
+ # do some canonicalization of target machine
+ if 'x86_64' in target:
+ self.machine = 'x64'
+ elif '86' in target:
+ self.machine = 'x86'
+ else:
+ self.machine = target
# Override CCompiler.get_always_args
def get_always_args(self):
@@ -1473,7 +1479,7 @@ class VisualStudioCCompiler(CCompiler):
return ['/nologo']
def get_linker_output_args(self, outputname):
- return ['/OUT:' + outputname]
+ return ['/MACHINE:' + self.machine, '/OUT:' + outputname]
def get_linker_search_args(self, dirname):
return ['/LIBPATH:' + dirname]
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 738a5c6..15234ee 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -31,7 +31,7 @@ from .compilers import (
PGICompiler
)
-from mesonbuild.mesonlib import EnvironmentException, is_osx
+from mesonbuild.mesonlib import EnvironmentException, is_osx, LibType
class FortranCompiler(Compiler):
@@ -241,7 +241,7 @@ class FortranCompiler(Compiler):
def find_library_impl(self, *args):
return CCompiler.find_library_impl(self, *args)
- def find_library(self, libname, env, extra_dirs, libtype='shared-static'):
+ def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED):
code = '''program main
call exit(0)
end program main'''
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index fba90fa..cb50961 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -211,8 +211,8 @@ class UserFeatureOption(UserComboOption):
return self.value == 'auto'
-def load_configs(filenames):
- """Load native files."""
+def load_configs(filenames, subdir):
+ """Load configuration files from a named subdirectory."""
def gen():
for f in filenames:
f = os.path.expanduser(os.path.expandvars(f))
@@ -225,7 +225,7 @@ def load_configs(filenames):
os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share')),
] + os.environ.get('XDG_DATA_DIRS', '/usr/local/share:/usr/share').split(':')
for path in paths:
- path_to_try = os.path.join(path, 'meson', 'native', f)
+ path_to_try = os.path.join(path, 'meson', subdir, f)
if os.path.isfile(path_to_try):
yield path_to_try
break
@@ -265,7 +265,7 @@ class CoreData:
self.compiler_options = PerMachine({}, {}, {})
self.base_options = {}
self.external_preprocess_args = PerMachine({}, {}, {}) # CPPFLAGS only
- self.cross_file = self.__load_cross_file(options.cross_file)
+ self.cross_files = self.__load_config_files(options.cross_file)
self.compilers = OrderedDict()
self.cross_compilers = OrderedDict()
self.deps = OrderedDict()
@@ -276,57 +276,19 @@ class CoreData:
@staticmethod
def __load_config_files(filenames):
+ # Need to try and make the passed filenames absolute because when the
+ # files are parsed later we'll have chdir()d.
if not filenames:
return []
filenames = [os.path.abspath(os.path.expanduser(os.path.expanduser(f)))
for f in filenames]
return filenames
- @staticmethod
- def __load_cross_file(filename):
- """Try to load the cross file.
-
- If the filename is None return None. If the filename is an absolute
- (after resolving variables and ~), return that absolute path. Next,
- check if the file is relative to the current source dir. If the path
- still isn't resolved do the following:
- Windows:
- - Error
- *:
- - $XDG_DATA_HOME/meson/cross (or ~/.local/share/meson/cross if
- undefined)
- - $XDG_DATA_DIRS/meson/cross (or
- /usr/local/share/meson/cross:/usr/share/meson/cross if undefined)
- - Error
-
- Non-Windows follows the Linux path and will honor XDG_* if set. This
- simplifies the implementation somewhat.
- """
- if filename is None:
- return None
- filename = os.path.expanduser(os.path.expandvars(filename))
- if os.path.isabs(filename):
- return filename
- path_to_try = os.path.abspath(filename)
- if os.path.isfile(path_to_try):
- return path_to_try
- if sys.platform != 'win32':
- paths = [
- os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share')),
- ] + os.environ.get('XDG_DATA_DIRS', '/usr/local/share:/usr/share').split(':')
- for path in paths:
- path_to_try = os.path.join(path, 'meson', 'cross', filename)
- if os.path.isfile(path_to_try):
- return path_to_try
- raise MesonException('Cannot find specified cross file: ' + filename)
-
- raise MesonException('Cannot find specified cross file: ' + filename)
-
def libdir_cross_fixup(self):
# By default set libdir to "lib" when cross compiling since
# getting the "system default" is always wrong on multiarch
# platforms as it gets a value like lib/x86_64-linux-gnu.
- if self.cross_file is not None:
+ if self.cross_files:
self.builtins['libdir'].value = 'lib'
def sanitize_prefix(self, prefix):
@@ -642,8 +604,8 @@ def read_cmd_line_file(build_dir, options):
options.cmd_line_options = d
properties = config['properties']
- if options.cross_file is None:
- options.cross_file = properties.get('cross_file', None)
+ if not options.cross_file:
+ options.cross_file = ast.literal_eval(properties.get('cross_file', '[]'))
if not options.native_file:
# This will be a string in the form: "['first', 'second', ...]", use
# literal_eval to get it into the list of strings.
@@ -654,7 +616,7 @@ def write_cmd_line_file(build_dir, options):
config = CmdLineFileParser()
properties = {}
- if options.cross_file is not None:
+ if options.cross_file:
properties['cross_file'] = options.cross_file
if options.native_file:
properties['native_file'] = options.native_file
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 8bd3b68..4e61f4c 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -36,7 +36,7 @@ from ..compilers import clib_langs
from ..environment import BinaryTable, Environment, MachineInfo
from ..mesonlib import MachineChoice, MesonException, OrderedSet, PerMachine
from ..mesonlib import Popen_safe, version_compare_many, version_compare, listify
-from ..mesonlib import Version
+from ..mesonlib import Version, LibType
# These must be defined in this file to avoid cyclical references.
packages = {}
@@ -700,7 +700,7 @@ class PkgConfigDependency(ExternalDependency):
libs_found = OrderedSet()
# Track not-found libraries to know whether to add library paths
libs_notfound = []
- libtype = 'static' if self.static else 'shared-static'
+ libtype = LibType.STATIC if self.static else LibType.PREFER_SHARED
# Generate link arguments for this library
link_args = []
for lib in full_args:
@@ -1990,6 +1990,12 @@ class ExternalProgram:
# We know what python3 is, we're running on it
if len(commands) > 0 and commands[0] == 'python3':
commands = mesonlib.python_command + commands[1:]
+ else:
+ # Replace python3 with the actual python3 that we are using
+ if commands[0] == '/usr/bin/env' and commands[1] == 'python3':
+ commands = mesonlib.python_command + commands[2:]
+ elif commands[0].split('/')[-1] == 'python3':
+ commands = mesonlib.python_command + commands[1:]
return commands + [script]
except Exception as e:
mlog.debug(e)
diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py
index 609899c..e211945 100644
--- a/mesonbuild/envconfig.py
+++ b/mesonbuild/envconfig.py
@@ -69,16 +69,6 @@ CPU_FAMILES_64_BIT = [
class MesonConfigFile:
@classmethod
- def parse_datafile(cls, filename):
- config = configparser.ConfigParser()
- try:
- with open(filename, 'r') as f:
- config.read_file(f, filename)
- except FileNotFoundError:
- raise EnvironmentException('File not found: %s.' % filename)
- return cls.from_config_parser(config)
-
- @classmethod
def from_config_parser(cls, parser: configparser.ConfigParser):
out = {}
# This is a bit hackish at the moment.
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index ac6e70a..d0dccf4 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -408,12 +408,13 @@ class Environment:
if self.coredata.config_files is not None:
config = MesonConfigFile.from_config_parser(
- coredata.load_configs(self.coredata.config_files))
+ coredata.load_configs(self.coredata.config_files, 'native'))
self.binaries.build = BinaryTable(config.get('binaries', {}))
self.paths.build = Directories(**config.get('paths', {}))
- if self.coredata.cross_file is not None:
- config = MesonConfigFile.parse_datafile(self.coredata.cross_file)
+ if self.coredata.cross_files:
+ config = MesonConfigFile.from_config_parser(
+ coredata.load_configs(self.coredata.cross_files, 'cross'))
self.properties.host = Properties(config.get('properties', {}), False)
self.binaries.host = BinaryTable(config.get('binaries', {}), False)
if 'host_machine' in config:
@@ -1179,7 +1180,7 @@ class Environment:
popen_exceptions[' '.join(linker + [arg])] = e
continue
if '/OUT:' in out.upper() or '/OUT:' in err.upper():
- return VisualStudioLinker(linker)
+ return VisualStudioLinker(linker, getattr(compiler, 'machine', None))
if p.returncode == 0 and ('armar' in linker or 'armar.exe' in linker):
return ArmarLinker(linker)
if 'DMD32 D Compiler' in out or 'DMD64 D Compiler' in out:
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 3c3cfae..08f10a2 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -1493,11 +1493,11 @@ class CompilerHolder(InterpreterObject):
for i in search_dirs:
if not os.path.isabs(i):
raise InvalidCode('Search directory %s is not an absolute path.' % i)
- libtype = 'shared-static'
+ libtype = mesonlib.LibType.PREFER_SHARED
if 'static' in kwargs:
if not isinstance(kwargs['static'], bool):
raise InterpreterException('static must be a boolean')
- libtype = 'static' if kwargs['static'] else 'shared'
+ libtype = mesonlib.LibType.STATIC if kwargs['static'] else mesonlib.LibType.SHARED
linkargs = self.compiler.find_library(libname, self.environment, search_dirs, libtype)
if required and not linkargs:
raise InterpreterException(
@@ -2119,6 +2119,9 @@ class Interpreter(InterpreterBase):
def holderify(self, item):
if isinstance(item, list):
return [self.holderify(x) for x in item]
+ if isinstance(item, dict):
+ return {k: self.holderify(v) for k, v in item.items()}
+
if isinstance(item, build.CustomTarget):
return CustomTargetHolder(item, self)
elif isinstance(item, (int, str, bool)) or item is None:
diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py
index 5432514..c6302bf 100644
--- a/mesonbuild/linkers.py
+++ b/mesonbuild/linkers.py
@@ -26,8 +26,9 @@ class StaticLinker:
class VisualStudioLinker(StaticLinker):
always_args = ['/NOLOGO']
- def __init__(self, exelist):
+ def __init__(self, exelist, machine):
self.exelist = exelist
+ self.machine = machine
def get_exelist(self):
return self.exelist[:]
@@ -39,7 +40,11 @@ class VisualStudioLinker(StaticLinker):
return []
def get_output_args(self, target):
- return ['/OUT:' + target]
+ args = []
+ if self.machine:
+ args += ['/MACHINE:' + self.machine]
+ args += ['/OUT:' + target]
+ return args
def get_coverage_link_args(self):
return []
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 0afc21b..25e15e4 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -1274,3 +1274,13 @@ def relpath(path, start):
return os.path.relpath(path, start)
except ValueError:
return path
+
+
+class LibType(Enum):
+
+ """Enumeration for library types."""
+
+ SHARED = 0
+ STATIC = 1
+ PREFER_SHARED = 2
+ PREFER_STATIC = 3
diff --git a/mesonbuild/modules/unstable_kconfig.py b/mesonbuild/modules/unstable_kconfig.py
new file mode 100644
index 0000000..1639eed
--- /dev/null
+++ b/mesonbuild/modules/unstable_kconfig.py
@@ -0,0 +1,72 @@
+# Copyright 2017, 2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from . import ExtensionModule
+
+from .. import mesonlib
+from ..mesonlib import typeslistify
+from ..interpreterbase import FeatureNew, noKwargs
+from ..interpreter import InvalidCode
+
+import os
+
+class KconfigModule(ExtensionModule):
+
+ @FeatureNew('Kconfig Module', '0.51.0')
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.snippets.add('load')
+
+ def _load_file(self, path_to_config):
+ result = dict()
+ try:
+ with open(path_to_config) as f:
+ for line in f:
+ if '#' in line:
+ comment_idx = line.index('#')
+ line = line[:comment_idx]
+ line = line.strip()
+ try:
+ name, val = line.split('=', 1)
+ except ValueError:
+ continue
+ result[name.strip()] = val.strip()
+ except IOError as e:
+ raise mesonlib.MesonException('Failed to load {}: {}'.format(path_to_config, e))
+
+ return result
+
+ @noKwargs
+ def load(self, interpreter, state, args, kwargs):
+ sources = typeslistify(args, (str, mesonlib.File))
+ if len(sources) != 1:
+ raise InvalidCode('load takes only one file input.')
+
+ s = sources[0]
+ if isinstance(s, mesonlib.File):
+ # kconfig input is processed at "meson setup" time, not during
+ # the build, so it cannot reside in the build directory.
+ if s.is_built:
+ raise InvalidCode('kconfig input must be a source file.')
+ s = s.relative_name()
+
+ s = os.path.join(interpreter.environment.source_dir, s)
+ if s not in interpreter.build_def_files:
+ interpreter.build_def_files.append(s)
+
+ return self._load_file(s)
+
+
+def initialize(*args, **kwargs):
+ return KconfigModule(*args, **kwargs)
diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py
index 023afdb..6e8ca83 100644
--- a/mesonbuild/msetup.py
+++ b/mesonbuild/msetup.py
@@ -29,7 +29,9 @@ from .mesonlib import MesonException
def add_arguments(parser):
coredata.register_builtin_arguments(parser)
- parser.add_argument('--cross-file', default=None,
+ parser.add_argument('--cross-file',
+ default=[],
+ action='append',
help='File describing cross compilation environment.')
parser.add_argument('--native-file',
default=[],
diff --git a/mesonbuild/munstable_coredata.py b/mesonbuild/munstable_coredata.py
index 78f3f34..913f942 100644
--- a/mesonbuild/munstable_coredata.py
+++ b/mesonbuild/munstable_coredata.py
@@ -81,8 +81,9 @@ def run(options):
print('Last seen PKGCONFIG enviroment variable value: ' + v)
elif k == 'version':
print('Meson version: ' + v)
- elif k == 'cross_file':
- print('Cross File: ' + (v or 'None'))
+ elif k == 'cross_files':
+ if v:
+ print('Cross File: ' + ' '.join(v))
elif k == 'config_files':
if v:
print('Native File: ' + ' '.join(v))
diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py
index 8967a53..85f6897 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -22,6 +22,7 @@ from . import compilers
forbidden_option_names = coredata.get_builtin_options()
forbidden_prefixes = [lang + '_' for lang in compilers.all_languages] + ['b_', 'backend_']
+reserved_prefixes = ['cross_']
def is_invalid_name(name):
if name in forbidden_option_names:
@@ -29,6 +30,9 @@ def is_invalid_name(name):
pref = name.split('_')[0] + '_'
if pref in forbidden_prefixes:
return True
+ if pref in reserved_prefixes:
+ from . import mlog
+ mlog.deprecation('Option uses prefix "%s", which is reserved for Meson. This will become an error in the future.' % pref)
return False
class OptionException(mesonlib.MesonException):
diff --git a/run_project_tests.py b/run_project_tests.py
index 96fe99a..467d522 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -551,6 +551,7 @@ def detect_tests_to_run():
('failing-meson', 'failing', False),
('failing-build', 'failing build', False),
('failing-test', 'failing test', False),
+ ('kconfig', 'kconfig', False),
('platform-osx', 'osx', not mesonlib.is_osx()),
('platform-windows', 'windows', not mesonlib.is_windows() and not mesonlib.is_cygwin()),
diff --git a/run_unittests.py b/run_unittests.py
index 0b2164f..f0410ab 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -47,7 +47,7 @@ from mesonbuild.ast import AstInterpreter
from mesonbuild.mesonlib import (
is_windows, is_osx, is_cygwin, is_dragonflybsd, is_openbsd, is_haiku,
windows_proof_rmtree, python_command, version_compare,
- BuildDirLock, Version, PerMachine
+ BuildDirLock, Version, PerMachine, LibType
)
from mesonbuild.environment import detect_ninja
from mesonbuild.mesonlib import MesonException, EnvironmentException
@@ -612,7 +612,7 @@ class InternalTests(unittest.TestCase):
configfile.flush()
configfile.close()
opts = get_fake_options()
- opts.cross_file = configfilename
+ opts.cross_file = (configfilename,)
env = get_fake_env(opts=opts)
detected_value = env.need_exe_wrapper()
os.unlink(configfilename)
@@ -627,7 +627,7 @@ class InternalTests(unittest.TestCase):
config.write(configfile)
configfile.close()
opts = get_fake_options()
- opts.cross_file = configfilename
+ opts.cross_file = (configfilename,)
env = get_fake_env(opts=opts)
forced_value = env.need_exe_wrapper()
os.unlink(configfilename)
@@ -702,13 +702,13 @@ class InternalTests(unittest.TestCase):
stc = patterns[platform]['static']
shrstc = shr + tuple([x for x in stc if x not in shr])
stcshr = stc + tuple([x for x in shr if x not in stc])
- p = cc.get_library_naming(env, 'shared')
+ p = cc.get_library_naming(env, LibType.SHARED)
self.assertEqual(p, shr)
- p = cc.get_library_naming(env, 'static')
+ p = cc.get_library_naming(env, LibType.STATIC)
self.assertEqual(p, stc)
- p = cc.get_library_naming(env, 'static-shared')
+ p = cc.get_library_naming(env, LibType.PREFER_STATIC)
self.assertEqual(p, stcshr)
- p = cc.get_library_naming(env, 'shared-static')
+ p = cc.get_library_naming(env, LibType.PREFER_SHARED)
self.assertEqual(p, shrstc)
# Test find library by mocking up openbsd
if platform != 'openbsd':
@@ -724,7 +724,7 @@ class InternalTests(unittest.TestCase):
f.write('')
with open(os.path.join(tmpdir, 'libfoo.so.70.0.so.1'), 'w') as f:
f.write('')
- found = cc.find_library_real('foo', env, [tmpdir], '', 'shared-static')
+ found = cc.find_library_real('foo', env, [tmpdir], '', LibType.PREFER_SHARED)
self.assertEqual(os.path.basename(found[0]), 'libfoo.so.54.0')
def test_find_library_patterns(self):
@@ -5871,6 +5871,25 @@ class CrossFileTests(BasePlatformTests):
'-Ddef_sharedstatedir=sharedstatebar',
'-Ddef_sysconfdir=sysconfbar'])
+ def test_cross_file_dirs_chain(self):
+ # crossfile2 overrides crossfile overrides nativefile
+ testcase = os.path.join(self.unit_test_dir, '57 native file override')
+ self.init(testcase, default_args=False,
+ extra_args=['--native-file', os.path.join(testcase, 'nativefile'),
+ '--cross-file', os.path.join(testcase, 'crossfile'),
+ '--cross-file', os.path.join(testcase, 'crossfile2'),
+ '-Ddef_bindir=binbar2',
+ '-Ddef_datadir=databar',
+ '-Ddef_includedir=includebar',
+ '-Ddef_infodir=infobar',
+ '-Ddef_libdir=libbar',
+ '-Ddef_libexecdir=libexecbar',
+ '-Ddef_localedir=localebar',
+ '-Ddef_localstatedir=localstatebar',
+ '-Ddef_mandir=manbar',
+ '-Ddef_sbindir=sbinbar',
+ '-Ddef_sharedstatedir=sharedstatebar',
+ '-Ddef_sysconfdir=sysconfbar'])
class TAPParserTests(unittest.TestCase):
def assert_test(self, events, **kwargs):
diff --git a/test cases/kconfig/1 basic/.config b/test cases/kconfig/1 basic/.config
new file mode 100644
index 0000000..071d185
--- /dev/null
+++ b/test cases/kconfig/1 basic/.config
@@ -0,0 +1,3 @@
+CONFIG_VAL1=y
+# CONFIG_VAL2 is not set
+CONFIG_VAL_VAL=4
diff --git a/test cases/kconfig/1 basic/meson.build b/test cases/kconfig/1 basic/meson.build
new file mode 100644
index 0000000..5dc8d19
--- /dev/null
+++ b/test cases/kconfig/1 basic/meson.build
@@ -0,0 +1,16 @@
+project('kconfig basic test')
+
+k = import('unstable-kconfig')
+conf = k.load('.config')
+
+if not conf.has_key('CONFIG_VAL1')
+ error('Expected CONFIG_VAL1 to be set, but it wasn\'t')
+endif
+
+if conf.has_key('CONFIG_VAL2')
+ error('Expected CONFIG_VAL2 not be set, but it was')
+endif
+
+if conf.get('CONFIG_VAL_VAL').to_int() != 4
+ error('Expected CONFIG_VAL_VAL to be 4')
+endif
diff --git a/test cases/kconfig/2 subdir/.config b/test cases/kconfig/2 subdir/.config
new file mode 100644
index 0000000..0599d46
--- /dev/null
+++ b/test cases/kconfig/2 subdir/.config
@@ -0,0 +1,2 @@
+CONFIG_IS_SET=y
+# CONFIG_NOT_IS_SET is not set
diff --git a/test cases/kconfig/2 subdir/dir/meson.build b/test cases/kconfig/2 subdir/dir/meson.build
new file mode 100644
index 0000000..12f1502
--- /dev/null
+++ b/test cases/kconfig/2 subdir/dir/meson.build
@@ -0,0 +1,13 @@
+
+k = import('unstable-kconfig')
+
+conf = k.load(meson.source_root() / '.config')
+
+if not conf.has_key('CONFIG_IS_SET')
+ error('Expected CONFIG_IS_SET to be set, but it wasn\'t')
+endif
+
+if conf.has_key('CONFIG_NOT_IS_SET')
+ error('Expected CONFIG_NOT_IS_SET not be set, but it was')
+endif
+
diff --git a/test cases/kconfig/2 subdir/meson.build b/test cases/kconfig/2 subdir/meson.build
new file mode 100644
index 0000000..1245b18
--- /dev/null
+++ b/test cases/kconfig/2 subdir/meson.build
@@ -0,0 +1,4 @@
+project('kconfig subdir test')
+
+# Test into sub directory
+subdir('dir')
diff --git a/test cases/kconfig/3 load_config files/dir/config b/test cases/kconfig/3 load_config files/dir/config
new file mode 100644
index 0000000..0599d46
--- /dev/null
+++ b/test cases/kconfig/3 load_config files/dir/config
@@ -0,0 +1,2 @@
+CONFIG_IS_SET=y
+# CONFIG_NOT_IS_SET is not set
diff --git a/test cases/kconfig/3 load_config files/dir/meson.build b/test cases/kconfig/3 load_config files/dir/meson.build
new file mode 100644
index 0000000..d7b8d44
--- /dev/null
+++ b/test cases/kconfig/3 load_config files/dir/meson.build
@@ -0,0 +1,13 @@
+
+k = import('unstable-kconfig')
+
+conf = k.load(files('config'))
+
+if not conf.has_key('CONFIG_IS_SET')
+ error('Expected CONFIG_IS_SET to be set, but it wasn\'t')
+endif
+
+if conf.has_key('CONFIG_NOT_IS_SET')
+ error('Expected CONFIG_NOT_IS_SET not be set, but it was')
+endif
+
diff --git a/test cases/kconfig/3 load_config files/meson.build b/test cases/kconfig/3 load_config files/meson.build
new file mode 100644
index 0000000..1245b18
--- /dev/null
+++ b/test cases/kconfig/3 load_config files/meson.build
@@ -0,0 +1,4 @@
+project('kconfig subdir test')
+
+# Test into sub directory
+subdir('dir')
diff --git a/test cases/kconfig/4 load_config builddir/config b/test cases/kconfig/4 load_config builddir/config
new file mode 100644
index 0000000..0599d46
--- /dev/null
+++ b/test cases/kconfig/4 load_config builddir/config
@@ -0,0 +1,2 @@
+CONFIG_IS_SET=y
+# CONFIG_NOT_IS_SET is not set
diff --git a/test cases/kconfig/4 load_config builddir/meson.build b/test cases/kconfig/4 load_config builddir/meson.build
new file mode 100644
index 0000000..93136ba
--- /dev/null
+++ b/test cases/kconfig/4 load_config builddir/meson.build
@@ -0,0 +1,14 @@
+project('kconfig builddir test')
+
+k = import('unstable-kconfig')
+
+configure_file(input: 'config', output: 'out-config', copy: true)
+conf = k.load(meson.build_root() / 'out-config')
+
+if not conf.has_key('CONFIG_IS_SET')
+ error('Expected CONFIG_IS_SET to be set, but it wasn\'t')
+endif
+
+if conf.has_key('CONFIG_NOT_IS_SET')
+ error('Expected CONFIG_NOT_IS_SET not be set, but it was')
+endif
diff --git a/test cases/unit/57 native file override/crossfile2 b/test cases/unit/57 native file override/crossfile2
new file mode 100644
index 0000000..70946c9
--- /dev/null
+++ b/test cases/unit/57 native file override/crossfile2
@@ -0,0 +1,4 @@
+[paths]
+bindir = 'binbar2'
+
+; vim: ft=dosini
diff --git a/test cases/windows/5 resources/res/dummy.c b/test cases/windows/5 resources/res/dummy.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/windows/5 resources/res/dummy.c
diff --git a/test cases/windows/5 resources/res/meson.build b/test cases/windows/5 resources/res/meson.build
index 6d501a2..160d651 100644
--- a/test cases/windows/5 resources/res/meson.build
+++ b/test cases/windows/5 resources/res/meson.build
@@ -3,3 +3,7 @@ win = import('windows')
res = win.compile_resources('myres.rc',
depend_files: 'sample.ico',
include_directories : inc)
+
+# test that with MSVC tools, LIB/LINK invokes CVTRES with correct /MACHINE
+static_library('reslib', res, 'dummy.c')
+shared_library('shreslib', res, 'dummy.c')