GCC入门

24 篇文章 7 订阅

来源:微信公众号「编程学习基地」

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能够找得到共享库,有下面几种方法:

  1. 拷贝.so文件到系统共享库路径下,一般指/usr/lib
  2. 在~/.bash_profile文件中,配置LD_LIBRARY_PATH变量
  3. 配置/etc/ld.so.conf,配置完成后调用ldconfig更新ld.so.cache

其中,shared选项表示生成共享库格式。fPIC表示产生位置无关码(position independent code),位置无关码表示它的运行、加载与内存位置无关,可以在任何内存地址进行加载。

原文链接:https://www.cnblogs.com/QG-whz/p/5456720.html

制作动态库

动态库后缀: .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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeRoy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值