Remove unused includes from C++ code

Hi guys,
is there a way to remove unused includes from my C++ files? Or do I have to go manually to do that?
I know there are some tools for standard C++, but do they work on Unreal too?
Thank you

I’m pretty sure you need to do it manually and compile outside the editor.

I would expect whatever tool you use to analyze it should work. If not, it’s likely due to the complexity of the source, and whatever tool not being robust enough to handle complex source.

Yeah, maybe I’ll do everything manually.
Perhaps to make things faster I can remove all includes on a cpp file, compile, see the errors and add the needed includes again.
Thank you guys for the help!

Rider greys out unused includes: Inspection: Unused include directive | CLion

1 Like

Nice to know! Unfortunately I use Visual Studio :frowning_face:

Rider for Unreal is a drop-in replacement for Visual Studio. It works seamlessly with .sln / .vcproj files. The UI is very similar to VS, the only difference is that Rider actually works. :slight_smile:

… in very controlled scenarios.

There’s a surprising lack of decent c++ linters, and I definitely would not 100% trust Rider’s “unused include” notification – there’s a reason why C++ Linters don’t seem to incorporate that function, and I don’t know for sure, but I’d suspect that it’s a task that is more difficult than it seems. So if you remove an include at it’s advice, make sure you full build afterwards to make sure you didn’t break anything. Sometimes when you remove that header that isn’t used in file A, it’s also no longer available when file B builds, so you end up needing it in a different file now.

1 Like
  • The damage from a false positive is low. If you accidentally remove a needed include then you’re project just won’t compile, which, as a static error, is not a big deal and easy to fix.

  • If an IDE actually parses the code and forms an accurate compilation database of what entities are defined in what headers, and which entities are used in your translation unit, then it’s trivial to derive which headers are used and which ones are not. The reason linter tools can’t do it is because most of them operate on individual source files, and don’t have the complete compilation database.

  • The whole point of IWYU is that you should include the headers that define entities you use in the translation unit, and not depend on transitive includes. ie If file B.cpp uses entity X defined in X.h, then it should #include directly X.h and not depend on the fact that A.h includes X.h. Having said that, Rider deals which transitive includes just fine afaik.

1 Like

This is definitely the ideal, but in practice it is not what happens. As long as new code compiles, includes are almost never considered. In your example if A.h was already being included, then a use of X would work just fine and most C++ programmers wouldn’t bother looking at the includes until something breaks.

Myself included.

IWYU is also compromised in Unreal by the Unity build process which can mask issues with includes unless you either build with that turned off (which makes the build take longer) or have an automated process that can warn you when it might be an issue.

Certainly, I’m not saying you shouldn’t do this, I’m just saying that if you do remove an include at it’s advice, make sure that your project still builds afterwards. If you’ve got a crusty not well maintained large codebase, be prepared to spend some time.

right, it’s been a long time since I’ve discussed the topic, and the specifics to the reasoning were not coming to me, thanks for the reminder.

It seems a lot more effort has been put into improving developer experiences in more recent languages and their tooling, than into C++ in recent history – as Javascript/TypeScript are the two things I otherwise use outside of Unreal these days, the analysis tools available for those languages seem to far surpass C++. But, also, C++ code tends to be much, much more complex, so… there’s probably a reason there.

I tried to use IWYU inside the IncludeTools extension of Visual Studio but I get a “Couldn’t find a VCLinkerTool in VC++ project” error when I try to use it.
Regarding IWYU of Unreal, I already use it and I already forward declare if it’s possible to do so, but when you refactor some code and delete some things, useless includes can still remain inside the cpp files. I don’t have a deep knowledge of the building system, but I think these useless includes can increase compile times (and maybe make the executable bigger? Don’t know this, correct me if I’m wrong). That’s why I was trying to remove some of the useless includes during my code refactoring process.
Anyway thank you guys for your informations, I find them precious! :smile:

In general unneeded includes and/or transitive includes increase compile-times but do not effect codesize or runtime performance.

Forward declarations are a different story. They do reduce compilation times, but at other costs.

See the entires:

  1. https://google.github.io/styleguide/cppguide.html#Include_What_You_Use

and

  1. https://google.github.io/styleguide/cppguide.html#Forward_Declarations

from the Google C++ Style Guide.

2 Likes