我把一個很簡單的程式分為幾個檔案存放,然後使用makefile來處理
下面是一個很簡單的c語言模拟出入棧的程式,分為三部分,分别存放在三個檔案:
main.c 主函數
func.h 頭檔案
stack.c 出入棧函數
====================================================
func.h
==================
#define MAXVAL 20
void push(double);
double pop(void);
main.c
#include <stdio.h>
#include "func.h"
main()
{
double t = 2.0;
int i=14;
while(--i)
push(t++); /*入棧*/
printf("\n");
for(i=0; i<12; i++)
printf("%2.1f ", pop()); /*出棧*/
}
stack.c
static int sp=0;
static double val[MAXVAL];
void push(double s)
if(sp < MAXVAL)
{
printf("%2.1f ", s);
val[sp++] = s;
}
else
printf("stack is full\n");
double pop(void)
if(--sp >= 0)
return val[sp];
{
printf("stack is empty\n");
return -1;
===============================================
下面是makefile的内容,我會逐條解釋:
makefile
===================
code : main.o stack.o
gcc -o bin main.o stack.o
main.o : main.c func.h
gcc -c main.c
stack.o : func.h stack.c
gcc -c stack.c
clean :
rm -rf *.o
makefile格式:
目标 : 依賴檔案
指令
冒号左右兩邊都要有空格,如果目标依賴的檔案有多個,則用空格隔開,指令前面是[tab]鍵,
一行一條指令,clean編譯完成後,使用者執行#make clean 指令時所做的動作,若單條指令過長或是目标依賴的檔案有多個而為了易看将指令的後半部分寫在下一行可以使用反斜杠\
====================
這裡開始解釋:
code[空格]:[空格]main.o[空格]stack.o
[Tab] gcc -o bin main.o stack.o
code是目标名,首行的目标名可以是任意的,因為這是最終要生成的目标,開始是不存在的。
在這裡code可以取任何你想取的名字。main.o stack.o是我們最終生成二進制可執行檔案需要
的目标檔案(object),分别由main.c stack.c彙編得到。bin是生成的最終的可執行檔案名,
這裡的bin可以取任何你想取的名字,這裡為了說明是以我分别取了code這個目标名和
bin這個最終可執行檔案名,不過實際中我們常常取兩者相同。比如在這個程式裡,實作
的功能是出入棧,那麼上面的code和bin我都用stack這個目标名,也即變成了下面這樣:
stack[空格]:[空格]main.o[空格]stack.o
[Tab] gcc -o stack main.o stack.o
如果有很多個檔案要分行放置的話,可以這樣:
stack : main.o \
stack.o
gcc -o stack main.o stack.o
格式和上面說的一緻。make工具的執行過程有點像入棧出棧,首先找到最終的目标和依賴檔案,
然後再找各個檔案的依賴,入棧。最終目标檔案依賴于main.o和stack.o兩個檔案,main.o依賴于
main.c func.h兩個檔案,通過 gcc -c main.c 指令來彙編得得到目标檔案main.o,
stack.o依賴于stack.c func.h兩個檔案,通過 gcc -c stack.c 指令來彙編得得到
目标檔案stack.o。
得到了最終目标檔案的以來檔案,出棧。通過執行 gcc -o stack main.o stack.o指令
連結得到目标可執行檔案stack。至此,我們的一個簡單的makefile檔案就完成了,
最後一個簡單的make指令就可以編譯得到目标可執行檔案了。
使用gcc編譯可執行檔案的過程:
gcc -o 目标可執行二進制檔案名 源檔案.c
這樣一條指令我們就可以得到一個可執行檔案,它包含了下面四步:
(1)預處理、(2)彙編、(3)編譯 (4)連結
1.預處理,生成.i的檔案[預處理器cpp]
2.将預處理後的檔案不轉換成彙編語言,生成檔案.s[編譯器egcs]
3.有彙編變為目标代碼(機器代碼)生成.o的檔案[彙編器as]
4.連接配接目标代碼,生成可執行程式[連結器ld]
1)預處理(Pre-processing)
在該階段,編譯器将C源代碼中的包含的頭檔案如stdio.h編譯進來,使用者可以使用gcc的選項”-E”進行檢視。
用法:#gcc -E 源檔案.c -o 目标檔案.i
2)編譯階段(Compiling)
第二步進行的是編譯階段,在這個階段中,Gcc首先要檢查代碼的規範性、是否有文法錯誤等,以确定代碼的實際要做的工作,在檢查無誤後,Gcc把代碼翻譯成彙編語言。使用者可以使用”-S”選項來進行檢視,該選項隻進行編譯而不進行彙編,生成彙編代碼。
選項 -S
用法:# gcc –S 源檔案.i -o 目标檔案.s
3)彙編階段(Assembling)
彙編階段是把編譯階段生成的”.s”檔案轉成二進制目标代碼.
選項 -c
用法:# gcc –c 源檔案.s –o 目标檔案.o
4)連結階段(Link)
在成功編譯之後,就進入了連結階段。
無選項連結
用法:# gcc 源檔案.o –o 目标可執行檔案