আমি কীভাবে আমার মেকফিলটিকে ডিবাগ এবং রিলিজ বিল্ডগুলির জন্য কনফিগার করতে পারি?


175

আমার প্রকল্পের জন্য আমার কাছে নিম্নলিখিত মেকফিল রয়েছে এবং আমি এটি রিলিজ এবং ডিবাগ বিল্ডগুলির জন্য কনফিগার করতে চাই। আমার কোডে আমার কাছে প্রচুর #ifdef DEBUGম্যাক্রোগুলি রয়েছে, সুতরাং এটি কেবল এই ম্যাক্রোটি সেট করার এবং -g3 -gdwarf2সংযোজকগুলিতে পতাকাগুলি যুক্ত করার বিষয়। কিভাবে আমি এটি করতে পারব?

$(CC) = g++ -g3 -gdwarf2
$(cc) = gcc -g3 -gdwarf2

all: executable

executable: CommandParser.tab.o CommandParser.yy.o Command.o
    g++ -g -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl

CommandParser.yy.o: CommandParser.l 
    flex -o CommandParser.yy.c CommandParser.l
    gcc -g -c CommandParser.yy.c

CommandParser.tab.o: CommandParser.y
    bison -d CommandParser.y
    g++ -g -c CommandParser.tab.c

Command.o: Command.cpp
    g++ -g -c Command.cpp

clean:
    rm -f CommandParser.tab.* CommandParser.yy.* output *.o

কেবল স্পষ্ট করে বলার জন্য, যখন আমি বলি রিলিজ / ডিবাগ বিল্ডস, আমি মেকফিলে জিনিসগুলি ম্যানুয়ালি মন্তব্য না করে কেবল টাইপ করতে makeএবং একটি রিলিজ বিল্ড make debugপেতে এবং একটি ডিবাগ বিল্ড পেতে সক্ষম হতে চাই ।


12
মনোযোগ!
C

4
এক্সিকিউটেবল টার্গেট মেকফাইলেসের সুবর্ণ নিয়ম লঙ্ঘন করে: প্রতিটি লক্ষ্য আপনার ক্ষেত্রে "এক্সিকিউটেবল" ক্ষেত্রে টার্গেটের নামকরণ করা ফাইল আপডেট করে।
জেস্পের

3
। এবং যদি এটি না হয় তবে এটি ঘোষণা করা উচিত.PHONY
আন্ডারস্কোর_১৩

উত্তর:


192

আপনি লক্ষ্য-নির্দিষ্ট ভেরিয়েবল মানগুলি ব্যবহার করতে পারেন । উদাহরণ:

CXXFLAGS = -g3 -gdwarf2
CCFLAGS = -g3 -gdwarf2

all: executable

debug: CXXFLAGS += -DDEBUG -g
debug: CCFLAGS += -DDEBUG -g
debug: executable

executable: CommandParser.tab.o CommandParser.yy.o Command.o
    $(CXX) -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl

CommandParser.yy.o: CommandParser.l 
    flex -o CommandParser.yy.c CommandParser.l
    $(CC) -c CommandParser.yy.c

আপনার সমস্ত সংকলিত আদেশে in (CXX) বা $ (সিসি) ব্যবহার করতে ভুলবেন না।

তারপরে, 'মেক ডিবাগ' -র অতিরিক্ত পতাকা থাকবে যেমন -ডিডিইইউবিউ এবং -জি যেখানে 'মেক' হবে না।

পার্শ্ব নোটে, আপনি অন্যান্য পোস্টগুলির পরামর্শ মতো আপনার মেকফিলটিকে অনেক বেশি সংক্ষিপ্ত করে তুলতে পারেন।


42
আপনার কোনও মেকফিল বা ব্যাডহিংসমেহ্যাপেন (টিএম) এর মধ্যে কখনই সিএক্সএক্স বা সিসি পরিবর্তন করা উচিত নয়, যার মধ্যে চালানোর জন্য নির্বাহীদের পথ এবং / অথবা নাম রয়েছে। সিপিপিএফএলএজিএস, সিএক্সএক্সএফএলএজিএস এবং সিএফএলএজিএস এই উদ্দেশ্যে পরিবেশন করে।

11
এই পরামর্শটি দুর্বল কারণ এটি ডিবাগ এবং নন-ডিবাগ অবজেক্ট ফাইলগুলিকে মিশ্রিত করে, যাতে কোনওটি দূষিত বিল্ডের সাথে শেষ হয়।
ম্যাক্সিম এগারুশকিন

@ ম্যাক্সিমএগরোশকিন কীভাবে এটি ঠিক করবেন? আমি সম্প্রতি এই সমস্যাটি পেরিয়ে এসেছি। আমার একটি ডিবাগ এক্সিকিউটেবল বিল্ড রয়েছে, এটি রিলিজ অবজেক্ট ফাইলগুলির সাথে সংযুক্ত ছিল। কেবলমাত্র এখন পর্যন্ত সমাধানটি ছিল ডিবাগ ঘোষণা করা এবং তারেস্ট ফোনি প্রকাশ করা
মরিস

3
@ মরিসআর্যান্ডম নাম্বার এর নিজস্ব ফোল্ডারে ডেবিগ / রিলিজ করুন। উদাহরণ: stackoverflow.com/a/48793058/412080
বচন Egorushkin

43

একটি অনুরূপ সমস্যার সন্ধানের সময় এই প্রশ্নটি প্রায়শই উপস্থিত হয়, তাই আমি অনুভব করি যে একটি সম্পূর্ণরূপে বাস্তবায়িত সমাধানের ব্যবস্থা করা হয়েছে। বিশেষত যেহেতু আমি (এবং আমি অন্যকে ধরে নেব) সমস্ত বিভিন্ন উত্তর একসাথে পাইকে লড়াই করার চেষ্টা করেছি।

নীচে একটি নমুনা মেকফাইল রয়েছে যা পৃথক ডিরেক্টরিতে একাধিক বিল্ড প্রকারকে সমর্থন করে। উদাহরণস্বরূপ উদাহরণস্বরূপ ডিবাগ এবং রিলিজ বিল্ডগুলি দেখায়।

সমর্থন ...

  • নির্দিষ্ট বিল্ডগুলির জন্য পৃথক প্রকল্প ডিরেক্টরি
  • একটি ডিফল্ট টার্গেট বিল্ড সহজ নির্বাচন
  • প্রকল্পটি নির্মাণের জন্য প্রয়োজনীয় ডিরেক্টরি তৈরির জন্য নীরব প্রস্তুতির লক্ষ্য
  • বিল্ড-নির্দিষ্ট সংকলক কনফিগারেশন পতাকা
  • প্রকল্পটির পুনর্নির্মাণের প্রয়োজন কিনা তা নির্ধারণের জিএনইউ মেকের প্রাকৃতিক পদ্ধতি
  • অপ্রচলিত প্রত্যয় নিয়মের পরিবর্তে প্যাটার্ন বিধিগুলি

#
# Compiler flags
#
CC     = gcc
CFLAGS = -Wall -Werror -Wextra

#
# Project files
#
SRCS = file1.c file2.c file3.c file4.c
OBJS = $(SRCS:.c=.o)
EXE  = exefile

#
# Debug build settings
#
DBGDIR = debug
DBGEXE = $(DBGDIR)/$(EXE)
DBGOBJS = $(addprefix $(DBGDIR)/, $(OBJS))
DBGCFLAGS = -g -O0 -DDEBUG

#
# Release build settings
#
RELDIR = release
RELEXE = $(RELDIR)/$(EXE)
RELOBJS = $(addprefix $(RELDIR)/, $(OBJS))
RELCFLAGS = -O3 -DNDEBUG

.PHONY: all clean debug prep release remake

# Default build
all: prep release

#
# Debug rules
#
debug: $(DBGEXE)

$(DBGEXE): $(DBGOBJS)
    $(CC) $(CFLAGS) $(DBGCFLAGS) -o $(DBGEXE) $^

$(DBGDIR)/%.o: %.c
    $(CC) -c $(CFLAGS) $(DBGCFLAGS) -o $@ $<

#
# Release rules
#
release: $(RELEXE)

$(RELEXE): $(RELOBJS)
    $(CC) $(CFLAGS) $(RELCFLAGS) -o $(RELEXE) $^

$(RELDIR)/%.o: %.c
    $(CC) -c $(CFLAGS) $(RELCFLAGS) -o $@ $<

#
# Other rules
#
prep:
    @mkdir -p $(DBGDIR) $(RELDIR)

remake: clean all

clean:
    rm -f $(RELEXE) $(RELOBJS) $(DBGEXE) $(DBGOBJS)

আপনি মেকফিল যে ডিরেক্টরিটিতে থাকেন সে ব্যতীত কোনও ডিরেক্টরিতে উত্স ফাইল তৈরির অনুমতি দেওয়ার জন্য কীভাবে এটি পরিবর্তন করবেন?
জেফারসন হাডসন

@ জেফারসন হাডসন যদি উত্স ফাইলগুলি নামের কোনও ডিরেক্টরিতে থাকে srcতবে SRCS = file1.c file2.c file3.c file4.cপড়ার জন্য লাইনটি সংশোধন করুন SRCS = src/file1.c src/file2.c src/file3.c src/file4.c
শূন্য 2cx

3
আমি যে জিনিসটি পছন্দ করি না তা হ'ল ডিবাগ এবং প্রকাশের জন্য সমস্ত নিয়ম এবং ভেরিয়েবলের সদৃশ। আমার অনুরূপ মেকফিল রয়েছে তবে এটি প্রসারিত করার সময় আমার ডিবাগ এবং রিলিজের জন্য প্রতিটি নতুন জিনিস সাবধানতার সাথে অনুলিপি করা উচিত এবং এটি সাবধানে রূপান্তর করতে হবে।
BeeOnRope

এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। আমি আশা করি আমি এটি অনেক আগে দেখেছি।
মাইকেল ডারস্ট

42

যদি রিলিজ / বিল্ড কনফিগার করে আপনার বোঝায় যে প্রতি মেকফিলের জন্য আপনার কেবল একটি কনফিগারেশন প্রয়োজন, তবে এটি কেবল বিষয় এবং সিসি এবং সিএফএলএজিএস ডিকপলিং:

CFLAGS=-DDEBUG
#CFLAGS=-O2 -DNDEBUG
CC=g++ -g3 -gdwarf2 $(CFLAGS)

আপনি gnu মেকফিল ব্যবহার করতে পারবেন কিনা তার উপর নির্ভর করে আপনি এটিকে কিছুটা ফ্যানসিয়ার করতে শর্তসাপেক্ষ ব্যবহার করতে পারেন এবং কমান্ড লাইন থেকে এটি নিয়ন্ত্রণ করতে পারেন:

DEBUG ?= 1
ifeq ($(DEBUG), 1)
    CFLAGS =-DDEBUG
else
    CFLAGS=-DNDEBUG
endif

.o: .c
    $(CC) -c $< -o $@ $(CFLAGS)

এবং তারপরে ব্যবহার করুন:

make DEBUG=0
make DEBUG=1

আপনার যদি একই সাথে উভয় কনফিগারেশন নিয়ন্ত্রণ করতে হয় তবে আমার মনে হয় বিল্ড ডিরেক্টরিগুলি এবং একটি বিল্ড ডিরেক্টরি / কনফিগারেশন থাকা ভাল is


18
আমি অদ্ভুত কিছু করছি জানি না, কিন্তু যদি কাজ (থেকে বিবৃতি ডিবাগ পেতে ifeq (DEBUG, 1)) আমার জন্যে, DEBUGতাই মত পরিবর্তনশীল বন্ধনীর মধ্যে আবৃত প্রয়োজন: ifeq ($(DEBUG), 1)
শনিয়েট

25

নোট করুন যে আপনি একই সাথে আপনার মেকফিলটিকে আরও সহজ করে তুলতে পারেন:

DEBUG ?= 1
ifeq (DEBUG, 1)
    CFLAGS =-g3 -gdwarf2 -DDEBUG
else
    CFLAGS=-DNDEBUG
endif

CXX = g++ $(CFLAGS)
CC = gcc $(CFLAGS)

EXECUTABLE = output
OBJECTS = CommandParser.tab.o CommandParser.yy.o Command.o
LIBRARIES = -lfl

all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CXX) -o $@ $^ $(LIBRARIES)

%.yy.o: %.l 
    flex -o $*.yy.c $<
    $(CC) -c $*.yy.c

%.tab.o: %.y
    bison -d $<
    $(CXX) -c $*.tab.c

%.o: %.cpp
    $(CXX) -c $<

clean:
    rm -f $(EXECUTABLE) $(OBJECTS) *.yy.c *.tab.c

এখন আপনাকে পুরো জায়গা জুড়ে ফাইলের নাম পুনরাবৃত্তি করতে হবে না। যে কোনও .l ফাইলগুলি ফ্লেক্স এবং জিসিসি-এর মাধ্যমে পাস হবে, যে কোনও ফাইল ফাইল বাইসন এবং জি ++ এবং কেবলমাত্র জি ++ এর মাধ্যমে কোনও .cpp ফাইলের মধ্য দিয়ে যাবে।

আপনার দ্বারা শেষ হওয়া প্রত্যাশিত ফাইলগুলি কেবলমাত্র তালিকাভুক্ত করুন এবং কোন বিধিগুলি প্রয়োজনীয়তা পূরণ করতে পারে তা নির্ধারণের কাজটি মেক করবে ...

রেকর্ড এর জন্য:

  • $@ লক্ষ্য ফাইলের নাম (কোলনের আগে একটি)

  • $< প্রথম (বা শুধুমাত্র) পূর্বশর্ত ফাইলের নাম (কোলনের পরে প্রথমটি)

  • $^ সমস্ত পূর্বশর্ত ফাইলের নাম (স্থান পৃথক)

  • $*কান্ড (বিট যা %নিয়মের সংজ্ঞাতে ওয়াইল্ডকার্ডের সাথে মেলে ।


আপনি "রেকর্ডের জন্য" বিভাগে একটি বর্ণনাকে বিভিন্ন বর্ণনার সাথে দুবার সংজ্ঞায়িত করা হয়েছে। মতে gnu.org/software/make/manual/make.html#Automatic-Variables , $^পূর্বশর্ত এমন সমস্ত ফাইলের জন্য হয়।
গ্রান্ট পিটারস

এই অনুদানের জন্য ধন্যবাদ - টাইপো স্থির! (আমি মেকফিলটি পরীক্ষা করেছিলাম, এবং এটি উপস্থিত হয়ে আমি এটি সঠিকভাবে ব্যবহার করেছি, তবে ব্যাখ্যাটি
টাইপ করেছি

2
আমি আশা করি স্বয়ংক্রিয় ভেরিয়েবলগুলি সহ যুক্তিসঙ্গতভাবে ছোট মেকফিলগুলি লেখার জন্য এই সংক্ষিপ্ত গাইডের আরও কিছু ছিল।
এজেপি

মেকফিলটি পরিবর্তন না করেই একটি ডিবাগ এবং রিলিজ লক্ষ্য এবং আপনার নিজের পছন্দসই ভিত্তিতে ডিফল্ট বাছাই করার ক্ষমতা উভয়ই ভাল।

1
এই সমাধানটিতে সমস্যা আছে যে ডিবাগ এবং রিলিজ আউটপুট ফাইলগুলি একই ডিরেক্টরিতে একত্রে মিশ্রিত হয়। যদি তারা সামঞ্জস্য না করে তবে এটি অদ্ভুত এবং আশ্চর্যজনক উপায়ে উত্থিত হবে যদি না আপনি প্রতিবারই ডিবাগের মধ্যে পরিবর্তন না করে পরিবর্তিত হয়ে পরিষ্কার করার বিষয়ে সতর্ক হন। এমনকি যদি তারা সামঞ্জস্যপূর্ণ হয় তবে এটি পরিষ্কার ছাড়া আপনি যা প্রত্যাশা করেন তা তা করবে না: যদি আপনার প্রকল্পটি রিলিজ হিসাবে নির্মিত হয় এবং তারপরে DEBUG = 1 তৈরি করে তবে এটি কেবলমাত্র সেই ফাইলগুলি পুনর্নির্মাণ করবে যার উত্স পরিবর্তিত হয়েছে, সুতরাং আপনি সাধারণত করবেন না এইভাবে একটি "ডিবাগ" তৈরি করুন।
BeeOnRope

3

আপনি একটি পরিবর্তনশীল থাকতে পারে

DEBUG = 0

তারপরে আপনি শর্তযুক্ত বিবৃতি ব্যবহার করতে পারেন

  ifeq ($(DEBUG),1)

  else

  endif

2

পূর্বের থেকে উত্তরগুলি সম্পূর্ণ করা হচ্ছে ... আপনার কমান্ডগুলিতে আপনি তথ্যটি সংজ্ঞায়িত করে চলকগুলি উল্লেখ করতে হবে ...

DEBUG ?= 1
ifeq (DEBUG, 1)
    CFLAGS =-g3 -gdwarf2 -DDEBUG
else
    CFLAGS=-DNDEBUG
endif

CXX = g++ $(CFLAGS)
CC = gcc $(CFLAGS)

all: executable

executable: CommandParser.tab.o CommandParser.yy.o Command.o
    $(CXX) -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl

CommandParser.yy.o: CommandParser.l 
    flex -o CommandParser.yy.c CommandParser.l
    $(CC) -c CommandParser.yy.c

CommandParser.tab.o: CommandParser.y
    bison -d CommandParser.y
    $(CXX) -c CommandParser.tab.c

Command.o: Command.cpp
    $(CXX) -c Command.cpp

clean:
    rm -f CommandParser.tab.* CommandParser.yy.* output *.o

1
একটি (এখন মুছে ফেলা হয়েছে?) উত্তর আছে (যা একটি উত্তরের মন্তব্য ifeq (DEBUG, 1)হওয়া উচিত ছিল ) যা উল্লেখ করা উচিত ifeq ($(DEBUG), 1)। আমি অনুমান করছি এটি এখানে আপনার উত্তর উল্লেখ করা হয়েছে।
কিথ এম

0

আপনি নিজের মেকফিলের মতো সাধারণ কিছুও যুক্ত করতে পারেন

ifeq ($(DEBUG),1)
   OPTS = -g
endif

তারপরে এটি ডিবাগিংয়ের জন্য সংকলন করুন

make DEBUG=1

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.