diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7fd05a33..b64895f3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,12 +37,21 @@ jobs: run: | sudo apt-get update -y sudo apt-get install -y \ - build-essential gcc-14 g++-14 ninja-build \ + build-essential ninja-build wget lsb-release software-properties-common gnupg \ libgl1-mesa-dev libglew-dev libglfw3-dev \ libpng-dev libopenal-dev libluajit-5.1-dev \ libserialport-dev libsndfile1-dev \ xorg-dev libxkbcommon-dev libwayland-dev wayland-protocols + - name: Install LLVM/Clang 22 + run: | + # Noble ships Clang 18, whose C++20 module support is not good enough + # for this tree; apt.llvm.org has current releases. + wget -qO /tmp/llvm.sh https://apt.llvm.org/llvm.sh + chmod +x /tmp/llvm.sh + sudo /tmp/llvm.sh 22 + sudo apt-get install -y clang-tools-22 # clang-scan-deps, needed to scan modules + - name: Build current OpenAL Soft run: | git clone --depth 1 --branch 1.24.2 https://github.com/kcat/openal-soft.git /tmp/openal-soft @@ -52,28 +61,19 @@ jobs: sudo cmake --install /tmp/openal-soft/build sudo ldconfig - # A little bit of magic for unbreaking GCC. Not an issue for Clang and MSVC. - # Fix for specific hard-errors for a combo of: varargs and always_inline - - name: Patch GLM for GCC - run: | - sed -i 's/GLM_FUNC_QUALIFIER std::string format(const char\* message, \.\.\.)/inline std::string format(const char* message, ...)/' \ - ref/glm/glm/gtx/string_cast.inl - grep -n "std::string format(const char\* message" ref/glm/glm/gtx/string_cast.inl - - name: Install SonarQube Cloud Build Wrapper uses: SonarSource/sonarqube-scan-action/install-build-wrapper@fd88b7d7ccbaefd23d8f36f73b59db7a3d246602 # v6.0.0 - name: Configure (CMake) env: - # C++20 named modules need GCC 14+; noble's default build-essential is GCC 13 - CC: gcc-14 - CXX: g++-14 + CC: clang-22 + CXX: clang++-22 run: | cmake -S . -B build -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DWITH_BETTER_RENDERER=OFF \ -DWITH_ZMQ=OFF -DWITH_OPENVR=OFF -DUSE_LTO=OFF \ - -DCMAKE_CXX_FLAGS="-Wno-attributes -fno-inline-functions-called-once" \ + -DCMAKE_CXX_FLAGS="-Wno-attributes" \ -DPython3_EXECUTABLE="$(which python3)" - name: Build under Build Wrapper diff --git a/.github/workflows/build_bin.yml b/.github/workflows/build_bin.yml index 485cfc4b..9219ed6d 100644 --- a/.github/workflows/build_bin.yml +++ b/.github/workflows/build_bin.yml @@ -149,7 +149,7 @@ jobs: sudo apt-get update sudo apt-get install -y \ - build-essential gcc-14 g++-14 ninja-build \ + build-essential ninja-build wget lsb-release software-properties-common gnupg \ libgl1-mesa-dev \ libglew-dev \ libglfw3-dev \ @@ -163,6 +163,15 @@ jobs: libwayland-dev \ wayland-protocols + - name: Install LLVM/Clang 22 + run: | + # Noble ships Clang 18, whose C++20 module support is not good enough + # for this tree; apt.llvm.org has current releases. + wget -qO /tmp/llvm.sh https://apt.llvm.org/llvm.sh + chmod +x /tmp/llvm.sh + sudo /tmp/llvm.sh 22 + sudo apt-get install -y clang-tools-22 # clang-scan-deps, needed to scan modules + # # Existing MaSzyna CI already builds OpenAL Soft 1.24.2, # so retain that instead of relying only on Ubuntu's package. @@ -193,17 +202,16 @@ jobs: - name: Show environment run: | - gcc-14 --version - g++-14 --version + clang-22 --version + clang-scan-deps-22 --version ninja --version cmake --version python --version - name: Configure env: - # C++20 named modules need GCC 14+; noble's default build-essential is GCC 13 - CC: gcc-14 - CXX: g++-14 + CC: clang-22 + CXX: clang++-22 run: | cmake \ -S . \ @@ -215,7 +223,7 @@ jobs: -DWITH_OPENVR=OFF \ -DUSE_LTO=OFF \ -DPython3_EXECUTABLE="${{ steps.python.outputs.python-path }}" \ - -DCMAKE_CXX_FLAGS="-Wno-attributes -fno-inline-functions-called-once" + -DCMAKE_CXX_FLAGS="-Wno-attributes" - name: Build run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e6ec765..9e984853 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -483,14 +483,13 @@ target_sources(${PROJECT_NAME} set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF) -# GCC's lazy loading of module interfaces trips over the simulation-core partition -# ("failed to load pendings" / "Bad file data" while reading eu07.simcore:dynobj). -# Loading eagerly avoids it; drop this once the compiler bug is fixed. -# GCC 16's lazy loading of module interfaces is broken for this project: reading -# eu07.simcore:dynobj gives "Bad file data", and eu07.glm gives "recursive lazy -# load" / "failed to load pendings for glm::vec". Eager loading is the only way -# through, and it costs roughly twice the memory per compiler process. -# Drop both this and the job pool below once the compiler bug is fixed. +# Clang is the compiler this project is built and tested with (Clang 22 in CI); +# it needs none of the workarounds below. GCC 16 still builds the tree, but only +# with eager module loading: its lazy loading is broken here, reading +# eu07.simcore:dynobj gives "Bad file data" and eu07.glm gives "recursive lazy +# load" / "failed to load pendings for glm::vec". Eager loading costs roughly +# twice the memory per compiler process. Drop this and the job pool below once +# the compiler bug is fixed. if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") target_compile_options(${PROJECT_NAME} PRIVATE -fno-module-lazy) diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 85c29b81..2ccfd2b3 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -1,4 +1,5 @@ module; +#include #include #include #include diff --git a/McZapkie/Oerlikon_ESt.cpp b/McZapkie/Oerlikon_ESt.cpp index 0516fdd9..26438a9c 100644 --- a/McZapkie/Oerlikon_ESt.cpp +++ b/McZapkie/Oerlikon_ESt.cpp @@ -1,4 +1,5 @@ module; +#include #include #include #include diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index bf4a9ecd..b85f975a 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -1,4 +1,5 @@ module; +#include #include #include #include diff --git a/application/driverhints.cpp b/application/driverhints.cpp index e66dfcd9..7eec0c20 100644 --- a/application/driverhints.cpp +++ b/application/driverhints.cpp @@ -1,4 +1,7 @@ module; +#include +#include +#include #include #include #include "utilities/Globals_macros.h" diff --git a/application/editoruipanels.cpp b/application/editoruipanels.cpp index def3b095..ca76338f 100644 --- a/application/editoruipanels.cpp +++ b/application/editoruipanels.cpp @@ -1,4 +1,5 @@ module; +#include #include #include #include diff --git a/model/MdlMngr.cpp b/model/MdlMngr.cpp index 6c0631a2..61ffd708 100644 --- a/model/MdlMngr.cpp +++ b/model/MdlMngr.cpp @@ -1,4 +1,5 @@ module; +#include #include #include #include diff --git a/rendering/particles.cppm b/rendering/particles.cppm index ec7e99cb..cc9e7fc4 100644 --- a/rendering/particles.cppm +++ b/rendering/particles.cppm @@ -213,6 +213,8 @@ private: +} // export -- out-of-line member definitions are not namespace-scope +// declarations, so they cannot carry `export`; the class itself is exported. template void fixedstep_modifier::update( Type_ &Variable, double const Timedelta ) const { @@ -251,4 +253,5 @@ fixedstep_modifier::deserialize( cParser &Input ) { } } +export { } // export diff --git a/scene/scenenodegroups.cpp b/scene/scenenodegroups.cpp index ebd92b94..7fc65b36 100644 --- a/scene/scenenodegroups.cpp +++ b/scene/scenenodegroups.cpp @@ -12,6 +12,7 @@ module; #include "global_include/interfaces/ITexture_macros.h" module eu07.scene.scenenodegroups; +import eu07.glm; import eu07.simulation.simulation; import eu07.utilities.globals; import eu07.simcore; diff --git a/scripting/ladderlogic.cpp b/scripting/ladderlogic.cpp index 86464853..b07a746b 100644 --- a/scripting/ladderlogic.cpp +++ b/scripting/ladderlogic.cpp @@ -1,4 +1,5 @@ module; +#include #include #include "utilities/utilities_macros.h" #include diff --git a/utilities/Float3d.cppm b/utilities/Float3d.cppm index dd7c1092..37220154 100644 --- a/utilities/Float3d.cppm +++ b/utilities/Float3d.cppm @@ -121,7 +121,7 @@ export inline float Dot(const float4 &q1, const float4 &q2); export inline float4 &operator*=(float4 &v1, float const d); export inline float4 Slerp(const float4 &q0, const float4 &q1, float t); export inline float3 operator*(const float4x4 &m, const float3 &v); -inline glm::vec3 operator*(const float4x4 &m, const glm::vec3 &v); +export inline glm::vec3 operator*(const float4x4 &m, const glm::vec3 &v); export inline float4x4 operator*(const float4x4 &m1, const float4x4 &m2); export inline float Det2x2(float a, float b, float c, float d); export inline float Det3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3); @@ -302,7 +302,7 @@ export inline float3 operator*(const float4x4 &m, const float3 &v) { v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + m[3][2]); } -inline glm::vec3 operator*(const float4x4 &m, const glm::vec3 &v) { +export inline glm::vec3 operator*(const float4x4 &m, const glm::vec3 &v) { return glm::vec3( v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + m[3][0], v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + m[3][1], diff --git a/utilities/Globals.cppm b/utilities/Globals.cppm index f7113fb2..703205fa 100644 --- a/utilities/Globals.cppm +++ b/utilities/Globals.cppm @@ -385,6 +385,8 @@ struct global_settings { export_as_text( std::ostream &Output, std::string const Key, Type_ const &Value ) const; }; +} // export -- out-of-line member definitions are not namespace-scope +// declarations, so they cannot carry `export`; the class itself is exported. template void global_settings::export_as_text( std::ostream &Output, std::string const Key, Type_ const &Value ) const { @@ -392,9 +394,6 @@ global_settings::export_as_text( std::ostream &Output, std::string const Key, Ty Output << Key << " " << Value << "\n"; } -} // export -- out-of-line member definitions and explicit -// specialisations are not namespace-scope declarations, so they cannot -// carry `export`; the class itself is exported and that is what counts. template <> void global_settings::export_as_text( std::ostream &Output, std::string const Key, std::string const &Value ) const; diff --git a/utilities/parser.cpp b/utilities/parser.cpp index 55517579..7aad5b54 100644 --- a/utilities/parser.cpp +++ b/utilities/parser.cpp @@ -1,4 +1,5 @@ module; +#include #include "utilities/Globals_macros.h" #include #include diff --git a/vehicle/Driver.cppm b/vehicle/Driver.cppm index 4ffc765d..2fe66fc8 100644 --- a/vehicle/Driver.cppm +++ b/vehicle/Driver.cppm @@ -659,6 +659,9 @@ public: std::string OwnerName() const; }; +} // export -- out-of-line member definitions are not namespace-scope +// declarations, so they cannot carry `export`; the class itself is exported. + inline TOrders TController::OrderCurrentGet() const { return OrderList[ OrderPos ]; } @@ -667,4 +670,5 @@ inline TOrders TController::OrderNextGet() const { return OrderList[ OrderPos + 1 ]; } +export { } // export diff --git a/world/Event.cppm b/world/Event.cppm index 362621fa..a6004cf3 100644 --- a/world/Event.cppm +++ b/world/Event.cppm @@ -736,6 +736,8 @@ private: +} // export -- out-of-line member definitions are not namespace-scope +// declarations, so they cannot carry `export`; the class itself is exported. inline void basic_event::group( scene::group_handle Group ) { @@ -762,6 +764,7 @@ basic_event::init_targets( TableType_ &Repository, std::string const &Targettype } } +export { //--------------------------------------------------------------------------- } // export diff --git a/world/Segment.cpp b/world/Segment.cpp index 4e8c0b2e..42ba8167 100644 --- a/world/Segment.cpp +++ b/world/Segment.cpp @@ -1,4 +1,5 @@ module; +#include #include #include #include diff --git a/world/Track.cpp b/world/Track.cpp index f872f052..d4ee9fa3 100644 --- a/world/Track.cpp +++ b/world/Track.cpp @@ -1,4 +1,5 @@ module; +#include #include "glad/glad.h" #include #include diff --git a/world/TrkFoll.cpp b/world/TrkFoll.cpp index 043fd67b..a4894daf 100644 --- a/world/TrkFoll.cpp +++ b/world/TrkFoll.cpp @@ -1,4 +1,5 @@ module; +#include #include #include "utilities/Globals_macros.h" #include "vehicle/DynObj_macros.h"