이번에는 OpenCV 의 static library를 이용하여 DLL없이 실행파일만으로 동작 가능하도록 만드는 방법에 대해서 알아보겠습니다.
여담이지만 최근 제공되는 OpenCV 배포판은 윈도우 환경에서 굳이 새로 빌드하지 않아도 쓰는데 크게 지장이 없습니다. 얼마전 CMake를 이용해서 소스코드를 여러번 빌드할 일이 있었는데 배포판에 빌드된 버전과 크게 다를게 없더군요. 가끔 소스코드를 수정해야 하는 경우에는 필요하겠지만 처음 사용하는 경우라면 굳이 새로 빌드한다고 쇼를 할 필요는 없겠습니다.
본론으로 들어가기 전에 왜 static library 를 이용해서 빌드하는 게 필요한지 알아야 겠죠. 윈도우에서는 보통 DLL (Dynamic Link Library) 이라는 파일에 필수적인 함수들을 묶어서 사용하게 됩니다. 이렇게 함으로서 재사용성이 좋아지고 메모리 점유율을 낮출 수가 있죠. 중복 코드를 줄일 수 있는 방법이라고 봐도 됩니다.
그런데 문제는 내가 작성한 프로그램이 다른 사람의 컴퓨터에서 실행되지 않을 수 있다는 것입니다. OpenCV로 작성한 경우 OpenCV가 설치되어 있지 않은 컴퓨터에서 실행하고자 할 경우에는 실행 파일 뿐 아니라 opencv_xxx.dll 이라는 파일들도 함께 옮겨 주어야 실행이 정상적으로 됩니다. 그러지 않은 경우 아래와 같은 경고창들을 자주 보게 됩니다.
물론, static library를 이용하여 실행 파일을 만들 경우에는 실행파일의 크기가 커지게 됩니다.
DLL 파일만 있으면 수백 킬로바이트면 실행되던 것이 수메가바이트로 커지게 되죠. 어떻게 빌드하는 것이 좋은지는 사용 환경에 따라 달라지므로 판단은 프로그램을 작성하는 사람이 현명하게 결정해야 합니다.
그럼 본론으로 들어가서 static library를 이용하여 실행파일을 만드는 방법을 설명하도록 하죠. 설명에 사용된 개발 환경은 다음과 같습니다.
- Windows7 Professional K 64bit
- Visual Studio 2010 professional
- OpenCV 2.4.2 (pre-compiled)
설치 방법에 대해서는 이전에 설명하였으므로 바로 본론으로 들어가보겠습니다.
먼저 프로젝트를 생성하고 코드를 작성해야 겠죠. 새 프로젝트를 콘솔로 생성하였습니다. 추가 옵션에서 빈 프로젝트에 체크 후 마침을 누르면 만들어집니다.
소스파일에서 추가 - 새항목 을 누르셔서 확장자가 cpp 인 파일을 하나 생성합니다. 그리고 간단하게 영상처리의 여왕 레나를 화면에서 보는 코드를 작성하였습니다. 안보일듯 하여 첨부합니다.
코드 작성이 끝났으면 이제 속성을 변경해야 겠지요. 프로젝트 이름을 마우스 우클릭하여 제일 아래의 속성으로 들어갑니다.
먼저 C/C++ -> 일반 탭에서 추가포함 디렉터리를 옮겨줍니다. 여기에 OpenCV의 include 폴더를 지정합니다.
추가로 "다중 프로세서 컴파일"을 "예" 로 해주시면 컴파일 속도가 조금 더 빨라진다는...
C/C++ -> 코드 생성 탭에서 런타임 라이브러리를 변경합니다. 보시면 네가지 라이브러리가 있습니다. 이중에서 현재 프로젝트가 Debug 모드이므로 "다중 스레드 디버그"로 변경합니다.
Release 모드로 빌드할 경우에는 "다중 스레드"를 선택하시면 됩니다. DLL이 포함된 것을 선택하면 안됩니다.
링커 -> 일반 탭에서 추가 라이브러리 디렉터리에 static library를 추가합니다. 보시는 바와 같이 win32 (x86 모드) 에서 빌드하며 개발 환경인 Visual Studio 2010 (버전이 v10 입니다) 폴더에 보시면 lib와 staticlib 폴더가 있습니다. 여기에서 staticlib 폴더를 선택합니다.
마지막으로 링커 -> 입력에서 추가 종속성을 입력해야 합니다. 여기에는 opencv 라이브러리 뿐만 아니라 third_party 라이브러리도 일부 포함해야 빌드가 가능합니다. 긁어서 붙여넣기 편하게 아래에 나열해 두겠습니다.
opencv_calib3d242d.lib
opencv_contrib242d.lib
opencv_core242d.lib
opencv_features2d242d.lib
opencv_flann242d.lib
opencv_gpu242d.lib
opencv_haartraining_engined.lib
opencv_highgui242d.lib
opencv_imgproc242d.lib
opencv_legacy242d.lib
opencv_ml242d.lib
opencv_nonfree242d.lib
opencv_objdetect242d.lib
opencv_photo242d.lib
opencv_stitching242d.lib
opencv_ts242d.lib
opencv_video242d.lib
opencv_videostab242d.lib
libjasperd.lib
libjpegd.lib
libpngd.lib
libtiffd.lib
zlibd.lib
comctl32.lib
vfw32.lib
아시다시피 파일명 맨 끝의 'd' 는 디버그 모드용 입니다. 릴리즈 모드에서는 'd' 가 없는 파일들을 사용하시면 되죠. 여기에서 opencv_ 로 시작하지 않는 녀석들이 몇개 보이네요. lib로 시작하는 파일들은 영상 포멧과 관련된 것들입니다.
comclt32.lib 는 윈도우 라이브러리로 없을 경우 아래와 같은 오류가 발생하며 빌드되지 않습니다. 이거 해결하는데도 구글링으로 겨우 찾았던 기억이...
D:\WithMuse\TestOpenCV\Debug\TestOpenCV.exe : fatal error LNK1120: 1개의 확인할 수 없는 외부 참조입니다.
마지막의 vfw32.lib 는 카메라를 사용하는 경우에 필요합니다.
이제 빌드를 해 보시면 출력창에 무수한 경고가 뜸에도 불구하고 빌드가 정상적으로 되는 것을 확인할 수 있습니다. 이 경고들은 해당 라이브러리 파일들의 디버깅용 db가 없다고 뜨는것이며 빌드에는 문제가 없습니다.
이제 해당 프로젝트가 있는 폴더의 Debug 폴더에 보시면 실행파일이 있습니다. 몇줄 작성하지 않았는데도 크기가 4메가바이트가 넘네요;;; 그래도 코드에 포함할 수 없는 이미지 파일만 있으면 어디서든 실행이 됩니다.
크기 비교를 위하여 DLL파일을 사용하는 실행파일을 만들어 보았습니다. 무려 100배 가까운 크기의 차이를 보입니다. 단지 이미지 하나 읽어서 출력하는 프로그램인데 말이죠. 간단한 코드에서도 이러한데 코드가 길어지면 그 차이는 상상하기 쉽지 않네요. 물론 DLL 라이브러리의 크기도 무시할 수 없겠지만 재사용성이나 메모리 점유에 대한 부분을 따진다면 어떤 것이 좋다라고 할 수는 없겠습니다. 그저 사용하는 용도에 따라 현명하게 선택해야 겠죠.