gcc使用
gcc编译过程
选项名 | 作用 | -o | 产生目标(.i、.s、.o、可执行文件等) | -E | 只运行C预编译器 | -S | 告诉编译器产生汇编程序文件后停止编译,产生的汇编语言文件拓展名为.s | -c | 通知gcc取消连接步骤,即编译源码,并在最后生成目标文件 | -w | 不产生任何警告信息 | -Wall | 使gcc对源文件的代码有问题的地方发出警告 | -Idir | 指定 include 包含文件的搜索目录 | -Ldir | 指定编译的时候,搜索的库的路径。 | -lLib | 在程序编译的时候,指定使用的库 | -g | 在目标文件中嵌入调试信息,以便gdb之类的调试程序调试 | -D | 允许从编译程序命令行进行宏定义符号 | gcc的使用示例:
gcc -E hello.c -o hello.i 对hello.c文件进行预处理,生成了hello.i 文件
gcc -S hello.i -o hello.s 对预处理文件进行编译,生成了汇编文件
gcc -c hello.s -o hello.o 对汇编文件进行编译,生成了目标文件
gcc hello.o -o hello 对目标文件进行链接,生成可执行文件
gcc hello.c -o hello 直接编译链接成可执行目标文件
gcc -c hello.c 或 gcc -c hello.c -o hello.o 编译生成可重定位目标文件 gcc编译多个文件
test目录下有是哪个文件hello.c hello.h main.c ,三个文件的内容如下:
// hello.c
#include<stdio.h>
#include"hello.h"
void printHello()
{
printf("hello world!\n");
}
//main.c
#include<stdio.h>
#include"hello.h"
int main()
{
printHello();
return 0;
}
//hello.h
//仅包含函数声明
#ifndef _HELLO_
#define _HELLO_
void printHello();
#endif 编译这三个文件,可以一次编译生成可执行文件main:
gcc hello.c main.c -o main
#!/bin/bash
gcc hello.c main.c -o main 也可以独立编译:
gcc -Wall -c main.c -o main.o
gcc -Wall -c hello.c -o hello.o
gcc -Wall main.o hello.o -o main1
#!/bin/bash
gcc -Wall -c main.c -o main.o
gcc -Wall -c hello.c -o hello.o
gcc -Wall main.o hello.o -o main1
echo "install main1"
sudo cp ./main1 /usr/bin #执行这步可以在任意目录下运行main1这个程序 独立编译的好处是,当其中某个模块发送改变时,只需要编译该模块就行,不必重新编译所有文件,这样可以节省编译时间。
使用外部库
静态库与动态库:
- 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。静态库比较占用磁盘空间,而且程序不可以共享静态库。运行时也是比较占内存的,因为每个程序都包含了一份静态库。
- 动态库(.so或.sa):程序在运行的时候才去链接共享库的代码,多个程序共享使用库的代码,这样就减少了程序的体积。
一般头文件或库文件的位置在:
- /usr/include及其子目录底下的include文件夹
- /usr/local/include及其子目录底下的include文件夹
- /usr/lib
- /usr/local/lib
- /lib
生成静态库
- 为了生成.a文件,我们需要先生成.o文件。下面这行命令将我们的hello.o打包成静态库libhello.a:
ar rcs libhello.a hello.o ar是gun归档工具,rcs表示replace and create,如果libhello之前存在,将创建新的libhello.a并将其替换。
r - 将文件插入备存文件中
c - 建立备存文件
s - 索引
gcc -Wall main.c libhello.a -o main 生成共享库(动态库)
- 生成一个共享库,名称的规则是libxxx.so。将刚才hello.o生成libhello.so的命令为:
gcc hello.c -fPIC -shared -o libhello.ao
#gcc -shared -fPIC hello.c -o libhello.so
deroy@ubuntu:~/work/test$ ls
hello.c hello.h hello.o libhello.a main main.c
deroy@ubuntu:~/work/test$ gcc hello.c -fPIC -shared -o libhello.ao
deroy@ubuntu:~/work/test$ ls
hello.c hello.h hello.o libhello.a libhello.ao main main.c
deroy@ubuntu:~/work/test$ rm libhello.ao
deroy@ubuntu:~/work/test$ ls
hello.c hello.h hello.o libhello.a main main.c
deroy@ubuntu:~/work/test$ gcc -shared -fPIC hello.c -o libhello.so
deroy@ubuntu:~/work/test$ ls
hello.c hello.h hello.o libhello.a libhello.so main main.c
deroy@ubuntu:~/work/test$ readelf -h libhello.so
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x5a0
Start of program headers: 64 (bytes into file)
Start of section headers: 6264 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 7
Size of section headers: 64 (bytes)
Number of section headers: 29
Section header string table index: 26
gcc -o main main.c -L . -lhello
#直接执行会报错,解决方法
#方法一:拷贝.so文件到系统共享库路径下,一般指/usr/lib或者/lib/目录
sudo cp libhello.so /usr/lib/
#方法二:在~/.bash_profile文件中,配置LD_LIBRARY_PATH变量
export LD_LIBRARY_PATH=./
deroy@ubuntu:~/work/test$ gcc -o main main.c -L . -lhello
deroy@ubuntu:~/work/test$ ls
hello.c hello.h hello.o libhello.a libhello.so main main.c
deroy@ubuntu:~/work/test$ ./main
./main: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory
deroy@ubuntu:~/work/test$ ldd main
linux-vdso.so.1 => (0x00007ffd467d9000)
libhello.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6fa83d2000)
/lib64/ld-linux-x86-64.so.2 (0x000055e7399ee000)
deroy@ubuntu:~/work/test$ cp libhello.so /usr/lib/
cp: cannot create regular file '/usr/lib/libhello.so': Permission denied
deroy@ubuntu:~/work/test$ sudo cp libhello.so /usr/lib/
[sudo] password for deroy:
deroy@ubuntu:~/work/test$ ./main
hello world!
deroy@ubuntu:~/work/test$ sudo rm /usr/lib/libhello.so
deroy@ubuntu:~/work/test$ ./main
./main: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory
deroy@ubuntu:~/work/test$ export LD_LIBRARY_PATH=./
deroy@ubuntu:~/work/test$ ./main
hello world!
deroy@ubuntu:~/work/test$ ldd main
linux-vdso.so.1 => (0x00007ffc2f9d8000)
libhello.so => ./libhello.so (0x00007fa4712c6000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa470ee3000)
/lib64/ld-linux-x86-64.so.2 (0x000055d6e2f08000) 该命令与使用静态库的命令相同,但是在共享库与静态库共存的情况下,优先使用共享库。
共享库有时候并不不在当前的目录下,为了让gcc能够找得到共享库,有下面几种方法:
- 拷贝.so文件到系统共享库路径下,一般指/usr/lib
- 在~/.bash_profile文件中,配置LD_LIBRARY_PATH变量
- 配置/etc/ld.so.conf,配置完成后调用ldconfig更新ld.so.cache
其中,shared选项表示生成共享库格式。fPIC表示产生位置无关码(position independent code),位置无关码表示它的运行、加载与内存位置无关,可以在任何内存地址进行加载。
制作动态库
动态库后缀: .so – libmyname.so
制作步骤:
- 生成与位置无关的代码(.o)
gcc -fPIC -c *.c -Iinclude - 将.o打包生成.so文件
gcc -shared *.o -o libmytest.so - 使用 main.c lib include
gcc main.c -Llib -lmytest -Iinlude -o app
应用程序不能执行, 动态链接器连接不到自己制作的库
- 临时设置的方法:
export LD_LIARARY_PATH=./lib - 永久设置的方法:
找到动态链接库的配置文件: /etc/ld.so.conf
在该文件中添加动态库的目录(绝对路径)
更新: sudo ldconfig -v
|