Windows 上未链接的 OpenGL 扩展

OpenGL extensions not linking on Windows

我正在尝试 link OpenGL 到 Windows 的应用程序(基于 Windows)。

我使用 Conan 作为包管理器,使用 CMake 进行构建,使用 MSVC 作为编译器(使用 CLion 作为 IDE)。

程序可以编译,但我有 linker 错误,因为我认为是 OpenGL 中的扩展函数:

imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glBlendEquation referenced in function "void __cdecl ImGui_ImplOpenGL3_SetupRenderState(struct ImDrawData *,int,int,unsigned int)" (?ImGui_ImplOpenGL3_SetupRenderState@@YAXPEAUImDrawData@@HHI@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glActiveTexture referenced in function "void __cdecl ImGui_ImplOpenGL3_RenderDrawData(struct ImDrawData *)" (?ImGui_ImplOpenGL3_RenderDrawData@@YAXPEAUImDrawData@@@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glBlendFuncSeparate referenced in function "void __cdecl ImGui_ImplOpenGL3_RenderDrawData(struct ImDrawData *)" (?ImGui_ImplOpenGL3_RenderDrawData@@YAXPEAUImDrawData@@@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glBindBuffer referenced in function "void __cdecl ImGui_ImplOpenGL3_RenderDrawData(struct ImDrawData *)" (?ImGui_ImplOpenGL3_RenderDrawData@@YAXPEAUImDrawData@@@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glDeleteBuffers referenced in function "void __cdecl ImGui_ImplOpenGL3_DestroyDeviceObjects(void)" (?ImGui_ImplOpenGL3_DestroyDeviceObjects@@YAXXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glGenBuffers referenced in function "bool __cdecl ImGui_ImplOpenGL3_CreateDeviceObjects(void)" (?ImGui_ImplOpenGL3_CreateDeviceObjects@@YA_NXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glBufferData referenced in function "void __cdecl ImGui_ImplOpenGL3_RenderDrawData(struct ImDrawData *)" (?ImGui_ImplOpenGL3_RenderDrawData@@YAXPEAUImDrawData@@@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glBlendEquationSeparate referenced in function "void __cdecl ImGui_ImplOpenGL3_RenderDrawData(struct ImDrawData *)" (?ImGui_ImplOpenGL3_RenderDrawData@@YAXPEAUImDrawData@@@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glAttachShader referenced in function "bool __cdecl ImGui_ImplOpenGL3_CreateDeviceObjects(void)" (?ImGui_ImplOpenGL3_CreateDeviceObjects@@YA_NXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glCompileShader referenced in function "bool __cdecl ImGui_ImplOpenGL3_CreateDeviceObjects(void)" (?ImGui_ImplOpenGL3_CreateDeviceObjects@@YA_NXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glCreateProgram referenced in function "bool __cdecl ImGui_ImplOpenGL3_CreateDeviceObjects(void)" (?ImGui_ImplOpenGL3_CreateDeviceObjects@@YA_NXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glCreateShader referenced in function "bool __cdecl ImGui_ImplOpenGL3_CreateDeviceObjects(void)" (?ImGui_ImplOpenGL3_CreateDeviceObjects@@YA_NXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glDeleteProgram referenced in function "void __cdecl ImGui_ImplOpenGL3_DestroyDeviceObjects(void)" (?ImGui_ImplOpenGL3_DestroyDeviceObjects@@YAXXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glDeleteShader referenced in function "void __cdecl ImGui_ImplOpenGL3_DestroyDeviceObjects(void)" (?ImGui_ImplOpenGL3_DestroyDeviceObjects@@YAXXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glDetachShader referenced in function "void __cdecl ImGui_ImplOpenGL3_DestroyDeviceObjects(void)" (?ImGui_ImplOpenGL3_DestroyDeviceObjects@@YAXXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glEnableVertexAttribArray referenced in function "void __cdecl ImGui_ImplOpenGL3_SetupRenderState(struct ImDrawData *,int,int,unsigned int)" (?ImGui_ImplOpenGL3_SetupRenderState@@YAXPEAUImDrawData@@HHI@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glGetAttribLocation referenced in function "bool __cdecl ImGui_ImplOpenGL3_CreateDeviceObjects(void)" (?ImGui_ImplOpenGL3_CreateDeviceObjects@@YA_NXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glGetProgramiv referenced in function "bool __cdecl CheckProgram(unsigned int,char const *)" (?CheckProgram@@YA_NIPEBD@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glGetProgramInfoLog referenced in function "bool __cdecl CheckProgram(unsigned int,char const *)" (?CheckProgram@@YA_NIPEBD@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glGetShaderiv referenced in function "bool __cdecl CheckShader(unsigned int,char const *)" (?CheckShader@@YA_NIPEBD@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glGetShaderInfoLog referenced in function "bool __cdecl CheckShader(unsigned int,char const *)" (?CheckShader@@YA_NIPEBD@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glGetUniformLocation referenced in function "bool __cdecl ImGui_ImplOpenGL3_CreateDeviceObjects(void)" (?ImGui_ImplOpenGL3_CreateDeviceObjects@@YA_NXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glLinkProgram referenced in function "bool __cdecl ImGui_ImplOpenGL3_CreateDeviceObjects(void)" (?ImGui_ImplOpenGL3_CreateDeviceObjects@@YA_NXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glShaderSource referenced in function "bool __cdecl ImGui_ImplOpenGL3_CreateDeviceObjects(void)" (?ImGui_ImplOpenGL3_CreateDeviceObjects@@YA_NXZ)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glUseProgram referenced in function "void __cdecl ImGui_ImplOpenGL3_RenderDrawData(struct ImDrawData *)" (?ImGui_ImplOpenGL3_RenderDrawData@@YAXPEAUImDrawData@@@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glUniform1i referenced in function "void __cdecl ImGui_ImplOpenGL3_SetupRenderState(struct ImDrawData *,int,int,unsigned int)" (?ImGui_ImplOpenGL3_SetupRenderState@@YAXPEAUImDrawData@@HHI@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glUniformMatrix4fv referenced in function "void __cdecl ImGui_ImplOpenGL3_SetupRenderState(struct ImDrawData *,int,int,unsigned int)" (?ImGui_ImplOpenGL3_SetupRenderState@@YAXPEAUImDrawData@@HHI@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glVertexAttribPointer referenced in function "void __cdecl ImGui_ImplOpenGL3_SetupRenderState(struct ImDrawData *,int,int,unsigned int)" (?ImGui_ImplOpenGL3_SetupRenderState@@YAXPEAUImDrawData@@HHI@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glGetStringi referenced in function "bool __cdecl ImGui_ImplOpenGL3_Init(char const *)" (?ImGui_ImplOpenGL3_Init@@YA_NPEBD@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glBindVertexArray referenced in function "void __cdecl ImGui_ImplOpenGL3_RenderDrawData(struct ImDrawData *)" (?ImGui_ImplOpenGL3_RenderDrawData@@YAXPEAUImDrawData@@@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glDeleteVertexArrays referenced in function "void __cdecl ImGui_ImplOpenGL3_RenderDrawData(struct ImDrawData *)" (?ImGui_ImplOpenGL3_RenderDrawData@@YAXPEAUImDrawData@@@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glGenVertexArrays referenced in function "void __cdecl ImGui_ImplOpenGL3_RenderDrawData(struct ImDrawData *)" (?ImGui_ImplOpenGL3_RenderDrawData@@YAXPEAUImDrawData@@@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glDrawElementsBaseVertex referenced in function "void __cdecl ImGui_ImplOpenGL3_RenderDrawData(struct ImDrawData *)" (?ImGui_ImplOpenGL3_RenderDrawData@@YAXPEAUImDrawData@@@Z)
imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glBindSampler referenced in function "void __cdecl ImGui_ImplOpenGL3_RenderDrawData(struct ImDrawData *)" (?ImGui_ImplOpenGL3_RenderDrawData@@YAXPEAUImDrawData@@@Z)
soundstate.exe : fatal error LNK1120: 34 unresolved externals

我想我已经在整个互联网上寻找解决方案,但我不明白缺少什么。我的直觉是,目前 OpenGL 扩展没有 linked(作为 OpenGL 菜鸟,我不是 100% 确定这甚至意味着什么)。

我正在使用 GL_GLEXT_PROTOTYPES=1 进行编译。

这是正在执行的 linker 命令:

C:\PROGRA~2\MIB055~119\COMMUN~1\VC\Tools\MSVC29~1.300\bin\Hostx86\x64\link.exe /nologo @CMakeFiles\soundstate.dir\objects1.rsp /out:soundstate.exe /implib:soundstate.lib /pdb:<project dir>\cmake-build-debug\soundstate.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console core.lib ..\vendor\fmod\windows\lib\x64\fmodL_vc.lib <user dir>\.conan\data\imgui-docking.83\trololo\stable\package6e49ae2c2d7b4448ca2380ea2b4c7a382d695b\lib\imgui.lib <user dir>\.conan\data\sdl2.0.14\bincrafters\stable\package\a5e24820448cb570d848a2e59f317dd7edebe889\lib\SDL2maind.lib <user dir>\.conan\data\sdl2.0.14\bincrafters\stable\package\a5e24820448cb570d848a2e59f317dd7edebe889\lib\SDL2d.lib user32.lib gdi32.lib winmm.lib imm32.lib ole32.lib oleaut32.lib version.lib uuid.lib advapi32.lib setupapi.lib shell32.lib <user dir>\.conan\data\libiconv.16\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib\iconv.lib C:\Users\simon\.conan\data\libiconv.16\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib\charset.lib <user dir>\.conan\data\glew.2.0\_\_\packagecd10aa7b17419a389740c9a9a85afec1178e5cf\lib\libglew32d.lib opengl32.lib Glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\soundstate.dir/intermediate.manifest CMakeFiles\soundstate.dir/manifest.res

我试过:

这是我的CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(soundstate C CXX)
set(CMAKE_CXX_STANDARD 17)

set(CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})

find_package(imgui REQUIRED CONFIG)
find_package(SDL2 REQUIRED CONFIG)
find_package(immer REQUIRED CONFIG)
find_package(cereal REQUIRED CONFIG)
find_package(Boost REQUIRED CONFIG)
find_package(rxcpp REQUIRED CONFIG)
find_package(range-v3 REQUIRED CONFIG)
find_package(opengl_system REQUIRED CONFIG)
find_package(glew REQUIRED CONFIG)

#
# FMOD
#
set(CMAKE_VERBOSE_MAKEFILE ON)
if (WIN32)
    add_library(fmod STATIC IMPORTED)
    set_target_properties(fmod PROPERTIES
            LINKER_LANGUAGE C
            INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/fmod/linux/inc
            IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/vendor/fmod/windows/lib/x64/fmodL_vc.lib
            )
else ()
    file(COPY vendor/fmod/linux/lib/x86_64/libfmodL.so.12.9 DESTINATION ${CMAKE_BINARY_DIR}/resources/lib)
    set_target_properties(fmod PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/resources/lib/libfmodL.so)
endif ()

#
# Core
#
set(CORE_SOURCES
        core/model.h
        core/actions.h
        core/reducers.h
        core/utils.h core/utils.cpp
        core/reducers.cpp
        core/cursors.h core/cursors.cpp
        core/io.cpp core/io.h
        core/serialization.h
        core/audio/audio_engine.cpp core/audio/audio_engine.h
        core/audio/audio_context.cpp core/audio/audio_context.h)

add_library(core STATIC ${CORE_SOURCES})

target_include_directories(core PUBLIC include)
target_include_directories(core PUBLIC ${CONAN_INCLUDE_DIRS})

set(CORE_LIBS
        immer::immer
        cereal::cereal
        Boost::Boost
        rxcpp::rxcpp
        range-v3::range-v3
        )

set(ALL_LIBS
        imgui::imgui
        SDL2::SDL2
        immer::immer
        cereal::cereal
        Boost::Boost
        rxcpp::rxcpp
        range-v3::range-v3
        opengl::opengl
        GLEW::GLEW
        )

target_link_libraries(core fmod ${CORE_LIBS})


#
# Main
#
set(SOURCES
        ui/imgui/main.cpp
        ui/imgui/panels/panel.cpp ui/imgui/panels/panel.h
        ui/imgui/panels/playables_tree_panel.cpp ui/imgui/panels/playables_tree_panel.h
        ui/imgui/gui_manager.cpp ui/imgui/gui_manager.h
        ui/imgui/panels/playable_editor_panel.cpp ui/imgui/panels/playable_editor_panel.h
        ui/imgui/editors/editor.cpp ui/imgui/editors/editor.h
        ui/imgui/editors/file_playable_editor.cpp ui/imgui/editors/file_playable_editor.h
        ui/imgui/editors/list_playable_editor.cpp ui/imgui/editors/list_playable_editor.h
        ui/imgui/editors/state_editor.cpp ui/imgui/editors/state_editor.h
        ui/imgui/editors/state_option_editor.cpp ui/imgui/editors/state_option_editor.h
        ui/imgui/imgui_extras.h
        ui/imgui/icons_fa5.h
        include/ImGuiFileDialog/ImGuiFileDialog.cpp
        ui/imgui/panels/state_list_panel.cpp
        ui/imgui/panels/state_list_panel.h
        ui/imgui/panels/debug_panel.cpp
        ui/imgui/panels/debug_panel.h
        ui/imgui/panels/controls_panel.cpp
        ui/imgui/panels/controls_panel.h
        bindings/imgui_impl_opengl3.h
        bindings/imgui_impl_opengl3.cpp
        bindings/imgui_impl_sdl.h
        bindings/imgui_impl_sdl.cpp
        bindings/imgui_stdlib.h
        bindings/imgui_stdlib.cpp
        )

add_executable(soundstate ${SOURCES})

target_include_directories(soundstate PUBLIC vendor)
# Configure Imgui to use OpengGL through SDL2
target_compile_definitions(soundstate PUBLIC IMGUI_IMPL_OPENGL_LOADER_CUSTOM=<SDL_opengl.h> GL_GLEXT_PROTOTYPES=1)
target_link_libraries(soundstate core ${ALL_LIBS})

# Copy resources
file(COPY resources/fonts/Roboto-Regular.ttf DESTINATION ${CMAKE_BINARY_DIR}/resources/fonts)
file(COPY resources/fonts/fa-regular-400.ttf DESTINATION ${CMAKE_BINARY_DIR}/resources/fonts)
file(GLOB AUDIO_FILES resources/audio/*)
file(COPY ${AUDIO_FILES} DESTINATION ${CMAKE_BINARY_DIR}/resources/audio)
file(COPY vendor/fmod/windows/lib/x64/fmodL.dll DESTINATION ${CMAKE_BINARY_DIR}/resources/lib)
file(COPY vendor/fmod/windows/lib/x64/fmodL_vc.lib DESTINATION ${CMAKE_BINARY_DIR}/resources/lib)

I'm compiling with GL_GLEXT_PROTOTYPES=1.

好吧,别那样做。这永远不会以便携的方式工作。在 windows 上,opengl32.dll 始终 仅导出 OpenGL 1.1 中的函数,对于除此之外的所有内容,您必须依赖 OpenGL extension loading mechanism 运行时.

I have tried:

  • [...]
  • Adding GLEW

这是朝着正确方向迈出的一步。但这并不能使事情神奇地起作用。像 GLEW 这样的 GL 加载器通常将其 own header 作为 GL.hglext.h 等的 replacement ., 而典型的 GL 加载器(如 GLEW)只是 re-define 每个 GL 都作为一个宏运行,如下所示:

#define glFooFunc() __myloader_FooFunc

其中 __myloader_FooFunc 只是一个 函数指针 必须使用加载程序提供的某些函数进行初始化(如 glewInit)。

现在这有一些影响:如果在某些源文件中包含 GL 加载器的 header,预处理器将已经替换所有 glSomething 函数名称,链接器将永远看不到它们。但这只在那个特定的源文件中是正确的。如果您有另一个没有加载程序的源文件 header,将使用实际的 GL 函数名称,链接器将找不到它们。

从您的错误消息中,例如:

imgui_impl_opengl3.cpp.obj : error LNK2019: unresolved external symbol __imp_glBlendEquation referenced in function "void __cdecl ImGui_ImplOpenGL3_SetupRenderState(struct ImDrawData *,int,int,unsigned int)" (?ImGui_ImplOpenGL3_SetupRenderState@@YAXPEAUImDrawData@@HHI@Z)

很容易看出函数ImGui_ImplOpenGL3_SetupRenderState没有用GL加载器编译,而是直接使用了GL函数名。

由于ImGui支持OpenGL后端,所以已经有办法处理,看官方examples:

// About Desktop OpenGL function loaders:
//  Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
//  Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).
//  You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
#include <GL/gl3w.h>            // Initialize with gl3wInit()
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
#include <GL/glew.h>            // Initialize with glewInit()
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
#include <glad/glad.h>          // Initialize with gladLoadGL()
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2)
#include <glad/gl.h>            // Initialize with gladLoadGL(...) or gladLoaderLoadGL()
[...]

因此,如果您想将 ImGui 与 GLEW 一起使用,则必须使用 IMGUI_IMPL_OPENGL_LOADER_GLEW