Bir Fincan Kahve ve Programlama-3

Hersekese güzel bir hafta sonundan merhaba. Geçen hafta “cross compile” olayından bahsetmiştim. Bu yazımda C/C++ derleme işleminde önemli bir rolü olan “makefile” ve “cmake” yapılarından bahsetmeyi düşünüyorum.

Eğer bir IDE kullanıyorsanız ki bu konuya daha ayrıntılı değineceğiz; makefile ve cmake ile alakalı başlangıç seviyelerde düşünmenize gerek kalmaz çünkü zaten bunları sizin yerinize kullandığınız IDE ayarlar ve düzenler. Bir makefile aslında derleyiceye programı nasıl derleyeceğini anlatan bir çeşit scripttir. Genellikle unix ve linux işletim sistemlerinde daha çok kullanılıyor. Şimdi burada derleyiciye programı nasıl derleyeceğini anlatan bir script deyince kafası karışanlar olabilir. Tek bir “.c” dosyasına sahip programı, tek satırlık bir kodla derleyebilirsiniz. Fakat yazdığınız program bir proje olmuş içerisinde bir çok “.c” dosyası aynı zamanda “.h” dosyası ve bu dosyaların refer ettiği bir çok kütüphane mevcutsa derleyiciye bunları nasıl ve nereden başlayarak derlemesi gerektiğini anlatmanız gerekiyor. Aksi taktirde derleyici tek bir dosyayı derlemeye çalışacak ve ya şaşıracaktır.

Aslında makefile yazmak için derleyicinin çalışma mantığını da bilmek gerekiyor. Buraya tıklayarak konuya bir göz atabilirsiniz. Makefile yapısı genel olarak şu şekildedir;

hedef: üretiminde kullanılan dosyalar
            komut

Bu yazımda ikinci satırın bir “tab” boşlukla başlaması önemlidir. Aksi taktirde makefile çalışmayacaktır. Şimdi bu yapıda bir makefile yazmaya çalışalım. Örneğin, toplama işlemi yapan bir programımız olsun ve bu program, toplama işlemini yapmak için “sum.c” ve sum.h” dosyalarından oluşan bir sınıf kullansın. Ve progamımızın “main” fonksiyonu “main.c” dosyasında olsun. Doğal olarak “main.c” dosyası #include direktifi ile “sum.h” dosyasını içeriyor yani “sum.h” dosyasına bağımlı olmalı. Bir “.c” dosyası derlendiğinde bu derleme işleminin sonucunda bir “.o” çıktılı makine dilini içeren obje dosyası oluşmalı. Fakat bu “.o” çıktılarını düzgün bir sırayla derlemeliyiz ki bağımlılıkları olan dosyalar derlenebilsin. Derleme işlemi bağımlılığı şu şekilde olacaktır;

o halde makefile’ın ilk komut dizisi şu şekilde olmalı;

sum: main.o sum.o
         gcc -o sum main.o sum.o

bu komut dizisi ile derleyiciye, main.o ve sum.o obje dosyaları çalıştırılabilir programın makine dilindeki komut setlerini içeriyor ve ikisinin birbirine bağlanması yani link edilmesi gerektiğini söylüyoruz. Fakat halen bu dosyalar oluşmuş durumda değil. Bu sebeple derleyiciye bu dosyaları nasıl oluşturması gerektiğini de söylememiz gerek. Öncelikle “main.o” dosyasını nasıl üreteceğini söyleyelim;

main.o: main.c sum.h
             gcc -c main.c

ve aynı zamanda “sum.o” dosyasını da

sum.o: sum.c sum.h
            gcc -c sum.c

komutu ile üretmeli. Dikkat ettiyseniz derleyiciye hangi dosyaları üretmek için hangi dosyaları kullanacağını tek tek söyledik. Eğer bu komutları “Makefile” isminde bir dosya oluşturup programınızın bulunduğu konuma atar ve “make” komutunu çalıştırırsanız programınız düzgün bir şekilde derlenecektir. Make komutunu çalıştırdığınızda işletim sistemi ilk olarak ilk komut setini işleyecektir. Burada koyduğunuz hedef isminin bir önemi yok. Fakat başka bir komut setini işletmek istiyorsanız make komutunun yanına onun ismini de yazabilirsiniz. Mesela “make sum.o” komutunu işletirseniz çıktı olarak sadece “sum.o” dosyasının oluştuğunu görürsünüz.

Aslında proje büyüdükçe bu tarzda bir makefile size yetersiz gelmeye başlayacaktır. Çünkü kullanıdığını kütüphaneler, dosya bağımlılıkları oldukça artmıştır ve bu makefile’ı yazarken bir çok şeyi tekrar tekrar yazmak istemezsiniz. Bunun için makefile içerisinde macrolar ve tanımlamalar yapılabilir. Örneğin;

CC = gcc
CFLAG = -o
OBJS = main.o sum.o
sum: $(OBJS)
$(CC) $(CFLAG) $(OBJS)
%.c: %.o sum.h
$(CC) -c $*.c

Komutları ile yukarıdaki kodun aynısını yazmış oluruz. Eğer daha önce hiç script yazmadıysanız bu kodların size çok yabancı geldiğinin farkındayım. Fakat açıklamaya çalışayım.

“CC” kullanılacak derleyicinin ismini tanımlamamıza yarıyan macro dur. “CFLAG”, -o -c gibi derleyici seçeneklerini tanımlayabilmemize olanak tanır. “OBJS” ile de derleme sonucunda oluşacak tüm obje dosyalarının ne olacağını tanımlıyoruz. Bu tanımlamaları aşağıda $() ifadeleri arasına yerleştiriyoruz. “%” işareti bu komut paterninin tüm verilen uzantılar için geçerli olduğu anlamına gelir. “$*” işareti ise bulunualan konumdaki tüm dosyaları aynı uzantılı dosyaları belirtir.

 

 

referans: https://www.youtube.com/watch?v=43-2t7CveRI

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Copyright © Tüm Hakları Saklıdır.