Using the IGL library

The igl lib is a collection of useful/reusable/sharable C++ functions with very few external dependencies. The library may be used as a "headers only" library or a statically linked library.

Headers (.h) only library

All classes and functions in the IGL library are written in a way in which the entire library may be compiled just-in-time, effectively behaiving as if it were a "headers only" library (like e.g. Eigen). This is achieved by careful organization of each pair of .h and .cpp files. To take advantage of this one must only include the path to igl_lib directory in one's project's include path and define the preprocessor macro IGL_HEADER_ONLY. Defining IGL_HEADER_ONLY may be done at the project level, prescribing that all included igl headers be treated as code that should be inlined. Consequently all templated functions will be derived at compile time if need be. One may also define IGL_HEADER_ONLY not only on a per-file basis, but a per-include basis. For example it may be useful for a project to use the static library for most functionality from IGL, but then include a certain IGL function as an inlined function. This may be achieved by surrounding the relevant include with a define and undefine of the IGL_HEADER_ONLY macro. Like so:

...
#include <some_other_igl_function.h>
#define IGL_HEADER_ONLY
#include <igl_function_to_inline.h>
#undef IGL_HEADER_ONLY
#include <yet_another_igl_function.h>
...
      
example examples/XXX also highlights this feature
This practice is not recommended outside of debugging purposes.

Benefits of headers-only library

Easy templates: When using the IGL library as a headers-only library no special care need be taken when using templated functions.

Drawbacks of headers-only library

As a headers-only library we depend on the compiler to properly inline each function call. This means compile time is high and binary size can be quite large. Further, most compilers do not guarantee that functions will get inlined even if explicitly told to do so. Though we have not yet encountered this problem, it is always a risk.

Statically linked library

Explicit specialization of templated functions

Special care must be taken by the developers of each function and class in the IGL library that uses C++ templates. If this function is intended to be compiled into the statically linked igl library then function is only compiled for each explicitly specialized declaration. These should be added at the bottom of the corresponding .cpp file surrounded by a #ifndef IGL_HEADER_ONLY. Of course, a developer may not know ahead of time which specializations should be explicitly included in the igl static lib. One way to find out is to add one explicit specialization for each call in one's own project. This only ever needs to be done once for each template. The process is somewhat mechanical using a linker with reasonable error output. Supposed for example we have compiled the igl static lib, including the cat.h and cat.cpp functions, without any explicit instanciation. Say using the makefile in the igl_lib directory:

cd $IGL
make
        
Now we if we try to compile a project and link against it we may get an error like:

Undefined symbols for architecture x86_64:
  "Eigen::Matrix<int, -1, -1, 0, -1, -1> igl::cat<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(int, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&)", referenced from:
      uniform_sample(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, int, double, Eigen::Matrix<double, -1, -1, 0, -1, -1>&)in Skinning.o
  "Eigen::SparseMatrix<double, 0, int> igl::cat<Eigen::SparseMatrix<double, 0, int> >(int, Eigen::SparseMatrix<double, 0, int> const&, Eigen::SparseMatrix<double, 0, int> const&)", referenced from:
      covariance_scatter_matrix(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, ArapEnergy, Eigen::SparseMatrix<double, 0, int>&)in arap_dof.o
      arap_rhs(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, ArapEnergy, Eigen::SparseMatrix<double, 0, int>&)in arap_dof.o
        
This looks like a mess, but luckily we don't really need to read it all. Just copy the first highlighted part in quotes, then append it to the list of explicit templat specializations at the end of cat.cpp after the word template and followed by a semi-colon. Like this:

...
#ifndef IGL_HEADER_ONLY
  // Explicit template specialization
  template Eigen::Matrix<int, -1, -1, 0, -1, -1> igl::cat<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(int, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&);
#endif
        
Then you must recompile the IGL static library.

cd $IGL
make
        
And try to compile your project again, potentially repeating this process until no more symbols are undefined.
It may be useful to check that you code compiles with no errors first using the headers-only version to be sure that all errors are from missing template specializations.

Benefits of static library

Drawbacks of static library

Special care (by the developers of the library) needs to be taken when exposing templated functions.

Dependencies

By design the IGL library has very few external dependencies.

Mandatory dependencies

Besides the standard C++ library, there are a few dependencies, without which the main library will not compile or work properly. These are:

Optional dependencies

Certain functions and classes included the IGL library have external dependencies by construction (e.g. the matlab_interface routines are only useful when matlab is present anyway). These are never compiled by default into the static igl library and are only exposed through compiler options. These are: