Switching between toolchains made easy!

It is quite common to have several toolchains and to switch back and forth between them while doing development. At least, this is something I do a lot when doing Buildroot development and debugging. As I hate typing full paths all the time, I usually put the toolchain bin/ directory into my $PATH variable, so that I can easily access the toolchain binaries. However, it means that everytime you run a new shell or everytime you want to switch from one toolchain to another, you need to modify the PATH variable manually by re-exporting it. Of course, one could easily put all the bin/ directories of all toolchains in the PATH, but that would clutter what is shown when I do arm-TAB-TAB, and that’s not nice.

So, I ended up hacking a few lines of Bash that provide me with two new commands: xtoolsadd, to add a toolchain to my PATH and xtoolsdel, to remove a toolchain from my PATH. These commands work by making the assumption that all toolchains are stored in a common directory. In my case /usr/local/xtools/ contains all the toolchains, one per subdirectory. So I have /usr/local/xtools/arm-unknown-linux-gnu for an ARM glibc-based non-EABI toolchain, or /usr/local/xtools/arm-unknown-linux-uclibcgnueabi for an ARM uClibc-based EABI toolchain).

So, now I can do things such as

xtoolsadd arm-unknown-linux-gnu

or

xtoolsdel arm-unknown-linux-uclibcgnueabi

Because these commands must modify the PATH variable of the current shell, they cannot be implemented as separate shell scripts, so they are in fact implemented as functions in my ~/.bashrc script. And in addition to these functions, I also implemented completion, so when you do xtoolsadd TAB-TAB, it gives you a choice of toolchains, and if you start typing one and press TAB, it will just automatically complete for you. The same thing works with xtoolsdel, of course.

To make this work, here is what you need to put in your ~/.bashrc file:

export XTOOLSDIR=/usr/local/xtools

xtoolsadd() {
    TOOLCHAINDIR=$XTOOLSDIR/$1/bin
    if [ ! -d $TOOLCHAINDIR ] ; then
        echo "Directory $XTOOLSDIR doesn't exist"
    else
        case "$PATH" in
            *"$XTOOLSDIR"*)
                ;;
            *)
                export PATH=$TOOLCHAINDIR:$PATH
        esac
    fi
}

xtoolsdel() {
    TOOLCHAINDIR=$XTOOLSDIR/$1/bin
    NEWPATH=
    found=0
    for i in $(echo $PATH | tr ":" "\n") ; do
        if [ $i == $TOOLCHAINDIR ] ; then
            found=1
        else
            NEWPATH=$NEWPATH:$i
        fi
    done
    if [ $found == 0 ] ; then
        echo "$1 is not in your PATH"
    else
        export PATH=$NEWPATH
    fi
}

_xtoolsadd() {
    cur=${COMP_WORDS[COMP_CWORD]}
    LIST=$(ls -1 $XTOOLSDIR | tr "\n" " ")
    COMPREPLY=( $( compgen -W "$LIST" -- $cur))
}

_xtoolsdel() {
    cur=${COMP_WORDS[COMP_CWORD]}
    LIST=$(echo $PATH | tr ":" "\n" | grep "^$XTOOLSDIR" | sed "s%$XTOOLSDIR/\([^/]*\)/bin%\1%")
    COMPREPLY=( $( compgen -W "$LIST" -- $cur))
}

complete -F _xtoolsadd xtoolsadd
complete -F _xtoolsdel xtoolsdel

The shell code may not be perfect or fully optimized, but it works. Of course, if you have suggestions or questions, don’t hesitate to post comments!

Buildroot gains better support for external toolchains

Buildroot logoBuildroot is a tool that I’ve already covered in a previous blog post. To me, its main purpose is to build the root filesystem for an embedded Linux system, with all the necessary applications and libraries. It automates the tedious process of cross-compiling and integrating all the free software components in an embedded system.

In addition to root filesystem generation, Buildroot is also known for its ability to generate a uClibc-based cross-compilation toolchain. Buildroot used to be for quite some time the only way to generate a toolchain based on this size-effective C library, but it is no longer the case with Crosstool-NG supporting glibc, uClibc and eglibc.

However, I’ve personaly never been really satisfied with uClibc generation of cross-compiling toolchains:

  • It mixes the process of the cross-compilingn toolchain generation with the process of root filesystem generation, which are, in my opinion, two very different processes. Once your toolchain is generated, you generally don’t touch it, but regenerate your root filesystem dozens or hundred of times until all your components are here and properly integrated.
  • The attention paid to toolchain generation in the Buildroot project itself is relatively small, while other projects like Crosstool-NG or vendors like Codesourcery, are specifically dedicated to providing toolchains. The fact that, for example, uClibc is the only C library supported is one example of this.
  • It might necessary, for various reasons, make sense to use an already existing toolchain.

Support for the usage of external toolchains has already been present in Buildroot for a long time, but wasn’t developed enough to be easily usable. Months ago, I’ve started to improve the situation (here, here, here and here), and last week, two other patches have been integrated.

  • The first patch, visible here removes the ugly configuration option that allows to configure the set of libraries that must be copied to the target filesystem, and replaces it with a nice selection of the C libary type: uClibc or glibc. It makes it clear that generating Linux system with the glibc library is possible with Buildroot, even if Buildroot has often been advertised as a uClibc only tool.
  • The second patch, visible here adds checks for the conformity of Buildroot configuration versus the C library configuration. There are configuration options in Buildroot that must tell whether the C library supports IPv6, supports RPC, supports locale, supports large file, etc. These options must be set in the configuration interface according to the C library configuration, because some userspace packages depend on them. The added checks verify that the value set to these options match the configuration of your C library

So, now, external toolchains are a little bit easier to use with Buildroot, and your own vendor toolchain, Codesourcery toolchains or any other toolchain can be used with Buildroot. The only requirement is that the toolchain supports the sysroot feature, which is very common in most toolchains.

Crosstool-ng 1.3.0 released!

Crosstool-ng is a tool that allows automated building of cross-compiling toolchain, easing a process known to be very difficult. Crosstool-ng has been started as a rewrite of Crosstool, the famous tool authored by Dan Kegel. Now Crosstool-ng offers several improvements over Crosstool: an active development community, stable releases, support of uClibc, glibc and eglibc, a menuconfig configuration interface, a good documentation, etc.

Yann Morin, the lead developer of Crosstool-ng announced today the release of Crosstool-ng 1.3.0. He says: « There has been many improvements, new features and bug fixes all around. If I had to, my pick would be the support for the gcc 4.3 series. But I would also have to tell you about the latest uClibc version, support for eglibc, and the ability to build bare-metal compilers, and the list would not yet be complete… »

He also mention that SuperH and IA-64 can now build a minimalist C-only toolchain, so the support for these architectures is not complete yet, but progressing. Of course, most components have been updated: new versions, new features, updated patchsets, etc. It for example include support for the latest version of uClibc, 0.9.30, released only two weeks ago.

The Changelog is available, as is a tarball of the new release.

If you need to build some cross-compiling toolchain, you definitely should take a look at Crosstool-ng. It’s great, and well supported: Yann is both very responsive and very helpful when problems are being reported.