详解Linux下环境变量C_INCLUDE_PATH、CPLUS_INCLUDE_PATH、CPATH以及常见错误

C_INCLUDE_PATHCPLUS_INCLUDE_PATH以及CPATH常被用于在全局性地添加预处理C/C++时的包含目录,其中C_INCLUDE_PATH仅对预处理C有效,CPLUS_INCLUDE_PATH仅对预处理C++有效,而CPATH对所有语言均有效。下面我们仅以C_INCLUDE_PATH为例来讨论。

常用的容易出错的设置方法是在~/.bashrc等文件中简单地使用递归式赋值:

export C_INCLUDE_PATH=$C_INCLUDE_PATH:/somewhere/include

这条语句的命令会将C_INCLUDE_PATH赋值为它原本的值之后再附加上:/somewhere/include而组成的值。

例如,如果原本$C_INCLUDE_PATH的值为/previous/include,那么执行过这一条shell语句后,$C_INCLUDE_PATH的值就会变为/previous/include:/somewhere/include,而如果原本没有定义过环境变量C_INCLUDE_PATH或定义了但值为空,那么$C_INCLUDE_PATH的值就会变为:/somewhere/include.

可为什么说这样写是容易出错的呢?

我们知道在Linux中是使用冒号:分隔两个目录的(Windows下常用分号;),我们使用这条语句期望达成的效果应该是添加/somewhere/include到预处理C时的包含目录。

GCC的官方文档影响GCC的环境变量中有这样一句:

In all these variables, an empty element instructs the compiler to search its current working directory. Empty elements can appear at the beginning or end of a path. For instance, if the value of CPATH is :/special/include, that has the same effect as -I. -I/special/include.

意思是:在所有这些变量中,一个空的元素会指示编译器搜索当前工作目录空的元素可以出现在一个路径的开头或结尾。例如,如果CPATH的值是:/special/include,这将会等效于-I. -I/special/include.

因此在之前的例子中,我们只想在预处理搜索路径中添加一个/somewhere/include,期望的C_INCLUDE_PATH的值是/somewhere/include,但实际上C_INCLUDE_PATH却被赋值为了:/somewhere/include,开头的冒号之前虽然为空,却会为预处理搜索路径添加上当前工作目录,也即Linux中的.且优先级是所有目录中最高的!

而这往往并不是我们想要的结果,这会导致预处理的包含目录随着当前工作目录的改变而改变,如果当前工作目录中恰好有一个与源代码中包含的文件同名的文件,则会导致不可预期的错误。

不巧的是,VSCode在为我们自动生成的tasks.json中,默认的tasks.options.cwd恰好是/usr/bin,因此一旦错误地设置了C_INCLUDE_PATH的值,同时/usr/bin中恰好有一个同名的文件(要知道这里的文件大多都是可执行程序),那么在编译C程序时,就会错把这个同名文件当作源代码文件包含进来,接下来就可以欣赏海量的编译错误了。譬如目前最受欢迎的Linux发行版Manjaro,在安装好后的/usr/bin中就会有一个名为array的可执行程序,与C++的<array>重名。

正确方法:

首先明确一点,这几个预处理包含目录的环境变量并不是Linux操作系统的一部分,因此一般情况下Linux是不会设置这些环境变量的。

所以在对某一个环境变量第一次设置时,应该直接将其赋值为所需的目录,在之后的设置中再使用递归式的赋值;或者直接一次性将所有目录用:分隔开,一起赋值;或者索性不使用这些环境变量,而是在编译时使用-I参数来添加包含目录。

其他:

查看gcc预处理C时的的搜索目录:

echo | gcc -x c -v -E -

查看gcc预处理C++时的的搜索目录:

echo | gcc -x c++ -v -E -

查看clang预处理C++时的搜索目录:

echo | clang -x c++ -v -E -

cwd : current working directory 当前工作目录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值