<h3>Introduction</h3>
In the last week there were a few questions about how to use ArrayFire with CMake on Linux on the <a href="https://groups.google.com/forum/#!forum/arrayfire-users">ArrayFire Google Groups page</a>. Although we have some quick notes about this <a href="http://sandbox.arrayfire.com/docs/using_on_linux.htm">in the documentation</a> I thought it would be fun to provide a fully worked example that demonstrates a cool CMake trick to reduce compilation time by a factor of three when linking against multiple backends. At the bottom of this post is a link to a GitHub repository containing a minimal CMake project setup which links a program against ArrayFire's CPU, OpenCL, and CUDA backends.

<!--more-->

The instructions below will work on Linux, OSX, and Windows; however, you will need to use <a href="http://www.cmake.org/cmake/help/v3.0/manual/cmake-generators.7.html">CMake generators</a> if you want to use XCode or Visual Studio to compile your code. For Visual Studio specifically, we suggest you <a href="http://sandbox.arrayfire.com/docs/using_on_windows.htm">follow the documentation</a> to set up Visual Studio projects rather than using CMake generators because it is a much more straightforward process.
<h3>Prerequisites</h3>
Foremost, make sure that you have both a C++11 compatible compiler and CMake 3.0 (or later) installed on your system. Please <a href="http://sandbox.arrayfire.com/docs/using_on_linux.htm">see the documentation</a> for specific commands for Fedora, Debian, Ubuntu, and a special requirement for the Tegra TK1. Next, ensure that you have <a href="http://sandbox.arrayfire.com/download">downloaded</a> (or <a href="https://github.com/arrayfire/arrayfire">compiled ArrayFire from source</a>) and installed it to your system. Pay close attention to the installation path as this <em>may</em> need to be manually specified at a later stage.
<h3>Creating a project</h3>
Set up a directory as you would any other project. Lets say we have two sources files, <code>fooA.cpp</code> and <code>fooB.cpp </code>which we wish to compile into an executable called <code>fooExe</code> and link against ArrayFire. In the top level folder of your project create a file called <code>CMakeLists.txt</code> and fill it with the following contents:
<pre><code>CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
PROJECT(foo)
FIND_PACKAGE(ArrayFire REQUIRED)
INCLUDE_DIRECTORIES(${ArrayFire_INCLUDE_DIRS})

ADD_EXECUTABLE(fooExe fooA.cpp fooB.cpp)
TARGET_LINK_LIBRARIES(fooExe ${ArrayFire_LIBRARIES} )
</code></pre>
The <code>FIND_PACKAGE</code> command will attempt to find the ArrayFire library using ArrayFire’s pre-built <code>ArrayFireConfigure.cmake</code> script located in the <code>share/ArrayFire/cmake</code> sub-folder of the ArrayFire installation root. The word <code>REQUIRED</code> will cause CMake to fail during the setup stage if ArrayFire is not found. The <code>ADD_EXECUTABLE</code> command specifies that we wish to create an executable called <code>fooExe</code> which will be composed of the <code>fooA.cpp</code> and <code>fooB.cpp</code> source files. Next, the <code>TARGET_LINK_LIBRARIES</code> command instructs CMake to link the <code>fooExe</code> program with the most powerful ArrayFire backend library (typically CUDA). If you wish to link against a different backend, the <code>ArrayFireConfigure.cmake</code> script also provides the following variables for use:
<pre><code>ArrayFire_CPU_FOUND        - True of the ArrayFire CPU library has been found.
ArrayFire_CPU_LIBRARIES    - Location of ArrayFire's CPU library, if found
ArrayFire_CUDA_FOUND       - True of the ArrayFire CUDA library has been found.
ArrayFire_CUDA_LIBRARIES   - Location of ArrayFire's CUDA library, if found
ArrayFire_OpenCL_FOUND     - True of the ArrayFire OpenCL library has been found.
ArrayFire_OpenCL_LIBRARIES - Location of ArrayFire's OpenCL library, if found
</code></pre>
See the <a href="http://www.cmake.org/cmake/help/v3.3/">CMake documentation</a> for inquires about the other portions of the file.

Now, to build the project we execute the following commands:
<pre><code>cmake .
make
</code></pre>
The <code>cmake</code> command instructs CMake to parse the current directory’s <code>CMakeLists.txt</code> file and generate the necessary files for compiling the program. If the ArrayFire library is not found, you may get an error like the following:
<pre><code>CMake Error at src/CMakeLists.txt:5 (FIND_PACKAGE):
  By not providing "FindArrayFire.cmake" in CMAKE_MODULE_PATH this project
  has asked CMake to find a package configuration file provided by
  "ArrayFire", but CMake did not find one.

  Could not find a package configuration file provided by "ArrayFire" with
  any of the following names:

    ArrayFireConfig.cmake
    arrayfire-config.cmake

  Add the installation prefix of "ArrayFire" to CMAKE_PREFIX_PATH or set
  "ArrayFire_DIR" to a directory containing one of the above files.  If
  "ArrayFire" provides a separate development package or SDK, be sure it has
  been installed.
</code></pre>
In this case you need to specify the full path to the folder which contains the <code>ArrayFireConfigure.cmake</code> script (found in the <code>share/ArrayFire/cmake</code> sub-directory of the installation folder). For example, if ArrayFire were installed to <code>/opt</code> this <code>cmake</code> command above would be replaced with the following:

<code>cmake -DArrayFire_DIR=/opt/share/ArrayFire/cmake .</code>

If all goes well, then CMake will generate the necessary files and the compilation will be successful and you will have a project running with ArrayFire in only a few lines of CMake code!
<h3>Reduce compilation time when linking against multiple backends</h3>
If you are building a project that will link against multiple ArrayFire backends, here is a pretty awesome trick to reduce compilation times significantly. We will take advantage of <a href="http://www.cmake.org/Wiki/CMake/Tutorials/Object_Library">CMake Object Libraries</a> to compile source code that is <em>common to all backends</em> into object files and then link them together with a <em>specific</em> ArrayFire backend. Here is a quick demonstration of this in action in a CMakeLists.txt file:
<pre><code>...
FILE(GLOB SOURCE "*.cpp")
ADD_LIBRARY(FOO_CORE OBJECT ${SOURCE})
ADD_EXECUTABLE(fooExe $&lt;TARGET_OBJECTS:FOO_CORE&gt;)
TARGET_LINK_LIBRARIES(fooExe ${ArrayFire_LIBRARIES} )
</code></pre>
The <code>FILE</code> operation isn’t suggested by the CMake folks, but it makes getting all of the source files in a directory very quick. The <code>ADD_LIBRARY</code> command with the optional <code>OBJECT</code> argument creates a library of object files called <code>FOO_CORE</code>. Lastly, the <code>ADD_EXECUTABLE</code> command with the <code>$&lt;TARGET_OBJECTS:FOO_CORE&gt;</code> argument uses the compiled objects to create the <code>fooEXE</code> executable.

This looks very similar to what we did before, but because the source files are pre-compiled, we can create several executables that link against different ArrayFire backends without re-compiling the source files. Consider the following <code>CMakeLists.txt</code> file:
<pre><code>...
FILE(GLOB SOURCE "*.cpp")
ADD_LIBRARY(FOO_CORE OBJECT ${SOURCE})
ADD_EXECUTABLE(fooExe-cuda $&lt;TARGET_OBJECTS:FOO_CORE&gt;)
TARGET_LINK_LIBRARIES(fooExe-cuda ${ArrayFire_CUDA_LIBRARIES} )
ADD_EXECUTABLE(fooExe-opencl $&lt;TARGET_OBJECTS:FOO_CORE&gt;)
TARGET_LINK_LIBRARIES(fooExe-opencl ${ArrayFire_OpenCL_LIBRARIES} )
</code></pre>
Here we create two executables, <code>fooExe-cuda</code> and <code>fooExe-opencl</code>, but only compile the <code>fooA.cpp</code> and <code>fooB.cpp</code> files once! If you were to link against all three backends, like the <a href="https://github.com/bkloppenborg/arrayfire-benchmark">ArrayFire benchmark suite</a> does, this simple trick could reduce your compilation times by about a f actor of three!
<h3>A fully worked example</h3>
Please see my <a href="https://github.com/bkloppenborg/arrayfire-cmake-example">ArrayFire CMake Project Example</a> for a fully worked example that efficiently compiles code and links it with all three of ArrayFire's backends.