Linux-2


1 GCC

  1. GCC原名为GNU C Complier(C语言编译器),只针对C语言的编译。而今,GCC还支持其他语言的编译,如C++、Objective-C、JAVA、Ada和Go语言,因而更名为GNU Complier Collection(GNU编译器套件)。
  2. 安装指令:sudo apt install gcc g++(版本>4.8.5).

    gcc可以理解为用于编译c的套件,g++则是用于编译C++.

  3. 版本查询:gcc/g++ -v/--version

2 GCC工作流程

  1. 工作流程

  2. 参数选项

3 GCC和G++差别

  1. 对于.c文件,GCC会将其认为是c文件进行编译,而G++则是当作cpp文件进行编译;而对于.cpp文件,二者均是认为是cpp文件。

  2. gcc可以编译.c文件,也可以编译.cpp文件,但是编译后者时无法自动和C++程序所使用的库进行链接,而是需要调用g++来实现;而g++则是在编译阶段会自动调用gcc

4 静态库&动态库

  静态库在程序的链接阶段被复制到程序中,而动态库则并未进行复制,而是在运行过程时由程序动态加载到内存中以供调用。

4.1 库的规范

  • 静态库

    • 命名规则
      • Linux: libxxx.a, 其中lib为固定前缀,xxx则是用户自定义静态库名,.a则为固定后缀。
      • Windows:libxxx.lib
    • 制作
      • gcc获得.o文件,即链接前的格式: gcc -c a.c b.c
      • .o文件通过ar命令进行打包:ar rcs libcalc.a a.o b.o, 其中r意为将文件插入备存文件中,c为建立备存文件,s则是索引
    • 使用
      • gcc main.c -o app -I ./path1 -L ./path2 -l calc, 其中path1用于指定main.c中包含的头文件的相对地址,其实就是指所使用的静态库的头文件,而path2则是指定静态库的相对地址,calc则是静态库的名称(注意不是libcalc).
  • 动态库

    • 命名规则
      • Linux:libxxx.so,其中lib为固定前缀,xxx则是用户自定义动态库名,.so则为固定后缀。为可执行文件。
      • Windows:libxxx.dll
    • 制作
      • gcc得到.o文件,得到和位置无关的代码:gcc -c -fpic/-fPIC a.c b.c
      • gcc得到动态库:gcc -shared a.o b.o -o libcalc.so.
    • 使用
      • gcc main.c -o app -I ./path1 -L ./path2 -l calc, 其中path1用于指定main.c中包含的头文件的相对地址,其实就是指所使用的动态库的头文件,而path2则是指定动态库的相对地址,calc则是动态库的名称(注意不是libcalc).

4.2 动态库加载失败原因及解决方法

  • 原因:链接时GCC只是把动态库的信息写入可执行程序中,并没有把动态库的代码打包到程序中,因而程序执行过程中需要系统的动态载入器来获取该库的绝对路径以加载对应的代码。对于elf格式的可执行程序,是由ld-linux.so来完成这个操作,搜索顺序为:elf文件的DT_RPATH段->环境变量LD_LIBRARY_PATH->/etc/ld.so.cache文件列表->/lib/,/usr/lib目录.

  • 解决:在上述任意的位置中加入动态库的绝对路径

    1. LD_LIBRARY_PATH中加入动态库地址

      • export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:Absolute_ path_of_dynamic_lib:冒号后加上动态库的绝对地址

        使用echo $LD_LIBRARY_PATH即可查看是否成功将动态库的绝对地址加入到环境变量中. 但直接在终端中配置时只是暂时的,关闭终端后重新执行程序会再次报错。

      • 用户级别:编辑.bashrc, 在最后一行加入空行再加入上边的命令。(Shift+G: 跳到最后一行,o:插入空行)

        source ~/.bashrc(等效于. ~/.bashrc):使更改生效.波浪号表示/Home/文件夹

      • 系统级别:sudo vim /etc/profile然后跟方法2一致.

    2. 修改/etc/ld.so.cache

      • sudo vim /etc/ld.so.conf,然后将路径加入到该文件中并用sudo ldconfig更新一下
    3. 修改/lib//usr/lib(不建议:存有系统本身自带的库,防止用户自定义库名与系统库一致导致将系统库擦除)

4.3 静态库和动态库的优缺点

  1. 静态库:

    • 加载速度快
    • 无需额外提供静态库,移植方便
    • 消耗系统资源,浪费内存
    • 更新、部署、发布麻烦(修改后需要重新编译)
  2. 动态库:

    • 可以实现进程间的资源共享:只需加载一次,进程间可以共享
    • 更新、部署、发布简单
    • 可以控制何时加载动态库
    • 加载速度慢
    • 发布时需要额外提供所依赖的动态库

使用动态库还是静态库,取决于库的大小,库如果较大则推荐使用动态库。

附录 Linux基本命令

  1. mkdir: 在当前目录下新建一个文件夹
  2. cd:打开某一个文件夹,cd ..为回到父文件夹
  3. touch:打开某一文件
  4. vi/vim: 编辑某一文件
  5. gcc xxx.c -o app: 编译某个c文件,输出名为app的目标,如果没有指定目标,则生成的是.out文件(同样是可执行文件)
  6. tree: 打开当前文件夹的目录树
  7. ls:查看当前文件夹具有哪些文件,ll查看当前文件夹中的文件的详细信息
  8. cp 源文件相对路径 目标文件相对路径:复制源文件到目标文件位置
  9. rm:删除文件,rmdir:删除文件夹
  10. ldd: 查看可执行文件所依赖的动态库
  11. env:查看环境变量
  12. pwd:查看当前文件夹得绝对路径

文章作者: Vyron Su
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Vyron Su !