Compiling C code with dietlibc and tcc

by Martin Monperrus

Tcc (aka Tiny C Compiler, or tinycc) is a very lightweight C compiler. Dietlibc is lightweight libc (as opposed to GNU libc). Using a tiny C compiler and a tiny libc is a kind of software minimalism.

Requirements

First install dietlibc (apt-get install dietlibc-dev).

Preparing tcc

Download tcc: http://download.savannah.gnu.org/releases/tinycc/

  wget http://download.savannah.gnu.org/releases/tinycc/tcc-0.9.27.tar.bz2
  tar xvjf tcc-0.9.27.tar.bz2
  cd tcc*

Modify configure and set the following variables.

  tcc_sysincludepaths="./"
  tcc_libpaths="./"
  tcc_crtprefix="./"

Then run:

  ./configure

Set CONFIG_TCCDIR in config.mak:

  CFLAGS=-Wall -g -O2 -DCONFIG_TCCDIR="\"./\""

In libtcc.c, remove the forced dependencies to crt1.o and crti.o:

  //      if (output_type != TCC_OUTPUT_DLL)
  //          tcc_add_crt(s, "crt1.o");
  //      tcc_add_crt(s, "crti.o");
          tcc_add_crt(s, "crt0.o");

In tccelf.c, remove the dependency to crtn.o:

  //if (s1->output_type != TCC_OUTPUT_MEMORY)
  //   tcc_add_crt(s1, "crtn.o");

And the run $ make (the part of the Makefile which executes tcc itself will fail).

This produces tcc that is free of any assumption with respect to the libc that is used, it only requires one crt0.o for implementing function _start (see below) . The

  $ ./tcc -vv
  tcc version 0.9.26 (i386 Linux)
  install: /usr/local/lib/tcc/
  crt:
     ./
  libraries:
    ./
  include:
    ./
  elfinterp:
    /lib/ld-linux.so.2

Compiling with tcc

You now need a startup crt file crt0.o that would provide function "_start". There are several ones (see http://www.monperrus.net/martin/compiling-where-is-_start). The one of dietlibc is in a file called start.o. We copy it to crt0.o (since this name is hard coded in tcc, see above):

  cp /usr/lib/diet/lib/start.o crt0.o
  # or
  cp /usr/lib/diet/lib-x86_64/start.o crt0.o
  # you may need also
  # mv ./libtcc.a ./libtcc1.a

And now you can compile against dietlibc:

  ./tcc -L. -L/usr/lib/diet/lib/ -I /usr/lib/diet/include/ -o foo foo.c
  # or 
  ./tcc -L. -L/usr/lib/diet/lib-x86_64 -I /usr/lib/diet/include/ -o foo foo.c

I got lua to be compiled this way.

This enables one to compile C code on machines with no compilation support at all. Basically, to compile C code, you only need tcc, libtcc1.a, libc.a, libm.a, and the dietlibc headers (one single self-contained folder).

Side notes

It is not possible to do the same thing with newlib because newlib heavily depends on the kernel and gcc headers (see https://sourceware.org/ml/newlib/2005/msg00723.html). On the contrary, dietlibc is self-contained.

Tagged as: