Re: GNUstep on Windows using Clang + MSVC ABI

David Chisnall <[email protected]>
Newsgroups gmane.comp.lib.gnustep.devel
Message-ID <[email protected]>
On 01/02/2021 18:24, Frederik Seiffert wrote:
> Sorry everyone, looks like my earlier draft got sent out prematurely...
> 
> 
>> Am 29.01.2021 um 17:28 schrieb David Chisnall 
>> <[email protected] <mailto:[email protected]>>:
>>
>> ld -r is pretty flaky everywhere.  LLD wasn't going to implement it at 
>> all and GNUstep was one of only two consumers so I think it's fair to 
>> say that it's pretty likely that it will continue to be intermittently 
>> broken by various linker versions.  I personally like the concept but 
>> it's probably better to not depend on it anywhere.
> 
> Yeah, hopefully this change will resolve these issues once and for all.
> 
> That being said, Richard raised one *potential* issue with this change 
> on GitHub, which is that it increases the length of the command that the 
> linker is being called with, as now all subproject object files are 
> passed directly to the linker. Hopefully OS command line limits are 
> large enough these days so that this won’t be an issue in practice, but 
> I’d still encourage everyone to try building their projects with the 
> "clang-msvc-support" branch of tools-make.

I'm curious about this.  GNUstep projects have fairly short linker lines 
in comparison with a bunch of C++ projects.  I had a quick look at the 
systems I have runningL

  - FreeBSD limits it to 256 KiB on processes with limited kernel 
virtual address space, 512 KiB elsewhere.
  - Linux limits it to 128KiB statically but can return a larger number 
via sysconf depending on the system.  For me, that is around 2MiB.
  - Windows limits it to 32 KiB, though cmd.exe only handles 8 KiB.

Even with the 8KiB limit, you'd need a few hundred files on the linker 
invocation for this to be a problem unless you're giving long absolute 
paths for everything.


>> Have you tried with the bash.exe in C:\Windows\System32?
> 
> I briefly tried building in WSL today, and the main difference to using 
> an MSYS2 shell is that Autoconf will consider it cross-compiling. This 
> means that some config checks will not be run (because Autoconf will 
> think that it can’t run the binaries), and we would need to provide a 
> cross.config file with pre-determined results of these config files 
> instead (just like when cross-compiling e.g. for Android). This is 
> obviously more fragile.
> 
> But this kind of illustrates what I consider the biggest challenge with 
> this setup: the need to install and jump between different shells in 
> order to build the whole system (i.e. CMD for libobjc2, libdispatch, and 
> probably others; Bash/MSYS2 for GNUstep).
> 
> I’m not sure if there’s an elegant solution to this. My current line of 
> thinking is to create a project like tools-android (tools-windows?) with 
> Batch + Bash scripts to build all dependencies and GNUstep in their 
> respective environments.

Oh, sorry, wrong bash.  The one I was thinking of is actually installed 
for me as c:\Program Files\Git\git-bash.exe.  It's installed by the git 
package and gives you a Windows-native bash environment.  If the 
configure scripts just depend on bash, that ought to be sufficient.

> 
> 
>> Is the -fuse-ld=lld line required?  You get LLD installed when you 
>> install clang, so it's not very important, but the runtime and its 
>> tests, at least, also work with LINK.EXE (though you may have to 
>> disable incremental linking if it's on by default).
> 
> I did:
> 
>>> I tried using the MS linker (link.exe), but while that seems to 
>>> generally work fine linking ObjC files, it throws up at some 
>>> configure tests (specifically when testing "whether objc really 
>>> works"). Using LLD works though, so one must run Make configure with 
>>> LDFLAGS="-fuse-ld=lld".
> 
> This is reproducible simply by compiling config/config.objc.m from 
> libs-base:
> 
> $ clang -o conftest.exe config/config.objc.m -I/c/GNUstep/x64/include 
> -L/c/GNUstep/x64/lib -fobjc-runtime=gnustep-2.0 -lobjc
> LINK : conftest.exe not found or not built by the last incremental link; 
> performing full link
> conftest-b38f3b.o : warning LNK4078: multiple '.CRT' sections found with 
> different attributes (40400040)
> libcmt.lib(initializers.obj) : warning LNK4254: section '.CRT' 
> (C0000040) merged into '.rdata' (40000040) with different attributes >
> $ ./conftest.exe
> Segmentation fault

This file appears to depend on objc-common.g, which looks like a 
generated file.  It probably only needs it for the root-class attribute 
(which only raises a warning if it's omitted, so isn't the end of the 
world).  Aside from that, the file looks like a bunch of the tests that 
we have in the libobjc2 repo, which pass in CI, so I'm not sure what's 
going on there.  Can you add -### to the clang command line and see how 
it compares to the same thing for the libobjc2 tests?

> 
> $ lldb conftest.exe
> (lldb) r
> Process 165928 stopped
> * thread #1, stop reason = Exception 0xc0000005 encountered at address 
> 0x7ffce04d1048: Access violation reading location 0x00000000
>      frame #0: 0x00007ffce04d1048 objc.dll`objc_msgSend + 40
> objc.dll`objc_msgSend:
> ->  0x7ffce04d1048 <+40>: movl   (%r10), %r11d
>      0x7ffce04d104b <+43>: cmpl   $0x8, %r11d
>      0x7ffce04d104f <+47>: je     0x7ffce04d1063            ; <+67>
>      0x7ffce04d1051 <+49>: cmpl   $0x0, %r11d
> 
> Let me know if I should open an issue for this somewhere, or if there’s 
> something in config.objc.m that we should change to fix this.

Please file a libobjc2 bug to track it for now, it might be an LLVM bug, 
but I suspect it's something in your environment - it looks as if you're 
linking two versions of the Windows C runtime somehow.


>>> For pthreads I have builthttp://www.sourceware.org/pthreads-win32/ 
>>> <http://www.sourceware.org/pthreads-win32/>from source by invoking 
>>> "nmake clean VC" in a VS native tools command prompt, and manually 
>>> copied the headers (pthread.h, sched.h, semaphore.h), pthreadVC2.lib 
>>> (renamed to pthread.lib), and phtreadVC2.dll.
>>
>> At some point it would be nice to lose this dependency.  I don't know 
>> how much the attitude to C++ in GNUstep has changed recently, but 
>> C++11 now has a nice set of threading abstractions that provide 
>> everything that NSThread, NSLock and friends need.  If we use those 
>> instead of pthreads then we'd have something that worked on any 
>> platform with a C++11 implementation (Linux, Windows, Fuschia, Haiku, 
>> and so on).
> 
> That’d be nice! I would personally be completely open to using C++ in 
> GNUstep, and that sounds to me like a much better solution than 
> implementing NSThread and NSLock with native Windows APIs, although 
> that’s of course also an option.
> 
> I’d appreciate any thoughts on this from others what they think about 
> C++ in GNUstep to replace specific APIs like pthreads? I guess this 
> could be guarded with a config check so that a pure-C version would 
> still be available using pthreads.

Maybe start a new thread for this?  This one is very long and I suspect 
many people have tuned out.


>>> - NSFileManager support
>>> NSFileManager is currently non-functional with this setup due to 
>>> dirent.h missing (MinGW has it, but Windows doesn’t).
>>> I found this MIT-licensed header-only implementation – would that be 
>>> ok to add to the project?
>>> https://github.com/win32ports/dirent_h/blob/master/dirent.h 
>>> <https://github.com/win32ports/dirent_h/blob/master/dirent.h>
>>
>> I think that looks easier than using Win32 ABIs directly.
> 
> Agreed. I’ll give it a go.
> 
> 
>>> - Autoconf GNUC / GCC / Clang detection
>>> When targeting the MSVC ABI, Clang does not define `__GNUC__`, which 
>>> causes Autoconf to not define $GCC (i.e. "checking whether we are 
>>> using the GNU C compiler" will be NO). I thus removed $GCC as a 
>>> pre-requisite in GS_CHECK_CC_IS_CLANG(), so that Clang is still 
>>> correctly detected in this setup.
>>
>> I *believe* this is controlled by either a gnu dialect (e.g. 
>> -std=gnu11 for C) or -fgnu-extensions.  That said, I'm not sure if you 
>> can #include Windows headers with gnu extensions enabled.
> 
> Yeah I tried with -fgnuc-version=xxx, but then Windows headers didn’t work.
> 
> 
>>> - Debug/Release CRT
>>> Just a heads up that on Windows the C runtime libraries (CRT) come in 
>>> two versions for debug and release builds (e.g. msvcrt and msvcrtd). 
>>> The libraries that are used seem to have to match between all DLLs – 
>>> e.g. building libobjc2 for debug will cause all sorts of crashes when 
>>> Base is build for release, e.g. when freeing memory allocated by 
>>> libobjc2 in Base.
>>
>> Fun.
> 
> Indeed. My plan is to link against debug libraries when building with 
> "make debug=yes".

This is one of the annoying issues with GNUstep Make.  Because the build 
is configured from the command line invoked in the source directory, not 
from the configuration in the build directory, it's very easy to 
accidentally mix the two.  If I were still actively working on 
Objective-C things, I'd be really tempted to replace GNUstep Make with 
some CMake packages now that CMake officially supports Objective-C and 
using Clang with the GCC-style driver on Windows.  It's really nice in 
the libobjc2 build that I can generate a Visual Studio project and use 
the VS debugger from the CMake.

> 
> 
>>> lld-link: error: relocation against symbol in discarded section: 
>>> __start_.objcrt$SEL
>>> >>> referenced by C:\msys64\tmp\conftest-78a937.o:(.objc_init)
>>> This is reproducible when building a file that calls ObjC runtime 
>>> functions but doesn’t actually contain any ObjC code. Not sure if 
>>> that’s expected behavior or bug.
>>
>> I think this is a bug, probably a clang bug (and probably my fault)
> 
> Should I open an LLVM issue for this?

Yes please.  There was an identical bug on ELF platforms, I may have 
failed to fix it for Windows.

> 
> 
>> Awesome work, and it makes me much happier than trying to support MinGW.
> 
> Thank you, glad you like it! This is also exciting to us because it 
> should e.g. allow us to use recent Windows technologies like the 
> C++/WinRT language projection from ObjC++ which are not compatible with 
> MinGW.
> 
> That being said, I would still very much like to get libobjc2 working 
> with MinGW as well, as it would allow people currently using GNUstep 
> with GCC in a MinGW environment to switch to Clang/libobjc2, should 
> result in a more streamlined setup experience with all dependencies 
> being available via MinGW packages and everything being built in one 
> shell, and allow for existing MinGW-based software to be used.
> 
> I’ll try to get you those instructions for building LLVM with the MinGW 
> patches in the next couple weeks.

I'll try to find some time to work on it.

>> We have given up supporting MinGW for snmalloc and I am considering 
>> optionally supporting snmalloc for Objective-C object allocations 
>> since it is much faster than the system malloc on most platforms and 
>> is particularly good for fixed-size allocations as are common in 
>> Objective-C.  It would be a shame for this to be an 
>> everywhere-except-Windows thing.
> 
> That looks really great! Would be interesting to see some performance 
> stats of this for ObjC specifically if you have that.

It depends on the workload, but in the worst case I've seen 2% 
improvement relative to jemalloc, in highly concurrent and 
allocation-heavy workloads it's been closer to 30%.  For parallel and 
relatively allocation-heavy workloads it's superlinear relative to the 
Windows allocator (improvement increases you add more threads).  I don't 
have any good Objective-C benchmarks though, so I'll probably make it an 
option and let other folks benchmark it on their workloads.

David
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.