version: '3' includes: common: ../Taskfile.yml tasks: build: summary: Builds the application # MPCkit builds on each system natively; there is no Docker cross-build. # The experimental CGO-free backend (-tags purego) needs no C toolchain, # so only it can be built for macOS elsewhere. preconditions: - sh: '{{if or (eq OS "darwin") (has "purego" (splitList "," (.EXTRA_TAGS | default "")))}}true{{else}}false{{end}}' msg: "The macOS app must be built on a Mac." cmds: - task: build:native vars: ARCH: '{{.ARCH}}' DEV: '{{.DEV}}' OUTPUT: '{{.OUTPUT}}' EXTRA_TAGS: '{{.EXTRA_TAGS}}' OBFUSCATED: '{{.OBFUSCATED}}' GARBLE_ARGS: '{{.GARBLE_ARGS}}' vars: DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' build:native: summary: Builds the application natively (on macOS, or anywhere with -tags purego) internal: true deps: - task: common:go:mod:tidy - task: common:build:frontend vars: BUILD_FLAGS: ref: .BUILD_FLAGS OBFUSCATED: ref: .OBFUSCATED DEV: ref: .DEV - task: common:generate:icons preconditions: - sh: '{{if eq .OBFUSCATED "true"}}command -v garble >/dev/null 2>&1{{else}}true{{end}}' msg: "garble is required for obfuscated builds. Install it with: go install mvdan.cc/garble@v0.16.0 (requires Go 1.24+). See https://github.com/burrowers/garble/releases for version/toolchain compatibility." cmds: - wails3 tool prepare-macos-output --dir "{{.BIN_DIR}}" - '{{if eq .OBFUSCATED "true"}}garble {{.GARBLE_ARGS}} build{{else}}go build{{end}} {{.BUILD_FLAGS}} -o "{{.OUTPUT}}"' vars: BUILD_FLAGS: '{{if eq .DEV "true"}}{{if or .EXTRA_TAGS (eq .OBFUSCATED "true")}}-tags {{if eq .OBFUSCATED "true"}}wails_obfuscated{{if .EXTRA_TAGS}},{{end}}{{end}}{{.EXTRA_TAGS}} {{end}}-buildvcs=false -gcflags=all="-l"{{else}}-tags production{{if eq .OBFUSCATED "true"}},wails_obfuscated{{end}}{{if .EXTRA_TAGS}},{{.EXTRA_TAGS}}{{end}} -trimpath -buildvcs=false -ldflags="-w -s -X git.monoexp.com/bajdev/mpckit/internal/app.Version={{.APP_VERSION}} -X git.monoexp.com/bajdev/mpckit/internal/app.Commit={{.COMMIT}}"{{end}}' DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' env: GOOS: darwin CGO_ENABLED: '{{if (has "purego" (splitList "," (.EXTRA_TAGS | default "")))}}0{{else}}1{{end}}' GOARCH: '{{.ARCH | default ARCH}}' CGO_CFLAGS: "-mmacosx-version-min=12.0" CGO_LDFLAGS: "-mmacosx-version-min=12.0" MACOSX_DEPLOYMENT_TARGET: "12.0" build:universal: summary: Builds darwin universal binary (arm64 + amd64) deps: - task: build vars: ARCH: amd64 OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" - task: build vars: ARCH: arm64 OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" cmds: - task: '{{if eq OS "darwin"}}build:universal:lipo:native{{else}}build:universal:lipo:go{{end}}' build:universal:lipo:native: summary: Creates universal binary using native lipo (macOS) internal: true cmds: - lipo -create -output "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - rm "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" build:universal:lipo:go: summary: Creates universal binary using wails3 tool lipo (Linux/Windows) internal: true cmds: - wails3 tool lipo -output "{{.BIN_DIR}}/{{.APP_NAME}}" -input "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" -input "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - rm -f "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" package: summary: Packages the application into a `.app` bundle deps: - task: build cmds: - task: create:app:bundle package:universal: summary: Packages darwin universal binary (arm64 + amd64) deps: - task: build:universal cmds: - task: create:app:bundle package:dmg: summary: Packages the application into a styled `.dmg` deps: - task: package cmds: - task: create:dmg create:dmg: summary: Creates a configurable `.dmg` from the `.app` bundle platforms: [darwin] cmds: - >- wails3 tool package --format dmg --name "{{.APP_NAME}}" --out "{{.BIN_DIR}}" --background "{{.DMG_BACKGROUND}}" --volume-icon "{{.DMG_VOLUME_ICON}}" --file-icon "{{.DMG_FILE_ICON}}" --window-width "{{.DMG_WINDOW_WIDTH}}" --window-height "{{.DMG_WINDOW_HEIGHT}}" {{if .DMG_FILES}}--files "{{.DMG_FILES}}"{{end}} vars: DMG_BACKGROUND: '{{.DMG_BACKGROUND | default "build/darwin/dmg-background.png"}}' DMG_VOLUME_ICON: '{{.DMG_VOLUME_ICON | default "build/darwin/icons.icns"}}' DMG_FILE_ICON: '{{.DMG_FILE_ICON | default "build/darwin/dmg-file-icon.icns"}}' DMG_WINDOW_WIDTH: '{{.DMG_WINDOW_WIDTH | default "540"}}' DMG_WINDOW_HEIGHT: '{{.DMG_WINDOW_HEIGHT | default "380"}}' DMG_FILES: '{{.DMG_FILES | default ""}}' create:app:bundle: summary: Creates an `.app` bundle cmds: # A reused bundle can acquire Finder metadata in synced folders. Build a # fresh bundle so codesign never has to replace a contaminated signature. - test -n "{{.BIN_DIR}}" && test -n "{{.APP_NAME}}" && rm -rf -- "{{.BIN_DIR}}/{{.APP_NAME}}.app" - mkdir -p "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS" - mkdir -p "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources" - cp build/darwin/icons.icns "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources" - | if [ -f build/darwin/Assets.car ]; then cp build/darwin/Assets.car "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources" fi - cp "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS" - cp build/darwin/Info.plist "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents" - task: '{{if eq OS "darwin"}}codesign:adhoc{{else}}codesign:skip{{end}}' codesign:adhoc: summary: Ad-hoc signs the app bundle (macOS only) internal: true cmds: - xattr -cr "{{.BIN_DIR}}/{{.APP_NAME}}.app" - codesign --force --deep --sign - "{{.BIN_DIR}}/{{.APP_NAME}}.app" - codesign --verify --deep --strict "{{.BIN_DIR}}/{{.APP_NAME}}.app" codesign:skip: summary: Skips codesigning when cross-compiling internal: true cmds: - 'echo "Skipping codesign (not available on {{OS}}). Sign the .app on macOS before distribution."' run: cmds: - wails3 tool prepare-macos-output --dir "{{.BIN_DIR}}" - test -n "{{.BIN_DIR}}" && test -n "{{.APP_NAME}}" && rm -rf -- "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app" - mkdir -p "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS" - mkdir -p "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources" - cp build/darwin/icons.icns "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources" - | if [ -f build/darwin/Assets.car ]; then cp build/darwin/Assets.car "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources" fi - cp "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS" - cp "build/darwin/Info.dev.plist" "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Info.plist" - xattr -cr "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app" - codesign --force --deep --sign - "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app" - codesign --verify --deep --strict "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app" - '"{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS/{{.APP_NAME}}"' sign: summary: Signs the application bundle with Developer ID desc: | Signs the .app bundle for distribution. Uses signing identity from `wails3 setup` (stored in ~/.config/wails/defaults.yaml). Override with: task darwin:sign -- --identity "Developer ID Application: ..." deps: - task: package cmds: - wails3 tool sign --input "{{.BIN_DIR}}/{{.APP_NAME}}.app" {{.CLI_ARGS}} sign:notarize: summary: Signs and notarizes the application bundle desc: | Signs the .app bundle and submits it for notarization. Uses signing identity and keychain profile from `wails3 setup`. First-time setup: wails3 setup deps: - task: package cmds: - wails3 tool sign --input "{{.BIN_DIR}}/{{.APP_NAME}}.app" --notarize {{.CLI_ARGS}}