introducing-cmake/usage-of-targets.tex

311 lines
8.8 KiB
TeX
Raw Normal View History

2019-07-27 18:28:47 +02:00
\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 either corresponds to an executable or library, or is a custom
2019-07-27 18:28:47 +02:00
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}
2019-07-27 18:28:47 +02:00
\end{frame}
% --------------------------------------------------------------------
\begin{frame}[containsverbatim]
\frametitle{Custom Target and Dependencies}
Example with custom targets:
\vspace{1em}
\begin{codebox}{CMake}{}
add_custom_command(OUTPUT output.file
COMMAND generator
--in ${CMAKE_CURRENT_SOURCE_DIR}/input.file
--out output.file
DEPENDS input.file
COMMENT "This is an example invocation of a generator"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_custom_target(my-target
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/output.file)
\end{codebox}
\end{frame}
2019-07-27 18:28:47 +02:00
\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}
% --------------------------------------------------------------------