From cb2250bb2690cb04995bd0dc8e574cdd228c2975 Mon Sep 17 00:00:00 2001 From: Mich-Dich Date: Wed, 1 Oct 2025 22:42:06 +0200 Subject: [PATCH 1/4] switch from premake5 to CMake (unfinished) --- .gitignore | 2 + CMakeLists.txt | 63 ++++++ premake5.lua | 413 ----------------------------------- scripts/imgui_CMakeLists.txt | 45 ++++ setup.py | 19 +- src/CMakeLists.txt | 114 ++++++++++ vendor/Catch2 | 2 +- vendor/glm | 2 +- 8 files changed, 232 insertions(+), 428 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 premake5.lua create mode 100644 scripts/imgui_CMakeLists.txt create mode 100644 src/CMakeLists.txt diff --git a/.gitignore b/.gitignore index 30a0511..f646fbe 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,5 @@ Makefile vendor/premake/ vendor/premake/* vendor/premake/LICENSE.txt + +build/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a284afa --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,63 @@ +# Root [CMakeLists.txt] + +cmake_minimum_required(VERSION 3.15) +project(application LANGUAGES CXX) + +# Set C++ standard and compiler flags +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Set output directories for binaries (similar to your targetdir and objdir) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin-int) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin-int) + +# Define configurations (Debug, RelWithDebInfo, Release) +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build" FORCE) +endif() +set(CMAKE_CONFIGURATION_TYPES "Debug;RelWithDebInfo;Release") + +# Platform-specific definitions +if(WIN32) + add_compile_definitions( + PLATFORM_WINDOWS + WIN32_LEAN_AND_MEAN + UNICODE + _UNICODE + ) +elseif(UNIX) + add_compile_definitions( + PLATFORM_LINUX + ) +endif() + +# Define common definitions and flags +add_compile_definitions( + _CRT_SECURE_NO_WARNINGS + NOMINMAX +) + +# Multi-processor compilation +add_compile_options($<$:/MP>) + +# For MinGW, add specific compiler options - FIXED: Only apply C flags to C files +if(CMAKE_C_COMPILER_ID MATCHES "GNU") + add_compile_options( + -Wall + $<$:-Wno-declaration-after-statement> + ) +endif() + +# Build GLFW first so it's available for ImGui +set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "Don't build the GLFW examples") +set(GLFW_BUILD_TESTS OFF CACHE BOOL "Don't build the GLFW tests") +set(GLFW_BUILD_DOCS OFF CACHE BOOL "Don't build the GLFW docs") +set(GLFW_INSTALL OFF CACHE BOOL "Don't create an GLFW install target") +add_subdirectory(vendor/glfw) + +# Then build ImGui (which depends on GLFW) +add_subdirectory(vendor/imgui) + +# Create your main application project +add_subdirectory(src) \ No newline at end of file diff --git a/premake5.lua b/premake5.lua deleted file mode 100644 index 75304b6..0000000 --- a/premake5.lua +++ /dev/null @@ -1,413 +0,0 @@ - ------------------- dependencies ------------------ - ------------- path ------------ -vendor_path = {} -vendor_path["glew"] = "%{wks.location}/vendor/glew" -vendor_path["glfw"] = "%{wks.location}/vendor/glfw" -vendor_path["glm"] = "%{wks.location}/vendor/glm" -vendor_path["ImGui"] = "%{wks.location}/vendor/imgui" -vendor_path["implot"] = "%{wks.location}/vendor/implot" -vendor_path["stb_image"] = "%{wks.location}/vendor/stb_image" -vendor_path["catch2"] = "%{wks.location}/vendor/Catch2" - ------------- include ------------ -IncludeDir = {} -IncludeDir["glew"] = "%{vendor_path.glew}/include" -IncludeDir["glfw"] = "%{vendor_path.glfw}" -IncludeDir["glm"] = "%{vendor_path.glm}" -IncludeDir["ImGui"] = "%{vendor_path.ImGui}" -IncludeDir["implot"] = "%{vendor_path.implot}" -IncludeDir["stb_image"] = "%{vendor_path.stb_image}" -IncludeDir["catch2"] = "%{vendor_path.catch2}/src" - -workspace "application" - platforms "x64" - startproject "application_template" - - configurations - { - "Debug", - "RelWithDebInfo", - "Release", - } - - flags - { - "MultiProcessorCompile" - } - - outputs = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}" - local project_path = os.getcwd() - defines - { - "ENGINE_INSTALL_DIR=\"" .. project_path .. "/bin/" .. outputs .. "\"", - "OUTPUTS=\"" .. outputs .. "\"", - } - - ---------- DISABLED FOR DEV ---------- - if os.target() == "linux" then - print("---------- target platform is linux => manually compile GLFW ----------") - os.execute("cmake -S ./vendor/glfw -B ./vendor/glfw/build") -- manuel compilation - os.execute("cmake --build ./vendor/glfw/build") -- manuel compilation - print("---------- Done compiling GLFW ----------") - end - -group "dependencies" - include "vendor/imgui" - if os.target() == "windows" then - include "vendor/glfw" - end -group "" - - -group "core" - project "application_template" -- generated by the setup.py script, modefiy "app_settings.yml" to change name - - location "%{wks.location}" - kind "WindowedApp" - language "C++" - cppdialect "C++20" - staticruntime "on" - - targetdir ("%{wks.location}/bin/" .. outputs .. "/%{prj.name}") - objdir ("%{wks.location}/bin-int/" .. outputs .. "/%{prj.name}") - - pchheader "util/pch.h" - pchsource "src/util/pch.cpp" - - defines - { - "_CRT_SECURE_NO_WARNINGS", - "GLFW_INCLUDE_NONE", - "NOMINMAX", - } - - files - { - "src/**.h", - "src/**.cpp", - "src/**.embed", - - "vendor/implot/*.h", -- directly bake implot into application - "vendor/implot/*.cpp", - "vendor/imgui/backends/imgui_impl_opengl3.h", - "vendor/imgui/backends/imgui_impl_opengl3.cpp", - } - - includedirs - { - "src", - "assets", - "vendor", - - "%{IncludeDir.glew}", - "%{IncludeDir.glm}", - "%{IncludeDir.glfw}/include", - "%{IncludeDir.ImGui}", - "%{IncludeDir.ImGui}/backends/", - "%{IncludeDir.implot}", - "%{IncludeDir.stb_image}", - } - - links - { - "ImGui", - } - - libdirs - { - "vendor/imgui/bin/" .. outputs .. "/imgui", - } - - filter "files:vendor/implot/**.cpp" - flags { "NoPCH" } - - filter "files:vendor/imgui/**.cpp" - flags { "NoPCH" } - - filter "system:linux" - systemversion "latest" - defines "PLATFORM_LINUX" - - includedirs - { - "/usr/include", - } - - externalincludedirs -- treat VMA as system headers (prevent warnings) - { - "/usr/include/x86_64-linux-gnu/qt5", -- Base Qt include path - "/usr/include/x86_64-linux-gnu/qt5/QtCore", - "/usr/include/x86_64-linux-gnu/qt5/QtWidgets", - "/usr/include/x86_64-linux-gnu/qt5/QtGui", - } - - libdirs - { - "%{wks.location}/vendor/glfw/build/src", - "/usr/lib/x86_64-linux-gnu", - "/usr/lib/x86_64-linux-gnu/qt5", - } - - links - { - "GLEW", - "GL", - "glfw3", - "Qt5Core", - "Qt5Widgets", - "Qt5Gui", - } - - buildoptions - { - "-msse4.1", -- include the SSE4.1 flag for Linux builds - "-fPIC", - "-Wall", -- compiler options - "-Wno-dangling-else", - } - - postbuildcommands - { - '{COPYDIR} -n "%{wks.location}/assets" "%{wks.location}/bin/' .. outputs .. '/%{prj.name}"', - '{COPYDIR} -n "%{wks.location}/config" "%{wks.location}/bin/' .. outputs .. '/%{prj.name}"', - } - - filter "system:windows" - systemversion "latest" - defines - { - "PLATFORM_WINDOWS", - "WIN32_LEAN_AND_MEAN", - "GLEW_STATIC", - "UNICODE", - "_UNICODE", - } - - links - { - "ImGui", - "glfw", - "glew32s", - "opengl32", - "gdi32", - "user32", - "comdlg32", - "shell32", - } - - libdirs - { - "%{wks.location}\\vendor\\glfw\\bin\\" .. outputs .. "\\glfw", - "%{wks.location}\\vendor\\imgui\\bin\\" .. outputs .. "\\imgui", - "%{vendor_path.glew}\\lib\\Release\\x64", - } - - postbuildcommands - { - '{COPYDIR} "%{wks.location}\\assets" "%{wks.location}\\bin\\' .. outputs .. '\\%{prj.name}\\assets"', - '{COPYDIR} "%{wks.location}\\config" "%{wks.location}\\bin\\' .. outputs .. '\\%{prj.name}\\config"', - } - - - filter { "system:windows", "action:gmake2" } -- MinGW specific settings - links - { - "ImGui", - "glfw3", - "glew32", - "opengl32", - "gdi32", - "user32", - "comdlg32", - "shell32", - } - - libdirs - { - "%{wks.location}\\vendor\\glfw\\build-mingw\\src", - "%{wks.location}\\vendor\\glfw\\bin\\' .. outputs .. '\\glfw", - "%{vendor_path.glew}\\lib\\Release\\Win32", - } - - - filter "configurations:Debug" - defines "DEBUG" - runtime "Debug" - symbols "on" - - filter "configurations:RelWithDebInfo" - defines "RELEASE_WITH_DEBUG_INFO" - runtime "Release" - symbols "on" - optimize "on" - - filter "configurations:Release" - defines "RELEASE" - runtime "Release" - symbols "off" - optimize "on" - -group "" - - -group "tests" - project "tests" - kind "ConsoleApp" - language "C++" - cppdialect "C++20" - staticruntime "on" - - targetdir ("%{wks.location}/bin/" .. outputs .. "/%{prj.name}") - objdir ("%{wks.location}/bin-int/" .. outputs .. "/%{prj.name}") - - files - { - "testing/**.h", - "testing/**.cpp", - - "src/util/timing/**.h", - "src/util/timing/**.cpp", - - "src/util/data_structures/data_types.h", - "src/util/data_structures/deletion_queue.h", - "src/util/data_structures/deletion_queue.cpp", - "src/util/data_structures/type_deletion_queue.h", - "src/util/data_structures/type_deletion_queue.cpp", - - "src/util/math/random.cpp", - "src/util/math/math.cpp", - "src/util/io/io.cpp", - "src/util/io/config.cpp", - "src/util/io/logger.cpp", - "src/util/io/serializer_data.h", - "src/util/io/serializer_yaml.h", - "src/util/io/serializer_yaml.cpp", - "src/util/io/serializer_binary.h", - "src/util/io/serializer_binary.cpp", - - - "src/util/data_structures/string_manipulation.cpp", - "src/util/system.cpp", - } - - includedirs - { - "src", - "testing", - "%{IncludeDir.catch2}", - "%{IncludeDir.glm}", - "%{vendor_path.catch2}/Build/generated-includes", - - "%{IncludeDir.glew}", - "%{IncludeDir.glm}", - "%{IncludeDir.glfw}/include", - "%{IncludeDir.ImGui}", - "%{IncludeDir.ImGui}/backends/", - "%{IncludeDir.implot}", - "%{IncludeDir.stb_image}", - } - - links - { - "ImGui", - } - - libdirs - { - "%{vendor_path.catch2}/Build/src", - "vendor/imgui/bin/" .. outputs .. "/imgui", - } - - prebuildcommands - { - "cmake -S ./vendor/Catch2 -B ./vendor/Catch2/Build -DCMAKE_BUILD_TYPE=%{cfg.buildcfg} -DCATCH_INSTALL_DOCS=OFF -DCATCH_INSTALL_EXTRAS=OFF", - "cmake --build ./vendor/Catch2/Build --config %{cfg.buildcfg}" - } - - filter "configurations:Debug" - links { "Catch2Maind", "Catch2d" } - - filter "configurations:RelWithDebInfo" - links { "Catch2Main", "Catch2" } - - filter "configurations:Release" - links { "Catch2Main", "Catch2" } - - filter "files:vendor/implot/**.cpp" - flags { "NoPCH" } - - filter "files:vendor/imgui/**.cpp" - flags { "NoPCH" } - - filter "system:linux" - systemversion "latest" - defines "PLATFORM_LINUX" - links { - "pthread", -- Catch2 requires pthread on Linux - "Qt5Core", -- Add Qt libraries if needed - "Qt5Widgets", - "Qt5Gui", - } - - buildoptions - { - "-msse4.1", - "-fPIC", - "-Wall", - "-Wno-dangling-else" - } - - externalincludedirs -- treat VMA as system headers (prevent warnings) - { - "/usr/include/x86_64-linux-gnu/qt5", -- Base Qt include path - "/usr/include/x86_64-linux-gnu/qt5/QtCore", - "/usr/include/x86_64-linux-gnu/qt5/QtWidgets", - "/usr/include/x86_64-linux-gnu/qt5/QtGui", - } - - filter "system:windows" - systemversion "latest" - defines - { - "PLATFORM_WINDOWS", - "UNICODE", - "_UNICODE", - } - - links - { - "ImGui", - "glfw", - "glew32s", - "opengl32", - "gdi32", - "user32", - "comdlg32", -- For GetOpenFileNameW - "shell32", -- For other Windows APIs - } - - libdirs - { - "%{wks.location}/vendor/glfw/lib-vc2022", - "%{vendor_path.glew}/lib/Release/x64", - } - - filter "configurations:Debug" - defines "DEBUG" - runtime "Debug" - symbols "on" - - filter "configurations:RelWithDebInfo" - defines "RELEASE_WITH_DEBUG_INFO" - runtime "Release" - symbols "on" - optimize "on" - - filter "configurations:Release" - defines "RELEASE" - runtime "Release" - symbols "off" - optimize "on" -group "" diff --git a/scripts/imgui_CMakeLists.txt b/scripts/imgui_CMakeLists.txt new file mode 100644 index 0000000..e7637fc --- /dev/null +++ b/scripts/imgui_CMakeLists.txt @@ -0,0 +1,45 @@ +# ImGui [vendor/imgui/CMakeLists.txt] + +project(imgui LANGUAGES CXX) + +# Set C++ standard +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# List source files +set(IMGUI_SOURCES + imconfig.h + imgui.h + imgui.cpp + imgui_draw.cpp + imgui_internal.h + imgui_tables.cpp + imgui_widgets.cpp + imstb_rectpack.h + imstb_textedit.h + imstb_truetype.h + imgui_demo.cpp + backends/imgui_impl_glfw.h + backends/imgui_impl_glfw.cpp +) + +# Create static library +add_library(imgui STATIC ${IMGUI_SOURCES}) + +# Include directories +target_include_directories(imgui PUBLIC + . + backends + ${CMAKE_SOURCE_DIR}/vendor/glfw/include +) + +# Add GLFW_INCLUDE_NONE for ImGui if it uses GLFW +target_compile_definitions(imgui PRIVATE GLFW_INCLUDE_NONE) + +# Platform-specific settings +if(WIN32) + # Windows-specific settings +elseif(UNIX) + # Linux-specific settings + set_target_properties(imgui PROPERTIES POSITION_INDEPENDENT_CODE ON) +endif() \ No newline at end of file diff --git a/setup.py b/setup.py index e27f3f0..9b1f18b 100644 --- a/setup.py +++ b/setup.py @@ -35,13 +35,11 @@ if platform.system() == "Linux": from scripts.linux.setup_env import env_configuration - from scripts.linux.setup_premake import premake_configuration import scripts.linux.IDE_setup as IDE_setup elif platform.system() == "Windows": from scripts.windows.setup_env import env_configuration import scripts.windows.win_utils as win_util win_util.enable_ansi_support() - from scripts.windows.setup_premake import premake_configuration import scripts.windows.IDE_setup as IDE_setup else: raise Exception("Unsupported operating system") @@ -117,11 +115,6 @@ def main(): if not env_configuration.validate(): utils.print_c("Missing required packages - setup aborted", "red") sys.exit(1) - - utils.print_u("\nCHECK PREMAKE-5 SETUP") - if not premake_configuration.validate(): - utils.print_c("Premake5 download failed - setup aborted", "red") - sys.exit(1) utils.print_u("\nINITIALIZING SUBMODULES") # Initialize submodule configuration if not git_util.initialize_submodules(): @@ -129,16 +122,16 @@ def main(): sys.exit(1) utils.print_u("\nUPDATING SUBMODULES") # Update submodules to desired branches - # git_util.update_submodule("vendor/glfw", "main") - # git_util.update_submodule("vendor/glm", "master") - # git_util.update_submodule("vendor/imgui", "docking") - # git_util.update_submodule("vendor/implot", "master") - # git_util.update_submodule("vendor/Catch2", "devel") + git_util.update_submodule("vendor/glfw", "main") + git_util.update_submodule("vendor/glm", "master") + git_util.update_submodule("vendor/imgui", "docking") + git_util.update_submodule("vendor/implot", "master") + git_util.update_submodule("vendor/Catch2", "devel") utils.print_u("\nAPPLY SETTINGS") utils.print_c("Settings are defined at [./config/app_settings.yml]. after changing the settings, it is recommended to reexecute the setup script", "blue") - apply_premake_settings() + # apply_premake_settings() application_name = get_application_name() clean_art_on_build = get_clean_build_artifacts_on_build() print(f"name: {application_name}") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..536880e --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,114 @@ +# Application [src/CMakeLists.txt] + +project(application_template LANGUAGES CXX) + +# Find required packages +find_package(OpenGL REQUIRED) + +# List your source files +file(GLOB_RECURSE SOURCES_CONAN "*.cpp" "*.h") +file(GLOB IMPLOT_SOURCES "../vendor/implot/*.h" "../vendor/implot/*.cpp") + +# Add ImGui OpenGL3 backend files - THESE WERE MISSING +file(GLOB IMGUI_OPENGL3_SOURCES + "../vendor/imgui/backends/imgui_impl_opengl3.h" + "../vendor/imgui/backends/imgui_impl_opengl3.cpp" +) + +# Add executable with ALL required sources +add_executable(application_template + ${SOURCES_CONAN} + ${IMPLOT_SOURCES} + ${IMGUI_OPENGL3_SOURCES} +) + +# Precompiled headers (requires CMake 3.16+) +target_precompile_headers(application_template PRIVATE util/pch.h) + +# Include directories +target_include_directories(application_template PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/assets + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/glew/include + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/glm + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/glfw/include + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/imgui + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/imgui/backends + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/implot + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/stb_image +) + +# Add definitions for application target +target_compile_definitions(application_template PRIVATE + GLFW_INCLUDE_NONE + GLEW_STATIC +) + +# Configuration-specific definitions +target_compile_definitions(application_template PRIVATE + $<$:DEBUG> + $<$:RELEASE_WITH_DEBUG_INFO> + $<$:RELEASE> +) + +# Link libraries +target_link_libraries(application_template PRIVATE + imgui + glfw + OpenGL::GL +) + +# Platform-specific linking +if(WIN32) + # Try different GLEW library paths for MinGW + find_library(GLEW_LIBRARY + NAMES glew32s glew32 + PATHS + ${CMAKE_SOURCE_DIR}/vendor/glew/lib/Release/x64 + ${CMAKE_SOURCE_DIR}/vendor/glew/lib + ${CMAKE_SOURCE_DIR}/vendor/glew/lib/Release/Win32 + NO_DEFAULT_PATH + ) + + if(GLEW_LIBRARY) + target_link_libraries(application_template PRIVATE ${GLEW_LIBRARY}) + else() + # Fallback: try to find GLEW system-wide or use a different approach + find_package(GLEW) + if(GLEW_FOUND) + target_link_libraries(application_template PRIVATE GLEW::GLEW) + else() + message(WARNING "GLEW library not found. Please check the path.") + endif() + endif() + + target_link_libraries(application_template PRIVATE + gdi32 + user32 + comdlg32 + shell32 + opengl32 + ) + + # Copy assets post-build + add_custom_command(TARGET application_template POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_SOURCE_DIR}/assets + $/assets + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_SOURCE_DIR}/config + $/config + ) +endif() + +# Disable PCH for specific files (similar to your Premake flags) +set_source_files_properties( + ../vendor/implot/implot.cpp + ../vendor/implot/implot_items.cpp + ../vendor/implot/implot_demo.cpp + ../vendor/imgui/backends/imgui_impl_glfw.cpp + ../vendor/imgui/backends/imgui_impl_opengl3.cpp # ADD THIS + PROPERTIES + SKIP_PRECOMPILE_HEADERS ON +) \ No newline at end of file diff --git a/vendor/Catch2 b/vendor/Catch2 index cd93d20..b3fb4b9 160000 --- a/vendor/Catch2 +++ b/vendor/Catch2 @@ -1 +1 @@ -Subproject commit cd93d202e047f91370b922f09db2e658653088de +Subproject commit b3fb4b9feafcd8d91c5cb510a4775143fdbef02f diff --git a/vendor/glm b/vendor/glm index 2d4c4b4..e771488 160000 --- a/vendor/glm +++ b/vendor/glm @@ -1 +1 @@ -Subproject commit 2d4c4b4dd31fde06cfffad7915c2b3006402322f +Subproject commit e7714885929f1dcd2bdc2531cc99d3c1dc6daa18 From 6a8e68170ee695e5ba9025d1de476e317e87448f Mon Sep 17 00:00:00 2001 From: Mich-Dich Date: Thu, 2 Oct 2025 07:17:14 +0200 Subject: [PATCH 2/4] update readme --- .gitignore | 2 +- README.md | 20 ++++++-------------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index f646fbe..c4d83f2 100644 --- a/.gitignore +++ b/.gitignore @@ -60,4 +60,4 @@ vendor/premake/ vendor/premake/* vendor/premake/LICENSE.txt -build/ \ No newline at end of file +build/ diff --git a/README.md b/README.md index ecdb2ee..b9ccb44 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ A simple, cross-platform C++ application template with a graphical user interfac * **ImGui** for immediate-mode GUI widgets * **GLFW** for window and input management * **OpenGL** (configurable via `GL_renderer`) -* **Premake5** for build configuration The template handles platform detection, dependency setup, and IDE integration out of the box. @@ -64,26 +63,18 @@ If you selected **VSCode** during setup: From the project root directory: ```bash -cd application_template -.vscode/build.sh # Generate gmake2 files and run premake -make -j # Compile with parallel jobs +cmake -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug # Generate build files +cmake --build build --parallel 16 # Compile with parallel jobs ``` -If you modify `premake5.lua`, regenerate build files: - -```bash -make clean && vendor/premake/premake5 gmake2 -make -j -``` - -**Optional Bash Aliases** (add to your `~/.bashrc`): + ## 6. Window Manager Integration @@ -97,7 +88,8 @@ This matches ImGui popup windows by their title prefix. ## 7. Usage -Run the compiled binary directly or via IDE. The main window displays ImGui controls—customize widgets in `application.cpp`. +'F5' Runs the compiled binary directly or via IDE. +The main window displays ImGui controls—customize widgets in `application.cpp`. ## Dashboard Module From 6fb0b63e5fd861f3d87d695517497318e37ae40c Mon Sep 17 00:00:00 2001 From: Mich Date: Sat, 4 Oct 2025 16:56:19 +0200 Subject: [PATCH 3/4] make build system part of the setup process (allows for multiple build systems) --- .gitignore | 15 +- CMakeLists.txt | 63 -- README.md | 15 +- scripts/create_build_system.py | 1015 ++++++++++++++++++++++++++++++++ scripts/imgui_CMakeLists.txt | 45 -- scripts/linux/IDE_setup.py | 20 +- scripts/utils.py | 21 +- scripts/windows/IDE_setup.py | 32 +- setup.py | 353 +++++++---- src/CMakeLists.txt | 114 ---- 10 files changed, 1327 insertions(+), 366 deletions(-) delete mode 100644 CMakeLists.txt create mode 100644 scripts/create_build_system.py delete mode 100644 scripts/imgui_CMakeLists.txt delete mode 100644 src/CMakeLists.txt diff --git a/.gitignore b/.gitignore index c4d83f2..9b3a25d 100644 --- a/.gitignore +++ b/.gitignore @@ -40,12 +40,20 @@ # debug information files *.dwo - # generated files .vscode/ .vs/ + +build/ bin/ bin-int/ + +**/premake5.lua +premake5.lua + +**/CMakeLists.txt +CMakeLists.txt + scripts/__pycache__/ scripts/linux/__pycache__/ scripts/windows/__pycache__/ @@ -54,10 +62,9 @@ scripts/windows/__pycache__/ *.vcxproj *.vcxproj.filters *.vcxproj.user -vendor/glew/ Makefile + +vendor/glew/ vendor/premake/ vendor/premake/* vendor/premake/LICENSE.txt - -build/ diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index a284afa..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,63 +0,0 @@ -# Root [CMakeLists.txt] - -cmake_minimum_required(VERSION 3.15) -project(application LANGUAGES CXX) - -# Set C++ standard and compiler flags -set(CMAKE_CXX_STANDARD 23) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# Set output directories for binaries (similar to your targetdir and objdir) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin-int) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin-int) - -# Define configurations (Debug, RelWithDebInfo, Release) -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build" FORCE) -endif() -set(CMAKE_CONFIGURATION_TYPES "Debug;RelWithDebInfo;Release") - -# Platform-specific definitions -if(WIN32) - add_compile_definitions( - PLATFORM_WINDOWS - WIN32_LEAN_AND_MEAN - UNICODE - _UNICODE - ) -elseif(UNIX) - add_compile_definitions( - PLATFORM_LINUX - ) -endif() - -# Define common definitions and flags -add_compile_definitions( - _CRT_SECURE_NO_WARNINGS - NOMINMAX -) - -# Multi-processor compilation -add_compile_options($<$:/MP>) - -# For MinGW, add specific compiler options - FIXED: Only apply C flags to C files -if(CMAKE_C_COMPILER_ID MATCHES "GNU") - add_compile_options( - -Wall - $<$:-Wno-declaration-after-statement> - ) -endif() - -# Build GLFW first so it's available for ImGui -set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "Don't build the GLFW examples") -set(GLFW_BUILD_TESTS OFF CACHE BOOL "Don't build the GLFW tests") -set(GLFW_BUILD_DOCS OFF CACHE BOOL "Don't build the GLFW docs") -set(GLFW_INSTALL OFF CACHE BOOL "Don't create an GLFW install target") -add_subdirectory(vendor/glfw) - -# Then build ImGui (which depends on GLFW) -add_subdirectory(vendor/imgui) - -# Create your main application project -add_subdirectory(src) \ No newline at end of file diff --git a/README.md b/README.md index b9ccb44..9db50ac 100644 --- a/README.md +++ b/README.md @@ -56,26 +56,25 @@ If you selected **VSCode** during setup: ###### While in the VSCode editor: * Press Ctrl + Shift + B to build the application. -* Press F5 to launch the application in the debugger after building. +* Press F5 to build and launch the application in the debugger. ### Manual Build From the project root directory: ```bash -cmake -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug # Generate build files -cmake --build build --parallel 16 # Compile with parallel jobs +cmake -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug +cmake --build build --parallel 16 ``` - - ## 6. Window Manager Integration If you use a tiling window manager (e.g., `Krohnkite`), ImGui may spawn floating glfw windows with a prefix. Add the following rule to allow floating windows: diff --git a/scripts/create_build_system.py b/scripts/create_build_system.py new file mode 100644 index 0000000..0d3f55d --- /dev/null +++ b/scripts/create_build_system.py @@ -0,0 +1,1015 @@ +import os +import sys +import scripts.utils as utils + + + +def prompt_build_sys_selection(): + build_sys = ["CMake", "Premake5"] + + for i, ide in enumerate(build_sys): + print(f"{i}. {ide}") + + while (True): + choice = input("Select a Build System to use (enter the number): ") + try: + choice_index = int(choice) + if 0 <= choice_index < len(build_sys): + return build_sys[choice_index] + + print("Invalid selection number.") + except ValueError: + print("Please enter a valid number.") + + + +def write_file(target_dir, content): + with open(target_dir, "w") as f: + f.write(content) + utils.print_info(f"Created {target_dir}") + + +def apply_cmake_build_system(project_name): + + root_cmake = """ +# Root [CMakeLists.txt] + +cmake_minimum_required(VERSION 3.15) +project(application LANGUAGES CXX) + +# Set C++ standard and compiler flags +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Set output directories for binaries (similar to your targetdir and objdir) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin-int) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin-int) + +# Define configurations (Debug, RelWithDebInfo, Release) +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build" FORCE) +endif() +set(CMAKE_CONFIGURATION_TYPES "Debug;RelWithDebInfo;Release") + +# Platform-specific definitions +if(WIN32) + add_compile_definitions( + PLATFORM_WINDOWS + WIN32_LEAN_AND_MEAN + UNICODE + _UNICODE + ) +elseif(UNIX) + add_compile_definitions( + PLATFORM_LINUX + ) +endif() + +# Define common definitions and flags +add_compile_definitions( + _CRT_SECURE_NO_WARNINGS + NOMINMAX +) + +# Multi-processor compilation +add_compile_options($<$:/MP>) + +# For MinGW, add specific compiler options - FIXED: Only apply C flags to C files +if(CMAKE_C_COMPILER_ID MATCHES "GNU") + add_compile_options( + -Wall + $<$:-Wno-declaration-after-statement> + ) +endif() + +# Build GLFW first so it's available for ImGui +set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "Don't build the GLFW examples") +set(GLFW_BUILD_TESTS OFF CACHE BOOL "Don't build the GLFW tests") +set(GLFW_BUILD_DOCS OFF CACHE BOOL "Don't build the GLFW docs") +set(GLFW_INSTALL OFF CACHE BOOL "Don't create an GLFW install target") +add_subdirectory(vendor/glfw) + +# Then build ImGui (which depends on GLFW) +add_subdirectory(vendor/imgui) + +# add the tests +add_subdirectory(testing) + +# Create your main application project +add_subdirectory(src) +""" + + src_cmake = f""" +# Application [src/CMakeLists.txt] + +project({project_name} LANGUAGES CXX) + +# Find required packages +find_package(OpenGL REQUIRED) +find_package(Qt5 COMPONENTS Core Widgets REQUIRED) # For Qt5 +# find_package(Qt6 COMPONENTS Core Widgets REQUIRED) # For Qt6 # not needed yet + +# List your source files +file(GLOB_RECURSE SOURCES_CONAN "*.cpp" "*.h") +file(GLOB IMPLOT_SOURCES "../vendor/implot/*.h" "../vendor/implot/*.cpp") + +# Add ImGui OpenGL3 backend files - THESE WERE MISSING +file(GLOB IMGUI_OPENGL3_SOURCES + "../vendor/imgui/backends/imgui_impl_opengl3.h" + "../vendor/imgui/backends/imgui_impl_opengl3.cpp" +) + +# Add executable with ALL required sources +add_executable(application_template + ${{SOURCES_CONAN}} + ${{IMPLOT_SOURCES}} + ${{IMGUI_OPENGL3_SOURCES}} +) + +# Precompiled headers (requires CMake 3.16+) +target_precompile_headers(application_template PRIVATE util/pch.h) + +# Include directories +target_include_directories(application_template PRIVATE + ${{CMAKE_CURRENT_SOURCE_DIR}} + ${{CMAKE_CURRENT_SOURCE_DIR}}/assets + ${{CMAKE_CURRENT_SOURCE_DIR}}/../vendor + ${{CMAKE_CURRENT_SOURCE_DIR}}/../vendor/glew/include + ${{CMAKE_CURRENT_SOURCE_DIR}}/../vendor/glm + ${{CMAKE_CURRENT_SOURCE_DIR}}/../vendor/glfw/include + ${{CMAKE_CURRENT_SOURCE_DIR}}/../vendor/imgui + ${{CMAKE_CURRENT_SOURCE_DIR}}/../vendor/imgui/backends + ${{CMAKE_CURRENT_SOURCE_DIR}}/../vendor/implot + ${{CMAKE_CURRENT_SOURCE_DIR}}/../vendor/stb_image + ${{Qt5Core_INCLUDE_DIRS}} + ${{Qt5Widgets_INCLUDE_DIRS}} +) + +# Add definitions for application target +target_compile_definitions(application_template PRIVATE + GLFW_INCLUDE_NONE + GLEW_STATIC +) + +# Configuration-specific definitions +target_compile_definitions(application_template PRIVATE + $<$:DEBUG> + $<$:RELEASE_WITH_DEBUG_INFO> + $<$:RELEASE> +) + +# Link libraries +target_link_libraries(application_template PRIVATE + imgui + glfw + OpenGL::GL + Qt5::Core + Qt5::Widgets +) + +# Platform-specific linking +if(WIN32) + # Try different GLEW library paths for MinGW + find_library(GLEW_LIBRARY + NAMES glew32s glew32 + PATHS + ${{CMAKE_SOURCE_DIR}}/vendor/glew/lib/Release/x64 + ${{CMAKE_SOURCE_DIR}}/vendor/glew/lib + ${{CMAKE_SOURCE_DIR}}/vendor/glew/lib/Release/Win32 + NO_DEFAULT_PATH + ) + + if(GLEW_LIBRARY) + target_link_libraries(application_template PRIVATE ${{GLEW_LIBRARY}}) + else() + # Fallback: try to find GLEW system-wide or use a different approach + find_package(GLEW) + if(GLEW_FOUND) + target_link_libraries(application_template PRIVATE GLEW::GLEW) + else() + message(WARNING "GLEW library not found. Please check the path.") + endif() + endif() + + target_link_libraries(application_template PRIVATE + gdi32 + user32 + comdlg32 + shell32 + opengl32 + ) + + # Copy assets post-build + add_custom_command(TARGET application_template POST_BUILD + COMMAND ${{CMAKE_COMMAND}} -E copy_directory + ${{CMAKE_SOURCE_DIR}}/assets + $/assets + COMMAND ${{CMAKE_COMMAND}} -E copy_directory + ${{CMAKE_SOURCE_DIR}}/config + $/config + ) +else() + # Linux-specific GLEW handling + find_package(PkgConfig REQUIRED) + pkg_check_modules(GLEW REQUIRED glew) + + # Add GLEW include directories and link libraries for Linux + target_include_directories(application_template PRIVATE + ${{GLEW_INCLUDE_DIRS}} + ) + + target_link_libraries(application_template PRIVATE + ${{GLEW_LIBRARIES}} + GL + X11 + pthread + dl + ) + + # Alternative method if pkg-config doesn't work: + # find_library(GLEW_LIBRARY NAMES GLEW glew) + # if(GLEW_LIBRARY) + # target_link_libraries(application_template PRIVATE ${{GLEW_LIBRARY}}) + # endif() + + # Copy assets for Linux (create the directories first) + add_custom_command(TARGET application_template POST_BUILD + COMMAND ${{CMAKE_COMMAND}} -E make_directory + $/assets + COMMAND ${{CMAKE_COMMAND}} -E make_directory + $/config + COMMAND ${{CMAKE_COMMAND}} -E copy_directory + ${{CMAKE_SOURCE_DIR}}/assets + $/assets + COMMAND ${{CMAKE_COMMAND}} -E copy_directory + ${{CMAKE_SOURCE_DIR}}/config + $/config + ) +endif() + +# Disable PCH for specific files (similar to your Premake flags) +set_source_files_properties( + ../vendor/implot/implot.cpp + ../vendor/implot/implot_items.cpp + ../vendor/implot/implot_demo.cpp + ../vendor/imgui/backends/imgui_impl_glfw.cpp + ../vendor/imgui/backends/imgui_impl_opengl3.cpp # ADD THIS + PROPERTIES + SKIP_PRECOMPILE_HEADERS ON +) +""" + + tests_cmake = """ + +# Tests [testing/CMakeLists.txt] + +project(tests LANGUAGES CXX) + +# Use FetchContent for Catch2 +include(FetchContent) +FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v3.5.4 +) +FetchContent_MakeAvailable(Catch2) + +# Find required packages +find_package(OpenGL REQUIRED) +find_package(Qt5 COMPONENTS Core Widgets REQUIRED) + +# List test source files +file(GLOB_RECURSE TEST_SOURCES "*.cpp" "*.h") + +# List utility source files from main application using file(GLOB) +file(GLOB UTIL_TIMING_SOURCES "../src/util/timing/*.cpp" "../src/util/timing/*.h") +file(GLOB UTIL_DATA_STRUCTURES_SOURCES + "../src/util/data_structures/data_types.h" + "../src/util/data_structures/deletion_queue.h" + "../src/util/data_structures/deletion_queue.cpp" + "../src/util/data_structures/type_deletion_queue.h" + "../src/util/data_structures/type_deletion_queue.cpp" + "../src/util/data_structures/string_manipulation.cpp" +) +file(GLOB UTIL_MATH_SOURCES + "../src/util/math/random.cpp" + "../src/util/math/math.cpp" +) +file(GLOB UTIL_IO_SOURCES + "../src/util/io/io.cpp" + "../src/util/io/config.cpp" + "../src/util/io/logger.cpp" + "../src/util/io/serializer_data.h" + "../src/util/io/serializer_yaml.h" + "../src/util/io/serializer_yaml.cpp" + "../src/util/io/serializer_binary.h" + "../src/util/io/serializer_binary.cpp" +) +file(GLOB UTIL_SYSTEM_SOURCES + "../src/util/system.cpp" +) + +# Combine all utility sources +set(UTIL_SOURCES + ${UTIL_TIMING_SOURCES} + ${UTIL_DATA_STRUCTURES_SOURCES} + ${UTIL_MATH_SOURCES} + ${UTIL_IO_SOURCES} + ${UTIL_SYSTEM_SOURCES} +) + +# Add executable +add_executable(tests ${TEST_SOURCES} ${UTIL_SOURCES}) + +# Set C++ standard +set_target_properties(tests PROPERTIES + CXX_STANDARD 23 + CXX_STANDARD_REQUIRED ON +) + +# Include directories (remove the local Catch2 src path) +target_include_directories(tests PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../src + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/glew/include + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/glm + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/glfw/include + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/imgui + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/imgui/backends + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/implot + ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/stb_image + ${Qt5Core_INCLUDE_DIRS} + ${Qt5Widgets_INCLUDE_DIRS} +) + +# Add definitions +target_compile_definitions(tests PRIVATE + _CRT_SECURE_NO_WARNINGS + GLFW_INCLUDE_NONE + NOMINMAX +) + +# Configuration-specific definitions +target_compile_definitions(tests PRIVATE + $<$:DEBUG> + $<$:RELEASE_WITH_DEBUG_INFO> + $<$:RELEASE> +) + +# Platform-specific definitions +if(WIN32) + target_compile_definitions(tests PRIVATE + PLATFORM_WINDOWS + WIN32_LEAN_AND_MEAN + UNICODE + _UNICODE + GLEW_STATIC + ) +else() + target_compile_definitions(tests PRIVATE + PLATFORM_LINUX + ) +endif() + +# Link libraries +target_link_libraries(tests PRIVATE + imgui + glfw + OpenGL::GL + Qt5::Core + Qt5::Widgets + Catch2::Catch2WithMain +) + +# Platform-specific linking +if(WIN32) + # GLEW library for Windows + find_library(GLEW_LIBRARY + NAMES glew32s glew32 + PATHS + ${CMAKE_SOURCE_DIR}/vendor/glew/lib/Release/x64 + ${CMAKE_SOURCE_DIR}/vendor/glew/lib + ${CMAKE_SOURCE_DIR}/vendor/glew/lib/Release/Win32 + NO_DEFAULT_PATH + ) + + if(GLEW_LIBRARY) + target_link_libraries(tests PRIVATE ${GLEW_LIBRARY}) + else() + find_package(GLEW) + if(GLEW_FOUND) + target_link_libraries(tests PRIVATE GLEW::GLEW) + else() + message(WARNING "GLEW library not found for tests.") + endif() + endif() + + target_link_libraries(tests PRIVATE + gdi32 + user32 + comdlg32 + shell32 + opengl32 + ) + +else() + # Linux-specific linking + find_package(PkgConfig REQUIRED) + pkg_check_modules(GLEW REQUIRED glew) + + target_include_directories(tests PRIVATE + ${GLEW_INCLUDE_DIRS} + ) + + target_link_libraries(tests PRIVATE + ${GLEW_LIBRARIES} + GL + X11 + pthread + dl + ) +endif() + +# Use FetchContent for Catch2 instead of manual build +include(FetchContent) +FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v3.5.4 # Use a specific stable version +) +FetchContent_MakeAvailable(Catch2) + +# Link against Catch2 targets +target_link_libraries(tests PRIVATE Catch2::Catch2WithMain) + +# Compiler options +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_options(tests PRIVATE + -msse4.1 + -fPIC + -Wall + -Wno-dangling-else + ) +endif() + +# Disable PCH for specific files if needed +set_source_files_properties( + ../vendor/implot/implot.cpp + ../vendor/implot/implot_items.cpp + ../vendor/implot/implot_demo.cpp + ../vendor/imgui/backends/imgui_impl_glfw.cpp + ../vendor/imgui/backends/imgui_impl_opengl3.cpp + PROPERTIES + SKIP_PRECOMPILE_HEADERS ON +) +""" + + imgui_cmake = """ +# ImGui [vendor/imgui/CMakeLists.txt] + +project(imgui LANGUAGES CXX) + +# Set C++ standard +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# List source files +set(IMGUI_SOURCES + imconfig.h + imgui.h + imgui.cpp + imgui_draw.cpp + imgui_internal.h + imgui_tables.cpp + imgui_widgets.cpp + imstb_rectpack.h + imstb_textedit.h + imstb_truetype.h + imgui_demo.cpp + backends/imgui_impl_glfw.h + backends/imgui_impl_glfw.cpp +) + +# Create static library +add_library(imgui STATIC ${IMGUI_SOURCES}) + +# Include directories +target_include_directories(imgui PUBLIC + . + backends + ${CMAKE_SOURCE_DIR}/vendor/glfw/include +) + +# Add GLFW_INCLUDE_NONE for ImGui if it uses GLFW +target_compile_definitions(imgui PRIVATE GLFW_INCLUDE_NONE) + +# Platform-specific settings +if(WIN32) + # Windows-specific settings +elseif(UNIX) + # Linux-specific settings + set_target_properties(imgui PROPERTIES POSITION_INDEPENDENT_CODE ON) +endif() +""" + + + # Write files to their respective locations + try: + + write_file("./CMakeLists.txt", root_cmake) + write_file("./src/CMakeLists.txt", src_cmake) + write_file("./testing/CMakeLists.txt", tests_cmake) + write_file("./vendor/imgui/CMakeLists.txt", imgui_cmake) + utils.print_c(f"CMake build system successfully applied for project: {project_name}", "green") + + except Exception as e: + print(f"Error creating CMake files: {e}") + + + +def apply_premake_build_system(project_name): + + root_premake = f""" + +------------------ dependencies ------------------ + +------------ path ------------ +vendor_path = {{}} +vendor_path["glew"] = "%{{wks.location}}/vendor/glew" +vendor_path["glfw"] = "%{{wks.location}}/vendor/glfw" +vendor_path["glm"] = "%{{wks.location}}/vendor/glm" +vendor_path["ImGui"] = "%{{wks.location}}/vendor/imgui" +vendor_path["implot"] = "%{{wks.location}}/vendor/implot" +vendor_path["stb_image"] = "%{{wks.location}}/vendor/stb_image" +vendor_path["catch2"] = "%{{wks.location}}/vendor/Catch2" + +------------ include ------------ +IncludeDir = {{}} +IncludeDir["glew"] = "%{{vendor_path.glew}}/include" +IncludeDir["glfw"] = "%{{vendor_path.glfw}}" +IncludeDir["glm"] = "%{{vendor_path.glm}}" +IncludeDir["ImGui"] = "%{{vendor_path.ImGui}}" +IncludeDir["implot"] = "%{{vendor_path.implot}}" +IncludeDir["stb_image"] = "%{{vendor_path.stb_image}}" +IncludeDir["catch2"] = "%{{vendor_path.catch2}}/src" + +workspace "application" + platforms "x64" + startproject "{project_name}" + + configurations + {{ + "Debug", + "RelWithDebInfo", + "Release", + }} + + flags + {{ + "MultiProcessorCompile" + }} + + outputs = "%{{cfg.buildcfg}}-%{{cfg.system}}-%{{cfg.architecture}}" + local project_path = os.getcwd() + defines + {{ + "ENGINE_INSTALL_DIR=\\"" .. project_path .. "/bin/" .. outputs .. "\\"", + "OUTPUTS=\\"" .. outputs .. "\\"", + }} + + ---------- DISABLED FOR DEV ---------- + if os.target() == "linux" then + print("---------- pre-compile GLFW ----------") + os.execute("cmake -S ./vendor/glfw -B ./vendor/glfw/build") -- manuel compilation + os.execute("cmake --build ./vendor/glfw/build") -- manuel compilation + print("---------- Done compiling GLFW ----------") + end + +group "dependencies" + include "vendor/imgui" + if os.target() == "windows" then + include "vendor/glfw" + end +group "" + + +group "core" + project "{project_name}" -- generated by the setup.py script, modify "app_settings.yml" to change name + + location "%{{wks.location}}" + kind "WindowedApp" + language "C++" + cppdialect "C++20" + staticruntime "on" + + targetdir ("%{{wks.location}}/bin/" .. outputs .. "/%{{prj.name}}") + objdir ("%{{wks.location}}/bin-int/" .. outputs .. "/%{{prj.name}}") + + pchheader "util/pch.h" + pchsource "src/util/pch.cpp" + + defines + {{ + "_CRT_SECURE_NO_WARNINGS", + "GLFW_INCLUDE_NONE", + "NOMINMAX", + }} + + files + {{ + "src/**.h", + "src/**.cpp", + "src/**.embed", + + "vendor/implot/*.h", -- directly bake implot into application + "vendor/implot/*.cpp", + "vendor/imgui/backends/imgui_impl_opengl3.h", + "vendor/imgui/backends/imgui_impl_opengl3.cpp", + }} + + includedirs + {{ + "src", + "assets", + "vendor", + + "%{{IncludeDir.glew}}", + "%{{IncludeDir.glm}}", + "%{{IncludeDir.glfw}}/include", + "%{{IncludeDir.ImGui}}", + "%{{IncludeDir.ImGui}}/backends/", + "%{{IncludeDir.implot}}", + "%{{IncludeDir.stb_image}}", + }} + + links + {{ + "ImGui", + }} + + libdirs + {{ + "vendor/imgui/bin/" .. outputs .. "/imgui", + }} + + filter "files:vendor/implot/**.cpp" + flags {{ "NoPCH" }} + + filter "files:vendor/imgui/**.cpp" + flags {{ "NoPCH" }} + + filter "system:linux" + systemversion "latest" + defines "PLATFORM_LINUX" + + includedirs + {{ + "/usr/include", + }} + + externalincludedirs -- treat VMA as system headers (prevent warnings) + {{ + "/usr/include/x86_64-linux-gnu/qt5", -- Base Qt include path + "/usr/include/x86_64-linux-gnu/qt5/QtCore", + "/usr/include/x86_64-linux-gnu/qt5/QtWidgets", + "/usr/include/x86_64-linux-gnu/qt5/QtGui", + }} + + libdirs + {{ + "%{{wks.location}}/vendor/glfw/build/src", + "/usr/lib/x86_64-linux-gnu", + "/usr/lib/x86_64-linux-gnu/qt5", + }} + + links + {{ + "GLEW", + "GL", + "glfw3", + "Qt5Core", + "Qt5Widgets", + "Qt5Gui", + }} + + buildoptions + {{ + "-msse4.1", -- include the SSE4.1 flag for Linux builds + "-fPIC", + "-Wall", -- compiler options + "-Wno-dangling-else", + }} + + postbuildcommands + {{ + '{{COPYDIR}} -n "%{{wks.location}}/assets" "%{{wks.location}}/bin/' .. outputs .. '/%{{prj.name}}"', + '{{COPYDIR}} -n "%{{wks.location}}/config" "%{{wks.location}}/bin/' .. outputs .. '/%{{prj.name}}"', + }} + + filter "system:windows" + systemversion "latest" + defines + {{ + "PLATFORM_WINDOWS", + "WIN32_LEAN_AND_MEAN", + "GLEW_STATIC", + "UNICODE", + "_UNICODE", + }} + + links + {{ + "ImGui", + "glfw", + "glew32s", + "opengl32", + "gdi32", + "user32", + "comdlg32", + "shell32", + }} + + libdirs + {{ + "%{{wks.location}}\\\\vendor\\\\glfw\\\\bin\\\\" .. outputs .. "\\\\glfw", + "%{{wks.location}}\\\\vendor\\\\imgui\\\\bin\\\\" .. outputs .. "\\\\imgui", + "%{{vendor_path.glew}}\\\\lib\\\\Release\\\\x64", + }} + + postbuildcommands + {{ + '{{COPYDIR}} "%{{wks.location}}\\\\assets" "%{{wks.location}}\\\\bin\\\\' .. outputs .. '\\\\%{{prj.name}}\\\\assets"', + '{{COPYDIR}} "%{{wks.location}}\\\\config" "%{{wks.location}}\\\\bin\\\\' .. outputs .. '\\\\%{{prj.name}}\\\\config"', + }} + + + filter {{ "system:windows", "action:gmake2" }} -- MinGW specific settings + links + {{ + "ImGui", + "glfw3", + "glew32", + "opengl32", + "gdi32", + "user32", + "comdlg32", + "shell32", + }} + + libdirs + {{ + "%{{wks.location}}\\\\vendor\\\\glfw\\\\build-mingw\\\\src", + "%{{wks.location}}\\\\vendor\\\\glfw\\\\bin\\\\' .. outputs .. '\\\\glfw", + "%{{vendor_path.glew}}\\\\lib\\\\Release\\\\Win32", + }} + + + filter "configurations:Debug" + defines "DEBUG" + runtime "Debug" + symbols "on" + + filter "configurations:RelWithDebInfo" + defines "RELEASE_WITH_DEBUG_INFO" + runtime "Release" + symbols "on" + optimize "on" + + filter "configurations:Release" + defines "RELEASE" + runtime "Release" + symbols "off" + optimize "on" + +group "" + + +group "tests" + project "tests" + kind "ConsoleApp" + language "C++" + cppdialect "C++20" + staticruntime "on" + + targetdir ("%{{wks.location}}/bin/" .. outputs .. "/%{{prj.name}}") + objdir ("%{{wks.location}}/bin-int/" .. outputs .. "/%{{prj.name}}") + + files + {{ + "testing/**.h", + "testing/**.cpp", + + "src/util/timing/**.h", + "src/util/timing/**.cpp", + + "src/util/data_structures/data_types.h", + "src/util/data_structures/deletion_queue.h", + "src/util/data_structures/deletion_queue.cpp", + "src/util/data_structures/type_deletion_queue.h", + "src/util/data_structures/type_deletion_queue.cpp", + + "src/util/math/random.cpp", + "src/util/math/math.cpp", + "src/util/io/io.cpp", + "src/util/io/config.cpp", + "src/util/io/logger.cpp", + "src/util/io/serializer_data.h", + "src/util/io/serializer_yaml.h", + "src/util/io/serializer_yaml.cpp", + "src/util/io/serializer_binary.h", + "src/util/io/serializer_binary.cpp", + + + "src/util/data_structures/string_manipulation.cpp", + "src/util/system.cpp", + }} + + includedirs + {{ + "src", + "testing", + "%{{IncludeDir.catch2}}", + "%{{IncludeDir.glm}}", + "%{{vendor_path.catch2}}/Build/generated-includes", + + "%{{IncludeDir.glew}}", + "%{{IncludeDir.glm}}", + "%{{IncludeDir.glfw}}/include", + "%{{IncludeDir.ImGui}}", + "%{{IncludeDir.ImGui}}/backends/", + "%{{IncludeDir.implot}}", + "%{{IncludeDir.stb_image}}", + }} + + links + {{ + "ImGui", + }} + + libdirs + {{ + "%{{vendor_path.catch2}}/Build/src", + "vendor/imgui/bin/" .. outputs .. "/imgui", + }} + + prebuildcommands + {{ + "cmake -S ./vendor/Catch2 -B ./vendor/Catch2/Build -DCMAKE_BUILD_TYPE=%{{cfg.buildcfg}} -DCATCH_INSTALL_DOCS=OFF -DCATCH_INSTALL_EXTRAS=OFF", + "cmake --build ./vendor/Catch2/Build --config %{{cfg.buildcfg}}" + }} + + filter "configurations:Debug" + links {{ "Catch2Maind", "Catch2d" }} + + filter "configurations:RelWithDebInfo" + links {{ "Catch2Main", "Catch2" }} + + filter "configurations:Release" + links {{ "Catch2Main", "Catch2" }} + + filter "files:vendor/implot/**.cpp" + flags {{ "NoPCH" }} + + filter "files:vendor/imgui/**.cpp" + flags {{ "NoPCH" }} + + filter "system:linux" + systemversion "latest" + defines "PLATFORM_LINUX" + links {{ + "pthread", -- Catch2 requires pthread on Linux + "Qt5Core", -- Add Qt libraries if needed + "Qt5Widgets", + "Qt5Gui", + }} + + buildoptions + {{ + "-msse4.1", + "-fPIC", + "-Wall", + "-Wno-dangling-else" + }} + + externalincludedirs -- treat VMA as system headers (prevent warnings) + {{ + "/usr/include/x86_64-linux-gnu/qt5", -- Base Qt include path + "/usr/include/x86_64-linux-gnu/qt5/QtCore", + "/usr/include/x86_64-linux-gnu/qt5/QtWidgets", + "/usr/include/x86_64-linux-gnu/qt5/QtGui", + }} + + filter "system:windows" + systemversion "latest" + defines + {{ + "PLATFORM_WINDOWS", + "UNICODE", + "_UNICODE", + }} + + links + {{ + "ImGui", + "glfw", + "glew32s", + "opengl32", + "gdi32", + "user32", + "comdlg32", -- For GetOpenFileNameW + "shell32", -- For other Windows APIs + }} + + libdirs + {{ + "%{{wks.location}}/vendor/glfw/lib-vc2022", + "%{{vendor_path.glew}}/lib/Release/x64", + }} + + filter "configurations:Debug" + defines "DEBUG" + runtime "Debug" + symbols "on" + + filter "configurations:RelWithDebInfo" + defines "RELEASE_WITH_DEBUG_INFO" + runtime "Release" + symbols "on" + optimize "on" + + filter "configurations:Release" + defines "RELEASE" + runtime "Release" + symbols "off" + optimize "on" +group "" +""" + + imgui_premake = """ +project "imgui" + kind "StaticLib" + language "C++" + cppdialect "C++17" + staticruntime "on" + + targetdir ("bin/" .. outputs .. "/%{prj.name}") + objdir ("bin-int/" .. outputs .. "/%{prj.name}") + + files + { + "imconfig.h", + "imgui.h", + "imgui.cpp", + "imgui_draw.cpp", + "imgui_internal.h", + "imgui_tables.cpp", + "imgui_widgets.cpp", + "imstb_rectpack.h", + "imstb_textedit.h", + "imstb_truetype.h", + "imgui_demo.cpp", + "backends/imgui_impl_glfw.h", + "backends/imgui_impl_glfw.cpp", + } + + includedirs + { + "%{prj.name}", + ".", + "backends", + "%{IncludeDir.glfw}/include", + -- "%{IncludeDir.Vulkan}", + } + + filter "system:windows" + systemversion "latest" + + filter "system:linux" + pic "On" + systemversion "latest" + + filter "configurations:Debug" + runtime "Debug" + symbols "on" + + filter "configurations:RelWithDebInfo" + runtime "Release" + symbols "on" + optimize "on" + + filter "configurations:Release" + runtime "Release" + optimize "on" +""" + + # Write files to their respective locations + try: + + write_file("./premake5.lua", root_premake) + write_file("./vendor/imgui/premake5.lua", imgui_premake) + utils.print_c(f"Premake5 build system successfully applied for project: {project_name}", "green") + + except Exception as e: + print(f"Error creating CMake files: {e}") diff --git a/scripts/imgui_CMakeLists.txt b/scripts/imgui_CMakeLists.txt deleted file mode 100644 index e7637fc..0000000 --- a/scripts/imgui_CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -# ImGui [vendor/imgui/CMakeLists.txt] - -project(imgui LANGUAGES CXX) - -# Set C++ standard -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# List source files -set(IMGUI_SOURCES - imconfig.h - imgui.h - imgui.cpp - imgui_draw.cpp - imgui_internal.h - imgui_tables.cpp - imgui_widgets.cpp - imstb_rectpack.h - imstb_textedit.h - imstb_truetype.h - imgui_demo.cpp - backends/imgui_impl_glfw.h - backends/imgui_impl_glfw.cpp -) - -# Create static library -add_library(imgui STATIC ${IMGUI_SOURCES}) - -# Include directories -target_include_directories(imgui PUBLIC - . - backends - ${CMAKE_SOURCE_DIR}/vendor/glfw/include -) - -# Add GLFW_INCLUDE_NONE for ImGui if it uses GLFW -target_compile_definitions(imgui PRIVATE GLFW_INCLUDE_NONE) - -# Platform-specific settings -if(WIN32) - # Windows-specific settings -elseif(UNIX) - # Linux-specific settings - set_target_properties(imgui PROPERTIES POSITION_INDEPENDENT_CODE ON) -endif() \ No newline at end of file diff --git a/scripts/linux/IDE_setup.py b/scripts/linux/IDE_setup.py index 21ba08d..e886920 100644 --- a/scripts/linux/IDE_setup.py +++ b/scripts/linux/IDE_setup.py @@ -8,8 +8,7 @@ import json import datetime -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) -import utils +import scripts.utils as utils def detect_rider(): # Check common Rider installation paths on Linux @@ -64,8 +63,6 @@ def detect_IDEs(): if detect_rider(): # Detect available IDEs IDEs.append("JetBrains Rider") - IDEs.append("Makefile (CLion/Ninja compatible)") - if not IDEs: print("No supported IDEs detected.") sys.exit(1) @@ -76,6 +73,9 @@ def detect_IDEs(): def prompt_ide_selection(): IDEs = detect_IDEs() + if (len(IDEs) == 1) and utils.get_silent(): + return IDEs[0] + print("\nDetected IDEs:") for i, ide in enumerate(IDEs): print(f"{i}. {ide}") @@ -106,9 +106,11 @@ def prompt_build_config(): try: index = int(choice) if 0 <= index < len(configs): + if utils.SILENT: + print("") return configs[index] - else: - print("Invalid number.") + + print("Invalid selection number.") except ValueError: print("Please enter a valid number.") @@ -247,7 +249,7 @@ def setup_vscode_configs(project_root, build_config, application_name, clean_art with open(cpp_props_path, "w") as f: json.dump(cpp_props, f, indent=4) - print("VSCode integration files generated in .vscode/") + utils.print_info("VSCode integration files generated in .vscode/") utils.print_c("\nVSCode usage", "blue") - print(" Build the project: Ctrl+Shift+B (runs 'Clean & Build')") - print(" Launch the application: F5 (runs the debugger with selected config)") + utils.print_info(" Build the project: Ctrl+Shift+B (runs 'Clean & Build')") + utils.print_info(" Launch the application: F5 (runs the debugger with selected config)") diff --git a/scripts/utils.py b/scripts/utils.py index 7a9b4d7..43a224a 100644 --- a/scripts/utils.py +++ b/scripts/utils.py @@ -1,4 +1,4 @@ -# This is a modefied version of: https://github.com/TheCherno/Hazel/blob/master/scripts/Utils.py +# This is a modified version of: https://github.com/TheCherno/Hazel/blob/master/scripts/Utils.py import sys import os @@ -6,6 +6,13 @@ import time import urllib + +SILENT = False + + +def get_silent(): + return SILENT + def install(package): subprocess.check_call([sys.executable, '-m', 'pip', 'install', package]) @@ -36,12 +43,22 @@ def print_c(text, color): "white": "\033[37m", "reset": "\033[0m" # Reset to default color } - print(f"{colors.get(color, colors['reset'])}{text}{colors['reset']}") + if not SILENT and (color != "red" or color != "orange"): + print(f"{colors.get(color, colors['reset'])}{text}{colors['reset']}") + def print_u(text): + if SILENT: + return print(f"\033[4m{text}\033[0m") +def print_info(text): + """Print informational messages (suppressed in silent mode)""" + if SILENT: + return + print(text) + def download_file(url, filepath): is_ci = os.getenv("CI") == "true" diff --git a/scripts/windows/IDE_setup.py b/scripts/windows/IDE_setup.py index 2a846f1..4e90e27 100644 --- a/scripts/windows/IDE_setup.py +++ b/scripts/windows/IDE_setup.py @@ -103,18 +103,23 @@ def prompt_ide_selection(): print("only one IDE detected") return IDEs[0] - choice = input("Select an IDE to use (enter the number): ") - try: - choice_index = int(choice) - if 0 <= choice_index < len(IDEs): - return IDEs[choice_index] - else: - print("Invalid selection.") - sys.exit(1) + while (True): + choice = input("Select an IDE to use (enter the number): ") + try: + choice_index = int(choice) + if 0 <= choice_index < len(IDEs): - except ValueError: - print("Invalid input.") - sys.exit(1) + selected_ide = IDEs[choice_index] + if "VSCode" in selected_ide: + utils.print_c("\nVSCode usage", "blue") + print(" Build the project: Ctrl+Shift+B (runs 'Clean & Build')") + print(" Launch the application: F5 (runs the debugger with selected config)") + return selected_ide + + print("Invalid selection number.") + except ValueError: + print("Please enter a valid number.") + @@ -250,7 +255,4 @@ def setup_vscode_configs(project_root, build_config, application_name, clean_art with open(cpp_props_path, "w") as f: json.dump(cpp_props, f, indent=4) - print("VSCode integration files generated in .vscode/") - utils.print_c("\nVSCode usage", "blue") - print(" Build the project: Ctrl+Shift+B (runs 'Clean & Build')") - print(" Launch the application: F5 (runs the debugger with selected config)") \ No newline at end of file + print("VSCode integration files generated in .vscode/") \ No newline at end of file diff --git a/setup.py b/setup.py index 9b1f18b..9424fe2 100644 --- a/setup.py +++ b/setup.py @@ -27,12 +27,16 @@ import os import re import yaml +import shutil import socket +import argparse import platform import scripts.utils as utils import scripts.git_util as git_util IS_CI = os.getenv("CI") == "true" +import scripts.create_build_system as CBS + if platform.system() == "Linux": from scripts.linux.setup_env import env_configuration import scripts.linux.IDE_setup as IDE_setup @@ -45,40 +49,6 @@ raise Exception("Unsupported operating system") - -def apply_premake_settings(file_path="./config/app_settings.yml", premake_file_path="./premake5.lua"): - try: - with open(file_path, 'r') as stream: - data = yaml.safe_load(stream) - app_name = data['general_settings']['name'] - - # Read the premake5.lua content - with open(premake_file_path, 'r') as file: - content = file.read() - - # find/replace startproject name - content = re.sub( - r'(startproject\s*")[^"]*(")', - r'\1' + app_name + r'\2', - content - ) - - # find/replace project name - content = re.sub( - r'(project\s*")[^"]*(".*?-- generated by the setup\.py script)', - r'\1' + app_name + r'\2', - content - ) - - # Write the modified content back - with open(premake_file_path, 'w') as file: - file.write(content) - - except Exception as e: - utils.print_c(f"Error while applying settings: {str(e)}", "red") - sys.exit(1) - - def get_application_name(file_path="./config/app_settings.yml"): try: with open(file_path, 'r') as stream: @@ -99,10 +69,94 @@ def get_clean_build_artifacts_on_build(file_path="./config/app_settings.yml"): sys.exit(1) +def clean_build_artifacts(): + """Clean build artifacts and generated files""" + folders_to_clean = [ + "build", + "bin", + "bin-int", + "vendor/glfw/build", + "vendor/Catch2/Build", + ".vscode" # Optional: remove if you don't want to clean VSCode configs + ] + + files_to_clean = [ + "Makefile", + "*.workspace", + "*.sln", + "*.vcxproj*" + ] + + for folder in folders_to_clean: + if os.path.exists(folder): + utils.print_c(f"Removing {folder}", "yellow") + shutil.rmtree(folder) + + for pattern in files_to_clean: + for file in glob.glob(pattern): + utils.print_c(f"Removing {file}", "yellow") + os.remove(file) + def main(): - # Skip internet check in CI - if not IS_CI: + + parser = argparse.ArgumentParser( + description='Application Template Setup Script', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=''' +Examples: + python3 setup.py # Interactive setup with all prompts + python3 setup.py -k # Use CMake build system (skip selection) + python3 setup.py -p # Use Premake build system (skip selection) + python3 setup.py -V # Setup for VSCode (skip IDE selection) + python3 setup.py -n # Generate project files without building + python3 setup.py -c # Clean build artifacts before setup + python3 setup.py -C Release # Set build configuration + python3 setup.py -i -N # Offline setup (ignore submodules, no internet check) + +Common workflows: + Development: python3 setup.py -k -V -C Debug + Release: python3 setup.py -k -C Release -n + Quick setup: python3 setup.py -k -V -n + ''' + ) + + # Build system group + build_group = parser.add_argument_group('Build System Selection') + build_exclusive = build_group.add_mutually_exclusive_group() + build_exclusive.add_argument('-p', '--premake', action='store_true', help='Use Premake build system (skip selection prompt)') + build_exclusive.add_argument('-k', '--cmake', action='store_true', help='Use CMake build system (skip selection prompt)') + + # IDE selection group + ide_group = parser.add_argument_group('IDE Selection') + ide_exclusive = ide_group.add_mutually_exclusive_group() + ide_exclusive.add_argument('-V', '--vscode', action='store_true', help='Setup for VSCode (skip IDE selection)') + ide_exclusive.add_argument('-S', '--visual-studio', action='store_true', help='Setup for Visual Studio (Windows only)') + ide_exclusive.add_argument('-r', '--rider', action='store_true', help='Setup for JetBrains Rider') + ide_exclusive.add_argument('-m', '--makefile', action='store_true', help='Setup for Makefile (Linux only)') + + # Build configuration group + config_group = parser.add_argument_group('Build Configuration') + config_group.add_argument('-C', '--config', choices=['Debug', 'Release', 'RelWithDebInfo'], default='Debug', help='Build configuration (default: Debug)') + + # Behavior flags group + behavior_group = parser.add_argument_group('Behavior Flags') + behavior_group.add_argument('-s', '--skip-submods', action='store_true', help='Skip submodule updating') + behavior_group.add_argument('-N', '--no-net-check', action='store_true', help='Skip internet connectivity check') + behavior_group.add_argument('-n', '--no-build', action='store_true', help='Generate project files without building') + behavior_group.add_argument('-c', '--clean', action='store_true', help='Clean build artifacts before setup') + behavior_group.add_argument('-f', '--force', action='store_true', help='Force overwrite existing configurations') + behavior_group.add_argument('-q', '--quiet', action='store_true', help='Enable silent mode (suppress non-essential output)') + + args = parser.parse_args() + + # Set verbose mode early + if args.quiet: + utils.SILENT = True + + + # Skip internet check in CI or if --no-internet-check is passed + if not IS_CI and not args.no_net_check: try: socket.setdefaulttimeout(3) socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(("8.8.8.8", 53)) @@ -111,6 +165,12 @@ def main(): sys.exit(1) try: + + # Clean build artifacts if requested + if args.clean: + utils.print_u("\nCLEANING BUILD ARTIFACTS") + clean_build_artifacts() + utils.print_u("\nCHECKING SYSTEM DEPENDENCIES") if not env_configuration.validate(): utils.print_c("Missing required packages - setup aborted", "red") @@ -121,21 +181,40 @@ def main(): utils.print_c("Submodule initialization failed - setup aborted", "red") sys.exit(1) - utils.print_u("\nUPDATING SUBMODULES") # Update submodules to desired branches - git_util.update_submodule("vendor/glfw", "main") - git_util.update_submodule("vendor/glm", "master") - git_util.update_submodule("vendor/imgui", "docking") - git_util.update_submodule("vendor/implot", "master") - git_util.update_submodule("vendor/Catch2", "devel") - + if not args.skip_submods: + utils.print_u("\nUPDATING SUBMODULES") # Update submodules to desired branches + git_util.update_submodule("vendor/glfw", "main") + git_util.update_submodule("vendor/glm", "master") + git_util.update_submodule("vendor/imgui", "docking") + git_util.update_submodule("vendor/implot", "master") + git_util.update_submodule("vendor/Catch2", "devel") + else: + utils.print_c("ignoring update routine for submodules", "orange") utils.print_u("\nAPPLY SETTINGS") - utils.print_c("Settings are defined at [./config/app_settings.yml]. after changing the settings, it is recommended to reexecute the setup script", "blue") + utils.print_c("Settings are defined at [./config/app_settings.yml]. after changing the settings, it is recommended to re-execute the setup script", "blue") # apply_premake_settings() application_name = get_application_name() clean_art_on_build = get_clean_build_artifacts_on_build() - print(f"name: {application_name}") + utils.print_info(f"name: {application_name}") + shutil.copy2("./scripts/imgui_CMakeLists.txt", "./vendor/imgui/CMakeLists.txt") # copy template CMake file to correct directory + + # select build system + utils.print_u("\nSETUP A BUILD SYSTEM") # Initialize submodule configuration + + if args.premake: + build_sys = "Premake5" + elif args.cmake: + build_sys = "CMake" + else: + print("Available build systems:") + build_sys = CBS.prompt_build_sys_selection() + + if build_sys == "Premake5": + CBS.apply_premake_build_system(application_name) + else: # currently only supporting 2 systems -> CMake is default at error + CBS.apply_cmake_build_system(application_name) # setup IDE utils.print_u("\nSETUP IDE") @@ -145,73 +224,135 @@ def main(): selected_ide = IDEs[0] print(f"Selected IDE: {selected_ide}") else: - selected_ide = IDE_setup.prompt_ide_selection() + # Use command line selection if provided + if args.vscode: + selected_ide = "VSCode" + elif args.visual_studio: + selected_ide = "Visual Studio 2022" # Adjust based on detection + elif args.rider: + selected_ide = "JetBrains Rider" + elif args.makefile: + selected_ide = "Makefile" + else: + selected_ide = IDE_setup.prompt_ide_selection() # VSCode spcific setup - if "VSCode" in selected_ide: - if IS_CI: - build_config = "Debug" - else: + build_config = args.config + if "VSCode" in selected_ide and not (args.vscode or IS_CI): + # Only prompt if VSCode was not explicitly chosen via command line + # AND config was not explicitly set via -C/--config + if not any(arg in sys.argv for arg in ['-C', '--config']): build_config = IDE_setup.prompt_build_config() + IDE_setup.setup_vscode_configs(os.getcwd(), build_config, application_name, clean_art_on_build) - - if platform.system() == "Linux": # ---- LINUX VERSION ---- - # prepare premake command - premake_action = "gmake2" # Default to VSCode - if selected_ide == "JetBrains Rider": - premake_action = "rider" - elif "VSCode" in selected_ide: - premake_action = "gmake2" - elif "Makefile" in selected_ide: - premake_action = "gmake2" - - premake_result = subprocess.run(['vendor/premake/premake5', premake_action], text=True) - - else: # ---- WINDOWS VERSION ---- - # prepare premake command - premake_action = "vs2022" # Default to VS2022 - if selected_ide == "VSCode": - premake_action = "gmake2" # For MinGW-based builds - elif "Visual Studio" in selected_ide: # Map IDE selection to premake action - if "2022" in selected_ide: - premake_action = "vs2022" - elif "2019" in selected_ide: - premake_action = "vs2019" - elif "2017" in selected_ide: - premake_action = "vs2017" - elif selected_ide == "JetBrains Rider": - premake_action = "rider" - - premake_result = subprocess.run(['vendor\\premake\\premake5.exe', premake_action], text=True) - - if premake_result.returncode != 0: - utils.print_c(f"BUILD FAILED! Premake script encountered errors [{premake_result.returncode}]", "red") - else: - utils.print_c("BUILD SUCCESSFUL!", "green") - - - # print helpful hints - if platform.system() == "Linux": # ---- LINUX VERSION ---- + if build_sys == "Premake5": + if platform.system() == "Linux": # ---- LINUX VERSION ---- + # prepare premake command + premake_action = "gmake2" # Default to VSCode + if selected_ide == "JetBrains Rider": + premake_action = "rider" + elif "VSCode" in selected_ide: + premake_action = "gmake2" + elif "Makefile" in selected_ide: + premake_action = "gmake2" + + utils.print_c(f"\nCreating Build files using [vendor/premake/premake5 {premake_action}]", "blue") + premake_result = subprocess.run(['vendor/premake/premake5', premake_action], text=True) + + else: # ---- WINDOWS VERSION ---- + # prepare premake command + premake_action = "vs2022" # Default to VS2022 + if selected_ide == "VSCode": + premake_action = "gmake2" # For MinGW-based builds + elif "Visual Studio" in selected_ide: # Map IDE selection to premake action + if "2022" in selected_ide: + premake_action = "vs2022" + elif "2019" in selected_ide: + premake_action = "vs2019" + elif "2017" in selected_ide: + premake_action = "vs2017" + elif selected_ide == "JetBrains Rider": + premake_action = "rider" + + utils.print_c(f"\nCreating Build files using [vendor\\premake\\premake5.exe {premake_action}]", "blue") + premake_result = subprocess.run(['vendor\\premake\\premake5.exe', premake_action], text=True) + + if premake_result.returncode != 0: + utils.print_c(f"BUILD FAILED! Premake script encountered errors [{premake_result.returncode}]", "red") + else: + utils.print_c("Successfully generated build files and precompiled some libs", "green") + + # continue to compile only if generation was successful + if not args.no_build: + utils.print_c("\nBuilding project using [gmake -j]", "blue") + premake_result = subprocess.run(["gmake", "-j"]) + if premake_result.returncode == 0: + utils.print_c("BUILD SUCCESSFUL!", "green") + else: + utils.print_c(f"BUILD FAILED!", "red") + + # print helpful hints + if platform.system() == "Linux": # ---- LINUX VERSION ---- + utils.print_c("\nHelpful hints", "blue") + utils.print_info(" Apply changed premake scripts: vendor/premake/premake5 gmake2") + utils.print_info(" Cleanup generated files: gmake clean") + utils.print_info(" Compile application: gmake -j") + utils.print_info(" More help: vendor/premake/premake5 --help OR https://premake.github.io/docs/Using-Premake/") + + else: # ---- WINDOWS VERSION ---- + # Print helpful hints + utils.print_c("\nHelpful hints for Windows", "blue") + if "Visual Studio" in selected_ide or "Rider" in selected_ide: + utils.print_info(" Open solution file: *.sln") + utils.print_info(" Clean solution: msbuild /t:Clean") + utils.print_info(" Build solution: msbuild /t:Build") + elif selected_ide == "VSCode": + utils.print_info(" Apply changed premake scripts: vendor\\premake\\premake5.exe gmake2") + utils.print_info(" Clean solution: gmake clean") + utils.print_info(" Build solution: gmake -j") + utils.print_info(" More help: vendor\\premake\\premake5.exe --help") + + + else: # Default is CMake + utils.print_c(f"\nCreating Build files using [cmake -B build {build_config}]", "blue") + build_config = "-DCMAKE_BUILD_TYPE=" + build_config + cmake_result = subprocess.run(["cmake", "-B", "build", build_config]) + if cmake_result.returncode != 0: + utils.print_c("CMake configuration failed!", "red") + else: + utils.print_c("CMake configuration successful!", "green") + + # continue to compile only if generation was successful + if not args.no_build: + utils.print_c("\nBuilding project using [cmake --build build]", "blue") + cmake_result = subprocess.run(["cmake", "--build", "build"]) + if cmake_result.returncode == 0: + utils.print_c("BUILD SUCCESSFUL!", "green") + else: + utils.print_c("BUILD FAILED!", "red") + + # dont need platform if utils.print_c("\nHelpful hints", "blue") - print(" Apply changed premake scripts: vendor/premake/premake5 gmake2") - print(" Cleanup generated files: gmake clean") - print(" Compile application: gmake -j") - print(" More help: vendor/premake/premake5 --help OR https://premake.github.io/docs/Using-Premake/") - - else: # ---- WINDOWS VERSION ---- - # Print helpful hints - utils.print_c("\nHelpful hints for Windows", "blue") - if "Visual Studio" in selected_ide or "Rider" in selected_ide: - print(" Open solution file: *.sln") - print(" Clean solution: msbuild /t:Clean") - print(" Build solution: msbuild /t:Build") - elif selected_ide == "VSCode": - print(" Apply changed premake scripts: vendor\\premake\\premake5.exe gmake2") - print(" Clean solution: gmake clean") - print(" Build solution: gmake -j") - print(" More help: vendor\\premake\\premake5.exe --help") - + utils.print_info(" Build from the project root directory:") + utils.print_info(f" Generate build files : cmake -B build {build_config}") + utils.print_info(" Build project: cmake --build build --parallel 16") + + utils.print_info(" Build with manually creating 'build':") + utils.print_info(" create build dir: mkdir build && cd build") + utils.print_info(f" Generate build files : cmake .. {build_config}") + utils.print_info(" Build project: make -j") + + utils.print_u("\nQUICK REFERENCE") + utils.print_info("Common commands:") + utils.print_info(" Setup with different options:") + utils.print_info(" Development: python3 setup.py -k -V -C Debug") + utils.print_info(" Release: python3 setup.py -k -C Release -n") + utils.print_info(" Quick setup: python3 setup.py -k -V -n") + utils.print_info("\n Re-run setup:") + utils.print_info(" python3 setup.py -c -k -V # Full clean setup") + utils.print_info(" python3 setup.py -n -C Release # Change config only") + utils.print_info("\nFor more options: python3 setup.py -h") except KeyboardInterrupt: utils.print_c("\nProcess interrupted by user.", "red") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 536880e..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,114 +0,0 @@ -# Application [src/CMakeLists.txt] - -project(application_template LANGUAGES CXX) - -# Find required packages -find_package(OpenGL REQUIRED) - -# List your source files -file(GLOB_RECURSE SOURCES_CONAN "*.cpp" "*.h") -file(GLOB IMPLOT_SOURCES "../vendor/implot/*.h" "../vendor/implot/*.cpp") - -# Add ImGui OpenGL3 backend files - THESE WERE MISSING -file(GLOB IMGUI_OPENGL3_SOURCES - "../vendor/imgui/backends/imgui_impl_opengl3.h" - "../vendor/imgui/backends/imgui_impl_opengl3.cpp" -) - -# Add executable with ALL required sources -add_executable(application_template - ${SOURCES_CONAN} - ${IMPLOT_SOURCES} - ${IMGUI_OPENGL3_SOURCES} -) - -# Precompiled headers (requires CMake 3.16+) -target_precompile_headers(application_template PRIVATE util/pch.h) - -# Include directories -target_include_directories(application_template PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/assets - ${CMAKE_CURRENT_SOURCE_DIR}/../vendor - ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/glew/include - ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/glm - ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/glfw/include - ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/imgui - ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/imgui/backends - ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/implot - ${CMAKE_CURRENT_SOURCE_DIR}/../vendor/stb_image -) - -# Add definitions for application target -target_compile_definitions(application_template PRIVATE - GLFW_INCLUDE_NONE - GLEW_STATIC -) - -# Configuration-specific definitions -target_compile_definitions(application_template PRIVATE - $<$:DEBUG> - $<$:RELEASE_WITH_DEBUG_INFO> - $<$:RELEASE> -) - -# Link libraries -target_link_libraries(application_template PRIVATE - imgui - glfw - OpenGL::GL -) - -# Platform-specific linking -if(WIN32) - # Try different GLEW library paths for MinGW - find_library(GLEW_LIBRARY - NAMES glew32s glew32 - PATHS - ${CMAKE_SOURCE_DIR}/vendor/glew/lib/Release/x64 - ${CMAKE_SOURCE_DIR}/vendor/glew/lib - ${CMAKE_SOURCE_DIR}/vendor/glew/lib/Release/Win32 - NO_DEFAULT_PATH - ) - - if(GLEW_LIBRARY) - target_link_libraries(application_template PRIVATE ${GLEW_LIBRARY}) - else() - # Fallback: try to find GLEW system-wide or use a different approach - find_package(GLEW) - if(GLEW_FOUND) - target_link_libraries(application_template PRIVATE GLEW::GLEW) - else() - message(WARNING "GLEW library not found. Please check the path.") - endif() - endif() - - target_link_libraries(application_template PRIVATE - gdi32 - user32 - comdlg32 - shell32 - opengl32 - ) - - # Copy assets post-build - add_custom_command(TARGET application_template POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory - ${CMAKE_SOURCE_DIR}/assets - $/assets - COMMAND ${CMAKE_COMMAND} -E copy_directory - ${CMAKE_SOURCE_DIR}/config - $/config - ) -endif() - -# Disable PCH for specific files (similar to your Premake flags) -set_source_files_properties( - ../vendor/implot/implot.cpp - ../vendor/implot/implot_items.cpp - ../vendor/implot/implot_demo.cpp - ../vendor/imgui/backends/imgui_impl_glfw.cpp - ../vendor/imgui/backends/imgui_impl_opengl3.cpp # ADD THIS - PROPERTIES - SKIP_PRECOMPILE_HEADERS ON -) \ No newline at end of file From 5ecae8c69e916b182c46034df4d0fb37e2ef4d76 Mon Sep 17 00:00:00 2001 From: Mich Date: Sat, 4 Oct 2025 17:28:45 +0200 Subject: [PATCH 4/4] update readme --- README.md | 138 +++++++++++++++++++++++++++++++++++------------------- setup.py | 3 +- 2 files changed, 92 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 9db50ac..74fecbd 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,10 @@ A simple, cross-platform C++ application template with a graphical user interfac ## 1. Overview -`application_template` provides a minimal but fully functional starting point for GUI-based C++ applications. It uses: +`application_template` provides a functional starting point for GUI-based C++ applications. It uses: * **ImGui** for immediate-mode GUI widgets +* **ImPlot** * **GLFW** for window and input management * **OpenGL** (configurable via `GL_renderer`) @@ -14,7 +15,8 @@ The template handles platform detection, dependency setup, and IDE integration o ## 2. Features -* Cross-platform support (Linux; Windows support coming soon) +* Cross-platform support (Linux & Windows) +* Dual build system support: CMake and Premake5 * Automatic and manual build workflows * IDE configuration for VSCode (default) and others * Customizable dashboard module for runtime statistics or visuals @@ -28,7 +30,7 @@ The template handles platform detection, dependency setup, and IDE integration o ## 4. Installation & Setup -### Run Setup Script +### Clone Template Use this template to create your own project, and clone it. @@ -37,6 +39,8 @@ git clone cd ``` +### Run Setup Script + It is recommended to change the `name` of your project in the `config/app_settings.yml`. This can ofcourse be change at any time, as long as the setup script is run afterwards Execute the Python setup script to verify and install missing dependencies, configure the environment, and generate IDE/project files: @@ -46,8 +50,37 @@ python3 setup.py ``` * The script detects your OS (Linux/Windows) and ensures all libraries and tools are available. +* Select your build system when prompted (CMake or Premake5) * Select your IDE when prompted (currently VSCode is supported). + +### Build System Selection + +The template supports two build systems: + +#### CMake (Recommended) +- Modern, widely adopted build system +- Better IDE integration +- More configuration options +- Default selection + +#### Premake5 +- Simple Lua-based configuration +- Fast project generation +- Cross-platform project files + +**Command-line options for build system selection:** +```bash +# Use CMake (skip selection prompt) +python3 setup.py -k + +# Use Premake5 (skip selection prompt) +python3 setup.py -p + +# Interactive selection (default) +python3 setup.py +``` + ## 5. Building the Application ### Automatic Build (VSCode) @@ -58,24 +91,69 @@ If you selected **VSCode** during setup: * Press Ctrl + Shift + B to build the application. * Press F5 to build and launch the application in the debugger. -### Manual Build +### Manual Build - CMake From the project root directory: ```bash -cmake -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug +# Generate build files and build +cmake -B build -DCMAKE_BUILD_TYPE=Debug cmake --build build --parallel 16 + +# Or create build directory manually +mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug +make -j ``` -Create 'build' manually: +### Manual Build - Premake5 + +From the project root directory: ```bash -mkdir build && cd build -cmake .. -make -j +# Generate build files (Linux) +./vendor/premake/premake5 gmake2 + +# Generate build files (Windows) +vendor\premake\premake5.exe gmake2 + +# Build the project +gmake -j + +# Clean build +gmake clean +``` + +## 6. Common Workflows + +### Development Setup +```bash +# CMake with VSCode for debugging +python3 setup.py -k -V -C Debug + +# Premake5 with VSCode +python3 setup.py -p -V -C Debug +``` + +### Release Build +```bash +# Generate release build files without building +python3 setup.py -k -C Release -n + +# Or with Premake5 +python3 setup.py -p -C Release -n +``` + +### Quick Setup +```bash +# CMake with VSCode, generate files only +python3 setup.py -k -V -n + +# Full clean setup (removes previous builds) +python3 setup.py -c -k -V ``` -## 6. Window Manager Integration +## 7. Window Manager Integration If you use a tiling window manager (e.g., `Krohnkite`), ImGui may spawn floating glfw windows with a prefix. Add the following rule to allow floating windows: @@ -85,7 +163,7 @@ ISM - This matches ImGui popup windows by their title prefix. -## 7. Usage +## 8. Usage 'F5' Runs the compiled binary directly or via IDE. The main window displays ImGui controls—customize widgets in `application.cpp`. @@ -94,7 +172,6 @@ The main window displays ImGui controls—customize widgets in `application.cpp` The dashboard files (`dashboard.h` / `dashboard.cpp`) are entry points for adding custom UI panels or runtime metrics. Extend this module by implementing: - ### Lifecycle Methods 1. `dashboard::init()` @@ -130,7 +207,6 @@ The dashboard files (`dashboard.h` / `dashboard.cpp`) are entry points for addin * Clean up resources allocated in `initialize()` (free textures, buffers). * Called on application exit. - ### Long startup process (optional) The template supports a simple, opt-in flow for long initialization/startup work. When enabled, the application will run the dashboard initialization in a separate thread and display a minimal "Initializing..." screen while the work completes. @@ -172,39 +248,7 @@ The UI shown while `dashboard::init()` runs is intentionally minimal and scales ```cpp void dashboard::draw_init_UI(f32 delta_time) { - ImGuiViewport* viewport = ImGui::GetMainViewport(); - ImGui::SetNextWindowPos(viewport->Pos); - ImGui::SetNextWindowSize(viewport->Size); - - ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; - - ImGui::Begin("Initialization", nullptr, window_flags); - { - - const char* text = "Initializing..."; - const float target_font_size = 50.0f; - ImVec2 base_text_size = ImGui::CalcTextSize(text); // Calculate base text size at default font scale - float scale = (base_text_size.y > 0) ? target_font_size / base_text_size.y : 1.0f; // Calculate required scale to reach target font size - ImVec2 available = ImGui::GetContentRegionAvail() * 0.9f; // Get available space with 10% margin - ImVec2 scaled_size = base_text_size * scale; // Calculate scaled text size - - if (scaled_size.x > available.x || scaled_size.y > available.y) { // Adjust scale if needed to fit available space - float width_ratio = available.x / scaled_size.x; - float height_ratio = available.y / scaled_size.y; - scale *= (width_ratio < height_ratio) ? width_ratio : height_ratio; - } - - // Set font scale and calculate final position - ImGui::SetWindowFontScale(scale); - ImVec2 text_size = ImGui::CalcTextSize(text); - ImVec2 position = (ImGui::GetContentRegionAvail() - text_size) * 0.5f; - - ImGui::SetCursorPos(position); - ImGui::TextUnformatted(text); - ImGui::SetWindowFontScale(1.0f); - } - ImGui::End(); + // Overwrite with own UI or leave default } ``` @@ -256,4 +300,4 @@ Contributions welcome! Please fork the repo and submit pull requests against `ma ## License -This project is licensed under the [MIT License](LICENSE). +This project is licensed under the [Apache 2.0 License](LICENSE). diff --git a/setup.py b/setup.py index 9424fe2..07985fb 100644 --- a/setup.py +++ b/setup.py @@ -196,8 +196,7 @@ def main(): # apply_premake_settings() application_name = get_application_name() clean_art_on_build = get_clean_build_artifacts_on_build() - utils.print_info(f"name: {application_name}") - shutil.copy2("./scripts/imgui_CMakeLists.txt", "./vendor/imgui/CMakeLists.txt") # copy template CMake file to correct directory + utils.print_info(f"application name loaded from [.config/app_settings.yml]: {application_name}") # select build system utils.print_u("\nSETUP A BUILD SYSTEM") # Initialize submodule configuration