使用 qmake 和 MSVC2015 创建共享库(.lib 和 .dll)
Create shared library (.lib and .dll) using qmake and MSVC2015
我正在将一个共享库从 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 文件 (<15kb)。我尝试添加 CONFIG += static
但创建了一个包含所有符号的 .lib 文件,而不是我要查找的共享库文件。
编辑:在深入研究之后,一个更好的问题可能是:
是否有 CMake 的 PUBLIC_HEADER 属性 的 qmake 等价物(或解决方法)?
简而言之:@Matt 是对的,您需要在源代码中采取积极行动来导出 类、函数和其他符号。这在 Windows 中是强制性的,但在 Unix 中也是推荐的做法。当 MSVC++ 编译器看到导出的符号时,它会自动创建 .DLL 和 .LIB 导入库。
要使用 qmake 以 cross-platform 方式执行此操作,一个很好的指南是遵循 Qt Creator 向导的模式:欢迎 -> 新建项目 -> 库 -> C++ 库。项目位置...,名称:'testlib'(例如)。下一步,下一步,选择你的工具包,下一步,完成。向导在项目目录中创建的文件是:
testlib.cpp
testlib_global.h
testlib.h
testlib.pro
testlib.pro.user
有趣的部分在 testlib.pro:
TEMPLATE = lib
DEFINES += TESTLIB_LIBRARY
还有 header "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
这个 header 应该包含在其他 header 中,这将使用像这样的 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
Specify public header files in a FRAMEWORK shared library target.
Shared library targets marked with the FRAMEWORK property generate
frameworks on macOS, iOS and normal shared libraries on other
platforms. This property may be set to a list of header files to be
placed in the Headers directory inside the framework folder. On
non-Apple platforms these headers may be installed using the
PUBLIC_HEADER option to the install(TARGETS) command.
因此 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
}
我正在将一个共享库从 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 文件 (<15kb)。我尝试添加 CONFIG += static
但创建了一个包含所有符号的 .lib 文件,而不是我要查找的共享库文件。
编辑:在深入研究之后,一个更好的问题可能是: 是否有 CMake 的 PUBLIC_HEADER 属性 的 qmake 等价物(或解决方法)?
简而言之:@Matt 是对的,您需要在源代码中采取积极行动来导出 类、函数和其他符号。这在 Windows 中是强制性的,但在 Unix 中也是推荐的做法。当 MSVC++ 编译器看到导出的符号时,它会自动创建 .DLL 和 .LIB 导入库。
要使用 qmake 以 cross-platform 方式执行此操作,一个很好的指南是遵循 Qt Creator 向导的模式:欢迎 -> 新建项目 -> 库 -> C++ 库。项目位置...,名称:'testlib'(例如)。下一步,下一步,选择你的工具包,下一步,完成。向导在项目目录中创建的文件是:
testlib.cpp
testlib_global.h
testlib.h
testlib.pro
testlib.pro.user
有趣的部分在 testlib.pro:
TEMPLATE = lib
DEFINES += TESTLIB_LIBRARY
还有 header "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
这个 header 应该包含在其他 header 中,这将使用像这样的 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
Specify public header files in a FRAMEWORK shared library target.
Shared library targets marked with the FRAMEWORK property generate frameworks on macOS, iOS and normal shared libraries on other platforms. This property may be set to a list of header files to be placed in the Headers directory inside the framework folder. On non-Apple platforms these headers may be installed using the PUBLIC_HEADER option to the install(TARGETS) command.
因此 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
}