[go] cmd/go: add .dll suffix to default c-shared output on windows

3 views
Skip to first unread message

Gerrit Bot (Gerrit)

unread,
Sep 23, 2026, 6:36:31 AMSep 23
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Gerrit Bot has uploaded the change for review

Commit message

cmd/go: add .dll suffix to default c-shared output on windows

When building a main package with -buildmode=c-shared for Windows
without the -o flag, go build named the output file after the package
with no extension, for example "mylib" instead of "mylib.dll". The
DLL file name is recorded in the PE export section at link time, so
renaming the file afterwards does not produce a usable DLL.

Set the executable suffix to ".dll" for -buildmode=c-shared on
Windows, like -buildmode=c-archive uses ".a" and -buildmode=plugin
uses ".so".

LinkAction appended the executable suffix to the temporary link
output name even when that name was taken from the package target,
which already is the final file name. With a non-empty suffix this
would link "mylib.dll.dll" and record that name in the DLL. Append
the suffix only to the default names, so the name recorded in the
DLL matches the file written by go build, with or without -o.

Fixes #38244
Change-Id: I633c3b376e8b3dcc473527be7199bfd76fc4d63c
GitHub-Last-Rev: 5df04508de803b185c07b8bc0c8fdd4b48bf9f60
GitHub-Pull-Request: golang/go#81703

Change diff

diff --git a/doc/next/3-tools.md b/doc/next/3-tools.md
index 730e5e0..cd4baba 100644
--- a/doc/next/3-tools.md
+++ b/doc/next/3-tools.md
@@ -2,6 +2,10 @@

### Go command {#go-command}

+When building for Windows with `-buildmode=c-shared` and no `-o` flag,
+`go build` now names the output file with a `.dll` extension.
+Previously the file had no extension. <!-- go.dev/issue/38244 -->
+
### Cgo {#cgo}

### Vet {#vet}
diff --git a/src/cmd/go/internal/work/action.go b/src/cmd/go/internal/work/action.go
index 5e27ff6..51cabfd 100644
--- a/src/cmd/go/internal/work/action.go
+++ b/src/cmd/go/internal/work/action.go
@@ -941,9 +941,9 @@
// in an otherwise empty subdirectory named exe to avoid
// naming conflicts. The only possible conflict is if we were
// to create a top-level package named exe.
- name := "a.out"
+ name := "a.out" + cfg.ExeSuffix
if p.Internal.ExeName != "" {
- name = p.Internal.ExeName
+ name = p.Internal.ExeName + cfg.ExeSuffix
} else if (cfg.Goos == "darwin" || cfg.Goos == "windows") && cfg.BuildBuildmode == "c-shared" && p.Target != "" {
// On OS X, the linker output name gets recorded in the
// shared library's LC_ID_DYLIB load command.
@@ -952,9 +952,10 @@
// we'll install it as; otherwise the library is only loadable as "a.out".
// On Windows, DLL file name is recorded in PE file
// export section, so do like on OS X.
+ // The target name is used as is, without adding cfg.ExeSuffix.
_, name = filepath.Split(p.Target)
}
- a.Target = a.Objdir + filepath.Join("exe", name) + cfg.ExeSuffix
+ a.Target = a.Objdir + filepath.Join("exe", name)
a.built = a.Target
b.addTransitiveLinkDeps(s, a, exportAction, "")

diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go
index 9226dd3..cee8ad2 100644
--- a/src/cmd/go/internal/work/init.go
+++ b/src/cmd/go/internal/work/init.go
@@ -253,8 +253,7 @@
case "linux", "android", "freebsd":
codegenArg = "-shared"
case "windows":
- // Do not add usual .exe suffix to the .dll file.
- cfg.ExeSuffix = ""
+ cfg.ExeSuffix = ".dll"
}
}
ldBuildmode = "c-shared"
diff --git a/src/cmd/go/testdata/script/build_cshared_windows_dll.txt b/src/cmd/go/testdata/script/build_cshared_windows_dll.txt
new file mode 100644
index 0000000..0816f38
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_cshared_windows_dll.txt
@@ -0,0 +1,51 @@
+# Issue #38244: when building for Windows with -buildmode=c-shared
+# and no -o flag, the output file should have a .dll extension.
+
+[compiler:gccgo] skip 'gccgo does not cross-compile to windows here'
+
+# Cross-compile with -n so that no C toolchain for Windows is needed.
+env GOOS=windows
+env GOARCH=amd64
+env CGO_ENABLED=1
+
+go build -n -buildmode=c-shared
+stderr ' -o mylib\.dll '
+stderr '^mv \$WORK[/\\]b001[/\\]exe[/\\]mylib\.dll mylib\.dll$'
+
+# An explicit -o name is used as is.
+go build -n -buildmode=c-shared -o other.dll
+stderr ' -o other\.dll '
+stderr '^mv \$WORK[/\\]b001[/\\]exe[/\\]other\.dll other\.dll$'
+
+go build -n -buildmode=c-shared -o noext
+stderr ' -o noext '
+stderr '^mv \$WORK[/\\]b001[/\\]exe[/\\]noext noext$'
+
+# Build for real on Windows hosts that support c-shared.
+[!GOOS:windows] stop
+[short] stop
+[!cgo] stop
+[!buildmode:c-shared] stop
+
+env GOOS=
+env GOARCH=
+env CGO_ENABLED=
+
+go build -buildmode=c-shared
+exists mylib.dll
+exists mylib.h
+! exists mylib
+
+-- go.mod --
+module example.com/mylib
+
+go 1.27
+-- main.go --
+package main
+
+import "C"
+
+//export Hello
+func Hello() {}
+
+func main() {}

Change information

Files:
  • M doc/next/3-tools.md
  • M src/cmd/go/internal/work/action.go
  • M src/cmd/go/internal/work/init.go
  • A src/cmd/go/testdata/script/build_cshared_windows_dll.txt
Change size: M
Delta: 4 files changed, 60 insertions(+), 5 deletions(-)
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newchange
Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I633c3b376e8b3dcc473527be7199bfd76fc4d63c
Gerrit-Change-Number: 837386
Gerrit-PatchSet: 1
Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

qiu laidongfeng (Gerrit)

unread,
Sep 23, 2026, 10:30:27 AMSep 23
to Gerrit Bot, goph...@pubsubhelper.golang.org, Michael Matloob, Gopher Robot, golang-co...@googlegroups.com
Attention needed from Michael Matloob

qiu laidongfeng voted Commit-Queue+1

Commit-Queue+1
Open in Gerrit

Related details

Attention is currently required from:
  • Michael Matloob
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I633c3b376e8b3dcc473527be7199bfd76fc4d63c
Gerrit-Change-Number: 837386
Gerrit-PatchSet: 1
Gerrit-Owner: Gerrit Bot <letsus...@gmail.com>
Gerrit-Reviewer: Michael Matloob <mat...@golang.org>
Gerrit-Reviewer: qiu laidongfeng <26454...@qq.com>
Gerrit-CC: Gopher Robot <go...@golang.org>
Gerrit-Attention: Michael Matloob <mat...@golang.org>
Gerrit-Comment-Date: Wed, 23 Sep 2026 14:30:16 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
unsatisfied_requirement
satisfied_requirement
open
diffy
Reply all
Reply to author
Forward
0 new messages