Creative Commons

2008-08-01 12:29:12

Installing camE: A Tutorial On Compiling From Source

I recently ran out of space on my main desktop with an 80GB drive. So I bought a 500GB drive to replace it. Instead of dd'ing the old drive to the new drive, I decided I was going to do a fresh install. My machine had originally been Fedora 5, upgraded to Fedora 6, upgraded to Fedora 7. Not that anything was wrong with it... Unlike Microsoft OSs, Linux upgrades perfectly fine without any degradation. However, I bit the bullet and started over.
On the old install I used `camstream` as the program that snapped webcam images and uploaded them to my website. That was a bit too fat for me. I just wanted a simple command line tool to do the same thing. I did a few Google searches and came across `streamer` from the XAwTV package. I played with it for a few minutes and could not, for the life of me, get it to work. So I continued my search. That's when I came across camE. It fulfilled all of my needs and is what's producing my site's webcam image at this very moment.
You can grab the camE tarball from it's website. Now let's start the install.
NOTE: You may wonder why I'm doing a step-by-step install... It's because getting camE to install takes some finessing that casual Linux users will find difficult.
> tar xzf camE-1.9.tar.gz > cd camE-1.9 > make
At this point you will be presented with a gajillion errors and warnings. If you scroll up to the first couple messages produced from the `make` command, you'll see this:
/bin/sh: giblib-config: command not found webcam.c:25:20: error: Imlib2.h: No such file or directory webcam.c:26:20: error: giblib.h: No such file or directory
This tells us two things. First, we don't have the IMlib libraries and second, we don't have the Giblib libraries. Yum to the rescue. First, let's look to see what's available.
> yum list | grep -ie ^imlib imlib2.i386 1.4.0-7.fc9 installed imlib.i386 1:1.9.15-7.fc9 fedora imlib-devel.i386 1:1.9.15-7.fc9 fedora imlib2-devel.i386 1.4.0-7.fc9 updates imlib2-id3tag-loader.i386 1.4.0-7.fc9 updates > yum list | grep -ie ^giblib giblib.i386 1.2.4-11 fedora giblib-devel.i386 1.2.4-11 fedora
You may be asking yourself, "I have imlib2 installed, why does it still say I don't have it?" This is a very important thing to remember when compiling programs from source. When `make` tells you that you don't have something installed, such as imlib2, it's ACTUALLY telling you that you don't have the SOURCE of imlib2 installed. `make` needs to access the source code in order to compile it into whatever program you're building. So, even though we have the BINARIES of imlib2, we need the source, also known as the -devel package. And while we're at it, let's get giblib also.
> yum install -y imlib2-devel giblib giblib-devel Excluding Packages in global exclude list Finished Setting up Install Process Parsing package install arguments Resolving Dependencies --> Running transaction check ---> Package giblib.i386 0:1.2.4-11 set to be updated ---> Package imlib2-devel.i386 0:1.4.0-7.fc9 set to be updated ---> Package giblib-devel.i386 0:1.2.4-11 set to be updated --> Finished Dependency Resolution Dependencies Resolved ============================================================================= Package Arch Version Repository Size ============================================================================= Installing: giblib i386 1.2.4-11 fedora 22 k giblib-devel i386 1.2.4-11 fedora 10 k imlib2-devel i386 1.4.0-7.fc9 updates 197 k Transaction Summary ============================================================================= Install 3 Package(s) Update 0 Package(s) Remove 0 Package(s) Total download size: 229 k Downloading Packages: (1/3): giblib-devel-1.2.4-11.i386.rpm | 10 kB 00:00 (2/3): giblib-1.2.4-11.i386.rpm | 22 kB 00:00 (3/3): imlib2-devel-1.4.0-7.fc9.i386.rpm | 197 kB 00:00 Running rpm_check_debug Running Transaction Test Finished Transaction Test Transaction Test Succeeded Running Transaction Installing : imlib2-devel [1/3] Installing : giblib [2/3] Installing : giblib-devel [3/3] Installed: giblib.i386 0:1.2.4-11 giblib-devel.i386 0:1.2.4-11 imlib2-devel.i386 0:1.4.0-7.fc9 Complete!
Ok, now that we have all (hopefully) of the dependencies, let's run `make` again and cross our fingers.
> make gcc -O3 -g -Wall -I./.. -I.. -D_GNU_SOURCE `giblib-config --cflags` -c -o webcam.o webcam.c webcam.c: In function ‘add_time_text’: webcam.c:654: warning: the address of ‘line’ will always evaluate as ‘true’ webcam.c: In function ‘ftp_upload’: webcam.c:991: error: ‘CURLOPT_MUTE’ undeclared (first use in this function) webcam.c:991: error: (Each undeclared identifier is reported only once webcam.c:991: error: for each function it appears in.) webcam.c:991: warning: type defaults to ‘int’ in declaration of ‘_curl_opt’ webcam.c: In function ‘main’: webcam.c:1291: warning: pointer targets in assignment differ in signedness <<<SNIPPED>>> make: *** [webcam.o] Error 1
Oh poop, it broke again. How do we know? The last line says "Error 1". That's bad. You need to scroll up the output until you see the cause of the error. In this case, CURLOPT_MUTE was undeclared. Ok, we know the problem, and we also know that it occurs on line 991 of webcam.c. So, let's go there and fix it.
> vi webcam.c
Once in `vi`, type :991 and hit ENTER to go to line 991. You will see this snippet of code.
/* shut up completely */ if (ftp_debug) curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1); else curl_easy_setopt(curl_handle, CURLOPT_MUTE, 1);
So what does this mean? Well, somewhere it's figuring out whether the user has enabled ftp debugging. If they have, use the verbose output, if they haven't, use muted output. Now we already know that CURLOPT_MUTE is the problem. It's not declared anywhere. There is another similar variable, CURLOPT_VERBOSE, which didn't produce an error. So what can we do? Well, since I always want verbose output, I can just edit this code, comment out the if/else and the CURLOPT_MUTE line, leaving only the line that works.
/* always be verbose */ // if (ftp_debug) curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1); // else // curl_easy_setopt(curl_handle, CURLOPT_MUTE, 1);
There... Now the if/else lines are commented out and so is the line containing the broken CURLOPT_MUTE variable. Let's save the file and run `make` again.
> make gcc -O3 -g -Wall -I./.. -I.. -D_GNU_SOURCE `giblib-config --cflags` -c -o webcam.o webcam.c webcam.c: In function ‘add_time_text’: webcam.c:654: warning: the address of ‘line’ will always evaluate as ‘true’ webcam.c: In function ‘main’: webcam.c:1291: warning: pointer targets in assignment differ in signedness <<<SNIPPED>>> gcc -O3 -g -Wall -I./.. -I.. -D_GNU_SOURCE `giblib-config --cflags` -c -o parseconfig.o parseconfig.c gcc -O3 -g -Wall -I./.. -I.. -D_GNU_SOURCE `giblib-config --cflags` -o camE webcam.o parseconfig.o `giblib-config --libs` -lcurl
Ok, no errors. The code has been compiled. Now we just need to install it. Remember, unless you're logged in as root, you don't have rights to anywhere these files will be installed into. So, either `su` to root or use `sudo` if you have it configured.
> sudo make install mkdir -p /usr/local/bin /usr/bin/install -c camE /usr/local/bin
Woohoo! It's installed. Now what? There's no documentation, so it took me a few minutes to figure out how to get this to actually work. Where do you configure what FTP server you want to use? Where do you set the filename? Image dimensions? There's a dotfile that you need to put in your home directory that contains all of these settings. Luckily, a fully populated example is provided with the camE source.
> cp example.camErc ~/.camErc > vi ~/.camErc
Now that we're in `vi` we can set our own settings. Here are just the settings that I have changed. If you want to change more, feel free, but these settings are what produces the webcam image on my site (of course, I have sanitized sensitive information).
[ftp] host = user = yourUsername pass = yourPassword dir = public_html/images file = webcam.jpg [grab] text = width = 160 height = 120 delay = 20 #logfile = /home/gilbertt/.camlog #infofile = /home/gilbertt/.caminfo archive_shot_every = 0
I want to reiterate that the above settings are just my changes to the .camErc file. That file has 182 lines total, so you'll have to search for those lines. Anyway, now that we're configured, we just need to run it. There are a few ways to run it, so I'll explain them.
> camE -h usage: camE [OPTION] -c FILE Use config file FILE -f Don't fork to background -d Detach after forking -s Single shot -h -v This message
If you execute `camE` with no parameters, it will daemonize but still spit the output to the terminal. If you close the terminal, camE will continue to run. If you run `camE -d` it will daemonize and completely detach from the terminal, so you won't see it's output. With both of these ways, camE is run as a daemon, which means it is not in the foreground. What that means is that you can't hit CTRL+c to kill it. You have to find it's PID from `ps ax` and kill it with the `kill` command. The way I run camE is to keep it in the foreground so I can kill it with CTRL+c whenever I need to. That way is `camE -f`.
I hope this was helpful to everyone. Compiling from source is always a burden when things don't go smoothly. What I've described is a very specific problem, however if you separate the theory from the execution you'll understand how to approach other programs that don't compile properly.


Post a comment!