使用freeglut编译出现问题

3

前言

最近我正在使用Code::Blocks编程C++,但在尝试编译包含freeglut的项目时遇到了问题。我使用的是Windows 8操作系统,并按照code::blocks wiki正确安装了freeglut。我还安装了git bash和mingw64。问题在于,我无法使用Code::Blocks或在gitbash中使用g++命令编译我的教授(使用freeglut的项目)编写的源代码。

main.cpp:

/* Copyright (c) Mark J. Kilgard, 1996. */

/* This program is freely distributable without licensing fees
and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */

#include "Graphics.h"
void display(void)
{
  glClear(GL_COLOR_BUFFER_BIT);
  setColor(RED);
  drawFilledTriangle(0,0,100,100,200,0);
  setColor(BLUE);
  drawFilledCircle(200,200,150);
  glFlush();  /* Single buffered, so needs a flush. */
}

int main(int argc, char **argv)
{
  graphicsSetup( argc, argv, &display);
  glutMainLoop();
  return 0;
}

Graphics.cpp

#include <iostream>
using namespace std;

#include "Graphics.h"
#include <cmath>
const double PI = acos(-1.0);
const double ANGLE_STEP      = PI/180.0;
void keyboard(unsigned char key, int x, int y)
{
    if (key == 27)
        exit(1);
}

void clearWindow() {
    glClear( GL_COLOR_BUFFER_BIT );
}

void setColor(ColorName name) {
    switch(name) {
        case WHITE: glColor3d(1.0, 1.0, 1.0); break;
        case GREY: glColor3d(0.4, 0.4, 0.4); break;
        case BLACK: glColor3d(0.0, 0.0, 0.0); break;
        case RED: glColor3d(1.0, 0.0, 0.0); break;
        case ORANGE: glColor3d(1.0, 0.5, 0.0); break;
        case YELLOW: glColor3d(1.0, 1.0, 0.0); break;
        case GREEN: glColor3d(0.0, 1.0, 0.0); break;
        case FOREST_GREEN: glColor3d(0.0, 0.25, 0.0); break;
        case BLUE: glColor3d(0.0, 0.0, 1.0); break;
        case CYAN: glColor3d(0.0, 1.0, 1.0); break;
        case MIDNIGHT_BLUE: glColor3d(0.0, 0.0, 0.25); break;
        case PURPLE: glColor3d(0.5, 0.25, 0.0); break;
        case MAGENTA: glColor3d(1.0, 0.0, 1.0); break;
        case BROWN: glColor3d(0.36, 0.16, 0.1); break;
        default: cerr << "Trying to set invalid color. Color unchanged" << endl;
    }
}
void graphicsSetup(int argc, char *argv[], void (*display)()) {
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB);
  if (! glutGet(GLUT_DISPLAY_MODE_POSSIBLE))
     glutInitDisplayMode(GLUT_INDEX);
  glutInitWindowPosition(50,50);
  glutInitWindowSize(640, 480);
  glutCreateWindow("single triangle");
  glClearColor(1.0,1.0,1.0,0.0);
  glutDisplayFunc(display);

  // set "esc" key to end program
  glutKeyboardFunc(keyboard);

  // set coordinates to "normal"
  glLoadIdentity();
  glOrtho(0,640,0,480, 1, -1);
}

void drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3) {
     glBegin(GL_LINE_STRIP);
     glVertex2i(x1,y1);
     glVertex2i(x2,y2);
     glVertex2i(x3,y3);
     glVertex2i(x1,y1);
     glEnd();
}

void drawFilledTriangle(int x1, int y1, int x2, int y2, int x3, int y3) {
     glBegin(GL_POLYGON);
     glVertex2i(x1,y1);
     glVertex2i(x2,y2);
     glVertex2i(x3,y3);
     glVertex2i(x1,y1);
     glEnd();
}

void drawLine(int x1, int y1, int x2, int y2) {
     glBegin(GL_LINE_STRIP);
     glVertex2i(x1,y1);
     glVertex2i(x2,y2);
     glEnd();
}

void drawBox(int x1, int y1, int x2, int y2) {
     glBegin(GL_LINE_STRIP);
     glVertex2i(x1,y1);
     glVertex2i(x2,y1);
     glVertex2i(x2,y2);
     glVertex2i(x1,y2);
     glVertex2i(x1,y1);
     glEnd();
}

void drawFilledBox(int x1, int y1, int x2, int y2) {
     glBegin(GL_POLYGON);
     glVertex2i(x1,y1);
     glVertex2i(x2,y1);
     glVertex2i(x2,y2);
     glVertex2i(x1,y2);
     glVertex2i(x1,y1);
     glEnd();
}

void drawCircle(int x, int y, int radius) {
     double angle;
     int X, Y;
     glBegin(GL_LINE_STRIP);
     for (angle=0;angle< 2.0*PI + ANGLE_STEP; angle += ANGLE_STEP) {
         X = x + int(double(radius) * cos(angle));
         Y = y + int(double(radius) * sin(angle));
         glVertex2i(X,Y);
     }
     glEnd();
}         

void drawFilledCircle(int x, int y, int radius) {
     double angle;
     int X0, Y0, X1, Y1;
     glBegin(GL_TRIANGLES);
     X1 = x + radius;
     Y1 = y;
         for (angle=0;angle< 2.0*PI + ANGLE_STEP; angle += ANGLE_STEP) {
             X0 = X1;
             Y0 = Y1;
             X1 = x + int(double(radius) * cos(angle));
             Y1 = y + int(double(radius) * sin(angle));
             glVertex2i(x,y);
             glVertex2i(X0,Y0);
             glVertex2i(X1,Y1);
         }
         glEnd();
    }    

Graphics.h

#include <GL/glut.h>

// set the pre-defined colors
enum ColorName {
    WHITE,
    GREY,
    BLACK,
    RED,
    ORANGE,
    YELLOW,
    GREEN,
    FOREST_GREEN,
    BLUE,
    MIDNIGHT_BLUE,
    CYAN,
    PURPLE,
    MAGENTA,
    BROWN,
    NUM_COLORS
};

void clearWindow();
void setColor(ColorName name);
void graphicsSetup(int argc, char *argv[], void (*display)());

// graphic object primatives
void drawTriangle(int x1, int y1,int x2,int y2,int x3,int y3);
void drawLine(int x1, int y1, int x2, int y2);
void drawBox(int x1, int y1, int x2, int y2); // x-y coords of upper-right     and lower-left corners
void drawCircle(int x, int y, int radius);

// filled graphics primatives
void drawFilledTriangle(int x1, int y1,int x2,int y2,int x3,int y3);
void drawFilledBox(int x1, int y1, int x2, int y2);
void drawFilledCircle(int x, int y, int radius);

makefile

TARGET = test.exe

CXX   = c:\usr\local\mingw32\bin\g++.exe
FILES = main.cpp Graphics.cpp
OBJS = $(FILES:.cpp=.o)

GINCS   = -I/usr/local/include/GL 
GLIBS   = -L/usr/local/lib -lfreeglut -lglu32 -lopengl32 -Wl,--subsystem,windows

all:  $(TARGET)

$(TARGET):  $(OBJS)
    $(CXX) -o $(TARGET) $(OBJS) $(GLIBS)

%.o:    %.cpp
    $(CXX) -c $< -o $@ $(GINCS)

clean:
    del $(TARGET) $(OBJS)

在GIT中编译

  1. 我使用 cd 命令进入包含 main.cpp ; Graphics.cpp ; Graphics.h ; makefile 的目录。

  2. 然后我运行 make 命令,虽然我已经将所有的 freeglut 库、头文件和二进制文件添加到了正确的目录下(C:\usr\local\mingw32(inlcude\,lib\,bin)),并且 GL\glut.h 文件也肯定存在……

$ make
c:\usr\local\mingw32\bin\g++.exe -c main.cpp -o main.o -I/usr/local/include/GL
In file included from main.cpp:7:0:
Graphics.h:1:21: fatal error: GL/glut.h: No such file or directory
compilation terminated.
makefile:16: recipe for target 'main.o' failed
make: *** [main.o] Error 1

在CODE::BLOCKS中编译

  1. 我在code::blocks中打开了main.cpp; Graphics.h; Graphics.cpp
  2. 选中main.cpp后,我点击“构建并运行”。我遇到了这个错误,除此之外好像什么也没有发生,但是现在项目目录中有一个main.o文件。
C:\Users\Admin\Desktop\C++Projects\cosc1337.code\GraphicsLib\examples\ex4\main.o:main.cpp|| undefined reference to `_imp____glutInitWithExit@12'
C:\Users\Admin\Desktop\C++Projects\cosc1337.code\GraphicsLib\examples\ex4\main.o:main.cpp|| undefined reference to `_imp____glutCreateWindowWithExit@8'
C:\Users\Admin\Desktop\C++Projects\cosc1337.code\GraphicsLib\examples\ex4\main.o:main.cpp|| undefined reference to `_imp____glutCreateMenuWithExit@8'
C:\Users\Admin\Desktop\C++Projects\cosc1337.code\GraphicsLib\examples\ex4\main.o:main.cpp|| undefined reference to `glClear@4'
C:\Users\Admin\Desktop\C++Projects\cosc1337.code\GraphicsLib\examples\ex4\main.o:main.cpp|| undefined reference to `setColor(ColorName)'
C:\Users\Admin\Desktop\C++Projects\cosc1337.code\GraphicsLib\examples\ex4\main.o:main.cpp|| undefined reference to `drawFilledTriangle(int, int, int, int, int, int)'
C:\Users\Admin\Desktop\C++Projects\cosc1337.code\GraphicsLib\examples\ex4\main.o:main.cpp|| undefined reference to `setColor(ColorName)'
C:\Users\Admin\Desktop\C++Projects\cosc1337.code\GraphicsLib\examples\ex4\main.o:main.cpp|| undefined reference to `drawFilledCircle(int, int, int)'
C:\Users\Admin\Desktop\C++Projects\cosc1337.code\GraphicsLib\examples\ex4\main.o:main.cpp|| undefined reference to `glFlush@0'
C:\Users\Admin\Desktop\C++Projects\cosc1337.code\GraphicsLib\examples\ex4\main.o:main.cpp|| undefined reference to `graphicsSetup(int, char**, void (*)())'
C:\Users\Admin\Desktop\C++Projects\cosc1337.code\GraphicsLib\examples\ex4\main.o:main.cpp|| undefined reference to `_imp__glutMainLoop@0'
=== Build failed: 11 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===
  1. 当Graphics.cpp处于活动状态时,我执行“build and run”操作时会出现与之前相同的错误,但是Graphics.o文件被创建。

总结:

在使用code::blocks创建对象文件后,我可以使用gitbash运行makefile将它们链接起来,并创建一个可运行的test.exe,以查看我的位置,但我困惑和沮丧的是,我不能只使用code::blocks或只使用git,因为这样调整代码需要不合理长的时间才能令人满意,并且肯定会在以后引起问题。

编辑

我编写的所有其他程序以及“hello world”都可以在code::blocks和gitbash上无问题编译。


1
这听起来像是你的makefile或者code::blocks,或者两者都没有正确配置。我建议你尝试编译极其简单的程序,比如 int main() {},直到你可以在两种方式下可靠、一致地编译而不出错为止。只要你做不到这一点,你的系统就需要进行一些调整。然后逐渐尝试包含free glut等内容,直到你能够让它正常工作,并且如果你真的遇到了困难,请再次在SO上发布。 - Chris Beck
我编写的所有其他程序都可以在code::blocks和git bash中无问题编译。而且我总是确保hello world从一开始就可以编译。 - Nolifepothead
2个回答

1

在控制台中构建

使用Makefile构建项目包括两个步骤:

  • 将源文件编译为二进制目标文件
  • 将目标文件链接到可执行文件

可以仅使用纯cmd控制台中的MinGW完成。唯一要求是设置PATH变量以指向MinGW二进制文件。例如,可以仅针对该控制台本地进行设置:

PATH=c:\MinGW\mingw-w64\i686-5.1.0-posix-dwarf-rt_v4-rev0\mingw32\bin;%PATH%

假设二进制文件 freeglut 3.0.0 MinGW Package 已提取到文件夹 c:\freeglut
::compilation
g++ -c main.cpp -o main.o -I"c:\freeglut\include"
g++ -c Graphics.cpp -o Graphics.o -I"c:\freeglut\include"

::linkage
g++ Graphics.o main.o -o test -L"c:\freeglut\lib" -lfreeglut -lglu32 -lopengl32 -Wl,--subsystem,windows

编译过程中会生成main.oGraphics.o对象文件。

在您的情况下,错误出现在这一步。它与头文件路径有关。检查在您的gitbash中路径/usr/local/include/是否存在,通过列出它ls /usr/local/include/。如果存在,则请注意在您的源文件中,头文件被包含为GL/glut.h,并且目录GL也存在于GINCS中。如果头文件路径为/usr/local/include/GL/glut.h,则会出现错误。因此,请从GINCS中删除GL

链接步骤会生成目标test.exe二进制文件。

Code::Blocks项目

Code::Blocks IDE可以进行调整,使GLUT项目模板能够与freeglue一起使用,如Using FreeGlut with Code::Blocks中所述。

只需要在向导脚本glut\wizard.script和项目模板glut.cbp中将Glut32替换为freeglut

现在可以使用GLUT项目预设创建新项目。它只会询问您glut路径。然后,Code::Blocks会自动创建配置了所需编译器选项(头文件路径)和链接器选项(路径和库)的项目。它还提供了带有基本示例的main.cpp文件,可以直接编译。

看起来您创建的不是GLUT项目,而只是一个普通的空应用程序项目。要使其正常工作,您需要配置项目构建选项

  • 搜索目录:在编译器选项卡中添加路径(c:\freeglut\include),并在链接器选项卡中添加路径(c:\freeglut\lib);
  • 链接器设置:添加所需库的名称,但不带l前缀(freeglutglu32opengl32)。

谢谢。你是正确的。但问题也在于我没有在glut项目模板中构建我的文件。 - Nolifepothead

0
在您的make文件中,我看到您正在使用像-lfreeglut这样的标志进行链接。我使用的是Linux,并且我记得必须将所有的“l”放在我的链接选项前面,特别是针对Linux。尝试使用-freeglut等其他选项。
在code::blocks中,您可以通过转到Project>Build选项,然后转到linker选项卡来添加glut32.lib。在那里,单击link libraries下的add。然后给它您的.lib文件的路径。一定不要使用相对路径。您需要字面路径。
我唯一的建议是#include <windows.h>。通常,当您遇到大量未定义的引用时,这是某种链接错误。

我现在将编辑makefile并尝试编译。我希望这就是问题所在,因为这些源文件直接来自我的教授,我确实不得不更改一些makefile,但完全没有大问题。关于您的code::blocks建议,code::blocks维基方向让我通过glut向导脚本,并将所有引用glut32的内容更改为freeglut。我不确定这是否有效,但我愿意尝试任何事情。 谢谢,我会在之后回复。 - Nolifepothead
更改了我的 makefile 并删除了引用前面的 l,但仍然出现相同的错误。经检查(code::blocks 的 mingw 和我的 mingw64 lib 路径),我没有看到任何 glut32.lib 或 glut32.a,但是 freeglut.a 文件都存在于两者中。 - Nolifepothead

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接