Be lost in thought…

Nineye’s personal weblog!!!

Archive for the ‘development tools’ Category

LaTeX에 unicode와 cjk 패키지 적용하기

Published by Nineye under development tools on November 23, 2009

 

회사에서 정보 공유의 목적으로 MediaWiki를 이용하여 위키를 만들게 되었는데, 업무를 목적으로 하다보니, 입력되는 위키 페이지들을 보고용으로 쉽게 만들 수 있게 하는 기능이 필요하게 되었다. 따라서 그 기능을 지원하기 위해, w2l이라는 MediaWiki extension을 설치하게 되었고, w2l을 이용하기 위해 기본적으로 세팅해야 하는 내용들 중, 폰트와 관련된 부분을 보기로 한다.

w2l extension은 LaTeX 기반이며, pdflatex명령어를 통해 “위키문서 => LaTeX코드 => pdf문서”로 만드는 extension이다. 즉, w2l extension을 이용하려면 해당 서버에서 LaTeX을 지원해 주어야 하는 것이다.

필자가 MediaWiki를 설치한 서버에는 texlive LaTeX package가 이미 설치되어 있었으며, 영문 문서를 테스트 했을 때는 아무런 문제가 없었다. 하지만 linux가 항상 그렇지만, 한글 문서를 적용하려고 하니 여러 가지 문제가 발생하였고, 문제의 근간이 된 폰트 문제에 대해 쓰고자 한다.

우선, 적용하고자 하는 서버에 LaTeX이 설치되어 있지 않다면 설치하자. 필자는 현재까지 계속 지원되고 있는 texlive를 설치하였다.

 
# Debian의 apt-get을 통한 설치(필자의 환경은 이것인데, 다른 환경은 구글링을 통해...ㅋㅋ)
# LaTeX 기본 설치(texlive tool + 기본 포맷 package)
$ apt-get install texlive
# LaTeX  풀 설치(약 700MB 정도된다. ㅡㅡ;;; 기본으로만 설치하고 필요한 package만 따로 설치해도 된다.)
$ apt-get install texlive-full

 

 

1 LaTeX에 한글은 어떻게 적용할까?

LaTeX 에 있어서의 변환 툴은 그저 껍데기에 지나지 않고, 실질적으로는 LaTeX문서를 다양하게 표현하는 package가 더욱 중요하다. LaTeX은 이러한 다양한 문서 표현에 대해, 사용자들이 직접 문서 표현 포맷을 작성하고, 이 포맷을 package로 공유하게 함으로써, 현재의 LaTeX은, 표현하지 못하는 문서의 모습은 거의 없을만큼 방대해 졌다. 하지만 너무 방대해 지고, 전 세계의 사용자들이 각각 package를 제작하다보니, package들 끼리의 관계가 너무 복잡하게 얽혀있어서 소위 삽질을 많이 하게 된다.  필자도 한글을 적용하면서 삽질을 많이 하였고, 다시 삽질을 하지 않기 위해 한글 적용 문제를 정리해 보고자 하는 것이다.

LaTeX에서의 한글 적용은 다양한 package들이 존재하는데, kotex, cjk(chinese, japanese, korean – 우리나라가 맨 마지막에 나와서 기분 나쁘지만 뭐, 알파벳 순서니… ㅡㅡ;;;)등이 그것들이다. kotex은 국내에서는 많이 알려졌는데, 세계적으로는 아시아권(한국, 중국, 일본) 언어를 지원하는 cjk package가 더욱 알려져있으며, 이 package에 대한 지원도 잘 되고 있어서, cjk package를 선택하기로 했다.

# cjk package는 각 언어별로 따로 설치할 수 있다. "latex-cjk-해당언어"의 명칭으로 package가 제공된다. 필자는 귀찮고 문제 생길까봐 다 설치했다.
$ apt-get install latex-cjk-all
# fontforge로 cjk 관련 폰트를 생성할 때, 폰트 스크립트가 필요하다. 이는 latex-cjk-common package에 들어 있으니, 없으면 설치하자.

자, cjk가 설치되었으니, pdflatex명령을 통해 한글 tex문서를 변환해 본다. 아마… 잘 안될 것이다. 변환이 잘 된다면 성공이고, 이후의 과정은 무시해도 된다. 필자의 경우 utf-8 인코딩으로 저장된 tex문서를 변환해야 해서, unicode font를 설치해야 했고, byte단위의 한글 인코딩 문서라면 잘 변환될 수도 있을 것 같다. 아래 과정은 tex문서가 utf-8로 인코딩된 문서라 가정하고,  utf-8문서를 다룰 수 있는 unicode font의 설치에 관련된 내용이니, 다른 문제로 고민한다면 아래 내용을 읽지 않아도 된다.

 

 

2 LaTeX에서는 어떻게 unicode를 지원할까?

pdflatex명령을 통해 생성되는 ~.log 파일에 “!Undefined control symbol ~어쩌구~ <문서내의 한글 내용> ~어쩌구~” 라는 에러 메세지가 있다면, 한글을 변환하는 cjk package는 정상적이지만, utf-8 인코딩 tex문서내의 한글 변환에 사용되는 폰트가 정상적이지 않은 것이다. 이 글에서는 이 경우의 오류만 다루기 때문에 다른 종류의 오류라면 구글링을 통해 찾아보기 바란다. 

우선, LaTeX package들이 설치되는 곳에 truetype폰트가 설치되어 있는지 확인해 보자. 위치는 필자의 경우, /usr/share/texmf/fonts/truetype/ 이었다. 일단 여기 font가 설치되어 있다면 unicode를 지원하는 font인지 확인해 보자. unicode를 지원하는 폰트라면 LaTeX cjk package가 사용가능한 font인지 해당 font정보를 확인해 보도록 하자. 만약 cjk package에서 적용하지 못하는 font이거나, unicode를 지원하는 font가 없다면 Bitstream의 Cyberbit font를 설치하자.

잠깐 Cyberbit font에 대해서 설명하면, 이 font는 Bitstream사가 보유한, 비영리적인 목적으로 사용할 때는 공짜인 font이다. 그리고 이 font는 전 세계에서 큰 비중을 차지하는 unicode 입력 리스트들에 대해 지원을 하는, 역사적으로 가장 널리 알려진 font중 하나이다. 이 font에 대한 상세 내용은, Bitstream사의 홈페이지(www.bitstream.com)에 가보면 어딨는지 잘 모르겠고, Wikipedia의 설명(http://en.wikipedia.org/wiki/Bitstream_Cyberbit)을 참고하자.

 

 

3 unicode를 표현하기 위한 cyberbit font를 설치해 보자.

Cyberbit font를 LaTeX내에 설치해 주는 package가 존재한다면, 그 package를 통해서 쉽게 설치할 수 있겠지만, 아쉽게도 아직 없나보다. 따라서 수동으로 설치하는 방법을 따라 설치하였다. 다음의 순서에 따라 cyberbit font를 LaTeX내에 설치해 보자. 참고로 설치하는 위치는 필자의 환경 기준으로 쓰며, 만약 설치 장소가 /usr/share/~ 가 아니면 환경에 맞게 설치한다.

1. cyberbit font의 복사

1. 여기를 클릭해서, cyberbit font를 받자.

2. 압축을 해제하면 Cyberbit.ttf가 나오는데 이를 cyberbit.ttf로 이름을 변환해서(LaTeX에서는 대소문자를 구분한다.) /usr/share/fonts/truetype/bitstream/ 위치에 넣자.

3. 이렇게 설치한 font를 LaTeX에서도 사용할 수 있게 링크를 걸어준다.

$ mkdir -p /usr/share/texmf/fonts/truetype/bitstream/cyberbit/
$ ln -s /usr/share/fonts/truetype/bitstream/cyberbit.ttf /usr/share/texmf/fonts/truetype/bitstream/cyberbit/cyberbit.ttf

2. LaTeX 문서의 변환에 이용되는 파일들의 설치

 - fontforge tool을 이용하여, LaTeX typesetting 시스템에 사용되는 파일 포맷인 .tfm(http://en.wikipedia.org/wiki/TeX_font_metric 참고)과, uuencoding에 사용되는 파일 포맷인 .enc(http://en.wikipedia.org/wiki/Uuencoding 참고)와,  PostScript에 이용되는 파일 포맷인 .pfb(http://en.wikipedia.org/wiki/PostScript_fonts)파일을 설치

1. fontforge가 설치되어 있지 않다면 설치한다.

$ apt-get install fontforge

2. 앞에서 latex-cjk-common package를 설치했으면, /usr/share/latex-cjk-common/utils/subfonts/ 위치에 cjk용 폰트 스크립트인 subfonts.pe 파일이 있다. 이를 작업 디렉토리에 복사하자.

3. fontforge에서 사용하는 unicode 폰트 형판(?) 파일(http://en.wikipedia.org/wiki/FontForge 참고)인 Unicode.sfd를 작업 디렉토리에 복사한다. 보통 freetype1-tools(현재는 freetype2-demos로 명칭이 변경된 듯 하다. 정확한 설명이 없음) package를 설치하면 /usr/share/texmf/fonts/sfd/ 위치에 있다고 하지만 필자의 경우 없었다. 따라서 여기에서 다운 받아서 위의 위치에 넣었다.

4. 이제 fontforge를 이용해서, 작업 디렉토리에 .tfm, .enc, .pfb 파일들을 생성한다. 이 작업은 시간이 많이 소요된다. 필자의 경우 한 4~5시간 정도? ㅡㅡ;;;

# 작업 디렉토리에서 실행
$ fontforge -script subfonts.pe cyberbit.ttf cyberbit /usr/share/texmf/fonts/sfd/Unicode.sfd

5. 파일들이 생성됐으면, LaTeX문서를 PostScript로 변환 시, 사용하는 .map 파일을 생성한다. 이는 .pfb파일로부터 다음의 스크립트를 통해 생성한다.

# 작업 디렉토리에서 실행
for i in *.pfb
do
echo "$(basename $i .pfb) $(basename $i .pfb) <$i" >> cyberbit.map
done

6. 이제 생성된 파일들을 다음의 위치에 넣는다.

  • .afm ==> /usr/share/texmf/fonts/afm/cyberbit/
  • .tfm ==> /usr/share/texmf/fonts/tfm/cyberbit/
  • .pfb ==> /usr/share/texmf/fonts/type1/cyberbit/
  • .map ==> /usr/share/texmf/fonts/map/dvips/cyberbit/

7. texmf 디렉토리 내의 구조가 변경되었으므로 “texhash”나 “mktexlsr” 명령을 root권한으로 실행하여 ls-R을 다시 구성한다.

3. 20cyberbit.cfg 파일의 추가

 - /etc/texmf/updmap.d/ 위치에 20cyberbit.cfg 파일을 다음과 같은 내용으로 편집하여 추가한다.

######
# 20cyberbit.cfg
Map cyberbit.map
######

4. cyberbit.map파일의 적용

 - 다음과 같은 명령을 실행하여, cyberbit.map font map 파일을 적용한다. 이 때 주의할 점은 작업 디렉토리내의 cyberbit.map 파일로 적용되지 않기 위해, 작업 디렉토리 내의 cyberbit.map 파일을 삭제하고 실행한다.

$ update-updmap -c /etc/texmf/updmap.d/
$ updmap-sys

5. c70song.fd파일의 생성

 - /usr/share/texmf/tex/latex/CJK/UTF8/의 위치에 c70song.fd 파일이 있는지 확인하고, 있으면 삭제하고 다음의 내용으로 c70song.fd 파일을 생성한다.

%%%%%%
% This is the file c70song.fd of the CJK package
%   for using Asian logographs (Chinese/Japanese/Korean) with LaTeX2e
%
% created by Werner Lemberg <wl@gnu.org>
%
% Version 4.6.0 (11-Aug-2005)

\def\fileversion{4.6.0}
\def\filedate{2005/08/11}
\ProvidesFile{c70song.fd}[\filedate\space\fileversion]

% character set: Unicode U+0080 - U+FFFD
% font encoding: Unicode

\DeclareFontFamily{C70}{song}{\hyphenchar \font\m@ne}

\DeclareFontShape{C70}{song}{m}{n}{<-> CJK * cyberbit}{}
\DeclareFontShape{C70}{song}{bx}{n}{<-> CJKb * cyberbit}{\CJKbold}

\endinput
%%%%%%

6. ls-R의 재 구성

 - root 권한으로 “texhash” 명령어를 다시 실행한다.

 

 

자, 이제 다 되었다. 위에서 테스트 한 LaTeX 소스 파일로 다시 테스트 해 보자. 필자의 경우 오류 없이 한글이 변환되었다. 드디어~ MediaWiki 한글 페이지를 pdf문서로 만들 수 있다~!!! 언제나 생각하는 것이지만 정말 linux에서는 어떤 프로젝트든지, 한글을 적용하는 것은 삽질이다. ㅡㅡ;;;

2 Responses to “LaTeX에 unicode와 cjk 패키지 적용하기”

Leave a Reply

linux linker ld에서 여러 library linking 시, library 순서에 대해

Published by Nineye under development tools on February 24, 2009

가끔 가다, project를 빌드할 때, 여러 library를 참조하고, 그 library들 중의 한 library가 또 다른 library를 참조하는 복잡한 링킹 구조일 때, 링킹 시키는 library순서에 따라 링킹 오류가 발생하는 경우가 있었다.

링커가 링킹시키는 과정은 http://blog.naver.com/nineye09/50028505467 에 설명되어 있다. 관련된 글을 약간 보면, 링커는 커맨드 라인에서 받아들인 재배치 가능한 object파일과 library파일을 왼쪽에서 오른쪽으로 스캔하는데, 입력으로 주어지는 library들은 순서대로 주어져서 다른 archive의 멤버들이 참조할 수 있도록 해야하며, 정의된 하나의 심볼은 뒤따르는 커맨드 라인의 입력에 의해 참조되어야 한단다. 결국 링킹 시키는 것도 순서가 중요한 것 같네… 어쨌건 우리가 하고자 하는 건, 이러한 복잡한 링킹 구조일 때, 어떻게 명확하게 링킹시킬 것인가 하는 것이다.

설마 이렇게 유명한 링커가 library의 순서나 따지는 무식한 짓을 할리는 없을 거라고 생각하며, 이와 관련해서 검색하다 보니 다음과 같은 좋은 방법이 있었다.

gcc -o exefile -Xlinker –start-group libmod1.a libmod2.a libmod3.a -Xlinker –end-group

-Xlinker 는 뒤에 따라오는 flag를 linker에 넘기라는 flag이다.

–start-group, –end-group : 두 개의 정의 사이에 오는 archive들은 새로운 undefined references 가 생성되지 않을 때까지 반복적으로 검색된다.

결국 위의 문장을 해석하면, exefile을 빌드하는데 mod1, mod2, mod3 library들을 링킹하고, 이 library들은 undefined references 가 하나도 없을 때까지 반복적으로 검색되게 된다… 는 것이다. 이제 우리가 고민했던 복잡한 링킹 구조에서 library를 빠짐없이 참조가 가능해진 것 같다.

Leave a Reply

SDL library와 SDL 응용 library들을 설치하면서

Published by Nineye under development tools on February 24, 2009

cygwin + mingw 환경하에서, SDL과 SDL응용 library들을 설치한 상태에서 SDL을 이용하는 App를 개발하다보니 계속 문제가 생겨서, 전체를 새로 설치하면서 삽질하는 내용들을 끄적여 본다.

1. 처음부터 새로 설치하다…

- mingw : cygwin과 mingw에는 컴파일러 라이브러리 include파일 등등 중복되는 것들이 많아서 뭔가 좀 이상하다. 그리고 mingw는 small cygwin이라할까… 뭔가 없는 내용들이 많다. 예를 들면 socket library라든지… mingw에서는 socket library가 없어서 MS거 쓰란다… ㅡㅡ;;; 그래서 과감하게 mingw를 버리기로 했다. mingw uninstall!!!

- cygwin : mingw를 uninstall하고 나니, 기존에 잘 빌드되던 프로젝트도 링킹오류를 내면서 빌드가 안된다. mingw uninstall의 여파인가??? cygwin을 새로 설치하기로 했다. 하긴, 설치되어 있던 cygwin이 뭔가 불안정 하긴 했다. man 환경 설정파일도 제대로 복사되어 있지 않아서 man도 실행이 되지 않고, sshd service도 제대로 설치가 되어 있지 않아서 ssh deamon띄우는데만 꽤 삽질을 했다. 그냥 싹~ 새로 설치하자. all uninstall후, cygwin폴더 싹~ 비우고, all install!!!

- SDL library : 이전에는 SDL-devel 버전을 받아서 내 환경에서 빌드하지 않고 그냥 빌드되어 있는 것을 설치만 했는데, 그래서 그런지는 잘 모르겠는데 SDL library의 응용 library들을 이용한 project를 빌드 시, 자주 링킹 오류를 내며 빌드가 잘 되지 않았다. 그리고 빌드가 잘 되지 않을 때는 library들의 링킹 순서만 바꿔줘도 빌드가 됐다는… 그리고 뭔가 다른 library를 추가하면 또 빌드가 되지 않고… 어쨌든 이상하다. 그래서 SDL library source를 받아서 내 환경하에서 새로 빌드를 하고, 설치를 했다. 버전은 SDL-1.2.13이고, ./configure; make install; 을 실행시키자… 잘 빌드되네…ㅋ

2. SDL 응용 library를 설치하자…

- Agar library : SDL 응용 library이다. 지금 이렇게 새로 설치하고 삽질을 하고 있는 것이 모두 다 이넘 때문이다. 이 library publisher에 메일을 보내니 정성스럽게 답변을 해주긴 하지만, 내 영어 실력이 딸리다 보니 메일 하나 쓰는데도 시간이 꽤 걸린다. 영어 공부 좀 해야지… ㅡㅡ;;; 어쨌건 지금까지 메일 주고 받으면서 알게 된 내용을 조금씩 써본다.

– Agar library의 stable release버전은 mingw관련 파일은 있지만 cygwin관련 파일은 없다. mingw와 cygwin환경은 세세한 면에서 상당히 다르기 때문에 구분을 지어야 하고, 현재 나는 cygwin환경만 사용할 것이기 때문에 Agar library가 cygwin환경하에서 정상 빌드 및 동작을 하는지가 중요했다. 그쪽에 물어보니, cygwin만 설치된 환경이나 아니면 mingw만 설치된 환경 모두 지원을 한다고 한다. 그리고 Agar library는 기본적으로 cygwin dependency를 없애려고 -mno-cygwin flag가 default로 세팅되어 있다.

– 맨 처음 Agar library를 사용한 project에서 빌드는 성공했지만, 실행하자마자 exit(3)을 리턴하면서 종료되어 버리는 현상이 있었다 : 이것은 Agar library 1.3.1버전까지는 XCF포맷을 사용했는데 Agar library가 기본적으로 필요로 하는 icon이나 font를 XCF포맷을 이용해서 로딩하는 부분이 있는데 icon이나 font파일을 찾지 못하면 문제가 생겨서 그런 것이라고 한다. Agar library 자체를 default 위치에 설치하려고 하다가, 그 이후 버전인 1.3.2rc3버전은 XCF를 전혀 참조하지 않는다고 해서 그냥 1.3.2rc3를 사용하기로 했다. 근데, 1.3.2버전은 stable release 버전이 아니어서 빌드되어 있는 것은 없고, source를 받아서 새로 빌드를 해야한단다.

– free type 문제 : Agar 1.3.2rc3를 빌드하려고 ./configure를 실행하니, 내 환경에서는 freetype library가 존재하지 않는다며, 중단되어 버린다. 그쪽에 물어보니, built-in font engine은 quality가 낮기 때문에, 적절한 font rendering과 다국어 지원을 위해서는 Free Type library를 사용하는 것을 강력히 추천한다고 한다. 그런데 난 이쁜 font같은 거 필요없기 때문에 걍 Free Type library를 사용하지 않기로 했다. ./configure –without-freetype; 을 실행시키자.

– thread 관련 문제 : –without-freetype으로 실행시키니, POSIX thread library를 찾을 수 없다는 에러가 나왔다. config.log를 확인해보니, pthread.h파일을 include 시키지 못해서 였다. pthread.h파일과 libpthread.a파일은 cygwin 환경하에서 각각 /usr/include와 /lib 위치에 존재하는데 왜 못찾을까… 생각해보니 -mno-cygwin flag가 영향을 미치는 것 같다. 기본적으로 gcc는 위의 위치를 참조하는데, 있는대도 참조하지 못하는 건 그 flag 영향이지 않을까…

위, thread문제 관련해서 답변을 받았는데… cygwin에서 thread를 사용해 본적이 없단다. 하긴 나도 cygwin환경에서 빌드해서 실행시켜 본 적이 거의 없기때문에 아직 사용해 본 적이 없다. 그래도 cygwin내에서 pthread library가 존재하기 때문에 thread를 지원하긴 하지만 linux OS에서의 thread와 동일하게 동작하는지는 잘 모르겠다. 어쨌든 Agar library에서는 thread가 필요없나보다. 결국 답변은 cygwin에서 thread사용하면서 삽질하지 말고, 차라리 thread를 사용하지 않는 flag를 주란다. ./configure –without-freetype –disable-threads 실행! 오~ 정상적으로 설정이 마쳤다.

그 이후 make와 make install명령은 순조로웠다. 다만, stable버전이 아니어서 OpenGL관련해서 약간 컴파일 오류가 났지만 일단 컴파일 오류 나는 부분만 수정해서 빌드 성공!!!

3. SDL, Agar library를 사용하는 내 프로젝트의 build…

- 이런… 제길… linking error발생! 혹시나 해서 그냥 Agar 예제 소스만 빌드해도 똑같은 linking error가 밸생한다. error message는 :

/usr/local/lib/libag_gui.a(text.o):text.c:(.text+0×16f): undefined reference to `__errno’
/usr/local/lib/libag_gui.a(file_dlg.o):file_dlg.c:(.text+0×1780): undefined reference to `__imp___iob’

흠… 아무래도 내 생각에 Agar library는 기본적으로 -mno-cygwin flag를 사용해서 빌드되는데, -mno-cygwin flag를 사용하지 않는 project와 같이 링킹시키거나 하면 이상해지는 것이 아닐까… 이 문제에 대해서는 구글링을 해봐도 질문만 있고 답이 거의 없었다. 그중에서 어느 정도 원인이라고 생각할 수 있는 글이 있었는데 다음과 같다.

 

Cygwin libraries use the Cygwin runtime. MinGW/MSYS libraries use the Microsoft (MSVCRT) runtime. These are two inherently different and incompatible implementations of a C runtime, so you can’t link a program that uses both and expect it to work.
It is technically possible if you are very sure of what you’re doing, but this would involve making sure that all C functions are resolved to the correct library. For example, printf() in the MinGW code must go to MSVCRT, printf() in the Cygwin code must go to cygwin1.dll. The only way I can think to do this is with LoadLibrary()/GetProcAddress() and function pointers for everything. It also would mean that no C library data structures could be passed between the two, such as file descriptors, FILE *, struct stat, etc. It would be an extremely inconvent way to write code, and it would be much easier and cleaner to just compile all code as Cygwin code or all code as native (MSVCRT) code.


요약하면, cygwin library는 cygwin runtime을 사용하고, mingw library는 MSVCRT runtime을 사용한다. 따라서 이 두가지를 동시에 linking할 수 없고, 또한 linking에 성공해도 제대로 된 동작을 보장하지는 못한다. 결국 모든 코드를 cygwin으로 빌드하거나, 모든 코드를 MSVCRT코드로 빌드하는 것이 쉽고 명백한 해결이다… 라고 한다.

과연, library들이 -mno-cygwin flag를 사용하여 빌드되었다고 꼭, 내 project도 -mno-cygwin flag를 붙여야 하는가? 설마… 그래야 한다면 너무 우울해진다… ㅡㅡ;;;

Leave a Reply

Be lost in thought… is powered by Nineye in WordPress | Entries RSS and Comments RSS

Copyright © 2009. All right reserved by Nineye.