-
Notifications
You must be signed in to change notification settings - Fork 119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Static linking does work on master, even when using the 1.9 ABI and with -DBUILD_STATIC_LIBOBJC=true set in cmake #85
Comments
I get this when trying to use static linking: ld: error: undefined symbol: __start___objc_classes
ld: error: undefined symbol: __stop___objc_classes
Works fine dynamically. I am compiling all my files with -fobjc-runtime=gnustep-1.9 so am not suing the 2.0 ABI as yet. Though the aim is to move to it in the end. Code still works fine if I checkout the 1.9 branch. System here is FreeBSD 12-STABLE, which is the latest one and thus has clang 7.0.1 as the native compiler. |
Note it also links fine if I enable the 2.0 ABI, (though then it doesn't run properly, but I think thats my fault) |
That's quite odd. It looks as if you've compiled libobjc2 with a compiler that supports the new ABI, so it's using the new ABI for the libobjc2 itself. Do you have a minimal reproduction case? I've tried a clean build using:
I've also tried setting #include <objc/runtime.h>
#include <stdio.h>
@interface Cls
{
id isa;
}
@end
@implementation Cls @end
int main()
{
fprintf(stderr, "%p\n", class_createInstance(objc_getClass("Cls"), 0));
} With:
It all seems to work correctly. The same is true if I use The __start and __stop symbols should be automatically created by the linker. There was an issue with programs that didn't contain any classes, but that should be fixed in the version of clang in packages. Can you check which version of clang you used to build libobjc2, and make sure that it's the latest version of the llvm70 package if it's 7.something? |
If you update to the latest stable then you get clang 7 in the base (but its very recent - http://www.freshbsd.org/commit/freebsd/src/344212 ), which is what I was truing. Will give it a try with llvm70 from ports and see what I get.... |
Well, that interesting :-) I rebuilt both libobjc2 and my code with clang70 from ports, and it links, but running it gives this: Version 2 Objective-C ABI may not be mixed with earlier versions. Have I made a wrong assumption here in that the libobjc2 should be useable with both 1.9 and 2.0 ABI ? Thanks for taking a look by the ay, I realise I am a bit of an edge case in the user base! |
Did another little test and compile the library with clang60, as that doesn't support the 2.0 ABI, and the result there fails 'gmake test' like this: The following tests FAILED: Haven't tried linking that against the rest of the code as it fails the test. |
Also, I tried your 'a.m' file above. As you say it seems to work fine if not states, but if I add '-static' then I get the same result: [pete@skerry ~]$ cc -static -I/usr/local/include a.m -L/usr/local/lib -lobjc
ld: error: undefined symbol: __stop___objc_classes
|
The following works for me (from the static build directory):
I suspect that you're hitting a known bug in the clang 7 release, which is fixed by a back-ported fix in the port, where it doesn't emit a placeholder symbol in the The mixing ABIs issue is also a little bit surprising, but indicates that it may be an issue with linker ordering. Looking at the code in loader.c, that can happen if you load some old ABI classes and then load the diff --git a/loader.c b/loader.c
index 7022469..3f5f15f 100644
--- a/loader.c
+++ b/loader.c
@@ -197,8 +197,28 @@ OBJC_PUBLIC void __objc_load(struct objc_init *init)
switch (CurrentABI)
{
case LegacyABI:
+ {
+ BOOL isRuntimeLib = NO;
+ for (Class *cls = init->cls_begin ; cls < init->cls_end ; cls++)
+ {
+ if (*cls == NULL)
+ {
+ continue;
+ }
+ // As a special case, allow using legacy ABI code with a new runtime.
+ if (strcmp((*cls)->name, "Protocol"))
+ {
+ isRuntimeLib = YES;
+ break;
+ }
+ }
+ if (isRuntimeLib)
+ {
+ break;
+ }
fprintf(stderr, "Version 2 Objective-C ABI may not be mixed with earlier versions.\n");
abort();
+ }
case UnknownABI:
isFirstLoad = YES;
CurrentABI = NewABI; |
Thanks for the patch, and the comment about the llvm70 in ports. So what I am not doing is building everything with the ports compiler. I applied your patch, recompiled all of libobjc and then tried the a.m file. It does indeed link, but running it gives the
That we had earlier. In the example you quote above where it runs, which compiler did you use to build the library ? All very puzzling.... |
I can get a.o to run with the 2.0 ABI though. Maybe I should just switch to getting my code to run under the 2.0 ABI using the ports compiler instead ? Will give that a shot in a bit.... |
Okay, it looks as if there was a bug in the |
Thanks - l I just pulled master and I still get the ABI mismatch output using the 'a.m' file unfortunately. I then tried the above patch, with the addition of the '== 0' to the strcmp line, and even with that it still gives me the ABI mismatch output. |
Aha, the above patch does nothing because that code is never run - that function is only ever called with an ABI type of 'Unknown'. The line with is actually printing the message about mixing version and aborting is not there, its the test at the top of '__objc_exec_class' |
So, I tried compiling the library with '-fobjc-runtime=gnustep-1.9' set, and it still says that you can't mix ABI's, despite there now being no code at all in the setup whtihc has been compiled without that flag set. I don't have much more time to look at this today, but am fairly keen to get it fixed now - I doubt I will be able to move to 2.0 in the foreseeable future because of the UTF-16 behaviour, but I don't want to be stuck on the 1.9 branch forever, as I don't want to its any improvements which go into master. Will try and find time to get back to this next week though. Thanks for the help... |
Okay, I understand the issue. We detect that we should reset the ABI check to unknown by checking if it's loading the Protocol class, but when you do static linking if you don't reference |
I am just revisiting all of this, and unfortunately, even with the fix, the original problem still exists. I still get the 'Version 2 Objective-C ABI may not be mixed with earlier versions.' when static linkinging, despite your commit which always links the protocol classes. I haven't done any further digging - I came to this because I had another issue with protocols in the 2.0 ABI - but can the be re-opened as an issue ? Sorry.... |
No description provided.
The text was updated successfully, but these errors were encountered: