原文:
opengl-superbible-5th-edition-set-up-problems
以下是翻译内容,其中路径部分在使用MSYS时斜杠是
/,在使用cmd的时候斜杠应改为
\ 。 另,不当之处,欢迎批评指正!
在编译《OpenGL超级宝典 第5版》第二章的Triangle示例代码时遇到了和你一样的问题。并且同样是使用 Code::Blocks + MinGW 。经过
不懈的努力,已经基本得到解决。
现在从头开始,第一件事就是设置正确的环境,配置 freeglut 以及 GLTools 库。
在这之前请安装好最新版本的MinGW,以及MSYS(其实不一定要MSYS,CMD也可以)。然后检查环境变量%path%是否已经包含了
C:/MinGW/bin。还要有个文件解压工具比如7z
设置 freeglut-2.6.0(现在已经是2.8.1),首先从源代码中编译出静态资源库。
- 从 http://freeglut.sourceforge.net/ 下载最新版本
- 在C:盘建立 libs 文件夹,复制并解压 freeglut-2.6.0.tar.gz 文件
- 运行 MSYS (c:/MinGW/msys/1.0/msys.bat)。
- 输入"cd /c/libs/freeglut-2.6.0/src" 并按Enter以进入对应目录。
- 执行"gcc -O2 -c -DFREEGLUT_STATIC *.c -I../include"
其中-O为优化选项,(这里优化级别为2);-DFREEGLUT_STATIC 定义宏,使它能够通过源码中的#ifdef 检验;
并且从相应的从 "../include" 目录中寻找头文件
- 执行 "ar rcs libfreeglut32_static.a *.o"
ar是一个编译静态库(.a文件)的工具,该命令从之前编译好的.o文件创建libfreeglut32_static.a
- 接着在 c:/libs/freeglut-2.6.0 目录下建立 lib 文件夹。然后把刚刚建立的.a文件复制过来。确切的位置是:
"c:/libs/freeglut-2.6.0/lib/libfreeglut32_static.a"
以下链接解释了MinGW编译freeglut的一些细节。
<
http://pinyotae.blogspot.com/2010/05/bu ... mingw.html>
在我们设置GLTools之前,为了确保freeglut能够正常运转:
- 打开Code::Blocks, 关掉任何打开的其他项目。进入"Settings->Compiler and Debugger" 然后打开 "Search Dierctory" (搜索目录)
标签,在编译器 - 包含目录中,增加:"c:/libs/freeglut-2.6.0/include/"
在链接库的目录列表中,添加: "c:/libs/freeglut-2.6.0/lib/"
- 建立新的项目,新建test.cpp文件,内容为 int main (){return 0;}
- 编译。(没问题对吧?)
- 在前面添加
#define FREEGLUT_STATIC
#include <GL/glut.h>
- 再次编译,编译失败。
- 在 Project->"Build Options" 选项点击右键,确定你选的是整个项目的选项,而不是debug或者release目标。移到 Linker 选项,增
加链接库"freeglut32_static"
- 尝试编译,再次失败。编译器提示 "undefined reference to" 错误,列出一大堆函数,复制其中的第一个函数,去谷歌搜索解决办法
,通常前面几个结果会告诉你这些函数的功能,但更重要的是告诉你它们来自哪些库文件。
- 通过搜索,得出类似 xxxxx.lib 这样的库的名称,把这些库添加到链接库目录的列表中
- 再次尝试编译,又失败了。重复 第7、第8 步骤,直到编译通过为止。最后总结:为了能够让freeglut正常运转,必须添加 "Winmm",
"Gdi32" 以及 "Opengl32" 库
- 再次编译。test.exe 终于出来了!
OK,现在我们有了可供使用的freeglut,继续。首先尝试重新建立GLTools库,来自SB5的独家Lib
- 从SuperBibe5官网下载下来的源代码压缩包中,应该包含4个文件夹:freeglut, linux, visualstudio 以及 src。进入src目录,复制
GLTools文件夹到 C:/libs (之前建立的)目录中
- 在 libs/GLTools 目录中建立 lib 文件夹。此时应该有3个目录:/include. /src 以及 /lib
- 再次运行 MSYS (或者CMD),输入 "cd /c/libs/GLTools/src" 并回车
- 就像之前配置freeglut 的时候一样,我们要集合所有工具的代码,并将其链接到同一个库文件中。执行"g++ -c *.cpp -I../include
",然后执行 "ar rcs libGLTools.a *.o"。
- 将生成的 libGLTools.a 复制到 "c:/libs/GLTools/lib"
- 对 glew 做同样的事情,执行 "g++ -c glew.c -I../include" 然后 "ar rcs libglew.a glew.o"
- 在Code::Blocks中,打开 "Settings->Compiler and Debugger",选择 "Search Directory" 标签。在Compiler 中添加 "c:/libs/GL
Tools/include。在Linker中添加"c:/libs/GLTools/lib/"
- 重新打开项目,在test.cpp前面添加 #include <GLTools.h> 然后尝试编译。这个时候出现一些这样的错误提示:
"'GLAPI' does not name a type"。原因是,某些代码位置并没有定义 GLAPI,或者定义不正确
这是值得探讨的,如果你从未这样探索库文件(我就没有,这是一次很好的实践)。打开 "freeglut-2.6.0/include/GL/glut.h",
就会发现它只是简单的包含了freeglut_std.h,而 freeglut_std.h 里面有一堆预定义指令。
在MinGW/include目录中搜索 包含字符 "GLAPI" 的文件(或者使用命令 grep "GLAPI" *.h),得出结果为:GL/gl.h, GL/glu.h,打开
gl.h 并找出相关的段落。
可以看到一段相关的代码:
/* GLAPI, part 1 (use WINGDIAPI, if defined) */
#if defined(__WIN32__) && defined(WINGDIAPI)
# define GLAPI WINGDIAPI
#endif
/* GLAPI, part 2 */
#if !defined(GLAPI)
# if defined(_MSC_VER) /* Microsoft Visual C++ */
# define GLAPI __declspec(dllimport)
# elif defined(__LCC__) && defined(__WIN32__) /* LCC-Win32 */
# define GLAPI __stdcall
# else /* Others (e.g. MinGW, Cygwin, non-win32) */
# define GLAPI extern
# endif
#endif
现在要做的就是把其中最可能执行的部分提取出来,
freeglut_std.h 并没有定义WINGDIAPI,所以跳过第一段代码,然后在第二段中寻找答案,#define GLAPI extern 就是我们要的东西。
(因为注释写着 /* Others (e.g. MinGW, Cygwin ... )
看起来似乎是这么回事:GLTools的一个头文件搞错了一些东西(对我们来说)
现在理清顺序:
GLTools.h没有用到GLAPI,但是包含了<windows.h>和<GL/glew.h> <GL/gl.h>,glew.h中有不少关于GLAPI的定义,这些定义告诉我们,GLAPI应该
定义为extern,所以最直接的办法就是直接在test.cpp中加入#define GLAPI extern, 顺序为
#include <GLTools.h>
#define FREEGLUT_STATIC
#define GLAPI extern
#include <GL/glut.h>
再一次编译,再一次失败,但这次得到了不一样的错误提示。所以我们得继续调试……
额…… 这次编译没有任何问题。Just kidding( )。别高兴,我们还没有正式引用GLTools中的任何函数,编译通过纯属正常。借着
刚才的运气继续添加头文件 <GLShaderManager.h> ,然后编译,并且没有任何错误提示。
OK, 几乎快要成功了。现在完善test.cpp,在mian函数之前添加
GLBatch triangleBatch;
GLShaderManager shaderManager;
编译的时候出现一些"undefined references" (未定义)字样的错误提示,打开编译选项,把之前的几个还没加入的库链接进去(GLTools)
然后出现一小堆glew函数的"undefined references"提示
Wee! So exciting.(……)现在添加glew库到编译选项中,我们学到了新的东西:你必须记得链接那些和头文件对应的库文件。
这点对我们以后建立别的什么项目的时候很有帮助。
当我们需要用到freeglut,它依赖于winmm, gdi32 以及opengl32;
我们还需要用到GLTools,其依赖于glew库,而glew库又依赖于opengl32,链接他们的顺序应该为:
freeglut, GLTools, glew, winmm, gdi32 and opengl32. 让我们试试这样的顺序是否正确:
哈!没有任何错误提示。Damn I'm good (not really
). (这句照搬)
OK,现在我们设置好了环境,复制并编译Triangle.cpp文件,没有任何错误。
我在两台电脑上试过了这个方法并成功编译。相信以上步骤足以解决Code::Blocks+MinGW编译SB5示例代码过程所遇到的所有问题。