gui/docs/ref/wails-v3/concepts/build-system.mdx
Snider 4bdbb68f46
Some checks failed
Security Scan / security (push) Failing after 9s
Test / test (push) Failing after 1m21s
refactor: update import path from go-config to core/config
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-14 10:26:36 +00:00

700 lines
13 KiB
Text

---
title: Build System
description: Understanding how Wails builds and packages your application
sidebar:
order: 4
---
import { Tabs, TabItem } from "@astrojs/starlight/components";
## 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.
```bash
wails3 build
```
**Output:** Native executable with everything embedded.
## Build Process Overview
{/*
TODO: Fix D2 diagram generation or embed as image.
The previous D2 code block was causing MDX parsing errors in the build pipeline.
*/}
**[Build Process Diagram Placeholder]**
## Build Phases
### 1. Analysis Phase
Wails scans your Go code to understand your services:
```go
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
#### TypeScript Bindings
Wails generates type-safe bindings:
```typescript
// Auto-generated: frontend/bindings/GreetService.ts
export function Greet(name: string): Promise<string> {
return window.wails.Call('GreetService.Greet', name)
}
```
**Benefits:**
- Full type safety
- IDE autocomplete
- Compile-time errors
- JSDoc comments
#### Frontend Build
Your frontend bundler runs (Vite, webpack, etc.):
```bash
# Vite example
vite build --outDir dist
```
**What happens:**
- JavaScript/TypeScript compiled
- CSS processed and minified
- Assets optimised
- Source maps generated (dev only)
- Output to `frontend/dist/`
### 3. Compilation Phase
#### Go Compilation
Go code is compiled with optimisations:
```bash
go build -ldflags="-s -w" -o myapp.exe
```
**Flags:**
- `-s`: Strip symbol table
- `-w`: Strip DWARF debugging info
- Result: Smaller binary (~30% reduction)
**Platform-specific:**
- Windows: `.exe` with icon embedded
- macOS: `.app` bundle structure
- Linux: ELF binary
#### Asset Embedding
Frontend assets are embedded into the Go binary:
```go
//go:embed frontend/dist
var assets embed.FS
```
**Result:** Single executable with everything inside.
### 4. Output
**Single native binary:**
- Windows: `myapp.exe` (~15MB)
- macOS: `myapp.app` (~15MB)
- Linux: `myapp` (~15MB)
**No dependencies** (except system WebView).
## Development vs Production
<Tabs syncKey="mode">
<TabItem label="Development (wails3 dev)" icon="seti:config">
**Optimised for speed:**
```bash
wails3 dev
```
**What happens:**
1. Starts frontend dev server (Vite on port 5173)
2. Compiles Go without optimisations
3. Launches app pointing to dev server
4. Enables hot reload
5. Includes source maps
**Characteristics:**
- **Fast rebuilds** (&lt;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)
</TabItem>
<TabItem label="Production (wails3 build)" icon="rocket">
**Optimised for size and performance:**
```bash
wails3 build
```
**What happens:**
1. Builds frontend for production (minified)
2. Compiles Go with optimisations
3. Strips debug symbols
4. Embeds assets
5. 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)
</TabItem>
</Tabs>
## Build Commands
### Basic Build
```bash
wails3 build
```
**Output:** `build/bin/myapp[.exe]`
### Build for Specific Platform
```bash
# Build for Windows (from any OS)
wails3 build -platform windows/amd64
# Build for macOS
wails3 build -platform darwin/amd64
wails3 build -platform darwin/arm64
# Build for Linux
wails3 build -platform linux/amd64
```
**Cross-compilation:** Build for any platform from any platform.
### Build with Options
```bash
# Custom output directory
wails3 build -o ./dist/myapp
# Skip frontend build (use existing)
wails3 build -skipbindings
# Clean build (remove cache)
wails3 build -clean
# Verbose output
wails3 build -v
```
### Build Modes
```bash
# Debug build (includes symbols)
wails3 build -debug
# Production build (default, optimised)
wails3 build
# Development build (fast, unoptimised)
wails3 build -devbuild
```
## Build Configuration
### Taskfile.yml
Wails uses [Taskfile](https://taskfile.dev/) for build configuration:
```yaml
# Taskfile.yml
version: '3'
tasks:
build:
desc: Build the application
cmds:
- wails3 build
build:windows:
desc: Build for Windows
cmds:
- wails3 build -platform windows/amd64
build:macos:
desc: Build for macOS (Universal)
cmds:
- wails3 build -platform darwin/amd64
- wails3 build -platform darwin/arm64
- lipo -create -output build/bin/myapp.app build/bin/myapp-amd64.app build/bin/myapp-arm64.app
build:linux:
desc: Build for Linux
cmds:
- wails3 build -platform linux/amd64
```
**Run tasks:**
```bash
task build:windows
task build:macos
task build:linux
```
### Build Options File
Create `build/build.json` for persistent configuration:
```json
{
"name": "My Application",
"version": "1.0.0",
"author": "Your Name",
"description": "Application description",
"icon": "build/appicon.png",
"outputFilename": "myapp",
"platforms": ["windows/amd64", "darwin/amd64", "linux/amd64"],
"frontend": {
"dir": "./frontend",
"install": "npm install",
"build": "npm run build",
"dev": "npm run dev"
},
"go": {
"ldflags": "-s -w -X main.version={{.Version}}"
}
}
```
## Asset Embedding
### How It Works
Wails uses Go's `embed` package:
```go
package main
import (
"embed"
"github.com/wailsapp/wails/v3/pkg/application"
)
//go:embed frontend/dist
var 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:**
1. Frontend built to `frontend/dist/`
2. `//go:embed` directive includes files
3. Files compiled into binary
4. Binary contains everything
**At runtime:**
1. App starts
2. Assets served from memory
3. No disk I/O for assets
4. Fast loading
### Custom Assets
Embed additional files:
```go
//go:embed frontend/dist
var frontendAssets embed.FS
//go:embed data/*.json
var dataAssets embed.FS
//go:embed templates/*.html
var templateAssets embed.FS
```
## Build Optimisations
### Frontend Optimisations
**Vite (default):**
```javascript
// vite.config.js
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
**Compiler flags:**
```bash
-ldflags="-s -w"
```
- `-s`: Strip symbol table (~10% reduction)
- `-w`: Strip DWARF debug info (~20% reduction)
**Additional optimisations:**
```bash
-ldflags="-s -w -X main.version=1.0.0"
```
- `-X`: Set variable values at build time
- Useful for version numbers, build dates
### Binary Compression
**UPX (optional):**
```bash
# After building
upx --best build/bin/myapp.exe
```
**Results:**
- ~50% size reduction
- Slightly slower startup (~100ms)
- Not recommended for macOS (code signing issues)
## Platform-Specific Builds
### Windows
**Output:** `myapp.exe`
**Includes:**
- Application icon
- Version information
- Manifest (UAC settings)
**Icon:**
```bash
# Specify icon
wails3 build -icon build/appicon.png
```
Wails converts PNG to `.ico` automatically.
**Manifest:**
```xml
<!-- build/windows/manifest.xml -->
<?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>
```
### macOS
**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
<?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:**
```bash
# Build for both architectures
wails3 build -platform darwin/amd64
wails3 build -platform darwin/arm64
# Combine into universal binary
lipo -create -output myapp-universal \
build/bin/myapp-amd64 \
build/bin/myapp-arm64
```
### Linux
**Output:** `myapp` (ELF binary)
**Dependencies:**
- GTK3
- WebKitGTK
**Desktop file:**
```ini
# myapp.desktop
[Desktop Entry]
Name=My App
Exec=/usr/bin/myapp
Icon=myapp
Type=Application
Categories=Utility;
```
**Installation:**
```bash
# Copy binary
sudo cp myapp /usr/bin/
# Copy desktop file
sudo cp myapp.desktop /usr/share/applications/
# Copy icon
sudo cp icon.png /usr/share/icons/hicolor/256x256/apps/myapp.png
```
## Build Performance
### Typical Build Times
| Phase | Time | Notes |
|-------|------|-------|
| Analysis | &lt;1s | Go code scanning |
| Binding Generation | &lt;1s | TypeScript generation |
| Frontend Build | 5-30s | Depends on project size |
| Go Compilation | 2-10s | Depends on code size |
| Asset Embedding | &lt;1s | Embedding frontend |
| **Total** | **10-45s** | First build |
| **Incremental** | **5-15s** | Subsequent builds |
### Speeding Up Builds
**1. Use build cache:**
```bash
# Go build cache is automatic
# Frontend cache (Vite)
npm run build # Uses cache by default
```
**2. Skip unchanged steps:**
```bash
# Skip frontend if unchanged
wails3 build -skipbindings
```
**3. Parallel builds:**
```bash
# Build multiple platforms in parallel
wails3 build -platform windows/amd64 &
wails3 build -platform darwin/amd64 &
wails3 build -platform linux/amd64 &
wait
```
**4. Use faster tools:**
```bash
# Use esbuild instead of webpack
# (Vite uses esbuild by default)
```
## Troubleshooting
### Build Fails
**Symptom:** `wails3 build` exits with error
**Common causes:**
1. **Go compilation error**
```bash
# Check Go code compiles
go build
```
2. **Frontend build error**
```bash
# Check frontend builds
cd frontend
npm run build
```
3. **Missing dependencies**
```bash
# Install dependencies
npm install
go mod download
```
### Binary Too Large
**Symptom:** Binary is >50MB
**Solutions:**
1. **Strip debug symbols** (should be automatic)
```bash
wails3 build # Already includes -ldflags="-s -w"
```
2. **Check embedded assets**
```bash
# Remove unnecessary files from frontend/dist/
# Check for large images, videos, etc.
```
3. **Use UPX compression**
```bash
upx --best build/bin/myapp.exe
```
### Slow Builds
**Symptom:** Builds take >1 minute
**Solutions:**
1. **Use build cache**
- Go cache is automatic
- Frontend cache (Vite) is automatic
2. **Skip unchanged steps**
```bash
wails3 build -skipbindings
```
3. **Optimise frontend build**
```javascript
// vite.config.js
export default {
build: {
minify: 'esbuild', // Faster than terser
},
}
```
## Best Practices
### ✅ Do
- **Use `wails3 dev` during development** - Fast iteration
- **Use `wails3 build` for releases** - Optimised output
- **Version your builds** - Use `-ldflags` to 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
- **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
**Building Applications** - Detailed guide to building and packaging
[Learn More →](/guides/building)
**Cross-Platform Builds** - Build for all platforms from one machine
[Learn More →](/guides/cross-platform)
**Creating Installers** - Create installers for end users
[Learn More →](/guides/installers)
---
**Questions about building?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [build examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/build).