Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-139212

New target form of qt6_wrap_cpp() doesn't work if given header files

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P2: Important P2: Important
    • None
    • 6.9.1
    • Build System: CMake
    • None
    • All

      Consider the following call to qt6_wrap_cpp():

      qt6_wrap_cpp(MyQtApp MyClass.h)
      

      where MyQtApp is a CMake target and MyClass.h is a header file that defines a typical subclass of QObject. This is using the new form of qt6_wrap_cpp() added in Qt 6.8.

      The implementation of qt6_wrap_cpp() calls _qt_internal_wrap_cpp(), passing dummy as the first argument, which is meant to hold the set of output files when that call returns. The value of dummy is never used.

      In _qt_internal_wrap_cpp(), the following code handles header files (provided through the function arguments):

              if(it_ext MATCHES "${HEADER_REGEX}")
                  _qt_internal_make_output_file("${it}" moc_ cpp outfile)
                  set(is_header_file TRUE)
              else()
                  ...
      

      Then later on, towards the end of _qt_internal_wrap_cpp() is the following:

          if(is_header_file)
              set(${outfiles} "${${outfiles}}" PARENT_SCOPE)
          endif()
      

      It seems that for header files, the output file from moc is not added directly to the target via target_sources() (which seems like the heart of this bug), it is only added to the list of files passed back to the caller of _qt_internal_wrap_cpp(), with the expectation that it will be in turn passed back to the caller of qt6_wrap_cpp(). However, the new target form discards that list (stored in dummy), so the caller never gets to see the list of output files. That in turn means the caller can't add the output files as sources to the target, so any output file from processing a header file never gets added to the build. The result is usually a linker error complaining about missing symbols related to vtables, etc.

      For files that are not headers, qt_internal_wrap_cpp() _does call target_sources() to add those to the target. It seems like an oversight that this isn't done for output files from headers too. Perhaps there is an assumption that a source file does a #include "moc_basename.cpp", but this is not stated in the documentation and is not required by the old form of qt6_wrap_cpp.

      The if(is_header_file) test at the end outside the foreach loop also looks wrong. Why should we only be returning the list of output files if at least one of them was a header? What we called qt6_wrap_cpp() with just source files? What if we called it with a mix of sources and headers? It's hard to see how the current logic could do the right thing in any of these cases.

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            qtbuildsystem Qt Build System Team
            crscott Craig Scott
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:

                There are no open Gerrit changes