2.ubuntu下使用g++编译cpp工程

C++编译中相关文件后缀文件含义
.a静态库(archive)
.C .c .cc .cp .cpp .cxx .c++c++源代码(需要编译预处理)
.hC或C++源代码的头文件
.iiC++源代码(不需要编译预处理的)
.o对象文件
.s汇编语言代码
.so动态库
标注C++系统可执行程序

ESc
iiso

gcc/g++编译过程

编译阶段命令阶段后的产物
C源代码
预处理gcc -E替换了宏的c源程序(即没有#define;#include),删除了注释
编译gcc -S汇编源程序
汇编gcc -c目标文件,二进制文件,允许有不在文件中的外部变量、函数
链接gcc可执行文件,一般由多个目标文件或库连接而成,二进制文件,有变量、函数都必须找得到

1.单个文件生成可执行程序

  • 语法1:g++ *.cpp 生成默认可执行文件a.out;
  • 语法2: g++ *.cpp -o runfile -o修改生成可执行文件名字;
    下面通过遵循源码的命名规范并指定对应库的名字,使用gcc编译C++程序;
  • 语法3: gcc *.cpp -lstdc++ -o runfile
    程序g++时将gcc默认设为C++的一个特殊版本,链接时自动使用c++标注库而不是有C标注库;

选项 -l(ell)通过添加前缀lib和后缀.a将跟随它的名字变换为库的名字:libstadc++.a,而后在标准库路径中查找该库。gcc编译过程和输出文件与g++完全相同的;

2.多个源文件生成可执行文件

//speak.h
#include <iostream>
class Speak
{
public: 
 void sayHello(const char *);
}; //注意有个分号
//speak.cpp
#include "speak.h"
void Speak::sayHello(const char *str)
{
std::cout<<"Hello "<<str<<"\n";
}

//hellospeak.cpp
#include "speak.h"
int main(int argc,char *argv[])
{
Speak speak;
speak.sayHello("world");
return (0);
}

  • 使用命令:g++ hellospeak.cpp speak.cpp -o hellospeak;

上面将两个源码文件编译链接成一个单一的可执行程序;
上述没有提到"speak.h",那是因为在speak.cpp中包含了#include “speak.h”, 它的意思时搜索系统头文件目录之前先在当前目录中搜索文件"speak.h";

3.预处理

  • 选项-E使用使得g++将源代码用编译预处理器处理后,不再执行其它动作。下面将预处理源码文件hellospeak.cpp;并将结果显示在标注输出中;
  • g++ -E hellospeak.cpp

源码文件只有几行,但是预处理后的版本有1200多行,这是因为头文件iostream被包含进来了;而且它有包含了其它头文件;除此还有若干个处理输入和输出的类的定义;
预处理过得文件GCC后缀为.ii,可以通过-o选项来生成;

  • gcc -E hellospeak.cpp -o helloworld.ii

4.编译生成汇编代码

  • 选项-S指示将编译器将程序编译成汇编语言,输出汇编语言代码后结束;生成汇编文件hellospeak.s
  • g++ -S hellospeak.cpp

5.汇编:源文件生成对象文件(目标代码、机器代码)

  • 选项-c用来告诉编译器编译源代码但是不要执行链接,输出结果为对象文件。文件默认名为与源文件名相同,只是将其后缀变为.o;
  • 下面命令将编译源码文件为对象文件,并将其链接成单一的可执行程序;
  1. g++ -c hellospeak.cpp
  2. g++ -c speak.cpp
  3. g++ hellospeak.o speak.o -o hellospeak
  • 选项-o不仅可以用来命名可执行文件名,也可以用来命名编译器输出的其它文件名;
  • 如g++ -c hellospeak.cpp -o hp.o

6.创建静态库

  • 静态库是编译器生成的一系列对象文件的集合。
  • 链接一个程序时使用库中的对象文件还是目录中的对象文件都是一样的;
  • 库中的成员函数包含普通函数,类的定义,类的对象实例等等。
  • 静态库的另一个名字叫归档文件(archive),管理这种归档文件的工具叫ar;

下面先创建两个对象模块,然后用其生成静态库;
头文件say.h包含sayHello()函数的原型和类Say的定义;

//say.h
#include <iostream>
void sayhello(void);
class Say{
private:
char *string;
public:
Say(char *str)
{
string =str;
}
void sayThis(const char *str)
{
std::cout<<str<<"from a static library\n";
}
void sayString(void);

};
  • 源码文件1:
  • 文件say.cpp是我们需要加入到静态库中的两个对象文件之一的源码;
  • 它包含Say类中定义的sayString()函数的定义体;类Say的一个实例librarysay的声明;
//say.cpp
#include "say.h"
void Say::sayString()
{
std::cout<<string<<"\n";
}
Say librarysay("Library instance of Say!");
  • 源码文件2:
  • sayhello.cpp是我们要加入到的静态库中的第二个文件的源码;
  • 它包含函数sayhello()的定义:
//sayhello.cpp
#include "say.h"
void sayhello()
{
std::cout<<"hello from a static library\n";
}
  • 将源码文件编译成对象文件,命令ar将其存进库中;
g++ -c sayhello.cpp
g++ -c  say.cpp
ar -r libsay.a sayhello.o say.o

程序ar配合一个参数-r创建一个新库libsay.a;并将命令行了列出的对象文件插入;如果库存在,将用新模块替换原来的模块;

  • 主程序saymain.cpp 调用libsay.a中的代码:
//saymain.cpp
#include "say.h"
int main(int argc,char *argv[])
{
extern Say librarysay; //可以置于变量或函数前,以标示变量或函数的定义在别的文件
Say localsay=Say("Local intstance of Say");
sayhello();
librarysay.sayThis("howdy");
librarysay.sayString();
localsay.sayString();
return(0);
}
  • 该程序使用如下命令来编译链接:
g++ saymian.cpp libsay.a -o saymain
  • 输出结果:
    hello from a static library
    howdyfrom a static library
    Library instance of Say!
    Local intstance of Say

内容来源:linux下使用g++编译cpp工程

7.反汇编工具objdump

  • objdump是Linux下的一个反汇编工具,能够反汇编目标文件、可执行文件。
  • 选项:
  • objdump -f 显示头文件信息
  • objdump -d 反汇编需要执行的指令的那些section
  • objdump -D 与-d类似,但是反汇编所有的section
  • objdump -h 显示Section Header信息;
  • objdump -x 显示全部Header信息;
  • objdump -s 将所有段的内容以十六进制的方式打印出来
#include<stdio.h>
int i = 1;
int main(void)
{
    ++i;
    printf("%d\n",i);
    return 0;
}
  • 生成汇编程序:gcc -S -o main.s main.c
  • 反汇编:
    gcc -c -o main.o main.c
    objdump -s -d main.o > main.o.txt
  • 可执行文件的反汇编:
gcc -o main main.c
objdump -s -d main > main.txt

linux下的目标文件(默认扩展为.o)和可执行的文件都是ELF格式的二进制文件,类似的,windows下visual C++编译出的目标文件(扩展名为.obj)采用COFF格式,而可执行文件(扩展名是.exe)采用PE格式,ELF和PE都是从COFF发展而来的;
因为Linux下目标文件和可执行文件的内容格式一样,所以objdump既可以反汇编可执行文件也可以反汇编目标文件;

参考

©️2020 CSDN 皮肤主题: 黑客帝国 设计师:上身试试 返回首页