golang/go · error
package using cgo has Go assembly file %s
Error message
package using cgo has Go assembly file %s
What it means
For cgo packages, the gas function compiles .s assembly files with gcc (the C assembler). Before doing so it scans each file's bytes for Go-plan9-assembler directives TEXT, DATA, or GLOBL (at the start or after a newline). If any are present, the build aborts because a cgo package cannot mix Go-style assembly with C-style assembly; the flagged file must use GAS syntax instead.
Source
Thrown at src/cmd/go/internal/work/exec.go:2546
func (noToolchain) cc(b *Builder, a *Action, ofile, cfile string) error {
return noCompiler()
}
// gcc runs the gcc C compiler to create an object from a single C file.
func (b *Builder) gcc(a *Action, workdir, out string, flags []string, cfile string) error {
p := a.Package
return b.ccompile(a, out, flags, cfile, b.GccCmd(p.Dir, workdir))
}
// gas runs the gcc c compiler to create an object file from a single C assembly file.
func (b *Builder) gas(a *Action, workdir, out string, flags []string, sfile string) error {
p := a.Package
data, err := os.ReadFile(sfile)
if err == nil {
if bytes.HasPrefix(data, []byte("TEXT")) || bytes.Contains(data, []byte("\nTEXT")) ||
bytes.HasPrefix(data, []byte("DATA")) || bytes.Contains(data, []byte("\nDATA")) ||
bytes.HasPrefix(data, []byte("GLOBL")) || bytes.Contains(data, []byte("\nGLOBL")) {
return fmt.Errorf("package using cgo has Go assembly file %s", sfile)
}
}
return b.ccompile(a, out, flags, sfile, b.GccCmd(p.Dir, workdir))
}
// gxx runs the g++ C++ compiler to create an object from a single C++ file.
func (b *Builder) gxx(a *Action, workdir, out string, flags []string, cxxfile string) error {
p := a.Package
return b.ccompile(a, out, flags, cxxfile, b.GxxCmd(p.Dir, workdir))
}
// gfortran runs the gfortran Fortran compiler to create an object from a single Fortran file.
func (b *Builder) gfortran(a *Action, workdir, out string, flags []string, ffile string) error {
p := a.Package
return b.ccompile(a, out, flags, ffile, b.gfortranCmd(p.Dir, workdir))
}
// ccompile runs the given C or C++ compiler and creates an object from a single source file.View on GitHub (pinned to b6b368adc5)
Solutions
- Open the flagged .s file and confirm it uses Go-assembler directives (TEXT/DATA/GLOBL)
- Rewrite the file in standard GAS (C) assembly syntax, or remove it
- Move the Go assembly into a separate non-cgo package that builds with the gc assembler
Example fix
// before (Go asm in a cgo package .s file)
TEXT ·myFunc(SB), $0
RET
// after (GAS syntax, or delete and implement in Go)
myfunc:
ret Defensive patterns
Strategy: validation
Validate before calling
// Scan .s files for Go-assembler directives before a cgo build
func hasGoAsmDirectives(path string) bool {
data, err := os.ReadFile(path)
if err != nil { return false }
for _, d := range []string{"TEXT", "DATA", "GLOBL"} {
if bytes.HasPrefix(data, []byte(d)) || bytes.Contains(data, []byte("\n"+d)) {
return true
}
}
return false
} Prevention
- Keep Go-plan9 assembly (.s with TEXT/DATA/GLOBL) out of cgo packages
- Use GAS syntax for assembly in cgo packages, or implement in Go
- Audit copied .s files when moving them between cgo and non-cgo packages
When it happens
Trigger: Fires in gas when bytes.HasPrefix or bytes.Contains matches TEXT, DATA, or GLOBL in an assembly file of a package that uses cgo.
Common situations: Copying a Go assembly file (from a non-cgo package) into a cgo package, or writing Go-assembler syntax in a .s file that is compiled through the cgo/gcc path.
Related errors
- CC not set and no default found
- unterminated quoted string in pkgconf output
- broken character escaping in pkgconf output
- must have SWIG version >= 3.0.6
- SWIG file must not use prefix 'cgo'
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/cae0a9c9e3c30d05.
Report an issue: GitHub.