.o
file adalah objek. Mereka adalah keluaran dari kompiler dan masukan ke penaut/pustakawan.
.a
file adalah arsip. Mereka adalah grup objek atau pustaka statis dan juga dimasukkan ke dalam linker.
Konten Tambahan
Saya tidak memperhatikan bagian "contoh" dari pertanyaan Anda. Umumnya Anda akan menggunakan makefile untuk menghasilkan pustaka statis.
AR = ar
CC = gcc
objects := hello.o world.o
libby.a: $(objects)
$(AR) rcu [email protected] $(objects)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o [email protected]
Ini akan mengkompilasi hello.c
dan world.c
menjadi objek dan kemudian mengarsipkannya ke perpustakaan. Bergantung pada platformnya, Anda mungkin juga perlu menjalankan utilitas bernama ranlib
untuk membuat daftar isi pada arsip.
Catatan tambahan yang menarik:.a
file secara teknis adalah file arsip dan bukan perpustakaan. Mereka mirip dengan file zip tanpa kompresi meskipun menggunakan format file yang jauh lebih tua. Daftar isi dihasilkan oleh utilitas seperti ranlib
adalah apa yang menjadikan arsip sebagai perpustakaan . File arsip Java (.jar
) serupa karena merupakan file zip yang memiliki beberapa struktur direktori khusus yang dibuat oleh pengarsip Java.
Ada satu lagi aspek penautan terhadap .a
vs .o
file:saat menautkan, semua .o
s diteruskan sebagai argumen disertakan dalam eksekusi akhir, sedangkan entri dari .a
apa pun argumen hanya disertakan dalam keluaran penaut jika menyelesaikan ketergantungan simbol dalam program.
Lebih khusus lagi, masing-masing .a
file adalah arsip yang terdiri dari beberapa .o
file. Anda dapat memikirkan setiap .o
menjadi unit kode atom. Jika penghubung membutuhkan simbol dari salah satu unit ini, seluruh unit tersedot ke dalam biner terakhir; tetapi tidak satu pun dari yang lain kecuali mereka juga dibutuhkan.
Sebaliknya, saat Anda memberikan .o
pada baris perintah, penaut menyedotnya karena Anda memintanya.
Untuk mengilustrasikannya, pertimbangkan contoh berikut, di mana kita memiliki pustaka statis yang terdiri dari dua objek a.o
dan b.o
. Program kita hanya akan mereferensikan simbol dari a.o
. Kita akan membandingkan bagaimana penaut memperlakukan a.o
yang lewat dan b.o
bersama-sama, vs. pustaka statis yang terdiri dari dua objek yang sama.
// 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();
}
Kita dapat mengkompilasi kode menggunakan Makefile ini:
.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
dan dapatkan dua executable main_o
dan main_a
yang berbeda adalah isi dari a.cc
dan b.cc
di mana disediakan melalui dua .o
s dalam kasus pertama dan melalui .a
di detik.
Terakhir kita memeriksa simbol dari executable akhir menggunakan nm
alat:
$ 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()
dan amati main_a
itu sebenarnya kekurangan simbol yang tidak dibutuhkan dari b.o
. Artinya, linker tidak menyedot konten b.o
dalam arsip lib.a
karena tidak ada simbol dari b.cc
direferensikan.
File .o adalah hasil kompilasi unit kompilasi tunggal (pada dasarnya file kode sumber, dengan file header terkait) sedangkan file .a adalah satu atau lebih file .o yang dikemas sebagai pustaka.
Jawaban D Shawley bagus, saya hanya ingin menambahkan beberapa poin karena jawaban lain mencerminkan pemahaman yang tidak lengkap tentang apa yang terjadi.
Perlu diingat bahwa file arsip (.a) tidak dibatasi untuk berisi file objek (.o). Mereka mungkin berisi file arbitrer. Sering tidak berguna, tetapi lihat info dependensi linker dinamis yang disematkan dalam arsip untuk trik linker bodoh.
Perhatikan juga bahwa file objek (.o) belum tentu merupakan hasil dari satu unit kompilasi. Beberapa file objek yang lebih kecil dapat ditautkan sebagian ke dalam satu file yang lebih besar.
http://www.mihaiu.name/2002/library_development_linux/ -- cari di halaman ini untuk "partial"