16 Nisan 2016 Cumartesi

GNU g++, gcc, make dosyası


gcc
gcc GNU ile kullanılan derleyici. Aslında gcc jenerik bir derleyici. Verilen dosya uzantısına göre gerekli olan derleyiciyi çağırıyor. Örneğin c++ dosyası verilirse g++ derleyicisini çağırıyor. Bu konu ile ilgili daha detaylı bilgiyi burada bulabilirsiniz.

gcc genelde şu dizine kurulur.
/usr/bin/gcc

g++
Bir c++ programını derlerken aslında g++ ile beraber bazen cc1 veya cc1plus isimli bir başka programın daha çalıştığını görüyoruz. cc1plus, g++ tarafından çağırılan gerçek derleyici oluyor.

Bazı gcc/g++ seçenekleri
gcc seçenekleri yazısına taşıdım.

Linker
Statik kütüpahene ile linklerken linker sadece ihtiyacımız olan metodları binary çıktının içine dahil eder. Dinamik kütüphanelerde böyle bir seçenek yoktur.

Burada verilen bir metodun değiştirme örneği var.

make dosyası

make dosyasını renkledirilmiş görmek için Notepad++ içinde Language / Makefile menüsünü tıklamak lazım.

Çok basit bir make dosyası
Şöyle yazılır
CXX=g++
CXXFLAGS=-std=c++11 -g -O2
LDLIBS=-ltbb

EXE=$(basename $(wildcard *.cc))

all: $(EXE)

clean:
    rm -fr $(EXE) *.dSYM
Default Değişkenler
makefile ve değişken yazısına taşıdım.

make komutuna dışarıdan parametre girmek
3 yöntem var.
1. ortam değişkenleri make dosyası içinde aynen kullanılabilir.
2. Komut satırından. Örnek:
make target FOO=bar
Buradaki örnekte parametreler make komutundan önce yazılmış. Önce veya sonra yazmanın farkını bilmiyorum.
$ CFLAGS="-Wall" make ex1
3. Ana make dosyasından export ederek. Örnek:
# Do like this
CFLAGS=-g
export CFLAGS
target:
        $(MAKE) -C target
make ve target
makefile ve target yazısına taşıdım.

dependency olarak tüm dosyalar
Aşağıdaki gibi yapabiliriz.
CPPFLAGS := -MMD -MP
CXXFLAGS := -Wall -Werror -std=c++11 -pedantic -Wvla -g
SOURCES  := $(wildcard *.cpp)

main: $(SOURCES:.cpp=.o)

-include $(SOURCES:.cpp=.d)
Eğer eski svn'i kullanıyorsak bazı dosyaları dışarıda bırakmak için şöyle yaparız.

SRC_ROOT := ./src
SRC_FILES := $(notdir $(shell find $(SRC_ROOT) -path "*/.svn" -prune -o -type f -name "*.cpp" -print))

target için dependency
Eğer target'ımızın dependency olarak gördüğü bir başka target, makefile içinde ve diskte yoksa aşağıdaki gibi bir hata alırız. Hatalı durumlarda komut satırına Stop. yazılır.
make: *** No rule to make target `b', needed by `a'.  Stop.

Eğer target'ımız bir önceki make komutundan sonra değişmemiş ise, aşağıdaki Nothing to be done ile başlayan cümleyi alırız.
make: Nothing to be done for `all'.

target için komut
Target için örnek command
fileClient:
    $(CC) $(CFLAGS) $(LDFLAGS) src/main.c -o fileClient

default target
Default target makefile içindeki ilk tanımlı target'tır. makefile target ismi verilmeden çağırılırsa default target çalışır.

.ignore
Eğer harici komut 0'dan farklı bir değer ile çıkarsa make komutu çalışmayı bırakır. Harici komutun döndürdüğü değer dikkate almamak için ignore kullanılır. Örnek:
  1. # Both these command exit non-0 when any violations occur
  2. # We want to ignore that so we can get all the results in jenkins
  3. .IGNORE: check-style-ci check-cpd-ci


.phony target
phony kelime anlamı olarak sahte demek. .phony genellikle harici bir komutu çalıştrmak için kullanılır. target'ımız ile aynı isimde bir başka dosya olsa bile, komutumuz çalışır. Örnek''te gösterildiği gibi, "make clean" yapılırsa clean isimli bir dosya olsa bile harici clean komutu çalışır.
.phony : clean
clean :
         rm -rf *.o
Bir başka örnek'te check-style komutu çalıştırılıyor

.PHONY: check-style
  1. check-style:
  2.     phpcs --standard=CakePHP --extensions=php,ctp -p ./


değişken tanımlama ve ekleme örneği
Makefile içinde anladığım kadarıyla iki çeşit değişken var. İlki değişken := değer şeklinde tanımlanıyor ve değişkenin değeri, makefile ilk defa okunurken bir kereliğine hesaplanıyor. Diğeri ise macro gibi ve değişken = değer şeklinde tanımlanıyor. Bu tür ise değişkenin geçtiği her yere değerinin yapıştırılması gibi düşünülebilir.

Değeri Hemen Hesaplanan Değişken
Örnekler:

LDDIRS := -L$(ORACLE_LIB)
LDDIRS += -L$(ORACLE_LIB)

Değeri hemen hesaplanan değişken shell komutu çalıştırmak için de kullanılabilir. Örnekte make çalışırken ne olursa olsun obj isimli bir dizin yaratmak gösteriliyor.
_dummy := $(shell mkdir -p obj)

Macro Değişken

Makefile işlenirken $(Değişken İsmi) şeklinde metinler aynı C'deki #define ile tanımlanan macro gibi metin açılımına uğrarlar. Yani değişken ismi yerine değişkenin değeri varmış gibi işlem yapılır.

Değişkenin Değerine Erişmek
$(Değişken İsmi) şeklindeki kullanımda değişkenin değerine erişilir.

Bir başka dosyadaki değişkenleri dahil etmek
Aşağıdaki gibi yapılabilir.
include $(DIR)/make/Makefile.vars

if koşulu

ifeq($(Variable),0)
  DIRECTORY := ./debug
else
  DIRECTORY := ./release
endif


Include Path Tanımlama
INCLUDES := -I../../include\
                         -I../../src
şeklinde çok satıra tanımlanabilir

Make İçindeki Komutlar
başka make dosyasının çağırılması
Genelde tüm projeleri derleyen en üstte bir make dosyası bulunur. Tepedeki make dosyasından başka make dosyalarını çağırmak için make -C komutu kullanılabilir. Kendi değişkenimizi, diğer make dosyasına da aşağıdaki gibi geçebiliriz.
Örnek:
subsystem:
         $(MAKE) -C subdir CPU=$(CPU)
cp
all :
 $(CP) ./debug/*.exe $(OUTPUT)

mkdir
Eğer bir dizin yoksa yaratmak için kullanılır
if [! -d "$(DIR)"]; then mkdir -p "$(DIR)";fi

notdir
SRC_FILES := $(notdir $(foreach dir; $(DIRS), $(wildcard $(DIR)/*.c $(DIR)/*.cpp) ) )

rm
clean :
     $(RM) $(OUTPUT)

subst
Windows dizinini, Unix dizinine çevirir
HOME := $(subst \,/, $(HOME))
make ve shell
$(shell command) şeklinde yazılan komutlar bir kabukta çalıştırılır ve çıktısı bir değişkene atanabilir. Eğer komutun çıktısına ihtiyaç yoksa $(shell ...) şeklinde çağırmaya da ihtiyaç yoktur. Örnek:
USERNAME := $(shell whoami)
Bir başka örnekte dostanın için bir değişkene alınıyor.
CONTENTS := $(shell cat foo)

bazı komut örnekleri
mkdir
Örnekte obj isimli dizin yaratma gösterilmiş
mkdir -p obj
find
Örnek:
HEADER = $(shell find . -name '*.h')

make clean
Bu komutla make'in yarattığı her şey temizlenir.

make distclean
Bu komutla make dosyası dahil ./configure ile yaratılan her şey silinir.

make install
Bir uygulamayı derler ve kurar.
./configure
make
sudo make install

make file çıktısı
make komutu errror ve warningleri stderr akımına veriyor. warning ve error'ları görmek için aşağıdaki gibi yapılabilir
make 2> out.txt

stderr da stdout'a yönlendirmek ve çıktı içinde hata aramayı kolaylaştırmak için aşağıdaki komut kullanılabilir.

make 2>@1 | grep warning -A 2 -B 2

-A 2 -B 2 seçenekleri warning içeren satırın 2 üst (above) ve 2 alt (below) satırını da gösterir ki hatayı daha rahat görebilelim.

1 yorum: