Skip to content

Commit

Permalink
build: Process compilers before calling link() and link_whole()
Browse files Browse the repository at this point in the history
To take good decisions we'll need to know if we are a Rust library which
is only know after processing source files and compilers.

Note that is it not the final list of compilers, some can be added in
process_compilers_late(), but those are compilers for which we don't
have source files any way.
  • Loading branch information
xclaesse committed Apr 27, 2023
1 parent 7945c5b commit c04d228
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 32 deletions.
3 changes: 1 addition & 2 deletions mesonbuild/ast/introspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,7 @@ def traverse_nodes(inqueue: T.List[BaseNode]) -> T.List[BaseNode]:
kwargs_reduced['_allow_no_sources'] = True
target = targetclass(name, self.subdir, self.subproject, for_machine, empty_sources, [], objects,
self.environment, self.coredata.compilers[for_machine], kwargs_reduced)
target.process_compilers()
target.process_compilers_late([])
target.process_compilers_late()

new_target = {
'name': target.get_basename(),
Expand Down
45 changes: 20 additions & 25 deletions mesonbuild/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,9 @@ def __init__(
# 2. Compiled objects created by and extracted from another target
self.process_objectlist(objects)
self.process_kwargs(kwargs)
self.missing_languages = self.process_compilers()
self.link(extract_as_list(kwargs, 'link_with'))
self.link_whole(extract_as_list(kwargs, 'link_whole'))
if not any([self.sources, self.generated, self.objects, self.link_whole_targets, self.structured_sources,
kwargs.pop('_allow_no_sources', False)]):
mlog.warning(f'Build target {name} has no sources. '
Expand Down Expand Up @@ -834,14 +837,14 @@ def can_compile_remove_sources(compiler: 'Compiler', sources: T.List['FileOrStri
removed = True
return removed

def process_compilers_late(self, extra_languages: T.List[str]):
def process_compilers_late(self):
"""Processes additional compilers after kwargs have been evaluated.
This can add extra compilers that might be required by keyword
arguments, such as link_with or dependencies. It will also try to guess
which compiler to use if one hasn't been selected already.
"""
for lang in extra_languages:
for lang in self.missing_languages:
self.compilers[lang] = self.all_compilers[lang]

# did user override clink_langs for this target?
Expand Down Expand Up @@ -1063,20 +1066,6 @@ def process_kwargs(self, kwargs):
self.original_kwargs = kwargs
kwargs.get('modules', [])
self.need_install = kwargs.get('install', self.need_install)
llist = extract_as_list(kwargs, 'link_with')
for linktarget in llist:
if isinstance(linktarget, dependencies.ExternalLibrary):
raise MesonException(textwrap.dedent('''\
An external library was used in link_with keyword argument, which
is reserved for libraries built as part of this project. External
libraries must be passed using the dependencies keyword argument
instead, because they are conceptually "external dependencies",
just like those detected with the dependency() function.
'''))
self.link(linktarget)
lwhole = extract_as_list(kwargs, 'link_whole')
for linktarget in lwhole:
self.link_whole(linktarget)

for lang in all_languages:
lang_args = extract_as_list(kwargs, f'{lang}_args')
Expand Down Expand Up @@ -1334,10 +1323,8 @@ def add_deps(self, deps):
self.extra_files.extend(f for f in dep.extra_files if f not in self.extra_files)
self.add_include_dirs(dep.include_directories, dep.get_include_type())
self.objects.extend(dep.objects)
for l in dep.libraries:
self.link(l)
for l in dep.whole_libraries:
self.link_whole(l)
self.link(dep.libraries)
self.link_whole(dep.whole_libraries)
if dep.get_compile_args() or dep.get_link_args():
# Those parts that are external.
extpart = dependencies.InternalDependency('undefined',
Expand Down Expand Up @@ -1386,8 +1373,8 @@ def get_external_deps(self) -> T.List[dependencies.Dependency]:
def is_internal(self) -> bool:
return False

def link(self, target):
for t in listify(target):
def link(self, targets):
for t in targets:
if isinstance(self, StaticLibrary) and self.need_install:
if isinstance(t, (CustomTarget, CustomTargetIndex)):
if not t.should_install():
Expand All @@ -1397,8 +1384,16 @@ def link(self, target):
elif t.is_internal():
# When we're a static library and we link_with to an
# internal/convenience library, promote to link_whole.
return self.link_whole(t)
return self.link_whole([t])
if not isinstance(t, (Target, CustomTargetIndex)):
if isinstance(t, dependencies.ExternalLibrary):
raise MesonException(textwrap.dedent('''\
An external library was used in link_with keyword argument, which
is reserved for libraries built as part of this project. External
libraries must be passed using the dependencies keyword argument
instead, because they are conceptually "external dependencies",
just like those detected with the dependency() function.
'''))
raise InvalidArguments(f'{t!r} is not a target.')
if not t.is_linkable_target():
raise InvalidArguments(f"Link target '{t!s}' is not linkable.")
Expand All @@ -1414,8 +1409,8 @@ def link(self, target):
mlog.warning(msg + ' This will fail in cross build.')
self.link_targets.append(t)

def link_whole(self, target):
for t in listify(target):
def link_whole(self, targets):
for t in targets:
if isinstance(t, (CustomTarget, CustomTargetIndex)):
if not t.is_linkable_target():
raise InvalidArguments(f'Custom target {t!r} is not linkable.')
Expand Down
5 changes: 2 additions & 3 deletions mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3132,9 +3132,8 @@ def add_target(self, name: str, tobj: build.Target) -> None:
raise InvalidCode(f'Tried to create target "{name}", but a target of that name already exists.')

if isinstance(tobj, build.BuildTarget):
missing_languages = tobj.process_compilers()
self.add_languages(missing_languages, True, tobj.for_machine)
tobj.process_compilers_late(missing_languages)
self.add_languages(tobj.missing_languages, True, tobj.for_machine)
tobj.process_compilers_late()
self.add_stdlib_info(tobj)

self.build.targets[idname] = tobj
Expand Down
3 changes: 1 addition & 2 deletions unittests/allplatformstests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4376,8 +4376,7 @@ def output_name(name, type_):
structured_sources=None,
objects=[], environment=env, compilers=env.coredata.compilers[MachineChoice.HOST],
kwargs={})
target.process_compilers()
target.process_compilers_late([])
target.process_compilers_late()
return target.filename

shared_lib_name = lambda name: output_name(name, SharedLibrary)
Expand Down

0 comments on commit c04d228

Please sign in to comment.