一、Qt Widgets 问题交流
二、Qt Quick 问题交流
三、其他
1.Qt qmake 在 Mac 上生成 dylib 相关的问题
默认的 lib 工程 qmake 输出如图,会生成带版本号的软链接:
一般我们只需要一个 lib 文件,可以增加设置:
CONFIG += unversioned_libname unversioned_soname
unversioned_libname 去掉了 lib 的版本号,unversioned_soname 去掉了链接里的版本号(Windows 版本对应的设置叫 skip_target_version_ext)。网上有的是用 CONFIG += plugin,这样写 QMAKE_SONAME_PREFIX 设置 rpath 就没生效。
一般还需要给库设置链接路径 rpath,不然运行时报错找不到库,qmake 设置:
QMAKE_SONAME_PREFIX = @rpath
这样引用这个库的可执行程序就会去如 Frameworks 之类的目录查找,如果不设置 dylib 中的路径最后还得设置可执行程序链接库的路径,qmake 构建的时候默认可执行程序的查找路径和 dylib 中的似乎是一样的。
上面去掉库文件名的版本号后,Qt5 在 mac 上用 profile 模式编译还会报错:
因为 qmake 的脚本有 bug,dylib 虽然是没版本号了,但是调试文件 dSYM 还是带版本号的,因为有一段逻辑里没判断 unversioned_libname 这个设置。
参考 Qt BUG Tracker:https://bugreports.qt.io/browse/QTBUG-64290
直接打开安装目录下的 mkspecs/features/resolve_target.prf ,修改如图,增加了 unversioned_libname 判断:
2.CMake 在 Windows 上生成 dll 时生成导入库 lib
方式一:使用 def 模块定义文件
参考文档:https://learn.microsoft.com/zh-cn/cpp/build/reference/module-definition-dot-def-files
写好 def 文件后,在 add_library 中包含这个文件:
add_library(${PROJECT_NAME} SHARED ${head_files} ${source_files} xxx.def)
方式二:使用 __declspec(dllexport)
__declspec(dllexport) void __cdecl Function1(void);
方式三:CMAKE 变量 CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
参考文档:https://cmake.org/cmake/help/latest/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.html
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
add_library(${PROJECT_NAME} SHARED ${head_files} ${source_files})
该设置会导出所有符号,但对于全局变量还是需要前面两种方式来显式导出。很多 GUN 风格的库没有声明导出符号,用这个变量设置再好不过了。
3.Windows 上一些和 std 冲突的处理
std::byte 由 /std:c++17 或更高版本启用,using namespace std 后会和 Windows SDK 中的 byte 定义冲突,可以增加宏定义:_HAS_STD_BYTE=0 屏蔽 std::byte,但是这又会导致某些库中的 std::byte 未定义,所以最好不要 using namespace std。
Windows SDK 中的 min max 函数有时候会和标准库中的冲突,可以增加宏定义:NOMINMAX
宏定义要么在工程配置里加,要么在 include Windows 头文件之前加,qmake 写法:
# conflict c++17 std::byte and window byte
DEFINES += _HAS_STD_BYTE=0
# std::min std::max
DEFINES += NOMINMAX