Linux C开发基础
GCC
gcc简介
GCC 原名为 GNU C语言编译器(GNU C Compiler)
GCC(GNU Compiler Collection,GNU编译器套件)是由 GNU 开发的编程语言 译器。GNU 编译器套件包括 C、C++、Objective-C、Java、Ada 和 Go 语言前 端,也包括了这些语言的库(如 libstdc++,libgcj等)
GCC 不仅支持 C 的许多“方言”,也可以区别不同的 C 语言标准;可以使用命令行 选项来控制编译器在翻译源代码时应该遵循哪个 C 标准。例如,当使用命令行参数
-std=c99
启动 GCC 时,编译器支持 C99 标准。安装命令 sudo apt install gcc g++ (版本 > 4.8.5)
查看版本 gcc/g++ -v/–version
gcc工作流程
gcc和g++的区别
gcc 和 g++都是GNU(组织)的一个编译器。
误区一:gcc 只能编译 c 代码,g++ 只能编译 c++ 代码。两者都可以,请注意: 后缀为 .c 的,gcc 把它当作是 C 程序,而 g++ 当作是 c++ 程序。 后缀为 .cpp 的,两者都会认为是 C++ 程序,C++ 的语法规则更加严谨一些。 编译阶段,g++ 会调用 gcc,对于 C++ 代码,两者是等价的,但是因为 gcc 命令不能自动和 C++ 程序使用的库联接,所以通常用 g++ 来完成链接,为了统 一起见,干脆编译/链接统统用 g++ 了,这就给人一种错觉,好像 cpp 程序只 能用 g++ 似的
误区二:gcc 不会定义 __cplusplus 宏,而 g++ 会。 实际上,这个宏只是标志着编译器将会把代码按 C 还是 C++ 语法来解释 。 如上所述,如果后缀为 .c,并且采用 gcc 编译器,则该宏就是未定义的,否则, 就是已定义
误区三:编译只能用 gcc,链接只能用 g++ 。 严格来说,这句话不算错误,但是它混淆了概念,应该这样说:编译可以用 gcc/g++,而链接可以用 g++ 或者 gcc -lstdc++。 gcc 命令不能自动和C++程序使用的库联接,所以通常使用 g++ 来完成联接。 但在编译阶段,g++ 会自动调用 gcc,二者等价
gcc常用参数选项
gcc编译选项 | 说明 |
---|---|
-E | 预处理指定的源文件,不进行编译 |
-S | 编译指定的源文件,但是不进行汇编 |
-c | 编译、汇编指定的源文件,但是不进行链接 |
-o [file1] [file2] / [file2] -o [file1] | 将文件 file2 编译成可执行文件 file1 |
-I directory | 指定 include 包含文件的搜索目录 |
-g | 在编译的时候,生成调试信息,该程序可以被调试器调试 |
-D | 在程序编译的时候,指定一个宏 |
-w | 不生成任何警告信息 |
-Wall | 生成所有警告信息 |
-On | 开启编译优化,-O0表 示没有优化,-O1为缺省值,-O3优化级别最高 |
-l | 在程序编译的时候,指定使用的库 |
-L | 指定编译的时候,搜索的库的路径。 |
-fPIC/fpic | 生成与位置无关的代码 |
-shared | 生成共享目标文件,通常用在建立共享库时 |
-std | 指定C方言,如:-std=c99,gcc默认的方言是GNU C |
静态库制作
命名规则
Linux : libxxx.a
lib : 前缀(固定)
xxx : 库的名字,自己起
.a : 后缀(固定)
Windows :
libxxx.lib
制作方法
gcc 获得 .o 文件
将 .o 文件打包,使用 ar 工具(archive)
ar rcs libxxx.a xxx.o xxx.o
r – 将文件插入备存文件中
c – 建立备存文件
s – 索引
动态库制作
当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统的动态载入器来获取该绝对路径。对于elf格式的可执行程序,是由ld-linux.so来完成的,它先后搜索elf文件的 DT_RPATH段 ——> 环境变量 LD_LIBRARY_PATH ——> /etc/ld.so.cache文件列表 ——> /lib/,/usr/lib 目录找到库文件后将其载入内存。
命名规则
Linux : libxxx.so
lib : 前缀(固定)
xxx : 库的名字,自己起
.so : 后缀(固定)
在Linux下是一个可执行文件
Windows :
libxxx.dll
制作方法
gcc 得到 .o 文件,得到和位置无关的代码
gcc -c –fpic/-fPIC a.c b.c
gcc 得到动态库
gcc -shared a.o b.o -o libcalc.so
Makefile
规则和工作原理
一个 Makefile 文件中可以有一个或者多个规则
目标 …: 依赖 …
命令(Shell 命令) …
目标:最终要生成的文件(伪目标除外)
依赖:生成目标所需要的文件或是目标
命令:通过执行命令对依赖操作生成目标(命令前必须 Tab 缩进)
Makefile 中的其它规则一般都是为第一条规则服务的。
命令在执行之前,需要先检查规则中的依赖是否存在
- 如果存在,执行命令
- 如果不存在,向下检查其它的规则,检查有没有一个规则是用来生成这个依赖的, 如果找到了,则执行该规则中的命令
检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间
- 如果依赖的时间比目标的时间晚,需要重新生成目标
- 如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被 执行
变量
自定义变量
变量名=变量值 var=hello $获取变量的值,$(变量名)
预定义变量
AR : 归档维护程序的名称,默认值为 ar
CC : C 编译器的名称,默认值为 cc
CXX : C++ 编译器的名称,默认值为 g++
$@ : 目标的完整名称
$< : 第一个依赖文件的名称
$^ : 所有的依赖文件
示例
1 |
|
模式匹配
1 |
|
函数
$(wildcard PATTERN…)
功能:获取指定目录下指定类型的文件列表
参数:PATTERN 指的是某个或多个目录下的对应的某种类型的文件,如果有多个目录,一般使用空格间隔
返回:得到的若干个文件的文件列表,文件名之间使用空格间隔
示例:
$(wildcard .c ./sub/.c)
返回值格式: a.c b.c c.c d.c e.c f.c
$(patsubst <pattern>,<replacement>,<text>)
功能:查找中<text>的单词(单词以空格”、“Tab”或“回车”“换行”分隔)是否符合<pattern>模式,如果匹配的话,则以<replacement>替换。
<pattern>可以包括通配符
%
,表示任意长度的字串。如果<replacement>中也包含%
,那么,<replacement>中的这个%
将是<pattern>中的那个%所代表的字串。(可以用\
来转义,以\%
来表示真实含义的%
字符)返回:函数返回被替换过后的字符串
示例:
$(patsubst %.c, %.o, x.c bar.c)
返回值格式: x.o bar.o
文件IO
1 |
|
参考链接
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!