Interpreter: Fix c_stdlib usage

- Exceptions raised during subproject setup were ignored.
- Allow c_stdlib in native file, was already half supported.
- Eliminate usage of subproject variable name by overriding
  '<lang>_stdlib' dependency name.
pull/6831/merge
Xavier Claessens 4 years ago committed by Xavier Claessens
parent adfee4460a
commit 1c403e20e7
  1. 2
      cross/ownstdlib.txt
  2. 14
      docs/markdown/Cross-compilation.md
  3. 6
      docs/markdown/snippets/stdlib.md
  4. 2
      mesonbuild/backend/backends.py
  5. 25
      mesonbuild/backend/ninjabackend.py
  6. 2
      mesonbuild/dependencies/base.py
  7. 49
      mesonbuild/interpreter.py
  8. 22
      run_unittests.py
  9. 0
      test cases/unit/79 nostdlib/meson.build
  10. 0
      test cases/unit/79 nostdlib/prog.c
  11. 0
      test cases/unit/79 nostdlib/subprojects/mylibc/libc.c
  12. 2
      test cases/unit/79 nostdlib/subprojects/mylibc/meson.build
  13. 0
      test cases/unit/79 nostdlib/subprojects/mylibc/stdio.h
  14. 0
      test cases/unit/79 nostdlib/subprojects/mylibc/stubstart.s

@ -10,4 +10,4 @@ endian = 'little'
[properties]
c_stdlib = ['mylibc', 'mylibc_dep'] # Subproject name, dependency name
c_stdlib = 'mylibc' # Subproject name

@ -268,7 +268,7 @@ invocation to use in your cross file is the following:
```ini
[properties]
c_stdlib = ['mylibc', 'mylibc_dep'] # Subproject name, dependency name
c_stdlib = ['mylibc', 'mylibc_dep'] # Subproject name, variable name
```
This specifies that C standard library is provided in the Meson
@ -277,6 +277,18 @@ is used on every cross built C target in the entire source tree
(including subprojects) and the standard library is disabled. The
build definitions of these targets do not need any modification.
Note that it is supported for any language, not only `c`, using `<lang>_stdlib`
property.
Since *0.56.0* the variable name parameter is no longer required as long as the
subproject calls `meson.override_dependency('c_stdlib', mylibc_dep)`.
The above example becomes:
```ini
[properties]
c_stdlib = 'mylibc'
```
## Changing cross file settings
Cross file settings are only read when the build directory is set up

@ -0,0 +1,6 @@
## Custom standard library
- It is not limited to cross builds any more, `<lang>_stdlib` property can be
set in native files.
- The variable name parameter is no longer required as long as the subproject
calls `meson.override_dependency('c_stdlib', mylibc_dep)`.

@ -657,7 +657,7 @@ class Backend:
# First, the trivial ones that are impossible to override.
#
# Add -nostdinc/-nostdinc++ if needed; can't be overridden
commands += self.get_cross_stdlib_args(target, compiler)
commands += self.get_no_stdlib_args(target, compiler)
# Add things like /NOLOGO or -pipe; usually can't be overridden
commands += compiler.get_always_args()
# Only add warning-flags by default if the buildtype enables it, and if

@ -2088,12 +2088,15 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
mod_files = _scan_fortran_file_deps(src, srcdir, dirname, tdeps, compiler)
return mod_files
def get_cross_stdlib_args(self, target, compiler):
if self.environment.machines.matches_build_machine(target.for_machine):
return []
if not self.environment.properties.host.has_stdlib(compiler.language):
return []
return compiler.get_no_stdinc_args()
def get_no_stdlib_args(self, target, compiler):
if compiler.language in self.build.stdlibs[target.for_machine]:
return compiler.get_no_stdinc_args()
return []
def get_no_stdlib_link_args(self, target, linker):
if hasattr(linker, 'language') and linker.language in self.build.stdlibs[target.for_machine]:
return linker.get_no_stdlib_link_args()
return []
def get_compile_debugfile_args(self, compiler, target, objfile):
# The way MSVC uses PDB files is documented exactly nowhere so
@ -2520,14 +2523,6 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
elem.add_item('CROSS', '--cross-host=' + self.environment.machines[target.for_machine].system)
self.add_build(elem)
def get_cross_stdlib_link_args(self, target, linker):
if isinstance(target, build.StaticLibrary) or \
self.environment.machines.matches_build_machine(target.for_machine):
return []
if not self.environment.properties.host.has_stdlib(linker.language):
return []
return linker.get_no_stdlib_link_args()
def get_import_filename(self, target):
return os.path.join(self.get_target_dir(target), target.import_filename)
@ -2689,7 +2684,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
linker,
isinstance(target, build.SharedModule))
# Add -nostdlib if needed; can't be overridden
commands += self.get_cross_stdlib_link_args(target, linker)
commands += self.get_no_stdlib_link_args(target, linker)
# Add things like /NOLOGO; usually can't be overridden
commands += linker.get_linker_always_args()
# Add buildtype linker args: optimization level, etc.

@ -2301,7 +2301,7 @@ def get_dep_identifier(name, kwargs) -> T.Tuple:
# 'required' is irrelevant for caching; the caller handles it separately
# 'fallback' subprojects cannot be cached -- they must be initialized
# 'default_options' is only used in fallback case
if key in ('version', 'native', 'required', 'fallback', 'default_options'):
if key in ('version', 'native', 'required', 'fallback', 'default_options', 'force_fallback'):
continue
# All keyword arguments are strings, ints, or lists (or lists of lists)
if isinstance(value, list):

@ -2572,21 +2572,25 @@ class Interpreter(InterpreterBase):
return self.variables
def check_stdlibs(self):
for for_machine in MachineChoice:
machine_choices = [MachineChoice.HOST]
if self.coredata.is_cross_build():
machine_choices.append(MachineChoice.BUILD)
for for_machine in machine_choices:
props = self.build.environment.properties[for_machine]
for l in self.coredata.compilers[for_machine].keys():
try:
di = mesonlib.stringlistify(props.get_stdlib(l))
if len(di) != 2:
raise InterpreterException('Stdlib definition for %s should have exactly two elements.'
% l)
projname, depname = di
subproj = self.do_subproject(projname, 'meson', {})
self.build.stdlibs.host[l] = subproj.get_variable_method([depname], {})
except KeyError:
pass
except InvalidArguments:
pass
continue
if len(di) == 1:
FeatureNew.single_use('stdlib without variable name', '0.56.0', self.subproject)
kwargs = {'fallback': di,
'native': for_machine is MachineChoice.BUILD,
'force_fallback': True,
}
name = display_name = l + '_stdlib'
dep = self.dependency_impl(name, display_name, kwargs)
self.build.stdlibs[for_machine][l] = dep
def import_module(self, modname):
if modname in self.modules:
@ -3682,9 +3686,11 @@ external dependencies (including libraries) must go to "dependencies".''')
wrap_mode = self.coredata.get_builtin_option('wrap_mode')
force_fallback_for = self.coredata.get_builtin_option('force_fallback_for')
force_fallback = kwargs.get('force_fallback', False)
forcefallback = has_fallback and (wrap_mode == WrapMode.forcefallback or \
name in force_fallback_for or \
dirname in force_fallback_for)
dirname in force_fallback_for or \
force_fallback)
if name != '' and not forcefallback:
self._handle_featurenew_dependencies(name)
kwargs['required'] = required and not has_fallback
@ -4786,8 +4792,7 @@ Try setting b_lundef to false instead.'''.format(self.coredata.base_options['b_s
target = targetclass(name, self.subdir, self.subproject, for_machine, sources, objs, self.environment, kwargs)
target.project_version = self.project_version
if not self.environment.machines.matches_build_machine(for_machine):
self.add_cross_stdlib_info(target)
self.add_stdlib_info(target)
l = targetholder(target, self)
self.add_target(name, l.held_object)
self.project_args_frozen = True
@ -4811,23 +4816,19 @@ This will become a hard error in the future.''', location=self.current_node)
kwargs['d_import_dirs'] = cleaned_items
def get_used_languages(self, target):
result = {}
result = set()
for i in target.sources:
# TODO other platforms
for lang, c in self.coredata.compilers.host.items():
for lang, c in self.coredata.compilers[target.for_machine].items():
if c.can_compile(i):
result[lang] = True
result.add(lang)
break
return result
def add_cross_stdlib_info(self, target):
if target.for_machine != MachineChoice.HOST:
return
def add_stdlib_info(self, target):
for l in self.get_used_languages(target):
props = self.environment.properties.host
if props.has_stdlib(l) \
and self.subproject != props.get_stdlib(l)[0]:
target.add_deps(self.build.stdlibs.host[l])
dep = self.build.stdlibs[target.for_machine].get(l, None)
if dep:
target.add_deps(dep)
def check_sources_exist(self, subdir, sources):
for s in sources:

@ -5054,6 +5054,28 @@ recommended as it is not supported on some platforms''')
self.build()
self.run_tests()
@unittest.skipUnless(is_linux(), 'Requires ASM compiler currently only available on Linux CI runners')
def test_nostdlib(self):
testdir = os.path.join(self.unit_test_dir, '79 nostdlib')
machinefile = os.path.join(self.builddir, 'machine.txt')
with open(machinefile, 'w') as f:
f.write(textwrap.dedent('''
[properties]
c_stdlib = 'mylibc'
'''))
# Test native C stdlib
self.meson_native_file = machinefile
self.init(testdir)
self.build()
# Test cross C stdlib
self.new_builddir()
self.meson_native_file = None
self.meson_cross_file = machinefile
self.init(testdir)
self.build()
class FailureTests(BasePlatformTests):
'''
Tests that test failure conditions. Build files here should be dynamically

@ -9,3 +9,5 @@ libc = static_library('c', 'libc.c', 'stubstart.s')
mylibc_dep = declare_dependency(link_with : libc,
include_directories : include_directories('.')
)
meson.override_dependency('c_stdlib', mylibc_dep)
Loading…
Cancel
Save