Как мне обнаружить ненужные файлы #include в большом проекте C ++? - PullRequest
89 голосов
/ 16 сентября 2008

Я работаю над большим проектом C ++ в Visual Studio 2008, и есть много файлов с ненужными директивами #include. Иногда #include - это просто артефакты, и все будет хорошо скомпилировано с их удалением, а в других случаях классы могут быть заранее объявлены, а #include может быть перемещено в файл .cpp. Есть ли хорошие инструменты для обнаружения обоих этих случаев?

Ответы [ 20 ]

3 голосов
/ 28 сентября 2008

PC-Lint действительно может это сделать. Один из простых способов сделать это - настроить его так, чтобы он обнаруживал только неиспользуемые включаемые файлы и игнорировал все другие проблемы. Это довольно просто - чтобы включить только сообщение 766 («Заголовочный файл не используется в модуле»), просто включите в командную строку опции -w0 + e766.

Тот же подход можно использовать и со связанными сообщениями, такими как 964 («Заголовочный файл не используется напрямую в модуле») и 966 («Косвенно включенный заголовочный файл не используется в модуле»).

FWIW Я написал об этом более подробно в блоге на прошлой неделе на http://www.riverblade.co.uk/blog.php?archive=2008_09_01_archive.xml#3575027665614976318.

2 голосов
/ 17 сентября 2008

Если вы хотите удалить ненужные файлы #include, чтобы сократить время сборки, лучше потратить время и деньги на параллелизацию процесса сборки, используя cl.exe / MP , make -j , Xoreax IncrediBuild , distcc / мороженое и т. д.

Конечно, если у вас уже есть процесс параллельной сборки и вы все еще пытаетесь ускорить его, то обязательно очистите ваши директивы #include и удалите эти ненужные зависимости.

2 голосов
/ 17 сентября 2008

Начните с каждого включаемого файла и убедитесь, что каждый включаемый файл содержит только то, что необходимо для его компиляции. Любые включаемые файлы, которые затем отсутствуют в файлах C ++, могут быть добавлены в сами файлы C ++.

Для каждого включаемого и исходного файла закомментируйте каждый включаемый файл по одному и посмотрите, скомпилируется ли он.

Также рекомендуется сортировать включаемые файлы в алфавитном порядке, а там, где это невозможно, добавьте комментарий.

1 голос
/ 27 апреля 2015

Последняя версия Jetbrains IDE, CLion, автоматически показывает (серым цветом) включения, которые не используются в текущем файле.

Также можно получить список всех неиспользуемых включений (а также функций, методов и т. Д.) Из IDE.

1 голос
/ 01 июня 2011

Если вы будете работать с Eclipse CDT, вы можете попробовать http://includator.com, чтобы оптимизировать структуру включения. Однако Includator может не знать достаточно о предопределенных включениях VC ++, а настройка CDT для использования VC ++ с правильными включениями еще не встроена в CDT.

1 голос
/ 17 сентября 2008

Добавление одного или обоих из следующих #defines исключит часто ненужные заголовочные файлы и может существенно улучшить время компиляции, особенно если код не использует функции Windows API.

#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN

См. http://support.microsoft.com/kb/166474

1 голос
/ 17 сентября 2008

Если вы еще этого не сделаете, использование предварительно скомпилированного заголовка для включения всего, что вы не собираетесь изменять (заголовки платформы, внешние заголовки SDK или статические уже завершенные части вашего проекта), будет иметь огромное значение во времени сборки .

http://msdn.microsoft.com/en-us/library/szfdksca(VS.71).aspx

Кроме того, хотя для вашего проекта это может быть слишком поздно, организация вашего проекта по разделам и не объединение всех локальных заголовков в один большой основной заголовок является хорошей практикой, хотя и требует небольшой дополнительной работы.

0 голосов
/ 11 ноября 2014

Если есть определенный заголовок, который, по вашему мнению, больше не нужен (скажем, string.h), вы можете закомментировать, что включает в себя, а затем поместить это ниже всех включает в себя:

#ifdef _STRING_H_
#  error string.h is included indirectly
#endif

Конечно, заголовки вашего интерфейса могут использовать другое соглашение #define записать их включение в память CPP. Или нет соглашения, в этом случае этот подход не сработает.

Затем восстановите. Есть три варианта:

  • Строится нормально. string.h не был критичным для компиляции, и включаем для него можно удалить.

  • Ошибка срабатывает. string.g был включен как-то косвенно Вы все еще не знаете, требуется ли string.h. Если это требуется, вы должен напрямую #include его (см. ниже).

  • Вы получаете другую ошибку компиляции. string.h был необходим и не является включается косвенно, поэтому включение было правильным для начала.

Обратите внимание, что в зависимости от косвенного включения, когда ваш .h или .c напрямую использует другой .h почти наверняка ошибка: вы фактически обещаете, что ваш код будет требовать только этот заголовок, пока какой-то другой заголовок вы используете требует этого, что, вероятно, не то, что вы имели в виду.

Предостережения, упомянутые в других ответах о заголовках, которые изменяют поведение скорее, здесь также применимы объявления о причинах сбоев сборки.

0 голосов
/ 30 июня 2010

Возможно, немного поздно, но однажды я нашел Perl-скрипт WebKit, который делал именно то, что вы хотели. Я думаю, что потребуется некоторая адаптация (я не очень хорошо разбираюсь в Perl), но это должно помочь:

http://trac.webkit.org/browser/branches/old/safari-3-2-branch/WebKitTools/Scripts/find-extra-includes

(это старая ветка, потому что в стволе больше нет файла)

0 голосов
/ 17 сентября 2008

Некоторые из существующих ответов утверждают, что это сложно. Это действительно так, потому что вам нужен полный компилятор для обнаружения случаев, когда было бы уместным предварительное объявление. Вы не можете разобрать C ++, не зная, что означают символы; грамматика просто слишком неоднозначна для этого. Вы должны знать, называет ли определенное имя класс (может быть объявлен заранее) или переменную (не может). Кроме того, вы должны быть осведомлены о пространстве имен.

...