I was trying to compile a program in Windows using clang
so that I can use cmdline options similar to gcc
while statically linking to the UCRT library (ucrt.lib
). Besides, I also want to specify the entry point to control when to initialize the runtime. Then I found some weird behaviors.
Take this snippet for example:
#include <memory.h>
char src[1000], dest[1000]; // Large enough to avoid inline memcpy
int main(void) {
memcpy(dest, src, sizeof (src));
// memcpy_s(dest, sizeof (dest), src, sizeof (src));
return 233;
}
Obviously, using normal options, it is okay to compile:
> clang test.c -Xlinker /SUBSYSTEM:CONSOLE -o test-llvm.exe
However, after specifying /ENTRY
, memcpy
(and some other library functions, if used) becomes undefined, quite like specifying -nostdlib
.
> clang test.c -Xlinker /SUBSYSTEM:CONSOLE -Xlinker /ENTRY:main -o test-llvm.exe
lld-link: error: undefined symbol: memcpy
>>> referenced by ...\test.o:(main)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
We can manually add the library though, but the error is still there afterwards.
> clang test.c -lucrt -Xlinker /SUBSYSTEM:CONSOLE -Xlinker /ENTRY:main -o test-llvm.exe
lld-link: error: undefined symbol: memcpy
>>> referenced by ...\test.o:(main)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The strangest thing is, if I make the commented line back (memcpy
not altered), the whole file will compile without problems.
> clang test-s.c -lucrt -Xlinker /SUBSYSTEM:CONSOLE -Xlinker /ENTRY:main -o test-llvm.exe
But why would memcpy_s
affect the whole linking process? Is that a bug?
I have also tried changing the linker to LLD by -fuse-ld=lld
and it produced identical results.
I once guessed it may be related to intrinsic functions, but adding options like -fno-builtin
-ffreestanding
doesn't change anything as well.