LINUX下文件编译
body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;} th{border: 1px solid gray; padding: 4px; background-color: #DDD;} td{border: 1px solid gray; padding: 4px;} tr:nth-child(2n){background-color: #f8f8f8;}
Linux 下文件编译与调试
|
gcc/g++编译器
对于.c格式的 C文件,可以采用gcc或g++编译
对于 .cc、.cpp格式的C++文件,应该采用g++进行编译
|
常用的选项:
-c 表示编译源文件
-o 表示输出目标文件
-g 表示在目标文件中产生调试信息,用于gdb调试
-D <宏定义> 编译时将宏定义传入进去
-Wall 打开所有类型的警告。
|
|
| 1. gcc编译过程:预编译->编译->汇编->链接 |
(1)预处理:预处理器将对源文件中的宏进行展开。
(2)编译:gcc将c文件编译成 汇编文件。
(3)汇编:汇编器as将汇编文件编译成机器码。
(4)链接:将目标文件和外部符号进行连接,得到一个可执行二进制文件。
//test.c
|
|
|
(1)预处理: gcc –E test.c -o test.i
我们用 cat 查看 test.i 的内容如下:int main() int x=(1+2); return 0;我们可以看到,文件中宏定义NUMBER出现的位置被(1+2)替换掉了,其它的内容保持不变。
预处理阶段:对包含的头文件(#include)和宏定义(#define、#ifdef等)进行处理 |
(2)编译:gcc -S test.i –o test.s 通过 cat test.s 查看 test.s 的内容为代码。
编译阶段:检查代码规范性、语法错误等,在检查无误后把代码翻译成汇编语言
|
|
|
(3)汇编:as test.s -o test.o 利用as将汇编文件编译成机器码。得到输出文件为 test.o。test.o 中为目标机器上的二进制文件. 用 nm 查看文件中的符号: nm test.o 输出如下:0000000000000000 T main。既然已经是二进制目标文件了,能不能执行呢?试一下 ./test.o,提示 cannotexecute binary file.T表示这个符号属于代码。
//test.o 得先加一个执行权限
|
(4)链接: gcc test.o –o test ,将所有的.o文件链接起来生产可执行程序。 链接阶段:将.s的文件以及库文件整合起来链接为可执行程序 |
| gcc所支持后缀名: | gcc常用选项: |
| gcc库选项: |
gcc警告选项: |
| file 文件名 看对应文件类型 |
|
//test1.c
#include<stdio.h>
int main()
{
#ifdef meihao
printf("define meihao\n");
#else
printf("not define meihao\n");
#endif
printf("main exit\n");
}
|
gcc -E test1.c -o test1.i |
|
静态库是目标文件.a 的归档文件(格式为libname.a)。如果在编译某个程序时链接静态库,则链接器将会搜索静态库并直接拷贝该程序的可执行二进制文件到当前文件中;
静态库将会整合到程序中,在程序执行时不用加载静态库。 因此,静态库会使你的程序臃肿并且难以升级,但比较容易部署。而动态库会使你的程序轻便易于升级但难以部署。
|
动态库(格式为 libname.so[.主版本号.次版本号.发行号])。在程序编译时并不会被链接到目标代码中,而是在程序运行时才被载入。
动态库只在执行时才被链接使用,不是直接编译为可执行文件,并且一个动态库可以被多个程序使用故可称为共享库。 |
|
| 创建静态库: >gcc -c add.c //编译add.c源文件生成add.o目标文件 >ar -crsv libadd.a add.o //对目标文件*.o进行归档,生成lib*.a,此处lib要写;命令参数: c 创建一个库。不管库是否存在,都将创建。 r 代替库中现有的文件或者插入新的文件 s 写入一个目标文件索引到库中,或者更新一个存在的目标文件索引 v 输出详细信息 a - add.o >su #cp ./libadd.a /lib //拷贝到标准程序设计库 >gcc main.c -w -o main -ladd >./main 1 2
sum=3
>gcc -c add.c
>ar -crsv libadd.a add.o
a - add.o >gcc main.c -w -o main -L./ -ladd //不要忘记-L后面的那个./ ;即在库文件的搜索路径中添加当前路径 -ladd表示链接库文件libadd.a/.so
>./main 1 2
sum=3 |
创建动态库:
>gcc -fPIC -Wall -c add.c //编译,允许发出警告,生成使用相对地址的位置无关的目标代码
>gcc -shared -o libadd.so add.o //生成库文件libadd.so
>su
#cp ./libadd.so /lib
#exit //拷贝到 /lib 库中
>gcc main.c -w -o main -ladd
>./main 1 2
sum=3
在运行main前,需要注册动态库的路径。
方法有3种:
▶修改/etc/ld.so.conf
▶修改LD_LIBRARY_PATH环境变量
▶将库文件拷贝到/lib或者/usr/lib下(系统默认搜索库路径)。 |
|
| //add.c int add(int a,int b)
{
return a+b;
}
|
//main.c #include<stdio.h>
#include<stdlib.h>
void main(int argc,char* argv[])
{
if(argc!=3)
{
printf("error args\n");
return;
}
int i=atoi(argv[1]);
int j=atoi(argv[2]);
printf("sum=%d\n",add(i,j));
}
|
程序调试
|
gdb常用命令
Linux 包含了一个叫gdb的调试程序。gdb可以用来调试 C 和 C++ 程序。在程序编译时用 -g 选项可打开调试选项,表示在目标文件中产生调试信息,用于gdb调试;
>gcc test1.c -Wall -g -o test //(—g和—o要挨在一起)(—g和—c要挨在一起)
>gdb ./test
|
| >ulimit -c unlimited |
>gcc test3.c -w -o test3
>gdb ./test3 core
//l 输出错误行代码,bt 打开调用栈查看自己错误行代码, q 退出;
|
| //test3.c #include<stdio.h>
int add(int a,int b)
{
return a+b;
}
int main(int argc,char **argv)
{
int i,j,sum;
i=atoi(argv[1]);
j=atoi(argv[2]);
sum=add(i,j);
printf("sum=%d\n",sum);
}
|
gcc对代码进行优化通过选项“-On”来控制优化级别(n是整数)。不同的优化级别对应不同的优化处理工作。如使用优化选项“-O1”主要进行线程跳转和延迟退栈两种优化。使用优化选项“-O2”除了完成所有“-O1”级别的优化之外,还要进行一些额外的调整工作,如处理其指令调度等。选项“-O3”则还包括循环展开或其他一些与处理器特性相关的优化工作。虽然优化选项可以加速代码的运行速度,但对于调试而言将是一个很大的挑战。因为代码在经过优化之后,原先在源程序中声明和使用的变量很可能不再使用,控制流也可能会突然跳转到意外的地方,循环语句也有可能因为循环展开而变得到处都有,所有这些对调试来讲都是不好的。所以在调试的时候最好不要使用任何的优化选项,只有当程序在最终发行的时候才考虑对其进行优化。
通常用的是-O2
|
LINUX下文件编译的更多相关文章
- 嵌入式之:Linux下文件编译过程
本文主要三个部分:1.GNU GCC简介 2.C/C++交叉编译器arm-elf-gcc 3.make文件,用于工程管理 部分一:GNU GCC简介: 该编译器基本功能: (1)输出预处理后的文件(展 ...
- dos2unix,去掉Linux下文件中的^M
Windows系统下使用VS2010编写好的CPP文件,想放到Linux上进行编译.发现Linux上文件中的每行代码末尾都跟着^M这个符号. 为什么同一份文件在windows上和Linux上显示的不一 ...
- ACE-6.1.0 linux 下的编译与安装步骤
ACE-6.1.0 linux 下的编译与安装步骤 引用至http://www.cnblogs.com/liangxiaxu/archive/2013/03/07/2948417.html 1.从 ...
- linux 下文件误删恢复
linux 下文件误删恢复 0x01 事件背景 某天晚上写代码的时候,本来想删除当前目录下一个叫xxx的文件夹 rm -rdf ./xxx/*, 结果光顾着和人说话,一不留神手贱把命令敲成了rm -r ...
- FFmpeg在Linux下安装编译过程
转载请把头部出处链接和尾部二维码一起转载,本文出自:http://blog.csdn.net/hejjunlin/article/details/52402759 今天介绍下FFmpeg在Linux下 ...
- Linux下nginx编译安装教程和编译参数详解
这篇文章主要介绍了Linux下nginx编译安装教程和编译参数详解,需要的朋友可以参考下 一.必要软件准备1.安装pcre 为了支持rewrite功能,我们需要安装pcre 复制代码代码如下: # y ...
- linux下将编译错误输出到一个文本文件
linux下将编译错误输出到一个文本文件 command > filename 把把标准输出重定向到一个新文件中 command > > filename 把把标准输出重定向到一个文 ...
- 从四个问题透析Linux下C++编译&链接
摘要:编译&链接对C&C++程序员既熟悉又陌生,熟悉在于每份代码都要经历编译&链接过程,陌生在于大部分人并不会刻意关注编译&链接的原理.本文通过开发过程中碰到的四个典型 ...
- Linux下文件的三种时间戳
Linux下文件的三种时间标记 三种时间对应关系表 column column column 访问时间 Access atime 修改时间 Modify mtime 状态改动时间 Change cti ...
随机推荐
- [js高手之路]从零开始打造一个javascript开源框架gdom与插件开发免费视频教程连载中
百度网盘下载地址:https://pan.baidu.com/s/1kULNXOF 优酷土豆观看地址:http://v.youku.com/v_show/id_XMzAwNTY2MTE0MA==.ht ...
- ElfJS从入门到精通(一)
介绍 Elf.js是一个简洁的高效的JavaScript框架.它不仅高度重视用户的体验,也高度重视开发者的体验.在实现当今主流技术的同时,以尽可能原生态的形式展现出来.在如今花样繁多的框架中,你是否感 ...
- Hyperledger Fabric 本地运行的简单示例
环境: Ubuntu 16.04 go 1.7.4 版本: Fabric v1.0.0-alpha 本文主要目的就是让大家体验以下Fabric网络环境搭建的具体过程,不基于集成化脚本手动搭建. 一.编 ...
- 【有上下界的网络流】ZOJ2341 Reactor Cooling(有上下界可行流)
Description The terrorist group leaded by a well known international terrorist Ben Bladen is bulidi ...
- 简易 bokeh 图像散景效果算法实现
bokeh百度百科的解释 摄影镜头光圈大小和拍摄距离决定了拍摄时的景深,相对于焦点位置,焦点前与焦点后的被拍摄物体会显得模糊,这个模糊区域被称为焦外.焦外具体的模糊程度还受到镜头中镜片单体和组合的物理 ...
- Android系统上如何实现easyconfig(airkiss)
刚买回来一个智能音箱和博联,需要给音箱和博联配置联网,音箱需要先打开蓝牙,然后在手机app中填写wifi的ssid和密码,通过蓝牙发送到音箱,音箱收到后连接到wifi. 博联就比较奇怪,进入联网模式以 ...
- 希尔排序(Go语言)
func ShellSort(num []int) { //increment相隔数量 ;increment> ;increment/= { //i序号较大的数组下标,i ,j进行比较 for ...
- ajax 处理请求回来的数据
比如接口 /test, 请求方式get, 请求过来的数据要处理在container 里,如下代码 $.get("/test", {}, function(result){ $(&q ...
- Python线程:线程的调度-守护线程
Python线程:线程的调度-守护线程 守护线程与普通线程写法上基本么啥区别,调用线程对象的方法setDaemon(true),则可以将其设置为守护线程.在python中建议使用的是thread. ...
- 类Unix平台程序调试
GNU Binutils GNU Binutils 建立main.c文件,内容如下: #include <stdio.h> void main() { int a = 5/0; } 编译m ...