Skip to content

Commit d15dd21

Browse files
committed
blog: add more example codes
1 parent 9ee1661 commit d15dd21

File tree

1 file changed

+146
-10
lines changed

1 file changed

+146
-10
lines changed

docs/blog/talk-to-executable.md

Lines changed: 146 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,155 @@ aside: true
77
## Description
88
待补充
99

10-
gcc -install_name @rpath/libutil.dylib -fPIC -shared -o src/dyn-util/libutil.dylib src/dyn-util/util.c
10+
## 动态链接和静态链接
11+
### 静态库
12+
:::code-group
13+
```c [src/static-util/util.c]
14+
#include "./util.h"
15+
#include "stdio.h"
1116

12-
在 macOS 系统上,动态链接库的搜索路径有一定的优先级排序。搜索逻辑和优先级如下:
13-
**@executable_path**:首先搜索可执行文件所在的目录。
14-
**@loader_path**:其次搜索加载该动态库的库所在的目录。
15-
**@rpath**:然后搜索运行路径(rpath),可以在编译时或运行时指定。
16-
**DYLD_LIBRARY_PATH**:接着搜索由 DYLD_LIBRARY_PATH 环境变量指定的目录。
17-
**DYLD_FALLBACK_LIBRARY_PATH**:如果前面的路径都没有找到,则搜索 DYLD_FALLBACK_LIBRARY_PATH 环境变量指定的目录。默认值为 /usr/local/lib 和 /usr/lib。
18-
系统默认路径:最后搜索系统默认的库路径,如 /usr/lib
17+
void hello() {
18+
printf("hello friends\n");
19+
}
20+
21+
int find(const char* source, char dest) {
22+
for ( int i = 0; source[i] != '\0'; i++) {
23+
if (source[i] == dest) return i;
24+
}
25+
return -1;
26+
}
27+
28+
```
29+
30+
```c [src/static-util/util.h]
31+
#ifndef __My_Util
32+
#define __My_Util
33+
void hello();
34+
int find(const char* source, char dest);
35+
#endif
36+
```
37+
38+
```c [src/main.c]
39+
#include <util.h>
40+
#include <stdio.h>
41+
42+
43+
int main() {
44+
hello();
45+
int index = find("Jack", 'c');
46+
if (index != -1) {
47+
printf("index: %d\n", index);
48+
}
49+
}
50+
```
51+
:::
52+
53+
生成静态库:
54+
```shell
55+
gcc -c src/static-util/util.c -o src/static-util/util.o
56+
ar r libutil.a src/static-util/util.o
57+
```
58+
> 在 unix 上静态文件 .a 后缀,在Windows是.lib后缀
59+
> 文件名是 lib{静态库名}
60+
61+
使用静态库:
62+
```shell
63+
gcc -o main -I "src/static-util" -L "src/static-util" -lutil src/main.c && ./main
64+
65+
# 或者
66+
gcc -o main -I "src/static-util" src/main.c src/static-util/libutil.a && ./main
67+
```
68+
> -I 指定`include <a.h>`的时候,到哪个文件夹去找`a.h`文件
69+
> -L 指定 寻找静态库的时候,到哪个文件夹去找
70+
> -l 指定静态库文件名,此时lib和.a后缀可省略
71+
72+
### 动态库
73+
:::code-group
74+
```c [src/dyn-util/util.c]
75+
76+
#include "./util.h"
77+
#include "stdio.h"
78+
79+
void hello() {
80+
printf("hello friends\n");
81+
}
1982

20-
生成动态链接库时,默认的注册名时./libutil.dylib, 但不知道为什么,macOS平台中,dyld使用可执行程序的当前工作目录或者DYLD_LIBRARY_PATH环境变量指定的目录,作为这个相对路径的参考目录,使用gcc -Wl.-rpath设置的动态链接库搜索目录将无效。为了解决这个问题,你要设置 -install_name, 告诉dyld,动链接库是rpath目录下的libutil.dylib文件
83+
int find(const char* source, char dest) {
84+
for ( int i = 0; source[i] != '\0'; i++) {
85+
if (source[i] == dest) return i;
86+
}
87+
return -1;
88+
}
89+
90+
```
91+
92+
```c [src/dyn-util/util.h]
93+
#ifndef __My_Util
94+
#define __My_Util
95+
void hello();
96+
int find(const char* source, char dest);
97+
#endif
98+
```
99+
100+
```c [src/main.c]
101+
#include <util.h>
102+
#include <stdio.h>
103+
104+
105+
int main() {
106+
hello();
107+
int index = find("Jack", 'c');
108+
if (index != -1) {
109+
printf("index: %d\n", index);
110+
}
111+
}
112+
```
113+
:::
114+
115+
生成动态库:
116+
```shell
117+
gcc -fPIC -shared -o src/dyn-util/libutil.dylib src/dyn-util/util.c
118+
```
119+
> 动态链接库名格式为 lib{库名}.{后缀};
120+
> linux的后缀是 so;
121+
> Mac的后缀是 dylib;
122+
> Windows的后缀是 dll;
123+
> -fPIC 中 PIC的含义是`Position Independent Code`;
124+
125+
使用动态库:
126+
```shell
127+
gcc -I "src/dyn-util" -L "src/dyn-util" -lutil -Wl,-rpath,$PWD/src/dyn-util -o main src/main.c && ./main
128+
```
129+
> -Wl, -rpath, $PWD/src/dyn-util 指定动态连接器的搜索路径,可以阅读[rust编译出来的executable file比cpp大](/blog/rust-binary-is-big)
130+
131+
如果你将上边生成的main文件移动到别的目录下,并在该目录下执行,就会报错,错误大致的意思是找不到动态链接库:
132+
```shell
133+
cp main src/main
134+
cd src
135+
./main
136+
```
137+
解决方法是,改用下边的指令生成动态链接库:
138+
```shell
139+
gcc -install_name @rpath/libutil.dylib -fPIC -shared -o src/dyn-util/libutil.dylib src/dyn-util/util.c
140+
```
141+
142+
生成动态链接库时,默认的注册名时./libutil.dylib, 但不知道为什么,macOS平台中,dyld使用可执行程序的当前工作目录或者DYLD_LIBRARY_PATH环境变量指定的目录,作为这个相对路径的参考目录,使用gcc -Wl.-rpath设置的动态链接库搜索目录将无效。为了解决这个问题,你要设置 -install_name, 告诉dyld,动链接库是rpath目录下的libutil.dylib文件.
21143

22144
-install_name是macOS特有的配置项,在 Linux 上,类似的功能可以通过 -soname 选项来实现:
23145
```shell
24146
gcc -shared -o libexample.so.1.0 source.c -Wl,-soname,libexample.so.1
25-
```
147+
```
148+
149+
:::tip <TipIcon />
150+
在 macOS 系统上,动态链接库的搜索路径有一定的优先级排序。搜索逻辑和优先级如下:
151+
1. **@executable_path**:首先搜索可执行文件所在的目录。
152+
2. **@loader_path**:其次搜索加载该动态库的库所在的目录。
153+
3. **@rpath**:然后搜索运行路径(rpath),可以在编译时或运行时指定。
154+
4. **DYLD_LIBRARY_PATH**:接着搜索由 DYLD_LIBRARY_PATH 环境变量指定的目录。
155+
5. **DYLD_FALLBACK_LIBRARY_PATH**:如果前面的路径都没有找到,则搜索 DYLD_FALLBACK_LIBRARY_PATH 环境变量指定的目录。默认值为 /usr/local/lib 和 /usr/lib。
156+
6. 系统默认路径:最后搜索系统默认的库路径,如 /usr/lib
157+
:::
158+
159+
## 查看可执行程序
160+
161+
## 调试可执行程序

0 commit comments

Comments
 (0)