Getting started » Linking Atlas into your project

Guide on how to find and link Atlas into your project

Using CMake

As Atlas is itself built with the CMake build system, it is very convenient to include Atlas in your own CMake project.

Finding Atlas

There are two approaches available, with tradeoffs for each.

  • Using a pre-installed Atlas
  • Bundling Atlas as a subproject

Using a pre-installed Atlas

This is the recommended option if Atlas is not part of your developments, and rather used as a stable third-party library. You then don’t need to add the overhead of Atlas compilation to each new build of your project. On the other hand, it is less convenient to try out different build types, compilers or other build options.

To aid CMake in finding Atlas, you can export atlas_ROOT in the environment

export atlas_ROOT=<path-to-atlas-install-prefix>

Within your own CMake project, then simply add

find_package( atlas REQUIRED )

The REQUIRED keyword is optional and causes CMake to exit with error if atlas was not found.

When atlas is found, the available atlas CMake targets will be defined:

  • atlas – The core C++ library
  • atlas_f – The Fortran interface library (only available if the atlas FORTRAN feature was enabled)

Additionally also following CMake variables will be defined:

  • atlas_FOUNDTrue if atlas was found correctly
  • atlas_HAVE_FORTRANTrue if the atlas FORTRAN feature was enabled
  • atlas_HAVE_MPITrue if atlas is capable to run in a MPI parallel context
  • atlas_HAVE_TESSELATIONTrue if the atlas TESSELATION feature was enabled
  • atlas_HAVE_TRANSTrue if the atlas TRANS feature was enabled

Bundling Atlas as a subproject

A self-contained alternative to a shared instance of the libraries, is to add atlas and its required depenencies directly into your project (as Git submodules, bundling downloaded archives etc.), and then to use CMake’s add_subdirectory() command to compile them on demand. With this approach, you don’t need to care about manually installing atlas, fckit, eckit, and ecbuild; however the usual tradeoffs when bundling code apply — slower full rebuilds, IDEs having more to parse etc. Conveniently, in this case, build-time options can be set before calling add_subdirectory(). Note that it’s necessary to use the CACHE ... FORCE arguments in order to have the options set properly.

# Set features required for Atlas
set( ENABLE_MPI         ON CACHE BOOL "" FORCE )
set( ENABLE_TESSELATION ON CACHE BOOL "" FORCE )

# Add Atlas and its dependencies as subprojects
add_subdirectory( ecbuild )
add_subdirectory( eckit )
add_subdirectory( fckit )
add_subdirectory( atlas )

find_package( atlas REQUIRED )

Linking your CMake library or executable with Atlas

To use the C++ API of Atlas all you need to do to link the atlas target to your target is using the target_link_libraries():

add_library( library_using_atlas
    source_using_atlas_1.cc
    source_using_atlas_2.cc )

target_link_libraries( library_using_atlas PUBLIC atlas )

Atlas include directories, compile definitions, and required C++ language flags (e.g. -std=c++11) are automatically added to your target.

Complete CMake example

We now show a full example of a mixed C++ / Fortran project, describing the two approaches in finding Atlas. The project contains two executables that simply print “Hello from atlas” implemented respectively in C++ and Fortran.

In the case of pre-installed Atlas the project’s directory structure should be:

project/
  ├── CMakeLists.txt
  └── src/
        ├── hello_atlas.cc
        └── hello_atlas_f.F90

In the case of bundling Atlas dependencies as subprojects, the project’s directory structure should instead be:

project/
  ├── CMakeLists.txt
  ├── src/
  │     ├── hello_atlas.cc
  │     └── hello_atlas_f.F90
  ├── ecbuild/
  ├── eckit/
  ├── fckit/
  └── atlas/

The bundled dependencies can be e.g. added as git submodules, symbolic links, or downloaded/added manually/automatically.

The content of the CMakeLists.txt at the project root contains

cmake_minimum_required( VERSION 3.12 )

project( hello_world VERSION 1.0.0 LANGUAGES CXX Fortran )

# Setup CMake behaviour
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY    ${CMAKE_BINARY_DIR}/bin )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY    ${CMAKE_BINARY_DIR}/lib )
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY    ${CMAKE_BINARY_DIR}/lib )
set( CMAKE_INSTALL_RPATH               ${CMAKE_INSTALL_PREFIX}/lib )
set( CMAKE_INSTALL_RPATH_USE_LINK_PATH True )

#############################################
### Optionally add dependencies as subprojects

option( BUNDLE "Bundle dependencies as subprojects" OFF)
  # Can be enabled with `-DBUNDLE=ON`

if( BUNDLE )
    # Note that this case means that the source codes for
    # each of the following dependencies is required to
    # be available inside this directory, which may be
    # achieved via e.g. `copy`, `symbolic links`,
    #   `git submodule`, ...

    # Set features for Atlas and dependencies
    set( ENABLE_MPI   ON  CACHE BOOL "" FORCE )
    set( ENABLE_TESTS OFF CACHE BOOL "" FORCE )

    # Add Atlas and dependencies as subprojects
    add_subdirectory( ecbuild )
    add_subdirectory( eckit )
    add_subdirectory( fckit )
    add_subdirectory( atlas )

endif()

#############################################
### Main project build

# Find package atlas
find_package( atlas REQUIRED COMPONENTS FORTRAN )

# Define a C++ executable and link with atlas
add_executable( hello-atlas src/hello-atlas.cc )
target_link_libraries( hello-atlas PUBLIC atlas )

# Define a Fortran executable and link with atlas_f
add_executable( hello-atlas_f src/hello-atlas_f.F90 )
target_link_libraries( hello-atlas_f PUBLIC atlas_f )

#############################################
### Installation

install( TARGETS hello-atlas hello-atlas_f
     RUNTIME DESTINATION bin )

Inspection of this CMakeLists.txt file shows that for this project we created a BUNDLE option to toggle the behaviour of either bundling the dependencies or not. To enable the bundling, the argument -DBUNDLE=ON needs to be passed on the cmake configuration command line.

  • The content of hello_atlas.cc is:
#include "atlas/library.h"
#include "atlas/runtime/Log.h"

int main(int argc, char* argv[]) {
  atlas::initialize(argc, argv);
  atlas::Log::info() << "Hello from atlas" << std::endl;
  atlas::finalize();
}
  • The content of hello_atlas_f.cc is:
program hello_atlas_f
  use atlas_module
  implicit none

  call atlas_initialize()
  call atlas_log%info("Hello from atlas")
  call atlas_finalize()
end program

Creating a new project with ecbuild

When creating a new project from scratch, please consider to use ecbuild, which is also used by atlas. It extends CMake with macros that make the experience easier. An example project CMakeLists.txt file would then be:

cmake_minimum_required( VERSION 3.12 )

find_package( ecbuild 3.0 ) # Required before project()

project( myproject VERSION 1.0.0 LANGUAGES CXX )

find_package( atlas REQUIRED )

ecbuild_add_library( TARGET mylib
    SOURCES
         src/mylib/myclass1.h
         src/mylib/myclass1.cc
         src/mylib/myclass2.h
         src/mylib/myclass12.cc
    PUBLIC_INCLUDES
         $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>
         $<INSTALL_INTERFACE:include>
    PUBLIC_LIBS        atlas
    INSTALL_HEADERS    ALL
    HEADER_DESTINATION include/mylib )

ecbuild_add_executable( TARGET myexe
    SOURCES src/programs/myexe.cc
    LIBS    mylib )

ecbuild_print_summary()
ecbuild_install_project( NAME myproject )

The strange entry PUBLIC_INCLUDES $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src> means that the directory src within the project’s source dir of mylib is used as include directory during compilation, but also propagated automatically (because PUBLIC) when compiling other targets (such as myexe further) that link with mylib which is not yet installed. The INSTALL_INTERFACE is used when myproject is installed, and downstream packages need to link with mylib. The original source directory may have modified, or not be available any more.

Using pkgconfig

The ecbuild CMake scripts provide the Atlas installation with pkgconfig files that contain the instructions for the required include directories, link directories and link libraries.

Given that the variable atlas_ROOT is present, we can compile the same hello_atlas.cc file above, using

export PKG_CONFIG_PATH=$atlas_ROOT/lib64/pkgconfig:$PKG_CONFIG_PATH
ATLAS_INCLUDES=$(pkg-config atlas --cflags)
ATLAS_LIBS=$(pkg-config atlas --libs)

$CXX hello-atlas.cc -o hello-atlas $ATLAS_INCLUDES $ATLAS_LIBS