Search code examples
qtcmakeconan

Cannot make Conan + CMake + QT work together. No valid Qt version found for target


When I set set(CMAKE_AUTOMOC ON) cmake says

CMake Warning (dev) in src/ProjQt/CMakeLists.txt: AUTOGEN: No valid Qt version found for target ProjQt. AUTOMOC disabled. Consider adding:

find_package(Qt<QTVERSION> COMPONENTS Core)

to your CMakeLists.txt file.

If I add find_package(Qt5 COMPONENTS Core) before set(CMAKE_AUTOMOC ON)

CMake Warning at src/ProjQt/CMakeLists.txt:5 (find_package):
By not providing "FindQt5.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "Qt5",
but CMake did not find one.
...

I thought conan provides a custom find_package which behaviour is conan-related first, then default if failed but it looks like it doesn't provide it like vcpkg does

All these actions are done after include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)


Solution

  • I've encountered the same issue again and this is how I managed to fix it:

    1. Set an appropriate conan generator to generate needed config CMake files
    • I use generators = "cmake_find_package_multi" as mentioned in this issue (Again my own issue)
    1. Conan now generates a whole lot of <PKG>Config/Target.cmake files (in my case), we need to point CMake to look for configurations in that folder as specified in conan docs and here in CMake docs
    2. At that point AUTOMOC, AUTOUIC and AUTORCC should work with this piece of config:
    find_package(Qt5 CONFIG REQUIRED)
    set(CMAKE_AUTOMOC ON)
    set(CMAKE_AUTOUIC ON)
    set(CMAKE_AUTORCC ON)
    

    I've encountered two types of different issues later on …


    AutoMoc error
    -------------
    "SRC:/src/<thisfilename>.cpp"
    contains a "Q_OBJECT" macro, but does not include "<thisfilename>.moc"!
    Consider to
      - add #include "<thisfilename>.moc"
      - enable SKIP_AUTOMOC for this file
    

    This is resolved either by moving Q_OBJECT class into header or adding #include <thisfilename.moc> below the class, CMake automatically populates direct path to this file without paths nesting. For example if I have a file called "test.cpp" I have to do this:

    #include <QObject>
    
    class TestObject : public QObject
    {
        Q_OBJECT
    };
    
    #include <test.moc>
    

    Linker errors with unresolved references to metaObject, qt_metacast, qt_metacall, etc …
    In that case it means that moc's generated source code was not added into compilation.
    It can be resolved either with adding header files along with .cpp files in add_executable call:

    file(GLOB SOURCES
        include/*.h
        src/*.cpp
    )
    add_executable(${PROJECT_NAME} ${SOURCES})
    

    the above has an obvious downside, after each newly created header you have to reconfigure CMake to generate moc stuff

    The other way to fix it is to include a file #include <moc_thisfilename.cpp> in the Q_OBJECT's cpp implementation file like that:
    test.hpp

    #include <QObject>
    
    class TestObject : public QObject
    {
        Q_OBJECT
    };
    

    test.cpp

    #include <test.hpp>
    #include <moc_test.cpp>
    

    I haven't yet find a way to forget about this moc generation magic and make CMake autoinclude everything in a smart way when including header containing Q_OBJECT related stuff