如何使用Linux的ar命令创建静态库

在开发软件时,使用Linux的jar命令创建函数库。本教程将通过示例代码向您展示如何创建、修改和在程序中使用静态库。

AR司令部是一个真正的老兵,它从1971年就开始存在了。名称ar引用了该工具最初的预期用途,即创建归档文件。存档文件是单个文件,用作其他文件的容器。有时用于许多其他文件。可以向存档添加文件、从存档中删除文件或从存档中提取文件。寻找这类功能的人们不再求助于ar。这一角色已经被其他公用事业公司取代,如tar。

不过,ar命令仍用于少数专业用途。AR用于创建静态库。这些在软件开发中使用。ar还用于创建包文件,如Debian Linux发行版中使用的“.deb”文件及其衍生产品(如Ubuntu)。

我们将演练创建和修改静态库所需的步骤,并演示如何在程序中使用库。要做到这一点,我们需要满足静态库的要求。此库的目的是对文本字符串进行编码,并对编码的文本进行解码。

请注意,出于演示目的,这是一次快速而肮脏的黑客攻击。不要对任何有价值的东西使用这种加密。这是世界上最简单的替代密码,A变成B,B变成C,以此类推。

相关:如何在Linux上使用tar命令压缩和解压缩文件

cipher_encode()和cipher_decode()函数

我们将在一个名为“library”的目录中工作,稍后我们将创建一个名为“test”的子目录。

我们在此目录中有两个文件。在名为cipher_encode.c的文本文件中,我们有cipher_encode()函数:

void cipher_encode(char *text) { for (int i=0; text[i] != 0x0; i++) { text[i]++; } } // end of cipher_encode

相应的cipher_decode()函数位于名为cipher_decde.c的文本文件中:

void cipher_decode(char *text) { for (int i=0; text[i] != 0x0; i++) { text[i]--; } } // end of cipher_decode

包含编程指令的文件称为源代码文件。我们将创建一个名为libcipher.a的库文件。它将包含这两个源代码文件的编译版本。我们还将创建一个名为libcipher.h的短文本文件。这是一个头文件,其中包含新库中两个函数的定义。

拥有该库和头文件的任何人都可以在自己的程序中使用这两个函数。他们不需要重新发明轮子和重写函数;他们只需利用我们库中的副本。

编译cipher_encode.c和cipher_decde.c文件

为了编译源代码文件,我们将使用标准GNU编译器GCC。c(编译,无链接)选项告诉GCC编译文件,然后停止。它从每个源代码文件生成一个中间文件,称为对象文件。GCC链接器通常获取所有目标文件,并将它们链接在一起以生成可执行程序。我们使用-c选项跳过了这一步。我们只需要目标文件。

让我们检查一下我们有没有我们认为有的文件。

ls -l

这两个源代码文件位于此目录中。我们用GCC把它们编译成目标文件。

gcc -c cipher_encode.cgcc -c cipher_decode.c

如果一切顺利,应该不会有GCC的输出。

这将生成两个与源代码文件同名但扩展名为“.o”的目标文件。这些是我们需要添加到库文件中的文件。

ls -l

创建libcipher.a库

要创建库文件(实际上是存档文件),我们将使用ar。

我们使用-c(CREATE)选项创建库文件,使用-r(ADD WITH REPLACE)选项将文件添加到库文件,使用-s(INDEX)选项创建库文件内文件的索引。

我们将把库文件命名为libcipher.a。我们在命令行上提供该名称,以及要添加到库中的目标文件的名称。

ar -crs libcipher.a cipher_encode.o cipher_decode.o

如果我们列出目录中的文件,我们将看到现在有了一个libcipher.a文件。

LS-l

如果我们将-t(表)选项与ar一起使用,我们可以看到库文件中的模块。

ar -t libcipher.a

创建libcipher.h头文件

libcipher.h文件将包含在使用libcipher.a库的任何程序中。但libcipher.h文件必须包含库中函数的定义。

要创建头文件,我们必须在文本编辑器(如Gedit)中键入函数定义。将文件命名为“libcipher.h”,并将其保存在与libcipher.a文件相同的目录中。

void cipher_encode(char *text); void cipher_decode(char *text);

使用libcipher库

测试我们的新库的唯一可靠方法是编写一个小程序来使用它。首先,我们将创建一个名为test的目录。

mkdir test

我们将把库文件和头文件复制到新目录中。

cp libcipher.* ./test

我们将切换到新目录。

cd test

让我们检查一下我们的两个文件是否在这里。

ls -l

我们需要创建一个可以使用库的小程序,并证明它按预期运行。在编辑器中键入以下文本行。将编辑器的内容保存到test目录中名为“test.c”的文件中。

#include #include #include "libcipher.h" int main(int argc, char *argv[]) { char text[]="How-To Geek loves Linux"; puts(text); cipher_encode(text); puts(text); cipher_decode(text); puts(text); exit (0); } // end of main

程序流程非常简单:

它包括libcipher.h文件,以便它可以看到库函数定义。 它创建一个名为“text”的字符串,并在其中存储“How-to Geek Love Linux”字样。 它会将该字符串打印到屏幕上。 它调用cipher_encode()函数对字符串进行编码,并将编码后的字符串打印到屏幕上。 它调用cipher_decode()对字符串进行解码,并将解码后的字符串打印到屏幕上。

要生成测试程序,我们需要编译test.c程序并链接到库中。o(输出)选项告诉GCC它生成的可执行程序的名称。

gcc test.c libcipher.a -o test

如果GCC默默地让你回到命令提示符,那就万事大吉了。现在让我们测试一下我们的程序。关键时刻:

./test

我们看到了预期的产量。测试程序打印纯文本,打印加密文本,然后打印解密文本。它正在使用我们新库中的函数。我们的图书馆正在运转。

成功。但为什么要止步于此呢?

将另一个模块添加到库中

让我们向库中添加另一个函数。我们将添加一个函数,程序员可以使用该函数来显示他们正在使用的库的版本。我们需要创建新函数、编译它,并将新的目标文件添加到现有的库文件中。

在编辑器中键入以下行。1将编辑器的内容保存到库目录中名为cipher_version.c的文件中。

#include void cipher_version(void) { puts("How-To Geek :: VERY INSECURE Cipher Library"); puts("Version 0.0.1 Alpha\n"); } // end of cipher_version

我们需要将新函数的定义添加到libcipher.h头文件中。在该文件的底部添加新行,使其如下所示:

void cipher_encode(char *text); void cipher_decode(char *text); void cipher_version(void);

保存修改后的libcipher.h文件。

我们需要编译cipher_version.c文件,以便拥有cipher_version.o目标文件。

gcc -c cipher_version.c

这将创建一个cipher_version.o文件。我们可以使用以下命令将新对象文件添加到libcipher.a库中。v(详细)选项让通常不说话的ar告诉我们它做了什么。

ar -rsv libcipher.a cipher_version.o

新对象文件将添加到库文件中。AR打印确认。“a”表示“添加”。

我们可以使用-t(表)选项来查看库文件中有哪些模块。

ar -t libcipher.a

现在,我们的库文件中有三个模块。让我们利用一下新功能吧。

使用cipher_version()函数。

让我们从test目录中删除旧库和头文件,复制新文件,然后切换回test目录。

我们将删除旧版本的文件。

rm ./test/libcipher.*

我们将把新版本复制到测试目录中。

cp libcipher.* ./test

我们将切换到测试目录。

cd test

现在我们可以修改test.c程序,使其使用新的库函数。

我们需要向test.c程序添加调用cipher_version()函数的新行。我们将把它放在第一个put(Text);行之前。

#include #include #include "libcipher.h" int main(int argc, char *argv[]) { char text[]="How-To Geek loves Linux"; // new line added here cipher_version(); puts(text); cipher_encode(text); puts(text); cipher_decode(text); puts(text); exit (0); } // end of main

将其另存为test.c。我们现在可以编译它并测试新函数是否可操作。

gcc test.c libcipher.a -o test

让我们运行新版本的test:

这项新功能正在发挥作用。我们可以在test的输出开始处看到库的版本。

但可能存在一个问题。

更换库中的模块

这不是该库的第一个版本,而是第二个版本。我们的版本号不正确。第一个版本中没有cipher_version()函数。这个可以。所以这应该是版本“0.0.2”。我们需要用更正后的函数替换库中的cipher_version()函数。

谢天谢地,AR让这件事变得非常容易。

首先,让我们编辑库目录中的cipher_version.c文件。将“Version 0.0.1 Alpha”文本更改为“Version 0.0.2 Alpha”。应该如下所示:

#include void cipher_version(void) {  puts("How-To Geek :: VERY INSECURE Cipher Library");   puts("Version 0.0.2 Alpha\n"); } // end of cipher_version

保存此文件。我们需要重新编译它以创建一个新的cipher_version.o目标文件。

gcc -c cipher_version.c

现在,我们将用新编译的版本替换库中现有的cipher_version.o对象。

我们以前使用过-r(Add With Place)选项,将新模块添加到库中。当我们将其与库中已有的模块一起使用时,ar将用新版本替换旧版本。-s(Index)选项将更新库索引,-v_s(详细)选项将使Jar告诉我们它做了什么。

ar -rsv libcipher.a cipher_version.o

这一次,ar报告它已经替换了cipher_version.o模块。“r”表示已替换。

使用更新的cipher_version()函数

我们应该使用修改后的库,并检查它是否正常工作。

我们将把库文件复制到test目录。

cp libcipher.* ./test

我们将切换到测试目录。

cd ./test

我们需要用新的库重新编译我们的测试程序。

gcc test.c libcipher.a -o test

现在我们可以测试我们的程序了。

./test

测试程序的输出符合我们的预期。版本字符串中显示了正确的版本号,并且加密和解密例程正在工作。

从库中删除模块

经过这一切似乎很遗憾,但是让我们从库文件中删除cipher_version.o文件。

为此,我们将使用-d(删除)选项。我们还将使用-v(详细)选项,这样ar就会告诉我们它做了什么。我们还将包括-s(索引)选项来更新库文件中的索引。

ar -dsv libcipher.a cipher_version.o

AR报告它已卸下该模块。“d”表示“已删除”。

如果我们要求ar列出库文件中的模块,我们将看到我们返回到两个模块。

ar -t libcipher.a

如果要从库中删除模块,请记住从库头文件中删除它们的定义。

共享您的代码

库以一种实用但私有的方式使代码可共享。您向其提供库文件和头文件的任何人都可以使用您的库,但您的实际源代码仍然是私有的。

相关文章