【发布时间】:2021-09-21 11:51:36
【问题描述】:
我有一个使用 CMake 生成构建文件的 c++ 项目。这个项目依赖于外部库,我从互联网上下载了必要的文件(头文件、.lib 和 .dll)。我的项目可以编译,如果库的 DLL 包含在 PATH 中,或者将 DLL 复制到与我的项目的 .exe 相同的位置,则它可以正常运行。现在我希望能够在另一台计算机上运行这个程序。为此,我需要知道我必须在 .exe 文件旁边包含哪些 DLL。
我已经看到任何给定 dll 或 exe 的 DLL 依赖项都可以使用 MVSC dumpbin 找到。例如这个主要的:
#include <QApplication>
#include <QStyleFactory>
#include <QFileDialog>
#include <QStandardPaths>
#include <opencv2/highgui/highgui.hpp>
int main(int argc, char** argv)
{
// Create application
QApplication app(argc, argv);
app.setStyle(QStyleFactory::create(QStringLiteral("Fusion")));
// Get file name
QString file_name = QFileDialog::getOpenFileName(nullptr, QObject::tr("Open File"),
QStandardPaths::displayName(QStandardPaths::HomeLocation),
QObject::tr("Images (*.png *.xpm *.jpg)"));
// Read image
cv::Mat mat = cv::imread(file_name.toStdString());
// Show image in opencv
cv::namedWindow("display",cv::WINDOW_KEEPRATIO |cv::WINDOW_GUI_NORMAL );
cv::imshow("display",mat);
cv::waitKey(0);
// Run application
return app.exec();
}
dumpbin /dependents main.exe 命令的输出是:
Microsoft (R) COFF/PE Dumper Version 14.28.29912.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file .\src\RelWithDebInfo\main.exe
File Type: EXECUTABLE IMAGE
Image has the following dependencies:
Qt5Widgets.dll
opencv_world347.dll
Qt5Core.dll
VCRUNTIME140.dll
VCRUNTIME140_1.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-heap-l1-1-0.dll
KERNEL32.dll
SHELL32.dll
Summary
1000 .00cfg
1000 .data
2000 .idata
1000 .pdata
3000 .rdata
1000 .reloc
1000 .rsrc
6000 .text
在这种情况下,我需要这个 DLL 列表才能运行我的程序。但是,有些是系统 DLL(KERNEL32.dll、SHELL32.dll...),有些是不是系统 DLL(Qt5Widgets.dll、opencv_world347.dll...)的库。
我应该在哪里决定停止复制 DLL 以发布我的程序?我应该与KERNEL32.dll 和SHELL32.dll一起发货,我应该包括api-ms-win*.dll还是应该只包括Qt5Widgets.dll、Qt5Core.dll和opencv_world347.dll? 我如何从列表中知道哪些是系统 DLL,哪些不是?
PS2:我知道专门针对 Qt 有 windeployqt 会自动处理 Qt DLL 部分,并且 VCRUNTIME140*.dll 部分也可以通过安装 vc_redist 来处理
注意:这个问题的范围只是知道在哪里停止。我对如何构建安装程序或如何自动化文件副本或在哪里查找相关 DLL 不感兴趣。
注意2:问题Find dependent modules of dll 和how do I include dll's such as kernel32.dll which my unmanaged dll needs 没有回答我的问题。
【问题讨论】:
-
不允许运送 Windows dll(kernel32、shell32),因为目标操作系统已经安装了它们,所以无论如何都是没有意义的。
-
@500-InternalServerError 我知道这两个,但是
api-ms-win*.dll呢?他们是系统吗?我应该复制它们并将它们放到我安装可执行文件的文件夹中吗?我更新了问题标题,试图更清楚地表明我正在寻找的是停止复制 dll 的限制,因为它们已经是系统的一部分。 -
"我应该只包括 Qt5Widgets.dll、Qt5Core.dll 和 opencv_world347.dll" ← 是
-
@spectras 我知道这个具体的例子。但更一般地说,我如何从列表中知道哪些是系统 DLL,哪些不是?
-
不,那些是 windows 文件。 — 如果您使用一些工具来管理依赖项(这是一个好主意),那么它的工作就是为您提供这些答案。它的工具应该有一些命令或某种方式来获取你必须部署的文件列表。