diff --git a/make.go b/make.go index f5e3647..e435dc3 100755 --- a/make.go +++ b/make.go @@ -57,6 +57,7 @@ func usage() { func main() { goos := flag.String("goos", runtime.GOOS, "Specify target operating system for cross compilation") goarch := flag.String("goarch", runtime.GOARCH, "Specify target architecture for cross compilation") + versionFlag := flag.String("version", "", "Specify version string to inject into binaries") flag.Parse() _ = os.Setenv("GOOS", *goos) @@ -74,9 +75,11 @@ func main() { action = flag.Arg(0) } + ver := resolveVersion(*versionFlag) + switch action { case "all": - buildAll() + buildAll(ver) case "test": testAll() default: @@ -84,19 +87,30 @@ func main() { } } -func buildAll() { +// resolveVersion resolves the build version string from the explicit CLI flag +// (e.g. go run make.go -version 1.8.0), falling back to "dev" for unflagged +// local development builds. +func resolveVersion(flagVersion string) string { + if flagVersion != "" { + return strings.TrimPrefix(flagVersion, "v") // Strip leading "v" so callers can pass git tag (e.g. v1.8.0) directly. + } + return "dev" +} + +func buildAll(ver string) { makeDir(buildOutputDir) goos := os.Getenv("GOOS") goarch := os.Getenv("GOARCH") + ldflags := fmt.Sprintf("-s -w -X main.Version=%s", ver) - fmt.Printf("Building binaries for %s/%s ...\n", goos, goarch) + fmt.Printf("Building binaries for %s/%s (version %s) ...\n", goos, goarch, ver) _ = runCmd("go", "build", "-ldflags", "-s -w", "-o", makeOutputPath(buildOutputDir, "updater"), rootNamespace+"/updater") - _ = runCmd("go", "build", "-ldflags", "-s -w", "-o", makeOutputPath(buildOutputDir, "service"), rootNamespace+"/service") + _ = runCmd("go", "build", "-ldflags", ldflags, "-o", makeOutputPath(buildOutputDir, "service"), rootNamespace+"/service") _ = runCmd("go", "build", "-ldflags", "", "-o", makeOutputPath(buildOutputDir, "jsonsig"), rootNamespace+"/lib/jsonsig/cmd") - _ = runCmd("go", "build", "-tags", "nohttp", "-ldflags", "-s -w", "-o", makeOutputPath(buildOutputDir, "service-no-http"), rootNamespace+"/service") + _ = runCmd("go", "build", "-tags", "nohttp", "-ldflags", ldflags, "-o", makeOutputPath(buildOutputDir, "service-no-http"), rootNamespace+"/service") if goos == "windows" { - _ = runCmd("go", "build", "-tags", "nohttp", "-ldflags", "-s -w -H=windowsgui", "-o", makeOutputPath(buildOutputDir, "service-no-window"), rootNamespace+"/service") + _ = runCmd("go", "build", "-tags", "nohttp", "-ldflags", ldflags+" -H=windowsgui", "-o", makeOutputPath(buildOutputDir, "service-no-window"), rootNamespace+"/service") _ = runCmd("go", "build", "-ldflags", "-s -w -H=windowsgui", "-o", makeOutputPath(buildOutputDir, "updater-no-window"), rootNamespace+"/updater") } diff --git a/service/args.go b/service/args.go index 522ef38..90bf8de 100644 --- a/service/args.go +++ b/service/args.go @@ -29,6 +29,7 @@ var validArgs = []string{ "validate", "run", "command", + "version", } func isArgsValid(args []string) bool { diff --git a/service/main.go b/service/main.go index 88d7109..05085be 100644 --- a/service/main.go +++ b/service/main.go @@ -11,6 +11,7 @@ import ( "os" "path" "path/filepath" + "runtime" "strings" "sync" "time" @@ -42,7 +43,21 @@ func main() { os.Exit(run()) } +// Version represents the build version string, set at build time via -ldflags "-X main.Version=x.y.z". +var Version = "dev" + +func printVersion() { + fmt.Printf("silver version %s %s/%s\n", Version, runtime.GOOS, runtime.GOARCH) +} + func run() (exitCode int) { + // Parse CLI args early to support diagnostic version command without requiring a config file. + action, actionArgs, parseErr := parse(os.Args) + if parseErr == nil && action == "version" { + printVersion() + return 0 + } + err := os.Chdir(exeFolder()) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "ERROR: Unable to set working directory: %v\n", err) @@ -57,9 +72,7 @@ func run() (exitCode int) { _, _ = fmt.Fprintf(os.Stderr, "ERROR: Invalid config - %v\n", err) return 1 } - - action, actionArgs, err := parse(os.Args) - if err != nil { + if parseErr != nil { printUsage(ctx.conf.ServiceDescription.DisplayName, ctx.conf.ServiceDescription.Description) return 1 } @@ -155,7 +168,7 @@ func printUsage(svcDisplayName, svcDesc string) { serviceName()) fmt.Printf("%s\n\n", svcDesc) fmt.Printf("Usage:\n") - fmt.Printf("%s [install|uninstall|start|stop|command|validate|run|help] [command-name]\n", exeName()) + fmt.Printf("%s [install|uninstall|start|stop|command|validate|run|version|help] [command-name]\n", exeName()) fmt.Printf(" install - Install the service.\n") fmt.Printf(" uninstall - Remove/uninstall the service.\n") fmt.Printf(" start - Start an installed service.\n") @@ -163,6 +176,7 @@ func printUsage(svcDisplayName, svcDesc string) { fmt.Printf(" validate - Test the configuration file.\n") fmt.Printf(" run - Run service on in command-line mode.\n") fmt.Printf(" command - Run a command [command-name].\n") + fmt.Printf(" version - Display version and target OS/architecture.\n") fmt.Printf(" help - This usage message.\n") }