diff --git a/builder.go b/builder.go index 5e6f23c..40eec93 100644 --- a/builder.go +++ b/builder.go @@ -15,6 +15,7 @@ package xcaddy import ( + "bytes" "context" "fmt" "log" @@ -93,6 +94,25 @@ func (b Builder) Build(ctx context.Context, outputFile string) error { } defer buildEnv.Close() + // generating windows resources for embedding + if b.OS == "windows" { + // get version string, we need to parse the output to get the exact version instead tag, branch or commit + cmd := buildEnv.newGoBuildCommand(ctx, "list", "-m", buildEnv.caddyModulePath) + var buffer bytes.Buffer + cmd.Stdout = &buffer + err = buildEnv.runCommand(ctx, cmd) + if err != nil { + return err + } + + // output looks like: github.com/caddyserver/caddy/v2 v2.7.6 + version := strings.TrimSpace(strings.TrimPrefix(buffer.String(), buildEnv.caddyModulePath)) + err = utils.WindowsResource(version, outputFile, buildEnv.tempFolder) + if err != nil { + return err + } + } + if b.SkipBuild { log.Printf("[INFO] Skipping build as requested") diff --git a/go.mod b/go.mod index 4d94301..9925154 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,9 @@ module github.com/caddyserver/xcaddy -go 1.14 +go 1.16 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 + github.com/josephspurrier/goversioninfo v1.4.0 ) diff --git a/go.sum b/go.sum index aab87c3..a3d7699 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,19 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/akavel/rsrc v0.10.2 h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw= +github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/josephspurrier/goversioninfo v1.4.0 h1:Puhl12NSHUSALHSuzYwPYQkqa2E1+7SrtAPJorKK0C8= +github.com/josephspurrier/goversioninfo v1.4.0/go.mod h1:JWzv5rKQr+MmW+LvM412ToT/IkYDZjaclF2pKDss8IY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/utils/resource.go b/internal/utils/resource.go new file mode 100644 index 0000000..e3a9b5f --- /dev/null +++ b/internal/utils/resource.go @@ -0,0 +1,86 @@ +package utils + +import ( + "embed" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/Masterminds/semver/v3" + "github.com/josephspurrier/goversioninfo" +) + +//go:embed resources/* +var embedFS embed.FS + +// WindowsResource create a Windows resource system object +// for embedding into the Caddy binary. +// reference: https://github.com/rclone/rclone/blob/v1.66.0/bin/resource_windows.go +func WindowsResource(version, outputFile, tempDir string) error { + vi := &goversioninfo.VersionInfo{} + + // FixedFileInfo + vi.FixedFileInfo.FileOS = "040004" // VOS_NT_WINDOWS32 + vi.FixedFileInfo.FileType = "01" // VFT_APP + + semanticVersion, err := semver.NewVersion(version) + if err != nil { + return err + } + + basename := filepath.Base(outputFile) + ext := filepath.Ext(basename) + + // FixedFileInfo.FileVersion + vi.FixedFileInfo.FileVersion.Major = int(semanticVersion.Major()) + vi.FixedFileInfo.FileVersion.Minor = int(semanticVersion.Minor()) + vi.FixedFileInfo.FileVersion.Patch = int(semanticVersion.Patch()) + vi.FixedFileInfo.FileVersion.Build = 0 + // FixedFileInfo.ProductVersion + vi.FixedFileInfo.ProductVersion.Major = int(semanticVersion.Major()) + vi.FixedFileInfo.ProductVersion.Minor = int(semanticVersion.Minor()) + vi.FixedFileInfo.ProductVersion.Patch = int(semanticVersion.Patch()) + vi.FixedFileInfo.ProductVersion.Build = 0 + + // StringFileInfo + vi.StringFileInfo.CompanyName = "https://caddyserver.com/" + vi.StringFileInfo.ProductName = "Caddy" + vi.StringFileInfo.FileDescription = "Caddy" + vi.StringFileInfo.InternalName = strings.TrimSuffix(basename, ext) + vi.StringFileInfo.OriginalFilename = basename + vi.StringFileInfo.LegalCopyright = "The Caddy Authors" + vi.StringFileInfo.FileVersion = semanticVersion.String() + vi.StringFileInfo.ProductVersion = semanticVersion.String() + + // extract ico file from embed to an actual file + ico, err := embedFS.ReadFile("resources/ico/caddy.ico") + if err != nil { + return err + } + icoCopy, err := os.Create(filepath.Join(tempDir, "caddy.ico")) + if err != nil { + return err + } + // set ico path + vi.IconPath = icoCopy.Name() + _, err = icoCopy.Write(ico) + if err != nil { + return err + } + err = icoCopy.Close() + if err != nil { + return err + } + + // Build native structures from the configuration data + vi.Build() + + // Write the native structures as binary data to a buffer + vi.Walk() + + arch := GetGOARCH() + + // Write the binary data buffer to file + return vi.WriteSyso(filepath.Join(tempDir, fmt.Sprintf("resource_windows_%s.syso", arch)), arch) +} diff --git a/internal/utils/resources/ico/caddy-bg.ico b/internal/utils/resources/ico/caddy-bg.ico new file mode 100644 index 0000000..6e5fd66 Binary files /dev/null and b/internal/utils/resources/ico/caddy-bg.ico differ diff --git a/internal/utils/resources/ico/caddy.ico b/internal/utils/resources/ico/caddy.ico new file mode 100644 index 0000000..1b9f6a2 Binary files /dev/null and b/internal/utils/resources/ico/caddy.ico differ