diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3b6c5df..41056eb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -193,7 +193,7 @@ jobs: matrix: # Build each combination of OS and release/debug variants os: [ windows-2019 ] - msystem: [ ucrt64, mingw64 ] + msystem: [ ucrt64, mingw64, clang64 ] build-type: [ Release, Debug ] include: - msystem: ucrt64 @@ -202,6 +202,10 @@ jobs: - msystem: mingw64 package-prefix: x86_64 cmake-flags: LDFLAGS="-fuse-ld=lld -lstdc++ -lgcc_s" + - msystem: clang64 + package-prefix: clang-x86_64 + cmake-flags: LDFLAGS="-lc++" + ctest-flags: -E UnexpectedException* # Don't abort runners if a single one fails fail-fast: false runs-on: ${{ matrix.os }} @@ -220,7 +224,7 @@ jobs: run: | mkdir build cd build - ${{ matrix.cmake-flags }} cmake .. -DTESTS=ON -DCMAKE_C_COMPILER="clang" -DCMAKE_CXX_COMPILER="clang" -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} + ${{ matrix.cmake-flags }} cmake .. -DTESTS=ON -DCMAKE_C_COMPILER="clang" -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} - name: Build working-directory: build run: | @@ -228,8 +232,15 @@ jobs: - name: Test working-directory: build run: | - ctest -j 4 --output-on-failure -T test - + ctest -j 4 --output-on-failure -T test ${{ matrix.ctest-flags }} + - name: Install + working-directory: build + run: | + cmake --install . --prefix=../dist + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.msystem }}-${{ matrix.build-type }} + path: dist/ # Fake check that can be used as a branch-protection rule. all-checks: diff --git a/CMakeLists.txt b/CMakeLists.txt index 3000da5..f68b014 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,13 @@ endif() enable_language(OBJC OBJCXX) +if (MINGW) + set(CMAKE_IMPORT_LIBRARY_SUFFIX ".dll.a") + set(CMAKE_LINK_LIBRARY_SUFFIX "") + set(CMAKE_SHARED_LIBRARY_PREFIX "lib") + set(CMAKE_OBJCXX_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) +endif () + INCLUDE (CheckCXXSourceCompiles) INCLUDE (FetchContent) @@ -301,6 +308,9 @@ if (NOT CMAKE_INSTALL_LIBDIR) set(CMAKE_INSTALL_LIBDIR lib) endif () +if (NOT CMAKE_INSTALL_BINDIR) + set(CMAKE_INSTALL_BINDIR bin) +endif () set(GNUSTEP_INSTALL_TYPE ${DEFAULT_INSTALL_TYPE} CACHE STRING "GNUstep installation type. Options are NONE, SYSTEM, NETWORK or LOCAL.") diff --git a/objcxx_eh.cc b/objcxx_eh.cc index f8c0f6d..757de78 100644 --- a/objcxx_eh.cc +++ b/objcxx_eh.cc @@ -8,6 +8,12 @@ typedef struct objc_object* id; #include "objc/runtime.h" #include "objc/objc-arc.h" +#ifndef DEBUG_EXCEPTIONS +#define DEBUG_LOG(...) +#else +#define DEBUG_LOG(str, ...) fprintf(stderr, str, ## __VA_ARGS__) +#endif + /** * Helper function that has a custom personality function. * This calls `cxx_throw` and has a destructor that must be run. We intercept @@ -295,10 +301,18 @@ namespace gnustep /* libc++-abi does not have __is_pointer_p and won't do the double dereference * required to get the object pointer. We need to do it ourselves if we have * caught an exception with libc++'s exception class. */ +#ifndef __MINGW32__ if (cxx_exception_class == llvm_cxx_exception_class) { return **(id**)obj; } return *(id*)obj; +#else +#ifdef _LIBCPP_VERSION + return **(id**)obj; +#else + return *(id*)obj; +#endif // _LIBCPP_VERSION +#endif // __MINGW32__ } }; @@ -355,14 +369,17 @@ bool gnustep::libobjc::__objc_id_type_info::__do_catch(const type_info *thrownTy // Id catch matches any ObjC throw if (dynamic_cast(thrownType)) { - *obj = *(id*)obj; + *obj = dereference_thrown_object_pointer(obj); + DEBUG_LOG("gnustep::libobjc::__objc_id_type_info::__do_catch caught 0x%x\n", *obj); return true; } if (dynamic_cast(thrownType)) { - *obj = *(id*)obj; + *obj = dereference_thrown_object_pointer(obj); + DEBUG_LOG("gnustep::libobjc::__objc_id_type_info::__do_catch caught 0x%x\n", *obj); return true; } + DEBUG_LOG("gnustep::libobjc::__objc_id_type_info::__do_catch returning false\n"); return false; }; @@ -494,6 +511,7 @@ extern "C" void test_cxx_eh_implementation() #else static void eh_cleanup(void *exception) { + DEBUG_LOG("eh_cleanup: Releasing 0x%x\n", *(id*)exception); objc_release(*(id*)exception); } @@ -504,6 +522,7 @@ void objc_exception_throw(id object) id *exc = (id *)__cxa_allocate_exception(sizeof(id)); *exc = object; objc_retain(object); + DEBUG_LOG("objc_exception_throw: Throwing 0x%x\n", *exc); __cxa_throw(exc, & __objc_id_type_info, eh_cleanup); } #endif