-
Notifications
You must be signed in to change notification settings - Fork 128
/
CMake-tutorial.tex
2794 lines (2555 loc) · 99.6 KB
/
CMake-tutorial.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
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
%
% (c) 2011-2016 - Eric NOULARD <[email protected]>
% This is a CMake (https://cmake.org) tutorial
% the material is open and may be found on github:
% https://github.com/TheErk/CMake-tutorial
%
% This set of slides are licensed with
% the creative commons CC-BY-SA license.
%
% For printed version uncomment trans
% If you want nice PDF presentation
% you may use Impress!ve: http://impressive.sourceforge.net/
% you use https://github.com/jberger/MakeBeamerInfo in order
% to create the impress!ve script more easily
%
\documentclass[compress,slidestop,table,usepdftitle=false
% trans
]
{beamer}
\usepackage{iwona}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage{xcolor}
\definecolor{cmakeblue}{RGB}{84,84,216}
\definecolor{cmakered}{RGB}{235,69,69}
\definecolor{cmakegreen}{RGB}{0,219,0}
\colorlet{cmaketimec}{green}
\colorlet{buildtimec}{red}
\colorlet{installtimec}{black}
\colorlet{cpacktimec}{blue}
\usepackage{graphicx}
\graphicspath{{figures/}{images/}}
\DeclareGraphicsExtensions{.eps,.png,.pdf,.eps,.jpg}
% Uncomment this for handout mode
\mode<handout>{
\usepackage{pgfpages}
\pgfpagesuselayout{2 on 1}[a4paper,border shrink=5mm]
\setbeamercolor{background canvas}{bg=black!5}
}
\mode<presentation>{
%\setbeamercovered{transparent}
\setbeamercovered{invisible}
% progressbar is a nice beamer theme by Sylvain BOUVERET
% http://recherche.noiraudes.net/fr/LaTeX.php
\usetheme{progressbar}
\progressbaroptions{
%headline=sections,
imagename=figures/CMake-logo-triangle-small.png,
titlepage=normal,
frametitle=picture-section
}
}
\usepackage{fancyvrb}
\VerbatimFootnotes
\usepackage{ulem}
\usepackage{multirow}
\usepackage{multicol}
\usepackage{tikz}
\usetikzlibrary{arrows,shapes}
\usetikzlibrary{patterns,snakes,automata,topaths}
\usetikzlibrary{matrix,chains}
\usetikzlibrary{shadows}
\usetikzlibrary{positioning}
\usetikzlibrary{shadings}
\usetikzlibrary{calc}
\tikzstyle{na} = [baseline=-.5ex]
\tikzstyle{every picture}+=[remember picture]
%\usepackage[underline=true,rounded corners=false]{pgf-umlsd}
\usepackage[formats]{listings}
\input{lstdefine-CMake}
\lstset{escapeinside={(*@}{@*)}}
\lstset{language=CMake,
basicstyle=\normalsize,
keywordstyle=\bfseries\textcolor{blue},
identifierstyle=\sffamily,
commentstyle=\itshape\textcolor{olive},
stringstyle=\ttfamily,
extendedchars=false,
showstringspaces=true,
numbers=left,
numberstyle=\tiny,
stepnumber=1,
frame=single,
tabsize=3
}
\hypersetup{
colorlinks=true,
bookmarks=true,
bookmarksopen=true,
bookmarksopenlevel=4,
pdfpagemode=UseOutlines,
pdftitle={CMake [and friends] tutorial},
pdfauthor={Eric NOULARD},
pdfsubject={CMake},
pdfkeywords={CMake, CPack, CTest, CDash, build systems, autotools, SCons}
}
\setcounter{tocdepth}{5}% Show up to level 4 (\paragraph) in ToC (and bookmarks)
\setcounter{secnumdepth}{5}% Show up to level 4 (\paragraph) in ToC (and bookmarks)
%
% Backslash '\'
\def\bs{\texttt{\char '134}}
\newcommand{\msgsrc}[1]{\lstinline[language=Java]!#1!}
%\newcommand{\fname}[1]{\verb+#1+}
\newcommand{\fname}[1]{\texttt{#1}}
\usepackage{xspace}
\newcommand{\cm}{CMake\xpspace}
\newcommand{\cp}{CPack\xpspace}
\newcommand{\ct}{CTest\xpspace}
\newcommand{\cd}{CDash\xpspace}
\AtBeginSubsection[]
{
\begin{frame}
\frametitle{Outline}
\tableofcontents[currentsection,currentsubsection]
\end{frame}
}
\AtBeginSection[]
{
\begin{frame}
\frametitle{Outline}
\tableofcontents[currentsection]
\end{frame}
}
\begin{document}
\pgfdeclareimage[interpolate=true,height=0.6cm]{CMakeLogo}{figures/CMake-logo-small}
\pgfdeclarelayer{background2}
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background2,background,main,foreground}
% If you tailor the presentation to your need
% you can perfectly put your name on it.
\title{CMake tutorial}
\subtitle{and its friends CPack, CTest and CDash}
\author[Eric NOULARD - \url{[email protected]}]{Eric NOULARD - \url{[email protected]}\\
\includegraphics[width=5cm]{figures/CMake-logo-small}\\
\url{https://cmake.org}}
\date{Compiled on \today}
\subject{Slides for CMake, CPack, CTest, CDash presentation. In english.}
\keywords{CMake, CPack, CTest, CDash, build systems, autotools, SCons}
\pdfbookmark[0]{CMake tutorial}{cmaketut}
\begin{frame}
\titlepage
\begin{center}
{\tiny
This presentation is licensed
\includegraphics[width=1.2cm]{figures/by-sa}
\url{http://creativecommons.org/licenses/by-sa/3.0/us/}
\url{https://github.com/TheErk/CMake-tutorial}
Initially given by Eric Noulard for Toulibre on February, $8^{th}$ 2012.
}
\end{center}
\end{frame}
\begin{frame}
\frametitle{Thanks to\ldots}
\begin{itemize}
\item \textcolor{cmakeblue}{Kitware for making a really nice set of tools and making them open-source}
\item \textcolor{cmakered}{the CMake mailing list for its friendliness and its more than valuable source of information}
\item \textcolor{cmakegreen}{CMake developers for their tolerance when I break the dashboard or mess-up
with the Git workflow,}
\item \textcolor{cmakeblue}{CPack users for their patience when things don't work as they \sout{should} expect}
\item \textcolor{cmakeblue}{Alan},
\textcolor{cmakered}{Alex},
\textcolor{cmakegreen}{Bill},
\textcolor{cmakeblue}{Brad},
\textcolor{cmakered}{Clint},
\textcolor{cmakegreen}{David},
\textcolor{cmakeblue}{Eike},
\textcolor{cmakered}{Julien},
\textcolor{cmakegreen}{Mathieu},
\textcolor{cmakeblue}{Michael \& Michael},
\textcolor{cmakered}{Stephen},
\textcolor{cmakegreen}{Domen},
\textcolor{cmakeblue}{and} \textcolor{cmakered}{many} \textcolor{cmakegreen}{more}\ldots
\item \textcolor{cmakegreen}{My son Louis for the nice CPack 3D logo done with Blender.}
\item \textcolor{cmakered}{and...Toulibre for initially hosting this presention in Toulouse, France.}
\end{itemize}
\end{frame}
\part{CMake}
\section{Overview}
\begin{frame}
\frametitle{And thanks to contributors as well\ldots}
{%\setbeamerfont{block title}{size=\fontsize{6pt}{9.0}}
\begin{block}{History}
\fontsize{9pt}{11}\selectfont
This presentation was initially made by Eric Noulard for a Toulibre
(\url{http://www.toulibre.fr}) given in Toulouse (France) on February,
$8^{th}$ 2012. After that, the source of the presentation has been
release under CC-BY-SA,
\url{http://creativecommons.org/licenses/by-sa/3.0/us/} and put on
\url{https://github.com/TheErk/CMake-tutorial} then contributors
stepped-in.
\end{block}
{\normalsize
Many thanks to all contributors (alphabetical order):
}
\begin{block}{Contributors}
\fontsize{9pt}{11}\selectfont
\textcolor{cmakeblue}{Sébastien Dinot},
\textcolor{cmakered}{Andreas Mohr}.
\end{block}
}
\end{frame}
\section{Introduction}
\begin{frame}[fragile]
\frametitle{CMake tool sets}
\begin{block}{CMake}
CMake is a \emph{cross-platform build systems generator} which makes it easier
to build software in a unified manner on a broad set of platforms:
\includegraphics[width=0.7cm]{TuxLogo_48},
\includegraphics[width=0.7cm]{FreeBSDLogo_48},
\includegraphics[width=0.7cm]{MSWindowsLogo_48},
\includegraphics[width=0.7cm]{AppleLogo_48},
AIX, IRIX,
\includegraphics[width=0.7cm]{AndroidLogo},
\includegraphics[width=0.7cm]{AppleIOSLogo_48}
$\cdots$
\end{block}
CMake has friends softwares that may be used on their own or together:
\begin{itemize}
\item CMake: build system generator
\item CPack: package generator
\item CTest: systematic test driver
\item CDash: a dashboard collector
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Outline of Part I: CMake}
\tableofcontents[part=1]
\end{frame}
\begin{frame}
\frametitle{Outline of Part II: CPack}
\tableofcontents[part=2]
\end{frame}
\begin{frame}
\frametitle{Outline of Part III: CTest and CDash}
\tableofcontents[part=3]
\end{frame}
\subsection*{Introduction to build systems}
\begin{frame}
\frametitle{Build what?}
\begin{block}{Software build system}
A software build system is the usage of a [set of] tool[s] for building software applications.
\end{block}
\begin{block}{Why do we need that?}
\begin{itemize}
\pause
\item because most softwares consist of several parts that need
some \emph{building} to put them together,
\pause
\item because softwares are written in \emph{various languages}
that may share the same building process,
\pause
\item because we want to build \emph{the same software for various computers} {\scriptsize (PC, Macintosh, Workstation, mobile phones and other PDA, embedded computers) and systems (Windows, Linux, *BSD, other Unices (many), Android, etc\ldots)}
\end{itemize}
\end{block}
\end{frame}
\begin{frame}[fragile]
\frametitle{Programming languages}
\begin{block}{Compiled vs interpreted or what?}
Building an application requires the use
of some programming \emph{language}: Python, Java, C++, Fortran, C, Go, Tcl/Tk, Ruby, Perl, OCaml,\ldots
\end{block}
\begin{tikzpicture}[
sbase/.style={
% The shape:
rectangle,
% The size:
minimum size=2mm,
minimum width=1.5cm,
% The border:
thick,
draw=black!50!black!50,
% 50% red and 50% black,
% and that mixed with 50% white
% The filling:
top color=white,
% a shading that is white at the top...
bottom color=red!80!black!20, % and something else at the bottom
% Font
font=\itshape\scriptsize},
scompiled/.style={sbase,
node distance=1cm and 1cm,
bottom color=green!70!black!20, % and something else at the bottom
},
sinterpreted/.style={sbase,
node distance=1cm and 1cm,
bottom color=orange!70!black!20, % and something else at the bottom
},
sintercomp/.style={sbase,
node distance=1cm and 1cm,
top color=orange!70!black!20, % and something else at the bottom
bottom color=green!70!black!20,
},
stools/.style={sbase,
rectangle,
minimum width=0cm,
bottom color=blue!80!black!20,
font=\slshape\scriptsize
}
]
\tikzstyle{boitearrondie} = [draw,
dashed,
opacity=.5,
fill=blue!20,
rounded corners]
\onslide<1->{\node [sbase, rotate=90, minimum width=3.5cm] (language)
{
\begin{tabular}{c}
Programming\\
languages
\end{tabular}
};
\node [matrix, below right=0.0 cm of language.south east] (linterp) {
\node [sinterpreted] (python) {Python}; \\
\node [sinterpreted] (perl) {Perl}; \\
\node [sinterpreted] (matlab) {Matlab}; \\
\node [sintercomp] (ocaml) {OCaml}; \\
};
%\node [matrix, right delimiter =\}, below=0.0cm of linterp] (lcompil) {
\node [matrix, below=0.0cm of linterp] (lcompil) {
\node [scompiled] (ccxx) {C/C++}; \\
\node [scompiled] (fortran) {Fortran}; \\
\node [scompiled] (ada) {ADA}; \\
};
}
\node[stools, above right=0cm and 3.5cm of linterp.west] (interpreter) {interpreter};
\node[stools, below right=0cm and 1.5cm of lcompil.south east, rotate=90] (object) {\begin{tabular}{c}
object\\
code
\end{tabular}
};
\node[stools, below right=0cm and 1.5 cm of object.south west, rotate=90] (executable) {executable};
\node[stools, minimum height=2cm, right=0 cm and 2 cm of executable.south east ] (running) {\begin{tabular}{c}
Running\\
program
\end{tabular}};
\draw [->,thick,color=black] (linterp.east) -- (interpreter.west) node[above,midway,font=\tiny] {?byte-compile?};
\draw [->,thick,color=black] (interpreter.east) -- (running.west) node[above,midway,font=\tiny] {interprets} ;
\draw [->,thick,color=black] (lcompil.east) -- (object.north) node[above,midway,font=\tiny] {compiles};
\draw [->,thick,color=black] (object.south) -- (executable.north) node[above,midway,font=\tiny] {links};
\draw [->,thick,color=black] (executable.south) -- (running.west) node[above,midway,font=\tiny] {executes};
\begin{pgfonlayer}{background}
\onslide<2->{
\draw[boitearrondie,top color=blue,bottom color=green,middle color=red] ([xshift=0.05cm]language.south) rectangle ([xshift=0.1cm,yshift=-0.7cm]running.south east);
\pgftext[top,at={\pgfpointanchor{running}{south}}]{\pgfuseimage{CMakeLogo}};
}
\end{pgfonlayer}
\end{tikzpicture}
\end{frame}
\begin{frame}
\frametitle{Build systems: several choices}
\begin{block}{Alternatives}
CMake is not the only build system [generator]:\\
\begin{itemize}
\item (portable) hand-written Makefiles, depends on \fname{make} tool (may be \href{https://www.gnu.org/software/make/}{GNU Make}).
\item Apache \href{http://ant.apache.org/}{ant} (or \href{https://maven.apache.org/}{Maven} or \href{https://gradle.org/}{Gradle}), dedicated to Java (almost).
\item Portable IDE: Eclipse, Code::Blocks, Geany, NetBeans, \ldots
\item GNU Autotools: \href{http://www.gnu.org/software/autoconf/}{Autoconf}, Automake, Libtool.
Produce makefiles. Bourne shell needed (and M4 macro processor).
\item \href{SCons}{http://www.scons.org} only depends on Python.
\item \ldots
\end{itemize}
\end{block}
\end{frame}
\begin{frame}[fragile]
\frametitle{Build systems or build systems generator}
\begin{block}{Build systems}
A tool which builds, a.k.a. compiles, a set of source files in order to produce binary executables and libraries.
Those kind of tools usually takes as input a file (e.g. a Makefile) and while reading it issues compile commands.
The main goal of a build tool is to (re)build the minimal subset of files when something changes.
A non exhaustive list: \href{https://www.gnu.org/software/make/}{[GNU] make}, \href{https://ninja-build.org/}{ninja}, \href{https://github.com/Microsoft/msbuild}{MSBuild}, \href{http://www.scons.org}{SCons}, \href{http://ant.apache.org/}{ant}, \ldots
\end{block}
A \textbf{Build systems generator} is a tool which generates files for a particular build system. e.g. \href{http://cmake.org}{CMake} or \href{http://www.gnu.org/software/autoconf/}{Autotools}.
\end{frame}
\begin{frame}
\frametitle{What build systems do?}
\begin{block}{Targets and sources}
The main feature of a build system is to offer a way to describe how a target (executable, PDF, shared library\ldots) is built from its sources (set of object files and/or libraries, a latex or rst file, set of C/C++/Fortran files\ldots). Basically a \emph{target} \textbf{depends} on one or several {sources} and one can run a set of \textbf{commands} in order to built the concerned \emph{target} from its \emph{sources}.
\end{block}
The main goals/features may be summarized as:
\begin{itemize}
\item describe dependency graph between sources and targets
\item associate one or several commands to \emph{rebuilt} target from source(s)
\item issue the \emph{minimal} set of commands in order to rebuild a target
\end{itemize}
\end{frame}
\begin{frame}[label=samplemakefile,fragile]
\frametitle{A sample \texttt{Makefile} for \texttt{make}}
\lstinputlisting[basicstyle=\tiny,numbers=left,firstline=2,language=make]{examples/totally-free/Makefile.manual}
\end{frame}
\begin{frame}
\frametitle{Comparisons and [success] stories}
\begin{alertblock}{Disclaimer}
This presentation is biased. \emph{I mean totally}.
I am a big CMake fan, I did contribute to CMake, thus I'm not
impartial \emph{at all}. But I will be ready to discuss why CMake
is the greatest build system out there :-)
\end{alertblock}
Go and forge your own opinion:
\begin{itemize}
\item Bare list: \url{http://en.wikipedia.org/wiki/List_of_build_automation_software}
\item A comparison: \url{http://www.scons.org/wiki/SconsVsOtherBuildTools}
\item KDE success story (2006): ``\textsl{Why the KDE project switched to CMake -- and how}''
\url{http://lwn.net/Articles/188693/}
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{CMake/Auto[conf\textbar make] on OpenHub}
\begin{center}
\includegraphics[width=0.9\textwidth,height=0.50\textheight]{compare_cmake_autotools_ohlo_color_transparent}
\end{center}
\begin{block}{\url{https://www.openhub.net/languages/compare}}
Language comparison of CMake to automake and
autoconf showing the percentage of developers commits that modify a
source file of the respective language (data from 2012).
\end{block}
\end{frame}
\begin{frame}
\frametitle{CMake/Autoconf/Gradle on Google Trend}
\begin{center}
\includegraphics[width=1.0\textwidth,height=0.50\textheight]{CMakeAutoconfGradle-trend-2016}
\end{center}
\begin{block}{\url{https://www.google.com/trends}}
Scale is based on the average worldwide request traffic searching for CMake, Autoconf and Gradle in all years (2004--now).
\end{block}
\end{frame}
\section{Basic CMake usage}
\begin{frame}
\frametitle{A build system generator}
\begin{itemize}
\item CMake is a \emph{generator}: it generates \emph{native} build systems files (Makefile, Ninja, IDE project files [XCode, CodeBlocks, Eclipse CDT, Codelite, Visual Studio, Sublime Text\ldots], \ldots),
\item CMake scripting language (declarative) is used to describe the build,
\item The developer edits \fname{CMakeLists.txt}, invokes CMake but
should \emph{never} edit the generated files,
\item CMake may be (automatically) re-invoked by the build system,
\item CMake has friends who may be very handy (CPack, CTest, CDash)
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{The CMake workflow}
\begin{enumerate}
\onslide<2->{\item \emph{CMake time}: CMake is running \& processing \fname{CMakeLists.txt}}
\onslide<3->{\item \emph{Build time}: the build tool (make, ninja, ...) runs and invokes (at least) the compiler}
\onslide<4->{\item \emph{Install time}: the compiled binaries are installed
i.e. from build area to an install location.
}
\onslide<5->{\item \emph{CPack time}: CPack is running for building package}
\onslide<6->{\item \emph{Package Install time}: the package (from previous step) is installed}
\end{enumerate}
\onslide<1->{
\begin{alertblock}{When do things take place?}
CMake is a \emph{generator} which means it does not compile (i.e. build) the sources,
the underlying build tool (make, ninja, XCode, Visual Studio\ldots) does.
\end{alertblock}
}
\end{frame}
\begin{frame}[label=cmakeworkflow]
\frametitle{The CMake workflow (pictured)}
\begin{tikzpicture}[
sbase/.style={ % The shape:
rectangle,
% The size:
minimum size=2mm,
minimum width=2.0cm,
minimum width=0.5cm,
% The border:
thick,
draw=black!50!black!50,
% 50% red and 50% black,
% and that mixed with 50% white
% The filling:
top color=white,
% a shading that is white at the top...
bottom color=red!80!black!20, % and something else at the bottom
% Font
font=\itshape\scriptsize}
]
\tikzstyle{edited} = [sbase,
draw,
bottom color=green!80!black!20,
%opacity=.5,
%fill=green!20,
rounded corners]
\tikzstyle{generated} = [sbase,
draw,
%dashed,
bottom color=red!80!black!20,
%opacity=.5,
%fill=green!20,
rounded corners]
\tikzstyle{installed} = [sbase,
draw,
bottom color=blue!80!black!20,
%opacity=.5,
%fill=green!20,
rounded corners]
\tikzstyle{pkg} = [installed,
dashed,
general shadow={fill=blue!60!black!40,shadow scale=1.05,shadow xshift=+2pt,shadow yshift=-2pt}
]
\onslide<1->{
\node[edited] (cmakelists) {\begin{tabular}{c}
CMakeLists.txt
\end{tabular}
};
\node[edited,below=1cm and 0cm of cmakelists.south] (sourcefiles)
{\begin{tabular}{c}
Source files
\end{tabular}
};
}
\onslide<2->{
\node[generated,right=0cm and 1.5cm of cmakelists.east] (projectfiles)
{\begin{tabular}{c}
Project file(s),\\
Makefiles, \ldots
\end{tabular}
};
\node[generated,below right=2cm and 1.5cm of cmakelists.east] (gensourcefiles) {\begin{tabular}{c}
Generated \\
Sources files
\end{tabular}
};
}
\onslide<3->{
\node[generated,right=0cm and 1.5cm of projectfiles.east] (objectfiles) {\begin{tabular}{c}
Object files
\end{tabular}
};
}
\onslide<5->{
\node[pkg, below left=1.7cm and 0cm of sourcefiles.south] (spackage)
{\begin{tabular}{c}
Source \\
package
\end{tabular}
};
}
\node[above right=0.5cm and 2.0cm of spackage.east] (legendL){};
\node[right=0cm and 2.3cm of legendL.east] (legendR){};
\onslide<5->{
\node[pkg, below right=-1.5cm and 7cm of spackage.east] (bpackage)
{\begin{tabular}{c}
Binary \\
package
\end{tabular}
};
}
\onslide<6->{
\node[installed, below=0.7cm and 0cm of bpackage.south] (ipackage)
{\begin{tabular}{c}
Installed \\
package
\end{tabular}
};
}
\onslide<4->{
\node[installed, above=0.7cm and 0cm of bpackage.north] (binstalled)
{\begin{tabular}{c}
Installed \\
files
\end{tabular}
};
}
\tikzstyle{cmaketime} = [-latex,thick,color=green]
\tikzstyle{buildtime} = [-latex,thick,color=red]
\tikzstyle{installtime} = [-latex,thick,color=black]
\tikzstyle{cpacktime} = [-latex,thick,color=blue]
\tikzstyle{packageinstalltime} = [-latex,thick,color=black,dashed]
\onslide<2->{
\draw [cmaketime] ([yshift=0.0cm]legendL.south) -- ([yshift=0.0cm]legendR.south) node[above=-2pt,midway,font=\tiny] {CMake time};
}
\onslide<3->{
\draw [buildtime] ([yshift=-0.5cm]legendL.south) -- ([yshift=-0.5cm]legendR.south) node[above=-2pt,midway,font=\tiny] {Build time};
}
\onslide<4->{
\draw [installtime] ([yshift=-1.0cm]legendL.south) -- ([yshift=-1.0cm]legendR.south) node[above=-2pt,midway,font=\tiny] {Install time};
}
\onslide<5->{
\draw [cpacktime] ([yshift=-1.5cm]legendL.south) -- ([yshift=-1.5cm]legendR.south) node[above=-2pt,midway,font=\tiny] {CPack time};
}
\onslide<6->{
\draw [packageinstalltime] ([yshift=-2.0cm]legendL.south) -- ([yshift=-2.0cm]legendR.south) node[above=-2pt,midway,font=\tiny] {Package Install time};
}
\begin{pgfonlayer}{background}
\onslide<2->{
\draw [cmaketime] (cmakelists) -- (projectfiles);
\draw [cmaketime] (cmakelists) -- (gensourcefiles);
\draw [cmaketime] (sourcefiles) -- (gensourcefiles);
}
\onslide<5->{
\draw [cpacktime] (cmakelists) -- (spackage);
\draw [cpacktime] (sourcefiles) -- (spackage);
\draw [cpacktime] ([xshift=-0.2cm]binstalled.south) -- ([xshift=-0.2cm]bpackage.north);
}
\onslide<3->{
\draw [buildtime] (sourcefiles) -- (objectfiles);
\draw [buildtime] (gensourcefiles) -- (objectfiles);
\draw [buildtime] (projectfiles) -- (gensourcefiles);
}
\onslide<4->{
\draw [installtime] (objectfiles) -- (binstalled);
\draw [installtime] (gensourcefiles) -- (binstalled);
\draw [installtime] (sourcefiles) -- (binstalled);
}
\onslide<6->{
\draw [packageinstalltime] (bpackage.south) -- (ipackage.north);
}
\end{pgfonlayer}
\end{tikzpicture}
\end{frame}
\begin{frame}[fragile]
\frametitle{Building an executable}
\begin{lstlisting}[basicstyle=\scriptsize,caption=Building a simple program]
cmake_minimum_required (VERSION 3.0)
# This project use C source code
project (TotallyFree C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_EXTENSIONS False)
# build executable using specified list of source files
add_executable(Acrolibre acrolibre.c)
\end{lstlisting}
CMake scripting language is [mostly] declarative.
It has \emph{commands} which are documented from within CMake:
{\tiny
\begin{verbatim}
$ cmake --help-command-list | wc -l
117
$ cmake --help-command add_executable
...
add_executable
Add an executable to the project using the specified source files.
\end{verbatim}
}
\end{frame}
\begin{frame}[fragile,allowframebreaks]
\frametitle{Builtin documentation}
\begin{Verbatim}[commandchars=\\\{\},fontsize=\tiny,numbers=left,frame=topline,label=CMake builtin doc for 'project' command]
$ cmake --help-command project
project
-------
Set a name, version, and enable languages for the entire project.
project(<PROJECT-NAME> [LANGUAGES] [<language-name>...])
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[LANGUAGES <language-name>...])
Sets the name of the project and stores the name in the
``PROJECT_NAME`` variable.
[...]
Optionally you can specify which languages your project supports.
Example languages are \textcolor{cmakeblue}{CXX} (i.e. C++), \textcolor{cmakeblue}{C}, \textcolor{cmakeblue}{Fortran}, etc. By \textcolor{cmakered}{default C} \textcolor{cmakered}{and CXX are enabled}.
E.g. if you do not have a C++ compiler, you can disable the check for it by explicitly
listing the languages you want to support, e.g. C. By using the special language "\textcolor{cmakeblue}{NONE}"
all checks for any language can be disabled.
\end{Verbatim}
Online doc : \url{https://cmake.org/documentation/}\\
Unix Manual: {\scriptsize \texttt{cmake-variables(7)}, \texttt{cmake-commands(7)}, \texttt{cmake-xxx(7)}, \ldots}\\
All doc generated using \href{http://www.sphinx-doc.org/en/stable/builders.html}{Sphinx},
QtHelp file as well:\\
\begin{small}
\begin{enumerate}
\item get QtHelp file from CMake: \url{https://cmake.org/cmake/help/v3.7/CMake.qch}
and copy it to \texttt{CMake-tutorial/examples/}
\item use CMake.qhcp you may find in the source of this tutorial:
\texttt{CMake-tutorial/examples/CMake.qhcp}
\item compile QtHelp collection file:
\texttt{qcollectiongenerator CMake.qhcp -o CMake.qhc}
\item display it using Qt Assistant:
\texttt{assistant -collectionFile CMake.qhc}
\end{enumerate}
\end{small}
\end{frame}
\defverbatim[colored]{\genmake}{
\begin{Verbatim}[commandchars=\\\{\},fontsize=\tiny,numbers=left,frame=topline,label=Building with make]
$ ls totally-free
acrolibre.c CMakeLists.txt
$ mkdir build
$ cd build
$ cmake ../totally-free
-- The C compiler identification is GNU 4.6.2
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
...
$ \textcolor{cmakeblue}{make}
...
[100%] Built target Acrolibre
$ ./Acrolibre toulibre
\end{Verbatim}
}
\defverbatim[colored]{\genninja}{
\begin{Verbatim}[commandchars=\\\{\},fontsize=\tiny,numbers=left,frame=topline,label=Building with ninja]
$ ls totally-free
acrolibre.c CMakeLists.txt
$ \textcolor{cmakered}{mkdir build-ninja}
$ \textcolor{cmakered}{cd build-ninja}
$ cmake \textcolor{cmakered}{-GNinja} ../totally-free
-- The C compiler identification is GNU 4.6.2
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
...
$ \textcolor{cmakered}{ninja}
...
[6/6] Linking C executable Acrodictlibre
$ ./Acrolibre toulibre
\end{Verbatim}
}
\defverbatim[colored]{\gencrosswin}{
\begin{Verbatim}[commandchars=\\\{\},fontsize=\tiny,numbers=left,frame=topline,label=Building with cross-compiler]
$ ls totally-free
acrolibre.c CMakeLists.txt
$ \textcolor{cmakegreen}{mkdir build-win32}
$ \textcolor{cmakegreen}{cd build-win32}
$ cmake \textcolor{cmakegreen}{-DCMAKE_TOOLCHAIN_FILE=../totally-free/Toolchain-cross-linux.cmake} ../totally-free
-- The C compiler identification is GNU 6.1.1
-- Check for working C compiler: /usr/bin/i686-w64-mingw32-gcc
...
$ \textcolor{cmakegreen}{make}
...
[100%] Linking C executable Acrolibre\textcolor{cmakegreen}{.exe}
[100%] Built target Acrolibre
$ ./Acrolibre toulibre
\end{Verbatim}
}
\begin{frame}[fragile]
\frametitle{Generating \& building}
\only<3>{\textcolor{cmakegreen}{Cross-}}Building with CMake and \only<1,3>{\textcolor{cmakeblue}{make}}\only<2>{\textcolor{cmakered}{ninja}} is easy:
\begin{center}
\only<1>{\genmake}\only<2>{\genninja}\only<3>{\gencrosswin}
\end{center}
\onslide<1->{
\begin{alertblock}{Source tree vs Build tree}
Even the most simple project should never mix-up sources
with generated files. CMake supports \emph{out-of-source} build.
\end{alertblock}}
\end{frame}
\begin{frame}[fragile]
\frametitle{Always build out-of-source}
\begin{alertblock}{Out-of-source is better}
People are lazy (me too) and they think that because
building in source is possible and authorizes less typing
they can get away with it.
In-source build is a \emph{BAD} choice.
\end{alertblock}
Out-of-source build is \emph{always} better because:
\begin{enumerate}
\pause
\item Generated files are separated from manually edited ones
(thus you don't have to clutter your favorite VCS ignore files).
\pause
\item You can have several build trees for the same source tree
\pause
\item This way it's always safe to completely delete the build tree
in order to do a clean build
\end{enumerate}
\end{frame}
\begin{frame}[fragile]
\frametitle{Building program + autonomous library}
\onslide<2->{
\begin{block}{Conditional build}
We want to keep a version of our program that can be compiled
and run without the new Acrodict library \emph{and} the new version which
uses the library.
\end{block}}
We now have the following set of files in our source tree:
\begin{itemize}
\item \fname{acrolibre.c}, the main C program
\item \fname{acrodict.h}, the Acrodict library header
\item \fname{acrodict.c}, the Acrodict library source
\item \fname{CMakeLists.txt}, the soon to be updated CMake input file
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\setlength{\columnsep}{0.8cm}
\vspace*{-0.5cm}
\begin{center}
The main program source
\end{center}
\begin{multicols}{2}
\begin{lstlisting}[basicstyle=\tiny,language=C,breaklines=true]
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#ifdef USE_ACRODICT
#include "acrodict.h"
#endif
int main(int argc, char* argv[]) {
const char * name;
#ifdef USE_ACRODICT
const acroItem_t* item;
#endif
if (argc < 2) {
fprintf(stderr,"%s: you need one argument\n",argv[0]);
fprintf(stderr,"%s <name>\n",argv[0]);
exit(EXIT_FAILURE);
}
name = argv[1];
#ifndef USE_ACRODICT
if (strcasecmp(name,"toulibre")==0) {
printf("Toulibre is a french organization promoting FLOSS.\n");
}
#else
item = acrodict_get(name);
if (NULL!=item) {
printf("%s: %s\n",item->name,item->description);
} else if (item=acrodict_get_approx(name)) {
printf("<%s> is unknown may be you mean:\n",name);
printf("%s: %s\n",item->name,item->description);
}
#endif
else {
printf("Sorry, I don't know: <%s>\n",name);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
\end{lstlisting}
\end{multicols}
\end{frame}
\begin{frame}[fragile]
\setlength{\columnsep}{0.8cm}
\vspace*{-0.5cm}
\begin{center}
The library source
\end{center}
\begin{multicols}{2}
\begin{lstlisting}[basicstyle=\tiny,language=C,breaklines=true]
#ifndef ACRODICT_H
#define ACRODICT_H
typedef struct acroItem {
char* name;
char* description;
} acroItem_t;
const acroItem_t*
acrodict_get(const char* name);
#endif
\end{lstlisting}
\begin{lstlisting}[basicstyle=\tiny,language=C,breaklines=true]
#include <stdlib.h>
#include <string.h>
#include "acrodict.h"
static const acroItem_t acrodict[] = {
{"Toulibre", "Toulibre is a french organization promoting FLOSS"},
{"GNU", "GNU is Not Unix"},
{"GPL", "GNU general Public License"},
{"BSD", "Berkeley Software Distribution"},
{"CULTe","Club des Utilisateurs de Logiciels libres et de gnu/linux de Toulouse et des environs"},
{"Lea", "Lea-Linux: Linux entre ami(e)s"},
{"RMLL","Rencontres Mondiales du Logiciel Libre"},
{"FLOSS","Free Libre Open Source Software"},
{"",""}};
const acroItem_t*
acrodict_get(const char* name) {
int current =0;
int found =0;
while ((strlen(acrodict[current].name)>0) && !found) {
if (strcasecmp(name,acrodict[current].name)==0) {
found=1;
} else {
current++;
}
}
if (found) {
return &(acrodict[current]);
} else {
return NULL;
}
}
\end{lstlisting}
\end{multicols}
\end{frame}
\againframe{samplemakefile}
\begin{frame}[fragile]
\frametitle{Building a library}
\vspace*{-0.5cm}
\begin{lstlisting}[basicstyle=\tiny,caption=Building a simple program + shared library]
cmake_minimum_required (VERSION 3.0)
project (TotallyFree C)
(*@\tikz[na] \coordinate(PdstC99);@*)set(CMAKE_C_STANDARD 99)
set(CMAKE_C_EXTENSIONS False)
add_executable(Acrolibre acrolibre.c)
(*@\tikz[na] \coordinate(PdstVarDef);@*)set(LIBSRC acrodict.c acrodict.h)
add_library(acrodict ${LIBSRC})(*@\tikz[na] \coordinate(PdstLibDef);@*)
add_executable(Acrodictlibre acrolibre.c)
(*@\tikz[na] \coordinate(PdstLinkOpt);@*)target_link_libraries(Acrodictlibre acrodict) (*@\label{linkline}@*)
(*@\tikz[na] \coordinate(PdstCompilOpt);@*)set_target_properties(Acrodictlibre PROPERTIES COMPILE_FLAGS "-DUSE_ACRODICT") (*@\label{propdef}@*)
\end{lstlisting}
\begin{itemize}
\item<1-> \tikz[na] \coordinate(PsrcC99);we precise that we want to compile with C99 flags
\item<2-> \tikz[na] \coordinate(PsrcVarDef);we define a variable and ask to build a library\tikz[na] \coordinate(PsrcLibDef);
\item<3-> \tikz[na] \coordinate(PsrcLinkOpt);we link an executable to our library %(line \ref{linkline})
\item<4-> \tikz[na] \coordinate(PsrcCompilOpt);we compile the source files of a particular target with specific compiler options
\end{itemize}
\begin{tikzpicture}[overlay]
\only<1>{
\path[->, red, thick] ($(PsrcC99)+(-0.5,0)$) edge[bend left] (PdstC99);
}
\only<2>{
\path[->, red, thick] ($(PsrcVarDef)+(-0.5,0)$) edge[bend left] ($(PdstVarDef)+(0,-0.1)$);
}
\only<3>{
\path[->, red, thick] ($(PsrcLinkOpt)+(-0.5,0)$) edge[bend left] ($(PdstLinkOpt)+(0,0)$);
}
\only<4>{
\path[->, red, thick] ($(PsrcCompilOpt)+(-0.5,0)$) edge[bend left] ($(PdstCompilOpt)+(0,0)$);
}
\end{tikzpicture}
\end{frame}
\begin{frame}[fragile,allowframebreaks]
\frametitle{Building a library - continued}
\begin{block}{And it builds...}
All in all CMake generates appropriate Unix makefiles which build
all this smoothly.
\end{block}
\begin{Verbatim}[fontsize=\tiny,numbers=left,frame=topline,label=CMake + Unix Makefile]