aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/coredata.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/coredata.py')
-rw-r--r--mesonbuild/coredata.py73
1 files changed, 64 insertions, 9 deletions
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 94f977f..329c333 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from . import mlog
+from . import mlog, mparser
import pickle, os, uuid
import sys
from itertools import chain
@@ -229,14 +229,6 @@ class UserFeatureOption(UserComboOption):
def is_auto(self):
return self.value == 'auto'
-
-def load_configs(filenames: T.List[str]) -> configparser.ConfigParser:
- """Load configuration files from a named subdirectory."""
- config = configparser.ConfigParser(interpolation=None)
- config.read(filenames)
- return config
-
-
if T.TYPE_CHECKING:
CacheKeyType = T.Tuple[T.Tuple[T.Any, ...], ...]
SubCacheKeyType = T.Tuple[T.Any, ...]
@@ -879,6 +871,69 @@ class CmdLineFileParser(configparser.ConfigParser):
# storing subproject options like "subproject:option=value"
super().__init__(delimiters=['='], interpolation=None)
+class MachineFileParser():
+ def __init__(self, filenames: T.List[str]):
+ self.parser = CmdLineFileParser()
+ self.constants = {'True': True, 'False': False}
+ self.sections = {}
+
+ self.parser.read(filenames)
+
+ # Parse [constants] first so they can be used in other sections
+ if self.parser.has_section('constants'):
+ self.constants.update(self._parse_section('constants'))
+
+ for s in self.parser.sections():
+ if s == 'constants':
+ continue
+ self.sections[s] = self._parse_section(s)
+
+ def _parse_section(self, s):
+ self.scope = self.constants.copy()
+ section = {}
+ for entry, value in self.parser.items(s):
+ if ' ' in entry or '\t' in entry or "'" in entry or '"' in entry:
+ raise EnvironmentException('Malformed variable name {!r} in machine file.'.format(entry))
+ # Windows paths...
+ value = value.replace('\\', '\\\\')
+ try:
+ ast = mparser.Parser(value, 'machinefile').parse()
+ res = self._evaluate_statement(ast.lines[0])
+ except MesonException:
+ raise EnvironmentException('Malformed value in machine file variable {!r}.'.format(entry))
+ except KeyError as e:
+ raise EnvironmentException('Undefined constant {!r} in machine file variable {!r}.'.format(e.args[0], entry))
+ section[entry] = res
+ self.scope[entry] = res
+ return section
+
+ def _evaluate_statement(self, node):
+ if isinstance(node, (mparser.StringNode)):
+ return node.value
+ elif isinstance(node, mparser.BooleanNode):
+ return node.value
+ elif isinstance(node, mparser.NumberNode):
+ return node.value
+ elif isinstance(node, mparser.ArrayNode):
+ return [self._evaluate_statement(arg) for arg in node.args.arguments]
+ elif isinstance(node, mparser.IdNode):
+ return self.scope[node.value]
+ elif isinstance(node, mparser.ArithmeticNode):
+ l = self._evaluate_statement(node.left)
+ r = self._evaluate_statement(node.right)
+ if node.operation == 'add':
+ if (isinstance(l, str) and isinstance(r, str)) or \
+ (isinstance(l, list) and isinstance(r, list)):
+ return l + r
+ elif node.operation == 'div':
+ if isinstance(l, str) and isinstance(r, str):
+ return os.path.join(l, r)
+ raise EnvironmentException('Unsupported node type')
+
+def parse_machine_files(filenames):
+ parser = MachineFileParser(filenames)
+ return parser.sections
+
def get_cmd_line_file(build_dir):
return os.path.join(build_dir, 'meson-private', 'cmd_line.txt')