Repository: mesonbuild/meson

Issue:
Names of custom_target’s from subproject collide
When a project contains a `custom_target` with the same name as a `custom_target` in one of the subprojects, it fails to configure:

```
Build started at 2018-10-16T00:52:

27.473138
Main binary: /nix/store/1c4zshbxizcsvyj46fwf5jj10h41wf6i-python3-3.6.6/bin/python3.6m
Python system: Linux
The Meson build system

Version: 0.48.0
Source dir: /home/jtojnar/projects/meson-subproject-custom-target
Build dir: /home/jtojnar/projects/meson-subproject-custom-target/build
Build type: native build
Project name: bar
Project version: 1.2.0
Sanity testing C compiler: ccache cc
Is cross compiler: False.
Sanity check compiler command line: ccache cc /home/jtojnar/projects/meson-subproject-custom-target/build/meson-private/sanitycheckc.c -o /home/jtojnar/projects/meson-subproject-custom-target/build/meson-private/sanitycheckc.exe
Sanity check compile stdout:

-----
Sanity check compile stderr:

-----
Running test binary command: /home/jtojnar/projects/meson-subproject-custom-target/build/meson-private/sanitycheckc.exe
Native C compiler: ccache cc (gcc 7.3.0 "cc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0")
Build machine cpu family: x86_64
Build machine cpu: x86_64
Found pkg-config: /usr/bin/pkg-config (0.29.1)
Determining dependency 'foo' with pkg-config executable '/usr/bin/pkg-config'
Called `/usr/bin/pkg-config --modversion foo` -> 1

Dependency foo found: NO (tried pkgconfig)
Looking for a fallback subproject for the dependency foo


Executing subproject foo 

Project name: foo
Project version: 1.2.0
Native C compiler: ccache cc (gcc 7.3.0 "cc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0")
Build targets in project: 2

Subproject foo finished.
Dependency foo from subproject subprojects/foo found: YES

meson.build:7:0: ERROR:  Tried to create target "mapfile", but a target of that name already exists.

```

Reproduction: [meson-subproject-custom-target.zip](https://github.com/mesonbuild/meson/files/2480822/meson-subproject-custom-target.zip)


Discussion:
It looks like it might have been fixed for `run_target` but not for `custom_target` https://github.com/mesonbuild/meson/pull/2286
I hit the same problem.
My use case is quite peculiar, as it's not about compiling software but building PDF files from different kinds of text files.  Probably not interesting for you, but for the records... here's the source tree:

```
── markdown
│   ├── basic.md
│   ├── meson.build
│   └── tablature.md
├── meson.build
├── README.md
└── tex
    ├── basic.tex
    ├── meson.build
    └── tablature.tex
```
The meson.build files in each subdir (markdown and tex) use the base name of the files in those directories as target name in a foreach loop with a custom_target. As base names are the same, Meson stops with an error as soon as the second subdir is checked:

```
tex/meson.build:7:2: ERROR:  Tried to create target "basic", but a target of that name already exists.
```
I'll use unique file names.

@martingkelly Do you want to implement this the same as you did for run_target in #2286?
Also check if this fixes #4477 if implemented.
@nioncode, yes I think namespacing is the right solution.

Resolving patch:
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -1887,9 +1887,6 @@ def __repr__(self):
         repr_str = "<{0} {1}: {2}>"
         return repr_str.format(self.__class__.__name__, self.get_id(), self.command)
 
-    def get_id(self):
-        return self.name + self.type_suffix()
-
     def get_target_dependencies(self):
         deps = self.dependencies[:]
         deps += self.extra_depends
diff --git a/run_unittests.py b/run_unittests.py
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -2677,7 +2677,7 @@ def test_introspect_target_files(self):
         self.init(testdir)
         expected = {
             'bindat@cus': ['data_source.txt'],
-            'depfile@cus': [],
+            'a685fbc@@depfile@cus': [],
         }
         t_intro = self.introspect('--targets')
         self.assertCountEqual([t['id'] for t in t_intro], expected)
@@ -4550,7 +4550,7 @@ def test_introspect_dependencies(self):
                 docbook_target = t
                 break
         self.assertIsInstance(docbook_target, dict)
-        ifile = self.introspect(['--target-files', 'generated-gdbus-docbook@cus'])[0]
+        ifile = self.introspect(['--target-files', '8d60afc@@generated-gdbus-docbook@cus'])[0]
         self.assertListEqual(t['filename'], [os.path.join(self.builddir, 'gdbus/generated-gdbus-doc-' + os.path.basename(ifile))])
 
     def test_build_rpath(self):


Test patch:
diff --git a/test cases/common/87 identical target name in subproject/meson.build b/test cases/common/87 identical target name in subproject/meson.build
--- a/test cases/common/87 identical target name in subproject/meson.build	
+++ b/test cases/common/87 identical target name in subproject/meson.build	
@@ -4,3 +4,4 @@ subproject('foo')
 
 executable('bar', 'bar.c')
 run_target('nop', command : ['true'])
+custom_target('cus', output: ['cus.c'], command : ['true'])
diff --git a/test cases/common/87 identical target name in subproject/subprojects/foo/meson.build b/test cases/common/87 identical target name in subproject/subprojects/foo/meson.build
--- a/test cases/common/87 identical target name in subproject/subprojects/foo/meson.build	
+++ b/test cases/common/87 identical target name in subproject/subprojects/foo/meson.build	
@@ -2,3 +2,4 @@ project('subfoo', 'c')
 
 executable('bar', 'bar.c')
 run_target('nop', command : ['true'])
+custom_target('cus', output: ['cus.c'], command : ['true'])