[uClibc] Buildroot questions.

Rob Landley rob at landley.net
Wed Aug 6 07:09:57 UTC 2003


So I'm playing with buildroot some more, and writing up a HOWTO, and I get
some questions:

I want to break the target list out of the Makefile.  Editing the makefile
should NOT be a necessary part of configuring things except for advanced users.
As such, a few defaults should be set to newbie-friendly values, and the
target list should be broken out.

The default value changes I propose are:

USE_UCLIBC_SNAPSHOT:=false
USE_BUSYBOX_SNAPSHOT:=false

For the simple reason that anybody who knows enough to use that knows enough
to change them (or can figure it out pretty quick).  A newbie's first
experience should probably be with a release version.

Just about all the other configuration you do is either compiler optimizations
(for which hacking the makefile is relatively obvious), or selecting targets.
There is one exception: USE_UCLIBC_TOOLCHAIN.

Question: What's USE_UCLIBC_TOOLCHAIN for?  I mean, what's the alternative?
Can anything after this point build if you DON'T first build the UCLIBC
toolchain?  (Does the rest of buildroot do anything useful if
USE_UCLIBC_TOOLCHAIN is false?  What will it do, build a root filesystem for
glibc instead?  Is this useful?  If so, shouldn't that just be a
glibc_toolchain target in that case that could be swapped out for
uclibc_toolchain?  If it doesn't build ANY toolchain, why not just remove the
uclibc_toolchain target from the targets list and document that?)

Note that the USE_UCLIBC_TOOLCHAIN define is used in Makefile as a
pointless guard around "TARGETS+=uclibc_toolchain" (we're already asking
them to add and remove TARGETS from the makefile as the primary configuration
mechanism; if they want to remove it why not just have them do so?)
And then again it's used as a guard at the top of uclibc_toolchain.mk
(#ifdefing out the whole file if it's not set), which is pointless if you
already #ifdefed out the include...

There are also some checks for it in gcc_target.mk.  (I believe gcc_target
makes the native uclibc compiler inside the root_fs, and the uclibc_toolchain
makes the cross-compiler on the host system, right?  Or is it more complicated
than that?)  The use of USE_UCLIBC_TOOLCHAIN in gcc_target largely seems to
skip redundant steps (like the first gcc build step, and building binutils)
if the toolchain build already did them.  It might be possible to avoid this
with more intelligent dependencies, or if it is really needed then maybe it's
possible to have uclibc_toolchain set it when it's included/run.  (And
again, what is buildroot used for when the toolchain is NOT built?)

Now we get to a new target list selection mechanism.  There are a couple of
options.  One is to just break it out into a separate "config" file that gets
included from the Makefile, still using make systax (so a bunch of
TARGETS+=blah lines).  That's a minimal disruption, and about a ten minute
job.  It also naturally preserves target ordering, which is nice if you
want uclibc_toolchain to build first and ext2root to run last.

A second thought is to pull a fast one on the "make" directory.  Have every
*.mk file add itself to the TARGETS list as it's included.  Rename the existing
make directory "examples", and create a new empty directory for "make".

Downsides:
  - directory renames bork CVS because CVS is dumb.  (So call the new
    directory "config" and rename the include.)
  - Ordering isn't naturally preserved.  (This could be fixed by putting
    proper inter-package dependencies in the makefiles, so openssh knows it
    needs openssl, and everything knows it needs a toolchain, and then make
    does the ordering for us.  That might be a good idea anyway...)

Upsides:
  - People have to look in the "make" directory to see what their options are,
    this gives them an incentive.
  - uclibc_toolchain.mk could set USE_UCLIBC_TOOLCHAIN to true when it's
    included, hence cleaning up gcc_target becomes unnecessary.

In either case, moving the targets to a file or to a directory, it becomes
MUCH easier to slap together an automated tool to configure a build, ala
menuconfig.

if we do this cleanup, buildroot might actually be ready for a numbered release
version.  (Presumably the same version number as the uclibc it uses...)

Rob

(More question comparing uclibc_toolchain with gcc_target...  If there's
a guard against recompiling binutils
-------------- next part --------------
The buildroot package automates the creation of a uClibc-only development
system.  This can be run under an existing linux system via a "user mode
linux" kernel and a loopback mounted root partition, or booted and run as
a full fledged linux system.

To create one of these suckers, follow these steps:

1) Download the buildroot package from

     http://www.uclibc.org/cgi-bin/cvsweb/buildroot/buildroot.tar.gz?tarball=1

   (Buildroot does not have releases yet, the above link will grab a snapshot
   of the current CVS version.)

2) Unpack the tarball and read the README file.

3) Edit the Makefile and adjust any options you feel like.  The Makefile
   has four sections:

   A) configuration options.

      A good first guess here is to set both USE_UCLIBC_SNAPSHOT and
      USE_BUSYBOX_SNAPSHOT to false, and leave everything else alone your
      first time.

   B) TARGETS list.

      This is the list of what to build.  Most of the interesting configuration
      is done by adding packages to the TARGETS list.  Step 4 will talk all
      about this; we'll come back to it.

   C) Root filesystem type.

      A special target at the end of your build creates a filesystem image
      file.  (An image file is a file that contains a virtual disk image,
      I.E. a bunch of virtual sectors all in a row, formatted as a filesystem,
      just like it would look like if it were on a block device like a ramdisk,
      hard drive, or CD-ROM.  You may have used an ISO cd-rom image file to
      burn a CD, or a floppy image file to create a boot diskette.  This is
      similar.  Step 7 of this HOWTO explains how to use this image file
      once the build has created it.)

      Since this image file gets formatted, we have to select the filesystem
      type to format it as.  EXT2 is the standard Linux filesystem type, and
      that's the default.  You can also select cramfs (a compressed read-only
      filesystem, suitable for burning into ROM), or jffs2 (a filesystem
      designed for use with flash memory).

      You can leave this at the default (ext2root) your first time

   D) Everything else.

      There's generally no reason to play with the rest of the Makefile.
      Someday, the first three sections may be broken out into a seperate
      configuration file that's included from the Makefile; in the meantime,
      just ignore the second half of the file unless you're curious how it
      works.


4) Select the packages you want to build.

   The Makefile contains a number of example targets.  You almost always want
   "uclibc_toolchain", which builds three things:

     A) uclibc itself
     B) gcc (configured to link executables against uclibc instead of glibc).
     B) the binutils package (linker, assembler, and other things needed
        to actually make executables and libraries).

   You need the uclibc toolchain to build anything else.

   Beyond the toolchain, an absolutely minimal system will contain the
   targets "busybox" and "tinylogin", to allow you to login and execute
   standard unix commands.  (Busybox is another project in the spirit of
   uclibc, re-implementing tiny versions of most of the standard unix command
   line utilities, and in the process providing a substitute for half a dozen
   traditional packages like fileutils, textutils, sh-utils, sysvinit, bash...)

   Adding targets appends them to the end of the list, and they get built in
   order.  This is important because some packages have prerequisites; for
   example, if you want openssh you must first make zlib and openssl.  Good
   documentation on this sort of thing may be found on the Linux From Scratch
   website: http://www.linuxfromscratch.org

   The make file contains a number of sample targets, including a group of
   packages required to make a development with enough tools to compile
   most other packakges, debugging tools, and network configuration tools
   needed to make a standalone firewall or smart router.

   The complete list of available targets can be found in the "make"
   subdirectory: there are a bunch of makefiles in there that know how to
   build existing packages under the uclibc environment created by buildroot.
   All of makefiles in this directory are automatically included from the
   top level Makefile (the line is "include make/*.mk"), and the target
   to trigger each one is usually found near the end of the makefile in
   question.  (For example, in "autoconf.mk", the target is "autoconf:",
   so you'd add "TARGETS+=autoconf" to the target list section of the top
   level Makefile in order to have buildroot build it for you.)

5) Optionally copy any of the tarballs that buildroot needs into the sources/dl
   directory.  If, for example, you already have the gcc-3.2 tarball or the
   linux-2.4.19 tarball, just copy them into place so you can avoid having
   buildroot download them once again from the net.

   Note that if you would like to download all the source for your selected
   targets immediately (useful on a dialup connection, or taking a laptop
   with you on a plane), the command is "make source".  (Be sure to configure
   your target list before doing this.)  Once the build system has downloaded
   a package, it keeps it around for future builds.  A "make clean" won't
   delete downloaded source packages (although a "make distclean" will).

   By default, the build system will download each package as it finds it
   needs it (using the "wget" command, which most modern Linux distributions
   have).

6) Run 'make' and wait a long time...  There is a lot of stuff that needs to
   be compiled, so be patient.  Go to the kitchen and make yourself a nice
   sandwich.  Since buildroot will download any source files it needs which
   are not already sitting in the sources/dl directory, if you have a slow net
   connection you might consider starting this before you go to bed in the
   hope that it will be done when you wake up. ;-)

7) When buildroot finishes, there will be a new Linux system sitting in
   build_i386/root (or whatever architecture your're building for).  If you're
   an old hand at installing filesystems by hand, you can copy it to a bootable
   partition, and use a boot disk or play with lilo or grub.  (One easy way to
   copy files while preserving permissions and links and such is to use a pipe
   between two instances of tar, ala:

     tar cC build_i386/root . | tar xvC /destinationdir

   To learn how to make a partition bootable, read the Linux Bootdisk HOWTO at
   "http://www.tldp.org/HOWTO/Bootdisk-HOWTO/".

   For pure testing purposes, you can chroot into the new system.  While
   logged in as root, go to the buildroot directory (where the Makefile is)
   and type "chroot build_i386/root /bin/sh --login", then try running stuff.
   Type "exit" when you want to return to your original Linux system.  See
   "man chroot" for more info.

8) If you told the build to create any of the filesystem image targets, you
   can loopback mount them and chroot into them.  As root, try something
   vaguely like:

     mkdir temp
     mount -o loop root_fs temp
     chroot temp /bin/sh --login

   Type "exit" when you're done, and don't forget to "umount temp".

   If you would like to make an initial ram disk, mount the root_fs, create a
   file "initrc" in the root directory of root_fs (which is a shell script that
   will run in instead of init), umount the root_fs, and then compress the
   root_fs file with gzip.  You're done.  Add "initrd=/path/to/root_fs" to
   the linux kernel's command line next time you boot, and it should use
   your new initial ramdisk.  (Note that if your initrc script exits, the boot
   will continue, mounting the normal root filesystem and running init.  For
   more information, see the bootdisk howto.)

   If you used the "user-mode-linux" target, the build process will create a
   special linux kernel that can be run as a normal application program.
   Just run the "UMlinux" executable; it will automatically mount the
   root_fs image and pop up some Xterm windows with which to interact with it.
   For more information, go to "http://user-mode-linux.sourceforge.net".


More information about the uClibc mailing list