Beberapa bulan yang lalu, saya datang dengan generik berikut Makefile
untuk tugas sekolah:
# ------------------------------------------------
# Generic Makefile
#
# Author: [email protected]
# Date : 2010-11-05
#
# Changelog :
# 0.01 - first version
# ------------------------------------------------
# project name (generate executable with this name)
TARGET = projectname
CC = gcc -std=c99 -c
# compiling flags here
CFLAGS = -Wall -I.
LINKER = gcc -o
# linking flags here
LFLAGS = -Wall
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:.c=*.o)
rm = rm -f
$(TARGET): obj
@$(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
@echo "Linking complete!"
obj: $(SOURCES) $(INCLUDES)
@$(CC) $(CFLAGS) $(SOURCES)
@echo "Compilation complete!"
clean:
@$(rm) $(TARGET) $(OBJECTS)
@echo "Cleanup complete!"
Ini pada dasarnya akan mengkompilasi setiap .c
dan .h
file untuk menghasilkan .o
file dan projectname
semua yang dapat dieksekusi dalam folder yang sama.
Sekarang, saya ingin mendorongnya sedikit. Bagaimana cara menulis Makefile untuk mengkompilasi proyek C dengan struktur direktori berikut?
./
./Makefile
./src/*.c;*.h
./obj/*.o
./bin/<executable>
Dengan kata lain, saya ingin memiliki Makefile yang mengkompilasi sumber C dari ./src/
ke ./obj/
dan kemudian menautkan semuanya untuk membuat file yang dapat dieksekusi ./bin/
.
Saya telah mencoba membaca Makefile yang berbeda, tetapi saya tidak dapat membuatnya berfungsi untuk struktur proyek di atas; sebaliknya, proyek gagal untuk dikompilasi dengan segala macam kesalahan. Tentu, saya bisa menggunakan IDE yang lengkap (Monodevelop, Anjuta, dll.), Tetapi sejujurnya saya lebih suka menggunakan gEdit dan terminal lama yang bagus.
Apakah ada guru yang bisa memberi saya solusi yang berfungsi, atau informasi yang jelas tentang bagaimana ini bisa dilakukan? Terima kasih!
** PERBARUI (v4) **
Solusi terakhir:
# ------------------------------------------------
# Generic Makefile
#
# Author: [email protected]
# Date : 2011-08-10
#
# Changelog :
# 2010-11-05 - first version
# 2011-08-10 - added structure : sources, objects, binaries
# thanks to http://stackoverflow.com/users/128940/beta
# 2017-04-24 - changed order of linker params
# ------------------------------------------------
# project name (generate executable with this name)
TARGET = projectname
CC = gcc
# compiling flags here
CFLAGS = -std=c99 -Wall -I.
LINKER = gcc
# linking flags here
LFLAGS = -Wall -I. -lm
# change these to proper directories where each file should be
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SOURCES := $(wildcard $(SRCDIR)/*.c)
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET): $(OBJECTS)
@$(LINKER) $(OBJECTS) $(LFLAGS) -o $@
@echo "Linking complete!"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
@$(CC) $(CFLAGS) -c $< -o $@
@echo "Compiled "$<" successfully!"
.PHONY: clean
clean:
@$(rm) $(OBJECTS)
@echo "Cleanup complete!"
.PHONY: remove
remove: clean
@$(rm) $(BINDIR)/$(TARGET)
@echo "Executable removed!"
Makefile
. Saya semakin dekat, tetapi saya mengalami masalah dengan variabel otomatis, jadi sepertinyaJawaban:
Pertama,
$(OBJECTS)
aturan Anda bermasalah, karena:file1.o
danfile2.o
)foo.o
) bukanlah yang sebenarnya akan dihasilkan oleh aturan (obj/foo.o
).Saya menyarankan yang berikut:
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o) $(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c $(CC) $(CFLAGS) -c $< -o $@ @echo "Compiled "$<" successfully!"
The
$(TARGET)
aturan memiliki masalah yang sama bahwa nama target tidak benar-benar menggambarkan apa aturan membangun. Oleh karena itu, jika Anda mengetikmake
beberapa kali, Make akan membangun kembali target setiap kali, meskipun tidak ada alasan untuk itu. Perubahan kecil memperbaiki bahwa:$(BINDIR)/$(TARGET): $(OBJECTS) $(LINKER) $@ $(LFLAGS) $(OBJECTS) @echo "Linking complete!"
Setelah semuanya beres, Anda mungkin mempertimbangkan penanganan ketergantungan yang lebih canggih; jika Anda memodifikasi salah satu file header, makefile ini tidak akan tahu objek / executable mana yang harus dibangun kembali. Tapi itu bisa menunggu hari lain.
EDIT:
Maaf, saya menghilangkan bagian dari
$(OBJECTS)
aturan di atas; Saya sudah memperbaikinya. (Saya harap saya dapat menggunakan "teguran" di dalam sampel kode.)sumber
obj/file1.o: In function 'main': \n main.c:(.text+0x0): multiple definition of 'main' \n obj/main.o:main.c:(.text+0x0): first defined here
main
fungsi? Mungkin satu masukfile1.c
dan satu masukmain.c
? Jika demikian, Anda tidak akan dapat menghubungkan objek-objek ini; hanya ada satumain
file yang dapat dieksekusi.file1.c
tetapi memberikan pesan yang sama ke setiap file proyek. Danmain.c
adalah satu - satunya dengan fungsi utama ... danmain.c
imporfile1.h
danfile2.h
(tidak ada hubungan antarafile1.c
danfile2.c
), tapi saya ragu masalahnya berasal dari sana.$(OBJECTS)
aturan saya ; Saya sudah mengeditnya. Dengan garis buruk saya mendapat kesalahan, tapi bukan yang Anda dapatkan ...Anda bisa menambahkan
-I
tanda ke tanda kompilator (CFLAGS) untuk menunjukkan di mana kompilator harus mencari file sumber, dan tanda -o untuk menunjukkan di mana biner harus ditinggalkan:CFLAGS = -Wall -I./src TARGETPATH = ./bin $(TARGET): obj @$(LINKER) $(TARGETPATH)/$(TARGET) $(LFLAGS) $(OBJECTS) @echo "Linking complete!"
Untuk meletakkan file objek ke dalam
obj
direktori, gunakan-o
opsi saat kompilasi. Juga, lihat variabel$@
dan$<
otomatis .Misalnya, pertimbangkan Makefile sederhana ini
Perbarui>
Dengan melihat makefile Anda, saya menyadari Anda menggunakan
-o
bendera. Baik. Lanjutkan menggunakannya, tetapi tambahkan variabel direktori target untuk menunjukkan di mana file keluaran harus ditulis.sumber
-l ...
keCFLAGS
dan ... sudah ada-o
argumen ke linker (LINKER
)make
, dari tempat Makefile dudukSaya telah berhenti menulis makefile akhir-akhir ini, jika niat Anda untuk belajar, silakan, jika tidak, Anda memiliki generator makefile yang bagus yang dilengkapi dengan CDT eclipse. Jika Anda menginginkan pemeliharaan / beberapa dukungan proyek dalam pohon build Anda, lihat yang berikut ini -
https://github.com/dmoulding/boilermake Menurut saya ini cukup bagus ..!
sumber