π¨ Exercise 1: Compiling Go Without Changes
In this exercise, you’ll learn how to build the Go toolchain from the source code without making any modifications. This is an essential skill before we start making changes to the language! β‘
π― Learning Objectives
By the end of this exercise, you will:
- β Understand the Go build process and bootstrap concept
- β Successfully compile Go from source
- β Know how to explore Go source code structure
- β Know how to test your custom Go build
π₯Ύ Step 1: Understanding the Bootstrap Process
Go is written in Go itself! π€ This creates a “chicken and egg” problem - how do you compile Go without having Go? The solution is bootstrapping:
- π¦ The Go team provides pre-compiled binaries
- π¨ These binaries compile the current Go source code
- β¨ The newly compiled version can then be used for development
Let’s check if you have Go installed (needed for bootstrapping): π
go version
# Must show version 1.24.6 or newer
β οΈ Critical: You must have Go 1.24.6 or newer installed to build Go 1.25.1. If you don’t have Go installed or your version is too old, install the latest version from https://golang.org/dl/ π₯
π Step 2: Navigate to the Go Source Directory
cd go/src
pwd
# Should show: /path/to/workshop/go/src
# Verify you're on the correct Go version
git describe --tags
# Should show: go1.25.1
π Step 3: Start the Build Process
Go provides different scripts for building. Let’s start with make.bash
which builds the toolchain, then explore the source code while it’s running! β‘
On Unix-like systems (Linux, macOS):
./make.bash
On Windows:
make.bat
This script will: π
- π¨ Build the Go toolchain (compiler, linker, runtime, standard library)
- β±οΈ Take approximately 2-10 minutes depending on your system
π Note: The first time you run this, it will take longer as it needs to compile everything from scratch.
π€ What about all.bash
and run.bash
?
You might wonder about other scripts in the src/
directory:
- π¨
make.bash
: Builds the Go toolchain only (what we’re using) - π§ͺ
run.bash
: Runs the comprehensive test suite (requires Go to be built first)
- π¦
all.bash
: Convenience script that runsmake.bash
+run.bash
+ prints build info
For this workshop, make.bash
is perfect because:
- β Faster build time means less waiting
- β We just need a working Go build for our experiments
- β
We can run tests later if needed with
run.bash
π Step 4: Explore Source Code While Building
While the build is running, open a new terminal or IDE and let’s explore the Go source code structure! This is a great time to understand what we’re building. π§
In your new terminal:
cd /path/to/workshop/go # Navigate to your Go source directory
ls -la
π Repository Structure
Key directories you should see:
- π
src/
: Contains the Go source code- π οΈ
src/cmd/
: Command-line tools (go, gofmt, etc.) - βοΈ
src/runtime/
: Go runtime system - π³
src/go/
: Go language packages (parser, AST, etc.)
- π οΈ
- π§ͺ
test/
: Test files for the Go language - π
api/
: API compatibility data - π
doc/
: Documentation
ποΈ Examine the Go Compiler Structure
The Go compiler is located in src/cmd/compile/
. Let’s explore it: π§
cd src/cmd/compile
ls -la
Key files and directories:
- πͺ
main.go
: Entry point of the compiler - π¦
internal/
: Internal compiler packages- π€
internal/syntax/
: Lexer/parser (scanner, parser) - β
internal/types2/
: Type checker - π
internal/ir/
: Intermediate representation - β‘
internal/gc/
: Code generation
- π€
π Step 5: Understanding the Build Output
Switch back to your original terminal where the build is running. As the build progresses, you should see output like: π
Building Go cmd/dist using /usr/local/go. (go1.25.1 darwin/amd64)
Building Go toolchain1 using /usr/local/go.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for darwin/amd64.
This shows the multi-stage bootstrap process:
- The compiler is build with the go version installed in your system (toolchain1)
- Then the compiler is built again using the toolchain1 to produce the toolchain2
- Finally the toolchain3 is generated using the toolchain2.
- The toolchain3 and toolchain2 should be identical
π Step 6: Locate Your Compiled Go Binary
After successful compilation, your new Go binary will be in: π―
ls -la /path/to/workshop/go/bin
You should see:
- π
go
- The main Go command - π¨
gofmt
- Go formatter - π οΈ Other Go tools
π§ͺ Step 7: Test Your Custom Go Build
Let’s test your newly compiled Go: β¨
# Check version of your compiled Go
../bin/go version
Create a hello.go in the a temporary directory, for example /tmp
.
package main
import "fmt"
func main() {
fmt.Println("Hello from my custom Go build!")
}
# Compile and run with your custom Go
/path/to/workshop/go/bin/go run /tmp/hello.go
π What We Learned
- π₯Ύ Bootstrap Process: Go compiles itself using an existing Go installation
- ποΈ Go Source Structure: Well-organized codebase with clear separation (cmd/, runtime/, etc.)
- β‘ Build Process:
./make.bash
builds everything
π Next Steps
Congratulations! π You now have a working Go toolchain built from source.
You can now proceed with any of the following exercises to learn about different parts of Go:
- Exercise 2: Adding the “=>” Arrow Operator for Goroutines - Scanner modifications
- Exercise 3: Multiple “go” Keywords - Parser Enhancement - Parser modifications
- Exercise 4: Inline Parameters - Function Inlining Experiments - Compiler parameters
- Exercise 5: gofmt Transformation - “hello” to “helo” - AST transformations
- Exercise 6: SSA Pass - Detecting Division by Powers of Two - SSA compiler passes
- Exercise 7: Patient Go - Making Go Wait for Goroutines - Runtime modifications
- Exercise 8: Goroutine Sleep Detective - Runtime State Monitoring - Scheduler monitoring
- Exercise 9: Predictable Select - Removing Randomness from Go’s Select Statement - Select behavior
- Exercise 10: Java-Style Stack Traces - Making Go Panics Look Familiar - Error formatting
Or return to the main workshop to choose an exercise.