“Hello,World!”示例的Clang链接器问题

7gcisfzg  于 2023-01-20  发布在  其他
关注(0)|答案(4)|浏览(120)

我刚刚试用了最新的LLVMClang trunk版本,它们编译时没有一个警告,但是我在链接Hello, World!示例时遇到了麻烦。

#include <stdio.h>

int main(){
  printf("Hello, World!\n");
}

如果我使用

clang test.c

我收到以下错误

/usr/bin/ld: crt1.o: No such file: No such file or directory
clang: error: linker command failed with exit code 1 (use -v to see invocation)

使用 -v 表明GNU ld被调用为:

"/usr/bin/ld" --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o a.out crt1.o crti.o crtbegin.o -L -L/../../.. /tmp/cc-0XJTsG.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed crtend.o crtn.o

但是我有crt1.o对象文件!

locate crt1.o

输出:

/usr/lib/Mcrt1.o
/usr/lib/Scrt1.o
/usr/lib/crt1.o
/usr/lib/gcrt1.o

这也适用于:

clang -c test.c
gcc test.o

当然

gcc test.c

我进一步尝试:

clang -Xlinker "-L /usr/lib" test.c

/usr/bin/ld: crt1.o: No such file: No such file or directory
clang: error: linker command failed with exit code 1 (use -v to see invocation)

clang -Xlinker "-L /usr/lib" test.c -v

"/usr/bin/ld" --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o a.out crt1.o crti.o crtbegin.o -L -L/../../.. -L /usr/lib /tmp/cc-YsI9ES.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed crtend.o

我也试着把 crt1.o 文件复制到当前目录中,看起来很有效,但是没有编译,因为在那之后 crti.o 就不见了。
我的Linux发行版是Ubuntu
嗯,我真的不知道下一步该怎么做。我不知道如何修复clang,也不知道如何在 ld 调用中注入必要的路径。有什么想法吗?

kwvwclae

kwvwclae1#

似乎是Clang版本无法检测主机的Linux版本和GCC版本...
必须添加crt* 路径的Clang代码:
llvm → tools → clang → lib → Driver → Tools.cpp

CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o")));
  CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
  CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));

GetFilePath将尝试在当前ToolChain的getFilePaths()列表中搜索所需的文件(文件clang/lib/Driver/ToolChains.cpp)。如果找不到文件,它将返回未更改的名称。

vyu0f0g1

vyu0f0g12#

在最新的(3.5)发行版中,对于在安装了GCC 4.7之前版本的libstdc++库的系统上使用--with-gcc-toolchain配置选项进行构建的任何人来说,这类问题再次出现。
您将看到它有两种风格:

echo '#include <string>' | clang++ -xc++ -
<stdin>:1:10: fatal error: 'string' file not found
#include <string>
          ^
1 error generated.

......也不会找到各种crt文件。
在这两种情况下,您可以通过以下方法解决问题,直到问题得到解决:

printf '#include <string>\nint main(int argc, char *argv[]) { return 0; }' > /tmp/blah.cc

# Fixes issue not finding C++ headers; note that it must be gcc >= 4.7
clang++ --gcc-toolchain=/path/to/gcc/install -c -o /tmp/blah.o /tmp/blah.cc

# Fixes the link error
clang++ --gcc-toolchain=/path/to/gcc/install /tmp/blah.o /tmp/blah
9jyewag0

9jyewag03#

这个可怕的黑客"修复"了Ubuntu 11.10 x86(Oneiric Ocelot)上与Clang 3.0(r142716)的编译/链接。
在*/usr/include/stdio. h:28 * 中包含的文件中:
/usr/包含/功能。小时:323:10:致命错误:未找到"bits/predefs. h"文件
/usr/文件夹/文件夹:找不到crt1.o:无此文件或目录
/usr/文件夹/文件夹:找不到crti. o:无此文件或目录

diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 75300b5..3e2be30 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -241,6 +241,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
   // FIXME: Handle environment options which affect driver behavior, somewhere
   // (client?). GCC_EXEC_PREFIX, LIBRARY_PATH, LPATH, CC_PRINT_OPTIONS.

+  PrefixDirs.push_back("/usr/lib/i386-linux-gnu");
   if (char *env = ::getenv("COMPILER_PATH")) {
     StringRef CompilerPath = env;
     while (!CompilerPath.empty()) {
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index b066e71..c6ffee8 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -562,10 +562,12 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
       AddPath("/usr/include/x86_64-linux-gnu", System, false, false, false);
       AddPath("/usr/include/i686-linux-gnu/64", System, false, false, false);
       AddPath("/usr/include/i486-linux-gnu/64", System, false, false, false);
+      AddPath("/usr/include/i386-linux-gnu/64", System, false, false, false);
     } else if (triple.getArch() == llvm::Triple::x86) {
       AddPath("/usr/include/x86_64-linux-gnu/32", System, false, false, false);
       AddPath("/usr/include/i686-linux-gnu", System, false, false, false);
       AddPath("/usr/include/i486-linux-gnu", System, false, false, false);
+      AddPath("/usr/include/i386-linux-gnu", System, false, false, false);
     } else if (triple.getArch() == llvm::Triple::arm) {
       AddPath("/usr/include/arm-linux-gnueabi", System, false, false, false);
     }
nkoocmlb

nkoocmlb4#

运行:

clang -v

在我的示例中,输出为:

clang version 3.0 (tags/RELEASE_30/final)
Target: armv7l-unknown-linux-gnueabi
Thread model: posix

以 * root * 身份运行以下命令,使用目标将缺少的目录创建为链接:

ln -s /lib/arm-linux-gnueabi /lib/armv7l-unknown-linux-gnueabi
ln -s /usr/lib/arm-linux-gnueabi /usr/lib/armv7l-unknown-linux-gnueabi
ldconfig

相关问题