Workshop: How to install programs from source

Table of Contents

In this workshop we will learn how to install a program from source to the home directory of the user. We will use the following programs, some of them already available at the computer room:

Name installed version latest version
fftw 3.3.4 3.3.6
Eigen C++ 3.2.7 3.3.3
git 2.9.0 2.12.2
voro++ Not installed 0.4.6

1 Checking the version for already installed programs

If you used apt-get or something related, you can use the package manager to check. But, in general, you can check the versions by looking at the appropriate places on your system. Typically, libraries are installed under /usr/lib or /usr/local/lib, while include files are installed under /usr/include or /usr/local/include . Normally, if you are looking fir library foo, then you should look for the file libfoo.a or libfoo.so . One usefull utility for this is the command locate or find .

locate libfoo
find /usr/lib -iname "*libfoo*"

2 Preparing the local places to install the utilities

In this case we will install everything under the ~/local subdirectory inside your home, so create it. The utilies will then create the appropriate folders there. NOTE: Better use the $HOME var instead of ~.

3 Typical installation algorithm

  1. Download the source from the project page. This normally implies downloading a tarball (file ending with .tar.gz or .tar.bz2) .
  2. Un-compress the downloaded file. For a tarball, the command will be

    tar xf filename.tar.gz
    
  3. Enter to the newly uncompressed folder (almost always usually cd filename).
  4. READ the README and/or the INSTALL file to check for important info regarding the program.
  5. CONFIGURATION: You have two options.
    1. If the program has a configure script, then just run

      ./configure --help
      

      to check all the available options. Since we want to install on the $HOME/local directory, then we need to use

      ./configure --prefix=$HOME/local
      

      If you don't specify the prefix, then the program will be installed on the /usr/bin or /usr/local/bin, whatever is the default. If this commands ends successfully, it will print some info to the screen and will tell you to go to the next step. Otherwise you will need to read the log and fix the errors (like installing a dependency).

    2. If the program uses cmake, a make configurator, then you need to do the following:

      mkdir build # creates a build directory to put there the temporary built files
      cd build 
      cmake ../ -DCMAKE_INSTALL_PREFIX:PATH=$HOME/local # configure the building process for the source code located on the parent directory
      
  6. COMPILATION: Now that you have configured your system, you need to compile by using the GNU make utility (Note: All this build utilities come from the gnu organization and are free software as in freedom). If you have several cores, you can use them in parallel, assuming the that the Makefile and your make versions supports it:

    make -j 3 # for three cores, but, if you are unsure, just use one core.
    
  7. INSTALLATION After successful compilation, you can install by using

    make install
    

    This will install the program (libraries, binaries, include files, manual files, etc) onto the prefix directory. If you want to instll system-wide (you did not set the prefix), then you need to use sudo make install .

  8. TESTING In this case use a program to test your installation. In this case, when you compile your program and you want to use the version that you installed, you need to tell the compiler where to find the libraries/includes, so you need something like

    g++ -L $HOME/local/lib -I $HOME/local/include  programname.cpp -llibname
    
    • -L $HOME/local/lib tells the compiler to look for libraries on the $HOME/local/lib directory.
    • -I $HOME/local/include tells the compiler to look for include files on the $HOME/local/include directory.
    • -llibname tells the compiler to link with the given library. Sometimes is not needed. Sometimes is crucial.

4 Workshop

For each of the proposed utilities written at the beginning, follow the next procedure:

  • Check the installed version number and compare with the latest one.
  • Install the latest version on your home directory by following the procedure stated above.
  • Run each of the following example program but make sure you a re using you installed version. Show to the instructor the compilation line.

5 Test Programs

5.1 fftw

// From : https://github.com/undees/fftw-example
/* Start reading here */

#include <fftw3.h>

#define NUM_POINTS 128


/* Never mind this bit */

#include <stdio.h>
#include <math.h>

#define REAL 0
#define IMAG 1

void acquire_from_somewhere(fftw_complex* signal) {
  /* Generate two sine waves of different frequencies and
   * amplitudes.
   */

  int i;
  for (i = 0; i < NUM_POINTS; ++i) {
    double theta = (double)i / (double)NUM_POINTS * M_PI;

    signal[i][REAL] = 1.0 * cos(10.0 * theta) +
      0.5 * cos(25.0 * theta);

    signal[i][IMAG] = 1.0 * sin(10.0 * theta) +
      0.5 * sin(25.0 * theta);
  }
}

void do_something_with(fftw_complex* result) {
  int i;
  for (i = 0; i < NUM_POINTS; ++i) {
    double mag = sqrt(result[i][REAL] * result[i][REAL] +
                      result[i][IMAG] * result[i][IMAG]);

    printf("%g\n", mag);
  }
}


/* Resume reading here */

int main() {
  fftw_complex signal[NUM_POINTS];
  fftw_complex result[NUM_POINTS];

  fftw_plan plan = fftw_plan_dft_1d(NUM_POINTS,
                                    signal,
                                    result,
                                    FFTW_FORWARD,
                                    FFTW_ESTIMATE);

  acquire_from_somewhere(signal);
  fftw_execute(plan);
  do_something_with(result);

  fftw_destroy_plan(plan);

  return 0;
}

5.2 Eigen C++


#include <iostream>
#include <Eigen/Dense>
#include <Eigen/Core>
using Eigen::MatrixXd;
int main()
{
  std::cout << EIGEN_MAYOR_VERSION << std::endl;
  std::cout << EIGEN_MINOR_VERSION << std::endl;
  MatrixXd m(2,2);
  m(0,0) = 3;
  m(1,0) = 2.5;
  m(0,1) = -1;
  m(1,1) = m(1,0) + m(0,1);
  std::cout << m << std::endl;
}

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
  Matrix2d a;
  a << 1, 2,
    3, 4;
  MatrixXd b(2,2);
  b << 2, 3,
    1, 4;
  std::cout << "a + b =\n" << a + b << std::endl;
  std::cout << "a - b =\n" << a - b << std::endl;
  std::cout << "Doing a += b;" << std::endl;
  a += b;
  std::cout << "Now a =\n" << a << std::endl;
  Vector3d v(1,2,3);
  Vector3d w(1,0,0);
  std::cout << "-v + w - v =\n" << -v + w - v << std::endl;
}

#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
int main()
{
  Matrix3f A;
  Vector3f b;
  A << 1,2,3,  4,5,6,  7,8,10;
  b << 3, 3, 4;
  cout << "Here is the matrix A:\n" << A << endl;
  cout << "Here is the vector b:\n" << b << endl;
  Vector3f x = A.colPivHouseholderQr().solve(b);
  cout << "The solution is:\n" << x << endl;
}

#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
int main()
{
  Matrix2f A;
  A << 1, 2, 2, 3;
  cout << "Here is the matrix A:\n" << A << endl;
  SelfAdjointEigenSolver<Matrix2f> eigensolver(A);
  if (eigensolver.info() != Success) abort();
  cout << "The eigenvalues of A are:\n" << eigensolver.eigenvalues() << endl;
  cout << "Here's a matrix whose columns are eigenvectors of A \n"
       << "corresponding to these eigenvalues:\n"
       << eigensolver.eigenvectors() << endl;
}

5.3 Git

Based on https://github.com/blog/2242-git-2-10-has-been-released .

$HOME/local/bin/git --version

Enter some repository you already have, make some changes, and run the following (this only works on the latest git)

$HOME/local/bin/git config color.diff.old "red strike"
$HOME/local/bin/git config color.diff.new "green italic"
$HOME/local/bin/git diff

Maybe you can create an alias, alias git=$HOME/local/bin/git, or you can modify the PATH permanently by adding the following to your $HOME/.bash_profile file :

export PATH=$HOME/local/bin:$PATH

5.4 Voro++

Use http://math.lbl.gov/voro++/examples/random_points/

// Voronoi calculation example code
//
// Author   : Chris H. Rycroft (LBL / UC Berkeley)
// Email    : chr@alum.mit.edu
// Date     : August 30th 2011

#include "voro++.hh"
using namespace voro;

// Set up constants for the container geometry
const double x_min=-1,x_max=1;
const double y_min=-1,y_max=1;
const double z_min=-1,z_max=1;
const double cvol=(x_max-x_min)*(y_max-y_min)*(x_max-x_min);

// Set up the number of blocks that the container is divided into
const int n_x=6,n_y=6,n_z=6;

// Set the number of particles that are going to be randomly introduced
const int particles=20;

// This function returns a random double between 0 and 1
double rnd() {return double(rand())/RAND_MAX;}

int main() {
  int i;
  double x,y,z;

  // Create a container with the geometry given above, and make it
  // non-periodic in each of the three coordinates. Allocate space for
  // eight particles within each computational block
  container con(x_min,x_max,y_min,y_max,z_min,z_max,n_x,n_y,n_z,
                false,false,false,8);

  // Randomly add particles into the container
  for(i=0;i<particles;i++) {
    x=x_min+rnd()*(x_max-x_min);
    y=y_min+rnd()*(y_max-y_min);
    z=z_min+rnd()*(z_max-z_min);
    con.put(i,x,y,z);
  }

  // Sum up the volumes, and check that this matches the container volume
  double vvol=con.sum_cell_volumes();
  printf("Container volume : %g\n"
         "Voronoi volume   : %g\n"
         "Difference       : %g\n",cvol,vvol,vvol-cvol);

  // Output the particle positions in gnuplot format
  con.draw_particles("random_points_p.gnu");

  // Output the Voronoi cells in gnuplot format
  con.draw_cells_gnuplot("random_points_v.gnu");
}

On gnuplot do the following:

Author: William Oquendo

Created: 2017-02-26 Sun 12:27

Validate