c语言模块化开发(GCC编译实例)

c语言编译步骤,即一个*.c文件是如何一步步成为*.exe的?

参见:C语言真正的编译过程

window下GCC(minGW)的安装

参见:MinGW下载安装

GCC常见命令:

参见:Linux GCC常用命令

本人理解的c语言编译过程、中间文件、常用命令

c语言模块化开发(GCC编译实例)_第1张图片

 

本次实验环境:

window7、minGW

实验代码:https://download.csdn.net/download/u010476739/10800828

实验一、编译单个文件

代码 test.c

#include 
#include 
int main()
{
	printf("hello\n");
	system("pause");
}

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

c语言模块化开发(GCC编译实例)_第2张图片

编译结果:

c语言模块化开发(GCC编译实例)_第3张图片

双击执行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 
#include 
#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 
 #include 

#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 
#include 

#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 
#include 
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 
#include 

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 
#include 
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 
 #include 

 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 
#include 

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 
#include 

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 
#include 

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即可看到效果
    
    
    

你可能感兴趣的:(c语言模块化开发(GCC编译实例))