I have tried several times in the past to write programs using OpenGL in C and C++ on several platforms, every time only to be stopped by the ridiculous dependency and linking issues that inevitably come up.
I am attempting to use GLFW with C++ on a linux system, building using CMake, with absolutely no success.
CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project( GL_TEST_PROJECT )
find_package(OpenGL REQUIRED)
if(NOT OPENGL_FOUND)
message("ERROR: OpenGL not found")
endif(NOT OPENGL_FOUND)
set(GL_LIBRARY GL GLU X11)
add_executable(testgl testgl.cpp)
target_link_libraries(testgl glfw3 Xxf86vm pthread dl Xi Xcursor Xrandr X11 ${GL_LIBRARY} m)
testgl.cpp:
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
static void error_callback(int error, const char* description)
{
fputs(description, stderr);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
int main(void)
{
GLFWwindow* window;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
while (!glfwWindowShouldClose(window))
{
float ratio;
int width, height;
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float) height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-ratio, ratio, -1.f, 1.f, 1.f, -1.f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef((float) glfwGetTime() * 50.f, 0.f, 0.f, 1.f);
glBegin(GL_TRIANGLES);
glColor3f(1.f, 0.f, 0.f);
glVertex3f(-0.6f, -0.4f, 0.f);
glColor3f(0.f, 1.f, 0.f);
glVertex3f(0.6f, -0.4f, 0.f);
glColor3f(0.f, 0.f, 1.f);
glVertex3f(0.f, 0.6f, 0.f);
glEnd();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
make output:
Linking CXX executable testgl
//usr/local/lib/libglfw3.a(x11_init.c.o): In function `initExtensions':
x11_init.c:(.text+0x1b8b): undefined reference to `XineramaQueryExtension'
x11_init.c:(.text+0x1ba3): undefined reference to `XineramaIsActive'
//usr/local/lib/libglfw3.a(x11_monitor.c.o): In function `_glfwPlatformGetMonitors':
x11_monitor.c:(.text+0x672): undefined reference to `XineramaQueryScreens'
collect2: error: ld returned 1 exit status
make[2]: *** [testgl] Error 1
make[1]: *** [CMakeFiles/testgl.dir/all] Error 2
make: *** [all] Error 2
I have tried several different changes to the CMakeLists.txt file, including removing and adding different dependencies, but it seems that there is nowhere for me to go from here. What do I need to do to get this program to compile?
Using the
set(CMAKE_CXX_FLAGS ...)
Does not work for me, but adding them all into
set(GLFW_DEPS X11 Xrandr Xinerama Xxf86vm Xcursor GL dl pthread)
Does get things working.
So, my target_link_libraries looks like this
target_link_libraries( ${PROJECT_NAME} glfw3 ${GLFW_DEPS} ${GLEW_STATIC_LIBRARY} )
It is possible that I'm not using CMAKE_CXX_FLAGS correctly, but you should try just adding the libraries your self. Do be careful about it, their order is important and depending on which version of GLFW you're using they could be different.
That error your getting is strictly because your missing the Xinerama library.
There are two ways to not have to add those libraries manually:
Option 1 is to use GLFW_LIBRARIES which you would have to include glfw source into your project as stated here build with Cmake and GLFW source
Option 2 would be to use the help of find_package as described here: Build with installed GLFW binaries
It appears as though you have glfw installed on your machine so I would recommend option 2, in part because I have yet to get option 1 to work and I'm currently having to manually enter the libraries. This is because I don't want to have glfw installed on machine vs having it all contained in the project.
Add this to "target_link_libraries()":
glfw ${GLFW_LIBRARIES} ${X11_LIBRARIES}
And then add this somewhere above "include_directories" in your CMakeLists.txt file:
#########################################################
# FIND X11
#########################################################
find_package(X11 REQUIRED)
include_directories(${X11_INCLUDE_DIRS})
link_directories(${X11_LIBRARY_DIRS})
add_definitions(${X11_DEFINITIONS})
if(NOT X11_FOUND)
message(ERROR " X11 not found!")
endif(NOT X11_FOUND)
Edit #2: And try adding the following to your CMakeLists.txt
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lglfw3 -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lGL -lpthread")
Related
I managed to get GLFW3 to work and properly display a window, however when i add glewInit() to my project it tells me undefined reference to glewInit'. I am using g++ as my compiler with -lglfw3 and lGl as flags. Below is a simple project to demonstrate my issue. I am on linux. Any help is much appreicated.
#include <GL/glew.h>
#include <GL/gl.h>
#include <GLFW/glfw3.h>
#include <iostream>
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// glfw window creation
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// here is the error, my glew is not intializing :(
if(glewInit() != GLEW_OK) {
return 0;
}
// render loop
while (!glfwWindowShouldClose(window))
{
// render
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
glfwSwapBuffers(window);
glfwPollEvents();
}
// glfw: terminate, clearing all previously allocated GLFW resources.
glfwTerminate();
return 0;
}
There is a standard way on Linux to get a correct set of libraries to link with your program - please look at man pkg-config. In your case you need to link everything, which is needed by both GLFW3 and GLEW - so you should call the pkg-config two times:
hekto#ubuntu:~$ pkg-config --libs glfw3
-lglfw
hekto#ubuntu:~$ pkg-config --libs glew
-lGLEW -lGLU -lGL
Therefore, you need to use -lglfw instead of -lglfw3 and add two more libraries - -lGLEW and -lGLU. These calls to the pkg-config tool can be directly added to your Makefile as well.
I've tried many ways to install OpenGL, using homebrew to install glfw and glew:
$ brew install glew glfw3
Or compile through source code:
$ cd glfw && cmake . && make && sudo make install
$ cd glew && make && sudo make install
Xcode is used to create the project. Opengl.framework, glut.framework, libglfw3. A and libglew. A are all added to the project. The header file path is / usr / local / include, and the library path is / usr / local / lib. Main.cpp source code:
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
void Render(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
{
glColor3f(1.0,0.0,0.0);
glVertex2f(0, .5);
glColor3f(0.0,1.0,0.0);
glVertex2f(-.5,-.5);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(.5, -.5);
}
glEnd();
}
int main(void) {
GLFWwindow* win;
if(!glfwInit()){
return -1;
}
win = glfwCreateWindow(640, 480, "OpenGL Base Project", NULL, NULL);
if(!win)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
if(!glewInit())
{
return -1;
}
glfwMakeContextCurrent(win);
while(!glfwWindowShouldClose(win)){
Render();
glfwSwapBuffers(win);
glfwPollEvents();
}
glfwTerminate();
exit(EXIT_SUCCESS);
return 0;
}
Error in compilation:
Undefined symbols for architecture x86_64:
... (many can't find errors)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Can anyone help me?
I'm attempting to learn OpenGL. I'm using Clion as an IDE, which uses a CMakeLists.txt file to organize/compile the project.
The compiler cannot find glClear for some reason:
Undefined symbols for architecture x86_64:
"_glClear", referenced from:
_main in main.cpp.o
"_glClearColor", referenced from:
_main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [GraphicsPractice] Error 1
make[1]: *** [CMakeFiles/GraphicsPractice.dir/all] Error 2
make: *** [all] Error 2
I'm able to successfully link GLEW and GLFW, however, my code breaks when I call glClear(GL_COLOR_BUFFER_BIT). I'm not sure why. If anyone could help point me in the right direction, that would be great.
CMakeList.txt
cmake_minimum_required(VERSION 3.6)
project(GraphicsPractice)
set(CMAKE_CXX_STANDARD 14)
set(SOURCE_FILES src/main.cpp)
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory(deps/glfw)
find_package(OpenGl REQUIRED)
find_package(GLEW REQUIRED)
include_directories("deps/glfw/include/")
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} glfw glew)
main.cpp
#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
int main() {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", 0, nullptr);
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
glewInit();
while (!glfwWindowShouldClose(window)) {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
You need to link the OpenGL Libraries. Namely:
target_link_libraries(${PROJECT_NAME} ${OPENGL_LIBRARIES} glfw glew etc...)
I'm trying to run an OpenGL program that uses GLFW and GLEW libraries I built myself. The starter code I use is
#include <iostream>
// GLEW
#define GLEW_STATIC
#include <glew.h>
// GLFW
#include <glfw3.h>
// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;
// The MAIN function, from here we start the application and run the game loop
int main()
{
std::cout << "Starting GLFW context, OpenGL 3.3" << std::endl;
// Init GLFW
glfwInit();
// Set all the required options for GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
// Create a GLFWwindow object that we can use for GLFW's functions
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", 0, 0);
glfwMakeContextCurrent(window);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
// Set the required callback functions
glfwSetKeyCallback(window, key_callback);
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
glewExperimental = GL_TRUE;
// Initialize GLEW to setup the OpenGL Function pointers
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
}
// Define the viewport dimensions
glViewport(0, 0, WIDTH, HEIGHT);
// Game loop
while (!glfwWindowShouldClose(window))
{
// Check if any events have been activated (key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents();
// Render
// Clear the colorbuffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Swap the screen buffers
glfwSwapBuffers(window);
}
// Terminate GLFW, clearing any resources allocated by GLFW.
glfwTerminate();
return 0;
}
// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
std::cout << key << std::endl;
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
Then I type
g++ -I<path to headers> Tma.cpp -L<path to libraries> -lglu32 -lopengl32 -lglfw3 -lglew32
Which yields a number of 'undefined reference to' errors.
The code should be OK, as I previously run it successfully in Visual Studio.
This command:
g++ -I<path to headers> Tma.cpp -L<path to libraries> -lglu32 -lopengl32 -lglfw3 -lglew32
will not be enough in Windows. You will need to link additional system libraries. For example, every project in Visual Studio 2012 have these attached by default:
kernel32.lib
user32.lib
gdi32.lib
winspool.lib
comdlg32.lib
advapi32.lib
shell32.lib
ole32.lib
oleaut32.lib
uuid.lib
odbc32.lib
odbccp32.lib
That is why it compiled fine in VS.
kernel32.lib and user32.lib should be always linked. gdi32.lib is required, when you do any graphic operations.
First solution:
Link these libraries manually:
g++ -I<path to headers> Tma.cpp -L<path to libraries> -lglu32 -lopengl32 -lglfw3 -lglew32 -lkernel32 -luser32 -lgdi32 -lws2_32
If I remember correctly, ws2_32.a is the name of WinSock2 library supplied with MinGW.
Second solution:
If you use MinGW, you can use -mwindows flag:
g++ -I<path to headers> Tma.cpp -L<path to libraries> -lglu32 -lopengl32 -lglfw3 -lglew32 -mwindows
This will link, among few others, gdi32.a, kernel32.a, user32.a and ws2_32.a.
I'm trying to initialize GLew 1.10 along with the latest version of GLFW3. I've managed to get GLFW3 to work without a problem, but GLew is being quite difficult. I followed the example from the GLew website on how to initialize, but glewInit() for some reason is undefined and glewGetContext identifier not found / undefined (errors at bottom):
#include <GLew110\glew.h>
#define GLFW_INCLUDE_GLU
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
static void error_callback(int error, const char* description)
{
fputs(description, stderr);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
int main(void)
{
GLFWwindow* window;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(800, 600, "Simple example", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
GLenum err = glewInit(); // <---- "glewGetContext" is undefined (line 29)
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
while (!glfwWindowShouldClose(window))
{
float ratio;
int width, height;
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float) height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-ratio, ratio, -1.f, 1.f, 1.f, -1.f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef((float) glfwGetTime() * 50.f, 0.f, 0.f, 1.f);
glBegin(GL_TRIANGLES);
glColor3f(1.f, 0.f, 0.f);
glVertex3f(-0.6f, -0.4f, 0.f);
glColor3f(0.f, 1.f, 0.f);
glVertex3f(0.6f, -0.4f, 0.f);
glColor3f(0.f, 0.f, 1.f);
glVertex3f(0.f, 0.6f, 0.f);
glEnd();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
TWO ERRORS LISTED:
error C3861: 'glewGetContext': identifier not found (line 29 pointing to glewInit())
IntelliSense: identifier "glewGetContext" is undefined (line 29)
Something is defining the macro GLEW_MX which is used to configure the glew library for multiple rendering contexts. Building with such a configuration requires some special preparation. The following is from http://glew.sourceforge.net/advanced.html (emphasis added):
Multiple Rendering Contexts (GLEW MX)
Starting with release 1.2.0, thread-safe support for multiple
rendering contexts, possibly with different capabilities, is
available. Since this is not required by most users, it is not added
to the binary releases to maintain compatibility between different
versions. To include multi-context support, you have to do the
following:
Compile and use GLEW with the GLEW_MX preprocessor token defined.
For each rendering context, create a GLEWContext object that will be available as long as the rendering context exists.
Define a macro or function called glewGetContext() that returns a pointer to the GLEWContext object associated with the rendering
context from which OpenGL/WGL/GLX calls are issued. This dispatch
mechanism is primitive, but generic.
Make sure that you call glewInit() after creating the GLEWContext object in each rendering context. Note, that the GLEWContext pointer
returned by glewGetContext() has to reside in global or thread-local
memory.
If you don't need multiple rendering contexts, the best thing might be to find out where GLEW_MX is being set and fix it.
Just in case someone has similar issue.
Please try to call glewInit after calling glfwMakeContextCurrent :)
/* Make the window's context current */
glfwMakeContextCurrent(window);
int glewErr = glewInit();