Skip to content

CI 在 Linux runner 上编译失败:cmd/tui/main.go 使用了 Windows 专用的 syscall.NewLazyDLL #44

@pionxe

Description

@pionxe

问题描述

当前仓库的 GitHub Actions 自动测试在 Linux runner 上失败,错误如下:

Error: cmd/tui/main.go:327:22: undefined: syscall.NewLazyDLL
Error: Process completed with exit code 1.

失败位置在:

  • cmd/tui/main.go:327

相关代码类似:

func setWindowsUTF8() {
    kernel32 := syscall.NewLazyDLL("kernel32.dll")
    setConsoleOutputCP := kernel32.NewProc("SetConsoleOutputCP")
    setConsoleCP := kernel32.NewProc("SetConsoleCP")

    setConsoleOutputCP.Call(uintptr(65001))
    setConsoleCP.Call(uintptr(65001))
}

复现方式

在 Linux 环境,或使用 Linux 目标平台进行编译/测试时可复现,例如:

go test ./...

或者:

GOOS=linux GOARCH=amd64 go test ./...

实际结果

CI 在编译阶段直接失败,无法继续执行测试与覆盖率上传。

预期结果

仓库应当能够在 Linux runner 上正常完成:

  • go build ./...
  • go test ./...

即使某段逻辑仅在 Windows 下运行,也不应阻塞 Linux 平台的编译。

原因分析

syscall.NewLazyDLL 是 Windows 专用 API。

虽然当前代码在运行时有类似 runtime.GOOS == "windows" 的判断,但 Go 会先对整个文件进行编译。
因此只要 Windows 专用符号出现在通用源码文件中,Linux 平台在编译阶段就会报:

undefined: syscall.NewLazyDLL

也就是说,这是一个编译期平台兼容性问题,不是运行期判断可以规避的问题。

影响范围

  • GitHub Actions 默认使用 ubuntu-latest
  • 所有 Linux 环境下的 CI / build / test 都会受到影响
  • 覆盖率上报也会被连带阻塞

建议修复方案

将平台相关逻辑拆分为带 build tag 的独立文件,例如:

  • cmd/tui/utf8_windows.go
  • cmd/tui/utf8_other.go

推荐方式:

  • utf8_windows.go 中保留 syscall.NewLazyDLL 的 Windows 实现
  • utf8_other.go 中提供空实现
  • main.go 中仅调用统一的 setUTF8Mode(),不要直接引用 Windows 专用符号

示例思路:

//go:build windows
func setUTF8Mode() {
    // Windows 实现
}
//go:build !windows
func setUTF8Mode() {}

补充说明

这是一个典型的跨平台构建问题。
建议后续凡是涉及:

  • syscall
  • kernel32.dll
  • Windows 控制台 API
  • Unix / Windows 差异命令

都优先使用 build tags 做平台隔离,避免类似问题再次进入 CI。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions