0
点赞
收藏
分享

微信扫一扫

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

1. 摘要

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

2. 准备工作

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

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源码:

package main

import (
    "syscall"
    "unsafe"
)

var (
    user32, _     = syscall.LoadLibrary("user32.dll")
    messageBox, _ = syscall.GetProcAddress(user32, "MessageBoxW")
)

func IntPtr(n int) uintptr {
    return uintptr(n)
}

func StrPtr(s string) uintptr {
    return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s)))
}

func ShowMessage(title, text string) {
    user32 := syscall.NewLazyDLL("user32.dll")
    MessageBoxW := user32.NewProc("MessageBoxW")
    MessageBoxW.Call(IntPtr(0), StrPtr(text), StrPtr(title), IntPtr(0))
}

func main() {
    defer syscall.FreeLibrary(user32)
    ShowMessage("成功消息!", "Hello!")
}

这段代码运行成功后, 将弹出一个成功的对话框。

2.3 图标文件

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

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

2.4 模拟服务后端程序

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

package main

import (
	"fmt"
	"os/exec"
)

const (
	hIconPath     = "/home/gocompile/icon/Folder.ico" // 图标文件路径
	ProgramName   = "gocompile"                       // 编译完成最终程序名称
	compileOutput = "./output/gocompile.exe"          // 编译之后最终的输出目录
)

func CompileProgram() {
	cmd := "./rsrc -arch 386 -ico " + hIconPath + " -o " + ProgramName + ".syso" + " && " +
		"CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -o " + compileOutput
	_, err := exec.Command("bash", "-c", cmd).Output()
	if err != nil {
		fmt.Println(err.Error())
		return
	}
}

func main() {
	CompileProgram()
}

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

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

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

3. 交叉编译

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

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

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

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

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

执行: source /etc/profile

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

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

4. 结果验证

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

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

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

在Linux中快速编译出带图标的windows程序_跨平台编译_06

举报

相关推荐

0 条评论