xmake-io / xmake

🔥 A cross-platform build utility based on Lua
https://xmake.io
Apache License 2.0
9.87k stars 776 forks source link

Xmake is not dealing with Q_OBJECT moc properly #5236

Closed HeavySnowJakarta closed 3 months ago

HeavySnowJakarta commented 3 months ago

Xmake Version

v2.9.2+HEAD.6b6557c54

Operating System Version and Architecture

x86_64-windows11-msvc2022-ucrt

Describe Bug

error: startup.cpp.obj : error LNK2001: 无法解析的外部符号 "public: virtual struct QMetaObject const * __cdecl Startup::metaObject(void)const " (?metaObject@Startup@@UEBAPEBUQMetaObject@@XZ)
startup.cpp.obj : error LNK2001: 无法解析的外部符号 "public: virtual void * __cdecl Startup::qt_metacast(char const *)" (?qt_metacast@Startup@@UEAAPEAXPEBD@Z)
startup.cpp.obj : error LNK2001: 无法解析的外部符号 "public: virtual int __cdecl Startup::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@Startup@@UEAAHW4Call@QMetaObject@@HPEAPEAX@Z)
startup.cpp.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: static class QString __cdecl QFileDialog::getOpenFileName(class QWidget *,class QString const &,class QString const &,class QString const &,class QString *,class QFlags<enum QFileDialog::Option>)" (__imp_?getOpenFileName@QFileDialog@@SA?AVQString@@PEAVQWidget@@AEBV2@11PEAV2@V?$QFlags@W4Option@QFileDialog@@@@@Z),函数 "public: void __cdecl Startup::open(void)" (?open@Startup@@QEAAXXZ) 中引用了该符号
startup.cpp.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: static class QString __cdecl QFileDialog::getSaveFileName(class QWidget *,class QString const &,class QString const &,class QString const &,class QString *,class QFlags<enum QFileDialog::Option>)" (__imp_?getSaveFileName@QFileDialog@@SA?AVQString@@PEAVQWidget@@AEBV2@11PEAV2@V?$QFlags@W4Option@QFileDialog@@@@@Z),函数 "public: void __cdecl Startup::create(void)" (?create@Startup@@QEAAXXZ) 中引用了该符号
startup.cpp.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: static enum QMessageBox::StandardButton __cdecl QMessageBox::critical(class QWidget *,class QString const &,class QString const &,class QFlags<enum QMessageBox::StandardButton>,enum QMessageBox::StandardButton)" (__imp_?critical@QMessageBox@@SA?AW4StandardButton@1@PEAVQWidget@@AEBVQString@@1V?$QFlags@W4StandardButton@QMessageBox@@@@W421@@Z),函数 "private: void __cdecl Startup::openNewWindow(class QString)" (?openNewWindow@Startup@@AEAAXVQString@@@Z) 中引用了该符号
build\windows\x64\debug\CollegeHRM.exe : fatal error LNK1120: 6 个无法解析的外部命令

Due to the net it's because Qt generates moc_*.cpp files for ones that contain Q_OBJECT. So either the moc_*.cpp is not generated properly or it's not included.

Expected Behavior

Do as TBOOX's website's example like below does not work.

target("qt_widgetapp")
    add_rules("qt.application")
    add_files("src/*.cpp") 
    add_files("src/mainwindow.ui")
    add_files("src/mainwindow.h")  -- add files with Q_OBJECT meta (only for qt.moc)
    add_frameworks("QtWidgets")

Maybe I should list the files that contain Q_OBJECT one by one?

    add_packages("cjson")
    add_headerfiles("src/lib/backend/*.h")
    add_headerfiles("src/lib/frontend/startup.h")
    add_headerfiles("src/lib/frontend/*.h")
    add_files("src/lib/backend/*.cpp")
    add_files("src/lib/frontend/*.cpp")

Not working.

What if I add_rule("qt.moc") specifically?

    add_rules("qt.application")
    add_rules("qt.moc")
    add_files("src/*.cpp")
    add_files("src/qml.qrc")

    add_packages("cjson")
    add_headerfiles("src/lib/backend/*.h")
    add_headerfiles("src/lib/frontend/*.h")
    add_files("src/lib/backend/*.cpp")
    add_files("src/lib/frontend/*.cpp")

Still not working.

Project Configuration

Here is a part of the xmake.lua:

set_languages("cxx17")

-- Library dependencies.
add_requires("cjson")

-- Target building.
target("MyQtQuickProject")
    add_rules("qt.application")
    add_files("src/*.cpp")
    add_files("src/qml.qrc")

    add_packages("cjson")
    add_headerfiles("src/lib/backend/*.h")
    add_headerfiles("src/lib/frontend/*.h", {rule = "qt.moc"}) -- Where the macro `Q_OBJECT` is used.
    add_files("src/lib/backend/*.cpp")
    add_files("src/lib/frontend/*.cpp")

    -- Temp debug settings.
    add_defines("QT_DEBUG")
    set_symbols("debug")       -- Add debug symbols
    set_optimize("none") 
    add_ldflags("/SUBSYSTEM:CONSOLE") 

    -- Automatically generate `qml.qrc`.
    --[[
    before_build(function (target) 
        if os.host() == 'windows' then
            os.exec('cmd /C scripts\\generate_qrc.bat')
        else
            os.exec('./scripts/generate_qrc.sh')
        end
    end)
    ]]

    -- Without this command xmake won't find `QFileDialog.h`.
    add_includedirs("C:\\Qt\\6.7.1\\msvc2019_64\\include\\QtWidgets")

ChatGPT suggests me to add {rule = 'qt.moc'} which does not work.

Additional Information and Error Logs

checking for cl.exe ... C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.38.33130\bin\HostX64\x64\cl.exe
checking for Microsoft Visual Studio (x64) version ... 2022
checkinfo: cannot runv(zig.exe version), No such file or directory
checking for zig ... no
checkinfo: cannot runv(zig.exe version), No such file or directory
checking for zig ... no
checkinfo: cannot runv(nim.exe --version), No such file or directory
checking for nim ... no
checkinfo: cannot runv(nim.exe --version), No such file or directory
checking for nim ... no
checking for unzip ... ok
checking for git ... ok
checking for gzip ... ok
checking for tar ... ok
git rev-parse HEAD
checking for cmake ... no
checking for cmake ... no
checking for cmake ... no
checking for cmake ... ok
finding cjson from xmake ..
checking for xmake::cjson ... cjson 1.7.15
checking for link.exe ... C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.38.33130\bin\HostX64\x64\link.exe
checking for the linker (ld) ... link.exe
checking for Qt SDK directory ... C:/Qt/6.7.1/msvc2019_64
checking for Qt SDK version ... 6.7.1
checking for cl.exe ... C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.38.33130\bin\HostX64\x64\cl.exe
checking for the c++ compiler (cxx) ... cl.exe
checking for C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.38.33130\bin\HostX64\x64\cl.exe ... ok
checking for flags (-FS -Fd) ... ok
> cl.exe "-FS" "-FdC:\Users\bians\AppData\Local\Temp\.xmake\240620\_B4C261DB5A4A47208FF9563A84AA8640.pdb" "-nologo"
checking for flags (-Od) ... ok
> cl.exe "-Od" "-nologo"
checking for flags (cl_external_includedir) ... ok
> cl.exe "-external:W0" "-external:IC:\Qt\6.7.1\msvc2019_64\include\QtGui" "-nologo"
checking for the c++ compiler (cxx) ... cl.exe
checking for the c++ compiler (cxx) ... cl.exe
checking for the c++ compiler (cxx) ... cl.exe
checking for the c++ compiler (cxx) ... cl.exe
checking for the c++ compiler (cxx) ... cl.exe
checking for flags (/Zc:__cplusplus) ... ok
> cl.exe "/Zc:__cplusplus" "-nologo"
checking for flags (/permissive-) ... ok
> cl.exe "/permissive-" "-nologo"
checking for C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.38.33130\bin\HostX64\x64\link.exe ... ok
checking for flags (/SUBSYSTEM:CONSOLE) ... ok
> link.exe "/SUBSYSTEM:CONSOLE" "-nologo" "-dynamicbase" "-nxcompat" "-machine:x64"
[ 88%]: linking.debug CollegeHRM.exe
"C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\VC\\Tools\\MSVC\\14.38.33130\\bin\\HostX64\\x64\\link.exe" -nologo -dynamicbase -nxcompat -machine:x64 -libpath:C:\Qt\6.7.1\msvc2019_64\lib -libpath:C:\Users\bians\AppData\Local\.xmake\packages\c\cjson\1.7.15\5d29b7ead93148bbac47aa2d02ef454d\lib -debug -pdb:build\windows\x64\debug\CollegeHRM.pdb cjson.lib Qt6Guid.lib Qt6Quickd.lib Qt6Qmld.lib Qt6Cored.lib Qt6Networkd.lib ws2_32.lib gdi32.lib ole32.lib advapi32.lib shell32.lib user32.lib opengl32.lib imm32.lib winmm.lib iphlpapi.lib /SUBSYSTEM:CONSOLE -out:build\windows\x64\debug\CollegeHRM.exe build\.objs\CollegeHRM\windows\x64\debug\src\main.cpp.obj build\.objs\CollegeHRM\windows\x64\debug\src\lib\backend\employee.cpp.obj build\.objs\CollegeHRM\windows\x64\debug\src\lib\backend\employees.cpp.obj build\.objs\CollegeHRM\windows\x64\debug\src\lib\frontend\lifeperiod.cpp.obj build\.objs\CollegeHRM\windows\x64\debug\src\lib\frontend\startup.cpp.obj build\.objs\CollegeHRM\windows\x64\debug\gens\rules\qt\qrc\qml_43BBE12C.cpp.obj
create ok!
compile_commands.json updated!
error: @programdir\core\main.lua:329: @programdir\actions\build\main.lua:148: @programdir\modules\async\runjobs.lua:322: @programdir\actions\build\kinds\binary.lua:53: @programdir\modules\core\tools\link.lua:175: startup.cpp.obj : error LNK2001: 无法解析的外部符号 "public: virtual struct QMetaObject const * __cdecl Startup::metaObject(void)const " (?metaObject@Startup@@UEBAPEBUQMetaObject@@XZ)
startup.cpp.obj : error LNK2001: 无法解析的外部符号 "public: virtual void * __cdecl Startup::qt_metacast(char const *)" (?qt_metacast@Startup@@UEAAPEAXPEBD@Z)
startup.cpp.obj : error LNK2001: 无法解析的外部符号 "public: virtual int __cdecl Startup::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@Startup@@UEAAHW4Call@QMetaObject@@HPEAPEAX@Z)
startup.cpp.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: static class QString __cdecl QFileDialog::getOpenFileName(class QWidget *,class QString const &,class QString const &,class QString const &,class QString *,class QFlags<enum QFileDialog::Option>)" (__imp_?getOpenFileName@QFileDialog@@SA?AVQString@@PEAVQWidget@@AEBV2@11PEAV2@V?$QFlags@W4Option@QFileDialog@@@@@Z),函数 "public: void __cdecl Startup::open(void)" (?open@Startup@@QEAAXXZ) 中引用了该符号
startup.cpp.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: static class QString __cdecl QFileDialog::getSaveFileName(class QWidget *,class QString const &,class QString const &,class QString const &,class QString *,class QFlags<enum QFileDialog::Option>)" (__imp_?getSaveFileName@QFileDialog@@SA?AVQString@@PEAVQWidget@@AEBV2@11PEAV2@V?$QFlags@W4Option@QFileDialog@@@@@Z),函数 "public: void __cdecl Startup::create(void)" (?create@Startup@@QEAAXXZ) 中引用了该符号
startup.cpp.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: static enum QMessageBox::StandardButton __cdecl QMessageBox::critical(class QWidget *,class QString const &,class QString const &,class QFlags<enum QMessageBox::StandardButton>,enum QMessageBox::StandardButton)" (__imp_?critical@QMessageBox@@SA?AW4StandardButton@1@PEAVQWidget@@AEBVQString@@1V?$QFlags@W4StandardButton@QMessageBox@@@@W421@@Z),函数 "private: void __cdecl Startup::openNewWindow(class QString)" (?openNewWindow@Startup@@AEAAXVQString@@@Z) 中引用了该符号
build\windows\x64\debug\CollegeHRM.exe : fatal error LNK1120: 6 个无法解析的外部命令

stack traceback:
    [C]: in function 'error'
    [@programdir\core\base\os.lua:973]:
    [@programdir\modules\core\tools\link.lua:175]: in function 'catch'
    [@programdir\core\sandbox\modules\try.lua:123]: in function 'try'
    [@programdir\modules\core\tools\link.lua:150]:
    [C]: in function 'xpcall'
    [@programdir\core\base\utils.lua:275]:
    [@programdir\core\tool\linker.lua:221]: in function 'link'
    [@programdir\actions\build\kinds\binary.lua:53]: in function 'callback'
    [@programdir\modules\core\project\depend.lua:217]: in function 'on_changed'
    [@programdir\actions\build\kinds\binary.lua:41]: in function '_do_link_target'
    [@programdir\actions\build\kinds\binary.lua:83]:
    [@programdir\actions\build\kinds\binary.lua:110]: in function '_link_target'
    [@programdir\actions\build\kinds\binary.lua:138]: in function 'jobfunc'
    [@programdir\modules\async\runjobs.lua:238]:
    [C]: in function 'xpcall'
    [@programdir\core\base\utils.lua:275]: in function 'trycall'
    [@programdir\core\sandbox\modules\try.lua:117]: in function 'try'
    [@programdir\modules\async\runjobs.lua:220]: in function 'cotask'
    [@programdir\core\base\scheduler.lua:406]:

stack traceback:
        [C]: in function 'error'
        @programdir\core\base\os.lua:973: in function 'os.raiselevel'
        (...tail calls...)
        @programdir\core\main.lua:329: in upvalue 'cotask'
        @programdir\core\base\scheduler.lua:406: in function <@programdir\core\base\scheduler.lua:399>
star-hengxing commented 3 months ago

Please see the doc again.

add_files("src/mainwindow.h")  -- add files with Q_OBJECT meta (only for qt.moc)

https://xmake.io/#/manual/project_target?id=targetadd_headerfiles

waruqi commented 3 months ago

use add_files, not add_headerfiles