文章目录
-
-
- gcc使用
- gcc编译多个文件
- 使用外部库
- 生成静态库
- 生成共享库(动态库)
- 制作动态库
-
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 - 索引
- 然后就可以这样来使用静态库libhello.a
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