Repository: mesonbuild/meson

Issue:
qt5.compile_moc ignores include paths from dependencies
**Describe the bug**
Passing the `dependency` parameter to `qt5.compile_moc` does not bring in all the include paths specified in the dependency.

**To Reproduce**
[mesontest.tar.gz](https://github.com/mesonbuild/meson/files/12482449/mesontest.tar.gz)

Results in a failed build:
```
[1/4] Generating 'program.p/moc_includer.cpp'.
FAILED: program.p/moc_includer.cpp 
/usr/lib/x86_64-linux-gnu/qt5/bin/moc --output-dep-file -DQT_CORE_LIB -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 -DQT_CORE_LIB -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 ../includer.h -o program.p/moc_includer.cpp
../includer.h:11: Parse error at "IFACE_NAME"
[2/4] Compiling C++ object program.p/main.cpp.o
ninja: build stopped: subcommand failed.
```

Note that the directory `subdir` is missing from the list of includes passed to `moc`.

**Expected behavior**
The include path added to the `subdir_dep` in `subdir/meson.build` should be added to the list of include paths when invoking the moc.

**system parameters**
* native build
* Ubuntu 22.04
* Python 3.10.12
* meson 0.61.2
* ninja 1.10.1



Discussion:
Occurs with meson 0.63.3 too.
Can you test with master?

@bruchar1 is this something you could help with?
At first sight, it seems that the qt module gets the compile args from the dependencies, but for internal dependencies, compile args do no include include dirs, as the include dirs are stored in a different member, and are usually resolved by the backend.

The fix is probably to add the include dirs to compile args, in the `_compile_moc_impl` function of the qt module. I wonder if this problem exists elsewhere in the code? But qt seems the only module to use Generator object, so the answer is probably no.

Resolving patch:
diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py
--- a/mesonbuild/modules/qt.py
+++ b/mesonbuild/modules/qt.py
@@ -23,7 +23,7 @@
 from .. import build
 from .. import coredata
 from .. import mlog
-from ..dependencies import find_external_dependency, Dependency, ExternalLibrary
+from ..dependencies import find_external_dependency, Dependency, ExternalLibrary, InternalDependency
 from ..mesonlib import MesonException, File, version_compare, Popen_safe
 from ..interpreter import extract_required_kwarg
 from ..interpreter.type_checking import INSTALL_DIR_KW, INSTALL_KW, NoneType
@@ -457,7 +457,10 @@ def _compile_moc_impl(self, state: 'ModuleState', kwargs: 'MocCompilerKwArgs') -
         inc = state.get_include_args(include_dirs=kwargs['include_directories'])
         compile_args: T.List[str] = []
         for dep in kwargs['dependencies']:
-            compile_args.extend([a for a in dep.get_all_compile_args() if a.startswith(('-I', '-D'))])
+            compile_args.extend(a for a in dep.get_all_compile_args() if a.startswith(('-I', '-D')))
+            if isinstance(dep, InternalDependency):
+                for incl in dep.include_directories:
+                    compile_args.extend(f'-I{i}' for i in incl.to_string_list(self.interpreter.source_root, self.interpreter.environment.build_dir))
 
         output: T.List[build.GeneratedList] = []
 
@@ -474,7 +477,7 @@ def _compile_moc_impl(self, state: 'ModuleState', kwargs: 'MocCompilerKwArgs') -
         if kwargs['sources']:
             moc_gen = build.Generator(
                 self.tools['moc'], arguments, ['@BASENAME@.moc'],
-                depfile='@BASENAME.moc.d@',
+                depfile='@BASENAME@.moc.d',
                 name=f'Qt{self.qt_version} moc source')
             output.append(moc_gen.process_files(kwargs['sources'], state))
 


Test patch:
diff --git a/test cases/frameworks/4 qt/manualinclude.cpp b/test cases/frameworks/4 qt/manualinclude.cpp
--- a/test cases/frameworks/4 qt/manualinclude.cpp	
+++ b/test cases/frameworks/4 qt/manualinclude.cpp	
@@ -1,4 +1,5 @@
 #include"manualinclude.h"
+#include <mocdep.h>
 #include<QCoreApplication>
 
 #include<QObject>
diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build
--- a/test cases/frameworks/4 qt/meson.build	
+++ b/test cases/frameworks/4 qt/meson.build	
@@ -2,6 +2,9 @@ project('qt4, qt5, and qt6 build test', 'cpp',
   # Qt6 requires C++ 17 support
   default_options : ['cpp_std=c++17'])
 
+# Visit the subdir before entering the loop
+subdir('mocdep')
+
 qt5_modules = ['Widgets']
 qt6_modules = ['Widgets']
 foreach qt : ['qt4', 'qt5', 'qt6']
@@ -114,17 +117,21 @@ foreach qt : ['qt4', 'qt5', 'qt6']
       moc_extra_arguments : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `extra_arguments`
       moc_sources : 'manualinclude.cpp',
       moc_headers : 'manualinclude.h',
-      method : get_option('method'))
+      method : get_option('method'),
+      dependencies: mocdep,
+    )
 
     manpreprocessed = qtmodule.compile_moc(
       extra_args : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `extra_arguments`
       sources : 'manualinclude.cpp',
       headers : 'manualinclude.h',
-      method : get_option('method'))
+      method : get_option('method'),
+      dependencies: mocdep,
+    )
 
     qtmaninclude = executable(qt + 'maninclude',
       sources : ['manualinclude.cpp', manpreprocessed],
-      dependencies : qtcore)
+      dependencies : [qtcore, mocdep])
 
     test(qt + 'maninclude', qtmaninclude)
 
diff --git a/test cases/frameworks/4 qt/mocdep/meson.build b/test cases/frameworks/4 qt/mocdep/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/frameworks/4 qt/mocdep/meson.build	
@@ -0,0 +1,3 @@
+mocdep = declare_dependency(
+    include_directories: include_directories('.'),
+)
diff --git a/test cases/frameworks/4 qt/mocdep/mocdep.h b/test cases/frameworks/4 qt/mocdep/mocdep.h
new file mode 100644
--- /dev/null
+++ b/test cases/frameworks/4 qt/mocdep/mocdep.h	
@@ -0,0 +1 @@
+#define MOC_DEP 1