cmake: support cmake config file syntax (#6917)

* cmake: enhance support of cmake config file syntax

Enhance the cmakedefine support by accepting 2 or 3 tokens
in the conf line as mesondefine supports strictly 2 tokens

* fixup! cmake: enhance support of cmake config file syntax

* fixup! fixup! cmake: enhance support of cmake config file syntax
pull/6945/head
dabrain34 5 years ago committed by GitHub
parent 2008cb2109
commit 97a72a1c53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 60
      mesonbuild/mesonlib.py
  2. 50
      run_unittests.py

@ -877,7 +877,7 @@ def do_replacement(regex: T.Pattern[str], line: str, variable_format: str,
start_tag = '${'
backslash_tag = '\\${'
else:
assert variable_format == 'meson'
assert variable_format in ['meson', 'cmake@']
start_tag = '@'
backslash_tag = '\\@'
@ -908,11 +908,22 @@ def do_replacement(regex: T.Pattern[str], line: str, variable_format: str,
return var
return re.sub(regex, variable_replace, line), missing_variables
def do_define(regex: T.Pattern[str], line: str, confdata: 'ConfigurationData', variable_format: str) -> str:
def get_cmake_define(line: str, confdata: 'ConfigurationData') -> str:
arr = line.split()
define_value=[]
for token in arr[2:]:
try:
(v, desc) = confdata.get(token)
define_value += [v]
except KeyError:
define_value += [token]
return ' '.join(define_value)
def do_mesondefine(line: str, confdata: 'ConfigurationData') -> str:
arr = line.split()
if len(arr) != 2:
raise MesonException('#mesondefine does not contain exactly two tokens: %s' % line.strip())
if variable_format == 'meson' and len(arr) != 2:
raise MesonException('#mesondefine does not contain exactly two tokens: %s' % line.strip())
varname = arr[1]
try:
(v, desc) = confdata.get(varname)
@ -926,18 +937,27 @@ def do_mesondefine(line: str, confdata: 'ConfigurationData') -> str:
elif isinstance(v, int):
return '#define %s %d\n' % (varname, v)
elif isinstance(v, str):
return '#define %s %s\n' % (varname, v)
if variable_format == 'meson':
result = v
else:
result = get_cmake_define(line, confdata)
result = '#define %s %s\n' % (varname, result)
(result, missing_variable) = do_replacement(regex, result, variable_format, confdata)
return result
else:
raise MesonException('#mesondefine argument "%s" is of unknown type.' % varname)
def do_conf_str (data: list, confdata: 'ConfigurationData', variable_format: str,
encoding: str = 'utf-8') -> T.Tuple[T.List[str],T.Set[str], bool]:
def line_is_valid(line : str, variable_format: str):
if variable_format == 'meson':
if '#cmakedefine' in line:
return False
else: #cmake format
if '#mesondefine' in line:
return False
return True
def do_conf_file(src: str, dst: str, confdata: 'ConfigurationData', variable_format: str,
encoding: str = 'utf-8') -> T.Tuple[T.Set[str], bool]:
try:
with open(src, encoding=encoding, newline='') as f:
data = f.readlines()
except Exception as e:
raise MesonException('Could not read input file %s: %s' % (src, str(e)))
# Only allow (a-z, A-Z, 0-9, _, -) as valid characters for a define
# Also allow escaping '@' with '\@'
if variable_format in ['meson', 'cmake@']:
@ -959,13 +979,27 @@ def do_conf_file(src: str, dst: str, confdata: 'ConfigurationData', variable_for
for line in data:
if line.startswith(search_token):
confdata_useless = False
line = do_mesondefine(line, confdata)
line = do_define(regex, line, confdata, variable_format)
else:
if not line_is_valid(line,variable_format):
raise MesonException('Format "{}" mismatched'.format(variable_format))
line, missing = do_replacement(regex, line, variable_format, confdata)
missing_variables.update(missing)
if missing:
confdata_useless = False
result.append(line)
return result, missing_variables, confdata_useless
def do_conf_file(src: str, dst: str, confdata: 'ConfigurationData', variable_format: str,
encoding: str = 'utf-8') -> T.Tuple[T.Set[str], bool]:
try:
with open(src, encoding=encoding, newline='') as f:
data = f.readlines()
except Exception as e:
raise MesonException('Could not read input file %s: %s' % (src, str(e)))
(result, missing_variables, confdata_useless) = do_conf_str(data, confdata, variable_format, encoding)
dst_tmp = dst + '~'
try:
with open(dst_tmp, 'w', encoding=encoding, newline='') as f:

@ -62,7 +62,7 @@ from mesonbuild.environment import detect_ninja
from mesonbuild.mesonlib import MesonException, EnvironmentException
from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram
import mesonbuild.dependencies.base
from mesonbuild.build import Target
from mesonbuild.build import Target, ConfigurationData
import mesonbuild.modules.pkgconfig
from mesonbuild.mtest import TAPParser, TestResult
@ -1870,6 +1870,54 @@ class AllPlatformTests(BasePlatformTests):
self.assertEqual(conf_file('@VAR@\n@VAR@\n', confdata), 'foo\nfoo\n')
self.assertEqual(conf_file('@VAR@\r\n@VAR@\r\n', confdata), 'foo\r\nfoo\r\n')
def test_do_conf_file_by_format(self):
def conf_str(in_data, confdata, vformat):
(result, missing_variables, confdata_useless) = mesonbuild.mesonlib.do_conf_str(in_data, confdata, variable_format = vformat)
return '\n'.join(result)
def check_formats (confdata, result):
self.assertEqual(conf_str(['#mesondefine VAR'], confdata, 'meson'),result)
self.assertEqual(conf_str(['#cmakedefine VAR ${VAR}'], confdata, 'cmake'),result)
self.assertEqual(conf_str(['#cmakedefine VAR @VAR@'], confdata, 'cmake@'),result)
confdata = ConfigurationData()
# Key error as they do not exists
check_formats(confdata, '/* #undef VAR */\n')
# Check boolean
confdata.values = {'VAR': (False,'description')}
check_formats(confdata, '#undef VAR\n')
confdata.values = {'VAR': (True,'description')}
check_formats(confdata, '#define VAR\n')
# Check string
confdata.values = {'VAR': ('value','description')}
check_formats(confdata, '#define VAR value\n')
# Check integer
confdata.values = {'VAR': (10,'description')}
check_formats(confdata, '#define VAR 10\n')
# Check multiple string with cmake formats
confdata.values = {'VAR': ('value','description')}
self.assertEqual(conf_str(['#cmakedefine VAR xxx @VAR@ yyy @VAR@'], confdata, 'cmake@'),'#define VAR xxx value yyy value\n')
self.assertEqual(conf_str(['#define VAR xxx @VAR@ yyy @VAR@'], confdata, 'cmake@'),'#define VAR xxx value yyy value')
self.assertEqual(conf_str(['#cmakedefine VAR xxx ${VAR} yyy ${VAR}'], confdata, 'cmake'),'#define VAR xxx value yyy value\n')
self.assertEqual(conf_str(['#define VAR xxx ${VAR} yyy ${VAR}'], confdata, 'cmake'),'#define VAR xxx value yyy value')
# Handles meson format exceptions
# Unknown format
self.assertRaises(mesonbuild.mesonlib.MesonException, conf_str,['#mesondefine VAR xxx'], confdata, 'unknown_format')
# More than 2 params in mesondefine
self.assertRaises(mesonbuild.mesonlib.MesonException, conf_str,['#mesondefine VAR xxx'], confdata, 'meson')
# Mismatched line with format
self.assertRaises(mesonbuild.mesonlib.MesonException, conf_str,['#cmakedefine VAR'], confdata, 'meson')
self.assertRaises(mesonbuild.mesonlib.MesonException, conf_str,['#mesondefine VAR'], confdata, 'cmake')
self.assertRaises(mesonbuild.mesonlib.MesonException, conf_str,['#mesondefine VAR'], confdata, 'cmake@')
# Dict value in confdata
confdata.values = {'VAR': (['value'],'description')}
self.assertRaises(mesonbuild.mesonlib.MesonException, conf_str,['#mesondefine VAR'], confdata, 'meson')
def test_absolute_prefix_libdir(self):
'''
Tests that setting absolute paths for --prefix and --libdir work. Can't

Loading…
Cancel
Save