summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2023-02-22 22:09:11 -0600
committerDylan Baker <dylan@pnwbakers.com>2023-10-05 08:43:38 -0700
commitadb1a360b9f9edb26eda233326b1d539baeccd5b (patch)
tree8de1c2930bec9d5183705d6e73da04acaab035ec
parent4fadb2a2962d0cdb39da7cadd5c7b1b12984eeb5 (diff)
downloadmeson-adb1a360b9f9edb26eda233326b1d539baeccd5b.tar.gz
build: use suffix when getting target id for exes
When checking target names, meson explictly forbids having multiple targets with the same name. This is good, but it is strict and it is impossible to have targets with the same basename and differing suffixes (e.g. foo and foo.bin) in the same directory. Allow this for executables by including the suffix (if it exists) in the interal target id. So foo would be foo@exe and foo.bin would be foo.bin@exe.
-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