prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Windows module fails on multiple resource files with same name
  I have a project with multiple subfolders that contain resource scripts named 'rsrc.rc', this worked with at least 0.44.0, but fails with current master:
  
  > meson.build:7:0: ERROR:  Tried to create target "Windows resource for file 'rsrc.rc'", but a target of that name already exists.
  
  Here is a small testcase: [rsrcbug.zip](https://github.com/mesonbuild/meson/files/2007861/rsrcbug.zip)
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `mesonbuild/modules/windows.py`
  Content:
  ```
  1 # Copyright 2015 The Meson development team
  2 
  3 # Licensed under the Apache License, Version 2.0 (the "License");
  4 # you may not use this file except in compliance with the License.
  5 # You may obtain a copy of the License at
  6 
  7 #     http://www.apache.org/licenses/LICENSE-2.0
  8 
  9 # Unless required by applicable law or agreed to in writing, software
  10 # distributed under the License is distributed on an "AS IS" BASIS,
  11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 # See the License for the specific language governing permissions and
  13 # limitations under the License.
  14 
  15 import os
  16 
  17 from .. import mlog
  18 from .. import mesonlib, dependencies, build
  19 from ..mesonlib import MesonException, extract_as_list
  20 from . import get_include_args
  21 from . import ModuleReturnValue
  22 from . import ExtensionModule
  23 from ..interpreterbase import permittedKwargs, FeatureNewKwargs
  24 
  25 class WindowsModule(ExtensionModule):
  26 
  27     def detect_compiler(self, compilers):
  28         for l in ('c', 'cpp'):
  29             if l in compilers:
  30                 return compilers[l]
  31         raise MesonException('Resource compilation requires a C or C++ compiler.')
  32 
  33     @FeatureNewKwargs('windows.compile_resources', '0.47.0', ['depend_files'])
  34     @permittedKwargs({'args', 'include_directories', 'depend_files'})
  35     def compile_resources(self, state, args, kwargs):
  36         comp = self.detect_compiler(state.compilers)
  37 
  38         extra_args = mesonlib.stringlistify(kwargs.get('args', []))
  39         wrc_deps = extract_as_list(kwargs, 'depend_files', pop = True)
  40         inc_dirs = extract_as_list(kwargs, 'include_directories', pop = True)
  41         for incd in inc_dirs:
  42             if not isinstance(incd.held_object, (str, build.IncludeDirs)):
  43                 raise MesonException('Resource include dirs should be include_directories().')
  44         extra_args += get_include_args(inc_dirs)
  45 
  46         if comp.id == 'msvc':
  47             rescomp = dependencies.ExternalProgram('rc', silent=True)
  48             res_args = extra_args + ['/nologo', '/fo@OUTPUT@', '@INPUT@']
  49             suffix = 'res'
  50         else:
  51             m = 'Argument {!r} has a space which may not work with windres due to ' \
  52                 'a MinGW bug: https://sourceware.org/bugzilla/show_bug.cgi?id=4933'
  53             for arg in extra_args:
  54                 if ' ' in arg:
  55                     mlog.warning(m.format(arg))
  56             rescomp_name = None
  57             # FIXME: Does not handle `native: true` executables, see
  58             # https://github.com/mesonbuild/meson/issues/1531
  59             if state.environment.is_cross_build():
  60                 # If cross compiling see if windres has been specified in the
  61                 # cross file before trying to find it another way.
  62                 rescomp_name = state.environment.cross_info.config['binaries'].get('windres')
  63             if rescomp_name is None:
  64                 # Pick-up env var WINDRES if set. This is often used for
  65                 # specifying an arch-specific windres.
  66                 rescomp_name = os.environ.get('WINDRES', 'windres')
  67             rescomp = dependencies.ExternalProgram(rescomp_name, silent=True)
  68             res_args = extra_args + ['@INPUT@', '@OUTPUT@']
  69             suffix = 'o'
  70         if not rescomp.found():
  71             raise MesonException('Could not find Windows resource compiler "%s".' % rescomp_name)
  72 
  73         res_targets = []
  74 
  75         def add_target(src):
  76             if isinstance(src, list):
  77                 for subsrc in src:
  78                     add_target(subsrc)
  79                 return
  80 
  81             if hasattr(src, 'held_object'):
  82                 src = src.held_object
  83 
  84             res_kwargs = {
  85                 'output': '@BASENAME@.' + suffix,
  86                 'input': [src],
  87                 'command': [rescomp] + res_args,
  88                 'depend_files': wrc_deps,
  89             }
  90 
  91             if isinstance(src, (str, mesonlib.File)):
  92                 name = 'file {!r}'.format(str(src))
  93             elif isinstance(src, build.CustomTarget):
  94                 if len(src.get_outputs()) > 1:
  95                     raise MesonException('windows.compile_resources does not accept custom targets with more than 1 output.')
  96 
  97                 name = 'target {!r}'.format(src.get_id())
  98             else:
  99                 raise MesonException('Unexpected source type {!r}. windows.compile_resources accepts only strings, files, custom targets, and lists thereof.'.format(src))
  100 
  101             # Path separators are not allowed in target names
  102             name = name.replace('/', '_').replace('\\', '_')
  103 
  104             # instruct binutils windres to generate a preprocessor depfile
  105             if comp.id != 'msvc':
  106                 res_kwargs['depfile'] = res_kwargs['output'] + '.d'
  107                 res_kwargs['command'] += ['--preprocessor-arg=-MD', '--preprocessor-arg=-MQ@OUTPUT@', '--preprocessor-arg=-MF@DEPFILE@']
  108 
  109             res_targets.append(build.CustomTarget('Windows resource for ' + name, state.subdir, state.subproject, res_kwargs))
  110 
  111         add_target(args)
  112 
  113         return ModuleReturnValue(res_targets, [res_targets])
  114 
  115 def initialize(*args, **kwargs):
  116     return WindowsModule(*args, **kwargs)
  117
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py
  --- a/mesonbuild/modules/windows.py
  +++ b/mesonbuild/modules/windows.py
  @@ -88,8 +88,10 @@
                   'depend_files': wrc_deps,
               }
   
  -            if isinstance(src, (str, mesonlib.File)):
  -                name = 'file {!r}'.format(str(src))
  +            if isinstance(src, str):
  +                name = 'file {!r}'.format(os.path.join(state.subdir, src))
  +            elif isinstance(src, mesonlib.File):
  +                name = 'file {!r}'.format(src.relative_name())
               elif isinstance(src, build.CustomTarget):
                   if len(src.get_outputs()) > 1:
                       raise MesonException('windows.compile_resources does not accept custom targets with more than 1 output.')
  
verification_info: {"golden_diff": "diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py\n--- a/mesonbuild/modules/windows.py\n+++ b/mesonbuild/modules/windows.py\n@@ -88,8 +88,10 @@\n                 'depend_files': wrc_deps,\n             }\n \n-            if isinstance(src, (str, mesonlib.File)):\n-                name = 'file {!r}'.format(str(src))\n+            if isinstance(src, str):\n+                name = 'file {!r}'.format(os.path.join(state.subdir, src))\n+            elif isinstance(src, mesonlib.File):\n+                name = 'file {!r}'.format(src.relative_name())\n             elif isinstance(src, build.CustomTarget):\n                 if len(src.get_outputs()) > 1:\n                     raise MesonException('windows.compile_resources does not accept custom targets with more than 1 output.')\n", "issue": "Windows module fails on multiple resource files with same name\nI have a project with multiple subfolders that contain resource scripts named 'rsrc.rc', this worked with at least 0.44.0, but fails with current master:\r\n\r\n> meson.build:7:0: ERROR:  Tried to create target \"Windows resource for file 'rsrc.rc'\", but a target of that name already exists.\r\n\r\nHere is a small testcase: [rsrcbug.zip](https://github.com/mesonbuild/meson/files/2007861/rsrcbug.zip)\r\n\n", "before_files": [{"content": "# Copyright 2015 The Meson development team\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport os\n\nfrom .. import mlog\nfrom .. import mesonlib, dependencies, build\nfrom ..mesonlib import MesonException, extract_as_list\nfrom . import get_include_args\nfrom . import ModuleReturnValue\nfrom . import ExtensionModule\nfrom ..interpreterbase import permittedKwargs, FeatureNewKwargs\n\nclass WindowsModule(ExtensionModule):\n\n    def detect_compiler(self, compilers):\n        for l in ('c', 'cpp'):\n            if l in compilers:\n                return compilers[l]\n        raise MesonException('Resource compilation requires a C or C++ compiler.')\n\n    @FeatureNewKwargs('windows.compile_resources', '0.47.0', ['depend_files'])\n    @permittedKwargs({'args', 'include_directories', 'depend_files'})\n    def compile_resources(self, state, args, kwargs):\n        comp = self.detect_compiler(state.compilers)\n\n        extra_args = mesonlib.stringlistify(kwargs.get('args', []))\n        wrc_deps = extract_as_list(kwargs, 'depend_files', pop = True)\n        inc_dirs = extract_as_list(kwargs, 'include_directories', pop = True)\n        for incd in inc_dirs:\n            if not isinstance(incd.held_object, (str, build.IncludeDirs)):\n                raise MesonException('Resource include dirs should be include_directories().')\n        extra_args += get_include_args(inc_dirs)\n\n        if comp.id == 'msvc':\n            rescomp = dependencies.ExternalProgram('rc', silent=True)\n            res_args = extra_args + ['/nologo', '/fo@OUTPUT@', '@INPUT@']\n            suffix = 'res'\n        else:\n            m = 'Argument {!r} has a space which may not work with windres due to ' \\\n                'a MinGW bug: https://sourceware.org/bugzilla/show_bug.cgi?id=4933'\n            for arg in extra_args:\n                if ' ' in arg:\n                    mlog.warning(m.format(arg))\n            rescomp_name = None\n            # FIXME: Does not handle `native: true` executables, see\n            # https://github.com/mesonbuild/meson/issues/1531\n            if state.environment.is_cross_build():\n                # If cross compiling see if windres has been specified in the\n                # cross file before trying to find it another way.\n                rescomp_name = state.environment.cross_info.config['binaries'].get('windres')\n            if rescomp_name is None:\n                # Pick-up env var WINDRES if set. This is often used for\n                # specifying an arch-specific windres.\n                rescomp_name = os.environ.get('WINDRES', 'windres')\n            rescomp = dependencies.ExternalProgram(rescomp_name, silent=True)\n            res_args = extra_args + ['@INPUT@', '@OUTPUT@']\n            suffix = 'o'\n        if not rescomp.found():\n            raise MesonException('Could not find Windows resource compiler \"%s\".' % rescomp_name)\n\n        res_targets = []\n\n        def add_target(src):\n            if isinstance(src, list):\n                for subsrc in src:\n                    add_target(subsrc)\n                return\n\n            if hasattr(src, 'held_object'):\n                src = src.held_object\n\n            res_kwargs = {\n                'output': '@BASENAME@.' + suffix,\n                'input': [src],\n                'command': [rescomp] + res_args,\n                'depend_files': wrc_deps,\n            }\n\n            if isinstance(src, (str, mesonlib.File)):\n                name = 'file {!r}'.format(str(src))\n            elif isinstance(src, build.CustomTarget):\n                if len(src.get_outputs()) > 1:\n                    raise MesonException('windows.compile_resources does not accept custom targets with more than 1 output.')\n\n                name = 'target {!r}'.format(src.get_id())\n            else:\n                raise MesonException('Unexpected source type {!r}. windows.compile_resources accepts only strings, files, custom targets, and lists thereof.'.format(src))\n\n            # Path separators are not allowed in target names\n            name = name.replace('/', '_').replace('\\\\', '_')\n\n            # instruct binutils windres to generate a preprocessor depfile\n            if comp.id != 'msvc':\n                res_kwargs['depfile'] = res_kwargs['output'] + '.d'\n                res_kwargs['command'] += ['--preprocessor-arg=-MD', '--preprocessor-arg=-MQ@OUTPUT@', '--preprocessor-arg=-MF@DEPFILE@']\n\n            res_targets.append(build.CustomTarget('Windows resource for ' + name, state.subdir, state.subproject, res_kwargs))\n\n        add_target(args)\n\n        return ModuleReturnValue(res_targets, [res_targets])\n\ndef initialize(*args, **kwargs):\n    return WindowsModule(*args, **kwargs)\n", "path": "mesonbuild/modules/windows.py"}], "after_files": [{"content": "# Copyright 2015 The Meson development team\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport os\n\nfrom .. import mlog\nfrom .. import mesonlib, dependencies, build\nfrom ..mesonlib import MesonException, extract_as_list\nfrom . import get_include_args\nfrom . import ModuleReturnValue\nfrom . import ExtensionModule\nfrom ..interpreterbase import permittedKwargs, FeatureNewKwargs\n\nclass WindowsModule(ExtensionModule):\n\n    def detect_compiler(self, compilers):\n        for l in ('c', 'cpp'):\n            if l in compilers:\n                return compilers[l]\n        raise MesonException('Resource compilation requires a C or C++ compiler.')\n\n    @FeatureNewKwargs('windows.compile_resources', '0.47.0', ['depend_files'])\n    @permittedKwargs({'args', 'include_directories', 'depend_files'})\n    def compile_resources(self, state, args, kwargs):\n        comp = self.detect_compiler(state.compilers)\n\n        extra_args = mesonlib.stringlistify(kwargs.get('args', []))\n        wrc_deps = extract_as_list(kwargs, 'depend_files', pop = True)\n        inc_dirs = extract_as_list(kwargs, 'include_directories', pop = True)\n        for incd in inc_dirs:\n            if not isinstance(incd.held_object, (str, build.IncludeDirs)):\n                raise MesonException('Resource include dirs should be include_directories().')\n        extra_args += get_include_args(inc_dirs)\n\n        if comp.id == 'msvc':\n            rescomp = dependencies.ExternalProgram('rc', silent=True)\n            res_args = extra_args + ['/nologo', '/fo@OUTPUT@', '@INPUT@']\n            suffix = 'res'\n        else:\n            m = 'Argument {!r} has a space which may not work with windres due to ' \\\n                'a MinGW bug: https://sourceware.org/bugzilla/show_bug.cgi?id=4933'\n            for arg in extra_args:\n                if ' ' in arg:\n                    mlog.warning(m.format(arg))\n            rescomp_name = None\n            # FIXME: Does not handle `native: true` executables, see\n            # https://github.com/mesonbuild/meson/issues/1531\n            if state.environment.is_cross_build():\n                # If cross compiling see if windres has been specified in the\n                # cross file before trying to find it another way.\n                rescomp_name = state.environment.cross_info.config['binaries'].get('windres')\n            if rescomp_name is None:\n                # Pick-up env var WINDRES if set. This is often used for\n                # specifying an arch-specific windres.\n                rescomp_name = os.environ.get('WINDRES', 'windres')\n            rescomp = dependencies.ExternalProgram(rescomp_name, silent=True)\n            res_args = extra_args + ['@INPUT@', '@OUTPUT@']\n            suffix = 'o'\n        if not rescomp.found():\n            raise MesonException('Could not find Windows resource compiler \"%s\".' % rescomp_name)\n\n        res_targets = []\n\n        def add_target(src):\n            if isinstance(src, list):\n                for subsrc in src:\n                    add_target(subsrc)\n                return\n\n            if hasattr(src, 'held_object'):\n                src = src.held_object\n\n            res_kwargs = {\n                'output': '@BASENAME@.' + suffix,\n                'input': [src],\n                'command': [rescomp] + res_args,\n                'depend_files': wrc_deps,\n            }\n\n            if isinstance(src, str):\n                name = 'file {!r}'.format(os.path.join(state.subdir, src))\n            elif isinstance(src, mesonlib.File):\n                name = 'file {!r}'.format(src.relative_name())\n            elif isinstance(src, build.CustomTarget):\n                if len(src.get_outputs()) > 1:\n                    raise MesonException('windows.compile_resources does not accept custom targets with more than 1 output.')\n\n                name = 'target {!r}'.format(src.get_id())\n            else:\n                raise MesonException('Unexpected source type {!r}. windows.compile_resources accepts only strings, files, custom targets, and lists thereof.'.format(src))\n\n            # Path separators are not allowed in target names\n            name = name.replace('/', '_').replace('\\\\', '_')\n\n            # instruct binutils windres to generate a preprocessor depfile\n            if comp.id != 'msvc':\n                res_kwargs['depfile'] = res_kwargs['output'] + '.d'\n                res_kwargs['command'] += ['--preprocessor-arg=-MD', '--preprocessor-arg=-MQ@OUTPUT@', '--preprocessor-arg=-MF@DEPFILE@']\n\n            res_targets.append(build.CustomTarget('Windows resource for ' + name, state.subdir, state.subproject, res_kwargs))\n\n        add_target(args)\n\n        return ModuleReturnValue(res_targets, [res_targets])\n\ndef initialize(*args, **kwargs):\n    return WindowsModule(*args, **kwargs)\n", "path": "mesonbuild/modules/windows.py"}]}