700 lines
13 KiB
Text
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** (<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 | <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
|
|
|
|
**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).
|