build: improve the warning for executables with the same name

adb1a360b9 added the feature and also the
usual meson-style warning to users that might be using the feature but
were not targeting a new enough meson version. Well unfortunately the
warning both doesn't actually work (it didn't take different directories
into account) and is also really slow because it creates an O(N^2) loop
for checking this.

Instead, rework this by adding an additional set that stores a tuple
containing the target name and its subdirectory. We only add this tuple
if the target is an executable since it is the only time it will be
relevant. After that, simply check if the name + subdir combination
already exists in the set along with the target being executable. If so,
then we execute FeatureNew which may possibly warn. This is a simply
O(1) lookup which is way faster. Fixes #12404.
pull/12416/head
Dudemanguy 1 year ago committed by Jussi Pakkanen
parent ae7a9b0f44
commit e9e098b73e
  1. 1
      mesonbuild/build.py
  2. 18
      mesonbuild/interpreter/interpreter.py

@ -252,6 +252,7 @@ class Build:
self.environment = environment
self.projects = {}
self.targets: 'T.OrderedDict[str, T.Union[CustomTarget, BuildTarget]]' = OrderedDict()
self.targetnames: T.Set[T.Tuple[str, str]] = set() # Set of executable names and their subdir
self.global_args: PerMachine[T.Dict[str, T.List[str]]] = PerMachine({}, {})
self.global_link_args: PerMachine[T.Dict[str, T.List[str]]] = PerMachine({}, {})
self.projects_args: PerMachine[T.Dict[str, T.Dict[str, T.List[str]]]] = PerMachine({}, {})

@ -3163,12 +3163,15 @@ class Interpreter(InterpreterBase, HoldableObject):
# To permit an executable and a shared library to have the
# same name, such as "foo.exe" and "libfoo.a".
idname = tobj.get_id()
for t in self.build.targets.values():
if t.get_id() == idname:
raise InvalidCode(f'Tried to create target "{name}", but a target of that name already exists.')
if isinstance(tobj, build.Executable) and isinstance(t, build.Executable) and t.name == tobj.name:
FeatureNew.single_use('multiple executables with the same name but different suffixes',
'1.3.0', self.subproject, location=self.current_node)
subdir = tobj.get_subdir()
namedir = (name, subdir)
if idname in self.build.targets:
raise InvalidCode(f'Tried to create target "{name}", but a target of that name already exists.')
if isinstance(tobj, build.Executable) and namedir in self.build.targetnames:
FeatureNew.single_use(f'multiple executables with the same name, "{tobj.name}", but different suffixes in the same directory',
'1.3.0', self.subproject, location=self.current_node)
if isinstance(tobj, build.BuildTarget):
self.add_languages(tobj.missing_languages, True, tobj.for_machine)
@ -3176,6 +3179,9 @@ class Interpreter(InterpreterBase, HoldableObject):
self.add_stdlib_info(tobj)
self.build.targets[idname] = tobj
# Only need to add executables to this set
if isinstance(tobj, build.Executable):
self.build.targetnames.update([namedir])
if idname not in self.coredata.target_guids:
self.coredata.target_guids[idname] = str(uuid.uuid4()).upper()

Loading…
Cancel
Save