歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

make和makefile的簡單學習

搞了兩年Windows的Client開發,什麼多線程,多進程開發,都接觸了不少,終覺缺點什麼,每天疲命於業務邏輯與Windows API中;後來發現這終不是我想要的,在Windows逐漸黃昏的今天,這條路還能走多久,值得深思;那天還是找到了我的最愛——Linux。終於狠下心來,決定搞搞Linux,曾經多少次接觸過,但止步於簡單的命令,所幸一不做,二不休,直接裝上了Ubuntu系統,所有辦公都轉到了Ubuntu系統下,包括我正在寫的這篇文章。白天看了一下Markdown的語法,也試一試用Markdown來寫篇文章。這條Linux路,走下去。

打基礎

Linux的東西那麼多,一口也吃不成一個打胖子;學習經驗和工作經驗告訴我,學習這件事,是細活,得慢慢來;基礎扎實了,沒有想飛而飛不起來的那天。
從最基本的命令開始,每天都會學習幾個,而不是一口氣看完,邊學邊用;而後,再轉到Linux C語言的練習,對於C語言,自己已然熟練於心,只是在Linux平台上不熟悉,基礎知識以熟悉Linux平台的C語言開發為主,然後就有了這篇文章——《make與makefile的學習》。

程序的編譯和鏈接

要先總結makemakefile,就需要先了解下面這個過程:
alt

  1. 預編譯:也叫預處理,進行一些文本替換工作,比如將#define定義的內容,在代碼中進行替換;
  2. 編譯:將預處理得到的代碼,進行詞法分析、語法分析、中間代碼……;如果是在Windows下,中間代碼就是.obj文件;在Linux系統下,中間代碼就是.o文件;
  3. 匯編:將編譯得到的匯編代碼,通過匯編程序得到01機器語言;
  4. 鏈接:鏈接各種靜態鏈接庫和動態鏈接庫得到可執行文件。

make和makefile能干啥

一個工程,那麼多源文件,一堆的cpph文件,怎麼編譯啊?編譯一個大型工程,如果Rebuild可能就需要好幾個小時,甚至十幾個小時;那我們就可能要問了。

  1. 如何像VS那樣,一鍵就能編譯整個項目?
  2. 如何修改了哪個文件,就編譯修改的那個文件,而不是重新編譯整個工程?

好吧,makemakefile就能搞定這些。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

Copyright © Linux教程網 All Rights Reserved