From 9565ce7cf82f00ffd94bce9bd6dbb02f1e549764 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Mon, 20 Jul 2026 00:02:35 -0400 Subject: [PATCH 1/8] Fix and test C++ module usage --- .github/workflows/Tests.yml | 26 ++++++++++++++++++ README.md | 53 ++++++++++++++++++++++++++++++++++--- examples/CMakeLists.txt | 12 +++++++++ examples/module/main.cpp | 29 ++++++++++++++++++++ modules/CMakeLists.txt | 48 ++++++++++++++++++++++++++------- 5 files changed, 154 insertions(+), 14 deletions(-) create mode 100644 examples/module/main.cpp diff --git a/.github/workflows/Tests.yml b/.github/workflows/Tests.yml index 1410da0d..159f44cd 100644 --- a/.github/workflows/Tests.yml +++ b/.github/workflows/Tests.yml @@ -57,3 +57,29 @@ jobs: - name: Test if: runner.os == 'Linux' run: ctest --verbose --test-dir build + + # Verify the C++20 module target (`import raylib;`) builds. Module + # dependency scanning requires the Ninja generator and a scan-capable + # compiler (LLVM Clang here), so this uses its own job. + modules: + name: C++20 Modules (Ninja Clang) + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install Dependencies + run: sudo apt-get update && sudo apt-get install -y ninja-build clang-18 clang-tools-18 libasound2-dev libx11-dev libxrandr-dev libxi-dev libgl1-mesa-dev libglu1-mesa-dev libxcursor-dev libxinerama-dev + + - name: Configure + run: > + cmake -B build -S . -G Ninja + -DCMAKE_C_COMPILER=clang-18 + -DCMAKE_CXX_COMPILER=clang++-18 + -DBUILD_RAYLIB_CPP_MODULES=ON + -DCMAKE_CXX_STANDARD=20 + -DGLFW_BUILD_WAYLAND=OFF + -DCMAKE_BUILD_TYPE=Release + + - name: Build modules + run: cmake --build build --target raylib_cpp_modules module diff --git a/README.md b/README.md index c812969f..54097891 100644 --- a/README.md +++ b/README.md @@ -255,12 +255,12 @@ raylib::Vector2 newDirection = direction.Rotate(30); ### Modules -If using C++20 or later, by passing `BUILD_RAYLIB_CPP_MODULES` to the build system the library may be imported as a module by using `import raylib;`. +If using C++20 or later, enabling `BUILD_RAYLIB_CPP_MODULES` lets the library be imported as a C++ module with `import raylib;`. Link against the `raylib_cpp_modules` target instead of `raylib_cpp`. ```cpp import raylib; -using raylib::Texture; +using raylib::Color; using raylib::Window; int main() { @@ -268,12 +268,57 @@ int main() { int screenHeight = 450; Window window(screenWidth, screenHeight, "raylib-cpp - basic window"); - Texture logo("raylib_logo.png"); - // ... + while (!window.ShouldClose()) { + window.BeginDrawing(); + window.ClearBackground(raylib::Colors::RAYWHITE); + raylib::DrawText("Imported raylib as a module!", 120, 200, 20, Color::LightGray()); + window.EndDrawing(); + } + + return 0; } ``` +#### Requirements + +C++ modules rely on CMake's dependency-scanning support, so the whole tool-chain (including the consuming project) must satisfy all of the following: + +* **CMake 3.28 or newer.** +* **A scanning-capable generator: Ninja, Ninja Multi-Config, or Visual Studio 17.4+.** The Makefile generators — the default on macOS and Linux, and what CLion uses unless changed — cannot scan for modules and produce the error *"the compiler does not provide a way to discover the import graph dependencies"*. Reconfigure with `-G Ninja`. +* **A compiler with module scanning: LLVM Clang 16+, MSVC 19.34+, or GCC 14+.** Apple Clang does not expose `clang-scan-deps` in a way CMake detects; install and select LLVM Clang (e.g. via Homebrew) instead. +* **C++20 or newer** for every target that does `import raylib;` (this also enables `CMAKE_CXX_SCAN_FOR_MODULES` by default). + +#### Consuming with FetchContent + +```cmake +cmake_minimum_required(VERSION 3.28) +project(example CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include(FetchContent) +FetchContent_Declare(raylib + GIT_REPOSITORY https://github.com/raysan5/raylib.git + GIT_TAG 5.5) +FetchContent_Declare(raylib_cpp + GIT_REPOSITORY https://github.com/RobLoach/raylib-cpp.git + GIT_TAG v6.0.2) +set(BUILD_RAYLIB_CPP_MODULES ON) +FetchContent_MakeAvailable(raylib raylib_cpp) + +add_executable(example main.cpp) +target_link_libraries(example PRIVATE raylib_cpp_modules) +``` + +Configure it with a supporting generator and compiler: + +```sh +cmake -B build -G Ninja -DCMAKE_CXX_COMPILER=clang++ +cmake --build build +``` + ## Getting Started *raylib-cpp* is a header-only library. This means in order to use it, you must link your project to [raylib](https://www.raylib.com/), and then include [`raylib-cpp.hpp`](raylib-cpp/include/raylib-cpp.hpp). diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d65ac409..a0dd38ab 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -58,5 +58,17 @@ endforeach() add_executable("multiple" multiple/main.cpp multiple/Player.cpp) target_link_libraries("multiple" PUBLIC raylib_cpp raylib) +# C++20 modules example: only built when modules are enabled and the +# raylib_cpp_modules target was created (CMake 3.28+). +if(BUILD_RAYLIB_CPP_MODULES AND TARGET raylib_cpp_modules) + add_executable("module" module/main.cpp) + target_link_libraries("module" PRIVATE raylib_cpp_modules) + set_target_properties("module" PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF + ) +endif() + # Copy all the resources file(COPY ${example_resources} DESTINATION "resources/") diff --git a/examples/module/main.cpp b/examples/module/main.cpp new file mode 100644 index 00000000..dfeaa59f --- /dev/null +++ b/examples/module/main.cpp @@ -0,0 +1,29 @@ +/** + * raylib-cpp example using C++20 modules. + * + * Build with modules enabled (requires the Ninja or Visual Studio generator + * and a compiler that can scan for module dependencies): + * + * cmake -B build -G Ninja -DBUILD_RAYLIB_CPP_MODULES=ON -DCMAKE_CXX_STANDARD=20 + * cmake --build build --target module + */ +import raylib; + +using raylib::Color; +using raylib::Window; + +int main() { + int screenWidth = 800; + int screenHeight = 450; + + Window window(screenWidth, screenHeight, "raylib-cpp - modules example"); + + while (!window.ShouldClose()) { + window.BeginDrawing(); + window.ClearBackground(raylib::Colors::RAYWHITE); + raylib::DrawText("Congrats! You imported raylib as a module!", 120, 200, 20, Color::LightGray()); + window.EndDrawing(); + } + + return 0; +} diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 6b2eff04..a28d738a 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -1,17 +1,43 @@ -file(GLOB_RECURSE RAYLIB_CPP_MODULES raylib.cppm) +# raylib-cpp C++ module target (`import raylib;`). +# +# Consuming this target requires a tool-chain that can scan for C++ module +# dependencies: +# * CMake 3.28 or newer. +# * A generator that supports module dependency scanning: Ninja, +# Ninja Multi-Config, or Visual Studio 17.4+. The Makefile generators +# (including the default on macOS/Linux) CANNOT scan for modules. +# * A compiler with scanning support: Clang 16+ (LLVM, not Apple Clang), +# MSVC 19.34+, or GCC 14+. +# +# When these requirements are not met CMake reports the cryptic error +# "the compiler does not provide a way to discover the import graph +# dependencies"; the checks below turn that into an actionable message. -add_library(raylib_cpp_modules) +if(CMAKE_VERSION VERSION_LESS 3.28) + message(WARNING + "raylib-cpp: C++ modules require CMake 3.28 or newer (found " + "${CMAKE_VERSION}). Skipping the raylib_cpp_modules target.") + return() +endif() + +# Module dependency scanning is only implemented for the Ninja and +# Visual Studio generators. +if(NOT CMAKE_GENERATOR MATCHES "Ninja|Visual Studio") + message(WARNING + "raylib-cpp: building C++ modules requires the Ninja or Visual Studio " + "generator; the '${CMAKE_GENERATOR}' generator cannot discover module " + "import dependencies. Reconfigure with '-G Ninja' to use 'import raylib;'.") +endif() -cmake_minimum_required(VERSION 3.28) +add_library(raylib_cpp_modules STATIC) +# Allow a parent project to customise how the module sources are attached. if(NOT COMMAND configure_cpp_module_target) function(configure_cpp_module_target target) - if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.28) - target_sources(${target} PUBLIC FILE_SET CXX_MODULES FILES ${RAYLIB_CPP_MODULES}) - else() - message(WARNING "C++ modules require CMake 3.28+. Using standard compilation.") - target_sources(${target} PRIVATE ${RAYLIB_CPP_MODULES}) - endif() + target_sources(${target} + PUBLIC + FILE_SET CXX_MODULES FILES ${CMAKE_CURRENT_SOURCE_DIR}/raylib.cppm + ) endfunction() endif() @@ -28,4 +54,6 @@ target_include_directories(raylib_cpp_modules ${PROJECT_SOURCE_DIR}/include ) -target_compile_features(raylib_cpp_modules PUBLIC cxx_std_20) \ No newline at end of file +# C++ modules require at least C++20; propagate the requirement to consumers +# so that module scanning is enabled for targets that `import raylib;`. +target_compile_features(raylib_cpp_modules PUBLIC cxx_std_20) From 159db6bc862db0c814610c96f2f0d3fe9e591dbb Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Mon, 20 Jul 2026 00:06:49 -0400 Subject: [PATCH 2/8] Fix stale GetRay module export --- modules/raylib.cppm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/raylib.cppm b/modules/raylib.cppm index e0903f86..0d8e662a 100644 --- a/modules/raylib.cppm +++ b/modules/raylib.cppm @@ -229,7 +229,7 @@ export namespace raylib { using raylib::Mouse::GetTouchX; using raylib::Mouse::GetTouchY; using raylib::Mouse::GetTouchPosition; - using raylib::Mouse::GetRay; + using raylib::Mouse::GetScreenToWorldRay; } /** From fecec4005793e485b1dedc1ea569bac8a1af989b Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Mon, 20 Jul 2026 00:11:22 -0400 Subject: [PATCH 3/8] Enable module scanning on example target --- examples/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a0dd38ab..b03accf1 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -67,6 +67,9 @@ if(BUILD_RAYLIB_CPP_MODULES AND TARGET raylib_cpp_modules) CXX_STANDARD 20 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF + # The examples directory defaults to C++11, so module scanning is not + # enabled for this target automatically; turn it on explicitly. + CXX_SCAN_FOR_MODULES ON ) endif() From b931d59d4dcdbe5b4d4ed33e95447e60e4f86ba1 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Mon, 20 Jul 2026 00:15:48 -0400 Subject: [PATCH 4/8] Match module extension flags in example --- examples/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b03accf1..40f1a5df 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -66,7 +66,10 @@ if(BUILD_RAYLIB_CPP_MODULES AND TARGET raylib_cpp_modules) set_target_properties("module" PROPERTIES CXX_STANDARD 20 CXX_STANDARD_REQUIRED ON - CXX_EXTENSIONS OFF + # Match raylib_cpp_modules' language flags: the compiled module (BMI) + # can only be imported by a consumer built with the same C++ standard + # and extension settings, so keep the default extensions here. + CXX_EXTENSIONS ON # The examples directory defaults to C++11, so module scanning is not # enabled for this target automatically; turn it on explicitly. CXX_SCAN_FOR_MODULES ON From 6271bf7c08302b0a5f64d150e94e9c275eba8d35 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Mon, 20 Jul 2026 00:26:19 -0400 Subject: [PATCH 5/8] Apply suggestion from @RobLoach --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 54097891..78d52309 100644 --- a/README.md +++ b/README.md @@ -285,8 +285,8 @@ int main() { C++ modules rely on CMake's dependency-scanning support, so the whole tool-chain (including the consuming project) must satisfy all of the following: * **CMake 3.28 or newer.** -* **A scanning-capable generator: Ninja, Ninja Multi-Config, or Visual Studio 17.4+.** The Makefile generators — the default on macOS and Linux, and what CLion uses unless changed — cannot scan for modules and produce the error *"the compiler does not provide a way to discover the import graph dependencies"*. Reconfigure with `-G Ninja`. -* **A compiler with module scanning: LLVM Clang 16+, MSVC 19.34+, or GCC 14+.** Apple Clang does not expose `clang-scan-deps` in a way CMake detects; install and select LLVM Clang (e.g. via Homebrew) instead. +* **Scanning Generator: Ninja, Ninja Multi-Config, or Visual Studio 17.4+ +* **Module-compatible Compiler: LLVM Clang 16+, MSVC 19.34+, or GCC 14+ * **C++20 or newer** for every target that does `import raylib;` (this also enables `CMAKE_CXX_SCAN_FOR_MODULES` by default). #### Consuming with FetchContent From 1a776f3b663750700a36b26d88f548a4222a785a Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Mon, 20 Jul 2026 00:28:01 -0400 Subject: [PATCH 6/8] Apply suggestion from @RobLoach --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 78d52309..220115a3 100644 --- a/README.md +++ b/README.md @@ -287,7 +287,8 @@ C++ modules rely on CMake's dependency-scanning support, so the whole tool-chain * **CMake 3.28 or newer.** * **Scanning Generator: Ninja, Ninja Multi-Config, or Visual Studio 17.4+ * **Module-compatible Compiler: LLVM Clang 16+, MSVC 19.34+, or GCC 14+ -* **C++20 or newer** for every target that does `import raylib;` (this also enables `CMAKE_CXX_SCAN_FOR_MODULES` by default). +* **C++20 or newer.** +* ``` #### Consuming with FetchContent From dc92cb745333a6d21b116ebe70b75014dd7681f3 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Mon, 20 Jul 2026 00:29:56 -0400 Subject: [PATCH 7/8] Apply suggestion from @RobLoach --- modules/CMakeLists.txt | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index a28d738a..ad81a0e6 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -1,17 +1,9 @@ # raylib-cpp C++ module target (`import raylib;`). # -# Consuming this target requires a tool-chain that can scan for C++ module -# dependencies: -# * CMake 3.28 or newer. -# * A generator that supports module dependency scanning: Ninja, -# Ninja Multi-Config, or Visual Studio 17.4+. The Makefile generators -# (including the default on macOS/Linux) CANNOT scan for modules. -# * A compiler with scanning support: Clang 16+ (LLVM, not Apple Clang), -# MSVC 19.34+, or GCC 14+. -# -# When these requirements are not met CMake reports the cryptic error -# "the compiler does not provide a way to discover the import graph -# dependencies"; the checks below turn that into an actionable message. +# Requirements +# - CMake 3.28+ +# - Module dependency scanning generator, like Ninja, VS17.4+ +# - Compiler with scanning support, like CLang (16+, MSVC 19.34+ or GCC 14+ if(CMAKE_VERSION VERSION_LESS 3.28) message(WARNING From 7f401e02bdfec6f25a794c18e1010b961ca058a7 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Mon, 20 Jul 2026 00:31:01 -0400 Subject: [PATCH 8/8] Apply suggestion from @RobLoach --- README.md | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/README.md b/README.md index 220115a3..d0f42958 100644 --- a/README.md +++ b/README.md @@ -280,46 +280,6 @@ int main() { } ``` -#### Requirements - -C++ modules rely on CMake's dependency-scanning support, so the whole tool-chain (including the consuming project) must satisfy all of the following: - -* **CMake 3.28 or newer.** -* **Scanning Generator: Ninja, Ninja Multi-Config, or Visual Studio 17.4+ -* **Module-compatible Compiler: LLVM Clang 16+, MSVC 19.34+, or GCC 14+ -* **C++20 or newer.** -* ``` - -#### Consuming with FetchContent - -```cmake -cmake_minimum_required(VERSION 3.28) -project(example CXX) - -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -include(FetchContent) -FetchContent_Declare(raylib - GIT_REPOSITORY https://github.com/raysan5/raylib.git - GIT_TAG 5.5) -FetchContent_Declare(raylib_cpp - GIT_REPOSITORY https://github.com/RobLoach/raylib-cpp.git - GIT_TAG v6.0.2) -set(BUILD_RAYLIB_CPP_MODULES ON) -FetchContent_MakeAvailable(raylib raylib_cpp) - -add_executable(example main.cpp) -target_link_libraries(example PRIVATE raylib_cpp_modules) -``` - -Configure it with a supporting generator and compiler: - -```sh -cmake -B build -G Ninja -DCMAKE_CXX_COMPILER=clang++ -cmake --build build -``` - ## Getting Started *raylib-cpp* is a header-only library. This means in order to use it, you must link your project to [raylib](https://www.raylib.com/), and then include [`raylib-cpp.hpp`](raylib-cpp/include/raylib-cpp.hpp).