├── .gitignore ├── Deploy.pri └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | *.slo 3 | *.lo 4 | *.o 5 | *.a 6 | *.la 7 | *.lai 8 | *.so 9 | *.so.* 10 | *.dll 11 | *.dylib 12 | 13 | # Qt-es 14 | object_script.*.Release 15 | object_script.*.Debug 16 | *_plugin_import.cpp 17 | /.qmake.cache 18 | /.qmake.stash 19 | *.pro.user 20 | *.pro.user.* 21 | *.qbs.user 22 | *.qbs.user.* 23 | *.moc 24 | moc_*.cpp 25 | moc_*.h 26 | qrc_*.cpp 27 | ui_*.h 28 | *.qmlc 29 | *.jsc 30 | Makefile* 31 | *build-* 32 | *.qm 33 | *.prl 34 | 35 | # Qt unit tests 36 | target_wrapper.* 37 | 38 | # QtCreator 39 | *.autosave 40 | 41 | # QtCreator Qml 42 | *.qmlproject.user 43 | *.qmlproject.user.* 44 | 45 | # QtCreator CMake 46 | CMakeLists.txt.user* 47 | 48 | # QtCreator 4.8< compilation database 49 | compile_commands.json 50 | 51 | # QtCreator local machine specific files for imported projects 52 | *creator.user* 53 | -------------------------------------------------------------------------------- /Deploy.pri: -------------------------------------------------------------------------------- 1 | # Author: Qt君 2 | # QQ交流群: 732271126 3 | # AUTHOR_INFO: 扫码关注微信公众号: [Qt君] 第一时间获取最新推送. 4 | #██████████████ ██ ██████████████ ██████████████ 5 | #██ ██ ████ ████ ██ ██ ██ ██ 6 | #██ ██████ ██ ██████ ██ ██ ██████ ██ 7 | #██ ██████ ██ ████ ██ ████████ ██ ██ ██████ ██ 8 | #██ ██████ ██ ██ ██ ██ ████ ██ ██████ ██ 9 | #██ ██ ██ ██ ████ ██ ██ ██ ██ 10 | #██████████████ ██ ██ ██ ██ ██ ██ ██ ██████████████ 11 | # ██ ██████ ██████ 12 | #██████████ ██████████ ██ ████████████ ██ ██ ██ ██ 13 | # ██ ████ ██ ██ ██ ████████ ██ 14 | # ██ ██ ████ ████ ████████████ ██ ██ ██████ 15 | # ██████ ██████ ██ ██ ██████ ██ 16 | # ██████████ ██ ██ ██ ██ ██ ██ ██ ████ 17 | # ██ ██ ██████ ████ ████████████ ██ ██ 18 | #████ ██████████ ██ ████ ██ ██ ██ ██ ██ 19 | #████ ████ ████ ██ ██████ ██████████ ██ 20 | # ██ ████ ██ ████ ██████ ██ ██ ██ ██ 21 | #████████ ██ ██ ████ ██ ████ ██████████ ██ 22 | #██ ████ ████ ██ ████ ████ ████ ████████ 23 | #██ ████ ██ ██ ██ ████ ██ ██ 24 | #██ ██████ ████ ████ ██████████ ██████████ ██████ 25 | # ████ ████ ████ ██ ██ ██████████ 26 | #██████████████ ████ ██████ ████ ██ ██████ 27 | #██ ██ ████ ██ ██████ ██████ ████ ██ 28 | #██ ██████ ██ ████ ████ ██ ██ ██████████████████ 29 | #██ ██████ ██ ████ ██████████ ██ ██ ████ 30 | #██ ██████ ██ ██ ██████ ██ ████████ ████████████ 31 | #██ ██ ██ ██ ████ ██ ████ ██████ ██ 32 | #██████████████ ██████████ ██ ████ ██ 33 | 34 | # ---v1.0.1--- # 35 | 36 | # --- [start]注意事项[start] --- # 37 | # 目前仅支持windows平台 # 38 | # --- [end]注意事项[end] --- # 39 | 40 | # --- [start]使用方法[start] --- # 41 | # 复制本脚本代码到你的项目文件中 # 42 | # 或在项目文件中使用include包含本文件 # 43 | # --- [end]使用方法[end] --- # 44 | 45 | # --- [start]输入参数[start] --- # 46 | # 指定打包后的输出目录 47 | # 默认为程序pro文件路径的package_output目录(没有则新键) 48 | isEmpty(DEPLOY_OUT_PUT_DIR): DEPLOY_OUT_PUT_DIR = $$_PRO_FILE_PWD_/package_output 49 | 50 | # 是否开启打印信息输出(不会影响主项目的打印输出) # 51 | # 需要屏蔽打印就将它注释即可 # 52 | # 默认不开启 # 53 | #DEBUG_LOGGER = hello world 54 | 55 | # 是否在编译完成后自动打开目标目录 56 | # 需要屏蔽该功能就将它注释即可 # 57 | # 默认开启 # 58 | DEPLOY_COMPLETE_AUTO_OPEN_EXPLORER = hello world 59 | 60 | # 是否开启实验性功能 # 61 | # 需要屏蔽实验性功能只需注释即可 # 62 | # 默认不开启 # 63 | #EXPERIMENTAL = hello world # 优化qmake执行速度 64 | # --- [end]输入参数[end] --- # 65 | 66 | # --- [start]函数[start] --- # 67 | # 移除多余的debug或release配置项(实验功能) 68 | defineReplace(remove_extra_config_parameter) { 69 | configs = $$1 70 | debug_and_release_params = 71 | keys = debug Debug release Release #debug_and_release 72 | for (iter, configs) { 73 | contains(keys, $$lower($$iter)) { 74 | debug_and_release_params += $$lower($$iter) 75 | } 76 | } 77 | 78 | for (iter, debug_and_release_params) { 79 | configs -= $$iter 80 | } 81 | 82 | configs += $$last(debug_and_release_params) 83 | 84 | return($$configs) 85 | } 86 | 87 | # 获取资源文件中的qml文件 88 | defineReplace(find_qml_file) { 89 | resources = $$1 90 | qml_file_list = 91 | 92 | for (resource, resources) { 93 | # 需要相对路径使用 94 | # _PRO_FILE_PWD_ 95 | resource_file = $$_PRO_FILE_PWD_/$$resource 96 | !exists($$resource_file) : error($$resource not found.) 97 | content_lines = $$cat($$resource_file) 98 | for (iter, content_lines) { 99 | tmp = $$find(iter, .*) 100 | !isEmpty(tmp) { 101 | qml_file_list += $$replace(iter, ((.*)), \2) 102 | } 103 | } 104 | } 105 | 106 | return ($$qml_file_list) 107 | } 108 | 109 | # 获取qml文件中使用到的模块 110 | defineReplace(get_qml_module_list) { 111 | qml_file_list = $$1 112 | default_qml_module_list = QtQuick.Shapes QtQuick.Particles QtQuick.VirtualKeyboard 113 | qml_module_list = 114 | for (file, qml_file_list) { 115 | qml_file = $$_PRO_FILE_PWD_/$$file 116 | !exists($$qml_file) : error($$file not found.) 117 | content_lines = $$cat($$qml_file) 118 | for (iter, content_lines) { 119 | contains(default_qml_module_list, $$iter) { 120 | module_name = $$section(iter, ., 1, 1) 121 | qml_module_list += $$module_name 122 | } 123 | } 124 | } 125 | 126 | return ($$qml_module_list) 127 | } 128 | 129 | # 获取需要复制qml库的命令行 130 | defineReplace(get_copy_qml_library_cmd_line) { 131 | qt_dir = $$1 132 | qt_bin_dir = $$2 133 | target_out_dir = $$3 134 | resources = $$4 135 | cmd_line = 136 | 137 | qml_file_list = $$find_qml_file($$resources) 138 | !isEmpty(DEBUG_LOGGER): !isEmpty(qml_file_list): message(result: $$qml_file_list) 139 | 140 | qml_module_list = $$get_qml_module_list($$qml_file_list) 141 | !isEmpty(DEBUG_LOGGER): message(qml_module_list: $$qml_module_list) 142 | 143 | for (qml_module, qml_module_list) { 144 | if (equals(qml_module, Particles)) { 145 | # 源qml的quick的某个模块库目录 146 | source = $${qt_dir}qml/QtQuick/$${qml_module}.2 147 | # 目标qml的quick的某个模块源库目录 148 | dest = $${target_out_dir}QtQuick/$${qml_module}.2 149 | } 150 | else { 151 | # 源qml的quick的某个模块库目录 152 | source = $${qt_dir}qml/QtQuick/$${qml_module} 153 | # 目标qml的quick的某个模块源库目录 154 | dest = $${target_out_dir}QtQuick/$${qml_module} 155 | } 156 | 157 | 158 | 159 | # 复制qml模块(dll)(命令行) 160 | CONFIG(debug, debug|release) { 161 | if (equals(qml_module, VirtualKeyboard)) { 162 | qml_module_params = $${qt_bin_dir}Qt5$${qml_module}d.dll $${target_out_dir} 163 | } 164 | else { 165 | qml_module_params = $${qt_bin_dir}Qt5Quick$${qml_module}d.dll $${target_out_dir} 166 | } 167 | } 168 | else { 169 | if (equals(qml_module, VirtualKeyboard)) { 170 | qml_module_params = $${qt_bin_dir}Qt5$${qml_module}.dll $${target_out_dir} 171 | } 172 | else { 173 | qml_module_params = $${qt_bin_dir}Qt5Quick$${qml_module}.dll $${target_out_dir} 174 | } 175 | } 176 | 177 | # 判断平台是/还是\为路径符 178 | equals(QMAKE_DIR_SEP, \\) { 179 | source = $$replace(source, /, \\) 180 | dest = $$replace(dest, /, \\) 181 | qml_module_params = $$replace(qml_module_params, /, \\) 182 | } 183 | 184 | 185 | copy_qml_quick_module_file_cmd_line = $$QMAKE_COPY_DIR $$source $$dest # 复制Qml模块到指定目录 186 | copy_qml_module_cmd_line = $$QMAKE_COPY_FILE $$qml_module_params 187 | 188 | cmd_line += && $$command_warpper($$copy_qml_quick_module_file_cmd_line, $$_LINE_) 189 | cmd_line += && $$command_warpper($$copy_qml_module_cmd_line, $$_LINE_) 190 | } 191 | 192 | return ($$cmd_line) 193 | } 194 | 195 | # 命令包装,主要附加命令本身打印 196 | defineReplace(command_warpper) { 197 | cmd_line = $$1 198 | line = $$2 199 | return (echo Execute Command: line: $$line cmd_line: $$cmd_line && $$cmd_line) 200 | } 201 | 202 | # 根据平台处理路径分隔符 203 | defineReplace(processing_slash) { 204 | tmp = $$1 205 | # 判断平台是/还是\为路径符 206 | equals(QMAKE_DIR_SEP, \\): return ($$replace(tmp, /, \\)) 207 | 208 | return ($$tmp) 209 | } 210 | 211 | defineReplace(is_debug) { 212 | CONFIG(debug, debug|release): return (true) 213 | return (false) 214 | } 215 | 216 | # 目前仅支持window系统 217 | defineReplace(get_copy_system_library_to_target_dir_cmd_line) { 218 | target = $$1 219 | !win32-msvc*: return (echo ignore) 220 | 221 | contains(QMAKE_HOST.arch, x86_64) { 222 | # 64bit 223 | system_dir = C:\Windows\SysWOW64 224 | } 225 | else { 226 | # 32bit 227 | system_dir = C:\Windows\System32 228 | } 229 | 230 | # fixed 231 | $$is_debug() { 232 | cmd_line = $$QMAKE_COPY_FILE $$system_dir\msvcp1?0d.dll $$target 233 | cmd_line = $$QMAKE_COPY_FILE $$system_dir\vcruntime*d.dll $$target 234 | cmd_line = $$QMAKE_COPY_FILE $$system_dir\ucrtbased.dll $$target 235 | } 236 | else { 237 | cmd_line = $$QMAKE_COPY_FILE $$system_dir\msvcp1?0.dll $$target 238 | cmd_line = $$QMAKE_COPY_FILE $$system_dir\vcruntime1?0.dll $$target 239 | cmd_line = $$QMAKE_COPY_FILE $$system_dir\ucrtbase.dll $$target 240 | } 241 | cmd_line += && $$QMAKE_COPY_FILE $$system_dir\api-ms-win-*.dll $$target 242 | 243 | return ($$cmd_line) 244 | } 245 | 246 | defineReplace(get_third_part_library_cmd_line) { 247 | target = $$1 248 | lib_file_list = 249 | lib_dir_list = 250 | lib_prefix = 251 | lib_suffix = 252 | cmd_line = 253 | for (iter, LIBS) { 254 | prefix = $$str_member($$iter, 0, 1) 255 | content = $$str_member($$iter, 2, -1) 256 | equals(prefix, -L) { 257 | suffix = $$str_member($$content, -1, -1)) 258 | !equals(suffix, /): content = $$content/ 259 | message(-L: $$content) 260 | lib_dir_list += $$content 261 | } 262 | else: equals(prefix, -l) { 263 | message(-l: $$content) 264 | lib_file_list += $$content 265 | } 266 | } 267 | 268 | win32: lib_suffix = *.dll 269 | 270 | for (file, lib_file_list) { 271 | for (dir, lib_dir_list) { 272 | exists($$_PRO_FILE_PWD_/$$dir$$file$$lib_suffix) { 273 | cmd_line += && $$QMAKE_COPY_FILE $$processing_slash($$_PRO_FILE_PWD_/$$dir$$file$$lib_suffix $$target) 274 | } 275 | } 276 | } 277 | 278 | message($$cmd_line) 279 | return ($$cmd_line) 280 | } 281 | # --- [end]函数[end] --- # 282 | 283 | # 获取从QMake执行文件的所在目录得出Qt的bin路径 284 | QT_DIR = $$[QT_INSTALL_PREFIX]/ 285 | # 获取Qt开发环境路径 286 | QT_BIN_DIR = $${QT_DIR}bin/ 287 | 288 | isEmpty(QT_DIR) { 289 | QT_BIN_DIR = $$replace(QMAKE_QMAKE, ^(\S*/)\S+$, \1) 290 | QT_DIR = $${QT_BIN_DIR}../ 291 | } 292 | 293 | # Qt打包工具参数配置集合 294 | DEPLOY_OPTIONS += --force 295 | 296 | # 可用的Qt模块 297 | QT_AVAILABLE_LIBRARY_LIST = \ 298 | bluetooth concurrent core declarative designer designercomponents enginio \ 299 | gamepad gui qthelp multimedia multimediawidgets multimediaquick network nfc \ 300 | opengl positioning printsupport qml qmltooling quick quickparticles quickwidgets \ 301 | script scripttools sensors serialport sql svg test webkit webkitwidgets \ 302 | websockets widgets winextras xml xmlpatterns webenginecore webengine \ 303 | webenginewidgets 3dcore 3drenderer 3dquick 3dquickrenderer 3dinput 3danimation \ 304 | 3dextras geoservices webchannel texttospeech serialbus webview 305 | 306 | # 扫描QT变量用于打包模块的参数配置 307 | for (LIBRARY_MODULE, QT_AVAILABLE_LIBRARY_LIST) { 308 | if (contains(QT, $$LIBRARY_MODULE)) { 309 | DEPLOY_OPTIONS *= --$$LIBRARY_MODULE 310 | } 311 | else { 312 | DEPLOY_OPTIONS *= --no-$$LIBRARY_MODULE 313 | } 314 | } 315 | 316 | # 针对Qml模块配置打包参数 317 | if (contains(QT, quick)) { 318 | DEPLOY_OPTIONS -= --no-qml 319 | DEPLOY_OPTIONS *= --qml 320 | 321 | DEPLOY_OPTIONS -= --no-network 322 | DEPLOY_OPTIONS *= --network 323 | 324 | DEPLOY_OPTIONS *= --qmldir $${QT_DIR}qml/ 325 | } 326 | 327 | if (!isEmpty(DESTDIR)) { 328 | # 如有设置目标输出路径则定向于该路径 329 | TARGET_OUT_DIR = $$OUT_PWD/$$DESTDIR/ 330 | } 331 | else { 332 | # 判断是debug版本还是release版本 333 | CONFIG(debug, debug|release) { 334 | contains(CONFIG, debug_and_release) { 335 | TARGET_OUT_DIR = $${OUT_PWD}/debug/ 336 | } 337 | else { 338 | TARGET_OUT_DIR = $${OUT_PWD}/ 339 | } 340 | DEPLOY_OPTIONS *= --debug 341 | } 342 | else { 343 | contains(CONFIG, debug_and_release) { 344 | TARGET_OUT_DIR = $${OUT_PWD}/release/ 345 | } 346 | else { 347 | TARGET_OUT_DIR = $${OUT_PWD}/ 348 | } 349 | DEPLOY_OPTIONS *= --release 350 | } 351 | } 352 | 353 | # 预打包目标目录 354 | isEmpty(DEPLOY_OUT_PUT_DIR) { 355 | DEPLOY_OUT_PUT_DIR = $$TARGET_OUT_DIR 356 | } 357 | 358 | # 实验性功能 359 | !isEmpty(EXPERIMENTAL) { 360 | # 该功能(用于优化qmake调试输出)是否开放还需待定,因为会导致其他未知的问题。 361 | CONFIG = $$remove_extra_config_parameter($$CONFIG) 362 | } 363 | 364 | win32 { 365 | # 拼接Qt部署程序的文件(windows平台下为windeployqt.exe) 366 | WIN_DEPLOY_BIN = $${QT_BIN_DIR}windeployqt.exe 367 | # 编译输出的执行文件(含文件和目录路径) 368 | TARGET_OUT_FILE = $$TARGET_OUT_DIR$${TARGET}.exe 369 | 370 | WIN_DEPLOY_BIN = $$processing_slash($$WIN_DEPLOY_BIN) 371 | TARGET_OUT_FILE = $$processing_slash($$TARGET_OUT_FILE) 372 | 373 | DEPLOY_OUT_PUT_DIR = $$absolute_path("&&&Qtjun&&&", $$DEPLOY_OUT_PUT_DIR) #需要fixed 374 | DEPLOY_OUT_PUT_DIR = $$replace(DEPLOY_OUT_PUT_DIR, &&&Qtjun&&&,) 375 | DEPLOY_OUT_PUT_DIR = $$processing_slash($$DEPLOY_OUT_PUT_DIR) 376 | 377 | TARGET_OUT_DIR = $$processing_slash($$TARGET_OUT_DIR) 378 | 379 | # 预编译所在目录的执行文件 380 | DEPLOY_OUT_PUT_FILE = $$DEPLOY_OUT_PUT_DIR$${TARGET}.exe 381 | DEPLOY_OUT_PUT_FILE = $$processing_slash($$DEPLOY_OUT_PUT_FILE) 382 | 383 | # 复制执行文件到预打包目录 384 | !equals(DEPLOY_OUT_PUT_DIR, $$TARGET_OUT_DIR) { 385 | !isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK += && 386 | QMAKE_POST_LINK += $$command_warpper($$QMAKE_MKDIR \"$$DEPLOY_OUT_PUT_DIR\", $$_LINE_) 387 | QMAKE_POST_LINK += & $$command_warpper($$QMAKE_COPY_FILE \"$$TARGET_OUT_FILE\" \"$$DEPLOY_OUT_PUT_DIR\", $$_LINE_) 388 | } 389 | 390 | # 编译完成后执行打包命令 391 | !isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK += && 392 | QMAKE_POST_LINK += $$command_warpper($$WIN_DEPLOY_BIN $$DEPLOY_OPTIONS \"$$DEPLOY_OUT_PUT_FILE\", $$_LINE_) 393 | 394 | # 扫描Qml依赖库,并在编译完成后自动复制qml依赖库到目标目录 395 | QMAKE_POST_LINK += $$get_copy_qml_library_cmd_line($$QT_DIR, $$QT_BIN_DIR, \"$$DEPLOY_OUT_PUT_DIR\", $$RESOURCES) 396 | 397 | # 复制系统库 398 | QMAKE_POST_LINK += && $$command_warpper($$get_copy_system_library_to_target_dir_cmd_line(\"$$DEPLOY_OUT_PUT_DIR\"), $$_LINE_) 399 | 400 | # 扫描复制第三方库 401 | # QMAKE_POST_LINK += $$command_warpper($$get_third_part_library_cmd_line($$DEPLOY_OUT_PUT_DIR), $$_LINE_) 402 | 403 | !isEmpty(DEPLOY_COMPLETE_AUTO_OPEN_EXPLORER) { 404 | # 打包完成后自动打开目标路径 405 | QMAKE_POST_LINK += && $$command_warpper(cmd /c explorer \"$$DEPLOY_OUT_PUT_DIR\", $$_LINE_) # FIXME 406 | } 407 | 408 | # 注意:该命令放在最后 409 | QMAKE_POST_LINK += & echo ------------------------------Package Success------------------------------ 410 | } 411 | 412 | # 调试输出 413 | !isEmpty(DEBUG_LOGGER) { 414 | message(TARGET_OUT_DIR: $$TARGET_OUT_DIR) # 生成文件的输出目录 415 | message(DEPLOY_OUT_PUT_DIR: $$DEPLOY_OUT_PUT_DIR) # 预打包文件的输出目录 416 | message(QMAKE_POST_LINK: $$QMAKE_POST_LINK) # 打印命令 417 | } 418 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DeployByQmake 2 | 简单添加pri文件即可在编译完成后对程序执行打包操作。 3 | 4 | ## 使用方法 5 | * 只需在项目文件pro加入`include(../Deploy.pri)`即可。 6 | --------------------------------------------------------------------------------