如果你对工具链的配置不熟悉,可以参考交叉编译工具链配置,接下来,我们开始编译我们的代码。
1 编译过程
文件名及其产物:
后缀 | 描述 | 后缀 | 描述 |
---|---|---|---|
.c | C 源文件 | .s/.S | 汇编语言源文件 |
.C/.cc/.cxx/.cpp | C++ 源文件 | .o/.obj | 目标文件 |
.h | C/C++ 头文件 | .a/.lib | 静态库 |
.i/.ii | 经过预处理的 C/C++ 文件 | .so/.dll | 动态库 |
2 编译命令
● -dumpspecs :显示所有内置规范字符串。
● -dumpversion :显示编译器的版本。
● -dumpmachine :显示编译器的目标处理器。
● -print-search-dirs :显示编译器搜索路径中的目录。
● -print-libgcc-file-name :显示编译器配套库的名称。
● -print-file-name= :显示库 的完整路径。
● -print-prog-name= :显示编译器组件 的完整路径。
● -print-multiarch :显示目标的规范化 GNU 三元组,用作库路径中的一个组件。
● -print-multi-directory :显示 libgcc 版本的根目录。
● -print-multi-lib :显示命令行选项和多个库搜索目录之间的映射。
● -print-multi-os-directory :显示操作系统库的相对路径。
● -print-sysroot :显示目标库目录。
● -print-sysroot-headers-suffix :显示用于查找标题的 sysroot 后缀。
● -Wa, :将逗号分隔的 传递给汇编器(assembler)。
● -Wp, :将逗号分隔的 传递给预处理器(preprocessor)。
● -Wl, :将逗号分隔的 传递给链接器(linker)。
● -Xassembler :将 传递给汇编器(assembler)。
● -Xpreprocessor :将 传递给预处理器(preprocessor)。
● -Xlinker :将 传递给链接器(linker)。
● -save-temps :不用删除中间文件。
● -save-temps= :不用删除指定的中间文件。
● -no-canonical-prefixes :在构建其他 gcc 组件的相对前缀时,不要规范化路径。
● -pipe :使用管道而不是中间文件。
● -time :为每个子流程的执行计时。
● -specs= :使用 的内容覆盖内置规范。
● -std= :假设输入源为 。
● --sysroot= :使用 作为头文件和库的根目录。
● -B :将 添加到编译器的搜索路径。
● -v :显示编译器调用的程序。
● -### :与 -v 类似,但引用的选项和命令不执行。
● -E :仅执行预处理(不要编译、汇编或链接)。
● -S :只编译(不汇编或链接)。
● -c :编译和汇编,但不链接。
● -o :指定输出文件。
● -pie :创建一个动态链接、位置无关的可执行文件。
● -I :指定头文件的包含路径。
● -L :指定链接库的包含路径。
● -shared :创建共享库/动态库。
● -static :使用静态链接。
● --help :显示帮助信息。
● --version :显示编译器版本信息。
以下面demo为例:
#include <iostream>
using namespace std;
int main()
{
std::cout << "gcc Demo";
cout << endl;
}
● 命令:g++ main.cpp
● 结果:a.out
默认编译出来的就是a.out。
如果想指定输出的文件名,则需要需要加上-o;
● 命令:g++ main.cpp -o test
● 结果:test
如果只进行预处理,则用- E命令
● 命令:g++ -E src/Main.cpp -o test.i
● 结果:test.i
如果只执行预处理和编译,则输出汇编文件(.s)
● 命令:g++ -S Main.cpp
● 结果:Main.s
如果想换成输出文件名,则用-o命令。
那么.i文件也可以生成.s文件
● 命令:g++ -S test.i -o test.s
● 结果:test.s
也可以将.i和.s文件生成.o文件:
● 命令: g++ test.i -o new.o
g++ test.s -o new.o
● 结果:new.o
3 静态库生成和使用
分为两步:第一步:生成.o文件;第二步:生成.a文件。
用下面的代码做演示:
class Asr
{
public:
void start();
};
#include<iostream>
#include "Asr.h"
void Asr::start()
{
std::cout << "this is start function!";
}
#include <iostream>
#include"Asr.h"
using namespace std;
void show();
int main()
{
std::cout << "gcc Demo";
cout << endl;
Asr *a = new Asr();
a->start();
}
从上面可以看出Main.cpp调用了Asr.h中的start函数。现在想通过命令进行编译成可执行文件。
● 命令:g++ Asr.cpp Main.cpp -o main
● 结果:main
执行./main
gcc Demo
this is static lib!%
如果把Asr.cpp做成库,这样的话就可以在其他地方方便的使用它了。库分为静态库和动态库。
生成.o文件
● 命令:g++ -c Asr.cpp
● 结果:Asr.o
生成.a文件
● 命令:ar rcs libasr.a Asr.o
● 结果:libasr.a
将静态库进行连接,
命令:g++ -o dis src/Main.cpp libasr.a
结果:dis
运行./dis得到
gcc Demo
this is static lib!%
4 动态库生成与使用
● 命令:g++ Asr.cpp -shared -fPIC -o asr.so
● 结果:asr.so
连接
● 命令:g++ -o asr src/Main.cpp asr.so
● 结果:asr
执行./asr
gcc Demo
this is static lib!%
参考:
gcc 编译命令详解及最佳实践