Compiling Configuration
=======================

.. _configuration

.. contents:: Table of Contents

Each SPBench benchmark has a configuration file that includes its parameters and build dependencies. 
SPBench reads this file and generates a makefile specific to the respective benchmark. 
Some triggers activate the generation of a new makefile. 
It happens whenever one of the following situations occurs:

- When the ``./spbench compile`` command is executed and there is no makefile yet.
- When the user runs the ``./spbench configure`` command and changes something in the JSON file (if nothing is changed, a new makefile will not be generated).
- When the user runs the ``./spbench update`` command.

Run ``./spbench -h`` for more info about the commands.

.. warning:: 
   In the ``./spbench configure`` command, the trigger for generating a new makefile is to exit the text editor. 
   So realize that if you use a text editor that will not exit or was not opened via the ``./spbench configure ... -editor <my_text_editor>`` command, the new makefile will not be generated automatically every time you change the file. 
   You will always need to run the 'update' command if you want to generate an updated makefile in these cases.

JSON Configuration File
-----------------------

This is the structure of the JSON configuration files:

.. code-block:: JSON

   {
      "CXX"          : "<compiler>",
      "CXX_FLAGS"    : "<compiler flags>",
      "PPI_CXX"      : "<custom PPI compiler>",
      "PPI_CXX_FLAGS": "<custom PPI compiler flags>",
      "PRE_SRC_CMD"  : "<specific commands added right before the benchmark source file>",
      "POST_SRC_CMD" : "<specific commands added right after the benchmark source file>",
      "MACROS"       : "<compiling macros>",
      "PKG-CONFIG":{
         "myPKG_1"   : "<package-config command>",
         "myPKG_2"   : "...",
         "myPKG_N"   : "..."
      },
      "INCLUDES":{
         "myINC_1"   : "-I <my includes>",
         "myINC_2"   : "...",
         "myINC_N"   : "..."
      },
      "LIBS":{
         "myLIB_1"   : "-L <my libs>",
         "myLIB_2"   : "...",
         "myLIB_N"   : "..."
      },
      "LDFLAGS"      : "-my_lib1 -my_lib2 ..."
   }

The compiler defined in CXX is the compiler used to compile the SPBench source code and the backend applications. 
PPI_CXX is the compiler that will be used to compile the code that the user has access to. 
If no custom compiler is defined for PPI_CXX, the CXX compiler will be used by default.

.. warning:: 
   SPBench recognizes all these keywords, but will not recognize others. 
   So be careful not to change the keys. 
   The exception are the subkeys from PKG-CONFIG, INCLUDES, and LIBS.

Example
-------

The example below shows the configuration file of a benchmark implemented with the SPar PPI. 
Note that SPar has its custom compiler and its flags.
For SPar it is also necessary to add a flag in front of the source code to be compiled. 
It is a case where PRE_SRC_CMD needs to be used. Also, note the syntax used to add pkg-config. 
You must not add the encapsulation of the command, only the parameters.

.. code-block:: JSON

   {
      "CXX"          : "g++",
      "CXX_FLAGS"    : "-std=c++1y -O3",
      "PPI_CXX"      : "$BENCH_DIR/ppis/SPar/bin/spar",
      "PPI_CXX_FLAGS": "-O3 -spar_ordered -spar_ondemand -spar_blocking",
      "PRE_SRC_CMD"  : "-spar_file",
      "POST_SRC_CMD" : "",
      "MACROS"       : "-DNO_DEFAULT_MAPPING",
      "PKG-CONFIG":{
         "opencv"    : "pkg-config --cflags --libs opencv"
      },
      "INCLUDES":{
         "opencv"    : "-I $BENCH_DIR/libs/opencv/opencv-2.4.13.6/include/",
         "UPL"       : "-I $BENCH_DIR/libs/upl/include/upl/"
      },
      "LIBS":{
         "UPL"       : "-L $BENCH_DIR/libs/upl/lib/x86 -lupl"
      },
      "LDFLAGS"      : "-lpthread"
   }

UPL
---

You can see in the example above that the configuration file includes the UPL library.
UPL stands for Utility Performance Library.
It is a static library that provides a set of functions useful for measuring performance in C/C++ programs (`more info here <https://github.com/dalvangriebler/upl>`_).

In SPBench, we use UPL for measuring CPU and memory usage.

That is why it is included in the configuration file. However, this library is only available for **x86** and **arm** architectures. The benchmarks default include the x86 version, as seen in the configuration file above. However, you can change ``upl/lib/x86`` to ``upl/lib/arm`` if you want to run SPBench on an arm processor.

It may not be possible to use UPL on other architectures at the moment, so if this is the case, you can disable UPL by adding the macro ``-DNO_UPL`` in the configuration file. You will not be able to evaluate CPU and memory usage. However, the other metrics will be available.

.. Tip::
   ``$BENCH_DIR`` defines the root of the SPBench. 
   It is basically an SPBench keyword. 
   If you want, you can also use it to define the paths that you insert into configuration files.

.. Tip::
   The macro ``-DNO_DEFAULT_MAPPING`` is used to disable FastFlow/SPar thread pinning. 
   This macro is active by default in all benchmarks. 
   FastFlow developers recommend not using this pinning if running in a hyper-threading environment.
   This thread pinning serves to allocate the threads to the processor's physical cores first.
   But if you want to use it, to make FastFlow/SPar properly recognize and map the cores of the processor you must run at SPBench root ``bash ./ppis/SPar/libraries/ff/mapping_string.sh`` and ``bash ./ppis/fastflow/ff/mapping_string.sh``. 
   It is only required once. 
   However, this FastFlow feature may not be able to automatically set this value in the ``./ppis/.../ff/config.sh`` file. 
   In this case, you must manually update this ``config.hpp`` file with the execution result of the ``mapping_string.sh`` script.
