我知道PC-林特可以告诉你关于被包括在内,但不使用标头。 是否有任何其他工具,可以做到这一点,最好是在Linux上?
我们通过过去15年里已经看到了很多功能的移动周围的一大片代码库,但很少这样做时,移动功能从一个实现文件到另一个,留给我们的这点不错乱七八糟剩下的#include指令移除。 我能明显做删除所有#include指令,并让编译器告诉我哪些是重新纳入的艰苦的事情,但我宁愿解决反向问题 - 找到未使用的 - 而不是重建使用的人的名单。
我知道PC-林特可以告诉你关于被包括在内,但不使用标头。 是否有任何其他工具,可以做到这一点,最好是在Linux上?
我们通过过去15年里已经看到了很多功能的移动周围的一大片代码库,但很少这样做时,移动功能从一个实现文件到另一个,留给我们的这点不错乱七八糟剩下的#include指令移除。 我能明显做删除所有#include指令,并让编译器告诉我哪些是重新纳入的艰苦的事情,但我宁愿解决反向问题 - 找到未使用的 - 而不是重建使用的人的名单。
免责声明:我的日常工作是工作,开发静态分析工具的公司。
我会感到惊讶,如果大部分(如果不是全部)静态分析工具没有某种形式的报头使用支票。 您可以使用此维基百科页面获得的可用工具列表,然后通过电子邮件的公司要问他们。
当你正在评估一个工具,你可以考虑的几点:
对于功能重载,你要包含所有重载头是可见的,不只是包含被重载决议选择的函数头:
// f1.h
void foo (char);
// f2.h
void foo (int);
// bar.cc
#include "f1.h"
#include "f2.h"
int main ()
{
foo (0); // Calls 'foo(int)' but all functions were in overload set
}
如果你采取强制方法,首先删除所有的标题,然后直到它编译,如果“f1.h”先加入,则代码编译,但程序的语义进行了更改重新添加。
当你有局部和专业类似的规则适用。 不要紧,如果选择与否的专业化,你需要确保所有专业都可见:
// f1.h
template <typename T>
void foo (T);
// f2.h
template <>
void foo (int);
// bar.cc
#include "f1.h"
#include "f2.h"
int main ()
{
foo (0); // Calls specialization 'foo<int>(int)'
}
对于过载例如,蛮力方法可能导致在一个程序,它仍然编译,但有不同的行为。
如果类型可以向前声明另一个相关类型的分析,你可以看出来的是检查。 考虑以下:
// A.h
class A { };
// foo.h
#include "A.h"
void foo (A const &);
// bar.cc
#include "foo.h"
void bar (A const & a)
{
foo (a);
}
在上面的例子中,“A”的定义不是必需的,并且因此头文件“foo.h中”可被改变,使得它仅具有用于“A”前向声明:
// foo.h
class A;
void foo (A const &);
这种支票,也减少了头部的依赖。
下面是做它的脚本:
#!/bin/bash
# prune include files one at a time, recompile, and put them back if it doesn't compile
# arguments are list of files to check
removeinclude() {
file=$1
header=$2
perl -i -p -e 's+([ \t]*#include[ \t][ \t]*[\"\<]'$2'[\"\>])+//REMOVEINCLUDE $1+' $1
}
replaceinclude() {
file=$1
perl -i -p -e 's+//REMOVEINCLUDE ++' $1
}
for file in $*
do
includes=`grep "^[ \t]*#include" $file | awk '{print $2;}' | sed 's/[\"\<\>]//g'`
echo $includes
for i in $includes
do
touch $file # just to be sure it recompiles
removeinclude $file $i
if make -j10 >/dev/null 2>&1;
then
grep -v REMOVEINCLUDE $file > tmp && mv tmp $file
echo removed $i from $file
else
replaceinclude $file
echo $i was needed in $file
fi
done
done
看一看Dehydra 。
从网站:
Dehydra是一种重量轻,可脚本,通用静态分析能够的C ++代码应用程序特定的分析工具。 在最简单的意义上说,Dehydra可以被看作是一个语义grep的工具。
应该可以拿出来检查未使用的#include文件的脚本。
谷歌的cppclean似乎做找到未使用的头文件的一份体面的工作。 我刚开始使用它。 它产生一些假阳性。 它会经常发现不必要包含头文件,但它不会告诉你的是,你需要的关联类的前向声明,以及包括需要移动到相应的源文件。
如果您使用的是Eclipse CDT你可以尝试Includator这是免费的beta测试者(在写这篇文章的时间),并自动删除多余的#includes或添加缺少的。
免责声明:我为发展Includator并一直在使用它在过去的几个月里一直在公司工作。 它的工作原理相当不错的我,所以给它一个尝试:-)
据我所知,没有一个(不是PC皮棉),这是一种耻辱,并不足为奇。 我见过的建议,做伪代码的此位(这基本上是自动化的“艰苦的过程”:
每一个CPP文件
对于每头包括
注释掉包括
编译cpp文件
如果(compile_errors)
取消注释掉头
其他
删除头从CPP包括
把在夜间cron,它应该做的工作,保持在释放未使用的头文件(你总是可以手动运行它,很明显,但它会花费很长的时间来执行)的问题projcet。 唯一的问题是,当不包括报头不产生错误,但仍然产生代码。
我手动这样做,它的价值是在短期(哦,是长期的 - 这需要很长的时间?)项由于减少编译时间:
它也是一个递归过程-即停留在需要检查,看看是否有头文件,它包括可移除的头文件。 另外,有时可以替代的前置声明的标题包括。
然后,整个过程需要每隔几个月/年重复保持对剩余的头顶部。
其实,我有点恼火C ++编译器,他们应该能够告诉你什么是没有必要的 - 微软编译器可以告诉你什么时候一个头文件的改变可以在编译过程中忽略。
如果有人有兴趣,我只是推杆sourceforge上正是出于这个做一个小的Java COMAND行工具。 由于它是用Java编写的,这显然是在Linux上可运行。
的链接,该项目是https://sourceforge.net/projects/chksem/files/chksem-1.0/
对于删除未使用的大多数方法包括更好地工作,如果你首先要确保您的每一个头文件编译自身。 我这样做是比较快如下错别字(道歉 - 我在家里打字:
find . -name '*.h' -exec makeIncluder.sh {} \;
其中makeIncluder.sh
包含:
#!/bin/sh
echo "#include \"$1\"" > $1.cpp
对于每个文件./subdir/classname.h
,这种方法创建一个文件名为./subdir/classname.h.cpp
包含线
#include "./subdir/classname.h"
如果您makefile
中。 目录编译所有的cpp文件,并包含-I.
,那么只需要重新编译将测试每一个包含文件可以编译自身。 在你喜欢的IDE与转到错误编译,并修复错误。
当你完成后, find . -name '*.h.cpp' -exec rm {} \;
find . -name '*.h.cpp' -exec rm {} \;