2

Currently I try to make ImGuiConfig.cmake file in order to use Dear ImGui GUI library.

I would like to use that library as below from external project.

find_package(ImGui REQUIRED)
add_executable(hello hello.cpp)
target_link_libraries(hello ${IMGUI_LIBRARIES})

Following CMakeLists.txt is a file I wrote to install ImGui library.

cmake_minimum_required(VERSION 3.10)

# Project Name
project(ImGui)

# This cmake file try to make a lib of ImGui glfw backend
add_definitions(-fPIC)

set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)

# Get header and source file name
file(GLOB_RECURSE SOURCE_CPP RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ImGui/*.cpp)
file(GLOB_RECURSE SOURCE_HEADER RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ImGui/*.h)

# create target
add_library(${PROJECT_NAME} STATIC ${SOURCE_CPP})
target_link_libraries(${PROJECT_NAME} PUBLIC glfw GLEW GL)
set_target_properties(${PROJECT_NAME} PROPERTIES IMPORTED_LINK_LIBRARIES "glfw;GLEW;GL")
set_target_properties(${PROJECT_NAME} PROPERTIES INTERFACE_LINK_LIBRARIES "glfw;GLEW;GL")

install(TARGETS ${PROJECT_NAME} 
    EXPORT ImGuiConfig
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    )

export(TARGETS ${PROJECT_NAME}
    FILE "${CMAKE_CURRENT_BINARY_DIR}/ImGuiConfig.cmake")

install(EXPORT ImGuiConfig
    DESTINATION lib/cmake/ImGui
    EXPORT_LINK_INTERFACE_LIBRARIES
    )

But When I compile external program which use ImGui library, I got following error.

harumo@harumo-thinkpad-x1:~/program/cpp/imgui/hello/build$ make
Scanning dependencies of target hello
[ 50%] Building CXX object CMakeFiles/hello.dir/hello.cpp.o
[100%] Linking CXX executable hello
CMakeFiles/hello.dir/hello.cpp.o: In function `main':
hello.cpp:(.text+0x32): undefined reference to `glfwWindowHint'
hello.cpp:(.text+0x41): undefined reference to `glfwWindowHint'
hello.cpp:(.text+0x50): undefined reference to `glfwWindowHint'
hello.cpp:(.text+0x5f): undefined reference to `glfwWindowHint'
hello.cpp:(.text+0x82): undefined reference to `glfwCreateWindow'
hello.cpp:(.text+0x8f): undefined reference to `glfwMakeContextCurrent'
hello.cpp:(.text+0x99): undefined reference to `glfwSwapInterval'
hello.cpp:(.text+0x9e): undefined reference to `glewInit'
hello.cpp:(.text+0xd3): undefined reference to `ImGui::DebugCheckVersionAndDataLayout(char const*, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)'
hello.cpp:(.text+0xe1): undefined reference to `ImGui::CreateContext(ImFontAtlas*)'
hello.cpp:(.text+0xea): undefined reference to `ImGui::GetIO()'
hello.cpp:(.text+0xf9): undefined reference to `ImGui::StyleColorsLight(ImGuiStyle*)'
hello.cpp:(.text+0x107): undefined reference to `ImGui_ImplGlfw_InitForOpenGL(GLFWwindow*, bool)'
hello.cpp:(.text+0x113): undefined reference to `ImGui_ImplOpenGL3_Init(char const*)'
hello.cpp:(.text+0x147): undefined reference to `glfwWindowShouldClose'
hello.cpp:(.text+0x155): undefined reference to `glfwPollEvents'
hello.cpp:(.text+0x15a): undefined reference to `ImGui_ImplOpenGL3_NewFrame()'
hello.cpp:(.text+0x15f): undefined reference to `ImGui_ImplGlfw_NewFrame()'
hello.cpp:(.text+0x164): undefined reference to `ImGui::NewFrame()'
hello.cpp:(.text+0x179): undefined reference to `ImGui::Begin(char const*, bool*, int)'
hello.cpp:(.text+0x18d): undefined reference to `ImGui::Text(char const*, ...)'
hello.cpp:(.text+0x1a4): undefined reference to `ImGui::Checkbox(char const*, bool*)'
hello.cpp:(.text+0x1ac): undefined reference to `ImGui::End()'
hello.cpp:(.text+0x1b1): undefined reference to `ImGui::Render()'
hello.cpp:(.text+0x1dc): undefined reference to `glfwGetFramebufferSize'
hello.cpp:(.text+0x1f0): undefined reference to `glViewport'
hello.cpp:(.text+0x209): undefined reference to `glClearColor'
hello.cpp:(.text+0x213): undefined reference to `glClear'
hello.cpp:(.text+0x218): undefined reference to `ImGui::GetDrawData()'
hello.cpp:(.text+0x220): undefined reference to `ImGui_ImplOpenGL3_RenderDrawData(ImDrawData*)'
hello.cpp:(.text+0x229): undefined reference to `glfwSwapBuffers'
hello.cpp:(.text+0x233): undefined reference to `ImGui_ImplOpenGL3_Shutdown()'
hello.cpp:(.text+0x238): undefined reference to `ImGui_ImplGlfw_Shutdown()'
hello.cpp:(.text+0x241): undefined reference to `ImGui::DestroyContext(ImGuiContext*)'
hello.cpp:(.text+0x24a): undefined reference to `glfwDestroyWindow'
hello.cpp:(.text+0x24f): undefined reference to `glfwTerminate'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
CMakeFiles/hello.dir/build.make:100: recipe for target 'hello' failed
make[2]: *** [hello] Error 1
CMakeFiles/Makefile2:92: recipe for target 'CMakeFiles/hello.dir/all' failed
make[1]: *** [CMakeFiles/hello.dir/all] Error 2
Makefile:100: recipe for target 'all' failed
make: *** [all] Error 2

It seems that glfw, GLEW and GL library are not imported.

I'm glad if you tell me how to import glfw, GLEW and GL library with the above CMakeLists.txt. If you need more information, feel free tell me.

Thanks in advance.


SOLUTION

Thanks to Tsyvarev's very appropriate comments, I was able to solve the problem. I changed my CMakeLists.txt as follows.

cmake_minimum_required(VERSION 3.10)

# Project Name
project(ImGui)

# This cmake file try to make a lib of ImGui glfw backend
add_definitions(-fPIC)

set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)

# Get header and source file name
file(GLOB_RECURSE SOURCE_CPP RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ImGui/*.cpp)
file(GLOB_RECURSE SOURCE_HEADER RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ImGui/*.h)

# create target
add_library(${PROJECT_NAME} STATIC ${SOURCE_CPP})
target_link_libraries(${PROJECT_NAME} PUBLIC glfw GLEW GL)
set_target_properties(${PROJECT_NAME} PROPERTIES IMPORTED_LINK_LIBRARIES "glfw;GLEW;GL")
set_target_properties(${PROJECT_NAME} PROPERTIES INTERFACE_LINK_LIBRARIES "glfw;GLEW;GL")
set(IMGUI_LIBRARIES ImGui;glfw;GLEW;GL)

install(TARGETS ${PROJECT_NAME} 
    EXPORT ImGuiConfig
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

export(TARGETS ${PROJECT_NAME}
FILE "${CMAKE_CURRENT_BINARY_DIR}/ImGuiConfig.cmake")

install(EXPORT ImGuiConfig
    DESTINATION lib/cmake/ImGui
    EXPORT_LINK_INTERFACE_LIBRARIES
)

I just added to my CMakeLists.txt

set(IMGUI_LIBRARIES ImGui;glfw;GLEW;GL)

By adding this line, I defined a CMAKE variable called IMGUI_LIBRARIES. The contents of this variable are ImGui;glfw;GLEW;GL. This allows the user to load the necessary libraries such as glfw, GLEW, and GL by doing the following.

target_link_libraries(hello ${IMGUI_LIBRARIES})
user438383
  • 5,716
  • 8
  • 28
  • 43
  • 1
    Config file, generated by CMake with `install(TARGETS ... EXPORT)` defines **IMPORTED library targets** with the same names, as names of the installed targets. This file doesn't define variable like `IMGUI_LIBRARIES`, so `${IMGUI_LIBRARIES}` is expanded to nothing. Not, that main config file (which is included via `find_package`) is generally written by you. This file `include()`-s files generated by CMake and may perform additional actions. I would suggest to read [CMake guide about packaging](https://cmake.org/cmake/help/v3.17/manual/cmake-packages.7.html). – Tsyvarev Apr 15 '20 at 07:19

1 Answers1

0

Thanks Tsyvarev!

Your comment is very useful. I changed my CMakeLists.txt as follows.

cmake_minimum_required(VERSION 3.10)

# Project Name
project(ImGui)

# This cmake file try to make a lib of ImGui glfw backend
add_definitions(-fPIC)

set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)

# Get header and source file name
file(GLOB_RECURSE SOURCE_CPP RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ImGui/*.cpp)
file(GLOB_RECURSE SOURCE_HEADER RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ImGui/*.h)

# create target
add_library(${PROJECT_NAME} STATIC ${SOURCE_CPP})
target_link_libraries(${PROJECT_NAME} PUBLIC glfw GLEW GL)
set_target_properties(${PROJECT_NAME} PROPERTIES IMPORTED_LINK_LIBRARIES "glfw;GLEW;GL")
set_target_properties(${PROJECT_NAME} PROPERTIES INTERFACE_LINK_LIBRARIES "glfw;GLEW;GL")
set(IMGUI_LIBRARIES ImGui;glfw;GLEW;GL)

install(TARGETS ${PROJECT_NAME} 
    EXPORT ImGuiConfig
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

export(TARGETS ${PROJECT_NAME}
FILE "${CMAKE_CURRENT_BINARY_DIR}/ImGuiConfig.cmake")

install(EXPORT ImGuiConfig
    DESTINATION lib/cmake/ImGui
    EXPORT_LINK_INTERFACE_LIBRARIES
)

I just added to my CMakeLists.txt

set(IMGUI_LIBRARIES ImGui;glfw;GLEW;GL)
  • 1
    It's great that you answered your own question with the help of a comment! Could you please edit your answer so that it can be understood without having to read the comment first? In other words, explain what the problem was and why adding that line solved it. – Yun Aug 16 '21 at 08:18