Search code examples
c++gitmakefilecodeblocksfreeglut

Compiling Problems using freeglut


PREFACE

So I've been recently programming c++ in Code::Blocks and have run into a problem compiling recently when trying to compile projects that include freeglut. I'm on windows 8, and I have installed freeglut correctly according to the code::blocks wiki. I also have git bash installed as well as mingw64. The problem is that I cannot compile the source code that my professor (project using freeglut) has written using code::blocks or using g++ commands in gitbash.

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)

COMPILING IN GIT

  1. I cdinto the directory containing main.cpp ; Graphics.cpp ; Graphics.h ; makefile.

  2. I then run makeand get the following even though I have added all the freeglut lib, include, and bin content files into the correct directories under C:\usr\local\mingw32(inlcude\,lib\,bin) and GL\glut.h is definently there...

$ 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

COMPILING IN CODE::BLOCKS

  1. I open main.cpp ; Graphics.h ; Graphics.cpp in code::blocks.
  2. With main.cpp active, I "build and run". I get this error and nothing seems to happen, except that now there is a main.o in the project directory.
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. Same thing as above when Graphics.cpp is active and I build and run, I get the same errors as before, but Graphics.o is created.

WRAPPING THIS UP:

After I have created the object files using code::blocks, I am able to then get on gitbash and run the makefile to link them, and it does create a working test.exe that I can run and see where my placement is, but I am perplexed and frustrated that I cannot use just code::blocks or just git, as doing this makes adjustments to the code take an unreasonable amount of time to get satisfactory and is sure to cause problems later on

EDIT

All other Programs I have written, as well as 'hello world' compile with no problem on code::blocks and gitbash.


Solution

  • Building in Console

    Building project using Makefile consists of two steps:

    • compilation of source files to binary object files
    • linkage of object files to excecutable

    It can be done using just MinGW from pure cmd console. The only requirement is to set the PATH variable to point to MinGW binaries. It can be done locally only for that console, for example:

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

    Suppose that the binary freeglut 3.0.0 MinGW Package is extracted to folder 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
    

    During compilation main.o and Graphics.o object files are generated.

    In your case the error is on this step. It is related to the header path. Check that in your gitbash the path /usr/local/include/ indeed exists by listing it ls /usr/local/include/. If it exists then note that in your source files the header is included as GL/glut.h and also GL directory is present in GINCS. It is an error if the header path is /usr/local/include/GL/glut.h. So, remove GL from GINCS.

    The linkage step produces the target test.exe binary.

    Code::Blocks project

    The Code::Blocks IDE can be tuned to make GLUT project template to work with freeglue as described in Using FreeGlut with Code::Blocks.

    It is just needed to replace Glut32 by freeglut in the wizard script glut\wizard.script and in the project template glut.cbp.

    Now it is possible to create a new project using GLUT project preset. It will only ask you glut path. Then Code::Blocks automatically creates project configured with required compiler options (header path) and linker options (path and libraries). It also gives the main.cpp file with basic example that can be compiled as is.

    It looks that you created not a GLUT project but just a regular empty application project. To make it work you need to configure Project build options:

    • Search directories: add path in the Compiler tab (c:\freeglut\include) and in the Linker tab (c:\freeglut\lib);
    • Linker settings: add names of required libraries without l prefix (freeglut, glu32, opengl32).