NotePublic/Software/Applications/GCC/GCC_编译连接参数.md

201 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# GCC 编译连接参数
## 1. 编译参数
GCC 编译程序的一般格式为:
```bash
gcc -o <target> <source files> [other parameters]
```
### 1.1. 常用参数
* -c只编译不链接产生 .o 文件(就是 obj 文件),不产生执行文件
* -o指定输出文件名
* -g可执行程序包含调试信息
* -O\<n\>:设置优化级别
* -static链接静态库禁止使用动态库
* -shared进行动态库编译链接动态库
* -I\<dir\>:在头文件的搜索路径中增加 dir 目录
* -L\<dir\>:在动态库的搜索路径中增加 dir 目录
* -l\<name\>链接静态库libname.a或动态库libname.so的库文件
* -fPIC(或 fpic):生成使用相对地址无关的目标代码
### 1.2. 编译警告控制参数
#### 1.2.1. -Werror
-Werror将所有的警告当成错误进行处理。
#### 1.2.2. -Wall
-Wall打开 gcc 的所有警告,主要包括以下部分:
```blk
-Waddress
-Warray-bounds=1 (only with -O2)
-Wbool-compare
-Wbool-operation
-Wc++11-compat-Wc++14-compat
-Wcatch-value (C++ and Objective-C++ only)
-Wchar-subscripts警告如果数组下标有char类型。 这是错误的常见原因,因为程序员经常忘记这种类型是在某些机器上签名的。
-Wcomment
-Wduplicate-decl-specifier (C and Objective-C only)
-Wenum-compare (in C/ObjC; this is on by default in C++)
-Wformat
-Wformat-security开启类型不匹配警告。
-Wint-in-bool-context
-Wimplicit (C and Objective-C only)
-Wimplicit-int (C and Objective-C only)
-Wimplicit-function-declaration (C and Objective-C only)
-Winit-self (only for C++)
-Wlogical-not-parentheses
-Wmain (only for C/ObjC and unless -ffreestanding)
-Wmaybe-uninitialized
-Wmemset-elt-size
-Wmemset-transposed-args
-Wmisleading-indentation (only for C/C++)
-Wmissing-attributes
-Wmissing-braces (only for C/ObjC)
-Wmultistatement-macros
-Wnarrowing (only for C++)
-Wnonnull
-Wnonnull-compare
-Wopenmp-simd
-Wparentheses
-Wpointer-sign
-Wreorder
-Wrestrict
-Wreturn-type
-Wsequence-point
-Wsizeof-pointer-div
-Wsizeof-pointer-memaccess
-Wstrict-aliasing
-Wstrict-overflow=1
-Wswitch
-Wtautological-compare
-Wtrigraphs
-Wuninitialized
-Wunknown-pragmas
-Wunused-function开启未使用的函数警告。
-Wunused-label
-Wunused-value
-Wunused-variable
-Wvolatile-register-var
```
每个警告参数都有对应的“-Wno-”参数实现相反的控制,例如:
```blk
-Wno-unused-parameter关闭未使用的参数警告。
-Wno-unused-function关闭未使用的函数警告。
-Wno-format-security关闭类型不匹配警告。
-Wno-sign-compare关闭有符号数和无符号数比较警告。
```
在同时开启 -Wall 和 -Werror 时将使编译警告变为编译错误,此时语法检查非常严格,如需放开某些限制,可结合“-Wno-”类参数使用,例如:-Wall -Werror -Wno-unused-parameter -Wno-unused-function。
#### 1.2.3. -Wextra
-Wextra启用一些未由-Wall启用的额外警告标志。 (此选项过去称为-W ,旧名称仍然受支持,但更新的名称更具描述性。)
```blk
-Wclobbered
-Wcast-function-type
-Wempty-body
-Wignored-qualifiers
-Wimplicit-fallthrough=3
-Wmissing-field-initializers
-Wmissing-parameter-type (C only)
-Wold-style-declaration (C only)
-Woverride-init
-Wsign-compare (C only):开启有符号数和无符号数比较警告。
-Wtype-limits
-Wuninitialized
-Wshift-negative-value (in C++03 and in C99 and newer)
-Wunused-parameter (only with -Wunused or -Wall):开启未使用的参数警告。
-Wunused-but-set-parameter (only with -Wunused or -Wall)
```
选项 -Wextra 还会打印以下情况的警告消息:
指针与整数零与< <= >或>= 。
仅限C ++)枚举器和非枚举器都出现在条件表达式中。
仅限C ++)不明确的虚拟基础。
仅限C ++为已声明为register的数组下标。
仅限C ++取得已声明register的变量的地址。
仅限C ++)基类不在派生类的复制构造函数中初始化。
### 1.3. -fomit-frame-pointer
GCC 会在汇编时加入一些堆栈跟踪信息,以便调试系统能够获取堆栈及调用信息如 call trace 等称为“stack frame pointer(SFP)”,通过 -fomit-frame-pointer 参数可关闭之。
## 2. 连接参数
### 2.1. rpath/rpath-link
* -rpath-link用于“链接”的时候的例如你显式指定的需要 FOO.so但是 FOO.so 本身是需要 BAR.so 的,后者你并没有指定,而是 FOO.so 引用到它,这个时候,会先从 -rpath-link 给的路径里找。
* -rpath: 用于“运行”的时候。运行的时候,如果要找 FOO.so 文件,会从这个选项里指定的地方去找。对于交叉编译,交叉编译链接器需已经配置 --with-sysroot 选项才能起作用。也就是说,-rpath 指定的路径会被记录在生成的可执行程序中,用于运行时查找需要加载的动态库。
举例如下:
如果 prog 依赖 libfoobar.so而 libfoobar.so libfoo.so 和 libbar.so按如下方式编译 program 将产生编译错误:
```bash
$ gcc -c -Wall main.c
$ gcc -o prog main.o -L. -lfoobar
/usr/bin/ld: warning: libfoo.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libbar.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
./libfoobar.so: undefined reference to `bar'
./libfoobar.so: undefined reference to `foo'
collect2: error: ld returned 1 exit status
```
此时可在编译 prog 时增加 -rpath/-rpath-link 参数:
```bash
gcc -o prog main.o -L. -lfoobar -Wl,-rpath=$(pwd)
```
即可。此时能够正常编译和运行 prog因为相关信息已经被写入到 libfoobar.so 文件中:
```bash
$ readelf -d prog
Dynamic section at offset 0xe08 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoobar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [/home/imk/develop/so/scrap]
... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
```
-rpath-link 只用于链接时查找。运行可执行程序时,-rpath-link 指定的路径不再有效,而 -rpath 指定的路径还有效。
The linker uses the following search paths to locate required shared libraries:
1. Any directories specified by -rpath-link options.
2. Any directories specified by -rpath options. The difference between -rpath and -rpath-link is that directories specified by -rpath options are included in the executable and used at runtime, whereas the -rpath-link option is only effective at link time. Searching -rpath in this way is only supported by native linkers and cross linkers which have been configured with the --with-sysroot option.
3. On an ELF system, for native linkers, if the -rpath and -rpath-link options were not used, search the contents of the environment variable "LD_RUN_PATH".
4. On SunOS, if the -rpath option was not used, search any directories specified using -L options.
5. For a native linker, the search the contents of the environment variable "LD_LIBRARY_PATH".
6. For a native ELF linker, the directories in "DT_RUNPATH" or "DT_RPATH" of a shared library are searched for shared libraries needed by it. The "DT_RPATH" entries are ignored if "DT_RUNPATH" entries exist.
7. The default directories, normally /lib and /usr/lib.
8. For a native linker on an ELF system, if the file /etc/ld.so.conf exists, the list of directories found in that file.
If the required shared library is not found, the linker will issue a warning and continue with the link.
在 Makefile 中设置 LD_RUN_PATH/LD_LIBRARY_PATH 的话,需要将环境变量的设置写到具体的编译命令一行中,因为 Makefile 规则中的每一行都在其自己的 shell 实例中运行,如:
```Makefile
CC=LD_LIBRARY_PATH=/my/library/path gcc
foo:
CC $< -o $@
```
## 3. 外部参考资料
1. [gcc警告选项汇总](https://blog.csdn.net/qq_17308321/article/details/79979514)