संकलित करने के लिए चाहते हैं यहाँ Makefile मैं प्रलेखन के लिए जोड़ा गया है (फिलहाल समीक्षा में तो मैं इसे यहाँ पोस्ट करेंगे):
# Set project directory one level above the Makefile directory. $(CURDIR) is a GNU make variable containing the path to the current working directory
PROJDIR := $(realpath $(CURDIR)/..)
SOURCEDIR := $(PROJDIR)/Sources
BUILDDIR := $(PROJDIR)/Build
# Name of the final executable
TARGET = myApp.exe
# Decide whether the commands will be shown or not
VERBOSE = TRUE
# Create the list of directories
DIRS = Folder0 Folder1 Folder2
SOURCEDIRS = $(foreach dir, $(DIRS), $(addprefix $(SOURCEDIR)/, $(dir)))
TARGETDIRS = $(foreach dir, $(DIRS), $(addprefix $(BUILDDIR)/, $(dir)))
# Generate the GCC includes parameters by adding -I before each source folder
INCLUDES = $(foreach dir, $(SOURCEDIRS), $(addprefix -I, $(dir)))
# Add this list to VPATH, the place make will look for the source files
VPATH = $(SOURCEDIRS)
# Create a list of *.c sources in DIRS
SOURCES = $(foreach dir,$(SOURCEDIRS),$(wildcard $(dir)/*.c))
# Define objects for all sources
OBJS := $(subst $(SOURCEDIR),$(BUILDDIR),$(SOURCES:.c=.o))
# Define dependencies files for all objects
DEPS = $(OBJS:.o=.d)
# Name the compiler
CC = gcc
# OS specific part
ifeq ($(OS),Windows_NT)
RM = del /F /Q
RMDIR = -RMDIR /S /Q
MKDIR = -mkdir
ERRIGNORE = 2>NUL || true
SEP=\\
else
RM = rm -rf
RMDIR = rm -rf
MKDIR = mkdir -p
ERRIGNORE = 2>/dev/null
SEP=/
endif
# Remove space after separator
PSEP = $(strip $(SEP))
# Hide or not the calls depending of VERBOSE
ifeq ($(VERBOSE),TRUE)
HIDE =
else
HIDE = @
endif
# Define the function that will generate each rule
define generateRules
$(1)/%.o: %.c
@echo Building [email protected]
$(HIDE)$(CC) -c $$(INCLUDES) -o $$(subst /,$$(PSEP),[email protected]) $$(subst /,$$(PSEP),$$<) -MMD
endef
# Indicate to make which targets are not files
.PHONY: all clean directories
all: directories $(TARGET)
$(TARGET): $(OBJS)
$(HIDE)echo Linking [email protected]
$(HIDE)$(CC) $(OBJS) -o $(TARGET)
# Include dependencies
-include $(DEPS)
# Generate rules
$(foreach targetdir, $(TARGETDIRS), $(eval $(call generateRules, $(targetdir))))
directories:
$(HIDE)$(MKDIR) $(subst /,$(PSEP),$(TARGETDIRS)) $(ERRIGNORE)
# Remove all objects, dependencies and executable files generated during the build
clean:
$(HIDE)$(RMDIR) $(subst /,$(PSEP),$(TARGETDIRS)) $(ERRIGNORE)
$(HIDE)$(RM) $(TARGET) $(ERRIGNORE)
@echo Cleaning done !
मुख्य विशेषताएं
निर्दिष्ट फ़ोल्डरों
- वस्तु और निर्भरता फ़ाइलों के लिए एकाधिक स्रोत फ़ोल्डर्स
- एकाधिक इसी लक्ष्य फ़ोल्डर में
C
सूत्रों के
- स्वत: पता लगाने
- प्रत्येक लक्ष्य फ़ोल्डर के लिए स्वचालित नियम पीढ़ी
- लक्ष्य फ़ोल्डर्स का निर्माण जब वे मौजूद नहीं हैं
gcc
साथ निर्भरता प्रबंधन: निर्माण केवल क्या आवश्यक है Unix
पर
- काम करता है और
DOS
सिस्टम
GNU Make
के लिए लिखित इस Makefile का उपयोग कैसे करें
अनुकूलन करने के लिए यह मेकफ़ाइल आपकी प्रोजेक्ट में है:
- बदलें
TARGET
चर अपने लक्ष्य नाम
- बदलें
SOURCEDIR
में Sources
और Build
फ़ोल्डरों के नाम से मेल और BUILDDIR
- बदलें Makefile खुद या मेकअप कॉल में में Makefile के शब्दाडंबर स्तर (
make all VERBOSE=FALSE
को)
- बदलें
DIRS
में फोल्डर, अपने स्रोतों से मेल खाते हैं और फ़ोल्डरों
- निर्माण यदि आवश्यक करने के लिए संकलक बदल सकते हैं और झंडे
के नाम
इस Makefile Folder0
, Folder1
और Folder2
में अपने FolderA
, FolderB
और FolderC
के बराबर हैं।
ध्यान दें कि मुझे इस समय यूनिक्स सिस्टम पर परीक्षण करने का अवसर नहीं मिला है लेकिन यह विंडोज पर सही तरीके से काम करता है।कुछ मुश्किल भागों में से
स्पष्टीकरण:
विंडोज mkdir त्रुटियों की उपेक्षा कर
ERRIGNORE = 2>NUL || true
यह है दो प्रभाव: पहले एक , 2>NUL
त्रुटि उत्पादन पुनर्निर्देशित करना होता है एनयूएल के लिए, क्योंकि यह कंसोल में नहीं आता है।
दूसरा, || true
आदेश स्तर को बढ़ाने से कमांड को रोकता है। यह मेकफ़ाइल के साथ विंडोज़ सामग्री से संबंधित नहीं है, यह यहां है क्योंकि विंडोज़ 'mkdir
कमांड त्रुटि स्तर को बढ़ाता है अगर हम पहले से मौजूद फ़ोल्डर बनाने का प्रयास करते हैं, जबकि हम वास्तव में परवाह नहीं करते हैं, अगर यह ठीक है तो यह ठीक है। सामान्य समाधान if not exist
संरचना का उपयोग करना है, लेकिन यह यूनिक्स-संगत नहीं है, भले ही यह मुश्किल हो, मैं अपने समाधान को और अधिक स्पष्ट मानता हूं। OBJS की
निर्माण उनके सही पथ के साथ सभी वस्तु फ़ाइलें
OBJS := $(subst $(SOURCEDIR),$(BUILDDIR),$(SOURCES:.c=.o))
यहाँ हम OBJS उनके रास्ते के साथ सभी वस्तु फ़ाइलें हो चाहते हैं, और हम पहले से ही स्रोत है जिसमें सभी स्रोत पथ उनके पथ के साथ। $(SOURCES:.c=.o)
सभी स्रोतों के लिए * .o में * .c बदलता है, लेकिन पथ अभी भी स्रोतों में से एक है। $(subst $(SOURCEDIR),$(BUILDDIR), ...)
बस बिल्ड पथ के साथ पूरे स्रोत पथ को घटाएगा, इसलिए अंततः हमारे पास एक चर है जिसमें .o फाइलें उनके पथ हैं।
Windows और यूनिक्स शैली पथ विभाजक
SEP=\\
SEP =/
PSEP = $(strip $(SEP))
इस लेनदेन के साथ ही हर किसी स्लैश का उपयोग करता है, जबकि Makefile, यूनिक्स और विंडोज पर काम करने के बाद से विंडोज पथ के बैकस्लैश का उपयोग करता है अनुमति देने के लिए मौजूद हैं ।
SEP=\\
यहां बैकस्लैश चरित्र से बचने के लिए डबल बैकस्लैश का उपयोग किया जाता है, जो make
आमतौर पर एकाधिक लाइनों पर लेखन की अनुमति देने के लिए "न्यूलाइन चरित्र को अनदेखा" के रूप में मानता है।
PSEP = $(strip $(SEP))
यह SEP
चर के स्पेस char को हटा देगा, जो स्वचालित रूप से जोड़ा गया है। प्रत्येक लक्ष्य फ़ोल्डर
define generateRules
$(1)/%.o: %.c
@echo Building [email protected]
$(HIDE)$(CC) -c $$(INCLUDES) -o $$(subst /,$$(PSEP),[email protected]) $$(subst /,$$(PSEP),$$<) -MMD
endef
शायद चाल है कि सबसे अपने USECASE के साथ संबंधित है कि के लिए नियमों की
स्वचालित पीढ़ी। यह एक नियम टेम्पलेट है जिसे $(eval $(call generateRules, param))
से उत्पन्न किया जा सकता है जहां param
आप टेम्पलेट में $(1)
के रूप में पा सकते हैं। यह मूलतः प्रत्येक लक्ष्य फ़ोल्डर के लिए इस तरह के नियमों के साथ Makefile भरना होगा:
path/to/target/%.o: %.c
@echo Building [email protected]
$(HIDE)$(CC) -c $(INCLUDES) -o $(subst /,$(PSEP),[email protected]) $(subst /,$(PSEP),$<) -MMD
आप एक बहुत ही सरल मेकफ़ाइल मांग रहे हैं, इसलिए अगर कोई आपको यहां देता है तो मुझे आश्चर्य नहीं होगा। लेकिन आम तौर पर हम मुफ्त सहायता प्रदान करते हैं, मुफ्त कोड नहीं। – Beta
हाँ आप सही हैं। –
इस प्रकार का सरल मेकफ़ाइल वास्तव में नई प्रलेखन सुविधा के लिए एक अच्छा मैच होगा, लेकिन क्यू/ए के लिए यह थोड़ा सा व्यापक है। – Tim