├── .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 |
--------------------------------------------------------------------------------