CMake не запускает moc для Q_NAMESPACE в общей библиотеке

Проблема

Я пытаюсь зарегистрировать пространство имен в QML из общей библиотеки, но компиляция завершается с ошибкой неразрешенного внешнего символа:

failed (exit code 1120) with the following output:
main.cpp.obj : error LNK2019: unresolved external symbol "struct QMetaObject const EnumNamespace::staticMetaObject" (?staticMetaObject@EnumNamespace@@3UQMetaObject@@B) referenced in function "class QDebug __cdecl operator<<<enum EnumNamespace::MyEnum>(class QDebug,enum EnumNamespace::MyEnum)" (??$?6W4MyEnum@EnumNamespace@@@@YA?AVQDebug@@V0@W4MyEnum@EnumNamespace@@@Z)
StaticMetaObject.exe : fatal error LNK1120: 1 unresolved externals

Я искал в каталоге сборки файл moc (moc_enum.cpp или аналогичный), но не смог его найти. Единственный файл, связанный с moc, который я смог найти, был mocs_compilation.cpp:

// This file is autogenerated. Changes will be overwritten.
// No files found that require moc or the moc files are included
enum some_compilers { need_more_than_nothing };

Почему CMake не находит нужный файл для moc?

PS: Если вместо использования CMake я использую qmake, он компилируется нормально, и файл moc_enum.cpp присутствует в каталоге сборки.

PS2: Есть несколько вопросов по этой проблеме или похожих, но, к сожалению, либо на них нет ответа, либо это не сработало (например: это , это или это)

Настраивать

  • Qt 5.12.10 и Qt Creator 10.0.0
  • CMake 3.23 (интегрирован в Qt Creator)
  • 64-битный компилятор Visual Studio 2017.

Код

Основной CMakeLists.txt

cmake_minimum_required(VERSION 3.23 FATAL_ERROR)

project(StaticMetaObject VERSION 1.0.0 LANGUAGES CXX DESCRIPTION "Static Meta Object Test")

set(BUILD_SHARED_LIBS ON)
set(CMAKE_DEBUG_POSTFIX d)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

find_package(QT NAMES Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Qml)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

add_subdirectory(enum)

add_executable(${PROJECT_NAME})
target_sources(${PROJECT_NAME} PUBLIC main.cpp)
target_link_libraries(${PROJECT_NAME} enumLib Qt${QT_VERSION_MAJOR}::Qml)

main.cpp

#include "enum/enum.h"
#include <QCoreApplication>
#include <QDebug>
#include <QQmlEngine>

// ------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------
int main(int argc, char * *argv)
{
    QCoreApplication app{argc, argv};
    qInfo() << EnumNamespace::TWO;

    // Comenting this line out doesn't solve the problem.
    qmlRegisterUncreatableMetaObject(EnumNamespace::staticMetaObject, "ABCDE", 1, 0, "EnumNamespace", "Error: only enums");

    return app.exec();
}

Библиотека перечисления

CMakeLists.txt

cmake_minimum_required(VERSION "${CMAKE_MINIMUM_REQUIRED_VERSION}" FATAL_ERROR)

set(LIB_NAME enumLib)
add_library(${LIB_NAME} SHARED)
set_target_properties(${LIB_NAME} PROPERTIES LINKER_LANGUAGE CXX)
target_sources(${LIB_NAME} PUBLIC enum.h enumLib.h)
target_compile_definitions(${LIB_NAME} PUBLIC ENUMLIB_BUILD)
target_link_libraries(${LIB_NAME} PUBLIC Qt${QT_VERSION_MAJOR}::Core)

перечисление.ч

#ifndef ENUM_H
#define ENUM_H

#include "enumLib.h"
#include <QObject>

namespace EnumNamespace {
    ENUMLIB_EXPORT Q_NAMESPACE
    enum MyEnum : unsigned int
    {
        ZERO = 0,
        ONE,
        TWO
    };
    Q_ENUM_NS(MyEnum);
}

#endif // ENUM_H

enumLib.h

#ifndef ENUMLIB_H
#define ENUMLIB_H

#if defined(ENUMLIB_BUILD)
#define ENUMLIB_EXPORT Q_DECL_EXPORT
#else
#define ENUMLIB_EXPORT Q_DECL_IMPORT
#endif

#endif // ENUMLIB_H

Профайл

QT = core

CONFIG += c++17 cmdline

QT += core qml

DEFINES += ENUMLIB_BUILD

HEADERS += \
        enum/enum.h \
        enum/enum.h \
        enum/enumLib.h

SOURCES += \
        main.cpp

Полный журнал сборки CMake

16:00:30: Running steps for project StaticMetaObject...
16:00:30: Starting: "C:\Qt\Tools\CMake_64\bin\cmake.exe" --build C:/SRC/MyTests/StaticMetaObject/build_release --target all
[1/7 21.4/sec] Automatic MOC and UIC for target enumLib
[2/5 22.1/sec] Automatic MOC and UIC for target StaticMetaObject
[3/5 9.0/sec] Building CXX object CMakeFiles\StaticMetaObject.dir\StaticMetaObject_autogen\mocs_compilation.cpp.obj
[4/5 4.3/sec] Building CXX object CMakeFiles\StaticMetaObject.dir\main.cpp.obj
[5/5 4.8/sec] Linking CXX executable StaticMetaObject.exe
FAILED: StaticMetaObject.exe 
cmd.exe /C "cd . && C:\Qt\Tools\CMake_64\bin\cmake.exe -E vs_link_exe --intdir=CMakeFiles\StaticMetaObject.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\mt.exe --manifests  -- C:\PROGRA~2\MICROS~2\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\Hostx64\x64\link.exe /nologo CMakeFiles\StaticMetaObject.dir\StaticMetaObject_autogen\mocs_compilation.cpp.obj CMakeFiles\StaticMetaObject.dir\main.cpp.obj  /out:StaticMetaObject.exe /implib:StaticMetaObject.lib /pdb:StaticMetaObject.pdb /version:0.0 /machine:x64 /INCREMENTAL:NO /subsystem:console  enum\enumLib.lib  C:\Qt\5.12.10\msvc2017_64\lib\Qt5Qml.lib  C:\Qt\5.12.10\msvc2017_64\lib\Qt5Network.lib  C:\Qt\5.12.10\msvc2017_64\lib\Qt5Core.lib  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
LINK: command "C:\PROGRA~2\MICROS~2\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\Hostx64\x64\link.exe /nologo CMakeFiles\StaticMetaObject.dir\StaticMetaObject_autogen\mocs_compilation.cpp.obj CMakeFiles\StaticMetaObject.dir\main.cpp.obj /out:StaticMetaObject.exe /implib:StaticMetaObject.lib /pdb:StaticMetaObject.pdb /version:0.0 /machine:x64 /INCREMENTAL:NO /subsystem:console enum\enumLib.lib C:\Qt\5.12.10\msvc2017_64\lib\Qt5Qml.lib C:\Qt\5.12.10\msvc2017_64\lib\Qt5Network.lib C:\Qt\5.12.10\msvc2017_64\lib\Qt5Core.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:StaticMetaObject.exe.manifest" failed (exit code 1120) with the following output:
main.cpp.obj : error LNK2019: unresolved external symbol "struct QMetaObject const EnumNamespace::staticMetaObject" (?staticMetaObject@EnumNamespace@@3UQMetaObject@@B) referenced in function "class QDebug __cdecl operator<<<enum EnumNamespace::MyEnum>(class QDebug,enum EnumNamespace::MyEnum)" (??$?6W4MyEnum@EnumNamespace@@@@YA?AVQDebug@@V0@W4MyEnum@EnumNamespace@@@Z)
StaticMetaObject.exe : fatal error LNK1120: 1 unresolved externals
ninja: build stopped: subcommand failed.
16:00:32: The process "C:\Qt\Tools\CMake_64\bin\cmake.exe" exited with code 1.
Error while building/deploying project StaticMetaObject (kit: Desktop Qt 5.12.10 MSVC2017 64bit)
When executing step "Build"
16:00:32: Elapsed time: 00:01.

Подробный журнал CMake

19:08:34: Running steps for project StaticMetaObject...
19:08:34: Starting: "C:\Qt\Tools\CMake_64\bin\cmake.exe" --build C:/SRC/MyTests/StaticMetaObject/build_release --target all --verbose
[1/7 25.6/sec] cmd.exe /C "cd /D C:\SRC\MyTests\StaticMetaObject\build_release\enum && C:\Qt\Tools\CMake_64\bin\cmake.exe -E cmake_autogen C:/SRC/MyTests/StaticMetaObject/build_release/enum/CMakeFiles/enumLib_autogen.dir/AutogenInfo.json Release"
[2/7 8.7/sec] C:\PROGRA~2\MICROS~2\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\HostX64\x64\cl.exe  /nologo /TP -DENUMLIB_BUILD -DQT_CORE_LIB -DQT_NO_DEBUG -DenumLib_EXPORTS -IC:\SRC\MyTests\StaticMetaObject\build_release\enum\enumLib_autogen\include -external:IC:\Qt\5.12.10\msvc2017_64\include -external:IC:\Qt\5.12.10\msvc2017_64\include\QtCore -external:IC:\Qt\5.12.10\msvc2017_64\.\mkspecs\win32-msvc -external:W0 /DWIN32 /D_WINDOWS /EHsc /O2 /Ob2 /DNDEBUG -MD -std:c++17 /showIncludes /Foenum\CMakeFiles\enumLib.dir\enumLib_autogen\mocs_compilation.cpp.obj /Fdenum\CMakeFiles\enumLib.dir\ /FS -c C:\SRC\MyTests\StaticMetaObject\build_release\enum\enumLib_autogen\mocs_compilation.cpp
[3/7 7.6/sec] cmd.exe /C "cmd.exe /C "C:\Qt\Tools\CMake_64\bin\cmake.exe -E __create_def C:\SRC\MyTests\StaticMetaObject\build_release\enum\CMakeFiles\enumLib.dir\.\exports.def C:\SRC\MyTests\StaticMetaObject\build_release\enum\CMakeFiles\enumLib.dir\.\exports.def.objs && cd C:\SRC\MyTests\StaticMetaObject\build_release" && C:\Qt\Tools\CMake_64\bin\cmake.exe -E vs_link_dll --intdir=enum\CMakeFiles\enumLib.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\mt.exe --manifests  -- C:\PROGRA~2\MICROS~2\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\Hostx64\x64\link.exe /nologo enum\CMakeFiles\enumLib.dir\enumLib_autogen\mocs_compilation.cpp.obj  /out:enum\enumLib.dll /implib:enum\enumLib.lib /pdb:enum\enumLib.pdb /dll /version:0.0 /machine:x64 /INCREMENTAL:NO  /DEF:enum\CMakeFiles\enumLib.dir\.\exports.def  C:\Qt\5.12.10\msvc2017_64\lib\Qt5Core.lib  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib  && cd ."
[4/7 9.2/sec] cmd.exe /C "cd /D C:\SRC\MyTests\StaticMetaObject\build_release && C:\Qt\Tools\CMake_64\bin\cmake.exe -E cmake_autogen C:/SRC/MyTests/StaticMetaObject/build_release/CMakeFiles/StaticMetaObject_autogen.dir/AutogenInfo.json Release"
[5/7 10.5/sec] C:\PROGRA~2\MICROS~2\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\HostX64\x64\cl.exe  /nologo /TP -DENUMLIB_BUILD -DQT_CORE_LIB -DQT_NETWORK_LIB -DQT_NO_DEBUG -DQT_QML_LIB -IC:\SRC\MyTests\StaticMetaObject\build_release\StaticMetaObject_autogen\include -external:IC:\Qt\5.12.10\msvc2017_64\include -external:IC:\Qt\5.12.10\msvc2017_64\include\QtCore -external:IC:\Qt\5.12.10\msvc2017_64\.\mkspecs\win32-msvc -external:IC:\Qt\5.12.10\msvc2017_64\include\QtQml -external:IC:\Qt\5.12.10\msvc2017_64\include\QtNetwork -external:W0 /DWIN32 /D_WINDOWS /EHsc /O2 /Ob2 /DNDEBUG -MD -std:c++17 /showIncludes /FoCMakeFiles\StaticMetaObject.dir\StaticMetaObject_autogen\mocs_compilation.cpp.obj /FdCMakeFiles\StaticMetaObject.dir\ /FS -c C:\SRC\MyTests\StaticMetaObject\build_release\StaticMetaObject_autogen\mocs_compilation.cpp
[6/7 5.4/sec] C:\PROGRA~2\MICROS~2\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\HostX64\x64\cl.exe  /nologo /TP -DENUMLIB_BUILD -DQT_CORE_LIB -DQT_NETWORK_LIB -DQT_NO_DEBUG -DQT_QML_LIB -IC:\SRC\MyTests\StaticMetaObject\build_release\StaticMetaObject_autogen\include -external:IC:\Qt\5.12.10\msvc2017_64\include -external:IC:\Qt\5.12.10\msvc2017_64\include\QtCore -external:IC:\Qt\5.12.10\msvc2017_64\.\mkspecs\win32-msvc -external:IC:\Qt\5.12.10\msvc2017_64\include\QtQml -external:IC:\Qt\5.12.10\msvc2017_64\include\QtNetwork -external:W0 /DWIN32 /D_WINDOWS /EHsc /O2 /Ob2 /DNDEBUG -MD -std:c++17 /showIncludes /FoCMakeFiles\StaticMetaObject.dir\main.cpp.obj /FdCMakeFiles\StaticMetaObject.dir\ /FS -c C:\SRC\MyTests\StaticMetaObject\src\main.cpp
[7/7 5.9/sec] cmd.exe /C "cd . && C:\Qt\Tools\CMake_64\bin\cmake.exe -E vs_link_exe --intdir=CMakeFiles\StaticMetaObject.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\mt.exe --manifests  -- C:\PROGRA~2\MICROS~2\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\Hostx64\x64\link.exe /nologo CMakeFiles\StaticMetaObject.dir\StaticMetaObject_autogen\mocs_compilation.cpp.obj CMakeFiles\StaticMetaObject.dir\main.cpp.obj  /out:StaticMetaObject.exe /implib:StaticMetaObject.lib /pdb:StaticMetaObject.pdb /version:0.0 /machine:x64 /INCREMENTAL:NO /subsystem:console  enum\enumLib.lib  C:\Qt\5.12.10\msvc2017_64\lib\Qt5Qml.lib  C:\Qt\5.12.10\msvc2017_64\lib\Qt5Network.lib  C:\Qt\5.12.10\msvc2017_64\lib\Qt5Core.lib  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
FAILED: StaticMetaObject.exe 
cmd.exe /C "cd . && C:\Qt\Tools\CMake_64\bin\cmake.exe -E vs_link_exe --intdir=CMakeFiles\StaticMetaObject.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\mt.exe --manifests  -- C:\PROGRA~2\MICROS~2\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\Hostx64\x64\link.exe /nologo CMakeFiles\StaticMetaObject.dir\StaticMetaObject_autogen\mocs_compilation.cpp.obj CMakeFiles\StaticMetaObject.dir\main.cpp.obj  /out:StaticMetaObject.exe /implib:StaticMetaObject.lib /pdb:StaticMetaObject.pdb /version:0.0 /machine:x64 /INCREMENTAL:NO /subsystem:console  enum\enumLib.lib  C:\Qt\5.12.10\msvc2017_64\lib\Qt5Qml.lib  C:\Qt\5.12.10\msvc2017_64\lib\Qt5Network.lib  C:\Qt\5.12.10\msvc2017_64\lib\Qt5Core.lib  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
LINK: command "C:\PROGRA~2\MICROS~2\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\Hostx64\x64\link.exe /nologo CMakeFiles\StaticMetaObject.dir\StaticMetaObject_autogen\mocs_compilation.cpp.obj CMakeFiles\StaticMetaObject.dir\main.cpp.obj /out:StaticMetaObject.exe /implib:StaticMetaObject.lib /pdb:StaticMetaObject.pdb /version:0.0 /machine:x64 /INCREMENTAL:NO /subsystem:console enum\enumLib.lib C:\Qt\5.12.10\msvc2017_64\lib\Qt5Qml.lib C:\Qt\5.12.10\msvc2017_64\lib\Qt5Network.lib C:\Qt\5.12.10\msvc2017_64\lib\Qt5Core.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:StaticMetaObject.exe.manifest" failed (exit code 1120) with the following output:
main.cpp.obj : error LNK2019: unresolved external symbol "struct QMetaObject const EnumNamespace::staticMetaObject" (?staticMetaObject@EnumNamespace@@3UQMetaObject@@B) referenced in function "class QDebug __cdecl operator<<<enum EnumNamespace::MyEnum>(class QDebug,enum EnumNamespace::MyEnum)" (??$?6W4MyEnum@EnumNamespace@@@@YA?AVQDebug@@V0@W4MyEnum@EnumNamespace@@@Z)
StaticMetaObject.exe : fatal error LNK1120: 1 unresolved externals
ninja: build stopped: subcommand failed.
19:08:36: The process "C:\Qt\Tools\CMake_64\bin\cmake.exe" exited with code 1.
Error while building/deploying project StaticMetaObject (kit: Desktop Qt 5.12.10 MSVC2017 64bit)
When executing step "Build"
19:08:36: Elapsed time: 00:01.

Обновлять

Использование сгенерированного CMake файла экспорта также не сработало. Компиляция завершается с той же ошибкой.

enum/CMakeLists.txt с использованием автоматически сгенерированного файла экспорта

cmake_minimum_required(VERSION "${CMAKE_MINIMUM_REQUIRED_VERSION}" FATAL_ERROR)

set(LIB_NAME enumLib)
add_library(${LIB_NAME} SHARED)
set_target_properties(${LIB_NAME} PROPERTIES LINKER_LANGUAGE CXX)
target_sources(${LIB_NAME} PUBLIC enum.h)

include(GenerateExportHeader)
generate_export_header(${LIB_NAME} EXPORT_MACRO_NAME ENUMLIB_EXPORT)

target_compile_definitions(${LIB_NAME} PUBLIC enumLib_EXPORTS)
target_include_directories(${LIB_NAME} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(${LIB_NAME} PUBLIC Qt${QT_VERSION_MAJOR}::Core)

Не уверен, что cmake --build ... --verbose выводит команды moc, но если да, то было бы интересно, если бы определение ENUMLIB_BUILD передавалось в moc...

fabian 09.05.2023 18:59

Привет @fabian. Я разместил подробные журналы, как они появляются в терминале Qt Creator. Единственные ссылки на файл moc относятся к файлу mocs_compilation.cpp, который находится в C:\SRC\MyTests\StaticMetaObject\build_release\enum\enumLib_a‌​utogen\mocs_compilat‌​ion.cpp.

Adri C.S. 09.05.2023 19:12

на сайте disource.cmake.org: discourse.cmake.org/t/…

starball 14.05.2023 00:51
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

AUTOMOC_MACRO_NAMES — это переменная, используемая для указания CMake запускать moc файлы, которые

содержит определенные ключевые слова в качестве первой строки без пробела в новой строке или как первая строка без пробела после { на новой строке.
Значение по умолчанию: Q_OBJECT;Q_GADGET;Q_NAMESPACE;Q_NAMESPACE_EXPORT.

Поскольку Q_NAMESPACE предшествовал ENUMLIB_EXPORT, CMake не заметил его как одно из ключевых слов для moc. Решение состоит в том, чтобы поместить Q_NAMESPACE в отдельную строку:

namespace EnumNamespace {
    ENUMLIB_EXPORT
    Q_NAMESPACE
    
    // Rest of the code
}

Заявка на связанную проблему: gitlab.kitware.com/cmake/cmake/-/issues/24905

starball 14.05.2023 00:52

Другие вопросы по теме