Reputation: 41
I set up CLion, MinGW and added the appropriate freeglut files into MinGW.
Now, I'm trying to run this code:
/*
* GL01Hello.cpp: Test OpenGL C/C++ Setup
*/
#include <windows.h> // For MS Windows
#include <GL/glut.h> // GLUT, includes glu.h and gl.h
/* Handler for window-repaint event. Call back when the window first appears and
whenever the window needs to be re-painted. */
void display() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer
// Draw a Red 1x1 Square centered at origin
glBegin(GL_QUADS); // Each set of 4 vertices form a quad
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex2f(-0.5f, -0.5f); // x, y
glVertex2f( 0.5f, -0.5f);
glVertex2f( 0.5f, 0.5f);
glVertex2f(-0.5f, 0.5f);
glEnd();
glFlush(); // Render now
}
/* Main function: GLUT runs as a console application starting at main() */
int main(int argc, char** argv) {
glutInit(&argc, argv); // Initialize GLUT
glutCreateWindow("OpenGL Setup Test"); // Create a window with the given title
glutInitWindowSize(320, 320); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutDisplayFunc(display); // Register display callback handler for window re-paint
glutMainLoop(); // Enter the infinitely event-processing loop
return 0;
}
...and this is the console message I get:
====================[ Build | test | Default ]==================================
"D:\CLion 2021.1.2\bin\cmake\win\bin\cmake.exe" --build D:\test\cmake-build-default --target test -- -j 9
[ 25%] Built target libfreeglut_static.a
[ 50%] Built target libfreeglut.a
Scanning dependencies of target test
[ 75%] Building CXX object CMakeFiles/test.dir/main.cpp.obj
[100%] Linking CXX executable test.exe
CMakeFiles\test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x25): undefined reference to `__imp___glutInitWithExit'
CMakeFiles\test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x4c): undefined reference to `__imp___glutCreateWindowWithExit'
CMakeFiles\test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x72): undefined reference to `__imp___glutCreateMenuWithExit'
CMakeFiles\test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x192): undefined reference to `__imp_glutInitWindowSize'
CMakeFiles\test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x1a5): undefined reference to `__imp_glutInitWindowPosition'
CMakeFiles\test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x1b5): undefined reference to `__imp_glutDisplayFunc'
CMakeFiles\test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x1be): undefined reference to `__imp_glutMainLoop'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe[3]: *** [CMakeFiles\test.dir\build.make:106: test.exe] Error 1
mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:99: CMakeFiles/test.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:106: CMakeFiles/test.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:136: test] Error 2
And my CMakeLists.txt looks like this:
cmake_minimum_required(VERSION 3.19)
project(test)
find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -pthread -fpermissive")
add_executable(test main.cpp)
link_directories(${OPENGL_gl_LIBRARY})
add_library(libfreeglut.a SHARED ${CMAKE_SOURCE_DIR}/lib/)
set_target_properties(libfreeglut.a PROPERTIES LINKER_LANGUAGE CXX)
add_library(libfreeglut_static.a STATIC ${CMAKE_SOURCE_DIR}/lib/)
set_target_properties(libfreeglut_static.a PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(test libfreeglut.a libfreeglut_static.a ${OPENGL_gl_LIBRARY})
I'm sure the issue is with linking the libraries, but I don't understand why some of the freeglut functions work regardless, which makes me think that I must have done something right somewhere.
The two functions that are highlighted work just fine, and they are defined in one of the freeglut libraries:
Update:
As per ben10's suggestion, I enabled CMAKE_EXPORT_COMPILE_COMMANDS
before modifying anything in my CMake file, and this was generated:
[
{
"directory": "D:/test/cmake-build-default",
"command": "D:\\minGW\\mingw64\\bin\\x86_64-w64-mingw32-g++.exe -std=c++14 -pthread -fpermissive -std=gnu++14 -o CMakeFiles\\test.dir\\main.cpp.obj -c D:\\test\\main.cpp",
"file": "D:/test/main.cpp"
}
]
After that, I modified CMakeLists.txt according to what ben10 recommended, and now it won't compile. The error message is below:
"D:\CLion 2021.1.2\bin\cmake\win\bin\cmake.exe" -DCMAKE_MAKE_PROGRAM=D:/minGW/mingw64/bin/mingw32-make.exe -DCMAKE_C_COMPILER=D:/minGW/mingw64/bin/x86_64-w64-mingw32-gcc.exe -DCMAKE_CXX_COMPILER=D:/minGW/mingw64/bin/x86_64-w64-mingw32-g++.exe -G "CodeBlocks - MinGW Makefiles" D:\test
-- Configuring done
CMake Error at CMakeLists.txt:22 (add_library):
No SOURCES given to target: libfreeglut
CMake Error at CMakeLists.txt:23 (add_library):
No SOURCES given to target: libfreeglut_static
CMake Generate step failed. Build files cannot be regenerated correctly.
[Failed to reload]
Since it says that libfreeglut has no source (although it was pointed towards CMAKE_SOURCE_DIR/lib/
), could that mean I messed up adding glut to MinGW? I reinstalled both MinGW and glut and I'm still getting the same result.
Upvotes: 4
Views: 4232
Reputation: 241
I really want to spread some modern CMake practice, and who knows it may lead you to solving the issue you have.
My feeling is you're not linking with GLUT::GLUT
, but I can't verify that.
I'd rewrite some of the CMakeLists.txt as follows:
cmake_minimum_required(VERSION 3.19)
project(test)
# from the docs, this gives you `OpenGL::GL`
find_package(OpenGL REQUIRED)
# from the docs, this gives you `GLUT::GLUT`
find_package(GLUT REQUIRED)
# and this `Threads::Threads` which adds the pthread flag, only when needed
find_package(Threads REQUIRED)
# why do you need permisive? seems odd, you should try to fix that instead of just using fpermissive
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
# the first argument is just the name of a target, not the name of the library, prefix and suffix get added, if needed
# I have no idea what you have in these folders, but I d consider using an OBJECT library, to not compile the code twice
add_library(libfreeglut_obj OBJECT ${CMAKE_SOURCE_DIR}/lib/)
target_link_libraries(libfreeglut_obj PUBLIC OpenGL::GL GLUT::GLUT Threads::Threads)
set_target_properties(libfreeglut_obj PROPERTIES LINKER_LANGUAGE CXX)
add_library(libfreeglut SHARED $<TARGET_OBJECTS:libfreeglut_obj>)
add_library(libfreeglut_static STATIC $<TARGET_OBJECTS:libfreeglut_obj>)
# with the version of cmake you have, you might actually be able to do just `target_link_libraries` with the object lib, or
target_link_libraries(libfreeglut PUBLIC libfreeglut_object)
target_link_libraries(libfreeglut_static PUBLIC libfreeglut_object)
# seems like it s the same code in both the shared and static lib, pick one, I picked the shared one for you
add_executable(test main.cpp)
target_link_libraries(test libfreeglut)
Now, with this (or before this) I'd activate CMAKE_EXPORT_COMPILE_COMMANDS
link and CMAKE_VERBOSE_MAKEFILE
link and run the build again, just to see exactly what gets compiled/linked.
EDIT: awesome article on CMake shared/static builds link. thanks @AlexReinking!
Upvotes: 2