前言

mingw是gcc的windows版本,能够使用gcc的命令在windows环境下编译c/c++代码,本边文章就从零使用wingw的gcc来编译一个windows项目。并比较用visual studio编译的区别。


一、wingw编译的常用命令

头文件搜索路径:

“ ”引用的头文件:
1)先搜索当前目录
2)搜索 -I指定目录
3)收缩gcc的环境变量
CPATH:gcc和g++都适用
C_INCLUDE_PATH :gcc使用的环境变量
CPLUS_INCLUDE_PATH: g++使用的环境变量
windows中通过set CPATH=路径 设置临时的环境变量;通过windows编辑系统环境变量能够设置永久的环境变量,重启后生效
4) mingw内定的目录(包括常用的标准库头文件)
<>引用的头文件: 除了不搜索当前目录,其他都是一样的。自己写的头文件一般用“ ”,库的头文件一般用<>。

编译链接动态库搜索路径:

1)-L指定的路径
2)gcc环境变量指定的路径
LIBRARY_PATH
3) mingw中内定的目录(如c/c++标准库的动态库)

运行时动态库搜索路径:

1).exe所在目录
2)环境变量PATH
set PATH=%PATH%;动态库路径
3)mingw内定目录(链接标准库时gcc直接链接)
注意:通过实验LD_LIBRARY_PATH,-rpath在windows当中都不生效。要想在运行时不拷贝动态库,就要设置将动态库路径设置到PATH环境变量当中。

编译静态库

1)生成.o:gcc *.c -c
2) 将生成的.o文件打包:ar rcs static.lib *.o
3)更新符号表:randlib 静态库

编译动态库

1)生成.o:gcc *.c -c -fPIC (-fPIC编译位置独立的代码)
2)生成.dll和.lib,-shared表明生成动态库,-wl后面的内容是ld参数,需要传给ld,–out-implib生成动态库的导出库,-out-def生成.def文件(也可以不用生成)
gcc -shared -o shared.dll *.o -Wl,–out-implib,shared.lib,–out-def,shared.def
注意:-static选项用于在链接时优先选择静态库,比如链接的目录中同时有静态库和动态库,就会直接链接静态库。

编译可执行文件

gcc *.c -o app -I 头文件路径 -L 库路径 -lshared -lstatic -DDEBUG

二、Mingw编译工程

工程编译的脚本

本次编译的项目为之前的项目:https://blog.csdn.net/qq_36472340/article/details/126395749
.bat的一些常用命令:
del:删除文件
md:创建目录
copy:复制文件
set:设置变量
cd:切换目录
%~dp0:当前目录
%PATH%:获取PATH变量当中的值
创建函数:
:函数名(函数开始)
goto eof (函数结束)
调用函数:
call:函数名 (调用函数要在创建函数的开始位置)

项目的批处理脚本如下:

@echo off
for %%d in (lib,include,bin) do (
 if exist %%d (
	cd %%d
	del /q/a/f *.*
	cd ..
 ) else (
	md %%d
 )
)

if "%1" == "-s" (
	call:build_static
) else if  "%1" == "-r" (
	call:build_shared
) else if  "%1" == "-a" (
	call:build_static
	call:build_shared
	call:build_exe
) else (
	call:help
)
@REM complie static lib
:build_static
set STATIC_SRC= %~dp0src\static\*.*
set STATIC_INCLUDE= %~dp0src\static\
set STATIC_LIB_NAME=add.lib
cd ./lib
g++ %STATIC_SRC% -c -I %STATIC_INCLUDE%
ar rcs %STATIC_LIB_NAME% *.o
ranlib %STATIC_LIB_NAME%
del /q/a/f *.o
cd ..
copy %~dp0src\static\multi.h %~dp0include\
goto:eof
	
@REM complie shared lib
:build_shared
set SHARED_SRC=%~dp0src\shared\*.*
set SHARED_INCLUDE=%~dp0src\shared\
set SHARED_LIB_NAME=multi
cd ./lib
g++ %SHARED_SRC% -c -I %SHARED_INCLUDE% -fPIC -DEXPORTS
g++ -shared -o %SHARED_LIB_NAME%.dll *.o -I %SHARED_INCLUDE% -DEXPORTS -Wl,--out-implib,%SHARED_LIB_NAME%.lib,--output-def,multi.def
del /q/a/f *.o
cd ..
copy %~dp0src\shared\add.h  %~dp0include\
goto:eof

@REM complie excutable
:build_exe
set MAIN_SRC=%~dp0src\main\*.cpp
set MAIN_NAME=app
set INCLUDE=%~dp0include\
set LIB_DIR=%~dp0lib\

cd ./bin

set PATH=%PATH%;C:\Users\Administrator\Desktop\gcc_testa\lib
g++ %MAIN_SRC% -o %MAIN_NAME% -L %LIB_DIR% -lmulti -ladd -DDEBUG -I %INCLUDE%
cd ..
goto:eof
	
:help
echo -s build_static
echo -r build_shared
echo -a build_exe
echo -c clean
echo -* help
goto:eof

Mingw和visual c++编译的区别

1)Mingw在导出动态库时加不加_declspec(dllexport)这个都能够导出,而visual c++必须加上这个关键字才能导出。
Mingw不加_declspec(dllexport)关键字的符号表:
EXPORTS
_Z3addii @1
_Z3subii @2
_Z9print_addi @3
_Z9print_subi @4
Mingw加上_declspec(dllexport)关键字的符号表:
EXPORTS
_Z3addii @1
_Z3subii @2
可见:加上关键字导出库的符号表就只有加上关键字的函数,而不加关键字导出库的符号表是动态库里面的所有函数。
2)visual c++导出的函数表
?add@@YAHH@Z
?sub@@YAHH@Z
可见:visual c++和MinGw g++导出的函数表是不相同的,每个编译器对函数名称都做了特殊处理,所以不同编译器编译的库不能够相互使用;同时gcc和g++编译也对不同函数名进行了不同的处理,在cpp文件中也不能直接是有c文件中的函数。
cpp中要使用c语言,则要将使用的c函数进行如下声明,这样cpp才能知道函数是按照c语言进行编译的。

#ifdef __cplusplus
extern "C" {
#endif
c语言中的函数定义;
#ifdef __cplusplus
}
#endif

总结

MingW中的gcc编译选项和linux下面的编译大体相同,只是windows编译的脚本是.bat文件,linux下编译的脚本是shell脚本。Mingw在编译动态库的时候不用_declspec(dllexport)也能导出动态库,为了windows平台的统一,在编译windows平台下的代码最好都加上_declspec(dllexport)关键字。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐