2012년 11월 21일 수요일

Doxygen - 소스 분석 툴

다른 사람이 작성한 소스코드를 분석하고자 할 때에 유용할 수도(?) 있는 도구 입니다.

C/C++로 작성된 소스 코드를 분석하여 다양한 포맷의 문서로 출력을 해 준다고 합니다.

최근에 소스를 받아서 빌드한 프로그램이 잘 작동하지 않아, 디버깅을 하기 위해 찾아보던 중에 알게 된 것인데 그 사용 방법 및 결과를 간단히 써 보겠습니다.

사용환경은 우분투(Ubuntu) 10.04
doxygen 1.6.3
graphviz 2.20

프로그램의 목적이나 용도만 보아도 꽤 많은 옵션이 있을 수 있는 프로그램입니다.
그런 프로그램이 GUI가 아닌 커맨드 라인 프로그램이니 익히기 껄끄럽겠죠.
혹시나 하고 찾아보니 프론트엔드(front-end) 프로그램으로 doxywizard라는 것이 있습니다.


프로젝트 이름, 소스 디텍토리, 출력 파일 포맷, 분석 옵션 등을 지정해 주면 지정된 출력 포맷으로 분석 결과를 내 줍니다.

특히 분석 옵션 가운데, graphviz 패키지의 기능을 이용하여 함수의 호출관계를 보여주는 옵션을 선택하는 부분이, 가장 많은 시간과 가장 많은 출력 결과물의 크기를 좌우하게 됩니다.

극단적이긴 하지만 약 1.2M byte의 소스 파일을 풀 옵션으로 분석한 결과 시간도 상당히 걸렸지만(수십분 정도), 출력된 파일들의 크기 또한 250M byte에 달하는 것으로 나타났습니다.


그렇게 분석한 결과들의 예를 보면,

메인페이지
클래스 리스트

클래스 계층도

그림으로 나타낸 클래스 계층도

메쏘드의 호출 그래프1
메쏘드의 호출 그래프2

메쏘드의 호출/피호출 그래프


프로젝트를 마치고 프로젝트에 대한 문서를 작성하는 것이라면 꽤나 유용하게 사용할 수 있지 않나 싶습니다만, 소스를 분석하고자 하는 사람들의 일반적인 목적에서의 유용성은 의심이 듭니다.

왜냐하면,
전체적인 프로그램의 흐름을 파악할 방법이 거의 없습니다.
특정한 일부분을 분석하기 위해서도 메쏘드와 멤버들의 유기적인 연관 관계를 보아야 하는데 그런 측면이 약합니다.

즉, 부분 혹은 하나의 개체들에 대한 분석은 완벽할 지 모르나, 그것들을 유기적으로 연결하여 큰 것으로 묶는 것에 있어서는 취약하다는 것입니다.
애초에 그런 역할은 사람에게 남겨진 몫이긴 하나 그 과정을 도와줄 도구 또한 필요합니다.
doxygen의 결과물은 도구의 역할은 하지 못하지만 좋은 참고자료는 될 것 입니다.

따라서 소스를 분석하고자 하는 사람에게 doxygen이 유용한 도구임에는 틀림 없으나 추가적인 도구가 필요함을 잊지 말아야 할 것입니다.

Code:Blocks Debian Package 설치

컴퓨터의 사양이 낮은 관계로 아직까지 Ubuntu 10.04에 머무르고 있는 상황입니다.

Ubuntu는 Software의 설치가 간편하다는 것이 큰 장점입니다.
우분투 소프트웨어 센터를 통해 간단하게 필요한 소프트웨어를 검색 및 설치할 수 있고, 설치된 소프트웨어를 검토하고 제거할 수도 있습니다. 여기에 시냅틱 패키지 관리자는 좀 더 광범위한 소프트웨어를 제공하기에, 어지간한 경우를 제외하고는 목적에 부합하는 소프트웨어를 찾는 것이 어렵지 않습니다.

그러나, 내가 원하는 소프트웨어가 우분투 소프웨어 센터나 시냅틱 패키지 관리자에서 제공되지 않으면 설치하는 데 애를 먹곤 합니다.

현재 사용하고 있는 크롬 브라우저도 비슷한 경우에 해당합니다.
크롬 부라우저를 다운로드 받아서 압축을 풀고 나면 다음과 같은 파일이 나옵니다.
google-chrome-stable_current_i386.deb

이와 같이 확장자가 .deb인 파일은 데비안 패키지를 의미하는 것으로써 /usr/bin/gdebi*를 이용하여 설치가 가능합니다.


리눅스에서 C/C++용으로 쓸만한 IDE 가운데 하나인 Code:Blocks라는 것이 있습니다.
현재 릴리즈된 최신 버전은 10.05입니다만, Ubuntu 10.04의 소프트웨어 센터에서는 그 이전의 버전인 8.02만을 제공하고 있습니다.

그래서 Code:Blocks의 홈페이지에서 10.04 버전을 직접 다운로드 받았습니다.
http://www.codeblocks.org/downloads/26

다운로드 받은 파일의 압축을 풀면 다음과 같이 여러개의 데비안 패키지들이 나옵니다.

데비안 패키지가 하나인 경우에는 문제가 없지만 여러개인 경우에는 설치 순서에 문제가 있을 수 있습니다.

파일의 이름으로 미루어 가장 적절한 패키지를 살펴 보면, 우측상단에서 두번째 파일인 codeblocks_10.05-1_i386.deb입니다. 이걸 gdebi에서 열어 보면,
 libcodeblocks0 패키지를 먼저 설치해야 하는군요.


그럼 libcodeblocks0_10.05-1_i386.deb를 열어보면,

오류는 없으나 패키지 2개를 설치해야 한다는 문구네요.
상세정보를 보면,

혹시나 해서 이름이 비슷한 libwxsmithlib0와 wxsmith*를 열어보니 맨 처음의 codeblocks와 같은 오류가 뜰 뿐입니다.

갑자기 탁 막혀버린 느낌이고 똥개훈련 받고 있는 느낌이고 ㅇㄴ마ㅓ로이ㅑ맨붕ㅠㅠ

저런 경우에는 apt-get으로 패키지를 설치해 주어야 한답니다.

그래서 터미널에서 패키지들을 먼저 설치해 줍니다.
libwxbase2.8-0 설치

libwxgtk2.8-0 설치
위의 패키지들은 시냅틱 패키지 관리자에서도 설치가 가능합니다.

그 후에 libcodeblocks0를 다시 열어보면,
아무 불만이 없나 봅니다^^

이후의 설치 순서는,
libwxsmith0
codeblocks-common
codeblocks-contrib-common

이후에 codeblocks-contrib를 설치하는 부분에서 다시 오류가 뜹니다.

그 이유를 찾아보니, 이전에 설치한 두개의 패키지에 이상한 점이 있습니다.
codeblocks-common과 codeblocks-contrib-common의 패키지 제어 데이터를 보니,


아직 설치하지도 않은 codeblocks와 codeblocks-contrib가 충돌이라고 오류를 낸 것인지, 아니면 저 패키지들과의 충돌 조건이 저러하다고 명시를 한 것인지 모르겠습니다.

무언가 이상하다 생각하고 일단 codeblcoks-common과 codeblocks-contrib-common을 제거하려고 보니, gdebi에서는 패키지를 삭제할 수가 없습니다.

페키지 삭제는 dpkg 혹은 aptitude를 사용하면 됩니다.

이 aptitude를 사용해서 패키지를 찾다 보니, codeblocks의 8.02 패키지에 대한 정보들이 존재합니다. 비록 설치되어 있지는 않지만 8.02 패키지와의 충돌로 이런 문제가 발생한 것이 아닌가 싶습니다.

Code:Blocks의 홈페이지에 있는 포럼에 들어가서 같은 문제를 겪고 있는 사람들의 해결 방안을 찾아 보았습니다.
마침 비슷한 질문이 있었고, 답변이 달려있습니다.

http://forums.codeblocks.org/index.php/topic,16569.0.html


개발자 중의 하나로 보이는데, 패키지 소스 리스트에 서버 URL 하나만 추가하면 된다고 답변이 있습니다.


반신반의 하면서 APT 소스 리스트에 추가를 했습니다.

그리고 시냅틱 패키지 관리자에서 "패키지 정보 새로 고침"이라는 메뉴 항목을 선택하자, 프로그레스 바가 몇 번 진행을 하고나서 Code:Blocks의 정보들이 8.02에서 10.05로 모두 바뀌었습니다!!


우분투 소프트웨어 센터에서도 버전이 바뀐 것이 확인 됩니다만, 설치하려고 하면 인증되지 않은 패키지라는 메시지와 함께 설치가 중단되어 버립니다.

시냅틱 패키지 관리자에서는 같은 경고 메시지가 나오지만 강제로 설치할 수 있습니다.

처음에 길게 썼지만.... 결국엔 리포지터리(저장소) 하나 추가하면 말끔하게 해결되는 일이었습니다.ㅠㅠ

기념으로 시작시에 나오는 타이틀화면

2012년 11월 17일 토요일

XU4 : Ultima4 recreated

Ultima 시리즈 가운데 4번째인 Ultima4 : Quest of the Avatar의 업그레이드 버전인 XU4에 도전해 보았습니다.

이 외에도 각 시리즈별 업그레이드는 다음과 같습니다.
Ultima5 : Lazarus
Ultima6 : Nuvie
Ultima7 : Exult
Ultima8 : Pentagram

도전할 게 뭐가 있냐고 생각할 수도 있지만,  XU4는 윈도우즈와 맥用의 바이너리만 배포합니다. 그러니 우분투에서 사용해 보려면 소스를 컴파일 해야 합니다.

일단 필요한 것을 나열해 보면,
xu4 웹사이트 : http://xu4.sourceforge.net/
xu4 소스 : http://prdownloads.sourceforge.net/xu4/xu4-1.0beta3.tar.gz?download
ultima4(DOS) : http://www.thatfleminggent.com/ultima/u4download.html
ultima4 업그레이드 파일 : http://prdownloads.sourceforge.net/xu4/u4upgrad.zip?download


현재 사용중인 우분투는 10.04 버전입니다.
기본적인 설치를 마친 직후라 추가로 설치해야 하는 패키지들이 있습니다.

libxml2-dev
libsdl1.2-dev
libsdl-mixer1.2-dev
zlib1g-dev
g++

위의 패키지를 시냅틱 패키지 관리자에서 선택해 추가하면, 함께 필요한 패키지들이 자동으로 선택되니 모두 설치하면 됩니다.


이제 소스를 컴파일해 봅니다.
중간에 에러가 나는 경우가 종종 있었는데, 소스를 약간 수정해야만 했습니다.

다음이 수정한 내역입니다.
=================================================================

vc6.h
line 11에 추가
#include <stdlib.h>
#include <string.h>

imagemgr.h
line 105 SubImage *ImageMgr::getSubImage(const std::string &name);
==> SubImage *getSubImage(const std::string &name);

menuitem.cpp
line 7에 추가
#include <stdio.h>

u4file.h
line 13에 추가
#undef putc

lzw/u6decode.cpp
line 36에 추가
#define EXIT_SUCCESS 0
#define EXIT_FAILURE -1
=================================================================

컴파일이 완료되면 몇개의 실행 파일이 생성됩니다.
u4
u4enc
u4dec
tlkconv
dumpsavegame

이 디렉토리에 위에서 받은 ultima4(DOS) 와 Ultima4  업그레이드 파일을 저장해 둡니다.
압축된 상태 그대로 두면 되고 파일의 이름음 ultima4.zip과 u4upgrad.zip으로 되어 있을 것입니다.

압축파일을 다루는데 문제가 좀 있는지 잠깐 로딩 바가 보이다가 종료가 됩니다.
프로그램의 구조를 확인하고 디버깅을 해야 문제를 고칠 수 있지 않을까 싶습니다.

프로그램에 문제가 발생할 경우, 디버깅 방법에 대해 고민을 하곤 합니다.
소스의 구조를 파악해서 논리적으로 문제가 발생한 지점을 찾아낼 것인가?
대략 에러가 난 곳과 의심되는 곳에 메시지를 넣어서 범위를 최소로 줄일 것인가?
디버거를 이용해서 스텝을 따라가면서 문제를 추적할 것인가?

위와 같이 문제가 발생하는 시점과 항상 일정하고 항상 재현이 되는 경우에는 마지막 방법이 좋을 것입니다.

하지만, 내가 만든 소스도 아니고, 소스를 살펴보거나 배우기 위한 것이 아니라....
소스에 포함된 문서를 읽어 보다가, ultima4.zip의 압축을 풀어서 ultima4라는 디렉토리에 넣어 두어도 된다는 문구가 있어 시험 삼아 압축을 풀어 보았습니다.

그냥 실행이 되었습니다.^^
울어야 할지 웃어야 할지.....

암튼 실행 화면이라도 감상해야죠.





=================================================================

디버깅 결과 압축파일에서 원하는 파일을 찾는 부분에 문제가 있었습니다.
그 이유는 ultima4.zip에서 원하는 파일을 찾을 때, <"ultima4/"+파일이름>과 같이 앞 부분에 ultima4라는 디렉토리 이름을 붙여서 찾으려 하고 있기 때문에 원하는 파일을 찾지 못하게 됩니다.
업그레이드 파일인 u4upgrad.zip일 경우에는 디렉토리 이름을 붙이지 않았기에 문제가 없었습니다.

수정해야 할 부분은 u4file.cpp의 238 line입니다.
초기에 압축파일에 대한 정보를 지정하는 부분에서 서브 디렉토리 이름을 지정하지 않도록 수정하는 것입니다.


지금 캡쳐한 사진을 보니, ultima4-1.01.zip인 파일을 사용하는 경우에도 문제가 발생하겠네요.
소스를 수정할 수 없는 상황이라면, 실행 파일이 있는 곳에 ultima4라는 서브디렉토리를 만들고 이곳에 압축 파일을 넣어도 됩니다.

간만에 소스 들여다 보며 디버깅하려니 힘드는군요^^
=================================================================