Linux下编译环境及Makefile的学习笔记
一、GCC类警告提示:GCC 的提示选项有很多种类型,主要可分为“-Wall”类警告和非“-Wall”类警告。
Wall类警告包含打开所有警告的功能并且可以单独对常见错误分别指定警告,这些警告中最为常用的为-Wall类警告。它的作用是打开所有类型的语法警告。
非Wall类警告提示最常见的有以下两种:
-ansi 和 -pedantic
前者强制GCC生成标准语法所要求的告警信息,并不能保证所有没有警告的程序都是符合ANSIC标准的。
后者该选项允许发出ANSIC标准所列的全部告警信息。
二、linux函数库的介绍
Linux中函数库可以有三种使用的形式:静态、共享和动态。
静态库的代码在编译时就已经链接到应用程序中,而共享库只是在程序开始运行时才载入。
动态库也是在程序开始运行时才载入,但与共享库不同的是,动态库使用的库函数不是在程序开始运行时开始载入而是在程序中的语句需要使用该函数时才载入。动态库可以在程序运行期间释放动态库所占的内存,供其他程序使用。
由于共享库和动态库并没有在程序中包含库函数的内容,只包含了对库的引用,因此代码的规模较小。共享库和动态库的后缀名由.so和版本号组成,静态库的后缀名为.a
三、相关路径选项
(a)由于库文件的通常路径不是在系统默认的路径下,因此,首先要使用调用路径选项来制定相关的库文件的位置,两个常用选项的使用方法:
(1)“-I dir”它可以在头文件的搜索路径列表中添加dir目录。
gcc hello.c -I /root/workpace/gcc/ -o hello
(2)“-L dir”它的功能与-I类似,其区别在于-L选项用于指定库文件的路径。
gcc hello.c -L /root/workpace/gcc/lib -o hello
注意:两者均指定了路径,而没有指定文件,因此不能再路径中包含文件名
(b)使用三种类型链接库
使用三种链接库都是用-l选项,由于linux的函数库的命名规则都是以“lib”开头的,因此,这里的库文件只需填写lib之后的内容即可。
例如有静态库文件libm.a和libm.so在调用时也只需写作“-lm”即可。若系统中同时存在文件名相同的静态库文件和动态库文件,linux系统默认的调用动态链接方式,若想调用静态库文件需显示的写明包含后缀名的文件名。
四、gdb调试
进入gdb只需输入gdb和要调试的可执行文件(在编译时加入-g参数)即可:
1、查看文件
在gdb 中键入“l”(list)就可以查看所在如的文件。
2、设置断点
设置断点可以使程序到一定的文职暂停他的运行,程序员在该位置处可以方便的查看变量的值、堆栈的情况,在gdb中只需在“b”后加入对应的行号:
(gdb) b 8
注意:在gdb中利用行号设置断点是指代码运行到对应行之前暂停,并没有运行到指定行。
3、查看断点情况
在设置完断点后,用户可以键入“info b”来查看断点情况,在gdb中可以设置多个断点。
(gdb) info b
4、运行代码
gdb默认的是从首行开始运行代码,可键入“r”即可,在“r”后加上行号即可从程序中指定行开始运行
(gdb) r
5、查看变量的值
在程序停止运行之后,程序员需要查看断点处的相关变量的值,在GDB中只需键入“p+变量值”即可
(gdb) p n
gdb 在显示变量时,会在对应值之前加上“N”标记,它是当前变量值的引用标记,所以以后再次引用改变量的时候就可以直接写作“N”标记,它是当前变量值的引用标记,所以以后再次引用改变量的时候就可以直接写作“N”而无需写冗长的变量名。
6、观察变量
在某一循环处,希望能够观察到一个变量的变化情况,这时就可以键入命令“watch”来观察变量的变化情况。
(gdb) watch n
7、单步运行
单步运行是指一次只运行一条语句,这样可以方便程序员检查程序运行的结果,只需输入n即可
(gdb) n
8、程序继续运行
命令“c”可以使GDB继续运行一下的程序,程序再次遇到断点时停止 (gdb) c
9、退出GDB只需“q”即可:
五、Makefile
1.Makefile 中的变量
Makefile中的变量分为用户自定义变量,预定义变量,自动变量和环境变量,自定义变量的值有用户自行设定,而预定义变量和自动变量为通常在Makefile中都会出现的变量,其中部分有默认值。预定义变量包含了常见编译器、汇编器的名称及其编译选项。
Makefile中常见预定义变量:
CC C编译器的名称默认值为 cc
CXX c++编译器的名称默认值为g++
CFLAGS C编译器的选项,无默认值
CPPFLAGS C 预编译的选项,无默认值
CXXFLAGS C++ 编译器的选项,无默认值
为了简化Makefile的编写,引入了自动变量,自动变量通常可以代表编译语句中出现的目标文件和依赖文件。
$* 不包含扩展名的目标文件名称
$+ 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
$< 第一个依赖文件的名称
$?所有时间戳比目标文件完的依赖文件
$@目标文件的完整名称
$^ 所有不重复的文件,以空格分开
$% 如果目标是归档成员,则该变量表示目标的归档成员名称
2.Makefile 中的规则
在Makefile规则中,通配符将被自动展开,但在变量的定义和函数的引用时,通配符将失效,这种情况下如果要使通配符有效就需要使用函数“wildcard”,它的用法是:$(wildcard partters...)。在Makefile中,它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件的列表。
一般情况下:“$(wildcard *.cpp)”来获取工作目录下的所有的.cpp文件列表;复杂一些用法:可以使用“$(patsubst %.cpp,%.o,$(wildcard *.cpp))”,首先使用“wildcard”函数获取工作目录下的.cpp文件列表之后将列表中所有文件名的后缀.cpp替换为.o。这样我们就可以得到在当前目录可生成的.o文件列表。因此在一个目录下可以使用如下内容的Makefile来将工作目录下的所有的.cpp文件进行编译并最后连接成为一个可执行文件。
#sample Makefile
objects :=(patsubst(patsubst(wildcard*.c))
//%和*都代表通配符但是%是GNUmake语法层的makefile中的,而*是shell命令行下的。
foo : $(objects)
cc -o foo $(objects)
=是最基本的赋值
:=是覆盖之前的值
?=是如果没有被赋值过就赋予等号后面的值
+=是添加等号后面的值
Makefile中变量赋值的“=”“:=”
1、“=”
make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:
x = foo
y = $(x) bar
x = xyz
在上例中,y的值将会是xyz bar,而不是foo bar。
2、“:=”
“:=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。
x := foo
y := $(x) bar
x := xyz
在上例中,y的值将会是foo bar,而不是xyz bar了。
如果觉得《Linux下编译环境及Makefile的学习笔记》对你有帮助,请点赞、收藏,并留下你的观点哦!