--- 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 { 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 **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) **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) ## 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 ``` ### 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 CFBundleName My App CFBundleIdentifier com.example.myapp CFBundleVersion 1.0.0 ``` **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).