added version package

Makefile now sets the version string for the project. the version
package tries to set a meaningful version string if the project is not
built with the Makefile

added VERSION command
This commit is contained in:
JetSetIlly 2023-11-08 16:04:56 +00:00
parent 9b2359890c
commit b48d487643
8 changed files with 187 additions and 23 deletions

View file

@ -1,9 +1,14 @@
version = v0.27.0 pre-release
goBinary = go
gcflags = '-c 3 -B -wb=false'
gcflags = -c 3 -B -wb=false
ldflags = -s -w
ldflags_version = $(ldflags) -X 'github.com/jetsetilly/gopher2600/version.number=$(version)'
profilingRom = /home/steve/Desktop/2600_dev/zackattack/waterbed-bouncers-2600/source/bouncers.bin
### support targets
.PHONY: all clean tidy generate check_git check_glsl glsl_validate check_pandoc readme_spell
all:
@ -62,48 +67,50 @@ race_debug: generate test
### profiling targets
.PHONY: profile profile_cpu profile_cpu_play profile_cpu_debug profile_mem_play profile_mem_debug profile_trace
ldflags_profile= $(ldflags) -X 'github.com/jetsetilly/gopher2600/version.number=profiling'
profile:
@echo use make targets profile_cpu, profile_mem, etc.
profile_cpu: generate test
@$(goBinary) build -gcflags $(gcflags)
@$(goBinary) build -gcflags "$(gcflags)" -ldflags "$(ldflags_profile)"
@echo "performance mode running for 20s"
@./gopher2600 performance -profile=cpu -duration=20s $(profilingRom)
@$(goBinary) tool pprof -http : ./gopher2600 performance_cpu.profile
profile_cpu_play: generate test
@$(goBinary) build -gcflags $(gcflags)
@$(goBinary) build -gcflags "$(gcflags)" -ldflags "$(ldflags_profile)"
@echo "use window close button to end (CTRL-C will quit the Makefile script)"
@./gopher2600 play -profile=cpu -elf=none $(profilingRom)
@$(goBinary) tool pprof -http : ./gopher2600 play_cpu.profile
profile_cpu_debug : generate test
@$(goBinary) build -gcflags $(gcflags)
@$(goBinary) build -gcflags "$(gcflags)" -ldflags "$(ldflags_profile)"
@echo "use window close button to end (CTRL-C will quit the Makefile script)"
@./gopher2600 debug -profile=cpu -elf=none $(profilingRom)
@$(goBinary) tool pprof -http : ./gopher2600 debugger_cpu.profile
profile_mem_play : generate test
@$(goBinary) build -gcflags $(gcflags)
@$(goBinary) build -gcflags "$(gcflags)" -ldflags "$(ldflags_profile)"
@echo "use window close button to end (CTRL-C will quit the Makefile script)"
@./gopher2600 play -profile=mem -elf=none $(profilingRom)
@$(goBinary) tool pprof -http : ./gopher2600 play_mem.profile
profile_mem_debug : generate test
@$(goBinary) build -gcflags $(gcflags)
@$(goBinary) build -gcflags "$(gcflags)" -ldflags "$(ldflags_profile)"
@echo "use window close button to end (CTRL-C will quit the Makefile script)"
@./gopher2600 debug -profile=mem -elf=none $(profilingRom)
@$(goBinary) tool pprof -http : ./gopher2600 debugger_mem.profile
profile_trace: generate test
@$(goBinary) build -gcflags $(gcflags)
@$(goBinary) build -gcflags "$(gcflags)" -ldflags "$(ldflags_profile)"
@echo "performance mode running for 20s"
@./gopher2600 performance -profile=trace -duration=20s $(profilingRom)
@$(goBinary) tool trace -http : performance_trace.profile
### binary building targets for host platform
.PHONY: fontrendering build release
.PHONY: fontrendering build
# whether or not we build with freetype font rendering depends on the platform.
# for now freetype doesn't seem to work on MacOS with an M2 CPU
@ -114,15 +121,24 @@ fontrendering=imguifreetype
endif
build: fontrendering generate
$(goBinary) build -pgo=auto -gcflags $(gcflags) -trimpath -tags="$(fontrendering)"
$(goBinary) build -pgo=auto -gcflags "$(gcflags)" -trimpath -ldflags "$(ldflags_version)" -tags="$(fontrendering)"
release: fontrendering generate
$(goBinary) build -pgo=auto -gcflags $(gcflags) -trimpath -ldflags="-s -w" -tags="$(fontrendering) release"
### release building
.PHONY: version_check release
version_check :
ifndef version
$(error version is undefined)
endif
release: version_check fontrendering generate
$(goBinary) build -pgo=auto -gcflags "$(gcflags)" -trimpath -ldflags "$(ldflags_version)" -tags="$(fontrendering) release"
mv gopher2600 gopher2600_$(shell go env GOHOSTOS)_$(shell go env GOHOSTARCH)
### cross compilation for windows (tested when cross compiling from Linux)
.PHONY: check_rscr windows_manifest cross_windows cross_windows_development cross_winconsole_development
.PHONY: check_rscr windows_manifest cross_windows_release cross_windows_development cross_winconsole_development
check_rscr:
ifeq (, $(shell which rsrc))
@ -132,14 +148,17 @@ endif
windows_manifest: check_rscr
rsrc -ico .resources/256x256.ico,.resources/48x48.ico,.resources/32x32.ico,.resources/16x16.ico
cross_windows: generate windows_manifest
CGO_ENABLED="1" CC="/usr/bin/x86_64-w64-mingw32-gcc" CXX="/usr/bin/x86_64-w64-mingw32-g++" GOOS="windows" GOARCH="amd64" CGO_LDFLAGS="-static -static-libgcc -static-libstdc++ -L/usr/local/x86_64-w64-mingw32/lib" $(goBinary) build -pgo=auto -tags "static imguifreetype release" -gcflags $(gcflags) -trimpath -ldflags "-s -w -H=windowsgui" -o gopher2600_windows_amd64.exe .
cross_windows_release: version_check windows_manifest generate
CGO_ENABLED="1" CC="/usr/bin/x86_64-w64-mingw32-gcc" CXX="/usr/bin/x86_64-w64-mingw32-g++" GOOS="windows" GOARCH="amd64" CGO_LDFLAGS="-static -static-libgcc -static-libstdc++ -L/usr/local/x86_64-w64-mingw32/lib" $(goBinary) build -pgo=auto -tags "static imguifreetype release" -gcflags "$(gcflags)" -trimpath -ldflags "$(ldflags_version) -H=windowsgui" -o gopher2600_windows_amd64.exe .
rm rsrc_windows_amd64.syso
cross_windows_development: generate windows_manifest
CGO_ENABLED="1" CC="/usr/bin/x86_64-w64-mingw32-gcc" CXX="/usr/bin/x86_64-w64-mingw32-g++" GOOS="windows" GOARCH="amd64" CGO_LDFLAGS="-static -static-libgcc -static-libstdc++ -L/usr/local/x86_64-w64-mingw32/lib" $(goBinary) build -pgo=auto -tags "static imguifreetype release" -gcflags $(gcflags) -trimpath -ldflags "-s -w -H=windowsgui" -o gopher2600_windows_amd64_$(shell git rev-parse --short HEAD).exe .
# intentionally using ldflags and not ldflags for
# cross_windows_development and cross_winconsole_development
cross_windows_development: windows_manifest generate
CGO_ENABLED="1" CC="/usr/bin/x86_64-w64-mingw32-gcc" CXX="/usr/bin/x86_64-w64-mingw32-g++" GOOS="windows" GOARCH="amd64" CGO_LDFLAGS="-static -static-libgcc -static-libstdc++ -L/usr/local/x86_64-w64-mingw32/lib" $(goBinary) build -pgo=auto -tags "static imguifreetype release" -gcflags "$(gcflags)" -trimpath -ldflags "$(ldflags_version) -H=windowsgui" -o gopher2600_windows_amd64_$(shell git rev-parse --short HEAD).exe .
rm rsrc_windows_amd64.syso
cross_winconsole_development: generate windows_manifest
CGO_ENABLED="1" CC="/usr/bin/x86_64-w64-mingw32-gcc" CXX="/usr/bin/x86_64-w64-mingw32-g++" GOOS="windows" GOARCH="amd64" CGO_LDFLAGS="-static -static-libgcc -static-libstdc++ -L/usr/local/x86_64-w64-mingw32/lib" $(goBinary) build -pgo=auto -tags "static imguifreetype release" -gcflags $(gcflags) -trimpath -ldflags "-s -w -H=windows" -o gopher2600_winconsole_amd64_$(shell git rev-parse --short HEAD).exe .
cross_winconsole_development: windows_manifest generate
CGO_ENABLED="1" CC="/usr/bin/x86_64-w64-mingw32-gcc" CXX="/usr/bin/x86_64-w64-mingw32-g++" GOOS="windows" GOARCH="amd64" CGO_LDFLAGS="-static -static-libgcc -static-libstdc++ -L/usr/local/x86_64-w64-mingw32/lib" $(goBinary) build -pgo=auto -tags "static imguifreetype release" -gcflags "$(gcflags)" -trimpath -ldflags "$(ldflags_version) -H=windows" -o gopher2600_winconsole_amd64_$(shell git rev-parse --short HEAD).exe .
rm rsrc_windows_amd64.syso

View file

@ -51,6 +51,7 @@ import (
"github.com/jetsetilly/gopher2600/hardware/television/coords"
"github.com/jetsetilly/gopher2600/logger"
"github.com/jetsetilly/gopher2600/patch"
"github.com/jetsetilly/gopher2600/version"
)
var debuggerCommands *commandline.Commands
@ -2050,6 +2051,7 @@ func (dbg *Debugger) processTokens(tokens *commandline.Tokens) error {
case cmdLog:
option, ok := tokens.Get()
if ok {
option = strings.ToUpper(option)
switch option {
case "LAST":
s := &strings.Builder{}
@ -2084,6 +2086,18 @@ func (dbg *Debugger) processTokens(tokens *commandline.Tokens) error {
s.WriteString(fmt.Sprintf(" NumGC = %v", m.NumGC))
dbg.printLine(terminal.StyleLog, s.String())
case cmdVersion:
dbg.printLine(terminal.StyleLog, version.Version)
option, ok := tokens.Get()
if ok {
option = strings.ToUpper(option)
switch option {
case "REVISION":
dbg.printLine(terminal.StyleLog, version.Revision)
}
}
}
return nil

View file

@ -521,4 +521,7 @@ The ONTRACE command can be used to supplement the TRACE output with contextual i
Note that while "ONSTEP LOG LAST" is a valid construct it may not print what you expect - it will always print the last
log entry after every step, even if the last log entry is not new. "ONSTEP LOG LAST; LOG CLEAR" is maybe more intuitive
but with the maybe unwanted side effect of clearing the log.`,
cmdMemUsage: "Print memory usage information",
cmdVersion: "Print version information for the emulator",
}

View file

@ -77,6 +77,7 @@ const (
// meta.
cmdLog = "LOG"
cmdMemUsage = "MEMUSAGE"
cmdVersion = "VERSION"
)
const cmdHelp = "HELP"
@ -143,6 +144,7 @@ var commandTemplate = []string{
// emulation
cmdLog + " (LAST|RECENT|CLEAR)",
cmdMemUsage,
cmdVersion + " (REVISION)",
}
// list of commands that should not be executed when recording/playing scripts.

View file

@ -42,6 +42,7 @@ import (
"github.com/jetsetilly/gopher2600/recorder"
"github.com/jetsetilly/gopher2600/regression"
"github.com/jetsetilly/gopher2600/resources"
"github.com/jetsetilly/gopher2600/version"
)
// communication between the main goroutine and the launch goroutine.
@ -220,7 +221,7 @@ func launch(sync *mainSync) {
md := &modalflag.Modes{Output: os.Stdout}
md.NewArgs(os.Args[1:])
md.NewMode()
md.AddSubModes("RUN", "PLAY", "DEBUG", "DISASM", "PERFORMANCE", "REGRESS")
md.AddSubModes("RUN", "PLAY", "DEBUG", "DISASM", "PERFORMANCE", "REGRESS", "VERSION")
p, err := md.Parse()
switch p {
@ -252,6 +253,9 @@ func launch(sync *mainSync) {
case "REGRESS":
err = regress(md, sync)
case "VERSION":
err = showVersion(md)
}
if err != nil {
@ -803,6 +807,25 @@ with the LOG mode. Note that asking for log output will suppress regression prog
return nil
}
func showVersion(md *modalflag.Modes) error {
md.NewMode()
revision := md.AddBool("revision", false,
"display revision information from version control system (if available)")
p, err := md.Parse()
if err != nil || p != modalflag.ParseContinue {
return err
}
fmt.Println(version.Version)
if *revision {
fmt.Println(version.Revision)
}
return nil
}
// nopWriter is an empty writer.
type nopWriter struct{}

View file

@ -23,6 +23,7 @@ import (
"github.com/inkyblackness/imgui-go/v4"
"github.com/jetsetilly/gopher2600/logger"
"github.com/jetsetilly/gopher2600/version"
"github.com/veandco/go-sdl2/sdl"
)
@ -126,9 +127,9 @@ func newPlatform(img *SdlImgui) (*platform, error) {
profile_s = " ES"
}
var version sdl.Version
sdl.VERSION(&version)
logger.Logf("sdl", "version %d.%d.%d", version.Major, version.Minor, version.Patch)
var sdlVersion sdl.Version
sdl.VERSION(&sdlVersion)
logger.Logf("sdl", "version %d.%d.%d", sdlVersion.Major, sdlVersion.Minor, sdlVersion.Patch)
logger.Logf("sdl", "using GL version %d.%d%s", major, minor, profile_s)
plt := &platform{
@ -145,7 +146,7 @@ func newPlatform(img *SdlImgui) (*platform, error) {
// map sdl key codes to imgui codes
plt.setKeyMapping()
plt.window, err = sdl.CreateWindow(windowTitle,
plt.window, err = sdl.CreateWindow(fmt.Sprintf("%s (%s)", windowTitle, version.Version),
sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
int32(float32(plt.mode.W)*0.80), int32(float32(plt.mode.H)*0.80),
sdl.WINDOW_OPENGL|sdl.WINDOW_ALLOW_HIGHDPI|sdl.WINDOW_RESIZABLE|sdl.WINDOW_HIDDEN|sdl.WINDOW_FOREIGN)

18
version/doc.go Normal file
View file

@ -0,0 +1,18 @@
// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
// Package version provides a version string that can be used to indicate the
// version number of the project.
package version

84
version/version.go Normal file
View file

@ -0,0 +1,84 @@
// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
package version
import (
"fmt"
"runtime/debug"
)
// if number is empty then the project was probably not built using the makefile
var number string
// Version contains a the current version number of the project
//
// If the version string is "development" then it means that the project has
// been manually built (ie. not with the makefile). However, there is git
// information and so can be discerned to be part of the development process
//
// If the version string is "unknown" then it means that there is no no version
// number and no git information. This can happen when compiling/running with
// "go run ."
var Version string
// Revision contains the git revision hash. If the source has been modified but
// has not been committed then the Revision string will be suffixed with
// "[modified]"
var Revision string
func init() {
var vcs bool
var revision string
var modified bool
info, ok := debug.ReadBuildInfo()
if ok {
for _, v := range info.Settings {
switch v.Key {
case "vcs":
vcs = true
case "vcs.revision":
revision = v.Value
case "vcs.modified":
switch v.Value {
case "true":
modified = true
default:
modified = false
}
}
}
}
if revision == "" {
Revision = "no revision information"
} else {
Revision = revision
if modified {
Revision = fmt.Sprintf("%s [modified]", Revision)
}
}
if number == "" {
if vcs {
Version = "development"
} else {
Version = "unknown"
}
} else {
Version = number
}
}