사용하지 않는 포함 된 헤더를 찾는 도구?
PC-Lint 가 포함되어 있지만 사용되지 않은 헤더에 대해 알려줄 수 있다는 것을 알고 있습니다. 이 작업을 수행 할 수있는 다른 도구가 있습니까? 가급적 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 is a lightweight, scriptable, general purpose static analysis tool capable of application-specific analyses of C++ code. In the simplest sense, Dehydra can be thought of as a semantic grep tool.
It should be possible to come up with a script that checks for unused #include files.
Google's cppclean seems to do a decent job of finding unused header files. I just started using it. It produces a few false positives. It will often find unnecessary includes in header files, but what it will not tell you is that you need a forward declaration of the associated class, and the include needs to be moved to the associated source file.
If you are using Eclipse CDT you can try Includator which is free for beta testers (at the time of this writing) and automatically removes superfluous #includes or adds missing ones.
Disclaimer: I work for the company that develops Includator and have been using it for the past few months. It works quite well for me, so give it a try :-)
As far as I know, there isn't one (that isn't PC-Lint), which is a shame, and surprising. I've seen the suggestion to do this bit of pseudocode (which is basically automating your "painstaking process":
for every cpp file
for every header include
comment out the include
compile the cpp file
if( compile_errors )
un-comment out the header
else
remove header include from cpp
Put that in a nightly cron, and it should do the job, keeping the projcet in question free of unused headers (you can always run it manually, obviously, but it'll take a long time to execute). Only problem is when not including a header doesn't generate an error, but still produces code.
I've done this manually and its worth it in the short (Oh, is it the long term? - It takes a long time) term due to reduced compile time:
- Less headers to parse for each cpp file.
- Less dependencies - the whole world doesn't need re-compiling after a change to one header.
Its also a recursive process - each header file that stays in needs examining to see if any header files it includes can be removed. Plus sometimes you can substitute forward declarations for header includes.
Then the whole process needs repeating every few months/year to keep on top of leftover headers.
Actually, I'm a bit annoyed with C++ compilers, they should be able to tell you what's not needed - the Microsoft compiler can tell you when a change to a header file can be safely ignored during compilation.
If someone is interested, I just putted on sourceforge a small Java comand-line tool for doing exactly that. As it is written in Java, it is obviously runable on linux.
The link for the project is https://sourceforge.net/projects/chksem/files/chksem-1.0/
Most approaches for removing unused includes work better if you first make sure that each your header files compiles on its own. I did this relatively quickly as follows (apologies for typos -- I am typing this at home:
find . -name '*.h' -exec makeIncluder.sh {} \;
where makeIncluder.sh
contains:
#!/bin/sh
echo "#include \"$1\"" > $1.cpp
For each file ./subdir/classname.h
, this approach creates a file called ./subdir/classname.h.cpp
containing the line
#include "./subdir/classname.h"
If your makefile
in the . directory compiles all cpp files and contains -I.
, then just recompiling will test that every include file can compile on its own. Compile in your favorite IDE with goto-error, and fix the errors.
When you're done, find . -name '*.h.cpp' -exec rm {} \;
참고URL : https://stackoverflow.com/questions/1301850/tools-to-find-included-headers-which-are-unused
'Program Tip' 카테고리의 다른 글
Nodejs AWS SDK S3 미리 서명 된 URL 생성 (0) | 2020.11.02 |
---|---|
Facebook Graph API를 사용하는 페이지 '좋아요' (0) | 2020.11.02 |
REST를 통한 트랜잭션을 달성 할 수없는 경우 REST가 어떻게 정말로 유용 할 수 있습니까? (0) | 2020.11.02 |
qmake 또는 Qt Creator없이 Qt를 사용할 수 있습니까? (0) | 2020.11.02 |
“git checkout -f”와“git reset --hard HEAD”의 차이점은 무엇입니까? (0) | 2020.11.02 |