Repository: mesonbuild/meson

Issue:
Add something like depend_files to windows.compile_resources()
Resource script can include various other files (bitmap, cursor, font, html, icon, message table, binary data, manifest), it would be nice if it were possible to declare the resource script depends on these.


Discussion:
Compile resources parses the dependency file's contents and adds dependencies to files listed in it. This should already work.
Perhaps I should have noted I meant in the Windows module. I created a sample project with a resource file that includes an application manifest, and there does not seem to be any dependency on it.
~~~
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "foo.manifest"
~~~
> Resource script can include various other files (bitmap, cursor, font, html, icon, message table, binary data, manifest), it would be nice if it were possible to declare the resource script depends on these.

The other class of files the resource script may depend on are files which are  #included using the C preprocessor.  I guess it may be possible to write the custom target for invoking the resource compiler such that a depfile is generated by the preprocessor?
Please re-open this issue.  #2815 contains text like "could fix #2789", but doesn't fix this issue.

Resolving patch:
diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py
--- a/mesonbuild/modules/windows.py
+++ b/mesonbuild/modules/windows.py
@@ -30,11 +30,12 @@ def detect_compiler(self, compilers):
                 return compilers[l]
         raise MesonException('Resource compilation requires a C or C++ compiler.')
 
-    @permittedKwargs({'args', 'include_directories'})
+    @permittedKwargs({'args', 'include_directories', 'depend_files'})
     def compile_resources(self, state, args, kwargs):
         comp = self.detect_compiler(state.compilers)
 
         extra_args = mesonlib.stringlistify(kwargs.get('args', []))
+        wrc_deps = extract_as_list(kwargs, 'depend_files', pop = True)
         inc_dirs = extract_as_list(kwargs, 'include_directories', pop = True)
         for incd in inc_dirs:
             if not isinstance(incd.held_object, (str, build.IncludeDirs)):
@@ -83,6 +84,7 @@ def add_target(src):
                 'output': '@BASENAME@.' + suffix,
                 'input': [src],
                 'command': [rescomp] + res_args,
+                'depend_files': wrc_deps,
             }
 
             if isinstance(src, (str, mesonlib.File)):
diff --git a/run_unittests.py b/run_unittests.py
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -735,9 +735,7 @@ def assertRebuiltTarget(self, target):
             self.assertIn('Linking target {}'.format(target), ret)
         elif self.backend is Backend.vs:
             # Ensure that this target was rebuilt
-            clre = re.compile('ClCompile:\n [^\n]*cl[^\n]*' + target, flags=re.IGNORECASE)
             linkre = re.compile('Link:\n [^\n]*link[^\n]*' + target, flags=re.IGNORECASE)
-            self.assertRegex(ret, clre)
             self.assertRegex(ret, linkre)
         elif self.backend is Backend.xcode:
             raise unittest.SkipTest('Please help us fix this test on the xcode backend')
@@ -2337,6 +2335,7 @@ def setUp(self):
         super().setUp()
         self.platform_test_dir = os.path.join(self.src_root, 'test cases/windows')
 
+    @unittest.skipIf(is_cygwin(), 'Test only applicable to Windows')
     def test_find_program(self):
         '''
         Test that Windows-specific edge-cases in find_program are functioning
@@ -2389,6 +2388,16 @@ def test_ignore_libs(self):
         for l in cc.ignore_libs:
             self.assertEqual(cc.find_library(l, env, []), [])
 
+    def test_rc_depends_files(self):
+        testdir = os.path.join(self.platform_test_dir, '5 resources')
+        self.init(testdir)
+        self.build()
+        # Immediately rebuilding should not do anything
+        self.assertBuildIsNoop()
+        # Changing mtime of sample.ico should rebuild everything
+        self.utime(os.path.join(testdir, 'res', 'sample.ico'))
+        self.assertRebuiltTarget('prog')
+
 
 class LinuxlikeTests(BasePlatformTests):
     '''
@@ -3304,7 +3313,7 @@ def unset_envs():
         cases += ['LinuxlikeTests']
         if should_run_linux_cross_tests():
             cases += ['LinuxArmCrossCompileTests']
-    elif is_windows():
+    if is_windows() or is_cygwin():
         cases += ['WindowsTests']
 
     unittest.main(defaultTest=cases, buffer=True)


Test patch:
diff --git a/test cases/windows/5 resources/res/meson.build b/test cases/windows/5 resources/res/meson.build
--- a/test cases/windows/5 resources/res/meson.build	
+++ b/test cases/windows/5 resources/res/meson.build	
@@ -1,4 +1,5 @@
 win = import('windows')
 
 res = win.compile_resources('myres.rc',
+  depend_files: 'sample.ico',
   include_directories : inc)