artas2357
artas2357

Reputation: 183

GLAD initialization on multiple dlls that use GLAD

At the moment I am making a simple 3D space using glfw and glad. My approach for project management is to separate it into smaller projects, like:

ExternalGraphicsLibs has glfw, glad and glm dirs which source is directly from github (I have only made a single cmakelists file to make it .dll from this project). Renderer and Scene both use glad functionality (they do not see GLFW functionality) and Window only sees GLFW (no GLAD visibility).

The problem I am facing is that both Renderer and Scene need glad initialized, and if I initialize glad only in renderer, the scene does not see it so I need to reinitialize it there too. In my opinion, it is not the best approach, because both libs will have 2 different function pointers to glad which basically will do the same thing.

Do you guys know any solution to this problem? How to solve this problem, or just leave it this where every dll that uses glad would have it's own initialization?

My cmake for ExternalGraphicalLibs:

cmake_minimum_required(VERSION 3.24.0)
project(ExternalGraphicsLibs)

set(CMAKE_BUILD_PARALLEL_LEVEL)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Find and configure OpenGL
find_package(OpenGL REQUIRED)

# GLFW options
set(GLFW_BUILD_DOCS OFF CACHE BOOL "Disable GLFW docs" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "Disable GLFW tests" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "Disable GLFW examples" FORCE)
set(GLFW_INSTALL OFF CACHE BOOL "Disable GLFW install" FORCE)

# Add GLFW source code
add_subdirectory(glfw)

# Add GLAD source code
add_library(${PROJECT_NAME} 
    STATIC 
        ${CMAKE_CURRENT_SOURCE_DIR}/glad/src/gl.c
)

target_include_directories(${PROJECT_NAME} 
    PUBLIC
        glfw/include
        glad/include
        glm/
        ${OPENGL_INCLUDE_DIRS}
)

target_link_libraries(${PROJECT_NAME} 
    PUBLIC
        glfw
        ${OPENGL_LIBRARIES}
)

Upvotes: 1

Views: 69

Answers (2)

artas2357
artas2357

Reputation: 183

Big thanks to @Botje, I have managed to make GLAD a SHARED lib (.dll) with this cmake:

cmake_minimum_required(VERSION 3.24.0)
project(ExternalGraphicsLibs)

set(CMAKE_BUILD_PARALLEL_LEVEL)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Find and configure OpenGL
find_package(OpenGL REQUIRED)

# GLFW options
set(GLFW_BUILD_DOCS OFF CACHE BOOL "Disable GLFW docs" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "Disable GLFW tests" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "Disable GLFW examples" FORCE)
set(GLFW_INSTALL OFF CACHE BOOL "Disable GLFW install" FORCE)

# Add GLFW source code
add_subdirectory(glfw)

# Add GLAD source code
add_library(${PROJECT_NAME} 
    SHARED 
        ${CMAKE_CURRENT_SOURCE_DIR}/glad/src/gl.c
)

# Define GLM_DLL_EXPORT for exporting symbols
target_compile_definitions(${PROJECT_NAME} 
    PRIVATE 
        GLAD_API_CALL_EXPORT_BUILD
    PUBLIC 
        GLAD_API_CALL_EXPORT
)

target_include_directories(${PROJECT_NAME} 
    PUBLIC
        glfw/include
        glad/include
        glm/
        ${OPENGL_INCLUDE_DIRS}
)

target_link_libraries(${PROJECT_NAME} 
    PUBLIC
        glfw
        ${OPENGL_LIBRARIES}
)

P.S. note that ExternalGraphicsLibs subproject has GLFW and GLM directories in the same path as GLAD.

Upvotes: 1

Botje
Botje

Reputation: 30860

By making your ExternalGraphicsLibs STATIC, every library that links to it effectively has its own copy of GLAD. Make it SHARED instead, so the GLAD state can be shared by all of its customers.

It also looks like gladLoadGL is not designed to be called multiple times. You should wrap it in a simple function that prevents multiple calls. Or you could use std::call_once, which also handles any concurrent calls for you:

// As part of a second file in externalGraphicsLibs
std::once_flag loadGL_once;
int loadGL() {
  return std::call_once(loadGL_once, [](){ return gladLoadGL(glfwGetProcAddress); });
}

Upvotes: 2

Related Questions