• Linux 编译运行查找头文件和库的顺序


    前言

    linux中在使用gcc进行编译时,可能会出现找不到相应库或头文件的情况,往往让人十分头疼。因此,此文描述了库和头文件的查找顺序和一些注意事项,希望能帮助大家在出错时能够快速定位和解决。

    头文件

    gcc在编译时按照如下顺序寻找所需要的头文件:

    1.先搜索当前目录( 这里注意,只有用#include "headfile.h"时才会搜索当前目录
    2.接着搜索-I指定的目录
    3.然后找gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH
    4.再找内定目录: /usr/include, /usr/local/include
    5.最后找gcc的一系列自带目录,如:

    CPLUS_INCLUDE_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include
    

    库文件

    gcc在编译时按照如下顺序寻找所需要的库文件:

    1.gcc会去找-L指定的目录
    2.再找gcc的环境变量LIBRARY_PATH
    3.再找内定目录

    • /lib和/lib64
    • /usr/lib 和/usr/lib64
    • /usr/local/lib和/usr/local/lib64

    这是当初compile gcc时写在程序内的

    这里有两个问题:

    1.默认情况下,gcc编译时只会查找相应的头文件,而不会连接具体的lib。也就是说只要include设置完全,就可以编译通过。它没有进一步检查include中的类和函数有没有实现,而是在运行时才开始查找。所以就会经常发生编译可以通过,但运行时却无法运行,因为在运行时它找不到相关类或者函数的实现。

    这时,使用-Wl,--no-undefined参数,如果使用了include文件,连接器却找不到相应的实现,就会产生错误提示。

    2.编译时默认不查找当前目录,需要使用-L ./指定,例如

    运行时动态库的搜索路径

    动态库的搜索路径搜索的先后顺序是:

    1.编译目标代码时指定的动态库搜索路径;这是通过gcc的参数-Wl,-rpath=指定。当指定多个动态库搜索路径时,路径之间用冒号分隔
    2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径
    3.配置文件/etc/ld.so.conf中指定的动态库搜索路径
    4.默认的动态库搜索路径/lib, /usr/lib

    注意:

    1.动态库搜寻路径并不包括当前目录,所以当即使可执行文件和其所需的so文件在同一文件夹,也会出现找不到问题

    2.一般不推荐直接修改环境变量,而是修改/etc/ld.so.conf,将相应的路径添加上,然后ldconfig一下就好

    3.ldconfig做的这些东西都与运行程序时有关,跟编译时一点关系都没有,编译的时候还是该加-L就得加,不要混淆了

    4.往/lib/usr/lib里面lib,是不用修改/etc/ld.so.conf的,但是完了之后要调一下ldconfig(很重要),不然这个lib会找不到。而往其他目录加lib,需要修改/etc/ld.so.conf,并且要ldconfig一下。

    5.如果确实需要改环境变量,则有以下几种情况:

    • 临时修改(关闭shell后失效):若是权限不够(无法更改/etc/ld.so.conf)或只是想临时改一下环境变量用于测试,则可以使用export,就是export一个全局变量LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找lib。如:命令行执行:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/user/abc/lib

    一般来讲这只是一种临时的解决方案,在没有权限或临时需要的时候使用。

    • 修改作用于当前用户:在.bashrc中设置或者在./bash_profile设置,这对当前用户生效。记得source ~/.bashrcsource ~/.bash_profile

    • 修改作用于所有用户:在/etc/profile中设置或在/etc/profile.d/中创建一个自定义的shell(**.sh)脚本,一般推荐使用后者。原因如下:

    It's NOT a good idea to change this file unless you know what you are doing. It's much better to create a custom.sh shell script in /etc/profile.d/ to make custom changes to your environment, as this will prevent the need for merging in future updates.

    翻译即:除非您知道自己在做什么,否则更改此文件不是一个好主意。 最好在/etc/profile.d/中创建一个自定义的shell(**.sh)脚本,以对您的环境进行自定义更改,因为这样可以避免在将来的更新中合并。

    • 最后是关于环境变量的写法:

    如:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/user/abc/lib
    或者这样写:export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/home/user/abc/lib"

    要用:隔开,注意要加上$LD_LIBRARY_PATH,避免之前存在的路径失效,在前则先搜索,在后则后搜索

    参考

    1.关于开发中常见的编译器技巧
    2.LD_LIBRARY_PATH环境变量设置及Linux动态库查找方法

    感谢阅读,如有问题,请批评指正,谢谢。
  • 相关阅读:
    python-Beautiful rose
    python-and和 or用法
    myspl数据库基础
    python 协程
    python-os 模块
    python-logging模块
    异常处理
    面向对象-类中的三个装饰器
    Flask初见
    django中的ContentType使用
  • 原文地址:https://www.cnblogs.com/clwsec/p/12525180.html
Copyright © 2020-2023  润新知