아주 오래 전부터 적용시키고 싶은 패치가 하나 있었다. 바로 KDE 3.x CP949 패치이다. Konversation이 자꾸 죽는 것은 둘째치더라도, 매일같이 뤂놈을 갈궈야 하는데 뤂이라는 글자는 EUC-KR에는 포함되지 않기 때문에, 프록시로 사용하고 있는 irssi를 켜서 뤂이라는 글자를 입력해 주는 수고를 해야만 했다. 그래서 해결책으로 Qt 3.x에 CP949 코덱을 추가하고, KDE 라이브러리에서 추가한 코덱을 인식시켜 주는 패치를 하면 되긴 된다. 허나 시도를 하면 할 때마다 실패해서 도대체 뭐가 문제인지 몰랐다. 며칠 전에 내가 미쳤는지 삽질을 해서 해결하기 시작했다.
Qt는 다양한 언어로 된 텍스트를 처리하기 위해서 텍스트 코덱이라는 것을 사용한다. 제일 미치고 환장하는 게 왜 Qt는 iconv라는 좋은 걸 놔두고 이딴 걸 쓰느냐기본적으로 들어있는 텍스트 코덱이 EUC-KR까지만 지원한다는 것이다. 하여튼 저기 용자 segfault 햏이 CP949를 지원하는 텍스트 코덱을 만들어서 트롤텍노키아에 갖다 바쳐서 Qt 4.3.0부터는 기본적으로 CP949 지원이 들어 있지만, 그 이전 버전이라면 대책이 없다. 여튼 Qt 3.x용으로 나온 CP949 패치와 KDE 라이브러리 패치를 여기에서 긁어서 빌드하기 시작했다.
일단 Qt 3.x용 CP949 코덱은 걍 빌드가 된다. 걍 빌드가 된다. 다음으로 남은 큰일은 고행이라고도 할 수 있는 KDE 라이브러리 패치이다. 이쯤에서 데비안 할렐루야를 외치고 싶어지는 게 패치 과정이 그다지 복잡하지 않은 편이기 때문이다.
- apt-get build-dep kdelibs
- apt-get source kdelibs
이 두 단계는 KDE 라이브러리를 빌드하기 위한 의존성이 걸려 있는 패키지를 모조리 깔고 KDE 라이브러리 소스 코드를 가지고 오라고 하는 단계이다. 어쨌든 apt-get source 명령을 실행하고 나면 KDE 라이브러리 소스 코드와, 데비안 패키지를 빌드할 수 있는 파일들이 떨어지는 것을 볼 수 있다. 자, 이제 저 링크에 있는 패치 파일을 debian/patches 아래에 02_cp949.diff라는 이름으로 복사해 넣고, debian/changelog를 잘 수정해서 버전 번호를 1 증가시키고(증가시키지 않으면 apt-get이 구토를 유발시킴) dpkg-buildpackage -rfakeroot -us -uc를 실행시키고 한참 기다리면 빌드를 다 해 준다. 내 T9300 CPU에서 약 한시간 남짓(정확히는 모르겠지만) 걸렸던 것 같다.
이론적으로는 저 빌드를 다 끝내고 생긴 deb 파일을 설치하면 CP949가 표시되어야 하는데, 텍스트 코덱으로 CP949를 선택하면 자꾸 죽어서 문제다. 혹시나 해서 Qt 3.x에 있는 qwerty라는 텍스트 코덱을 테스트하는 예제를 컴파일해서 실행시켜 봤는데 cp949 텍스트 코덱 자체는 인식했으나, KDE 라이브러리 단계로만 넘어가면 이놈이 자꾸 죽는다. 환장하겠다. 결국 Konversation을 디버그 빌드로 컴파일하여 무슨 문제가 생기는지 GDB로 짚어보기로 했다. 디버그 패키지를 빌드하려면 환경 변수 DEB_BUILD_OPTIONS=nostrip,noopt를 주고 dpkg-buildpackage를 수행하면 된다.
KDE 프로그램을 GDB 같은 놈으로 디버깅할 때 아무 옵션도 주지 않고 디버그를 수행하면 낭패보는 수가 있다. KDE 프로그램을 셸에서 실행하면, 눈치가 빠른 사람은 알겠지만 셸 프롬프트가 다시 떨어진다. 즉 fork()를 수행해서 셸에서 떨어져 나가서 실행되기 때문이다. 이 때문에 디버거를 돌리려면 –nofork라는 옵션을 줘야 한다. 또한 KDE의 충돌 관리자 Dr. Konqi가 실행되는 것을 방지하기 위해서 –nocrashhandler라는 옵션을 주고 디버깅을 시작해야 한다. QString과 같은 Qt 자료 구조 내부를 들여다보기 위해서 kde-devel-gdb 스크립트를 GDB에 설정해 두고 시작하는 것을 추천한다.
어쨌든 GDB로 충돌이 나는 부분을 찍어 보니 다음과 같았다.
DDD 화면.
저기 저 codec이라는 변수가 널 포인터 크리 덕분에 걍 비어 있었다. 그런데 왜 널 포인터가 뜨는 것일까 궁금해서 더 조사를 해 보았다. 저 codec이라는 변수에는 코덱이 넘어와야 하며, “cp949″라는 이름의 코덱이 설치되어 있는데도 불구하고 왜 널이 뜰까를 고민해 보다가, 텍스트 코덱을 생성하는 부분을 하드코딩해 보기로 했다. 그래서 “cp949″라는 코덱을 생성시켜 보았더니 널 포인터가 또 뜬다. 하아. 그렇다면 혹시, QTextCodec::codecForName(인코딩 이름에 따른 코덱을 만들어 주는 함수)이 대소문자를 구분하는 것 아닐까? 하드코딩한 부분을 “CP949″(대문자 주목)로 고치니까 그 부분을 뛰어넘는다. 할렐루야.
결국 텍스트 코덱을 다시 열어서, 이름에 있는 대문자 CP949를 소문자 cp949로 다시 고쳐서 컴파일한 결과 이번에는 널 포인터가 뜨지 않았다. 이런 우왕ㅋ굳ㅋ. KDE 라이브러리를 이것 때문에 통째로 다시 패치하느니, 대부분 Qt 텍스트 코덱의 이름이 소문자였기 때문에 텍스트 코덱을 다시 고치는 것이 빠르다고 판단했기 때문이다. 디버깅을 위해서 설치한 Konversation 빌드도 원상복구시키고 KDE 라이브러리만 패치 버전으로 교체하였다. 결국 뤂 패치의 끝은 이렇게 마무리되었다.
뤂 패치의 끝
세줄요약.
- Qt 3.x는 CP949를 지원하지 않으며, 4.3.0에 추가되었다.
- QTextCodec::codecForName 함수는 대소문자를 구분한다.
- 패키지 빌드는 오래걸리니 발 닦고 자면 된다.