اگه makefile پروژههای C++ رو با روشهای معمول بنویسیم، مجبوریم که مرتب با هر بار اضافه کردن یه فایل به پروژه makefile رو هم به روز رسانی کنیم. هر بار هم که وابستگی اون فایل تغییر میکنه ناچاریم این کار رو دوباره انجام بدیم. دنبال راه حل این مساله بودم که با سوییچهای خانواده M کامپایلر گنو آشنا شدم. این سوییچها به کامپایلر میگن که وابستگی یه برنامه رو به فرمت makefile بیرون بکشه. اگه این وابستگیها رو تو یه فایل ذخیره کنیم میتونیم بعدا با دستور include از اونها برای معرفی وابستگیها استفاده کنیم.
- سوییچ M این وابستگیها رو بیرون میکشه
- سوییچ MM مثل M اما فایلهایی که تو دایرکتوریهای سیستم هستن رو به عنوان وابستگی معرفی نمیکنه.
- سوییچ MF خروجی رو تو یه فایل میریزه
- سوییچ MT هم target مربوط به rule رو عوض میکنه. به طور پیشفرض قاعده تولید شده به اسم فایل ورودی منهای اسم و دایرکتوری و پسونده. در حالتی که بخوایم قاعدمون اسم دیگهای داشته باشه از این سوییچ استفاده میکنیم. مثلا اینجا اسم قاعدمون رو به اسم آبجکت فایل با دایرکتوریش تغییر دادم.
دیگه؟ با اون .PHONY هم به make میگم که قاعدههایی که بعدش اومده اسم فایل نیست.
این هم makefile ما:
SRCDIR = src OBJDIR = bin DEPDIR = bin BINDIR = bin CXX = g++ CXXFLAGS = -O3 -std=c++11 LDFLAGS = TARGET = $(BINDIR)/yourappname SRCS = $(wildcard $(SRCDIR)/*.cpp) OBJS = $(patsubst $(SRCDIR)/%.cpp,$(OBJDIR)/%.o,$(SRCS)) DEPS = $(patsubst $(SRCDIR)/%.cpp,$(DEPDIR)/%.depends,$(SRCS)) .PHONY: all clean run all: $(TARGET) @echo Done. $(TARGET): $(OBJS) @echo Linking $@ @mkdir -p $(BINDIR) @mkdir -p $(OUTDIR) @$(CXX) $(CXXFLAGS) $(OBJS) $(LDFLAGS) -o $(TARGET) $(OBJDIR)/%.o: $(SRCDIR)/%.cpp @echo Compiling $< @mkdir -p $(OBJDIR) @$(CXX) $(CXXFLAGS) -c $< -o $@ $(DEPDIR)/%.depends: $(SRCDIR)/%.cpp @echo Generating dependencies $< @mkdir -p $(DEPDIR) @$(CXX) -MM $(CXXFLAGS) $< -MT $(patsubst $(SRCDIR)/%.cpp,$(OBJDIR)/%.o,$<) -MF $@ clean: @rm -f $(OBJS) $(DEPS) $(TARGET) run: all $(TARGET) -include $(DEPS)