GCC [OPTION] [FILENAME]
GCC主要经过四个步骤,预处理、编译、汇编、链接的四个过程。
以一个hello.c为例,如果GCC -C hello.c 则会生成一个目标文件hello.o。
-O选项,则会对整个程序进行优化。这个是大O,还有O2。
GCC hello.c -o hello 这个会生成一个hello的文件,通过执行./hello会得到程序的结果。
-I dirname加入这个程序所依赖的头文件所在的目录位置去寻找 GCC -I /home/use hello.c -o hello //hello所依赖的头文件在/home/usr目录下存在 这样就可以找到。这个是在gcc进行编译的时候发生的,包含头文件。
-L dirname去指定库文件所在的路径。多一个可以寻找库文件的位置。跟-I意思一样,这个是在链接时候发生的。需要链接库文件。如线程库、数学库等。这个选项告诉链接程序,首先到-L指定的目录中去寻找,然后再到系统预设路径中寻找。
-l小L,默认的情况下会链接C库,在链接时,装载名字为"libname.a"的函数库,该函数库位于系统预设的目录或者由-L选项确定的目录下。例如-lm表示连接名为"libm.a"的数学函数库,一般会把前面的lib和.a后缀去掉。gcc foo.c -L /home/lib -lfoo -o foo。
-static 静态链接,在运行时会包含在一起,多个程序会有多个拷贝。动态链接库则是在运行时进行调用,而不包含,多个程序共享一个拷贝。默认的时候是采用动态链接方式。
-wall 生成所有的警告信息。
-w 不生成警告信息。
-DMACRO -D相当于define的作用,定义一个宏。
gcc -g tst.c -o tst这个编译生成可执行文件
启动GDB gdb tst
在main函数处设置断点 break main
运行程序 run
单步执行 nexrt
c连续运行 直到下一个断点或者结束。
退出 quit
list显示程序 一次10行
GNU的make能够使整个软件工程的编译、连接只需要一个命令就可以完成。linux内核大概1W个文件,使用make的作用就非常明显。make在执行时,需要一个命名为Makefile的文件。Makefile文件描述了整个工程的编译、连接等规则。其中包括:工程中的哪些源文件需要编译以及如何编译;需要创建哪些库文件以及如何创建这些苦文件,如何最后产生我们想要的可执行文件。
hello:main.o func1.o func2.o
gcc main.o func1.o func2.o -o hello
main.o:main.c
gcc -c main.c
func1.o:func1.c
gcc -c func1.c
func2.o:func2.c
gcc -c func2.c
.PHONY:clean
clean:
rm -f hello main.o func1.o func2.o
Makefile的术语:
规则:用于说明如何生存一个或多个目标文件,规则格式如下
targets:prerequisites
command
目标 依赖 命令(需要tab键开始)
func2.o:func2.c
gcc -c func2.c
make命令默认在当前目录下寻找名字为makefile的工程文件。当名字部位makefile时,通过makefile -f 文件名进行指定。.PHONY表示的是一个伪目标,没有任何依赖,只有命令没有依赖的目标。
在此我们可以使用SHELL编程指定变量:obj=main.o func1.o func2.o func3.o
hello:$(obj)
gcc $(obj) -o hello
指定obj一个变量,编译的时候取得obj变量的值就行。方便使用。使用变量的好处就是如果依赖条件增加,只需要在obj后面进行添加,执行命令的指令不需要改变。
gcc $^ -o $@ $^代表的是依赖目标 %@代表的是目标文件
加一个@符进行取消回显。
obect = *.o上面这个例子表示了,通符同样可以用在变量中。Objects的值就是"*.o"。makefile中的变量其实就是C/C++中的宏,如果你要让通配符在变量中展开,可以使用
object :=$(wildcard *.o)
在一些大的工程中,有大量的源文件,我们通常的做法是把着许多的源文件分类,并存放在不同的目录中。所以,当make需要去找寻文件的以来关系时,你可以在文件前加上路径,但最好的方法是把一个路径告诉make,让make在自动去找。
makefile文件中的特殊变量"VPATH"就是完成这个功能的,如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么make就会在当当前目录找不到的情况下,到所指定的目录中去找寻文件了。
VPATH=src:../headers
上面的定义指定两个目录,"src"和"../headers",make会按照这个顺序进行搜索,目录由"冒号"分隔,当然,当前目录永远是最高优先搜索的地方。
如果一个比较大型的工程,你必须清楚哪些C文件包含了哪些头文件,并且,你在加入或删除头文件时,也需要小心地修改makefile,这是一个很没有维护性的工作。为了避免这种繁重而又容易出错的事情,我们可以使用C/C++编译的一个功能,大多数的C/C++编译器都支持一个“-M”的选项,即自动找寻源文件中包含的头文件,并生成一个依赖关系。例如,如果我们执行下面的命令:
CC -M main.c
其输出是:main.o:main.c defs.h
于是由编译器自动生成的依赖关系,这样一来,你就不必再手动书写若干文件的依赖关系,而由编译器自动生成了。需要提醒一句的是,如果你使用GNU的编译器,你得用“-MM”参数,不然"-M"参数会把一些标准库的头文件也包含进来。
为了避免变量的无限递归,我们使用make中的另一种变量来定义变量的方法,这种方法使用的是“:=”操作符,如x:=foo
y:=$(x)bar
x:=later
其等价于:
y:=foo bar
x:=later
这种方法,前面的变量不能使用后面的变量,只能使用前面已定义好了的变量。
还有一种比较有用的操作符“?=”
FOO?=bar
其含义是,如果FOO没有被定义过,那么变量FOO的值就是"bar",如果FOO先前被定义过,那么这条语句将什么也不做。
系统变量“CFLAGS”可以控制编译时的编译器参数。
下面是所有隐含规则中会用到的变量:
1 关于命令的变量
AR 函数库打包程序,默认命令是“ar”
AS 汇编语言编译程序。默认命令是"as"
CC C语言编译程序,默认命令是"cc"
CXX C++语言编译程序,默认命令是"g++"
2 关于命令参数的变量:
下面的这些变量都是相关上面的命令的参数:
ARFLAGS 函数库打包程序AR命令的参数 。默认值时"rv"
ASFLAGS 汇编语言编译器参数
CFLAGS C语言编译器参数
CXXFALGS C++语言编译器参数
COFLAGS RCS命令参数
定义模式规则:
模式规则介绍:模式规则中,至少在规则的目标定义中要包含"%",否则,就是一般的规则。目标中的"%"定义表示对文件名的匹配。"%"表示任意的非空字符串。
%.o:%.c:
其含义是之处了怎么从所有的.c文件中生成相应的.o文件的规则。
自动化变量:$@ 表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,"$@"就是匹配于目标中模式定义的集合。
$% 仅当目标是函数库文件中,表示规则中的目标成员名。
$< 依赖目标中的第一个目标名字。如果依赖目标是以模式"即%"定义的,那么"$<"将是符合模式的一系列的文件集。注意,其实一个一个取出来的。
$? 所有比目标新的依赖目标的集合。以空格分隔。
$^ 所有的依赖目标的集合,以空格分隔。如果在依赖目标中由多个重复的,那么这个变量会去除重复的依赖目标,只保留一份。
$+ 这个变量很像“$^”。也就是所有依赖目标的集合。只是它不去除重复的依赖目标。
老式风格的"后缀规则"
后缀规则是一个比较老式的定义隐含规则的方法,后缀规则会被模式规则逐步取代。为了和老版本的makefile兼容,GNU make同样兼容于这些东西,后缀规则有两种方式:“双后缀“和"单后缀"。
双后缀:.c.o相当于"%o:%c"