Import Dynamic or Static Library By Visual Studio
목차
mosquitto나 ifcplusplused 같은 오픈소스를 Build 하기 위해 많은 노력을 했었는데 그 과정에서 얻게 된 지식을 공유하기 위해 작성하였습니다.
dll, lib
dll과 lib은 무엇일까?
먼저 무엇인지 말하면 dll
은 동적 라이브러리이고, lib
은 정적 라이브러리입니다.
외부의 코드를 사용하기 위한 Library라고 생각하시면 됩니다. dll은 Runtime 중에, lib은 Compile 할 때 필요합니다.
lib
Link 단계에서 정적으로 라이브러리 파일을 추가합니다.
일반적으로 실행 파일을 만들 때는 소스 코드를 컴파일하고 만들어진 obj 파일을 링커가 하나로 묶어 exe 파일을 만듭니다. 여기서 lib
을 사용하면 링크 단계에서 링커가 이 lib
파일도 같이 묶어서 하나의 exe 파일을 만들게 됩니다.
쉽게 말하면 우리가 컴파일에 성공해 만들어지는 exe 파일 안에 lib의 내용이 모두 들어가게 됩니다.
우리가 일반적으로 쓰는 stdio.h
같은 코드 덩어리도 실제 선언한 곳에 전부 들어가 있게 됩니다. 그렇기 때문에 많이 쓰이면 쓰일수록 파일이 무거워지게 되며, RAM에 메모리가 많이 올라가게 됩니다.
미리 컴파일된 헤더 pch와의 차이는??
pch
는 말 그대로 전처리기가 헤더 파일의 내용을 가져와서 컴파일러가 그 내용을 컴파일하지만, lib
은 이미 컴파일된 obj 파일을 가지고 링커가 연결만 시켜줍니다.
또한 pch
는 사용하고자 하는 곳에 모두 명시를 해야 하지만, lib
은 하지 않아도 괜찮습니다. 다만 아까 말했듯이 많이 사용한다면 파일의 크기가 커지는 단점이 있습니다. -> (이러한 단점을 해결하기 위해 dll이 나왔습니다.)
내 소스에 적용하기
lib
을 만들고 해당 소스를 외부의 다른 프로젝트에서 사용하려면 필요한 것은 2가지가 있습니다.
- 링커에게 해당
lib
의 경로를 알려준다. - 해당
include(header)
의 경로를 알려준다.
직접 자신의 소스 파일에 적용하는 방법은 뒤에서 진행하도록 하겠습니다.
dll
- Link 단계에서 동적으로 라이브러리 파일을 추가합니다.
dll
은 lib
과 달리 파일을 실행할 때 해당 링커가 dll
의 위치를 알고 있다면 exe 파일에 내용이 포함되어 있지 않아도 실행이 가능합니다.
즉 동적인 링킹이 가능합니다. (dll
은 프로세스의 주소 공간에 동적으로 로드가 가능하게 만들어져있기 때문입니다.)
동적 링킹으로 인한 장점은?
- 실행 파일의 메모리 절약이 가능합니다.
- RAM 메모리 절약 또한 가능합니다. 2개 이상의 파일에서 하나의
dll
파일을 사용할 때 RAM에는 하나의dll
파일만 올라가게 됩니다. - 그 밖에도 여러 가지가 있지만 현재 게시글에서 필요한 내용만 적도록 하겠습니다.
링킹의 방법
dll
은 프로세스의 주소 공간에 로드 되어야만 사용될 수 있는데, 로드 되는 방법에는 2가지가 있습니다.
- 암시적 링킹
실행 파일 자체에 어떤 dll
의 어떤 함수를 사용하겠다는 정보를 포함시키고 운영체제가 프로그램 실행 시 해당 함수들을 초기화한 후 그것을 이용하는 방법입니다.
- 명시적 링킹
프로그램이 실행 중일 때 dll
파일이 있는지 검사하고 동적으로 원하는 함수만 불러와서 쓰는 방법입니다.
현 게시글은 외부 라이브러리를 Import 하기 위한 내용이므로, 각 링킹의 정확한 방법은 밑의 참고에서 확인하시기 바랍니다.
dll 파일의 사용
명시적 링킹은 설명한 그대로 직접 코드를 통해 원하는 함수만 불러와서 사용하는 방법입니다. 더 구체적으로 말하면 함수 포인터를 얻어와서 사용하는 방법입니다. 일반적인 오픈 소스에서는 이런 방식을 이용하지 않고 암시적 링킹을 통해 제공하기 때문에 암시적 링킹에 대한 설명 방법을 알려드리도록 하겠습니다.
암시적 링킹의 방법을 통해 dll
파일을 생성할 경우 총 2개의 파일이 만들어지게 됩니다. 하나는 *.dll
이고, 다른 하나는 *.lib
입니다. 여기서 만들어진 lib
파일은 위에서 설명한 정적 라이브러리가 아니라 dll
을 통해 불러들일 함수가 들어있습니다.
내 소스에 적용하기
dll
에서는 lib
과 다르게 필요한 것이 총 3가지입니다.
lib
파일 (위의 정적 라이브러리 x)include(header)
파일dll
파일
여기서 중요한 것은! dll
파일은 lib
과 다르게, Compile과 실행에 필요한 것이 다르다는 것입니다.
- Compile 하기
Compile 할 때는 lib
과 마찬가지로 링커에게 해당 lib
의 경로를 알려준 후, 해당 헤더 파일(include)의 경로를 알려주면 Compile에 성공합니다. 하지만 실행하려 할 경우 해당 dll
이 없다며 실패합니다. 해당 함수의 실체인 dll
을 exe 파일이 모르기 때문입니다.
- 실행하기
따라서 해당 파일을 실행하기 위해선 exe 파일이 실행할 때 필요한 dll
파일을 연결해줘야 합니다.
- 왜
lib(정적 라이브러리)
는 실행에 필요한 과정이 없을까?
위에서 주의 깊게 읽으셨다면 잘 알겠지만 lib(정적 라이브러리)
의 경우에는 해당 파일의 실체가 다 exe 파일 안에 들어가게 됩니다.
내 프로젝트에 각종 오픈 소스 적용하기
어떤 소스를 적용하던 크게 2가지만 생각하시면 됩니다.
-
만약 Compile만 하기 위해 Compile 과정만 거쳤다면 Compile에는 성공하지만 실행은 되지 않습니다.
-
Compile 과는 별개로 실행만을 목적으로 하고 있다면 따로 lib과 include 파일을 연결하지 않아도 exe 파일 안에 dll 파일만 넣을 경우 실행에 성공하게 됩니다.
따라서 직접 오픈 소스를 적용하여 테스트하고 싶다면 Compile 하기 위한 lib, include 파일 그리고 실행하기 위해선 dll 파일이 모두 필요합니다.
Visual Studio 기준으로 각 파일을 링크하는 방법입니다. 예제는 ptrhead입니다.
Compile
Compile 하기 위해선 lib
파일과 include(header)
파일이 필요합니다.
lib
- 링커 > 일반 > 추가 라이브러리 디렉터리
해당 lib 파일의 경로를 입력해줍니다.
- 링커 > 입력 > 추가 종속성
해당 lib 파일의 파일명을 입력해줍니다.
include
- C/C++ > 일반 > 추가 포함 디렉터리
해당 헤더 파일의 경로를 입력해줍니다.
실행
dll
해당 dll 파일의 경로를 입력해줍니다.
예제 pthread 연습해보기
예제인 pthread를 직접 사용하기위해 Compile 하여 실행해본다면 더 이해가 빠르게 될 수 있습니다. 다음 url은 Window 환경에서 Visual Studio를 이용해 pthread를 사용하는 방법입니다.
그밖에…
각 파일을 링크하는 속성 창 중에 VC++ 디렉토리에도 비슷한 것이 있습니다.
- VC++ 디렉터리 > 포함 디렉터리
- VC++ 디렉터리 > 라이브러리 디렉터리
다음의 2가지는 Visual Studio의 기본 lib과 include 파일을 설정해주는 부분입니다. 추가적인 작업을 할 때는 제가 설명해준 방법대로 하시면 됩니다.
저도 헷갈려서 mosquitto Build 과정을 위와 섞어서 사용하였는데 추후에 고치도록 하겠습니다.
정리하자면 다음과 같습니다.