Erik Tellier
Erik Tellier

Reputation: 230

How can i link GLFW and Dear ImGUI in CMAKE

the last few days i was messing with CMake, and everything worked fine, except that i can't find a way to link ImGUI with GLFW

Everything is build from source

Here is the error :

Consolidate compiler generated dependencies of target glad
[  2%] Built target glad
Consolidate compiler generated dependencies of target stb
[  5%] Built target stb
Consolidate compiler generated dependencies of target glfw
[ 29%] Built target glfw
Consolidate compiler generated dependencies of target imgui
[ 30%] Building CXX object CMakeFiles/imgui.dir/lib/imgui/imgui.cpp.o
[ 31%] Building CXX object CMakeFiles/imgui.dir/lib/imgui/imgui_demo.cpp.o
[ 33%] Building CXX object CMakeFiles/imgui.dir/lib/imgui/imgui_draw.cpp.o
[ 34%] Building CXX object CMakeFiles/imgui.dir/lib/imgui/imgui_tables.cpp.o
[ 36%] Building CXX object CMakeFiles/imgui.dir/lib/imgui/imgui_widgets.cpp.o
[ 37%] Building CXX object CMakeFiles/imgui.dir/lib/imgui/imgui_impl_glfw.cpp.o
/home/erik/Workspace/LearnOpenGL/lib/imgui/imgui_impl_glfw.cpp:45:10: fatal error: GLFW/glfw3.h: No such file or directory
   45 | #include <GLFW/glfw3.h>
      |          ^~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/imgui.dir/build.make:146: CMakeFiles/imgui.dir/lib/imgui/imgui_impl_glfw.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:228: CMakeFiles/imgui.dir/all] Error 2
make: *** [Makefile:156: all] Error 2

And here is my CMakeLists.txt :

cmake_minimum_required(VERSION 3.1)

project(LearnOpenGL)


set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/source")
set(LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib")

set(SOURCES "${SRC_DIR}/Main.cpp"
    )


add_executable(${PROJECT_NAME} ${SOURCES})

target_include_directories(${PROJECT_NAME} PRIVATE "${SRC_DIR}")

set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11)


# GLFW

set(GLFW_DIR "${LIB_DIR}/glfw")

set(GLFW_BUILD_EXAMPLES OFF CACHE INTERNAL "Build the GLFW example programs")
set(GLFW_BUILD_TESTS OFF CACHE INTERNAL "Build the GLFW test programs")
set(GLFW_BUILD_DOCS OFF CACHE INTERNAL "Build the GLFW documentation")
set(GLFW_INSTALL OFF CACHE INTERNAL "Generate installation target")

add_subdirectory("${GLFW_DIR}")

target_link_libraries(${PROJECT_NAME} "glfw" "${GLFW_LIBRARIES}")
target_include_directories(${PROJECT_NAME} PRIVATE "${GLFW_DIR}/include")
target_compile_definitions(${PROJECT_NAME} PRIVATE "GLFW_INCLUDE_NONE")


# Glad

set(GLAD_DIR "${LIB_DIR}/glad")

add_library("glad" "${GLAD_DIR}/src/glad.c")

target_include_directories("glad" PRIVATE "${GLAD_DIR}/include")
target_include_directories(${PROJECT_NAME} PRIVATE "${GLAD_DIR}/include")
target_link_libraries(${PROJECT_NAME} "glad" "${CMAKE_DL_LIBS}")


# GLM 

set(GLM_DIR "${LIB_DIR}/glm")

add_subdirectory(${GLM_DIR})

target_link_libraries(${PROJECT_NAME} "glm")


# STB

set(STB_DIR "${LIB_DIR}/stb")

add_library("stb" "${STB_DIR}/src/stb_image.cpp")

target_include_directories("stb" PRIVATE "${STB_DIR}/include")
target_include_directories(${PROJECT_NAME} PRIVATE "${STB_DIR}/include")
target_link_libraries(${PROJECT_NAME} "stb" "${CMAKE_DL_LIBS}")


# Freetype

set(FREETYPE_DIR "${LIB_DIR}/freetype")

add_subdirectory("${FREETYPE_DIR}")

target_link_libraries(${PROJECT_NAME} "${FREETYPE_LIBRARIES}")
target_include_directories(${PROJECT_NAME} PRIVATE "${FREETYPE_DIR}/include")


# ImGUI

set(IMGUI_DIR "${LIB_DIR}/imgui")

add_library("imgui" "${IMGUI_DIR}/imgui.cpp"
                  "${IMGUI_DIR}/imgui_demo.cpp"
                  "${IMGUI_DIR}/imgui_draw.cpp"
                  "${IMGUI_DIR}/imgui_tables.cpp"
                  "${IMGUI_DIR}/imgui_widgets.cpp"
                  
                  "${IMGUI_DIR}/imgui_impl_glfw.cpp"
                  "${IMGUI_DIR}/imgui_impl_opengl3.cpp")

target_include_directories("imgui" PRIVATE "${IMGUI_DIR}")
target_include_directories(${PROJECT_NAME} PRIVATE "${IMGUI_DIR}")
target_link_libraries(${PROJECT_NAME} "imgui" "${CMAKE_DL_LIBS}")

And here is my folder construction

 1. build
 2. lib
    -  freetype
    -  glad
    -  glfw
    -  glm
    -  imgui
    -  stb
 3. source
    -  Main.cpp
 4. CMakeLists.txt

Here is my question : How i can tell imgui that glfw is already here and he can use it?

Thanks in advance

Upvotes: 8

Views: 18944

Answers (1)

Alex Reinking
Alex Reinking

Reputation: 19956

Your build should consist of nothing but the following:

cmake_minimum_required(VERSION 3.20)
project(LearnOpenGL)

## Find dependencies
find_package(glfw3 REQUIRED)
find_package(glad REQUIRED)
find_package(glm REQUIRED)
find_package(freetype REQUIRED)
find_package(imgui REQUIRED)

# stb does not have a CMake build, but is header-only
find_path(STB_INCLUDE_DIRS "stb.h") 

## Create main executable
add_executable(main source/Main.cpp)
target_include_directories(main 
  PRIVATE 
    ${STB_INCLUDE_DIRS}
    "${CMAKE_CURRENT_LIST_DIR}/source"
)
target_link_libraries(
  main
  PRIVATE
    freetype
    glfw
    glad::glad
    glm::glm
    imgui::imgui
)

If you aren't using CMake 3.20, (a) you should be, but (b) you can try with an earlier version. But never put a version below the one you test with. CMake is only backwards compatible, not forwards compatible.

If you only need freetype as a dependency of imgui, then you can remove the references to it in the CMakeLists.txt.

To build this, you'll want to use vcpkg. To that end, create a file called vcpkg.json next to your CMakeLists.txt with the following contents:

{
  "name": "learn-opengl",
  "version": "0.1.0",
  "dependencies": [
    "glfw3",
    "glad",
    "glm",
    "freetype",
    "stb",
    {
      "name": "imgui",
      "features": ["freetype", "glfw-binding", "opengl3-glad-binding"]
    }
  ]
}

This is just telling vcpkg which dependencies you want, and that you want imgui built with freetype support and the glfw bindings.

Then you just need to run three commands.

$ git clone https://github.com/microsoft/vcpkg.git
$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_TOOLCHAIN_FILE=$PWD/vcpkg/scripts/buildsystems/vcpkg.cmake
$ cmake --build build

The only thing here that might be unexpected is setting CMAKE_TOOLCHAIN_FILE, this is just telling CMake to use vcpkg. The first time this runs, vcpkg will download your dependencies, build them, cache them in ~/.cache/vcpkg and install them into your build folder. Subsequent runs will build just your code.

This sequence successfully built your code for me on my Ubuntu 20.04 LTS machine.


To make this easier, consider creating a CMakePresets.json file, also in your root directory, with the following contents:

{
  "version": 2,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 20,
    "patch": 0
  },
  "configurePresets": [
    {
      "name": "default",
      "displayName": "Default Config",
      "description": "Default build using Make and vcpkg",
      "generator": "Unix Makefiles",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake"
      }
    },
    {
      "name": "default-msvc",
      "displayName": "Default MSVC",
      "description": "Default build using Visual Studio and vcpkg",
      "generator": "Visual Studio 16 2019",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": {
        "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake"
      }
    }
  ]
}

Then you can just run cmake --preset=default instead of the longer command above.

Upvotes: 5

Related Questions