Added windows installer
This commit is contained in:
parent
9621a23c79
commit
e19c9509d3
BIN
dist/livetrace-3.3.2-setup.exe
vendored
Normal file
BIN
dist/livetrace-3.3.2-setup.exe
vendored
Normal file
Binary file not shown.
30
installer/Dockerfile.installer
Normal file
30
installer/Dockerfile.installer
Normal file
@ -0,0 +1,30 @@
|
||||
# Dockerfile.installer
|
||||
# Builds the livetrace Windows installer (.exe) using NSIS on Linux.
|
||||
#
|
||||
# Usage (from your project root):
|
||||
# docker build -f Dockerfile.installer -t livetrace-installer .
|
||||
# docker run --rm -v "$PWD/dist":/out livetrace-installer
|
||||
#
|
||||
# The finished installer lands at ./dist/livetrace-3.3.2-setup.exe
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
# Install NSIS (makensis) — no Go needed, binary is pre-built
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends nsis && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Copy the NSIS script and helper
|
||||
COPY installer/livetrace-installer.nsi .
|
||||
COPY installer/EnvVarUpdate.nsh .
|
||||
|
||||
# Copy the pre-built Windows binary from dist/
|
||||
COPY dist/livetrace-windows-amd64.exe .
|
||||
|
||||
# Build the installer
|
||||
RUN makensis livetrace-installer.nsi
|
||||
|
||||
# Default: copy the output to /out (bind-mount your dist/ folder there)
|
||||
CMD ["sh", "-c", "cp livetrace-*.exe /out/ && echo 'Installer written to /out/'"]
|
||||
142
installer/EnvVarUpdate.nsh
Normal file
142
installer/EnvVarUpdate.nsh
Normal file
@ -0,0 +1,142 @@
|
||||
; EnvVarUpdate.nsh
|
||||
; Adds/removes a value from a Windows environment variable (PATH-style, semicolon-delimited)
|
||||
; Usage:
|
||||
; ${EnvVarUpdate} $0 "PATH" "A" "HKLM" "$INSTDIR" ; append
|
||||
; ${UnEnvVarUpdate} $0 "PATH" "HKLM" "$INSTDIR" ; remove
|
||||
|
||||
!ifndef ENVVARUPDATE_NSH
|
||||
!define ENVVARUPDATE_NSH
|
||||
|
||||
!include "LogicLib.nsh"
|
||||
!include "WinMessages.nsh"
|
||||
|
||||
; --------------------------------------------------------------------------
|
||||
; Macro: _EnvVarUpdate
|
||||
; Action: "A" = Append, "P" = Prepend, "R" = Remove
|
||||
; --------------------------------------------------------------------------
|
||||
!macro _EnvVarUpdate OUTVAR EnvVarName Action RegLoc PathString
|
||||
|
||||
Push $0
|
||||
Push $1
|
||||
Push $2
|
||||
Push $3
|
||||
Push $4
|
||||
Push $5
|
||||
|
||||
; Read current value
|
||||
ReadRegStr $1 ${RegLoc} \
|
||||
"SYSTEM\CurrentControlSet\Control\Session Manager\Environment" \
|
||||
"${EnvVarName}"
|
||||
|
||||
; Strip trailing semicolon
|
||||
StrCpy $5 $1 1 -1
|
||||
${If} $5 == ";"
|
||||
StrCpy $1 $1 -1
|
||||
${EndIf}
|
||||
|
||||
; Check if PathString already exists
|
||||
Push "${PathString}"
|
||||
Push $1
|
||||
Call _EnvVarUpdateStrStr
|
||||
Pop $2 ; $2 = position, or "" if not found
|
||||
|
||||
${If} "${Action}" == "A"
|
||||
${If} $2 == ""
|
||||
${If} $1 == ""
|
||||
StrCpy $3 "${PathString}"
|
||||
${Else}
|
||||
StrCpy $3 "$1;${PathString}"
|
||||
${EndIf}
|
||||
WriteRegExpandStr ${RegLoc} \
|
||||
"SYSTEM\CurrentControlSet\Control\Session Manager\Environment" \
|
||||
"${EnvVarName}" "$3"
|
||||
${EndIf}
|
||||
${ElseIf} "${Action}" == "P"
|
||||
${If} $2 == ""
|
||||
${If} $1 == ""
|
||||
StrCpy $3 "${PathString}"
|
||||
${Else}
|
||||
StrCpy $3 "${PathString};$1"
|
||||
${EndIf}
|
||||
WriteRegExpandStr ${RegLoc} \
|
||||
"SYSTEM\CurrentControlSet\Control\Session Manager\Environment" \
|
||||
"${EnvVarName}" "$3"
|
||||
${EndIf}
|
||||
${ElseIf} "${Action}" == "R"
|
||||
${If} $2 != ""
|
||||
; Remove entry
|
||||
StrLen $4 "${PathString}"
|
||||
StrCpy $0 $1 $2 ; everything before the match
|
||||
IntOp $4 $2 + $4 ; position after the match
|
||||
StrCpy $5 $1 "" $4 ; everything after the match
|
||||
; Strip leading/trailing semicolons from join point
|
||||
StrCpy $4 $5 1
|
||||
${If} $4 == ";"
|
||||
StrCpy $5 $5 "" 1
|
||||
${EndIf}
|
||||
StrCpy $4 $0 1 -1
|
||||
${If} $4 == ";"
|
||||
StrCpy $0 $0 -1
|
||||
${EndIf}
|
||||
${If} $0 == ""
|
||||
StrCpy $3 $5
|
||||
${ElseIf} $5 == ""
|
||||
StrCpy $3 $0
|
||||
${Else}
|
||||
StrCpy $3 "$0;$5"
|
||||
${EndIf}
|
||||
WriteRegExpandStr ${RegLoc} \
|
||||
"SYSTEM\CurrentControlSet\Control\Session Manager\Environment" \
|
||||
"${EnvVarName}" "$3"
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
; Broadcast change to all windows
|
||||
SendMessage ${HWND_BROADCAST} ${WM_SETTINGCHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
|
||||
Pop $5
|
||||
Pop $4
|
||||
Pop $3
|
||||
Pop $2
|
||||
Pop $1
|
||||
Pop $0
|
||||
|
||||
!macroend
|
||||
|
||||
; Helper: find substring position (returns "" if not found)
|
||||
Function _EnvVarUpdateStrStr
|
||||
Exch $R0 ; haystack
|
||||
Exch
|
||||
Exch $R1 ; needle
|
||||
Push $R2
|
||||
Push $R3
|
||||
Push $R4
|
||||
Push $R5
|
||||
StrLen $R3 $R1
|
||||
StrLen $R4 $R0
|
||||
IntOp $R4 $R4 - $R3
|
||||
StrCpy $R2 0
|
||||
loop:
|
||||
IntCmp $R2 $R4 done done
|
||||
StrCpy $R5 $R0 $R3 $R2
|
||||
StrCmp $R5 $R1 found
|
||||
IntOp $R2 $R2 + 1
|
||||
Goto loop
|
||||
found:
|
||||
StrCpy $R0 $R2
|
||||
Goto end
|
||||
done:
|
||||
StrCpy $R0 ""
|
||||
end:
|
||||
Pop $R5
|
||||
Pop $R4
|
||||
Pop $R3
|
||||
Pop $R2
|
||||
Pop $R1
|
||||
Exch $R0
|
||||
FunctionEnd
|
||||
|
||||
!define EnvVarUpdate `!insertmacro _EnvVarUpdate`
|
||||
!define UnEnvVarUpdate `!insertmacro _EnvVarUpdate "" "${__LINE__}" "R"`
|
||||
|
||||
!endif ; ENVVARUPDATE_NSH
|
||||
62
installer/build-installer.sh
Executable file
62
installer/build-installer.sh
Executable file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
# build-installer.sh
|
||||
# Builds livetrace-3.3.2-setup.exe on Linux — natively or via Docker.
|
||||
#
|
||||
# Usage:
|
||||
# ./installer/build-installer.sh # requires: apt install nsis
|
||||
# ./installer/build-installer.sh --docker # requires: docker
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
VERSION="3.3.2"
|
||||
OUTPUT="livetrace-${VERSION}-setup.exe"
|
||||
|
||||
# ── Docker build ───────────────────────────────────────────────────────────
|
||||
if [[ "${1:-}" == "--docker" ]]; then
|
||||
echo ">>> Building installer via Docker …"
|
||||
docker build \
|
||||
-f "${SCRIPT_DIR}/Dockerfile.installer" \
|
||||
-t livetrace-installer \
|
||||
"${PROJECT_ROOT}"
|
||||
|
||||
docker run --rm \
|
||||
-v "${PROJECT_ROOT}/dist":/out \
|
||||
livetrace-installer
|
||||
|
||||
echo ""
|
||||
echo "✓ Done: ${PROJECT_ROOT}/dist/${OUTPUT}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── Native build ───────────────────────────────────────────────────────────
|
||||
if ! command -v makensis &>/dev/null; then
|
||||
echo "ERROR: makensis not found."
|
||||
echo " Install: sudo apt install nsis"
|
||||
echo " Or run: $0 --docker"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SRC_EXE="${PROJECT_ROOT}/dist/livetrace-windows-amd64.exe"
|
||||
if [[ ! -f "${SRC_EXE}" ]]; then
|
||||
echo "ERROR: ${SRC_EXE} not found."
|
||||
echo " Run your Go build first, e.g.:"
|
||||
echo " GOOS=windows GOARCH=amd64 go build -o dist/livetrace-windows-amd64.exe ./src"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ">>> Building installer with makensis …"
|
||||
# Copy binary next to the .nsi script so NSIS can find it
|
||||
cp "${SRC_EXE}" "${SCRIPT_DIR}/livetrace-windows-amd64.exe"
|
||||
|
||||
cd "${SCRIPT_DIR}"
|
||||
makensis livetrace-installer.nsi
|
||||
|
||||
# Move the output to dist/
|
||||
mv "${SCRIPT_DIR}/${OUTPUT}" "${PROJECT_ROOT}/dist/${OUTPUT}"
|
||||
rm -f "${SCRIPT_DIR}/livetrace-windows-amd64.exe"
|
||||
|
||||
echo ""
|
||||
echo "✓ Done: ${PROJECT_ROOT}/dist/${OUTPUT}"
|
||||
echo " Size: $(du -sh "${PROJECT_ROOT}/dist/${OUTPUT}" | cut -f1)"
|
||||
138
installer/livetrace-installer.nsi
Normal file
138
installer/livetrace-installer.nsi
Normal file
@ -0,0 +1,138 @@
|
||||
; livetrace-installer.nsi
|
||||
; NSIS installer for livetrace v3.3.2
|
||||
; Builds on Linux (or in Docker) with: makensis livetrace-installer.nsi
|
||||
;
|
||||
; Place livetrace-windows-amd64.exe in the same directory before building.
|
||||
|
||||
Unicode True
|
||||
|
||||
; ──────────────────────────────────────────────
|
||||
; Metadata
|
||||
; ──────────────────────────────────────────────
|
||||
!define APPNAME "livetrace"
|
||||
!define APPVERSION "3.3.2"
|
||||
!define PUBLISHER "ngtech1ltd"
|
||||
|
||||
; Source binary name (as built by Go)
|
||||
!define SRC_EXE "livetrace-windows-amd64.exe"
|
||||
; Name it will have after installation
|
||||
!define INST_EXE "livetrace.exe"
|
||||
|
||||
; Registry key for Add/Remove Programs
|
||||
!define REG_UNINSTALL \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}"
|
||||
|
||||
; ──────────────────────────────────────────────
|
||||
; Installer settings
|
||||
; ──────────────────────────────────────────────
|
||||
Name "${APPNAME} ${APPVERSION}"
|
||||
OutFile "livetrace-${APPVERSION}-setup.exe"
|
||||
InstallDir "$PROGRAMFILES64\${APPNAME}"
|
||||
InstallDirRegKey HKLM "${REG_UNINSTALL}" "InstallLocation"
|
||||
|
||||
; Administrator rights required (Program Files + system PATH)
|
||||
RequestExecutionLevel admin
|
||||
|
||||
SetCompressor /SOLID lzma
|
||||
SetCompressorDictSize 32
|
||||
|
||||
; ──────────────────────────────────────────────
|
||||
; UI
|
||||
; ──────────────────────────────────────────────
|
||||
!include "MUI2.nsh"
|
||||
|
||||
!define MUI_ABORTWARNING
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
|
||||
; ──────────────────────────────────────────────
|
||||
; Version info (visible in Properties → Details)
|
||||
; ──────────────────────────────────────────────
|
||||
VIProductVersion "3.3.2.0"
|
||||
VIAddVersionKey "ProductName" "${APPNAME}"
|
||||
VIAddVersionKey "ProductVersion" "${APPVERSION}"
|
||||
VIAddVersionKey "CompanyName" "${PUBLISHER}"
|
||||
VIAddVersionKey "FileDescription" "${APPNAME} Installer"
|
||||
VIAddVersionKey "FileVersion" "${APPVERSION}"
|
||||
VIAddVersionKey "LegalCopyright" "(c) ${PUBLISHER}"
|
||||
|
||||
; ──────────────────────────────────────────────
|
||||
; PATH helpers (PowerShell – avoids NSIS macro
|
||||
; namespace issues between install / uninstall)
|
||||
; ──────────────────────────────────────────────
|
||||
|
||||
; Append $INSTDIR to the machine-wide PATH
|
||||
; Note: $$p / $$parts / $$_ are PowerShell variables — $$ escapes the $ for NSIS
|
||||
!macro AddToPath
|
||||
DetailPrint "Adding $INSTDIR to system PATH …"
|
||||
nsExec::ExecToLog \
|
||||
'powershell.exe -NonInteractive -NoProfile -Command \
|
||||
"$$p = [Environment]::GetEnvironmentVariable(\"Path\",\"Machine\"); \
|
||||
if ($$p -notlike \"*$INSTDIR*\") { \
|
||||
[Environment]::SetEnvironmentVariable(\"Path\", \"$$p;$INSTDIR\", \"Machine\") \
|
||||
}"'
|
||||
!macroend
|
||||
|
||||
; Remove $INSTDIR from the machine-wide PATH
|
||||
!macro RemoveFromPath
|
||||
DetailPrint "Removing $INSTDIR from system PATH …"
|
||||
nsExec::ExecToLog \
|
||||
'powershell.exe -NonInteractive -NoProfile -Command \
|
||||
"$$parts = [Environment]::GetEnvironmentVariable(\"Path\",\"Machine\") -split \";\"; \
|
||||
$$parts = $$parts | Where-Object { $$_ -ne \"$INSTDIR\" }; \
|
||||
[Environment]::SetEnvironmentVariable(\"Path\", ($$parts -join \";\"), \"Machine\")"'
|
||||
!macroend
|
||||
|
||||
; ──────────────────────────────────────────────
|
||||
; Install section
|
||||
; ──────────────────────────────────────────────
|
||||
Section "livetrace (required)" SecMain
|
||||
|
||||
SectionIn RO ; cannot be deselected
|
||||
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
; Copy binary — rename to plain "livetrace.exe" on the way in
|
||||
File "/oname=${INST_EXE}" "${SRC_EXE}"
|
||||
|
||||
; Add install dir to system PATH
|
||||
!insertmacro AddToPath
|
||||
|
||||
; Register with Add/Remove Programs
|
||||
WriteRegStr HKLM "${REG_UNINSTALL}" "DisplayName" "${APPNAME} ${APPVERSION}"
|
||||
WriteRegStr HKLM "${REG_UNINSTALL}" "DisplayVersion" "${APPVERSION}"
|
||||
WriteRegStr HKLM "${REG_UNINSTALL}" "Publisher" "${PUBLISHER}"
|
||||
WriteRegStr HKLM "${REG_UNINSTALL}" "InstallLocation" "$INSTDIR"
|
||||
WriteRegStr HKLM "${REG_UNINSTALL}" "UninstallString" '"$INSTDIR\uninstall.exe"'
|
||||
WriteRegStr HKLM "${REG_UNINSTALL}" "QuietUninstallString" '"$INSTDIR\uninstall.exe" /S'
|
||||
WriteRegDWORD HKLM "${REG_UNINSTALL}" "NoModify" 1
|
||||
WriteRegDWORD HKLM "${REG_UNINSTALL}" "NoRepair" 1
|
||||
|
||||
; Write the uninstaller
|
||||
WriteUninstaller "$INSTDIR\uninstall.exe"
|
||||
|
||||
SectionEnd
|
||||
|
||||
; ──────────────────────────────────────────────
|
||||
; Uninstall section
|
||||
; ──────────────────────────────────────────────
|
||||
Section "Uninstall"
|
||||
|
||||
; Remove from system PATH
|
||||
!insertmacro RemoveFromPath
|
||||
|
||||
; Delete files
|
||||
Delete "$INSTDIR\${INST_EXE}"
|
||||
Delete "$INSTDIR\uninstall.exe"
|
||||
RMDir "$INSTDIR"
|
||||
|
||||
; Remove Add/Remove Programs entry
|
||||
DeleteRegKey HKLM "${REG_UNINSTALL}"
|
||||
|
||||
SectionEnd
|
||||
Loading…
x
Reference in New Issue
Block a user