289 lines
8.2 KiB
TeX
289 lines
8.2 KiB
TeX
\subsection{The CMake processing steps}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{Projects and targets}
|
||
|
||
\begin{center}
|
||
\huge Defining what to build
|
||
\end{center}
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{The CMake Process}
|
||
|
||
\begin{columns}
|
||
\begin{column}{0.425\textwidth}
|
||
CMake has two main steps:
|
||
\begin{itemize}
|
||
\item Configure step.
|
||
\item Generate step.
|
||
\end{itemize}
|
||
\end{column}
|
||
|
||
\begin{column}{0.575\textwidth}
|
||
\begin{figure}
|
||
\centering
|
||
\includegraphics[width=.8\textwidth,keepaspectratio]{images/cmake-simple-flowchart.png}
|
||
\caption*{\tiny 2017 © Jeff Preshing \url{http://preshing.com/20170511/how-to-build-a-cmake-based-project/}}
|
||
\end{figure}
|
||
\end{column}
|
||
\end{columns}
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{$1^{st}$ step - Configuration}
|
||
|
||
In the \emph{configure} step CMake processes all the input given to
|
||
it, via \texttt{CMakeLists.txt}, and creates an internal
|
||
representation of the build to be performed. \texttt{CMakeCache.txt}
|
||
is generated at this step.
|
||
|
||
\vspace{1em}
|
||
|
||
The end of this step is expressed by \texttt{"Configuring done"}
|
||
message from CMake.
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{$2^{nd}$ step - Generation}
|
||
|
||
In the \emph{generate} step CMake will produce native build tool
|
||
files e.g. Visual Studio solution files, XCode project files, Ninja
|
||
build files etc.
|
||
|
||
\vspace{1em}
|
||
|
||
The end of this step is expressed by \texttt{"Generating done"}
|
||
message from CMake.
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\subsection{About targets}
|
||
|
||
\begin{frame}
|
||
\frametitle{Targets and dependency propagation}
|
||
|
||
\begin{center}
|
||
\huge Targets and their dependencies
|
||
\end{center}
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{Targets}
|
||
|
||
A CMake-based buildsystem is organized as a set of high-level
|
||
logical \emph{targets}.
|
||
|
||
\vspace{1em}
|
||
|
||
Each target corresponds to an executable or library, or is a custom
|
||
target containing custom commands.
|
||
|
||
\vspace{1em}
|
||
|
||
\begin{codebox}{CMake}{}
|
||
add_library(archive archive.cpp zip.cpp lzma.cpp)
|
||
add_executable(zipapp zipapp.cpp)
|
||
target_link_libraries(zipapp archive)
|
||
\end{codebox}
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{Transitive Usage Requirements}
|
||
|
||
The usage requirements of a target can transitively propagate to
|
||
dependents.
|
||
|
||
\vspace{1em}
|
||
|
||
The {\code{target\_link\_libraries()}} command has
|
||
\texttt{PRIVATE}, \texttt{INTERFACE}, and \texttt{PUBLIC} keywords
|
||
to control the propagation.
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{Transitive Usage Requirements}
|
||
|
||
A dependency should be specified in a use of
|
||
{\code{target\_link\_libraries()}} with the:
|
||
|
||
\begin{itemize}
|
||
\item \texttt{PRIVATE} keyword, if it is used \emph{only} by the
|
||
implementation of a library, and not in its public header files.
|
||
\item \texttt{PUBLIC} keyword, if a dependency is additionally
|
||
used in the header files of a library (e.g. any header
|
||
inclusion).
|
||
\item \texttt{INTERFACE} keyword, if is \emph{not} used by the
|
||
implementation of a library, but only by its public header
|
||
files.
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{Transitive Usage Requirements – Example}
|
||
|
||
\begin{codebox}{CMake}{}
|
||
add_library(liba a.cpp)
|
||
target_compile_definitions(liba INTERFACE USING_LIB_A)
|
||
|
||
add_library(libb b.cpp)
|
||
target_compile_definitions(libb INTERFACE USING_LIB_B)
|
||
|
||
add_library(libc c.cpp)
|
||
target_link_libraries(libc PUBLIC liba PRIVATE libb)
|
||
# libc is compiled with -DUSING_LIB_A and -DUSING_LIB_B
|
||
|
||
add_executable(app main.cpp)
|
||
target_link_libraries(app libc)
|
||
# app is compiled with -DUSING_LIB_A
|
||
\end{codebox}
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{Targets – Modifier functions}
|
||
|
||
You should use the following functions to control your targets:
|
||
|
||
\begin{itemize}
|
||
\item {\code{target\_include\_directories()}} – adds directories to
|
||
the include search path.
|
||
\item {\code{target\_compile\_definitions()}} – adds pre-processor
|
||
definitions.
|
||
\item {\code{target\_compile\_options()}} – adds compiler options
|
||
(\texttt{-Wall, /bigobj}).
|
||
\item {\code{target\_compile\_features()}} – adds necessary compiler
|
||
features (\texttt{cxx\_constexpr, cxx\_variadic\_templates}).
|
||
\item {\code{target\_sources()}} – adds more source files to the
|
||
target.
|
||
\item {\code{target\_link\_libraries()}} – add library dependency.
|
||
\end{itemize}
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\subsection{Preparing for packaging}
|
||
|
||
\begin{frame}
|
||
\frametitle{Locating packages}
|
||
|
||
\begin{center}
|
||
\huge Preparing the project for packaging
|
||
\end{center}
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{CMake packages}
|
||
Packages provide dependency information to CMake.
|
||
|
||
\vspace{1em}
|
||
|
||
Packages are found with the {\code{find\_package()}} command.
|
||
|
||
\vspace{1em}
|
||
|
||
The result of using {\code{find\_package()}} is either a set of
|
||
\texttt{IMPORTED} targets, or a set of variables
|
||
e.g. \texttt{<package>\_FOUND}, \texttt{<package>\_INCLUDE\_DIRS},
|
||
\texttt{<package>\_LIBRARIES}.
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{Packages – Example}
|
||
CMake provides direct support for two forms of packages:
|
||
\begin{itemize}
|
||
\item \texttt{CONFIG}-file packages (the new way).
|
||
\item Find-\texttt{MODULE} packages (prioritized for backwards-compat).
|
||
\end{itemize}
|
||
|
||
\begin{codebox}{CMake}{}
|
||
# CMake provides a Boost find-module
|
||
find_package(Boost 1.60.0 MODULE REQUIRED)
|
||
|
||
# Qt Project provides a Qt5 package config file.
|
||
find_package(Qt5Core 5.9.0 CONFIG REQUIRED
|
||
COMPONENTS Widgets)
|
||
|
||
# Use pkg-config via the LibXml2 find-module
|
||
find_package(LibXml2 MODULE REQUIRED)
|
||
\end{codebox}
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{Packages – Config-file}
|
||
|
||
A config-file package the recommended CMake package type.
|
||
|
||
\vspace{1em}
|
||
|
||
The config-file package consists of a set of files provided by
|
||
upstreams for downstreams to use.
|
||
|
||
\vspace{1em}
|
||
|
||
The Qt Project doesn't use CMake as their own build system, but
|
||
they do provide a config-file package for CMake users.
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{Packages -- Find-module}
|
||
|
||
A find-module is needed when the upstream is not built with CMake,
|
||
or is not CMake-aware enough to otherwise provide a package
|
||
configuration file.
|
||
|
||
\vspace{1em}
|
||
|
||
The find-module is a file with a set of rules for finding the
|
||
required pieces of a dependency, primarily header files and
|
||
libraries e.g. \texttt{FindBoost.cmake}.
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|
||
|
||
\begin{frame}[containsverbatim]
|
||
\frametitle{Packages – Config-file continued}
|
||
|
||
A config-file package can be used in two ways:
|
||
\begin{itemize}
|
||
\item to find a configured project that is already part of the
|
||
build.
|
||
\item to import an installed package.
|
||
\end{itemize}
|
||
|
||
\vspace{1em}
|
||
|
||
The process of creating a config-file package using CMake commands
|
||
({\code{configure\_package\_config\_file()}},
|
||
{\code{write\_basic\_package\_version\_file()}}, {\code{install()}},
|
||
{\code{export()}}) is quite verbose, and error prone.
|
||
\end{frame}
|
||
|
||
% --------------------------------------------------------------------
|