After successfully and easily compiling a project in Windows with clang-cl I wanted to change the command to clang. clang itself lies in Linux (WSL 2.0) and the C library to be used is that of MSVC. Eventually I learned about the triple, but by that time I had almost succeeded. I run into several issues:
1.| (Seems a bug). -fno-signed-char (or -funsigned-char) is ignored depending on the triple settings:
targeting Linux, default option for the triple O.K.
targeting Windows, x86_64-windows-windows-msvc<xx.xx.x> O.K.
targeting Windows, x86_64-windows-windows-gnu wrong
and there were some other combination where it was also wrong. The compiler insists in char being signed, which generates me hundreds of warnings.
2.| <abi> in the triple
According to CrossCompilation.rst, "Finally, the ABI option is something that will pick default CPU/FPU,
define the specific behaviour of your code (PCS, extensions), and also choose the correct library calls, etc."
So, it seems it is not what defines the format of the generated object files (what I would expect given its "abi" name). Since I had already managed to make clang compile the sources by specifying the -isystem directories, and I wanted to avoid any windows related magic as much as possible, I tried to specify x86_64-windows-windows-none or x86_64-pc-windows-none, but "none" there, or "unknown" always got replaced by msvc19.11.0. Maybe it does not make sense to have the abi unknown? Therefore I finally compiled with x86_64-windows-windows-gnu, although gnu had nothing to do with my compilation.
I would expect that the application binary interface specification on the command line (or elsewhere) is what would make llvm generate object files for either or other consumer, but having seen that specifying "gnu" there generates .obj files just as specifying "msvc"; i.e., object files that Windows' link program handles well, it seems it is not.
So the question is: what in the triple is what makes the backend generate object files in one or the other format?
Except for the architecture part of the triple, which is clear what it means, I have found the documentation for the other parts (when I at last could find it) unclear in what they change or determine in a compilation process.
So, compiling with x86_64-windows-windows-gnu -fno-builtin -fms-compatibility -fshort-wchar -Wno-pointer-sign -fvisibility-ms-compat
and a bunch of defines like -D _M_X64=100, everything runs fine and linking the objects from Windows, with its link command, works properly, just as if I had compiled with x86_64-windows-windows-msvc19.16.00, EXCEPT for the function
which the linker cannot find. This function is inserted by the compiler when a function requires a large amount of stack space. I solved this by declaring the problematic objects static, but I'd like to know why this happens.
By the way, even without -fms-compatibility, just with -fdeclspec and some #defines in the code, I also succeeded in compiling.
4.| -fms-compatibility vs. -fms-extensions
The help which is displayed by clang -help says
-fms-compatibility Enable full Microsoft Visual C++ compatibility
-fms-extensions Accept some non-standard constructs supported by the Microsoft compiler
which is not very informative. Which one enables less stuff? Is one a superset of the other. "Enable full Microsoft Visual C++ compatibility" seems to imply that this indeed is a superset of the other, but considering that even compiling with clang-cl there are the options /Ze and /Za which enable o disable Microsoft extensions, one is lead to think that the -fms-extensions are beyond the compatibility provided by -fms-compatibility. What, then?
5.| -m... options.
I know that once I have specified my architecture to be x86_64 there are options that can improve the performance of the binaries: "Once your target is specified, it's time to pick the hardware you'll
be compiling to. For every architecture, a default set of CPU/FPU/ABI will be chosen, so you'll almost always have to change it via flags."
Where can the available flags be found? If they are so important and can have such an impact on the program, why is the documentation for them so difficult to find? (Specially if you are working off-line as I use to).
In general, it seems that a good, thought document explaining each of the parts of the "triple" AND what the determine in the compilation process, and those -m flags would be very welcome, and if clang -help would point where that documentation could be found that would be very helpful also. Just browse the internet for Q&A related to the triple, and you'll find that "official" explanations should definitely be easier to find.
Thanks in advance
-- Javier A. Múgica