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++ libraryatlas_f
– The Fortran interface library (only available if the atlas FORTRAN feature was enabled)
Additionally also following CMake variables will be defined:
atlas_FOUND
– True if atlas was found correctlyatlas_HAVE_FORTRAN
– True if the atlas FORTRAN feature was enabledatlas_HAVE_MPI
– True if atlas is capable to run in a MPI parallel contextatlas_HAVE_TESSELATION
– True if the atlas TESSELATION feature was enabledatlas_HAVE_TRANS
– True 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