10

I just tried out the latest LLVM and Clang trunk versions. They compiled without a single warning out of the box, but I'm having trouble linking a Hello, World! example. My code is

#include <stdio.h>

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

If I compile using

clang test.c

I get the following error

/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)

Using -v shows that the GNU ld is invoked as:

"/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

But I have the crt1.o object file!

locate crt1.o

Output:

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

This also works:

clang -c test.c
gcc test.o

And of course

gcc test.c

What I further tried:

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

I also tried copying the crt1.o file into the current directory. That seemed to work. Well, it didn't compile because after that crti.o was missing.

My Linux distribution is Ubuntu.

Well, I don't really know what to try next. I don't see how I could fix clang nor do I have an idea on how to inject the necessary path in the ld invocation. Any ideas?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ben04
  • 103
  • 1
  • 1
  • 4
  • I only have a brief description of -Xlinker in my clang's page but isn't -Xlinker supposed to be passed twice for options with an arguments? This is what gcc's man pages says for -Xlinker. – anddam Nov 14 '12 at 18:24

4 Answers4

3

It seems to be the Clang version which can't detect the host's Linux version and GCC version...

This code in Clang which must add path to the crt*:

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")));

and the GetFilePath will try to search asked files in getFilePaths() list of current ToolChain (file clang/lib/Driver/ToolChains.cpp). If it can't find a file it will return the Name unchanged.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
osgx
  • 90,338
  • 53
  • 357
  • 513
  • 2
    Curiously the implemtation of that function I have differs from the one you quoted... However adding Paths.push_back("/usr/lib");Paths.push_back("/usr/lib/gcc/i486-linux-gnu/4.4/"); did the trick. If I interprete the code I have correctly then it only looks in /usr/lib when /usr/lib64 does not exist. However that directory exists on my system – Ben04 Nov 12 '10 at 00:01
  • there was a very old quote. now I get the http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ and can check code for your combination of clang rev, ubuntu and gcc version – osgx Nov 12 '10 at 00:03
  • Code of `GetFilePath()` trys to open a file asked (crt1.o) in every directory in `getFilePaths()` list. It will stop if there is a file somewhere or it will return file name without the path – osgx Nov 12 '10 at 00:05
  • 4
    I've had good success setting the environment variable COMPILER_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.4.4 with the latest clang out of SVN (version 3.1SVN). – Sam Feb 06 '12 at 14:26
  • sam, what is the exact svn revision and branch? – osgx Feb 06 '12 at 18:29
1

On the most recent (3.5) release this sort of problem has cropped up again for anyone who does a build using the --with-gcc-toolchain configure option on a system with a pre-GCC 4.7 libstdc++ library installed.

You'll see it in two flavors:

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

... as well as not being about to find the various crt files.

In both cases, the following allows you to work around the problem until it gets fixed:

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Brian Vandenberg
  • 4,011
  • 2
  • 37
  • 53
1

This horrible hack "fixes" compiling/linking with Clang 3.0 (r142716) on Ubuntu 11.10 x86 (Oneiric Ocelot).

In the file included from /usr/include/stdio.h:28:

/usr/include/features.h:323:10: fatal error: 'bits/predefs.h' file not found

/usr/bin/ld: cannot find crt1.o: No such file or directory
/usr/bin/ld: cannot find crti.o: No such file or directory

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);
     }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Peter
  • 61
  • 3
  • 2
    This patch is not necessary anymore since r143344, r143345, r143346. The problem should be fixed now. see http://llvm.org/bugs/show_bug.cgi?id=11223 – Peter Oct 31 '11 at 17:50
0

Run:

clang -v

In my example, the output is:

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

Run the following as root to use the target to create the missing directory as a link:

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user340994
  • 479
  • 4
  • 3