I would like to use a Makefile to generate a binary that does unit tests for me. It takes all the object files of my program, as well a compiled tester object, and packages it all together. The issue is, I want to use a custom entry point inside the tester file instead of main
.
So no problem, ld
comes with a flag -e
where I can specify said entry point. So inside of my Makefile I have written:
$(CC) $(ALL_CFLAGS) -Wl,-e$(TEST_ENTRY) $(OBJDIR)/$(TEST_SUITE:.c=.o) $(OBJECTS) -o $(BINDIR)/$(TARGET)-test
Taking care to note that I am doing all my linking with the gcc
function so I have to pass my command to the linker with -Wl
. This is where the problem begins:
Using gcc
on Debian, this command works perfectly and my program runs as expected.
Using clang
on MacOS, I am presented with the following error during compile time:
ld: unknown option: -etester
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [test] Error 1
The Makefile is putting the entry point (named tester
) with the argument without any space. As far as I know, this should be perfectly acceptable? After all, gcc
accepts it.
If I add a space, it will assume $(TEST_ENTRY)
is an argument for the compiler instead. I can avoid this with quotation marks. So I also tried the following:
-Wl,"-e $(TEST_ENTRY)"
However I get the same error
ld: unknown option: -e tester
May I ask if anybody knows a solution that will allow clang to function correctly while not sabotaging the fact that it already works in gcc? Perhaps I am missing something here.
This seems related to the function name mangling of clang. To avoid user-defined function name duplicated with intrinsic function names in libc or Sysmte.A, compiler mangle user-defined function names. for c language, usually, a '_' is added as prefix.
for example,
int test(..)
is mangled to
_test
in clang compilation procedure.
#include "stdio.h"
int main(int argc, char const *argv[]) {
printf("hello world\n");
return 0;
}
int test(int argc, char const* argv[]){
printf("hello test entry\n");
return 0;
}
When compiled with clang helloworld.c -o helloworld
,
execution result:
╰─$ ./helloworld
hello world
when compiled with clang helloworld.c -o helloworld -e_test
,
execution result:
╰─$ ./helloworld
hello test entry
refer to https://en.wikipedia.org/wiki/Name_mangling for more details or reply to ask.