| <?php |
| /******************************************************************************* |
| * Copyright (c) 2015 Eclipse Foundation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Eric Poirier (Eclipse Foundation) - Initial implementation |
| *******************************************************************************/ |
| ?> |
| |
| <h1 class="article-title"><?php echo $pageTitle; ?></h1> |
| |
| <p>No C or C++ programmer likes to see compilation errors due to |
| missing #include statements. Determining what #include statements |
| are required to compile a given program is a tedious task. It |
| becomes even worse when pieces of code are moved from one source |
| file to another. Figuring out which #include statements should be |
| added and which can be removed can easily become a lengthy process |
| of trial and error unless assisted by a software tool.</p> |
| |
| <p> |
| Such a tool is finally available in Eclipse CDT. The <i>Organize |
| Includes</i> command adds missing #include statements, removes |
| unnecessary ones, and even adds forward declarations for symbols |
| that can be forward declared. A programmer can just hit <i>Shift+Ctrl+O</i> |
| and the #include statements are taken care of. Sounds simple, isn’t |
| it? |
| </p> |
| |
| <p>To deliver this simplicity to the user, a lot of work is happening |
| under the hood. Organizing #include statements in C or C++ is a |
| pretty complex task that only on the surface looks similar to |
| organizing imports in Java. Several aspects of C and C++ languages |
| and a wide variation of C/C++ development practices make the problem |
| of organizing #include statements hard.</p> |
| |
| <p>We will now look at different aspects of the problem and learn how |
| CDT approaches them.</p> |
| |
| <h2>Include or Forward Declare</h2> |
| |
| <p>C++ has quite complex rules for when a forward declaration is |
| sufficient and when the definition of a symbol has to be visible at |
| the point of use. Here is a simple example:</p> |
| |
| <pre class="prettyprint lang-xtend"> |
| #include "A.h" |
| A foo(A a) { // definition of A is required |
| return a; |
| } |
| |
| class A; |
| A* bar(A* a) { // definition of A is not required |
| return a; |
| } |
| |
| #include "A.h" |
| void baz(A* a) { |
| a->f(); // definition of A is required |
| } |
| |
| #include "D.h" |
| class E; |
| class C { |
| D x; // definition of D is required |
| static E y; // definition of E is not required |
| }; |
| </pre> |
| <br /> |
| |
| <p>There are also more complex rules. Template type arguments, for |
| example, can be forward declared for some templates but not for |
| others:</p> |
| |
| <pre class="prettyprint lang-xtend"> |
| #include "A.h" |
| class B; |
| std::vector<A> a; // definition of A is required |
| std::shared_ptr<B> b; // definition of B is not required |
| </pre> |
| <br /> |
| |
| <p>It is not possible to tell whether forward declaration of a |
| template argument is sufficient or not without examining details of |
| the template definition.</p> |
| |
| <p> |
| In some cases forward declarations are allowed by the language but |
| should not be used to avoid creating code that is hard to maintain. |
| In addition to following the language rules, <i>Organize Includes</i> |
| allows users to selectively prevent the use of some kinds of forward |
| declarations: |
| </p> |
| |
| <img |
| src="/community/eclipse_newsletter/2013/october/images/octarticle3.1.png" |
| alt="organize includes" width="600" /> |
| <br /> |
| <br /> |
| |
| <h2>Indirect Inclusion</h2> |
| |
| <p>Header files in C and C++ can be included in a source file directly |
| or through other included header files. Sometimes relying on |
| indirect inclusion is ok, but sometimes it may lead to code |
| fragility when seemingly innocent changes not affecting the public |
| API can break compilation of other source files. Consider the |
| following example:</p> |
| <p>GC.h</p> |
| |
| <pre class="prettyprint lang-xtend"> |
| class GC { ... }; |
| </pre> |
| <br /> |
| <p>Graphics.h</p> |
| |
| <pre class="prettyprint lang-xtend"> |
| #include "GC.h" |
| inline void drawLine(int x1, int y1, int x2, int y2) { |
| GC.getCurrent().drawLine(x1, y1, x2, y2); |
| } |
| </pre> |
| <br /> |
| <p>main.cpp</p> |
| <pre class="prettyprint lang-xtend"> |
| #include "Graphics.h" |
| void main() { |
| drawLine(0, 0, 1, 1); |
| GC gc; |
| ... |
| } |
| </pre> |
| <br /> |
| <p>If Graphics.h is refactored by moving the body of the drawLine |
| method and the #include "GC.h" statement to Graphics.cpp, main.cpp |
| will no longer compile.</p> |
| |
| <p> |
| The <a target="_blank" |
| href="https://code.google.com/p/include-what-you-use/w/list"><i>Include |
| What You Use</i> principle</a> is intended to prevent this kind |
| of code fragility. According to this principle main.cpp must include |
| GC.h directly because it uses the GC type defined in that file. |
| </p> |
| |
| <p>Sometimes it is OK to rely on indirect inclusion.</p> |
| |
| <p>MyString.h</p> |
| |
| <pre class="prettyprint lang-xtend"> |
| class MyString { |
| public: |
| MyString(const char* s); |
| }; |
| </pre> |
| <br /> |
| <p>Compare.h</p> |
| |
| <pre class="prettyprint lang-xtend"> |
| #include "MyString.h" |
| int compare(const MyString& s1, const MyString& s2); |
| </pre> |
| <br /> |
| <p>main.cpp</p> |
| |
| <pre class="prettyprint lang-xtend"> |
| #include "Compare.h" |
| int main(int argc, const char* argv[]) { |
| return compare(argv[1], argv[2]); |
| } |
| </pre> |
| <br /> |
| |
| <p>In this example main.cpp can rely on Compare.h providing the |
| definition of MyString class because, due to the existence of the |
| conversion constructor MyString(const char* s), the compare(const |
| MyString& s1, const MyString& s2) method may be called without |
| explicitly mentioning MyString. On the other hand, Compare.h may not |
| be written as:</p> |
| |
| <pre class="prettyprint lang-xtend"> |
| class MyString; |
| int compare(const MyString& s1, const MyString& s2); |
| </pre> |
| <br /> |
| <p>If it were, main.cpp would have to include MyString.h although it |
| does not mention the MyString class anywhere.</p> |
| |
| <p>In some cases indirect inclusion is mandatory since some header |
| files are simply not intended to be included directly. For example, |
| to use std::vector someone has to include <vector>, not |
| <bits/stl_vector.h>, which contains the definition of |
| std::vector.</p> |
| |
| <p> |
| In some cases any of a set of headers can be included for a |
| particular symbol. In such situations <i>Organize Includes</i> tries |
| to include headers that minimize the number of #include statements. |
| </p> |
| |
| <p>The rules for using some header files instead of some other header |
| files are defined through preferences:</p> |
| |
| <img |
| src="/community/eclipse_newsletter/2013/october/images/octarticle3.2.png" |
| alt="header substitution" width="600" /> |
| <br /> |
| <br /> |
| |
| <img |
| src="/community/eclipse_newsletter/2013/october/images/octarticle3.3.png" |
| alt="header substitution map" width="600" /> |
| <br /> |
| <br /> |
| |
| <p>Another factor that contributes to rules for indirect inclusion is |
| include pragmas in header files.</p> |
| |
| <p>facade.h</p> |
| |
| <pre class="prettyprint lang-xtend"> |
| #include "detail/Constants.h" // IWYU pragma: export |
| #include "detail/Types.h" // IWYU pragma: export |
| #include <vector> |
| </pre> |
| <br /> |
| <p>main.cpp</p> |
| |
| <pre class="prettyprint lang-xtend"> |
| #include "Facade.h" |
| #include <vector> |
| std::vector<Thing> things(MAX_THINGS); |
| </pre> |
| <br /> |
| |
| <p>Facade.h exports detail/Types.h and detail/Constants.h and may be |
| included instead of these header files that define the Thing class |
| and the MAX_THINGS constant.</p> |
| |
| <p> |
| Include pragmas are configurable in preferences. The default is |
| compatible with the <a target="_blank" |
| href="https://code.google.com/p/include-what-you-use/wiki/IWYUPragmas">Include-What-You-Use |
| project</a>. |
| </p> |
| |
| <img |
| src="/community/eclipse_newsletter/2013/october/images/octarticle3.4.png" |
| alt="include pragmas" width="600" /> |
| <br /> |
| <br /> |
| |
| <h2>Ordering of #include Statements</h2> |
| |
| <p>There are many different styles for ordering of #include |
| statements. Most of these styles can be represented as some grouping |
| of #include statements with some ordering between groups and |
| alphabetic ordering within each group.</p> |
| |
| <img |
| src="/community/eclipse_newsletter/2013/october/images/octarticle3.5.png" |
| alt="include style" width="600" /> |
| <br /> |
| <br /> |
| |
| <p> |
| A <i>partner header</i> is the header file most closely related to |
| the source file. For example, if MyClass.h contains the definition |
| of MyClass, MyClass.cpp contains the implementation of the class, |
| and MyClassTest.cpp contains a unit test for it, MyClass.h is the |
| partner header for both, MyClass.cpp and MyClassTest.cpp. |
| </p> |
| |
| <img |
| src="/community/eclipse_newsletter/2013/october/images/octarticle3.6.png" |
| alt="include style2" width="600" /> |
| <br /> |
| <br /> |
| |
| <p> |
| All header files that don’t fall into any category with the <i>Keep |
| include statements together</i> option enabled, are grouped under |
| <i>Other Headers</i>. |
| </p> |
| |
| <p> |
| The default style mostly follows the <a target="_blank" |
| href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Names_and_Order_of_Includes">Google |
| C++ Style Guide</a> that is designed to reduce hidden |
| dependencies. |
| </p> |
| |
| <h2>Parting Words</h2> |
| <p> |
| If you are curious how <i>Organize Includes</i> is implemented or |
| would like to extend its functionality, the code is located in the <a |
| href="http://wiki.eclipse.org/Getting_started_with_CDT_development">CDT |
| GIT repository</a> and can be viewed <a |
| href="http://git.eclipse.org/c/cdt/org.eclipse.cdt.git/tree/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes">here</a>. |
| </p> |
| |
| <p>If you don’t like tweaking your tools as long as they work, simply |
| start using Shift+Ctrl+O in C/C++ editor and stop worrying about |
| those messy #include statements.</p> |
| |
| <script |
| src="http://www.eclipse.org/xtend/google-code-prettify/prettify.js" |
| type="text/javascript"></script> |
| <script |
| src="http://www.eclipse.org/xtend/google-code-prettify/lang-xtend.js" |
| type="text/javascript"></script> |
| <script type="text/javascript"> |
| prettyPrint(); |
| </script> |
| |
| <div class="bottomitem"> |
| <h3>About the Authors</h3> |
| |
| <div class="row"> |
| <div class="col-sm-12"> |
| <div class="row"> |
| <div class="col-sm-8"> |
| <img class="author-picture" |
| src="/community/eclipse_newsletter/2013/october/images/sergey75.png" |
| alt="Sergey Prigogin" /> |
| </div> |
| <div class="col-sm-16"> |
| <p class="author-name"> |
| Sergey Prigogin<br /> |
| <a target="_blank" href="http://www.google.com/about/">Google</a> |
| </p> |
| <ul class="author-link"> |
| <!--<li><a target="_blank" href="http://tasktop.com/blog/author/steffenpingel">Blog</a></li> |
| <li><a target="_blank" href="https://twitter.com/steffen_pingel">Twitter</a></li>--> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <script> |
| (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ |
| (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), |
| m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) |
| })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); |
| |
| ga('create', 'UA-34967275-3', 'eclipse.org'); |
| ga('send', 'pageview'); |
| |
| </script> |