著者:後藤大地
前回は静的ライブラリを作る方法を取り上げた。.cのファイルを.oのファイルへコンパイルし、それらをまとめて静的ライブラリとする。静的ライブラリはいわば部品の集まりで、コンパイル時にこの静的ライブラリから必要な部品を持ってきて利用することになる。コンパイルごとに静的ライブラリから部品がコピーされ、生成されるバイナリファイルへ含まれることになる。
ライブラリにはもうひとつ「共有ライブラリ」というものがある。動的ライブラリと呼ばれることもある。共有ライブラリの方はバイナリファイル生成時に指定はするものの、ここから部品をコピーしてバイナリに組み込むといったことはしない。生成したバイナリを実行するときにリアルタイムに共有ライブラリを見に行って、そのときに使われる。
記事本文掲載のシェルスクリプトマガジンvol.48は以下リンク先でご購入できます。
1 2 3 4 5 |
% ldd /bin/cat /bin/cat: libc.so.7 => /lib/libc.so.7 (0x800823000) % |
1 2 3 4 5 |
% file /lib/libc.so.7 /lib/libc.so.7: ELF 64-bit LSB shared object, x86-64, version 1 (FreeBSD), dynamically linked, stripped % |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
% nm --dynamic /bin/cat 00000000006037f0 B _CurrentRuneLocale 0000000000602720 B _DefaultRuneLocale w _Jv_RegisterClasses U _ThreadRuneLocale U __error 00000000006037a0 B __isthreaded 0000000000602718 B __mb_sb_limit 00000000006026d8 D __progname U __srget U __stack_chk_fail 00000000006037b0 B __stack_chk_guard 00000000006037f8 B __stderrp 0000000000602710 B __stdinp 0000000000602700 B __stdoutp U __swbuf 0000000000603828 A _end U _init_tls U atexit U clearerr U close U connect 0000000000603820 B environ U err U exit U fclose U fcntl U fdopen U feof U ferror U fileno U fprintf U freeaddrinfo U fstat U fwrite U gai_strerror U getaddrinfo U getc U getopt U malloc U open 0000000000602708 B optind U putc U read U realpath U setbuf U setlocale U shutdown U socket U strcmp U sysconf U warn U write % |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
% tree . |-- include | `-- ore.h |-- lib `-- libore |-- Makefile |-- indent.c |-- ore.c |-- setmsg.c |-- usage.c `-- version.c 3 directories, 7 files % |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#ifndef _ORE_H_ #define _ORE_H_ #define BUFFER_SIZE 4096 #define USAGE_OUT stderr #define VERSION_OUT stdout #define ESC_SEQ_NORM "\x1b[0m" #define ESC_SEQ_BOLD "\x1b[1m" #define ESC_SEQ_GRAY "\x1b[2m" #define ESC_SEQ_UBAR "\x1b[4m" #define ES_BOLD(X) ESC_SEQ_BOLD X ESC_SEQ_NORM #define ES_LIGHT(X) ESC_SEQ_GRAY X ESC_SEQ_NORM #define ES_UBAR(X) ESC_SEQ_UBAR X ESC_SEQ_NORM char *_usage_msg; char *_version_msg; char *indent(char *); int setmsg(char *, char *); void usage(void); void version(void); #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include "ore.h" char * indent(char *t) { static char buf[BUFFER_SIZE]; char *p; int i = 0; p = t; buf[i++] = '\t'; for (; i < BUFFER_SIZE - 1; i++, p++) { buf[i] = *p; if ('\n' == *p) buf[++i] = '\t'; if ('\0' == *p) break; } if ('\0' != buf[i]) buf[i] = '\0'; return buf; } |
1 |
#include "ore.h" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include #include #include "ore.h" int setmsg(char *key, char *value) { if (0 == strcmp("usage", key)) { _usage_msg = calloc(1, BUFFER_SIZE * sizeof(char)); strncpy(_usage_msg, value, BUFFER_SI ZE); _usage_msg[BUFFER_SIZE - 1] = '\0'; } else if (0 == strcmp("version", key)) { _version_msg = calloc(1, BUFFER_SIZE * sizeof(char)); strncpy(_version_msg, value, BUFFER_ SIZE); _version_msg[BUFFER_SIZE - 1] = '\0'; } else return (-1); return 0; } |
1 2 3 4 5 6 7 8 9 10 11 |
#include #include "ore.h" void usage(void) { fprintf(USAGE_OUT, ES_BOLD("使い方:") "\n%s \n", indent(_usage_msg)); } |
1 2 3 4 5 6 7 8 9 10 |
#include #include "ore.h" void version(void) { fprintf(USAGE_OUT, ES_BOLD("バージョン:") " %s\n", _version_msg); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
CFLAGS= -I. -I./../include/ -O2 -pipe -fPIC LIBSO= ./../lib/libore.so OBJS!= ls | grep '[.]c$$' 2> /dev/null | s ed 's/.c$$/.o/g' .SUFFIXES: .o .c .c.o: cc ${CFLAGS} -c $< -o $@ all: ${OBJS} cc -shared -o ${LIBSO} ${OBJS} objcopy --strip-unneeded ${LIBSO} clean: rm -f ${LIBSO} ${OBJS} |
1 2 3 4 5 6 7 8 9 10 11 12 |
% cd libore % make cc -I. -I./../include/ -O2 -pipe -fPIC -c indent.c -o indent.o cc -I. -I./../include/ -O2 -pipe -fPIC -c ore.c -o ore.o cc -I. -I./../include/ -O2 -pipe -fPIC -c setmsg.c-o setmsg.o cc -I. -I./../include/ -O2 -pipe -fPIC -c usage.c-o usage.o cc -I. -I./../include/ -O2 -pipe -fPIC -c version.c -o version.o cc -shared -o ./../lib/libore.so indent.o ore.o setmsg.o usage.o version.o objcopy --strip-unneeded ./../lib/libore.so % |
1 2 3 4 5 6 |
% cd ../lib % file libore.so libore.so: ELF 64-bit LSB shared object, x86-64, version 1 (FreeBSD), dynamically linked, stripped % |
1 2 3 4 5 6 7 |
% file libore.a libore.a: current ar archive % ls -al libore.a -rw-r--r-- 1 daichi wheel 7824 Apr 5 17:51 libore.a % |
1 2 3 4 5 6 7 |
% file libore.so libore.so: ELF 64-bit LSB shared object, x86-64, version 1 (FreeBSD), dynamically linked, stripped % ls -al libore.so -rwxr-xr-x 1 daichi wheel 5304 Apr 5 17:44 libore.so % |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
% tree . |-- bin |-- include | `-- ore.h |-- lib | `-- libore.so |-- libore | |-- Makefile | |-- indent.c | |-- ore.c | |-- setmsg.c | |-- usage.c | `-- version.c `-- src `-- bin `-- oreapp |-- Makefile `-- oreapp.c 7 directories, 10 files % |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#include #include #include #include #include "ore.h" int main(int argc, char *argv[]) { setmsg("usage", "oreapp [-v] [-h] string..."); setmsg("version", "1.0"); int ch; while ((ch = getopt(argc, argv, "hv")) != -1 ) { switch (ch) { case 'v': version(); exit(EX_USAGE); break; case '?': case 'h': usage(); exit(EX_USAGE); break; default: usage(); exit(EX_USAGE); break; } } argc -= optind; argv += optind; for (int i = 0; i < argc; i++) printf("%06d %s\n", 1+i, argv[i]); return(EX_OK); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
BIN= ./../../../bin/oreapp LIBDIR= ./../../../lib/ OBJS!= ls | grep '[.]c$$' 2> /dev/null | sed 's/.c$$/.o/g' CFLAGS= -I. -I./../../../include/ -O2 -pipe .SUFFIXES: .o .c .c.o: cc ${CFLAGS} -c $< -o $@ all: ${OBJS} cc ${CFLAGS} -o ${BIN} ${OBJS} -L${LIBDIR} - lore objcopy --strip-unneeded ${BIN} clean: rm -f ${BIN} ${OBJS} |
1 2 3 4 5 6 |
% make cc -I. -I./../../../include/ -O2 -pipe -c oreapp.c-o oreapp.o cc -I. -I./../../../include/ -O2 -pipe -o ./../../../bin/oreapp oreapp.o -L./../../../lib/ -lore objcopy --strip-unneeded ./../../../bin/oreapp % |
1 2 3 4 5 6 |
% cd ../../../bin/ % file oreapp oreapp: ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked, interpreter /libexec/ld-elf.so.1, for FreeBSD 11.0 (1100122), FreeBSD-style, stripped % |
1 2 3 4 5 6 |
% ldd oreapp oreapp: libore.so => not found (0) libc.so.7 => /lib/libc.so.7 (0x800821000) % |
1 2 3 4 5 6 |
% env LD_LIBRARY_PATH=../lib ldd oreapp oreapp: libore.so => ../lib/libore.so (0x800821000) libc.so.7 => /lib/libc.so.7 (0x800a23000) % |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
% file oreapp oreapp: ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked, interpreter /libexec/ld-elf.so.1, for FreeBSD 11.0 (1100122), FreeBSD-style, stripped % ls -l oreapp -rwxr-xr-x 1 daichi wheel 6440 Apr 5 18:10 orea pp % nm --dynamic oreapp w _Jv_RegisterClasses 0000000000600f98 D __progname 0000000000600fc8 B __stderrp 0000000000601fe8 A _end U _init_tls U atexit U calloc 0000000000601fd0 B environ U exit U fprintf U getopt 0000000000600fc0 B optind U printf U strcmp U strncpy % |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
% file oreapp oreapp: ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked, interpreter /libexec/ld-elf.so.1, for FreeBSD 11.0 (1100122), FreeBSD-style, stripped % ls -l oreapp -rwxr-xr-x 1 daichi wheel 6000 Apr 5 18:05 orea pp % nm --dynamic oreapp w _Jv_RegisterClasses 0000000000600df9 A __bss_start 0000000000600de0 D __progname 0000000000600df9 A _edata 0000000000600e28 A _end U _init_tls 0000000000600e10 B _usage_msg 0000000000600e20 B _version_msg U atexit 0000000000600e08 B environ U exit U getopt 0000000000600e00 B optind U printf U setmsg U usage U version % |
1 2 3 4 |
% ./oreapp Shared object "libore.so" not found, required by "oreapp" % |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
% env LD_LIBRARY_PATH=../lib ./oreapp -v バージョン: 1.0 % env LD_LIBRARY_PATH=../lib ./oreapp -h 使い方: oreapp [-v] [-h] string... % env LD_LIBRARY_PATH=../lib ./oreapp a b c d 000001 a 000002 b 000003 c 000004 d % |