Compiling Source Code Guide
Compiling Source Code Guide
Compiling source code Alan Pae Last Revised: March 15, 2003 Compiling source code on Unix systems used to be a time consuming, trial and error ordeal. The reason that compiling software in the old days was so difficult is because there was no universal way to create a Makefile for different machines and operating systems. Introduction A C compiler uses the Makefile as a kind of blueprint that tells the compiler the steps to take to compile the source code into a usable binary file. Binary files are the programs you're trying to run. They're also called executables. In the old days, when a developer was writing his/her code, they were writing it to run on their machine and may or may not have been trying to make it run on another platform or two, but generally not all Unices. Thus, software written to run on one system, under their structure, would not necessarily compile on another vendors Unix variant under their structure. If you wanted to run someone else's code from another architecture on yours, it was up to you to figure out how to make it compile and work on your machine. Writing software on Unix has essentially gone through three different stages. First was the Makefile stage. This was all you got. It was up to you to figure out which system libraries and which header files on your system were needed to make the program compile. Each system has its own header files. These are files that end in .h These files define how C programs can access your system. They provide system definitions that programmers can use to write their code. If your machine didn't have a "dependent" application or library, you had to go out and redo the process all over again for those dependencies. Although this is still true today, the biggest change is that there is now a system in place to help you create the Makefile, whereas in the old days, there was not. The second era that software went through was the Imake stage. This stage was used mainly for X Windows applications. Since X Windows is pretty standard across all machines, a system was developed to take advantage of this situation. An Imakefile was created. This was essentially a template that your system would use to help in the creation of a Makefile. In addition to the applications Imakefile, your system had variables that that it would supply to Imake that would then create the Makefile for you. The biggest disadvantage to this system is that not all software was written with X Windows in mind, and so it wasn't always applicable. There are other pluses and minuses to the Imake system that you can explore on your own if you desire. The GNU autoconf manual has a section towards the end that addresses the differences between Imake and Autoconf. The third stage of software development is the one we're in right now. This era of software development has tools that are designed to generate a Makefile regardless of your hardware or Operating Environment. This stage uses the autoconf utilities to generate a Makefile for your machine. The autoconf utility creates a script called "configure" which creates a Makefile custom tailored for your hardware/operating system. The autoconf utility tries to ease the process of having to write a different Makefile for each vendors hardware/operating system. The autoconf utility uses a variety of techniques and other programs to ascertain what Unix system your running on, runs some checks to see what your system has and doesn't have, checks for dependencies, and then creates a Makefile for your system. This allows a developer to work on the source code and not worry so much about how to get it to compile on your machine. This frees up the developer to work on features and bug fixes (also called features). The web pages that follow will assist you in getting your machine ready to compile software, and then will attempt to walk you through the process for compiling software for each of the situations mentioned above. The first scenario I'll present you with is the autoconf method since its in heavy use today. The first two compilation scenarios will be shown for completeness. Sometimes, you will have to resort to the old ways as well. In addition there will be other topics covered such as how to create a package as well as a short dialog on static versus dynamic libraries. Preparing your system For compiling software you will need a few things. You'll need the source code for the program that you're trying to compile. You'll need a compiler, and lastly, if you need it, have the e-mail address of the author or company available. If that fails, turn to your favorite search engine, newsgroup, e-mail list, or wherever else you go to get help. On Solaris systems there are two different compilers you can use. These are: Sun's C Compiler - cc is short for C compiler Gnu's C Compiler - GCC is short for Gnu's Compiler Collection. There are a few differences in these compilers. The first is money. Sun's compilers will cost you a few bucks while Gnu's is free. The reason for this is Sun's compilers come with a lot of goodies built in that Gnu's doesn't. You can supplement Gnu's with other Gnu software to achieve some of the same functionality, but you have to assemble all the pieces yourself. In addition, Solaris is written with Sun's compilers in mind and not Gnu's. What does that mean to you. It means that some Solaris utilities will not work when using Gnu's compiler and you may have to find Gnu equivalents in order to get some software programs to compile correctly. Solaris commands such as tr or gettext, would not work when compiling early version of Gnome for instance. The fix was to download and install a GNU version of tr or gettext and place that version first in your path statement.
These packages are all on the Solaris 2.x CDs, except that some packages may only exist in some releases and not in others. Some packages may be on separate CDs, such as the "Desktop/CDE" CD, but all are part of the Solaris "bundle". Some of the above packages do not exist in all Solaris releases. As the FAQ says, don't use Gnu's as or ld commands, make sure these are Sun's and not Gnu's. All the binaries live in /usr/ccs/bin. Make sure that this is present in your path before you attempt to compile software. The first thing you should do if you're going to use Gnu's compiler, is to compile your own compiler. Not an easy task since you don't get one to start with. If you're going to use Sun's compiler, read through the included docs, and you're on your way. Using Sun's compilers will not be covered here. We are going to go through the steps to compile GCC on your computer. The steps to compile any other program will pretty much be the same. It's important to remember that you don't need to install a compiler on all your computers. If you have several Sun 4U architecture machines, than one machine can compile source code for all your Sun 4U machines. After you compile the code, you can use pkgadd, ftp, or whatever means are available to push the code out to other machines. You also need to be aware of versions of Solaris. If your compiler sits on a machine running Solaris version 8, you probably won't be able to run this code on an earlier version of Solaris. However, your compiled code should run on later revisions of Solaris code. This is because Sun is constantly adding things to the OS and what exists later on, may or may not be available on an earlier revision of Solaris. Ok, so how do you go about compiling your own Gnu compiler since you start out with nothing? Not as hard as it sounds. First, on the machine that you're going to use to compile software, insure that the packages listed above are installed. Second, modify your path to include /usr/ccs/bin. Now you have one of two or more options. Sun is now shipping a "Companion" CD that does include a copy of GCC. In addition you could easily ftp a copy from http://www.sunfreeware.com. If that doesn't work, you can have someone you know burn it on CD, setup an ftp server, NFS mount a share with it, etc.... If you use the first two methods, you should have a package file that will make it super easy to install the software. You simply use the pkgadd command to install the software. Usually its something like pkgadd -d . Include the period in the command. This assumes that you're currently in the directory that contains the GCC package and your using a user account that will allow you to install software onto the current machine. After typing pkgadd -d . the package add command will list all of the packages it finds in the current directory. Simply select the number corresponding to the package that you want to install, and barring any problems, Solaris will take care of the rest. Be sure to note which directory that the files are being created in. You'll need to add this to you're path statement as well, preferable before /usr/ccs/bin. You'll also need to set LD_LIBRARY_PATH to the lib directory for the package you just installed. Typically, this is LD_LIBRARY_PATH=/usr/local/lib; export LD_LIBRARY_PATH if your using the GCC package available from Sunfreeware. After you've installed the package, modified your path, and set the LD_LIBRARY_PATH environment variable, the command, gcc --version, should return the version of gcc that you've just installed on your system.
Export CC CFLAGS CXX CPPFLAGS TMPDIR LDFLAGS LD_LIBRARY_PATH. You don't have to set environment variables for GCC to use them. You could simply add them to the configure command line as shown below: ./configure CC=gcc CFLAGS=-O3 LDFLAGS="-L/usr/local/lib -R/usr/local/lib" TMPDIR=/tmp LIBS=-lposix Let's take a look at what each of these do: CC=gcc tells configure that your C Compiler (CC) is gcc. CFLAGS=-03 tells configure that you want the compiler to use the following optimization flags. By using optimization flags you can adjust how the code is compiled. For instance, -03 tells the compiler to optimize the code for speed. There are other switches you can use and some of them are listed at the end of this page. You should check the GCC manual for all the different flags that you can set to see if there are any of those you think you should use. If you are currently running SPARC hardware it is strongly suggested that you set at least -mv8, so GCC can use some hardware registers that otherwise would not be available for it to use. In addition to compiler optimizations, you can also add include directories here. The terms include and header files are used interchangeable. If the compiler cannot find a filename.h file, you can tell it to look in the directories listed here to help the compiler find the files it needs to compile the program. An example would be: CFLAGS=-I/usr/local/include CXX=g++ tells configure that your C++ compiler is named g++, the GNU equivalent of c++. CPPFLAGS=-I/usr/local/include same as CFLAGS listed above, except for use with C++. LDFLAGS="-L/usr/local/lib -R/usr/local/lib" Linking is the final stage of compiling. One of the things that you need to be concerned with is where do the programs libraries go. Libraries can be thought of as binaries as the system does not know where they are unless you specifically tell it. When you go to run a program you will sometimes run into a situation where you need to set LD_LIBRARY_PATH. On Solaris 8 and greater you can get around this by using the crle command instead. Or, you can fix the issue right here so you don't have to do either. The LD_LIBRARY_PATH variable is to libraries what PATH is to executables. When you run a program that is dynamically linked, it will search LD_LIBRARY_PATH directories to find the libraries that it needs to run. If the program cannot find all its libraries, it won't run. Just like PATH, LD_LIBRARY_PATH is a colon-delimited list of directories. There are two parts to LDFLAGS. The first part is used for compiling, that's the -L part. The other part is used at runtime, that's the -R part. When your telling GCC to look into this directory to find the libraries that you need to find to compile the program, you set the -L half of LDFLAGS. When your telling GCC to include the path to the library so the executable will know where to find them when you go to run the program, you use the -R part. Properly setting -R should remove the need to use LD_LIBRARY_PATH or crle. When you type the name of the executable, it already knows the path to the library files. There are two types of library files. Static libraries files end in .a Dynamic or shared library files end in .so To see which libraries an executable program uses, use the ldd command. ldd binary_program_name this command will send an output to your screen with all the library files that the program needs to run. If it can find the library, it will display the full path to and the name of the library. If it cannot find the library file, it will report, "(not found)". Unless the program can find all the library files, it will not run. There will be a discussion on static versus dynamic libraries later on. TMPDIR=/tmp If TMPDIR is set, it specifies the directory to use for temporary files. GCC uses temporary files to hold the output of one stage of compilation, which is to be used as input to the next stage: for example, the output of the pre-processor, which is the input to the compiler proper. Those are the main environment variables that you need to be concerned with.