Clang 链接器无法识别 -e 选项,但 GCC 链接器可以

Clang linker not recognising -e option but GCC linker does

我想使用 Makefile 生成二​​进制文件来为我进行单元测试。它获取我程序的所有目标文件,以及一个编译的测试器对象,并将它们打包在一起。问题是,我想在测试文件中使用自定义入口点而不是 main.

所以没问题,ld 带有一个标志 -e,我可以在其中指定所述入口点。所以在我的 Makefile 里面我写了:

$(CC) $(ALL_CFLAGS) -Wl,-e$(TEST_ENTRY) $(OBJDIR)/$(TEST_SUITE:.c=.o) $(OBJECTS) -o $(BINDIR)/$(TARGET)-test

请注意,我正在使用 gcc 函数进行所有链接,因此我必须使用 -Wl 将我的命令传递给链接器。这是问题开始的地方:

在 Debian 上使用 gcc,此命令完美运行,我的程序按预期运行。

在 MacOS 上使用 clang,我在编译时遇到以下错误:

ld: unknown option: -etester
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [test] Error 1

Makefile 将入口点(名为 tester)与没有任何 space 的参数放在一起。据我所知,这应该是完全可以接受的?毕竟gcc接受了

如果我添加 space,它会假设 $(TEST_ENTRY) 是编译器的参数。我可以用引号避免这种情况。所以我也尝试了以下方法:

-Wl,"-e $(TEST_ENTRY)"

但是我得到了同样的错误

ld: unknown option: -e tester

请问是否有人知道一个解决方案可以让 clang 正常运行,同时不破坏它已经在 gcc 中运行的事实?也许我在这里遗漏了一些东西。

man page for lld(LLVM 链接器)表示指定入口点的标志是 --entry。所以在 MacOS 上你必须使用像 -Wl,--entry=$(TEST_ENTRY) 这样的参数。

函数名称修改

这似乎与 clang 的函数名重整有关。为避免用户定义的函数名称与 libc 或 Sysmte.A 中的内部函数名称重复,编译器会混淆用户定义的函数名称。对于c语言,通常会加一个'_'作为前缀。

例如,

int test(..)

被破坏为

_test 在 clang 编译过程中。

测试项目:

#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;
}

clang helloworld.c -o helloworld
编译时 执行结果:

╰─$ ./helloworld     
hello world

当使用 clang helloworld.c -o helloworld -e_test
编译时 执行结果:

╰─$ ./helloworld     
hello test entry

参考https://en.wikipedia.org/wiki/Name_mangling了解更多详情或回复询问。