Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 143 additions & 0 deletions CMake/FlingModule.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Fling build-module helper.
#
# Add a new engine module with a folder (inc/ + src/) and:
#
# fling_add_module(Physics
# PUBLIC_DEPS Core
# PRIVATE_DEPS Gameplay
# )
#
# Public deps propagate include dirs and link libs to consumers.
# Private deps do not. Modules are SHARED by default; pass STATIC for a
# static library (API macros become empty).
#
# Generated ${NAME}API.h (e.g. GraphicsAPI.h / GRAPHICS_API) is written to
# that module's build dir and is PUBLIC, so only linkers of the module see it.
#
# Do not call this until the module's PUBLIC_DEPS / PRIVATE_DEPS targets
# already exist (bottom-up add_subdirectory order). Cycles are a configure error.

set(FLING_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "Path to first-party CMake helpers")

function(fling_add_module NAME)
cmake_parse_arguments(MODULE
"STATIC"
""
"PUBLIC_DEPS;PRIVATE_DEPS;PUBLIC_LIBS;PRIVATE_LIBS"
${ARGN}
)

if(NOT NAME)
message(FATAL_ERROR "fling_add_module() requires a module name")
endif()

string(TOUPPER "${NAME}" MODULE_UPPER)

foreach(dep IN LISTS MODULE_PUBLIC_DEPS MODULE_PRIVATE_DEPS)
if(NOT TARGET "${dep}" AND NOT TARGET "Fling::${dep}")
message(FATAL_ERROR
"fling_add_module(${NAME}): dependency '${dep}' does not exist. "
"Add modules bottom-up (dependencies before dependents).")
endif()

get_property(_dep_all GLOBAL PROPERTY "FLING_MODULE_${dep}_ALL_DEPS")
if(NAME IN_LIST _dep_all)
message(FATAL_ERROR
"Fling module dependency cycle: ${NAME} -> ${dep} -> ... -> ${NAME}")
endif()
endforeach()

set(_all_deps ${MODULE_PUBLIC_DEPS} ${MODULE_PRIVATE_DEPS})
foreach(dep IN LISTS MODULE_PUBLIC_DEPS MODULE_PRIVATE_DEPS)
get_property(_dep_all GLOBAL PROPERTY "FLING_MODULE_${dep}_ALL_DEPS")
list(APPEND _all_deps ${_dep_all})
endforeach()
list(REMOVE_DUPLICATES _all_deps)
set_property(GLOBAL PROPERTY "FLING_MODULE_${NAME}_ALL_DEPS" "${_all_deps}")

set(_module_dir "${CMAKE_CURRENT_SOURCE_DIR}")
file(GLOB_RECURSE _module_sources CONFIGURE_DEPENDS
"${_module_dir}/src/*.cpp"
"${_module_dir}/src/*.h"
"${_module_dir}/src/*.hpp"
"${_module_dir}/src/*.inl"
"${_module_dir}/inc/*.h"
"${_module_dir}/inc/*.hpp"
"${_module_dir}/inc/*.inl"
)

if(NOT _module_sources)
message(FATAL_ERROR "fling_add_module(${NAME}): no sources under ${_module_dir}/inc or src")
endif()

if(MODULE_STATIC)
add_library(${NAME} STATIC ${_module_sources})
else()
add_library(${NAME} SHARED ${_module_sources})
endif()

add_library(Fling::${NAME} ALIAS ${NAME})

set(_gen_dir "${CMAKE_CURRENT_BINARY_DIR}/Generated")
file(MAKE_DIRECTORY "${_gen_dir}")
configure_file(
"${FLING_CMAKE_DIR}/FlingModuleAPI.h.in"
"${_gen_dir}/${NAME}API.h"
@ONLY
)

target_include_directories(${NAME}
PUBLIC
"${_module_dir}/inc"
"${_gen_dir}"
PRIVATE
"${_module_dir}/src"
)

target_compile_definitions(${NAME} PRIVATE "FLING_${MODULE_UPPER}_BUILD=1")
if(MODULE_STATIC)
target_compile_definitions(${NAME} PUBLIC "FLING_${MODULE_UPPER}_STATIC=1")
endif()

set(_public_link)
foreach(dep IN LISTS MODULE_PUBLIC_DEPS)
if(TARGET "Fling::${dep}")
list(APPEND _public_link "Fling::${dep}")
else()
list(APPEND _public_link "${dep}")
endif()
endforeach()

set(_private_link)
foreach(dep IN LISTS MODULE_PRIVATE_DEPS)
if(TARGET "Fling::${dep}")
list(APPEND _private_link "Fling::${dep}")
else()
list(APPEND _private_link "${dep}")
endif()
endforeach()

target_link_libraries(${NAME}
PUBLIC
${_public_link}
${MODULE_PUBLIC_LIBS}
PRIVATE
${_private_link}
${MODULE_PRIVATE_LIBS}
)

set_target_properties(${NAME} PROPERTIES
FOLDER "Fling/Modules"
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
)

if(MSVC)
foreach(_source IN ITEMS ${_module_sources})
get_filename_component(_source_path "${_source}" PATH)
string(REPLACE "${CMAKE_SOURCE_DIR}" "" _group_path "${_source_path}")
string(REPLACE "/" "\\" _group_path "${_group_path}")
source_group("${_group_path}" FILES "${_source}")
endforeach()
endif()
endfunction()
11 changes: 11 additions & 0 deletions CMake/FlingModuleAPI.h.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include "FlingLibExports.h"

#if defined(FLING_@MODULE_UPPER@_STATIC)
# define @MODULE_UPPER@_API
#elif defined(FLING_@MODULE_UPPER@_BUILD)
# define @MODULE_UPPER@_API FLING_LIB_EXPORT
#else
# define @MODULE_UPPER@_API FLING_LIB_IMPORT
#endif
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ message( STATUS "Cmake mod path: " ${CMAKE_MODULE_PATH} )

# Include any .cmake macros here from the ./Cmake dir
include(FlingEngineInc)
include(FlingModule)
include(MSVC_PCH)
include(FlingCompilerFlag)
include (InstallRequiredSystemLibraries)
Expand Down
17 changes: 17 additions & 0 deletions FlingEngine/Core/inc/FlingLibExports.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

/**
* Primitive import/export attributes used by generated per-module *API.h headers.
* Do not use these directly on engine types — use CORE_API, GRAPHICS_API, etc.
*/

#if defined(_WIN32)
# define FLING_LIB_EXPORT __declspec(dllexport)
# define FLING_LIB_IMPORT __declspec(dllimport)
#elif defined(__GNUC__) && (__GNUC__ >= 4)
# define FLING_LIB_EXPORT __attribute__((visibility("default")))
# define FLING_LIB_IMPORT
#else
# define FLING_LIB_EXPORT
# define FLING_LIB_IMPORT
#endif
2 changes: 1 addition & 1 deletion Skills/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Fling Engine uses [Catch2 3](https://github.com/catchorg/Catch2) for first-party
tests. The test target is `FlingTests`, built from `FlingTests/src`, and links the
full `FlingEngine` library (plus `Foundation`), so tests can exercise real engine
full `FlingEngine` library, so tests can exercise real engine
code, not just isolated units.

## Running tests
Expand Down
64 changes: 27 additions & 37 deletions docs/BuildModules.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ monolithic `FlingEngine` library into Unreal-style **build modules** so a system
Vulkan pipeline.

This document is the working design for branch `feature/169-engine-modules`.
Implementation has not started; this file is the spec.
Phase 0 (infrastructure + Core tree) is in progress.

## Locked decisions

Expand Down Expand Up @@ -34,25 +34,20 @@ These are settled. Do not re-open them while implementing.

- Root `CMakeLists.txt` configures options, third-party deps, then adds
`FlingEngine`, `FlingTests`, and `Sandbox`.
- `FlingEngine/CMakeLists.txt` glob-recurses almost every engine source file
into **one** `add_library(FlingEngine ...)` (static `.a` / `.lib`).
- `CMake/FlingEngineInc.cmake` adds **every** engine `inc/` folder to the
include path of anything that uses Fling. Consumers cannot opt out of Graphics.
- There is already a prototype: `FlingEngine/Foundation` is a **SHARED** library
with its own `FOUNDATION_API` macro. It is a stub (`FoundationClass`) and is
still linked into the monolith.
- DLL export today is a single `FLING_API`, toggled by `FLING_EXPORT` inside
`Utils/inc/pch.h`. That cannot scale to per-module exports.
- `pch.h` is **not actually a precompiled header**. `CMake/MSVC_PCH.cmake` is
included but never called, and nothing uses `target_precompile_headers`.
It is a kitchen-sink include parsed from scratch in every TU. It also
`#define`s `FLING_EXPORT` and `F_ENABLE_LOGGING`. Several **public headers**
include it (`Timing.h`, `Version.h`, `FlingWindow.h`, `UniformBufferObject.h`),
which is the opposite of how PCH is supposed to work. Decision: **delete it**.

Folder layout already hints at modules (`Core`, `Graphics`, `Gameplay`,
`Resources`, `Utils`, `Platform`, `Editor`, `Foundation`) but CMake and
includes treat them as one target.
- `FlingEngine/CMakeLists.txt` glob-recurses engine sources into **one**
`add_library(FlingEngine ...)` (static `.a` / `.lib`).
- `CMake/FlingEngineInc.cmake` still adds every remaining engine `inc/` folder
to consumers. Isolation via `target_link_libraries` starts in Phase 1.
- `CMake/FlingModule.cmake` provides `fling_add_module()`; it is not used by a
real shared module yet (Phase 1: Core).
- `Utils/` and `Platform/` have been folded into `FlingEngine/Core/`.
`ImGuiInputBinding.hpp` lives under `Graphics/inc/` (not Core).
- Foundation stub DLL has been deleted.
- DLL export today is still a single `FLING_API`, toggled by `FLING_EXPORT`
inside `Core/inc/pch.h`. Per-module `*_API` macros are generated by
`fling_add_module()` once modules exist.
- `pch.h` is **not actually a precompiled header**. Decision: **delete it**
in Phase 1.

## Goal

Expand Down Expand Up @@ -181,13 +176,10 @@ FlingEngine/Engine/ # created in Phase 3 when Engine.cpp leaves Core

Keep `#include "Logger.h"` style. Do not introduce `Core/Logger.h` prefixes.

`Platform/inc/ImGuiInputBinding.hpp` currently lives with Platform and is
included from `LinuxInput.cpp` / `WindowsInput.cpp`. Moving Platform into
Core would put an ImGui/GLFW-native header in Core. **Do not leave it there
as a Core public header.** During the move, place it under Graphics or Editor
(ImGui is a Graphics/Editor concern). Input `.cpp` files that need it will
have to stop living as Core-only, or the ImGui path becomes a hook Graphics
registers. Resolve this in Phase 0/1; do not give Core a hard ImGui include.
`Graphics/inc/ImGuiInputBinding.hpp` used to live under Platform. Input
`.cpp` files still include it while the engine is a monolith; do not move it
back into Core. Phase 1 must replace that include with a Graphics-registered
hook so Core has no ImGui dependency.

Until Phase 3, `Engine.h` / `Engine.cpp` / `FlingEngine.h` may still live under
`Core/` but they are **not** part of the Core module’s sources once Engine is
Expand Down Expand Up @@ -344,16 +336,14 @@ Work stays on `feature/169-engine-modules`. Each phase should leave

### Phase 0 — Infrastructure + Core tree

- Add `CMake/FlingModule.cmake` with `fling_add_module()` and
`CMake/FlingModuleAPI.h.in`.
- Add `FlingLibExports.h` in Core.
- Physically move `FlingEngine/Utils/**` and `FlingEngine/Platform/**` into
`FlingEngine/Core/inc` and `FlingEngine/Core/src`. Update CMake include
paths. Delete empty Utils/Platform dirs.
- Delete Foundation (sources, CMake target, `Engine.cpp` include).
- Stop globbing the whole engine tree in a way that still picks up moved
files twice.
- Document how to add a module (this file + a short comment on the macro).
Done:

- `CMake/FlingModule.cmake` (`fling_add_module()`) and `CMake/FlingModuleAPI.h.in`.
- `FlingLibExports.h` in Core.
- `Utils/` and `Platform/` moved into `FlingEngine/Core/`.
- `ImGuiInputBinding.hpp` moved to `Graphics/inc/`.
- Foundation stub deleted (`Engine.cpp` include and Sandbox/Tests link removed).
- `FLING_ENGINE_INC()` no longer references deleted Utils/Platform include dirs.

### Phase 1 — Core as a real shared library

Expand Down
Loading