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