Build System
Unified Build System
Section titled “Unified Build System”Wails provides a unified build system that compiles Go code, bundles frontend assets, embeds everything into a single executable, and handles platform-specific builds—all with one command.
wails3 buildOutput: Native executable with everything embedded.
Build Process Overview
Section titled “Build Process Overview”[Build Process Diagram Placeholder]
Build Phases
Section titled “Build Phases”1. Analysis Phase
Section titled “1. Analysis Phase”Wails scans your Go code to understand your services:
type GreetService struct { prefix string}
func (g *GreetService) Greet(name string) string { return g.prefix + name + "!"}What Wails extracts:
- Service name:
GreetService - Method name:
Greet - Parameter types:
string - Return types:
string
Used for: Generating TypeScript bindings
2. Generation Phase
Section titled “2. Generation Phase”TypeScript Bindings
Section titled “TypeScript Bindings”Wails generates type-safe bindings:
// Auto-generated: frontend/bindings/<full-go-import-path>/greetservice.js// (TypeScript is also generated when you pass `-ts`. The shape below is the real// runtime call format — numeric IDs via $Call.ByID, imported from /wails/runtime.js.)import { Call as $Call } from "/wails/runtime.js";
export function Greet($0) { return $Call.ByID(1234567890, $0);}Benefits:
- Full type safety
- IDE autocomplete
- Compile-time errors
- JSDoc comments
Frontend Build
Section titled “Frontend Build”Your frontend bundler runs (Vite, webpack, etc.):
# Vite examplevite build --outDir distWhat happens:
- JavaScript/TypeScript compiled
- CSS processed and minified
- Assets optimised
- Source maps generated (dev only)
- Output to
frontend/dist/
3. Compilation Phase
Section titled “3. Compilation Phase”Go Compilation
Section titled “Go Compilation”Go code is compiled with optimisations:
go build -ldflags="-s -w" -o myapp.exeFlags:
-s: Strip symbol table-w: Strip DWARF debugging info- Result: Smaller binary (~30% reduction)
Platform-specific:
- Windows:
.exewith icon embedded - macOS:
.appbundle structure - Linux: ELF binary
Asset Embedding
Section titled “Asset Embedding”Frontend assets are embedded into the Go binary:
//go:embed frontend/distvar assets embed.FSResult: Single executable with everything inside.
4. Output
Section titled “4. Output”Single native binary:
- Windows:
myapp.exe(~15MB) - macOS:
myapp.app(~15MB) - Linux:
myapp(~15MB)
No dependencies (except system WebView).
Development vs Production
Section titled “Development vs Production”Optimised for speed:
wails3 devWhat happens:
- Starts frontend dev server (Vite on port 9245 by default)
- Compiles Go without optimisations
- Launches app pointing to dev server
- Enables hot reload
- Includes source maps
Characteristics:
- Fast rebuilds (<1s for frontend changes)
- No asset embedding (served from dev server)
- Debug symbols included
- Source maps enabled
- Verbose logging
File size: Larger (~50MB with debug symbols)
Optimised for size and performance:
wails3 buildWhat happens:
- Builds frontend for production (minified)
- Compiles Go with optimisations
- Strips debug symbols
- Embeds assets
- Creates single binary
Characteristics:
- Optimised code (minified, tree-shaken)
- Assets embedded (no external files)
- Debug symbols stripped
- No source maps
- Minimal logging
File size: Smaller (~15MB)
Build Commands
Section titled “Build Commands”Basic Build
Section titled “Basic Build”wails3 buildOutput: bin/<APP_NAME> (or bin/<APP_NAME>.exe on Windows). The bin/ directory sits at the project root.
wails3 build is a thin wrapper around wails3 task build. The only build-time flag it forwards is --tags, which becomes the EXTRA_TAGS Taskfile variable:
# Build with extra Go build tagswails3 build --tags "myfeature,gtk4"There are no -platform, -o, -skipbindings, -clean, -debug, -devbuild, -icon, -ldflags, or -package flags on wails3 build. Cross-compilation, output paths, icons, and packaging are controlled through the project’s Taskfile (Taskfile.yml + build/config.yml).
Cross-platform and platform-specific builds
Section titled “Cross-platform and platform-specific builds”Platform builds are exposed as Taskfile tasks under the darwin: / windows: / linux: namespaces (defined in build/Taskfile.<platform>.yml). For example:
# macOS — universal binarywails3 task darwin:build:universal
# macOS — current archwails3 task darwin:build
# Windowswails3 task windows:build
# Linuxwails3 task linux:buildTo see every available task in the current project:
wails3 task --listIcons and packaging
Section titled “Icons and packaging”Generate platform icons (build/icons.icns, build/icon.ico, etc.) from a source PNG:
wails3 generate icons -input appicon.pngBuild platform-specific installers/packages:
wails3 package # uses the current Go build envwails3 task linux:create:debwails3 task windows:packagewails3 task darwin:package:universalBuild Configuration
Section titled “Build Configuration”Taskfile.yml
Section titled “Taskfile.yml”Wails 3 projects use Taskfile as their build orchestrator. The root Taskfile.yml includes per-platform task files from build/:
# Taskfile.yml (excerpt — the real templates are richer)version: '3'
includes: common: ./build/Taskfile.yml darwin: ./build/Taskfile.darwin.yml windows: ./build/Taskfile.windows.yml linux: ./build/Taskfile.linux.yml
tasks: build: desc: Build the application cmds: - task: "{{OS}}:build"Run tasks with wails3 task <name> or task <name>:
wails3 task windows:buildwails3 task darwin:package:universalwails3 task linux:create:appimageProject configuration: build/config.yml
Section titled “Project configuration: build/config.yml”Project metadata (name, identifier, version, info-plist values, NSIS settings, .desktop fields, custom protocols, etc.) lives in build/config.yml. The Taskfile reads this file when generating icons, manifests, installers, and the like. There is no build/build.json file in Wails 3.
# build/config.yml (illustrative)info: productName: "My App" productIdentifier: "com.example.myapp" productVersion: "1.0.0" companyName: "Example Ltd." productDescription: "An application built with Wails"Run wails3 generate build-assets (or wails3 update build-assets) to refresh the platform-specific build assets from this config.
Asset Embedding
Section titled “Asset Embedding”How It Works
Section titled “How It Works”Wails uses Go’s embed package:
package main
import ( "embed" "github.com/wailsapp/wails/v3/pkg/application")
//go:embed frontend/distvar assets embed.FS
func main() { app := application.New(application.Options{ Name: "My App", Assets: application.AssetOptions{ Handler: application.AssetFileServerFS(assets), }, })
app.Window.New() app.Run()}At build time:
- Frontend built to
frontend/dist/ //go:embeddirective includes files- Files compiled into binary
- Binary contains everything
At runtime:
- App starts
- Assets served from memory
- No disk I/O for assets
- Fast loading
Custom Assets
Section titled “Custom Assets”Embed additional files:
//go:embed frontend/distvar frontendAssets embed.FS
//go:embed data/*.jsonvar dataAssets embed.FS
//go:embed templates/*.htmlvar templateAssets embed.FSBuild Optimisations
Section titled “Build Optimisations”Frontend Optimisations
Section titled “Frontend Optimisations”Vite (default):
export default { build: { minify: 'terser', terserOptions: { compress: { drop_console: true, // Remove console.log drop_debugger: true, }, }, rollupOptions: { output: { manualChunks: { vendor: ['react', 'react-dom'], // Separate vendor bundle }, }, }, },}Results:
- JavaScript minified (~70% reduction)
- CSS minified (~60% reduction)
- Images optimised
- Tree-shaking applied
Go Optimisations
Section titled “Go Optimisations”Compiler flags:
-ldflags="-s -w"-s: Strip symbol table (~10% reduction)-w: Strip DWARF debug info (~20% reduction)
Additional optimisations:
-ldflags="-s -w -X main.version=1.0.0"-X: Set variable values at build time- Useful for version numbers, build dates
Binary Compression
Section titled “Binary Compression”UPX (optional):
# After buildingupx --best bin/myapp.exeResults:
- ~50% size reduction
- Slightly slower startup (~100ms)
- Not recommended for macOS (code signing issues)
Platform-Specific Builds
Section titled “Platform-Specific Builds”Windows
Section titled “Windows”Output: myapp.exe
Includes:
- Application icon
- Version information
- Manifest (UAC settings)
Icon:
# Generate platform icons from a source PNGwails3 generate icons -input appicon.png -windowsfilename build/icon.icoThe Windows tool package step then embeds the generated .ico into the executable.
Manifest:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity version="1.0.0.0" name="MyApp"/> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> <requestedExecutionLevel level="asInvoker" uiAccess="false"/> </requestedPrivileges> </security> </trustInfo></assembly>Output: myapp.app (application bundle)
Structure:
myapp.app/├── Contents/│ ├── Info.plist # App metadata│ ├── MacOS/│ │ └── myapp # Binary│ ├── Resources/│ │ └── icon.icns # Icon│ └── _CodeSignature/ # Code signature (if signed)Info.plist:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict> <key>CFBundleName</key> <string>My App</string> <key>CFBundleIdentifier</key> <string>com.example.myapp</string> <key>CFBundleVersion</key> <string>1.0.0</string></dict></plist>Universal Binary:
The macOS Taskfile ships a darwin:build:universal (and darwin:package:universal) task that builds both architectures and combines them via wails3 tool lipo:
wails3 task darwin:build:universalOutput: myapp (ELF binary)
Dependencies:
- GTK3
- WebKitGTK
Desktop file:
# myapp.desktop[Desktop Entry]Name=My AppExec=/usr/bin/myappIcon=myappType=ApplicationCategories=Utility;Installation:
# Copy binarysudo cp myapp /usr/bin/
# Copy desktop filesudo cp myapp.desktop /usr/share/applications/
# Copy iconsudo cp icon.png /usr/share/icons/hicolor/256x256/apps/myapp.pngBuild Performance
Section titled “Build Performance”Typical Build Times
Section titled “Typical Build Times”| Phase | Time | Notes |
|---|---|---|
| Analysis | <1s | Go code scanning |
| Binding Generation | <1s | TypeScript generation |
| Frontend Build | 5-30s | Depends on project size |
| Go Compilation | 2-10s | Depends on code size |
| Asset Embedding | <1s | Embedding frontend |
| Total | 10-45s | First build |
| Incremental | 5-15s | Subsequent builds |
Speeding Up Builds
Section titled “Speeding Up Builds”1. Use build cache:
# Go build cache is automatic# Frontend cache (Vite)npm run build # Uses cache by default2. Run only what you need:
# Pick the specific Taskfile target you actually needwails3 task common:build:frontend # rebuild only the frontendwails3 task windows:build # rebuild only the Windows binary3. Parallel builds (multi-machine / CI):
Cross-compilation between Linux/Windows/macOS in v3 generally happens in a Docker wails-cross container or on dedicated runners per platform — wails3 build itself targets the host OS. See Cross-platform Builds for the supported workflows.
4. Use faster tools:
# Use esbuild instead of webpack# (Vite uses esbuild by default)Troubleshooting
Section titled “Troubleshooting”Build Fails
Section titled “Build Fails”Symptom: wails3 build exits with error
Common causes:
-
Go compilation error
Terminal window # Check Go code compilesgo build -
Frontend build error
Terminal window # Check frontend buildscd frontendnpm run build -
Missing dependencies
Terminal window # Install dependenciesnpm installgo mod download
Binary Too Large
Section titled “Binary Too Large”Symptom: Binary is >50MB
Solutions:
-
Strip debug symbols (the shipped Taskfile already passes
-ldflags="-s -w"togo build). -
Check embedded assets
Terminal window # Remove unnecessary files from frontend/dist/# Check for large images, videos, etc. -
Use UPX compression
Terminal window upx --best bin/myapp.exe
Slow Builds
Section titled “Slow Builds”Symptom: Builds take >1 minute
Solutions:
-
Use build cache
- Go cache is automatic
- Frontend cache (Vite) is automatic
-
Run only the task you need
Terminal window wails3 task common:build:frontendwails3 task windows:build -
Optimise frontend build
vite.config.js export default {build: {minify: 'esbuild', // Faster than terser},}
Best Practices
Section titled “Best Practices”- Use
wails3 devduring development - Fast iteration - Use
wails3 buildfor releases - Optimised output - Version your builds - Use
-ldflagsto embed version - Test builds on target platforms - Cross-compilation isn’t perfect
- Keep frontend builds fast - Optimise bundler config
- Use build cache - Speeds up subsequent builds
❌ Don’t
Section titled “❌ Don’t”- Don’t commit
build/directory - Add to.gitignore - Don’t skip testing builds - Always test before release
- Don’t embed unnecessary assets - Keep binaries small
- Don’t use debug builds for production - Use optimised builds
- Don’t forget code signing - Required for distribution
Next Steps
Section titled “Next Steps”Building Applications - Detailed guide to building and packaging
Learn More →
Cross-Platform Builds - Build for all platforms from one machine
Learn More →
Creating Installers - Create installers for end users
Learn More →
Questions about building? Ask in Discord or check the build examples.