• 在Linux中快速编译带图标的windows程序


    一. 引言

    以前做的一个项目有个需求, 需要在Linux系统上的服务后端根据前端配置动态编译出能在Windows平台运行的程序, 并且能支持程序带图标, 虽然使用Go语言能够方便的编译跨平台运行的代码, 但编译带资源图标的Windows可执行程序还未尝试过, 本篇文章对这部分内容做一个实践尝试。

    二. 准备工作

    如果要单独完成这项任务, 需要准备以下几样"配菜":

    1.rsrc程序, 开源项目, 地址: https://github.com/akavel/rsrc

    2.一份模拟在Windows平台运行的源码, 当被自动编译后, 能看到运行效果。

    3.一份图标文件, 文件后缀为.ico。

    4.一份模拟服务后端功能的程序, 该程序负责编译出最终带图标的Windows程序。

    下面将依次介绍这四样"配菜"的调制方法:

    2.1 rsrc程序

    rsrc程序是一个开源专门负责将ico资源文件写入Windows PE可执行程序的工具, 该工具使用Go语言开发, 能够支持将rsrc代码编译成支持不同平台的可执行程序, 支持的系统包括: Darwin、Linux(amd64)、Windows(386)、Windows(amd64)。

    rsrc程序的参数在实际使用过程中主要有三个:

    1.-arch 该参数将指定嵌入资源后的程序运行的CPU架构, 为了向下同时兼容32位和64位系统, 这里一般设置的参数为:"-arch 386"。

    2.-ico 该参数执行传入的图标文件保存的全路径。

    3.-o 该参数是一个输出参数, 将输出一个.res或者.syso的资源文件, 如果不指定资源文件的名字, rsrc将默认输出一个名为:rsrc_windows_{arch}.syso的文件, 在我们实际应用中, 将输出格式为: .syso的文件。

    2.2 模拟Windows程序

    模拟Windows程序, 这里为了能看到运行的实际效果, 将在Go代码中嵌入Windows的对话框元素, 双击执行后将弹出一个对话框, 表示程序运行成功。以下是模拟Windows程序的Go源码:

    1. package main
    2. import (
    3.   "syscall"
    4.   "unsafe"
    5. )
    6. var (
    7.   user32, _     = syscall.LoadLibrary("user32.dll")
    8.   messageBox, _ = syscall.GetProcAddress(user32, "MessageBoxW")
    9. )
    10. func IntPtr(n int) uintptr {
    11.   return uintptr(n)
    12. }
    13. func StrPtr(s string) uintptr {
    14.   return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s)))
    15. }
    16. func ShowMessage(title, text string) {
    17.   user32 := syscall.NewLazyDLL("user32.dll")
    18.   MessageBoxW := user32.NewProc("MessageBoxW")
    19.   MessageBoxW.Call(IntPtr(0), StrPtr(text), StrPtr(title), IntPtr(0))
    20. }
    21. func main() {
    22.   defer syscall.FreeLibrary(user32)
    23.   ShowMessage("成功消息!", "Hello!")
    24. }
    这段代码运行成功后, 将弹出一个成功的对话框。

    2.3 图标文件

    图标文件准备标准的ico格式文件即可, 以下是我的图标文件:

    2.4 模拟服务后端程序

    模拟服务后端程序主要负责利用rsrc将资源文件编译成.syso格式,并利用go build完成最终的二进程程序编译, 完整代码如下:`

    1. package main
    2. import (
    3. "fmt"
    4. "os/exec"
    5. )
    6. const (
    7. hIconPath     = "/home/gocompile/icon/Folder.ico" // 图标文件路径
    8. ProgramName   = "gocompile"                       // 编译完成最终程序名称
    9. compileOutput = "./output/gocompile.exe"         // 编译之后最终的输出目录
    10. )
    11. func CompileProgram() {
    12. cmd := "./rsrc -arch 386 -ico " + hIconPath + " -o " + ProgramName + ".syso" + " && " +
    13. "CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -o " + compileOutput
    14. _, err := exec.Command("bash", "-c", cmd).Output()
    15. if err != nil {
    16. fmt.Println(err.Error())
    17. return
    18. }
    19. }
    20. func main() {
    21. CompileProgram()
    22. }

    利用以下命令将模拟服务后端程序编译成能在Linux系统上运行的程序:

    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o gocontrol

    将编译完成的gocontrol程序上传到Linux服务器, 准备完成最终的跨平台程序编译。

    三. 交叉编译

    在Linux服务器上建立工作目录:/home/gocompile, 在目录下新建code和icon两个目录, 将本地的所有图标文件上传到icon文件夹下;将

    编译完成的gocontrol、模拟Windows程序源码、rsrc程序上传到code 目录下, 如图:

    编辑/etc/profile, 在最后加上路径:export PATH=$PATH:/home/gocompile/code,如图 :

    执行: source /etc/profile

    进入code目录, 给予gocontrol和rsrc可执行权限, ./gocontrol运行程序, 如果没有错误产生,将在output目录中生成名为gocompile.exe程序,如图:

    四. 结果验证

    将output中的gocompile.exe程序拷贝到WIndows系统上,可以看到已经生成了带图标的程序,如图:

    双击执行该程序, 可以看到已经执行成功:

    五. 总结

    这里主要利用了rsrc开源库将图标资源写入可执行程序, 利用Go语言的跨平台特性方便的在Linux系统上生成了在WIndows系统中执行的程序。

  • 相关阅读:
    ​P1102 A-B 数对 【双指针(尺取法)】​
    动态数据模型分析与应用
    java计算机毕业设计校园二手交易系统源码+系统+mysql数据库+lw文档+部署
    TCP三次握手和四次挥手以及TCP的11个状态
    ClickHouse—入门
    HTML+CSS+JS鲜花商城网页设计期末课程大作业 web前端开发技术 web课程设计 网页规划与设计
    Sylvester矩阵、子结式、辗转相除法的三者关系(第二部分)
    mysql文档--myisam存储引擎--myisam引擎全解--底层探索
    如何实现人机界面与多台plc之间无线通讯?
    LeetCode 1758. 生成交替二进制字符串的最少操作数
  • 原文地址:https://blog.csdn.net/suntiger/article/details/132632558