Dapatkah saya mengkompilasi semua file .cpp di src / to .o di obj /, lalu menautkan ke biner di ./?

116

Direktori proyek saya terlihat seperti ini:

/project
    Makefile
    main
    /src
        main.cpp
        foo.cpp
        foo.h
        bar.cpp
        bar.h
    /obj
        main.o
        foo.o
        bar.o

Apa yang saya ingin makefile saya lakukan adalah mengkompilasi semua .cppfile di /srcfolder ke .ofile di /objfolder, lalu menautkan semua .ofile /objke dalam biner keluaran di folder tingkat atas /project.

Saya hampir tidak memiliki pengalaman dengan Makefiles, dan saya tidak begitu yakin apa yang harus dicari untuk mencapai ini.

Juga, apakah ini cara yang "baik" untuk melakukan ini, atau adakah pendekatan yang lebih standar untuk apa yang saya coba lakukan?

Austin Hyde
sumber
6
@aaa: Saya menduga OP menginginkan solusi yang tidak memerlukan daftar eksplisit setiap file sumber.
Cascabel
7
Saya tidak ingin menentukan setiap file sumber yang saya miliki, dan saya sudah mencoba membaca manual itu sebelumnya, tetapi saya merasa tidak teratur dan sulit untuk dipahami. Saya belajar jauh lebih baik dari contoh aktual yang melakukan apa yang saya harapkan dan dijelaskan dengan baik, daripada manual teknis kering.
Austin Hyde
baik. Tetapi membuat dokumentasi sangat baik dengan contoh-contoh yang baik (tidak mencoba manual teknis). Anda mencari aturan pola: gnu.org/software/make/manual/make.html#Pattern-Rules
Anycorn
11
Itu terlihat lebih seperti yang saya inginkan. Padahal, IMHO, manual make agak kering, karena tampaknya lebih ditargetkan untuk pengembang yang berada di level menengah dengan make, dan di luar itu sangat besar dan mendalam. Mungkin terlalu berlebihan.
Austin Hyde

Jawaban:

180

Makefile bagian dari pertanyaan

Ini cukup mudah, kecuali Anda tidak perlu menggeneralisasi, coba sesuatu seperti kode di bawah ini (tetapi ganti indentasi spasi dengan tab di dekat g ++)

SRC_DIR := .../src
OBJ_DIR := .../obj
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
LDFLAGS := ...
CPPFLAGS := ...
CXXFLAGS := ...

main.exe: $(OBJ_FILES)
   g++ $(LDFLAGS) -o $@ $^

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
   g++ $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<

Pembuatan grafik ketergantungan otomatis

Sebuah fitur "harus" untuk kebanyakan sistem make. Dengan GCC dapat dilakukan dalam sekali jalan sebagai efek samping dari kompilasi dengan menambahkan -MMDtanda ke CXXFLAGSdan -include $(OBJ_FILES:.o=.d) di akhir badan makefile:

CXXFLAGS += -MMD
-include $(OBJ_FILES:.o=.d)

Dan seperti yang telah disebutkan orang-orang, selalu ada GNU Make Manual , ini sangat membantu.

bobah
sumber
11
Ah, Anda mengalahkan saya beberapa detik. Tapi saya sarankan OBJ_FILES = $(patsubst src/%.cpp,obj/%.o,$(CPP_FILES)).
Beta
1
Saya harus mengubah ini agar berfungsi: $<harus $^untuk aturan main.exe dan saya pikir ada kesalahan ketik obj/%.o: src/%cpp.
1
@bobah Anda melewatkan '.' dalam aturan objek Anda untuk cpp
regomodo
1
variabel khusus mungkin perlu dijelaskan, karena mereka membuat file khusus dan sulit untuk dicari: gnu.org/software/make/manual/html_node/Automatic-Variables.html
Blake
2
Saya tahu ini adalah pertanyaan lama, tetapi saya memodifikasi sedikit sesuai dengan proyek saya, tetapi tidak berhasil. Ini makefile saya: pastebin.com/4CksG9Wc Saya dapatkan di konsol:make: *** No rule to make target '/main.o', needed by 'bin/main'. Pare.
Mateus Felipe
5

Wildcard juga berfungsi untuk saya, tetapi saya ingin memberikan catatan tambahan bagi mereka yang menggunakan variabel direktori. Selalu gunakan garis miring untuk pohon folder (bukan garis miring terbalik), jika tidak maka akan gagal:

BASEDIR = ../..
SRCDIR = $(BASEDIR)/src
INSTALLDIR = $(BASEDIR)/lib

MODULES = $(wildcard $(SRCDIR)/*.cpp)
OBJS = $(wildcard *.o)
xesf
sumber
maksudmu garis miring? Contoh Anda menunjukkan apa yang secara tradisional dianggap sebagai garis miring ke depan. Secara khusus, yang "condong ke kanan" dianggap "maju" dan yang kiri dianggap "kembali"
Evan Teran
Ya, Anda benar, maksud saya hanya "garis miring". Saya memperbarui posting.
xesf