article0 - webispy/aln GitHub Wiki
์ํ C ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ค์ํ ์ด์์ฒด์ ์ ๊ฐ ํจํค์ง ์์คํ ์ ๋ง๊ฒ ํจํค์งํ๊ณ ๋ฐฐํฌํ๊ธฐ
๋ค์ด๊ฐ๋ฉฐ
C/C++ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐ๋ฐ์์๊ฒ ํฌ๋ก์ค ํ๋ซํผ ์ง์์ ์ค์ํ ๊ณผ์ ์ ๋๋ค. ์ด ๋ธ๋ก๊ทธ ์๋ฆฌ์ฆ์์๋ ์ํ C ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ง๋ค๊ณ , ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ๋ฌ ์ด์์ฒด์ ์ ๋ง์ถฐ ํจํค์ง ๋ฐ ๋ฐฐํฌํ๋ ๊ณผ์ ์ ์๊ฐํ๋ ค๊ณ ํฉ๋๋ค.
์๋ฆฌ์ฆ ๊ตฌ์ฑ:
- ์ํ C ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก์ ๊ฐ์ถฐ์ผ ํ ์์๋ค
- Ubuntu Linux์ deb ํจํค์ง๋ก ๋ฐฐํฌํ๊ธฐ
- Fedora Linux์ rpm ํจํค์ง๋ก ๋ฐฐํฌํ๊ธฐ
- macOS์ Homebrew TAP์ ํตํด ๋ฐฐํฌํ๊ธฐ
- Windows์ vcpkg custom registry๋ฅผ ํตํด ๋ฐฐํฌํ๊ธฐ
์ํ C ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก์ ๊ฐ์ถฐ์ผ ํ ์์๋ค
ALN(Amazing Lucky Numbers) ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์๊ฐ
๋จผ์ , ํจํค์ง ์์๋ฅผ ์ํ ์ ์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ํ์ ๋ํด ๊ณ ๋ฏผ์ด ์์์ต๋๋ค. ๋๋ฌด ๋จ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ค์ ๊ฐ๋ฐ ์ํฉ๊ณผ ๊ฑฐ๋ฆฌ๊ฐ ๋ฉ๊ณ , ๋ฐ๋๋ก ๋๋ฌด ๋ณต์กํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํจํค์ง ๊ณผ์ ๋ณด๋ค ์ฝ๋ ์ดํด์ ๋ ๋ง์ ์๊ฐ์ ํ ์ ํ๊ฒ ๋ง๋ค ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด๋ฌํ ๊ณ ๋ฏผ ๋์, ์ ๋นํ ์์ค์ ๋ณต์ก์ฑ์ ๊ฐ์ง ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ง๋ค๊ธฐ๋ก ๊ฒฐ์ ํ๊ณ 'ALN(Amazing Lucky Numbers)'์ด๋ผ๋ ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ง๋ค์์ต๋๋ค. ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ ํน์ง์ ๊ฐ์ง๊ณ ์์ต๋๋ค:
- ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(
glib
)์ ๋ํ ์์กด์ฑ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. - API๋ฅผ ํธ์ถํ๋ฉด ํ์ด์ ๋ฒํธ๋ฅผ ์์ฑํด์ฃผ๋ ๊ธฐ๋ฅ์ ์ํํฉ๋๋ค.
- 6๊ฐ์ API๋ฅผ ์ ๊ณตํฉ๋๋ค. - ALN ์์ฑ/ํด์ /๋ฆฌ์ , ๋ฒํธ ์์ฑ (ํ๋ฒ์/ํ๋์ฉ), ๋ฒํธ ์ป๊ธฐ
ALN ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ ์ฒด ์์ค ์ฝ๋๋ GitHub ์ ์ฅ์(https://github.com/webispy/aln)์์ ํ์ธํ์ค ์ ์์ต๋๋ค. ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ค์ ๋ก๋ ๋ฒํธ๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ, ๋จ์ํ ์์ ๋ฅผ ์ํ 'ํ์ด์ ๋ฒํธ'๋ฅผ ์ ๊ณตํ๋ค๋ ์ ์ ์ ์ํด ์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.
์ด์ ์ด ALN ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก, C ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๊ฐ์ถฐ์ผ ํ ํต์ฌ ์์๋ค๊ณผ ๋ฉํฐ ํ๋ซํผ ์ง์์ ์ํ ๊ณ ๋ ค์ฌํญ๋ค์ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ตฌ์ฑ ์์
๊ฐ๋ฐ์๊ฐ ALN ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ์ ๊ณตํด์ผ ํ ํ์์ ์ธ ์์๋ค๊ณผ ์ฌ์ฉ ํธ์์ฑ์ ๋์ด๊ธฐ ์ํ ์ถ๊ฐ ์์๋ค์ ๋ํด ์์ธํ ์์๋ณด๊ฒ ์ต๋๋ค.
ํ์ ์์
์๋ ๋ ์์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ์ ์ํด ๋ฐ๋์ ํ์ํฉ๋๋ค.
- ํค๋ ํ์ผ (Header File):
- API์ ์ ์ธ์ด ํฌํจ๋
.h
ํ์ผ์ ๋๋ค. - ์ฌ์ฉ์๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ธฐ๋ฅ์ ์ดํดํ๊ณ ์ฌ์ฉํ ์ ์๊ฒ ํด์ค๋๋ค.
- API์ ์ ์ธ์ด ํฌํจ๋
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ (Library File):
- ์ปดํ์ผ๋ ์ฝ๋๊ฐ ํฌํจ๋ Shared object(
.so
,.dylib
,.dll
๋ฑ) ๋๋ Static archive(.a
,.lib
) ํ์ผ์ ๋๋ค. - ์ดํ๋ฆฌ์ผ์ด์ ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋งํฌํ์ฌ ์ฌ์ฉํ ์ ์๊ฒ ํฉ๋๋ค.
- ์ปดํ์ผ๋ ์ฝ๋๊ฐ ํฌํจ๋ Shared object(
์ถ๊ฐ ์์
๋น๋ ์ ๋ณด ์ ๊ณต (pkg-config ํ์ผ)
๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๊ฐ์ง๊ณ ์๋ ์์กด์ฑ๊ณผ ๋น๋ ๋ฐฉ๋ฒ์ ๋ํ ์ ๋ณด๋ ๋งค์ฐ ์ค์ํ๋ฐ, ์ด๋ฐ ์ ๋ณด๋ค์ ์ ๊ณตํ๋ ๊ฐ์ฅ ํจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ์ pkg-config ํ์ผ(.pc
)์ ๊ฐ์ด ์ ๊ณตํ๋ ๊ฒ์
๋๋ค.
๋ค์์ Linux์ /usr/lib/x86_64-linux-gnu/pkgconfig
๋๋ ํ ๋ฆฌ์ ์๋ xdmcp.pc
ํ์ผ์ ๋ด์ฉ์
๋๋ค. (์ฌ์ฉ์์ ํ๊ฒฝ์ ๋ฐ๋ผ libxdmcp-dev
ํจํค์ง๊ฐ ์ค์น๋์ด ์์ง ์์ผ๋ฉด ํด๋น ํ์ผ์ด ์์ ์ ์์ต๋๋ค.)
prefix=/usr
exec_prefix=${prefix}
libdir=${prefix}/lib/x86_64-linux-gnu
includedir=${prefix}/include
Name: Xdmcp
Description: X Display Manager Control Protocol library
Version: 1.1.3
Requires: xproto
Cflags: -I${includedir}
Libs: -L${libdir} -lXdmcp
์ ํ์ผ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ด๋ฆ(Name
), ์ค๋ช
(Description
), ๋น๋ํ ๋ ํ์ํ ์ปดํ์ผ ์ต์
(Cflags
)๊ณผ ๋งํฌ ์ต์
(Libs
), ๊ทธ๋ฆฌ๊ณ ์์กด์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(Requires
) ์ ๋ณด๋ฅผ ํ์ธํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ xdmcp
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด xproto
๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ํ๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
.pc
ํ์ผ์ ๊ธฐ์ ๋ ๋ด์ฉ์ ์๋์ ๊ฐ์ด pkg-config
๋ช
๋ น์ ํตํด ์ง์ ๊ฐ์ ์ป์ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ์ด์ฉํ๋ฉด xdmcp ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ดํ๋ฆฌ์ผ์ด์
์ ์ฝ๊ฒ ๋น๋ํ ์ ์์ต๋๋ค.
$ pkg-config --cflags --libs xdmcp
-lXdmcp
$ gcc -o a.out test.c `pkg-config --cflags --libs xdmcp`
# `gcc -o a.out test.c -lXdmcp` ์ ๋์ผ
xdmcp ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ๋๋ง ์ฌ์ฉํ๋ ์์ ๋ผ pkg-config
์์ด ์ง์ ์ปดํ์ผ ์ต์
์ ๋ฃ๋ ๊ฒ์ด ๋ ๊ฐ๋จํด ๋ณด์ผ ์ ์์ง๋ง, ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐฏ์๊ฐ ๋์ด๋๊ฒ ๋๋ฉด ํฐ ํ์ ๋ฐํํ๊ฒ ๋ฉ๋๋ค.
์๋๋ ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ ALN์์ ์ ๊ณตํ๋ aln.pc
ํ์ผ์ ๋ํ pkg-config ๊ฒฐ๊ณผ์
๋๋ค.
$ pkg-config --cflags --libs aln.pc
-I/usr/include/aln -I/usr/include/glib-2.0 -I/usr/lib/aarch64-linux-gnu/glib-2.0/include -laln -lglib-2.0
aln.pc
์ ์ ์๋ ์์กด์ฑ ์ ๋ณด(Requires:
)๋ฅผ ์ฐธ์กฐํด์ ์์กด์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ glib์ ๋ํ ๋น๋ ์ต์
๊น์ง ํ๋ฒ์ ๊ฒฐ๊ณผ๋ก ์ถ๋ ฅ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
API ๋ฌธ์
์์์ ์ธ๊ธํ ํค๋ ํ์ผ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ, pkg-config ํ์ผ ๋ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณตํด์ผ ํ๋ ๊ธฐ๋ณธ ๊ตฌ์ฑ ์์๋ค ์ธ์๋ API ๋ฌธ์๊ฐ ์๋ค๋ฉด ๋์ฑ ์ข์ต๋๋ค. ๋ง์ ๊ฐ๋ฐ์๋ค์ด ๋ฌธ์ํ๋ฅผ ๊ท์ฐฎ์ํ์ง๋ง, API๋ฅผ ์์ฑํ ๋ Doxygen ํํ๋ก ์ฃผ์์ ์ถ๊ฐํด ๋์ผ๋ฉด ๋ฌธ์ ์์ ๋ ํฐ ๋ ธ๋ ฅ ์์ด ์ด๋ ์ ๋ ๋์์ด ๊ฐ๋ฅํฉ๋๋ค.
๋ํ Doxygen์ ์น๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฉํ ์ ์๋ HTML ๊ธฐ๋ฐ์ API ๋ฌธ์์ ์ฝ์์์ ํ์ธํ ์ ์๋ man ํ์ด์ง ํํ์ API ๋ฌธ์๋ฅผ ๋ชจ๋ ๋ง๋ค์ด๋ผ ์ ์์ต๋๋ค. ์์ธํ ์ฌ์ฉ๋ฒ์ https://www.doxygen.nl/manual/index.html ์์ ์ฐธ๊ณ ํ ์ ์์ต๋๋ค. ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ ALN์์๋ Doxygen์ ์ด์ฉํด์ ๋ฌธ์๋ฅผ ๋ง๋ค๊ณ ์์ผ๋ ์ฐธ๊ณ ํ์๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
์ํ ํ๋ก๊ทธ๋จ
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ๋ง๋ค์ด์ ์ ๊ณตํ๋๋ฐ, ์ฌ์ฉํ๋ ๊ณณ์์ ์๋ชป ์ฌ์ฉํ๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ ํ ์ ์์ต๋๋ค. ๋ฐ๋๋ก, ์ฌ์ฉํ๋ ๊ณณ์ ์์คํ ํน์ฑ์ ๊ณ ๋ คํ์ง ์์ ์ค์๋ํ ๊ฒฝ์ฐ ์ํ ํ๋ก๊ทธ๋จ์ด ์์ผ๋ฉด ์ด๋ฅผ ํตํด ๋ก๊ทธ ๋ฐ ๋คํ๋ฅผ ์ ๊ณต๋ฐ์ ์ ์์ด ๋๋ฒ๊น ์ ๋์์ด ๋ฉ๋๋ค. ๋ฐ๋ผ์ ๋์์ ๊ฒ์ฆํ ์ ์๋ ์ํ ํ๋ก๊ทธ๋จ๋ ๊ฐ์ด ์ ๊ณตํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ ๊ณตํ๋ API์ ๊ธฐ๋ฅ์ด ๋ค์ํ๋ค๋ฉด, ์ํ ํ๋ก๊ทธ๋จ์ ๊ธฐ๋ฅ ๋จ์๋ก ๋๋์ ์ฌ๋ฌ ๊ฐ์ ์ํ ํ๋ก๊ทธ๋จ๋ค์ ์ ๊ณตํ๊ฑฐ๋ ์คํ ์ต์ ์ ํตํด API๋ฅผ ํ ์คํธํ ์ ์๊ฒ ํ๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ ๋๋ค.
ALN์ ๊ฒฝ์ฐ ์ํ ํ๋ก๊ทธ๋จ ์คํ์ ์ถ๊ฐ ์ต์
์ ํตํด API ๊ธฐ๋ฅ์ ํ
์คํธํ ์ ์๊ฒ ๊ตฌํํ์๊ณ , --help
์ต์
์ผ๋ก ์ ์ฒด ์ต์
๋ค์ ํ์ธํ ์ ์๋๋ก ๊ตฌํํ์์ต๋๋ค.
์์ธํ ๋ด์ฉ์ https://github.com/webispy/aln/tree/master/tool ์ ์๋ ์์ค ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค.
ALN ๊ตฌ์ฑ ์์
ALN ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ต์ข ๋ฐฐํฌ ํ์ผ ๊ตฌ์กฐ๋ ์๋์ ๊ฐ์ต๋๋ค. (HTML ๊ธฐ๋ฐ์ API ๋ฌธ์๋ https://webispy.github.io/aln ์์ ํ์ธํ ์ ์์ต๋๋ค.)
.
โโโ usr
โโโ bin
โ โโโ aln
โโโ include
โ โโโ aln
โ โโโ aln.h
โโโ lib
โ โโโ x86_64-linux-gnu
โ โโโ libaln.so -> libaln.so.0
โ โโโ libaln.so.0 -> libaln.so.0.1.0
โ โโโ libaln.so.0.1.0
โ โโโ pkgconfig
โ โโโ aln.pc
โโโ share
โโโ man
โโโ man1
โ โโโ aln.1
โโโ man3
โโโ aln.h.3
โโโ aln_draw_all.3
โโโ aln_draw_number.3
โโโ aln_free.3
โโโ aln_get_number.3
โโโ aln_new.3
โโโ aln_reset.3
์ด ๊ตฌ์ฑ์ ํค๋ ํ์ผ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ, pkg-config ํ์ผ, ์ํ ์คํ ํ์ผ, ๊ทธ๋ฆฌ๊ณ man ํ์ด์ง๋ฅผ ํฌํจํ๊ณ ์์ด, ์ฌ์ฉ์๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฝ๊ฒ ์ฌ์ฉํ๊ณ ๋ฌธ์๋ฅผ ์ฐธ์กฐํ ์ ์๊ฒ ํด์ค๋๋ค.
๋ฉํฐ ํ๋ซํผ ์ง์์ ์ํด ๊ณ ๋ คํ๊ธฐ
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ๋ฌ ํ๋ซํผ์์ ์ฌ์ฉํ ์ ์๋๋ก ๋ง๋ค๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ ์์๋ค์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค:
- ๋น๋ ์์คํ
- ํ๋ซํผ๋ง๋ค ์ง์ํ๋ ๋น๋ ์์คํ ์ด ๋ค๋ฅผ ์ ์์ต๋๋ค.
- ํฌ๋ก์ค ํ๋ซํผ ๋น๋๋ฅผ ์ง์ํ๋ ๋น๋ ์์คํ ์ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ ํ๋ซํผ์์์ ๋น๋ ํ๋ก์ธ์ค๋ฅผ ๋จ์ํํ ์ ์์ต๋๋ค
- ํ๋ซํผ ํธํ์ฑ
- ๊ฐ ํ๋ซํผ๋ณ๋ก ํ์ค C API ๋ฐ ํ๋ ์์ํฌ API๊ฐ ๋ค๋ฅผ ์ ์์ต๋๋ค.
- ํ๋ซํผ ํน์ฑ์ ์ํฅ์ ๋ฐ๋ ํ๋ ์์ํฌ API๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ฉด, ์กฐ๊ฑด๋ถ ์ปดํ์ผ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์:
#ifdef _WIN32
- Shared Library ํน์ฑ
- ํ๋ซํผ๋ณ๋ก shared library์ ํน์ฑ์ด ๋ค๋ฅด๊ธฐ ๋๋ฌธ์, API ๊ตฌํ ์ ์ด๋ฅผ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
- ์๋ฅผ ๋ค์ด, ์ฌ๋ณผ ๊ฐ์์ฑ(symbol visibility) ์ค์ ์ ํตํด ์๋ํ API๋ง ์ธ๋ถ์ ๋ ธ์ถ๋๋๋ก ํด์ผ ํฉ๋๋ค.
ALN ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์์ ๊ณ ๋ ค์ฌํญ๋ค์ ๋ค์๊ณผ ๊ฐ์ด ์ ์ฉํ์์ต๋๋ค:
-
๋น๋ ์์คํ
- CMake๋ฅผ ์ ํํ์์ต๋๋ค. CMake๋ ์ค๋๋๊ณ ๋์ค์ ์ด๋ฉฐ, ๋ค์ํ ํ๋ซํผ์ ์ง์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ค๋ฅธ ์ต์ ์ผ๋ก๋ meson, scons, autotools ๋ฑ์ด ์์ผ๋ฉฐ, ๊ฐ์ธ ์ ํธ์ ๋ฐ๋ผ ์ ํํ ์ ์์ต๋๋ค.
- ๊ฐ์ธ์ ์ผ๋ก ๋ค์ ํ๋ก์ ํธ์ ๋น๋ ์์คํ ์ ์ ํํ๋ผ๊ณ ํ๋ฉด meson์ ์ ํํ ๊ฒ ๊ฐ์ต๋๋ค. ์ฐธ๊ณ ๋ก meson์์ ์ ๊ณตํ๋ ๋น๋ ์์คํ ๋น๊ต ๋ฌธ์ https://mesonbuild.com/Simple-comparison.html ๊ณต์ ๋๋ฆฝ๋๋ค.
-
ํ๋ซํผ ํธํ์ฑ
- ์ด๋ฒ ๊ธฐ์ ๋ธ๋ก๊ทธ์ ์ฃผ ๋ชฉ์ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฒด์ ์๊ธฐ ๋๋ฌธ์, ๋์ ํ๋ซํผ(Linux, macOS, Windows)์์ ๋ชจ๋ ํธํ ๊ฐ๋ฅํ API ๋ฐ ๋ชจ๋ ๋์ ํ๋ซํผ์ ์ง์ํ๋ ์์กด์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(glib)๋ฅผ ์ฌ์ฉํ์์ต๋๋ค.
- ๋ฐ๋ผ์ ALN ์ฝ๋ ์์๋ ํ๋ซํผ์ ๋ฐ๋ผ ๋ถ๊ธฐํด์ Framework API๋ฅผ ํธ์ถํ๋ ๋ก์ง์ ์์ต๋๋ค. ๋จ, API ์ฌ๋ณผ ์ฒ๋ฆฌ๋ฅผ ์ํ macro ์ฒ๋ฆฌ๋ ์กด์ฌํฉ๋๋ค.
-
Shared Library ํน์ฑ
- ์ฌ๋ณผ ๊ฐ์์ฑ ์ค์ ๋ฑ์ ํตํด ์๋ํ API๋ง ์ธ๋ถ์ ๋ ธ์ถ๋๋๋ก ํ์์ต๋๋ค. ๋ํ, Windows์ DLL ๋น๋์ ํ์ํ ์ฌ๋ณผ์ export/import ์ฒ๋ฆฌ๋ ํฌํจํ๊ณ ์์ต๋๋ค.
ํ๋ซํผ๋ณ Shared library ํน์ฑ
Linux
Linux์์ ์ฌ์ฉ๋๋ Shared library๋ .so
ํํ์ ํ์ผ ์ด๋ฆ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
๋ฒ์ ๋ฐ SONAME
.so
ํ์ผ์ ๊ฒฝ์ฐ ์ผ๋ฐ์ ์ผ๋ก 3๊ฐ์ ํ์ผ์ ๊ฐ์ด ์ ๊ณตํฉ๋๋ค. ์๋๋ ALN ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณตํ๋ ํ์ผ๋ค์
๋๋ค.
libaln.so -> libaln.so.0
libaln.so.0 -> libaln.so.0.1.0
libaln.so.0.1.0
์ค์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ์ libaln.so.0.1.0
์ด๊ณ , ๋๋จธ์ง 2๊ฐ ํ์ผ์ ์ด ํ์ผ์ ๋ํ symbolic link ์
๋๋ค.
์ ์ด๋ ๊ฒ ํ๋ ๊ฑธ๊น์? ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐฐํฌ ์ ํ์ ๋ณดํต ์๋ 2๊ฐ์ง๋ก ๋ถ๋ฅํ ์ ์์ต๋๋ค.
- ์ดํ๋ฆฌ์ผ์ด์ ์ ์ค์น/๋ฐฐํฌํ๋ ๋ฐ ํ์ํ ์์กด์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก์ ๋ฐฐํฌ
- ์ดํ๋ฆฌ์ผ์ด์ ์ ๋น๋ํ ๋ ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก์ ๋ฐฐํฌ
1๋ฒ์ ๊ฒฝ์ฐ ์ค์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ์ธ libaln.so.0.1.0
์ด ์์ด์ผ ํ๊ณ , 2๋ฒ์ ๊ฒฝ์ฐ ์ปดํ์ผํ ๋ -laln
์ต์
์ผ๋ก ๋งํฌํ๋ ค๋ฉด libaln.so
ํ์ผ์ด ์์ด์ผ ํฉ๋๋ค(ํค๋ํ์ผ๋ ์์ด์ผ ํฉ๋๋ค). ๋ฐ๋ผ์ ์ด 2๊ฐ ํ์ผ์ด ์กด์ฌํด์ผ ํ๋ค๋ ๊ฒ์ ์ด๋์ ๋ ์ดํด๊ฐ ๋ฉ๋๋ค.
๊ฒฝ์ฐ์ ๋ฐ๋ผ 1,2๋ฒ ๋ชจ๋์ ํด๋นํ ์๋ ์์ผ๋ 2๊ฐ ํ์ผ์ ๊ฐ๊ฐ ์ ๊ณตํ๋ ๊ฒ๋ณด๋ค Symbolic link๋ก ์ ๊ณตํ๋ ๊ฒ์ด ๋ ํจ์จ์ ์ผ ๊ฒ์ ๋๋ค.
libaln.so -> libaln.so.0.1.0
libaln.so.0.1.0
๊ทธ๋ผ libaln.so.0
ํ์ผ์ ์ ํ์ํ ๊น์? ์ผ๋ฐ์ ์ผ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ ์ major.minor.patch ํ์(Semantic Versioning ์ฐธ๊ณ )์ ๋ฐ๋ฆ
๋๋ค. ๊ทธ๋ฆฌ๊ณ major ๋ฒ์ ๋ณ๊ฒฝ์ API ํธํ์ฑ์ด ๊นจ์ง ์ ์์์ ์๋ฏธํฉ๋๋ค. ๋ฐ๋ผ์ v0.1.0์ v0.2.0์ API ํธํ์ฑ์ด ์ ์ง๋์ด์ผ ํ๊ณ , API์ ํฐ ๋ณ๋์ด ์๋ค๋ฉด major ๋ฒ์ ์ ์ฌ๋ ค์ v1.0.0 ๊ฐ์ ๋ฒ์ ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์, Linux ์์คํ ์ ์๋์ ๊ฐ์ด ๊ฐ์ ์ด๋ฆ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ๋ฐ major ๋ฒ์ ์ด ๋ค๋ฅธ ํ์ผ๋ค์ด ์กด์ฌํ ์ ์์ง๋ง, ๊ฐ์ major ๋ฒ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ผ๋ฐ์ ์ผ๋ก ์ต์ ๋ฒ์ 1๊ฐ๋ง ์กด์ฌํฉ๋๋ค.
libaln.so.0 -> libaln.so.0.1.1
libaln.so.0.1.0 -> ๋ถํ์ํ ํ์ผ
libaln.so.0.1.1
libaln.so.1 -> libaln.so.1.0.0
libaln.so.1.0.0
๋ง์ฝ ALN ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ด๋ถ์์ ๋ฒ๊ทธ ํจ์น ๋ฑ์ด ๋ฐ์ํด์ 0.1.1 ๋ฒ์ ์ด ์๋ก ๋ฐฐํฌ๋์๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค.
libaln.so.0.1.0 (๊ธฐ์กด)
libaln.so.0.1.1 (์ ๊ท)
์์คํ ์ ์ค์น๋ ALN ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ 0.1.1๋ก ๋ฒ์ ์ ๋๋ฉด ๊ธฐ์กด 0.1.0 ๋ฒ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋์ด์ ์กด์ฌํ ์ด์ ๊ฐ ์์ผ๋ ์ง์์ผ ํฉ๋๋ค. ๊ทธ๋ผ 0.1.0 ๋ฒ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํด ๋น๋๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ด๋ป๊ฒ ๋ ๊น์? ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์ผ๋ ์คํํ ์ ์์ต๋๋ค.
์ด๋ฐ ์ํฉ์ ํด๊ฒฐํ๊ธฐ ์ํด libaln.so.0
ํ์ผ์ด ํ์ํฉ๋๋ค.
์, ๋ค์ libaln.so.0.1.0
ํ์ผ๋ก ๋์๊ฐ์, ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ์ readelf
๋ผ๋ ํด์ ์ด์ฉํด ๋ด์ฉ์ ์ดํด๋ณด๋ฉด ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
$ readelf -d libaln.so.0.1.0
...
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libglib-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000e (SONAME) Library soname: [libaln.so.0]
...
NEEDED
type์ ์์กด์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํ ์ ๋ณด์
๋๋ค. ์ฌ๊ธฐ์ ์ค์ํ๊ฒ ๋ณผ ํญ๋ชฉ์ ๋ฐ๋ก SONAME
์
๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ ์ด๋ฆ์ ๋ถ๋ช
libaln.so.0.1.0
์ธ๋ฐ, ์ค์ SONAME
์ libaln.so.0
์ผ๋ก ์ค์ ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก, ALN ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ์ดํ๋ฆฌ์ผ์ด์
์ ๋น๋ํ ํ readelf
ํด์ ์ด์ฉํด์ ์ดํ๋ฆฌ์ผ์ด์
์ ๋ณด๋ฅผ ํ์ธํด ๋ณด๋ฉด ์๋์ ๊ฐ์ด NEEDED
ํญ๋ชฉ์ libaln.so.0.1.0
์ด ์๋๋ผ SONAME
์ธ libaln.so.0
์ด ์ฌ์ฉ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
$ readelf -d /usr/bin/aln
...
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libaln.so.0]
0x0000000000000001 (NEEDED) Shared library: [libglib-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
...
์ด๋ ๊ฒ ๋๋ฉด, aln v0.1.0
์์ aln v0.1.1
์ผ๋ก ๋ฒ์ ์ ์
๊ทธ๋ ์ด๋ ํด๋ ๊ธฐ์กด ์ดํ๋ฆฌ์ผ์ด์
์ ์ฌ์ ํ libaln.so.0
์ ๋ฐ๋ผ๋ณด๊ณ ์๊ธฐ ๋๋ฌธ์ ๋ณ๋์ ์ฌ๋น๋์์ด ์
๊ทธ๋ ์ด๋๋ ALN ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐฐํฌ์ ์๋์ฒ๋ผ ํ์ผ์ ๊ตฌ์ฑํ๊ฒ ๋ฉ๋๋ค.
# libaln v0.1.0
libaln.so -> libaln.so.0
libaln.so.0 -> libaln.so.0.1.0
libaln.so.0.1.0
# libaln v0.1.1
libaln.so -> libaln.so.0
libaln.so.0 -> libaln.so.0.1.1
libaln.so.0.1.1
๊ทธ๋ผ SONAME
์ ์ด๋ป๊ฒ ํด์ผ ์ค์ ํ ์ ์์๊น์?
์ง์ gcc ๋ฑ์ ์ด์ฉํด ์ปดํ์ผํ ๊ฒฝ์ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋น๋์ ์ปดํ์ผ ์ต์
์ -Wl,-soname,libaln.so.0
์ต์
์ ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค.
CMake์ ๊ฐ์ ๋น๋ ์์คํ
์ ์ฌ์ฉํ๋ค๋ฉด ์๋์ฒ๋ผ Property๋ฅผ ์ค์ ํ๋ฉด ๋ฉ๋๋ค.
set_target_properties(libaln PROPERTIES VERSION "0.1.0" SOVERSION 0 OUTPUT_NAME aln)
Symbol visibility
๋ค๋ฅธ ๊ณ ๊ธ ์ธ์ด๋ค๊ณผ๋ ๋ฌ๋ฆฌ C ์ธ์ด์๋ ๋ณ๋์ namespace๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค. ์ด๋ ๊ฐ๋ฐ์๊ฐ ๋ง๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ API๊ฐ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ API์ ์ด๋ฆ์ด ์ถฉ๋ํ ์ ์์์ ์๋ฏธํฉ๋๋ค. ์ด๋ฐ ์ํฉ์ด ๋ฐ์ํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์์ ์ผ๋ก ๋น๋ํ ์ ์์ต๋๋ค. ๊ฒฐ๊ตญ, ์ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ด๋ฆ์ ๋ฐ๊ฟ์ผ ํ๋ ์ํฉ์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
๊ทธ๋์ ๋ณดํต ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋งค์ฐ ์ ๋ช ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ ๊ฒฝ์ฐ, ๊ณต๊ฐํ API ์ด๋ฆ ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ด๋ฆ์ ๋ถ์ด๋ ๊ฒ์ด ๊ดํ์ ๋๋ค.
int draw_all(...); // X
int aln_draw_all(...); // O
ํ์ง๋ง, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ท๋ชจ๊ฐ ์ปค์ง๋ฉด ์๊ธฐ์น ์๊ฒ ์ด๋ฆ์ด ์ถฉ๋ํ๋ ์ํฉ์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ด์ ์์ค ํ์ผ์ด ์์ญ ๊ฐ๋ก ๋์ด๋๊ณ , ํจ์๊ฐ ์ปค์ ธ ์ฌ๋ฌ ํจ์๋ก ๋ถ๋ฆฌ๋๋ฉฐ, ๋ค๋ฅธ ์์ค ํ์ผ์ ํจ์๋ฅผ ํธ์ถํ๋ ๋ฑ์ ์ํฉ์ด ๋ณต์กํด์ง๋ฉด ๋ชจ๋ ํจ์์ prefix๋ฅผ ๋ถ์ด๊ธฐ ์ด๋ ค์์ง๋๋ค.
๋ค์์ ์ด๋ฐ ์ํฉ์ ์ค๋ช ํ๋ ๊ฐ๋จํ ์์ค์ฝ๋์ ์๊ตฌ์ฌํญ์ ๋๋ค.
์์ค์ฝ๋:
// include/aln_foo.h
int aln_foo_draw();
// src/aln_foo.c
int calculate() { ... }
int aln_foo_draw() { calculate(); gen_hash(); ... }
// include/aln_bar.h
int aln_bar_draw();
// src/aln_bar.c
int aln_bar_draw() { gen_hash(); ... }
// src/util.h
int gen_hash()
// src/util.c
int gen_hash() { ... }
์๊ตฌ์ฌํญ:
aln_foo.h
,aln_bar.h
๋ฅผ ํตํดaln_foo_draw()
,aln_bar_draw()
๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.aln_foo.c
๋ด์calculate()
ํจ์๋ ํด๋น ์์คํ์ผ ๋ด์์๋ง ์ฌ์ฉํฉ๋๋ค.- ๋ด๋ถ ๊ณต์ฉ ๊ธฐ๋ฅ์ผ๋ก
util.c
์gen_hash()
ํจ์๋ฅผ ๋ง๋ค์๋๋ฐ, ์ด ํจ์๋ ์ธ๋ถ๋ก header ํ์ผ์ ์ ๊ณตํ์ง ์์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ํจ์ ์ฌ๋ณผ์ด ์ฌ์ ํ ๋ ธ์ถ๋๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ํด๊ฒฐํ๊ณ ์ถ์ต๋๋ค.
์ผ๋จ aln_foo.c
์ calculate()
ํจ์๋ static
์ ํตํด ์ฝ๊ฒ ํด๊ฒฐํ ์ ์์ต๋๋ค.
// src/aln_foo.c
static int calculate() { ... }
int aln_foo_draw() { calculate(); gen_hash(); ... }
๊ทธ๋ฌ๋ util.c
์ gen_hash
์ฌ๋ณผ์ ์ธ๋ถ๋ก ๋
ธ์ถ๋์ง ์๊ฒ ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น์?
GCC ์์๋ -fvisibility
๋ผ๋ ์ต์
์ ์ ๊ณตํ๊ณ ์๋๋ฐ, ๊ธฐ๋ณธ๊ฐ์ -fvisibility=default
์
๋๋ค. ์ด๋ ๋ชจ๋ ์ฌ๋ณผ์ด ์ธ๋ถ๋ก ๋
ธ์ถ๋๋ค๋ ์๋ฏธ์
๋๋ค. ์ด ๊ฐ์ -fvisibility=hidden
์ผ๋ก ๋ณ๊ฒฝํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ์ฌ๋ณผ์ด ์จ๊ฒจ์ง๋ฉฐ, ์ํ๋ ์ฌ๋ณผ๋ง ์๋์ ๊ฐ์ด annotation์ ํตํด ๋
ธ์ถํ ์ ์์ต๋๋ค.
// include/aln_bar.h, include/aln_foo.h
#ifndef ALN_API
#define ALN_API __attribute__ ((visibility ("default")))
#endif
ALN_API aln_foo_draw();
ALN_API aln_bar_draw();
์ด ๋ฐฉ๋ฒ์ ์ฅ์ ์ ๋ด๊ฐ API๋ก ์ ๊ณตํ๊ณ ์ถ์ ํจ์๋ค๋ง ์ ํ์ ์ผ๋ก ๋ ธ์ถํ ์ ์๋ค๋ ์ ์ธ์๋ ๋ค์๊ณผ ๊ฐ์ ์ถ๊ฐ ์ฅ์ ์ด ์์ต๋๋ค. (ChatGPT ํ์ฐฌ)
- ๋ฐ์ด๋๋ฆฌ ํฌ๊ธฐ ๊ฐ์ ๊ธฐ๋ณธ ๊ฐ์์ฑ์ hidden์ผ๋ก ์ค์ ํ๋ฉด ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํฌํจ๋๋ ์ฌ๋ณผ ์๊ฐ ์ค์ด๋ญ๋๋ค. ์ด๋ ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ฐ์ด๋๋ฆฌ ํฌ๊ธฐ๋ฅผ ๊ฐ์์ํค๊ณ , ๋ก๋ ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ค์ ๋๋ค.
- ๋งํฌ ์๊ฐ ๋ฐ ๋ก๋ ์๊ฐ ๋จ์ถ ์ฌ๋ณผ ํด์์ ํ์ํ ์๊ฐ์ด ์ค์ด๋ค๊ธฐ ๋๋ฌธ์ ๋งํฌ ์๊ฐ๊ณผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ก๋ ์๊ฐ์ด ๋จ์ถ๋ฉ๋๋ค. ์ด๋ ํ๋ก๊ทธ๋จ ์์ ์๊ฐ์ ๊ฐ์ ํ ์ ์์ต๋๋ค.
- ๋ค์์คํ์ด์ค ์ถฉ๋ ๊ฐ์ ์จ๊ฒจ์ง ์ฌ๋ณผ์ ์ธ๋ถ์์ ์ฐธ์กฐํ ์ ์์ผ๋ฏ๋ก, ๋์ผํ ์ฌ๋ณผ ์ด๋ฆ์ ์ฌ์ฉํ๋ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ถฉ๋์ ๋ฐฉ์งํ ์ ์์ต๋๋ค. ์ด๋ ํนํ ๋๊ท๋ชจ ํ๋ก์ ํธ์์ ์ค์ํ ์ด์ ์ ๋๋ค.
- ์ต์ ํ ๊ธฐํ ์ฆ๊ฐ ์ปดํ์ผ๋ฌ๊ฐ ์จ๊ฒจ์ง ์ฌ๋ณผ์ ๋ ๊ณต๊ฒฉ์ ์ผ๋ก ์ต์ ํํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ธ๋ผ์ธ ํ์ฅ์ด๋ ๋ถํ์ํ ์ฝ๋ ์ ๊ฑฐ์ ๊ฐ์ ์ต์ ํ๊ฐ ๋ ์ ์ํ๋ ์ ์์ต๋๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ๊ณตํ๋ ์ ์ฅ์์๋ ์ฌ์ฉํ์ง ์์ ์ด์ ๊ฐ ์๋ ์ต์ ์ ๋๋ค. ์์ ๋ก ๋ง๋ ALN ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ท๋ชจ๊ฐ ์์ ๋ด๋ถ ํจ์ ์์ด ์ ๋ถ ์ธ๋ถ๋ก ๋ ธ์ถํ ํจ์๋ค๋ก๋ง ๊ตฌ์ฑ๋์ด ์์ง๋ง, ์์ค์ฝ๋์์ ์ ์ต์ ๋ค์ ์ฐธ๊ณ ํ ์ ์์ต๋๋ค.
rpath
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ๋ฐํ ๋, ์ ๋ ํ ์คํธ๋ ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ํตํด ์ง์ ์คํํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋์์ ํ์ธํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ์ด ๊ณผ์ ์์ ๋ค์๊ณผ ๊ฐ์ ์๋ฌ ๋ฉ์์ง๋ฅผ ์์ฃผ ๋ง์ฃผ์น ๊ฒฝํ์ด ์์ ๊ฒ์ ๋๋ค.
$ ./aln
./aln: error while loading shared libraries: libaln.so.0: cannot open shared object file: No such file or directory
์ฌ์ง์ด ์คํ ํ์ผ์ธ aln
๊ณผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ์ธ libaln.so.0
์ด ๊ฐ์ ๋๋ ํ ๋ฆฌ ์์ ์๋๋ฐ๋ ์คํ์ด ๋์ง ์์ต๋๋ค.
$ ls
aln libaln.so libaln.so.0 libaln.so.0.1.0
์ด๋ ๋ง์ปค๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ค์ ๋ ์์คํ
๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฒฝ๋ก(/lib
, /usr/lib
๋ฑ)์์๋ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์ผ๋ ค๊ณ ํ๊ธฐ ๋๋ฌธ์
๋๋ค. ์๋์ ๊ฐ์ด ๋๋ฒ๊น
์ต์
์ ์ผ๊ณ ์คํ์ ํ๋ฉด ์ด๋ค ๊ฒฝ๋ก๋ฅผ ์ฐพ๋์ง ํ์ธํ ์ ์์ต๋๋ค.
$ LD_DEBUG=libs ./aln
4068: find library=libaln.so.0 [0]; searching
4068: search cache=/etc/ld.so.cache
4068: search path=...:/lib/aarch64-linux-gnu/aarch64:...
:/usr/lib/aarch64-linux-gnu:/...:/usr/lib (system search path)
...
4068: trying file=/lib/aarch64-linux-gnu/libaln.so.0
...
4068: trying file=/usr/lib/aarch64-linux-gnu/libaln.so.0
...
./aln: error while loading shared libraries: libaln.so.0: cannot open shared object file: No such file or directory
์์ ๊ฐ์ ์ํฉ์์ ์ผ๋ฐ์ ์ผ๋ก LD_LIBRARY_PATH
ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค.
# ํ๊ฒฝ๋ณ์์ ํ์ฌ ๋๋ ํ ๋ฆฌ๋ฅผ ์ค์ ํ๊ณ aln ์คํ
$ LD_LIBRARY_PATH=. ./aln
# ํ๊ฒฝ๋ณ์ ์
๋ฐ์ดํธ ํ ์คํ
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
$ ./aln
# ๋๋ฒ๊น
์ต์
์ ํตํด ํ์ธ
$ LD_DEBUG=libs LD_LIBRARY_PATH=. ./aln
5131: find library=libaln.so.0 [0]; searching
5131: search path=./tls/aarch64/atomics:./tls/aarch64
:./tls/atomics:./tls:./aarch64/atomics:./aarch64:./atomics:. (LD_LIBRARY_PATH)
...
5131: trying file=./libaln.so.0
ํ์ง๋ง, ๋งค๋ฒ LD_LIBRARY_PATH
ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ๋ ๊ฒ์ ๋นํจ์จ์ ์ผ ์ ์๋๋ฐ, ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก rpath
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. rpath
๋ ์คํ ํ์ผ์ ๋ด์ฅ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฒ์ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ์ฌ, ์คํ ์์ ์ ๋์ ์ผ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ๋ ๊ณผ์ ์์ ๊ฒฝ๋ก๋ฅผ ๋ณ๊ฒฝํฉ๋๋ค.
์ปดํ์ผ ๊ณผ์ ์์ ์๋์ ๊ฐ์ด -Wl,-rpath,{path}
์ต์
์ ํตํด ๊ฒฝ๋ก๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
gcc -o myapp myapp.c -Wl,-rpath,/path/to/libs -L/path/to/libs -lmylib
์๋๋ rpath
๊ฐ ์ ์ฉ๋ aln ์คํํ์ผ์ readelf
๋ช
๋ น์ผ๋ก ํ์ธํด๋ณธ ๊ฒฐ๊ณผ์
๋๋ค.
$ readelf -d build/tool/aln
...
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libaln.so.0]
0x0000000000000001 (NEEDED) Shared library: [libglib-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
0x000000000000001d (RUNPATH) Library runpath: [/home/parallels/git/my/aln/build/src:]
...
์์ค ์ฝ๋๊ฐ ์๋ ๋๋ ํ ๋ฆฌ๋ /home/parallels/git/my/aln
์ด๊ณ , ๋น๋์ build
๋๋ ํ ๋ฆฌ ์๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์คํํ์ผ๋ค์ด ์์ฑ๋๋๋ก ๊ตฌ์ฑ๋์ด ์๋ ์ํ์์ rpath
(RUNPATH
) ๊ฐ์ด ์ ์์ ์ผ๋ก ์ค์ ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
์ด์ ์ ๋ ํ ์คํธ๋ ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์คํ์ ๋ณ๋ค๋ฅธ ์ค์ ์์ด ๋ฐ๋ก ์คํํ๋ฉด ์๋ฌ ์์ด ์ ์์ ์ผ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์์ ์คํ๋ฉ๋๋ค.
$ LD_DEBUG=libs ./aln
6659: find library=libaln.so.0 [0]; searching
6659: search path=.../home/parallels/git/my/aln/build/src:tls/aarch64/atomics:tls/aarch64
:tls/atomics:tls:aarch64/atomics:aarch64:atomics: (RUNPATH from file ./aln)
...
6659: trying file=/home/parallels/git/my/aln/build/src/libaln.so.0
...์คํ ๊ฒฐ๊ณผ...
๋จ, ์ฃผ์ํ ์ ์ ๊ฐ๋ฐ ๋จ๊ณ์์๋ rpath
๋ฅผ ์ฌ์ฉํ๋ฉด ์ข์ง๋ง ์ด๋ฅผ ์ธ๋ถ์ ๋ฐฐํฌํ ๋์๋ ๊ผญ ํ์ํ ๊ฒฝ์ฐ๊ฐ ์๋๋ฉด rpath
์ ๋ณด๋ฅผ ์ ๊ฑฐํ ์ํ๋ก ๋ฐฐํฌํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์๋์ผ๋ก ์ ๊ฑฐํ๋ ๋ฐฉ๋ฒ์ chrpath
๋๊ตฌ๋ฅผ ์ค์นํด์ chrpath -d aln
๋ช
๋ น์ผ๋ก ์ ๊ฑฐํ ์ ์์ต๋๋ค.
๋ ์ฌ์ด ๋ฐฉ๋ฒ์ CMake์ ๊ฐ์ ๋น๋ ์์คํ
์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. CMake๋ฅผ ํตํด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ง๋ค๊ณ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์์กด์ฑ์ ๊ฐ์ง๋ ์คํํ์ผ์ ๋น๋ํ๋ฉด ์๋์ผ๋ก rpath
์ ๋ณด๊ฐ ์คํํ์ผ์ ์ฝ์
๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ cmake install
์ ํตํด ๋น๋ํ ํ์ผ๋ค์ ์ค์นํ๋ฉด ์๋์ผ๋ก rpath
์ ๋ณด๊ฐ ์ ๊ฑฐ๋ ์ํ๋ก ์ค์น๋ฉ๋๋ค.
์๋๋ ALN ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํด CMake๋ฅผ ์ฌ์ฉํด์ ๋น๋ ๋ฐ ์คํ, ๋ฐฐํฌํ ํ์ผ๋ค์ ๋ง๋ค์ด๋ด๋ ์์ ์ ๋๋ค.
- ๋จผ์ ํ๋ก์ ํธ์ ์ ์๋ CMakeLists.txt ์คํฌ๋ฆฝํธ๋ฅผ ์ด์ฉํด์ ๋น๋ configuration์ ์งํํฉ๋๋ค. ๊ฒฐ๊ณผ๋ฌผ์ ํ์์ build ๋๋ ํ ๋ฆฌ์ ์์ฑ๋ฉ๋๋ค.
$ cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.2")
-- Checking for module 'glib-2.0'
-- Found glib-2.0, version 2.72.4
-- Configuring done
-- Generating done
-- Build files have been written to: /home/parallels/git/my/aln/build
- ๋ค์์ผ๋ก ์์์ ์์ฑ๋ ๋น๋ configuration์ ๊ธฐ๋ฐ์ผ๋ก ์ค์ ๋น๋๋ฅผ ์งํํฉ๋๋ค.
$ cmake --build build --parallel
[ 16%] Building C object src/CMakeFiles/libaln.dir/aln.c.o
[ 33%] Linking C shared library libaln.so
[ 33%] Built target libaln
[ 66%] Building C object tool/CMakeFiles/aln.dir/main.c.o
[ 66%] Building C object tests/CMakeFiles/test_default.dir/test_default.c.o
[ 83%] Linking C executable aln
[100%] Linking C executable test_default
[100%] Built target aln
[100%] Built target test_default
- ์์ฑ๋ ์คํ ํ์ผ๋ค์๋
rpath
์ ๋ณด๊ฐ ๋ชจ๋ ์ฝ์ ๋์ด ์๊ธฐ ๋๋ฌธ์, ์ง์ ์ ๋ ํ ์คํธ ๋ฐ ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํ ์ ์์ต๋๋ค.
$ cd build && make test && cd -
Running tests...
Test project /home/parallels/git/my/aln/build
Start 1: test_default
1/1 Test #1: test_default ..................... Passed 0.00 sec
100% tests passed, 0 tests failed out of 1
Total Test time (real) = 0.01 sec
$ ./build/tool/aln
01 05 36 16 25 07
22 09 07 04 23 11
32 44 21 13 22 01
16 33 03 39 31 26
19 32 22 17 06 31
- ๋ฐฐํฌํ ํ์ผ๋ค์ ์์ฑํฉ๋๋ค. ์ฌ๊ธฐ์ ์์ฑ๋ ํ์ผ๋ค์
rpath
์ ๋ณด๊ฐ ๋น ์ ธ์์ต๋๋ค. ์ฐธ๊ณ ๋กDESTDIR
ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ์ง ์์ผ๋ฉด ์์คํ (/usr/
๊ฒฝ๋ก)์ ๋ฐ๋ก ์ค์น๋ฉ๋๋ค. ์ด์ ์์ฑ๋out
๋๋ ํ ๋ฆฌ์ ์๋ ํ์ผ๋ค์ ๋ฌถ์ด์ ๋ฐฐํฌํ๋ฉด ๋ฉ๋๋ค.
$ DESTDIR=out cmake --install build
-- Install configuration: ""
-- Installing: out/usr/include/aln/
-- Installing: out/usr/include/aln//aln.h
-- Installing: out/usr/lib/aarch64-linux-gnu/pkgconfig/aln.pc
-- Installing: out/usr/lib/aarch64-linux-gnu/libaln.so.0.1.0
-- Installing: out/usr/lib/aarch64-linux-gnu/libaln.so.0
-- Installing: out/usr/lib/aarch64-linux-gnu/libaln.so
-- Installing: out/usr/bin/aln
-- Set runtime path of "out/usr/bin/aln" to ""
-- Installing: out/usr/share/man/man1/aln.1
macOS
macOS์์ ์ฌ์ฉ๋๋ Shared library๋ .dylib
ํํ์ ํ์ผ ์ด๋ฆ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. Linux์ ์ ์ฌํ ์ ๋ค์ด ๋ง์ง๋ง, ๋ช ๊ฐ์ง ์ฐจ์ด์ ์ด ์์ต๋๋ค.
Linux์ ์ ์ฌํ ์
- ํ์ผ ํ์ฅ์:
.so
๋์.dylib
๋ฅผ ์ฌ์ฉํฉ๋๋ค. - ๋ฒ์ ๊ด๋ฆฌ: Linux์ ์ ์ฌํ๊ฒ symbolic link๋ฅผ ์ฌ์ฉํ์ง๋ง, ํ์ฅ์๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ํํ๊ฐ ์ฝ๊ฐ ๋ค๋ฆ ๋๋ค.
libaln.0.dylib -> libaln.0.1.0.dylib
libaln.dylib -> libaln.0.dylib
libaln.0.1.0.dylib
๋ค๋ฅธ ์
macOS์๋ rpath
์ ์ ์ฌํ ๊ฐ๋
์ด ์กด์ฌํ์ง๋ง ์ด๋ฅผ ์ค์ ํ๊ณ ํ์ธํ๋ ๋ฐฉ๋ฒ์ด ์กฐ๊ธ ๋ค๋ฆ
๋๋ค. ์๋์์ ๋ค์ ํญ๋ชฉ๋ค์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
@executable_path
@loader_path
@rpath
์๋์ ๋๊ตฌ๋ค๋ ๊ฐ์ด ์ฌ์ฉ๋๋ฉฐ, ์ค๋ช ์ ์๋ ์์ ๋ฅผ ์ฐธ๊ณ ํ๋ฉด ์ดํดํ๋ ๋ฐ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
install_name_tool
- change dynamic shared library install namesotool
- object file displaying tool
@executable_path
Linux์ ๋ค๋ฅด๊ฒ macOS์๋ @executable_path
๋ผ๋ ์ต์
์ด ์กด์ฌํฉ๋๋ค. ๊ฐ๋จํ ์์ ๋ฅผ ํตํด ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
// get_num.h
int get_num();
// get_num.c
int get_num() { return 1; }
// main.c
#include "get_num.h"
int main() { return get_num(); }
์ปดํ์ผ ๋ฐ ์คํ:
gcc -dynamiclib -o libget_num.dylib get_num.c
gcc -o main main.c -L . -lget_num
./main
Linux์์๋ LD_LIBRARY_PATH
๋ฑ์ ์ค์ ํด์ผ ๋์ํ๋๋ฐ, macOS์์๋ ์ ์์ ์ผ๋ก ์คํ๋ฉ๋๋ค. otool
๋ก ํ์ธํด๋ณด๋ฉด ์๋ฌด๋ฐ ๊ฒฝ๋ก ์ ๋ณด ์์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ ์ด๋ฆ(์ค์ ๋ก๋ LC_ID_DYLIB
ํญ๋ชฉ์ ์ค์ ๋ ์ด๋ฆ)์ด ๊ทธ๋๋ก ์ ์ฉ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
$ otool -L libget_num.dylib
libget_num.dylib:
libget_num.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1345.120.2)
$ otool -L main
main:
libget_num.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1345.120.2)
๊ทธ๋ฌ๋, ์๋์ ๊ฐ์ด ๋ค๋ฅธ ๋๋ ํ ๋ฆฌ์์ ์คํํ๋ฉด ์คํํ ์ ์๋ค๋ ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค.
$ mkdir sub && cd sub
$ ../main
dyld[27832]: Library not loaded: libget_num.dylib
Referenced from: <EFBFA0E2-6711-3629-A8A8-C5CB8BB113A8> /Volumes/work/git/my/aln/mac/main
Reason: tried: 'libget_num.dylib' (no such file), ...
[1] 27832 abort ../main
์ด ๋ install_name_tool
์ ์ด์ฉํด @executable_path
๋ฅผ ์ ์ฉํ๋ฉด ์คํํ ์ ์๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
$ install_name_tool -change libget_num.dylib @executable_path/libget_num.dylib main
$ otool -L main
main:
@executable_path/libget_num.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1345.120.2)
$ cd sub
$ ../main
main
์คํํ์ผ์์ libget_num.dylib
๋ฅผ ์ฐพ์ ๋, @executable_path
๊ฐ ์ ์ฉ๋์ด ์๊ธฐ ๋๋ฌธ์, main
์ด ์คํ๋ ๊ฒฝ๋ก์์ libget_num.dylib
๋ฅผ ์ฐพ๊ฒ ๋ฉ๋๋ค. ๋ฐ๋ผ์, ํ์ ๋๋ ํ ๋ฆฌ์์ main
์ ์คํํ์ด๋ main
์ ํ๋ฆฌ์ผ์ด์
์ด ์์นํ๋ ๋๋ ํ ๋ฆฌ์ libget_num.dylib
์ด ๊ฐ์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์ ์์ ์ผ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์์ ์คํ๋ฉ๋๋ค.
@loader_path
์์ ์์ ์ฝ๋๋ฅผ ์กฐ๊ธ ๋ณ๊ฒฝํด์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(libget_num.dylib
)๊ฐ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(libget_even_num.dylib
)์ ๋ํด ์์กด์ฑ์ ๊ฐ์ง๋๋ก ์์ ํด๋ณด๊ฒ ์ต๋๋ค.
// get_even_num.h
int get_even_num();
// get_even_num.c
int get_even_num() { return 2; }
// get_num.h
int get_num();
// get_num.c
#include "get_even_num.h"
int get_num() { return get_even_num(); }
// main.c
#include "get_num.h"
int main() { return get_num(); }
์ปดํ์ผ ๋ฐ ์คํ: libget_even_num.dylib
-> libget_num.dylib
-> main
gcc -dynamiclib -o libget_even_num.dylib get_even_num.c
gcc -dynamiclib -o libget_num.dylib get_num.c -L. -lget_even_num
gcc -o main main.c -L . -lget_num
./main
์ด๋ฒ์๋ ์ ์์ ์ผ๋ก ์คํ์ด ๋ฉ๋๋ค. ๊ทธ๋ฌ๋, ํ์ ๋๋ ํ ๋ฆฌ์์ ์คํํ ๊ฒฝ์ฐ @executable_path
๋ฅผ ์ค์ ํ์์๋ ์ ์์ ์ผ๋ก ์คํ๋์ง ์์ต๋๋ค.
$ install_name_tool -change libget_num.dylib @executable_path/libget_num.dylib main
$ otool -L main
main:
@executable_path/libget_num.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1345.120.2)
$ mkdir sub && cd sub
$ ../main
dyld[38258]: Library not loaded: libget_even_num.dylib
Referenced from: <4CCFE945-934C-38A9-AF72-19E2BB273789> /Volumes/work/git/my/aln/mac/libget_num.dylib
Reason: tried: 'libget_even_num.dylib' (no such file)
[1] 38258 abort ../main
๊ทธ ์ด์ ๋ main
์์ ์์กดํ๊ณ ์๋ libget_num.dylib
๋ @executable_path
๋ฅผ ํตํด ์ ์์ ์ผ๋ก ์ฐพ์ ์ ์์ง๋ง, libget_num.dylib
๊ฐ ์์กดํ๊ณ ์๋ libget_even_num.dylib
๋ ์ฐพ์ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
$ otool -L libget_num.dylib
libget_num.dylib:
libget_num.dylib (compatibility version 0.0.0, current version 0.0.0)
libget_even_num.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1345.120.2)
$ otool -L libget_even_num.dylib
libget_even_num.dylib:
libget_even_num.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1345.120.2)
์ด ๋ install_name_tool
์ ์ด์ฉํด libget_num.dylib
๋ผ์ด๋ธ๋ฌ๋ฆฌ์ @loader_path
๋ฅผ ์ ์ฉํ๋ฉด ์คํํ ์ ์๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
$ install_name_tool -change libget_even_num.dylib @loader_path/libget_even_num.dylib libget_num.dylib
$ otool -L libget_num.dylib
libget_num.dylib:
libget_num.dylib (compatibility version 0.0.0, current version 0.0.0)
@loader_path/libget_even_num.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1345.120.2)
@rpath
Linux์ ์ ์ฌํ๊ฒ macOS์์๋ rpath
์ ๋ณด๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
$ gcc -dynamiclib -o libget_even_num.dylib get_even_num.c -install_name @rpath/libget_even_num.dylib
$ otool -L libget_even_num.dylib
libget_even_num.dylib:
@rpath/libget_even_num.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1345.120.2)
# libget_num.dylib์์ ์์กดํ๋ libget_even_num.dylib ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์๋ ์ฌ์ฉํ rpath ์ ๋ณด๋ฅผ ์ถ๊ฐ
$ gcc -dynamiclib -o libget_num.dylib get_num.c -install_name @rpath/libget_num.dylib -L. -Wl,-rpath,$PWD -lget_even_num
$ otool -L libget_num.dylib
libget_num.dylib:
@rpath/libget_num.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libget_even_num.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1345.120.2)
# otool๋ก ํ์ธํด๋ณด๋ฉด LC_RPATH ํญ๋ชฉ์ด ์ถ๊ฐ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
$ otool -l libget_num.dylib
...
Load command 13
cmd LC_RPATH
cmdsize 48
path /Volumes/work/git/my/aln/mac (offset 12)
...
# ์คํํ์ผ์๋ rpath๋ฅผ ์ค์ ํฉ๋๋ค.
$ gcc -o main main.c -L. -Wl,-rpath,$PWD -lget_num
์ด์ ์คํํด๋ณด๋ฉด ํ์ฌ ๋๋ ํ ๋ฆฌ ๋ฟ๋ง ์๋๋ผ ๋ค๋ฅธ ๋๋ ํ ๋ฆฌ์์๋ ๋ณ๋ค๋ฅธ ์ค์ ์์ด ์ ์์ ์ผ๋ก ์คํ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
./main
mkdir sub && cd sub
../main
Windows
Windows์ ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ Linux๋ macOS์ ๋ช ๊ฐ์ง ์ค์ํ ์ฐจ์ด์ ์ด ์์ต๋๋ค:
- ํ์ผ ํ์ฅ์:
.dll
(Dynamic-Link Library)์ ์ฌ์ฉํฉ๋๋ค. - Windows๋ ์ผ๋ฐ์ ์ผ๋ก symbolic link์ ํ์ผ๋ช ์ ํตํ ๋ฒ์ ๊ด๋ฆฌ๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.
- Import Library: Windows์์๋
.dll
ํ์ผ๊ณผ ํจ๊ป.lib
ํ์ผ(import library)์ ์ ๊ณตํฉ๋๋ค. ์ด ํ์ผ์ ์ปดํ์ผ ์์ ์ฌ์ฉ๋ฉ๋๋ค. - Symbol Export/Import: Windows์์๋
__declspec(dllexport)
์__declspec(dllimport)
๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ณผ์ ๊ฐ์์ฑ์ ์ ์ดํฉ๋๋ค.
3๋ฒ๊ณผ 4๋ฒ์ด ๊ฐ์ฅ ํฐ ์ฐจ์ด์ ์ธ๋ฐ, ํ๋์ฉ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
dll / lib
Linux์ macOS์์๋ ํฌ๊ฒ 2๊ฐ์ง ์ข ๋ฅ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ตฌ๋ถํ ์ ์์์ต๋๋ค.
- Static library (
.a
) - Shared library (
.so
,.dylib
)
Static library์ ๊ฒฝ์ฐ ๊ฐ์ ธ๋ค ์ฌ์ฉํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ์ด ํฌํจ๋์ด ๋น๋ ๋ฐ ๋ฐฐํฌ๋๊ณ , Shared library์ ๊ฒฝ์ฐ๋ ๋น๋ํ ๋ ๋งํฌ๋ง ๋๊ณ ๋ณ๊ฐ๋ก ๋ฐฐํฌ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์ ํ๋ฆฌ์ผ์ด์
์์ Shared library๋ก๋ง ์ฌ์ฉํ ๊ฒฝ์ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐฐํฌ ์ .a
ํ์ผ์ ๊ฐ์ด ๋ฐฐํฌํ ํ์๊ฐ ์์ต๋๋ค.
ํ์ง๋ง, Windows์์๋ .lib
ํ์ผ์ด Static library ์ญํ ๋ ํ์ง๋ง .dll
์ ๋ํ Import library ์ญํ ๋ ๊ฐ์ด ์ํํฉ๋๋ค. Import Library๋ DLL์ ํจ์๋ฅผ ํธ์ถํ๋ ๋ฐ ํ์ํ ์ ๋ณด๋ฅผ ํฌํจํ๊ณ ์์ด, ๋ง์ปค๊ฐ ์ด๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์
๊ณผ DLL์ ์ฐ๊ฒฐํฉ๋๋ค.
๋ฐ๋ผ์ .dll
ํ์ผ๋ง ์์ด๋ ์คํํ ๋๋ ๋ฌธ์ ๊ฐ ์์ง๋ง, ๋น๋ํ ๋๋ .lib
ํ์ผ์ด ์์ด์ผ ์ ํ๋ฆฌ์ผ์ด์
์ ์ ์์ ์ผ๋ก ๋น๋ํ ์ ์์ต๋๋ค.
Linux์ macOS์์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์ ๋ rpath์ ๊ฐ์ ๋ฐฉ๋ฒ์ ์ฌ์ฉํด์ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ ์ ์์์ต๋๋ค. ํ์ง๋ง, Windows๋ ์ง์ ์ ์ธ rpath ๊ฐ๋
์ด ์์ต๋๋ค. ์คํ ํ์ผ๊ณผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(.dll
)๊ฐ ๊ฐ์ ๊ฒฝ๋ก์ ์๊ฑฐ๋, PATH
ํ๊ฒฝ ๋ณ์๋ก ์ง์ ๋ ๊ฒฝ๋ก์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์ผ๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.
dllexport / dllimport
๋ค์์ผ๋ก ์ดํด๋ณผ ํน์ง์ Linux์ macOS์๋ ์๋ ๊ฐ๋ ์ด๋ผ์ ์กฐ๊ธ ํน์ดํฉ๋๋ค. Windows์์๋ ํจ์๋ฅผ ์ ์ํ ๋ ์ด ํจ์๊ฐ DLL๋ก ์ ๊ณตํ๊ธฐ ์ํด ๋ด๋ณด๋ผ ๋ชฉ์ ์ธ์ง, DLL์์ ์ ๊ณตํ ํจ์๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ๊ฐ์ ธ์ค๋ ๋ชฉ์ ์ธ์ง ๊ตฌ๋ถํด์ ์๋ ค์ค์ผ ํฉ๋๋ค.
DLL๋ก ๋ง๋ค์ด์ ๋ด๋ณด๋ผ ๋:
// get_num.h
__declspec(dllexport) int get_num();
// get_num.c
int get_num() { return 0; }
DLL์์ ์ ๊ณตํ๋ ํจ์๋ฅผ ๊ฐ์ ธ์์ ์ฌ์ฉํ ๋:
// my_app.c
__declspec(dllimport) int get_num();
int main() { return get_num(); }
dllexport, dllimport์ฉ์ผ๋ก ํค๋ํ์ผ์ ๋๋ฒ์ฉ ๋ง๋ค์ด์ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ฌด ๋นํจ์จ์ ์ด๋ผ์ ์ผ๋ฐ์ ์ผ๋ก ์๋์ ๊ฐ์ด ๋งคํฌ๋ก๋ฅผ ํตํด ์๋ ์ ์ฉ๋๋ ๋ฐฉ์์ ์ฌ์ฉํฉ๋๋ค. DLL์ ๋ง๋ค ๋์๋ ALN_LIBRARY_BUILD
๋งคํฌ๋ก๋ฅผ ํ์ฑํ์ํค๊ณ ๊ทธ ์ธ์ ๊ฒฝ์ฐ์๋ ๋นํ์ฑํ ์ํค๋ ๋ฐฉ์์ผ๋ก ํ์ฉํ ์ ์์ต๋๋ค.
#ifdef ALN_LIBRARY_BUILD
#define ALN_API __declspec(dllexport)
#else
#define ALN_API __declspec(dllimport)
#endif
ALN_API int aln_foo_draw();
Linux์ Windows๋ฅผ ๋ชจ๋ ๊ณ ๋ คํ๋ฉด ์๋์ ๊ฐ์ด ๋งคํฌ๋ก๋ฅผ ๋ ํ์ฅํ ์ ์์ต๋๋ค.
#if defined(_WIN32)
#define ALN_API_EXPORT __declspec(dllexport)
#define ALN_API_IMPORT __declspec(dllimport)
#else
#define ALN_API_EXPORT __attribute__((visibility("default")))
#define ALN_API_IMPORT
#endif
#ifdef ALN_LIBRARY_BUILD
#define ALN_API ALN_API_EXPORT
#else
#define ALN_API ALN_API_IMPORT
#endif
๋ง๋ฌด๋ฆฌ
์ง๊ธ๊น์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ตฌ์ฑ ์์์ ๊ฐ ํ๋ซํผ๋ณ ํน์ฑ์ ๋ํด ์์๋ณด์์ต๋๋ค. ์ด์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ ํ๋ซํผ์์ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.