How to compile a new project with brainvisa-cmake

The project must contain 2 files:

  • project_info.cmake: describes the name and version of the project.

    • Alternatively, for a Python project, this file can be replaced by a python file, info.py located in a python subdirectory.

    See also the section How to create version files with brainvisa-cmake.

  • CMakeLists.txt: describes the elements which will be generated when the project will be built.

Moreover, the new project must be declared in bv_maker.cfg to enable its compilation with bv_maker.

Example with a personal project:

[ source $HOME/brainvisa/source ]
  + standard trunk
  + perso/myself/myproject

[ build $HOME/brainvisa/build/trunk ]
  make_options = -j8
  standard trunk $HOME/brainvisa/source
  + $HOME/brainvisa/source/perso/myself/myproject

Project_info.cmake

Example: project_info file for anatomist-free component of anatomist project.

The following file is in anatomist/anatomist-free/tags/4.5/project_info.cmake.

set( BRAINVISA_PACKAGE_NAME anatomist-free )
set( BRAINVISA_PACKAGE_MAIN_PROJECT anatomist )
set( BRAINVISA_PACKAGE_MAINTAINER "CEA - IFR 49" )
set( BRAINVISA_PACKAGE_VERSION_MAJOR 4 )
set( BRAINVISA_PACKAGE_VERSION_MINOR 5 )
set( BRAINVISA_PACKAGE_VERSION_PATCH 0 )
set( BRAINVISA_PACKAGE_LICENCES "CeCill-B" )

Example: project_info file for axon project.

The following file is in axon/trunk/project_info.cmake.

set( BRAINVISA_PACKAGE_NAME axon )
set( BRAINVISA_PACKAGE_MAIN_PROJECT axon )
set( BRAINVISA_PACKAGE_MAINTAINER "IFR 49" )
set( BRAINVISA_PACKAGE_VERSION_MAJOR 4 )
set( BRAINVISA_PACKAGE_VERSION_MINOR 6 )
set( BRAINVISA_PACKAGE_VERSION_PATCH 0 )
set( BRAINVISA_PACKAGE_LICENCES "CeCill-V2" )

Variables

A few additional optional variables may be set in project_info.cmake:

BRAINVISA_PACKAGE_DEFAULT_INSTALL

set( BRAINVISA_PACKAGE_DEFAULT_INSTALL "run" "usrdoc" )

Specifies that the package should be pre-selectionned for installation in the installer, for its “run” and “usrdoc” categories components. Packages components are divided into several categories:

  • “run” is the runtime files, used when using the software
  • “dev” is the development files, used when developing software using this component as a library
  • “test” is the test files, used to test the component (generally only useful for developers)
  • “usrdoc” is the user documentation files
  • “devdoc” is the development documentation files

Info.py alternative

If your project is only using the Python language, you may like to use a python file to describe this information, because it would also be usable in the project code as a python module.

Thus, alternatively to the project_info.cmake file, brainvisa-cmake will look for an info.py file, located:
  • in a <modules> subdirectory of the project directory.
  • or in a python/<modules> subdirectory of the project directory.

This file contains basically the same information as project_info.cmake but in pyton language:

NAME = 'soma-base'
PROJECT = 'soma'      # optional, taken as NAME if omitted
MAINTAINER = "CEA"    # optional
LICENSE = "CeCILL-B"
version_major = 4
version_minor = 5
version_micro = 8

Other variables are of course allowed, it is a standard python files. The variables above will be translated to those of project_infi.cmake and will be available under the latter names in CMakeLists.txt files:

PROJECT -> BRAINVISA_PACKAGE_MAIN_PROJECT
NAME -> BRAINVISA_PACKAGE_NAME
MAINTAINER -> BRAINVISA_PACKAGE_MAINTAINER
LICENSE -> BRAINVISA_PACKAGE_LICENCES
version_major -> BRAINVISA_PACKAGE_VERSION_MAJOR
version_minor -> BRAINVISA_PACKAGE_VERSION_MINOR
version_micro -> BRAINVISA_PACKAGE_VERSION_PATCH

How to create version files with brainvisa-cmake

It is possible to use brainvisa-cmake to generate source code containing the version stored in project_info.cmake. Here is an example from old_connectomist project. There are two template files, one for C++ and one for Python:

config/config.h.in:

#ifndef COMIST_VERSION_H
#define COMIST_VERSION_H

#define connectomist_version "@connectomist_VERSION@"

#endif // ifndef COMIST_VERSION_H

config/config.py.in:

share = 'connectomist-@BRAINVISA_PACKAGE_VERSION_MAJOR@.@BRAINVISA_PACKAGE_VERSION_MINOR@'
version = '@BRAINVISA_PACKAGE_VERSION_MAJOR@.@BRAINVISA_PACKAGE_VERSION_MINOR@.@BRAINVISA_PACKAGE_VERSION_PATCH@'

These config files are used in CMaleLists.txt to generate the matching config.h and config.py at configure step:

configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/config/config.py.in" "${CMAKE_BINARY_DIR}/python/connectomist/config.py" @ONLY )
BRAINVISA_INSTALL( FILES "${CMAKE_BINARY_DIR}/python/connectomist/config.py"
                  DESTINATION "python/connectomist"
                  COMPONENT ${PROJECT_NAME} )
configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/config/config.h.in" "${CMAKE_BINARY_DIR}/include/connectomist/config.h" @ONLY )
BRAINVISA_INSTALL( FILES "${CMAKE_BINARY_DIR}/include/connectomist/config.h"
                  DESTINATION "include/connectomist"
                  COMPONENT ${PROJECT_NAME}-dev )

CMakeLists.txt

This file is used by CMake to generate the Makefiles that will be used to build the project.

This file is written in the CMake specific language. See CMake documentation for more information.

On top of the classic CMake functions, we defined functions in brainvisa-cmake that help defining CMakeLists files for Brainvisa projects. These functions names start with BRAINVISA_ and are defined in the file brainvisa-cmake-config.cmake.in in brainvisa-cmake project.

Example: CMakeLists.txt of morphologist-gpl component of the morphologist project.

cmake_minimum_required( VERSION 2.6 )
find_package( brainvisa-cmake REQUIRED )
BRAINVISA_PROJECT()

BRAINVISA_COPY_PYTHON_DIRECTORY( "${CMAKE_CURRENT_SOURCE_DIR}/brainvisa"
                                 ${PROJECT_NAME} )

BRAINVISA_COPY_DIRECTORY( "${CMAKE_CURRENT_SOURCE_DIR}/doc"
                          "share/doc/t1mri-${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}"
                          ${PROJECT_NAME}-usrdoc )

BRAINVISA_CREATE_CMAKE_CONFIG_FILES()

The first 3 lines are mandatory, they check the version of cmake, search for brainvisa_cmake project and initialize the current project information reading the project_info.cmake file.

The rest of the file depends on the content of the component. In the previous example, t1mri-gpl only contains a Brainvisa toolbox (python files) and some documentation. The Brainvisa toolbox files and the documentation will be linked in the build directory.

The last line is useful only if the component is a dependency of another one. If so, you need to write 2 more files in a cmake directory: <component>-config.cmake.in and <component>-use.cmake.in.

brainvisa-cmake functions

Here is a glimpse of the brainvisa-cmake helper functions which can be used in the CMakeLists.txt files.

C++

BRAINVISA_GET_FILE_LIST_FROM_PRO

BRAINVISA_GET_FILE_LIST_FROM_PRO( proFilename <pro variable> <cmake variable> [<pro variable> <cmake variable>...] )

This function was useful when we switched from our home made tool build-config to cmake because build-config used .pro files (similar to Qt’s Qmake) containing the list of headers and sources files needed to build a target. With this function, existing .pro files can be reused in CMakeLists files.

Example

BRAINVISA_GET_FILE_LIST_FROM_PRO( "${_pro}"
                                  TARGET _target
                                  SOURCES _proSources )

_target variable contains the name of the lib or executable target.

_proSources variable contains the name of C++ source files.

BRAINVISA_COPY_AND_INSTALL_HEADERS

BRAINVISA_COPY_AND_INSTALL_HEADERS( <headers list> <include directory> <target_variable> [NO_SYMLINKS] )

Copies or creates symlinks on the header files in the include directory of the build directory.

Example: from anatomist library’s CMakeLists.txt

BRAINVISA_GET_FILE_LIST_FROM_PRO( project.pro "HEADERS" _headers "SOURCES" _sources )
BRAINVISA_COPY_AND_INSTALL_HEADERS( _headers anatomist headersTarget )
add_library( anatomist SHARED ${_sources} )
add_dependencies( anatomist ${headersTarget} )

The list of header and source files is extracted from the project.pro file. The headers are linked in <build_directory>/include/anatomist. The anatomist shared library is created from the source files. A dependency is added between the creation of the library and the copy of the headers.

Python

BRAINVISA_COPY_PYTHON_DIRECTORY

BRAINVISA_COPY_PYTHON_DIRECTORY ( <python directory&gt <component> [<destination directory>] [NO_SYMLINKS] )

Create targets to copy, byte compile and install all Python code contained in a directory. If the destination directory is not set, the right most directory name in the python directory is used.

Example: from axon’s CMakeLists.txt

BRAINVISA_COPY_PYTHON_DIRECTORY( "${CMAKE_CURRENT_SOURCE_DIR}/python"
                                 ${PROJECT_NAME} )
BRAINVISA_COPY_PYTHON_DIRECTORY( "${CMAKE_CURRENT_SOURCE_DIR}/brainvisa"
                                 ${PROJECT_NAME} )

The python directory in source directory will be linked in the python directory of the build directory.

The brainvisa directory in source directory will be linked in the brainvisa directory of the build directory.

SIP

BRAINVISA_ADD_SIP_PYTHON_MODULE

BRAINVISA_ADD_SIP_PYTHON_MODULE( <module> <directory> <mainSipFile> [ SIP_SOURCES <file> ... ] [ SIP_INCLUDE <directory> ... ] [ SIP_INSTALL <directory> ] )

Example: from pyanatomist’s CMakeLists.txt

BRAINVISA_ADD_SIP_PYTHON_MODULE( anatomistsip
    anatomist/cpp
    "${CMAKE_BINARY_DIR}/${ANATOMIST_RELATIVE_SIP_DIRECTORY}/anatomist_VOID.sip"
    SIP_SOURCES ${_generatedSipFileList} ${_sipSources}
    SIP_INCLUDE "${CMAKE_BINARY_DIR}/${ANATOMIST_RELATIVE_SIP_DIRECTORY}"
      "${AIMS-FREE_SIP_DIRECTORY}" "${PYQT${DESIRED_QT_VERSION}_SIP_DIR}"
    SIP_INSTALL "${ANATOMIST_RELATIVE_SIP_DIRECTORY}" )

A library named anatomistsip will be created in python/anatomist/cpp directory in build directory from the sources files indicated.

Qt

BRAINVISA_ADD_MOC_FILES

BRAINVISA_ADD_MOC_FILES <result variable> <header files>

Creates a makefile target to generate the C++ code needed to replace Q_OBJECT macro. It uses the Qt Meta-Object compiler (moc).

Example: from anatomist library’s CMakeLists.txt

BRAINVISA_GET_FILE_LIST_FROM_PRO( project.pro "HEADERS" _headers "SOURCES" _sources )
BRAINVISA_ADD_MOC_FILES( _sources ${_headers} )
add_library( anatomist SHARED ${_sources} )

The files generated by moc will be added to the source files used to generate anatomist library.

BRAINVISA_ADD_TRANSLATION

BRAINVISA_ADD_TRANSLATION <source_share_dir> <dest_share_dir> <component>

Searches recursively qt linguist source files (*.ts) in the source share directory and generates the commands to create the associated *.qm files in the build share directory and creates associated install rules.

Example: from anatomist-free’s CMakeLists.txt

BRAINVISA_ADD_TRANSLATION( "shared" "share/anatomist-${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}" ${PROJECT_NAME})

Files and directories

BRAINVISA_COPY_FILES

BRAINVISA_COPY_FILES( <component> <source files> [SOURCE_DIRECTORY <directory>] DESTINATION <destination directory> [IMMEDIATE] [GET_TARGET <target variable>][GET_OUTPUT_FILES <target variable>] [NO_SYMLINKS] )

Copies a list of files from the source directory to a directory in the build directory.

Example: from cartodata’s CMakeLists.txt

BRAINVISA_COPY_FILES(${PROJECT_NAME}-devdoc ${CMAKE_CURRENT_SOURCE_DIR}/changelog.html
    DESTINATION share/doc/cartodata-${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}/doxygen )

BRAINVISA_COPY_DIRECTORY

BRAINVISA_COPY_DIRECTORY( <source directory> <destination directory> <component> [IMMEDIATE] [GET_TARGET <target variable>] [NO_SYMLINKS] )

Recursively copies and installs all files in <source directory> except files named CMakeLists.txt, *~, */.svn/*, *.odt, *.odp, *.doc, *.sdw, *.sxw.

Example: from axon’s CMakeLists.txt

BRAINVISA_COPY_DIRECTORY( "${CMAKE_CURRENT_SOURCE_DIR}/share"
                          "share/${PROJECT_NAME}-${BRAINVISA_PACKAGE_VERSION_MAJOR}.${BRAINVISA_PACKAGE_VERSION_MINOR}"
                          ${PROJECT_NAME} )
BRAINVISA_COPY_DIRECTORY( "${CMAKE_CURRENT_SOURCE_DIR}/doc"
                          "share/doc/${PROJECT_NAME}-${BRAINVISA_PACKAGE_VERSION_MAJOR}.${BRAINVISA_PACKAGE_VERSION_MINOR}"
                          ${PROJECT_NAME}-usrdoc )
BRAINVISA_COPY_DIRECTORY( "${CMAKE_CURRENT_SOURCE_DIR}/bin"
                          bin
                          ${PROJECT_NAME} )
BRAINVISA_COPY_DIRECTORY( "${CMAKE_CURRENT_SOURCE_DIR}/scripts"
                          scripts
                          ${PROJECT_NAME} )

Documentation

BRAINVISA_GENERATE_DOXYGEN_DOC

BRAINVISA_GENERATE_DOXYGEN_DOC( <input_variable> [<file to copy> ...] [INPUT_PREFIX <path>] [COMPONENT <name>] )

Adds rules to generate doxygen documentation (documentation of C++ source files) with “make doc” or “make devdoc”.

  • <input_variable>: variable containing a string or a list of input sources.
  • <file to copy>: file (relative to ${CMAKE_CURRENT_SOURCE_DIR}) to copy in the build tree. Files are copied in ${DOXYGEN_BINARY_DIR} if defined, otherwise they are copied in ${PROJECT_BINARY_DIR}/doxygen. The doxygen configuration file is generated in the same directory.
  • <input prefix>: directory where finding input files

<component>: component name for this doxygen documentation. it is used to create the output directory and the tag file name. By default it is the PROJECT_NAME. But it is useful to give an alternative name when there are several libraries documented with doxygen in the same project.

Before calling this function, it is possible to specify values that are going to be written in doxygen configuration file by setting variable names DOXYFILE_<doxyfile variable name>. For instance, in order to set project name in Doxygen, one should use:

SET( DOXYFILE_PROJECT_NAME, "My wonderful project" ).

Example: from cartodata’s CMakeLists

FIND_PACKAGE( Doxygen )
IF ( DOXYGEN_FOUND )
    SET(component_name "cartodata")
    set( DOXYFILE_PREDEFINED "${AIMS_DEFINITIONS}")
    set(aims_version "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}")
    set( DOXYFILE_TAGFILES "${CMAKE_BINARY_DIR}/share/doc/cartobase-${aims_version}/doxygen/cartobase.tag=../../cartobase-${aims_version}/doxygen")
    BRAINVISA_GENERATE_DOXYGEN_DOC( _headers
                                    INPUT_PREFIX "${CMAKE_BINARY_DIR}/include/${component_name}"
                                    COMPONENT "${component_name}")
    add_dependencies( ${component_name}-doxygen cartobase-doxygen )
ENDIF ( DOXYGEN_FOUND )

BRAINVISA_GENERATE_EPYDOC_DOC

BRAINVISA_GENERATE_EPYDOC_DOC( <source directory> [ <source directory> ... ] <output directory> [ EXCLUDE <exclude list> ] )

Generates documentation for python source files with Epydoc. No longer used, we write sphinx doc now.

BRAINVISA_GENERATE_SPHINX_DOC

BRAINVISA_GENERATE_SPHINX_DOC( <source directory> <output directory> [TARGET <target_name>] )

Generates documentation for python source files with Sphinx.

Example: from axon’s CMakeLists

BRAINVISA_GENERATE_SPHINX_DOC( "sphinxdoc/sphinx"
    "share/doc/axon-${BRAINVISA_PACKAGE_VERSION_MAJOR}.${BRAINVISA_PACKAGE_VERSION_MINOR}/sphinx" )

BRAINVISA_GENERATE_DOCBOOK_DOC

BRAINVISA_GENERATE_DOCBOOK_DOC( [EXCLUDE <docbook_project_name>] )

Generates docbook documentation. No longer used either, we are using sphinx.

Dependencies

BRAINVISA_CREATE_CMAKE_CONFIG_FILES

BRAINVISA_CREATE_CMAKE_CONFIG_FILES()

BRAINVISA_FIND_PACKAGE

BRAINVISA_FIND_PACKAGE( <component> )

BRAINVISA_DEPENDENCY

BRAINVISA_DEPENDENCY( <pack_type> <dependency_type> <component> <component_pack_type> [ <version ranges> ] [BINARY_INDEPENDENT] )

This function enables to declare that the current brainvisa component has a dependency on another component. That other component can be a Brainvisa component or a thirdparty dependency.

  • <pack_type>: type of package which have this dependency. Indeed, the compilation and runtime dependencies are not necessary the same. Can be RUN for runtime package, DEV for development package or DOC for documenation package.
  • <dependency_type>: indicates if the dependency is mandatory or not. Can be DEPENDS or RECOMMENDS.
  • <component>: name of the dependency component.
  • <component_pack_type>: type of package for the dependency package: RUN, DEV or DOC.
  • <version ranges>: required version of the dependency package.
  • BINARY_INDEPENDENT can be added to indicate that the component and its dependency are binary independent (dependency between python modules for example) but this information is not used currently.

At configuration time, the information declared in this function will be written in a file named compilation_info.py in the directory <build_directory>/python/brainvisa. This file is used by the bv_packaging script to create Brainvisa packages with the needed dependencies.

Examples (from anatomist-free CMakeLists.txt)

BRAINVISA_DEPENDENCY( RUN DEPENDS aims-gpl RUN "= ${aims-gpl_VERSION}" )
BRAINVISA_DEPENDENCY( DEV DEPENDS aims-gpl DEV )
BRAINVISA_DEPENDENCY( RUN DEPENDS libqtcore4 RUN ">= ${QT_VERSION}" )
BRAINVISA_DEPENDENCY( DEV DEPENDS libqtcore4 DEV )
BRAINVISA_DEPENDENCY( RUN DEPENDS libqwt5-qt4 RUN)

BRAINVISA_THIRDPARTY_DEPENDENCY

BRAINVISA_THIRDPARTY_DEPENDENCY( <source component> <package type> <dependency type> <dest component> <dest component package type> [ <version ranges> ] [BINARY_INDEPENDENT] )

This function enables to declare a dependency of a thirdparty component. There is generally no need to use this function directly in a project CMakeLists.txt. This function is used in brainvisa-cmake special files that describes the packaging rules for thirdparty components. These files are in development/brainvisa-cmake/trunk/cmake.

Install

Install rules will be used by bv_packaging script to create Brainvisa packages.

Be careful, if you want to use directly the make install command to install files of the build directory in another location, you’ll have to specify the variable BRAINVISA_INSTALL_PREFIX in the make install command. Indeed, to be able to specify an install location when using bv_packaging script, we had to use a variable that have to be defined at installation step instead of the CMAKE_INSTALL_PREFIX which is defined at configuration step.

Example

make BRAINVISA_INSTALL_PREFIX=/tmp/test install-aims-gpl

BRAINVISA_INSTALL_DIRECTORY

BRAINVISA_INSTALL_DIRECTORY( directory destination component )

BRAINVISA_INSTALL

BRAINVISA_INSTALL

BRAINVISA_INSTALL_RUNTIME_LIBRARIES

BRAINVISA_INSTALL_RUNTIME_LIBRARIES( component )