Using the FindSeqAn CMake Module

Overview

CMake is a cross-platform build system generator. That is, you describe the different executables and binaries and their dependencies CMakeLists.txt files. Then, CMake generates build systems from this, for example in the form of Makefiles or Visual Studio projects.

This article will not describe how to use CMake in general but only how to use SeqAn easily from within CMake projects. In CMake projects, one uses modules to find libraries such as SeqAn. SeqAn ships with such a module in util/cmake/FindSeqAn.cmake.

This article describes how to use this module.

A Running Example

In the directory util/raw_cmake_project, you can find a small example project that uses the FindSeqAn.cmake module outside the SeqAn build system. The directory sturcture looks as follows:

.
|-- CMakeLists.txt
|-- README
`-- src
    |-- CMakeLists.txt
    `-- main.cpp

The Project’s Contents

The file src/main.cpp contains a minimal SeqAn program.

#include <iostream>

#include <seqan/basic.h>
#include <seqan/sequence.h>
#include <seqan/stream.h>

using namespace seqan;

int main() {
    std::cout << CharString("Hello SeqAn!") << std::endl;
    return 0;
}

The root CMakeLists.txt file just sets up the project name, defines a minimal CMake version, makes all binaries go to the bin subdirectory, and then includes src/CMakeLists.txt.

# Example CMakeLists.txt file that uses the FindSeqAn.cmake module for
# building a SeqAn-based app.

project (raw_cmake_project)
cmake_minimum_required (VERSION 2.8.2)

# Place binaries into "bin" directory.
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/")

# Go to "src" subdirectory.
add_subdirectory (src)

This included file calls find_package(SeqAn REQUIRED). If the library could not be found, the REQUIRED parameter will make the find_package() call fail. Before this, the variable SEQAN_FIND_DEPENDENCIES is set such that zlib and libbz2 are searched for the in find_package() call and enabled in the SeqAn library through compiler defines.

# Configure SeqAn, enabling features for libbz2 and zlib.
set (SEQAN_FIND_DEPENDENCIES ZLIB BZip2)
find_package (SeqAn REQUIRED)

# Add include directories, defines, and flags for SeqAn (and its dependencies).
include_directories (${SEQAN_INCLUDE_DIRS})
add_definitions (${SEQAN_DEFINITIONS})
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SEQAN_CXX_FLAGS}")

# Build the program and link it against the SeqAn dependency libraries.
add_executable (main main.cpp)
target_link_libraries (main ${SEQAN_LIBRARIES})

This is followed by adding the include directory, definitions, and compiler flags required for compiling a program against the SeqAn library, Finally, the source file main.cpp is compiled into a program called main and the libraries that SeqAn was configured with are linked to main. Note that SeqAn itself does not require a linking step but when using compression (e.g. for the BAM format), we have to link to zlib.

Building The Project

By default, the cmake program will look for FindSeqAn.cmake in its module directory. Usually, this is located in /usr/share/cmake-2.8/Modules or a similar location that is available system-wide. Installing FindSeqAn.cmake there is one option of making it available in your CMakeLists.txt. A better option might be to pass the path to the util/cmake directory of your SeqAn checkout to the CMAKE_MODULE_PATH CMake variable through the command line.

Also, CMake will look for the SeqAn include files in central location such as /usr/local/include. Instead of installing SeqAn there, you can pass additional directories to search in using the CMake variable SEQAN_INCLUDE_PATH.

Putting this together, you can execute cmake for the example CMake project with the following command line:

# mkdir -p ~/tmp/cmake_example_build
# cd ~/tmp/cmake_example_build
# cmake path/to/raw_cmake_project \
    -DCMAKE_MODULE_PATH=~/seqan_checkout/util/cmake \
    -DSEQAN_INCLUDE_PATH=~/seqan_checkout/include
[...]
# make main && ./bin/main
Hello SeqAn!

Input / Output of the FindSeqAn Module

As with all other modules, you have to make the file FindSeqAn.cmake available as a CMake module, either by putting it into the same directory as the CMakeLists.txt that you are using it from or by adding the path to the file FindSeqAn.cmake to the variable CMAKE_MODULE_PATH.

Then, you can use it as follows (the argument REQUIRED is optional):

find_package (SeqAn REQUIRED)

Input

SeqAn is somewhat special as a library since it has some optional dependencies. Certain features in SeqAn can be enabled or disabled, depending on whether the dependencies could be found.

You can set the dependencies to search for with the variable SEQAN_FIND_DEPENDENCIES (which is a list). For example:

set (SEQAN_FIND_DEPENDENCIES ZLIB BZip2)
find_package (SeqAn)

Note that FindSeqAn.cmake itself will not search for its dependencies with the argument REQUIRED. Rather, it will set the variables SEQAN_HAS_* and add corresponding definitions to SEQAN_DEFINIONS (see below).

Currently, you can specify the following dependencies:

ALL
Enable all dependencies.
DEFAULT
Enable default dependencies (zlib, OpenMP if available)
NONE
Disable all dependencies.
ZLIB
zlib compression library
BZip2
libbz2 compression library
OpenMP
OpenMP language extensions to C/C++
CUDA
CUDA language extensions to C/C++

If you want FindSeqAn.cmake to expect the SeqAn build system layout then set the variable SEQAN_USE_SEQAN_BUILD_SYSTEM to TRUE. In this case, it will try to locate the library parts from root of the SeqAn source files.

Output

The call to find_package(SeqAn) will set the following variables:

SEQAN_FOUND
Indicate whether SeqAn was found.``

Variables indicating whether dependencies were found:

SEQAN_HAS_ZLIB
TRUE `` if zlib was found.``
SEQAN_HAS_BZIP2
TRUE `` if libbz2 was found.``
SEQAN_HAS_OPENMP
TRUE `` if OpenMP was found.``
SEQAN_HAS_CUDA
TRUE `` if CUDA was found.``

Variables to be passed to include_directories(), target_link_directories(), and add_definitions() in your CMakeLists.txt:

SEQAN_INCLUDE_DIRS
A list of include directories.
SEQAN_LIBRARIES
A list of libraries to link against.
SEQAN_DEFINITIONS
A list of definitions to be passted to the compiler.

Required additions to C++ compiler flags are in the following variable:

SEQAN_CXX_FLAGS
C++ Compiler flags to add.

The following variables give the version of the SeqAn library, its major, minor, and the patch version part of the version string.

SEQAN_VERSION_STRING
Concatenated version string, `` ${SEQAN_VERSION_MAJOR}.${SEQAN_VERSION_MINOR}.${SEQAN_VERSION_PATCH} .
SEQAN_VERSION_MAJOR
Major version.
SEQAN_VERSION_MINOR
Minor version.
SEQAN_VERSION_PATCH
Patch-level version.

The following flag defines whether this is a trunk version and the version given by the variables above is meant to be used as the previously released version.

SEQAN_VERSION_DEVELOPMENT
Whether or not this is a pre-release version.

Example

Below you can find a minimal example CMakeLists.txt file that uses the FindSeqAn.cmake.

cmake_minimum_required (VERSION 2.8.2)
project (apps_dfi)

# ----------------------------------------------------------------------------
# Dependencies
# ----------------------------------------------------------------------------

# Only search for zlib as a dependency for SeqAn.
set (SEQAN_FIND_DEPENDENCIES ZLIB)
find_package (SeqAn REQUIRED)

# ----------------------------------------------------------------------------
# Build Setup
# ----------------------------------------------------------------------------

# Add include directories.
include_directories (${SEQAN_INCLUDE_DIRS})

# Add definitions set by find_package (SeqAn).
add_definitions (${SEQAN_DEFINITIONS})

# Add CXX flags found by find_package (SeqAn).
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SEQAN_CXX_FLAGS}")

# Add executable and link against SeqAn dependencies.
add_executable (app app.cpp)
target_link_libraries (dfi ${SEQAN_LIBRARIES})