정적/동적 라이브러리 원하는 것으로 링크하기
C/C++ 빌드시 정적/동적 라이브러리를 원하는 것으로 자유롭게 링크하는 방법이다.
라이브러리 링크
정적(static) 라이브러리의 링크는 Makefile 파일에서 아래와 같이 링크시키면 된다. (이때 실제 라이브러리의 파일 이름은 lib<라이브러리_이름>.a 형태임)
-l<라이브러리_이름>
한편, 동적(dynamic, shared) 라이브러리의 링크는 Makefile 파일에서 아래와 같이 링크시키면 된다. (이때 실제 라이브러리의 파일 이름은 lib<라이브러리_이름>.so 형태임)
-l<라이브러리_이름>
즉, 정적 라이브러리이건 동적 라이브러리이건 동일하게 -l<라이브러리_이름>으로 링크되는데, 링크시킬 라이브러리의 경로는 표준 라이브러리 경로이거나, -L 옵션으로 지정되는 경로이다.
만약에 라이브러리 경로에서 정적 또는 동적 라이브러리가 1개만 있는 경우에는, 발견된 라이브러리가 사용된다. 그런데 만약 동일한 경로에서 정적 라이브러리와 동적 라이브러리가 둘 다 존재하는 경우에는, 다음 섹션에서 설명하는 방법으로 이 중에서 원하는 것을 지정할 수 있다.
정적/동적 라이브러리 지정해서 링크
위에서 보듯이 정적이나 동적 라이브러리를 링크하는 방법은 동일하게 -l<라이브러리_이름>을 명시하는 것이다. 그런데 하나의 프로그램에서 정적 라이브러리와 동적 라이브러리가 둘 다 있으면, 원하는 않는 라이브러리가 링크될 수 있고, 이로 인해 rootfs에 존재하는 동적 라이브러리와 매치가 되지 않는 경우에는, 프로그램 실행시 에러가 발생하게 된다.
회사 프로젝트에서 이런 경우가 있었는데, 이런 라이브러리 링크 문제를 제대로 해결을 못하고, 모든 모듈들을 동적 라이브러리로 빌드하여 링크시키는 방법을 사용하고 있었다. 그런데 이 방법을 사용하면 회사 라이브러리들이 so 파일로 빌드되어서 쉽게 누출 및 대치될 수 있다는 문제점이 있었다.
사실 하나의 C/C++ 프로그램에서 동시에 두 라이브러리 타입을 동시에 링크시킬 수도 있고, 동일한 경로에 정적/동적 라이브러리가 존재하는 경우에는 원하는 것을 지정시킬 수도 있는데, 다음과 같은 2가지 방법이 있었다.
- 정적 라이브러리 링크를
-l<라이브러리_이름>대신에 전체 경로(파일 이름 포함)를 명시하는 방법 - 아래 형태와 같이
-Wl,-Bstatic이후에 정적 라이브러리들을 명시하고,-Wl,-Bdynamic이후에 동적 라이브러리들을 명시하는 방법-Wl,-Bstatic -l<정적_lib_1> -l<정적_lib_2> -Wl,-Bdynamic -l<동적_lib_1> -l<동적_lib_2>물론
-Wl,-Bstatic,-Wl,-Bdynamic옵션의 순서는 중요하지 않고, 필요하면 여러 번 사용할 수 있다.
참고로 만약에 정적/동적 라이브러리가 둘 다 존재하지만 다른 경로에 존재하는 경우에는, 링크시키고 싶은 라이브러리의 경로를 먼저 -L 옵션으로 지정하면 된다. (즉, 링크시 지정한 순서대로 검색하여 발견되면 링크시킴)
ℹ️ 실제로 링크시 어떤 라이브러리들을 사용하여 링크되는지를 확인하려면
-Wl,-t링크 옵션을 추가하면 된다.
실제로 나는 이 방법을 사용하여 동일한 라이브러리가 서로 다른 경로와(buildroot 경로, 자체 lib 경로) 정적/동적 라이브러리가 모두 있는 경우에, 실제로 어떤 것이 링크되는지 확인할 수 있었고, 의도치 않았던 라이브러리가 링크되는 것을 발견하여 수정할 수 있었다.
라이브러리 dependency 문제
참고로 만약에 링크시 라이브러리들 간의 dependency로 인해 순서가 문제되는 경우에는, 간단히 아래 예와 같이 -Xlinker --start-group과 -Xlinker --end-group 사이에 라이브러리들을 넣으면 된다.
-Xlinker --start-group -l<lib_1> -l<lib_2> -l<lib_3> -Xlinker --end-group
맺음말
위와 같은 방법을 사용하여 어떤 라이브러리들은 정적 라이브러리로, 어떤 라이브러리들은 동적 라이브러리로 자유롭게 원하는 것으로 링크시킬 수 있다.
간단한 Makefile 팁인데 모르는 사람들이 많은 관계로 간단히 공유한다.