Unix 开发工具与脚本语言全解析
在 Unix 系统开发中,有许多实用的工具和脚本语言,它们能帮助开发者更高效地完成工作。下面将详细介绍这些工具和语言的使用方法和特点。
1. 共享库安装与预防措施
在安装共享库时,可采用一致的方法,使用
-Wl,-rpath
来创建运行时链接路径,或者直接使用不常用库的静态版本,以此预防可能出现的问题。
2. make 工具
当程序包含多个源文件或需要特殊编译选项时,手动编译会变得十分繁琐。而
make
作为传统的 Unix 编译管理工具,能有效解决这一问题。
2.1 make 的基本概念
-
目标(target)
:是
make要达成的目标,可以是文件(如.o文件、可执行文件等)或标签。 -
依赖(dependencies)
:部分目标依赖于其他目标,例如生成可执行文件前需要先有完整的
.o文件集合。 -
规则(rule)
:
make依据规则生成目标,它本身自带许多规则,同时也支持自定义规则。
2.2 Makefile 示例
以下是一个简单的 Makefile,用于从
aux.c
和
main.c
生成名为
myprog
的程序:
# arquivos-objeto
OBJS=aux.o main.o
all: myprog
myprog: $(OBJS)
$(CC) -o myprog $(OBJS)
-
首行的
#表示注释。 -
OBJS是宏定义,定义了两个目标文件名,后续通过$(OBJS)引用。 -
all是默认目标,即直接执行make时要创建的目标。 -
all依赖于myprog,而myprog依赖于$(OBJS)展开后的aux.o和main.o。
执行
make
时,输出如下:
$ make
cc -c -o aux.o aux.c
cc -c -o main.o main.c
cc -o myprog aux.o main.o
2.3 预设规则
make
知道如何从
.c
文件生成
.o
文件,即使
.c
文件未在 Makefile 中明确列出,它也会遵循预设规则,执行
cc -c
命令来完成转换。
2.4 最终程序生成
生成
myprog
的最后一步,是在拥有
$(OBJS)
中的两个目标文件后,执行以下命令(
$(CC)
会展开为编译器名称):
$(CC) -o myprog $(OBJS)
注意,命令前必须有一个制表符,否则会出现
Makefile:7: *** missing separator. Stop.
错误。
2.5 保持更新
make
的一个重要原则是目标要与其依赖保持同步。例如,连续两次执行
make
,第一次会生成
myprog
,第二次则会提示
make: Nothing to be done for 'all'.
,因为依赖文件未发生变化。若要测试更新机制,可按以下步骤操作:
1. 执行
touch aux.c
。
2. 再次执行
make
,此时
make
会判断
aux.c
比
aux.o
新,从而重新编译
aux.c
。
3. 由于
myprog
依赖于
aux.o
,且
aux.o
比
myprog
新,所以
make
会重新创建
myprog
。
2.6 命令行参数和选项
-
指定单个目标
:可在命令行指定单个目标,如
make aux.o仅生成aux.o文件。 -
定义宏
:能在命令行定义宏,例如使用
clang编译器:
$ make CC=clang
-
无 Makefile 执行
:若
make的预设规则能匹配目标,可直接执行make尝试创建目标,如make blah可处理简单的blah.c程序。不过,对于需要特殊库或包含目录的程序,通常需要创建 Makefile。 - 重要选项 :
-
-n:显示构建所需命令,但不实际执行。 -
-f arquivo:让make从指定文件读取规则,而非默认的 Makefile 或 makefile。
2.7 常用宏和变量
-
宏(macro)
:通常在 Makefile 开头定义,常见的有:
| 宏名称 | 说明 |
| ---- | ---- |
|CFLAGS| C 编译器选项 |
|LDFLAGS| 链接器选项,用于从目标代码创建可执行文件 |
|LDLIBS| 存放库名选项,避免与搜索路径选项混合 |
|CC| C 编译器,默认是cc|
|CPPFLAGS| C 预处理器选项 |
|CXXFLAGS| GNU make 中 C++ 编译器的标志 | -
变量(variable)
:在生成目标过程中会发生变化,常见的有:
| 变量名 | 说明 |
| ---- | ---- |
|$@| 在规则中展开为当前目标 |
|$*| 展开为当前目标的基本名称,如生成blah.o时展开为blah|
2.8 常规目标
多数 Makefile 包含以下常规目标:
-
clean
:通常用于删除所有目标文件和可执行文件,以便重新开始或打包软件。例如:
clean:
rm -f $(OBJS) myprog
- distclean :用于移除所有不属于原始发行版的内容,包括 Makefile。
-
install
:将编译好的文件和程序复制到系统中合适的位置。执行前建议先使用
make -n install查看操作内容。 - test 或 check :部分开发者提供此目标,用于确保构建后一切正常。
-
depend
:通过
-M选项调用编译器检查源代码来创建依赖关系,不过这种做法现在不太常见。 - all :通常是 Makefile 的第一个目标,常作为可执行文件的引用。
2.9 Makefile 组织
虽然 Makefile 有多种风格,但多数程序员遵循一些通用规则:
-
宏定义
:将库和包含文件按包分组,例如:
MYPACKAGE_INCLUDES=-I/usr/local/include/mypackage
MYPACKAGE_LIB=-L/usr/local/lib/mypackage -lmypackage
PNG_INCLUDES=-I/usr/local/include
PNG_LIB=-L/usr/local/lib -lpng
CFLAGS=$(CFLAGS) $(MYPACKAGE_INCLUDES) $(PNG_INCLUDES)
LDFLAGS=$(LDFLAGS) $(MYPACKAGE_LIB) $(PNG_LIB)
-
目标文件分组
:目标文件通常按可执行文件分组。例如,有
boring和trite两个可执行文件,每个都有自己的.c文件且依赖util.c,可这样组织:
UTIL_OBJS=util.o
BORING_OBJS=$(UTIL_OBJS) boring.o
TRITE_OBJS=$(UTIL_OBJS) trite.o
PROGS=boring trite
all: $(PROGS)
boring: $(BORING_OBJS)
$(CC) -o $@ $(BORING_OBJS) $(LDFLAGS)
trite: $(TRITE_OBJS)
$(CC) -o $@ $(TRITE_OBJS) $(LDFLAGS)
不建议将两个可执行目标合并为一个规则,否则可能导致依赖关系错误。
3. 调试器(Debuggers)
在 Linux 系统中,默认的调试器是
gdb
,同时也有用户友好的前端工具,如 Eclipse IDE 和 Emacs 系统。
3.1 调试准备
为了能对程序进行完整调试,需在编译时使用
-g
选项,将符号表和其他调试信息记录到可执行文件中。
3.2 gdb 基本操作
- 启动 gdb :
$ gdb programa
-
执行程序并传递参数
:在
(gdb)提示符下输入:
(gdb) run opções
-
打印变量值
:使用
print命令查看变量值,该命令也适用于 C 语言中的数组和结构体。
(gdb) print variável
- 设置断点 :
(gdb) break arquivo:num_linha
- 继续执行 :
(gdb) continue
- 清除断点 :
(gdb) clear arquivo:num_linha
4. Lex 和 Yacc
在编译读取配置文件或命令文件的程序时,可能会用到 Lex 和 Yacc,它们是编程语言的构建块。
-
Lex
:是一个标记生成器(tokenizer),将文本转换为带标签的数字标记。GNU/Linux 版本为
flex
,可能需要
-ll
或
-lfl
链接标志。
-
Yacc
:是一个解析器,尝试根据语法读取标记。GNU 解析器是
bison
,使用
bison -y
可与 Yacc 兼容,可能需要
-ly
链接标志。
5. 脚本语言
过去,Unix 系统管理员主要关注 Bourne shell 和 awk 脚本语言。如今,虽然 shell 脚本仍是 Unix 的重要组成部分,但 awk 在脚本领域的使用逐渐减少,取而代之的是许多功能强大的脚本语言。
5.1 脚本语言的基本信息
所有脚本语言的脚本首行都类似 Bourne shell 脚本的 shebang。例如,Python 脚本以如下内容开头:
#!/usr/bin/python
或
#!/usr/bin/env python
在 Unix 中,以
#!
开头的可执行文本文件就是脚本,
#!
后面的路径名是脚本语言解释器的可执行文件。当 Unix 尝试执行以
#!
开头的文件时,会执行
#!
后面的程序,并将文件其余部分作为标准输入。
5.2 常见脚本语言
-
Python
:拥有众多追随者,具备强大的功能,如文本处理、数据库访问、网络和多线程等。其可执行文件通常为
/usr/bin/python,还常用于网站开发。 - Perl :是 Unix 中较古老的第三方脚本语言,曾是编程工具的“瑞士军刀”。尽管近年来在某些方面被 Python 超越,但在文本处理、文件转换和操作方面表现出色。
- 其他脚本语言 :
- PHP :是超文本处理语言,常用于 Web 开发。
通过合理运用这些工具和脚本语言,开发者能在 Unix 系统上更高效地进行开发和调试工作。
Unix 开发工具与脚本语言全解析
5.3 脚本语言使用注意事项
-
解释器路径问题
:脚本首行指定的解释器路径必须正确,否则会出现错误。例如,若脚本首行为
#!/usr/bin/tail -2,而系统中tail实际路径为/bin,执行脚本会报错:
bash: ./myscript: /usr/bin/tail: bad interpreter: No such file or directory
- 命令行参数问题 :不建议在脚本首行添加多个参数,因为不同系统处理方式可能不同,容易导致意外结果。
下面通过一个 mermaid 流程图展示脚本执行的基本流程:
graph TD;
A[开始] --> B{是否以 #! 开头};
B -- 是 --> C[获取 #! 后路径];
C --> D[执行对应程序];
D --> E[将脚本其余部分作为输入];
E --> F[程序处理并输出结果];
B -- 否 --> G[非脚本文件,结束];
F --> H[结束];
6. 总结与操作建议
为了更清晰地对比不同工具和脚本语言的特点及使用场景,我们整理了以下表格:
| 工具/语言 | 主要功能 | 使用场景 | 操作要点 |
| ---- | ---- | ---- | ---- |
| make | 编译管理 | 处理多源文件或特殊编译选项的程序 | 编写 Makefile,注意目标、依赖、规则的设定,命令前用制表符分隔 |
| gdb | 程序调试 | 查找程序中的错误 | 编译时加
-g
选项,掌握
run
、
print
、
break
等基本命令 |
| Lex(flex) | 标记生成 | 处理文本转换为标记的任务 | 可能需
-ll
或
-lfl
链接标志 |
| Yacc(bison) | 语法解析 | 解析标记并根据语法处理 | 用
bison -y
与 Yacc 兼容,可能需
-ly
链接标志 |
| Python | 脚本编程 | 文本处理、数据库访问、网站开发等 | 脚本首行用 shebang 指定解释器路径 |
| Perl | 脚本编程 | 文本处理、文件转换和操作 | 学习其基本语法和常用函数 |
| PHP | 超文本处理 | Web 开发 | 搭建 Web 服务器环境进行开发 |
在实际开发中,可按以下步骤选择和使用这些工具和语言:
1.
确定需求
:明确开发任务的具体需求,如编译管理、调试、文本处理等。
2.
选择工具/语言
:根据需求从上述表格中选择合适的工具或语言。
3.
学习操作要点
:针对所选工具或语言,学习其操作要点和注意事项。
4.
实践应用
:在实际项目中运用所学知识,不断积累经验。
以下是一个简单的操作流程列表,展示如何使用
make
和
gdb
进行程序开发和调试:
1.
编写源代码
:创建
.c
源文件,如
aux.c
和
main.c
。
2.
编写 Makefile
:
# arquivos-objeto
OBJS=aux.o main.o
all: myprog
myprog: $(OBJS)
$(CC) -o myprog $(OBJS)
- 编译程序 :
$ make
-
调试准备
:在编译时添加
-g选项:
$ make CC="cc -g"
- 启动调试 :
$ gdb myprog
- 执行调试命令 :如设置断点、打印变量等。
通过以上对 Unix 开发工具和脚本语言的详细介绍,希望能帮助开发者更好地掌握这些工具和语言的使用,提高开发效率和质量。在实际应用中,不断探索和实践,将这些知识灵活运用到具体项目中。
超级会员免费看
4万+

被折叠的 条评论
为什么被折叠?



