假设我在linux下下载了一个库并构建它:configure,make,sudo make install。
该库带有我要包含在项目中的标头。编译器如何知道在哪里搜索标头?
提请Dorman对This Question的回答给出了一个很好的示例,说明了如何在系统级别检查编译器在哪里寻找标头:
gcc -print-prog-name=cc1plus
-v
包含文件夹可以在项目中添加带有-I参数的makefile。自然,它们可以在Makefile中看到。
还有其他我未考虑过的用于注册标头位置的机制吗?这些组合的方法是否给我提供了全面的了解,或者换句话说,如果我查看这些地方,假设我正在使用gnu-make,是否已经看到了所有内容?最后,是否有一种方便的方法可以让Make向我显示要检查标题的位置?
背景: 我正在处理的库是zeromq和Google的协议缓冲区。平台是CentOS。编译器抱怨找不到标题。我已经在替代系统(Fedora)上构建了该程序,该系统似乎不需要其他干预即可确保可访问这些标头。
答案 0 :(得分:0)
在Linux(或其他类似Unix的操作系统)中没有通常的机制来注册标头搜索位置。
对于您的系统类型,GCC是内置的,带有默认的预处理程序搜索目录列表 对于C和C ++中的每一个。您可以使用以下命令(包括其他命令)为C显示该列表:
$ gcc -x c -E -Wp,-v -
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/8/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
...
$ [CNTL-C]
以及对于C ++:
$ gcc -x c++ -E -Wp,-v -
ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/8"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/include/c++/8
/usr/include/x86_64-linux-gnu/c++/8
/usr/include/c++/8/backward
/usr/lib/gcc/x86_64-linux-gnu/8/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
...
$ [CNTL-C]
请注意,C和C ++的默认搜索目录不同:C ++-list 是C列表的超集。当您以常规方式编译C源文件时,将搜索C列表:
gcc [options...] foo.c ...
,当您以常规方式编译C ++源代码时,将搜索C ++列表:
g++ [options...] foo.cpp bar.cc gum.cxx ...
只有两种方法可以将标头搜索目录传递给 预处理器:-
您可以使用以下命令在命令行中明确指定搜索目录 选项:
-I dir
-iquote dir
-isystem dir
-idirafter dir
按照the manual: 3.15 Options for Directory Search
或者您可以在环境变量之一的设置中列出搜索目录 预处理器将其解释为搜索目录列表。对于C,这些是:
CPATH
C_INCLUDE_PATH
对于C ++,它们是:
CPATH
CPLUS_INCLUDE_PATH
按照the manual: 3.20 Environment Variables Affecting GCC
在Linux中可以给环境变量一个持久的默认值
系统范围内的定义,方法是在根特权文件/etc/environment
,/etc/profile
,/etc/profile.d/
,/etc/bash.bashrc
中定义一个。
因此,如果某个代理商要在以下其中一项中定义CPATH
和或C_INCLUDE_PATH|CPLUS_INCLUDE_PATH
这些文件作为:
标点符号的目录列表,可以有效地注册
这些目录作为C | C ++的GCC搜索目录。但是,不会安装GCC安装
任何此类设置:只能由root用户手动设置。您可以检查,然后
如果绘制空白,则只有在以下位置定义这些变量时,这些变量才有影响力
瞬态外壳。在构建系统中很少使用它们,正是因为
引入了对手术环境的不透明依赖。
我上面用来列出默认搜索目录的命令对 通过两种可能的方法之一添加非默认目录:
$ mkdir my_include
$ gcc -x c -I my_include -E -Wp,-v -
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
my_include
/usr/lib/gcc/x86_64-linux-gnu/8/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
或:
$ gcc -x c -iquote my_include -E -Wp,-v -
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
my_include
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/8/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
或:
$ export CPLUS_INCLUDE_PATH=my_include
$ gcc -x c++ -E -Wp,-v -
ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/8"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
my_include
/usr/include/c++/8
/usr/include/x86_64-linux-gnu/c++/8
/usr/include/c++/8/backward
/usr/lib/gcc/x86_64-linux-gnu/8/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
是否有一种方便的方法可以让Make向我显示要检查标题的位置?
Make对编译过程及其所涉及的概念一无所知:它不知道 检查标题在其工作过程中经常发生。在执行makefile时,命令可能是 运行并调用GCC前端执行编译,然后 it 将尝试 以已经概述的方式定位头文件。
在其他条件相同的情况下,编译代码的最可能原因
应该在某些Fedora系统上成功,但在某些CentOS系统上失败,因为,
例如#include <google/protobuf/someheader.h>
无法解决,是因为
具有root特权的用户已安装开发包protobuf-devel
或
Fedora系统上的protobuf
源压缩文件,而CentOS系统上没有人做过。
如果两个系统上均确实安装了protobuf
,则
其他情况不平等。
google/protobuf/someheader.h
可能是一个标头,
由Fedora系统上安装的protobuf
的(较新的?)版本提供
但不是由CentOS系统上安装的(较旧的)版本提供的。
其他一些不平等现象可能解释了您的情况,但没有具体说明
Fedora和CentOS软件包安装步骤的详细信息和具体示例
投机成功和失败的构建只能描述所有这些。您现在对GCC解决#include
指令的方法一无所知,对此几乎可以肯定没有解释。
类似的注意事项适用于您发现的编译失败
到zeromq
标头。