diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7cfe295..b980d84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,8 +30,9 @@ jobs: build-type: Release build-shared: 'ON' cxx-standard: 17 - cc_compiler: clang - cxx_compiler: clang++ + cxx-compiler: clang++ + cxx-flags: '' + cc-compiler: clang compiler-desc: clang os: ubuntu-latest @@ -42,8 +43,9 @@ jobs: build-type: Debug build-shared: 'ON' cxx-standard: 17 - cc_compiler: clang - cxx_compiler: clang++ + cxx-compiler: clang++ + cxx-flags: '' + cc-compiler: clang compiler-desc: clang os: ubuntu-latest @@ -55,6 +57,7 @@ jobs: build-shared: 'ON' cxx-standard: 17 cxx-compiler: g++ + cxx-flags: '' cc-compiler: gcc compiler-desc: gcc os: ubuntu-latest @@ -67,6 +70,7 @@ jobs: build-shared: 'ON' cxx-standard: 17 cxx-compiler: g++ + cxx-flags: '' cc-compiler: gcc compiler-desc: gcc os: ubuntu-latest @@ -99,7 +103,7 @@ jobs: working-directory: _build - name: Test run: | - ctest --build-config ${{ matrix.build_type }} --verbose + ctest --build-config ${{ matrix.build-type }} --verbose working-directory: _build # --------------------------------------------------------------------------- @@ -119,6 +123,7 @@ jobs: build-type: Release build-shared: 'ON' cxx-standard: 17 + cxx-flags: '' os: macos-latest # Debug @@ -127,6 +132,7 @@ jobs: build-shared: 'ON' build-docs: 'OFF' cxx-standard: 17 + cxx-flags: '' os: macos-latest steps: @@ -155,7 +161,7 @@ jobs: working-directory: _build - name: Test run: | - ctest --build-config ${{ matrix.build_type }} --verbose + ctest --build-config ${{ matrix.build-type }} --verbose working-directory: _build # --------------------------------------------------------------------------- @@ -175,6 +181,7 @@ jobs: build-type: Release build-shared: 'ON' cxx-standard: 17 + cxx-flags: '' os: windows-latest # Debug @@ -182,6 +189,7 @@ jobs: build-type: Debug build-shared: 'ON' cxx-standard: 17 + cxx-flags: '' os: windows-latest @@ -217,4 +225,4 @@ jobs: run: | ctest -C ${{ matrix.build-type }} shell: bash - working-directory: _build \ No newline at end of file + working-directory: _build diff --git a/.github/workflows/meson.yml b/.github/workflows/meson.yml new file mode 100644 index 0000000..b653f4e --- /dev/null +++ b/.github/workflows/meson.yml @@ -0,0 +1,145 @@ +name: Meson + +on: + pull_request: + push: + +jobs: + meson-build-and-tests: + runs-on: ${{ matrix.platform }} + name: ${{ matrix.platform }}, ${{ matrix.mode.name }} ${{ matrix.flavor }} + strategy: + fail-fast: false + matrix: + flavor: + - debug + - release + mode: + - name: default + extra_envs: {} + + # Alternative compiler setups + - name: gcc + extra_envs: + CC: gcc + CXX: g++ + - name: clang + extra_envs: + CC: clang + CXX: clang++ + + - name: sanitize + args: >- + "-Db_sanitize=address,undefined" + extra_envs: {} + + # This is for MSVC, which only supports AddressSanitizer. + # https://learn.microsoft.com/en-us/cpp/sanitizers/ + - name: sanitize+asanonly + args: -Db_sanitize=address + extra_envs: + ASAN_OPTIONS: report_globals=0:halt_on_error=1:abort_on_error=1:print_summary=1 + + - name: clang+sanitize + args: >- + "-Db_sanitize=address,undefined" + extra_envs: + CC: clang + CXX: clang++ + + # default clang on GitHub hosted runners is from MSYS2. + # Use Visual Studio supplied clang-cl instead. + - name: clang-cl+sanitize + args: >- + "-Db_sanitize=address,undefined" + extra_envs: + CC: clang-cl + CXX: clang-cl + platform: + - ubuntu-22.04 + - windows-2022 + - macos-latest + + exclude: + # clang-cl only makes sense on windows. + - platform: ubuntu-22.04 + mode: + name: clang-cl+sanitize + - platform: macos-latest + mode: + name: clang-cl+sanitize + + # Use clang-cl instead of MSYS2 clang. + # + # we already tested clang+sanitize on linux, + # if this doesn't work, it should be an issue for MSYS2 team to consider. + - platform: windows-2022 + mode: + name: clang + - platform: windows-2022 + mode: + name: clang+sanitize + + # MSVC-only sanitizers + - platform: ubuntu-22.04 + mode: + name: sanitize+asanonly + - platform: macos-latest + mode: + name: sanitize+asanonly + - platform: windows-2022 + mode: + name: sanitize + + # clang is the default on macos + # also gcc is an alias to clang + - platform: macos-latest + mode: + name: clang + - platform: macos-latest + mode: + name: gcc + + # gcc is the default on linux + - platform: ubuntu-22.04 + mode: + name: gcc + + # only run sanitizer tests on linux + # + # gcc/clang's codegen shouldn't massively change across platforms, + # and linux supports most of the sanitizers. + - platform: macos-latest + mode: + name: clang+sanitize + - platform: macos-latest + mode: + name: sanitize + steps: + - name: Setup meson + run: | + pipx install meson ninja + - name: Checkout + uses: actions/checkout@v4 + - name: Activate MSVC and Configure + if: ${{ matrix.platform == 'windows-2022' }} + env: ${{ matrix.mode.extra_envs }} + run: | + meson setup build-${{ matrix.flavor }} --buildtype=${{ matrix.flavor }} -Ddefault_library=static ${{ matrix.mode.args }} --vsenv + - name: Configuring + if: ${{ matrix.platform != 'windows-2022' }} + env: ${{ matrix.mode.extra_envs }} + run: | + meson setup build-${{ matrix.flavor }} --buildtype=${{ matrix.flavor }} -Db_lundef=false ${{ matrix.mode.args }} + - name: Building + run: | + meson compile -C build-${{ matrix.flavor }} + - name: Running tests + env: ${{ matrix.mode.extra_envs }} + run: | + meson test -C build-${{ matrix.flavor }} --timeout-multiplier 0 + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: ${{ matrix.platform }}-${{ matrix.mode.name }}-${{ matrix.flavor }}-logs + path: build-${{ matrix.flavor }}/meson-logs diff --git a/CMakeLists.txt b/CMakeLists.txt index 758b20a..595a262 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.5) -project(pystring CXX) +project(pystring LANGUAGES CXX VERSION 1.1.4) option (BUILD_SHARED_LIBS "Build shared libraries (set to OFF to build static libs)" ON) @@ -7,6 +7,10 @@ add_library(pystring pystring.cpp pystring.h ) +set_target_properties(pystring PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} +) add_executable (pystring_test test.cpp) TARGET_LINK_LIBRARIES (pystring_test pystring) diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..db5f121 --- /dev/null +++ b/meson.build @@ -0,0 +1,46 @@ +project( + 'pystring', + 'cpp', + version: '1.1.4', + license: 'BSD-3-Clause', + license_files: 'LICENSE', + meson_version: '>=1.3', + default_options: ['cpp_std=c++17,c++11', 'warning_level=3'], +) + +inc = include_directories('.') + +srcs = files('pystring.cpp') +hdrs = files('pystring.h') + +pystring_lib = library( + 'pystring', + srcs, + implicit_include_directories: false, + include_directories: inc, + version: meson.project_version(), + install: true, +) +pystring_dep = declare_dependency( + link_with: pystring_lib, + include_directories: inc, +) +meson.override_dependency('pystring', pystring_dep) + +test( + 'PyStringTest', + executable( + 'pystring_test', + 'test.cpp', + dependencies: pystring_dep, + build_by_default: false, + ), +) + +install_headers(hdrs, subdir: 'pystring') + +pkgconfig = import('pkgconfig') +pkgconfig.generate( + pystring_lib, + description: 'C++ functions matching the interface and behavior of python string methods with std::string', +) diff --git a/unittest.h b/unittest.h index 536d9cb..7412029 100644 --- a/unittest.h +++ b/unittest.h @@ -23,11 +23,11 @@ struct PYSTRINGTest PYSTRINGTestFunc function; }; -typedef std::vector UnitTests; +typedef std::vector UnitTests; UnitTests& GetUnitTests(); -struct AddTest { AddTest(PYSTRINGTest* test); }; +struct AddTest { AddTest(PYSTRINGTest&& test); }; /// PYSTRING_CHECK_* macros checks if the conditions is met, and if not, /// prints an error message indicating the module and line where the @@ -102,22 +102,22 @@ struct AddTest { AddTest(PYSTRINGTest* test); }; #define PYSTRING_ADD_TEST(group, name) \ static void pystringtest_##group##_##name(); \ - AddTest pystringaddtest_##group##_##name(new PYSTRINGTest(#group, #name, pystringtest_##group##_##name)); \ + AddTest pystringaddtest_##group##_##name(PYSTRINGTest(#group, #name, pystringtest_##group##_##name)); \ static void pystringtest_##group##_##name() #define PYSTRING_TEST_SETUP() \ int unit_test_failures = 0 #define PYSTRING_TEST_APP(app) \ - std::vector& GetUnitTests() { \ - static std::vector pystring_unit_tests; \ + std::vector& GetUnitTests() { \ + static std::vector pystring_unit_tests; \ return pystring_unit_tests; } \ - AddTest::AddTest(PYSTRINGTest* test){GetUnitTests().push_back(test);}; \ + AddTest::AddTest(PYSTRINGTest&& test){GetUnitTests().emplace_back(test);}; \ PYSTRING_TEST_SETUP(); \ int main(int, char **) { std::cerr << "\n" << #app <<"\n\n"; \ for(size_t i = 0; i < GetUnitTests().size(); ++i) { \ - int _tmp = unit_test_failures; GetUnitTests()[i]->function(); \ - std::cerr << "Test [" << GetUnitTests()[i]->group << "] [" << GetUnitTests()[i]->name << "] - "; \ + int _tmp = unit_test_failures; GetUnitTests()[i].function(); \ + std::cerr << "Test [" << GetUnitTests()[i].group << "] [" << GetUnitTests()[i].name << "] - "; \ std::cerr << (_tmp == unit_test_failures ? "PASSED" : "FAILED") << "\n"; } \ std::cerr << "\n" << unit_test_failures << " tests failed\n\n"; \ return unit_test_failures; }