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
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.