CMake error with Q_NAMESPACE and Q_ENUM_NS
-
Hi, I'm trying to use Q_NAMESPACE and Q_ENUM_NS to access externally defined enums in a header file. First I read a configuration entry from an .ini file and then get the value of that entry from the external defined enum. I have this code that works in a Qt .pro project but not in CMake 3.21
MLSettings.h file :
#pragma once #include <QSettings> class MLSettings { public: MLSettings(QString filename); int displayMode(); private: QSettings m_settings; };
MLSettings.cpp
#include "MLSettings.h" #include "MLAPIWrapper.h" #include <QMetaEnum> using namespace ML; MLSettings::MLSettings(QString filename) : m_settings(filename, QSettings::IniFormat) {} int MLSettings::displayMode() { QMetaEnum displayEnum = QMetaEnum::fromType< _BMDDisplayMode>(); return displayEnum.keyToValue(m_settings.value("DisplayMode").toString().toLatin1().data()); }
MLAPIWrapper.h
#pragma once #include <QObject> namespace ML { Q_NAMESPACE #include "DeckLinkAPI.h" Q_ENUM_NS( _BMDDisplayMode); Q_ENUM_NS( _BMDPixelFormat); };
and finally the external defined enums in DeckLinkAPI.h
typedef enum _BMDDisplayMode { bmdModeNTSC = 0x6e747363, bmdModeNTSC2398 = 0x6e743233, bmdModePAL = 0x70616c20, bmdModeNTSCp = 0x6e747370, bmdModePALp = 0x70616c70, bmdModeHD1080p2398 = 0x32337073, bmdModeHD1080p24 = 0x32347073, bmdModeHD1080p25 = 0x48703235, bmdModeHD1080p2997 = 0x48703239, bmdModeHD1080p30 = 0x48703330, bmdModeHD1080p4795 = 0x48703437, bmdModeHD1080p48 = 0x48703438, bmdModeHD1080p50 = 0x48703530, bmdModeHD1080p5994 = 0x48703539, bmdModeUnknown = 0x69756e6b } BMDDisplayMode;
This is the error I get when I compile this code in my CMAKE project
C:\APP\build\debug\src\APP_autogen\BTEEH7TBXR\moc_mlnamespace.cpp:243: error: 'bmdModeNTSC' is not a member of 'ML'; did you mean 'bmdModeNTSC'?
In file included from C:/APP/build/debug/src/APP_autogen/mocs_compilation.cpp:8:
C:/APP/build/debug/src/APP_autogen/BTEEH7TBXR/moc_mlnamespace.cpp:243:20: error: 'bmdModeNTSC' is not a member of 'ML'; did you mean 'bmdModeNTSC'?
243 | 2, uint(ML::bmdModeNTSC),
| ^~~~~~~~~~~ -
CMake compiles the code just fine for me. It fails linking because the code is not complete.
It looks to me like CMake's AUTOMOC never processes
MLAPIWrapper.h
.. This means the code to provide support to the Metaobject system is not built and included. While automoc does read MLSettings.h it does not follow the include.The easiest way I found to trigger this processing was to add a one-line
MLAPIWrapper.cpp
file:#include "MLAPIWrapper.h"
and add this to:
add_executable(test main.cpp MLSettings.cpp MLAPIWrapper.cpp )
-
@ChrisW67 said in CMake error with Q_NAMESPACE and Q_ENUM_NS:
It looks to me like CMake's AUTOMOC never processes MLAPIWrapper.h
It does but there is no trigger to create a moc file from: https://cmake.org/cmake/help/latest/prop_tgt/AUTOMOC.html#header-file-processing
The easiest way I found to trigger this processing was to add a one-line MLAPIWrapper.cpp file:
or use qt_wrap_cpp()
-
@ChrisW67 , @Christian-Ehrlicher , thank you very much for your answers. I think I'll have to go with @ChrisW67 's answer because qt_wrap_cpp() is deprecated since 3.14. qt_wrap_cpp.html ...... again much appreciated.
-
@xyfix said in CMake error with Q_NAMESPACE and Q_ENUM_NS:
qt_wrap_cpp() is deprecated since 3.14
I did not wrote qt5_wrap_cpp() or qt6_wrap_cpp since I was unsure about the version you use. They're not deprecated.
-
Hi,
Are you wrapping the Blackmagic API for your application ?
-
@Christian-Ehrlicher , my bad you're absolutely right, it's not depricated ... I tried both of the solutions but I still get compilation errors while building moc_compilation.cpp
error: 'bmdModeNTSC' is not a member of 'ML'; did you mean 'bmdModeNTSC'?
The moc_mlapiwrapper.cpp is created though ( below is a part of a much larger file)
/**************************************************************************** ** Meta object code from reading C++ file 'mlapiwrapper.h' ** ** Created by: The Qt Meta Object Compiler version 68 (Qt 6.2.4) ** ** WARNING! All changes made in this file will be lost! *****************************************************************************/ #include <memory> #include "../../../../../src/acquisition/mlapiwrapper.h" #include <QtCore/qbytearray.h> #include <QtCore/qmetatype.h> #if !defined(Q_MOC_OUTPUT_REVISION) #error "The header file 'mlapiwrapper.h' doesn't include <QObject>." #elif Q_MOC_OUTPUT_REVISION != 68 #error "This file was generated using the moc from 6.2.4. It" #error "cannot be used with the include files from this version of Qt." #error "(The moc has changed too much.)" #endif QT_BEGIN_MOC_NAMESPACE QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED struct qt_meta_stringdata_ML_t { const uint offsetsAndSize[252]; char stringdata0[2146]; }; #define QT_MOC_LITERAL(ofs, len) \ uint(offsetof(qt_meta_stringdata_ML_t, stringdata0) + ofs), len static const qt_meta_stringdata_ML_t qt_meta_stringdata_ML = { { QT_MOC_LITERAL(0, 2), // "ML" QT_MOC_LITERAL(3, 15), // "_BMDDisplayMode" QT_MOC_LITERAL(19, 11), // "bmdModeNTSC" QT_MOC_LITERAL(31, 15), // "bmdModeNTSC2398" QT_MOC_LITERAL(47, 10), // "bmdModePAL" QT_MOC_LITERAL(58, 12), // "bmdModeNTSCp" QT_MOC_LITERAL(71, 11), // "bmdModePALp" QT_MOC_LITERAL(83, 18), // "bmdModeHD1080p2398" QT_MOC_LITERAL(102, 16), // "bmdModeHD1080p24" QT_MOC_LITERAL(119, 16), // "bmdModeHD1080p25" QT_MOC_LITERAL(136, 18), // "bmdModeHD1080p2997" QT_MOC_LITERAL(155, 16), // "bmdModeHD1080p30" QT_MOC_LITERAL(172, 18), // "bmdModeHD1080p4795" QT_MOC_LITERAL(191, 16), // "bmdModeHD1080p48" QT_MOC_LITERAL(208, 16), // "bmdModeHD1080p50" QT_MOC_LITERAL(225, 18), // "bmdModeHD1080p5994"
I'm doing something wrong but not sure what ? I also tried the set_property( mlapiwrapper.h PROPERTY SKIP_AUTOMOC ON) but no success.
-
What I don't understand is why my moc_MLAPIWrapper.cpp is the same (as in my previous post) whether I have a MLAPIWrapper.cpp ( with the line "#include "MLAPIWrapper.h" ) or not? and why are the enums not found in the ML namespace while they are there in the moc file?
-
Did you check whether it's simply not included in the final file list to build for your application ?
-
@SGaist ,
yes I had checked that and now double checked it after your message. My main CMakeLists.txt contains
target_link_libraries( APPLib PUBLIC DecklinkSupport::libUltraStudioRecorder3G)
I have a DecklinkSupport.cmake file
include(GNUInstallDirs) if (NOT WIN32) message(FATAL_ERROR "Decklink package only supports Windows.") endif() ## Find library files # includes find_path(LIBDECKLINK_INCLUDE_DIR NAMES UltraStudioRecorder3G.h PATHS ${DECKLINK_DIR}/include ) # UltraStudoRecorder3G find_library(LIBULTRASTUDIORECORDER3G_LIBRARY NAMES libUltraStudioRecorder3G PATHS ${DECKLINK_DIR}/lib ) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(DecklinkSupport DEFAULT_MSG LIBULTRASTUDIORECORDER3G_LIBRARY LIBDECKLINK_INCLUDE_DIR ) mark_as_advanced(LIBULTRASTUDIORECORDER3G_LIBRARY LIBDECKLINK_INCLUDE_DIR) ## Create library targets if(DecklinkSupport_FOUND) if (NOT TARGET DecklinkSupport::libUltraStudioRecorder3G) add_library(DecklinkSupport::libUltraStudioRecorder3G STATIC IMPORTED GLOBAL) set_target_properties(DecklinkSupport::libUltraStudioRecorder3G PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBDECKLINK_INCLUDE_DIR}" IMPORTED_LOCATION "${LIBULTRASTUDIORECORDER3G_LIBRARY}" ) endif() endif()
the ${DECKLINK_DIR}/include directory holds all the decklink header files.
and the CMakeLists.txt file in my aquisition subdirectory
target_sources( APPLib PRIVATE Interfaces/iacquisition.h Interfaces/icamera.h mlapiwrapper.h mlsettings.cpp mlsettings.h ultrastudioacquisition.cpp ultrastudioacquisition.h ultrastudiocamera.cpp ultrastudiocamera.h )
It fails when it tries to build the mocs_compilation.obj file
FAILED: src/CMakeFiles/APPLib.dir/APPLib_autogen/mocs_compilation.cpp.obj C:\Qt\Tools\mingw1120_64\bin\g++.exe -DMINGW_HAS_SECURE_API=1 -DNTDDI_VERSION=NTDDI_WIN10_CO -DQT_CONCURRENT_LIB -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_OPENGLWIDGETS_LIB -DQT_OPENGL_LIB -DQT_PRINTSUPPORT_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_QUICK_LIB -DQT_SERIALPORT_LIB -DQT_SQL_LIB -DQT_STATEMACHINE_LIB -DQT_USE_QSTRINGBUILDER -DQT_WIDGETS_LIB -DQT_XML_LIB -DUNICODE -DUSING_PCH -DWIN32 -DWIN64 -DWINVER=0x0A00 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE -D_USER32_ -D_WIN32_WINNT=0x0A00 -D_WIN64 -IC:/development/APP/build/debug/src -IC:/development/APP/src -IC:/development/APP/build/debug/src/APPLib_autogen/include -IC:/development/APP/src/log -IC:/development/APP/src/../Libraries -IC:/development/APP/src/../Tools/qt-solutions/qtsingleapplication/src -isystem C:/Qt/6.2.4/mingw_64/include/QtConcurrent -isystem C:/Qt/6.2.4/mingw_64/include -isystem C:/Qt/6.2.4/mingw_64/include/QtCore -isystem C:/Qt/6.2.4/mingw_64/mkspecs/win32-g++ -isystem C:/Qt/6.2.4/mingw_64/include/QtGui -isystem C:/Qt/6.2.4/mingw_64/include/QtQuick -isystem C:/Qt/6.2.4/mingw_64/include/QtQml -isystem C:/Qt/6.2.4/mingw_64/include/QtNetwork -isystem C:/Qt/6.2.4/mingw_64/include/QtQmlModels -isystem C:/Qt/6.2.4/mingw_64/include/QtOpenGL -isystem C:/Qt/6.2.4/mingw_64/include/QtPrintSupport -isystem C:/Qt/6.2.4/mingw_64/include/QtWidgets -isystem C:/Qt/6.2.4/mingw_64/include/QtSerialPort -isystem C:/Qt/6.2.4/mingw_64/include/QtSql -isystem C:/Qt/6.2.4/mingw_64/include/QtXml -isystem C:/Qt/6.2.4/mingw_64/include/QtOpenGLWidgets -isystem C:/Qt/6.2.4/mingw_64/include/QtStateMachine -isystem C:/development/APP/build/debug/_deps/opencv_release/include -isystem C:/boost/boost_1_79_0 -isystem C:/Qt/qwt-6.2.0/include -isystem C:/development/APP/build/debug/_deps/decklinksupport_debug/include -isystem C:/development/APP/Libraries/OpenSSL/include -isystem C:/development/APP/Libraries/ADVobfuscator/include -isystem C:/development/APP/Libraries/RLM/include -g -ftemplate-depth=2000 -std=gnu++20 -MD -MT src/CMakeFiles/APPLib.dir/APPLib_autogen/mocs_compilation.cpp.obj -MF src\CMakeFiles\APPLib.dir\APPLib_autogen\mocs_compilation.cpp.obj.d -o src/CMakeFiles/APPLib.dir/APPLib_autogen/mocs_compilation.cpp.obj -c C:/development/APP/build/debug/src/APPLib_autogen/mocs_compilation.cpp In file included from C:/development/APP/build/debug/src/APPLib_autogen/mocs_compilation.cpp:9: C:/development/APP/build/debug/src/APPLib_autogen/BTEEH7TBXR/moc_decklinknamespace.cpp:243:20: error: 'bmdModeNTSC' is not a member of 'ML'; did you mean 'bmdModeNTSC'? 243 | 2, uint(ML::bmdModeNTSC), | ^~~~~~~~~~~ In file included from C:/development/APP/build/debug/_deps/decklinksupport_debug/include/DecklinkFrame.h:5, from C:/development/APP/build/debug/_deps/decklinksupport_debug/include/IFrameHandler.h:4, from C:/development/APP/src/acquisition/UltraStudioAcquisition.h:6, from C:/development/APP/build/debug/src/APPLib_autogen/BTEEH7TBXR/moc_UltraStudioAcquisition.cpp:10, from C:/development/APP/build/debug/src/APPLib_autogen/mocs_compilation.cpp:8: C:/development/APP/build/debug/_deps/decklinksupport_debug/include/DeckLinkAPI.h:1089:9: note: 'bmdModeNTSC' declared here 1089 | bmdModeNTSC = 0x6e747363, | ^~~~~~~~~~~ In file included from C:/development/APP/build/debug/src/APPLib_autogen/mocs_compilation.cpp:9: C:/development/APP/build/debug/src/APPLib_autogen/BTEEH7TBXR/moc_decklinknamespace.cpp:244:20: error: 'bmdModeNTSC2398' is not a member of 'ML'; did you mean 'bmdModeNTSC2398'? 244 | 3, uint(ML::bmdModeNTSC2398), | ^~~~~~~~~~~~~~~
-
I just found out that if I copy the two enums from the DeckLinkAPI.h file and put them in a new file ( only the enums ) and include that file like this
#pragma once #include <QObject> namespace DLink { Q_NAMESPACE // #include "DeckLinkAPI.h" #include "DeckLinkEnumWrapper.h" Q_ENUM_NS( _BMDDisplayMode); Q_ENUM_NS( _BMDPixelFormat); };
and then everything compiles and works. I guess the DeckLinkAPI.h file has something that prevents a successful compilation, since this is an external file I don't know how to solve it other than what I did above, any one have an idea?