Set Up the Environment
vim-go doesn’t support travesal through the go source code, so I switch to vscode and it works out of box (with Go plugin && gopls installed).
Start Point (go run)
- File:
src/cmd/go/main.go - Declaration:
run.CmdRun - Function:
run.runRun - Key data structures:
build.Contextwork.Builderload.Packagework.Action
The runRun function will go through several stages:
- Check
shouldUseOutsideModuleMode. This procedure is used bygo run cmd@version work.BuildInit. This will setup the build context:- Initialize
modloadmodule. It will check go module flags and set up the flags, no actual module download. instrumentInitandbuildModeInit, and update the defaultbuild.Contextaccordingly.
- Initialize
- Get a
work.Builder.work.NewBuilderwill check the environment and make sure it’s ready to do the actual build. - Inits a
load.Packagefrom all*.gofiles passed togo run.load.Packagehas a public struct for definitions, and an internal struct for running state.
- Setup
builder.LinkAction.LinkActionwill callcacheAction(for looking up action cache, not build cache),CompileAction, andinstallAction(not forgo run).work.Actionis a DAG, the action cache depends onmodeand package info.
- Initialize a
work.Action, use the link action initialized at the above stage as dependencies. - Build the
work.Actionwith builder.
Build Stage (Builder.Do)
- Set up the cache trim. There’s a
trim.txtinsidego-buildcache folder, it’s used to track the timestamp of last trim action. - Build the action list, visit the DAG as “depth-first post-order travelsal”. The priority will set by the list order, which means deepest will run first.
writeActionGraph. Internal feature, this will dump the DAG as JSON.- Set up triggers. Triggers are the inverse of dependencies, which means when the dependency ready, it will trigger its root instead of its dependencies.
- The
handlefunction will do the actual jobs.- Actions are run in parallel, the actual job is defined by
action.Func. - After actions done, update the global state. There’s a lock to make sure there’s no data races.
- If all dependencies finished, push the action node to ready queue and signal the
readySema. Ready queue are protected with the same global state lock.
- Actions are run in parallel, the actual job is defined by
- Run all actions from the DAG in parallel.
What’s Next
Travesal through the action.Func definitions:
Builder.buildBuilder.link