为了技术,我不会停下学习的脚步,我相信我还能走二十年。
分类:
2012-09-20 20:15:00
原文地址:Linux命令学习手册-ar命令 作者:vaqeteart
参考资料:
http://www.cppblog.com/prayer/archive/2009/05/27/85877.html
ar [ -c ] [ -l ] [ -g | -o ] [ -s ] [ -v ] [ -C ] [ -T ] [ -z ] { -h | -p | -t | -x } [ -X {32|64|32_64}]
ArchiveFile [ File ... ]
ar [ -c ] [ -l ] [ -g | -o ] [ -s ] [ -v ] [ -C ] [ -T ] [ -z ] { -m | -r [ -u ] } [ { -a | -b | -i }
PositionName ] [ -X {32|64|32_64}] ArchiveFile File ...
ar [ -c ] [ -l ] [ -g | -o ] [ -s ] [ -v ] [ -C ] [ -T ] [ -z ] { -d | -q } [ -X {32|64|32_64}] ArchiveFile File
...
ar [ -c ] [ -l ] [ -v ] [ -C ] [ -T ] [ -z ] { -g | -o | -s | -w } [ -X {32|64|32_64}] ArchiveFile
【功能】
ar命令可以用来创建、修改库,也可以从库中提出单个模块。库是一单独的文件,里面包含了按照特定的结构组织起来的其它的一些文件(称做此库文件的member)。原始文件的内容、模式、时间戳、属主、组等属性都保留在库文件中。
【举例】
*查看ar的版本号:
$ar -V
*要创建一个库:
$ ar -rv libhello.a hello1.o hello2.o hello3.o hello4.o hello5.o hello6.o
输入之后,输出如下:
ar: creating libhello.a
a - hello1.o
a - hello2.o
a - hello3.o
a - hello4.o
a - hello5.o
a - hello6.o
这里,从多个用 ld 命令创建的共享模块(hello*.o目标文件)中创建一个压缩文档库,编译并链接如何使用这个库文件本文有举例。注意这里的添加顺序。-v标志设置详细方式,在此方式中 ar 命令在其进行时显示进程报告,如果没有这个v将只显示:
ar: creating libhello.a。
*创建一个库的另一个方法:
$ ar -qv libhello.a hello1.o hello2.o hello3.o hello4.o hello5.o hello6.o
这里,如果 libhello.a 库不存在,则此命令创建它,并将文件hello1.o-hello6.o的副本输入其中。如果 libhello.a 库存在,则此命令在不检查相同成员的情况下,将新的成员添加到末尾。
*查看库中的所有模块:
$ ar -t libhello.a
输入之后,输出如下:
hello1.o
hello2.o
hello3.o
hello4.o
hello5.o
hello6.o
这样会依次列出库中所有的模块成员。显示的次序不是根据名字的,而是添加模块时候决定的。加-v则类似ls -l的长格式。
*删除库中的指定模块:
$ ar -dv libhello.a hello3.o
输入之后输出如下:
d - hello3.o
这样会在库中删除指定的模块成员hello3.o,加-v是为了显示删除什么文件。下面用详细方式显示删除后的库文件如下:
$ ar -tv libhello.a
输入之后输出如下:
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello1.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello2.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello4.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello5.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello6.o
*将库中指定的模块提取出来:
$ ar -xv libhello.a hello1.o
输入之后,输出如下:
x - hello1.o
这样,会将库中的模块hello1.o释放到当前的文件夹,不会在库中删除该模块。这里实际是加-v选项是为了显示输出删除了那个模块。
*打印成员的内容:
$ ar -pv libhello.a hello1.o
输入之后,输出如下:
^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^A^@>^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@(^A^@^@^@^@^@^@^@^@^@^@@^@^@^@^@^@@^@^M^@
.....由于篇幅关系,后面省略了......
这里,打印的是hello1.o的内容,估计我们也看不懂,如果不加-v选项,就不会打印第一行的
*解压缩并重命名一个成员:
$ar -p libhello.a hello1.o >hello1copy.o
此命令将成员hello.o 复制到一个名为hello1copy.o 的文件,实际就是一个重定向的操作。
*要指定在模块的前面插入新成员:
$ ar -rb hello1.o libhello.a hello3.o
或$ar -ri hello1.o libhello.a hello3.o
这样,没用-v所以没有输出,但会把hello3.o插入libtest.a中,并且在hello1.o模块前.用-t可以看到次序如下:
$ar -tv libhello.a
输入之后,输出如下:
rw-r--r-- 14506/1001 1488 Jul 4 14:24 2009 hello3.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello1.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello2.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello4.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello5.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello6.o
如果要插入的成员已经存在于库中,结果相当于将原来的同名模块删除,之后再插入,如下:
quietheart@ubuntu:~/libTest/hellolib/ver2obj/bak$ ar -rb hello4.o libhello.a hello3.o
quietheart@ubuntu:~/libTest/hellolib/ver2obj/bak$ ar -tv libhello.a
输入之后,输出如下:
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello1.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello2.o
rw-r--r-- 14506/1001 1488 Jul 4 14:25 2009 hello3.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello4.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello5.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello6.o
在这里,我们用-v选项会显示详细的插入信息,这里我修改了hello3.o的内容,如果不修改,那么始终时间是14:23怎么加都是。
*要指定在模块的后面插入新成员:
$ar -ra hello2.o libhello.a hello3.o
这里的操作和rb或者ri选项指定的在前面插入原理一样,不过插入的方向变成了在后面追加插入了。用-v会显示详细的插入信息。
*要替换或添加新成员到库中:
$ar -r libhello.a hello6.o
这样,如果libhello.a库中没有hello6.o那么就会把模块hello6.o添加到库的末尾,如果有的话就会替换之( 位置还是原来的位置)。
*要更新一个已经更改过的成员:
$ar -ru libhello.a hello3.o
这时候,仅当hello3.o比库中的hello3.o更新时或者没有在库中时才替代库中的hello3.o或者加入hello3.o.
*更改库成员的顺序:
$ar -mav hello4.o libhello.a hello1.o hello3.o
输入之后,输出如下:
m - hello1.o
m - hello3.o
此命令将成员hello1.o和hello3.o移动到hello4.o后面。当库中如果有若干模块有相同的符号定义(如函数定义),则成员的位置顺序很重要。
如果没有指定任选项,任何指定的成员将移到库的最后。也可以使用’a’,’b’,或’i’任选项移动到指定的位置。检查结果如下:
$ar -tv libhello.a
输入之后,输出如下:
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello2.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello4.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello3.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello1.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello5.o
rw-r--r-- 14506/1001 1488 Jul 4 14:23 2009 hello6.o
这里,注意,发现参考资料中别人的解释和实践之后的结果不一样,那个参考资料这样说的:
$ar -v -m -a strcmp.o lib.a strcat.o strcpy.o
此命令将成员 strcat.o 和 strcpy.o 移动到紧跟在 strcmp.o 成员之后的位置。保留 strcat.o 和 strcpy.o 成员的相对顺序。换句话说,如果在移动之前 strcpy.o 成员在 strcat.o 成员之前,那么(移动后)它依旧如此。可是我运行了这个命令发现相对次序也变化了??
【描述】
当我们的程序中有经常使用的模块,而且这种模块在其他程序中也会用到,这时按照软件重用的思想,我们应该将它们生成库,使得以后编程
可以减少开发代码量。
*选项
选项前可以有 ‘-’字符,也可以没有。
-a PositionName 在 PositionName 参数标识的现有文件后安置指定的文件。
-b PositionName 在 PositionName 参数标识的现有文件前安置指定的文件。
-c 禁止在创建库时产生的正常消息。
-C 阻止解压缩的文件替换文件系统中同名的文件。
-d 从库中删除指定的文件。
-g 对压缩文档成员进行排序以确保用最小数量的未用空间获得最大的加载效率。在几乎所有情况下,-g 标志以压缩文档成员的逻辑链接顺序
物理地安置它们。最终生成的压缩文档通常写成小格式,这样该标志可用来将大格式压缩文档转换成小格式压缩文档。包含 64 位 XCOFF 对象
的压缩文档不能创建成或转换至小格式。
-h 将指定的文件的成员报头中的修改时间设置为当前日期和时间。如果不指定任何文件名称,则 ar 命令设置所有成员报头的时间戳记。此标
志不能和 -z 标志一起使用。
-i PositionName 在 PositionName 参数标识的现有文件前安置指定的文件(和 -b 相同)。
-l 将临时文件置于当前(本地)目录中,而非 TMPDIR 目录中(缺省为 /tmp)。
-m 将指定的文件移动到库中的某个其它位置。缺省情况下,它将指定的文件移动到库的末尾。使用位置标志(abi)来指定某个其它位置。
-o 对压缩文档成员进行排序以确保用最小数量的未用空间获得最大的加载效率。在几乎所有情况下,-o 标志以压缩文档成员的逻辑链接顺序
物理地安置它们。最终生成的压缩文档通常写成大格式,这样该标志可用来将小格式压缩文档转换成大格式压缩文档。
-p 将 Files 参数中指定的文件的内容或在 ArchiveFile 参数中指定的所有文件(如果您不指定任何文件)都写至标准输出。
-q 将指定的文件添加到库的末尾。另外,如果指定同一个文件两次,它可能被放入库中两次。
-r 如果指定的文件已经存在于库中,则替换它。因为指定的文件在库中占据它们替换的文件的同一个位置,位置标志没有任何附加的影响。当
和 -u 标志(更新)一起使用时,-r 标志仅替换自从最后一次添加到库中以后修改的文件。
如果指定的文件不存在于库中,则 ar 命令添加它。在这种情况下,位置标志影响放置。如果不指定位置,则将新文件置于库的末尾。如果指
定同一个文件两次,它可能被放入库中两次。
-s 无论 ar 命令是否修改了库内容都强制重新生成库符号表。请在库上使用 strip 命令之后,使用此标志来恢复库符号表。
-t 将库的目录写至标准输出。如果指定文件名称,则仅显示指定的那些文件。如果不指定任何文件,-t 标志列出库中的所有文件。
-T 如果压缩文档成员名称比文件系统支持的长,则允许文件名称截短。此选项无效,因为文件系统支持的名称长度等于 255 个字符的最大压
缩文档成员名称。
-u 仅复制自它们最后一次复制起更改的文件(请参阅先前讨论过的 -r 标志)。
-v 将建立新库的详细的逐个文件的描述写至标准输出。当和 -t 标志一起使用时,它给出类似于 ls -l 命令给出的长列表。当和 -x 标志一
起使用时,它在每个文件前加一个名称。当和 -h 标志一起使用,它列出成员名称和更新的修改时间。
-w 显示压缩文档符号表。每个符号和其中定义此符号的文件的名称一起列出。
-x 通过将指定的文件复制到当前目录来解压缩它们。这些副本和原始文件(保留在库中)具有相同的名称。如果不指定任何文件,-x 标志复
制库中的所有文件。此过程不会更改库。
-X mode 指定 ar 应检查的目标文件的类型。mode 必须是以下项之一:
32
仅处理 32 位目标文件
64
仅处理 64 位目标文件
32_64
处理 32 位 和 64 位目标文件
缺省值是处理 32 位目标文件(忽略 64 位对象)。mode 还可以用 OBJECT_MODE 环境变量来设置。例如,OBJECT_MODE=64 使 ar 处理任何
64 位对象并忽略 32 位对象。-X 标志覆盖 OBJECT_MODE 变量。
-z 创建压缩文档的临时副本并对副本执行所有要求的修改。当所有操作成功完成时,压缩文档的工作副本覆盖原始副本。此标志不能和 -h 标
志一起使用。
ArchiveFile 指定压缩文档文件名称;必需。
MemberName ... 各压缩文档成员的名称。
*退出状态
该命令返回以下出口值:
0 成功完成。
>0 发生错误。
【其它】
*利用库文件进行编译举例1(后面有简化):
1)编辑hello1.c/h hello2.c/h hello3.c/h hello4.c/h hello5.c/h hello6.c/h
内容如下:
//hello1.h
1 int hello1();
//hello2.h-hello6.h的内容类似,不过把hello1替换成相应的hello2-hello6了.
//hello1.c
1 #include
2 #include "hello1.h"
3 int hello1()
4 {
5 printf("hello1\n");
6 }
//hello2.c-hello6.c的内容类似,不过把hello1替换成相应的hello2-hello6了.
2)编译生成目标文件(模块)
$gcc -c hello*.c
这样会在当前目录下面生成hello1.o hello2.o hello3.o hello4.o hello5.o hello6.o
3)打成libhello.a库包:
$ar -rv libhello.a hello*.o
这样会把所有的.o文件做为模块打包进libhello.a库中。
4)编辑main.c
//main.c
1 #include
2 #include"hello1.h"
3 #include"hello3.h"
4
5 int main(int argc, char *argv[])
6 {
7 hello1();
8 hello3();
9 return 0;
10 }
5)建立一个子文件夹program/,把hello*.h 和main.c移动到program 里面并且利用刚才的库编译main.c:
$mkdir program;mv hello*.h program;mv main.c hello*.h;cd program
$gcc -o main main.c -L ../ -lhello
这样,在program中生成了main,编译命令的-L选项指定库的路径,-l指定ld链接的库的名字,即libhello.a中的hello。
6)运行测试:
$./main
输入之后,输出如下:
hello1
hello3
*利用库进行编译链接举例2(对例1的简化):
1)过程同上例1,不同的唯一之处是:
hello*.c中不需要包含hello*.h头文件,
其内容如下:
//hello1.c
1 #include
2 //#include "hello1.h"
3 int hello1()
4 {
5 printf("hello1\n");
6 }
//hello2.c-hello6.c的内容类似,不过把hello1替换成相应的hello2-hello6了.
2)编译运行:
$gcc -o main main.c -L ../ -lhello
这样编译之后,照样能运行。
*利用库进行编译链接举例3(对例3的进一步简化,这样看不到接口头文件了):
1)过程同上例2,不同的唯一之处是:
main.c中不需要包含hello*.h头文件了(即所有文件任何地方都不需要头文件了),
其内容如下:
//main.c
1 #include
2 //#include"hello1.h"
3 //#include"hello3.h"
4
5 int main(int argc, char *argv[])
6 {
7 hello1();
8 hello3();
9 return 0;
10 }
2)编译运行:
$gcc -o main main.c -L ../ -lhello
这样编译之后,照样能运行。