hello.c
#include
int main(int argc, char *argv[])
{
printf("hello, world\n");
return 0;
}
$ sudo apt-get isntall build-essential #若没有安装GCC,安装
$ gcc -o hello hello.c #转换成可执行文件hello
$ ./hello #运行
不加-o,编译器将可执行文件命名为a.out。
在执行hello文件时,在hello前添加./,是让Shell在当前目录下寻找需要运行的可执行文件
;如果不添加./,Shell会在PATH环境变量设置的目录中寻找可执行文件,这些目录中通常不会包含当前目录,也就无法找到hello文件。
头文件提供对常量的定义和堆库函数调用的声明
。对C语言来说,这些头文件几乎总在/usr/include目录及其子目录下
。
依赖特定Linux版本的头文件通常在/usr/include/sys和/usr/include/linux中。
其他编程系统也有各自的include文件,并将其存储在能被相应编译器自动搜索到的目录里。例如,X视窗系统的/usr/include/X11目录和GNU C++的/usr/include/g++目录。
在调用C语言编译器时,可使用-I选项来包含保存在子目录或非标准位置中的include文件。例如:
$ gcc -I/usr/openwin/include fred.c
只是编译器不仅在标准位置,也在/usr/openwin/include目录中查找程序fred.c中包含的头文件。
标准库文件一般存储在/lib和/usr/lib目录中。默认情况下,C语言链接程序只搜索标准C语言库。
库名字以lib开头,其后指明是什么库(例如,c代表C语言库,m代表数学库)
。
文件名最后以“.”开始,然后给出库文件的类型:.a代表传统静态函数库, .so代表共享函数库
。
$ ls /usr/lib #查看函数库
创建库文件前,将需要的目标文件编译好,再将这些目标文件合并成单独的库文件
。例如,用于拥有foo1.c和foo2.c两个源文件,希望将其打包成一个库文件:
$ gcc -c fool.c
$ gcc -c foo2.c
$ sudo ar crv libfoo.a foo1.o foo2.o
make是用于自动化编译源文件的工具,使用make工具时,用户需要提供一个文件,用来说明源文件之间的依赖关系和构建规则
,这个文件称为makefile。make命令会读取makefile文件的内容,先确定要创建的目标文件,然后比较该目标所依赖的源文件的日期和时间,以决定应该采用哪条规则来构造目标。
比如:有3个头文件:a.h,b.h和c.h,3个源文件:main.c,2.che 3.c,具体情况
/ *main.c* /
#include “a.h”
…
/ *2.c* /
#include “a.h”
#include “b.h”
…
/ *3.c* /
#include “b.h”
#include “c.h”
…
依赖关系定义最终应用程序中的每个文件与源文件之间的关系。上面将依赖关系定义为最终应用程序依赖于文件main.o、2.o和3.o。同样main.o依赖于mian.c和a.h,2.o依赖于2.c、a.h和b.h,3.o依赖于3.c、b.h和c.h。
makefile文件的写法是:先写目标名称,后面跟冒号,接着是空格或制表符,最后是用空格或制表符隔开的文件列表。
上面可以写成:
myapp:main.o 2.o 3.o
main.o:main.c a.h
2.o:2.c a.h b.h
3.o:3.c b.h c.h
如果要一次制作多个文件,可以利用名义上的目标all。假设应用程序有二进制文件myapp和使用手册myapp.1组成,可以用下面这行语句进行定义:
all:myapp myapp.1
除了指定文件之间的依赖关系,还需要知道如何创建文件。例如2.c修改后,2.o用什么命令创建。makefile有默认规则,用户也可以指定规则。上例中,创建一个makefile,命名为Makefile1:
myapp:main.o 2.o 3.o
gcc -o myapp main.o 2.o 3.o
main.o:main.c a.h
gcc -c main.c
2.o:2.c a.h b.h
gcc -c 2.c
3.o:3.c b.h c.h
gcc -c 3.c
$ make -f Makefile1
makefile文件中,
宏作用:常用于设置编译器选项,设置编译器名称(如gcc、cc或c89)
定义宏:MACRONAME=value。可在makefile内部定义,也可在调用make命令时定义。例如:make CC=c89
引用宏:$(MACRONAME)或${MACRONAME}。
宏为空:令等号后面无内容
下面是一个使用宏的makefile
#Makefile2
all:myapp
CC = gcc
INCLUDE =
CFLAGS = -g -Wall -ansi
myapp:main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o:main.c a.h
$(CC) -I$(INCLUDE)$(CFLAGS) -c main.c
2.o:2.c a.h b.h
$(CC) -I$(INCLUDE)$(CFLAGS) -c 2.c
3.o:3.c b.h c.h
$(CC) -I$(INCLUDE)$(CFLAGS) -c 3.c
make自带内置规则,例如对源文件foo1.c,在没有makefile时,make命令也知道如何编译main.c
make命令知道如何调用编译器,默认使用的编译器为cc。可以通过宏改变编译器名称。
通过make -p命令打印make命令的内置规则
。比较重要的是:
OUTPUT_OPTION = -o $@
COMPILE.c = $(CC) -$(CFLAGS)$(CPPFLAGS)$(TARGET_ARCH) -c
$.o:$.c
$(COMPILE.c)$(OUTPUT_OPTION)$
大多数时候,用户只需在makefile中指定依赖关系,并且gcc能够自动编著用户创建这些依赖关系,通过gcc -MM命令可以导出项目中的依赖关系清单
:
$ gcc -MM main.c 2.c 3.c
main.o:main.c a.h
2.o:2.c a.h b.h
3.o:3.c b.h c.h
可以添加clean目标用于删除不需要的临时文件,通过install目标用于将编译后的应用程序安装到指定目录下。
$ sudo make #编译
$ sudo make install //安装
$ sudo make clean //清除
???
Linux内核中makefile文件包括5部分:
makefile /*顶层makefile文件*/
.config /*内核配置文件*/
arch/$(ARCH)/makefile /*机器体现makefile文件*/
scripts/makefile.* /*所有内核makefile共用定义和规则*/
kbuild makefiles /*其他makefile文件*/
通过内核配置操作产生.config文件,顶层makefile文件读取该文件的配置,它负责产生两个主要程序:内核映像(vmlinux image)和模块。
每个子目录有一个makfefile文件,其任务是根据上级目录makefile文件命令启动编译。这些makefile文件使用.config文件配置数据构建各种文件列表,并使用这些文件列表编译内嵌或模块目标文件。 scripts/makefile.*包含了所有的定义和规则,与makefile文件一起编译出内核程序。
调试器:adb、sdb和dbx和GNU的gdb。
gdb
$ gdb foo1.c