-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
3940 lines (3701 loc) · 226 KB
/
index.html
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/main.css" media="screen"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<title>std::stream of consciousness</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Dancing+Script:wght@700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Lato&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@200&display=swap');
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script type="text/javascript" defer src="js/language.js"></script>
<script type="text/javascript" defer src="js/stackoverflow.js"></script>
<script type="text/javascript" defer src="js/main.js"></script>
<script type="text/javascript" defer src="js/tabs.js"></script>
<script src="https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)"></script>
<!--link rel="stylesheet" href="highlight/styles/agate.min.css"-->
<!--link rel="stylesheet" href="highlight/styles/androidstudio.min.css"-->
<!--link rel="stylesheet" href="highlight/styles/base16/darcula.min.css"-->
<!--link rel="stylesheet" href="highlight/styles/atom-one-dark.min.css"-->
<link rel="stylesheet" href="highlight/styles/base16/solarized-dark.min.css">
<link rel="icon" href="img/aster_logo.ico" type="image/x-icon">
<script src="highlight/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
</head>
<body onload="populateSOProfileWidged(); populateSORadarPlot();">
<div class="body centered-container"> <!-- this double container pattern is to avoid getting blind when opening dev tools -->
<header>
<div class="top-bar box-shadow centers-based-flex">
<div>
<div>
<input id="toggle" class="toggle hidden dark-light-mode" type="checkbox"/>
<label for="toggle"></label>
<div>
<span lang="en">dark and light mode coming soon…-ish</span>
<span lang="it">modalità chiara e scura in arrivo…</span>
</div>
</div>
</div>
<div>
<ul class="social-links">
<li><a href="https://github.com/Aster89" class="fa fa-github"></a></li>
<li>
<a id="stackoverflow-link" href="https://stackoverflow.com/users/5825294" class="fa fa-stack-overflow"></a>
<div class="stackoverflow-widget flex box-shadow">
<img class="avatar" src="https://graph.facebook.com/10207587812237236/picture?type=large" alt="?"/>
<span class=reputation>?</span>
<ul class="badges flex">
<li class="gold">?</li>
<li class="silver">?</li>
<li class="bronze">?</li>
</ul>
</div>
</li>
<li><a href="https://www.linkedin.com/in/enrico-maria-de-angelis-1b9b1a116/" class="fa fa-linkedin"></a></li>
</ul>
</div>
<div>
<ul class="choice-picker">
<li>
<input id="lang-it" class="hidden" type="radio" name="choose-language" onclick="setLanguage('it')">
<label for="lang-it" title="Italiano">
<svg preserveAspectRatio="none" class="country-flag" xmlns="http://www.w3.org/2000/svg" width="1500" height="1000" viewBox="0 0 3 2">
<rect width="3" height="2" fill="#009246"/>
<rect width="2" height="2" x="1" fill="#fff"/>
<rect width="1" height="2" x="2" fill="#ce2b37"/>
</svg>
</label>
</li>
<li>
<input id="lang-en" class="hidden" type="radio" name="choose-language" onclick="setLanguage('en')">
<label for="lang-en" title="English">
<svg preserveAspectRatio="none" class="country-flag" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 30" width="1200" height="600">
<clipPath id="s">
<path d="M0,0 v30 h60 v-30 z"/>
</clipPath>
<clipPath id="t">
<path d="M30,15 h30 v15 z v15 h-30 z h-30 v-15 z v-15 h30 z"/>
</clipPath>
<g clip-path="url(#s)">
<path d="M0,0 v30 h60 v-30 z" fill="#012169"/>
<path d="M0,0 L60,30 M60,0 L0,30" stroke="#fff" stroke-width="6"/>
<path d="M0,0 L60,30 M60,0 L0,30" clip-path="url(#t)" stroke="#C8102E" stroke-width="4"/>
<path d="M30,0 v30 M0,15 h60" stroke="#fff" stroke-width="10"/>
<path d="M30,0 v30 M0,15 h60" stroke="#C8102E" stroke-width="6"/>
</g>
</svg>
</label>
</li>
</ul>
</div>
</div>
<div class="page-title-and-author">
<h1 id="page-title" class="page-title center-text-horz text-shadow">
<code class="language-cpp"><span class="transparent-50">std::io</span>stream </code>
<span class="handwriting"> of consciousness</span>
</h1>
<h4 class="handwriting page-author text-shadow">
<a class="my-email" href="mailto:enricomaria.dean6elis@gmail.com">
— Enrico Maria De Angelis
</a>
</h4>
</div>
</header>
<div lang="en" class="wip center-text-horz text-shadow">Work in progress…</div>
<div lang="it" class="wip center-text-horz text-shadow">Lavori in corso…</div>
<nav> <!-- consider moving this into the header: http://www.cellbiol.com/bioinformatics_web_development/chapter-3-your-first-web-page-learning-html-and-css/introducing-html5-footer-header-nav-article-section-and-aside-elements/ -->
<ul class="site-nav">
<li class="switch-button">
<input class="hidden" type="radio" name="nav-tabs" id="posts-radio" value="posts" checked>
<label for="posts-radio" class="box-shadow">
<span class="text">
<span lang="en">Thoughts</span>
<span lang="it">Pensieri</span>
</span>
<span class="icon fa fa-comment"></span>
</label>
</li>
<li class="switch-button">
<input class="hidden" type="radio" name="nav-tabs" id="projects-radio" value="projects">
<label for="projects-radio" class="box-shadow">
<span class="text">
<span lang="en">Projects</span>
<span lang="it">Progetti</span>
</span>
<span class="icon fa fa-code"></span>
</label>
</li>
<li class="switch-button">
<input class="hidden" type="radio" name="nav-tabs" id="suggested-books-radio" value="suggested-books">
<label for="suggested-books-radio" class="box-shadow">
<span class="text">
<span lang="en">Readings</span>
<span lang="it">Letture</span>
</span>
<span class="icon fa fa-book"></span>
</label>
</li>
<li class="switch-button">
<input class="hidden" type="radio" name="nav-tabs" id="about-me-radio" value="about-me">
<label for="about-me-radio" class="box-shadow">
<span class="text">Curriculum</span>
<span class="icon fa fa-university"></span>
</label>
</li>
</ul>
</nav>
<main id="main">
<div class="main centered-container">
<section class="tab-page" id="posts-tab">
<article class="post-entry" id="c++-headers-and-libraries">
<div class="__after-only-child-center-below centered-container">
<h6 class="text-shadow handwriting underline-underbullet">15/10/2022</h6>
</div>
<div class="panel panel--rounded box-shadow text-shadow">
<div class="panel__header center-text-horz">
<img class="panel-icon" src="img/c++-logo.png" alt="">
<h2><a href="#c++-headers-and-libraries">Libraries in C++ — Header-only, static, dynamic, and lazily loaded</a></h2>
</div>
<div class="text-shadow">
<p>Just how many times have you cried because of a linker error?</p>
<p>I have. And so many times!</p>
<p>In hindsight, it is a pretty simple topic, but if you're so used
to just write code, and let the build system take care of compiling
and linking, then you'll probably hit linker errors infrequently
enough that you'll be tolerant of the frustration of those moments,
as long as some trial and error with build configuration files
will get you out of trouble.
</p>
<p>But sometimes you can't just hold the frustration anymore, and
you command yourself to dedicate some time to go to the bottom of this
topic; or, if not to the bottom, at least as low as it takes
for you to be happy with it, and no more frustrated by the
linking failures.
</p>
<p>So here's how I came to write this post: I started by creating
a directory with an evocative name, moved into it,
and started to play with C++ files in an attempt to
reproduce the frustrating workflow to better understand it.
When I started to erroneously delete the wrong file,
to forget what edit I made to file such and such, and
to feel more frustrated because didn't want to spend time
creating a <code>Makefile</code> to deal with this crap
on my behalf (after all, the <code>Makefile</code> would
be the guy shielding me away from exactly the topic I
was trying to understand, so probably using one would have
killed the purpose of the exercise), I decided
that writing a post to help myself track the progress of
my understanding was maybe a good idea.
</p>
<p>Eventually, this post turned out to be a personally
reworded collage of all the info I've found on the web that
helped me build a firmer understanding of the compilation
process, as well as of the various types of libraries that
exist. These two aspects are tightly bounded together,
in the sense that libraries (yours or third party's) are
exactly the expression of the fact that a program can
be written in separate and independently developed, tested,
and sometimes built pieces.
</p>
<p>(Little but important note: I'm on Linux, both at work and
in my personal time, so I will not even try giving Windows
examples; but most of this post should be useful anyway.)</p>
<h3 id="gcc-steps"><a href="#gcc-steps">The steps from source code to executable</a></h3>
<p>First of all, it is important to have an understanding of what
"compiling" a source codes into an executable really means. I've
quoted the word "compiling" because proper compilation is just
one of the steps that a compiler executes to go from source
code to executable program.
<a href="https://stackoverflow.com/a/9244030/5825294">This short but very good answer on StackOverflow</a>
outlines the phases that GCC goes through in the process.
</p>
<div class="collapsible-widget">
<input type="checkbox" value="" name="show more" id="steps-of-compilation-show-more"/>
<label for="steps-of-compilation-show-more">
<span>For instance…</span>
<span>For instance, if you have a single <code>mysource.cpp</code> file, when you execute</span>
</label>
<div class="collapsible">
<div>
<p></p>
<pre><code class="language-bash">g++ mysource.cpp -o mysource</code></pre>
<p>GCC in reality does the following (I'm barely rewording from the linked answer).
</p>
<ol>
<li id="c-preprocessor">It preprocesses the source code, by
stripping comments and expanding macros and
<code>#include</code>s; you can obtain this intermediate
product yourself by passing the <code>-E</code> to
<code>g++</code>:
<pre><code class="language-bash">g++ -E mysource.cpp -o mysource.ii</code></pre>
</li>
<li>It compiles that preprocessed source code to assembly, which you can
do yourself by means of the <code>-S</code> option:
<pre><code class="language-bash">g++ -S mysource.ii -o mysource.s</code></pre>
</li>
<li>It compiles the assembly into an object binary file, which you can do by means of
the <code>-c</code> option:
<pre><code class="language-bash">g++ -c mysource.s -o mysource.o</code></pre>
</li>
<li id="linker">Finally, it links the object
into the executable; you can do this by passing no options:
<pre><code class="language-bash">g++ mysource.o -o mysource</code></pre>
(you can list other object files too, if needed).
</li>
</ol>
<p>For the sake of accuracy, the flags <code>-E</code>,
<code>-S</code>, <code>-c</code> and none tell <code>g++</code>
at which step to <i>stop</i> the process, whereas where to begin
from is dictated simply the file you throw at it (not because of the extension
but because of what's inside it). To give a couple of examples,
</p>
<pre><code class="language-bash">g++ -S mysource.cpp -o mysource.s</code></pre>
<p>performs steps 1 and 2, whereas
</p>
<pre><code class="language-bash">g++ mysource.ii -o mysource</code></pre>
<p>executes steps 2, 3, and 4.
</p>
</div>
</div>
</div>
<h3 id="include-is-copy-and-paste"><a href="#include-is-copy-and-paste"><code>#include</code> is copy-and-paste</a></h3>
<p>As you might have guessed from its description,
step 1 is what takes care of, among other things,
<code>#include</code> directives; and you might also
wonder how simple this preprocessing might be,
considering that it happens so early in the process.
</p>
<p>And it is indeed a very simple thing:
</p>
<p style="text-align: center;" id="headers-are-copied-and-pasted">
<b>
<code>#include</code>ing a <i>file</i> is equivalent to
copying-and-pasting it into the includer.
</b>
</p>
<p>(If you know it already, you can <a href="#gcc-steps">skip the current section</a>.)
</p>
<p>
And I'm intentionally saying <i>file</i> instead of
<i>header</i>: <i>whatever</i> you <code>#include</code> is
just copy-and-pasted.
There's truly nothing other than copy-and-paste when you
<code>#include</code> something.
</p>
<p>Indeed, so little is special about <code>#include</code>, that
if you write a header without having that simple idea in mind, you can easily run in errors
which become obvious, once you are aware that there's just a copy-and-paste going on.
</p>
<p>Here's three flawed headers, each defining a different class,
one of which is included by the other two, which are in turn included
in the <code>main</code> program:
</p>
<pre><code class="language-cpp">// Foo.hpp
#include "Bar.hpp" // because every
struct Foo { // Foo needs a Bar,
Bar b; // doesn't it?
};</code></pre>
<pre><code class="language-cpp">// Bar.hpp
struct Bar {
// whatever
};</code></pre>
<pre><code class="language-cpp">// Baz.hpp
#include "Bar.hpp" // Even Baz needs a Bar!
struct Baz {
Bar b;
};</code></pre>
<a href="https://godbolt.org/z/Pq8jK6zTf" target="_blank">
<pre><code class="language-cpp">// main.cpp
#include "Baz.hpp"
#include "Foo.hpp"
int main() {
// not even trying to make
// any use of the headers
}</code></pre>
</a>
<p>If you click on the last snippet, you'll see that the program
can't be compiled because it results in a redefinition of <code>Bar</code>,
the reason being that both <code>Foo.hpp</code> and <code>Baz.hpp</code>
are <code>#include</code>ing, i.e. copying-and-pasting, <code>Bar.hpp</code>.
</p>
<p>In other words, it's just like we tried to compile this source file alone:</p>
<pre><code class="language-cpp">// main.cpp
struct Bar {
// whatever
};
struct Baz {
Bar b;
};
struct Bar { // oops, I did it again
// whatever
};
struct Foo {
Bar b;
};
int main() {
// not even trying to make
// any use of the headers
}</code></pre>
<p>The source above, in fact, is the known as a <i>translation unit</i>,
which is the thing that the compiler compiles (or attempts to,
in this case) and which is roughly "the source file, conventionally named
with extension <code>.cpp</code>/<code>.cxx</code>/<code>.c</code>/whatever, that you feed
to the compiler, in which all <code>#include</code>s have been copied-and-pasted
(and all other <code>#</code>-directives have been "resolved", e.g. macro substituted, and so on)"
</p>
<div class="collapsible-widget">
<input type="checkbox" value="" name="show more" id="include-is-copy-and-paste-show-more"/>
<label for="include-is-copy-and-paste-show-more">
<p>In light of the steps we've seen earlier,
another, more direct way of verifying that <code>#include</code>
means copy-and-paste, is to examine the output of the following
command
</p>
</label>
<div class="collapsible">
<div>
<pre><code class="language-bash">g++ -E main.cpp -o main.ii</code></pre>
<p>which is successful and produces the following (it's not
a C++ file, but a file of type <code>initng</code> which contains
a mix of C++ syntax and something else, as you can see; more info
<a href="https://stackoverflow.com/questions/73763861/is-a-translation-unit-valid-c-and-is-a-translation-unit-for-gcc-the-output" target="_blank">here</a>):
</p>
<pre><code class="language-cpp"># 0 "main.cpp"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "main.cpp"
# 1 "Bar.hpp" 1
struct Bar {
};
# 2 "main.cpp" 2
# 1 "Foo.hpp" 1
# 1 "Bar.hpp" 1
struct Bar {
};
# 2 "Foo.hpp" 2
struct Foo {
Bar b;
};
# 3 "main.cpp" 2
int main() {
}</code></pre>
<p>where you can clearly see the duplicate definition of
<code>Bar</code>.
</p>
</div>
</div>
</div>
<p>But then why doesn't this problem occur when we include standard headers?
</p>
<p>The answer is simple: the standard headers use a device know as
<a href="https://en.wikipedia.org/wiki/Include_guard" target="_blank"><code>#include</code> guards</a>
to prevent multiple inclusions of the same header in the same translation unit,
and you should do so in every single one of your headers.
</p>
<p>To see how an include guard looks like, open any system header, such as
<code>iostream</code>, that on my system is located at <code>/usr/include/c++/12.2.0/iostream</code>
at the time of writing, and you'll see it has this structure:</p>
<pre><code class="language-cpp">// comments only
#ifndef _GLIBCXX_IOSTREAM
#define _GLIBCXX_IOSTREAM 1
// the content of the header
#endif /* _GLIBCXX_IOSTREAM */
// EOF</code></pre>
<p>And this is what gets copied-and-pasted in the source includer file,
resulting in the translation unit that the compiler tries to compile.
</p>
<p>When the compiler reaches the above snippet of code while compiling
a translation unit, it will verify that the macro <code>_GLIBCXX_IOSTREAM</code>
is <b><i>not</i></b> defined (because it's <code>#ifndef</code>, not <code>#ifdef</code>)
before actually pasting <code>// the content of the header</code>; it will also, at
that point, <code>#define</code> the macro that was not defined yet (the value <code>1</code> is
irrelevant), so that, should this snippet of code happen to occur again in this same
translation unit, <code>#ifndef _GLIBCXX_IOSTREAM</code> will not fire and the
<code>// the content of the header</code> will not be copied-and-pasted again.
</p>
<p>Another simpler way of enforcing an
<code>#include</code> guard, even though not standard, but
practically permitted by all major compilers, is to put
<a href="https://en.cppreference.com/w/cpp/preprocessor/impl#.23pragma_once" target="_blank"><code>#pragma once</code></a>
at the top of your header, and nothing else. What's the difference? Practically speaking,
none. Anyway, you can find more info
<a href="https://stackoverflow.com/questions/787533/is-pragma-once-a-safe-include-guard" target="_blank">here</a>
and at the previous link.
</p>
<h3 id="header-only-libraries"><a href="#header-only-libraries">Header-only libraries</a></h3>
<p>Knowing that <a href="#headers-are-copied-and-pasted"><code>#include</code>d headers are simply copied-and-pasted</a>,
you can easily imagine you can provide all the functionality you want to a
client of yours by providing them with one or more header files (and by
"header" I mean a proper one, with the <code>#include</code> guard)
defining all functions and classes they need.
<a href="https://stackoverflow.com/a/12673877/5825294" target="_blank">That's not necessarily
a good idea</a>,
but <a href="https://stackoverflow.com/a/12671412/5825294" target="_blank">sometimes it's the only option</a>,
for instance <a href="https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file" target="_blank">when you are defining templates</a>
(<a href="https://stackoverflow.com/a/495056/5825294" target="_blank">unless you already know all possible usages of your template</a>).
</p>
<div class="collapsible-widget">
<input type="checkbox" value="" name="show more" id="header-only-libraries-show-more"/>
<label for="header-only-libraries-show-more">
<p>Using such a library is as easy as adding the <code>#include</code> you need
into your source code,</p>
</label>
<div class="collapsible">
<div>
<pre><code class="language-cpp">// HeaderOnly.hpp
#pragma once
#include <iostream>
void foo(int i) {
std::cout << "Header-only library speaking, "
<< i
<< std::endl;
}</code></pre>
<pre><code class="language-cpp">// main.cpp
#include "HeaderOnly.hpp"
int main() {
foo(101);
}</code></pre>
<p>and <b><i>it becomes part of your program as soon as during
<a href="#c-preprocessor">step 1, the preprocessing stage</a></i></b>, as
demonstrated by the following few commands
</p>
<pre><code class="language-bash">$ g++ -E main.cpp -o main.ii # preprocess main.cpp
$ rm HeaderOnly.hpp # delete header to show it's not needed anymore
$ g++ main.ii -o main # compile & link
$ ./main # execute
Header-only library speaking, 101
</code></pre>
<p><a href="http://boostorg.github.io/hana/" target="_blank">Boost.Hana</a>
is a beautiful example of a header-only library,
designed to facilitate C++ meta-programming and suited for
computations on both types and values.
</p>
</div>
</div>
</div>
<h3 id="static-libraries"><a href="#static-libraries">Static libraries</a></h3>
<p>One of the drawbacks of header-only libraries is that they
<code>#include</code> all the headers their implementation needs;
which translates to what is known as <i>code bloat</i>: your translation
unit ends up being huge because of all the direct and indirect
<code>#include</code>s. Indeed, in the example above, you can well see
that the code inside <code><iostream></code> gets pasted into
<code>main.cpp</code>, even though <code>main.cpp</code> doesn't
need to know anything about <code><iostream></code>; all it
needs to know is how to call <code>foo</code>, i.e. it needs to
know its signature.
</p>
<p>
<a href="https://stackoverflow.com/questions/2174657/when-are-header-only-libraries-acceptable">Whether you should fear this problem and how
much</a> is another matter that this post does not address
at all, and it is influenced, among other things, by how smart the
compiler is.
</p>
<p>Anyway, what is the solution? There's basically no solution if you provide
templates that will be instantiated with types you don't know of, and
that's why templates are often accused of causing code bloat (see also
§9.1.1 from <i><a href="http://www.tmplbook.com/">C++ Templates - The Complete Guide - 2nd edition</a></i> for more
details), but for the simple case of non-template entities, such
as the <code>foo</code> function above,
the solution is simple enough.
Indeed, all <code>main.cpp</code> needs to know about <code>foo</code>
in order to be able to call it, is that it takes <code>void</code>
and returns <code>void</code>, i.e. that its type is <code>void(void)</code>,
or more simply <code>void()</code>. And all we need to do to make it aware
of this fact, is writing in it a declaration of <code>foo</code>,
i.e. <code>void foo();</code>.
As you might have guessed, we don't do that manually, but by
including an header which contains that declaration.
</p>
<p>So here's our solution in code:</p>
<ul>
<li>
<code>MyLib.hpp</code> declares <code>foo</code>,
<pre><code class="language-cpp">// MyLib.hpp
#pragma once
void foo();</code></pre>
</li>
<li>
<code>MyLib.cpp</code> defines it,
<pre><code class="language-cpp">// MyLib.cpp
#include "MyLib.hpp"
void foo() {
std::cout << "Hello" << std::endl;
}</code></pre>
</li>
<li>
and <code>main.cpp</code> <code>#include</code>s the header and uses <code>foo</code>.
<a href="https://godbolt.org/z/z8q68rxz7" target="_blank">
<pre><code class="language-cpp">// main.cpp
#include "MyLib.hpp"
int main() {
foo();
}</code></pre>
</a>
</li>
</ul>
<p>If you're wondering why <code>MyLib.cpp</code>
<code>#include</code>s its own header <code>MyLib.hpp</code>
the answer is that
there is such a myriad of scenarios where doing so is necessary
(e.g. <code>MyLib.hpp</code> defines an <code>inline</code>
variable to be used in client code as well as in the
implementation of some other exposed function), that
not doing it in a rare scenario like the one above
(more likely to happen in toy examples than in real code)
is just not worth the risk of forgetting it when it's needed.
You can read more about it
<a href="https://stackoverflow.com/questions/73248689/is-there-any-reason-i-should-include-a-header-in-the-associated-cpp-file-if-the" target="_blank">in this question I asked on
StackOverflow</a> and in the
associated answers.
</p>
<p id="the-building-process">The above example can be built like this
</p>
<pre><code class="language-bash">g++ -c main.cpp -o main.o # compile main.cpp
g++ -c MyLib.cpp -o MyLib.o # compile MyLib.cpp
g++ main.o MyLib.o -o main # link</code></pre>
<p>where the first two commands can be executed in any order,
because the translation units can be compiled independently,
thanks to the fact that the only thing that <code>main.cpp</code>
needs to know about <code>MyLib.cpp</code>, i.e. the declaration
of <code>foo</code>, has indeed been "pasted" into <code>main.cpp</code>
as well, via the inclusion of <code>MyLib.hpp</code>.</p>
<div class="collapsible-widget" style="--collapsible-transition-time: .8s;">
<input type="checkbox" value="" name="show more" id="static-libraries-show-more"/>
<label for="static-libraries-show-more">
<p>You can even use the program <code>nm</code> on both <code>*.o</code>
to list the symbols (not the executable code) they contain,
in order to observe how they relate:
</p>
</label>
<div class="collapsible">
<div>
<pre><code class="language-bash">$ nm main.o
0000000000000000 T main
U _Z3foov</code></pre>
<pre><code class="language-bash">$ nm MyLib.o
U __cxa_atexit
U __dso_handle
U _GLOBAL_OFFSET_TABLE_
0000000000000084 t _GLOBAL__sub_I__Z3foov
0000000000000000 T _Z3foov
0000000000000032 t _Z41__static_initialization_and_destruction_0ii
U _ZNSolsEPFRSoS_E
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
U _ZSt4cout
U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000000000 b _ZStL8__ioinit
U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc</code></pre>
<p><code>_Z3foov</code> is a so-called <i>mangled name</i> (which will become important
<a href="#mangled-name-2" id="mangled-name-1">later on</a>),
in which the compiler
encodes the signature of the specific overload of <code>foo</code> in use, and the line
<code>U _Z3foov</code> in <code>main.o</code> is the <i>undefined
reference to <code>`foo()'</code></i> (that <code>U</code> stands for "undefined"); the <code>0000000000000000 T _Z3foov</code>
line in <code>MyLib.o</code> indicates that that file contains the definition
of the same <code>foo</code> that <code>main.o</code> references.
</p>
<p>Another way to visualize this bond between the two files
that does not need an external program like <code>nm</code>
is to look at their assembly code. Let's obtain that code first
</p>
<pre><code class="language-bash">g++ -S main.cpp -o main.s
g++ -S MyLib.cpp -o MyLib.s</code></pre>
<p>and look for <code>_Z3foov</code> in the two files
<code>main.s</code> and <code>MyLib.s</code>.
</p>
<pre><code class="language-x86asm">.file "main.cpp"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
call _Z3foov@PLT
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 12.2.0"
.section .note.GNU-stack,"",@progbits</code></pre>
<pre><code class="language-x86asm"> .file "static.cpp"
.text
.local _ZStL8__ioinit
.comm _ZStL8__ioinit,1,1
.section .rodata
.align 8
.LC0:
.string "Hello world, static library speaking"
.text
.globl _Z3foov
.type _Z3foov, @function
_Z3foov:
.LFB1761:
# more stuff</code></pre>
</div>
</div>
</div>
<p><a href="#the-building-process">Going back to the building process</a>,
once again, it can be executed in one step,
but I think it's instructive to see what happens if you try linking
without telling the linker where <code>MyLib.o</code> is. What you get
is an error from the linker, <code>ld</code>, complaining about
an <b><i>undefined reference</i></b> to <code>foo()</code>:</p>
<pre><code class="language-bash">$ g++ main.o -o main # forgot MyLib.o
/usr/bin/ld: main.o: in function `main':
main.cpp:(.text+0x5): undefined reference to `foo()'
collect2: error: ld returned 1 exit status</code></pre>
<p>And maybe it's even important to know how this error differs
from the one you get if you forget to <code>#include "MyLib.hpp"</code>
in <code>main.cpp</code>, which complains about
<code>foo</code> being <b><i>not declared</i></b>. This is an
error that happens at compile-time, rather than link time,
because <code>main.cpp</code> doesn't even know <code>foo</code>'s
signature.</p>
<pre><code class="language-bash">$ g++ -c main.cpp -o main.o
main.cpp: In function ‘int main()’:
main.cpp:3:5: error: ‘foo’ was not declared in this scope
3 | foo();
| ^~~</code></pre>
<p>(More precisely, the error above happens during
the compilation to assembly, i.e. you get the same
error if you run the command <code>$ g++ -S main.cpp -o main.s</code>.)</p>
<p>At this point one question that might arise is:
where did the code in <code>MyLib.cpp</code> end up
being? You can verify, by getting rid of the <code>*.o</code>
files, that <code>main</code> works well in isolation:
</p>
<pre><code class="language-bash">$ rm MyLib.o main.o
$ ./main
Hello</code></pre>
<p>Therefore,
you can also be sure that all the code it needs, including
the one originally in <code>MyLib.cpp</code> and compiled
in <code>MyLib.o</code>, is indeed
embedded into the binary named <code>main</code>.
In other words, <b><i>the code of a static library becomes
part of the executable file <a href="#linker">at link time</a></i></b>.
</p>
<div class="collapsible-widget">
<input type="checkbox" value="" name="show more" id="static-libraries-are-dot-a-show-more"/>
<label for="static-libraries-are-dot-a-show-more">
<p>To be accurate, by the name <i>static libraries</i> go those files conventionally
named <code>something.a</code>, which are not one single <code>*.o</code> file, but an archive
containing one or more of those.
</p>
</label>
<div class="collapsible">
<div>
<p>For instance the following command creates a properly known static library containing one
object file only
</p>
<pre><code class="language-bash">ar rcs libMyLib.a MyLib.o</code></pre>
<p>which you can link like this</p>
<pre><code class="language-bash">g++ main.o libMyLib.a -o main</code></pre>
<p>The reason why I chose the name <code>libMyLib.a</code> instead of
<code>MyLib.a</code> is that this is customary for static libraries,
so much that there's another syntax for linking them which assumes the
<code>lib</code> prefix in the filename:
</p>
<pre><code class="language-bash">g++ main.o -lMyLib -L. -o main</code></pre>
<p>where <code>-l</code><i><code>name</code></i> tells the linker to look for
a file named <i><code>libname.a</code></i> and <code>-L</code><i><code>dir</code></i>
tells it to look for that file in the directory <i><code>dir</code></i>. Indeed,
if we had named the archive <code>MyLib.a</code>, the command above would error
with a fairly understandable wording:
</p>
<pre><code class="language-bash">/usr/bin/ld: cannot find -lMyLib: No such file or directory
/usr/bin/ld: note to link with ./MyLib.a use -l:MyLib.a or rename it to libMyLib.a
collect2: error: ld returned 1 exit status</code></pre>
</div>
</div>
</div>
<h3 id="dynamic-libraries"><a href="#dynamic-libraries">Dynamic libraries</a></h3>
<p>So we've verified that when linking a <a href="#static-libraries">static library</a>
against a client code, the library's and client's code end up in the same produced executable.
Therefore, if the static library changes, i.e. if its author changes <code>MyLib.cpp</code>,
recompiles it into <code>MyLib.o</code> and gives the latter to you, you still have
to re-link your <code>main.o</code> against the new <code>MyLib.o</code>, otherwise you'll
be still using the old one.
</p>
<p>Is there a way that the library writer can compile the library such that they're
free to change the implementation of the library without forcing us to re-link?
Yes there is.
</p>
<p>Let's make just one little change to the workflow
described above. The source and header files stay the same,
but we compile the library with a different command:
</p>
<pre><code class="language-bash">g++ -fPIC -shared MyLib.cpp -o libMyLib.so</code></pre>
<p>Then we link using the same command as before:</p>
<pre><code class="language-bash">$ g++ main.o libMyLib.so -o main</code></pre>
<p>If we try to run the executable straight away as we did earlier, though,
we get an error,</p>
<pre><code class="language-bash">$ ./main
./main: error while loading shared libraries: libMyLib.so: cannot open shared object file: No such file or directory</code></pre>
<p>This error tells us two things:</p>
<ul>
<li>"<code>error while loading shared libraries</code>"
tells us that linking doesn't embed the library
executable code into the <code>main</code>
executable;</li>
<li>"<code>No such file or directory</code>" tells us that the runtime system
that attempted to start the program couldn't find the library, so
we need a way to instruct it about where to look
for it.
</li>
</ul>
<p>The solution here is easy: we can pass the missing
information via the <code>LD_LIBRARY_PATH</code> macro,
</p>
<pre><code class="language-bash">$ LD_LIBRARY_PATH='.' ./main # . is the current dir, where the library is
Hello</code></pre>
<p>Now it should be clear that if we delete <code>MyLib.so</code>
and run <code>main</code>, we get the same error as before,</p>
<pre><code class="language-bash">$ rm MyLib.so
$ LD_LIBRARY_PATH='.' ./main
./main: error while loading shared libraries: libMyLib.so: cannot open shared object file: No such file or directory</code></pre>
<p>but a more interesting observation is that we can
<i>change</i> <code>MyLib.cpp</code> (but leaving its interface
intact, i.e. we <i>don't</i> change <code>MyLib.hpp</code>),
recompile the library, and executing <code>main</code> will
reflect those changes, without any need to re-link:
</p>
<pre><code class="language-bash">
$ sed -i 's/Hello/Bye/' MyLib.cpp # change Hello to Bye (you can do it any other way)
$ g++ -fPIC -shared MyLib.cpp -o libMyLib.so # recompile only the library
$ LD_LIBRARY_PATH='.' ./main
Bye</code></pre>
<p>Therefore, an author of a dynamic library
can do all the changes they like to the implementation of the
library (but not to the interface they promised), share the
binaries with the client, and the client will just have to
overwrite the old shared objects with the new ones, and the
executable will pick them up. In other words, <i><b>the code
of a dynamic library becomes part of your program at
<strike>runtime</strike> startup time.</b></i>
And this means the <code>*.so</code> file must be there when
you run <code>main</code>, even if <code>main</code> doesn't
make use of it (try removing the call to <code>foo()</code> from
inside <code>main.cpp</code>, recompile and relink it against
<code>libMyLib.so</code>, then delete <code>libMyLib.so</code>,
run <code>LD_LIBRARY_PATH='.' ./main</code> and you'll get same error as above).
</p>
<p>Why have I specifically written <i>"startup time"</i>
rather than <i>"runtime"</i>? Because the runtime system
loads the library even before the actual program starts
executing. How can we verify this? Simple: put a print
statement in <code>main.cpp</code> before the call to
<code>foo</code>, like this
</p>
<pre><code class="language-cpp">// main.cpp
#include "MyLib.hpp"
int main() {
std::cout << "before" << std::endl;
foo();
}</code></pre>
<p>and then</p>
<pre><code class="language-bash">$ g++ -c main.cpp -o main.o
$ g++ main.o libMyLib.so -o main
$ rm libMyLib.so
$ LD_LIBRARY_PATH='.' ./main
./main: error while loading shared libraries: libMyLib.so: cannot open shared object file: No such file or directory
</code></pre>
<p>As you can see, no trace of the text <i>before</i>: the executable
hasn't even started.</p>
<p>This also means, though, that once the executable has started,
you can indeed delete the <code>.so</code> file, and the
running process will not be impacted, which you can verify by
repeating the above process, but changing this
</p>
<pre><code class="language-cpp"> std::cout << "before" << std::endl;</code></pre>
<p>to this</p>
<pre><code class="language-cpp"> int dummy;
std::in << dummy;</code></pre>
<p>re-compiling, re-linking, starting the program, deleting
<code>libMyLib.so</code> while the executable is waiting for
your input, and then entering the input. The program will do
just fine.
</p>
<p>At this point, if you cannot guess already what the
next section is about, I think you probably will if I ask you
two questions:
</p>
<ul>
<li>How much does loading a library cost?</li>
<li>How many libraries are we realistically loading in a non-toy application?</li>
</ul>
<p>Clearly, the answers vary wildly across the use cases, but
the point is that loading a library does have a cost, and for
big programs, especially those with multiple functionalities
that are not all necessarily needed at the same time (or not
at all if the user chooses not to use them in a session of
the program), there can be many of those costs; as many that
they can add up at the expense of the startup time of the
program and, consequently, of the user experience.
</p>
<p>You might now be wondering whether a way exists to load a
dynamic library only when it is needed. This is the question
that leads us to the final section of this post…</p>
<h3 id="dynamic-libraries-lazy-load"><a href="#dynamic-libraries-lazy-load">Lazily loaded dynamic libraries</a></h3>
<p>If the library is not loaded by the runtime system as soon
as we start the program, then who takes of care of loading it?
There's no other answer than "the program" itself. After all,
that's what we want: the program logic to decide when and
if to load the library. And the API to do so is part of the
GNU C library.</p>
<p>Before showing the code, I think it is important to stress
a few points:</p>
<ul>
<li>we already have a dynamic library in place, and from
the perspective of the clients of the library, that's not
gonna change;
</li>
<li>the library implementer can change the implementation of it
(i.g. the <code>MyLib.cpp</code> file), but as long as
they keep the interface (i.e. the <code>MyLib.hpp</code>)
unchanged, for the clients it's just like the library
doesn't change;
</li>
<li>the lazy or eager policy in loading the library is
a decision made on the client side, which the implementer
of the library knows nothing about.
</li>
</ul>
<p>That being said, it should be clear that we will now only
play the role of the library clients, with the aim of loading
the library lazily, during run time, rather than eagerly,
during launch time. For this reason, we'll only have to
review two things:
</p>
<ol>
<li>
the actual code of our application, <code>main.cpp</code>,
to make it actually handle the loading of the library,
</li>
<li>
and the command to build our application (which is fairly
straightforward, if not unsatisfying).
</li>
</ol>
<p>As regards the first point, <code>main.cpp</code> is
now a bit more complicated, because it needs to deal with the
possibility of failure when loading the library and/or