I had experimented with smaller projects (none using explicit linker), and clang g++ worked exactly as MinGW g++ … but in my current application, I got this error:
BTW, I resolved this linker error by defining the following function in my module:
#ifdef USING_CLANG
void ___chkstk_ms(void)
{
} #endif
That allowed me to get the the project to build, and the program appears to work properly… Are there any hidden surprises that might leap out at me as a result of this hack ??
___chkstk_ms is supposed to implement stack probing: accessing the stack once for every 4KB allocated so you don’t skip over the guard page on the stack. If you skip probing, you might get a crash. (A closer look at the stack guard page - The Old New Thing has a description of how this works.)
The static library that provides ___chkstk_ms is supposed to get linked in automatically if you’re targeting MinGW; not sure why that isn’t working for you.
I went here because I wanted an i686 gnu build, which the default distribution site didn’t have… it did have a
clang+llvm-18.1.8-x86_64-pc-windows-msvc
distribution, but that dist didn’t have g++.exe/gcc.exe , so wasn’t sure that was equivalent…
Can you add -v to the linking command (D:\clang\bin\g++ media_list.o ext_lookup.o file_fmts.o conio_min.o der_libs\common_funcs.o der_libs\common_win.o der_libs\qualify.o MediaInfoDll.o -s -O3 -dUNICODE -d_UNICODE -o MediaList.exe -lshlwapi -lgdi32 -lcomdlg32) to let it print out more exactly what it tells the linker to do.
The symbol ___chkstk_ms sure is available, in the x86_64 version of the compiler-rt builtins library. (Common sources of this issue would be if linking with -nostdlib or similar, and failing to add the right libraries. This can happen with libtool due to a longstanding issue there - but this case doesn’t seem to have libtool or -nostdlib involved.)
However, if you’re building things in i686 mode, then you wouldn’t be getting references to ___chkstk_ms, then you should be getting references to __alloca instead; the stack probe function has different names between the architectures (see Compiler Explorer as example). But then again, if you would be mixing in object files of inconsistent architectures, the linker would complain about that as well.
as for what version I have, I’m definitely beginning to suspect that the package that I got from mstorsjo (linked above) is not valid, but I don’t know where else to get that specific package from, and I really don’t want to deal with building the whole thing myself!!
I also had another issue with that package; I tried building a Windows app (this one is a console app), and got an error message from windres, about my .rc files which no other package has had any issue with… I didn’t bother posting about that error, as I’m waiting to see how this discussion resolves first…
That’s definitely not the right conclusion here - that toolchain is quite ok. (I’m the one who maintains it.)
So it is linking in i686 mode, but for some unknown reason you end up with an undefined reference to ___chkstk_ms - in der_libs\common_funcs.o. But you shouldn’t be getting a reference to that symbol in an i686 build, only in an x86_64 build.
My suspicion is that something in the source itself produces this reference to ___chkstk_ms, which isn’t something you can assume to exist in an i686 build. (Although with libgcc, both variants of stack probe functions are available in both architectures, even if the “wrong” ones are entirely unused normally.)
Can you provide a way to reproduce your der_libs\common_funcs.o? Can you show the command that builds that file, plus the source files? Ideally for someone else to reproduce it, they’d need all transitive headers etc. But it’s possible to reproduce building the object file if you produce the preprocessed output from it, making it standalone. So from a command like cc <lots of options> -c source.c -o source.o, change it into cc <lots of options> -E source.c -o source-preproc.c. Then upload source-preproc.c somewhere where someone can fetch it and reproduce building it.
This toolchain uses llvm-rc/llvm-windres, which can be a bit more picky about unusual inputs than GNU windres or MS rc.exe - please file an issue for that on GitHub · Where software is built if it can be reproduced neatly.
Okay, first step:
common_funcs.cpp is in my der_libs library; in this case, it is being used used by my media_list utility… both are free software on my github page:
you can clone the package using (note --recursive to get der_libs submodule):
git clone GitHub - DerellLicht/media_list --recursive
then just build using ‘make’ …
You’ll probably have to update the path to the toolchain in Makefile…
Although, if you just want that one debug file, I can generate that too!!
I’ll get back to you in a little while…
NEVERMIND !!!
I figured out what was wrong…
I had my ‘clean’ label defined wrong, so it wasn’t deleting object files in the der_libs submodule … meaning that as I was experimenting with different toolchains (32-bit and 64-bit), I was leaving obsolete object files in der_libs - which includes common_funcs.o … I thought I had updated the clean labels in all my projects, long ago, but apparently not…
Now that I corrected the Makefile so that it cleans the submodule as well, the clang package is working fine !!!
Ok, thanks, that explains it! Yes that was also one of my hunches here - although I’m surprised that the linker doesn’t straight out error out when mixing architectures. But that’s on us to try to figure out why
This toolchain uses llvm-rc/llvm-windres, which can be a bit more picky about unusual inputs than GNU windres or MS rc.exe - please file an issue for that on GitHub · Where software is built if it can be reproduced neatly.
BTW, I did post the windres issue over on that github page…
That issue was not related to this one, and was not involved in the .o confusion.
I am trying to build a mingw based toolchain which uses compiler-rt instead of libgcc.
For x86_64 target it works.
For i386 target it is not able to link because libmingw for i386 is referencing __chkst_ms, which is missing in i386 compiler-rt.
I think additionally linking libgcc would work, but the user would need to add this manually because the MinGW driver omits libgcc if compiler-rt is used.
Currently I just added the __chkst_ms implementation to i386 compiler-rt.
Is there another way to make this work? Is this a supported usecase?
It sounds like your build is messed up somehow, because on i386, the compiler (both GCC and Clang) generate calls to `_alloca`, not `__chkstk_ms` - see e.g. Compiler Explorer.
It sounds like you are mixing in some incorrectly compiled objects somewhere, if you have references to `__chkstk_ms` in i386 mode; this is what you need to figure out where they come from.
Maybe I was not precise enough.
The symbol is not generated by a compilation of the toolchain itself.
Its the shipped i386 libmingw32 of the installed mingw64 toolchain which already references the symbol.
So, when I try to link the new i386 toolchain with libmingw32 and compiler-rt (instead of libgcc) I get the unresolved symbol error, because libmingw32 needs __chkst_ms.
I assume the libmingw32 was build with gcc which produces the call to __chkst_ms.
Your compiler explorer example with MinGW gcc e.g. produces the call.
Does this work in the llvm-mingw project?
If yes, how?
I cant/dont want to use llvm-mingw for now because the goal is to have a complete toolchain build on Windows with company cleared tools…
I was quite sure and convinced that Clang modelled the exact behaviour of GCC in this aspect - that’s the intent generally - but it turns out that they differ in this aspect, that Clang generates calls to _alloca, while GCC generates calls to ___chkstk_ms, on i386. Sorry for missing that detail!
For further context - before GCC 4.6, GCC emit references to ___chkstk (with three leading underscores, as opposed to MSVC which references __chkstk with two leading underscores). But apparently Clang does something entirely different here. (This changed in GCC commit https://github.com/gcc-mirror/gcc/commit/174425adcde4e0f7205e9ac6832f4e7a451b123e.)
I’ll try to sort this out properly for compiler-rt and restore a function that works for both old and new GCC.