您的位置:首页 > 运维架构 > Linux

gcc编译器搜索Linux下头文件路径

2015-03-20 16:16 183 查看
gcc编译器搜索头文件路径

本文介绍在linux下gcc编译器是如何找到程序中的头文件的。头文件是一种文本文件,使用文本编辑器将代码编写好之后,以扩展名.h保存就行了。头文件中一般放一些重复使用的代码,例如函数声明、变量声明、常数定 义、宏的定义等等。当使用#include语句将头文件引用时,相当于将头文件中所有内容,复制到#include处。#include有两种写法形式, 分别是:

#include <> : 直接到系统指定的某些目录中去找某些头文件。

#include “” : 先到源文件所在文件夹去找,然后再到系统指定的某些目录中去找某些头文件。

#include文件可能会带来一个问题就是重复应用,如a.h引用的一个函数是某种实现,而b.h引用的这个函数却是另外一种实现,这样在编译的时候将会出现错误。所以,为了避免因为重复引用而导致的编译错误,头文件常具有:

#ifndef LABEL

#define LABEL

//代码部分

#endif

的格式。其中LABEL为一个唯一的标号,命名规则跟变量的命名规则一样。常根据它所在的头文件名来命名,例如,如果头文件的文件名叫做hardware.h,那么可以这样使用:

#ifndef __HARDWARE_H__

#define __HARDWARE_H__

//代码部分

#endif

这样写的意思就是,如果没有定义__HARDWARE_H__,则定义__HARDWARE_H__,并编译下面的代码部分,直到遇到#endif。这样当重复引用时,由于__HARDWARE_H__已经被定义,则下面的代码部分就不会被编译了,这样就避免了重复定义。

一句话,头文件事实上只是把一些常用的命令集成在里面,你要用到哪方面的命令就载入哪个头文件就可以了。
默认情况下,gcc在下面目录中搜索头文件:

/usr/local/include/

/usr/include/

在下面目录中搜索库:

/usr/local/lib/

/usr/lib/

搜索头文件的目录列表常被称为include路径,而搜索库的目录列表被称为搜索路径或链接路径。

在这些路径中的目录是按次序搜索的,在上面的两个列表中从第一个到最后一个。例如,“/usr/local/include”中找到的头文件优先于“/usr/include”中的同名文件。类似的,“/usr/local/lib”

中找到的库优先于“/usr/lib”中的同名库。

当有其他库被安装到另外的目录中,为了能按序找到这些库,需要扩展搜索路径。编译器选项“-I”和“-L”用于把新目录添加到各自的include路径和库搜索路径的头上。

通过shell中的环境可以控制头文件和库的搜索路径。可以在每次开始shell会话的相应登录文件中,比如“.bash_profile”,自动地设置它们。

可以使用环境变量C_INCLUDE_PATH(针对C的头文件)或CPP_INCLUDE_PATH(针对C++的头文件)把其他目录添加到include路径中。

例如,当编译C程序时,下面的命令会把“/opt/gdbm-1.8.3/include”添加到include路径中:

$ C_INCLUDE_PATH=/opt/gdbm-1.8.3/include

$ export C_INCLUDE_PATH

该目录将在命令行上用选项“-I”指定的任何目录之后,但在标准默认目录“/usr/local/include”和“/usr/include”之前被搜索。

Shell命令export是必要的,以便shell以外的程序也能获得该环境变量,比如象编译器----对每一次shell会话的每一个变量来说,只需要设一次,也可以在相应的登录文件中设置。

类似的,使用环境变量LIBRARY_PATH可以把另外的目录添加到链接路径中去。例如,下面的命令会把“/opt/gdbm-1.8.3/lib”添加到链接路径中:

$ LIBRARY_PATH=/opt/gdbm-1.8.3/lib

$ export LIBRARY_PATH

该目录将在命令行上用选项“-L”指定的任何目录之后,但在标准默认目录“/usr/local/lib”和“/usr/lib”之前被搜索。

环境变量被设置好以后,程序可以不用带“-I”和“-L”选项就能成功被编译,

$ gcc -Wall dbmain.c -lgdbm

因为现在默认路径包括了在环境变量C_INCLUDE_PATH和LIBRARY_PATH中指定的目录。

遵循标准Unix搜索路径的规范,搜索目录可以在环境变量中用冒号分隔的列表形式一起指定:

DIR1:DIR2:DIR3:...

这些目录被依次从左到右搜索。单个点“.”可以用来指示当前目录。7

例如,下面的设置把安装软件包的当前目录,及在“/optgdbm-1.8.3”和“/net”目录下各自的“include”,“lib”目录放到默认的include和链接路径中去:

$ C_INCLUDE_PATH=.:/opt/gdbm-1.8.3/include:/net/include

$ LIBRARY_PATH=.:/opt/gdbm-1.8.3/lib:/net/lib

在命令行上可以重复使用“-I”和“-L”选项来指定多个搜索路径的目录。例如,下面的命令,

$ gcc -I. -I/opt/gdbm-1.8.3/include -I/net/include -L. -L/opt/gdbm-1.8.3/lib -L/net/lib .....

等同于上面在环境变量中设置的。

当环境变量和命令行选项被同时使用时,编译器按下面的次序搜索目录:

1. 从左到右搜索由命令行“-I”和“-L”指定的目录

2. 由环境变量,比如C_INCLUDE_PATH和LIBRARY_PATH指定的目录

3. 默认的系统目录

gcc还有一个参数:-nostdinc,它使编译器不再系统缺省的头文件目录里面找头文件,一般和-I联合使用,明确限定头文件的位置。在编译驱动模块时,由于非凡的需求必须强制GCC不搜索系统默认路径,也就是不搜索/usr/include要用参数-nostdinc,还要自己用-I参数来指定内核
头文件路径,这个时候必须在Makefile中指定。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: