我在包含文件时遇到了一个奇怪的问题,并且Eclipse的构建过程与其错误报告之间明显断开。我将给出重现此问题的详细步骤,以便我们尽快缩小原因范围。
适用于C/C++ Linux开发人员的Eclipse 3.7.1(Indigo SR1),Ubuntu 10.10 64位
当我导入一个现有的可以“自行制作”的项目时,一切就开始了:我认为Eclipse将在导航文件和确定做什么方面大有帮助。但是,某些#include
d系统 header 似乎在Eclipse的 View 中没有发挥正确的作用。这非常令人困惑,在调查过程中,我设法在一个很小的沙盒中重现了该问题。
第一步:使用File: New: C Project
示例创建一个新的C项目(Hello World ANSI C Project
)。参数为Executable: Hello World ANSI C Project/Linux GCC
,其余Empty
项目设置为Linux GCC
,并且GNU Autotools
设置为Hello World ANSI C Autotools Project
。称它为“你好”。确保自动生成makefile(“高级设置”,我相信它是默认设置)。
第二步:调整包含路径。使用Project: Properties: C/C++ General: Paths and Symbols: Includes: GNU C
将搜索路径设置为/usr/local/include
,/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include
和/usr/include
。第二条路径取决于您已安装的gcc的确切版本。只要构建路径至少包含/usr/include
,这无关紧要。
现在,如果您打开hello.c
,它看起来非常简单,并且Eclipse非常高兴,除了return EXIT_SUCCESS;
不能解析EXIT_SUCCESS
。用零(EXIT_SUCCESS
)替换0
,Eclipse提供了清晰的显示。选择Project: Build Project
生成可执行文件。
打开命令行窗口,然后深入到Eclipse工作区文件夹的hello/Debug
子文件夹。到达那里后,您可以使用./hello
行运行可执行文件。
现在,乐趣开始了。修改hello.c
以阅读其后一部分:
#include <fcntl.h>
int main(void) {
printf("Hello World!\n");
int zz = SPLICE_F_MOVE;
printf("zz (SPLICE_F_MOVE) is '%d'\n", zz);
printf("Bye World!\n");
return 0;
}
您会在
int zz...
行上看到错误:"Symbol 'SPLICE_F_MOVE' could not be resolved"
。如果您构建项目,则在控制台 View 中将收到类似的错误:"error: 'SPLICE_F_MOVE' undeclared"
。现在,如果您将序言更改为:
#define _GNU_SOURCE
#include <fcntl.h>
您仍然在
int zz
行上(在编辑器中)收到错误,但是该项目将正确构建!您可以通过在先前打开的命令行窗口中运行二进制文件来确认这一点。这真的很奇怪,因为对/usr/include/fcntl.h
的检查将显示#include
s <bits/fcntl.h>
和后面的 header #define
s SPLICE_F_MOVE
(以及其他一堆)放在受#ifdef __USE_GNU
保护的块中(如果__USE_GNU
为#define
d,则_GNU_SOURCE
将得到#define
d)。为什么在地球上我们的#define _GNU_SOURCE
没有在工作空间透视图中正确传播?简而言之,这就是我的问题:为什么编辑器(和所有Eclipse CDT)报告一个错误(显然是拒绝正确处理一个include),但是底层构建成功了?
最佳答案
使用GNU和非GNU兼容工具链交叉编译各种微 Controller 时,我遇到了类似的问题。 CDT报告许多错误,但是即使所有 header 都正确位于项目设置中,实际的构建也可以正常工作。
问题在于CDT的运作方式与您的make系统版本不同。 CDT是一个独立的词法分析器,解析器和预处理器,并且不会利用您用于构建的工具链。一旦您将项目设置设置为与作为构建工具的命令行参数生成的设置相匹配,这通常就可以正常工作,但是许多工具链经常将隐藏的隐式定义作为其编译器/预处理器本身的一部分。根据我的经验,隐式/隐藏定义的文档通常是粗略且不完整的,因此几乎无法确定为给定工具链设置了哪些定义(有时甚至取决于构建选项)以及它们的含义。尽管看起来所有正确的定义集都可以解决您遇到的问题,但我通常会发现(尤其是在GNU中)缺少某些东西,从而无法按照您的方式处理开关预期的。
当我调试这样的东西时,我首先要确保首先找到我的项目目录中的所有 header ,如果它们的名称与其他目录中的名称相匹配,然后慢慢地开始将 header 从标准的include文件夹移动到我的项目文件夹中。 CDT不能很好地表明它首先要解析头文件的可能版本,并且经常在您最不期望的情况下提取系统环境设置,但是它确实会在项目文件夹中查找头文件(如果您没有)。请勿在您的项目设置中将系统标题路径设置为优先)。通过将系统头文件从您正在查看的位置移动到项目目录,您可以确切地知道CDT正在解析哪个头文件。此外,如果在移动后重建索引,然后在Eclipse中打开文件,CDT将通过灰色显示或折叠 header 中未启用的分支来指示它认为启用或禁用的开关。通过此过程,每次都为我解决了这个确切的问题,显示了我何时具有指向同一 header 的多个副本,意外重复的 header ,在意外开关下定义或包含的路径等。
关于c - Eclipse CDT,包含的系统头文件和底层C构建之间的奇怪断开,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8333887/