Я часто замечаю, что раздел заголовков файла все время становится все больше и больше, но никогда не становится меньше. На протяжении жизни исходного файла классы могли перемещаться и подвергаться рефакторингу, и вполне возможно, что есть довольно много #includes, которым не нужно больше присутствовать. Оставляя их там, вы только увеличиваете время компиляции и добавляете ненужные зависимости компиляции. Попытка выяснить, какие из них еще нужны, может быть довольно утомительной.
Есть ли какой-то инструмент, который может обнаруживать лишние директивы #include и предлагать, какие из них я могу безопасно удалить? Может ли lint это сделать?
См. Также: stackoverflow.com/questions/74326/ Eclipse 19.06.2009
Связанный вопрос, похоже, решает проблему только в Windows, в частности с использованием Visual Studio. D'Nabre 07.11.2014
Голосование за повторное открытие, поскольку дубликат, в частности, касается использования Visual Studio. Drew Dormann 14.05.2015
Это не происходит автоматически, но doxygen создаст диаграммы зависимостей для #included файлов. Вам нужно будет просмотреть их визуально, но они могут быть очень полезны для получения представления о том, что и что использует.
Ответ 2 · рейтинг 187 · Josh Kelley
Cppclean от Google (ссылки на: загрузить, documentation) может найти несколько категорий проблем C ++, а теперь может найти лишние #includes.
Также существует инструмент на основе Clang, include-what-you-use, которые могут это сделать. include-what-you-use может даже предлагать форвардные объявления (так что вам не нужно так много #include) и, при необходимости, очищать ваши #includes за вас.
В текущих версиях Eclipse CDT также встроена эта функция: переход в меню "Источник" и нажатие "Организовать включает" приведет к расположите в алфавитном порядке ваши # include, добавьте любые заголовки, которые, по мнению Eclipse, вы используете, не включая их напрямую, и закомментируйте любые заголовки, которые, по его мнению, вам не нужны. Однако эта функция не на 100% надежна.
Проблема с обнаружением лишних включений заключается в том, что это не может быть просто средство проверки зависимостей типов. Излишнее включение - это файл, который ничего не представляет для компиляции и не изменяет другой элемент, от которого зависят другие файлы. Есть много способов, которыми файл заголовка может изменить компиляцию, например, путем определения константы, переопределения и / или удаления используемого макроса, добавления пространства имен, которое изменяет поиск имени в некоторой степени вниз по строке. Для обнаружения таких элементов, как пространство имен, вам нужно гораздо больше, чем препроцессор, вам фактически почти нужен полноценный компилятор.
Lint - это скорее средство проверки стиля и, конечно же, не будет иметь такой полной возможности.
Я думаю, вы найдете единственный способ обнаружить лишнее включение - это удалить, скомпилировать и запустить наборы.
Ответ 5 · рейтинг 15 · itsmatt
Я думал, что PCLint сделает это, но прошло несколько лет с тех пор, как я посмотрел на это. Вы можете это проверить.
Я просмотрел этот блог, и автор немного поговорил о настройке PCLint для поиска неиспользуемых включений. Стоит взглянуть.
Ответ 6 · рейтинг 7 · Diomidis Spinellis
Браузер с рефакторингом CScout может обнаруживать лишние директивы include в коде C (к сожалению, не C ++). Вы можете найти описание того, как это работает, в этой журнальной статье.
Ответ 7 · рейтинг 5 · Gilad Naor
Вы можете написать быстрый сценарий, который стирает одну директиву #include, компилирует проекты и регистрирует имя в #include и файл, из которого он был удален, в случае, если ошибок компиляции не произошло.
Дайте ему поработать на ночь, и на следующий день у вас будет 100% правильный список включаемых файлов, которые вы можете удалить.
Иногда просто срабатывает брутфорс :-)
изменить: а иногда нет :-). Вот немного информации из комментариев:
Иногда можно удалить два файла заголовков по отдельности, но не оба вместе. Решение состоит в том, чтобы удалить файлы заголовков во время выполнения и не возвращать их. Будет найден список файлов, которые вы можете безопасно удалить, хотя может быть решение с большим количеством файлов для удаления, которые этот алгоритм не найдет. (это жадный поиск по пространству включаемых файлов для удаления. Будет найден только локальный максимум)
В поведении могут быть небольшие изменения, если некоторые макросы переопределены по-разному в зависимости от некоторых #ifdef. Я думаю, что это очень редкие случаи, и модульные тесты, которые являются частью сборки, должны улавливать эти изменения.
Ответ 8 · рейтинг 5 · Dan
Извините за (повторно) публикацию здесь, люди часто не расширяют комментарии.
Прочтите мой комментарий к crashmstr, FlexeLint / PC-Lint сделает это за вас. Информационное сообщение 766. Это обсуждается в разделе 11.8.1 моего руководства (версия 8.0).
Кроме того, и это важно, продолжайте повторять, пока сообщение не исчезнет. Другими словами, после удаления неиспользуемых заголовков и повторного запуска lint дополнительные файлы заголовков могут стать "ненужными" после удаления некоторых ненужных заголовков. (Это может показаться глупым, прочтите это медленно и проанализируйте, это имеет смысл.)
Ответ 9 · рейтинг 5 · Dan Olson
Я никогда не находил полноценного инструмента, который бы выполнял то, о чем вы просите. Ближайшая вещь, которую я использовал, - это IncludeManager, которая отображает дерево включения заголовка, чтобы вы могли визуально обнаруживать такие вещи, как заголовки, включенные только в один файл, и включения круглых заголовков.
Ответ 10 · рейтинг 4 · Ben Martin
Я пробовал использовать Flexelint (unix-версию PC-Lint) и получил несколько неоднозначные результаты. Вероятно, это потому, что я работаю над очень большой и запутанной кодовой базой. Я рекомендую внимательно изучить каждый файл, который считается неиспользованным.
Главное беспокойство - это ложные срабатывания. Несколько включений одного и того же заголовка сообщаются как ненужный заголовок. Это плохо, поскольку Flexelint не сообщает вам, в какую строку включен заголовок или где он был включен раньше.
Один из способов, которым автоматизированные инструменты могут ошибиться:
В A.hpp:
class A {
// ...
};
В B.hpp:
#include "A.hpp
class B {
public:
A foo;
};
В C.cpp:
#include "C.hpp"
#include "B.hpp" // <-- Unneeded, but lint reports it as needed
#include "A.hpp" // <-- Needed, but lint reports it as unneeded
Если вы слепо следите за сообщениями Flexelint, вы испортите свои #include зависимости. Есть и другие патологические случаи, но в основном вам нужно будет проверить заголовки самостоятельно для достижения наилучших результатов.
Я настоятельно рекомендую эту статью о Physical Structure и C ++ из блога Games изнутри. Они рекомендуют комплексный подход к устранению беспорядка #include:
Руководящие указания
Вот обобщенный набор рекомендаций из книги Лакоса, которые минимизируют количество физических зависимостей между файлами. Я использую их в течение многих лет и всегда был очень доволен результатами.
Каждый файл cpp сначала включает собственный файл заголовка. [отрывок]
Заголовочный файл должен включать все заголовочные файлы, необходимые для его анализа. [отрывок]
Заголовочный файл должен иметь минимальное количество заголовочных файлов, необходимое для его анализа. [отрывок]
Ответ 11 · рейтинг 4 · PeterSom
Если вы используете Eclipse CDT, вы можете попробовать http://includator.com, который бесплатен для бета-тестеров (во время это письмо) и автоматически удаляет лишние #includes или добавляет недостающие. Для тех пользователей, у которых есть FlexeLint или PC-Lint и которые используют Elicpse CDT, вариантом может быть http://linticator.com. (также бесплатно для бета-тестирования). Хотя он использует анализ Lint, он предоставляет быстрые исправления для автоматического удаления лишних операторов #include.
Ответ 12 · рейтинг 2 · Steve Gury
В этой статье объясняется техника удаления #include с помощью синтаксического анализа Doxygen. Это просто Perl-скрипт, поэтому пользоваться им довольно просто.