Repository: mesonbuild/meson

Issue:
configure_file(): be more strict with missing variables in the configuration
Given a template file and a configuration it would be nice it meson would warn, or have a flag to make it more strict and error out, in case a "@foo@" does not have a corresponding "foo" variable in the configuration.


Discussion:
I thought we already had a bug open for this, but I checked and we don't. We should indeed have a flag like this.

Resolving patch:
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -2512,7 +2512,14 @@ def func_configure_file(self, node, args, kwargs):
                 if conffile not in self.build_def_files:
                     self.build_def_files.append(conffile)
                 os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
-                mesonlib.do_conf_file(ifile_abs, ofile_abs, conf.held_object)
+                missing_variables = mesonlib.do_conf_file(ifile_abs, ofile_abs,
+                                                          conf.held_object)
+                if missing_variables:
+                    var_list = ", ".join(map(repr, sorted(missing_variables)))
+                    mlog.warning(
+                        "The variable(s) %s in the input file %r are not "
+                        "present in the given configuration data" % (
+                            var_list, inputfile))
             else:
                 mesonlib.dump_conf_header(ofile_abs, conf.held_object)
             conf.mark_used()
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -375,6 +375,7 @@ def get_library_dirs():
 
 def do_replacement(regex, line, confdata):
     match = re.search(regex, line)
+    missing_variables = set()
     while match:
         varname = match.group(1)
         if varname in confdata:
@@ -386,10 +387,11 @@ def do_replacement(regex, line, confdata):
             else:
                 raise RuntimeError('Tried to replace a variable with something other than a string or int.')
         else:
+            missing_variables.add(varname)
             var = ''
         line = line.replace('@' + varname + '@', var)
         match = re.search(regex, line)
-    return line
+    return line, missing_variables
 
 def do_mesondefine(line, confdata):
     arr = line.split()
@@ -423,17 +425,20 @@ def do_conf_file(src, dst, confdata):
     # Also allow escaping '@' with '\@'
     regex = re.compile(r'[^\\]?@([-a-zA-Z0-9_]+)@')
     result = []
+    missing_variables = set()
     for line in data:
         if line.startswith('#mesondefine'):
             line = do_mesondefine(line, confdata)
         else:
-            line = do_replacement(regex, line, confdata)
+            line, missing = do_replacement(regex, line, confdata)
+            missing_variables.update(missing)
         result.append(line)
     dst_tmp = dst + '~'
     with open(dst_tmp, 'w', encoding='utf-8') as f:
         f.writelines(result)
     shutil.copymode(src, dst_tmp)
     replace_if_different(dst, dst_tmp)
+    return missing_variables
 
 def dump_conf_header(ofilename, cdata):
     with open(ofilename, 'w', encoding='utf-8') as ofile:


Test patch: