Skip to content

Commit 1c403e2

Browse files
committed
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.
1 parent adfee44 commit 1c403e2

File tree

14 files changed

+81
-43
lines changed

14 files changed

+81
-43
lines changed

cross/ownstdlib.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ endian = 'little'
1010

1111
[properties]
1212

13-
c_stdlib = ['mylibc', 'mylibc_dep'] # Subproject name, dependency name
13+
c_stdlib = 'mylibc' # Subproject name

docs/markdown/Cross-compilation.md

+13-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ invocation to use in your cross file is the following:
268268

269269
```ini
270270
[properties]
271-
c_stdlib = ['mylibc', 'mylibc_dep'] # Subproject name, dependency name
271+
c_stdlib = ['mylibc', 'mylibc_dep'] # Subproject name, variable name
272272
```
273273

274274
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
277277
(including subprojects) and the standard library is disabled. The
278278
build definitions of these targets do not need any modification.
279279

280+
Note that it is supported for any language, not only `c`, using `<lang>_stdlib`
281+
property.
282+
283+
Since *0.56.0* the variable name parameter is no longer required as long as the
284+
subproject calls `meson.override_dependency('c_stdlib', mylibc_dep)`.
285+
The above example becomes:
286+
287+
```ini
288+
[properties]
289+
c_stdlib = 'mylibc'
290+
```
291+
280292
## Changing cross file settings
281293

282294
Cross file settings are only read when the build directory is set up

docs/markdown/snippets/stdlib.md

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

mesonbuild/backend/backends.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ def generate_basic_compiler_args(self, target, compiler, no_warn_args=False):
657657
# First, the trivial ones that are impossible to override.
658658
#
659659
# Add -nostdinc/-nostdinc++ if needed; can't be overridden
660-
commands += self.get_cross_stdlib_args(target, compiler)
660+
commands += self.get_no_stdlib_args(target, compiler)
661661
# Add things like /NOLOGO or -pipe; usually can't be overridden
662662
commands += compiler.get_always_args()
663663
# Only add warning-flags by default if the buildtype enables it, and if

mesonbuild/backend/ninjabackend.py

+10-15
Original file line numberDiff line numberDiff line change
@@ -2088,12 +2088,15 @@ def get_fortran_deps(self, compiler: FortranCompiler, src: Path, target) -> T.Li
20882088
mod_files = _scan_fortran_file_deps(src, srcdir, dirname, tdeps, compiler)
20892089
return mod_files
20902090

2091-
def get_cross_stdlib_args(self, target, compiler):
2092-
if self.environment.machines.matches_build_machine(target.for_machine):
2093-
return []
2094-
if not self.environment.properties.host.has_stdlib(compiler.language):
2095-
return []
2096-
return compiler.get_no_stdinc_args()
2091+
def get_no_stdlib_args(self, target, compiler):
2092+
if compiler.language in self.build.stdlibs[target.for_machine]:
2093+
return compiler.get_no_stdinc_args()
2094+
return []
2095+
2096+
def get_no_stdlib_link_args(self, target, linker):
2097+
if hasattr(linker, 'language') and linker.language in self.build.stdlibs[target.for_machine]:
2098+
return linker.get_no_stdlib_link_args()
2099+
return []
20972100

20982101
def get_compile_debugfile_args(self, compiler, target, objfile):
20992102
# The way MSVC uses PDB files is documented exactly nowhere so
@@ -2520,14 +2523,6 @@ def generate_shsym(self, target):
25202523
elem.add_item('CROSS', '--cross-host=' + self.environment.machines[target.for_machine].system)
25212524
self.add_build(elem)
25222525

2523-
def get_cross_stdlib_link_args(self, target, linker):
2524-
if isinstance(target, build.StaticLibrary) or \
2525-
self.environment.machines.matches_build_machine(target.for_machine):
2526-
return []
2527-
if not self.environment.properties.host.has_stdlib(linker.language):
2528-
return []
2529-
return linker.get_no_stdlib_link_args()
2530-
25312526
def get_import_filename(self, target):
25322527
return os.path.join(self.get_target_dir(target), target.import_filename)
25332528

@@ -2689,7 +2684,7 @@ def generate_link(self, target, outname, obj_list, linker, extra_args=None, stdl
26892684
linker,
26902685
isinstance(target, build.SharedModule))
26912686
# Add -nostdlib if needed; can't be overridden
2692-
commands += self.get_cross_stdlib_link_args(target, linker)
2687+
commands += self.get_no_stdlib_link_args(target, linker)
26932688
# Add things like /NOLOGO; usually can't be overridden
26942689
commands += linker.get_linker_always_args()
26952690
# Add buildtype linker args: optimization level, etc.

mesonbuild/dependencies/base.py

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

mesonbuild/interpreter.py

+25-24
Original file line numberDiff line numberDiff line change
@@ -2572,21 +2572,25 @@ def get_variables(self):
25722572
return self.variables
25732573

25742574
def check_stdlibs(self):
2575-
for for_machine in MachineChoice:
2575+
machine_choices = [MachineChoice.HOST]
2576+
if self.coredata.is_cross_build():
2577+
machine_choices.append(MachineChoice.BUILD)
2578+
for for_machine in machine_choices:
25762579
props = self.build.environment.properties[for_machine]
25772580
for l in self.coredata.compilers[for_machine].keys():
25782581
try:
25792582
di = mesonlib.stringlistify(props.get_stdlib(l))
2580-
if len(di) != 2:
2581-
raise InterpreterException('Stdlib definition for %s should have exactly two elements.'
2582-
% l)
2583-
projname, depname = di
2584-
subproj = self.do_subproject(projname, 'meson', {})
2585-
self.build.stdlibs.host[l] = subproj.get_variable_method([depname], {})
25862583
except KeyError:
2587-
pass
2588-
except InvalidArguments:
2589-
pass
2584+
continue
2585+
if len(di) == 1:
2586+
FeatureNew.single_use('stdlib without variable name', '0.56.0', self.subproject)
2587+
kwargs = {'fallback': di,
2588+
'native': for_machine is MachineChoice.BUILD,
2589+
'force_fallback': True,
2590+
}
2591+
name = display_name = l + '_stdlib'
2592+
dep = self.dependency_impl(name, display_name, kwargs)
2593+
self.build.stdlibs[for_machine][l] = dep
25902594

25912595
def import_module(self, modname):
25922596
if modname in self.modules:
@@ -3682,9 +3686,11 @@ def dependency_impl(self, name, display_name, kwargs):
36823686

36833687
wrap_mode = self.coredata.get_builtin_option('wrap_mode')
36843688
force_fallback_for = self.coredata.get_builtin_option('force_fallback_for')
3689+
force_fallback = kwargs.get('force_fallback', False)
36853690
forcefallback = has_fallback and (wrap_mode == WrapMode.forcefallback or \
36863691
name in force_fallback_for or \
3687-
dirname in force_fallback_for)
3692+
dirname in force_fallback_for or \
3693+
force_fallback)
36883694
if name != '' and not forcefallback:
36893695
self._handle_featurenew_dependencies(name)
36903696
kwargs['required'] = required and not has_fallback
@@ -4786,8 +4792,7 @@ def build_target_decorator_caller(self, node, args, kwargs):
47864792
target = targetclass(name, self.subdir, self.subproject, for_machine, sources, objs, self.environment, kwargs)
47874793
target.project_version = self.project_version
47884794

4789-
if not self.environment.machines.matches_build_machine(for_machine):
4790-
self.add_cross_stdlib_info(target)
4795+
self.add_stdlib_info(target)
47914796
l = targetholder(target, self)
47924797
self.add_target(name, l.held_object)
47934798
self.project_args_frozen = True
@@ -4811,23 +4816,19 @@ def kwarg_strings_to_includedirs(self, kwargs):
48114816
kwargs['d_import_dirs'] = cleaned_items
48124817

48134818
def get_used_languages(self, target):
4814-
result = {}
4819+
result = set()
48154820
for i in target.sources:
4816-
# TODO other platforms
4817-
for lang, c in self.coredata.compilers.host.items():
4821+
for lang, c in self.coredata.compilers[target.for_machine].items():
48184822
if c.can_compile(i):
4819-
result[lang] = True
4823+
result.add(lang)
48204824
break
48214825
return result
48224826

4823-
def add_cross_stdlib_info(self, target):
4824-
if target.for_machine != MachineChoice.HOST:
4825-
return
4827+
def add_stdlib_info(self, target):
48264828
for l in self.get_used_languages(target):
4827-
props = self.environment.properties.host
4828-
if props.has_stdlib(l) \
4829-
and self.subproject != props.get_stdlib(l)[0]:
4830-
target.add_deps(self.build.stdlibs.host[l])
4829+
dep = self.build.stdlibs[target.for_machine].get(l, None)
4830+
if dep:
4831+
target.add_deps(dep)
48314832

48324833
def check_sources_exist(self, subdir, sources):
48334834
for s in sources:

run_unittests.py

+22
Original file line numberDiff line numberDiff line change
@@ -5054,6 +5054,28 @@ def test_multi_output_custom_target_no_warning(self):
50545054
self.build()
50555055
self.run_tests()
50565056

5057+
@unittest.skipUnless(is_linux(), 'Requires ASM compiler currently only available on Linux CI runners')
5058+
def test_nostdlib(self):
5059+
testdir = os.path.join(self.unit_test_dir, '79 nostdlib')
5060+
machinefile = os.path.join(self.builddir, 'machine.txt')
5061+
with open(machinefile, 'w') as f:
5062+
f.write(textwrap.dedent('''
5063+
[properties]
5064+
c_stdlib = 'mylibc'
5065+
'''))
5066+
5067+
# Test native C stdlib
5068+
self.meson_native_file = machinefile
5069+
self.init(testdir)
5070+
self.build()
5071+
5072+
# Test cross C stdlib
5073+
self.new_builddir()
5074+
self.meson_native_file = None
5075+
self.meson_cross_file = machinefile
5076+
self.init(testdir)
5077+
self.build()
5078+
50575079
class FailureTests(BasePlatformTests):
50585080
'''
50595081
Tests that test failure conditions. Build files here should be dynamically
File renamed without changes.

manual tests/9 nostdlib/subprojects/mylibc/meson.build renamed to test cases/unit/79 nostdlib/subprojects/mylibc/meson.build

+2
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ libc = static_library('c', 'libc.c', 'stubstart.s')
99
mylibc_dep = declare_dependency(link_with : libc,
1010
include_directories : include_directories('.')
1111
)
12+
13+
meson.override_dependency('c_stdlib', mylibc_dep)

0 commit comments

Comments
 (0)