meson: Qt compile_moc() doesn't support files with the same name

Describe the bug

When using Qt’s compile_moc(), files that have the same file name, while being placed in different sub directories in the source tree, produce a configure-time error:

ERROR: Multiple producers for Ninja target "app.p/moc_value.cpp". Please rename your targets.

or

ERROR: Multiple producers for Ninja target "app.p/value.moc". Please rename your targets.

depending on whether one is using the headers or sources keyword argument.

To Reproduce

This minimal meson.build file:

project('bug', 'cpp')
qt = import('qt6')
app_sources = files('app.cpp')
app_sources += qt.compile_moc(sources: [
    'one/value.h',
    'two/value.h'])
executable('app', sources: app_sources)

Files one/value.h and two/value.h must exist, but can, for this error at configure time, be empty.

Expected behavior

There is no technical reason, why this shouldn’t work. CMake can do it and a handcrafted Makefile certainly can as well. The moc files need either be placed in separate directories (CMake creates unique build directories for this) and the include paths to these directories have to be provided at compile time. Or the filenames have to be prefixed with the directory (‘one_value.moc’ / ‘two_value.moc’), which seems more mesonic, but creates a problem when you want to include these files again (‘#include “one_value.moc”’ instead of the canonic ‘#include “value.moc”’ in both files, trusting the include paths to be correct.)

system parameters

  • Native linux build.
  • python 3.10.4
  • meson 0.63.3
  • ninja 1.10.1

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Comments: 21 (21 by maintainers)

Most upvoted comments

Yes, even if I place individual meson.build files inside the subdirectories one and two it wants to create two files app.p/value.moc. I’ve tried that before but forgot about that.

app.p is a per-target private directory.

If this were handled via manual running of generator().process() with find_program('moc') as the command to run, then all files will be generated into process() has a preserve_path_from: kwarg, which allows the input one/value.h to be transformed into app.p/one/moc_value.cpp; this is fine, because although Meson doesn’t generally allow outputting files into subdirectories, it allows it when operating inside the private directory for a target.

It’s perfectly reasonable to argue that the builtin moc should always do that too.