Building go2cs from source

This page is for developers who want to build the converter themselves, check its results, or work on it: how to build it, how to run its tests, how to validate a converted package against go test, what its error codes mean, and where things live in the repository.

Build the converter

You need the Go release and the .NET SDK named in the README’s Requirements, with your Go environment set up (GOROOT/GOPATH). Converted projects target the framework named by src/Directory.Build.props. The converter’s module path is plain go2cs, so it cannot be installed by URL: clone the repository and install from the clone, as the README’s Installing the converter shows. Go produces a self-contained native binary; to target another platform, use Go’s standard cross-compilation (GOOS/GOARCH). Rebuild after every pull, with the same Go release you convert with.

go2cs -version prints which release the binary belongs to and which Go toolchain built it, one key=value line per key (Command-line options). Paste it into a bug report.

Run the converter’s own tests

cd go2cs/src/go2cs
go test ./...

The per-feature Go-versus-C# tests live under src/tests/Behavioral: each one is transpiled, compiled and compared against a committed expected output, and each runnable one is executed with its output compared against Go’s. CONTRIBUTING.md says how to run them before you send a change.

Three focused checks run by hand when you change what they guard:

Validate a converted test suite

Every validated package ships its converted C# test sources next to the production code under src/core (for example, unicode/utf8/utf8_test.cs), so you can read the exact C# that runs — and re-run the validation yourself. You need the Go release and the .NET SDK in the README’s Requirements (Go for the reference go test run), and go2cs on your PATH (see Build the converter).

Run it from the root of your clone. The first argument is the package’s Go source, and the second is the package’s home in the converted tree; the converter locates the runtime and the package’s standard-library dependencies from there, so no other flags or environment setup are needed. The ten minutes are the deadline for running the tests and comparing them with go test; building the test host has its own, longer allowance, because the first build compiles the converted runtime and the package’s standard-library dependencies.

PowerShell, on Windows:

go2cs -tests -test-action all -test-timeout 10m "$(go env GOROOT)\src\unicode\utf8" src/core/unicode/utf8

bash, on Linux and macOS:

go2cs -tests -test-action all -test-timeout 10m "$(go env GOROOT)/src/unicode/utf8" src/core/unicode/utf8

Expected final line:

Validated 14 tests against go test (0 skipped identically on both sides, 1 disclosed-divergent (deferred), 47 disclosed-unsupported declarations excluded).

The command converts the _test.go files to C#, generates a test host, builds it against the converted standard library, runs it in an isolated process, captures a clean go test -json -count=1 baseline, and compares terminal results by full Go test name — reporting validated only when every test agrees on both sides and every unsupported declaration (benchmarks, examples) is accounted for. It regenerates the local converted .cs in place; the Go source copies and run manifests it stages are git-ignored. The same command validates every other package on the table — substitute its GOROOT source path and its src/core/<pkg> path in the two arguments.

The test host is published in the Release configuration and run with the CLR’s tiered JIT off (DOTNET_TieredCompilation=0), so every method is compiled once at full optimization and a verdict cannot depend on when the runtime promotes a method; -test-tiered turns tiering back on, and -test-config Debug publishes a Debug host. ReadyToRun is opt-in — set PublishReadyToRun=true in the environment to publish a precompiled host — because it buys a slower steady state on heavy suites, a larger host and a longer first publish, and because precompiled code does not keep the JIT’s stack frames, so a test that asserts on frames can answer differently.

A few packages carry a disclosed divergence: a Go test asserting something the converted runtime does not satisfy — an allocation count Go meets through compiler escape analysis, or a collectibility check Go answers from per-safepoint liveness maps. Some of these a managed runtime provably cannot satisfy; others — marked deferred, such as unicode/utf8’s own zero-allocation TestRuneCountNonASCIIAllocation — it can, and each of those is pinned against the named plan that will retire it. Rather than skip those tests, each affected package pins the divergence in a hand-owned, committed go2cs_test_disclosures.json that the differential oracle matches by exact failure signature — any other failure is still a hard mismatch — and reports as disclosed-divergent in the summary. Packages without a manifest compare strictly.

The GO2CS error codes a conversion reports are listed in Command-line options, Diagnostics.

Project layout

Path Contents
src/go2cs/ The converter (written in Go, using go/ast + go/types).
src/core/ The converted Go standard library — every package, with unsafe and testing hand-written rather than converted. Everything (tests, tour, NuGet) builds against this one tree.
src/core/golib/ The C# runtime library (slice, map, channel, @string, built-ins, type aliases).
src/core/go2cs/ Shared Symbols project — the canonical marker glyphs used by the runtime and the generators.
src/gen/go2cs-gen/ Roslyn source generators (interface implementation, receiver overloads, struct embedding).
src/tour/ Tour of go2cs — the Tour of Go beside a live Go-to-C# workspace.
src/tests/Behavioral/ Per-feature Go↔C# equivalence tests (transpile, compile, run-and-compare).
src/tests/Performance/ Go vs transpiled C# runtime benchmarks (JIT and Native AOT) — see the performance comparison for current numbers.

To build the whole converted standard library in Visual Studio, open the Go Standard Library Solution.

Contributing

Contributors: start with CONTRIBUTING.md, then see Architecture.md, ConversionStrategies.md and Roadmap.md for details. There’s plenty of low-hanging fruit here; jump in if you’d like to help.