Linux下clang-cl交叉编译Windows时CMake库路径标志错误的解决问询
Linux下CMake+clang-cl+lld-link交叉编译Windows二进制的参数适配问题
问题场景
在Linux环境下尝试通过CMake配合clang-cl和lld-link交叉编译Windows二进制文件,编译阶段成功,但链接阶段失败。核心问题是CMake生成了GCC风格的-L库路径参数,而clang-cl需要使用MSVC风格的/LIBPATH:<path>参数传递给lld-link,手动修改参数后链接可正常完成,希望让CMake将clang-cl识别为cl.exe以生成正确的命令行参数。
当前工具链文件
set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_C_COMPILER /usr/bin/clang-cl) set(CMAKE_CXX_COMPILER /usr/bin/clang-cl) set(CMAKE_RC_COMPILER /usr/bin/llvm-rc-15) set(CMAKE_AR /usr/bin/llvm-ar-15) add_compile_options(-Wno-ignored-attributes -EHa) add_link_options(-fuse-ld=lld-link) include_directories( /home/workspace/sysroots/windows/crt/include /home/workspace/sysroots/windows/sdk/include/ucrt /home/workspace/sysroots/windows/sdk/include/shared /home/workspace/sysroots/windows/sdk/include/um ) link_directories( /home/workspace/sysroots/windows/sdk/lib/ucrt/x86_64 /home/workspace/sysroots/windows/crt/lib/x86_64 /home/workspace/sysroots/windows/sdk/lib/um/x86_64 )
链接错误日志
/usr/bin/clang-cl -m64 -m64 -fuse-ld=lld-link CMakeFiles/cmTC_dd439.dir/Debug/testCCompiler.c.obj -o Debug/cmTC_dd439 -L/home/workspace/sysroots/windows/sdk/lib/ucrt/x86_64 -L/home/workspace/sysroots/windows/crt/lib/x86_64 -L/home/workspace/sysroots/windows/sdk/lib/um/x86_64 && : FAILED: Debug/cmTC_dd439 : && /usr/bin/clang-cl -m64 -m64 -fuse-ld=lld-link CMakeFiles/cmTC_dd439.dir/Debug/testCCompiler.c.obj -o Debug/cmTC_dd439 -L/home/workspace/sysroots/windows/sdk/lib/ucrt/x86_64 -L/home/workspace/sysroots/windows/crt/lib/x86_64 -L/home/workspace/sysroots/windows/sdk/lib/um/x86_64 && : clang: warning: unknown argument ignored in clang-cl: '-L/home/workspace/sysroots/windows/sdk/lib/ucrt/x86_64' [-Wunknown-argument] clang: warning: unknown argument ignored in clang-cl: '-L/home/workspace/sysroots/windows/crt/lib/x86_64' [-Wunknown-argument] clang: warning: unknown argument ignored in clang-cl: '-L/home/workspace/sysroots/windows/sdk/lib/um/x86_64' [-Wunknown-argument] lld-link: error: could not open 'libcmt.lib': No such file or directory lld-link: error: could not open 'oldnames.lib': No such file or directory clang: error: linker command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed.
解决方案
1. 强制CMake以MSVC编译器规则生成参数
修改工具链文件,明确设置编译器ID为MSVC,替换原有的Generic系统名称为Windows,并改用/LIBPATH:传递库路径(避免使用link_directories):
set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_C_COMPILER /usr/bin/clang-cl) set(CMAKE_CXX_COMPILER /usr/bin/clang-cl) set(CMAKE_RC_COMPILER /usr/bin/llvm-rc-15) set(CMAKE_AR /usr/bin/llvm-ar-15) # 强制CMake按MSVC编译器逻辑生成参数 set(CMAKE_C_COMPILER_ID MSVC) set(CMAKE_CXX_COMPILER_ID MSVC) set(CMAKE_C_SIMULATE_ID MSVC) set(CMAKE_CXX_SIMULATE_ID MSVC) set(CMAKE_C_COMPILER_FRONTEND_VARIANT MSVC) set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT MSVC) # 编译选项 add_compile_options(-Wno-ignored-attributes -EHa) # 链接选项:指定lld-link,传递MSVC风格库路径 add_link_options( -fuse-ld=lld-link /LIBPATH:/home/workspace/sysroots/windows/sdk/lib/ucrt/x86_64 /LIBPATH:/home/workspace/sysroots/windows/crt/lib/x86_64 /LIBPATH:/home/workspace/sysroots/windows/sdk/lib/um/x86_64 ) # 包含目录 include_directories( /home/workspace/sysroots/windows/crt/include /home/workspace/sysroots/windows/sdk/include/ucrt /home/workspace/sysroots/windows/sdk/include/shared /home/workspace/sysroots/windows/sdk/include/um ) # 显式指定需要链接的CRT库(根据实际环境选择MT/MD模式) add_link_options(libcmt.lib oldnames.lib)
2. 关键调整说明
- 将
CMAKE_SYSTEM_NAME设为Windows而非Generic,让CMake明确目标平台为Windows,启用对应工具链逻辑。 - 强制设置
CMAKE_*_COMPILER_ID为MSVC,覆盖CMake自动识别的Clang,使其生成MSVC风格的命令行参数(包括用/LIBPATH:替代-L)。 - 放弃使用
link_directories,直接通过add_link_options传递/LIBPATH:参数,避免CMake生成错误的-L选项。 - 显式添加缺失的CRT库链接选项,确保lld-link能找到对应的库文件。
补充信息
- CMake版本:3.26.1
- CMake自动识别输出:
-- The C compiler identification is Clang 15.0.7 with MSVC-like command-line -- The CXX compiler identification is Clang 15.0.7 with MSVC-like command-line -- Detecting C compiler ABI info -- Detecting C compiler ABI info - failed -- Check for working C compiler: /usr/bin/clang-cl -- Check for working C compiler: /usr/bin/clang-cl - broken
- CMake调试信息:
-- CMAKE_C_COMPILER_ID = Clang -- CMAKE_C_SIMULATE_ID = MSVC -- CMAKE_C_COMPILER FRONTEND_VARIANT = MSVC -- CMAKE_CXX_COMPILER_ID = Clang -- CMAKE_CXX_SIMULATE_ID = MSVC -- CMAKE_CXX_COMPILER FRONTEND_VARIANT = MSVC
内容的提问来源于stack exchange,提问作者user3725041
相关产品推荐
相关产品推荐

