libobjc2
libobjc2 copied to clipboard
Add support for MinGW
These are some first steps to add support for MinGW, which was outlined by David as follows:
- Make libobjc2 build in a MinGW environment (and add MinGW to the test matrix eventually, though not until we’ve had a new LLVM release).
- Make it build the *NIX version of the exception handling code, not the Windows version, when targeting MinGW.
- Add a __gnustep_objc_personality_seh0 that calls _GCC_specific_handler, passing __gnustep_objc_personality_v0 as the last parameter (see: https://reviews.llvm.org/D49638).
- Modify clang using the patch to only use Windows native exceptions with an MSVC target triple and to use __gnustep_objc_personality_seh0 instead of the Windows C++ exception handler.
These patches do 1–3 above, including adding MinGW to CI using MSYS2 and the latest official Clang 11 from MSYS2 packages. This allows building the DLL in an MinGW environment, although building the tests currently expectantly fails on CI with the following errors (other tests involving exceptions fail with the same linker errors minus the vtable one):
FAILED: Test/ObjCXXEHInterop.exe
cmd.exe /C "cd . && D:\a\msys64\mingw64\bin\clang.exe -Xclang -fexceptions -Xclang -fobjc-exceptions -O0 -Xclang -fno-inline -g -fuse-ld=lld Test/CMakeFiles/test_runtime.dir/Test.m.obj Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.mm.obj Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.m.obj -o Test\ObjCXXEHInterop.exe -Wl,--major-image-version,0,--minor-image-version,0 libobjc.dll.a -lstdc++ -lgcc_s -lgcc_s -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
lld-link: error: undefined symbol: objc_exception_throw
>>> referenced by ../Test\ObjCXXEHInterop.mm:33
>>> Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.mm.obj:(poke_objcxx)
>>> referenced by ../Test\ObjCXXEHInterop.m:10
>>> Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.m.obj:(rethrow)
lld-link: error: undefined symbol: vtable for gnustep::libobjc::__objc_class_type_info
>>> referenced by Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.mm.obj:(.weak.__objc_eh_typeinfo_Test.default.check_uncaught_count)
lld-link: error: undefined symbol: objc_begin_catch
>>> referenced by ../Test\ObjCXXEHInterop.m:19
>>> Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.m.obj:(main)
lld-link: error: undefined symbol: objc_end_catch
>>> referenced by ../Test\ObjCXXEHInterop.m:21
>>> Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.m.obj:(main)
>>> referenced by ../Test\ObjCXXEHInterop.m:21
>>> Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.m.obj:(main)
I’m unsure about the vtable issue, but I think fixing the other missing symbols requires patching Clang. I’m basically just running blind here as I have no knowledge of Clang internals, but I tried the following patch based on David’s patches sent on the mailing list, replacing EHPersonality::MSVC_CxxFrameHandler3 with EHPersonality::GNU_ObjC_SEH.
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -2137,8 +2137,7 @@
ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) {
msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend");
- usesSEHExceptions =
- cgm.getContext().getTargetInfo().getTriple().isWindowsMSVCEnvironment();
+ usesSEHExceptions = cgm.getLangOpts().SEHExceptions;
CodeGenTypes &Types = CGM.getTypes();
IntTy = cast<llvm::IntegerType>(
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -142,6 +142,8 @@
case ObjCRuntime::WatchOS:
return EHPersonality::NeXT_ObjC;
case ObjCRuntime::GNUstep:
+ if (L.SEHExceptions)
+ return EHPersonality::GNU_ObjC_SEH;
if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
return EHPersonality::GNUstep_ObjC;
LLVM_FALLTHROUGH;
@@ -194,6 +196,8 @@
return getObjCPersonality(Target, L);
case ObjCRuntime::GNUstep:
+ if (L.SEHExceptions)
+ return EHPersonality::GNU_ObjC_SEH;
return EHPersonality::GNU_ObjCXX;
// The GCC runtime's personality function inherently doesn't support
This fixes the objc_begin_catch/objc_end_catch errors, but not objc_exception_throw and adds some new errors involving the standard library:
FAILED: Test/ObjCXXEHInterop.exe
cmd.exe /C "cd . && C:\msys64\mingw64\bin\clang.exe -Xclang -fexceptions -Xclang -fobjc-exceptions -fuse-ld=lld Test/CMakeFiles/test_runtime.dir/Test.m.obj Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.mm.obj Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.m.obj -o Test\ObjCXXEHInterop.exe -Wl,--major-image-version,0,--minor-image-version,0 libobjc.dll.a C:/msys64/usr/lib/libm.a -lstdc++ -lgcc_s -lgcc_s -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
lld-link: error: undefined symbol: objc_exception_throw
>>> referenced by Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.mm.obj:(poke_objcxx)
>>> referenced by Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.m.obj:(rethrow)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
[138/214] Linking C executable Test\objc_msgSend.exe
FAILED: Test/objc_msgSend.exe
cmd.exe /C "cd . && C:\msys64\mingw64\bin\clang.exe -Xclang -fexceptions -Xclang -fobjc-exceptions -fuse-ld=lld Test/CMakeFiles/test_runtime.dir/Test.m.obj Test/CMakeFiles/objc_msgSend.dir/objc_msgSend.m.obj -o Test\objc_msgSend.exe -Wl,--major-image-version,0,--minor-image-version,0 libobjc.dll.a C:/msys64/usr/lib/libm.a -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
lld-link: error: undefined symbol: objc_exception_throw
>>> referenced by Test/CMakeFiles/objc_msgSend.dir/objc_msgSend.m.obj:(_c_MsgTest__initialize)
lld-link: error: undefined symbol: vtable for __cxxabiv1::__class_type_info
>>> referenced by Test/CMakeFiles/objc_msgSend.dir/objc_msgSend.m.obj:(typeinfo for objc_object)
lld-link: error: undefined symbol: vtable for __cxxabiv1::__pointer_type_info
>>> referenced by Test/CMakeFiles/objc_msgSend.dir/objc_msgSend.m.obj:(typeinfo for objc_object*)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
[141/214] Linking C executable Test\NilException.exe
Note that the above is using libstdc++. I’m not sure if that’s what we want to use here – I also tried using libc++, which required some patching for the typeinfo test to work, but this resulted in the following errors linking the DLL:
FAILED: libobjc.dll libobjc.dll.a
cmd.exe /C "cd . && C:\msys64\mingw64\bin\clang.exe -Xclang -fexceptions -Xclang -fobjc-exceptions -fuse-ld=lld -shared -o libobjc.dll -Wl,--out-implib,libobjc.dll.a -Wl,--major-image-version,0,--minor-image-version,0 CMakeFiles/objc.dir/alias_table.c.obj CMakeFiles/objc.dir/block_to_imp.c.obj CMakeFiles/objc.dir/caps.c.obj CMakeFiles/objc.dir/category_loader.c.obj CMakeFiles/objc.dir/class_table.c.obj CMakeFiles/objc.dir/dtable.c.obj CMakeFiles/objc.dir/encoding2.c.obj CMakeFiles/objc.dir/hooks.c.obj CMakeFiles/objc.dir/ivar.c.obj CMakeFiles/objc.dir/loader.c.obj CMakeFiles/objc.dir/mutation.m.obj CMakeFiles/objc.dir/protocol.c.obj CMakeFiles/objc.dir/runtime.c.obj CMakeFiles/objc.dir/sarray2.c.obj CMakeFiles/objc.dir/selector_table.c.obj CMakeFiles/objc.dir/sendmsg2.c.obj CMakeFiles/objc.dir/eh_personality.c.obj CMakeFiles/objc.dir/block_trampolines.S.obj CMakeFiles/objc.dir/objc_msgSend.S.obj CMakeFiles/objc.dir/eh_trampoline.s.obj CMakeFiles/objc.dir/NSBlocks.m.obj CMakeFiles/objc.dir/Protocol2.m.obj CMakeFiles/objc.dir/associate.m.obj CMakeFiles/objc.dir/blocks_runtime.m.obj CMakeFiles/objc.dir/properties.m.obj CMakeFiles/objc.dir/gc_none.c.obj CMakeFiles/objc.dir/arc.mm.obj CMakeFiles/objc.dir/objcxx_eh.cc.obj -Wl,-Bstatic -lc++abi -Wl,-Bdynamic C:/msys64/usr/lib/libm.a -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
lld-link: error: undefined symbol: operator delete(void*)
>>> referenced by CMakeFiles/objc.dir/arc.mm.obj:(objc_storeWeak)
>>> referenced by CMakeFiles/objc.dir/arc.mm.obj:(incrementWeakRefCount(objc_object*))
>>> referenced by CMakeFiles/objc.dir/arc.mm.obj:(objc_loadWeakRetained)
>>> referenced 96 more times
lld-link: error: undefined symbol: operator new(unsigned long long)
>>> referenced by CMakeFiles/objc.dir/arc.mm.obj:(incrementWeakRefCount(objc_object*))
lld-link: error: undefined symbol: std::__1::__libcpp_execute_once(void**, void (*)())
>>> referenced by libc++abi.a(cxa_exception_storage.cpp.obj):(__cxa_get_globals)
>>> referenced by libc++abi.a(cxa_exception_storage.cpp.obj):(__cxa_get_globals_fast)
lld-link: error: undefined symbol: std::__1::__libcpp_tls_get(long)
>>> referenced by libc++abi.a(cxa_exception_storage.cpp.obj):(__cxa_get_globals)
>>> referenced by libc++abi.a(cxa_exception_storage.cpp.obj):(__cxa_get_globals_fast)
lld-link: error: undefined symbol: std::__1::__libcpp_tls_set(long, void*)
>>> referenced by libc++abi.a(cxa_exception_storage.cpp.obj):(__cxa_get_globals)
>>> referenced by libc++abi.a(cxa_exception_storage.cpp.obj):(__cxxabiv1::(anonymous namespace)::destruct_(void*))
lld-link: error: undefined symbol: std::__1::__libcpp_tls_create(long*, void (*)(void*))
>>> referenced by libc++abi.a(cxa_exception_storage.cpp.obj):(__cxxabiv1::(anonymous namespace)::construct_())
lld-link: error: undefined symbol: std::__1::__libcpp_mutex_lock(void**)
>>> referenced by libc++abi.a(cxa_guard.cpp.obj):(__cxa_guard_acquire)
>>> referenced by libc++abi.a(cxa_guard.cpp.obj):(__cxa_guard_release)
>>> referenced by libc++abi.a(cxa_guard.cpp.obj):(__cxa_guard_abort)
>>> referenced 4 more times
lld-link: error: undefined symbol: std::__1::__libcpp_condvar_wait(void**, void**)
>>> referenced by libc++abi.a(cxa_guard.cpp.obj):(__cxa_guard_acquire)
lld-link: error: undefined symbol: std::__1::__libcpp_mutex_unlock(void**)
>>> referenced by libc++abi.a(cxa_guard.cpp.obj):(__cxa_guard_acquire)
>>> referenced by libc++abi.a(cxa_guard.cpp.obj):(__cxa_guard_acquire)
>>> referenced by libc++abi.a(cxa_guard.cpp.obj):(__cxa_guard_release)
>>> referenced 5 more times
lld-link: error: undefined symbol: std::__1::__libcpp_condvar_broadcast(void**)
>>> referenced by libc++abi.a(cxa_guard.cpp.obj):(__cxa_guard_release)
>>> referenced by libc++abi.a(cxa_guard.cpp.obj):(__cxa_guard_abort)
I’d very much appreciate your further input @davidchisnall.
Thanks, I hope to get to this at the weekend.
Please can you add some instructions for how to build with MinGW? I have installed msys2 from choco and started the msys2 shell. I have run:
$ pacman --needed -S mingw-w64-x86_64-cmake
$ pacman --needed -S mingw-w64-x86_64-ninja
These seem to have worked (running them again tells me that these things are already installed) but cmake is not in my path and neither is ninja. I can't test or work on this if I can't build it.
So far my experience with MinGW makes me absolutely loath it. It's painfully slow, it doesn't let me use a modern terminal, and it is incredibly badly documented.
Yeah the documentation is definitely lacking. The thing to know is that there are three subsystems with mostly separate binaries and installation paths: MSYS, mingw32, and mingw64. Since you installed the 64-bit packages they will only be available in the mingw64 environment. This page has a bit more info about this: https://www.msys2.org/wiki/MSYS2-introduction/
You'll want to launch a mingw64 shell by running e.g.:
<msys-root>/msys2_shell.cmd -defterm -mingw64 -here
And then run cmake and ninja there.
If you use the MSYS2 installer you'll get Start menu launchers for the different shells. You can also add the different shells to Windows Terminal: https://www.msys2.org/docs/terminals/
(In the CI script, to avoid further branching I'm running CMake directly in the native CMD shell, but it picks up the right clang binary because I added the mingw64 bin directory to the path. ninja needs the bash shell tho to run some of the scripts, so it's easiest to just run everything from the MinGW shell.)
Hope that helps! Thanks for giving it a try and please let me know if you need more info.
At the moment, I have a small time window each weekend when I can spare the time to work on this. I still can't build it. Please can you provide me with step-by-step instructions for building with a freshly built LLVM? I now have the MinGW shell working and CMake runs. I need to invoke it with:
cmake .. -G Ninja -DCMAKE_C_COMPILER=${LLVM_BUILD_PATH}/bin/clang.exe -DCMAKE_CXX_COMPILER=${LLVM_BUILD_PATH}/bin/clang++.exe -DCMAKE_RC_COMPILER=${LLVM_BUILD_PATH}/bin/llvm-rc.exe -DCMAKE_SHARED_LINKER_FLAGS='-fuse-ld=lld' -DCMAKE_EXE_LINKER_FLAGS='-fuse-ld=lld'
I now get a load of link failures for things like malloc and other libc symbols. It's also missing symbols for _DllMainCRTStartup and __acrt_iob_func, so it looks as if we're not linking the C runtime? I thought MinGW did that automatically. Do I need some MinGW-specific patches to LLVM to be able to build? If so, where do I find those (is there a git branch I can grab for my LLVM source tree)?
A bit more poking and it turns out that CMake isn't passing a MinGW triple. I (try to) fix that by adding this to my CMake invocation:
-DCMAKE_C_FLAGS='-target x86_64-pc-mingw64' -DCMAKE_CXX_FLAGS='-target x86_64-pc-mingw64'
Now it fails to compile because it can't find sys/types.h. Which, apparently, isn't in my MinGW install at all:
$ find / -name types.h
/mingw64/include/brotli/types.h
I am trying to minimise my stress levels this year, after a particularly stressful 2020. I have now reached my limit in frustration with this for today and am going to step away from my computer. I'll have another try next weekend. If you can provide me with instructions that I can use for building and testing it with an LLVM that I have built from source, using the normal LLVM build process for Windows, then I will be able to make the required clang changes.
Thank you very much for looking into this further, I am sorry this is not so straightforward.
I’ll try to get you step-by-step instructions for building Clang main with the MinGW Clang patches by next weekend. I had previously built the MinGW Clang package directly (using makepkg), which applies these patches automatically, but for the purposes of working on Clang sources I can see you’ll want to use the normal LLVM build process instead.
The libobjc2 library needs to be buildable under MSYS2. I would very much like to get clang working WITHOUT, I REPEAT WITHOUT using Visual Studio or any MS tools in any way, shape, or form.
The libobjc2 library needs to be buildable under MSYS2. I would very much like to get clang working WITHOUT, I REPEAT WITHOUT using Visual Studio or any MS tools in any way, shape, or form.
I really hate to keep emphasizing this!
The libobjc2 library needs to be buildable under MSYS2. I would very much like to get clang working WITHOUT, I REPEAT WITHOUT using Visual Studio or any MS tools in any way, shape, or form.
I really hate to keep emphasizing this!
Then please don't. You are contributing nothing to the discussion other than demands for unpaid volunteers to do work that you think is important.
The libobjc2 library needs to be buildable under MSYS2. I would very much like to get clang working WITHOUT, I REPEAT WITHOUT using Visual Studio or any MS tools in any way, shape, or form.
I really hate to keep emphasizing this!
Then please don't. You are contributing nothing to the discussion other than demands for unpaid volunteers to do work that you think is important.
David,
My sincere apologies if you thought I was asking for that. I had simply thought that it was something that would be easy for you to do.
I will create a branch and work on some changes which will make it possible to build on the MSYS2 command line. I may have questions for you along these lines. While working purely in Visual Studio is a nice idea I would still like for it to be possible to build from the MSYS2 command line. I will let you know when the changes are ready for review.
Yours... GC
Greg, thanks for your offer to help with this. I just want to make sure we’re all on the same page here: were you taking about a libobjc2 or LLVM branch you want to work on?
This libobjc2 branch mingw should already contain all necessary changes for building it under MSYS2/MinGW, including adding this configuration to CI using MSYS2.
The outstanding issue is the ObjC runtime support in Clang needing changes to work with MinGW. In order for David to be able to look into this, we need to figure out how to build LLVM with the MinGW patches in such a way that he can work on it. Last time I tried this I got an error "number of sections exceeded object file", but I’m planning to look into this further.
So instead of trying to compile LLVM with the MinGW patches, I’ve tried to get the standard Clang to use the MinGW ABI and made a bit of progress here.
First, one needs to make sure to use the "normal" Windows Ninja, not the one from MinGW as it will choke on Windows paths. If you installed LLVM and Ninja via Chocolatey just add their directories to your path in the MinGW shell:
export PATH="$PATH:/c/Program Files/LLVM/bin:/c/ProgramData/chocolatey/bin"
Then we tell CMake to use the x86_64-w64-mingw64 target triple, the MinGW sysroot, and tell it to use libc++:
cmake .. -G Ninja -DTESTS=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_ASM_COMPILER=clang \
-DCMAKE_SHARED_LINKER_FLAGS='-fuse-ld=lld' -DCMAKE_EXE_LINKER_FLAGS='-fuse-ld=lld' \
-DCMAKE_C_COMPILER_TARGET=x86_64-w64-mingw64 -DCMAKE_CXX_COMPILER_TARGET=x86_64-w64-mingw64 -DCMAKE_ASM_COMPILER_TARGET=x86_64-w64-mingw64 \
-DCMAKE_SYSROOT=/mingw64 \
-DCMAKE_CXX_FLAGS=-stdlib=libc++
The remaining problem I have is that the try_compile for typeinfo_test.cc is failing, so no C++ runtime is detected:
[2/4] Building CXX object
CMakeFiles/test_cxx_runtime.dir/typeinfo_test.cc.obj
[3/4] Linking C executable test_cxx_runtime.exe
FAILED: test_cxx_runtime.exe
cmd.exe /C "cd . && C:\PROGRA~1\LLVM\bin\clang.exe
--target=x86_64-w64-mingw64 --sysroot=C:/msys64/mingw64
-fuse-ld=lld CMakeFiles/test_cxx_runtime.dir/typeinfo_test.cc.obj -o
test_cxx_runtime.exe -Wl,--major-image-version,0,--minor-image-version,0
C:/msys64/usr/lib/libm.a -Wl,-Bstatic -lc++abi -Wl,-Bdynamic -lkernel32
-luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32
-ladvapi32 && cd ."
lld-link: error: undefined symbol: operator delete(void*)
>>> referenced by
CMakeFiles/test_cxx_runtime.dir/typeinfo_test.cc.obj:(type_info2::~type_info2())
>>> referenced by
libc++abi.a(stdlib_typeinfo.cpp.obj):(std::type_info::~type_info())
>>> referenced by
libc++abi.a(stdlib_typeinfo.cpp.obj):(std::bad_cast::~bad_cast())
>>> referenced 90 more times
lld-link: error: undefined symbol: std::__1::__libcpp_execute_once(void**,
void (*)())
>>> referenced by
libc++abi.a(cxa_exception_storage.cpp.obj):(__cxa_get_globals)
>>> referenced by
libc++abi.a(cxa_exception_storage.cpp.obj):(__cxa_get_globals_fast)
lld-link: error: undefined symbol: std::__1::__libcpp_tls_get(long)
>>> referenced by
libc++abi.a(cxa_exception_storage.cpp.obj):(__cxa_get_globals)
>>> referenced by
libc++abi.a(cxa_exception_storage.cpp.obj):(__cxa_get_globals_fast)
...
I’m guessing we need to pass some additional options to try_compile() in the test_cxx function. I’m already passing the target and sysroot for the above test, but that doesn’t seem to be enough. Any idea?
try_compile(USERUNTIME
"${CMAKE_BINARY_DIR}/CMake"
"${CMAKE_CURRENT_LIST_DIR}/CMake"
test_cxx_runtime
CMAKE_FLAGS "-DCXX_RUNTIME=${CXX_RUNTIME_LIB}"
"-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS}"
"-DCMAKE_C_COMPILER_TARGET=${CMAKE_C_COMPILER_TARGET}"
"-DCMAKE_CXX_COMPILER_TARGET=${CMAKE_CXX_COMPILER_TARGET}"
"-DCMAKE_SYSROOT=${CMAKE_SYSROOT}"
${CXX_RUNTIME_FLAGS}
OUTPUT_VARIABLE TRY_COMPILE_OUTPUT)
message(WARNING ${TRY_COMPILE_OUTPUT})
I got it working thanks to the help of the MinGW folks!
@davidchisnall the following steps should allow you to build libobjc2 for MinGW using the standard Windows (non-MinGW) Clang, and thereby also enable you to use the normal LLVM/Clang build process for Windows in order to debug this further. I tested this with a clean MSYS2 installation.
- Download this CMake toolchain file clang-mingw.cmake.txt (rename to
clang-mingw.cmake). - Open a MinGW 64-bit shell, e.g. using:
C:\tools\msys64\msys2_shell.cmd -mingw64 - Uninstall MinGW Ninja if needed, as we’ll need to use Windows Ninja for Windows Clang to get Windows-style paths:
pacman -R mingw-w64-x86_64-ninja - Uninstall MinGW Clang if needed so it doesn’t get picked up by CMake:
pacman -R mingw-w64-x86_64-clang - Make sure you have CMake and GCC installed (GCC is needed for the system libraries):
pacman --needed -S mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc - Add the Ninja installation directory from Windows (installed via Chocolatey) to your PATH, as well as the LLVM bin dir (here I’m using LLVM installed via Chocolatey, so you will have to change this path when building your own):
export PATH="$PATH:/c/ProgramData/chocolatey/bin:/c/Program Files/LLVM/bin" - Make sure you’re on the libobjc2 branch
mingw. - Run CMake by specifying the toolchain file:
cmake .. -G Ninja -DTESTS=ON -DCMAKE_TOOLCHAIN_FILE=path/to/clang-mingw.cmake - Build:
ninja
This should result in the exact same build errors as we’re seeing here on the CI, and which I presume will require changes in Clang, i.e.:
lld-link: error: undefined symbol: objc_exception_throw
>>> referenced by Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.mm.obj:(poke_objcxx)
>>> referenced by Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.m.obj:(rethrow)
lld-link: error: undefined symbol: vtable for gnustep::libobjc::__objc_class_type_info
>>> referenced by Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.mm.obj:(.weak.__objc_eh_typeinfo_Test.default.check_uncaught_count)
lld-link: error: undefined symbol: objc_begin_catch
>>> referenced by Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.m.obj:(main)
lld-link: error: undefined symbol: objc_end_catch
>>> referenced by Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.m.obj:(main)
>>> referenced by Test/CMakeFiles/ObjCXXEHInterop.dir/ObjCXXEHInterop.m.obj:(main)
I've pushed some changes that allow me to compile and link everything (with a one-line patch to clang):
Nice!
The exception tests are all failing; however. What do you use to debug things with MinGW? WinDBG doesn't seem to like MinGW .exes.
Good question. Maybe @mstorsjo would know?
I'm guessing GDB or lldb from MSYS2 should work.
pacman -S gdb
I've tried installing gdb in mingw, but it doesn't seem to be able to set breakpoints (even one on main).
There's something odd with MinGW's bridging of the SEH and DWARF EH models that is breaking the code that tries to figure out the layout of the C++ exception structure. I've pushed changes that let me pass all of the tests except those related to C++ exception interop.
It looks as if the __gxx_personality_v0 symbol isn't exported from the C++ runtime with MinGW, so we can't wrap it for Objective-C++ anyway. I don't see any way of getting C++ exception interop working with MinGW. If you know anyone on the MinGW project, perhaps they could help? My experience so far is that the MinGW environment is just sufficiently different from Windows and *NIX to be annoyingly incompatible with both and a massive pain to work with.
Thinking a bit more about it, the right strategy for MinGW may be to simply punt all exception handling to the C++ runtime, as Apple does.
I just saw that MSYS2 added a new "CLANG64" environment that is using an LLVM toolchain and libc++: https://www.msys2.org/docs/environments/
Maybe that's more compatible with libobj2's EH integration. I'll give it a try.
I tried using the MSYS2 CLANG64 environment, which uses clang and libc++ by default, but it’s failing with the following linker errors. Any ideas?
lld-link: error: undefined symbol: test_eh_personality_internal
>>> referenced by CMakeFiles/objc.dir/eh_personality.c.obj:(test_eh_personality)
lld-link: error: undefined symbol: cxx_throw()
>>> referenced by CMakeFiles/objc.dir/eh_trampoline.s.obj:(eh_trampoline())
Closing this as basic MinGW support was added in #254.