llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.64k stars 11.84k forks source link

Cross-compiling with clang-cl to intel on an arm machine doesn't work great (or at all) #81070

Closed nico closed 7 months ago

nico commented 8 months ago

I saw https://neugierig.org/software/blog/2024/02/cross-compile.html and was like "this is super easy to do with clang-cl as long as you have a win sysroot!". Then I tried it on my Apple Silicon laptop:

 % cat main.c
int main() {}
 % out/gn/bin/clang-cl main.c /winsysroot ~/src/chrome/src/third_party/depot_tools/win_toolchain/vs_files/27370823e7                                         
clang-cl: error: unable to execute command: Executable "link.exe" doesn't exist!
clang-cl: error: linker command failed with exit code 1 (use -v to see invocation)

Ah right, I have to use lld, of course:

% out/gn/bin/clang-cl main.c /winsysroot ~/src/chrome/src/third_party/depot_tools/win_toolchain/vs_files/27370823e7 -fuse-ld=lld
% file main.exe
main.exe: PE32+ executable (console) Aarch64, for MS Windows

Hm. I suppose that makes sense? But let's make an intel binary. Just -m32 picks 32-bit arm which I suppose maybe makes sense, so let's pass an explicit triple:

% out/gn/bin/clang-cl main.c /winsysroot ~/src/chrome/src/third_party/depot_tools/win_toolchain/vs_files/27370823e7 -fuse-ld=lld --target=x86_64-pc-windows 
clang (LLVM option parsing): Unknown command line argument '-x86-asm-syntax=intel'.  Try: 'clang (LLVM option parsing) --help'
clang (LLVM option parsing): Did you mean '--asan-stack=intel'?

Whaat? Why is that command line arg unknown? That should work?

I suppose this bug report is only about this very last thing. (But maybe we should default to lld too, at least on non-Win hosts, since link.exe can't possibly work there?)

@zmodem

nico commented 8 months ago

(Why do we get this error at all? Because clang/lib/Driver/ToolChains/Clang.cpp adds it in Clang::AddX86TargetArgs:

  } else if (D.IsCLMode()) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-x86-asm-syntax=intel");
  }

That seems like a good thing – but it shouldn't produce an error.

zmodem commented 8 months ago

Did you build LLVM without the X86 target? That's the only way I can reproduce that error.

$ bin/clang -c /tmp/a.c --target=x86_64-pc-windows -mllvm -x86-asm-syntax=intel
clang (LLVM option parsing): Unknown command line argument '-x86-asm-syntax=intel'.  Try: 'clang (LLVM option parsing) --help'
clang (LLVM option parsing): Did you mean '--asan-stack=intel'?

I think the real bug is that the driver doesn't check that the target exists. Instead that check happens later on (in cc1 I suppose).

$ bin/clang -c /tmp/a.c --target=x86_64-pc-windows                             
error: unable to create target: 'No available targets are compatible with triple "x86_64-pc-windows-msvc19.33.0"'
1 error generated.
nico commented 7 months ago
% out/gn/bin/clang -c main.c --target=x86_64-pc-windows      
error: unable to create target: 'No available targets are compatible with triple "x86_64-pc-windows-msvc19.33.0"'

Hmm!

But:

% rg '^llvm_targets' out/gn/args.gn
18:llvm_targets_to_build = [ "AArch64", "X86" ]

Maybe that's stale? I'll try rebuilding clang. With that:

% out/gn/bin/clang -c main.c --target=x86_64-pc-windows    

So yes, I had that target enabled, sorry for the noise :(

Now

out/gn/bin/clang-cl main.c /winsysroot ~/src/chrome/src/third_party/depot_tools/win_toolchain/vs_files/27370823e7 -fuse-ld=lld --target=x86_64-pc-windows

works without problems.

So maybe this here is only about usability. But most people won't disable individual targets and then forget about it, so maybe we can also just close it.