ฉันสามารถรวบรวมไฟล์. cpp ทั้งหมดใน src / ถึง. ของใน obj / แล้วเชื่อมโยงไปยังไบนารีใน. / ได้หรือไม่


116

ไดเรกทอรีโครงการของฉันมีลักษณะดังนี้:

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

สิ่งที่ฉันต้องการ Makefile ของฉันจะทำจะรวบรวมทุก.cppไฟล์ใน/srcโฟลเดอร์.oไฟล์ใน/objโฟลเดอร์แล้วเชื่อมโยงทุก.oไฟล์ในเข้าไปในไบนารีการส่งออกในโฟลเดอร์ระดับบนสุด/obj/project

ฉันไม่มีประสบการณ์กับ Makefiles เลยและฉันไม่แน่ใจจริงๆว่าจะค้นหาอะไรเพื่อให้บรรลุเป้าหมายนี้

นอกจากนี้นี่เป็นวิธีที่ "ดี" ในการทำเช่นนี้หรือมีแนวทางที่เป็นมาตรฐานมากกว่าสำหรับสิ่งที่ฉันกำลังพยายามทำอยู่หรือไม่



6
@aaa: ฉันเดาว่า OP ต้องการโซลูชันที่ไม่ต้องการการแสดงรายการไฟล์ต้นฉบับอย่างชัดเจน
Cascabel

7
ฉันไม่ต้องการระบุไฟล์ต้นฉบับแต่ละไฟล์ที่ฉันมีและฉันได้พยายามอ่านคู่มือนั้นมาก่อน แต่ฉันพบว่ามันไม่เป็นระเบียบและเข้าใจยาก ฉันเรียนรู้ได้ดีขึ้นมากจากตัวอย่างจริงที่ทำในสิ่งที่ฉันคาดหวังและอธิบายได้ดีแทนที่จะเป็นคู่มือทางเทคนิคแบบแห้ง
Austin Hyde

ตกลง. แต่การจัดทำเอกสารเป็นเรื่องที่ยอดเยี่ยมพร้อมตัวอย่างที่ดี (อย่าลองใช้คู่มือทางเทคนิค) คุณกำลังมองหาก
Anycorn

11
นั่นดูเหมือนสิ่งที่ฉันต้องการมากกว่าเล็กน้อย แม้ว่า IMHO คู่มือ make จะค่อนข้างแห้งเนื่องจากดูเหมือนว่าจะมีเป้าหมายมากกว่าสำหรับนักพัฒนาซอฟต์แวร์ที่อยู่ในระดับกลางด้วย make และยิ่งไปกว่านั้นก็มีขนาดใหญ่และเชิงลึกมาก บางทีอาจจะมากเกินไป
Austin Hyde

คำตอบ:


180

Makefile เป็นส่วนหนึ่งของคำถาม

นี่เป็นเรื่องง่ายมากเว้นแต่คุณไม่จำเป็นต้องสรุปให้ลองทำเช่นโค้ดด้านล่าง (แต่แทนที่การเยื้องช่องว่างด้วยแท็บใกล้ 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 $@ $<

การสร้างกราฟการพึ่งพาอัตโนมัติ

คุณลักษณะ "ต้อง" สำหรับระบบการสร้างส่วนใหญ่ ด้วย GCC ในสามารถทำได้ในครั้งเดียวเป็นผลข้างเคียงของการรวบรวมโดยการเพิ่ม-MMDแฟล็กลงในCXXFLAGSและ -include $(OBJ_FILES:.o=.d) ต่อท้ายเนื้อหา makefile

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

และตามที่กล่าวมาแล้วให้มีGNU Make Manualอยู่เสมอมันจะมีประโยชน์มาก


11
คุณเอาชนะฉันทีละวินาที OBJ_FILES = $(patsubst src/%.cpp,obj/%.o,$(CPP_FILES))แต่ผมขอแนะนำให้
เบต้า

1
ฉันต้องเปลี่ยนสิ่งนี้เพื่อให้ใช้งานได้: $<ควรเป็น$^กฎของ main.exe และฉันคิดว่ามีการพิมพ์ผิดด้วยobj/%.o: src/%cpp.

1
@bobah คุณไม่มี "." ในวัตถุของคุณกฎสำหรับ cpp
regomodo

1
ตัวแปรพิเศษน่าจะอธิบายได้เนื่องจากเป็น makefile ที่เฉพาะเจาะจงและค้นหายาก: gnu.org/software/make/manual/html_node/Automatic-Variables.html
Blake

2
ฉันรู้ว่านี่เป็นคำถามเก่า แต่ฉันแก้ไขเล็กน้อยตามโครงการของฉัน แต่ไม่ได้ผล นี่คือ makefile ของฉัน: pastebin.com/4CksG9Wc ฉันเข้าคอนโซล:make: *** No rule to make target '/main.o', needed by 'bin/main'. Pare.
Mateus Felipe

5

สัญลักษณ์แทนก็ใช้ได้สำหรับฉันเช่นกัน แต่ฉันต้องการให้ข้อสังเกตสำหรับผู้ที่ใช้ตัวแปรไดเร็กทอรี ใช้เครื่องหมายทับสำหรับแผนผังโฟลเดอร์เสมอ (ไม่ใช่แบ็กสแลช) มิฉะนั้นจะล้มเหลว:

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

MODULES = $(wildcard $(SRCDIR)/*.cpp)
OBJS = $(wildcard *.o)

คุณหมายถึงเครื่องหมายทับหรือเปล่า ตัวอย่างของคุณแสดงสิ่งที่ถือเป็นเครื่องหมายทับไปข้างหน้า โดยเฉพาะคนที่ "เอนไปทางขวา" ถือเป็น "ไปข้างหน้า" และคนที่อยู่ทางซ้ายจะถือว่าเป็น "ถอยหลัง"
Evan Teran

ใช่คุณพูดถูกฉันหมายถึง "เฉือน" เท่านั้น ผมปรับปรุงโพสต์
xesf
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.