-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathCMake_Cheatsheet.tex
345 lines (229 loc) · 13.9 KB
/
CMake_Cheatsheet.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% CMake Cheatsheet
% By Morten Nobel-Jørgensen ([email protected]) (01/09/2017)
%
% MIT License
%
%
%
% LaTeX Template
% Version 1.0 (12/12/15)
%
% This template has been downloaded from:
% http://www.LaTeXTemplates.com
%
% Original author:
% Michael Müller (https://github.com/cmichi/latex-template-collection) with
% extensive modifications by Vel ([email protected])
%
% License:
% The MIT License (see included LICENSE file)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%----------------------------------------------------------------------------------------
% PACKAGES AND OTHER DOCUMENT CONFIGURATIONS
%----------------------------------------------------------------------------------------
\documentclass[11pt,a4paper,landscape]{scrartcl} % 11pt font size
\usepackage[utf8]{inputenc} % Required for inputting international characters
\usepackage[T1]{fontenc} % Output font encoding for international characters
\usepackage[margin=30pt, landscape]{geometry} % Page margins and orientation
\usepackage{graphicx} % Required for including images
\usepackage{listings}
\usepackage{multicol}
\usepackage{color} % Required for color customization
\definecolor{mygray}{gray}{.75} % Custom color
\usepackage{url} % Required for the \url command to easily display URLs
\usepackage{xcolor}
\usepackage{listings}
\usepackage{xparse}
\usepackage[ % This block contains information used to annotate the PDF
colorlinks=false,
pdftitle={CMake Cheatsheet},
pdfauthor={Morten Nobel-Jørgensen},
pdfsubject={A gentle introduction to CMake},
pdfkeywords={Cross-platform development, Open Source, CMake}
]{hyperref}
\lstset{frame=lrbt,xleftmargin=\fboxsep,xrightmargin=-\fboxsep}
\setlength{\unitlength}{1mm} % Set the length that numerical units are measured in
\setlength{\parindent}{0pt} % Stop paragraph indentation
\renewcommand{\dots}{\ \dotfill{}\ } % Fills in the right amount of dots
\newcommand{\command}[2]{#1~\dotfill{}~#2\\} % Custom command for adding a shorcut
\newcommand{\sectiontitle}[1]{\paragraph{#1} \ \\} % Custom command for subsection titles
\NewDocumentCommand{\codeword}{v}{%
\texttt{#1}%
}
%----------------------------------------------------------------------------------------
\begin{document}
%----------------------------------------------------------------------------------------
% TITLE SECTION
%----------------------------------------------------------------------------------------
\section*{CMake Cheatsheet -- A gentle introduction to CMake} % Title
%----------------------------------------------------------------------------------------
% FIRST COLUMN SPECIFICATION
%----------------------------------------------------------------------------------------
\setlength{\columnsep}{1.5cm}
\begin{multicols}{2}
%----------------------------------------------------------------------------------------
% HEADING ONE
%----------------------------------------------------------------------------------------
This cheatsheet will give you an idea how CMake works and how it can be used to configure software projects.
The document and the CMake examples are available at \url{https://github.com/mortennobel/CMake-Cheatsheet}.
\sectiontitle{CMake - Creating a simple C++ project}
CMake is a tool for configuring how a cross-platform source code project should be built on a given platform.
A small project could be organized like this:
\vspace{\baselineskip} % Whitespace before the next section
\noindent\fbox{%
\parbox{\columnwidth}{%
CMakeLists.txt \\
src/main.cpp \\
src/foo.cpp\\
src/foo.hpp
}%
}
\vspace{\baselineskip} % Whitespace before the next section
This project contains two source files located in the src directory and one header file in the include directory in the same directory.
When running CMake on this project you are asked to for a binary directory. It is best practice to create a new directory since this directory will contain all files related to building the project. If something goes wrong, you can delete the folder and start over.
Running CMake will not create the final executable, but instead, it will generate project files for Visual Studio, XCode or makefiles. Use these tools to build the project.
\sectiontitle{Understanding CMakeLists.txt}
Creating project files using CMake requires a \codeword{CMakeLists.txt} file, which describes how the project is structured and how it should be built.
For example 1 the file looks like this:
\lstinputlisting[language=bash]{examples/example1/CMakeLists.txt}
First, the minimum version of CMake is defined. Then the project name is defined using the command \codeword{project()}. A project can contain multiple targets (either executables or libraries). This project defines a single executable target called \codeword{Hello}, which is created by compiling and linking the two source files \codeword{main.cpp} and \codeword{foo.cpp} files.
When the two source files are compiled the compiler will search for the header file \codeword{foo.h} since both source files depend on this using a \codeword{#include "foo.hpp"}. Since the file is located in the same located as the source file, the compiler will not have any problems finding the file.
\sectiontitle{The CMake Scripting Language}
The CMakeLists.txt describes the build process using a command based programming language. The commands are case insensitive and take a list of arguments.
\begin{lstlisting}[language=bash]
# This is a comment.
COMMAND( arguments go here )
ANOTHER_COMMAND() # this command has no arguments
YET_ANOTHER_COMMAND( these
arguments are spread # another comment
over several lines )
\end{lstlisting}
CMake script also has variables. Variables can either be defined by CMake or can be defined in the CMake script. The command \codeword{set(parameter value)} set a given parameter to a value. The command \codeword{message(value)} print out the value to the console. To get the value of a variable use \codeword{${varname}}, which substitutes the variable name with its value.
\lstinputlisting[language=bash]{examples/example2/CMakeLists.txt}
All variable values are a text string. Text strings can be evaluated as boolean expressions (e.g. when used in \codeword{IF()} and \codeword{WHILE()}). The values "FALSE", "OFF", "NO", or any string ending in "-NOTFOUND" evaluates be false - everything else to true.
Text strings can represent multiple values as a list by separating entities using a semicolon.
\lstinputlisting[language=bash]{examples/example3/CMakeLists.txt}
Lists can be iterated using the command \codeword{FOREACH (var val)}:
\lstinputlisting[language=bash]{examples/example4/CMakeLists.txt}
\sectiontitle{Exposing compile options}
CMake allows the end user (who runs CMake) to modify some values of some variables. This is usually used to defined properties of the build such as locations of files, machine architecture, and string values.
The command \codeword{set(<variable> <value> CACHE <type> <docstring>)} set the variable to the default value - but allows the value to be changed by the cmake user when configuring the build. The type should be one of the following:
\begin{itemize}
\item FILEPATH = File chooser dialog.
\item PATH = Directory chooser dialog.
\item STRING = Arbitrary string.
\item BOOL = Boolean ON/OFF checkbox.
\item INTERNAL = No GUI entry (used for persistent variables).
\end{itemize}
In the following example, the user can configure if "Hello" or an alternative string should be printed based on the configuration variables hello and other\_msg.
\lstinputlisting[language=bash]{examples/example5/CMakeLists.txt}
During configuration of the project, the CMake user gets prompted with the exposed options.
\includegraphics[width=\columnwidth]{variable-options}
The values that the CMake user enters will be saved in the text file \codeword{CMakeCache.txt} as key-value pairs:
\begin{lstlisting}[language=bash]
// ....
//Print hello
hello:BOOL=OFF
//Not hello value
other_msg:STRING=Guten tag
// ....
\end{lstlisting}
\sectiontitle{Complex projects}
Some project both contains multiple executables and multiple libraries. For instance when having both unit tests and programs. It is common to separate these subprojects into subfolders. Example:
\vspace{\baselineskip} % Whitespace before the next section
\noindent\fbox{%
\parbox{\columnwidth}{%
CMakeLists.txt \\
somelib/CMakeLists.txt \\
somelib/foo.hpp \\
somelib/foo.cpp \\
someexe/CMakeLists.txt\\
someexe/main.cpp
}%
}
\vspace{\baselineskip} % Whitespace before the next section
The main \codeword{CMakeLists.txt} contains the basic project settings but then includes the subprojects:
\lstinputlisting[language=bash]{examples/example6/CMakeLists.txt}
First the library Foo is compiled from the source in the \codeword{somelib} directory:
\lstinputlisting[language=bash]{examples/example6/somelib/CMakeLists.txt}
Finally, the executable Hello is compiled and linked to the Foo library - note that the target name is used here - not the actual path. Since the main.cpp references to header file Foo.hpp the somelib directory is added to the header search path:
\lstinputlisting[language=bash]{examples/example6/someexe/CMakeLists.txt}
\sectiontitle{Searching for source files}
Use the \codeword{find(GLOB varname patterns)} to automatically search for files within a directory given one or more search patterns. Note that in the example below, both source files and header files are added to the project. This is not needed for compiling the project, but it is convenient when using an IDE since this also adds the header files to the project.
\lstinputlisting[language=bash]{examples/example6-find/CMakeLists.txt}
\sectiontitle{Runtime resources}
Often runtime resources (such as DLLs, game-assets and text files) are read relative to the executable. One solution is to copy resources into the same directory as the executable. Example:
\vspace{\baselineskip} % Whitespace before the next section
\noindent\fbox{%
\parbox{\columnwidth}{%
CMakeLists.txt \\
someexe/main.cpp \\
someexe/res.txt
}%
}
In this project, the source files assume that the resource is located in the same directory as the executable:
\lstinputlisting[language=c++]{examples/example7/someexe/main.cpp}
The CMakeLists.txt make sure to copy the file.
\lstinputlisting[language=bash]{examples/example7/CMakeLists.txt}
Note: One problem with this approach is if you modify the original resources, then you need to run CMake again.
\sectiontitle{External libraries}
External libraries basically come in two flavors; dynamically linked libraries (DLLs) which are linked with the binary at runtime and statical linked libraries which are linked at compile time.
Static libraries have the most simple setup. To use one, the compiler needs to know the location of where to locate the header files and the linker need to know the location of the actual library. Unless the external libraries are distributed along with the project it is usually not possible to know their location - for this reason, it is common to use cached variables, where the CMake user can change the location. Static libraries have the file ending .lib on Windows and .a on most other platforms.
\lstinputlisting[language=bash]{examples/example8/CMakeLists.txt}
Dynamically linked libraries work similar to statical linked libraries. On Windows, it is still needed to link to a library at compile time, but the actual linking to the DLL happens at compile time. The executable file needs to be able to find the DLL file in the runtime linkers search path. If the DLL is not a system library, an easy solution is to copy the DLL next to the executable. Working with DLL often requires platform specific actions, which CMake support using the built-in variables \codeword{WIN32}, \codeword{APPLE}, \codeword{UNIX}.
\lstinputlisting[language=bash]{examples/example9/CMakeLists.txt}
\sectiontitle{Automatically locating libraries}
CMake also contains a feature to automatically find libraries (based on a number of suggested locations) using the command \codeword{find_package()}. However, this feature works best on macOS and Linux.
\url{https://cmake.org/Wiki/CMake:How_To_Find_Libraries}.
\sectiontitle{C++ version}
The C++ version can be set using the commands:
\begin{lstlisting}[language=bash]
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
\end{lstlisting}
\sectiontitle{Defining preprocessor symbols}
Use the \codeword{add_definitions()} to add preprocessor symbols to the project.
\begin{lstlisting}[language=bash]
# ...
add_definitions(-DFOO=\"XXX\")
add_definitions(-DBAR)
\end{lstlisting}
This will create the symbols \codeword{FOO} and \codeword{BAR}, which can be used in the source code:
\begin{lstlisting}[language=c++]
#include <iostream>
using namespace std;
int main(){
#ifdef BAR
cout << "Bar"<< endl;
#endif
cout << "Hello world "<<FOO << endl;
return 0;
}
\end{lstlisting}
\vspace{\baselineskip} % Whitespace before the next section
%----------------------------------------------------------------------------------------
% LINKS AND INFORMATION
%----------------------------------------------------------------------------------------
\sectiontitle{Links and information}
\url{https://cmake.org/Wiki/CMake/Language_Syntax}
\url{https://cmake.org/cmake/help/v3.0/command/set.html}
%----------------------------------------------------------------------------------------
% FOOTNOTE
%----------------------------------------------------------------------------------------
\vspace{\baselineskip}
\linethickness{0.5mm} % Thickness of the footer line
{\color{mygray}\line(1,0){30}} % Print the line with a custom color
\footnotesize{
Created by Morten Nobel-Jørgensen, [email protected], ITU, 2017\\
Released under the MIT license. \\
Latex template by John Smith, 2015\\
\url{http://johnsmith.com/}\\
Released under the MIT license.
}
%----------------------------------------------------------------------------------------
\end{multicols}
%----------------------------------------------------------------------------------------
\end{document}