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 = '${' start_tag = '${'
backslash_tag = '\\${' backslash_tag = '\\${'
else: else:
assert variable_format == 'meson' assert variable_format in ['meson', 'cmake@']
start_tag = '@' start_tag = '@'
backslash_tag = '\\@' backslash_tag = '\\@'
@ -908,11 +908,22 @@ def do_replacement(regex: T.Pattern[str], line: str, variable_format: str,
return var return var
return re.sub(regex, variable_replace, line), missing_variables 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() arr = line.split()
if len(arr) != 2: if variable_format == 'meson' and len(arr) != 2:
raise MesonException('#mesondefine does not contain exactly two tokens: %s' % line.strip()) raise MesonException('#mesondefine does not contain exactly two tokens: %s' % line.strip())
varname = arr[1] varname = arr[1]
try: try:
(v, desc) = confdata.get(varname) (v, desc) = confdata.get(varname)
@ -926,18 +937,27 @@ def do_mesondefine(line: str, confdata: 'ConfigurationData') -> str:
elif isinstance(v, int): elif isinstance(v, int):
return '#define %s %d\n' % (varname, v) return '#define %s %d\n' % (varname, v)
elif isinstance(v, str): 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: else:
raise MesonException('#mesondefine argument "%s" is of unknown type.' % varname) 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 # Only allow (a-z, A-Z, 0-9, _, -) as valid characters for a define
# Also allow escaping '@' with '\@' # Also allow escaping '@' with '\@'
if variable_format in ['meson', 'cmake@']: 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: for line in data:
if line.startswith(search_token): if line.startswith(search_token):
confdata_useless = False confdata_useless = False
line = do_mesondefine(line, confdata) line = do_define(regex, line, confdata, variable_format)
else: 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) line, missing = do_replacement(regex, line, variable_format, confdata)
missing_variables.update(missing) missing_variables.update(missing)
if missing: if missing:
confdata_useless = False confdata_useless = False
result.append(line) 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 + '~' dst_tmp = dst + '~'
try: try:
with open(dst_tmp, 'w', encoding=encoding, newline='') as f: 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.mesonlib import MesonException, EnvironmentException
from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram
import mesonbuild.dependencies.base import mesonbuild.dependencies.base
from mesonbuild.build import Target from mesonbuild.build import Target, ConfigurationData
import mesonbuild.modules.pkgconfig import mesonbuild.modules.pkgconfig
from mesonbuild.mtest import TAPParser, TestResult 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@\n@VAR@\n', confdata), 'foo\nfoo\n')
self.assertEqual(conf_file('@VAR@\r\n@VAR@\r\n', confdata), 'foo\r\nfoo\r\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): def test_absolute_prefix_libdir(self):
''' '''
Tests that setting absolute paths for --prefix and --libdir work. Can't Tests that setting absolute paths for --prefix and --libdir work. Can't

Loading…
Cancel
Save