Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CMake configuration #3027

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,6 @@ examples/example_glut_opengl2/example_glut_opengl2
examples/example_null/example_null
examples/example_sdl_opengl2/example_sdl_opengl2
examples/example_sdl_opengl3/example_sdl_opengl3

## Commonly used CMake directories
/build*/
98 changes: 98 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
cmake_minimum_required (VERSION 3.8.2)
project(imgui VERSION 1.73.0 LANGUAGES CXX C)

option (IMGUI_EXAMPLES "Build ImGui examples" ON)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and everywhere else the space before brace is not idiomatic. Ideally it would be good to follow the style used in CMake docs and not opinionated style.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space before brace is not idiomatic

There is no "idiom" when it comes to whitespace in CMake files - I personally prefer the space as it makes things easier to read in all of the projects I create, hence why they're here. The whitespace makes no difference, and since there isn't a CMake linter it's hard to enforce things either way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CMake scripts will be maintained for years to come by many people. I think it's easier to show people CMake docs as an example of how to write scripts than choose an arbitrary, subjective style and allow inconsistencies which will be introduced in future PRs (the spaces are missing already in some lines of the code in your PR, for example).

Qix- marked this conversation as resolved.
Show resolved Hide resolved
option (IMGUI_DEMO "Include the ImGui demo window implementation in library" ON)

option (IMGUI_IMPL_SDL "Build the SDL implementation (only if supported)" ON)
option (IMGUI_IMPL_METAL "Build the Metal implementation (only if supported)" ${APPLE})
option (IMGUI_IMPL_OSX "Build the OSX implementation (only if supported)" ${APPLE})
option (IMGUI_IMPL_WIN32 "Build the Win32 (native winapi) implementation (only if supported)" ${WIN32})
option (IMGUI_IMPL_GLFW "Build the GLFW implementation (only if supported)" ON)
option (IMGUI_IMPL_GLUT "Build the GLUT implementation (only if supported)" ON)
option (IMGUI_IMPL_OPENGL "Build the OpenGL implementation (only if supported)" ON)
option (IMGUI_IMPL_OPENGL2 "Build the OpenGL 2 (legacy) implementation (only if supported)" ${IMGUI_IMPL_OPENGL})
option (IMGUI_IMPL_DX9 "Build the DirectX 9 implementation (only if supported)" ${WIN32})
option (IMGUI_IMPL_DX10 "Build the DirectX 10 implementation (only if supported)" ${WIN32})
option (IMGUI_IMPL_DX11 "Build the DirectX 11 implementation (only if supported)" ${WIN32})
option (IMGUI_IMPL_DX12 "Build the DirectX 12 implementation (only if supported)" ${WIN32})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having a separate option for each implementation, could this just be replaced with a cached list variable of backends to be build? Having individual yes/no options is convenient when configuring cmake via a gui, but a nightmare when doing so on the command line. Keep in mind that if imgui is used via add_subdirectory those aren't the only options a developer has to deal with.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having a separate option for each implementation, could this just be replaced with a cached list variable of backends to be build?

That's pretty unusual for a cmake project. I'd be hestiant to manage config that way.

Having individual yes/no options is convenient when configuring cmake via a gui, but a nightmare when doing so on the command line.

I don't really agree; a few keystrokes difference doesn't really warrant changing the convention most properly written CMake configurations follow.

Keep in mind that if imgui is used via add_subdirectory those aren't the only options a developer has to deal with.

I don't follow; could you explain?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is an example of what I had in mind:

https://github.com/boostorg/cmake/blob/efbbc015ba9de6367880a6a1e0e1ce0dd52fe371/include/BoostRoot.cmake#L29

Imho

cmake .. -DBUILD_VERSIONS=Foo;Bar;Boo

is much more elegant than

cmake .. -DBUILD_FOO=ON -DBUILD_BAR=ON -DBUILD_BAZ=OFF -DBUILD_BOO=ON

But well, just a suggestion.


add_library (imgui
imgui.cpp
imgui_draw.cpp
imgui_widgets.cpp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this also needs imgui_tables.cpp now

$<$<BOOL:IMGUI_DEMO>:imgui_demo.cpp>
Qix- marked this conversation as resolved.
Show resolved Hide resolved
)

add_library(imgui::imgui ALIAS imgui)

target_include_directories (imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You better add variables for add_subdirectory and install usage.

target_include_directories(imgui PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>)

Furthermore, it is a good practice to store headers in include/lib_name folder. By including the whole source dir you pollute includes. Using a separate include/imgui folder for headers will make it clear for library users to understand which library the included header belongs to:
#include <imgui/imgui.h>
https://cliutils.gitlab.io/modern-cmake/chapters/basics/structure.html - a good reference for modern cmake

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm aware of how good projects are structured. As I've stated elsewhere in this PR, this was modeled to match the existing build system and layout.


target_compile_features(imgui PRIVATE cxx_std_98)
Qix- marked this conversation as resolved.
Show resolved Hide resolved

if (IMGUI_EXAMPLES)
# Sets up polyfill libraries for Windows examples (e.g. GLFW)
include (examples/libs/glfw.cmake)
endif ()

if (NOT IMGUI_DEMO)
target_compile_definitions (imgui PUBLIC -DIMGUI_DISABLE_DEMO_WINDOWS=1)
endif ()

if (IMGUI_IMPL_SDL)
include (examples/imgui_impl_sdl.cmake)
endif ()
if (IMGUI_IMPL_METAL)
include (examples/imgui_impl_metal.cmake)
endif ()
if (IMGUI_IMPL_OSX)
include (examples/imgui_impl_osx.cmake)
endif ()
if (IMGUI_IMPL_WIN32)
include (examples/imgui_impl_win32.cmake)
endif ()
if (IMGUI_IMPL_GLFW)
include (examples/imgui_impl_glfw.cmake)
endif ()
if (IMGUI_IMPL_OPENGL OR IMGUI_IMPL_OPENGL2)
include (examples/imgui_impl_opengl.cmake)
endif ()
if (IMGUI_IMPL_GLUT)
include (examples/imgui_impl_glut.cmake)
endif ()
if (IMGUI_IMPL_DX9)
include (examples/imgui_impl_dx9.cmake)
endif ()
if (IMGUI_IMPL_DX10)
include (examples/imgui_impl_dx10.cmake)
endif ()
if (IMGUI_IMPL_DX11)
include (examples/imgui_impl_dx11.cmake)
endif ()
if (IMGUI_IMPL_DX12)
include (examples/imgui_impl_dx12.cmake)
endif ()

if (IMGUI_EXAMPLES)
set (IMGUI_EXAMPLE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")

#add_subdirectory (examples/example_allegro5)
add_subdirectory (examples/example_apple_metal)
add_subdirectory (examples/example_apple_opengl2)
#add_subdirectory (examples/example_emscripten)
add_subdirectory (examples/example_glfw_metal)
add_subdirectory (examples/example_glfw_opengl2)
add_subdirectory (examples/example_glfw_opengl3)
#add_subdirectory (examples/example_glfw_vulkan)
add_subdirectory (examples/example_glut_opengl2)
add_subdirectory (examples/example_null)
#add_subdirectory (examples/example_sdl_directx11)
add_subdirectory (examples/example_sdl_metal)
add_subdirectory (examples/example_sdl_opengl2)
add_subdirectory (examples/example_sdl_opengl3)
#add_subdirectory (examples/example_sdl_vulkan)
add_subdirectory (examples/example_win32_directx10)
add_subdirectory (examples/example_win32_directx11)
add_subdirectory (examples/example_win32_directx12)
add_subdirectory (examples/example_win32_directx9)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of many add_subdirectory calls here, we can move them to "examples/CMakeLists.txt"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recall there being a reason I didn't do that initially, but otherwise I agree.

endif ()
18 changes: 18 additions & 0 deletions examples/example_apple_metal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
if (TARGET imgui-metal AND TARGET imgui-osx)
# TODO proper bundling of assets for macOS and iOS

add_executable (imgui_example_apple_metal
Shared/main.m
Shared/AppDelegate.m
Shared/Renderer.mm
Shared/ViewController.mm
)

target_link_libraries (imgui_example_apple_metal
imgui-metal imgui-osx
)

set_target_properties (imgui_example_apple_metal
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
11 changes: 11 additions & 0 deletions examples/example_apple_opengl2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (TARGET imgui-osx AND TARGET imgui-opengl2)
add_executable (imgui_example_apple_opengl2 main.mm)

target_link_libraries (imgui_example_apple_opengl2
imgui-osx imgui-opengl2
)

set_target_properties (imgui_example_apple_opengl2
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
11 changes: 11 additions & 0 deletions examples/example_glfw_metal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (TARGET imgui-glfw AND TARGET imgui-metal)
add_executable (imgui_example_glfw_metal main.mm)

target_link_libraries (imgui_example_glfw_metal
imgui-glfw imgui-metal
)

set_target_properties (imgui_example_glfw_metal
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
11 changes: 11 additions & 0 deletions examples/example_glfw_opengl2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (TARGET imgui-glfw AND TARGET imgui-opengl2)
add_executable (imgui_example_glfw_opengl2 main.cpp)

target_link_libraries (imgui_example_glfw_opengl2
imgui-glfw imgui-opengl2
)

set_target_properties (imgui_example_glfw_opengl2
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
11 changes: 11 additions & 0 deletions examples/example_glfw_opengl3/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (TARGET imgui-glfw AND TARGET imgui-opengl)
add_executable (imgui_example_glfw_opengl3 main.cpp)

target_link_libraries (imgui_example_glfw_opengl3
imgui-glfw imgui-opengl
)

set_target_properties (imgui_example_glfw_opengl3
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
11 changes: 11 additions & 0 deletions examples/example_glut_opengl2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (TARGET imgui-glut AND TARGET imgui-opengl2)
add_executable (imgui_example_glut_opengl2 main.cpp)

target_link_libraries (imgui_example_glut_opengl2
imgui-glut imgui-opengl2
)

set_target_properties (imgui_example_glut_opengl2
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
6 changes: 6 additions & 0 deletions examples/example_null/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
add_executable (imgui_example_null main.cpp)
target_link_libraries (imgui_example_null imgui)

set_target_properties (imgui_example_null
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
11 changes: 11 additions & 0 deletions examples/example_sdl_metal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (TARGET imgui-sdl AND TARGET imgui-metal)
add_executable (imgui_example_sdl_metal main.mm)

target_link_libraries (imgui_example_sdl_metal
imgui-sdl imgui-metal
)

set_target_properties (imgui_example_sdl_metal
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
11 changes: 11 additions & 0 deletions examples/example_sdl_opengl2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (TARGET imgui-sdl AND TARGET imgui-opengl2)
add_executable (imgui_example_sdl_opengl2 WIN32 main.cpp)

target_link_libraries (imgui_example_sdl_opengl2
imgui-sdl imgui-opengl2
)

set_target_properties (imgui_example_sdl_opengl2
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
11 changes: 11 additions & 0 deletions examples/example_sdl_opengl3/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (TARGET imgui-sdl AND TARGET imgui-opengl)
add_executable (imgui_example_sdl_opengl3 main.cpp)

target_link_libraries (imgui_example_sdl_opengl3
imgui-sdl imgui-opengl
)

set_target_properties (imgui_example_sdl_opengl3
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
11 changes: 11 additions & 0 deletions examples/example_win32_directx10/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (TARGET imgui-win32 AND TARGET imgui-dx10)
add_executable (imgui_example_win32_directx10 main.cpp)

target_link_libraries (imgui_example_win32_directx10
imgui-win32 imgui-dx10
)

set_target_properties (imgui_example_win32_directx10
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
11 changes: 11 additions & 0 deletions examples/example_win32_directx11/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (TARGET imgui-win32 AND TARGET imgui-dx11)
add_executable (imgui_example_win32_directx11 main.cpp)

target_link_libraries (imgui_example_win32_directx11
imgui-win32 imgui-dx11
)

set_target_properties (imgui_example_win32_directx11
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
11 changes: 11 additions & 0 deletions examples/example_win32_directx12/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (TARGET imgui-win32 AND TARGET imgui-dx12)
add_executable (imgui_example_win32_directx12 main.cpp)

target_link_libraries (imgui_example_win32_directx12
imgui-win32 imgui-dx12
)

set_target_properties (imgui_example_win32_directx12
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
11 changes: 11 additions & 0 deletions examples/example_win32_directx9/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (TARGET imgui-win32 AND TARGET imgui-dx9)
add_executable (imgui_example_win32_directx9 main.cpp)

target_link_libraries (imgui_example_win32_directx9
imgui-win32 imgui-dx9
)

set_target_properties (imgui_example_win32_directx9
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${IMGUI_EXAMPLE_OUTPUT_DIR}"
)
endif ()
26 changes: 26 additions & 0 deletions examples/imgui_impl_dx10.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
if (WIN32)
find_library (D3D10_LIBRARY "d3d10")
if (NOT D3D10_LIBRARY)
message (WARNING "IMGUI_IMPL_DX10 set to ON but d3d10.dll not found")
endif ()

find_library (DXGI_LIBRARY "dxgi")
if (NOT DXGI_LIBRARY)
message (WARNING "IMGUI_IMPL_DX10 set to ON but dxgi.dll not found")
endif ()

if (D3D10_LIBRARY AND DXGI_LIBRARY)
add_library (imgui-dx10 OBJECT
"${CMAKE_CURRENT_LIST_DIR}/imgui_impl_dx10.cpp"
)

target_link_libraries (imgui-dx10 PUBLIC
imgui
${D3D10_LIBRARY} ${DXGI_LIBRARY}
)

target_include_directories (imgui-dx10 PUBLIC "${CMAKE_CURRENT_LIST_DIR}")
endif ()
else ()
message (WARNING "IMGUI_IMPL_DX10 set to ON but platform is not Win32")
endif ()
26 changes: 26 additions & 0 deletions examples/imgui_impl_dx11.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
if (WIN32)
find_library (D3D11_LIBRARY "d3d11")
if (NOT D3D11_LIBRARY)
message (WARNING "IMGUI_IMPL_DX11 set to ON but d3d11.dll not found")
endif ()

find_library (DXGI_LIBRARY "dxgi")
if (NOT DXGI_LIBRARY)
message (WARNING "IMGUI_IMPL_DX11 set to ON but dxgi.dll not found")
endif ()

if (D3D11_LIBRARY AND DXGI_LIBRARY)
add_library (imgui-dx11 OBJECT
"${CMAKE_CURRENT_LIST_DIR}/imgui_impl_dx11.cpp"
)

target_link_libraries (imgui-dx11 PUBLIC
imgui
${D3D11_LIBRARY} ${DXGI_LIBRARY}
)

target_include_directories (imgui-dx11 PUBLIC "${CMAKE_CURRENT_LIST_DIR}")
endif ()
else ()
message (WARNING "IMGUI_IMPL_DX11 set to ON but platform is not Win32")
endif ()
26 changes: 26 additions & 0 deletions examples/imgui_impl_dx12.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
if (WIN32)
find_library (D3D12_LIBRARY "d3d12")
if (NOT D3D12_LIBRARY)
message (WARNING "IMGUI_IMPL_DX12 set to ON but d3d12.dll not found")
endif ()

find_library (DXGI_LIBRARY "dxgi")
if (NOT DXGI_LIBRARY)
message (WARNING "IMGUI_IMPL_DX12 set to ON but dxgi.dll not found")
endif ()

if (D3D12_LIBRARY AND DXGI_LIBRARY)
add_library (imgui-dx12 OBJECT
"${CMAKE_CURRENT_LIST_DIR}/imgui_impl_dx12.cpp"
)

target_link_libraries (imgui-dx12 PUBLIC
imgui
${D3D12_LIBRARY} ${DXGI_LIBRARY}
)

target_include_directories (imgui-dx12 PUBLIC "${CMAKE_CURRENT_LIST_DIR}")
endif ()
else ()
message (WARNING "IMGUI_IMPL_DX12 set to ON but platform is not Win32")
endif ()
19 changes: 19 additions & 0 deletions examples/imgui_impl_dx9.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
if (WIN32)
find_library (D3D9_LIBRARY "d3d9")
if (D3D9_LIBRARY)
add_library (imgui-dx9 OBJECT
"${CMAKE_CURRENT_LIST_DIR}/imgui_impl_dx9.cpp"
)

target_link_libraries (imgui-dx9 PUBLIC
imgui
${D3D9_LIBRARY}
)

target_include_directories (imgui-dx9 PUBLIC "${CMAKE_CURRENT_LIST_DIR}")
else ()
message (WARNING "IMGUI_IMPL_DX9 set to ON but d3d9.dll not found")
endif ()
else ()
message (WARNING "IMGUI_IMPL_DX9 set to ON but platform is not Win32")
endif ()
14 changes: 14 additions & 0 deletions examples/imgui_impl_glfw.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
if (NOT TARGET glfw)
find_package (GLFW3 QUIET)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is QUIET specified here? It would be good to fail here loudly instead of failing quietly and user scratching their head because the example is not built for some reason.

Same applies to all find_package calls in this implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look a bit further down. We craft our own error message based on whether or not glfw was brought in as a CMake submodule or not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Then I have some further questions.

  1. Maybe the message shouldn't be a warning, but an error instead? The target fails to build because the dependency is not found, it's an error in my opinion
  2. Maybe glfw_FOUND variable (set by find_package) should be used instead of the current check for target's existence and GLFW3_DIR?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand this PR is closed now anyway, but maybe one of you still has an optinion on this that [s]he cares to elaborate, because I use similar mechanisms in other projects:

Shouldn't the order be the opposite? First check, if the target is already available (e.g. through add_subdirectory) and only if not, fall back to find_package. Assuming a library has the ability to use a local version of a dependency at all, I'd be extremely suprised, if if that local version got replaced, just because for some completely unrelated reason someone installed the dependency system wiede via a package manager.

endif ()

if (TARGET glfw OR GLFW3_DIR)
add_library (imgui-glfw OBJECT
"${CMAKE_CURRENT_LIST_DIR}/imgui_impl_glfw.cpp"
)

target_link_libraries (imgui-glfw PUBLIC imgui glfw)
target_include_directories (imgui-glfw PUBLIC "${CMAKE_CURRENT_LIST_DIR}")
else ()
message (WARNING "IMGUI_IMPL_GLFW set to ON but glfw3 could not be located")
endif ()
Loading