Writing CMakeLists Files
************************

This chapter will cover the basics of writing effective CMakeLists
files for your software. It will cover the basic commands and issues
you will need to handle most projects. While CMake can handle extremely complex
projects, for most projects you will find this chapter's contents will tell 
you all you need to know. CMake is driven by the CMakeLists.txt files written 
for a software project. The CMakeLists files determine everything from which
options to present to users, to which source files to compile. In
addition to discussing how to write a CMakeLists file, this chapter
will also cover how to make them robust and maintainable.


Editing CMakeLists Files
========================

CMakeLists files can be edited in almost any text editor. Some
editors, such as Notepad++, come with CMake syntax highlighting and
indentation support built-in. For editors such as Emacs or Vim, CMake
includes indentation and syntax highlighting modes. These can be found
in the ``Auxiliary`` directory of the source distribution, or downloaded from
the CMake `Download <www.cmake.org/download>`_ page.

Within any of the supported generators (Makefiles, Visual Studio, etc.), if
you edit a CMakeLists file and rebuild, there are rules that will automatically
invoke CMake to update the generated files (e.g. Makefiles or project
files) as required. This helps to assure that your generated files are
always in sync with your CMakeLists files.


.. index::
   single: languages

CMake Language
==============

The CMake language is composed of comments, commands, and variables.


.. index::
   single: comments
   single: escape character
   single: syntax of CMake

Comments
========

Comments start with ``#`` and run to the end of the line. See the
:manual:`cmake-language <cmake-language(7)>` manual for more details.

.. index::
   single: variables

Variables
=========

CMakeLists files use variables much like any programming language. CMake 
variable names are case sensitive and may only contain alphanumeric
characters and underscores.

A number of useful variables are automatically defined by CMake and are 
discussed in the  :manual:`cmake-variables <cmake-variables(7)>` manual. 
These variables begin with ``CMAKE_``. Avoid this naming convention (and, 
ideally, establish your own) for variables specific to your project.

All CMake variables are stored internally as strings although they may 
sometimes be interpreted as other types.

Use the :command:`set` command to set variable values. In its simplest form, 
the first argument to :command:`set` is the name of the variable and the 
rest of the arguments are the values. Multiple value arguments are packed 
into a semicolon-separated list and stored in the
variable as a string. For example:

.. code-block:: cmake

 set(Foo "")      # 1 quoted arg -> value is ""
 set(Foo a)       # 1 unquoted arg -> value is "a"
 set(Foo "a b c") # 1 quoted arg -> value is "a b c"
 set(Foo a b c)   # 3 unquoted args -> value is "a;b;c"
 
Variables may be referenced in command arguments using syntax
``${VAR}`` where ``VAR`` is the variable name. If the named variable
is not defined, the reference is replaced with an empty string;
otherwise it is replaced by the value of the variable. Replacement is
performed prior to the expansion of unquoted arguments, so variable
values containing semicolons are split into zero-or-more arguments in
place of the original unquoted argument. For example:

.. code-block:: cmake

 set(Foo a b c)    # 3 unquoted args -> value is "a;b;c"
 command(${Foo})   # unquoted arg replaced by a;b;c
                   # and expands to three arguments
 command("${Foo}") # quoted arg value is "a;b;c"
 set(Foo "")       # 1 quoted arg -> value is empty string
 command(${Foo})   # unquoted arg replaced by empty string
                   # and expands to zero arguments
 command("${Foo}") # quoted arg value is empty string

.. index::
   single: environment variables
   single: Windows ; registry values

System environment variables and Windows registry values can be
accessed directly in CMake. To access system environment variables,
use the syntax ``$ENV{VAR}``. CMake can also reference registry
entries in many commands using a syntax of the form
``[HKEY_CURRENT_USER\\Software\\path1\\path2;key]``, where the paths
are built from the registry tree and key.

.. index::
   single: variable scope

Variable Scope
--------------

Variables in CMake have a scope that is a little different from most
languages. When you set a variable, it is visible to the current
CMakeLists file or function and any subdirectory's CMakeLists files,
any functions or macros that are invoked, and any files that are
included using the :command:`include` command. When a new subdirectory
is processed (or a function called), a new variable scope is created and
initialized with the current value of all variables in the calling
scope. Any new variables created in the child scope, or changes made
to existing variables, will not impact the parent scope. Consider the
following example:

.. code-block:: cmake

 function(foo)
   message(${test}) # test is 1 here
   set(test 2)
   message(${test}) # test is 2 here, but only in this scope
 endfunction()

 set(test 1)
 foo()
 message(${test}) # test will still be 1 here

In some cases, you might want a function or subdirectory to set a
variable in its parent's scope. There is a way for CMake to return a
value from a function, and it can be done by using the
``PARENT_SCOPE`` option with the :command:`set` command. We can modify
the prior example so that the function ``foo`` changes the value of test
in its parent's scope as follows:

.. code-block:: cmake

 function(foo)
   message(${test}) # test is 1 here
   set(test 2 PARENT_SCOPE)
   message(${test}) # test still 1 in this scope
 endfunction()

 set(test 1)
 foo()
 message(${test}) # test will now be 2 here

Variables in CMake are defined in the order of the execution of 
:command:`set` commands.

Consider the following example:

.. code-block:: cmake

 # FOO is undefined

 set(FOO 1)
 # FOO is now set to 1

 set(FOO 0)
 # FOO is now set to 0

To understand the scope of variables, consider this example:

.. code-block:: cmake

 set(foo 1)

 # process the dir1 subdirectory
 add_subdirectory(dir1)

 # include and process the commands in file1.cmake
 include(file1.cmake)

 set(bar 2)
 # process the dir2 subdirectory
 add_subdirectory(dir2)

 # include and process the commands in file2.cmake
 include(file2.cmake)

In this example, because the variable ``foo`` is defined at the
beginning, it will be defined while processing both dir1 and dir2. In
contrast, ``bar`` will only be defined when processing dir2. Likewise,
``foo`` will be defined when processing both file1.cmake and
file2.cmake, whereas ``bar`` will only be defined while processing
file2.cmake.

Commands
========

A command consists of the command name, opening parenthesis, whitespace
separated arguments, and a closing parenthesis. Each command is evaluated in
the order that it appears in the CMakeLists file. See the
:manual:`cmake-commands <cmake-commands(7)>` manual for a full list of
CMake commands.

.. index::
   single: case sensitivity

CMake is no longer case sensitive to command names, so where you see
``command``, you could use ``COMMAND`` or ``Command`` instead. It is considered
best practice to use lowercase commands.  All whitespace (spaces, line feeds,
tabs) is ignored except to separate arguments. Therefore, commands may span
multiple lines as long as the command name and the opening parenthesis are on
the same line.

.. index::
   single: quoting

CMake command arguments are space separated and case sensitive. Command
arguments may be either quoted or unquoted.  A quoted argument starts and ends
in a double quote (") and always represents exactly one argument. Any double
quotes contained inside the value must be escaped with a backslash. Consider
using bracket arguments for arguments that require escaping, see the
:manual:`cmake-language <cmake-language(7)>` manual. An unquoted argument
starts in any character other than a double quote (later double quotes are
literal) and is automatically expanded into zero-or-more arguments by
separating on semicolons within the value.  For example:

.. code-block:: cmake

 command("")          # 1 quoted argument
 command("a b c")     # 1 quoted argument
 command("a;b;c")     # 1 quoted argument
 command("a" "b" "c") # 3 quoted arguments
 command(a b c)       # 3 unquoted arguments
 command(a;b;c)       # 1 unquoted argument expands to 3

Basic Commands
--------------

As we saw earlier in the, the :command:`set` and :command:`unset` commands
explicitly set or unset variables. The :command:`string`, :command:`list`, and
:command:`separate_arguments` commands offer basic manipulation of strings and lists.

The :command:`add_executable` and :command:`add_library` commands are the main
commands for defining the executables and libraries to build, and
which source files comprise them. For Visual Studio projects, the
source files will show up in the IDE as usual, but any header files
the project uses will not be. To have the header files show up, simply
add them to the list of source files for the executable or library;
this can be done for all generators. Any generators that do not use
the header files directly (such as Makefile based generators) will
simply ignore them.

.. index::
   single: conditional statements
   single: flow control
   single: function
   single: looping constructs
   single: procedure definitions
   
Flow Control
============

The CMake language provides three flow control constructs to help organize 
your CMakeLists files and keep them maintainable. 

* Conditional statements (e.g. :command:`if`)
* Looping constructs (e.g. :command:`foreach` and :command:`while`)
* Procedure definitions (e.g. :command:`macro` and :command:`function`)

Conditional Statements
----------------------

First we will consider the :command:`if` command. In many ways, the
:command:`if` command in CMake is just like the :command:`if` command in any
other language. It evaluates its expression and uses it to execute the code
in its body or optionally the code in the :command:`else` clause. For
example:

.. code-block:: cmake

 if(FOO)
   # do something here
 else()
   # do something else
 endif()

CMake also supports :command:`elseif` to help sequentially test for multiple
conditions. For example:

.. code-block:: cmake

 if(MSVC80)
   # do something here
 elseif(MSVC90)
   # do something else
 elseif(APPLE)
   # do something else
 endif()

The :command:`if` command documents the many conditions it can test.

Looping Constructs
------------------

The :command:`foreach` and :command:`while` commands allow you to handle
repetitive tasks that occur in sequence. The :command:`break` command breaks
out of a :command:`foreach` or :command:`while` loop before it would normally
end. 

The :command:`foreach` command enables you to execute a group
of CMake commands repeatedly on the members of a list. Consider the
following example adapted from VTK

.. index::
   single: command ; add_test

.. code-block:: cmake

 foreach(tfile
         TestAnisotropicDiffusion2D
         TestButterworthLowPass
         TestButterworthHighPass
         TestCityBlockDistance
         TestConvolve
         )
   add_test(${tfile}-image ${VTK_EXECUTABLE}
     ${VTK_SOURCE_DIR}/Tests/rtImageTest.tcl
     ${VTK_SOURCE_DIR}/Tests/${tfile}.tcl
     -D ${VTK_DATA_ROOT}
     -V Baseline/Imaging/${tfile}.png
     -A ${VTK_SOURCE_DIR}/Wrapping/Tcl
     )
 endforeach()

The first argument of the :command:`foreach` command is the name of the
variable that will take on a different value with each iteration of
the loop; the remaining arguments are the list of values over which to
loop. In this example, the body of the :command:`foreach` loop is just one
CMake command, :command:`add_test`. In the body of the :command:`foreach`, each
time the loop variable (``tfile`` in this example) is referenced will
be replaced with the current value from the list. In the first
iteration, occurrences of ``${tfile}`` will be replaced with
``TestAnisotropicDiffusion2D``. In the next iteration, ``${tfile}``
will be replaced with ``TestButterworthLowPass``. The :command:`foreach` loop
will continue to loop until all of the arguments have been processed.

It is worth mentioning that :command:`foreach` loops can be nested, and that
the loop variable is replaced prior to any other variable
expansion. This means that in the body of a :command:`foreach` loop, you can
construct variable names using the loop variable. In the code below,
the loop variable ``tfile`` is expanded, and then concatenated with
``_TEST_RESULT``. The new variable name is then expanded and tested to
see if it matches ``FAILED``.

.. code-block:: cmake

 if(${${tfile}}_TEST_RESULT} MATCHES FAILED)
   message("Test ${tfile} failed.")
 endif()

The :command:`while` command provides looping based on a test condition. The
format for the test expression in the :command:`while` command is the same as
it is for the :command:`if` command, as described earlier. Consider the
following example, which is used by CTest. Note that CTest updates the value of
``CTEST_ELAPSED_TIME`` internally.

.. code-block:: cmake

 #####################################################
 # run paraview and ctest test dashboards for 6 hours
 #
 while(${CTEST_ELAPSED_TIME} LESS 36000)
   set(START_TIME ${CTEST_ELAPSED_TIME})
   ctest_run_script("dash1_ParaView_vs71continuous.cmake")
   ctest_run_script("dash1_cmake_vs71continuous.cmake")
 endwhile()

Procedure Definitions
---------------------

The :command:`macro` and :command:`function` commands support repetitive tasks 
that may be scattered throughout your CMakeLists files. Once a macro or 
function is defined, it can be used by any CMakeLists files processed after 
its definition.

A function in CMake is very much like a function in C or C++. You can
pass arguments into it, and they become variables within the
function. Likewise, some standard variables such as ``ARGC``,
``ARGV``, ``ARGN``, and ``ARGV0``, ``ARGV1``, etc. are
defined. Function calls have a dynamic scope.  Within a function you
are in a new variable scope; this is like how you drop into a
subdirectory using the :command:`add_subdirectory` command and are in a new
variable scope. All the variables that were defined when the function
was called remain defined, but any changes to variables or new
variables only exist within the function. When the function returns,
those variables will go away. Put more simply: when you invoke a
function, a new variable scope is pushed; when it returns, that
variable scope is popped.

The :command:`function` command defines a new function.  The first argument
is the name of the function to define; all additional arguments are
formal parameters to the function.

.. code-block:: cmake

 function(DetermineTime _time)
   # pass the result up to whatever invoked this
   set(${_time} "1:23:45" PARENT_SCOPE)
 endfunction()

 # now use the function we just defined
 DetermineTime(current_time)

 if(DEFINED current_time)
   message(STATUS "The time is now: ${current_time}")
 endif()

Note that in this example, ``_time`` is used to pass the name of the
return variable. The :command:`set` command is invoked with the value of
``_time``, which will be ``current_time``. Finally, the :command:`set`
command uses the ``PARENT_SCOPE`` option to set the variable in the
caller's scope instead of the local scope.

.. index::
  single: command ; macro
  single: macros

Macros are defined and called in the same manner as functions. The
main differences are that a macro does not push and pop a new variable
scope, and that the arguments to a macro are not treated as variables
but as strings replaced prior to execution. This is very much like the
differences between a macro and a function in C or C++. The first
argument is the name of the macro to create; all additional arguments
are formal parameters to the macro.

.. code-block:: cmake

 # define a simple macro
 macro(assert TEST COMMENT)
   if(NOT ${TEST})
     message("Assertion failed: ${COMMENT}")
   endif()
 endmacro()

 # use the macro
 find_library(FOO_LIB foo /usr/local/lib)
 assert(${FOO_LIB} "Unable to find library foo")

The simple example above creates a macro called ``assert``. The macro
is defined into two arguments; the first is a value to test and the
second is a comment to print out if the test fails. The body of the
macro is a simple :command:`if` command with a :command:`message` command
inside of it. The macro body ends when the :command:`endmacro` command is
found. The macro can be invoked simply by using its name as if it were a
command. In the above example, if ``FOO_LIB`` was not found then a
message would be displayed indicating the error condition.

.. index::
   single: variable argument list

The :command:`macro` command also supports defining macros that take variable
argument lists. This can be useful if you want to define a macro that
has optional arguments or multiple signatures. Variable arguments can
be referenced using ``ARGC`` and ``ARGV0``, ``ARGV1``, etc., instead
of the formal parameters. ``ARGV0`` represents the first argument to
the macro; ``ARGV1`` represents the next, and so forth. You can also
use a mixture of formal arguments and variable arguments, as shown in
the example below.

.. code-block:: cmake

 # define a macro that takes at least two arguments
 # (the formal arguments) plus an optional third argument
 macro(assert TEST COMMENT)
   if(NOT ${TEST})
     message("Assertion failed: ${COMMENT}")

     # if called with three arguments then also write the
     # message to a file specified as the third argument
     if(${ARGC} MATCHES 3)
       file(APPEND ${ARGV2} "Assertion failed: ${COMMENT}")
     endif()

   endif()
 endmacro()

 # use the macro
 find_library(FOO_LIB foo /usr/local/lib)
 assert(${FOO_LIB} "Unable to find library foo")

In this example, the two required arguments are ``TEST`` and
``COMMENT``. These required arguments can be referenced by name, as
they are in this example, or by referencing ``ARGV0`` and
``ARGV1``. If you want to process the arguments as a list, use the
``ARGV`` and ``ARGN`` variables. ``ARGV`` (as opposed to ``ARGV0``,
``ARGV1``, etc) is a list of all the arguments to the macro, while
``ARGN`` is a list of all the arguments after the formal
arguments. Inside your macro, you can use the :command:`foreach` command to
iterate over ``ARGV`` or ``ARGN`` as desired.

The :command:`return` command returns from a function, directory or file. Note 
that a macro, unlike a function, is expanded in place and therefore cannot 
handle :command:`return`.

.. index::
   single: regular expressions

Regular Expressions
===================

A few CMake commands, such as :command:`if` and :command:`string`, make use of
regular expressions or can take a regular expression as an
argument. In its simplest form, a regular expression is a sequence of
characters used to search for exact character matches. However, many
times the exact sequence to be found is unknown, or only a match at
the beginning or end of a string is desired. Since there are several
different conventions for specifying regular expressions, CMake's
standard is described in the :command:`string` command documentation. The
description is based on the open source regular expression class from Texas
Instruments, which is used by CMake for parsing regular expressions.

Advanced Commands
=================

.. index::
   single: dependencies

There are a few commands that can be very useful, but are not
typically used in writing CMakeLists files. This section will discuss
a few of these commands and when they are useful.

First, consider the :command:`add_dependencies` command which creates a 
dependency between two targets. CMake automatically creates dependencies 
between targets when it can determine them. For example, CMake will 
automatically create a dependency for an executable target that depends on a 
library target. The :command:`add_dependencies` command command is typically 
used to specify inter-target dependencies between targets where at least one 
of the targets is a custom target (see :ref:`add_custom_command` section).

.. index::
   single: regular expressions

The :command:`include_regular_expression` command also relates to
dependencies. This command controls the regular expression that is
used for tracing source code dependencies. By default, CMake will
trace all the dependencies for a source file including system files
such as ``stdio.h``. If you specify a regular expression with the
:command:`include_regular_expression` command, that regular expression will
be used to limit which include files are processed. For example; if
your software project's include files all started with the prefix foo
(e.g. ``fooMain.c fooStruct.h``, etc), you could specify a regular
expression of ``^foo.*$`` to limit the dependency checking to just the
files of your project.
