Sign in to follow this  
hatfarm

CMake Issue - Need Help Getting it to work with GLEW and SFML

Recommended Posts

hatfarm    224

Hello all, so I've been working with SFML and GLEW in MSVC 2010 and have had very few issues (despite using static libraries for both, which can be an issue).  I'm able to compile and run and have no linking issues or anything.  However, I have plenty of friends whom I'd like to play my game that use Linux exclusively (Macs also for that matter).  So, I wanted to use CMake to allow me to compile on several different platforms.  I followed along the articles written here (http://www.gamedev.net/page/resources/_/technical/general-programming/cross-platform-test-driven-development-environment-using-cmake-part-1-r2986).   I put together a successful CMakeLists.txt and it gets through fine, finding my GLEW and SFML directories.  However, I get GLEW linking errors when I try to compile.  It compiles the game fine, but when it gets to linking it cannot get past this GLEW stuff.  At first I just thought it was the GLEW in SFML conflicting with my GLEW, but no matter what order I put the libraries in, I have the same issue.  I'm hoping that since I can compile with MSVC2010 .sln file, but not with this, it's just a configuration issue.  Hopefully someone here with experience with these 3 systems can give me some advice.  Here's my CMakeList.txt:

 

cmake_minimum_required(VERSION 2.6)
project(BattleMap)

include_directories(
	"${PROJECT_BINARY_DIR}"
	$ENV{GLM_ROOT}
	$ENV{RAPIDXML_ROOT}
	$ENV{GLEW_ROOT}/include
)

set(EXECUTABLE_NAME "BattleMap")
set(BattleMap_SRCS	
	battlemap.cpp
	battlemap.h
	
	bufferobject.cpp
	bufferobject.h
	
	camera.cpp
	camera.h
	
	globals.h
	
	vertices.h
	
	texture.cpp
	texture.h
	
	vao.cpp
	vao.h
	
	supertexture.cpp
	supertexture.h
	
	shaderprog.cpp
	shaderprog.h
	
	scene.cpp
	scene.h
	
	submapscene.cpp
	submapscene.h
	
	mapscene.cpp
	mapscene.h
	
	mousepointerscene.cpp
	mousepointerscene.h
	
	application.cpp
	application.h
	
	main.cpp
)
	
add_executable(${EXECUTABLE_NAME} ${BattleMap_SRCS})

IF (WIN32)
	MESSAGE("IS Win32")
ELSE (WIN32)
	MESSAGE("NOT Win32")
ENDIF (WIN32)

set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})

IF (WIN32)
	add_library(glew_static STATIC IMPORTED)
	set_target_properties(glew_static PROPERTIES
		IMPORTED_LOCATION $ENV{GLEW_ROOT}/lib/glew32s.lib)
	target_link_libraries(${EXECUTABLE_NAME} glew_static)
ELSE (WIN32)
		find_package(GLEW REQUIRED)
ENDIF (WIN32)



# Detect and add SFML
find_package(SFML 2.0 REQUIRED system window graphics)
#find_package(GLEW REQUIRED)

if(SFML_FOUND)
  include_directories(${SFML_INCLUDE_DIR})
  target_link_libraries(${EXECUTABLE_NAME} ${SFML_LIBRARIES})
endif()

#if(GLEW_FOUND)
#	MESSAGE("GLEW include path found!")
#	include_directories(${GLEW_INCLUDE_PATH})
#	target_link_libraries(${EXECUTABLE_NAME} ${GLEW_LIBRARY})
#endif()

# Install target
install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin)

 

Some of the GLEW stuff commented out is just me trying different orders for CMake.  If more information would be helpful, I'm more than happy to provide it.  Thanks ahead of time.

Share this post


Link to post
Share on other sites
Hiwas    5807

This is unfortunately a pain in the butt, I went through the problems myself recently.  The simple answer is to look at the updated environment which is part of my next article, you can find the source at: https://code.google.com/p/a8u-tutorial-sources/.  (Under the Game directory, not the "environment" one, that's out of date.)  The SFML and XO applications link against SFML 2 statically on all three platforms.  In your above cmake code you are likely linking against shared objects on Linux which can cause other problems.  I'll take a further look into your code listfile when I move downstairs and get on my laptop and see if I can't point out specific issues.

 

Oh, an important item of note.  SFML links against glew already, so if you link statically as I do, don't bother trying to link glew, it's already there.

Edited by AllEightUp

Share this post


Link to post
Share on other sites
hatfarm    224

Hmm... see it seems like it can't find a GLEW to link against, despite linking it or not... here's some of the linking output:

 

 

>bufferobject.obj : error LNK2001: unresolved external symbol __imp____glewBindBuffer
2>texture.obj : error LNK2019: unresolved external symbol __imp__glTexImage2D@36
 
I'm having trouble figuring out why.  It knows where my GLEW library is, because the glew.h include isn't a problem.  CMake is such a hassle...

Share this post


Link to post
Share on other sites
Hiwas    5807

CMake is not really the problem here, mixing dll's, static libs and such on Window's is being a pain in the butt for you.  Notice in your link errors the prefix portion: __imp__.  That means something is still attempting to use the glew headers without having defined GLEW_STATIC.  Given this is windows, I'd suggest taking a look at the updated CMake files which deal with all this nonsense.  I'm going to take a look at your listfile in more detail now, give me about 15-20 minutes.

Share this post


Link to post
Share on other sites
Hiwas    5807

First pass notes, obviously I'm only able to poke at this so much without having a better idea of your setup.  Basically you should not have to include the glew stuff at all for Window's, just point at the SFML glew include directory (in order to keep the version sync'd) in the extlibs dir.  The other problem is not setting the static flag for SFML before the find.  Hope this gets you going forward, let me know what goes wrong next.  :)

 




#<snippity snip>

set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})

IF (WIN32)
#   Don't do this, glew is already statically linked as part of SFML 2.0.
#   It is probable that CMake strips this all out anyway, just be safe.
#   add_library(glew_static STATIC IMPORTED)
#   set_target_properties(glew_static PROPERTIES
#       IMPORTED_LOCATION $ENV{GLEW_ROOT}/lib/glew32s.lib)
#   target_link_libraries(${EXECUTABLE_NAME} glew_static)
ELSE (WIN32)
    # NOTE: this will give you the shared object on other platforms.
    # not a problem, just important to keep in mind.
        find_package(GLEW REQUIRED)
ENDIF (WIN32)

# Detect and add SFML
# You need to tell this to use static libs, probably only on Windows though:
IF( WIN32 )
  SET( SFML_STATIC_LIBRARIES TRUE )
ENDIF()

find_package(SFML 2.0 REQUIRED system window graphics)
#find_package(GLEW REQUIRED)

if(SFML_FOUND)
  include_directories(${SFML_INCLUDE_DIR} )
  target_link_libraries(${EXECUTABLE_NAME} ${SFML_LIBRARIES})
endif()

#if(GLEW_FOUND)
#   MESSAGE("GLEW include path found!")
#   include_directories(${GLEW_INCLUDE_PATH})
#   target_link_libraries(${EXECUTABLE_NAME} ${GLEW_LIBRARY})
#endif()

# Install target
install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin)


 

Share this post


Link to post
Share on other sites
hatfarm    224

I've still got the same problem.  I'm wondering if this is due to me using a different version of GLEW as SFML.  I'm using 1.9.0, I don't know what SFML uses, but could that be an issue?

 

... nope, that is not the issue.  Even if I add {SFML_ROOT}/extlib/headers to my includes, it gives me the same linking error.  I'm not sure what the difference could possibly be.

Share this post


Link to post
Share on other sites
Hiwas    5807

Oops, forgot one other item.  You need to add:

 

ADD_DEFINITIONS( -DSFML_STATIC -DGLEW_STATIC )

To your application..  Without this you are trying to use the dynamic includes.

Share this post


Link to post
Share on other sites
hatfarm    224

Well, that changes things, but nothing good unfortunately.  It just tells me that I defined GLEW_STATIC in more than one file.  Which is nice to know, but not helpful.  It still has the same problem once I get to linking.  This is pretty frustrating...

Share this post


Link to post
Share on other sites
hatfarm    224

I also want to say, thank you so much for your help.  Even though I haven't been able to resolve the issue, I really appreciate that you are helping me so much.

Share this post


Link to post
Share on other sites
Hiwas    5807

Well, for the moment, I'm not sure.  Probably you need to remove the glew static define since that is obviously not needed.  But I'm not sure how to fix the link error, that is almost surely an indication of glew static not being defined somewhere and as such trying to use declspec'd versions incorrectly, but I can't think of anything we've missed right now.  I'll go poke around in my codebase and see if I can find anything I did there that hasn't been covered yet.

 

One thing you might try is to remove any inclusions of glew/gl headers and only use the <SFML/OpenGL.hpp> header just in case there is an include order conflict somewhere.

 

As to helping out, no worries.  Been fighting with an SFML integration problem tonight trying to test the Spine runtimes, might use them for 2D stuff, just an experiment but it doesn't want to work correctly as of yet.

Share this post


Link to post
Share on other sites
hatfarm    224

Yeah, I'm wondering if using SDL might be a better option, or if maybe I should use Qt.  Qt 5.1 removes a need for GLEW at all, and would lose my need for GLM or SFML type stuff (and RapidXML).  However, I'd have to go in and refactor all my code for the way Qt does things, which is no fun.  However, I'd have a multiplatform project file that I understand pretty well already.  Anyway, thanks again.  I'm gonna keep plugging away, because I'd prefer not to have to refactor, but at some point I'm going to have to work on making actual code progress as opposed to CMake tinkering.

Share this post


Link to post
Share on other sites
Hiwas    5807

Before you do anything drastic.  The best way I could help is with a buildable item.  Make a copy, remove all your code and just stick a main file in there that creates a window.  Assuming that still has the link problems, zip it up and let me take a look at it, can probably figure it out in fairly short order that way.

Share this post


Link to post
Share on other sites
hatfarm    224

Wow!  I got it to work.  It started with me essentially copying your CMakeLists.txt and adjusting it in ways I knew I could get it to work.  I think the problem was with FindSFML.cmake, because removing that and linking the directories made it compile (after some finessing).  Here's my final file, maybe you can think of a way to make it more brief :)

 

cmake_minimum_required(VERSION 2.6)
project(BattleMap)

include_directories(
	"${PROJECT_BINARY_DIR}"
	$ENV{GLM_ROOT}
	$ENV{RAPIDXML_ROOT}
	$ENV{SFML_ROOT}/extlibs/headers
	$ENV{SFML_ROOT}/include
)

set(EXECUTABLE_NAME "BattleMap")
set(BattleMap_SRCS	
	battlemap.cpp
	battlemap.h
	
	bufferobject.cpp
	bufferobject.h
	
	camera.cpp
	camera.h
	
	globals.h
	
	vertices.h
	
	texture.cpp
	texture.h
	
	vao.cpp
	vao.h
	
	supertexture.cpp
	supertexture.h
	
	shaderprog.cpp
	shaderprog.h
	
	scene.cpp
	scene.h
	
	submapscene.cpp
	submapscene.h
	
	mapscene.cpp
	mapscene.h
	
	mousepointerscene.cpp
	mousepointerscene.h
	
	application.cpp
	application.h
	
	main.cpp
)

IF (WIN32)
	MESSAGE("IS Win32")
ELSE (WIN32)
	MESSAGE("NOT Win32")
ENDIF (WIN32)
	
ADD_DEFINITIONS( -DSFML_STATIC )
	
add_executable(${EXECUTABLE_NAME} ${BattleMap_SRCS})

add_library(sfml_main STATIC IMPORTED)
add_library(sfml_window STATIC IMPORTED)
add_library(sfml_system STATIC IMPORTED)
add_library(sfml_graphics STATIC IMPORTED)

set_target_properties(sfml_main PROPERTIES
       IMPORTED_LOCATION $ENV{SFML_ROOT}/lib/sfml-main.lib)

set_target_properties(sfml_window PROPERTIES
       IMPORTED_LOCATION $ENV{SFML_ROOT}/lib/sfml-window-s.lib)
	   
set_target_properties(sfml_system PROPERTIES
       IMPORTED_LOCATION $ENV{SFML_ROOT}/lib/sfml-system-s.lib)
	   
set_target_properties(sfml_graphics PROPERTIES
       IMPORTED_LOCATION $ENV{SFML_ROOT}/lib/sfml-graphics-s.lib)
	   
add_library(sfml_main_d STATIC IMPORTED)
add_library(sfml_window_d STATIC IMPORTED)
add_library(sfml_system_d STATIC IMPORTED)
add_library(sfml_graphics_d STATIC IMPORTED)

set_target_properties(sfml_main_d PROPERTIES
       IMPORTED_LOCATION $ENV{SFML_ROOT}/lib/sfml-main-d.lib)

set_target_properties(sfml_window_d PROPERTIES
       IMPORTED_LOCATION $ENV{SFML_ROOT}/lib/sfml-window-s-d.lib)
	   
set_target_properties(sfml_system_d PROPERTIES
       IMPORTED_LOCATION $ENV{SFML_ROOT}/lib/sfml-system-s-d.lib)
	   
set_target_properties(sfml_graphics_d PROPERTIES
       IMPORTED_LOCATION $ENV{SFML_ROOT}/lib/sfml-graphics-s-d.lib)
	   
SET(link_sfml_main optimized sfml_main debug sfml_main_d)
SET(link_sfml_window optimized sfml_window debug sfml_window_d)
SET(link_sfml_system optimized sfml_system debug sfml_system_d)
SET(link_sfml_graphics optimized sfml_graphics debug sfml_graphics_d)
	   
TARGET_LINK_LIBRARIES(${EXECUTABLE_NAME}
	${link_sfml_main}
	${link_sfml_window}
	${link_sfml_system}
	${link_sfml_graphics}
)

SET_TARGET_PROPERTIES(${EXECUTABLE_NAME}
	PROPERTIES
	COMPILE_DEFINITIONS
	"GLEW_STATIC="
)

# Install target
install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin)

 

 

Thank you again for your help.  Without your file, I wouldn't have been able to get this working.

Share this post


Link to post
Share on other sites
hatfarm    224

Now, I'm having an issue, but it's one I can stand to have.  It's generating a bad VS2010 solution.  When I try to run it, it tells me that it cannot find the file "path_to_bin\bin\Debug\ALL_BUILD".  Any experience with anything like that?  I'm not going to complain too much, but I'd like to be able to use the VS2010 debugger for debugging my code.  Thanks.

Share this post


Link to post
Share on other sites
hatfarm    224

And, that's just me being dumb.  It's because VS2010 will have ALL_BUILD as the default project.  Setting the BattleMap project as the default project fixed it.

Share this post


Link to post
Share on other sites
Hiwas    5807

Glad you figured it all out.  I'll see if I can come up with any simplifications for your new listfile, though CMake is often quite verbose as you know, so maybe not.  I'm going to be looking into the new 2.8.11 target usage requirement stuff because it solves a huge number of annoyances I have with CMake in larger projects.  It makes all the nonsense with passing parent scoped variables up the context chains go away.

 

Of course I rather expect you might be back in a bit with issues getting it to build on OsX and Linux.  I remember there being a couple gotcha's, mostly on OsX to make it all work.

Share this post


Link to post
Share on other sites
hatfarm    224

I don't know how soon I'll be building in those environments.  Right now the code is only barely functional and not really something anyone would want to use and the only Mac I've got is my wife's Macbook that's a little over 4 years old.  As for Linux, I've got a virtual machine running Linux Mint that I could load up, but I really don't feel like troubleshooting that right now :)  However, I'm sure it's a good idea to troubleshoot now as opposed to later when I'm just trying to build it for a friend real quick.  Looking forward to your future articles!

Share this post


Link to post
Share on other sites
Hiwas    5807

As a note, I started experimenting with the new target usage requirements introduced in CMake 2.8.11.  As soon as folks start pushing those out in their CMake environments your list files get quite a bit more simplified.  No more futzing around with figuring out required includes, support libraries or compile definitions.  All that work I did standardizing the parent scoped values goes away completely.  I think a CMake Part 5 will be coming soon as the changes are well worth a good article.  :)

Share this post


Link to post
Share on other sites
hatfarm    224

So, I think I'm a day short of a necro on this, so just under the gun.  However, I thought I'd post in this thread again because it's related to that.  So, I've got it working in Windows, but I'm having issues with Linux.  I have it generate a Makefile, but it's not listing my include directories/libraries.  Any thoughts?  It's essentially the same as the text that was posted above (just a few more source files).  

Share this post


Link to post
Share on other sites
Hiwas    5807

So, I think I'm a day short of a necro on this, so just under the gun.  However, I thought I'd post in this thread again because it's related to that.  So, I've got it working in Windows, but I'm having issues with Linux.  I have it generate a Makefile, but it's not listing my include directories/libraries.  Any thoughts?  It's essentially the same as the text that was posted above (just a few more source files).  

My first thought is to double check that on Linux you have the static version of SFML installed, I don't believe most Linux installations bother with the static version and only install the shared library versions.  As such, yup, you won't find what you are looking for.  Perhaps for Linux just try to use the shared version and see if that changes anything for you.

Share this post


Link to post
Share on other sites
hatfarm    224

Actually, it's not finding GLM.  That's the first file included that it cannot find, so the problem is that it's not getting my include files right.  I checked that I have the environment variables setup, and they are, and they point to the correct place, but it says "cannot find glm/glm.h".  However, I didn't compile SFML in Linux, so I'll have to do that also.  I was thinking I could just put the libraries I'm using into the include path directory if I really need to, but I'd prefer to not have to do that, since CMake should be doing that work for me.

Share this post


Link to post
Share on other sites
Hiwas    5807

Well, that is a separate issue.  Glm is not part of, nor included with SFML, that's the GL math library which you have to install/build separately.  I don't believe that Linux distro's include that normally so you likely need to make sure it is all good.  Another item to keep in mind is that you may need to deal with the differences in '/' and '\', if you have '\' it could screw up CMake though it usually takes care of such things.  Hmm, can't think of anything else at the moment though, I have never used GLM myself so not familiar with it's setup.

Share this post


Link to post
Share on other sites
hatfarm    224

Yeah, I understand that, but at the beginning of my CmakeLists.txt file I have:

 

include_directories(
	"${PROJECT_BINARY_DIR}"
	$ENV{GLM_ROOT}
	$ENV{RAPIDXML_ROOT}
	$ENV{SFML_ROOT}/extlibs/headers
	$ENV{SFML_ROOT}/include
)

And the environment variable "GLM_ROOT" points to the location where I have GLM (it's a header only library, so nothing to compile).  I have it point to the root directory /home/glm, which is where I have it point to in Windows (essentially... c:\glm there) and it works, but in Linux I have no such luck.  The Makefile created under Linux doesn't seem to know where the include file is located.  

Share this post


Link to post
Share on other sites
hatfarm    224

Well, I figured it out.  It was an issues with / vs \ .  I had to fix that in the files including my included files.  Now I've got to sift through all the errors and resolve them.  I'm glad that defines are so easy in CMake, so I can define smart_ptr differently in windows and linux.  Thanks for your help.  I apologize it wasn't actually Cmake related, but it was build environment related :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this