introducing-cmake/cmake-for-scripting.tex

216 lines
5.0 KiB
TeX
Raw Normal View History

2019-07-27 18:28:47 +02:00
\begin{frame}
\frametitle{CMake as a language}
\begin{center}
\huge CMake as a language: variables, iterating, and functions
\end{center}
\end{frame}
% --------------------------------------------------------------------
\subsection{Variables}
\begin{frame}[containsverbatim]
\frametitle{Setting variables}
\begin{codebox}{CMake}{}
set(local_variable "a string")
set(local_list "item1" "item2" "item3")
set(another_local_list "item1;item2;item3")
set_property(GLOBAL PROPERTY
A_GLOBAL_PROPERTY "${local_variable}")
# Not overridden if already in cache:
set(CACHE_VARIABLE ${local_list}
CACHE BOOL "Variable description")
# Always override, for our internal use:
set(INTERNAL_CACHE_VARIABLE ${local_list}
CACHE INTERNAL "Variable description")
\end{codebox}
\end{frame}
% --------------------------------------------------------------------
\begin{frame}[containsverbatim]
\frametitle{Scoping of variables}
\begin{codebox}{CMake}{}
# in folder A
set(local_variable "A")
add_subdirectory("B")
message(STATUS ${local_variable}) # -- prints A
# in folder B
set(local_variable "B")
message(STATUS ${local_variable}) # -- prints B
\end{codebox}
\texttt{add\_subdirectory} introduces a new scope.
\end{frame}
% --------------------------------------------------------------------
\begin{frame}[containsverbatim]
\frametitle{Scoping of variables -- propagating}
\begin{codebox}{CMake}{}
# in folder A
set(local_variable "A")
add_subdirectory("B")
message(STATUS ${local_variable}) # -- prints B
# in folder B
set(local_variable "B" PARENT_SCOPE)
message(STATUS ${local_variable}) # -- prints B
\end{codebox}
\texttt{add\_subdirectory} introduces a new scope.
\end{frame}
% --------------------------------------------------------------------
\begin{frame}[containsverbatim]
\frametitle{Scoping of variables -- caching}
\begin{codebox}{CMake}{}
message(STATUS ${VARIABLE}) # 1st run: nothing, 2nd run: B
add_subdirectory("C")
# in folder C
set(VARIABLE "A")
message(STATUS ${VARIABLE}) # 1st run: A, 2nd run: A
set(VARIABLE "B" CACHE STRING "A looney var")
message(STATUS ${VARIABLE}) # 1st run: B, 2nd run: A
\end{codebox}
Note how, the second time, setting a variable in the cache
is effectively a no-op, since it is already present there.
\end{frame}
% --------------------------------------------------------------------
\subsection{Conditionals and iterating}
\begin{frame}[containsverbatim]
\frametitle{Conditionals}
\texttt{if} has a lot of comparison operators. Read the docs!
\vspace{.5em}
\begin{codebox}{CMake}{}
# for historical reasons, unquoted variable
# names are always expanded:
if(var1 STREQUAL var2)
# if true...
elseif("var1" STREQUAL "var2") # ... but not if quoted!
# (never enters here)
else()
# otherwise
endif()
\end{codebox}
\end{frame}
% --------------------------------------------------------------------
\begin{frame}[containsverbatim]
\frametitle{Iterating on lists}
\begin{codebox}{CMake}{}
set(a_list "a" "b" "c")
foreach(var IN LISTS a_list)
message(STATUS ${var}) # prints on separate lines: a, b, c
endforeach()
foreach(var IN ITEMS "one" "two" "three" ${a_list})
message(STATUS ${var}) # prints on separate lines:
# one, two, three, a, b, c
endforeach()
# Note that quoted lists do not expand twice here:
foreach(var IN ITEMS "${a_list}")
message(STATUS ${var}) # prints on ONE line a;b;c
endforeach()
\end{codebox}
\end{frame}
% --------------------------------------------------------------------
\subsection{Functions}
\begin{frame}[containsverbatim]
\frametitle{Defining functions}
\begin{codebox}{CMake}{}
function(f a b c)
# here you can use a, b, and c.
# ARGN is a magic list that contains all elements
# provided after the third ("c").
endfunction(f)
# Invocation:
f("${var1}" "${var2}" "${var3}" "${var4}")
# This could lead to unexpected results with empty vars:
f(${var1} ${var2} ${var3} ${var4})
\end{codebox}
{\footnotesize Macros are like functions, but do not create a new
scope. Plus assigning values to parameters is strange. Short
rule: do \emph{not} use macros unless you know what you are
doing.}
\end{frame}
% --------------------------------------------------------------------
\begin{frame}[containsverbatim]
\frametitle{Returning values from functions}
There is no ``\texttt{return value}'' construct.
\vspace{.5em}
\begin{codebox}{CMake}{}
function(identity VAR a)
# We use VAR as the name of the return variable in the
# parent scope.
set("${VAR}" "${a}" PARENT_SCOPE)
endfunction(identity)
# Invocation:
set(a "value")
identity(a "${a}")
\end{codebox}
\end{frame}
% --------------------------------------------------------------------
\subsection{Invoking as a script}
\begin{frame}[containsverbatim]
\frametitle{Invoking a file as a script}
Why using CMake for scripting?
Well, it is more portable than bash across systems!
\vspace{.5em}
\begin{codebox}{Bash}{}
$ cmake -DVAR1="value1" ... -P script-name.cmake
\end{codebox}
\end{frame}
% --------------------------------------------------------------------