Qt中创建的C++库如何直接生成DLL到总项目的bin文件中

本文介绍如何在Qt项目中配置C++库以生成并正确部署DLL文件至项目的bin目录。通过设置pro文件中的DESTDIR参数指定DLL的目标路径,并解决debug与release模式下DLL缺失的问题。

Qt中创建的C++库如何直接生成DLL到总项目的bin文件中,以下代码为C++库的pro文件的内容

QT -= gui
QT += serialport

TARGET = IGTC
TEMPLATE = lib
DEFINES += IGTC_LIBRARY

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

#Following code is generate DLL files to "D:\build-CarDetectorV2-Desktop_Qt_5_14_2_MinGW_32_bit-Debug\bin" folder
DESTDIR = ../bin

SOURCES += \
    atreceiverbuffer.cpp \
    igtc.cpp

HEADERS += \
    IGTC_global.h \
    atreceiverbuffer.h \
    igtc.h

# Default rules for deployment.
unix {
    target.path = /usr/lib
}
!isEmpty(target.path): INSTALLS += target

win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/./release/ -lIGTC
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/./debug/ -lIGTC
else:unix: LIBS += -L$$OUT_PWD/./ -lIGTC

INCLUDEPATH += $$PWD/.
DEPENDPATH += $$PWD/.

,其中有一行是起这个作用,那就是:

#Following code is generate DLL files to "D:\build-CarDetectorV2-Desktop_Qt_5_14_2_MinGW_32_bit-Debug\bin" folder
DESTDIR = ../bin

另外:
含有c++ library的Qt项目在debug编译时可以正常运行,改为release模式后,提示:找不到IGTC.DLL文件。
原因如下:因为在release/IGTC/release目录下找不到这个文件导致。
解决方案:从debug/IGTC/debug目录下拷贝IGTC.DLL到release/IGTC/release文件夹下,再编译即运行成功!
要想在发布文件夹下有IGTC.DLL文件,必须保证在ICTC/release文件夹下有该文件才能发布到bin文件夹下,否则不行!

秋风写于淄博,业务联系与技术交流:375172665

<think>我们参考用户提供的引用内容,特别是引用[2]中关于设置dll和lib输出目录的部分。 在引用[2]中,我们看到在.pro文件中,通过设置LIBS来指定链接的路径,并且通过DESTDIR设置可执行文件的输出目录(在这里,由于是控制台程序,它设置的是exe的输出目录)。但是我们的问题是关于DLL项目dll文件和lib文件的输出目录。 根据Qt的文档,我们可以使用以下变量来设置输出目录: - DESTDIR: 指定目标文件(如可执行文件文件)的输出目录。 - DLLDESTDIR: 专门用于指定dll文件的输出目录(仅适用于Windows平台)。 - 另外,对于lib文件,由于在生成时,lib文件是作为目标文件的一部分,所以通常也会输出到DESTDIR指定的目录中。但是,如果我们想将dll和lib输出到不同的目录,可能需要分别设置。 然而,在标准的Qt项目中,我们通常使用: DESTDIR = your_path # 设置目标文件(包括dll和lib)的输出目录 但是,如果我们希望dll和lib输出到不同的目录,我们可以考虑在构建后步骤中移动文件,或者使用不同的变量分别设置。 实际上,在Qt中,生成时,会同时生成dll和lib(在Windows上)。默认情况下,它们都输出到DESTDIR指定的目录。 如果我们想要将dll和lib分别输出到不同的目录,可以通过在.pro文件设置不同的变量来实现。但是,Qt本身并没有提供单独的变量来分别设置dll和lib的输出路径(在Windows上)。因此,我们可以使用以下方法: 方法1:使用构建后的步骤(使用QMAKE_POST_LINK)来将dll和lib分别移动到不同的目录。 方法2:使用两个不同的配置(例如Debug和Release),然后在每个配置中设置不同的DESTDIR,但这并不能同时输出dll和lib到不同的目录,因为DESTDIR是同时影响两者的。 然而,我们注意到在引用[2]中,对于可执行文件项目,他们分别设置了Debug和Release的输出目录: Debug:DESTDIR = $$PWD/../bin_d Release: DESTDIR = $$PWD/../bin 那么,在DLL项目中,我们可以类似地设置DESTDIR来同时控制dll和lib的输出目录。但是,如果一定要分开,我们可以考虑在构建后步骤中移动lib文件(或者dll文件)到另一个目录。 例如,如果我们希望将dll文件输出到bin目录,而lib文件输出到lib目录,可以这样写: 在.pro文件中: # 设置目标文件名 TARGET = mydll # 默认输出目录(同时输出dll和lib) DESTDIR = $$OUT_PWD/bin # 然后,我们添加构建后步骤,将lib文件移动到lib目录 win32 { # 注意:这里使用相对路径或绝对路径 LIB_DIR = $$OUT_PWD/lib # 创建lib目录(如果不存在) QMAKE_POST_LINK += $$QMAKE_MKDIR $$shell_path($$LIB_DIR) $$escape_expand(\\n\\t) # 移动lib文件到lib目录 QMAKE_POST_LINK += $$QMAKE_MOVE $$shell_path($$DESTDIR/$${TARGET}.lib) $$shell_path($$LIB_DIR) } 注意:在Windows平台上,生成的lib文件名为$${TARGET}.lib,而dll文件名为$${TARGET}.dll。 但是,上述方法在移动文件时可能会遇到问题,因为链接过程中可能还需要lib文件(如果同时构建依赖此dll的可执行项目),所以通常建议将lib文件放在可执行项目能够找到的地方(比如和dll同一个目录,或者通过LIBS指定目录)。 因此,更常见的做法是: 将dll和lib都输出到同一个目录(比如bin目录),然后在发布时,将dll复制到可执行文件目录,而lib文件则用于开发(链接时使用),不需要发布。 但是,如果用户确实需要分开,我们可以使用上述构建后步骤。 另外,Qt Creator 4.11开始支持单独的lib文件输出目录设置(通过QMAKE_LIBDIR变量?),但通常QMAKE_LIBDIR是用于指定链接的搜索路径,而不是输出路径。 所以,在Qt项目中,标准做法是使用DESTDIR设置目标文件的输出目录(包括dll和lib)。如果需要分开,则通过构建后步骤进行移动。 下面是一个示例.pro文件设置,将dll和lib输出到不同的目录: ``` TEMPLATE = lib CONFIG += dll # 设置dll的输出目录 DESTDIR = $$OUT_PWD/bin # 设置lib的输出目录 win32 { MINGW: LIB_SUFFIX = .a else: LIB_SUFFIX = .lib # 定义lib的输出目录 LIB_DIR = $$OUT_PWD/lib # 在构建后移动lib文件 QMAKE_POST_LINK += $$QMAKE_MKDIR $$shell_path($$LIB_DIR) $$escape_expand(\\n\\t) QMAKE_POST_LINK += $$QMAKE_MOVE $$shell_path($$DESTDIR/$${TARGET}$${LIB_SUFFIX}) $$shell_path($$LIB_DIR) } ``` 注意:在Windows上,MinGW和MSVC生成文件后缀不同:MinGW生成的是.a和.dll,而MSVC生成的是.lib和.dll。所以我们需要判断编译器。 但是,上述方法在MSVC下可能有问题,因为生成的导入(.lib)和静态(.lib)同名,而且动态的导入和静态都是.lib后缀(但动态还会生成一个.dll)。实际上,对于动态,MinGW生成的是.dll和.a(导入),而MSVC生成的是.dll和.lib(导入)。 因此,我们可以根据不同的编译器设置不同的后缀。 另外,对于静态构建(CONFIG += staticlib),则只会生成一个静态文件(在MinGW下是.a,在MSVC下是.lib),此时我们不需要dll。所以上述方法只适用于动态dll项目。 综上所述,在Qt中分别设置dll和lib的输出目录需要自定义构建步骤。但通常并不需要这样做,因为lib文件开发阶段用于链接,在发布可执行文件时只需要dll。 根据用户的问题,我们给出如下方法: 方法:在.pro文件设置DESTDIR为dll的输出目录,然后通过构建后步骤将lib文件移动到另一个目录。 示例代码: ``` # 假设是动态项目 TEMPLATE = lib CONFIG += dll # 设置dll和lib的默认输出目录(先都输出到bin) DESTDIR = $$OUT_PWD/bin # 然后,我们创建lib目录并将lib文件移过去 win32 { # 对于MinGW,导入后缀为.a;对于MSVC,导入后缀为.lib contains(QT_ARCH, i386): { # 如果是MinGW MINGW { LIB_FILE = $$DESTDIR/$${TARGET}.a LIB_DIR = $$OUT_PWD/lib QMAKE_POST_LINK += $$QMAKE_MKDIR $$shell_path($$LIB_DIR) $$escape_expand(\\n\\t) QMAKE_POST_LINK += $$QMAKE_MOVE $$shell_path($$LIB_FILE) $$shell_path($$LIB_DIR) } MSVC { LIB_FILE = $$DESTDIR/$${TARGET}.lib LIB_DIR = $$OUT_PWD/lib QMAKE_POST_LINK += $$QMAKE_MKDIR $$shell_path($$LIB_DIR) $$escape_expand(\\n\\t) QMAKE_POST_LINK += $$QMAKE_MOVE $$shell_path($$LIB_FILE) $$shell_path($$LIB_DIR) } } # 如果是64位,同样处理 contains(QT_ARCH, x86_64): { MINGW { LIB_FILE = $$DESTDIR/$${TARGET}.a LIB_DIR = $$OUT_PWD/lib QMAKE_POST_LINK += $$QMAKE_MKDIR $$shell_path($$LIB_DIR) $$escape_expand(\\n\\t) QMAKE_POST_LINK += $$QMAKE_MOVE $$shell_path($$LIB_FILE) $$shell_path($$LIB_DIR) } MSVC { LIB_FILE = $$DESTDIR/$${TARGET}.lib LIB_DIR = $$OUT_PWD/lib QMAKE_POST_LINK += $$QMAKE_MKDIR $$shell_path($$LIB_DIR) $$escape_expand(\\n\\t) QMAKE_POST_LINK += $$QMAKE_MOVE $$shell_path($$LIB_FILE) $$shell_path($$LIB_DIR) } } } ``` 注意:$$OUT_PWD是Qt构建系统提供的变量,表示构建目录的绝对路径。 但是,这种方法可能会带来问题,因为链接后的文件被移动了,那么在同一构建树中后续构建其他依赖此项目时,可能会找不到lib文件(因为被移走了)。因此,通常不建议在开发过程中将lib文件移走,而是通过设置LIBS路径来指向lib所在的目录(如果分开存放)。 所以,更推荐的做法是:将dll和lib都放在同一个目录下(比如lib目录),然后在可执行项目中通过LIBS指定该目录,同时将dll文件复制到可执行文件目录(或者将lib目录加入PATH)以便运行时加载dll。或者,按照引用[2]中的方式,将dll放在bin目录,lib放在lib目录,然后在可执行项目的.pro文件中分别设置Debug和Release的LIBS路径。 结:在QtDLL项目中,默认情况下dll和lib都输出到DESTDIR指定的目录。若要分开,可使用构建后步骤移动lib文件到指定目录。 根据上述分析,我们给出在Qt DLL项目中分别设置dll和lib输出目录的方法: 1. 设置dll的输出目录:通过设置DESTDIR变量(因为dll是目标文件,所以会输出到DESTDIR)。 2. 设置lib的输出目录:没有直接支持的变量,因此需要在构建后将lib文件从DESTDIR移动到另一个目录(例如lib目录)。 示例代码(.pro文件): ``` TEMPLATE = lib CONFIG += dll # 设置dll的输出目录(同时lib也会先输出到这里) DESTDIR = $$OUT_PWD/bin # 设置lib的输出目录 win32 { # 创建lib目录 LIB_DIR = $$OUT_PWD/lib # 根据编译器类型确定lib文件后缀 contains(QMAKE_EXT_OBJ, .o) { # MinGW: 使用.a LIB_SUFFIX = a } else { # MSVC: 使用.lib LIB_SUFFIX = lib } LIB_FILE = $$DESTDIR/$${TARGET}.$${LIB_SUFFIX} # 构建后步骤:创建lib目录并移动lib文件 !build_pass: QMAKE_POST_LINK += $$QMAKE_MKDIR $$quote($$LIB_DIR) $$escape_expand(\\n\\t) !build_pass: QMAKE_POST_LINK += $$QMAKE_MOVE $$quote($$LIB_FILE) $$quote($$LIB_DIR) } ``` 注意:使用`!build_pass`是为了确保在构建时只执行一次,而不是在生成Makefile时执行。 另外,在Qt中,我们也可以使用`QMAKE_DISTCLEAN`来清理移动后的文件,但通常清理构建目录直接删除整个目录,所以不需要额外步骤。 最后,用户需要根据实际情况调整路径。 因此,回答如下: 在QtDLL项目中,您可以通过在.pro文件设置`DESTDIR`变量来指定生成dll文件(以及同时生成的lib文件)的默认输出目录。如果希望将lib文件输出到不同的目录,可以在构建后步骤中使用`QMAKE_POST_LINK`将lib文件移动到另一个目录。 具体步骤如下: 1. 设置dll的输出目录:使用`DESTDIR`指定一个目录(例如`DESTDIR = $$OUT_PWD/bin`)。 2. 设置一个用于存放lib文件目录(例如`LIB_DIR = $$OUT_PWD/lib`)。 3. 根据编译器类型确定lib文件的后缀(MinGW为`.a`,MSVC为`.lib`)。 4. 使用`QMAKE_POST_LINK`命令创建lib目录,并将lib文件从`DESTDIR`移动到`LIB_DIR`。 示例.pro文件代码: ``` TEMPLATE = lib CONFIG += dll # 设置dll和lib的初始输出目录 DESTDIR = $$OUT_PWD/bin win32 { # 定义lib文件的目标目录 LIB_DIR = $$OUT_PWD/lib # 判断编译器,确定lib后缀 contains(QMAKE_EXT_OBJ, .o) { # MinGW编译器 LIB_NAME = $${TARGET}.a } else { # MSVC编译器 LIB_NAME = $${TARGET}.lib } # 构建后步骤:创建lib目录,移动lib文件 QMAKE_POST_LINK += mkdir -p $$shell_path($$LIB_DIR) & $$escape_expand(\\n\\t) QMAKE_POST_LINK += move /Y $$shell_path($$DESTDIR/$$LIB_NAME) $$shell_path($$LIB_DIR) } ``` 注意:上述命令在Windows下使用`move`命令,而在MinGW环境下,我们假设使用类似bash的命令(在Qt Creator中,MinGW环境通常使用sh.exe,因此支持mkdir和mv命令)。为了跨编译器兼容,可能需要分别编写MinGW和MSVC的命令。 对于MinGW,我们应该使用bash命令(mkdir和mv): ``` win32:mingw { QMAKE_POST_LINK += mkdir -p $$shell_path($$LIB_DIR) $$escape_expand(\\n\\t) QMAKE_POST_LINK += mv -f $$shell_path($$DESTDIR/$$LIB_NAME) $$shell_path($$LIB_DIR) } win32:msvc { QMAKE_POST_LINK += if not exist $$shell_path($$LIB_DIR) mkdir $$shell_path($$LIB_DIR) $$escape_expand(\\n\\t) QMAKE_POST_LINK += move /Y $$shell_path($$DESTDIR/$$LIB_NAME) $$shell_path($$LIB_DIR) } ``` 因此,完整的示例: ``` TEMPLATE = lib CONFIG += dll DESTDIR = $$OUT_PWD/bin win32 { LIB_DIR = $$OUT_PWD/lib contains(QMAKE_EXT_OBJ, .o) { LIB_NAME = $${TARGET}.a } else { LIB_NAME = $${TARGET}.lib } } win32:mingw { QMAKE_POST_LINK += mkdir -p $$shell_path($$LIB_DIR) $$escape_expand(\\n\\t) QMAKE_POST_LINK += mv -f $$shell_path($$DESTDIR/$$LIB_NAME) $$shell_path($$LIB_DIR) $$escape_expand(\\n\\t) } win32:msvc { QMAKE_POST_LINK += if not exist $$shell_path($$LIB_DIR) mkdir $$shell_path($$LIB_DIR) $$escape_expand(\\n\\t) QMAKE_POST_LINK += move /Y $$shell_path($$DESTDIR/$$LIB_NAME) $$shell_path($$LIB_DIR) $$escape_expand(\\n\\t) } ``` 这样,在构建DLL项目后,dll文件将位于bin目录,而lib文件将位于lib目录。 请根据实际项目调整路径。 注意:在Qt Creator中,构建后步骤可能会因为路径包含空格而出错,可以使用`$$shell_path()`函数来处理路径,它会将路径转换为带双引号的字符串(如果包含空格)。 另外,在构建后步骤中,多个命令使用`$$escape_expand(\\n\\t)`来分隔,这样在Makefile中会写成多行,每个命令前有一个制表符。 最后,用户需要确保目标目录存在(上面的mkdir命令会创建目录)。 这样,我们就实现了在Qt DLL项目中分别设置dll文件和lib文件生成目录的方法。 </think>在QtDLL项目中分别设置dll文件和lib文件生成目录,可以通过修改.pro项目文件实现。以下是具体方法及步骤: ### 核心配置方法 ```qmake # 基本配置 TEMPLATE = lib CONFIG += dll # 设置.dll文件输出目录(默认同时影响.lib) DESTDIR = $$PWD/bin # 主输出目录 # 单独设置.lib文件目录(通过复制实现) win32 { # DEBUG版本配置 Debug: { # 设置.lib文件目标目录 LIB_OUTPUT = $$PWD/lib/debug # 创建目录并复制文件(构建后步骤) QMAKE_POST_LINK += $$QMAKE_MKDIR $$shell_path($$LIB_OUTPUT) $$escape_expand(\\n\\t) QMAKE_POST_LINK += $$QMAKE_COPY $$shell_path($$DESTDIR/$${TARGET}.lib) $$shell_path($$LIB_OUTPUT) } # RELEASE版本配置 Release: { LIB_OUTPUT = $$PWD/lib/release QMAKE_POST_LINK += $$QMAKE_MKDIR $$shell_path($$LIB_OUTPUT) $$escape_expand(\\n\\t) QMAKE_POST_LINK += $$QMAKE_COPY $$shell_path($$DESTDIR/$${TARGET}.lib) $$shell_path($$LIB_OUTPUT) } } ``` ### 关键说明 1. **DESTDIR指令** 控制主输出目录,默认同时存放.dll和.lib文件。例如: ```qmake DESTDIR = $$PWD/bin # 输出到项目/bin目录 ``` [^2][^3] 2. **分离.lib文件的原理** - Qt没有直接分离.lib输出目录的配置项 - 通过`QMAKE_POST_LINK`在构建完成后复制.lib文件到自定义目录 - 使用`$$QMAKE_COPY`执行复制操作(跨平台兼容) 3. **编译器差异处理** - **MSVC编译器**:生成`.dll` + `.lib`(导入) - **MinGW编译器**:生成`.dll` + `.a`(等效.lib) ```qmake mingw: LIB_EXT = .a msvc: LIB_EXT = .lib QMAKE_POST_LINK += $$QMAKE_COPY $$DESTDIR/$${TARGET}$${LIB_EXT} $$LIB_OUTPUT ``` 4. **目录结构示例** ``` project/ ├── bin/ # DLL输出目录 │ ├── debug/ │ └── release/ ├── lib/ # LIB专用目录 │ ├── debug/ │ └── release/ └── src/ # 源代码 ``` ### 完整配置示例 ```qmake TEMPLATE = lib CONFIG += dll c++11 TARGET = mydll # 主输出目录 DESTDIR = $$PWD/../bin/$${CONFIG} MOC_DIR = $$PWD/tmp/moc OBJECTS_DIR = $$PWD/tmp/obj # 分离.lib文件到独立目录 win32 { # 根据编译器确定后缀 mingw: LIB_EXT = .a msvc: LIB_EXT = .lib LIB_OUTPUT = $$PWD/../lib/$${CONFIG} # 创建目录并复制.lib文件 QMAKE_POST_LINK += $$QMAKE_MKDIR $$shell_path($$LIB_OUTPUT) $$escape_expand(\\n\\t) QMAKE_POST_LINK += $$QMAKE_COPY $$shell_path($$DESTDIR/$${TARGET}$${LIB_EXT}) $$shell_path($$LIB_OUTPUT) } ``` ### 注意事项 1. **路径符号处理** 使用`$$shell_path()`确保路径中的空格和特殊字符被正确处理 2. **清理构建** 添加`QMAKE_DISTCLEAN`自动清理生成文件 ```qmake QMAKE_DISTCLEAN += $$LIB_OUTPUT/$${TARGET}$${LIB_EXT} ``` 3. **依赖项目引用** 其他项目调用此DLL时需配置: ```qmake LIBS += -L$$PWD/../lib/release -lmydll INCLUDEPATH += $$PWD/../include ``` >[!TIP] >此方案通过构建后操作实现物理分离,不影响Qt的原始编译流程。如需完全独立的编译输出,可考虑创建符号链接或使用自定义编译脚本[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值