1[/
2  Copyright 2015 Peter Dimov
3
4  Distributed under the Boost Software License, Version 1.0.
5
6  See accompanying file LICENSE_1_0.txt or copy at
7  http://boost.org/LICENSE_1_0.txt
8]
9
10[article Boostdep
11  [quickbook 1.6]
12  [id boostdep]
13  [copyright 2014, 2015 Peter Dimov]
14  [license Distributed under the
15    [@http://boost.org/LICENSE_1_0.txt Boost Software License, Version 1.0].
16  ]
17]
18
19[template simplesect[title]
20[block '''<simplesect><title>'''[title]'''</title>''']]
21
22[template endsimplesect[]
23[block '''</simplesect>''']]
24
25[section Introduction]
26
27/Boostdep/ is a tool for generating Boost dependency reports. It scans
28the header or source files of the Boost libraries for `#include`
29directives, builds a dependency graph from this information and outputs
30its findings in plain text or HTML.
31
32[section Modular Boost]
33
34/Boostdep/ requires the so-called "modular Boost" directory structure.
35
36If you already have a [@https://svn.boost.org/trac/boost/wiki/ModularBoost
37modular Boost installation], you can skip this section. Otherwise, read on.
38
39Boost libraries reside in subdirectories under the =libs= directory. For
40example, the contents of the Boost.Filesystem library are in =libs/filesystem=.
41This includes the build scripts (in =libs/filesystem/build=), the source files
42(in =libs/filesystem/src=), the tests (in =libs/filesystem/test=), the documentation
43(in =libs/filesystem/doc=), and so on.
44
45In the past, when Boost used SVN as its version control system, the header files
46were an exception. The header files of all libraries resided in the =boost= subdirectory,
47and it wasn't possible to accurately determine which header belonged to which library.
48
49When Boost moved to Git for version control, header files were moved to their corresponding
50libraries, into an =include= subdirectory. The header files of Boost.Filesystem are now in
51=libs/filesystem/include=.
52
53For compatibility, =boost= is now a "virtual" directory, containing links to the headers.
54It's maintained automatically by Boost.Build. (The command =b2 headers= creates or recreates
55the contents of the =boost= directory.)
56
57This new structure allows /Boostdep/ to determine that, when faced with an
58`#include <boost/filesystem.hpp>` directive, that this header is part of Boost.Filesystem, and
59that therefore, the current library being scanned depends on Boost.Filesystem.
60
61Unfortunately, Boost releases do not have this structure. For backward compatibility, they
62have an old-style =boost= directory containing all header files, whereas the per-library =include=
63subdirectories are missing. Therefore, /Boostdep/ will not work with a downloaded Boost release.
64
65To use /Boostdep/, you will have to clone the Boost Git repository instead. To do that, execute the
66following command:
67
68[pre
69git clone https://github.com/boostorg/boost.git boost
70]
71
72This will download the Boost "superproject" (the master project, without any libraries) and place it
73into the subdirectory =boost= of the current directory. To override the directory name, pass it as a
74second argument instead of =boost=:
75
76[pre
77git clone https://github.com/boostorg/boost.git /mydir/
78]
79
80You can now =cd= into the newly created directory with
81
82[pre
83cd /mydir/
84]
85
86This directory is called the "Boost root". All of the commands below assume that it is the current directory.
87
88The above =git clone= commands download the default branch of the Boost Git repository, which is =master=.
89This is the current more-or-less stable version of Boost.
90
91To verify this, issue the command
92
93[pre
94git status
95]
96
97from the Boost root. This will output
98
99[pre
100# On branch master
101nothing to commit, working directory clean
102]
103
104To download a specific release instead, such as 1.58.0, issue the following command after =git clone=, from
105the Boost root:
106
107[pre
108git checkout boost-1.58.0
109]
110
111=git status= will now say
112
113[pre
114# HEAD detached at boost-1.58.0
115nothing to commit, working directory clean
116]
117
118Then, download all the libraries:
119
120[pre
121git submodule update --init
122]
123
124This step will take a while.
125
126If all goes well, you will now have the complete contents of Boost's latest =master= branch (if you didn't =checkout=
127a specific release by name) or the corresponding Boost release (if you did).
128
129You can switch between the =master= branch, the =develop= (unstable) branch, and a release, by issuing the following
130commands:
131
132[:For the =master= branch:]
133
134[pre
135git checkout master
136git pull
137git submodule update --init
138]
139
140[:(=git pull= updates your local copy of the =master= branch from the server, in case it has changed since your initial
141checkout.)]
142
143[:For the =develop= branch:]
144
145[pre
146git checkout develop
147git pull
148git submodule update --init
149]
150
151[:For the =boost-1.58.0= release:]
152
153[pre
154git checkout boost-1.58.0
155git submodule update --init
156]
157
158[:For the =boost-1.57.0= release:]
159
160[pre
161git checkout boost-1.57.0
162git submodule update --init
163]
164
165Note that, while the initial =git submodule update= is quite slow, as it needs to download all the libraries, the
166subsequent invocations are a lot faster.
167
168Also note that if a new Boost library (=libs/convert=, for example) is present in, say, =master=, and you have it checked out,
169when you later switch to =boost-1.58.0=, where this library doesn't exist, Git will not delete =libs/convert=. In this case,
170=git status= will output
171
172[pre
173# HEAD detached at boost-1.58.0
174# Untracked files:
175#   (use "git add <file>..." to include in what will be committed)
176#
177#       libs/convert/
178nothing added to commit but untracked files present (use "git add" to track)
179]
180
181and you will have to remove =libs/convert= by hand.
182
183Once you have the Boost contents which you want to analyze for dependencies, proceed with the next step, building /Boostdep/.
184
185[endsect]
186
187[section Building Boostdep]
188
189To build /Boostdep/, issue the following command from the Boost root:
190
191[pre
192b2 tools/boostdep/build//install
193]
194
195This will build /Boostdep/ from source using the default "toolset" (a Boost.Build term meaning "compiler") and if successful,
196place it into the =dist/bin= subdirectory. The command assumes that =b2= (the Boost.Build executable) is somewhere in your path.
197If you don't have =b2=, execute
198
199[pre
200.\bootstrap
201]
202
203under Windows or
204
205[pre
206./bootstrap.sh
207]
208
209under Unix-like systems, which should build =b2= and place it into the current directory. You can then use =./b2= instead of =b2=.
210
211[endsect]
212
213[section Running Boostdep]
214
215Once you have built /Boostdep/, execute it with the following command:
216
217[pre
218dist/bin/boostdep
219]
220
221or
222
223[pre
224dist\bin\boostdep
225]
226
227on Windows. The commands below are given as using =dist/bin/boostdep=; if you're using Windows, use =dist\bin\boostdep= instead.
228
229This will print out the following help message:
230
231[pre
232Usage:
233
234    boostdep --list-modules
235    boostdep --list-buildable
236    boostdep \[--track-sources\] --list-dependencies
237
238    boostdep \[options\] --module-overview
239    boostdep \[options\] --module-levels
240    boostdep \[options\] --module-weights
241
242    boostdep \[options\] \[--primary\] <module>
243    boostdep \[options\] --secondary <module>
244    boostdep \[options\] --reverse <module>
245    boostdep \[options\] \[--header\] <header>
246
247    \[options\]: \[--track-sources\] \[--title <title>\] \[--footer <footer>\] \[--html\]
248]
249
250(The 1.58.0 version of /Boostdep/ has an unfortunate bug that causes the above output to be truncated after =boostdep --list-modules=.
251The rest of the functionality is intact though, so you can still use it as described.)
252
253[endsect]
254
255[endsect]
256
257[section Usage]
258
259[section Simple Queries]
260
261To list the dependencies of a specific library, use the command
262
263[pre
264dist/bin/boostdep /library/
265]
266
267For Boost.Filesystem, for example, type
268
269[pre
270dist/bin/boostdep filesystem
271]
272
273This will print out something similar to the following:
274
275[pre
276Primary dependencies for filesystem:
277
278assert:
279    <boost/assert.hpp>
280        from <boost/filesystem/operations.hpp>
281        from <boost/filesystem/path_traits.hpp>
282
283config:
284    <boost/config.hpp>
285        from <boost/filesystem/config.hpp>
286        from <boost/filesystem/convenience.hpp>
287        from <boost/filesystem/fstream.hpp>
288        from <boost/filesystem/operations.hpp>
289        from <boost/filesystem/path.hpp>
290        from <boost/filesystem/path_traits.hpp>
291    /.../
292
293functional:
294    <boost/functional/hash_fwd.hpp>
295        from <boost/filesystem/path.hpp>
296
297io:
298    <boost/io/detail/quoted_manip.hpp>
299        from <boost/filesystem/path.hpp>
300
301iterator:
302    <boost/iterator/iterator_facade.hpp>
303        from <boost/filesystem/path.hpp>
304    /.../
305]
306
307This lists the immediate dependencies of Boost.Filesystem. =assert:= is the library,
308=<boost/assert.hpp>= is the file that is being included, and =from <boost/filesystem/config.hpp>=
309shows where =<boost/assert.hpp>= is being included.
310
311/Boostdep/ names libraries (or modules) after their directory name. The =libs/filesystem=
312directory, for example, is the =filesystem= module. The =libs/numeric/conversion= directory
313is the =numeric~conversion= module, according to the /Boostdep/ naming convention.
314
315The reason forward slashes are replaced with tildes is that =numeric~conversion= is a valid
316file name, which makes generating HTML reports a bit easier.
317
318To see where a given header resides and who includes it, type
319
320[pre
321dist/bin/boostdep /header/
322]
323
324For =boost/filesystem.hpp=, for example, type
325
326[pre
327dist/bin/boostdep boost/filesystem.hpp
328]
329
330This will print something along the lines of
331
332[pre
333Inclusion report for <boost/filesystem.hpp> (in module filesystem):
334
335    from spirit:
336        <boost/spirit/home/x3/support/utility/testing.hpp>
337]
338
339What this tells you is that =boost/filesystem.hpp= is part of Boost.Filesystem and is only
340included once, from =<boost/spirit/home/x3/support/utility/testing.hpp>=. Other headers,
341such as =boost/shared_ptr.hpp=, are more widely used, as you can see if you try
342
343[pre
344dist/bin/boostdep boost/shared_ptr.hpp
345]
346
347To print the reverse dependencies of a library, use
348
349[pre
350dist/bin/boostdep --reverse /library/
351]
352
353For example,
354
355[pre
356dist/bin/boostdep --reverse filesystem
357]
358
359will list which libraries depend on Boost.Filesystem:
360
361[pre
362Reverse dependencies for filesystem:
363
364graph_parallel:
365    <boost/filesystem/operations.hpp>
366        from <boost/graph/distributed/adjlist/serialization.hpp>
367    <boost/filesystem/path.hpp>
368        from <boost/graph/distributed/adjlist/serialization.hpp>
369
370log:
371    <boost/filesystem/config.hpp>
372        from <boost/log/detail/config.hpp>
373    <boost/filesystem/path.hpp>
374        from <boost/log/sinks/event_log_backend.hpp>
375        from <boost/log/sinks/text_file_backend.hpp>
376        from <boost/log/sinks/text_multifile_backend.hpp>
377
378spirit:
379    <boost/filesystem.hpp>
380        from <boost/spirit/home/x3/support/utility/testing.hpp>
381    <boost/filesystem/fstream.hpp>
382        from <boost/spirit/home/x3/support/utility/testing.hpp>
383    <boost/filesystem/path.hpp>
384        from <boost/spirit/home/x3/support/utility/error_reporting.hpp>
385
386wave:
387    <boost/filesystem/operations.hpp>
388        from <boost/wave/util/cpp_include_paths.hpp>
389        from <boost/wave/util/cpp_iterator.hpp>
390        from <boost/wave/util/filesystem_compatibility.hpp>
391    <boost/filesystem/path.hpp>
392        from <boost/wave/cpp_context.hpp>
393        from <boost/wave/util/cpp_include_paths.hpp>
394        from <boost/wave/util/cpp_iterator.hpp>
395        from <boost/wave/util/cpp_macromap.hpp>
396        from <boost/wave/util/filesystem_compatibility.hpp>
397]
398
399[endsect]
400
401[section HTML reports]
402
403The primary purpose of /Boostdep/ is to generate HTML dependency reports. In
404the typical case, two types of reports are generated: overviews that contain
405information for all modules, and per-module ones that list information for a
406specific library.
407
408/Boostdep/ can generate three types of the first kind of report: module overview,
409module levels and module weights. To generate a module overview, use the command
410
411[pre
412dist/bin/boostdep --html --module-overview > module-overview.html
413]
414
415For a module level report, use
416
417[pre
418dist/bin/boostdep --html --module-levels > module-levels.html
419]
420
421For a module weight report, use
422
423[pre
424dist/bin/boostdep --html --module-weights > module-weights.html
425]
426
427In these reports, module names such as /module/ are HTML links to [^/module/.html].
428
429To make these links work as expected, you can generate HTML reports for each module
430as follows:
431
432[pre
433dist/bin/boostdep --title "Dependency Report for /module/" --html --primary /module/ --secondary /module/ --reverse /module/ > /module/.html
434]
435
436This step can be automated if you generate a module list first with
437
438[pre
439dist/bin/boostdep --list-modules > list-modules.txt
440]
441
442that will contain one module name per line, and then use a script to issue the previous
443command for each module name.
444
445For more information about the /Boostdep/ options and commands, see the [link boostdep.reference Reference] section.
446
447For an example of a report generation script, see the file =tools/boostdep/examples/report.bat=.
448This is a Windows batch file, but translating it to a Unix-style shell script should be
449straightforward.
450
451For convenience, the contents of =tools/boostdep/examples/report.bat= are given below:
452
453[pre
454SET BOOSTDEP=dist\bin\boostdep.exe
455
456FOR /f %%i IN ('git rev-parse HEAD') DO @SET REV=%%i
457
458FOR /f %%i IN ('git rev-parse --short HEAD') DO @SET SHREV=%%i
459
460FOR /f %%i IN ('git rev-parse --abbrev-ref HEAD') DO @SET BRANCH=%%i
461
462SET FOOTER=Generated on %DATE% %TIME% from revision %REV% on branch '%BRANCH%'
463
464SET OUTDIR=..\report-%BRANCH%-%SHREV%
465
466mkdir %OUTDIR%
467
468%BOOSTDEP% --list-modules > %OUTDIR%\list-modules.txt
469
470%BOOSTDEP% --footer "%FOOTER%" --html --module-overview > %OUTDIR%\module-overview.html
471%BOOSTDEP% --footer "%FOOTER%" --html --module-levels > %OUTDIR%\module-levels.html
472%BOOSTDEP% --footer "%FOOTER%" --html --module-weights > %OUTDIR%\module-weights.html
473
474FOR /f %%i IN (%OUTDIR%\list-modules.txt) DO %BOOSTDEP% --title "Dependency Report for %%i" --footer "%FOOTER%" --html --primary %%i --secondary %%i --reverse %%i > %OUTDIR%\%%i.html
475]
476
477[endsect]
478
479[endsect]
480
481[section Reference]
482
483[section --list-modules]
484=boostdep --list-modules= prints the module list. /Boostdep/ considers a
485subdirectory of =libs= a module if it contains an =include= subdirectory.
486
487This command is typically used from scripts which then use the list to execute
488a command for each module.
489[endsect]
490
491[section --list-buildable]
492=boostdep --list-modules= prints a list of the modules that require building.
493/Boostdep/ considers a module to require building if it contains subdirectories
494named =build= and =src=.
495
496This command is typically used from scripts.
497
498[endsect]
499
500[section --list-dependencies]
501=boostdep --list-dependencies= prints a module list in which each line is of the
502form
503
504[pre
505module -> dependency1 dependency2 /.../
506]
507
508By default, only the =include= directory is scanned for `#include` directives. If
509the option =--track-sources= is given, the =src= directory is also scanned.
510
511This command is typically used from scripts. The output is virtually identical to
512=--module-overview= in plain text, but slightly more machine-friendly.
513[endsect]
514
515[section --module-overview]
516=boostdep --module-overview= generates a module overview, in plain text or HTML. The
517plain text output is of the form
518
519[pre
520Module Overview:
521
522accumulators -> array assert circular_buffer concept_check config core fusion iterator mpl numeric~conversion numeric~ublas parameter preprocessor range static_assert throw_exception tuple type_traits typeof
523algorithm -> array assert bind concept_check config core exception function iterator mpl range regex static_assert tuple type_traits unordered
524align -> assert config core static_assert throw_exception
525]
526
527whereas the HTML output is similar to
528
529[:
530*Module Overview*
531
532[*/accumulators/]
533
534\u21E2 array assert circular_buffer concept_check config core fusion iterator mpl numeric~conversion numeric~ublas parameter preprocessor range static_assert throw_exception tuple type_traits typeof
535]
536
537where /accumulators/ is a link to =accumulators.html=.
538
539As before, if =--track-sources= is given, the =src= subdirectory is scanned for `#include` directives.
540
541HTML output is enabled by the =--html= option. The =--title= and =--footer= options set the HTML =<title>=
542and the page footer and need to precede =--html=, like in the following example:
543
544[pre
545dist/bin/boostdep --title "Module Overview" --footer "Generated on 21.05.2015 20:53:11" --html --module-overview > module-overview.html
546]
547
548[endsect]
549
550[section --module-levels]
551
552=boostdep --module-levels= generates a report that groups modules by level. Levels are determined in such
553a way so that a module of level =N= never depends on modules of levels greater than =N=, and in the absence
554of cyclical dependencies, doesn't depend on other modules of level =N=. It takes the same options as
555=--module-overview=.
556
557[pre
558dist/bin/boostdep --title "Module Levels" --footer "Generated on 21.05.2015 20:53:11" --html --module-levels > module-levels.html
559]
560
561[endsect]
562
563[section --module-weights]
564
565=boostdep --module-weights= generates a report that lists modules by weight. A module weight is the total number of
566its dependencies. This includes the indirect dependencies.
567
568=--module-weights= takes the same options as =--module-overview=.
569
570[pre
571dist/bin/boostdep --title "Module Weights" --footer "Generated on 21.05.2015 20:53:11" --html --module-weights > module-weights.html
572]
573
574[endsect]
575
576[section --primary]
577
578[^boostdep --primary /module/] lists the primary (direct) dependencies of /module/. It takes the same options as =--module-overview=.
579
580[pre
581dist/bin/boostdep --title "Primary Dependencies of filesystem" --footer "Generated on 21.05.2015 20:53:11" --html --primary filesystem > filesystem-primary.html
582]
583
584[endsect]
585
586[section --secondary]
587
588[^boostdep --secondary /module/] lists the secondary (indirect) dependencies of /module/. It takes the same options as =--module-overview=.
589
590[pre
591dist/bin/boostdep --title "Secondary Dependencies of filesystem" --footer "Generated on 21.05.2015 20:53:11" --html --secondary filesystem > filesystem-secondary.html
592]
593
594You can combine =--primary= and =--secondary= in one invocation.
595
596[pre
597dist/bin/boostdep --title "Dependencies of filesystem" --footer "Generated on 21.05.2015 20:53:11" --html --primary filesystem --secondary filesystem > filesystem.html
598]
599
600[endsect]
601
602[section --reverse]
603
604[^boostdep --reverse /module/] lists the reverse dependencies of /module/, that is, it lists which modules depend on /module/. It takes the same options as =--module-overview=.
605
606[pre
607dist/bin/boostdep --title "Reverse Dependencies of filesystem" --footer "Generated on 21.05.2015 20:53:11" --html --reverse filesystem > filesystem-reverse.html
608]
609
610You can combine =--reverse= with =--primary= and =--secondary= for a complete module report.
611
612[pre
613dist/bin/boostdep --title "Dependency Report for filesystem" --footer "Generated on 21.05.2015 20:53:11" --html --primary filesystem --secondary filesystem --reverse filesystem > filesystem.html
614]
615
616[endsect]
617
618[section --header]
619
620[^boostdep --header /header/] creates an inclusion report for /header/. It takes the same options as =--module-overview=.
621
622[pre
623dist/bin/boostdep --title "Inclusion Report for <boost/shared_ptr.hpp>" --footer "Generated on 21.05.2015 20:53:11" --html --header boost/shared_ptr.hpp > header-boost-shared_ptr.html
624]
625
626[endsect]
627
628[section --track-sources]
629
630The =--track-sources= option instructs /Boostdep/ to scan the =src= library subdirectory for `#include` directives. By default,
631only the =include= subdirectory is scanned.
632
633[endsect]
634
635[section --title]
636
637[^--title /title/] sets the contents of the HTML =<title>= tag. It must precede =--html= to have an effect.
638
639[endsect]
640
641[section --footer]
642
643[^--footer /footer/] sets the page footer text. It has no effect if =--html= is not given.
644
645[endsect]
646
647[section --html]
648
649=--html= switches to HTML output mode (the default is plain text). It must precede the commands that generate output.
650
651[endsect]
652
653[endsect]
654