version: '3' includes: common: ../Taskfile.yml vars: # Signing configuration - edit these values for your project # SIGN_CERTIFICATE: "path/to/certificate.pfx" # SIGN_THUMBPRINT: "certificate-thumbprint" # Alternative to SIGN_CERTIFICATE # TIMESTAMP_SERVER: "http://timestamp.digicert.com" # # Password is stored securely in system keychain. Run: wails3 setup signing # Docker image for cross-compilation with CGO (used when CGO_ENABLED=1 on non-Windows) CROSS_IMAGE: wails-cross tasks: build: summary: Builds the application for Windows cmds: # CGO Windows builds from Linux use mingw-w64 (lighter than docker). # Docker is only needed if mingw-w64 is unavailable. - task: build:native vars: ARCH: '{{.ARCH}}' DEV: '{{.DEV}}' EXTRA_TAGS: '{{.EXTRA_TAGS}}' vars: CGO_ENABLED: '{{.CGO_ENABLED | default "0"}}' build:console: summary: Builds a console-attached Windows binary so logs go to the terminal. desc: | Same as `windows:build` but links against the console PE subsystem instead of windowsgui, so stdout/stderr (logrus, panics) print to the terminal that launched the .exe. Useful for chasing tray, event-stream, or daemon-RPC bugs that have no other feedback channel on Windows. Output is bin/netbird-ui-console.exe — kept distinct so the production binary built by `windows:build` isn't shadowed. Cross-compile from Linux works the same way: CGO_ENABLED=1 task windows:build:console deps: - task: common:go:mod:tidy - task: common:build:frontend vars: BUILD_FLAGS: ref: .BUILD_FLAGS DEV: ref: .DEV - task: common:generate:icons preconditions: - sh: '[ "{{OS}}" = "windows" ] || [ "{{.CGO_ENABLED}}" != "1" ] || command -v {{.CC}}' msg: "{{.CC}} not found. Install with: sudo apt-get install gcc-mingw-w64-x86-64 (Debian/Ubuntu) / sudo dnf install mingw64-gcc (Fedora)" cmds: - task: generate:syso - go build {{.BUILD_FLAGS}} -o "{{.BIN_DIR}}/{{.APP_NAME}}-console.exe" - cmd: powershell Remove-item *.syso platforms: [windows] - cmd: rm -f *.syso platforms: [linux, darwin] vars: # Identical to build:native's flags except no -H windowsgui, so the # binary attaches to the launching console. BUILD_FLAGS: '-tags production{{if .EXTRA_TAGS}},{{.EXTRA_TAGS}}{{end}} -trimpath -buildvcs=false -ldflags="-w -s"' CGO_ENABLED: '{{.CGO_ENABLED | default "0"}}' CC: '{{.CC | default "x86_64-w64-mingw32-gcc"}}' env: GOOS: windows CGO_ENABLED: '{{.CGO_ENABLED}}' GOARCH: '{{.ARCH | default ARCH}}' CC: '{{.CC}}' build:native: summary: Builds for Windows natively, or cross-compiles from Linux/macOS via mingw-w64. internal: true deps: - task: common:go:mod:tidy - task: common:build:frontend vars: BUILD_FLAGS: ref: .BUILD_FLAGS DEV: ref: .DEV - task: common:generate:icons preconditions: # When cross-compiling with CGO from a non-Windows host, the mingw-w64 # cross-gcc must be present. Native Windows builds skip this check. - sh: '[ "{{OS}}" = "windows" ] || [ "{{.CGO_ENABLED}}" != "1" ] || command -v {{.CC}}' msg: "{{.CC}} not found. Install with: sudo apt-get install gcc-mingw-w64-x86-64 (Debian/Ubuntu) / sudo dnf install mingw64-gcc (Fedora)" cmds: - task: generate:syso - go build {{.BUILD_FLAGS}} -o "{{.BIN_DIR}}/{{.APP_NAME}}.exe" - cmd: powershell Remove-item *.syso platforms: [windows] - cmd: rm -f *.syso platforms: [linux, darwin] vars: BUILD_FLAGS: '{{if eq .DEV "true"}}{{if .EXTRA_TAGS}}-tags {{.EXTRA_TAGS}} {{end}}-buildvcs=false -gcflags=all="-l"{{else}}-tags production{{if .EXTRA_TAGS}},{{.EXTRA_TAGS}}{{end}} -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{end}}' CGO_ENABLED: '{{.CGO_ENABLED | default "0"}}' CC: '{{.CC | default "x86_64-w64-mingw32-gcc"}}' env: GOOS: windows CGO_ENABLED: '{{.CGO_ENABLED}}' GOARCH: '{{.ARCH | default ARCH}}' CC: '{{.CC}}' build:docker: summary: Cross-compiles for Windows using Docker with Zig (for CGO builds on non-Windows) internal: true deps: - task: common:build:frontend - task: common:generate:icons preconditions: - sh: docker info > /dev/null 2>&1 msg: "Docker is required for CGO cross-compilation. Please install Docker." - sh: docker image inspect {{.CROSS_IMAGE}} > /dev/null 2>&1 msg: | Docker image '{{.CROSS_IMAGE}}' not found. Build it first: wails3 task setup:docker cmds: - task: generate:syso - docker run --rm -v "{{.ROOT_DIR}}:/app" {{.GO_CACHE_MOUNT}} {{.REPLACE_MOUNTS}} -e APP_NAME="{{.APP_NAME}}" {{if .EXTRA_TAGS}}-e EXTRA_TAGS="{{.EXTRA_TAGS}}"{{end}} {{.CROSS_IMAGE}} windows {{.DOCKER_ARCH}} - docker run --rm -v "{{.ROOT_DIR}}:/app" alpine chown -R $(id -u):$(id -g) /app/bin - rm -f *.syso vars: DOCKER_ARCH: '{{.ARCH | default "amd64"}}' # Mount Go module cache for faster builds GO_CACHE_MOUNT: sh: 'echo "-v ${GOPATH:-$HOME/go}/pkg/mod:/go/pkg/mod"' # Extract replace directives from go.mod and create -v mounts for each REPLACE_MOUNTS: sh: | grep -E '^replace .* => ' go.mod 2>/dev/null | while read -r line; do path=$(echo "$line" | sed -E 's/^replace .* => //' | tr -d '\r') # Convert relative paths to absolute if [ "${path#/}" = "$path" ]; then path="$(cd "$(dirname "$path")" 2>/dev/null && pwd)/$(basename "$path")" fi # Only mount if directory exists if [ -d "$path" ]; then echo "-v $path:$path:ro" fi done | tr '\n' ' ' package: summary: Packages the application cmds: - task: '{{if eq (.FORMAT | default "nsis") "msix"}}create:msix:package{{else}}create:nsis:installer{{end}}' vars: FORMAT: '{{.FORMAT | default "nsis"}}' generate:syso: summary: Generates Windows `.syso` file dir: build cmds: - wails3 generate syso -arch {{.ARCH}} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_{{.ARCH}}.syso vars: ARCH: '{{.ARCH | default ARCH}}' create:nsis:installer: summary: Creates an NSIS installer dir: build/windows/nsis deps: - task: build cmds: # Create the Microsoft WebView2 bootstrapper if it doesn't exist - wails3 generate webview2bootstrapper -dir "{{.ROOT_DIR}}/build/windows/nsis" - | {{if eq OS "windows"}} makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}\{{.BIN_DIR}}\{{.APP_NAME}}.exe" project.nsi {{else}} makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" project.nsi {{end}} vars: ARCH: '{{.ARCH | default ARCH}}' ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}' create:msix:package: summary: Creates an MSIX package deps: - task: build cmds: - |- wails3 tool msix \ --config "{{.ROOT_DIR}}/wails.json" \ --name "{{.APP_NAME}}" \ --executable "{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" \ --arch "{{.ARCH}}" \ --out "{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}-{{.ARCH}}.msix" \ {{if .CERT_PATH}}--cert "{{.CERT_PATH}}"{{end}} \ {{if .PUBLISHER}}--publisher "{{.PUBLISHER}}"{{end}} \ {{if .USE_MSIX_TOOL}}--use-msix-tool{{else}}--use-makeappx{{end}} vars: ARCH: '{{.ARCH | default ARCH}}' CERT_PATH: '{{.CERT_PATH | default ""}}' PUBLISHER: '{{.PUBLISHER | default ""}}' USE_MSIX_TOOL: '{{.USE_MSIX_TOOL | default "false"}}' install:msix:tools: summary: Installs tools required for MSIX packaging cmds: - wails3 tool msix-install-tools run: cmds: - '{{.BIN_DIR}}/{{.APP_NAME}}.exe' sign: summary: Signs the Windows executable desc: | Signs the .exe with an Authenticode certificate. Configure SIGN_CERTIFICATE or SIGN_THUMBPRINT in the vars section at the top of this file. Password is retrieved from system keychain (run: wails3 setup signing) deps: - task: build cmds: - wails3 tool sign --input "{{.BIN_DIR}}/{{.APP_NAME}}.exe" {{if .SIGN_CERTIFICATE}}--certificate {{.SIGN_CERTIFICATE}}{{end}} {{if .SIGN_THUMBPRINT}}--thumbprint {{.SIGN_THUMBPRINT}}{{end}} {{if .TIMESTAMP_SERVER}}--timestamp {{.TIMESTAMP_SERVER}}{{end}} preconditions: - sh: '[ -n "{{.SIGN_CERTIFICATE}}" ] || [ -n "{{.SIGN_THUMBPRINT}}" ]' msg: "Either SIGN_CERTIFICATE or SIGN_THUMBPRINT is required. Set it in the vars section at the top of build/windows/Taskfile.yml" sign:installer: summary: Signs the NSIS installer desc: | Creates and signs the NSIS installer. Configure SIGN_CERTIFICATE or SIGN_THUMBPRINT in the vars section at the top of this file. Password is retrieved from system keychain (run: wails3 setup signing) deps: - task: create:nsis:installer cmds: - wails3 tool sign --input "build/windows/nsis/{{.APP_NAME}}-installer.exe" {{if .SIGN_CERTIFICATE}}--certificate {{.SIGN_CERTIFICATE}}{{end}} {{if .SIGN_THUMBPRINT}}--thumbprint {{.SIGN_THUMBPRINT}}{{end}} {{if .TIMESTAMP_SERVER}}--timestamp {{.TIMESTAMP_SERVER}}{{end}} preconditions: - sh: '[ -n "{{.SIGN_CERTIFICATE}}" ] || [ -n "{{.SIGN_THUMBPRINT}}" ]' msg: "Either SIGN_CERTIFICATE or SIGN_THUMBPRINT is required. Set it in the vars section at the top of build/windows/Taskfile.yml"