Home / ایجاد یک makefile در لینوکس برای کامپایل برنامه در gcc

ایجاد یک makefile در لینوکس برای کامپایل برنامه در gcc


ابزار 
make 
فرایند ایجاد برنامه اجرایی از کد منبع را راحت می کند
برنامه 
make 
که به نام 
makefile
نیز شناخته می شود، شامل قواعدی است که نحوه ایجاد برنامه اجرایی از کد منبع را در بر دارد.
برای دیدن پارامتر های این دستور  می توانید از دستور
make --help
استفاده کنید. و یا اینکه دستور
man make 
را بزنید

اولین 
makefile 
با یک مثال
کد منبع مثال:
1
2
3
4
5
6
7
// hello.c
#include <stdio.h>
 
int main() {
    printf("Hello, world!\n");
    return 0;
}

برای ساخت یک 
makefile
برای کد بالا
یک فایل با همین نام در پوشه ای که فایل کد بالا قرار دارد ایجاد کنید.
برای فاصله در کد این فایل از تب استفاده می کنیم. (از کلید فاصله استفاده نمی کنیم)
all: hello.exe

hello.exe: hello.o
	 gcc -o hello.exe hello.o

hello.o: hello.c
	 gcc -c hello.c
     
clean:
	 rm hello.o hello.exe
حال برنامه
make
را در همان پوشه اجرا کنید
> make
gcc -c hello.c
gcc -o hello.exe hello.o

اجرای برنامه 
make 
بدون هیچ پارامتری باعث می شود تا بخش 
all 
به صورت پیشفرض اجرا شود.

یک فایل 
makefile 
از مجموعه قواعدی تشکیل شده است و هر قاعده از سه بخش ساخته شده است
یک هدف یک لیست از پیش نیاز ها و یک دستور
target: pre-req-1 pre-req-2 ...
	command
بخش های هدف و پیش نیاز ها با یک دو نقطه از هم جدا نشده اند و برای فاصله از تب استفاده می شود. از کلید فاصله استفاده نمی شود..
وقتی برنامه 
make
می خواهد یک قاعده را ارزیابی کند
سعی می کند که فایل های تعریف شده در پیشنیاز ها را پیدا کند و اگر هرکدام از فایل ها خود یک قاعده داشتند اول آنها را بررسی می کند.
در مثال بالا پیشنیاز بخش 
all
فایل 
hello.exe 
است.
این فایل وجود ندارد و بنابراین برنامه به دنبال قاعده ایجاد آن می رود  تا آن را ایجاد کند.
در این مثال چون فایل hello.o 
نیز وجود ندارد برنامه بدنبال قاعده آن می رود و
چون در قاعده آن فایل 
hello.c 
را می بیند و این فایل نیز در پوشه جاری برنامه وجود دارد کد مربوط به قاعده 
hello.o 
را اجرا می کند
یعنی 
gcc -c hello.c
و حالا که فایل ها ایجاد شد به سراغ فایل 
hello.o 
رفته و کد آن را اجرا می کند و 

gcc -o hello.exe hello.o
و در انتها قاعده 
all
کاری برای انجام ندارد.
توجه به این نکته ضروری است که برنامه تنها زمانی به سراغ پیش نیاز ها می رود که فایل هدف وجود نداشته باشد
مثلا اگر دوباره برنامه
make 
را اجرا کنیم:
> make
make: Nothing to be done for `all'.
در اینجا برنامه سراغ 
all
رفت و وقتی hello.exe
را دید 
به سراغ 
دستورات بخش 
all
رفت و درآنجا چیزی برای انجام نبود


2.2  More on Makefile

Comment & Continuation

A comment begins with a # and lasts till the end of the line. Long line can be broken and continued in several lines via a back-slash (\).

Syntax of Rules

A general syntax for the rules is:

target1 [target2 ...]: [pre-req-1 pre-req-2 ...]
	[command1
	 command2
	 ......]

The rules are usually organized in such as way the more general rules come first. The overall rule is often name "all", which is the default target for make.

Phony Targets (or Artificial Targets)

A target that does not represent a file is called a phony target. For example, the "clean" in the above example, which is just a label for a command. If the target is a file, it will be checked against its pre-requisite for out-of-date-ness. Phony target is always out-of-date and its command will be run. The standard phony targets are: allcleaninstall.

Variables

A variable begins with a $ and is enclosed within parentheses (...) or braces {...}. Single character variables do not need the parentheses. For example,$(CC)$(CC_FLAGS)$@$^.

Automatic Variables

Automatic variables are set by make after a rule is matched. There include:

  • $@: the target filename.
  • $*: the target filename without the file extension.
  • $<: the first prerequisite filename.
  • $^: the filenames of all the prerequisites, separated by spaces, discard duplicates.
  • $+: similar to $^, but includes duplicates.
  • $?: the names of all prerequisites that are newer than the target, separated by spaces.

For example, we can rewrite the earlier makefile as:

all: hello.exe
 
# $@ matches the target; $< matches the first dependent
hello.exe: hello.o
	gcc -o $@ $<

hello.o: hello.c
	gcc -c $<
     
clean:
	rm hello.o hello.exe
Virtual Path - VPATH & vpath

You can use VPATH (uppercase) to specify the directory to search for dependencies and target files. For example,

# Search for dependencies and targets from "src" and "include" directories
# The directories are separated by space
VPATH = src include

You can also use vpath (lowercase) to be more precise about the file type and its search directory. For example,

# Search for .c files in "src" directory; .h files in "include" directory
# The pattern matching character '%' matches filename without the extension
vpath %.c src
vpath %.h include
Pattern Rules

A pattern rule, which uses pattern matching character '%' as the filename, can be applied to create a target, if there is no explicit rule. For example,

# Applicable for create .o object file.
# '%' matches filename.
# $< is the first pre-requisite
# $(COMPILE.c) consists of compiler name and compiler options
# $(OUTPUT_OPTIONS) could be -o $@
%.o: %.c
	$(COMPILE.c) $(OUTPUT_OPTION) $<
 
# Applicable for create executable (without extension) from object .o object file
# $^ matches all the pre-requisites (no duplicates)
%: %.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
Implicit Pattern Rules

Make comes with a huge set of implicit pattern rules. You can list all the rule via --print-data-base option.

2.3  A Sample Makefile

This sample makefile is extracted from Eclipse's "C/C++ Development Guide -Makefile".

# A sample Makefile
# This Makefile demonstrates and explains 
# Make Macros, Macro Expansions,
# Rules, Targets, Dependencies, Commands, Goals
# Artificial Targets, Pattern Rule, Dependency Rule.

# Comments start with a # and go to the end of the line.

# Here is a simple Make Macro.
LINK_TARGET = test_me.exe

# Here is a Make Macro that uses the backslash to extend to multiple lines.
OBJS =  \
 Test1.o \
 Test2.o \
 Main.o

# Here is a Make Macro defined by two Macro Expansions.
# A Macro Expansion may be treated as a textual replacement of the Make Macro.
# Macro Expansions are introduced with $ and enclosed in (parentheses).
REBUILDABLES = $(OBJS) $(LINK_TARGET)

# Here is a simple Rule (used for "cleaning" your build environment).
# It has a Target named "clean" (left of the colon ":" on the first line),
# no Dependencies (right of the colon),
# and two Commands (indented by tabs on the lines that follow).
# The space before the colon is not required but added here for clarity.
clean : 
  rm -f $(REBUILDABLES)
  echo Clean done

# There are two standard Targets your Makefile should probably have:
# "all" and "clean", because they are often command-line Goals.
# Also, these are both typically Artificial Targets, because they don't typically
# correspond to real files named "all" or "clean".  

# The rule for "all" is used to incrementally build your system.
# It does this by expressing a dependency on the results of that system,
# which in turn have their own rules and dependencies.
all : $(LINK_TARGET)
  echo All done

# There is no required order to the list of rules as they appear in the Makefile.
# Make will build its own dependency tree and only execute each rule only once
# its dependencies' rules have been executed successfully.

# Here is a Rule that uses some built-in Make Macros in its command:
# $@ expands to the rule's target, in this case "test_me.exe".
# $^ expands to the rule's dependencies, in this case the three files
# main.o, test1.o, and  test2.o.
$(LINK_TARGET) : $(OBJS)
  g++ -g -o $@ $^

# Here is a Pattern Rule, often used for compile-line.
# It says how to create a file with a .o suffix, given a file with a .cpp suffix.
# The rule's command uses some built-in Make Macros:
# $@ for the pattern-matched target
# $< for the pattern-matched dependency
%.o : %.cpp
  g++ -g -o $@ -c $<

# These are Dependency Rules, which are rules without any command.
# Dependency Rules indicate that if any file to the right of the colon changes,
# the target to the left of the colon should be considered out-of-date.
# The commands for making an out-of-date target up-to-date may be found elsewhere
# (in this case, by the Pattern Rule above).
# Dependency Rules are often used to capture header file dependencies.
Main.o : Main.h Test1.h Test2.h
Test1.o : Test1.h Test2.h
Test2.o : Test2.h

# Alternatively to manually capturing dependencies, several automated
# dependency generators exist.  Here is one possibility (commented out)...
# %.dep : %.cpp
#   g++ -M $(FLAGS) $< > $@
# include $(OBJS:.o=.dep)

2.4  Brief Summary

I have presented the basic make features here so that you can read and understand simple makefiles for building C/C++ applications. Make is actually quite complex, and can be considered as a programming language by itself!!




     RSS of this page