长途漫漫,慢慢走来:Linux的第二课
【datatime】2006-08-14
【title】gcc的使用
gcc格式
gcc [-c 编译,不连接] [-S] [-E] [-std] [-g 加入调试信息] [-pg加入剖析信息] [-Olevel]
[-W 警告设置] [-pedantic 发出所有标准C列出的警告] [-Idir 添加包含目录到搜索列表中] [-Ldir添加库目录到搜索列表中]
[-D] [-U] [-f] [-m] [-o 编译到可执行文件,并作一些优化]...
说明:
-w 关闭所有警告设置
-Wall 允许发出所有警告
-werror 把所有警告转化为错误
-v 显示编译过程中的每一步用到的命令
-ggdb 在可执行程序中包含大量的调试信息
-MM 输出一个make兼容的相关列表
-O 优化编译过的代码
-fsyntax-only 只检查语法,其他都不做
-save-temps 保存编译过程中产生的中间文件
-Q 编译器输出编译每个函数时所花的时间信息
gcc的优化选项:
-O等价于-O1,并且包含线程直接跳转和迟延堆栈这两种优化。
-O2包含了-O1的优化选项,并增加了一些额外的调整,如包含对处理器指令调度的调整。
-O3也类似
gcc的调试选项:
-g == -g2,该级别包括扩展符号表、行号、以及局部变量或外部变量。-g3除了包含-g2的信息外,还包含了源代码中定义的宏.
gcc的扩展:
数据类型,如 long long来表示64位的存储单元。
内联函数,inline关键字只是一个建议而不是指令,内联的优化由编译器分析完成。
函数和变量的属性,关键字attribute,在函数或是变量的尾部加上_attribute_((属性名))来完成。
void FunctionName() _attribute_((noreturn)); /* 不返回值 */
int int_var _attribute((aligned 16)) = 0; /* 对齐到16位 */
注释,//呵呵,这个在标准c中没有,标准c中的注释是/* */。
构造函数名称,使用_FUNCTION_就可以输出当前调用函数的名称。如
void main(void)
{
printf("%s", _FUNCTION_);
}
【title】make的使用
Makefile规则格式如下:
target : dependency [dependency [...]]
command
command
[...]
target为目标体,即make要创建的文件;dependency依赖体,必须有依赖文件,即头文件和目标文件或源文件;
警告:
每个命令的第一字符必须为制表符,不能用8个空格来代替。
Example:
1.创建一个Makefile文件,用文本编辑
2.输入下列代码
helloworld : main.o function.o function.h
gcc main.o function.o -o helloworld
main.o : main.c function.h
gcc -c main.c
function.o : function.c function.h
gcc -c function.c
all : helloworld
clean : /* 只是个动作 ,并不真的删除.o文件 */
rm *.o
3.在目录中输入make就可以得到编译的文件了。
【error | make: **No targets specified and on makefile founcd. stop | 缺少Makefile文件名的文件】
【error | make: Circular function.o <- function.o dependency dropped | 依赖文件错误】
【error | on newline at end of file | 需要在每一个源文件的最后敲入一个回车符】
在加入.PHONY后,就直接执行Makefile文件中的命令。
make读取环境变量,如果在Makefile文件中有同名的变量,则这个变量取代环境变量。
make命令的命令行参数:
-f file 指定的makefile文件名
-n 打印将要执行的命令
-Idirname 指定被包含的makefile所在的目录
-s 在执行时不打印命令名
-w 如果在make执行时改变目录, 打印当前目录
-Wfile 如果文件已修改,则使用-n来显示make将要执行的命令
-r 禁用所有的make的内置规则
-d 打印调试信息
-i 忽略返回的非零错误
-k 直到目标编译终止后停止,忽略中间的编译失败
-jN 每次允许N条命令
使用include指令来包含多个make文件。如果想忽略include文件,将用-include指令来代替include指令。
【title】比较和合并源代码文件
diff命令的使用:
格式:diff [options] srcfile dstfile
options参数:
-a 将所有的文件看作为文本,逐行进行比较
-b 忽略空白数目改变
-B 忽略插入或删除空行造成的改变
-H 修改diff处理大文件的方式
-i 忽略大小写
-w 逐行比较时忽略空白
这个工具没搞明白,好像出了点问题,输出的与书本上的例子不一致。
【title】版本管理与控制 RCS(Revision Control System)和CVS(Concurrent Version System)
RCS的基本用法,ci和co,ci表示检入文件到RCS库中;co表示检出文件;
在第一次检入某个文件到RCS库中时,系统需要你输入文件的描述信息,用"."来结束输入。使用-i来告诉RCS这是首次检入的文件。
检出文件用co -l 文件名。 -r可以指定检入或检出的文件的版本。
RCS的关键字:$Id$ $Log$ $Author$ $Date$ $Header$ $Locker$ $Name$ $RCSfile$ $Revision$ $Source$ $State$ 这些关键字可以嵌入到
程序中,利用ident命令可以显示关键字信息。如:文件pen_env
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static char rcsid[] = "$Id$\n";
int main(void)
{
extern char **environ;
char **my_env = environ;
while (*my_env)
{
printf("%s\n", *my_env);
my_env++;
}
exit(EXIT_SUCCESS);
}
用make prn_env.c编译后,在命令行输入$ident prn_env就可以得到$Id$的信息。
用$rlog 文件名就可以从RCS数据库中检出该文件被修改的日志信息了。
CVS的使用:
1.使用$cvs -d dir init命令初始化cvs库。
2.设置环境变量$CVSROOT,命令export CVSROOT = dir。
3.导入目录到CVS中,先在CVSROOT下建立一个目录cdir,然后用命令cvs import [-m msg] cdir lpu2 start,执行就自动把当前目录中的文件导入到cvs/cdir下.