[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: GNUstep on Windows using Clang + MSVC ABI
From: |
Frederik Seiffert |
Subject: |
Re: GNUstep on Windows using Clang + MSVC ABI |
Date: |
Mon, 1 Feb 2021 13:52:21 +0100 |
>> - Linking subproject object files directly (instead of merging)
>> As David had suspected, merging the subproject object files turned out to be
>> an issue: `ld -r` is not available on Windows, and using `ar cr` resulted in
>> a subproject.o that didn’t contain all the symbols (I’m guessing because ar
>> doesn't correctly handle PE/COFF files).
>> So I looked into how we could instead use the subproject object files
>> directly when linking the project, and came up with this solution: instead
>> of merging the object files into subproject.o, we simply write the list of
>> object files to a subproject.txt file (in the same location), and read that
>> to create SUBPROJECT_OBJ_FILES.
>> The change is pretty minimal and seems to work fine on all
>> platforms/configurations in CI:
>> https://github.com/gnustep/tools-make/commit/434f957df0ad81b52a09e3f8c4a200734898b342
>> Given that this affects all platforms I’d appreciate everyone’s feedback on
>> this, but given that issues with incremental linking with various setups has
>> been talked about multiple times on the mailing list, I hope that this
>> change will be an overall improvement.
>
> 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.
>
>> - Building
>> Building with this setup requires using a standard (non-MinGW) Clang that
>> e.g. comes with Visual Studio or is available as pre-built binary from the
>> LLVM website, and requires passing a host to configure like
>> --host=x86_64-pc-windows. Invoking `clang -v` should show a target like
>> "x86_64-pc-windows-msvc". It *might* be that using a MinGW Clang works too
>> when invoked with --target x86_64-pc-windows-msvc, but I haven’t tried that.
>
> The easiest way of installing clang on Windows is via Chocolatey: just run
> `choco install llvm` once it's installed. Choco is also the easiest way of
> installing cmake and Ninja for building the runtime.
Thanks, good point!
>> The build is best done in an MSYS2 shell that does not have any additional
>> *-devel packages installed that might get picked up by configure.
>> Alternatively --disable-xxx flags can be used to prevent these dependencies
>> to be picked up.
>
> Have you tried with the bash.exe in C:\Windows\System32?
>> I’m currently building like this:
>> # tools-make
>> export CC=/C/LLVM/bin/clang
>> export CXX=/C/LLVM/bin/clang++
>> export OBJCXX=/C/LLVM/bin/clang++
>> ./configure --host=x86_64-pc-windows --with-library-combo=ng-gnu-gnu
>> --with-runtime-abi=gnustep-2.0 --prefix=/c/GNUstep/x64 LDFLAGS="-fuse-ld=lld"
>> make install
>
> 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).
Yeah:
>> 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".
>> # libs-base
>> . /c/GNUstep/x64/share/GNUstep/Makefiles/GNUstep.sh
>> ./configure --host=x86_64-pc-windows --disable-iconv --disable-tls
>> --disable-icu --disable-xml
>> make -j12 install
>> - Dependencies
>> While most dependencies should be available via NuGet, I have not been able
>> to figure out yet how we might integrate NuGet packages into the build
>> process. Downloading the packages results in individual folders per package
>> with deeply nested folder structures containing the libraries for different
>> architectures, debug/release targets, and Visual Studio versions.
>> For now I have manually copied the headers and libffi.lib import library
>> (renamed to ffi.lib) from the libffi package, and the libffi.dll from the
>> libffi.redist package.
>> For pthreads I have built 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).
>
>
>> I haven’t build with any other dependencies so far but that will be my next
>> endeavor. If anyone has suggestions on how the NuGet packages might be used
>> directly I’d appreciate any input. This is also the main reason I haven’t
>> set this up on CI yet, as we’d have to replicate the currently manual
>> process somehow.
>> I’m also thinking about writing some scripts similar to tools-android that
>> could build all the dependencies and GNUstep itself, ideally also for the
>> different architectures and debug/release targets.
>> - 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
>
> I think that looks easier than using Win32 ABIs directly.
>
>> - 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.
>
>
>> - 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.
>
>> - Linker issues
>> 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".
>> I also had to bypass the config checks for objc_sync_enter(),
>> objc_setProperty(), _Block_copy(), and non-fragile-abi support and assume
>> these functions are there, as these checks result in the following linker
>> errors.
>> 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)
>
>> While 64-bit builds works fine with this setup, I have not been able to get
>> 32-bit builds to work yet due to this linker error, but I’m probably just
>> missing some flags somewhere:
>> lld-link: error: libcmt.lib: machine type x64 conflicts with x86
>> Also, as David noted, this setup requires dllexport/dllimport on all ObjC
>> classes, so I annotated all our ObjC class interfaces with GS_EXPORT_CLASS
>> (and also added missing GS_DECLARE annotations in externs.m), in order for
>> these symbols to be correctly exported in the DLL.
>
> Awesome work, and it makes me much happier than trying to support MinGW. 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.
>
> David
>
>
- Re: GNUstep on Windows using Clang + MSVC ABI,
Frederik Seiffert <=