NDK<第三篇>:gcc和g++(windows环境)
1、wingw环境配置
【1】下载wingw
MinGW-w64 - for 32 and 64 bit Windows - Browse Files at SourceForge.net
image.png下载完成之后解压。
【2】配置环境变量
下载之后,将 mingw64
目录的 bin
目录的路径配置到环境变量中。
并且将 mingw32-make
文件改成 make
。
2、gcc和g++的使用
【1】预处理
不输出文件:
gcc -E Hello.cpp(同样适用于c文件)
或
g++ -E Hello.cpp(同样适用于c文件)
输出文件:(将预处理信息输出到Hello.i)
gcc -E Hello.cpp -o Hello.i(同样适用于c文件)
或
g++ -E Hello.cpp -o Hello.i(同样适用于c文件)
【2】转换为汇编文件
不指定预处理文件:
gcc -S Hello.cpp // 生成Hello.s文件(同样适用于c文件)
gcc -S Hello.cpp -o Hello.s // 生成Hello.s文件(同样适用于c文件)
或
g++ -S Hello.cpp // 生成Hello.s文件(同样适用于c文件)
g++ -S Hello.cpp -o Hello.s // 生成Hello.s文件(同样适用于c文件)
指定预处理文件:
gcc -S Hello.i // 生成Hello.s文件(同样适用于c文件)
gcc -S Hello.i -o Hello.s // 生成Hello.s文件(在windows上测试失败,并没有生成Hello.s,c文件也同样如此)
或
g++ -S Hello.i // 生成Hello.s文件(同样适用于c文件)
g++ -S Hello.i -o Hello.s // 生成Hello.s文件(同样适用于c文件)
【3】编译(生成目标文件)
不指定汇编文件:
gcc -c Hello.cpp // 生成目标文件Hello.o(同样适用于c文件)
gcc -c Hello.cpp -o Hello.o // 生成目标文件Hello.o(同样适用于c文件)
或
g++ -c Hello.cpp // 生成目标文件Hello.o(同样适用于c文件)
g++ -c Hello.cpp -o Hello.o // 生成目标文件Hello.o(同样适用于c文件)
指定汇编文件:
gcc -c Hello.s // 生成目标文件Hello.o(同样适用于c文件)
gcc -c Hello.s -o Hello.o // 生成目标文件Hello.o(同样适用于c文件)
或
g++ -c Hello.s // 生成目标文件Hello.o(同样适用于c文件)
g++ -c Hello.s -o Hello.o // 生成目标文件Hello.o(同样适用于c文件)
【4】链接(生成可执行文件)
不指定目标文件:
gcc Hello.cpp // 链接失败,不能生成可执行文件(适用于c文件,生成a.exe)
gcc Hello.cpp -o Hello // 链接失败,不能生成可执行文件(适用于c文件,生成Hello.exe)
gcc Hello.cpp -o Hello.exe // 链接失败,不能生成可执行文件(适用于c文件,生成Hello.exe)
gcc -o Hello Hello.cpp // 链接失败,不能生成可执行文件(适用于c文件,生成Hello.exe)
或
g++ Hello.cpp // 生成a.exe文件(适用于c文件,生成a.exe)
g++ Hello.cpp -o Hello // 生成Hello.exe文件(适用于c文件,生成Hello.exe)
g++ Hello.cpp -o Hello.exe // 生成Hello.exe文件(适用于c文件,生成Hello.exe)
g++ -o Hello Hello.cpp // 生成Hello.exe文件(适用于c文件,生成Hello.exe)
g++ -o Hello.exe Hello.cpp // 生成Hello.exe文件(适用于c文件,生成Hello.exe)
指定目标文件:
gcc Hello.o // 链接失败,不能生成可执行文件(适用于c文件,生成a.exe)
gcc Hello.o -o Hello // 链接失败,不能生成可执行文件(适用于c文件,生成Hello.exe)
gcc Hello.o -o Hello.exe // 链接失败,不能生成可执行文件(适用于c文件,生成Hello.exe)
或
g++ Hello.o // 生成a.exe文件(适用于c文件,生成a.exe)
g++ Hello.o -o Hello // 生成Hello.exe文件(适用于c文件,生成Hello.exe)
g++ Hello.o -o Hello.exe // 生成Hello.exe文件(适用于c文件,生成Hello.exe)
【5】执行可执行文件
.\Hello
或
.\Hello.exe
3、gcc/g++多文件多目录
同目录多文件的情况下:
gcc Hello.c A.c B.c -o Hello
或使用通配符:
gcc *.c -o Hello
如果将头文件放入单独的文件夹中(header文件夹):
gcc -I header *.c -o Hello
4、gcc/g++常用编译选项
【1】-o FILE: 指定输出文件名,在编译为目标代码时,这一选项不是必须的。
如果FILE没有指定,缺省文件名是a.out;
【2】-c: 只编译生成目标文件,不链接;
【3】-Wall: 允许发出gcc能提供的所有有用的警告,也可以用-W(warning)来标记指定的警告;
g++ -W Hello.o -o Hello
g++ -Wall Hello.o -o Hello
【4】-Werror: 把所有警告转换为错误,以在警告发生时中止编译过程;
g++ -Werror Hello.o -o Hello
【5】-v: 显示在编译过程的每一步中用到的命令;
g++ -v Hello.o -o Hello
【6】-static: 链接静态库,即执行静态链接,g++默认是链接动态库,如果需要链接静态库需要使用本选项进行指定;
【7】-g: 在可执行程序中包含标准调试信息, 使用该选项生成的可执行文件可以用gdb工具进行调试;
【8】-w: 关闭所有警告,建议不要使用该选项
【9】-shared: 生成共享目标文件。通常用在建立共享库时;
【10】-On: 这是一个优化选项,如果在编译时指定该选项,则编译器会根据n的值(n取0到3之间)对代码进行不同程度的优化,其中-O0 表示不优化,n的值越大,优化程度越高;
【11】-L: 库文件依赖选项,该选项用于指定编译的源程序依赖的库文件路径,库文件可以是静态链接库,也可以是动态链接库,linux系统默认的库路径是/usr/lib,如果需要的库文件不在这个路径下就要用-L指定
g++ foo.cpp -L/home/lib -lfoo -o foo
【12】-I: 该选项用于指定编译程序时依赖的头文件路径,linux平台默认头文件路径在/usr/include下,如果不在该目录下,则编译时需要使用该选项指定头文件所在路径
gcc foo.cpp -I/home/include -o foo
5、动态库和静态库
【1】生成动态库
动态库在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库。Linux中后缀名为“.so”。
动态库节省空间:如果一个动态库被两个程序调用,那么这个动态库只需要在内存中。
【1】分步骤生成动态库
g++ -fPIC -c Hello.cpp -o Hello.o
g++ -shared -o libHello.so Hello.o
【2】一步生成动态库
g++ -fPIC -shared -o libHello.so Hello.o
或
g++ -fPIC -shared -o libHello.so Hello.cpp
【2】生成静态库
静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。Linux中后缀名为”.a”。
静态库节省时间:不需要再进行动态链接,需要调用的代码直接就在代码内部。
ar -crv libHello.a Hello.o
或
ar -crv libHello.a Hello.cpp
【3】链接静态库(生成可执行文件)
g++ Hello.cpp -o Hello -static -L. -l Hello
-L指定库目录,.表示当前目录。
-l Hello 指定libHello.a静态库。
【4】-I 添加搜索头文件的路径(大写i)
系统默认头文件搜索路径大致为
当前目录(如果是双引号包含的话) --> /usr/include --> /usr/local/include
// 添加/home/include 到搜索路径
g++ test.cpp -I/home/include
【5】-L 指定要链接的库所在目录,-l 指定路径寻找库文件
链接时库搜索路径 /lib --> /usr/lib -->/usr/local/lib
运行时库搜索路径 /lib --> /usr/lib
// -L 将/lib 添加到库搜索目录,
// -l 将 libmt.so 库文件链接到项目
g++ test.cpp -L/usr/local/lib -lfmt
【6】查看可执行文件符号
nm main
【7】默认优先使用动态库
gcc main.c -L. -lTest -o main
【8】强制使用静态库
#-Wl 表示传递给 ld 链接器的参数
#最后的 -Bdynamic 表示 默认仍然使用动态库
gcc main.c -L. -Wl,-Bstatic -lTest -Wl,-Bdynamic -o main
【9】打包 .a 到so
#打包 .a 到so
#--whole-archive: 将未使用的静态库符号(函数实现)也链接进动态库
#--no-whole-archive : 默认,未使用不链接进入动态库
gcc -shared -o libMain.so -Wl,--whole-archive libMain.a -Wl,--no-whole-archive
【10】其它命令
--sysroot=XX
使用XX作为这一次编译的头文件与库文件的查找目录,查找下面的 usr/include usr/lib 目录。
g++ --sysroot=C:\Users\94317\AppData\Local\Android\ndk\android-ndk-r20b\sysroot Hello.cpp
-isysroot XX
头文件查找目录,覆盖--sysroot ,查找 XX/usr/include
-isystem XX
指定头文件查找路径(直接查找根目录)
-IXX
头文件查找目录
优先级:
-I -> -isystem -> sysroot
【本章完...】