简体   繁体   English

.o 文件与.a 文件

[英].o files vs .a files

What is the difference between these two file types.这两种文件类型有什么区别。 I see that my C++ app links against both types during the construction of the executable.我看到我的 C++ 应用程序在构建可执行文件期间链接了这两种类型。

How to build.a files?如何构建.a 文件? links, references, and especially examples, are highly appreciated.链接,参考,尤其是示例,非常感谢。

.o files are objects. .o文件是对象。 They are the output of the compiler and input to the linker/librarian.它们是编译器的 output 和链接器/图书馆员的输入。

.a files are archives. .a文件是档案。 They are groups of objects or static libraries and are also input into the linker.它们是对象组或 static 库,也输入到 linker 中。

Additional Content附加内容

I didn't notice the "examples" part of your question.我没有注意到您问题的“示例”部分。 Generally you will be using a makefile to generate static libraries.通常,您将使用 makefile 来生成 static 库。

AR = ar 
CC = gcc

objects := hello.o world.o

libby.a: $(objects)
    $(AR) rcu $@ $(objects)

%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

This will compile hello.c and world.c into objects and then archive them into library.这会将hello.cworld.c编译成对象,然后将它们归档到库中。 Depending on the platform, you may also need to run a utility called ranlib to generate the table of contents on the archive.根据平台的不同,您可能还需要运行一个名为ranlib的实用程序来生成存档的目录。

An interesting side note: .a files are technically archive files and not libraries.一个有趣的旁注: .a文件在技术上是存档文件,而不是库。 They are analogous to zip files without compression though they use a much older file format.它们类似于没有压缩的 zip 文件,尽管它们使用更旧的文件格式。 The table of contents generated by utilities like ranlib is what makes an archive a library .由诸如ranlib等实用程序生成的目录是使存档成为的原因。 Java archive files ( .jar ) are similar in that they are zip files that have some special directory structures created by the Java archiver. Java archive files ( .jar ) are similar in that they are zip files that have some special directory structures created by the Java archiver.

Ao file is the result of compiling a single compilation unit (essentially a source-code file, with associated header files) while aa file is one or more.o files packaged up as a library. ao 文件是编译单个编译单元的结果(本质上是一个源代码文件,带有关联的 header 文件),而 aa 文件是一个或多个打包为库的.o 文件。

D Shawley's answer is good, I just wanted to add a couple of points because other answers reflect an incomplete understanding of what's going on. D Shawley 的回答很好,我只想补充几点,因为其他答案反映了对正在发生的事情的不完整理解。

Keep in mind that archive files (.a) are not restricted to containing object files (.o).请记住,存档文件 (.a) 不限于包含 object 文件 (.o)。 They may contain arbitrary files.它们可能包含任意文件。 Not often useful, but see dynamic linker dependenciy info embedded in an archive for a stupid linker trick.不常用,但请参阅嵌入存档中的动态 linker 依赖信息,了解愚蠢的 linker 技巧。

Also notice that object files (.o) are not necessarily the result of a single compilation unit.另请注意,object 文件 (.o) 不一定是单个编译单元的结果。 It is possible to partially link several smaller object files into a single larger file.可以将几个较小的 object 文件部分链接到一个较大的文件中。

http://www.mihaiu.name/2002/library_development_linux/ -- search in this page for "partial" http://www.mihaiu.name/2002/library_development_linux/ -- 在此页面中搜索“部分”

You can use ar to create .a file (static library) from .o files (object files)您可以使用ar.o文件(目标文件)创建.a文件(静态库)

See man ar for details.有关详细信息,请参阅man ar

There is one more aspect of linking against .a vs .o files: when linking, all .o s passed as arguments are included in the final executable, whereas entries from any .a arguments are only included in the linker output if they resolve a symbol dependency in the program. There is one more aspect of linking against .a vs .o files: when linking, all .o s passed as arguments are included in the final executable, whereas entries from any .a arguments are only included in the linker output if they resolve a程序中的符号依赖。

More specifically, each .a file is an archive comprising multiple .o files.更具体地说,每个.a文件是一个包含多个.o文件的档案。 You can think of each .o being an atomic unit of code.您可以将每个.o视为代码的原子单元。 If the linker needs a symbol from one of these units, the whole unit gets sucked into the final binary;如果 linker 需要这些单元之一的符号,则整个单元将被吸入最终的二进制文件; but none of the others are unless they too are needed.但其他人都不是,除非他们也需要。

In contrast, when you pass a .o on the command line, the linker sucks it in because you requested it.相反,当您在命令行上传递.o时,linker 会因为您请求它而将其吸入。

To illustrate this, consider the following example, where we have a static library comprising two objects ao and bo .为了说明这一点,请考虑以下示例,其中我们有一个包含两个对象aobo的 static 库。 Our program will only reference symbols from ao .我们的程序只会引用来自ao的符号。 We will compare how the linker treats passing ao and bo together, vs. the static library which comprises the same two objects.我们将比较 linker 如何同时处理传递aobo ,与包含相同两个对象的 static 库。

// header.hh
#pragma once

void say_hello_a();
void say_hello_b();
// a.cc
#include "header.hh"
#include <iostream>

char hello_a[] = "hello from a";

void say_hello_a()
{
        std::cout << hello_a << '\n';
}
// b.cc
#include "header.hh"
#include <iostream>

char hello_b[] = "hello from b";

void say_hello_b()
{
        std::cout << hello_b << '\n';
}
// main.cc
#include "header.hh"

int main()
{
        say_hello_a();
}

We can compile the code using this Makefile:我们可以使用这个 Makefile 编译代码:

.PHONY = compile archive link all clean

all: link

compile:
        @echo ">>> Compiling..."
        g++ -c a.cc b.cc main.cc

archive: compile
        @echo ">>> Archiving..."
        ar crs lib.a a.o b.o

link: archive
        @echo ">>> Linking..."
        g++ -o main_o main.o a.o b.o
        g++ -o main_a main.o lib.a

clean:
        rm *.o *.a main_a main_o

and obtain two executables main_o and main_a that differ in that the contents of a.cc and b.cc where provided through two .o s in the first case and through a .a in the second.并获得两个可执行文件main_omain_a ,它们的不同之处在于a.ccb.cc的内容在第一种情况下通过两个.o提供,在第二种情况下通过.a提供。

Lastly we examine the symbols of the final executables using the nm tool:最后,我们使用nm工具检查最终可执行文件的符号:

$ nm --demangle main_o | grep hello
00000000000011e9 t _GLOBAL__sub_I_hello_a
000000000000126e t _GLOBAL__sub_I_hello_b
0000000000004048 D hello_a
0000000000004058 D hello_b
0000000000001179 T say_hello_a()
00000000000011fe T say_hello_b()
$ nm --demangle main_a | grep hello
00000000000011e9 t _GLOBAL__sub_I_hello_a
0000000000004048 D hello_a
0000000000001179 T say_hello_a()

and observe that main_a is in fact lacking the unneeded symbols from bo .并观察main_a实际上缺少bo中不需要的符号。 That is, the linker did not suck in the contents of bo within the archive lib.a because none of the symbols from b.cc were referenced.也就是说,linker 没有吸收归档lib.abo的内容,因为没有引用来自b.cc的符号。

I believe an.a file is an archive that can contain multiple object files.我相信 an.a 文件是一个可以包含多个 object 文件的存档。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM