[cfe-dev] How can I make clang/llvm use specific toolchain?

Leonid Borisenko leo.borisenko at gmail.com
Mon Dec 24 12:25:54 PST 2012


Journeyer J. Joh wrote:
> I wonder how I can make clang use specific linker.
>
> I am now trying to compile a hello world c code on an Ubuntu box for
> ARM and X86.
> And I have successfully built for ARM but NOT ABLE TO build one for X86.
>
> I am using a cross toolchain in the scratchbox environment of Tizen SDK.
>
> <...>
>
> The problem above is that clang tries to call "ld" but there is not a
> effective path to it.
> I now need to make clang use a specific "ld" in the cross toolchain of
> the scratchbox.

Recently, I've started using scratchbox2 [1] for ARM cross-compilation and
met the same problem in invoking clang under scratchbox2: executing of
linker by clang wasn't redirected by scratchbox2 to cross-linker. Instead,
host system linker (/usr/bin/ld) was invoked. Also host assembler was
invoked when -integrated-as wasn't used.

I've found source of problem and a workaround. Hope it will help somebody
else.

In short:
* clang tries to find "<triple>-ld" or "ld" executable (as fallback) in a
  bunch of directories. <triple> could be (re-)defined by -target option.
* found executable is invoked by posix_spawn function (on systems, where
  it's supported) or fork/execve (as fallback). posix_spawn support is
  determined in process of LLVM compilation. posix_spawn is supported on
  many systems, Linux including.
* posix_spawn from glibc internally calls fork/__execve, but __execve isn't
  known as intercepting target to scratchbox2, so scratchbox2 couldn't
  change __execve arguments to point to cross-linker.
* and host linker is invoked.

Workaround: I was lucky enough to have cross-linker installed into
/usr/bin/arm-linux-gnueabi-ld. So I've passed following options to clang:

  -target arm-linux-gnueabi -march=armv7-a -mthumb -mtune=cortex-a8

As -target is defined, clang will try to find arm-linux-gnueabi-ld first and
it will be found. -march, -mthumb and -mtune options are overriding defaults
set after -target value.

And 'sb2 clang ...' with these options invokes cross-linker.

Used programs:
* clang 3.2 release from Debian Experimental (package clang 3.2-1~exp1)
* ARM cross-compiling gcc 4.7.2 from emdebian.net (package
  gcc-4.7-arm-linux-gnueabi 4.7.2-4)
* ARM cross-compiling binutils 2.22 from emdebian.net (package
  binutils-arm-linux-gnueabi 2.22-7.1)
* scratchbox2 from git (version 2.3.90, 2.3_development branch,
  commit 6439d12)

Just for reference, here is program flow for linker invoking:

clang: make ld invoking command
===============================

processed by functions sequence looking like
  Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
invoked in file clang/tools/clang/lib/Driver/Tools.cpp

clang: find path to ld
======================

processed by function clang::driver::ToolChain::GetProgramPath( ... )
defined in file clang/tools/clang/lib/Driver/ToolChain.cpp

which is invoking function clang::driver::Driver::GetProgramPath( ... )
(where all logic is contained)
defined in file clang/tools/clang/lib/Driver/Driver.cpp

clang/LLVM/glibc: execute ld command
====================================

processed by function clang::driver::Compilation::ExecuteCommand( ... )
defined in file clang/tools/clang/lib/Driver/Compilation.cpp

which is invoking function llvm::sys::Program::ExecuteAndWait( ... )
defined in file llvm/lib/Support/Program.cpp

which is invoking function llvm::sys::Program::Execute( ... )
defined in file llvm/lib/Support/Unix/Program.inc

which is invoking posix_spawn( ... )
(if HAVE_POSIX_SPAWN was defined in compilation of LLVM)
defined in file glibc/posix/spawn.c

which is invoking function __spawni( ... )
defined in file glibc/sysdeps/posix/spawni.c

which is invoking function __execve( ... )

scratchbox2
===========

scratchbox2 works by preloading it's own library with LD_PRELOAD,
intercepting some library calls (like execve) and changing calls' arguments
according to some (user-defined) rules. For example, execve of /usr/bin/ld
could be changed to execve of /usr/bin/arm-linux-gnueabi-ld. It provides
some transparency to cross-compiling process.

But __execve isn't intercepted by scratchbox2 (looking at source [2]).

[1] http://maemo.gitorious.org/scratchbox2
[2] http://maemo.gitorious.org/scratchbox2/scratchbox2/blobs/master/preload/interface.master



More information about the cfe-dev mailing list