Tôi có thể biên dịch tất cả các tệp .cpp trong src / thành .o's trong obj /, sau đó liên kết đến tệp nhị phân trong ./ không?


116

Thư mục dự án của tôi trông như thế này:

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

Những gì tôi muốn makefile của mình làm là biên dịch tất cả .cppcác tệp trong /srcthư mục thành .ocác tệp trong /objthư mục, sau đó liên kết tất cả các .otệp trong tệp /objnhị phân đầu ra trong thư mục cấp cao nhất /project.

Tôi không có kinh nghiệm gì với Makefiles và không thực sự chắc chắn phải tìm kiếm những gì để thực hiện điều này.

Ngoài ra, đây có phải là một cách "tốt" để làm điều này hay là có một cách tiếp cận tiêu chuẩn hơn cho những gì tôi đang cố gắng làm?



6
@aaa: Tôi đoán OP muốn một giải pháp không yêu cầu liệt kê rõ ràng từng tệp nguồn.
Cascabel

7
Tôi không muốn chỉ định từng tệp nguồn mà tôi có, và tôi đã cố gắng đọc hướng dẫn đó trước đây, nhưng tôi thấy nó vô tổ chức và khó hiểu. Tôi học tốt hơn nhiều từ một ví dụ thực tế làm được những gì tôi mong đợi và được giải thích rõ ràng, thay vì các hướng dẫn kỹ thuật khô khan.
Austin Hyde

Được chứ. Nhưng làm cho tài liệu là tuyệt vời với các ví dụ tốt (nó không phải là thử hướng dẫn kỹ thuật). bạn đang tìm kiếm các quy tắc mẫu: gnu.org/software/make/manual/make.html#Pattern-Rules
Anycorn

11
Điều đó trông giống với những gì tôi muốn hơn một chút. Mặc dù, IMHO, sách hướng dẫn tạo ra hơi khô khan, vì nó có vẻ nhắm mục tiêu nhiều hơn đến các nhà phát triển ở trình độ trung cấp với chế tạo, và xa hơn nữa là sách hướng dẫn rất rộng và chuyên sâu. Có lẽ quá nhiều như vậy.
Austin Hyde

Câu trả lời:


180

Makefile một phần của câu hỏi

Điều này khá dễ dàng, trừ khi bạn không cần phải tổng quát, hãy thử một cái gì đó như mã bên dưới (nhưng thay thế thụt lề khoảng cách bằng các tab gần 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 $@ $<

Tạo đồ thị phụ thuộc tự động

Một tính năng "phải" cho hầu hết các hệ thống tạo. Với GCC in có thể được thực hiện trong một lần chuyển như là một tác dụng phụ của quá trình biên dịch bằng cách thêm -MMDcờ vào CXXFLAGS -include $(OBJ_FILES:.o=.d) vào cuối thân makefile:

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

Và như những người đã đề cập, hãy luôn có GNU Make Manual bên cạnh, nó rất hữu ích.


11
Ah, bạn đã đánh bại tôi trong vài giây. Nhưng tôi đề nghị OBJ_FILES = $(patsubst src/%.cpp,obj/%.o,$(CPP_FILES)).
Beta

1
Tôi đã phải thay đổi điều này để nó hoạt động: $<phải $^dành cho quy tắc của main.exe và tôi nghĩ rằng có lỗi đánh máy với obj/%.o: src/%cpp.

1
@bobah Bạn đang thiếu dấu '.' trong đối tượng của bạn cai trị cho cpp
regomodo

1
các biến đặc biệt có lẽ đáng để giải thích, vì chúng tạo nên tệp
Blake

2
Tôi biết đây là một câu hỏi cũ, nhưng tôi đã sửa đổi một chút theo dự án của mình, nhưng nó không hoạt động. Đây là tệp makefile của tôi: pastebin.com/4CksG9Wc Tôi nhận được trong bảng điều khiển:make: *** No rule to make target '/main.o', needed by 'bin/main'. Pare.
Mateus Felipe

5

Ký tự đại diện cũng hoạt động đối với tôi, nhưng tôi muốn đưa ra một lưu ý phụ cho những người sử dụng biến thư mục. Luôn sử dụng dấu gạch chéo cho cây thư mục (không phải dấu gạch chéo ngược), nếu không nó sẽ không thành công:

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

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

ý của bạn là dấu gạch chéo? Ví dụ của bạn cho thấy những gì theo truyền thống được coi là dấu gạch chéo. Cụ thể, những người "nghiêng về bên phải" được coi là "tiến lên" và những người bên trái được coi là "quay lại"
Evan Teran

Vâng, bạn nói đúng, ý tôi là "chém" thôi. Tôi đã cập nhật bài viết.
xesf
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.