Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

目标平台为 Windows 时 Clang 工具链不主动加载 MSVC 编译环境 #5978

Closed
Doekin opened this issue Dec 16, 2024 · 13 comments
Closed
Labels

Comments

@Doekin
Copy link
Contributor

Doekin commented Dec 16, 2024

Xmake 版本

xmake v2.9.6+HEAD.abd15c255

操作系统版本和架构

Windows 10

描述问题

使用 Clang 工具链(LLVM-MinGW)为 Windows 平台构建程序,出现找不到标准库头文件的错误

fatal error: 'stdio.h' file not found
    1 | #include <stdio.h>
      |          ^~~~~~~~~

而在 Developer PowerShell 中执行 clang -m64 --target=x86_64-windows-msvc src\hello.c 可以正常编译

期待的结果

使用 Clang 工具链时,能主动加载 MSVC 环境(类似使用 MSVC 工具链时 XMake 的行为)

工程配置

$ xmake f -c -vD --toolchain=clang
$ xmake -r -vD hello_c

附加信息和错误日志

诊断日志

checking for clang ... ok
checking for the c compiler (cc) ... clang
checking for flags (-O3) ... ok
> clang "-O3" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
checking for flags (-DNDEBUG) ... ok
> clang "-DNDEBUG" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
checking for clang ... ok
checking for the c++ compiler (cxx) ... clang
[ 50%]: cache compiling.release src\hello.c
clang -c -Qunused-arguments -m64 --target=x86_64-windows-msvc -fvisibility=hidden -O3 -DNDEBUG -o build\.objs\hello_c\windows\x64\release\src\hello.c.obj src\hello.c
checking for flags (-MMD -MF) ... ok
> clang "-MMD" "-MF" "C:\Users\leemu\AppData\Local\Temp\.xmake\241216\_2C63DED93CDF473082B0786F9FF45880" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
checking for flags (-fdiagnostics-color=always) ... ok
> clang "-fdiagnostics-color=always" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
checking for flags (-fansi-escape-codes) ... ok
> clang "-fansi-escape-codes" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
checking for flags (-Wno-gnu-line-marker -Werror) ... ok
> clang "-Wno-gnu-line-marker" "-Werror" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
error: @programdir\core\main.lua:329: @programdir\actions\build\main.lua:148: @programdir\modules\async\runjobs.lua:325: @programdir\modules\private\action\build\object.lua:91: @programdir\modules\core\tools\gcc.lua:966: src\hello.c:1:10:
 fatal error: 'stdio.h' file not found
    1 | #include <stdio.h>
      |          ^~~~~~~~~
1 error generated.
stack traceback:
    [C]: in function 'error'
    [@programdir\core\base\os.lua:1004]:
    [@programdir\modules\core\tools\gcc.lua:966]: in function 'catch'
    [@programdir\core\sandbox\modules\try.lua:123]: in function 'try'
    [@programdir\modules\core\tools\gcc.lua:907]:
    [C]: in function 'xpcall'
    [@programdir\core\base\utils.lua:244]:
    [@programdir\core\tool\compiler.lua:288]: in function 'compile'
    [@programdir\modules\private\action\build\object.lua:91]: in function 'script'
    [@programdir\modules\private\action\build\object.lua:122]: in function 'build_object'
    [@programdir\modules\private\action\build\object.lua:147]: in function 'jobfunc'
    [@programdir\modules\async\runjobs.lua:241]:
    [C]: in function 'xpcall'
    [@programdir\core\base\utils.lua:244]: in function 'trycall'
    [@programdir\core\sandbox\modules\try.lua:117]: in function 'try'
    [@programdir\modules\async\runjobs.lua:223]: in function 'cotask'
    [@programdir\core\base\scheduler.lua:406]:

stack traceback:
        [C]: in function 'error'
        @programdir\core\base\os.lua:1004: in function 'base/os.raiselevel'
        (...tail calls...)
        @programdir\core\main.lua:329: in upvalue 'cotask'
        @programdir\core\base\scheduler.lua:406: in function <@programdir\core\base\scheduler.lua:399>
@Doekin Doekin added the bug label Dec 16, 2024
@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


Title: When the target platform is Windows, the Clang tool chain does not actively load the MSVC compilation environment

@Doekin
Copy link
Contributor Author

Doekin commented Dec 16, 2024

Update

Clang 在目标平台为 Windows 时,是会加载 MSVC 环境变量的,只是不知道为什么,似乎不太管用

if toolchain:is_plat("windows") then
target = target .. "-windows-msvc"
-- add vs environments
local expect_vars = {"PATH", "LIB", "INCLUDE", "LIBPATH"}
local curenvs = os.getenvs()
for _, name in ipairs(expect_vars) do
_add_vsenv(toolchain, name, curenvs)
end
for _, name in ipairs(find_vstudio.get_vcvars()) do
if not table.contains(expect_vars, name:upper()) then
_add_vsenv(toolchain, name, curenvs)
end
end
if is_host("linux") then
toolchain:add("ldflags", "-fuse-ld=lld-link" .. suffix)
toolchain:add("shflags", "-fuse-ld=lld-link" .. suffix)
end

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


Update

Clang will load the MSVC environment variable when the target platform is Windows, but I don’t know why and it doesn’t seem to work.

if toolchain:is_plat("windows") then
target = target .. "-windows-msvc"
-- add vs environments
local expect_vars = {"PATH", "LIB", "INCLUDE", "LIBPATH"}
local curenvs = os.getenvs()
for _, name in ipairs(expect_vars) do
_add_vsenv(toolchain, name, curenvs)
end
for _, name in ipairs(find_vstudio.get_vcvars()) do
if not table.contains(expect_vars, name:upper()) then
_add_vsenv(toolchain, name, curenvs)
end
end
if is_host("linux") then
toolchain:add("ldflags", "-fuse-ld=lld-link" .. suffix)
toolchain:add("shflags", "-fuse-ld=lld-link" .. suffix)
end

@star-hengxing
Copy link
Contributor

可以 add_cxflags("-v") 看看搜索路径

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


You can add_cxflags("-v") to see the search path

@Doekin
Copy link
Contributor Author

Doekin commented Dec 17, 2024

xmake f -c -vD --toolchain=clang

checking for platform ... windows
checking for architecture ... x64
checking for clang ... ok
checking for clang++ ... ok
checking for the linker (ld) ... clang++
checking for clang++ ... ok
checking for the shared library linker (sh) ... clang++
configure
{
    mingw = D:/Applications/Scoop/apps/mingw-mstorsjo-llvm-ucrt/current/
    network = public
    proxy = socks5://127.0.0.1:20170
    ccache = true
    buildir = build
    toolchain = clang
    arch = x64
    mode = release
    kind = static
    clean = true
    proxy_pac = pac.lua
    ndk_stdcxx = true
    host = windows
    theme = default
    plat = windows
}

xmake -r -vD hello_c

checking for clang ... ok
checking for the c compiler (cc) ... clang
checking for flags (-O3) ... ok
> clang "-O3" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
checking for flags (-v) ... ok
> clang "-v" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
checking for flags (-DNDEBUG) ... ok
> clang "-DNDEBUG" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
checking for clang ... ok
checking for the c++ compiler (cxx) ... clang
[ 50%]: cache compiling.release src\hello.c
clang -c -Qunused-arguments -m64 --target=x86_64-windows-msvc -fvisibility=hidden -O3 -v -DNDEBUG -o build\.objs\hello_c\windows\x64\release\src\hello.c.obj src\hello.c
checking for flags (-MMD -MF) ... ok
> clang "-MMD" "-MF" "C:\Users\leemu\AppData\Local\Temp\.xmake\241217\_A3ADF10C90344B60830345B334841170" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
checking for flags (-fdiagnostics-color=always) ... ok
> clang "-fdiagnostics-color=always" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
checking for flags (-fansi-escape-codes) ... ok
> clang "-fansi-escape-codes" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
checking for flags (-Wno-gnu-line-marker -Werror) ... ok
> clang "-Wno-gnu-line-marker" "-Werror" "-Qunused-arguments" "-m64" "--target=x86_64-windows-msvc"
error: @programdir\core\main.lua:329: @programdir\actions\build\main.lua:148: @programdir\modules\async\runjobs.lua:325: @programdir\modules\private\action\build\object.lua:91: @programdir\modules\core\tools\gcc.lua:966: clang version 19.1.5 (https://github.com/llvm/llvm-project.git ab4b5a2db582958af1ee308a790cfdb42bd24720)
Target: x86_64-unknown-windows-msvc
Thread model: posix
InstalledDir: D:/Applications/Scoop/apps/mingw-mstorsjo-llvm-ucrt/19.1.5-20241203/bin
 (in-process)
 "D:/Applications/Scoop/apps/mingw-mstorsjo-llvm-ucrt/19.1.5-20241203/bin/clang-19.exe" -cc1 -triple x86_64-unknown-windows-msvc19.33.0 -emit-obj -mincremental-linker-compatible -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name hello.c 
-mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -fdebug-compilation-dir=D:/projects/cpp-playground -v -fcoverage-compilation-dir=D:/projects/cpp-playground -resource-dir D:/Applications/Scoop/apps/mingw-mstorsjo-llvm-ucrt/19.1.5-20241203/lib/clang/19 -dependency-file "C:\\Users\\leemu\\AppData\\Local\\Temp\\.xmake\\241217\\_0E60883D424248308CAA376A3578D1B0" -MT "build\\.objs\\hello_c\\windows\\x64\\release\\src\\hello.c.obj" -D NDEBUG -internal-isystem D:/Applications/Scoop/apps/mingw-mstorsjo-llvm-ucrt/19.1.5-20241203/lib/clang/19/include -internal-isystem "C:/Program Files/Microsoft Visual Studio 10.0/VC/include" -internal-isystem "C:/Program Files/Microsoft Visual Studio 9.0/VC/include" -internal-isystem "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include" -internal-isystem "C:/Program Files/Microsoft Visual Studio 8/VC/include" -internal-isystem "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" -O3 -ferror-limit 19 -fvisibility=hidden -fno-use-cxa-atexit -fms-extensions -fms-compatibility -fms-compatibility-version=19.33 -fskip-odr-check-in-gmf -fdelayed-template-parsing -fcolor-diagnostics -fansi-escape-codes -vectorize-loops -vectorize-slp -faddrsig -o "build\\.objs\\hello_c\\windows\\x64\\release\\src\\hello.c.obj" 
-x c "src\\hello.c"
clang -cc1 version 19.1.5 based upon LLVM 19.1.5 default target x86_64-w64-mingw32
ignoring nonexistent directory "C:/Program Files/Microsoft Visual Studio 10.0/VC/include"
ignoring nonexistent directory "C:/Program Files/Microsoft Visual Studio 9.0/VC/include"
ignoring nonexistent directory "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include"
ignoring nonexistent directory "C:/Program Files/Microsoft Visual Studio 8/VC/include"
ignoring nonexistent directory "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
#include "..." search starts here:
#include <...> search starts here:
 D:/Applications/Scoop/apps/mingw-mstorsjo-llvm-ucrt/19.1.5-20241203/lib/clang/19/include
End of search list.
src\hello.c:1:10: fatal error: 'stdio.h' file not found
    1 | #include <stdio.h>
      |          ^~~~~~~~~
1 error generated.
stack traceback:
    [C]: in function 'error'
    [@programdir\core\base\os.lua:1004]:
    [@programdir\modules\core\tools\gcc.lua:966]: in function 'catch'
    [@programdir\core\sandbox\modules\try.lua:123]: in function 'try'
    [@programdir\modules\core\tools\gcc.lua:907]:
    [C]: in function 'xpcall'
    [@programdir\core\base\utils.lua:244]:
    [@programdir\core\tool\compiler.lua:288]: in function 'compile'
    [@programdir\modules\private\action\build\object.lua:91]: in function 'script'
    [@programdir\modules\private\action\build\object.lua:122]: in function 'build_object'
    [@programdir\modules\private\action\build\object.lua:147]: in function 'jobfunc'
    [@programdir\modules\async\runjobs.lua:241]:
    [C]: in function 'xpcall'
    [@programdir\core\base\utils.lua:244]: in function 'trycall'
    [@programdir\core\sandbox\modules\try.lua:117]: in function 'try'
    [@programdir\modules\async\runjobs.lua:223]: in function 'cotask'
    [@programdir\core\base\scheduler.lua:406]:

stack traceback:
        [C]: in function 'error'
        @programdir\core\base\os.lua:1004: in function 'os.raiselevel'
        (...tail calls...)
        @programdir\core\main.lua:329: in upvalue 'cotask'
        @programdir\core\base\scheduler.lua:406: in function <@programdir\core\base\scheduler.lua:399>

@Doekin
Copy link
Contributor Author

Doekin commented Dec 17, 2024

if toolchain:is_plat("windows") then
target = target .. "-windows-msvc"
-- add vs environments
local expect_vars = {"PATH", "LIB", "INCLUDE", "LIBPATH"}
local curenvs = os.getenvs()
for _, name in ipairs(expect_vars) do
_add_vsenv(toolchain, name, curenvs)
end
for _, name in ipairs(find_vstudio.get_vcvars()) do
if not table.contains(expect_vars, name:upper()) then
_add_vsenv(toolchain, name, curenvs)
end
end
if is_host("linux") then
toolchain:add("ldflags", "-fuse-ld=lld-link" .. suffix)
toolchain:add("shflags", "-fuse-ld=lld-link" .. suffix)
end

在这段代码后面用 toolchain:get("runenvs") 或者 toolchain:config("runenvs") ,打印出来 runenvs 都是 nil

可能是 check 时没添加到

function main(toolchain, suffix)
-- only for windows or linux (msvc-wine)
if not is_host("windows", "linux") then
return
end
local sdkdir = toolchain:sdkdir()
if sdkdir then
return _check_vc_build_tools(toolchain, sdkdir, suffix)
end
end

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


if toolchain:is_plat("windows") then
target = target .. "-windows-msvc"
-- add vs environments
local expect_vars = {"PATH", "LIB", "INCLUDE", "LIBPATH"}
local curenvs = os.getenvs()
for _, name in ipairs(expect_vars) do
_add_vsenv(toolchain, name, curenvs)
end
for _, name in ipairs(find_vstudio.get_vcvars()) do
if not table.contains(expect_vars, name:upper()) then
_add_vsenv(toolchain, name, curenvs)
end
end
if is_host("linux") then
toolchain:add("ldflags", "-fuse-ld=lld-link" .. suffix)
toolchain:add("shflags", "-fuse-ld=lld-link" .. suffix)
end

Use toolchain:get("runenvs") or toolchain:config("runenvs") after this code, and the printed runenvs will be nil

It may be that it was not added during check.

function main(toolchain, suffix)
-- only for windows or linux (msvc-wine)
if not is_host("windows", "linux") then
return
end
local sdkdir = toolchain:sdkdir()
if sdkdir then
return _check_vc_build_tools(toolchain, sdkdir, suffix)
end
end

I did not specify sdk, and sdkdir was printed as nil

@Doekin
Copy link
Contributor Author

Doekin commented Dec 17, 2024

或许可以模仿 clang-cl 工具链的做法,寻找 vs 并添加相关环境变量

function main(toolchain)
-- only for windows or linux (msvc-wine)
if not is_host("windows", "linux") then
return
end
-- @see https://github.com/xmake-io/xmake/pull/679
local cc = path.basename(config.get("cc") or "clang-cl"):lower()
local cxx = path.basename(config.get("cxx") or "clang-cl"):lower()
local mrc = path.basename(config.get("mrc") or "rc"):lower()
if cc == "clang-cl" or cxx == "clang-cl" or mrc == "rc" then
local sdkdir = toolchain:sdkdir()
if sdkdir then
return _check_vc_build_tools(toolchain, sdkdir)
else
-- find it from packages
for _, package in ipairs(toolchain:packages()) do
local installdir = package:installdir()
if installdir and os.isdir(installdir) then
local result = _check_vc_build_tools(toolchain, installdir)
if result then
return result
end
end
end
-- find it from system
return _check_vstudio(toolchain)
end
end
end

我将上面这段复制给 clang 的 check:

function main(toolchain, suffix)
-- only for windows or linux (msvc-wine)
if not is_host("windows", "linux") then
return
end
local sdkdir = toolchain:sdkdir()
if sdkdir then
return _check_vc_build_tools(toolchain, sdkdir, suffix)
end
end

可以编译本地项目

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


Specifying sdkdir does not work either. In _check_vc_build_tools, vcvarsall prints out nil

function _check_vc_build_tools(toolchain, sdkdir, suffix)
local opt = {}
opt.sdkdir = sdkdir
opt.vs_toolset = toolchain:config("vs_toolset") or config.get("vs_toolset")
opt.vs_sdkver = toolchain:config("vs_sdkver") or config.get("vs_sdkver")
local vcvarsall = find_vstudio.find_build_tools(opt)

The possible reason is that the installation path of Visual Studio Build Tools 2022 is different from the default one.

function find_build_tools(opt)
opt = opt or {}
local sdkdir = opt.sdkdir
if not sdkdir or not os.isdir(sdkdir) then
return
end
local variables = {}
local VCToolsVersion
local vs_toolset = opt.vs_toolset
if vs_toolset and os.isdir(path.join(sdkdir, "VC/Tools/MSVC", vs_toolset)) then
VCToolsVersion = vs_toolset
else
local dir = find_directory("14*", path.join(sdkdir, "VC/Tools/MSVC"))
if dir then
VCToolsVersion = path.filename(dir)
else
return
end
end
variables.VCToolsVersion = VCToolsVersion
variables.VCToolsInstallDir = path.join(sdkdir, "VC/Tools/MSVC", VCToolsVersion)
local WindowsSDKVersion
local vs_sdkver = opt.vs_sdkver
if vs_sdkver and os.isdir(path.join(sdkdir, "Windows Kits/10/Lib", vs_sdkver)) then
WindowsSDKVersion = vs_sdkver
else
local dir = find_directory("10*", path.join(sdkdir, "Windows Kits/10/Lib"))
if dir then
WindowsSDKVersion = path.filename(dir)
else
return
end
end
variables.WindowsSDKVersion = WindowsSDKVersion
variables.WindowsSdkDir = path.join(sdkdir, "Windows Kits/10")

On my computer, sdkdir is set to C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\ and VCToolsInstallDir is C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.42.34433, WindowsSdkDir is C:\Program Files (x86)\Windows Kits\10\

@waruqi
Copy link
Member

waruqi commented Dec 19, 2024

Clang 在目标平台为 Windows 时,是会加载 MSVC 环境变量的,只是不知道为什么,似乎不太管用

目前 clang 那个 toolchain ,check 阶段仅仅做了 portable build msvc 的支持,不会去检测加载系统 vs 环境。

只有 clang-cl 的才会。

return _check_vstudio(toolchain)

另外,即使 clang toolchain 不加载 msvc ,也是可以正常编译的。

xmake f --toolchain=clang -c; xmake -rv
checking for platform ... windows
checking for architecture ... x64
checking for clang ... ok
checking for the c compiler (cc) ... clang
checking for flags (-O3) ... ok
checking for flags (-DNDEBUG) ... ok
checking for clang ... ok
checking for the c++ compiler (cxx) ... clang
[ 50%]: cache compiling.release src\main.c
clang -c -Qunused-arguments -m64 --target=x86_64-windows-msvc -fvisibility=hidden -O3 -DNDEBUG -o build\.objs\test\windows\x64\release\src\main.c.obj src\main.c
checking for flags (-MMD -MF) ... ok
checking for flags (-fdiagnostics-color=always) ... ok
checking for flags (-fansi-escape-codes) ... ok
checking for flags (-Wno-gnu-line-marker -Werror) ... ok
[ 75%]: linking.release test.exe
clang++ -o build\windows\x64\release\test.exe build\.objs\test\windows\x64\release\src\main.c.obj -m64 --target=x86_64-windows-msvc
[100%]: build ok, spent 1.766s

而且 llvm/clang 原本就不应该跟 msvc 两套环境强耦合绑定。它本就是独立的工具链,有自己的 libc++ 头文件,干嘛默认要跟 msvc 耦合在一起?除非显式指定 要用 msvc 的

@Doekin
Copy link
Contributor Author

Doekin commented Dec 19, 2024

对哦,我一时没转过弯来,想得不够周到
谢谢解答

@Doekin Doekin closed this as completed Dec 19, 2024
@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


That's right, I didn't turn around for a moment and didn't think carefully enough.
Thanks for the answer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants