11-F.6: Software Builds from Source
- Page ID
- 41981
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)EXAM OBJECTIVES COVERED
2.1 Given a scenario, conduct software installations, configurations, updates, and removals.
What is Building from Source
Building software from source means installing a program either by using a package manager and downloading a source package, or by using some other method to download to source code. Then, you compile the source code and install the binaries to your computer.
Many projects provide their source code via hosting services such as GitHub, GitLab, or Bitbucket. Larger projects at times host their source code on a project specific website. The code will usually be available as compressed archive file of some sort.
Compilers
One of the key components when building from source is the compiler. Every computer programming language has its own compiler (or interpreter), that converts the programming statements into machine readable executable language, also referred to as binary files.
In Linux, the most common compiler is the GNU compiler collection, which includes front end for several compilers including C and C++.
Libraries
In addition to the compiler, building programs from source requires that certain files, called libraries, are installed on the system. Libraries are collections of pre-compiled code that can be linked into other programs. The most common use of libraries is to provide system functions, such as the square root function sqrt found in the math library, or the C++ cout function.
Libraries are typically stored in special archive files with the extension '.a,' referred to as static libraries. Compiled programs need to be able to access shared libraries when they run so as to link to the library code. The standard system libraries are usually found in the directories '/usr/lib' and '/lib.'
The ldd Command
The ldd command prints the shared libraries required by each program or shared library specified on the command line.
pbmac@pbmac-server $ ldd zoo
linux-vdso.so.1 (0x00007ffd6fb7e000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f3f565d6000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f3f563be000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3f55fcd000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3f55c2f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3f5695f000)
This shows the libraries like linux-vdso, libc.so and ld-linux-x86-64.so are used by the zoo binary. There is also the full path of the given libraries where they are generally residing in /lib or /lib64 directories.
The Compiling Process
A special set of tools help automate the building process. On Linux systems, this often comes in the form of a command line program called make. Source code written in different languages need specific compilers and commands to change them into binaries. The make program automates this process. Over the years, a pretty specific process has been developed for most open source software. This process is outlined below, and shows the commands to build the example application.
1. take the file you have downloaded, and extract the files. In this case its a gzipped tar file
pbmac@pbmac-server $ tar -xzvf testP.tar.gz
Unpacking ...
2. Usually the files are archived wihtin a directory - so we have to change into the directory where the files are
pbmac@pbmac-server $ cd testP
3. Usually there is a file named INSTALL which tells you the process to build this package.
pbmac@pbmac-server $ more INSTALL
4. Run the configure script, which determines the system configuration
pbmac@pbmac-server $ ./configure
5. Now run the 'make' command to actually compile all the source files, and create the final executable file
pbmac@pbmac-server $ make
6. Finally, install the newly created package
pbmac@pbmac-server $ make install
The make Command and makefiles
There is a command - the make command - that reads a configuration file called the makefile, which contains rules for building the application. If we were going to put together a makefile for an applicatoin named testP, it might look like the following:
testP: testP.o other.o @echo "Checking.." g++ -lm testP.o -o testP testP.o: testP.cpp @echo "Creating object.." g++ -c testP.cpp other.o: other.cpp g++c other.cpp
On the first line - testP is known as the 'target' - this is what we are creating. It is dependent on two files: testP.o and other.o. The .o files are object files that have been partially compiled. Since there are dependencies, the make command will look at each of them, and check out the other rules. For testP.o it will check and see if testP.cpp has changed since testP.o was last created....if so then the two lines following the testP.o target get executed, which echoes "Creating object..." and compiles the testp.cpp file. The same is true of the other.o rule. Once everything is up to date, the testP executable file is created.
Make files are really awesome; it's almost like learning another programming language when you get into the really comprehensive files.
Adapted from:
"What is a Makefile and how does it work?" by Sachin Patil, OpenSource.com is licensed under CC BY-SA 4.0