{"record":{"id":"452e01a126629d74","repo":"golang/go","slug":"s-requires-external-cgo-linking-but-cgo-is-not","errorCode":null,"errorMessage":"%s requires external (cgo) linking, but cgo is not enabled","messagePattern":"(.+?) requires external \\(cgo\\) linking, but cgo is not enabled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/load/pkg.go","lineNumber":2683,"sourceCode":"// We accept leading . _ and / as likely in file system paths.\n// There is a copy of this function in cmd/compile/internal/noder/noder.go.\nfunc SafeArg(name string) bool {\n\tif name == \"\" {\n\t\treturn false\n\t}\n\tc := name[0]\n\treturn '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf\n}\n\n// LinkerDeps returns the list of linker-induced dependencies for main package p.\nfunc LinkerDeps(s *modload.Loader, p *Package) ([]string, error) {\n\t// Everything links runtime.\n\tdeps := []string{\"runtime\"}\n\n\t// External linking mode forces an import of runtime/cgo.\n\tif what := externalLinkingReason(s, p); what != \"\" && cfg.BuildContext.Compiler != \"gccgo\" {\n\t\tif !cfg.BuildContext.CgoEnabled {\n\t\t\treturn nil, fmt.Errorf(\"%s requires external (cgo) linking, but cgo is not enabled\", what)\n\t\t}\n\t\tdeps = append(deps, \"runtime/cgo\")\n\t}\n\t// On ARM with GOARM=5, it forces an import of math, for soft floating point.\n\tif cfg.Goarch == \"arm\" {\n\t\tdeps = append(deps, \"math\")\n\t}\n\t// Using the race detector forces an import of runtime/race.\n\tif cfg.BuildRace {\n\t\tdeps = append(deps, \"runtime/race\")\n\t}\n\t// Using memory sanitizer forces an import of runtime/msan.\n\tif cfg.BuildMSan {\n\t\tdeps = append(deps, \"runtime/msan\")\n\t}\n\t// Using address sanitizer forces an import of runtime/asan.\n\tif cfg.BuildASan {\n\t\tdeps = append(deps, \"runtime/asan\")","sourceCodeStart":2665,"sourceCodeEnd":2701,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/load/pkg.go#L2665-L2701","documentation":"Returned by LinkerDeps at line 2687. externalLinkingReason (line 2714) decides the final binary must use external (cgo) linking — because the target platform always requires it (platform.MustLinkExternal, e.g. some os/arch combos), because of -buildmode=c-shared/plugin, because of -linkshared, because PIE on a platform without internal-link PIE support, or because -ldflags=-linkmode=external was passed. If cgo is then disabled (cfg.BuildContext.CgoEnabled false, and compiler != gccgo), runtime/cgo cannot be pulled in and the build aborts. gccgo is exempt because it links externally natively.","triggerScenarios":"Building with CGO_ENABLED=0 while any of: targeting a platform in platform.MustLinkExternal; -buildmode=c-shared or -plugin (non-wasm); -linkshared; -buildmode=pie on a platform lacking InternalLinkPIESupported; or -ldflags=-linkmode=external.","commonSituations":"Docker `CGO_ENABLED=0` scratch images combined with `-buildmode=pie` or `-buildmode=c-shared`; cross-compiling to darwin/arm64 or android with cgo off; CI hardening setting PIE defaults while forcing static binaries; passing -linkshared without a cgo-enabled toolchain.","solutions":["Enable cgo: set CGO_ENABLED=1 and ensure a C compiler (gcc/clang) is on PATH for the target.","Remove the constraint that forces external linking: drop -buildmode=c-shared/plugin/pie, drop -linkshared, or drop -ldflags=-linkmode=external.","If you must ship a static binary, switch to a target/platform that supports internal linking and drop the external-linking buildmode.","On gccgo the check is skipped, but switching compiler is rarely the right fix — prefer enabling cgo."],"exampleFix":"# before\nCGO_ENABLED=0 go build -buildmode=pie ./cmd/app\n# after\nCGO_ENABLED=1 go build -buildmode=pie ./cmd/app   # or drop -buildmode=pie","handlingStrategy":"validation","validationCode":"// Detect the conflict up front: if any external-linking-forcing flag is set,\n// CGO must be enabled. Mirror externalLinkingReason's decision inputs.\npackage buildcheck\n\nimport (\n\t\"errors\"\n\t\"os\"\n\t\"strings\"\n)\n\n// platforms that always require external linking; consult cmd/go's\n// platform.MustLinkExternal for the authoritative list.\nvar mustLinkExternal = map[string]bool{\n\t\"android/arm\": true, // etc.\n}\n\nfunc CgoCompatibleWithFlags(goos, goarch, buildmode, ldflags string) error {\n\tcgoEnabled := os.Getenv(\"CGO_ENABLED\") != \"0\"\n\tforcesExternal := false\n\tswitch buildmode {\n\tcase \"c-shared\", \"plugin\":\n\t\tforcesExternal = true\n\tcase \"pie\":\n\t\tforcesExternal = true // conservative; depends on InternalLinkPIESupported\n\t}\n\tif strings.Contains(ldflags, \"-linkmode=external\") {\n\t\tforcesExternal = true\n\t}\n\tif mustLinkExternal[goos+\"/\"+goarch] {\n\t\tforcesExternal = true\n\t}\n\tif forcesExternal && !cgoEnabled {\n\t\treturn errors.New(\"selected build flags require external (cgo) linking; set CGO_ENABLED=1\")\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"// If a scripted build fails with this message, retry with cgo enabled:\n//\n//   cmd := exec.Command(\"go\", \"build\", flags...)\n//   if out, err := cmd.CombinedOutput(); err != nil &&\n//      bytes.Contains(out, []byte(\"requires external (cgo) linking\")) {\n//       cmd = exec.Command(\"go\", append([]string{\"env\", \"-w\", \"CGO_ENABLED=1\"})...)\n//       _ = cmd.Run()\n//   }","preventionTips":["Never combine `CGO_ENABLED=0` with `-buildmode=pie/c-shared/plugin` or `-linkshared` without verifying the platform supports internal linking.","In Dockerfiles, set CGO_ENABLED explicitly and document why — silent defaults cause this collision."],"tags":["cgo","linking","buildmode","pie","toolchain","build"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}