This course will become read-only in the near future. Tell us at community.p2pu.org if that is a problem.

Troubleshooting


When a package build fails

.Your task this time ist to simply keep this page opened in another tab. You're done, so go ahead and check it off. Refer to it later if a package build fails.

  • The most likely problem is a missed depencency. If you're following instructions you got online, and THEY missed a dependency, the right thing to do if you have time is to drop them a line and let them know.
     
  • The second most likely problem is that you are trying to install an old version of the package. Check the home page for the package and see if they've released a more recent version. This also means you can sometimes solve your problem by simply waiting. If you need to report a problem, most packages have tracking lists or bug tracking programs like bugzilla.
     
  • The the third most likely problem is that your version is too recent. You want to chase stable versions of packages, but not development versions, unless the stable ones haven't been updated in a long time or you've already tried them. The reason why this is a problem is sometimes called "dependency hell". Some other software that relies on your package hasn't caught up to the bleeding edge software you're installing.
     
  • Feeling "helpless" ? Let the configure script know!

    ./configure --help | less

    "Helpless" works for a LOT of unix tools - check it out! Here it will give you a brief description of every option you can pass the configure script. There are a lot, but they're organized. Look for these targets:

    --with-package
    --without-package
    --enable-package
    --disable-package

    Most build problems are dependency problems. You can use these switches to disable packages you don't have and functionality you don't need, and you can use the list to help you track down dependencies.

     
  • You can get the version number from most installed programs with this flag:

    --version

    Running a command with that flag will give you two key pieces of information: whether it exists, and its version number. If it tells you the binary doesn't exist, but you're sure it does, it means you're missing a library. The LDD command will tell you which library you're missing. You run it like so:

    ldd /bin/progtocheck

    You can also run that command directly on a library.

    You can get a list of every library associated with an entire package if you have pkgconfig installed like this:

    pkgconfig --libs packname

    That command will give you some output that looks like

    -L/opt/packname/lib -lone -ltwo -lthree

    Here we see three libraries, called libone, libtwo, and libthree. The -L part might not be there; if it's not, leave out the third substitution in this next command:

    ls -l /{,usr,usr/local,opt/packname/}lib/lib{one,two,three}*


    If you looked and you have all the right libraries, it's possible you forgot to run ldconfig. ldconfig is a program that makes symbolic links for different version numbers for libraries automatically. This is done for backwards compatibility. You can run ldconfig, as an administrator, like this:

    ldconfig -l
    ldconfig


    It's hacky and could lead to long term problems, but if that didn't work, you can try making some symbolic links manually. This is usually safe if you're moving from an old version to a new version. This example would link version 10 to your current version:

    ln -s /usr/lib/libone.so{,.10.0}

    Even hackier, but if you're 100% sure you don't need some functionality, you can try building the package with a "faked" library, like this:

    touch /usr/lib/libone.so.10.0
     
  • If the configure script is running a test you don't want it to run, you can force that test to pass with a config.cache file. This is a little in depth, but there are examples in the book covering how to do this. The names of the test targets can be found in the configure.in file if it's present, or the configure file if not.
     
  • If it's present, the config.log file in the package's build directory will be a very detailed and easy to follow log covering everything the configure script did. It's very likely that your problem is right at the end of config.log .
     
  • When you write specs, be verbose. Most command line tools have a -v switch.
     
  • Also when you're writing specs that are shell scripts, use "set -e". This will cause the script to exit immediately if there are any errors. This makes it very easy to track down problems.
     
  • Try copying error messages verbatim.
    • The line that contains "error:" or "Error:", a filename, a line number, and an error description, after removing the line number, can be pasted directly into a search engine, in quotes. 99 times out of 100 this will give you a place to start. Mailing lists are the best results, followed by bugzilla pages, and finally message boards.
       
    • If you need a good tool for copying text in from the console, there's "xsel". If you're on windows, you'll need to build this in cygwin with x11 development headers (package xorg-server-devel)and an x server like xming running.

      Start to finish, to compile xsel it's
      cd ~/clfs/build
      wget
      http://svn.kfish.org/xsel/trunk/xsel.c
      wget http://svn.kfish.org/xsel/trunk/xsel.h

      gcc -DVERSION="\"2001\"" xsel.c -o xsel -lX11

      And to install, it's (add .exe or another extension as appropriate)

      install -v -m755 /home/user/clfs/build/xsel /usr/bin/xsel

      Once you've done that, you can pipe all the output from a command through it and into your clipboard like so:

      make 2>&1 | xsel -b

      The version I grabbed is not the original version. That is no longer available online. It used to be at http://www.niksula.cs.hut.fi/~vherva/xsel/xsel.c .
       
    • It's a good idea when you're asking for help online to be verbose, but not too verbose. The book recommends this as well. You'll want to send all your output between the first occurence of the word "error" or "Error" at the beginning of a line, and the end of what you captured.
       
    • The "2>&1" in the above statement is what's called a "redirect". Bash gives you output on two "channels". Channel 1 is called "standard out", and channel 2 is called "standard error". Pipes on the right side of the > symbol need the symbol & in front of them. You can also pipe into a file like this:

      command > somefile.txt

      One use of this is to turn off a channel. To turn off standard error, it's

      command 2>/dev/null

      /dev/null is a special file called the "bit bin". Anything you write to it is immediately deleted, and reading it is always like reading an empty file.


      • If you're redirecting multiple times, like say channel 1 and channel 2 to a file, the format is this (NOT intuitive):

        make > somefile.txt 2>&1

        In other words, you dump to a file first, THEN you send channel 2 into channel 1

         
      • If you need to split something so it goes into a file AND shows up on your screen, you can do that with the tee command like this:

        make 2>&1 | tee -a logfile.txt

        The -a flag means "append"; if you'd rather delete the contents of logfile.txt and start writing to a fresh log, just omit it.

         
  • When you make changes, make them to the spec. This is the other reason I picked RPM; it has options for letting you skip part of the build process and warp right to whatever was giving you problems. If you change the spec, then you don't have to retrace your steps later. And there will be a later.
     
  • Between builds, always at the very least run the build target "make clean". If it exists, "make distclean" is better, and if it exists, "make mrproper" (I remember "mister proper") is the best. If no clean target exists, move your changes and hacks and kludges out of the directory and then delete the entire package directory.


    • EXCEPTION: If you're trying to track down a problem, it's sometimes useful to NOT run make clean. If you just run "make" again, it will pick off close to where it choked last time. HOWEVER, once you've fixed the problem, always run make clean to make sure you've REALLY fixed the problem.
       
  • Some packages have a "make check" or "make test" build target. These are more for making sure something was really built correctly than tracking down problems, but can be used for both purposes. The upshot is that this will pretty much tell you exactly what's wrong. The downside is that you'll have a LOT of output to sift through, and some tests have added dependencies - and sometimes those dependencies include the package you're trying to install.
     
  • When all else fails, patch. Don't put any changes any source files in your spec; always add them to a patch file. This is how you do that:


    • copy the file you're changing:

      cp ./path/to/file/you/are/changing.c{,.orig}
       
    • make your changes
       
    • create a patch (pay careful attention to where the comma is):

      diff -du ./path/to/file/you/are/changing.c{.orig,} > \
        packagename-version-description.patch
       
    • Keep your patches saved somewhere. They can be useful to other people with the same problem as you, and even developers. It's a good idea to keep them under version control.

Task Discussion