环境:Ubuntu 10.04.3
安装gcc
他们的依赖关系如右图-----------
按照从内圈到外圈的顺序安装(gmp的安装需要m4,而mpfr依赖gmp,而mpc依赖gmp和mpfr,所以要先安装m4,其次装gmp,再其次mpfr,最后是mpc)
命令安装 :
(1) sudo apt-get build-dep gcc (2)sudo apt-get install build-essential
查看是否安装成功 gcc --version
编译
gcc -Wall Hello.c // 生成默认的 a.out
gcc -Wall Hello.c -o Hello
执行: ./a.out ./Hello
注: -Wall 会避免一些编译的错误,但是在gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3版本里面和以前的有点不同的
使用 ./ 表明当前目录 linux会执行从环境变量搜索, windows 会先从当前目录 然后环境变量
编译多个 .c源文件
gcc -Wall main.c hello.c -o Hello
双引号 "" 表示从当前目录查找头文件
<>表示先从系统目录 在从当前目录查找头文件
编译(源文件到 .o)-->链接(obj -> exe)
-c 只编译 (.o) gcc -Wall-c main.c hello.c
优点:便于只要修改一部分的时候可以单独编译生成 目标文件 .o
-o 链接 生成可执行文件
gcc main.o hello.o -o hello GCC 可以不考虑链接顺序 .但是有的是遵循 调用者 在前面 如 main.o hello.o
ls -ltr /usr/bin/ld 使用的是 ld 这个工具
引用外部裤(.a)
gcc -Wall calc.c /user/libm.a -o calc
或者 gcc -W calc.c -la -o calc
规则: -lName --> 'libName.a' 注意 这个库是标准库
链接库: 方向和链接目标文件一样
搜索目录
顺序
1. 命令行 -I -L
2. 设置环境变量 C_INCLUDE_PATH LIBRARY_PATH
3.默认的系统目录
推荐 第一种 命令行方式
//create or replace
//创建静态库
ar cr libName.a file1.o file2.o ... filen.o
//查看库的内容
ar t libName.a
例子:
mylib.h, fun1.c,fun2.c,main.c
ar cr libmylib.a fun1.o fun2.o
gcc -Wall main.c libmylib.a -o main
注: 在使用 库文件的时候 ,链接是有顺序的, 先 main.c 后 libmylib.a
cp libmylib.a /usr/lib 拷贝到系统目录
gcc -Wall main.c -lmylib -o main2
// alternative or absolute suggest
gcc -Wall main.c -L. -lmylib -o h5 or gcc -Wall main.c -L/home/anubis/dev/gcc -lmylib -o h5
//add to env path
anubis@ubuntu:~/dev/gcc$ env | grep LIB
anubis@ubuntu:~/dev/gcc$ export LIBRARY_PATH=/home/anubis/dev/gcc:$LIBRARY_PATH
anubis@ubuntu:~/dev/gcc$ env | grep LIB
LIBRARY_PATH=/home/anubis/dev/gcc:gcc -Wall main.c -lmylib -o h7
tree view
gcc -Wall -Iinclude -c main.c
gcc -Wall main.o -Llib -lmylib -o hello
shared library (.so)
在可执行文件保存的是调用方法的一个地址,(或者能找到这个指令的地址信息), 内存里面只有一个, 执行的时候 动态加载 节省内存和磁盘空间
如果有2个库一样,GCC优先会使用动态库
LD_LIBRARY_PATH 执行的时候得动态库
严格安装标准C编译
gcc -Wall -ansi -pedantic xxx.c
-Wall:
-Wcomment -Wformat -Wunused -Wimplicit -Wreturn-type
预处理:
int main(void)
{
#define MAX 1024+33
int a;
a=MAX * 2; //1024+33*2
}
宏定义只会机械的变换
#include <stdio.h>
int main(void)
{
#ifdef TEST
printf("Test define");
#endif
printf("end");
return 0;
}
gcc -Wall -DTEST pred.c -o pred
//GCC预定义的宏
cpp -dM /dev/null
替换 NUM : gcc -Wall -DNUM=123 test1.c -o test1
-E 只预处理
debugger说明
ulimit -c 查看是否产生 core dumped日志文件 生成的是 core.xx文件 core文件是进程在内存的里面影像
test:
gcc -Wall -g debuggerdemo.c
anubis@ubuntu:~/dev/gcc$ ulimit -c
0
anubis@ubuntu:~/dev/gcc$ ulimit -c unlimited
anubis@ubuntu:~/dev/gcc$ ulimit -c
unlimited
anubis@ubuntu:~/dev/gcc$ ./a.out
Segmentation fault (core dumped)
然后使用 gdb 调试
gdb ./a.out core
print p 查看 指针P的值
backtrace 查看调用关系
编译器是怎么工作的
有很多过程阶段 ,每个阶段使用到不同的, ld,等等 。。 形成 tool chain
step:
preprocessing ( to expand macros) --->cpp 生成 .i .ii cpp comp.c > comp.i
Compilation (from source code to assembly language) comp.s文件 gcc -Wall -S comp.i
assembly ( from assembly to mac-code) --> obj file LD .o .o as comp.s -o comp.o
linking (to create the final executable file ..) gcc comp.o -o comp
-save-tmps保存中间所有的文件
gcc -Wall -v comp.c 编译详细输出
anubis@ubuntu:~/dev/gcc$ file comp
comp: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
ELF表示可以执行文件
LSB least significant byte 表示低位在前 Intel AMDX86
MSB 高位在前 Motorola 680X0
anubis@ubuntu:~/dev/gcc$ nm comp T表示定义 U未定义(引用动态库的)
ldd comp 检查依赖库关系
编译测试工具
1.gprof 2.gcov