article0 - webispy/aln GitHub Wiki

์ƒ˜ํ”Œ C ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋‹ค์–‘ํ•œ ์šด์˜์ฒด์ œ์˜ ๊ฐ ํŒจํ‚ค์ง• ์‹œ์Šคํ…œ์— ๋งž๊ฒŒ ํŒจํ‚ค์ง•ํ•˜๊ณ  ๋ฐฐํฌํ•˜๊ธฐ

๋“ค์–ด๊ฐ€๋ฉฐ

C/C++ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ํฌ๋กœ์Šค ํ”Œ๋žซํผ ์ง€์›์€ ์ค‘์š”ํ•œ ๊ณผ์ œ์ž…๋‹ˆ๋‹ค. ์ด ๋ธ”๋กœ๊ทธ ์‹œ๋ฆฌ์ฆˆ์—์„œ๋Š” ์ƒ˜ํ”Œ C ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ , ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์—ฌ๋Ÿฌ ์šด์˜์ฒด์ œ์— ๋งž์ถฐ ํŒจํ‚ค์ง• ๋ฐ ๋ฐฐํฌํ•˜๋Š” ๊ณผ์ •์„ ์†Œ๊ฐœํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์‹œ๋ฆฌ์ฆˆ ๊ตฌ์„ฑ:

  1. ์ƒ˜ํ”Œ C ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž‘์„ฑ ๋ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ์„œ ๊ฐ–์ถฐ์•ผ ํ•  ์š”์†Œ๋“ค
  2. Ubuntu Linux์— deb ํŒจํ‚ค์ง€๋กœ ๋ฐฐํฌํ•˜๊ธฐ
  3. Fedora Linux์— rpm ํŒจํ‚ค์ง€๋กœ ๋ฐฐํฌํ•˜๊ธฐ
  4. macOS์— Homebrew TAP์„ ํ†ตํ•ด ๋ฐฐํฌํ•˜๊ธฐ
  5. Windows์— vcpkg custom registry๋ฅผ ํ†ตํ•ด ๋ฐฐํฌํ•˜๊ธฐ

์ƒ˜ํ”Œ C ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž‘์„ฑ ๋ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ์„œ ๊ฐ–์ถฐ์•ผ ํ•  ์š”์†Œ๋“ค

ALN(Amazing Lucky Numbers) ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์†Œ๊ฐœ

๋จผ์ €, ํŒจํ‚ค์ง• ์˜ˆ์‹œ๋ฅผ ์œ„ํ•œ ์ ์ ˆํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ ํƒ์— ๋Œ€ํ•ด ๊ณ ๋ฏผ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋„ˆ๋ฌด ๋‹จ์ˆœํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์‹ค์ œ ๊ฐœ๋ฐœ ์ƒํ™ฉ๊ณผ ๊ฑฐ๋ฆฌ๊ฐ€ ๋ฉ€๊ณ , ๋ฐ˜๋Œ€๋กœ ๋„ˆ๋ฌด ๋ณต์žกํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ํŒจํ‚ค์ง• ๊ณผ์ •๋ณด๋‹ค ์ฝ”๋“œ ์ดํ•ด์— ๋” ๋งŽ์€ ์‹œ๊ฐ„์„ ํ• ์• ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๊ณ ๋ฏผ ๋์—, ์ ๋‹นํ•œ ์ˆ˜์ค€์˜ ๋ณต์žก์„ฑ์„ ๊ฐ€์ง„ ์˜ˆ์ œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ธฐ๋กœ ๊ฒฐ์ •ํ•˜๊ณ  'ALN(Amazing Lucky Numbers)'์ด๋ผ๋Š” ์˜ˆ์ œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค:

  1. ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(glib)์— ๋Œ€ํ•œ ์˜์กด์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  2. API๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ–‰์šด์˜ ๋ฒˆํ˜ธ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  3. 6๊ฐœ์˜ API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. - ALN ์ƒ์„ฑ/ํ•ด์ œ/๋ฆฌ์…‹, ๋ฒˆํ˜ธ ์ƒ์„ฑ (ํ•œ๋ฒˆ์—/ํ•˜๋‚˜์”ฉ), ๋ฒˆํ˜ธ ์–ป๊ธฐ

ALN ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ „์ฒด ์†Œ์Šค ์ฝ”๋“œ๋Š” GitHub ์ €์žฅ์†Œ(https://github.com/webispy/aln)์—์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์‹ค์ œ ๋กœ๋˜ ๋ฒˆํ˜ธ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋‹จ์ˆœํžˆ ์˜ˆ์ œ๋ฅผ ์œ„ํ•œ 'ํ–‰์šด์˜ ๋ฒˆํ˜ธ'๋ฅผ ์ œ๊ณตํ•œ๋‹ค๋Š” ์ ์„ ์œ ์˜ํ•ด ์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ด์ œ ์ด ALN ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ, C ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๊ฐ–์ถฐ์•ผ ํ•  ํ•ต์‹ฌ ์š”์†Œ๋“ค๊ณผ ๋ฉ€ํ‹ฐ ํ”Œ๋žซํผ ์ง€์›์„ ์œ„ํ•œ ๊ณ ๋ ค์‚ฌํ•ญ๋“ค์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ตฌ์„ฑ ์š”์†Œ

๊ฐœ๋ฐœ์ž๊ฐ€ ALN ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ œ๊ณตํ•ด์•ผ ํ•  ํ•„์ˆ˜์ ์ธ ์š”์†Œ๋“ค๊ณผ ์‚ฌ์šฉ ํŽธ์˜์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•œ ์ถ”๊ฐ€ ์š”์†Œ๋“ค์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ•„์ˆ˜ ์š”์†Œ

์•„๋ž˜ ๋‘ ์š”์†Œ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ์„ ์œ„ํ•ด ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  1. ํ—ค๋” ํŒŒ์ผ (Header File):
    • API์˜ ์„ ์–ธ์ด ํฌํ•จ๋œ .h ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.
    • ์‚ฌ์šฉ์ž๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๊ธฐ๋Šฅ์„ ์ดํ•ดํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.
  2. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŒŒ์ผ (Library File):
    • ์ปดํŒŒ์ผ๋œ ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋œ Shared object(.so, .dylib, .dll ๋“ฑ) ๋˜๋Š” Static archive(.a, .lib) ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.
    • ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋งํฌํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ์š”์†Œ

๋นŒ๋“œ ์ •๋ณด ์ œ๊ณต (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 ํŽ˜์ด์ง€๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์–ด, ์‚ฌ์šฉ์ž๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ  ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

๋ฉ€ํ‹ฐ ํ”Œ๋žซํผ ์ง€์›์„ ์œ„ํ•ด ๊ณ ๋ คํ•˜๊ธฐ

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์—ฌ๋Ÿฌ ํ”Œ๋žซํผ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์š”์†Œ๋“ค์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

  1. ๋นŒ๋“œ ์‹œ์Šคํ…œ
    • ํ”Œ๋žซํผ๋งˆ๋‹ค ์ง€์›ํ•˜๋Š” ๋นŒ๋“œ ์‹œ์Šคํ…œ์ด ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ํฌ๋กœ์Šค ํ”Œ๋žซํผ ๋นŒ๋“œ๋ฅผ ์ง€์›ํ•˜๋Š” ๋นŒ๋“œ ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ํ”Œ๋žซํผ์—์„œ์˜ ๋นŒ๋“œ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋‹จ์ˆœํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
  2. ํ”Œ๋žซํผ ํ˜ธํ™˜์„ฑ
    • ๊ฐ ํ”Œ๋žซํผ๋ณ„๋กœ ํ‘œ์ค€ C API ๋ฐ ํ”„๋ ˆ์ž„์›Œํฌ API๊ฐ€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ํ”Œ๋žซํผ ํŠน์„ฑ์— ์˜ํ–ฅ์„ ๋ฐ›๋Š” ํ”„๋ ˆ์ž„์›Œํฌ API๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ์กฐ๊ฑด๋ถ€ ์ปดํŒŒ์ผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ: #ifdef _WIN32
  3. Shared Library ํŠน์„ฑ
    • ํ”Œ๋žซํผ๋ณ„๋กœ shared library์˜ ํŠน์„ฑ์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์—, API ๊ตฌํ˜„ ์‹œ ์ด๋ฅผ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ์‹ฌ๋ณผ ๊ฐ€์‹œ์„ฑ(symbol visibility) ์„ค์ •์„ ํ†ตํ•ด ์˜๋„ํ•œ API๋งŒ ์™ธ๋ถ€์— ๋…ธ์ถœ๋˜๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ALN ์˜ˆ์ œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์œ„์˜ ๊ณ ๋ ค์‚ฌํ•ญ๋“ค์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค:

  1. ๋นŒ๋“œ ์‹œ์Šคํ…œ

    • CMake๋ฅผ ์„ ํƒํ•˜์˜€์Šต๋‹ˆ๋‹ค. CMake๋Š” ์˜ค๋ž˜๋˜๊ณ  ๋Œ€์ค‘์ ์ด๋ฉฐ, ๋‹ค์–‘ํ•œ ํ”Œ๋žซํผ์„ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์˜ต์…˜์œผ๋กœ๋Š” meson, scons, autotools ๋“ฑ์ด ์žˆ์œผ๋ฉฐ, ๊ฐœ์ธ ์„ ํ˜ธ์— ๋”ฐ๋ผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ๊ฐœ์ธ์ ์œผ๋กœ ๋‹ค์Œ ํ”„๋กœ์ ํŠธ์˜ ๋นŒ๋“œ ์‹œ์Šคํ…œ์„ ์„ ํƒํ•˜๋ผ๊ณ  ํ•˜๋ฉด meson์„ ์„ ํƒํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ meson์—์„œ ์ œ๊ณตํ•˜๋Š” ๋นŒ๋“œ ์‹œ์Šคํ…œ ๋น„๊ต ๋ฌธ์„œ https://mesonbuild.com/Simple-comparison.html ๊ณต์œ ๋“œ๋ฆฝ๋‹ˆ๋‹ค.
  2. ํ”Œ๋žซํผ ํ˜ธํ™˜์„ฑ

    • ์ด๋ฒˆ ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ์˜ ์ฃผ ๋ชฉ์ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž์ฒด์— ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋Œ€์ƒ ํ”Œ๋žซํผ(Linux, macOS, Windows)์—์„œ ๋ชจ๋‘ ํ˜ธํ™˜ ๊ฐ€๋Šฅํ•œ API ๋ฐ ๋ชจ๋“  ๋Œ€์ƒ ํ”Œ๋žซํผ์„ ์ง€์›ํ•˜๋Š” ์˜์กด์„ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(glib)๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.
    • ๋”ฐ๋ผ์„œ ALN ์ฝ”๋“œ ์•ˆ์—๋Š” ํ”Œ๋žซํผ์— ๋”ฐ๋ผ ๋ถ„๊ธฐํ•ด์„œ Framework API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋กœ์ง์€ ์—†์Šต๋‹ˆ๋‹ค. ๋‹จ, API ์‹ฌ๋ณผ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ macro ์ฒ˜๋ฆฌ๋Š” ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
  3. 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. ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„ค์น˜/๋ฐฐํฌํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์˜์กด์„ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ์„œ ๋ฐฐํฌ
  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 ํ˜‘์ฐฌ)

  1. ๋ฐ”์ด๋„ˆ๋ฆฌ ํฌ๊ธฐ ๊ฐ์†Œ ๊ธฐ๋ณธ ๊ฐ€์‹œ์„ฑ์„ hidden์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ๊ณต์œ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ํฌํ•จ๋˜๋Š” ์‹ฌ๋ณผ ์ˆ˜๊ฐ€ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค. ์ด๋Š” ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ฐ”์ด๋„ˆ๋ฆฌ ํฌ๊ธฐ๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๊ณ , ๋กœ๋“œ ์‹œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์ค„์ž…๋‹ˆ๋‹ค.
  2. ๋งํฌ ์‹œ๊ฐ„ ๋ฐ ๋กœ๋“œ ์‹œ๊ฐ„ ๋‹จ์ถ• ์‹ฌ๋ณผ ํ•ด์„์— ํ•„์š”ํ•œ ์‹œ๊ฐ„์ด ์ค„์–ด๋“ค๊ธฐ ๋•Œ๋ฌธ์— ๋งํฌ ์‹œ๊ฐ„๊ณผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋กœ๋“œ ์‹œ๊ฐ„์ด ๋‹จ์ถ•๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ”„๋กœ๊ทธ๋žจ ์‹œ์ž‘ ์‹œ๊ฐ„์„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ถฉ๋Œ ๊ฐ์†Œ ์ˆจ๊ฒจ์ง„ ์‹ฌ๋ณผ์€ ์™ธ๋ถ€์—์„œ ์ฐธ์กฐํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ, ๋™์ผํ•œ ์‹ฌ๋ณผ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€์˜ ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํŠนํžˆ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ ์ค‘์š”ํ•œ ์ด์ ์ž…๋‹ˆ๋‹ค.
  4. ์ตœ์ ํ™” ๊ธฐํšŒ ์ฆ๊ฐ€ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ˆจ๊ฒจ์ง„ ์‹ฌ๋ณผ์„ ๋” ๊ณต๊ฒฉ์ ์œผ๋กœ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ธ๋ผ์ธ ํ™•์žฅ์ด๋‚˜ ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ ์ œ๊ฑฐ์™€ ๊ฐ™์€ ์ตœ์ ํ™”๊ฐ€ ๋” ์ž˜ ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ œ๊ณตํ•˜๋Š” ์ž…์žฅ์—์„œ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ์ด์œ ๊ฐ€ ์—†๋Š” ์˜ต์…˜์ž…๋‹ˆ๋‹ค. ์˜ˆ์ œ๋กœ ๋งŒ๋“  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๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋นŒ๋“œ ๋ฐ ์‹คํ–‰, ๋ฐฐํฌํ•  ํŒŒ์ผ๋“ค์„ ๋งŒ๋“ค์–ด๋‚ด๋Š” ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

  1. ๋จผ์ € ํ”„๋กœ์ ํŠธ์— ์ •์˜๋œ 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
  1. ๋‹ค์Œ์œผ๋กœ ์œ„์—์„œ ์ƒ์„ฑ๋œ ๋นŒ๋“œ 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
  1. ์ƒ์„ฑ๋œ ์‹คํ–‰ ํŒŒ์ผ๋“ค์—๋Š” 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
  1. ๋ฐฐํฌํ•  ํŒŒ์ผ๋“ค์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ƒ์„ฑ๋œ ํŒŒ์ผ๋“ค์€ 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์™€ ์œ ์‚ฌํ•œ ์ 
  1. ํŒŒ์ผ ํ™•์žฅ์ž: .so ๋Œ€์‹  .dylib๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  2. ๋ฒ„์ „ ๊ด€๋ฆฌ: 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 names
  • otool - 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์™€ ๋ช‡ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ์ฐจ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

  1. ํŒŒ์ผ ํ™•์žฅ์ž: .dll(Dynamic-Link Library)์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  2. Windows๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ symbolic link์™€ ํŒŒ์ผ๋ช…์„ ํ†ตํ•œ ๋ฒ„์ „ ๊ด€๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  3. Import Library: Windows์—์„œ๋Š” .dll ํŒŒ์ผ๊ณผ ํ•จ๊ป˜ .lib ํŒŒ์ผ(import library)์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด ํŒŒ์ผ์€ ์ปดํŒŒ์ผ ์‹œ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  4. 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

๋งˆ๋ฌด๋ฆฌ

์ง€๊ธˆ๊นŒ์ง€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๊ตฌ์„ฑ ์š”์†Œ์™€ ๊ฐ ํ”Œ๋žซํผ๋ณ„ ํŠน์„ฑ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ด์ œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐ ํ”Œ๋žซํผ์—์„œ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.