diff --git a/.github/workflows/ecode-nightly.yml b/.github/workflows/ecode-nightly.yml index 40e158dd0..f4308da4e 100644 --- a/.github/workflows/ecode-nightly.yml +++ b/.github/workflows/ecode-nightly.yml @@ -52,14 +52,14 @@ jobs: container: image: ubuntu:20.04 env: - CC: gcc - CXX: g++ + CC: clang-20 + CXX: clang++-20 steps: - name: Install essentials run: | export DEBIAN_FRONTEND=noninteractive apt-get update - apt-get install -y --no-install-recommends software-properties-common build-essential git ca-certificates + apt-get install -y --no-install-recommends software-properties-common build-essential git ca-certificates wget lsb-release gnupg - name: Checkout Code uses: actions/checkout@v6 with: { fetch-depth: 0, submodules: 'recursive', set-safe-directory: true } @@ -77,44 +77,30 @@ jobs: - name: Install dependencies shell: bash run: | - apt-get install -y curl libfuse2 fuse premake4 mesa-common-dev libgl1-mesa-dev sudo file appstream + apt-get install -y curl libfuse2 fuse premake4 mesa-common-dev libgl1-mesa-dev sudo file appstream libdw-dev curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - apt-get install -y nodejs add-apt-repository -y universe add-apt-repository -y multiverse - SUCCESS=false - for i in {1..3}; do - echo "Attempt $i: Adding PPA via Launchpad API..." - if timeout 30s sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; then - SUCCESS=true - echo "Successfully added PPA." - break - fi - echo "Launchpad API failed or timed out. Retrying in 5 seconds..." - sleep 5 - done + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + ./llvm.sh 20 - if [ "$SUCCESS" = false ]; then - echo "add-apt-repository failed 3 times. Executing manual fallback..." - . /etc/os-release - echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu $VERSION_CODENAME main" | sudo tee /etc/apt/sources.list.d/ubuntu-toolchain-r-fallback.list - sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 60C317803A41BA51845E371A1E9377A2BA9EF27F || true - fi + apt-get install -y libc++-20-dev libc++abi-20-dev + + update-alternatives --install /usr/bin/cc cc /usr/bin/clang-20 30 + update-alternatives --set cc /usr/bin/clang-20 + update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-20 30 + update-alternatives --set c++ /usr/bin/clang++-20 - sudo apt-get update - apt-get install -y gcc-13 g++-13 libdw-dev - update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 10 - update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 10 - update-alternatives --install /usr/bin/cc cc /usr/bin/gcc 30 - update-alternatives --set cc /usr/bin/gcc - update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 30 - update-alternatives --set c++ /usr/bin/g++ - update-alternatives --config gcc - update-alternatives --config g++ bash projects/linux/scripts/install_sdl2.sh - name: Build ecode run: | + export CC="clang-20" + export CXX="clang++-20 -stdlib=libc++" + export LDFLAGS="-stdlib=libc++" + bash projects/linux/ecode/build.app.sh --with-static-cpp --version ${{ env.INSTALL_REF }} --arch ${{ matrix.config.arch }} - name: Upload Files uses: softprops/action-gh-release@v3 diff --git a/include/eepp/system/color.hpp b/include/eepp/system/color.hpp index b4e2c97fb..e518e5f82 100644 --- a/include/eepp/system/color.hpp +++ b/include/eepp/system/color.hpp @@ -406,7 +406,7 @@ class EE_API Color : public tColor { static void initColorMap(); - template + template static bool isColorStringT( StringType str, bool searchColorNames ); }; diff --git a/include/eepp/system/functionstring.hpp b/include/eepp/system/functionstring.hpp index 3ce0f169e..b789a758f 100644 --- a/include/eepp/system/functionstring.hpp +++ b/include/eepp/system/functionstring.hpp @@ -5,13 +5,8 @@ #include #include -#include #include -template -concept AllowedFunctionString = - std::same_as || std::same_as; - namespace EE { namespace System { class EE_API FunctionString { @@ -19,10 +14,14 @@ class EE_API FunctionString { using Parameters = SmallVector; using TypeStringVector = SmallVector; + static FunctionString parse( const std::string& function ); + static FunctionString parse( std::string_view function ); static FunctionString parse( String::View function ); + FunctionString() {} + FunctionString( const std::string& name, const Parameters& parameters, const TypeStringVector& typeStringData ); @@ -42,7 +41,7 @@ class EE_API FunctionString { Parameters parameters; TypeStringVector typeStringData; - template static FunctionString parse( StringType function ); + template static FunctionString parse( StringType function ); }; }} // namespace EE::System diff --git a/include/eepp/ui/css/stylesheetspecification.hpp b/include/eepp/ui/css/stylesheetspecification.hpp index e52540971..e8fa730f0 100644 --- a/include/eepp/ui/css/stylesheetspecification.hpp +++ b/include/eepp/ui/css/stylesheetspecification.hpp @@ -22,7 +22,7 @@ typedef std::function +template bool Color::isColorStringT( StringType str, bool searchColorNames ) { if ( str.empty() ) return false; diff --git a/src/eepp/system/functionstring.cpp b/src/eepp/system/functionstring.cpp index 53f8a211b..42c2d962a 100644 --- a/src/eepp/system/functionstring.cpp +++ b/src/eepp/system/functionstring.cpp @@ -2,13 +2,12 @@ #include #include -#include #include +#include namespace EE { namespace System { -template -FunctionString FunctionString::parse( StringType function ) { +template FunctionString FunctionString::parse( StringType function ) { using CharType = typename StringType::value_type; size_t funcSep = function.find( '(' ); @@ -35,7 +34,7 @@ FunctionString FunctionString::parse( StringType function ) { int parenDepth = 0; auto pushBufferToParams = [&]() { - if constexpr ( std::same_as ) { + if constexpr ( std::is_same_v ) { if ( !currentParamIsString ) String::trimInPlace( buffer ); funcParameters.push_back( buffer ); @@ -109,13 +108,17 @@ FunctionString FunctionString::parse( StringType function ) { if ( !buffer.empty() || currentParamIsString ) pushBufferToParams(); - if constexpr ( std::same_as ) { + if constexpr ( std::is_same_v ) { return FunctionString( std::string{ funcName }, funcParameters, typeStringData ); } else { return FunctionString( String( funcName ).toUtf8(), funcParameters, typeStringData ); } } +FunctionString FunctionString::parse( const std::string& function ) { + return parse( std::string_view{ function } ); +} + FunctionString FunctionString::parse( std::string_view function ) { return parse( function ); } diff --git a/src/tests/unit_tests/uitextnode_tests.cpp b/src/tests/unit_tests/uitextnode_tests.cpp index 5029048c0..575e53c64 100644 --- a/src/tests/unit_tests/uitextnode_tests.cpp +++ b/src/tests/unit_tests/uitextnode_tests.cpp @@ -189,9 +189,9 @@ UTEST( UITextNode_CSSSelectors, EmptyWithTextNodes ) { ASSERT_TRUE( rtEmpty != nullptr ); // rtText has a text node child → NOT empty - EXPECT_FALSE( emptySel.selector( rtText, 0, 0, FunctionString::parse( "" ) ) ); + EXPECT_FALSE( emptySel.selector( rtText, 0, 0, FunctionString() ) ); // rtEmpty has no children → empty - EXPECT_TRUE( emptySel.selector( rtEmpty, 0, 0, FunctionString::parse( "" ) ) ); + EXPECT_TRUE( emptySel.selector( rtEmpty, 0, 0, FunctionString() ) ); destroyRichTextScene( sceneNode ); } @@ -220,8 +220,8 @@ UTEST( UITextNode_CSSSelectors, FirstChildWithTextNodes ) { ASSERT_TRUE( elem0 != nullptr ); ASSERT_TRUE( elem1 != nullptr ); - EXPECT_TRUE( sel.selector( elem0, 0, 0, FunctionString::parse( "" ) ) ); - EXPECT_FALSE( sel.selector( elem1, 0, 0, FunctionString::parse( "" ) ) ); + EXPECT_TRUE( sel.selector( elem0, 0, 0, FunctionString() ) ); + EXPECT_FALSE( sel.selector( elem1, 0, 0, FunctionString() ) ); destroyRichTextScene( sceneNode ); } @@ -250,8 +250,8 @@ UTEST( UITextNode_CSSSelectors, LastChildWithTextNodes ) { ASSERT_TRUE( elem0 != nullptr ); ASSERT_TRUE( elem1 != nullptr ); - EXPECT_FALSE( sel.selector( elem0, 0, 0, FunctionString::parse( "" ) ) ); - EXPECT_TRUE( sel.selector( elem1, 0, 0, FunctionString::parse( "" ) ) ); + EXPECT_FALSE( sel.selector( elem0, 0, 0, FunctionString() ) ); + EXPECT_TRUE( sel.selector( elem1, 0, 0, FunctionString() ) ); destroyRichTextScene( sceneNode ); } @@ -279,7 +279,7 @@ UTEST( UITextNode_CSSSelectors, OnlyChildWithTextNodes ) { ASSERT_TRUE( elem0 != nullptr ); // Text nodes are invisible → elem0 IS the only element child - EXPECT_TRUE( sel.selector( elem0, 0, 0, FunctionString::parse( "" ) ) ); + EXPECT_TRUE( sel.selector( elem0, 0, 0, FunctionString() ) ); destroyRichTextScene( sceneNode ); } @@ -311,9 +311,9 @@ UTEST( UITextNode_CSSSelectors, FirstOfTypeWithTextNodes ) { Node* br0 = sceneNode->find( "br0" ); ASSERT_TRUE( br0 != nullptr ); - EXPECT_TRUE( sel.selector( span0, 0, 0, FunctionString::parse( "" ) ) ); - EXPECT_FALSE( sel.selector( span1, 0, 0, FunctionString::parse( "" ) ) ); - EXPECT_TRUE( sel.selector( static_cast( br0 ), 0, 0, FunctionString::parse( "" ) ) ); + EXPECT_TRUE( sel.selector( span0, 0, 0, FunctionString() ) ); + EXPECT_FALSE( sel.selector( span1, 0, 0, FunctionString() ) ); + EXPECT_TRUE( sel.selector( static_cast( br0 ), 0, 0, FunctionString() ) ); destroyRichTextScene( sceneNode ); } @@ -411,8 +411,8 @@ UTEST( UITextNode_CSSSelectors, OnlyOfTypeWithTextNodes ) { ASSERT_TRUE( br0 != nullptr ); // Each is the only one of its C++ type - EXPECT_TRUE( sel.selector( span0, 0, 0, FunctionString::parse( "" ) ) ); - EXPECT_TRUE( sel.selector( static_cast( br0 ), 0, 0, FunctionString::parse( "" ) ) ); + EXPECT_TRUE( sel.selector( span0, 0, 0, FunctionString() ) ); + EXPECT_TRUE( sel.selector( static_cast( br0 ), 0, 0, FunctionString() ) ); destroyRichTextScene( sceneNode ); } @@ -443,9 +443,9 @@ UTEST( UITextNode_CSSSelectors, LastOfTypeWithTextNodes ) { Node* br0 = sceneNode->find( "br0" ); ASSERT_TRUE( br0 != nullptr ); - EXPECT_FALSE( sel.selector( span0, 0, 0, FunctionString::parse( "" ) ) ); - EXPECT_TRUE( sel.selector( span1, 0, 0, FunctionString::parse( "" ) ) ); - EXPECT_TRUE( sel.selector( static_cast( br0 ), 0, 0, FunctionString::parse( "" ) ) ); + EXPECT_FALSE( sel.selector( span0, 0, 0, FunctionString() ) ); + EXPECT_TRUE( sel.selector( span1, 0, 0, FunctionString() ) ); + EXPECT_TRUE( sel.selector( static_cast( br0 ), 0, 0, FunctionString() ) ); destroyRichTextScene( sceneNode ); } @@ -1048,7 +1048,7 @@ UTEST( UITextNode_Regression, ElementCountingDoesNotCountDeletedNodes ) { ASSERT_TRUE( elem0 != nullptr ); // elem0 is first element child (text node skipped) - EXPECT_TRUE( sel.selector( elem0, 0, 0, FunctionString::parse( "" ) ) ); + EXPECT_TRUE( sel.selector( elem0, 0, 0, FunctionString() ) ); destroyRichTextScene( sceneNode ); } @@ -1078,14 +1078,14 @@ UTEST( UITextNode_Regression, OnlyOfTypeStaysCorrectAfterModification ) { ASSERT_TRUE( br0 != nullptr ); // Each is only-of-type - EXPECT_TRUE( sel.selector( span0, 0, 0, FunctionString::parse( "" ) ) ); - EXPECT_TRUE( sel.selector( static_cast( br0 ), 0, 0, FunctionString::parse( "" ) ) ); + EXPECT_TRUE( sel.selector( span0, 0, 0, FunctionString() ) ); + EXPECT_TRUE( sel.selector( static_cast( br0 ), 0, 0, FunctionString() ) ); // Remove br0 → span0 still only-of-type br0->detach(); eeDelete( br0 ); - EXPECT_TRUE( sel.selector( span0, 0, 0, FunctionString::parse( "" ) ) ); + EXPECT_TRUE( sel.selector( span0, 0, 0, FunctionString() ) ); destroyRichTextScene( sceneNode ); }