C – Linker ve Nesne Dosyaları

Header Dosyalarının yerleri ve Search Path Ayarları yazısının girişinde sorduğum sorulardan;

  • Bir Header dosyasının belirttiği bir object file nasıl bulunur? Linker bunu nerede arar?

sorularını burada cevaplayacağım. Bunu yaparken, Linker ve Linker parametrelerinden söz edeceğim.

Object File

Stackoverflow‘da Why compile to an object file first? sorusuna verilen cevaplarda önce object code‘a derleme konusunda aşağıdaki noktalara değiniliyor.

Bu olaya, separate compilation denir.

  • Aynı anda, farklı object file‘larda birden fazla kişi çalışabilir.
  • Daha hızlı derleme, aynı dosyaları tekrar tekrar derlemene gerek yoktur.
  • object file‘lar farklı dillerden derlenerek oluşturulmuş olabilir. Daha sonra, Linker ile birleştirilebilirler.
  • separate compilation birçok sistem geneli library‘nin dağıtımını kolaylaştırır. Bunlar static ya da shared library‘ler olabilir. Mesela; işletim sistemi kütüphaneleri, dillerin standart kütüphaneleri, ya da üçüncü parti kütüphaneler.

Yukarıda anlatılanlardan, Make vs. Ant – Build araçları ile konfigürasyon yönetimi yazısında bahsetmiştim. Burada, object file‘ları birleştirmek Linker‘ın işidir.

gcc ile Link işlemini, çeşitli parametreler kullanarak yapabiliriz. Ayrıca, binutils den biri olan ld ile de bu işlemi linker adımı içerisinde yapabiliriz.

GCC ve Linker Parametreleri

Options for Linking‘de link aşamasında kullanılabilecek olan parametreler açıklanıyor.

gcc -c file1.c file2.c

Yukarıdaki yapıdaki -c, compile demektir, bu parametre Derleyicinin kullandığı bir parametredir.  Belirtilen kaynak kodların object filelarını oluşturur. linker bu parametreyi, -S ve -E parametrelerinden biriyle işlem yapıldığında görmezden gelir.

gcc -o exe_dosya file1.o file2.o

Yukarıdaki yapıda, -o (output) parametresi belirtildiği için, belirtilen object file‘lar, Linker tarafından Link edilerek executable oluşturulur. Dolayısıyla, Linker‘ın en temel parametresi, .o uzantılı object file‘dır. Ama çoğu zaman tek başına .o lar ile işlem yapılmaz. Kütüphaneler(shared->.so ya da static->.a) ile işlem yapılır.

C ile LIBC’yi Kullanmadan Program Yazmak yazısında bahsettiğim -nostdlib‘e de değinmek isterim.

gcc -nostdlib -o hello hello.c

-nostdlib Linker‘a, .c dosyası derlendikten sonra oluşan .o dosyasını libc kütüphanesiyle link etmemesini söylüyor. Yoksa bu .o, .c dosyasında #include <stdio.h>, #include <stdlib.h> ... ifadeleri belirtilmemiş bile olsa standart kütüphaneyle link edilirdi. Bu parametre ile .o dosyasına link edilmeyecek olan libc kütüphanesi,

/usr/lib/gcc/i486-linux-gnu/4.4/libgcc.a

dir.

Bununla birlikte hazır bakmışken libgcc ile ilgili başka nerelerde neler var onlara da bakalım.

lifeinbeta@lifeinbeta:/$ sudo find / -name libgcc*
/opt/lampp/lib/libgcc_s.so.1
/usr/share/lintian/overrides/libgcc1
/usr/share/doc/libgcc1
/usr/lib/ure/lib/libgcc3_uno.so
/usr/lib/gcc/i486-linux-gnu/4.4/libgcc_s.so
/usr/lib/gcc/i486-linux-gnu/4.4/libgcc.a
/usr/lib/gcc/i486-linux-gnu/4.4/libgcc_eh.a
/usr/lib/libgccpp.so.1
/usr/lib/libgccpp.so.1.0.2
/var/lib/dpkg/info/libgcc1.md5sums
/var/lib/dpkg/info/libgcc1.shlibs
/var/lib/dpkg/info/libgcc1.postrm
/var/lib/dpkg/info/libgcc1.symbols
/var/lib/dpkg/info/libgcc1.postinst
/var/lib/dpkg/info/libgcc1.list
/lib/libgcc_s.so.1

-llib: Linker, belirtilen object file‘ı, burada belirtilen library ile link eder.

UNIX’te bir kütüphanenin ismi, “liblibrary_name(.ar | .so)” şeklindedir. Link edilmesi istenen kütüphane, -llibname şeklinde değil, -lname şeklinde belirtilmelidir.

gcc parametreleri belirtilirken, -l parametresinin hangi sırada belirtildiği önemlidir. Eğer, foo.o -lname zoo.o şeklinde bir ifade varsa, zoo.o, name kütühanesindeki gerekli .o ile link edilmez. Çünkü, Linker, object file‘ları ve kütüphaneleri, gcc komutunda bunların belirtildiği noktaya gelince arar ve sadece o noktada işlem yapar. Yukarıda, -lname, bütün object file‘lardan sonra belirtilmiş olsaydı, Linker, önce object file‘ları işleyecekti sonra en sonda belirtilen kütüphaneyi arayacaktı ve bulduğunda bunu, önceden farkettiği object file‘lar ile link edebilecekti.

Peki, yukarıda sadece library ismini belirttik. UNIX üzerinde yüzlerce dizin olduğunu hesaba katarsak, Linker belirtilen kütüphaneyi hangi dizinde bulacak? Linker, gerekli olan bir kütüphaneyi, bir standart dizin listesindeki dizinlerde arar. Daha sonra bu kütüphanenin içinden gerekli olan object file‘ın nasıl alınarak nasıl link edildiğini Loaders yazısında anlatacağım.

Library Search Path = Link Path = Load Path

setting search paths‘te ve When should i set LD_LIBRARY_PATH‘te belirtildiği gibi;

Linker, kütüphaneleri sırasıyla /usr/lib/ ve /usr/local/lib/ dizinlerinde arar. Bu dizinler, link edilecek dosyaların aranması için kullanılan, varsayılan dizinlerdir. Bu dizinlere, library search path ya da link path ya da load path denir. Standart C Kütüphanesi olan libgcc, /usr/lib/ altında bulunur ve varsayılan olarak her zaman link edilir. Link işleminde kullanılması gereken harici bir kütüphanenin bu dizin listesine eklenmesi gerekir.

Load Path‘e yeni bir dizin, LD_LIBRARY_PATH ortam değişkeni aracılığıyla eklenebilir(Ancak bu, güvenlik nedeniyle, tavsiye edilmez). Bu değişken, varsayılan dizinleri tutmaz, sadece harici olarak eklenmiş dizinleri tutar. Ortam değişkenine eklemekle, yeni eklenen dizin başka link işlemlerinde de aranması için kalıcı hale getirilmiş olur. Sadece uygulamaya göre, Linker tarafından içinde kütüphane aranacak olan, dizin belirtmek için(tavsiye edilen) -Ldizin parametresi kullanılmalıdır.

Ancak, -L parametresiyle link path‘e her link işlemi için dizin belirtmek istemeyiz. Aynı şekilde, -l parametresiyle link edilmesini istediğimiz library‘leri belirtirken de tekrar tekrar bu işi yapmak istemeyiz. Bunlara alternatif olarak, makefile kullanabiliriz. Aşağıda örnek bir Makefile var.

CC = gcc -Wall
SOURCE = hello.c
FLAGS = -lglut
BINARY = hellogl

all:
        $(CC) $(SOURCE) -o $(BINARY) $(FLAGS)

clean:
        @echo Temizleniyor...
        @rm $(BINARY)
        @echo Temiz!

freeglut3 Kurulumu

Şimdi, freeglut3‘ü sistemimize yükleyelim.

Bunun için, OpenGL Utility Toolkit(freeglut3) ü kurduktan sonra aşağıdaki işlemi yaptım.

lifeinbeta@lifeinbeta:/$ sudo find / -name freeglut*
/usr/share/doc/freeglut3
/var/cache/apt/archives/freeglut3_2.6.0-0ubuntu2_i386.deb
/var/lib/dpkg/info/freeglut3.postinst
/var/lib/dpkg/info/freeglut3.list
/var/lib/dpkg/info/freeglut3.postrm
/var/lib/dpkg/info/freeglut3.shlibs
/var/lib/dpkg/info/freeglut3.md5sums

Henüz .h ve .so dosyları yok. Daha sonra, development libraries and headers for GLUT(freeglut-dev)i kurdum ve aşağıdaki işlemi yaptım.

lifeinbeta@lifeinbeta:/$ sudo find / -name freeglut*
/usr/share/doc/freeglut3
/usr/share/doc/freeglut3-dev
/usr/share/doc/freeglut3-dev/freeglut.html
/usr/share/doc/freeglut3-dev/freeglut_user_interface.html
/usr/share/doc/freeglut3-dev/freeglut_logo.png
/usr/include/GL/freeglut_std.h
/usr/include/GL/freeglut.h
/usr/include/GL/freeglut_ext.h
/var/cache/apt/archives/freeglut3_2.6.0-0ubuntu2_i386.deb
/var/cache/apt/archives/freeglut3-dev_2.6.0-0ubuntu2_i386.deb
/var/lib/dpkg/info/freeglut3-dev.list
/var/lib/dpkg/info/freeglut3.postinst
/var/lib/dpkg/info/freeglut3.list
/var/lib/dpkg/info/freeglut3.postrm
/var/lib/dpkg/info/freeglut3.shlibs
/var/lib/dpkg/info/freeglut3-dev.md5sums
/var/lib/dpkg/info/freeglut3.md5sums

Header dosyaları, /usr/include/ içinde /GL/ dizini oluşturularak buraya konuldu. Neden buraya konduğu konusunda bkz. Header dosyalarının yerleri ve Search Path ayarları. Ancak hala kütüphaneler ortada yok. development libraries … dediğine göre yüklenmiş olmalılar, ama bulamadım. 🙂 How to install freeglut?‘dan bakarak bu kütüphanelerin libglut isminde olduğunu gördüm.

Aşağıdaki işlemi yaptığımda bu dosyaları görebildim.

lifeinbeta@lifeinbeta:/$ sudo find / -name libglut*
/usr/share/doc/libglut3-dev
/usr/lib/libglut.so.3
/usr/lib/libglut.so
/usr/lib/libglut.so.3.9.0
/usr/lib/libglut.a
/var/cache/apt/archives/libglut3-dev_3.7-25_all.deb
/var/lib/dpkg/info/libglut3-dev.list
/var/lib/dpkg/info/libglut3-dev.md5sums

Linkler

Advertisements

Leave a comment

Filed under build, C, gcc, linker

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s