1. 程式人生 > >c語言模組化開發(GCC編譯例項)

c語言模組化開發(GCC編譯例項)

c語言編譯步驟,即一個*.c檔案是如何一步步成為*.exe的?

參見:C語言真正的編譯過程

window下GCC(minGW)的安裝

參見:MinGW下載安裝

GCC常見命令:

參見:Linux GCC常用命令

本人理解的c語言編譯過程、中間檔案、常用命令

 

本次實驗環境:

window7、minGW

實驗程式碼:https://download.csdn.net/download/u010476739/10800828

實驗一、編譯單個檔案

程式碼 test.c

#include <stdio.h>
#include <stdlib.h>
int main()
{
	printf("hello\n");
	system("pause");
}

gcc命令:(gcc test.c -o test.exe -save-temps)

編譯結果:

雙擊執行test.exe

實驗二、編譯多個檔案

目錄:
    sub.h
    sub.c
    main.c

程式碼sub.h

#ifndef MY_MATH
#define MY_MATH
	int add(int,int);
	int sub(int,int);
#endif

程式碼sub.c

int add(int x,int y)
{
	return x+y;
}
int sub(int x,int y)
{
	return x-y;
}

程式碼main.c

#include <stdio.h>
#include <stdlib.h>
#include "sub.h"
int main()
{
	int a=5;
	int b=2;
	printf("add(a,b)=%d\n",add(a,b));
	printf("sub(a,b)=%d\n",sub(a,b));
	system("pause");
	return 0;
}

執行命令:

gcc sub.c main.c -o test.exe

實驗三、模組化程式設計

檔案目錄結構:
    header
        m1.h
        m2.h
    mod1
        m1.c
    mod2
        m2.c
    main.c

程式碼:
m1.h
    

#ifndef M1
    #define M1
    int add(int,int);
#endif


m2.h
    

#ifndef M2
    #define M2
    int sub(int,int);
#endif


m1.c
    

int add(int x,int y)
{    
       return x+y;
}


m2.c
    

int sub(int x,int y)
{
        return x-y;
}


main.c

#include <stdio.h>
 #include <stdlib.h>

#include "header/m1.h"
#include "header/m2.h"

int main()
{
      int a=5,b=3;
      printf("add(a,b)=%d\n",add(a,b));
      printf("sub(a,b)=%d\n",sub(a,b));
      system("pause");
}

編譯方案一、各自單獨編譯,最後連結成exe程式
    1.編譯模組mod1(僅需要m1.c)
        cd mod1
        gcc -c m1.c -o m1.obj
    2.編譯模組mod2(僅需要m2.c)
        cd mod2
        gcc -c m2.c -o m2.obj
    3.編譯主模組main
        cd ..
        gcc -c main.c -o main.obj
    4.將main.obj,m1.obj,m2.obj連結到一起
        gcc main.obj mod1/m1.obj mod2/m2.obj -o test.exe

編譯方案二、直接編譯
    直接將這些檔案編譯成exe可執行程式
    gcc main.c mod1/m1.c mod2/m2.c -o test.exe

實驗四、gcc命令選項

檔案目錄結構:
    header
        m1.h
        m2.h
    mod1
        m1.c
    mod2
        m2.c
    main.c

程式碼:
m1.h
    

#ifndef M1
    #define M1
    int add(int,int);
#endif


m2.h
    

#ifndef M2
    #define M2
    int sub(int,int);
#endif


m1.c
    

int add(int x,int y)
{
      return x+y;
}


m2.c
  

 int sub(int x,int y)
{
     return x-y;
}


main.c
  

#include <stdio.h>
#include <stdlib.h>

#include "m1.h"
#include "m2.h"

int main()
{
      int a=5,b=3;
      printf("add(a,b)=%d\n",add(a,b));
      printf("sub(a,b)=%d\n",sub(a,b));
      system("pause");
}

1.編譯主模組main.c 並指定include查詢的路徑
    gcc -I ./header -c main.c -o main.obj
2.編譯模組m1.c
    gcc -c mod1/m1.c -o mod1.obj
3.編譯模組m2.c
    gcc -c mod2/m2.c -o mod2.obj
4.將編譯的結果連結為一個exe程式
    gcc main.obj mod1/m1.obj mod2/m2.obj -o test.exe

實驗五、gcc生成動態庫dll檔案

目錄結構:
myfunc
    myfunc.h
    myfunc.c
main.c

程式碼:
myfunc.h

#ifndef MYFUNC
    #define MYFUNC
    int add(int,int);
#endif

myfunc.c

int add(int x,int y)
{
    return x+y;
}

main.c

#include <stdio.h>
#include <stdlib.h>
int add(int,int);
int main()
{
        int a=10,b=2;
        printf("add(a,b)=%d\n",add(a,b));
        system("pause");
}

編譯思路:
    首先將myfunc.c編譯為動態庫檔案myfunc.dll,myfunc.h檔案可以供外面呼叫
    然後編譯main.c檔案並使用myfunc.dll連結為main.exe可執行檔案
    將myfunc.dll拷貝到main.exe同一個目錄下,雙擊main.exe可檢視效果

1.編譯myfunc.c檔案為動態庫myfunc.dll
    cd myfunc
    gcc myfunc.c -shared -o myfunc.dll
2.編譯main.c檔案並連結為main.exe可執行程式
    cd ..
    gcc main.c myfunc/myfunc.dll -o main.exe
3.將myfunc/myfunc.dll檔案拷貝至與main.exe同目錄後雙擊執行main.exe

實驗六、gcc生成靜態庫lib檔案

目錄結構:
    staticmod
        mod.h
        mod.c
    main.c

程式碼:
mod.h
    

#ifndef MOD
    #define MOD
    int add(int,int);
#endif


mod.c
    

int add(int x,int y)
{
     return x+y;
}


main.c
    

#include <stdio.h>
#include <stdlib.h>

int add(int,int);
int main()
{
     int a=1,b=6;
     printf("add(a,b)=%d\n",add(a,b));
     system("pause");
     return 0;
}

實現思路:
    首先將mod.c編譯為靜態連結庫 mod.lib(僅mod.c就可以了)
    然後編譯main.c生成main.exe,生成後的main.exe可單獨執行
1.將mod.c編譯生成靜態連結庫
    cd staticmod
    gcc -c mod.c -o mod.obj
    使用ar將obj檔案打包成.lib檔案
    ar -crv mod.lib mod.obj
2.編譯main.c生成main.exe可執行程式
    cd ..
    gcc main.c staticmod/mod.lib -o main.exe
    雙擊生成後的main.exe即可執行
    

實驗七、gcc生成的多個動態庫相互引用

目錄結構:
mod1
    m1.c
    m1.h
mod2
    m2.h
    m2.c
mod3
    m3.h
    m3.c
main.c

程式碼:
m1.h
    

#ifndef MOD1
    #define MOD1
    int func1(x,y);
#endif


m1.c
    

int func1(int x,int y)
{
      return x+y;
}


m2.h
    

#ifndef MOD2
    #define MOD2
    int func2(int,int);
#endif


m2.c
    

int func1(int,int);
int func2(int x,int y)
{
      int res=func1(x,y);
      res=res+2;
      return res;
}


m3.h
  

#ifdefine MOD3
    #define MOD3
    int func3(int,int);
#endif


m3.c
  

int func2(int,int);
int func3(int x,int y)
{
      int res=func2(x,y);
      res+=3;
      return res;
}


main.c
    

#include <stdio.h>
#include <stdlib.h>
int func3(int,int);
int main()
{
     int a=10,b=2;
     printf("func3(a,b)=%d\n",func3(a,b));
     system("pause");
     return 0;
}

實現思路:
    首先將m1.c編譯為動態庫m1.dll,m2.c編譯為m2.dll,m3.c編譯為m3.dll
    然後將main.c編譯並連結為main.exe,將m1.dll,m2.dll,m3.dll拷貝到main.exe同目錄下,然後雙擊main.exe執行可以看到效果
1.將m1.c編譯為m1.dll
    cd mod1
    gcc -shared m1.c -o m1.dll
2.將m2.c編譯為m2.dll
    cd ../mod2
    gcc -shared m2.c ../mod1/m1.dll -o m2.dll
3.將m3.c編譯為m3.dll
    cd ../mod3
    gcc -shared m3.c ../mod2/m2.dll -o m3.dll
4.將main.c編譯為main.exe
    cd ..
    gcc main.c mod3/m3.dll -o main.exe
    將m1.dll,m2.dll,m3.dll拷貝到main.exe同目錄下,雙擊main.exe即可看到效果

實驗八、gcc生成的多個靜態庫相互引用

mod1是一個靜態庫,mod2是一個靜態庫引用了mod1,主模組main引用了mod2
目錄結構:
mod1
    m1.h
    m1.c
mod2
    m2.h
    m2.c
main.c

程式碼:
m1.h
    

#ifndef MOD1
    #define MOD1
    int func1(int,int);
#endif


m1.c
    

int func1(int x,int y)
{
      return x+y;
}


m2.h
    

#ifndef MOD2
    #define MOD2
    int func2(int,int);
#endif


m2.c
    

int func1(int,int);
int func2(int x,int y)
{
      int res=func1(x,y);
      res+=3;
      return res;
}


main.c
  

 #include <stdio.h>
 #include <stdlib.h>

 int func2(int,int);
 int main()
 {
       int a=10,b=5;
       printf("func2(a,b)=%d\n",func2(a,b));
       system("pause");
 }


實現思路:
    首先將mod1編譯成obj檔案,可以考慮繼續打包成lib檔案
    然後將mod2編譯成obj檔案,然後將mod1的obj檔案和mod2的obj檔案一塊打包成m2.lib檔案
    最後編譯main.c引用m2.lib檔案即可
1.將mod1編譯成obj檔案
    cd mod1
    gcc -c m1.c -o m1.obj
    下一條命令可選
    ar -crv m1.lib m1.obj
2.將mod2編譯成obj檔案
    cd ../mod2
    gcc -c m2.c -o m2.obj
    將m1.obj和m2.obj聯合打包成m2.lib檔案
    ar -crv m2.lib ../mod1/m1.obj m2.obj
3.編譯main.c
    cd ..
    gcc main.c mod2/m2.lib -o main.exe
    雙擊執行main.exe即可看到效果

實驗九、gcc生成exe同時引用動態庫和靜態庫

主模組同時引用靜態庫和動態庫:
mod1是一個靜態庫,mod2是一個動態庫,主模組main引用了mod1和mod2
目錄結構:
mod1
    m1.h
    m1.c
mod2
    m2.h
    m2.c
main.c
程式碼:
m1.h
    

#ifndef MOD1
    #define MOD1
    int func1(int,int);
#endif


m1.c
    

int func1(int x,int y)
{
      return x+y;
}


m2.h
    

#ifndef MOD2
    #define MOD2
    int func2(int,int);
#endif


m2.c
    

int func2(int x,int y)
{
     return x-y;
}


main.c
    

#include <stdio.h>
#include <stdlib.h>

int func1(int,int);
int func2(int,int);
int main()
{
     int a=10,b=5;
     printf("func1(a,b)=%d\n",func1(a,b));
     printf("func2(a,b)=%d\n",func2(a,b));
     system("pause");
}


實現思路:
    首先將mod1編譯成obj並繼續打包成lib檔案,將mod2直接編譯為dll檔案
    然後編譯main.c引用m1.lib和m2.dll檔案即可,將m2.dll拷貝到main.exe同目錄雙擊執行即可
1.將mod1編譯成obj檔案並打包成lib檔案
    cd mod1
    gcc -c m1.c -o m1.obj
    ar -crv m1.lib m1.obj
2.將mod2編譯成dll檔案
    cd ../mod2
    gcc -shared m2.c -o m2.all
3.編譯main.c
    cd ..
    gcc main.c mod1/m1.lib mod2/m2.dll -o main.exe
    將m2.dll拷貝到main.exe同目錄,雙擊main.exe執行即可看到效果


實驗十、gcc靜態庫引用動態庫

mod1是動態庫,mod2是靜態庫並且引用mod1,,主模組引用mod2
目錄結構:
    mod1
        m1.h
        m1.c
    mod2
        m2.h
        m2.c
    main.c

程式碼:
m1.h
    

#ifndef MOD1
    #define MOD1
    int func1(int,int);
#endif


m1.c
    

int func1(int x,int y)
{
    return x+y;
}


m2.h
    

#ifndef MOD2
    #define MOD2
    int func2(int,int);
#endif


m2.c
    

int func1(int,int);
int func2(int x,int y)
{
     int res=func1(x,y);
     return res+3;
}


main.c
    

#include <stdio.h>
#include <stdlib.h>

int func2(int,int);
int main()
{
    int a=15,b=2;
    printf("func2(a,b)=%d\n",func2(a,b));
    system("pause");
}


實現思路:
    首先將mod1編譯為m1.dll
    然後將mod2編譯為m2.obj並將m2.obj打包為m2.lib
    最後編譯main.c並引用m2.lib和m1.dll生成main.exe
    將m1.dll拷貝至main.exe同目錄,雙擊執行即可看到效果

實驗十一、gcc動態庫引用靜態庫

mod1是靜態庫,mod2是動態庫並且引用mod1,主模組引用mod2
目錄結構:
mod1
    m1.h
    m1.c
mod2
    m2.h
    m2.c
main.c
程式碼:
m1.h
    

#ifndef MOD1
    #define MOD1
    int func1(int,int);
#endif


m1.c
    

int func1(int x,int y)
{
      return x+y;
}


m2.h
    

#ifndef MOD2
#define MOD2
    int func2(int,int);
#endif


m2.c
    

int func1(int,int);
int func2(int x,int y)
{
      int res=func1(x,y);
      return res+6;
}


main.c
  

#include <stdio.h>
#include <stdlib.h>

int func2(int,int);
int main()
{
     int a=12,b=3;
     printf("func2(a,b)=%d\n",func2(a,b));
     system("pause");
}


實現思路:
    首先將m1.c編譯為m1.obj並打包為m1.lib
    然後將m2.c編譯為m2.dll(gcc -shared m2.c ../mod1/m1.lib -o m2.dll)
    最後編譯主模組,引用了m2.dll,將m2.dll拷貝至main.exe同目錄,雙擊main.exe即可看到效果
1.將m1.c編譯為m1.obj並打包為m1.lib
    cd mod1
    gcc -c m1.c -o m1.obj
    ar -crv m1.lib m1.obj
2.將m2.c編譯為m2.dll
    cd ../mod2
    gcc -shared m2.c ../mod1/m1.lib -o m2.dll
3.編譯main.c
    cd ..
    gcc main.c mod2/m2.dll -o main.exe
    然後將m2.dll拷貝至main.exe同目錄,雙擊main.exe即可看到效果