这两种文件类型有什么区别。我看到我的C ++应用程序在构造可执行文件时链接了两种类型。
如何构建.a文件?链接,参考,尤其是示例,非常感谢。
答案 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.c
和world.c
编译成对象,然后将它们存档到库中。根据平台的不同,您可能还需要运行名为ranlib
的实用程序来生成存档中的目录。
一个有趣的旁注:.a
文件在技术上是归档文件而不是库。它们类似于没有压缩的zip文件,尽管它们使用的是更旧的文件格式。由ranlib
等实用程序生成的目录是使归档成为库的原因。 Java归档文件(.jar
)的相似之处在于它们是具有Java归档程序创建的一些特殊目录结构的zip文件。
答案 1 :(得分:14)
答案 2 :(得分:11)
请记住,存档文件(.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_o
和main_a
,它们的不同之处在于,a.cc
和b.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
中不需要的符号。