summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/snippets/executable-suffixes.md14
-rw-r--r--docs/yaml/functions/executable.yaml3
-rw-r--r--mesonbuild/build.py14
-rw-r--r--mesonbuild/interpreter/interpreter.py8
-rw-r--r--test cases/unit/119 executable suffix/main.c1
-rw-r--r--test cases/unit/119 executable suffix/meson.build3
-rw-r--r--unittests/allplatformstests.py10
7 files changed, 49 insertions, 4 deletions
diff --git a/docs/markdown/snippets/executable-suffixes.md b/docs/markdown/snippets/executable-suffixes.md
new file mode 100644
index 000000000..44471e9dd
--- /dev/null
+++ b/docs/markdown/snippets/executable-suffixes.md
@@ -0,0 +1,14 @@
+## Target names for executables now take into account suffixes.
+
+In previous versions of meson, a `meson.build` file like this:
+
+```
+exectuable('foo', 'main.c')
+exectuable('foo', 'main.c', name_suffix: 'bar')
+```
+
+would result in a configure error because meson internally used
+the same id for both executables. This build file is now allowed
+since meson takes into account the `bar` suffix when generating the
+second executable. This allows for executables with the same basename
+but different suffixes to be built in the same subdirectory.
diff --git a/docs/yaml/functions/executable.yaml b/docs/yaml/functions/executable.yaml
index 380759457..abbc5feee 100644
--- a/docs/yaml/functions/executable.yaml
+++ b/docs/yaml/functions/executable.yaml
@@ -10,6 +10,9 @@ description: |
The returned object also has methods that are documented in [[@exe]].
+ *Since 1.3.0* executable names can be the same across multiple targets as
+ long as they each have a different `name_suffix`.
+
warnings:
- The `link_language` kwarg was broken until 0.55.0
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 4c07d9691..d1888d7b2 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -634,8 +634,11 @@ class Target(HoldableObject, metaclass=abc.ABCMeta):
return my_id
def get_id(self) -> str:
+ name = self.name
+ if getattr(self, 'name_suffix_set', False):
+ name += '.' + self.suffix
return self.construct_id_from_path(
- self.subdir, self.name, self.type_suffix())
+ self.subdir, name, self.type_suffix())
def process_kwargs_base(self, kwargs: T.Dict[str, T.Any]) -> None:
if 'build_by_default' in kwargs:
@@ -2013,7 +2016,14 @@ class Executable(BuildTarget):
and self.environment.coredata.get_option(OptionKey("debug"))
)
if create_debug_file:
- self.debug_filename = self.name + '.pdb'
+ # If the target is has a standard exe extension (i.e. 'foo.exe'),
+ # then the pdb name simply becomes 'foo.pdb'. If the extension is
+ # something exotic, then include that in the name for uniqueness
+ # reasons (e.g. 'foo_com.pdb').
+ name = self.name
+ if getattr(self, 'suffix', 'exe') != 'exe':
+ name += '_' + self.suffix
+ self.debug_filename = name + '.pdb'
def process_kwargs(self, kwargs):
super().process_kwargs(kwargs)
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index 05581afeb..0b6ccef22 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -3169,8 +3169,12 @@ 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()
- if idname in self.build.targets:
- raise InvalidCode(f'Tried to create target "{name}", but a target of that name already exists.')
+ 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)
if isinstance(tobj, build.BuildTarget):
self.add_languages(tobj.missing_languages, True, tobj.for_machine)
diff --git a/test cases/unit/119 executable suffix/main.c b/test cases/unit/119 executable suffix/main.c
new file mode 100644
index 000000000..78f2de106
--- /dev/null
+++ b/test cases/unit/119 executable suffix/main.c
@@ -0,0 +1 @@
+int main(void) { return 0; }
diff --git a/test cases/unit/119 executable suffix/meson.build b/test cases/unit/119 executable suffix/meson.build
new file mode 100644
index 000000000..8f952260c
--- /dev/null
+++ b/test cases/unit/119 executable suffix/meson.build
@@ -0,0 +1,3 @@
+project('exectuable suffix', 'c')
+foo = executable('foo', 'main.c')
+foo_bin = executable('foo', 'main.c', name_suffix: 'bin')
diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py
index 4ee0de469..030b216d7 100644
--- a/unittests/allplatformstests.py
+++ b/unittests/allplatformstests.py
@@ -2039,6 +2039,16 @@ class AllPlatformTests(BasePlatformTests):
original = get_opt()
self.assertDictEqual(original, expected)
+ def test_executable_names(self):
+ testdir = os.path.join(self.unit_test_dir, '119 executable suffix')
+ self.init(testdir)
+ self.build()
+ exe1 = os.path.join(self.builddir, 'foo' + exe_suffix)
+ exe2 = os.path.join(self.builddir, 'foo.bin')
+ self.assertPathExists(exe1)
+ self.assertPathExists(exe2)
+ self.assertNotEqual(exe1, exe2)
+
def opt_has(self, name, value):
res = self.introspect('--buildoptions')
found = False