编译失败,#include "..." 但不是 #include <...>

我目前正在研究 C 库 NanoVG 库。该库依赖于 OpenGL 功能并具有 2 个头文件 nanovg.hnanovg_gl.h。后一个文件包含部分实现。为方便起见,我将这两个头文件放在 /usr/include/nanovg 中。

当我尝试将以下代码编译为目标文件时,gcc 不会报错:

// working.c
#include <GL/gl.h>
#include <nanovg/nanovg.h>
#define NANOVG_GL3_IMPLEMENTATION
#include <nanovg/nanovg_gl.h>

(命令:gcc -c working.c -o working.o

现在,我将头文件从 /usr/include/nanovg/ 复制到工作目录,并将代码替换为:

// notworking.c
#include <GL/gl.h>
#include "nanovg.h"
#define NANOVG_GL3_IMPLEMENTATION
#include "nanovg_gl.h"

(命令:gcc -c notworking.c -o notworking.o

Gcc 现在抱怨一些 OpenGL 函数没有声明:

... (many more similar complaints)
src/nanovg_gl.h: In function ‘glnvg__renderDelete’:
src/nanovg_gl.h:1540:3: warning: implicit declaration of function ‘glDeleteBuffers’; did you mean ‘glSelectBuffer’? [-Wimplicit-function-declaration]
 1540 |   glDeleteBuffers(1,&gl->fragBuf);
      |   ^~~~~~~~~~~~~~~
...

为什么一个文件编译顺利,而另一个文件编译不顺利?

深入一点: 使用 cpp 工具,我发现两个预处理文件之间的区别仅限于 # 指令,但就“C 内容”而言,我没有看到任何区别。下面是预处理过的 working.c 的片段。如果我添加预处理 notworking.c 中的 # 行,则 gcc 不再编译预处理 working.c 并抱怨 glDeleteBuffers 缺少声明。

// ... 
 if (gl == 
// # 1533 "src/nanovg_gl.h" 3 4 // <- uncomment this line and glDeleteBuffers is considered missing by gcc
          ((void *)0)
// # 1533 "src/nanovg_gl.h" // <- idem
              ) return;

 glnvg__deleteShader(&gl->shader);



 if (gl->fragBuf != 0)
  glDeleteBuffers(1,&gl->fragBuf); // <- the function that gcc complains about is here
// ...

编辑:只是为了确保我没有做任何可能导致差异的偷偷摸摸的事情,我遵循了以下步骤,希望可以在另一台计算机上重现:

  1. GCC 版本:gcc (Ubuntu 10.3.0-1ubuntu1) 10.3.0
  2. 将可以找到的 GL/gl.h 的版本复制到 here 到工作目录并将其命名为 glfoo.h
  3. nanovg 的标头(在 repo 中找到)复制到 /usr/include/nanovg/nanovg/(相对于工作目录)。
  4. 在工作目录中将以下内容另存为 test.c
#include "glfoo.h"
#include <nanovg/nanovg.h>
#define NANOVG_GL3_IMPLEMENTATION
#include <nanovg/nanovg_gl.h>
  1. 运行 gcc -c test.c -o test.o => 编译工作
  2. 在第 2 行和第 4 行将 <...> 替换为“..”并运行命令 => 编译失败。

刚刚尝试了这些确切的步骤,我就能够重现它。

YJX690271813 回答:编译失败,#include "..." 但不是 #include <...>

在对此进行了一番调查后,我找到了解决方案。 gcc 不对系统头文件应用相同的警告级别,因为它对“普通”文件应用相同的警告级别(这主要是因为系统头文件有时会做一些奇怪的事情,而这些事情并没有得到 C 的支持)标准,但对于他们附带的平台来说是“安全的”)。

gcc documentation 声明(强调我的):

-Wsystem-headers

为在系统头文件中找到的构造打印警告消息。 来自系统标题的警告通常被抑制,在 假设它们通常并不表示真正的问题,并且 只会使编译器输出更难阅读。 使用这个 命令行选项告诉 GCC 从系统头文件中发出警告,如 如果它们发生在用户代码中。但是,请注意在使用 -Wall 与此选项结合不会警告未知编译指示 系统标头——为此,还必须使用 -Wunknown-pragmas

当您通过 <...> 包含 nanovg 时,它被视为系统标头。

这样做gcc -Wsystem-headers working.c实际上会带来警告。

请注意,您的代码既不适用于 working.c 也不适用于 notworking.c,因为 working.c 只是隐藏了警告消息。访问任何超出 GL 1.1 定义的 GL 函数的正确方法是使用 GL 扩展机制,这意味着您必须在运行时查询 GL 函数指针。完整的 GL 加载程序库,如 GLEW 和glad 可以自动为您执行此操作。许多这些加载器(包括 GLEW 和 GLAD)的工作原理是将每个 GL 函数名称重新#define-ing 到一个内部函数指针,因此当您包含加载器附带的标头时,代码中调用的每个 GL 函数(和 nanovg 的)将被重新路由到加载程序库函数指针,并且您的代码实际上可以工作(前提是您在调用任何 GL 函数之前在运行时正确初始化加载程序)。

,

简单

#include <file.h>

从列出的路径中包含文件默认为编译器,而

#include "file.h"

包含当前文件夹(您正在编译的文件夹)中的文件。

与您的情况一样,从 切换到 "" 会导致文件丢失,从而导致编译器错误。

本文链接:https://www.f2er.com/2384.html

大家都在问