compiler.compiles/links: fix failure when compiling a built File object

In order to pass a File object down into the compiler impl and compile
it, we cannot pass a string with the filename, and we cannot either pass
the File object as-is, since it relies on being given Environment
attributes to calculate the relative location. So we build a fresh File
object as an absolute path.

But the code to do this was totally broken. Instead of using the File
method to get an absolute path, we used one that expected to create
builddir-relative paths... and then gave it the absolute source dir as
the "relative path portion" prefix. This worked by accident as long as
it wasn't a built File, but if it was a built file then we intentionally
didn't include that prefix -- which was wrong anyway, since we need the
build directory!

Use the correct method to get an absolute path in all cases, and emit a
warning if it was a built file. This never worked. Sometimes it crashed,
sometimes it silently returned false.

Fixes #11983
pull/11982/head
Eli Schwartz 1 year ago
parent b92858a5be
commit adaea4136f
No known key found for this signature in database
GPG Key ID: CEB167EFB5722BD6
  1. 10
      mesonbuild/interpreter/compiler.py
  2. 17
      test cases/common/28 try compile/meson.build

@ -448,9 +448,12 @@ class CompilerHolder(ObjectHolder['Compiler']):
def compiles_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool:
code = args[0]
if isinstance(code, mesonlib.File):
if code.is_built:
FeatureNew.single_use('compiler.compiles with file created at setup time', '1.2.0', self.subproject,
'It was broken and either errored or returned false.', self.current_node)
self.interpreter.add_build_def_file(code)
code = mesonlib.File.from_absolute_file(
code.rel_to_builddir(self.environment.source_dir))
code.absolute_path(self.environment.source_dir, self.environment.build_dir))
testname = kwargs['name']
extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
deps, msg = self._determine_dependencies(kwargs['dependencies'], endl=None)
@ -472,9 +475,12 @@ class CompilerHolder(ObjectHolder['Compiler']):
code = args[0]
compiler = None
if isinstance(code, mesonlib.File):
if code.is_built:
FeatureNew.single_use('compiler.links with file created at setup time', '1.2.0', self.subproject,
'It was broken and either errored or returned false.', self.current_node)
self.interpreter.add_build_def_file(code)
code = mesonlib.File.from_absolute_file(
code.rel_to_builddir(self.environment.source_dir))
code.absolute_path(self.environment.source_dir, self.environment.build_dir))
suffix = code.suffix
if suffix not in self.compiler.file_suffixes:
for_machine = self.compiler.for_machine

@ -8,20 +8,27 @@ breakcode = '''#include<nonexisting.h>
void func(void) { printf("This won't work.\n"); }
'''
foreach compiler : [meson.get_compiler('c'), meson.get_compiler('cpp')]
if compiler.compiles(code, name : 'should succeed') == false
foreach lang : ['c', 'cpp']
compiler = meson.get_compiler(lang)
if compiler.compiles(code, name : 'code should succeed') == false
error('Compiler ' + compiler.get_id() + ' is fail.')
endif
if compiler.compiles(files('valid.c'), name : 'file should succeed') == false
error('Compiler ' + compiler.get_id() + ' is fail.')
endif
if compiler.compiles(files('valid.c'), name : 'should succeed') == false
copied = configure_file(input: 'valid.c', output: lang + '-valid-copy.c', copy: true)
if compiler.compiles(copied, name : 'built file should succeed') == false
error('Compiler ' + compiler.get_id() + ' is fail.')
endif
if compiler.compiles(breakcode, name : 'should fail')
if compiler.compiles(breakcode, name : 'code should fail')
error('Compiler ' + compiler.get_id() + ' returned true on broken code.')
endif
if compiler.compiles(files('invalid.c'), name : 'should fail')
if compiler.compiles(files('invalid.c'), name : 'file should fail')
error('Compiler ' + compiler.get_id() + ' returned true on broken code.')
endif
endforeach

Loading…
Cancel
Save