2. Building GNDStk

We designed GNDStk with the hope that it will prove to be straightforward to download, to install, and to use. GNDStk resides on Github, and uses CMake as its primary build system.

The following description is based on commands that work for us, on a Linux system. Adapt our instructions as necessary for your own platform.

2.1. Download

Enter the directory in which you’d like GNDStk to reside. This might be your root user directory, e.g. /home/yourname/, or perhaps, say, in a dedicated directory that you use for your projects.

Download:

git clone https://github.com/njoy/GNDStk.git

Enter directory:

cd GNDStk

At this point you can, if you wish, check out a specific branch of GNDStk. As is typical in git repositories, our main branch is called master. So, if you wish:

Check out a branch:

git checkout master

With master that isn’t necessary, but you can replace master with something else.

2.2. Build & Test

Some people prefer, as you may, to create a build directory in which to build the project. (Doing as much certainly helps to keep a project’s base directory more free of clutter.) Continuing from the GNDStk directory, where we left off in the Downloading narrative above:

Make and enter a build directory:

mkdir build
cd build

Now run cmake itself, being sure to point it one level up, to where the CMakeLists.txt file resides, if you’re indeed down in build.

Run cmake:

cmake ..

The good news is that the above command should download GNDStk’s dependencies – the modest number of outside C++ libraries on which it depends – automatically. The bad news is that the download may, for the same reason, take quite some time. Resist the temptation to terminate the command, perhaps believing that your computer has hung, and consider starting cmake .. before lunch hour if you have a slow Internet connection. The main culprit appears to be the “nlohmann json” library, https://github.com/nlohmann/json. An excellent library, by all accounts, and invaluable as the workhorse for GNDStk’s JSON capabilities; but responsible, at the time of the writing, for over 400MB – about 95% – of the entire dependencies directory that the above command creates.

Finally, the Makefile that the above cmake command should have created, can be used to build GNDStk’s test suite.

Build GNDStk’s test suite:

make

Or, if you have for instance six processor cores available, then

Multicore build:

make -j 6

will no doubt run far faster.

GNDStk was carefully designed to not be one of those infamous C++ libraries that triggers hours-long, even many-minutes-long, compilations, leaving beleaguered users wondering if they could more quickly find the data they’re looking for by loading a file into an editor, finding the data of interest, and cutting-and-pasting in their own code. The above make in fact compiles several codes, comprising our entire, substantial GNDStk test suite with broad coverage across all of its considerable capabilities. Even so, we hope and believe that you won’t have the need to report to us that a multicore build took more than a minute or two, at most, on a modern and well-oiled home or office machine.

You can then invoke:

Run GNDStk’s tests:

make test

to run all of the tests. We hope that you will, at this point, have the same pleasant experience that we do when we invoke make test on our master GNDStk branch: a report that 100% tests passed.

2.3. Summary

Here’s a summary of the commands described above, from downloading GNDS from our repository, through building and running its full suite of tests:

# Get GNDStk
git clone https://github.com/njoy/GNDStk.git
cd GNDStk
git checkout master

# Cmake; may take some time
mkdir build
cd build
cmake ..

# Make and run test suite
make
# ...or make -j 6
make test

2.4. Your Own Application

Let’s outline how you can interface your own application code with GNDStk, using CMake.

First, you should have downloaded the GNDStk repository as described above. Building and running its test suite isn’t a prerequisite for our present purposes, but certainly wouldn’t hurt. Any problems you might encounter in that process would no doubt show themselves again, in some form, here.

Now assume you have some directory, call it MyApp, for your application, with the following file structure:

MyApp/
   CMakeLists.txt
   dependencies/
      GNDStk/
   src/
      app.cpp

GNDStk/ is the cloned GNDStk repository. (If you downloaded it elsewhere and don’t want a duplicate, then perhaps make it a symlink here , a.k.a. a shortcut, to the cloned repo.) Next, for our simple illustration here, let app.cpp be a single C++ source file that contains all of your code to be used with GNDStk. The remaining structure is typical for applications that use CMake.

A working CMakeLists.txt for the above is as follows:


cmake_minimum_required( VERSION 3.14 )
project( app LANGUAGES CXX )

set( CMAKE_CXX_STANDARD 17 )
set( CMAKE_CXX_STANDARD_REQUIRED YES )

add_subdirectory(dependencies/GNDStk)

add_executable(app src/app.cpp)
target_link_libraries(app PUBLIC GNDStk)

And, the simplest possible GNDStk-aware app.cpp would be:


#include "GNDStk.hpp"

int main()
{
}

Finally, building app should be as simple as this:

cd MyApp  # <== If you're not there already
mkdir build
cd build
cmake ..
make

If all went well, app.cpp should have been compiled into an executable file called app.

2.5. Alternative: Bash Script

An important goal for us is that GNDStk be accessible, with as minimally intrusive a build process as possible, to a wide variety of researchers.

If you’re using libraries other than GNDStk, they may impose their own build systems – possibly ones you like, possibly ones you don’t, but ones you’re stuck with, regardless, for better or for worse. You may, on the other hand, be using your preferred and well-liked build system. Independent of what you may or may not be working with in that respect, we want GNDStk to impose as little additional complexity as it can.

In the above spirit, and if you’re using a Linux or Linux-based machine, you may find that the contents of the following simple shell script can be adapted easily to your needs:

#!/bin/bash

# Specify your base GNDStk directory (as cloned from github) here.
GNDSTKDIR=/path/to/your/downloaded/GNDStk

# Example compilation command. -std=c++17, and the -Is, are needed.
COMPILE="
   g++
  -std=c++17
  -I$GNDSTKDIR/src
  -I$GNDSTKDIR/build/_deps/pugixml-adapter-src/src/src
  -I$GNDSTKDIR/build/_deps/json-src/include
  -I$GNDSTKDIR/build/_deps/json-src/include/nlohmann
  -I$GNDSTKDIR/build/_deps/log-src/src
  -I$GNDSTKDIR/build/_deps/spdlog-src/include
  -Wall -Wextra -Wpedantic"

# pugixml.cpp is the only C++ source file, other than your own,
# that needs to be compiled. We'll arrange to build it *once*.
if [ ! -f "pugixml.o" ]; then
$COMPILE \
   $GNDSTKDIR/build/_deps/pugixml-adapter-src/src/src/pugixml.cpp \
  -c -o pugixml.o
fi

# Compile your own C++ application, linking with the .o from above.
$COMPILE app.cpp pugixml.o -o app

Begin, as you can see, by specifying the base GNDStk directory you cloned. The script immediately uses this value to create a simple compilation command, in this case one that uses g++ as its C++ compiler. Next, the script checks to see if a certain .cpp file, from one of GNDStk’s dependencies, has been compiled. If it hasn’t been, yet, then it is now. Finally, another compilation command builds your own application – illustrated in this simple example as a single C++ source file called app.cpp. Consider trying this first with the minimal app.cpp that was shown in the section on CMake builds.

You’re welcome to adapt our script, or its contents, as may be necessary or helpful within your own build regime.

Some caveats. Use of the sample bash script assumes that you’ve downloaded GNDStk, and run cmake .. (and in a build directory), as outlined earlier. You can easily adjust the script if, for whatever reason, you configured things in a different manner. Realize, however, that the cmake .. in some form, or steps that created the same effect, must have happened in order for GNDStk’s dependencies to have been downloaded into the _deps directory that makes several appearances throughout the script’s compilation command.

Be aware also that the script reflects dependencies, and their locations in directories, that are correct at the time of this writing. While we intend to update these instructions if and when we make relevant changes to GNDStk, it’s possible that some detective work may prove to be necessary if we drop the documentation ball after dependencies do, for whatever reason, change. If, for instance, we decide to explore someday one of those deep mysteries of the universe that regularly visits our world through computers, such as why pugixml.cpp ended up in src/src/ rather than just in src/, then it’s possible, even as much as we try to behave, that we’ll make a quick change to our own make system’s actions without updating these instructions for a simple script in an entirely timely manner.

2.6. Header-Only Library

GNDStk, proper, is a C++ header-only library. You can find plenty of information online if you’re unfamiliar with the concept. In our opinion, header-only libraries provide a multitude of advantages, such as making builds far less complex than they’d otherwise be; and their disadvantages, generally distilling down to some variation of “builds can take longer,” are straightforward to mitigate with careful design. We designed GNDStk carefully.

Our library does, however, have one dependency, pugixml (https://pugixml.org/), that has a single C++ source (not header) file. That’s why our sample shell script, if you read that section, needed to compile one .cpp file, other than your own, directly.

We mention our library’s header-only nature not so as to conclude this chapter with any particular profound point, but largely for informational purposes. If you’re unfamiliar with the header-only concept, or with how to write or to use such libraries in C++, then you might find it helpful – or more importantly, fun – to learn more. With respect to GNDStk, knowing that it’s formulated in this fashion may allow you, in one way or another, to make the best use of GNDStk in your own build system, and in your own application.