github.com/artpar/rclone@v1.67.3/bin/resource_windows.go (about) 1 // Utility program to generate Rclone-specific Windows resource system object 2 // file (.syso), that can be picked up by a following go build for embedding 3 // version information and icon resources into a rclone binary. 4 // 5 // Run it with "go generate", or "go run" to be able to customize with 6 // command-line flags. Note that this program is intended to be run directly 7 // from its original location in the source tree: Default paths are absolute 8 // within the current source tree, which is convenient because it makes it 9 // oblivious to the working directory, and it gives identical result whether 10 // run by "go generate" or "go run", but it will not make sense if this 11 // program's source is moved out from the source tree. 12 // 13 // Can be used for rclone.exe (default), and other binaries such as 14 // librclone.dll (must be specified with flag -binary). 15 // 16 17 //go:generate go run resource_windows.go 18 //go:build tools 19 20 package main 21 22 import ( 23 "flag" 24 "fmt" 25 "log" 26 "path" 27 "runtime" 28 "strings" 29 30 "github.com/artpar/rclone/fs" 31 "github.com/coreos/go-semver/semver" 32 "github.com/josephspurrier/goversioninfo" 33 ) 34 35 func main() { 36 // Get path of directory containing the current source file to use for absolute path references within the code tree (as described above) 37 projectDir := "" 38 _, sourceFile, _, ok := runtime.Caller(0) 39 if ok { 40 projectDir = path.Dir(path.Dir(sourceFile)) // Root of the current project working directory 41 } 42 43 // Define flags 44 binary := flag.String("binary", "rclone.exe", `The name of the binary to generate resource for, e.g. "rclone.exe" or "librclone.dll"`) 45 arch := flag.String("arch", runtime.GOARCH, `Architecture of resource file, or the target GOARCH, "386", "amd64", "arm", or "arm64"`) 46 version := flag.String("version", fs.Version, "Version number or tag name") 47 icon := flag.String("icon", path.Join(projectDir, "graphics/logo/ico/logo_symbol_color.ico"), "Path to icon file to embed in an .exe binary") 48 dir := flag.String("dir", projectDir, "Path to output directory where to write the resulting system object file (.syso), with a default name according to -arch (resource_windows_<arch>.syso), only considered if not -syso is specified") 49 syso := flag.String("syso", "", "Path to output resource system object file (.syso) to be created/overwritten, ignores -dir") 50 51 // Parse command-line flags 52 flag.Parse() 53 54 // Handle default value for -file which depends on optional -dir and -arch 55 if *syso == "" { 56 // Use default filename, which includes target GOOS (hardcoded "windows") 57 // and GOARCH (from argument -arch) as suffix, to avoid any race conditions, 58 // and also this will be recognized by go build when it is consuming the 59 // .syso file and will only be used for builds with matching os/arch. 60 *syso = path.Join(*dir, fmt.Sprintf("resource_windows_%s.syso", *arch)) 61 } 62 63 // Parse version/tag string argument as a SemVer 64 stringVersion := strings.TrimPrefix(*version, "v") 65 semanticVersion, err := semver.NewVersion(stringVersion) 66 if err != nil { 67 log.Fatalf("Invalid version number: %v", err) 68 } 69 70 // Extract binary extension 71 binaryExt := path.Ext(*binary) 72 73 // Create the version info configuration container 74 vi := &goversioninfo.VersionInfo{} 75 76 // FixedFileInfo 77 vi.FixedFileInfo.FileOS = "040004" // VOS_NT_WINDOWS32 78 if strings.EqualFold(binaryExt, ".exe") { 79 vi.FixedFileInfo.FileType = "01" // VFT_APP 80 } else if strings.EqualFold(binaryExt, ".dll") { 81 vi.FixedFileInfo.FileType = "02" // VFT_DLL 82 } else { 83 log.Fatalf("Specified binary must have extension .exe or .dll") 84 } 85 // FixedFileInfo.FileVersion 86 vi.FixedFileInfo.FileVersion.Major = int(semanticVersion.Major) 87 vi.FixedFileInfo.FileVersion.Minor = int(semanticVersion.Minor) 88 vi.FixedFileInfo.FileVersion.Patch = int(semanticVersion.Patch) 89 vi.FixedFileInfo.FileVersion.Build = 0 90 // FixedFileInfo.ProductVersion 91 vi.FixedFileInfo.ProductVersion.Major = int(semanticVersion.Major) 92 vi.FixedFileInfo.ProductVersion.Minor = int(semanticVersion.Minor) 93 vi.FixedFileInfo.ProductVersion.Patch = int(semanticVersion.Patch) 94 vi.FixedFileInfo.ProductVersion.Build = 0 95 96 // StringFileInfo 97 vi.StringFileInfo.CompanyName = "https://rclone.org" 98 vi.StringFileInfo.ProductName = "Rclone" 99 vi.StringFileInfo.FileDescription = "Rclone" 100 vi.StringFileInfo.InternalName = (*binary)[:len(*binary)-len(binaryExt)] 101 vi.StringFileInfo.OriginalFilename = *binary 102 vi.StringFileInfo.LegalCopyright = "The Rclone Authors" 103 vi.StringFileInfo.FileVersion = stringVersion 104 vi.StringFileInfo.ProductVersion = stringVersion 105 106 // Icon (only relevant for .exe, not .dll) 107 if *icon != "" && strings.EqualFold(binaryExt, ".exe") { 108 vi.IconPath = *icon 109 } 110 111 // Build native structures from the configuration data 112 vi.Build() 113 114 // Write the native structures as binary data to a buffer 115 vi.Walk() 116 117 // Write the binary data buffer to file 118 if err := vi.WriteSyso(*syso, *arch); err != nil { 119 log.Fatalf(`Failed to generate Windows %s resource system object file for %v with path "%v": %v`, *arch, *binary, *syso, err) 120 } 121 }