.o文件与.a文件

时间:2009-03-17 15:20:45

标签: c++ c linux gcc build-process

这两种文件类型有什么区别。我看到我的C ++应用程序在构造可执行文件时链接了两种类型。

如何构建.a文件?链接,参考,尤其是示例,非常感谢。

6 个答案:

答案 0 :(得分:57)

.o个文件是对象。它们是编译器的输出和输入到链接器/库管理器。

.a个文件是档案。它们是对象组或静态库,也可以输入到链接器中。

其他内容

我没有注意到你问题的“例子”部分。通常,您将使用makefile生成静态库。

AR = ar 
CC = gcc

objects := hello.o world.o

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

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

这会将hello.cworld.c编译成对象,然后将它们存档到库中。根据平台的不同,您可能还需要运行名为ranlib的实用程序来生成存档中的目录。

一个有趣的旁注:.a文件在技术上是归档文件而不是库。它们类似于没有压缩的zip文件,尽管它们使用的是更旧的文件格式。由ranlib等实用程序生成的目录是使归档成为的原因。 Java归档文件(.jar)的相似之处在于它们是具有Java归档程序创建的一些特殊目录结构的zip文件。

答案 1 :(得分:14)

<。> .o文件是编译单个编译单元(本质上是源代码文件,带有相关的头文件)的结果,而.a文件是打包为库的一个或多个.o文件。

答案 2 :(得分:11)

D Shawley的答案很好,我只是想补充几点,因为其他答案反映了对正在发生的事情的不完全理解。

请记住,存档文件(.a)不限于包含目标文件(.o)。它们可能包含任意文件。不常用,但请参阅dynamic linker dependenciy info embedded in an archive了解愚蠢的链接技巧。

另请注意,目标文件(.o)不一定是单个编译单元的结果。可以将几个较小的目标文件部分链接到一个较大的文件中。

http://www.mihaiu.name/2002/library_development_linux/ - 在此页面中搜索“部分”

答案 3 :(得分:5)

您可以使用ar.a文件(目标文件)创建.o文件(静态库)

有关详细信息,请参阅man ar

答案 4 :(得分:2)

我相信.a文件是一个可以包含多个目标文件的存档。

答案 5 :(得分:2)

.a.o文件链接还有另一个方面:链接时,所有.o都包含在最终的可执行文件中,而来自.a的条目仅当它们满足.o中缺少的符号依赖性时,才包括在内。

为说明这一点,请考虑以下示例:

// 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();
}

我们可以使用以下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

并获得两个可执行文件main_omain_a,它们的不同之处在于,a.ccb.cc的内容在第一种情况下是通过两个.o提供的并在第二秒内通过.a

最后,我们使用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()

并观察到main_a实际上缺少b.o中不需要的符号。