introducing-cmake/usage-of-targets.tex

311 lines
8.8 KiB
TeX
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\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
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{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}
\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}
% --------------------------------------------------------------------