-
Notifications
You must be signed in to change notification settings - Fork 0
/
multifile-compile.md
119 lines (73 loc) · 4.27 KB
/
multifile-compile.md
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# 多文件编译
## 指定链接时 `.a` 文件的搜索路径
静态链接库的默认搜索行为和动态链接库是一样的。
如果静态库就在 GCC 的默认搜索路径下,可以直接使用下面的命令:
```bash
gcc your_program.c -lSDK
```
它会默认搜索名为 `libSDK.a` 的文件。
如果静态库没有在 GCC 的默认搜索路径下,需要人为指定搜索路径:
```bash
gcc your_program.c -Lpath/to/static/lib -lSDK
```
它会定位到名为 `path/to/static/lib/libSDK.a` 的文件。
如果库文件名没有 `lib` 前缀,那么在链接的时候,需要在 `-l` 参数后面加个冒号,改为 `-l:`:
```bash
gcc your_program.c -l:SDK
```
它会定位到名为 `SDK.a` 的文件。
## 指定运行时 `.so` 文件的搜索路径
增加编译选项:`rpath`
```bash
# 让程序在当前路径下搜索 so 文件
LDFLAGS += -Wl,--hash-style=sysv,-Bsymbolic,-rpath=.
```
## undefined reference to
出现这个问题,一般有以下几个原因:
1. 链接时缺少相关的 `.o` 文件(目标文件)
2. 链接时缺少相关的 `.so` 文件(动态库)
3. 链接时缺少相关的 `.a` 文件(静态库)
4. 链接库文件时顺序错误
5. 在 C++ 代码中链接了 C 语言相关的库
6. 函数模板的定义写在了 `.cpp` 文件中
针对前 3 个问题,只需要显式地给编译器指明去哪里找函数定义就可以了,具体做法就是在编译时增加编译选项 `-l<libname>` 和 `-L<libpath>`。
针对第 4 个问题,根据源代码的引用顺序调整库的链接顺序就可以了。
针对第 5 个问题,需要在 C++ 源代码的头文件中显示地声明引用的哪些头文件是用 C 语言写的,举例如下:
```cpp
#ifdef __cplusplus
extern "C"
{
#endif
// TODO: include C header files here
#ifdef __cplusplus
}
#endif
```
针对第 6 个问题,函数模板的定义需要写在 `.h` 文件中。
更多链接阶段出现的问题,可以参考 <https://www.cnblogs.com/schips/p/13728080.html>。
## DWARF error: could not find variable specification at offset
出现这个问题,可能的原因有:(1)非 `static` 函数,调用了 `static` 函数。(2)忘记了在 Makefile 中链接 undefined reference 指向函数所在的文件。
## line 1: can't open: no such file
出现这个错误,通常是因为使用的编译器和运行平台不匹配。可能是你用 GCC 编译了程序,但是却在开发板上运行了程序。
## line 2: syntax error: bad function name
出现这个错误,通常是因为使用的编译器和运行平台不匹配。可能是你用 GCC 编译了程序,但是却在开发板上运行了程序。
## real-ld: cannot find crti.o: No such file or directory
在编译时,明明使用 `-L` 指定了 `crti.o` 所在的路径,为什么还是会提示找不到这个文件呢?这种情况下,应该是忘记了在链接时指定 `--sysroot`。
## undefined reference to `rpl_malloc'
这种错误多出现在交叉编译时,对 `rpl_malloc` 函数进行了重新定义,导致找不到原来的函数了。我们只需要注释掉重新定义的语句就可以了。
```cpp
// config.h
//#define malloc rpl_malloc
```
## skipping incompatible
如果链接时报 skipping incompatible 错误,这主要是因为库版本和平台版本不一致:
- 查看平台版本:`readelf -h main.o | grep "Magic\|Machine"`
- 查看库版本:`readelf -h HD_CORS_SDK.a | grep "Magic\|Machine"`
注意:用正则表达式匹配字符的时候,不应该随便在 Pattern 中加空格,如果写成 `"Magic \| Machine"` 就匹配不到 `Magic` 字段了。
```{note}
Magic 字段主要关注前 5 个字节,第 1 个字节都是以 `0x7f` 开头,第 2、3、4 个字节分别是字母 `E`、`L`、`F` 的 ASCII 码,第 5 个字节如果是 `0x01` 表示该文件适用于 32 位平台,如果是 `0x02` 表示适用于 64 位平台。
Machine 字段中的 ARM 表示最高支持到 ARMv7 或 Aarch32,ARM 64-bit architecture 表示最高可支持到 ARMv8 或 Aarch64。
参考:[ELF 文件解析 1-前述+文件头分析 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/380908650)
```
## error: storage size of 'xxx' isn't known
一个可能的原因是 `$SYSROOT/usr/include` 目录下头文件和当前项目所用的同名头文件内容不一致。