{"id":7076,"date":"2020-12-02T12:26:58","date_gmt":"2020-12-02T20:26:58","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=7076"},"modified":"2020-12-02T12:26:58","modified_gmt":"2020-12-02T20:26:58","slug":"using-precompiled-headers-to-speed-up-linux-project-building","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/linux\/pch\/","title":{"rendered":"Using Precompiled Headers to Speed Up Linux Project Building"},"content":{"rendered":"<p>This tutorial shows how to use precompiled headers to speed up building of heavy Linux projects. We will create a simple project using the <a href=\"https:\/\/www.boost.org\/\">Boost<\/a> library, will demonstrate how parsing large C++ headers slows down the build, and will then used precompiled headers to speed it up. The techniques shown here will also work for embedded (e.g. STM32) and MinGW-based projects.<\/p>\n<ol>\n<li>Start Visual Studio and open the VisualGDB Linux Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/01-wiz.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7077\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/01-wiz.png\" alt=\"\" width=\"1024\" height=\"680\" \/><\/a><\/li>\n<li>Enter the name and location of the project you would like to create: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/02-name.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7078\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/02-name.png\" alt=\"\" width=\"1024\" height=\"680\" \/><\/a><\/li>\n<li>Select &#8220;Create a new project -&gt; Application -&gt; MSBuild&#8221;. Precompiled headers are supported out-of-the-box for MSBuild projects and can be manually enabled for CMake-based projects: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/03-msbuild.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7079\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/03-msbuild.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Select the Linux machine you would like to target and choose whether you want to build the project directly, or use a cross-compiler. Both options support precompiled headers: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/04-raspi.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7080\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/04-raspi.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Press &#8220;Finish&#8221; to create the project. Once a basic project is created, we will update it to use the <a href=\"https:\/\/www.boost.org\/\">Boost library<\/a> that will considerably slow down the build due to very heavy C++ header files. In order to install Boost on the target, open the SSH console for it:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/05-ssh.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7081\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/05-ssh.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>Then run &#8220;<strong>sudo apt-get install libboost-dev<\/strong>&#8221; or &#8220;<strong>sudo yum install libboost-dev<\/strong>&#8221; depending on the package manager you are using: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/06-boost.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7082\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/06-boost.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>If you are using a cross-compiler, you would need to <a href=\"https:\/\/visualgdb.com\/documentation\/linux\/sysroot\/\">synchronize the sysroot directory<\/a> to make sure the cross-toolchain can find the boost headers and libraries:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/07-sync.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7083\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/07-sync.png\" alt=\"\" width=\"990\" height=\"715\" \/><\/a><\/li>\n<li>Boost gets installed into the regular library locations, so the default sysroot synchronization options will work: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/08-dosync.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7084\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/08-dosync.png\" alt=\"\" width=\"786\" height=\"526\" \/><\/a><\/li>\n<li>Replace the contents of the main source file with the boost <a href=\"https:\/\/www.boost.org\/doc\/libs\/1_71_0\/doc\/html\/boost_asio\/example\/cpp11\/echo\/async_tcp_echo_server.cpp\">asynchronous TCP server example<\/a>. Then add &#8220;<strong>pthread<\/strong>&#8221; and &#8220;<strong>:libboost_system.so.&lt;version&gt;<\/strong>&#8221; to the Additional Library Names in VS Project Properties. Note that Boost uses versioned library names, so just adding &#8220;<strong>boost_system<\/strong>&#8221; to Additional Library Names would not work. Instead, the full library name including the &#8220;<strong>lib<\/strong>&#8221; prefix and the version should be used, prefixed by a colon:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/09-libs.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7085\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/09-libs.png\" alt=\"\" width=\"786\" height=\"544\" \/><\/a><\/li>\n<li>Try building the project and ensure it succeeds. To simulate a larger project with multiple source files using the same headers, add another source file via Solution Explorer:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/10-addsource.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7086\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/10-addsource.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>Copy the <strong>#include&lt;&gt;<\/strong> directives from the main source file to the newly added file and do not add any code after them:\n<pre class=\"\">#include &lt;boost\/asio.hpp&gt;\r\n#include &lt;cstdlib&gt;\r\n#include &lt;iostream&gt;\r\n#include &lt;memory&gt;\r\n#include &lt;utility&gt;<\/pre>\n<\/li>\n<li>Now we will measure the exact time it takes to build the project. Open <strong>VS Project Properties -&gt; Configuration Properties -&gt; Local Build<\/strong> and set <strong>Generate a .bat file<\/strong> to <strong>Yes<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/11-batch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7087\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/11-batch.png\" alt=\"\" width=\"786\" height=\"544\" \/><\/a><\/li>\n<li>Build the project. VisualGDB will generate a batch file with all the build commands. Add &#8220;<strong>echo %time%<\/strong>&#8221; between the GCC invocations to measure the exact time it takes to run gcc: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/12-time.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7088\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/12-time.png\" alt=\"\" width=\"985\" height=\"392\" \/><\/a><\/li>\n<li>Run the batch file and note the times it took for both sources to build: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/13-times-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7102\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/13-times-2.png\" alt=\"\" width=\"743\" height=\"292\" \/><\/a>In this example, the original TCP server example took 7 seconds to build, while an empty source file with just the <strong>#include&lt;&gt;<\/strong> directives took another 5 seconds. If the project was larger, every source file using these header files would take at least 5 seconds to build.<\/li>\n<li>Precompiled headers speed up the building of large projects by first <em>precompiling<\/em> a set of commonly used header files, and then simply loading it for each compiled file. Create a new file called <strong>pch.h<\/strong> and copy the <strong>#include&lt;&gt;<\/strong> directives from either of the source files into it:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/14-pch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7090\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/14-pch.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>Update both source files to include the <strong>pch.h<\/strong> file that, in turn, includes the actual headers: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/15-inc.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7091\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/15-inc.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>Go to <strong>VS Project Properties -&gt; C\/C++ -&gt; Precompiled Headers<\/strong> and set the <strong>Precompiled Header<\/strong> option to &#8220;<strong>Use<\/strong>&#8220;. Also set the precompiled file name to <strong>pch.h<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/16-use.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7092\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/16-use.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<li>Add another source file called <strong>pch.cpp<\/strong>, include <strong>pch.h<\/strong> from it and set &#8220;<strong>Precompiled Header<\/strong>&#8221; to &#8220;<strong>Create<\/strong>&#8221; just for that file: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/17-create.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7093\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/17-create.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a>This ensures that VisualGDB will first precompile <strong>pch.h <\/strong>file into a <strong>.gch<\/strong> file, and will then load when building the regular source files, instead of actually parsing <strong>pch.h<\/strong> over and over. Similarly to the regular Win32 projects, the <strong>pch.cpp<\/strong> file is needed because MSBuild does not build the header files directly.<\/li>\n<li>Build the project and open the updated batch file. Note how it now contains a line for precompiling <strong>pch.h<\/strong>. Add &#8220;<strong>echo %time<\/strong>&#8221; between the compiler invocations:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/18-pch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7094\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/18-pch.png\" alt=\"\" width=\"985\" height=\"426\" \/><\/a><\/li>\n<li>The updated timing shows how precompiling the header file added extra 7.2 seconds at the beginning of the build, however the subsequent compilations of the regular source files were sped up more than 2x:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/19-times-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7103\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/19-times-2.png\" alt=\"\" width=\"979\" height=\"363\" \/><\/a>The overall speedup will be greater for projects with more source files.<\/li>\n<li>Precompiling the headers also speed up partial rebuilds. Modifying the contents of the main source file (but not the headers included from <strong>pch.h<\/strong>) will not require rebuilding the precompiled header file. In this example, it translates to <strong>3.5 seconds + linking time <\/strong>instead of <strong>7.5 seconds + linking time<\/strong>: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/20-onefile-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7105\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/11\/20-onefile-1.png\" alt=\"\" width=\"1193\" height=\"873\" \/><\/a><\/li>\n<\/ol>\n<p>If different source files in your project use different sets of header files, consider moving the most common headers into the <strong>pch.h<\/strong> file. Even if some of these headers are not required by every source file, precompilation may still make the overall build faster. Also because most headers contain a <strong>#pragma once<\/strong> directive, or an <strong>#ifdef<\/strong>-based header guard, you can keep the original <strong>#include&lt;&gt;<\/strong> directives in the source files and duplicate them in <strong>pch.h<\/strong>. As long as <strong>pch.h<\/strong> is included <strong>before<\/strong> the rest of the headers, precompilation will work as expected and redundant <strong>#include&lt;&gt;<\/strong> statements will have no effect.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to use precompiled headers to speed up building of heavy Linux projects. We will create a<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7076"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=7076"}],"version-history":[{"count":1,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7076\/revisions"}],"predecessor-version":[{"id":7106,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7076\/revisions\/7106"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=7076"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=7076"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=7076"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}