我目前正在研究 C 库 NanoVG 库。该库依赖于 OpenGL 功能并具有 2 个头文件 nanovg.h
和 nanovg_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
// ...
编辑:只是为了确保我没有做任何可能导致差异的偷偷摸摸的事情,我遵循了以下步骤,希望可以在另一台计算机上重现:
- GCC 版本:
gcc (Ubuntu 10.3.0-1ubuntu1) 10.3.0
- 将可以找到的
GL/gl.h
的版本复制到 here 到工作目录并将其命名为glfoo.h
- 将
nanovg
的标头(在 repo 中找到)复制到/usr/include/nanovg/
和nanovg/
(相对于工作目录)。 - 在工作目录中将以下内容另存为
test.c
:
#include "glfoo.h"
#include <nanovg/nanovg.h>
#define NANOVG_GL3_IMPLEMENTATION
#include <nanovg/nanovg_gl.h>
- 运行
gcc -c test.c -o test.o
=> 编译工作 - 在第 2 行和第 4 行将 <...> 替换为“..”并运行命令 => 编译失败。
刚刚尝试了这些确切的步骤,我就能够重现它。