blob: ea3b1f3d74e6a75cfecec8c8c7a20af649c21df3 [file] [log] [blame]
<?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&#60;A&#62; a; // definition of A is required
std::shared_ptr&#60;B&#62; 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 &#60;vector&gt;, not
&#60;bits/stl_vector.h&gt;, 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 &#60;vector&#62;
</pre>
<br />
<p>main.cpp</p>
<pre class="prettyprint lang-xtend">
#include "Facade.h"
#include &#60;vector&#62;
std::vector&#60;Thing&#62; 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>