Go version
go version go1.26.1 windows/amd64
Output of go env in your module/workspace:
set AR=ar
set CC=gcc
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_ENABLED=1
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set CXX=g++
set GCCGO=gccgo
set GO111MODULE=
set GOAMD64=v1
set GOARCH=amd64
set GOAUTH=netrc
set GOBIN=
set GOCACHE=C:\Users\Stef\AppData\Local\go-build
set GOCACHEPROG=
set GODEBUG=
set GOENV=C:\Users\Stef\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFIPS140=off
set GOFLAGS=
set GOGCCFLAGS=-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=C:\Users\Stef\AppData\Local\Temp\go-build3706808720=/tmp/go-build -gno-record-gcc-switches
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMOD=C:\Users\Stef\Desktop\Projects\goWinDLLBug\go.mod
set GOMODCACHE=C:\Users\Stef\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\Stef\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTELEMETRY=local
set GOTELEMETRYDIR=C:\Users\Stef\AppData\Roaming\go\telemetry
set GOTMPDIR=
set GOTOOLCHAIN=auto
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.26.1
set GOWORK=
set PKG_CONFIG=pkg-config
What did you do?
Build a Go DLL using -buildmode=c-shared on Windows without an explicit -o flag:
go build -buildmode=c-shared ./cmd/mypackage
What did you see happen?
C:\Program Files\Go\pkg\tool\windows_amd64\link.exe: running gcc failed: exit status 1
C:\x86_64-15.2.0-release-posix-seh-msvcrt-rt_v13-rev0\mingw64\bin\gcc.exe -m64 -mconsole -Wl,--tsaware -Wl,--nxcompat -Wl,--major-os-version=6 -Wl,--minor-os-version=1 -Wl,--major-subsystem-version=6 -Wl,--minor-subsystem-version=1 -shared -Wl,--dynamicbase -Wl,--high-entropy-va -o mypackage. ..\..\..\..\AppData\Local\Temp\go-link-532916933\export_file.def -Wl,--no-insert-timestamp ..\..\..\..\AppData\Local\Temp\go-link-532916933\go.o ..\..\..\..\AppData\Local\Temp\go-link-532916933\000000.o ..\..\..\..\AppData\Local\Temp\go-link-532916933\000001.o ..\..\..\..\AppData\Local\Temp\go-link-532916933\000002.o ..\..\..\..\AppData\Local\Temp\go-link-532916933\000003.o ..\..\..\..\AppData\Local\Temp\go-link-532916933\000004.o ..\..\..\..\AppData\Local\Temp\go-link-532916933\000005.o ..\..\..\..\AppData\Local\Temp\go-link-532916933\000006.o ..\..\..\..\AppData\Local\Temp\go-link-532916933\000007.o ..\..\..\..\AppData\Local\Temp\go-link-532916933\000008.o ..\..\..\..\AppData\Local\Temp\go-link-532916933\000009.o -O2 -g -O2 -g -Wl,-T,C:\Users\Stef\AppData\Local\Temp\go-link-532916933\fix_debug_gdb_scripts.ld -Wl,--start-group -lmingwex -lmingw32 -Wl,--end-group -lkernel32
C:/x86_64-15.2.0-release-posix-seh-msvcrt-rt_v13-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/15.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: ..\..\..\..\AppData\Local\Temp\go-link-532916933\export_file.def:3: syntax error
C:/x86_64-15.2.0-release-posix-seh-msvcrt-rt_v13-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/15.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:C:\Users\Stef\AppData\Local\Temp\go-link-532916933\export_file.def: file format not recognized; treating as linker script
C:/x86_64-15.2.0-release-posix-seh-msvcrt-rt_v13-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/15.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:C:\Users\Stef\AppData\Local\Temp\go-link-532916933\export_file.def:1: syntax error
collect2.exe: error: ld returned 1 exit status
What did you expect to see?
A successful build producing a DLL, as was the case with Go 1.25.
Analysis
Go 1.26 introduced peCreateExportFile in src/cmd/link/internal/ld/pe.go which generates an export_file.def for controlling DLL symbol exports. The library name is derived from the output filename via filepath.Base(outopt) at lib.go:1823:
case ctxt.IsWindows() && !slices.Contains(flagExtldflags, wlPrefix+"export-all-symbols"):
fileName := peCreateExportFile(ctxt, filepath.Base(outopt))
When no -o flag is specified with -buildmode=c-shared, the output name is mypackage. (trailing dot, no extension). This produces:
LIBRARY mypackage.
EXPORTS
Hello
GNU ld (Binutils 2.45, tested with MinGW GCC 15.2.0) rejects the trailing dot in the LIBRARY directive as a syntax error.
Environment
- Windows 10 amd64
- MinGW GCC 15.2.0 (x86_64-posix-seh-msvcrt)
- GNU ld (GNU Binutils) 2.45
Repro
https://github.com/ElMostafaIdrassi/goWinDLLBug
Go version
go version go1.26.1 windows/amd64
Output of
go envin your module/workspace:What did you do?
Build a Go DLL using
-buildmode=c-sharedon Windows without an explicit-oflag:What did you see happen?
What did you expect to see?
A successful build producing a DLL, as was the case with Go 1.25.
Analysis
Go 1.26 introduced
peCreateExportFileinsrc/cmd/link/internal/ld/pe.gowhich generates anexport_file.deffor controlling DLL symbol exports. The library name is derived from the output filename viafilepath.Base(outopt)atlib.go:1823:When no -o flag is specified with
-buildmode=c-shared, the output name ismypackage.(trailing dot, no extension). This produces:GNU ld (Binutils 2.45, tested with MinGW GCC 15.2.0)rejects the trailing dot in theLIBRARYdirective as a syntax error.Environment
Repro
https://github.com/ElMostafaIdrassi/goWinDLLBug