简体   繁体   中英

Q_OBJECT does not name a type when converting a qmake project to cmake

I am trying to transition a shared library that uses Qt 5 and Q_OBJECT from QMake to CMake 3.2. Here is the current CMakeLists.txt file:

cmake_minimum_required(VERSION 3.2.2)

project(core)

# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)

find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Xml REQUIRED)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -pedantic-errors -Werror -Wextra -O2 -g -fno-omit-frame-pointer -Woverloaded-virtual")

add_definitions(-DCORE_LIBRARY)
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_NO_DEBUG)
add_definitions(-DQT_SHARED)

add_library( core SHARED
    src/reflect/TypeRegistry.h
    src/Profiler.h
    src/reflect/typeIdMacros.h
    src/reflect/Reflect.h
    src/AdapterManager.h
    src/core_api.h
    src/core.h
    src/EnvisionApplication.h
    src/EnvisionException.h
    src/EnvisionManager.h
    src/EnvisionPlugin.h
    src/PluginInfo.h
    src/global.h
    src/precompiled.h
    src/TestEvent.h
    src/TestRunner.h
    src/PluginManager.h
    src/EnvisionWindow.h
    src/reflect/TypeRegistry.cpp
    src/Profiler.cpp
    src/AdapterManager.cpp
    src/EnvisionException.cpp
    src/EnvisionManager.cpp
    src/core.cpp
    src/EnvisionApplication.cpp
    src/TestEvent.cpp
    src/TestRunner.cpp
    src/PluginManager.cpp
    src/EnvisionWindow.cpp
    src/global.cpp )

target_link_libraries(core Qt5::Core Qt5::Widgets Qt5::Xml Qt5::Gui)

With this CMakeLists.txt file, I can run cmake and it runs without any errors or warnings. However, when I run make I get an error:

$ make
[  7%] Automatic moc for target core
Generating moc_EnvisionApplication.cpp
Generating moc_EnvisionWindow.cpp
Generating moc_TestRunner.cpp
[  7%] Built target core_automoc
Scanning dependencies of target core
[ 14%] Building CXX object CMakeFiles/core.dir/src/reflect/TypeRegistry.cpp.o
[ 21%] Building CXX object CMakeFiles/core.dir/src/Profiler.cpp.o
[ 28%] Building CXX object CMakeFiles/core.dir/src/AdapterManager.cpp.o
[ 35%] Building CXX object CMakeFiles/core.dir/src/EnvisionException.cpp.o
[ 42%] Building CXX object CMakeFiles/core.dir/src/EnvisionManager.cpp.o
[ 50%] Building CXX object CMakeFiles/core.dir/src/core.cpp.o
In file included from /store/envision/envision/Core/src/core.cpp:27:0:
/store/envision/envision/Core/src/EnvisionWindow.h:30:1: error: expected class-name before ‘{’ token
 {
 ^
/store/envision/envision/Core/src/EnvisionWindow.h:31:2: error: ‘Q_OBJECT’ does not name a type
  Q_OBJECT
  ^
  ...

As you can see, the MOC is run, but it seems like the original header files with the Q_OBJECT macro are passed as is to gcc and it naturally has no clue what Q_OBJECT is and therefore fails. Perhaps the old build, QMake generated new header files and used those instead of the original ones, or avoided this issue in some other way.

Any ideas how to resolve this issue? I looked on-line but didn't find a definitive answer and I feel like there should be a straight-forward solution. Hopefully I don't have to modify any source code as this is just a small part of a bigger project.

I found the issue and it was quite silly, but I want to explain it just in case someone else runs into a similar problem while converting from QMake.

Since my code compiled just fine using QMake I didn't look inside the actual source file EnvisionWindow.h that gcc complained about, thinking that it must be a build issue. When I finally had a look, I saw that this file contains no includes, which is why the compiler couldn't find a definition for Q_OBJECT .

The reason it worked with QMake is because that build uses a precompiled header with the -include flag used for each source file, thus injecting all necessary definitions. This is the behavior one gets automatically when using PRECOMPILED_HEADER = precompiled_header_name.h in a QMake .pro file. I wish QMake didn't do this, since all files in my project are supposed to explicitly include the precompiled header.

Anyway, the solution was trivial: include the precompiled header in EnvisionWindow.h and everything compiles just fine now.

Lesson learned: take the compiler error more literally.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM