【问题标题】:Undefined reference to `__imp___glutInitWithExit' and others, but library is linked对 `__imp___glutInitWithExit' 和其他的未定义引用,但库已链接
【发布时间】:2021-09-07 02:19:41
【问题描述】:

我设置了 CLion、MinGW 并将适当的 freeglut 文件添加到 MinGW。

现在,我正在尝试运行这段代码:

/*
 * 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;
}

...这是我收到的控制台消息:

====================[ 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

我的 CMakeLists.txt 看起来像这样:

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})

我确定问题出在链接库上,但我不明白为什么某些 freeglut 函数无论如何都能正常工作,这让我觉得我一定在某个地方做了什么。

突出显示的两个函数工作得很好,它们是在 freeglut 库之一中定义的:

更新:

根据 ben10 的建议,我在修改 CMake 文件中的任何内容之前启用了CMAKE_EXPORT_COMPILE_COMMANDS,并生成了这个:

[
{
  "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"
}
]

之后我按照ben10的推荐修改了CMakeLists.txt,现在编译不出来了。错误信息如下:

"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]

既然它说 libfreeglut 没有来源(尽管它指向CMAKE_SOURCE_DIR/lib/),这是否意味着我搞砸了向 MinGW 添加 glut?我重新安装了 MinGW 和 glut,但仍然得到相同的结果。

【问题讨论】:

  • 我认为您不想同时链接此libfreeglut_static.alibfreeglut.a。我相信libfreeglut.a 使用 dll 而libfreeglut_static.a 没有。
  • 我会先做一些事情:1)删除库名称中的 .a,你有一个共享库和一个静态库,让 cmake 为你添加扩展名:@987654334 @ (我什至会考虑考虑 lib 前缀(在某些平台上也添加了)。2)我会做类似以下的事情:设置 CMAKE_VERBOSE_MAKEFILE 如果你使用的是 make (或忍者)并让 cmake 输出详细的构建命令,也许它们会帮助你弄清楚发生了什么
  • 错误消息表明您的构建需要链接到 freeglut 库 FWIW 的动态 (DLL) 版本。
  • 另外,我认为您需要与GLUT::GLUT 链接(如果我正确理解了 GLUT 的 find_package)
  • 编辑后,${CMAKE_SOURCE_DIR}/lib/ 的文件夹中究竟有什么?从compile_commands 的外观看来,似乎没有为这些人建造任何东西。这有点令人困惑。你也可以试试before 和CMAKE_VERBOSE_MAKEFILE 吗?并且,请提供一些关于它如何构建静态和共享库的输出

标签: c++ opengl cmake clion freeglut


【解决方案1】:

我真的很想传播一些现代 CMake 实践,谁知道它可能会引导你解决你遇到的问题。

我的感觉是你没有链接到GLUT::GLUT,但我无法验证。

我会重写一些 CMakeLists.txt 如下:

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)

现在,有了这个(或在此之前),我将激活 CMAKE_EXPORT_COMPILE_COMMANDSlinkCMAKE_VERBOSE_MAKEFILElink 并再次运行构建,以查看编译/链接的确切内容。

编辑:关于 CMake 共享/静态构建的精彩文章 link。谢谢@AlexReinking!

【讨论】:

  • 对于reasons I've published elsewhere,我不认为在单个构建中同时提供库的静态和共享版本是一种非常有效的做法,但我认为你对不的根本原因是正确的链接到 GLUT。例如,您的构建没有测试静态库的方法,由于符号可见性差异,这实际上很重要。
  • (不过我还是赞成你的回答,欢迎来到 StackOverflow!)
  • @AlexReinking 我很想看到更多这样的文章,干得好!
猜你喜欢
  • 2011-12-08
  • 2016-09-19
  • 1970-01-01
  • 2017-08-03
  • 1970-01-01
  • 2023-03-20
  • 2014-10-05
  • 2019-06-24
  • 1970-01-01
相关资源
最近更新 更多