gcc 在编译时如何去寻找所需要的头文件

转载 2006年06月03日 20:41:00
声明:
原文的连接地址为:
http://www.study-area.org/cyril/opentools/opentools/book1.html
里面的文字是繁体的,我把它转换成简体了。

标头档 函式库与gcc

标头定义档.h

当我们给

$ gcc -o foo.o foo.c

       

gcc怎么知道去哪里找foo.c里面所includeheader文件,连结数据库与系统定义呢? 总共有下列来源指定gcc去那找。

  1. 当初在编译时指定的(~gcc/gcc/collect2.c:locatelib()

  2. 写在specs内的

  3. 后来用-D -I -L指定的

  4. gcc环境变量设定(编译的时候)

  5. ld.so的环境变量(这是run time的时候)

prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.9.5/

       

里面有个很重要的specs这个档案 gcc根据这个档,做一些内定的动作。 通常系统上的specs内定装起来是在

/usr/lib/gcc-lib/xxxx-gnulibc/version/

       

specs档看起来是像这样

*asm:

%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}

 

*asm_final:

%|

 

*cpp:

%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:

-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}

 

*cc1:

%(cc1_cpu) %{profile:-p}

 

*cc1plus:

 

 

*endfile:

%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s

 

*link:

-m elf_i386 %{shared:-shared}   %{!shared:     %{!ibcs:       %{!static: 

%{rdynamic:-export-dynamic}     %{!dynamic-linker:-dynamic-linker

/lib/ld-linux.so.2}}  %{static:-static}}}

 

*lib:

%{shared: -lc --version-script libgcc.map%s}    %{!shared: %{mieee-fp:-lieee}

%{pthread:-lpthread}      %{profile:-lc_p} %{!profile: -lc}}

 

*libgcc:

-lgcc

 

*startfile:

%{!shared:      %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:%{profile:gcrt1.o%s}

%{!profile:crt1.o%s}}}}    crti.o%s %{!shared:crtbegin.o%s}

%{shared:crtbeginS.o%s}

 

*switches_need_spaces:

 

*signed_char:

%{funsigned-char:-D__CHAR_UNSIGNED__}

 

*predefines:

-D__ELF__ -Dunix -Di386 -D__i386__ -Dlinux -Asystem(posix)

 

*cross_compile:

0

 

*version:

egcs-2.91.66

 

*multilib:

. ;

 

*multilib_defaults:

 

*multilib_extra:

 

*multilib_matches:

 

*linker:

collect2

 

*cpp_cpu_default:

-D__tune_i386__

 

*cpp_cpu:

-Asystem(unix) -Acpu(i386) -Amachine(i386) %{!ansi:-Di386}

-D__i386 -D__i386__ %{march=i486:-D__i486 -D__i486__}

%{march=pentium|march=i586:-D__pentium -D__pentium__ }

%{march=pentiumpro|march=i686:-D__pentiumpro -D__pentiumpro__ }

%{m386|mcpu=i386:-D__tune_i386__ } %{m486|mcpu=i486:-D__tune_i486__ }

%{mpentium|mcpu=pentium|mcpu=i586:-D__tune_pentium__ }

%{mpentiumpro|mcpu=pentiumpro|mcpu=i686:-D__tune_pentiumpro__ }

%{!mcpu*:%{!m386:%{!m486:%{!mpentium*:%(cpp_cpu_default)}}}}

 

*cc1_cpu:

%{!mcpu*: %{m386:-mcpu=i386} %{mno-486:-mcpu=i386 -march=i386}

%{m486:-mcpu=i486} %{mno-386:-mcpu=i486 -march=i486}

%{mno-pentium:-mcpu=i486 -march=i486} %{mpentium:-mcpu=pentium}

%{mno-pentiumpro:-mcpu=pentium} %{mpentiumpro:-mcpu=pentiumpro}}

       

shell下用这行,-E 表示只做到preprocess就好

$ echo 'main(){}' | gcc -E -v -

       

你会看到gcc去读specs

Reading specs from /usr/lib/gcc-lib/i386-linux/2.95.2/specs

gcc version 2.95.2 20000220 (Debian GNU/Linux)

 /usr/lib/gcc-lib/i386-linux/2.95.2/cpp -lang-c -v -D__GNUC__=2 -D__GNUC_MINOR__=95 -D__ELF__ -Dunix -D__i386__ -Dlinux -D__ELF__ -D__unix__ -D__i386__ -D__linux__ -D__unix -D__linux -Asystem(posix) -Acpu(i386) -Amachine(i386) -Di386 -D__i386 -D__i386__ -

GNU CPP version 2.95.2 20000220 (Debian GNU/Linux) (i386 Linux/ELF)

#include "..." search starts here:

#include <...> search starts here:

 /usr/local/include

 /usr/lib/gcc-lib/i386-linux/2.95.2/include

 /usr/include

End of search list.

The following default directories have been omitted from the search path:

 /usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g++-3

 /usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include

End of omitted list.

# 1 ""

main(){}

       

所以有内定的定义,(就是用在#if defined #ifndef #define这些东西, 如果有定义这个字符串,就去编译等等。) -Dxxxx -Dxxxx -Axxxx。 还有内定的include文件的搜寻路径

/usr/include

/usr/local/include

/usr/lib/gcc-lib/i386-linux/2.95.2/include

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g++-3

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include

       

但是如果装gcc的时候,是有给定的prefix的话,那么就是

/usr/include

prefix/include

prefix/xxx-xxx-xxx-gnulibc/include

prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.8.1/include

       

所以header file的搜寻会从-I开始然后找gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH 再找上述的内定目录

函式库

当我们用到数学函式cos()cos这个symbolgcc并不晓它到底是什么东西, 是变量,是函式,要预留多少空间给他等等,完全没有任何讯息,你必须标头 檔要#include <math.h>gcc才知道。而且因为specs这个档里面只有要 link -lc也就是只有libc.so这个档内的symbol会被搜寻, 像printf scanf等都在这里面,可是像cos()等就没有了, 所以函式库的选项要多加 -lm ,这时ld才会来找libm这个函式库,

编译的时候,gcc会去找-L,再找gcc的环境变量LIBRARY_PATH,再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的, gcc环境变量与passld的机制在~gcc/gcc/collect2.c下找得到。 这上面只是搜寻路径而已,如果要不加-lm 也能正确的主动搜寻某个特定的lib,例如libm, 就要去在specs这个档案改一下,把math这个函式库加进自动联结函式库 之一。就不用写-lm了。

RUN TIME的时候, 如果编译时没有指定-static这个选项,其实可执行文件并不是真的可执行, 它必须在执行(run time)时需要ld.so来做最后的连结动作,建造一个可执行的 image丢到内存。如果是静态连结,编译时ld会去找libm.a的檔 。如果是动态连结去找libm.so。 所以每次有新改版程序, 或新加动态函式库如果不在原本的/etc/ld.so.conf搜寻路径中,都要把路径 加进来,然后用

ldconfig -v

       

会重建cache并且显示它所参照的函式库。Run Timeld.so才找得到lib"执行" ldld.so不一样喔。

一些重要的程序

ld             :Link Editor 连结各obj写进一个可执行档(executable)

ldd            :秀出一个执行文件用了那些动态函式库。

ld.so          :Dynamic Linker, 动态连结的话,是由ld.so完成执行时期symbol

                :参照与连结。

ld-linux.so    :ELF文件的动态连结,跟ld.so一样。只是ld.so是给a.out format的。

                :新的glicb2ld-linux.so.2已经跟ld.so.2结合成单一程序了。

ldconfig       :根据/etc/ld.so.conf内的目录,做出动态连结所需的cache檔。

       

ld 就是负责各个函式库文件的信息写进最后可执行档(executable),所以它叫做 link editor,编译时根据flags -L搜寻需要的libgcc也会把他的设定pass下来。 ld.so ld-linux.so.2是负责最后动态连结,叫做dynamic linker RUN Time 执行程序时,它根据这个顺序搜寻函式库。

  1. LD_LIBRARY_PATH LD_AOUT_LIBRARY_PATH环境变量所指的路径

  2. ldconfig所建立的cache

  3. /lib /usr/lib内的档

来找程序所需要的动态函式库

ldconfig会根据/etc/ld.so.conf这个档的设定,加上内定的两个目录 /lib /usr/lib来设定ld.so要用到所需要的连结 以及连结的cache/etc/ld.so.cache。 所以如果换了新的函式库,新的kernel,内部的标头档可能会有变化, 都要跟着改变让gcc正确的找到,喔不,应该是cpp, ld, ld.so能正确的找到。 不然编出来的执行档可能是错误的,执行时还可能segmentation fault

gcc 在编译时如何去寻找所需要的头文件:

gcc 在编译时如何去寻找所需要的头文件: ※所以header file的搜寻会从-I开始 ※然后找gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,O...
  • liuxuejin
  • liuxuejin
  • 2011年12月19日 16:56
  • 705

GCC在编译时如何寻找所需要的头文件(转)

当我们给 $ gcc -o foo.o foo.c         gcc怎么知道去哪里找foo.c里面所include的header文件,连结数据库与系统定义呢? 总共有下列来源...
  • zlj7777
  • zlj7777
  • 2011年08月09日 15:34
  • 301

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

gcc编译器搜索头文件路径     本文介绍在linux下gcc编译器是如何找到程序中的头文件的。头文件是一种文本文件,使用文本编辑器将代码编写好之后,以扩展名.h保存就行了。头文件中一般放...
  • tangsun999
  • tangsun999
  • 2015年03月20日 16:16
  • 5386

Linux编译程序时找不到头文件的解决办法

Linux编译程序时找不到头文件的解决办法 $ gcc test.c -o test test.c:9:16: fatal error: xxx.h: No such file or directo...
  • iw1210
  • iw1210
  • 2016年12月08日 10:58
  • 5234

GCC编译器是如何找到头文件的

分一下三个步骤寻找:       1.会在默认情况下指定到/usr/include文件夹(更深层次的是一个相对路径,GCC可执行程序的路径是/usr/bin,那么它在实际工作时指定头文件头径是一种相...
  • cgb165937385
  • cgb165937385
  • 2013年10月12日 10:24
  • 674

gcc 头文件查找路径

如果从纯粹的text文件来说,#include的作用就是搜索它后面指示的文件,并把这个文件的内容加到当前的文件中。一般我们编程时,都是包含一些与.h为后缀的头文件,但是它可以包含任何后缀的任何形式的t...
  • crazy_programmer_p
  • crazy_programmer_p
  • 2014年09月04日 20:55
  • 1926

GCC编译选项-包含的头文件

许多情况下,头文件和源文件会单独存放在不同的目录中。 可以直接在.c文件中利用#include“/path/file.h", 通过指定头文件的路径(可以是绝对路径,也可以是相对路径)来包含头文件. ...
  • Ethan_Novice
  • Ethan_Novice
  • 2012年01月10日 21:16
  • 7729

gcc中使用 -I 和 -L 引入外部头文件和库文件时路径的搜索次序

gcc中使用 -I 和 -L 引入外部头文件和库文件时路径的搜索次序   摘自《An Introduction to GCC》 默认情况下,gcc在下面目录中搜索头文件: /u...
  • origin_lee
  • origin_lee
  • 2014年07月10日 16:11
  • 1048

gcc 4.8.2编译时找不到头文件curses.h问题的解决

首先使用命令
  • RobertChenGuangzhi
  • RobertChenGuangzhi
  • 2014年11月17日 22:18
  • 1460

使用gcc时头文件路径和动态链接库路径

在使用gcc编译连接生成可执行文件时,经常会碰到变量未定义、链接时或者运行可执行文件时找不到相应的动态库等问题,本文首先介绍了gcc在编译时头文件路径相关选项以及搜索路径顺序,然后讨论了编译成可执行文...
  • MaximusZhou
  • MaximusZhou
  • 2014年08月14日 16:36
  • 8619
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:gcc 在编译时如何去寻找所需要的头文件
举报原因:
原因补充:

(最多只允许输入30个字)