Skip to content

Commit c70713d

Browse files
committed
cmd/link: support MSVC clang
Currently on Windows, for cgo, we support MinGW-based C toolchain, that is, with a -windows-gnu target. This CL makes it work with clang with a -windows-msvc target. The LLVM toolchain bundled in MSVC (https://learn.microsoft.com/en-us/cpp/build/clang-support-msbuild) is such an example. Currently it is expecting lld-link as the C linker, which is also bundled in MSVC, can be requested with -fuse-ld=lld, but is not the default. This is the first step, which makes it generate a working cgo binary. There are still more work to do, e.g. there are some linker warnings, and the binary doesn't have symbol table. all.bat doesn't pass with this setting. Change-Id: I54d33f7dd5f5eeeafa0735cd52f4127fe4865636 Reviewed-on: https://go-review.googlesource.com/c/go/+/703055 Reviewed-by: Than McIntosh <[email protected]> Reviewed-by: Florian Zenker <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 9271bbb commit c70713d

File tree

1 file changed

+56
-16
lines changed
  • src/cmd/link/internal/ld

1 file changed

+56
-16
lines changed

src/cmd/link/internal/ld/lib.go

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,9 @@ func (ctxt *Link) hostlink() {
14571457
// Only macOS supports unmapped segments such as our __DWARF segment.
14581458
combineDwarf := ctxt.IsDarwin() && !*FlagW && machoPlatform == PLATFORM_MACOS
14591459

1460+
var isMSVC bool // used on Windows
1461+
wlPrefix := "-Wl,--"
1462+
14601463
switch ctxt.HeadType {
14611464
case objabi.Hdarwin:
14621465
if combineDwarf {
@@ -1501,22 +1504,34 @@ func (ctxt *Link) hostlink() {
15011504
argv = append(argv, "-Wl,--no-execute-only")
15021505
}
15031506
case objabi.Hwindows:
1507+
isMSVC = ctxt.isMSVC()
1508+
if isMSVC {
1509+
// For various options, MSVC lld-link only accepts one dash.
1510+
// TODO: It seems mingw clang supports one or two dashes,
1511+
// maybe we can always use one dash, but I'm not sure about
1512+
// legacy compilers that currently work.
1513+
wlPrefix = "-Wl,-"
1514+
}
1515+
15041516
if windowsgui {
15051517
argv = append(argv, "-mwindows")
15061518
} else {
15071519
argv = append(argv, "-mconsole")
15081520
}
15091521
// Mark as having awareness of terminal services, to avoid
15101522
// ancient compatibility hacks.
1511-
argv = append(argv, "-Wl,--tsaware")
1523+
1524+
argv = append(argv, wlPrefix+"tsaware")
15121525

15131526
// Enable DEP
1514-
argv = append(argv, "-Wl,--nxcompat")
1527+
argv = append(argv, wlPrefix+"nxcompat")
15151528

1516-
argv = append(argv, fmt.Sprintf("-Wl,--major-os-version=%d", PeMinimumTargetMajorVersion))
1517-
argv = append(argv, fmt.Sprintf("-Wl,--minor-os-version=%d", PeMinimumTargetMinorVersion))
1518-
argv = append(argv, fmt.Sprintf("-Wl,--major-subsystem-version=%d", PeMinimumTargetMajorVersion))
1519-
argv = append(argv, fmt.Sprintf("-Wl,--minor-subsystem-version=%d", PeMinimumTargetMinorVersion))
1529+
if !isMSVC {
1530+
argv = append(argv, fmt.Sprintf("-Wl,--major-os-version=%d", PeMinimumTargetMajorVersion))
1531+
argv = append(argv, fmt.Sprintf("-Wl,--minor-os-version=%d", PeMinimumTargetMinorVersion))
1532+
argv = append(argv, fmt.Sprintf("-Wl,--major-subsystem-version=%d", PeMinimumTargetMajorVersion))
1533+
argv = append(argv, fmt.Sprintf("-Wl,--minor-subsystem-version=%d", PeMinimumTargetMinorVersion))
1534+
}
15201535
case objabi.Haix:
15211536
argv = append(argv, "-pthread")
15221537
// prevent ld to reorder .text functions to keep the same
@@ -1557,16 +1572,21 @@ func (ctxt *Link) hostlink() {
15571572
// an ancient compiler with ancient defaults.
15581573
var dbopt string
15591574
var heopt string
1560-
dbon := "--dynamicbase"
1561-
heon := "--high-entropy-va"
1562-
dboff := "--disable-dynamicbase"
1563-
heoff := "--disable-high-entropy-va"
1575+
dbon := wlPrefix + "dynamicbase"
1576+
heon := wlPrefix + "high-entropy-va"
1577+
dboff := wlPrefix + "disable-dynamicbase"
1578+
heoff := wlPrefix + "disable-high-entropy-va"
1579+
if isMSVC {
1580+
heon = wlPrefix + "highentropyva"
1581+
heoff = wlPrefix + "highentropyva:no"
1582+
dboff = wlPrefix + "dynamicbase:no"
1583+
}
15641584
if val {
15651585
dbopt = dbon
15661586
heopt = heon
15671587
} else {
15681588
// Test to see whether "--disable-dynamicbase" works.
1569-
newer := linkerFlagSupported(ctxt.Arch, argv[0], "", "-Wl,"+dboff)
1589+
newer := linkerFlagSupported(ctxt.Arch, argv[0], "", dboff)
15701590
if newer {
15711591
// Newer compiler, which supports both on/off options.
15721592
dbopt = dboff
@@ -1579,11 +1599,11 @@ func (ctxt *Link) hostlink() {
15791599
}
15801600
}
15811601
if dbopt != "" {
1582-
argv = append(argv, "-Wl,"+dbopt)
1602+
argv = append(argv, dbopt)
15831603
}
15841604
// enable high-entropy ASLR on 64-bit.
15851605
if ctxt.Arch.PtrSize >= 8 && heopt != "" {
1586-
argv = append(argv, "-Wl,"+heopt)
1606+
argv = append(argv, heopt)
15871607
}
15881608
return argv
15891609
}
@@ -1927,9 +1947,11 @@ func (ctxt *Link) hostlink() {
19271947
argv = append(argv, "-lsynchronization")
19281948
}
19291949
}
1930-
// libmingw32 and libmingwex have some inter-dependencies,
1931-
// so must use linker groups.
1932-
argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
1950+
if !isMSVC {
1951+
// libmingw32 and libmingwex have some inter-dependencies,
1952+
// so must use linker groups.
1953+
argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
1954+
}
19331955
argv = append(argv, peimporteddlls()...)
19341956
}
19351957

@@ -2182,6 +2204,7 @@ func trimLinkerArgv(argv []string) []string {
21822204
"-isysroot",
21832205
"--sysroot",
21842206
"-target",
2207+
"--target",
21852208
}
21862209
prefixesToKeep := []string{
21872210
"-f",
@@ -2192,6 +2215,7 @@ func trimLinkerArgv(argv []string) []string {
21922215
"-isysroot",
21932216
"--sysroot",
21942217
"-target",
2218+
"--target",
21952219
}
21962220

21972221
var flags []string
@@ -3024,3 +3048,19 @@ func (ctxt *Link) findExtLinkTool(toolname string) string {
30243048
cmdpath := strings.TrimRight(string(out), "\r\n")
30253049
return cmdpath
30263050
}
3051+
3052+
// isMSVC reports whether the C toolchain is clang with a -msvc target,
3053+
// e.g. the clang bundled in MSVC.
3054+
func (ctxt *Link) isMSVC() bool {
3055+
extld := ctxt.extld()
3056+
name, args := extld[0], extld[1:]
3057+
args = append(args, trimLinkerArgv(flagExtldflags)...)
3058+
args = append(args, "--version")
3059+
cmd := exec.Command(name, args...)
3060+
if out, err := cmd.CombinedOutput(); err == nil {
3061+
if bytes.Contains(out, []byte("-msvc\n")) || bytes.Contains(out, []byte("-msvc\r")) {
3062+
return true
3063+
}
3064+
}
3065+
return false
3066+
}

0 commit comments

Comments
 (0)