【问题标题】:Create shared library (.lib and .dll) using qmake and MSVC2015使用 qmake 和 MSVC2015 创建共享库(.lib 和 .dll)
【发布时间】:2019-10-21 22:36:04
【问题描述】:

我正在将一个共享库从 CMake 移植到 QMake(以便更好地与我们的其他代码库集成),并且在 Windows 中让 qmake 同时生成 .lib 和 .dll 文件时遇到了麻烦。 我已将它移植到 Linux 和 MacOS(使用 Unix 共享库格式更容易),但在使用 Windows 时遇到了问题。

请注意,我使用的不是 Mingw 编译器,而是 MSVC 2015 编译器。不幸的是,由于各种原因,我不能使用 Mingw 编译器。

我的 .pro 文件中的相关代码:

Qt -= core gui #not using the qt library
CONFIG += c++14 warn_on
TEMPLATE  = lib
TARGET = MyLibrary

使用 CMake,我能够将某些 .h 文件设置为 PUBLIC_HEADER 文件,并且在运行 make install 后,它生成了正确的 .lib 和 .dll 文件。

但是使用 qmake,它只生成了一个非常小的 .dll 文件(CONFIG += static,但这创建了一个包含所有符号的 .lib 文件,而不是我正在寻找的共享库文件。

编辑:在深入研究之后,一个更好的问题可能是: 是否有 CMake 的 PUBLIC_HEADER 属性的 qmake 等效项(或解决方法)?

【问题讨论】:

  • 在 Windows 下,默认情况下不会从 DLL 导出任何内容(与 *nix 不同,所有全局变量都是从 .so 导出的)。在构建源代码时,您必须将 dllexport 说明符附加到所有导出的类。

标签: c++ windows visual-c++ qmake


【解决方案1】:

简而言之:@Matt 是对的,您需要在源代码中采取主动行动来导出类、函数和其他符号。这在 Windows 中是强制性的,但在 Unix 中也是推荐的做法。当 MSVC++ 编译器看到导出的符号时,它会自动创建 .DLL 和 .LIB 导入库。

要使用 qmake 以跨平台的方式执行此操作,一个很好的指南是遵循 Qt Creator 向导的模式:欢迎 -> 新项目 -> 库 -> C++ 库。项目位置...,名称:'testlib'(例如)。下一步,下一步,选择你的套件,下一步,完成。向导在项目目录中创建的文件有:

testlib.cpp
testlib_global.h
testlib.h
testlib.pro
testlib.pro.user

有趣的部分在 testlib.pro 中:

TEMPLATE = lib
DEFINES += TESTLIB_LIBRARY

还有头文件“testlib_global.h”

#ifndef TESTLIB_GLOBAL_H
#define TESTLIB_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(TESTLIB_LIBRARY)
#  define TESTLIB_EXPORT Q_DECL_EXPORT
#else
#  define TESTLIB_EXPORT Q_DECL_IMPORT
#endif

#endif // TESTLIB_GLOBAL_H

这个头文件应该包含在其他头文件中,这将使用像这样的 TESTLIB_EXPORT 宏 (testlib.h):

#ifndef TESTLIB_H
#define TESTLIB_H

#include "testlib_global.h"

class TESTLIB_EXPORT Testlib
{
public:
        Testlib();
        // ...
};

关键是在构建库的项目.pro中定义TESTLIB_LIBRARY,所以TESTLIB_EXPORT宏定义为Q_DECL_EXPORT,在Windows中定义为__declspec(dllexport)避免在中定义TESTLIB_LIBRARY 使用库的项目。有关此here 的更多信息。

现在,问题的第二部分。在CMake documentation 中,它说:

PUBLIC_HEADER

在 FRAMEWORK 共享库目标中指定公共头文件。

用 FRAMEWORK 属性标记的共享库目标生成 macOS、iOS 上的框架和其他上的普通共享库 平台。这个属性可以设置为一个头文件列表 放置在框架文件夹内的Headers目录中。在 非 Apple 平台可以使用 install(TARGETS) 命令的 PUBLIC_HEADER 选项。

所以 PUBLIC_HEADER 属性仅用于安装公共标头。要在 qmake 中这样做,您需要在 testlib.pro 中使用 INSTALLS,例如:

unix {
    target.path = /usr/local/lib
    headers.path = /usr/local/include
}
!isEmpty(target.path) {
    INSTALLS += target
}

headers.files = $$HEADERS
!isEmpty(headers.path) {
    INSTALLS += headers
}

【讨论】:

  • 谢谢!这很有帮助。我试用了您的示例代码,效果很好!虽然这是正确的方法,但我在命名要导出的具有 std 类的类时出错,可以使用 pimpl 修复。为了避免大规模的重构,我决定使用 CMake 的 WINDOWS_EXPORT_ALL_SYMBOLS 属性在内部执行 CMake 的操作,即生成一个包含所有 .obj 文件中的符号的文件到一个 .def 文件中,并在链接时使用 /DEF 选项。在我们正确实施您所描述的内容之前,只有一个技巧。
猜你喜欢
  • 1970-01-01
  • 2011-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多