搞了兩年Windows的Client開發,什麼多線程,多進程開發,都接觸了不少,終覺缺點什麼,每天疲命於業務邏輯與Windows API中;後來發現這終不是我想要的,在Windows逐漸黃昏的今天,這條路還能走多久,值得深思;那天還是找到了我的最愛——Linux。終於狠下心來,決定搞搞Linux,曾經多少次接觸過,但止步於簡單的命令,所幸一不做,二不休,直接裝上了Ubuntu系統,所有辦公都轉到了Ubuntu系統下,包括我正在寫的這篇文章。白天看了一下Markdown的語法,也試一試用Markdown來寫篇文章。這條Linux路,走下去。
Linux的東西那麼多,一口也吃不成一個打胖子;學習經驗和工作經驗告訴我,學習這件事,是細活,得慢慢來;基礎扎實了,沒有想飛而飛不起來的那天。
從最基本的命令開始,每天都會學習幾個,而不是一口氣看完,邊學邊用;而後,再轉到Linux C語言的練習,對於C語言,自己已然熟練於心,只是在Linux平台上不熟悉,基礎知識以熟悉Linux平台的C語言開發為主,然後就有了這篇文章——《make與makefile的學習》。
要先總結make
和makefile
,就需要先了解下面這個過程:
#define
定義的內容,在代碼中進行替換;.obj
文件;在Linux系統下,中間代碼就是.o
文件;0
和1
機器語言;一個工程,那麼多源文件,一堆的cpp
和h
文件,怎麼編譯啊?編譯一個大型工程,如果Rebuild可能就需要好幾個小時,甚至十幾個小時;那我們就可能要問了。
好吧,make
和makefile
就能搞定這些。makefile
定義了一系列的規則來指定,哪些文件需要先編譯,哪些文件需要後編譯,哪些文件需要重新編譯,甚至於進行更復雜的功能操作,因為makefile
就像一個Shell腳本一樣,其中也可以執行操作系統的命令。makefile
帶來的好處就是——“自動化編譯”,一旦寫好,只需要一個make
命令,整個工程完全自動編譯,極大的提高了軟件開發的效率。
make
是一個命令工具,是一個解釋makefile
中指令的命令工具,一般來說,大多數的IDE都有這個命令,比如:Delphi的make
,Visual C++的nmake
,Linux下GNU的make
。可見,makefile
都成為了一種在工程方面的編譯方法。make命令執行時,需要一個makefile
文件,以告訴make
命令需要怎麼樣的去編譯和鏈接程序。
現在,應該明白了吧。make
是一個命令,用來解析makefile
文件;makefile
是一個文件,用來告訴make
命令,如何編譯整個工程,生成可執行文件。就是這麼簡單,我們繼續。
怎麼就出現了make這個東西了呢?還記得你入門C語言時,寫下的Hello World程序麼?
#include <stdio.h>int main(){
printf("Hello World\n");
return 0;}
當你在終端中輸入gcc HelloWorld.c
命令時,就會生成一個a.out
文件,然後就可以神奇的使用./a.out
執行該文件,打印出了Hello World
。這是一件讓初學者興奮的事情,當然了,我已經過了這個興奮的年齡了。啊哈,問題來了,現在就單單的一個HelloWorld.c
文件,如果有多個代碼文件,而多個代碼文件之間又存在引用關系,這個時候,該如何去編譯生成一個可執行文件呢?是的,問題來了。比如現在有一下源文件:
add.h
add.c
sub.h
sub.c
mul.h
mul.c
divi.h
divi.c
main.c
這些代碼文件的定義分別如下:
// add.h#ifndef _ADD_H_
#define _ADD_H_
int add(int a, int b);#endif// add.c#include "add.h"int add(int a, int b){
return a + b;}// sub.h#ifndef _SUB_H_
#define _SUB_H_
int sub(int a, int b);#endif// sub.c#include "sub.h"int sub(int a, int b
{
return a - b;}// mul.h#ifndef _MUL_H_
#define _MUL_H_
int mul(int a, int b);#endif// mul.c#include "mul.h"int mul(int a, int b){
return a * b;}// divi.h#ifndef _DIVI_H_
#define _DIVI_H_
int divi(int a, int b);#endif// divi.c#include "divi.h"int divi(int a, int b){
if (b == 0)
{
return 0;
}
return a / b;}// main.c#include <stdio.h>#include "add.h"#include "sub.h"#include "mul.h"#include "divi.h"int main(){
int a = 10;
int b = 2;
printf("%d + %d = %d\n", a, b, add(a, b));
printf("%d - %d = %d\n", a, b, sub(a, b));
printf("%d * %d = %d\n", a, b, mul(a, b));
printf("%d / %d = %d\n", a, b, divi(a, b));
return 0;}
你也看到了,在main.c中要引用這些文件,那現在如何編譯,生成一個可執行文件呢?問題來了,如何搞定呢?
最笨的解決方法就是所有文件,以此進行編譯,生成對應的目標.o文件。如下:
$ gcc -c sub.c -o sub.o
$ gcc -c add.c -o add.o
$ gcc -c sub.c -o sub.o
$ gcc -c mul.c -o mul.o
$ gcc -c divi.c -o divi.o
$ gcc -c main.c -o main.o
然後再使用如下命令對所生成的單個目標文件進行鏈接,生成可執行文件。
$ gcc -o main add.o sub.o mul.o divi.o main.o