c語言模組化開發(GCC編譯例項)
c語言編譯步驟,即一個*.c檔案是如何一步步成為*.exe的?
參見:C語言真正的編譯過程
window下GCC(minGW)的安裝
參見:MinGW下載安裝
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即可看到效果