LWN.net Logo

LFCS 2012: LLVM and Linux

LFCS 2012: LLVM and Linux

Posted Apr 26, 2012 16:21 UTC (Thu) by kmccarty (subscriber, #12085)
Parent article: LFCS 2012: LLVM and Linux

For what it's worth, I've found two severe issues in my attempts at experimenting with Clang at the company I work for. (Our production compiler for Linux is currently GCC 4.2.4)

Issue 1 is that it doesn't support OpenMP pragmas for parallelization, which is an absolute blocker to any possibility of our using it for production code. We are currently using it only for its compiler warnings as a static analyzer.

Issue 2 is that if one has installed a version of GCC in /usr/local, it seems to be impossible to build Clang such that by default it will use that GCC version's object files (crtbegin.o, etc.) and libstdc++ headers without actually hacking the portions of the Clang source code where these paths are defined. Perhaps this has improved since the version of Clang I'm at (SVN trunk from Sept. 30, 2011), but I experienced so much pain in getting this to work that I'm very reluctant to attempt to upgrade from this: it looks like all of the relevant Clang code has changed since then, which will cause serious merge conflicts with my local hacks.

At least as of that version of Clang, rather than support different GCC installation locations and default linker arguments with arguments to the configure script, the authors have actually defined the header and library search paths by putting them into the C++ source code, with various if statements based on what Linux distribution and version thereof, as well as what GCC version, that the program appears to be being compiled on.

This makes things easier for distributors, I suppose, although it means Clang will forever be playing catch-up with new versions. For anyone else building Clang, code like the following snippets is so incredibly ill-thought-out that it gives me misgivings about the rest of the project.

  static const char* GccVersions[] = {"4.6.1", "4.6.0", "4.6",
                                      "4.5.3", "4.5.2", "4.5.1", "4.5",
                                      "4.4.6", "4.4.5", "4.4.4", "4.4.3", "4.4",
                                      "4.3.4", "4.3.3", "4.3.2", "4.3",
                                      "4.2.4", "4.2.3", "4.2.2", "4.2.1",
                                      "4.2", "4.1.1"};

...

        if (GccTriple == "i386-linux-gnu") {
          // Ubuntu 11.04 uses an unusual path.
          std::string t4 =
              std::string(*it + "lib/i386-linux-gnu/gcc/i686-linux-gnu/") +
              GccVersions[i];
          if (!llvm::sys::fs::exists(t4 + "/crtbegin.o", Exists) && Exists)
            return t4;
        }

...

    else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-redhat-linux",
             Exists) && Exists)
      GccTriple = "x86_64-redhat-linux";
    else if (!llvm::sys::fs::exists("/usr/lib64/gcc/x86_64-suse-linux",
             Exists) && Exists)
      GccTriple = "x86_64-suse-linux";

...

  LinuxDistro Distro = DetectLinuxDistro(Arch);

  if (IsOpenSuse(Distro) || IsUbuntu(Distro)) {
    ExtraOpts.push_back("-z");
    ExtraOpts.push_back("relro");
  }

...

  if (IsDebian(Distro) || IsOpenSuse(Distro) || Distro == UbuntuLucid ||
      Distro == UbuntuJaunty || Distro == UbuntuKarmic)
    ExtraOpts.push_back("--hash-style=both");

[All excerpts above are from lib/Driver/ToolChains.cpp at SVN rev 140874]


(Log in to post comments)

LFCS 2012: LLVM and Linux

Posted May 1, 2012 14:53 UTC (Tue) by jwakely (subscriber, #60262) [Link]

Issue 2 is that if one has installed a version of GCC in /usr/local, it seems to be impossible to build Clang such that by default it will use that GCC version's object files (crtbegin.o, etc.) and libstdc++ headers without actually hacking the portions of the Clang source code where these paths are defined. Perhaps this has improved since the version of Clang I'm at (SVN trunk from Sept. 30, 2011)
Yes, it changed. At one time you needed to hack the source. Then you needed to use --with-cxx-include-root and --with-cxx-include-arch at configure-time, now you just use --with-gcc-toolchain and it does the right thing. It took a while getting there though.

LFCS 2012: LLVM and Linux

Posted May 1, 2012 22:29 UTC (Tue) by kmccarty (subscriber, #12085) [Link]

Yes, it changed. At one time you needed to hack the source. Then you needed to use --with-cxx-include-root and --with-cxx-include-arch at configure-time, now you just use --with-gcc-toolchain and it does the right thing. It took a while getting there though.

Thanks much for the update, this appears to work as advertised. I guess it is only available in SVN trunk, though, not in the 3.0 release?

I can get rid of my local Clang patches except for a couple lines to disable adding the --no-add-needed linker option when "IsRedhat(Distro)" returns true. (I'm not sure whether this distro autodetection is still enabled when GCC_INSTALL_PREFIX is pre-#define'd, but I didn't want to chance having to do yet another rebuild.)

I was even able to remove a bunch of -isystem flags pointing at GCC headers from the Clang-invoking wrapper scripts I have. I can't say that the relevant parts of Clang source code got very much prettier, though ;-)

LFCS 2012: LLVM and Linux

Posted May 2, 2012 9:00 UTC (Wed) by jwakely (subscriber, #60262) [Link]

> I guess it is only available in SVN trunk, though, not in the 3.0 release?

Dunno, sorry, I only use trunk

LFCS 2012: LLVM and Linux

Posted May 2, 2012 16:04 UTC (Wed) by kmccarty (subscriber, #12085) [Link]

(Replying to myself)

I was even able to remove a bunch of -isystem flags pointing at GCC headers from the Clang-invoking wrapper scripts I have.

Sadly I spoke too soon -- Clang compiled with --with-gcc-toolchain is not finding omp.h, which is under the GCC installation at <gccroot>/lib/gcc/x86_64-unknown-linux-gnu/4.2.4/include together with a few other things like float.h, varargs.h and limits.h. Ought I to file a bug?

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds