Karena ini untuk Unix, executable tidak memiliki ekstensi.
Satu hal yang perlu diperhatikan adalah root-config
utilitas yang menyediakan kompilasi yang tepat dan menghubungkan bendera; dan pustaka yang tepat untuk membangun aplikasi terhadap root. Itu hanya detail yang terkait dengan audiens asli untuk dokumen ini.
Make Me Baby
atau Anda Tidak Pernah Lupa Saat Pertama Kali Dibuat
Diskusi pengantar make, dan cara menulis makefile sederhana
Apa itu Make? Dan Mengapa Saya Harus Peduli?
Alat yang disebut Make adalah pengelola dependensi build. Yaitu, perlu mengetahui perintah apa yang harus dijalankan dalam rangka untuk mengambil proyek perangkat lunak Anda dari kumpulan file sumber, file objek, perpustakaan, header, dll, dll .- beberapa di antaranya mungkin telah berubah baru-baru ini --- dan mengubahnya menjadi versi program yang benar dan terkini.
Sebenarnya, Anda dapat menggunakan Make untuk hal-hal lain juga, tetapi saya tidak akan membicarakan hal itu.
Makefile yang Sepele
Misalkan Anda memiliki direktori yang berisi:, tool
tool.cc
tool.o
support.cc
support.hh
dan support.o
yang bergantung pada root
dan seharusnya dikompilasi ke dalam program yang disebut tool
, dan anggap bahwa Anda telah meretas file sumber (yang berarti yang ada tool
sekarang sudah ketinggalan zaman) dan ingin kompilasi program.
Untuk melakukan ini sendiri, Anda bisa
Periksa apakah salah satu support.cc
atau support.hh
lebih baru dari support.o
, dan jika demikian jalankan perintah suka
g++ -g -c -pthread -I/sw/include/root support.cc
Periksa apakah salah satu support.hh
atau tool.cc
lebih baru dari tool.o
, dan jika demikian jalankan perintah suka
g++ -g -c -pthread -I/sw/include/root tool.cc
Periksa apakah tool.o
lebih baru dari tool
, dan jika demikian jalankan perintah seperti
g++ -g tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
-Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl
Fiuh! Sungguh merepotkan! Ada banyak yang harus diingat dan beberapa peluang untuk melakukan kesalahan. (BTW-- rincian baris perintah yang ditampilkan di sini tergantung pada lingkungan perangkat lunak kami. Yang ini berfungsi di komputer saya.)
Tentu saja, Anda bisa menjalankan ketiga perintah setiap waktu. Itu akan berhasil, tetapi itu tidak skala baik ke bagian besar perangkat lunak (seperti DOGS yang membutuhkan lebih dari 15 menit untuk dikompilasi dari bawah ke atas di MacBook saya).
Alih-alih, Anda dapat menulis file bernama makefile
seperti ini:
tool: tool.o support.o
g++ -g -o tool tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
-Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl
tool.o: tool.cc support.hh
g++ -g -c -pthread -I/sw/include/root tool.cc
support.o: support.hh support.cc
g++ -g -c -pthread -I/sw/include/root support.cc
dan cukup ketik make
di baris perintah. Yang akan melakukan tiga langkah yang ditunjukkan di atas secara otomatis.
Baris yang tidak diindentifikasi di sini memiliki bentuk "target: dependencies" dan beri tahu Make bahwa perintah yang terkait (indents lines) harus dijalankan jika ada dependensi yang lebih baru daripada target. Yaitu, garis ketergantungan menggambarkan logika apa yang perlu dibangun kembali untuk mengakomodasi perubahan dalam berbagai file. Jika support.cc
perubahan itu berarti support.o
harus dibangun kembali, tetapi tool.o
dapat dibiarkan sendiri. Kapan support.o
perubahan tool
harus dibangun kembali.
Perintah-perintah yang terkait dengan setiap baris dependensi dimatikan dengan sebuah tab (lihat di bawah) harus memodifikasi target (atau setidaknya menyentuhnya untuk memperbarui waktu modifikasi).
Variabel, Aturan yang Terpasang, dan Barang Lainnya
Pada titik ini, makefile kami hanya mengingat pekerjaan yang perlu dilakukan, tetapi kami masih harus mencari tahu dan mengetik setiap perintah yang diperlukan secara keseluruhan. Tidak harus seperti itu: Make adalah bahasa yang kuat dengan variabel, fungsi manipulasi teks, dan banyak aturan bawaan yang bisa membuat ini lebih mudah bagi kita.
Buat Variabel
Sintaks untuk mengakses variabel make adalah $(VAR)
.
Sintaks untuk menetapkan ke variabel Make adalah: VAR = A text value of some kind
(atau VAR := A different text value but ignore this for the moment
).
Anda dapat menggunakan variabel dalam aturan seperti versi perbaikan dari makefile kami:
CPPFLAGS=-g -pthread -I/sw/include/root
LDFLAGS=-g
LDLIBS=-L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz \
-Wl,-framework,CoreServices -Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root \
-lm -ldl
tool: tool.o support.o
g++ $(LDFLAGS) -o tool tool.o support.o $(LDLIBS)
tool.o: tool.cc support.hh
g++ $(CPPFLAGS) -c tool.cc
support.o: support.hh support.cc
g++ $(CPPFLAGS) -c support.cc
yang sedikit lebih mudah dibaca, tetapi masih membutuhkan banyak pengetikan
Buat Fungsi
GNU make mendukung berbagai fungsi untuk mengakses informasi dari sistem file atau perintah lain pada sistem. Dalam hal ini kami tertarik untuk $(shell ...)
memperluas ke output dari argumen, dan $(subst opat,npat,text)
yang menggantikan semua contoh opat
dengan npat
dalam teks.
Mengambil keuntungan dari ini memberi kita:
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
tool: $(OBJS)
g++ $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
tool.o: tool.cc support.hh
g++ $(CPPFLAGS) -c tool.cc
support.o: support.hh support.cc
g++ $(CPPFLAGS) -c support.cc
yang lebih mudah diketik dan lebih mudah dibaca.
Perhatikan itu
- Kami masih menyatakan secara eksplisit dependensi untuk setiap file objek dan yang dapat dieksekusi akhir
- Kami harus secara eksplisit mengetik aturan kompilasi untuk kedua file sumber
Aturan Implisit dan Pola
Kami biasanya berharap bahwa semua file sumber C ++ harus diperlakukan dengan cara yang sama, dan Make menyediakan tiga cara untuk menyatakan ini:
- aturan suffix (dianggap usang dalam pembuatan GNU, tetapi disimpan untuk kompatibilitas mundur)
- aturan implisit
- aturan pola
Aturan implisit sudah ada, dan beberapa akan dibahas di bawah ini. Aturan pola ditentukan dalam bentuk seperti
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
yang berarti bahwa file objek dihasilkan dari file sumber C dengan menjalankan perintah yang ditunjukkan, di mana variabel "otomatis" $<
meluas ke nama dependensi pertama.
Aturan bawaan
Make memiliki seluruh aturan bawaan yang berarti bahwa seringkali, sebuah proyek dapat dikompilasi oleh makefile yang sangat sederhana.
GNU make built in rule untuk file sumber C adalah yang ditunjukkan di atas. Demikian pula kita membuat file objek dari file sumber C ++ dengan aturan seperti $(CXX) -c $(CPPFLAGS) $(CFLAGS)
.
File objek tunggal ditautkan menggunakan $(LD) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
, tetapi ini tidak akan berfungsi dalam kasus kami, karena kami ingin menautkan banyak file objek.
Variabel Digunakan Dengan Aturan Built-in
Aturan bawaan menggunakan seperangkat variabel standar yang memungkinkan Anda menentukan informasi lingkungan lokal (seperti tempat menemukan ROOT termasuk file) tanpa menulis ulang semua aturan. Yang paling mungkin menarik bagi kami adalah:
CC
- kompiler C untuk digunakan
CXX
- kompiler C ++ untuk digunakan
LD
- penghubung untuk digunakan
CFLAGS
- flag kompilasi untuk file sumber C
CXXFLAGS
- flag kompilasi untuk file sumber C ++
CPPFLAGS
- flag untuk c-preprocessor (biasanya menyertakan path file dan simbol yang didefinisikan pada baris perintah), digunakan oleh C dan C ++
LDFLAGS
- bendera tautan
LDLIBS
- perpustakaan untuk ditautkan
Makefile Dasar
Dengan memanfaatkan aturan bawaan kami dapat menyederhanakan makefile kami menjadi:
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
all: tool
tool: $(OBJS)
$(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
tool.o: tool.cc support.hh
support.o: support.hh support.cc
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) tool
Kami juga telah menambahkan beberapa target standar yang melakukan tindakan khusus (seperti membersihkan direktori sumber).
Perhatikan bahwa ketika make dipanggil tanpa argumen, ia menggunakan target pertama yang ditemukan dalam file (dalam hal ini semua), tetapi Anda juga dapat memberi nama target untuk mendapatkan apa yang membuat make clean
menghapus file objek dalam kasus ini.
Kami masih memiliki semua dependensi yang dikodekan.
Beberapa Perbaikan Misterius
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
all: tool
tool: $(OBJS)
$(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
depend: .depend
.depend: $(SRCS)
$(RM) ./.depend
$(CXX) $(CPPFLAGS) -MM $^>>./.depend;
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) *~ .depend
include .depend
Perhatikan itu
- Tidak ada lagi garis ketergantungan untuk file sumber!?!
- Ada beberapa sihir aneh yang terkait dengan .depend dan depend
- Jika Anda melakukannya
make
maka ls -A
Anda melihat file bernama .depend
yang berisi hal-hal yang terlihat seperti membuat garis ketergantungan
Bacaan Lainnya
Tahu Bug dan Catatan Sejarah
Bahasa input untuk Make adalah spasi putih. Secara khusus, garis tindakan dependensi harus dimulai dengan tab . Tetapi serangkaian ruang bisa terlihat sama (dan memang ada editor yang akan secara diam-diam mengubah tab menjadi spasi atau sebaliknya), yang menghasilkan file Make yang terlihat benar dan masih tidak berfungsi. Ini diidentifikasi sebagai bug sejak awal, tetapi ( ceritanya ) itu tidak diperbaiki, karena sudah ada 10 pengguna.
(Ini disalin dari pos wiki yang saya tulis untuk mahasiswa pascasarjana fisika.)