Closed cyclaero closed 5 years ago
Thanks for the report. I'll bump the port to use the fixed version, but in the meantime this should only be triggered when targeting the old ABI - adding -fobjc-runtime=gnustep-2.0
to your compiler flags should make things work again. This should be added by default for anything built with the latest gnustep-make port.
The fixed version did resolve my issue:
I don’t use anything of GNUstep, instead I set up a bare minimum root class which is basically a wrapper to the objc-runtime - see: https://github.com/cyclaero/ContentCGI/blob/master/plugins/CyObject.h https://github.com/cyclaero/ContentCGI/blob/master/plugins/CyObject.m
Adding the flag -fobjc-runtime=gnustep-2.0
did not change anything. Neither for the previous version (it still crashes) nor for the present fixed version, which works well with or without that flag.
I tried also -fobjc-nonfragile-abi
but this did not change anything either.
My programs work well on the latest macOS as well as on the latest FreeBSD (x86-32, x86-64, arm7). Do I really need any of these flags, and if yes, which would you recommend?
Thank you very much for resolving the issue so quickly.
Best regards
Rolf
The code path with the crash was only in the old-ABI upgrade path, so I'm surprised you hit it with the new ABI. Are you using clang70 or newer? The new ABI was introduced in clang 7 and the FreeBSD port has a bug fix back ported that may be needed (it shouldn't be triggered in real code, but it was in the GNUstep-base configure checks).
In terms of flags, don't use -fobjc-nonfragile-abi
. It was deprecated years ago and should be killed off. On macOS, XCode automatically adds something like -fobjc-runtime=macos-10.8
. When targeting this runtime, you want -fobjc-runtime=gnustep-{version}
. I'd recommend switching to the 2.0 ABI, because that gives you better reflection metadata and smaller binaries. Please report any issues you might have. One caveat with the new ABI: It changed the representation of NSConstantString
, so if you're providing an implementation of this for non-Apple platforms then you'll need to update it. You can see the representation for full objects here: https://github.com/gnustep/libobjc2/blob/master/Test/Test.h
Strings less than 8 7-bit ASCII characters long will be encoded in the pointer value and so won't require allocation. The layout will be (assuming a sane interpretation for C bitfields, don't actually rely on this):
struct nstinystring
{
uintptr_t char0 :7;
uintptr_t char1 :7;
uintptr_t char2 :7;
uintptr_t char3 :7;
uintptr_t char4 :7;
uintptr_t char5 :7;
uintptr_t char6 :7;
uintptr_t char7 :7;
uintptr_t length :5;
uintptr_t tag :3;
};
The value of the tag (low 3 bits) will be 4 (GNUstep uses other values for NSNumber
, but the compiler doesn't currently encode them). Any characters after the end will be 0, so you can always compare short strings for equality by a simple pointer comparison.
I am using clang from base of FreeBSD 12.0-RELEASE-p3, which happens to be:
FreeBSD clang version 6.0.1 (tags/RELEASE_601/final 335540) (based on LLVM 6.0.1)
In order to trigger the crash, nothing of GNUstep needs to be involved. Actually, the code snippet, which demonstrates the issue even doesn’t instantiate any object from the dummy class A. The crash happens before the entry point of main() is hit.
My projects which are targeted to FreeBSD need only a small subset of NSObject's functionality, no Foundation and nothing else, and yesterday I removed all -fobjc-xxx
flags, since everything is now working well without those flags and with the fixed version of libobjc2-2.0.
I don’t have any clang 7 installed here, and I would prefer to stay with the compilers in the base system, because this facilitates deployment of my programs on the various systems which I maintain.
I tried to build libobjc2-2.0 with OLDABI_COMPAT flag set to OFF in the CMake configuration using said clang 6.0.1, and this errors out. In addition, I needed to remove -fno-common
from the CFLAGS when building some of my Objective-C based code, since with that flag in place, the linker complained about error: duplicate symbol: objc_method_cache_version
.
Clang 7 will come with FreeBSD 13, and until then I will stay with the present fixed version of libobjc2-2.0 and the old ABI which it happens to provide for clang 6.
Thank you very much once again for taking your time on this.
Note that everything in ports has now moved to the 2.0 ABI (which is a breaking change, so you can't mix 1.x and 2.x ABI code in the same library). I expect to toggle the OLDABI_COMPAT
switch to OFF
by default in the packaged version at some point in the next year, so I would strongly recommend moving to clang 7.x and the new ABI. Please can you open another issue about the duplicate symbol? I expect that we're missing an extern
in a header...
I understand that „everything in ports“ actually means „everything GNUstep in ports“ and „so you can’t mix ...“ refers to the general you but not to me, since I don’t use anything from GNUstep.
That said, I am fine with your plans to dropping the old ABI at some point next year, since most probably FreeBSD 13 should then have been released already and it will come with clang >= 7 or even 8, and therefore libobjc2 won’t be dependent on a compiler which is not in the base system. I will do the move to clang >= 7 by then.
Concerning the duplicate symbol error, I will try to set up a reduced test case which demonstrates the issue. In the moment this happens when linking 2 objc object files dynamically against libobjc2 together into a custom library. More than 10 thousand lines of code are involved, and I must not remove the part which triggers the error. I will file the issue report, once I can reproduce it with a test case.
I understand that „everything in ports“ actually means „everything GNUstep in ports“ and „so you can’t mix ...“ refers to the general you but not to me, since I don’t use anything from GNUstep.
Everything in ports means 'everything that is built in the FreeBSD ports collection and depends on the GNUstep Objective-C Runtime (a.k.a. libobjc2)'. 'You can't mix' means 'if you attempt to mix within the same process, libobjc2 will refuse to load your code'.
That said, I am fine with your plans to dropping the old ABI at some point next year, since most probably FreeBSD 13 should then have been released already and it will come with clang >= 7 or even 8, and therefore libobjc2 won’t be dependent on a compiler which is not in the base system. I will do the move to clang >= 7 by then.
Major FreeBSD releases have a rough cadence of once every 2 years, so I imagine that there will be at least a year in which you're supporting
Concerning the duplicate symbol error, I will try to set up a reduced test case which demonstrates the issue. In the moment this happens when linking 2 objc object files dynamically against libobjc2 together into a custom library. More than 10 thousand lines of code are involved, and I must not remove the part which triggers the error. I will file the issue report, once I can reproduce it with a test case.
I believe this is now fixed.
Be assured that I appreciate your efforts very much. I guess, I understood the point very well, and I’ll see whether I need to move forward to a newer clang before FreeBSD does.
Concerning the duplicate symbol issue, I verified that PUBLIC
is a non-empty #define
only on Windows, and said issue is not resolved on FreeBSD. When I replace line 8 of the file /usr/local/include/objc/objc-visibility.h
by #define PUBLIC extern
then my issue has gone. However, I can’t tell whether this would open a bunch of other issues in the 107 ports which depend on libobjc2 and which I don’t u... - ehmmm forget it :-D
Ooops, sorry. Should actually be fixed now.
Compiling and executing the following code on FreeBSD 12.0-RELEASE-p3 (x86_64) results in a core dump:
When I replace
long double x
withdouble x
the above program prints „Hello, World!“.bt in lldb shows the following: