আমি কীভাবে এসআরসি, ওবিজে, এবং বিআইএন সাব-ডিরেক্টরি সহ সি প্রকল্পগুলির জন্য একটি মেকফিল তৈরি করতে পারি?


95

কয়েক মাস আগে, আমি Makefileস্কুল কাজের জন্য নিম্নলিখিত জেনেরিক নিয়ে এসেছি :

# ------------------------------------------------
# Generic Makefile
#
# Author: yanick.rochon@gmail.com
# Date  : 2010-11-05
#
# Changelog :
#   0.01 - first version
# ------------------------------------------------

# project name (generate executable with this name)
TARGET   = projectname

CC       = gcc -std=c99 -c
# compiling flags here
CFLAGS   = -Wall -I.

LINKER   = gcc -o
# linking flags here
LFLAGS   = -Wall

SOURCES  := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS  := $(SOURCES:.c=*.o)
rm       = rm -f

$(TARGET): obj
    @$(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
    @echo "Linking complete!"

obj: $(SOURCES) $(INCLUDES)
    @$(CC) $(CFLAGS) $(SOURCES)
    @echo "Compilation complete!"

clean:
    @$(rm) $(TARGET) $(OBJECTS)
    @echo "Cleanup complete!"

এটি মূলত প্রতিটি .cএবং .hফাইলকে একই ফোল্ডারে .oফাইল এবং এক্সিকিউটেবল projectnameসব উত্পন্ন করতে সংকলন করবে ।

এখন, আমি এটাকে একটু চাপ দিতে চাই। নিম্নলিখিত ডিরেক্টরি কাঠামোর সাথে একটি সি প্রকল্প সংকলন করতে আমি কীভাবে একটি মেকফিল লিখতে পারি?

 ./
 ./Makefile
 ./src/*.c;*.h
 ./obj/*.o
 ./bin/<executable>

অন্য কথায়, আমি একটি মেকফিল রাখতে চাই যা সি সূত্রগুলি থেকে সংকলন ./src/করে ./obj/এবং তারপরে এক্সিকিউটেবলটি তৈরি করতে সমস্ত কিছু লিঙ্ক করে ./bin/

আমি বিভিন্ন মেকফিলগুলি পড়ার চেষ্টা করেছি, তবে আমি কেবল তাদের উপরের প্রকল্প কাঠামোর জন্য কাজ করতে পারি না; পরিবর্তে, প্রকল্পটি ত্রুটিগুলির সকল প্রকারের সাথে সংকলন করতে ব্যর্থ। অবশ্যই, আমি পূর্ণ ব্লোড আইডিই (মনোডাভলভ, অঞ্জুতা, ইত্যাদি) ব্যবহার করতে পারি, তবে আমি সত্যিই জিইডিট এবং ভাল ওল 'টার্মিনালটি দিয়ে থাকতে পছন্দ করি।

এমন কোনও গুরু আছেন যিনি আমাকে একটি কার্যনির্বাহী সমাধান দিতে পারেন, বা কীভাবে এটি করা যায় সে সম্পর্কে পরিষ্কার তথ্য দিতে পারেন? ধন্যবাদ!

** আপডেট (ভি 4) **

চূড়ান্ত সমাধান:

# ------------------------------------------------
# Generic Makefile
#
# Author: yanick.rochon@gmail.com
# Date  : 2011-08-10
#
# Changelog :
#   2010-11-05 - first version
#   2011-08-10 - added structure : sources, objects, binaries
#                thanks to http://stackoverflow.com/users/128940/beta
#   2017-04-24 - changed order of linker params
# ------------------------------------------------

# project name (generate executable with this name)
TARGET   = projectname

CC       = gcc
# compiling flags here
CFLAGS   = -std=c99 -Wall -I.

LINKER   = gcc
# linking flags here
LFLAGS   = -Wall -I. -lm

# change these to proper directories where each file should be
SRCDIR   = src
OBJDIR   = obj
BINDIR   = bin

SOURCES  := $(wildcard $(SRCDIR)/*.c)
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS  := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
rm       = rm -f


$(BINDIR)/$(TARGET): $(OBJECTS)
    @$(LINKER) $(OBJECTS) $(LFLAGS) -o $@
    @echo "Linking complete!"

$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
    @$(CC) $(CFLAGS) -c $< -o $@
    @echo "Compiled "$<" successfully!"

.PHONY: clean
clean:
    @$(rm) $(OBJECTS)
    @echo "Cleanup complete!"

.PHONY: remove
remove: clean
    @$(rm) $(BINDIR)/$(TARGET)
    @echo "Executable removed!"

এখানে নির্দিষ্ট প্রশ্নটি কী?
অলিভার চার্লসওয়ার্থ

আমি নিশ্চিত আপনি কী করতে চান তা আমি বুঝতে পারি।
টম

আপডেট Makefile। আমি কাছাকাছি আসছি, তবে স্বয়ংক্রিয় ভেরিয়েবলগুলি নিয়ে আমার সমস্যা আছে, তাই যাইহোক এটি মনে হয়
ইয়ানিক রোচন

আমি সবেমাত্র একটি সমাধান পেয়েছি। যদি কেউ আরও ভাল কিছু আবিষ্কার করার বিষয়ে চিন্তা করেন তবে মেকফিলটি এখনও উন্নত হতে পারে।
ইয়ানিক রচন

4
@ ইয়ানিকরোচন আমার আপনার ইংরেজি দক্ষতার সমালোচনা করার অর্থ নেই। তবে PHONY টার্গেটগুলির জন্য যে কোনও ধারণা তৈরি করার জন্য আপনি সুনির্দিষ্টভাবে বনানা
joni

উত্তর:


34

প্রথমত, আপনার $(OBJECTS)বিধি সমস্যাযুক্ত কারণ:

  1. এটি একধরণের নির্বিচার, সমস্ত উত্সকে প্রতিটি বস্তুর পূর্বশর্ত তৈরি করে,
  2. এটি প্রায়শই ভুল উত্স ব্যবহার করে (যেমন আপনি আবিষ্কার করেছেন file1.oএবং file2.o)
  3. এটি বস্তুগুলিতে থামার পরিবর্তে এক্সিকিউটেবলগুলি তৈরি করার চেষ্টা করে এবং
  4. লক্ষ্যটির নাম ( foo.o) নিয়মটি আসলে কী উত্পাদন করে তা নয় ( obj/foo.o)।

আমি নিম্নলিখিত পরামর্শ:

OBJECTS  := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)

$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
    $(CC) $(CFLAGS) -c $< -o $@
    @echo "Compiled "$<" successfully!"

$(TARGET)নিয়ম একই সমস্যা যে লক্ষ্য নাম আসলে বর্ণনা কী নিয়ম তৈরী করে হয়েছে। যে কারণে, আপনি টাইপ করুনmake বেশ কয়েকবার করেন, তবে কোনও কারণ না থাকলেও মেক প্রতিটি সময় লক্ষ্যটিকে পুনর্নির্মাণ করবে। একটি ছোট পরিবর্তন স্থির করে যে:

$(BINDIR)/$(TARGET): $(OBJECTS)
    $(LINKER) $@ $(LFLAGS) $(OBJECTS)
    @echo "Linking complete!"

এটি একবারে ক্রমযুক্ত হয়ে গেলে আপনি আরও পরিশীলিত নির্ভরতা হ্যান্ডলিং বিবেচনা করতে পারেন; আপনি যদি কোনও একটি শিরোলেখ ফাইলটি সংশোধন করেন তবে এই মেকফিলটি কোন জিনিস / এক্সিকিউটেবলকে পুনর্নির্মাণ করতে হবে তা জানে না। তবে এটি অন্য দিনের জন্য অপেক্ষা করতে পারে।

সম্পাদনা:
দুঃখিত, আমি $(OBJECTS)উপরের নিয়মের কিছু অংশ বাদ দিয়েছি ; আমি সংশোধন করেছি। (আমি আশা করি কোনও কোডের নমুনার অভ্যন্তরে "ধর্মঘট" ব্যবহার করতে পারি।)


আপনার প্রস্তাবিত পরিবর্তনগুলি সহ, আমি পেয়েছি:obj/file1.o: In function 'main': \n main.c:(.text+0x0): multiple definition of 'main' \n obj/main.o:main.c:(.text+0x0): first defined here
ইয়ানিক রচন

@ ইয়ানিক রোচন: আপনার একাধিক mainফাংশন আছে? হয়তো এক file1.cএবং এক main.c? যদি তা হয় তবে আপনি এই বিষয়গুলি লিঙ্ক করতে সক্ষম হবেন না; mainএক্সিকিউটেবলের মধ্যে কেবল একজনই থাকতে পারে ।
বিটা

না আমি করিনি. প্রশ্নটিতে পোস্ট করা সর্বশেষ সংস্করণটি দিয়ে সবকিছু ঠিকঠাক কাজ করে। যখন আমি আমার মেকফিলটিকে আপনার পরামর্শ অনুসারে পরিবর্তন করি (এবং আপনি যা বলছেন তার সুবিধাগুলি আমি বুঝতে পারি) যা আমি পাই। আমি কেবল পেস্ট করেছি file1.cতবে এটি প্রকল্পের প্রতিটি ফাইলগুলিতে একই বার্তা দেয়। আর main.cনয় শুধুমাত্র একটি প্রধান ফাংশন সঙ্গে এক ... এবং main.cআমদানির file1.hএবং file2.h(তার মাঝে কোন সম্পর্ক নেই file1.cএবং file2.c), কিন্তু আমার সন্দেহ সমস্যা থেকে আসে।
ইয়ানিক রচন

@ ইয়ানিক রোচন: আমি আমার $(OBJECTS)নিয়মের প্রথম লাইনটি আটকে ভুল করেছি ; আমি এটি সম্পাদনা করেছি। খারাপ লাইনের সাথে আমি একটি ত্রুটি পেয়েছি, তবে আপনি যা পেয়েছেন তা নয় ...
বিটা

6

আপনি যোগ করতে পারেন -Iইঙ্গিত যেখানে কম্পাইলার সোর্স ফাইলের জন্য হওয়া উচিত কম্পাইলার পতাকা (CFLAGS) এর পতাকা, এবং -o পতাকা ইঙ্গিত যেখানে বাইনারি ছেড়ে দেওয়া উচিত:

CFLAGS   = -Wall -I./src
TARGETPATH = ./bin

$(TARGET): obj
    @$(LINKER) $(TARGETPATH)/$(TARGET) $(LFLAGS) $(OBJECTS)
    @echo "Linking complete!"

objডিরেক্টরিতে অবজেক্ট ফাইলগুলি ফেলে দেওয়ার জন্য , -oসংকলনের সময় বিকল্পটি ব্যবহার করুন । এছাড়াও, $@এবং $< স্বয়ংক্রিয় ভেরিয়েবলগুলি দেখুন

উদাহরণস্বরূপ, এই সাধারণ মেকফিলটি বিবেচনা করুন

CFLAGS= -g -Wall -O3                                                            
OBJDIR= ./obj

SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o )
all:$(OBJS)

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

আপডেট>

আপনার মেকফিলটি দেখে আমি বুঝতে পারি যে আপনি -oপতাকাটি ব্যবহার করছেন । ভাল. এটি ব্যবহার চালিয়ে যান, তবে আউটপুট ফাইলটি কোথায় লেখা উচিত তা নির্দেশ করতে একটি লক্ষ্য ডিরেক্টরি ভেরিয়েবল যুক্ত করুন।


আপনি আরো নির্দিষ্ট হতে পারে? আপনি কী যুক্ত -l ...করেছেন CFLAGSএবং ... এর মধ্যে ইতিমধ্যে -oলিঙ্কারের সাথে যুক্তি রয়েছে ( LINKER)
ইয়ানিক রোচন

হ্যাঁ, সিএফএলএজিএস এবং হ্যাঁ, -o ব্যবহার চালিয়ে যান, কেবল টার্গেটপ্যাথ ভেরিয়েবল যুক্ত করুন।
টম

আপনাকে ধন্যবাদ, আমি পরিবর্তনগুলি করেছি, তবে মনে হচ্ছে আমি এখনও কিছুটা মিস করছি (প্রশ্নের আপডেটটি দেখুন)
ইয়ানিক রোচন

ঠিক make, যেখান থেকে মেকফিল বসে
ইয়ানিক রোচন

আপনি যে আদেশটি কার্যকর করা হচ্ছে তা পড়তে পারবেন না? যেমন জিসিসি-সি ইয়াদায়দা ada খুব নিশ্চিত যে এমন একটি চলক রয়েছে যার মধ্যে আপনি যা আশা করেন তা ধারণ করে না
টম

-1

আমি আজকাল মেকফিলগুলি লেখা বন্ধ করে দিয়েছি, যদি আপনার উদ্দেশ্যটি শিখতে হয় তবে এগিয়ে যান, অন্যথায় আপনার কাছে ভাল মেকফিল জেনারেটর রয়েছে যা গ্রহন সিডিটি নিয়ে আসে। আপনি যদি আপনার বিল্ড ট্রিটিতে কিছু রক্ষণাবেক্ষণ / একাধিক প্রকল্প সমর্থন চান তবে নীচের বিষয়গুলি একবার দেখুন:

https://github.com/dmoulding/boilermake আমি এটিকে বেশ ভাল পেয়েছি ..!


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