V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
chouxw112233
V2EX  ›  C++

学习 QT,尝试链接静态库,但怎么都链接不上,请教一下大佬们这是怎么回事

  •  
  •   chouxw112233 · 12 天前 · 1414 次点击

    QT creator 12.0.2 Based on QT 6.6.0 windows 10

    windows git bash 输出的各个文件名 test 是自己的测试用的静态库 target 是可执行文件项目 libtest.a 已经生成了

    [pj]$ ls target/*
    target/main.cpp  target/target.pro  target/target.pro.user  target/widget.cpp  target/widget.h  target/widget.ui
    [pj]$ ls test/*
    test/test.cpp  test/test.h  test/test.pro  test/test.pro.user  test/test_global.h
    [pj]$ ls build-test-Desktop_Qt_6_6_3_MinGW_64_bit-Debug/*
    build-test-Desktop_Qt_6_6_3_MinGW_64_bit-Debug/Makefile        build-test-Desktop_Qt_6_6_3_MinGW_64_bit-Debug/Makefile.Release
    build-test-Desktop_Qt_6_6_3_MinGW_64_bit-Debug/Makefile.Debug
    
    build-test-Desktop_Qt_6_6_3_MinGW_64_bit-Debug/debug:
    libtest.a  test.o
    
    build-test-Desktop_Qt_6_6_3_MinGW_64_bit-Debug/release:
    

    以下是 test.pro, 我加了CONFIG += staticlib,现在在build-test-Desktop_Qt_6_6_3_MinGW_64_bit-Debug/debug下只会生成 libtest.a ,不会生成 test.dll

    QT -= gui
    
    TEMPLATE = lib
    DEFINES += TEST_LIBRARY
    
    CONFIG += c++17
    
    # You can make your code fail to compile if it uses deprecated APIs.
    # In order to do so, uncomment the following line.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    SOURCES += \
        test.cpp
    
    HEADERS += \
        test_global.h \
        test.h
    
    CONFIG += staticlib
    # Default rules for deployment.
    unix {
        target.path = /usr/lib
    }
    
    !isEmpty(target.path): INSTALLS += target
    
    

    我在默认的 target.pro 中添加了如下内容用来链接 libtest.a

    win32: LIBS += -L$$PWD/../build-test-Desktop_Qt_6_6_3_MinGW_64_bit-Debug/debug/ -ltest
    
    INCLUDEPATH += $$PWD/../test
    DEPENDPATH += $$PWD/../test
    
    win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../build-test-Desktop_Qt_6_6_3_MinGW_64_bit-Debug/debug/libtest.a
    else:win32-g++: PRE_TARGETDEPS += $$PWD/../build-test-Desktop_Qt_6_6_3_MinGW_64_bit-Debug/debug/libtest.a
    

    main.cpp

    #include "widget.h"
    #include "test.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        Test t;
        t.print();  // print 是 test 的 public 函数,用 qDebug 输出函数名
    
        QApplication a(argc, argv);
        Widget w;
        w.show();
        return a.exec();
    }
    

    编译报错 undefined reference, 应该是链接不到 libtest.a:

    :-1: error: debug/main.o: in function `qMain(int, char**)':
    D:\Qt\pj\target\main.cpp:7: error: undefined reference to `__imp__ZN4TestC1Ev'
    :-1: error: D:\Qt\pj\build-target-Desktop_Qt_6_6_3_MinGW_64_bit-Debug/../target/main.cpp:8: undefined reference to `__imp__ZN4Test5printEv'
    :-1: error: collect2.exe: error: ld returned 1 exit status
    :-1: error: [Makefile.Debug:72: debug/target.exe] Error 1
    

    不知道我是不是少了什么设置

    如果以上描述不到位,这是两个项目的文件。先构建 test ,后运行 target https://drive.google.com/file/d/1FxtwscpdG9Atj2-YnAnR-CCKcmIwx0P7/view?usp=drive_link

    11 条回复    2024-04-27 12:54:47 +08:00
    ysc3839
        1
    ysc3839  
       12 天前 via Android
    个人建议把编译工具换成 CMake ,mingw 也可以考虑直接用 MSYS2
    kokutou
        2
    kokutou  
       12 天前 via Android
    msys2 装个 static 版本的 qt
    cnbatch
        3
    cnbatch  
       11 天前
    Windows 系统?使用微软自己的工具链会更好,不想安装 Visual Studio 也可以只安装 Microsoft Build Tools
    最好直接用 vcpkg ,许多事情都会方便很多
    ljyst
        4
    ljyst  
       11 天前
    肿么 win 平台用 qt
    shuax
        5
    shuax  
       11 天前
    直接 vcpkg
    rockyhoujinsong
        6
    rockyhoujinsong  
       11 天前
    在 Win 路径下 似乎是 \
    chouxw112233
        7
    chouxw112233  
    OP
       11 天前
    @kokutou 搜了一下,似乎需要从源码开始编译?官方的 qt creator 不支持我这样链接吗
    @cnbatch @shuax 但是我链接的是自己写的库。不是第三方发布的库
    @rockyhoujinsong qt 应该都能识别。我试过 \ 和 \\ 都一样
    @ljyst win 的 qt 有什么问题吗?想学着写点东西,qt 本身也跨平台
    chouxw112233
        8
    chouxw112233  
    OP
       11 天前
    我看的 https://wiki.qt.io/MSYS2
    刚才安装了 MSYS ,并执行了这些

    ```
    pacman -S mingw-w64-x86_64-toolchain
    pacman -S mingw-w64-x86_64-qt5-static
    pacman -S mingw-w64-x86_64-qt-creator
    pacman -S cmake
    ```

    可以看到 D:\msys64\mingw64\bin\qtcreator.exe
    打开后版本已经更新到了 Qt Creator 13.0.0 Based on Qt 6.7.0 (GCC 13.2.0, x86_64)
    主楼里提到的项目还是没法静态链接。


    不过 cmake 还是不能用,是否有好用的教程?😥配置了半天连编译都不行
    4u1kto
        9
    4u1kto  
       6 天前   ❤️ 1
    静态库在编译时会被直接链接到使用它的项目中,因此不需要额外的导出标记 Q_DECL_EXPORT 。
    去掉 class 后边的 Q_DECL_EXPORT 就可以顺利编译,试试。

    或者去掉 CONFIG += staticlib ,动态链接。
    4u1kto
        10
    4u1kto  
       6 天前
    @chouxw112233
    对比其他语言后你会发现,C++编译工具链极其复杂,尽量挑一个 Qt 推荐的来使用,使用 QtCreator 来创建项目/静态库/动态库的模板,Qt5 可以用 qmake ,Qt6 要转为 cmake ,不过写 cmakelists.txt 又是一座大山,要多去 Github 学习别人构建方法。

    对于初学者我能给的建议不多,投入时间、多思考、善用搜索、报大腿,(这个论坛会写 C++的很少)。
    chouxw112233
        11
    chouxw112233  
    OP
       6 天前
    @4u1kto 非常感谢,成功了。

    之前后来尝试了手动用 g++命令:
    qmake -project 生成 pro 文件,修改生成的文件
    qmake 生成 makefile
    Mingw32-make 进行编译,提示 undefined reference
    手动把最后一行 g++命令复制出来,在命令最后加上-L 库路径 -l 库名,就成功了

    可以链接,但是没有像你说的去掉 Q_DECL_EXPORT 。我去研究下`Q_DECL_EXPORT`的作用


    @shuax 抱歉,以前没听过 vcpkg 。网络问题,装了很久的 vcpkg 和 vs 。vs 用起来有点不习惯,但最后用 vs 确实链接了自定义静态库和 qt 自带的 lib.a 库,生成了完全静态的可执行文件。安装过程确实有点花时间了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1348 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 17:00 · PVG 01:00 · LAX 10:00 · JFK 13:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.