EGE专栏:EGE专栏
目录
EGE程序打包发布与程序图标修改
在完成程序的编写和功能调试后,我们可以将程序打包,以便能够在本地计算机或其它安装了windows系统的计算机上运行。
我们先来了解一些程序的相关知识。
一、相关知识
1. x64 与 x86
x86 泛指一系列基于 Intel 8086 且向后兼容的中央处理器指令集架构。最早的8086处理器于1978年由Intel推出,为16位微处理器。
x86处理器架构包含32位架构和64位架构的,其中的64位架构称为 x86-64,简称 x64。
一般说的 x86处理器 是指 32位处理器,x64处理器是指64位处理器。
- 64位处理器支持安装64位操作系统和32位操作系统
- 32位处理器支持32位操作系统,不支持64位操作系统。
2. 64位操作系统与32位操作系统
64位操作系统可以运行64位程序和32位程序
32位操作系统可以运行32位程序,无法运行64位程序。
目前电脑使用的基本都是64位操作系统,32位操作系统已很少,32位操作系统一般在旧电脑上有。
在 此电脑 上右键选择 属性,可以查看计算机的基本信息。
从下图中可以看到,系统类型为64位操作系统,x64处理器
3. 64位程序与32位程序
在IDE中,可以看到如下的类似配置,用于配置生成的是64位程序还是32位程序。(一图为Dev-C++,二图为Visual Studio)
- 32位程序可以在64位操作系统上运行,也可以在32位操作系统上运行
- 64位程序只能在64位操作系统上运行
32位程序可最大寻址 2 32 2^{32} 232,理论上最大只能申请4GB的内存( 2 32 B = 4 G B 2^{32}B = 4GB 232B=4GB),而64位程序可寻址 2 64 2^{64} 264,可以申请大于4GB的内存。
64位系统上,64位程序性能更优。
目前市面上的软件依然有不少是32位程序。
4. 编译模式:Debug 与 Release
Debug是调试的意思,Release则为发布。
在IDE中,通常都有Debug 和 Release 模式 的选择。
这两种是有区别的,简单来说就是:
- 在编写代码,调试程序时,选择Debug编译模式
- 当程序测试完成需要查看运行结果,或者需要发布软件,选择Release编译模式
4.1 Debug与Release的区别
Debug和Release没有本质的区别,只是IDE会分别为这两种模式设置不同的编译选项,以适应调试和发布两种不同的情况,这两种编译选项可由用户自行配置。
Debug通常称为调试版本,通过一系列编译选项的配合,编译的结果通常包含调试信息,而且不做任何优化,以为开发人员提供强大的应用程序调试能力。
而Release通常称为发布版本,是为用户使用的,一般客户不允许在发布版本上进行调试。所以不保存调试信息,同时,它往往进行了各种优化,以期达到代码最小和速度最优,为用户的使用提供便利。
相对来说,Debug版本生成的可执行文件体积更大,性能较差。而Release版本的体积更小,运行速度更快。
4.2 Debug 和 Release报错情况不同
在Debug模式下,为了便于调试,未初始化变量的每个字节都会被赋值成0xCC,而Release则不会给未初始化变量赋值。
同时,Debug模式下可能会分配更多的内存,这就可能导致数组越界情况下,在Debug模式下程序运行正常,而Release模式下程序崩溃的问题。
Debug和Release模式下,依赖的外部环境有可能不同,造成Debug正常和Release下崩溃。
如果Release下运行正常,而Debug下运行出现异常,很有可能是代码有问题,而Release选择了忽略。
5. 静态编译与动态编译
相关文章
你所不知道的C和C++运行库
https://blog.csdn.net/ithzhang/article/details/20160009
VS2015静态编译设置
https://blog.csdn.net/weixin_39438040/article/details/81010393
GCC编译过程与动态链接库和静态链接库
https://www.cnblogs.com/king-lps/p/7757919.html
MSVC 与 CRT 之间的恩怨情仇
https://blog.csdn.net/zxh2075/article/details/16939193
设置静态编译后,对于我们程序使用到的依赖库都会去搜索其静态链接库,完成静态链接。
静态编译会在链接库中所需的指令嵌入到执行程序中,程序运行时,就不需要附带对应的链接库。如果是动态编译,那么在运行时,则可能需要附带上所链接的相关依赖库。
所以静态链接可以使我们的程序减少依赖库的附加。但是相应的,编译出来的文件体积会大一些。
5.1 VS设置静态编译
EGE安装包内的库不支持静态编译,即下面提到的VS运行库 /MT,选择将会编译报错。
进入项目属性。
然后左边 配置属性–> C/C++ -->代码生成 页面,运行库选择 多线程MT
下面是对应关系:
选项 | 链接方式 | 编译模式 |
---|---|---|
多线程Dll (/MD) | 动态 | Release |
多线程调试Dll (/MDd) | 动态 | Debug |
多线程(/MT) | 静态 | Release |
多线程(/MTd) | 静态 | Debug |
5.2 CodeBlocks
点击工具栏Project --> Build options…,进入到构建选项。
勾选 static 相关的选项,列表中有三个选项。这是使库以静态库方式链接。
5.3 DevC++
进入 工具–>编译选项。
加入 -static,或者三个选项全加。
-static -static-libstdc++ -static-libgcc
二、程序打包及发布
1. 代码检查、代码优化与运行调试
将程序打包发布前,最好先检查一下代码,进行调试,以确保不会出现严重问题。
可以考虑一下如何优化代码,当然,优化之前做好备份(防止你改错后改不回去,那你就凉了。)
把文件绝对路径改成相对路径
在代码里读取文件使用绝对路径是不允许的,除非这个文件被放在一个固定位置。
因为你不清楚你的程序会被别人放在哪个目录下。这样你程序里写的绝对路径就跟文件的实际位置匹配不上,读取文件就会出现问题。
读取不到问加你,就会出现图片显示不出,音乐无法播放等问题。
2. 设置编译模式为Release模式
Release是用于发布或查看运行结果的模式,程序体积更小,运行速度更快。即使在Debug模式下已经已经完毕,设置Release模式后,仍需要运行测试,避免出现问题。
2.1 设置Release编译模式的方法:
2.1.1 VS2019 设置
2.1.2 Dev-C++设置
2.2 重新编译生成
设置完成后,需要先 重新编译生成,再点击 运行 测试,否则运行的程序仍然是。
因为部分IDE在没有检测到代码更改是,直接点击编译是不会进行编译的,这样还是之前生成的文件。所以需要手动点击重新编译生成来进行重新编译。
2.2.1 Dev-C++
2.2.2 VS 2019
3. 文件打包
当一切已准备就绪,就要开始将文件进行打包了。
主要是将exe和所需的文件一同打包(注意:用到的文件与exe的相对路径,要和代码中写的相对路径一致,否则会查找不到文件。)
3.1 找到exe可执行文件
先找到生成的可执行文件。
编译生成成功后,在生成窗口都会提示生成的exe的文件路径。这时复制一下ege所在的目录,粘贴到文件资源管理器的搜索框里就能找到位置了。
例如:
下面是Dev-C++编译成功后的输出文件的提示,复制文件所在的文件夹路径。
打开文件资源管理器,把刚刚复制的文件夹路径粘贴到地址栏中,按回车键。这时就转到对应目录了,可以看到生成的exe文件。
VS 2019
VS2019显示在输出窗口中。
Dev-C++
编译成功后,输出文件路径显示在编译日志中。如果不显示,那就点击全部重新编译按钮。
Dev-C++的输出文件是在当前路径下,一般就是你源文件所在的目录。
如果你建了项目,那还可以在项目属性中查看。
3.2 找到在IDE运行程序时的当前目录
这个IDE运行程序时当前目录一般是源文件所在的目录。
在建项目的情况下,新建的文件都会默认在当前目录下。
如果不建项目,直接就编译一个单文件运行,那当前目录就是这个源文件所在的目录。
所以一般当前目录就是源文件所在的目录。如果之前你的程序读取过图片文件之类的,那么相信你已经能够确定当前目录在哪。
至于源文件所在的目录,在文件选项卡上右键,选择打开所在的文件夹即可。
VS 2019打开源文件目录
Dev-C++打开源文件目录
3.3 将exe文件 复制到 IDE运行程序时的当前目录(需要外部资源文件情况)
如果程序涉及到读取外部的资源文件的话,就需要复制过来。
现在把生成的exe文件复制过来,为什么呢?因为这样可以使打包时资源文件的相对路径保持一致。
在双击运行exe的情况下,当前目录是exe文件所在的目录,如果IDE运行程序的当前目录和exe所在目录不一致,那运行exe文件时就读取不到文件。
将exe文件复制到 上一步找到的 IDE运行程序时的当前目录。
Dev-C++
Dev-C++的exe文件就直接在当前目录生成,所以就不用动了。
VS 2019
可以看到,exe文件所在目录和 IDE运行程序时的当前目录不一致,所以VS2019得把这个exe文件复制到过来。
3.4 exe文件运行测试
现在在文件夹里 双击exe,运行程序。查看外部资源文件读取是否正常。
- 如果文件读取正常,那说明位置正确了。
- 如果文件读取失败,那么就需要重新确认一下IDE运行程序时的当前目录在哪。可以由代码里的相对路径反推。
3.5 将exe文件连同使用到的其它文件复制到文件夹中一同打包
现在找到exe文件和用到的资源文件,把他们都复制到 一个文件夹里,这样就成功了。
例如,下面是找到exe文件和 外部文件所在的data文件夹和resource文件夹,程序里需要读取的文件都在这两个文件夹里面了。
然后新建一个文件夹,以项目名命名,这些文件复制进去,这样就可以了。
3.6 完成打包
这样文件打包就完成了。接下来还需要进行运行测试,检查缺少的dll文件。
4. 沙盒测试
为什么有这个测试呢?因为要保证你的程序能在未搭建相应开发环境的电脑上也能正常运行。
相关问题:找不到dll,无法继续执行代码
因为部分的程序需要附加某些依赖库才能运行。程序在某个开发环境中编译生成,有时需要依赖一些动态链接库。移动到另一台电脑上启动时,结果这台电脑里没有这些依赖库,导致运行失败。
像下图一样。(这是VS编译出来的程序,实际运行时需要带上VC的运行时库)
如果你之前编译时设置了静态编译,那需要的动态链接库会少一些。
4.1 安装文件搜索工具Everything
这个是搜索文件的神器,电脑上的文件秒搜。
4.1 打开Windows Sandbox (沙盒)
Windows sandbox功能启用方法可以自行搜索教程,这里就不再重复。
4.2 在沙盒中运行程序,补充缺失的依赖库
复制我们打包好的文件到沙盒中,然后运行。
每报出一个依赖库缺少,就在自己电脑中使用Everything搜索相应的依赖库。
如下图,报了一个缺少 VCRUNTIME140.dll的错误。
那么如何找到这个缺少的dll呢
- 可以使用文件搜索工具Everything搜索文件
这个可以搜到,缺点就是不容易确定是哪个dll,需要自己分辨平台,因为不同的平台有不同的dll,但名字是一样的。 - 使用依赖库查看工具
目前我使用的是Dependenics, 可以方便查出依赖库的位置,复制过来即可。
Dependenics是使用在后面下面的 附加:依赖库查看工具 中提到
使用Everything搜索的方法
使用Everything搜索这个库名,可以看到,找到了非常多。因为其它软件运行也需要这个动态链接库,这些软件也这个库打包进去了。
我们根据我们的平台选择相应的库文件,注意看库文件所在的位置,路径中一般带有平台的表示(根据生成是32位还是64位,选x86或x64,而不是arm和arm64)。
然后复制到和exe同一个目录下,再次运行,直到不报缺少dll错误为止。
如果你复制错了不匹配的dll,会报出以下错误,这时你确认一下,找出正确的dll文件,因为用于不同平台的dll也是同样的文件名。
在实际的沙盒测试中,VS2019编译出来的ege程序,实际需要附加vcruntime140.dll和msvcp140.dll这两个依赖库。
而Dev-C++编译出来的程序,需要附加libwinpthread-1.dll依赖库。
解决完缺少动态链接库的问题,直到程序成功运行。
5. 附带依赖库
把在沙盒测试中找出的这些依赖库,和之前的文件一起打包,依赖库放到和exe同一个目录。
6. 发布程序
最后在打包好的文件中再次运行exe文件确认一下运行情况,所有工作就完成了。
这时可以将整个文件夹添加到压缩包中,发送给别人,别人解压后双击里面的exe文件,就可运行程序。
7. 附加内容:依赖库查看工具
下面列出可以查看依赖库的几个工具:
7.1 Dumpbin
这个是VS 中自带的一个命令行工具,可以使用Everything搜索 。
输入一下命令可以查看
dumpbin /DEPENDENTS "exe文件路径"
7.2 Dependenics
Dependenics Github
Dependenics Github 镜像
Visual C++ Redistributable 下载链接
Dependencis需要先安装 Visual C++ Redistributable ,如果安装过VS,那么这个环境之前就已经安装好了。
安装完成后,打开其中的 DependenciesGui.exe
打开后界面如下。
拖入exe文件即可查看依赖库,可以看到,下图中包含的两个跟编译环境有关的链接库。
同时,还可以复制dll路径,不需要自行搜索和确认。
其它类似的工具还有 exeScope、PeExplorer等。
三、程序图标修改
程序图标可以在项目中添加资源文件,编译生成时,就会自动把资源文件添加进可执行文件中。
如果是使用GCC编译器,也可以手动使用命令来编译生成包含图标的可执行文件。
还可以先生成可执行文件,然后用一些特定软件来修改EXE文件图标,这个是通用的方法,但不一定有效。
1. 图标文件格式:ico
图标文件的格式是 ico,而不是常用的jpg, png格式,所以需要先生成ico格式的图标。可以找一些在线网站或者下载一些软件进行转换。
1.1 在线网站
1.2 ico图标生成软件
IcoFx 一款可以生成Icon图标的工具,可以由图片生成,也可以使用画笔绘制。
2. 项目中添加图标
下面介绍在项目中添加图标的方法。
这种实际是添加ico资源文件到程序中,编译时会把ico作为程序图标
2.1 VS
VS是通过添加ico资源文件的方式添加图标。
① 在VS的解决方案资源管理器中,可以看到有个资源文件 。
② 这时我们在资源文件上右键, 选择 “添加” --> “资源”。
③ 选择 Icon, 点击"导入"。
④ 这时找到你要设置的 Icon图标文件,需要为 ico 类型 ,点击 打开。
⑤ 然后VS 就会打开 ico文件,出现Ico图标显示界面。
可以看到有很多尺寸的图标。8位, 32位是颜色占用的位数,越大能表示的颜色越多,64x64, 16x16是图标的分辨率,越大图片越精细。可以查看不同尺寸下的图标显示效果。
⑥ 这时我们会看到解决方案资源管理器中多了一些文件
⑦ 点击 “生成” --> “重新生成解决方案”
⑧ 此时就已经修改成功了, 可以到 exe 所在的目录查看
2.2 CodeBlocks
① 新建文件, 选择加入项目。
② 保存文件,给文件命名,扩展名为 rc, 例如 “icon.rc”, 这时工程目录中就会出现Resouces
③ icon.rc 文件中写入 MAINICON ICON “图标文件名(带路径)”,图标文件一定要是 ico 格式的
,文件名的写法 可以参考 **《文件名 绝对路径与相对路径》**部分。如果你把图标文件放在了源文件旁边,不需要带路径,直接写文件名即可。
④ 想要找到源文件所在的目录可以在文件选项卡中右键选择 “Open containing folder”
⑤ 保存, Build
⑥ 找到编译生成的exe可执行文件。打开源文件所在的目录,有个 bin 文件夹, 里面有Debug 和 Release 文件夹,进去就可以看到生成的可执行文件,具体在哪个目录要看刚才设置的编译模式。
2.3 DevC++
点击 项目(Project)–>项目属性(Project Options), 可以看到有设置Icon图标的地方,Library 是 DevC++ 里面内置的图标库,点击 Browse 可以选择自己的 ico 文件
全部重新编译,重新生成exe文件。
3. 使用软件直接修改EXE文件图标
这种是直接修改EXE文件的,不区分IDE,但对于部分exe文件不成功。
QIcon Changer 可直接修改EXE文件的图标,其它软件可自行查找。
步骤:
打开QIcon Changer,将exe文件拖入左边位置,ico图标拖入右边位置, 点击Applay即可。
4. GCC编译器添加图标
GCC主要是利用其中的 windres.exe 编译资源文件(.rc),生成目标文件(.o) ,再用 gcc.exe 或 g++.exe 将生成的目标文件和源文件一起编译链接,得到可执行文件。
4.1 资源文件的编写
资源文件中添加ico图标, 格式:任意ID ICON "ico图标文件路径"
示例
LOGO ICON "C:/MyImages/logo.ico"
4.2 使用 windres编译资源文件
windres.exe 位于GCC的bin目录下
可以在命令行使用以下命令生成目标文件:windres -i 资源文件路径 -o 目标文件名.o
示例
假设资源文件名为: logo.rc
,位于当前目录下。windres.exe和gcc.exe同在一个目录下,一般环境变量已配置好。
windres -i logo.rc -o logo.o
这样就生成了一个 logo.o
目标文件。
4.4 GCC编译链接
将上面由 资源文件编译出的目标文件和源文件一起编译链接即可。
格式:g++ 目标文件 源文件 其它选项 -o 可执行文件名
示例
假设由资源文件编译出的目标文件名为logo.o
,源文件只有main.cpp
,其它库可以使用-l
链接。
g++ logo.o main.cpp 其它选项 -o app.exe
下面是加上ege要链接的库的GCC编译命令。
g++ logo.o main.cpp -lgraphics64 -luuid -lmsimg32 -lgdi32 -limm32 -lole32 -loleaut32 -lwinmm -lgdiplus -o app.exe
这样就完成了。
5. 生成快捷方式
创建的快捷方式也是一样的图标。
复制快捷方式到桌面,就和正常软件一样打开了。
EGE专栏:EGE专栏