Structural Bioinformatics Library
Template C++ / Python API for developping structural bioinformatics applications.
Developers Using SBL: Tutorial

Tutorial guiding a developer for creating programs using the SBL library.

Introduction

As seen from Fig. fig-intro-sbl-architecture , the SBL is a library providing various resources for developers. The goal of this tutorial is to help developers willing to develop programs based on the SBL library. In the following, each section focuses on a particular task:

– in section Compiling with SBL : compiling a program using the SBL library,

– in section Creating one's programs based on existing Applications : using the existing Applications with different Models, or user-defined Models ,

– in section Creating Workflow, Modules and Loaders : creating an application using the Modules framework.

Compiling with SBL

As mentioned in the Installation Guide , CMake is used to compile programs based on the SBL library. CMake uses a configuration file called CMakeLists.txt, from which the makefile monitoring the compilation of individual targets is created.

Given a CMakeLists.txt file, compiling a program that uses the SBL is only few commands. Assuming that your working directory contains the CMakeLists.txt file, and that the SBL library is installed in a standard location :

> mkdir build; cd build;
> cmake ..
> make

If you are working directly with an uninstalled version of the SBL (a cloned repository, or a downloaded tarball), you have to define the path to the root directory of the SBL library when running the cmake command :

> cmake .. -DSBL_DIR=</path/to/sbl/dir>

If you installed the SBL library in a non-standard location, you have to tell CMake where to find the configuration files for the SBL :

> cmake .. -DCMAKE_MODULE_PATH=</path/to/install/sbl/dir>/share/cmake/Modules

Here is an example configuration file used to compile files found in the standard distribution:

cmake_minimum_required(VERSION 2.6)
set(SBL_USE_LIBS ESBTL CGAL MPFR GMP Boost)
find_package(SBL)
if ( SBL_FOUND )
include(${SBL_USE_FILE})
create_sbl_program(example_alpha_complex_of_molecular_model)
create_sbl_program(example_unfixed_alpha_complex_of_molecular_model)
create_sbl_program(example_alpha_complex_of_molecular_model_with_union_find)
create_sbl_program(example_alpha_complex_of_molecular_model_VMD_view)
create_sbl_program(example_alpha_complex_of_molecular_model_module)
endif()

The different functions used in the CMakeLists.txt file are:

cmake_minimum_required(VERSION 2.6)

This function checks whether the current version of CMake is at least 2.6.

set(SBL_USE_LIBS ESBTL CGAL MPFR GMP Boost)

This function sets all the libraries used by the SBL libraries for compiling the programs, as explained in section Linking libraries to SBL programs .

find_package(SBL)

This function seeks a file SBLConfig.cmake on standard path of cmake, or in a directory pointed by the environment variable SBL_DIR, as explained in section Finding the SBL location .

include(${SBL_USE_FILE}) 

This function sets a number of flags for including headers and linking to libraries during the compilation, as explained in section Setting Include and Link .

create_sbl_program(example_alpha_complex_of_molecular_model)

This function creates a target in the make file for compiling the example_alpha_complex_of_molecular_model.cpp source file, as explained in section Creating a program .

Linking libraries to SBL programs

The SBL library relies upon a number of libraries that needs to be included or linked during the compilation: the variable SBL_USE_LIBS must list all of them. Note that the libraries listed in SBL_USE_LIBS need to have an associated SBL_Use<LIB_NAME>.cmake file in a standard path or in a path CMake can find it. Such files are provided for all the libraries required for compiling a program that requires only the SBL library. If the files are not in the standard path, it is possible to indicate the directories that contain them using the cmake variable CMAKE_MODULE_PATH.

The following example shows the file SBL_UseGMP.cmake to use the GMP library within the SBL:

message(STATUS "Looking for GMP library...")
find_package(GMP)
if(GMP_FOUND)
message(STATUS "GMP library found: ${GMP_LIBRARIES_DIR}")
include_directories("${GMP_INCLUDE_DIR}")
link_directories("${GMP_LIBRARIES_DIR}")
if(BUILD_STATIC_SBL)
if("${WIN32}" OR "${WIN64}")
file(GLOB gmp_lib_file RELATIVE "${GMP_LIBRARIES_DIR}" "${GMP_LIBRARIES_DIR}/*gmp*.lib")
if(gmp_lib_file)
set(GMP_LINK "${GMP_LIBRARIES_DIR}/${gmp_lib_file}")
message(STATUS "Found library : ${GMP_LINK}")
endif()
else()
set(GMP_LINK "${GMP_LIBRARIES_DIR}/libgmp.a")
endif()
else()
set(GMP_LINK gmp)
endif()
if(SBL_COMMON_LIBS)
set(SBL_COMMON_LIBS ${SBL_COMMON_LIBS} ${GMP_LINK})
else()
set(SBL_COMMON_LIBS ${GMP_LINK})
endif()
set(SBL_WITH_GMP ON)
else()
set(SBL_WITH_GMP OFF)
endif()

If one wishes to use his/her own libraries, or libraries that were not previously used with the SBL , the following steps are required:

  • find the library location, for example using the cmake function find_package, as explained in section Finding the SBL location (note that some libraries are using other software than CMake for configuring the make files: please check that it is supported by CMake on its documentation),
  • include the directories containing the headers using the cmake function include_directories,
  • link the libraries (if necessary) by adding the flags to the cmake variable SBL_COMMON_LIBS (note that the cmake method target_link_libraries allows to link the libraries, but in order to have an homogeneous way to link all the libraries during the compilation, using the cmake variable SBL_COMMON_LIBS) is recommended.

All these steps may be directly included in one's CMakeLists.txt file, or in a file called SBL_Use<LIB_NAME>.cmake. In the latter case, one uses the cmake variable SBL_USE_LIBS in your CMakeLists.txt file: for each library listed in SBL_USE_LIBS, a cmake configuration file of this library will be searched and used for setting the includes and links. This framework allows one to use his/her libraries in different projects without duplicating the configuration code.

Finding the SBL location

In order to find the location of the SBL library, the cmake method find_package is used: this method looks for a SBLConfig.cmake file (or possibly a FindSBL.cmake file) in the cmake path. As mentioned in section Linking libraries to SBL programs , if one's copy of the SBL s not in a standard path, the cmake variable CMAKE_MODULE_PATH lists all the directories where CMake should look for these files.

The following example is the SBLConfig.cmake file implemented in the library, to find all the cmake configuration files related to the SBL:

# This files contains definitions needed to use SBL in a program.
# DO NOT EDIT THIS.
# This file is loaded by cmake via the command "find_package(SBL)"
#
# This file correspond to a possibly out-of-sources SBL configuration, thus the actual location
# must be given by the cmake variable or environment variable SBL_DIR.
set(SBL_INTERNAL_ARCHITECTURE OFF)
set(SBL_FOUND TRUE)
if(EXISTS ${SBL_DIR}/UseSBL.cmake)
set(SBL_CMAKE_DIR "${SBL_DIR}")
set(SBL_USE_FILE "${SBL_CMAKE_DIR}/UseSBL.cmake")
else()
if(EXISTS ${SBL_DIR}/cmake/Modules/UseSBL.cmake)
set(SBL_CMAKE_DIR "${SBL_DIR}/cmake/Modules")
set(SBL_USE_FILE "${SBL_CMAKE_DIR}/UseSBL.cmake")
else()
if(EXISTS ${SBL_DIR}/share/cmake/Modules/UseSBL.cmake)
set(SBL_CMAKE_DIR "${SBL_DIR}/share/cmake/Modules")
set(SBL_USE_FILE "${SBL_CMAKE_DIR}/UseSBL.cmake")
endif()
endif()
endif()

When found, this file is processed and a cmake variable SBL_FOUND is created and set to ON, indicating that the library was correctly found. In addition, it sets a number of cmake variables for finding all other files used by CMake with the SBL library. In particular, it sets the cmake variable SBL_USE_FILE to the location of the file UseSBL.cmake that will include all the dependencies of the SBL library.

Setting Include and Link

As mentioned in section Finding the SBL location, including the file pointed by the cmake variable SBL_USE_FILE will configure most of the other cmake variables required for compiling a program. In particular, it does the following tasks:

  • setting the version number of the SBL library,
  • setting the compile mode to Release if no one has been given,
  • including the header SBLConfig.h used in all applications,
  • configuring all the external libraries by including the headers and configuring the link to the programs,
  • including all headers from the Core and Models parts of the SBL library,
  • including the cmake methods designed specially for the SBL library,
  • adding all the possible warnings (excepting the unused local typedefs warning) if compiling in debug mode,
  • including the mandatory flags for compiling in static mode, if the cmake variable BUILD_STATIC_TYPE was defined and set to ON.

All this operations are done in cmake/Modules/UseSBL.cmake:

#If Win32, forbids the use of some packages(like Hierarchical Serialization)
if("${WIN32}" OR "${WIN64}")
add_definitions(-DWINDOWS_PLATFORM)
set(CMAKE_CXX_FLAGS "/EHsc")
endif()
#set the version number to add to all applications
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/VERSION)
file (STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/VERSION SBL_VERSION)
else()
set(SBL_VERSION "2.1.0")
endif()
string(REPLACE "." ";" SBL_VERSION_LIST ${SBL_VERSION})
list(GET SBL_VERSION_LIST 0 SBL_VERSION_MAJOR)
add_definitions(-DSBL_VERSION_MAJOR=${SBL_VERSION_MAJOR})
list(GET SBL_VERSION_LIST 1 SBL_VERSION_MINOR)
add_definitions(-DSBL_VERSION_MINOR=${SBL_VERSION_MINOR})
list(GET SBL_VERSION_LIST 2 SBL_VERSION_PATCH)
add_definitions(-DSBL_VERSION_PATCH=${SBL_VERSION_PATCH})
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
message(STATUS "Building in ${CMAKE_BUILD_TYPE} mode...")
if(BUILD_STATIC_SBL)
message(STATUS "Building STATIC executables...")
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
message(STATUS "Building as most as possible STATIC executables...")
else()
if("${WIN32}" OR "${WIN64}")
message(STATUS "Building as most as possible STATIC executables...")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
else()
message(STATUS "Building STATIC executables...")
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
if(CMAKE_EXE_LINKER_FLAGS)
set(CMAKE_EXE_LINKER_FLAGS "-static ${CMAKE_EXE_LINKER_FLAGS}")
else()
set(CMAKE_EXE_LINKER_FLAGS "-static")
endif()
set(SBL_COMMON_LIBS ${SBL_COMMON_LIBS} pthread)
endif()
endif()
endif()
include_directories("${PROJECT_BINARY_DIR}")
include(${SBL_CMAKE_DIR}/SBL_UseLibraries.cmake)
include(${SBL_CMAKE_DIR}/SBL_UseOptionalLibraries.cmake)
include(${SBL_CMAKE_DIR}/SBL_UseCore.cmake)
include(${SBL_CMAKE_DIR}/SBL_UseModels.cmake)
include(${SBL_CMAKE_DIR}/SBL_CreateSBLProgram.cmake)
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
#Traits class defines types that are not used locally, so we desactive these warnings
#In the CGAL mesher, there are unused variables ?
#add_definitions(-Wall -Wno-unused-local-typedefs -Wno-unused-variable)
add_definitions(-Wall -Wno-unused-local-typedefs)
endif()
if(SBL_OPENMP)
message(STATUS "Using OpenMP...")
find_package(OpenMP)
if(OPENMP_FOUND)
set(CMAKE_EXE_LINKER_FLAGS " ${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}")
add_definitions(-DSBL_OPENMP)
else()
message(STATUS "OpenMP not found !")
endif()
endif()
if(SBL_PROFILING)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
add_definitions(-pg -g)
endif()
if(SBL_MISSING_DEPENDENCIES)
message(STATUS "WARNING !!! The following libraries are missing and some of the executables will not be compiled : ${SBL_MISSING_DEPENDENCIES}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
add_definitions(-pg -g)
endif()

Creating a program

We provide two methods to create a program using the SBL library–see also illustrations in section Compiling with SBL :

  • create_sbl_program : takes at least one argument, that is the name of the main source file (.cpp) without extension; all other optional arguments are other source files (.cpp) required to compile the main source file.
  • create_sbl_application : does the same, but offers in addition the possibility to install the resulting program, i.e to copy it in a bin target directory.

In both cases, a program will be created with the name of the main source file, and the extension .exe. It is also in this method that all the libraries listed in SBL_USE_LIBS (or the flags in SBL_COMMON_LIBS) are linked.

These methods are defined in the file cmake/Modules/SBL_CreateSBLProgram.cmake:

#Creates a target <arg_1>.exe from the main source file <arg_1>.cpp,
#and possibly linking to all other optional sources <arg_n>.cpp
function(create_sbl_program arg)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${arg}.cpp")
set(SBL_LOCAL_CPPS ${arg}.cpp)
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${arg}.c")
set(SBL_LOCAL_CPPS ${arg}.c)
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${arg}.C")
set(SBL_LOCAL_CPPS ${arg}.C)
endif()
foreach(f ${ARGN})
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${f}.cpp")
set(SBL_LOCAL_CPPS ${SBL_LOCAL_CPPS} ${f}.cpp)
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${f}.c")
set(SBL_LOCAL_CPPS ${SBL_LOCAL_CPPS} ${f}.c)
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${f}.C")
set(SBL_LOCAL_CPPS ${SBL_LOCAL_CPPS} ${f}.C)
endif()
endforeach()
if(WIN32 OR WIN64)
set(program_name ${arg})
else()
set(program_name ${arg}.exe)
endif()
add_executable(${program_name} ${SBL_LOCAL_CPPS})
if(BUILD_STATIC_SBL)
set_target_properties(${program_name} PROPERTIES LINK_SEARCH_END_STATIC 1)
endif()
target_link_libraries(${program_name} ${SBL_COMMON_LIBS})
endfunction()
#Does the same as previously but allows in addition to install the
#resulting program in a bin directory at installation time.
function(create_sbl_application arg)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${arg}.cpp")
set(SBL_LOCAL_CPPS ${arg}.cpp)
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${arg}.c")
set(SBL_LOCAL_CPPS ${arg}.c)
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${arg}.C")
set(SBL_LOCAL_CPPS ${arg}.C)
endif()
foreach(f ${ARGN})
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${f}.cpp")
set(SBL_LOCAL_CPPS ${SBL_LOCAL_CPPS} ${f}.cpp)
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${f}.c")
set(SBL_LOCAL_CPPS ${SBL_LOCAL_CPPS} ${f}.c)
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${f}.C")
set(SBL_LOCAL_CPPS ${SBL_LOCAL_CPPS} ${f}.C)
endif()
endforeach()
if(WIN32 OR WIN64)
set(program_name ${arg})
else()
set(program_name ${arg}.exe)
endif()
add_executable(${program_name} ${SBL_LOCAL_CPPS})
if(BUILD_STATIC_SBL)
set_target_properties(${program_name} PROPERTIES LINK_SEARCH_END_STATIC 1)
endif()
target_link_libraries(${program_name} ${SBL_COMMON_LIBS})
install(TARGETS ${program_name} DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
endfunction()
#Creates a target <arg_1>.exe using visual components such as Qt,
#OpenGL and QGLViewer. It works exactly as create_sbl_program, but
#uses the qt4 precompilation wrappers on all local .ui files and the
#main .cpp file.
function(create_sbl_visual_program arg)
set(SBL_LOCAL_CPPS ${arg}.cpp)
foreach(f ${ARGN})
set(SBL_LOCAL_CPPS ${SBL_LOCAL_CPPS} ${f}.cpp)
endforeach()
file(GLOB UI_FILES "${CMAKE_SOURCE_DIR}/*ui")
qt4_wrap_ui(uis ${UI_FILES})
qt4_automoc(${arg}.cpp)
add_executable(${program_name} ${uis} ${SBL_LOCAL_CPPS})
target_link_libraries(${program_name} ${SBL_COMMON_LIBS})
endfunction()

Creating one's programs based on existing Applications

All the Applications in the SBL library are instantiated with one or more C++ models, leading to different programs solving the same problem, with different input or different algorithms.

Reusing C++ classes from the SBL, developers may create programs re-using the main classes defined for the Applications , in two ways:

Re-using existing SBL C++ models

An application in SBL is based on two important classes:

  • the Workflow class, that is the C++ class that defines how loaders and modules are combined to run the calculations,
  • the Traits class, that is the C++ class that defines the types used by the Workflow for instantiating the modules and loaders.

Usually, the Traits class is a C++ template class, the template arguments being some C++ concepts for which we provide C++ models in Models. For example, the Traits class T_Space_filling_model_interface_traits for the application Space_filling_model_interface have five template parameters, each of them being the C++ model of a C++ concept defined in Models. Thus, developing a program for an application consists on creating a unique source file (.cpp) that:

  • instantiates the Traits class of the application with the C++ models corresponding to the required C++ concepts,
  • instantiates the Workflow class with the instantiated Traits class,
  • defines the main method where an object of the class Workflow is created and the method start of the class Workflow is called.

Here is an example of a program for the Space_filling_model_interface application that computes the interface in a binary complex made of atoms, each atom being annotated with a name and a radius:

#include <SBL/Models/Atom_with_flat_info_and_annotations_traits.hpp>
#include <SBL/Models/AB_label_traits.hpp>
#include <SBL/Models/Water_label_traits.hpp>
#include "Space_filling_model_interface_traits.hpp"
#include "Space_filling_model_interface_workflow.hpp"
typedef Particle_traits_base::Annotator_default Particle_annotator;
typedef Particle_traits_base::Atom_with_flat_infos_builder Particles_builder;
typedef T_Space_filling_model_interface_traits<Particle_traits_base,
Partner_labels_traits,
Mediator_labels_traits,
Particle_annotator,
Particles_builder> Traits;
int main(int argc, char *argv[])
{
Workflow workflow("sbl-intervor-ABW-atomic", "");
workflow.start(argc, argv);
return 0;
}

To use this code with different C++ models, it is sufficient to replace the corresponding C++ model of interest when instantiating the Traits class. The usable C++ models for each template parameter of the Traits class are described in the reference manual of the Traits class. Note that each template parameter is documented and refers to the C++ concept it represents in the Models documentation.

Developing SBL C++ Models

Developing a C++ model consists of developing a C++ class that follows a C++ concept described in one of the packages in Models . For example, the C++ concept ParticleTraits defines types defining a particle. A C++ model of this C++ concept is the class SBL::Models::T_Atom_with_flat_info_traits, that represents an atom where the coordinates are represented with double number type. For adding a radius to an atom, one should use the class SBL::Models::T_Atom_with_flat_info_and_annotations_traits that adds to the atom an annotated name and an annotated radius. In practice, the class SBL::Models::T_Atom_with_flat_info_and_annotations_traits inherits from the class SBL::Models::T_Atom_with_flat_info_traits and redefines some types related to the atom.

All the requirements of a C++ concept is described in the user manual of the corresponding package in Models. Furthermore, each time that a class has as template argument a C++ concept represented by a package in Models, this template argument is documented and references the corresponding package in Models.

Creating Workflow, Modules and Loaders

All SBL applications are designed with a workflow class (see class SBL::Modules::Module_based_workflow in package Module_base). Such as class registers modules and loaders, and links them in a directed graph describing the flow of calculations along the run process. The main class to use is the class SBL::Modules::Module_based_workflow , which offers all the functionalities to create and manage the previous graph.

To create one's loaders and modules, it is sufficient to inherit from the base classes SBL::IO::Loader_base and SBL::Modules::Module_base. These classes have pure virtual methods, so that selected methods will have to be re-implemented in order to use them in the workflow.

For a detailed description of the classes SBL::Modules::Module_based_workflow, SBL::IO::Loader_base and SBL::Modules::Module_base, and their underlying mechanisms, we refer you to the user manual of the package Module_base.