用Go在Windows下写了一个.exe
的程序,这个程序默认是不带版本,版权,产品名称以及图标的,因此,这些东西我们要自己去生成。
Go对于程序版本这方面已经有了开源的包,见GitHub - https://github.com/josephspurrier/goversioninfo。
你可以自己在Go的代码中引入这个包,并且在生成.syso
文件,这样子是可以的。
既然提到了.syso
,那么可以推断出,要使得用Go编写的Windows程序具有这些属性信息,.syso
是必须的,至于怎么生成.syso
,那就有很多方法了。
这里只介绍用windres.exe
和.rc
资源文件还有.manifest
来生成这些属性。
windres.exe
Windows下是不带的,我用Everything在我的电脑上搜到的路径如下:
版本的生成
标准的做法是这样子的,a.b.c.d
,前三位是固定不动的,例如1.0.1
,这作为一个大版本,如果修改,需要人手动修改;
后面这一位就有讲究了,由于开发程序时我们都会有版本控制工具,而Git也是用得最多的,因此这最后一位要和Git版本控制挂钩。
而版本号有两个,产品版本号和文件版本号,表现形式又要分两种,一种是直接作为程序的标识,一种是给人看的(这个呈现在属性页上)。给人看的可以随便写,程序的标识可不能随便弄;
而文件版本号修改一次增加一次,产品版本号发布一次增加一次,由于我的程序是.exe
,因此这两个是一样的。
因此我们用两个Git的两个命令来生成版本号:
git rev-list --count HEAD
,获取该分支提交(修改)了多少次git rev-parse --short HEAD
,获取该分支最后一次提交的短哈希号
提交了多少次可以作为最后一位版本号,短哈希号可以附加到最后一位版本号后面,便于我们追踪问题。
因此我们需要一些脚本和一些文件来完成这些工作。
// version_template.h
#pragma once
#define VER_MAJOR 1
#define VER_MINOR 0
#define VER_PATCH 1
这个是前三位的版本号。
// make_version.bat
@ECHO OFF
cd /d %1
if exist %2 del /q %2
for /f "delims=" %%i in ('git rev-list --count HEAD') do (set REVISION=%%i)
for /f "delims=" %%i in ('git rev-parse --short HEAD') do (set REVISION_HASH=%%i)
if "%REVISION%" == "" (
set REVISION=0
)
(echo #define VER_REVISION %REVISION% && echo #define VER_REVISION_HASH %REVISION_HASH%) > %2
执行这个脚本make_version.bat ./ ./version.h
可以生成最后一位版本号和短哈希值。如下:
// version.h
#define VER_REVISION 33
#define VER_REVISION_HASH a883258
注意version.h
是通过脚本生成的,不要添加到版本库中,这属于无用的文件(因为可以生成啊)。
举个例子,最后的版本号应该是这个样子的:1.0.1.33
以及1.0.1.33.a883258
.manifest
这个东西我对它的了解只限于添加启动权限,因此这里也用它添加启动时需要管理员权限。
// FlushHip.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
.rc
这个是重点,通过.rc
文件把版权,版本,名称这些属性描述信息写进去。下面就提供一个模板。大家可以对应着地方进行修改
// FlushHip.rc
#define RT_MANIFEST 24
#include "version.h"
#include "version_template.h"
#define MAKEVER_S(a,b,c,d) a,b,c,d
#define MAKEVER(a,b,c,d,e) a.b.c.d.e
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
1 VERSIONINFO
PRODUCTVERSION MAKEVER_S(VER_MAJOR, VER_MINOR, VER_PATCH, VER_REVISION)
FILEVERSION MAKEVER_S(VER_MAJOR, VER_MINOR, VER_PATCH, VER_REVISION)
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0"
BEGIN
VALUE "CompanyName", "blog.csdn.net/FlushHip"
VALUE "FileDescription", "FlushHip"
VALUE "FileVersion", TOSTRING(MAKEVER(VER_MAJOR, VER_MINOR, VER_PATCH, VER_REVISION, VER_REVISION_HASH))
VALUE "InternalName", "FlushHip"
VALUE "LegalCopyright", "Copyright (C) 2018. FlushHip. All Rights Reserved."
VALUE "OriginalFilename", "FlushHip.exe"
VALUE "ProductName", "FlushHip"
VALUE "ProductVersion", TOSTRING(MAKEVER(VER_MAJOR, VER_MINOR, VER_PATCH, VER_REVISION, VER_REVISION_HASH))
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 0x04B0
END
END
1 ICON "FlushHip.ico"
1 RT_MANIFEST "FlushHip.manifest"
1 VERSIONINFO
PRODUCTVERSION MAKEVER_S(VER_MAJOR, VER_MINOR, VER_PATCH, VER_REVISION)
FILEVERSION MAKEVER_S(VER_MAJOR, VER_MINOR, VER_PATCH, VER_REVISION)
上面这三行代码是程序的表示,一定要不能错;
下面的描述信息可以随意,在属性页中呈现的就是这些东西;
1 RT_MANIFEST "FlushHip.manifest"
这个是加权限。
图标
1 ICON "FlushHip.ico"
只能用.ico
格式的图标
生成.syso
文件
我们写的上面的所有东西,最终的目的都是生成.syso
文件,因此可以这么做:
cd "%~dp0"
call make_version.bat ./ version.h
cd "%~dp0"
windres.exe -i FlushHip.rc -o FlushHip.syso
call go build -ldflags "-H windowsgui"
写的是后台程序,不希望弹出控制台,因此加上-ldflags "-H windowsgui"
。
这样子就可以在项目FlushHip
下生成一个FlushHip.exe
的文件,我们打开属性页看看
成功。