Categories in static lib not regocnized at runtime - objective-c

I am building an executable ("tool") on Linux. Using include $(GNUSTEP_MAKEFILES)/tool.make.
It's linked to a static lib that has also be build with GNUstep. The lib
contains Categories.
The executable builds fine but has errors at runtime not recognizing
methods defined in the static lib's Category:
Uncaught exception NSInvalidArgumentException, reason:
ClassNameOfClassTheCategoryExtends(instance) does not recognize
nameOfMethodInCategory
I am trying to fix that by passing -ObjC to the linker flags (also
tried -all_load) in the executable's GNUmakefile:
ADDITIONAL_LDFLAGS = -ObjC -all_load
But that seems to be ignored by clang. Here is the relevant output of
make install messages=yes debug=yes
clang: warning: argument unused during compilation: '-ObjC'
[-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-all_load'
[-Wunused-command-line-argument]
It looks like ADDITIONAL_LDFLAGS are used compiling, not linking.
Using this leads to the same result:
LDFLAGS := $(LDFLAGS) -ObjC
The excecutables GNUmakefileincludes the following:
include $(GNUSTEP_MAKEFILES)/common.make
# My make
include $(GNUSTEP_MAKEFILES)/tool.make
The resulting command line output is:
$ make install messages=yes debug=yes
This is gnustep-make 2.9.0. Type 'gmake print-gnustep-make-help' for help.
Running in gnustep-make version 2 strict mode.
Making all for tool NameOfExcecutable...
clang -ObjC -fuse-ld=/usr/bin/ld.gold -pthread -fexceptions -rdynamic -fobjc-runtime=gnustep-2.0 -fblocks -o obj/NameOfExcecutable \
./obj/NameOfExcecutable.obj/main.m.o ./obj/NameOfExcecutable.obj/MyClass.m.o ./obj/NameOfExcecutable.obj/StreamRunLoop.m.o ./obj/NameOfExcecutable.obj/Connector.m.o ./obj/NameOfExcecutable.obj/HTTPClient.m.o \
-L/home/user/GNUstep/Library/Libraries -L/usr/GNUstep/Local/Library/Libraries -L/usr/GNUstep/System/Library/Libraries -lgnustep-base -ldispatch -l/path/to/libOwnLib1.a -l/path/to/libOwnLib2.a -l/path/to/libOwnHavingTheCategories.a -l/path/to/libOwnLib4.a -l/path/to/libOwnLib5.a -luuid -lz -lpthread -ldl -lpthread -lobjc -lm
clang: warning: argument unused during compilation: '-ObjC' [-Wunused-command-line-argument]
Question:
What am I doing wrong
or
How can I work around the issue?

After digging into the issue of the linker not knowing the -ObjC flag (which we are used to use in Xcode) it looks like:
only ld.ld64 is aware of this flag
ld.ld64 is a (too genericly named) "linker for macOS" (from LLDB.org)
thus is not available for Linux linkers
To workaround we first stopped using GNUstep makefiles to
disable all GNUstep magic understand what is going on and wrote our own makefiles.
The actual fix to force link/load all .o files was to explicitly pass --whole-archive to the linker:
-Wl,-whole-archive path/to/static/lib/containing/categories/libOwnLib1.a -Wl,-no-whole-archive

Related

error: target Objective-C runtime differs in PCH file vs. current file

I'm trying to compile Objective-C or .m file using command-line (generated by CMake) for Catalyst, but am stuck with two compile errors!
1. Whenever I enable Catalyst with one of below flags:
-target x86_64-apple-ios-macabi
-target x86_64-apple-ios13.0-macabi
-target x86_64-apple-ios13.5-macabi
-target x86_64-apple-ios13.7-macabi
2. Then force rebuild (click Clean Build Folder, then Build).
3. The build fails with error:
fatal error: 'UIKit/UIKit.h' file not found
4. But once I switch to 13.6, I mean, change the flag to:
-target x86_64-apple-ios13.6-macabi
5. Then force-rebuild, I get a new error:
error: target Objective-C runtime differs in PCH file vs. current file
Note that I am not using any PCH file, and both errors seem completely confusing.
Also, I searched and found post similar to second error, but the fix suggested (namely, switching to 13.6) is the cause of the second error.
(Was supposed to fix it, yet is triggering it).
After capturing Xcode's full command-line, I noticed that it had -x objective-c flag while my CMake had not!
After searching (about how CMake support's Obj-C),
found actual mistake!
1. Basically, CMake needed me to do something like:
project(MyProject C CXX OBJC OBJCXX)
Instead of:
project(MyProject)
2. Also, should add Obj-C flags into CMAKE_OBJC_FLAGS instead of CMAKE_C_LINK_FLAGS variable.
3. Now CMake automaticaly adds missing -x objective-c flag, and I just need to add my custom flags.
Full Xcode command-line:
-x objective-c -target x86_64-apple-ios13.6-macabi -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -fobjc-arc -fmodules -gmodules -fmodules-cache-path=/Users/admin/Library/Developer/Xcode/DerivedData/ModuleCache.noindex -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fbuild-session-file=/Users/admin/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/Session.modulevalidation -fmodules-validate-once-per-build-session -fmodule-name=MyProject -fapplication-extension -fpascal-strings -O0 -fno-common -DDEBUG=1 -DOBJC_OLD_DISPATCH_PROTOTYPES=0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -fasm-blocks -fstrict-aliasing -g -fprofile-instr-generate -fcoverage-mapping -index-store-path /MyBuildDir/Index/DataStore -iquote /MyBuildDir-cofig/MyProject-generated-files.hmap -I/MyBuildDir-cofig/MyProject-own-target-headers.hmap -I/MyBuildDir-cofig/MyProject-all-non-framework-target-headers.hmap -ivfsoverlay /MyBuildDir-cofig/all-product-headers.yaml -iquote /MyBuildDir-cofig/MyProject-project-headers.hmap -I/MyProductDir/include -isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/iOSSupport/usr/include -I/MyBuildDir-cofig/DerivedSources-normal/x86_64 -I/MyBuildDir-cofig/DerivedSources/x86_64 -I/MyBuildDir-cofig/DerivedSources -F/MyProductDir -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/iOSSupport/System/Library/Frameworks -MMD -MT dependencies -MF /MyBuildDir-cofig/Objects-normal/x86_64/my-source.d --serialize-diagnostics /MyBuildDir-cofig/Objects-normal/x86_64/my-source.dia -c /Users/admin/my-project/my-source.m -o /MyBuildDir-cofig/Objects-normal/x86_64/my-source.o
Note that I replaced paths to shorten above, like:
MyBuildDir => /Users/admin/Library/Developer/Xcode/DerivedData/MyProject-gczfeuobxydqjrfbdhwzpqjsseyr
MyBuildDir-config => /Users/admin/Library/Developer/Xcode/DerivedData/MyProject-gczfeuobxydqjrfbdhwzpqjsseyr/Build/Intermediates.noindex/MyProject.build/Debug-maccatalyst/MyProject.build/
MyProductDir => /Users/admin/Library/Developer/Xcode/DerivedData/MyProject-gczfeuobxydqjrfbdhwzpqjsseyr/Build/Products/Debug-maccatalyst

How to use rpath with LLD linker (LLVM)

I recently managed to use the lld linker in a big cmake project. (LLVM 11, from this package)
I do not use clang, I use G++ with LLD.
But I encounter the following issue: lld: error: unknown argument: -rpath
Following the clang documentation, -rpath should work, at least with clang I guess ?
Here is the g++ command generated by cmake:
g++.exe [...] -fuse-ld=lld [...] -Wl,-rpath='$ORIGIN' [...]
I manually tried a lot of combinations:
-Wl,-rpath='$ORIGIN'
-Wl,-rpath,'$ORIGIN'
-Wl,-rpath '$ORIGIN'
... etc, nothing work.
Of what I understand, lld should behave exactly like ld ?, so -Wl,-rpath='$ORIGIN' should work ?
Did I miss something ?

Meson can't find static libs

I can compile my project by running
g++ main.cpp -l:libpj-x86_64-unknown-linux-gnu.a -lpthread -lm -luuid
or
g++ main.cpp /usr/local/lib/libpj-x86_64-unknown-linux-gnu.a -lpthread -lm -luuid
But when I try adding library with either one of:
meson.get_compiler('cpp').find_library('libpj-x86_64-unknown-linux-gnu.a')
meson.get_compiler('cpp').find_library('/usr/local/lib/libpj-x86_64-unknown-linux-gnu.a')
I'm getting error:
ERROR: C++ library 'libpj-x86_64-unknown-linux-gnu' not found
Solution was to add 'dirs' variable even tho file is in standard /usr/local/lib path and to remove .a extension.
cc.find_library('libpj-x86_64-unknown-linux-gnu', dirs: '/usr/local/lib/')
Later of course lib was available inside meson and was added to executable and tested.

linker error using static linking in g++

I am using other people's makefile and get troubles when trying to compile a 'static' version of the exe
I have printed out the makefile's rules and the error is like this:
g++ Main.or System.or Options.or -Wall -lz --static -o main
/usr/bin/ld: cannot find -lz
/usr/bin/ld: cannot find -lstdc++
/usr/bin/ld: cannot find -lm
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
If I do not include the '--static' option in the above command, it works fine.
The makefile also have rules to generate the static lib:
ar -rcsv lib_release.a Main.or System.or Options.or
r - Main.or
r - System.or
r - Options.or
Making Soft Link: lib_release.a -> lib.a
ln -sf lib_release.a lib.a
The -static linkage option instructs the linker to ignore all shared
libaries (libname.so) that could resolve the -lname linkage options (both explicit
and default) and accept only static libraries (libname.a). You have shared libraries installed on
your system that satisfy -lz, -lstdc++, -lm and -lc but no static ones.
For your linkage to work as it stands you must install the static libraries:
libz.a (Compression library)
libstdc++.a (The standard C++ library)
libm.a (The math library)
libc.a The standard C library
by the method that is appropriate to your distro.

pthread library inclusion at (linking?) step

I'm trying to compile a program provided to me. I noticed in the Makefile it runs the command
g++ -o test [...] -lpthread
I noticed the pthread library file is in /lib/libpthread.so.0 , but when I try to make the target, it gives me this error:
/usr/bin/ld: cannot find -lpthread
collect2: ld returned 1 exit status
how do I fix this?
In order to use -lpthread, you need a libpthread.a library archive and this is for static linking. libpthread.so.0 is a shared object which means it is used for dynamic linking. See GCC Link Options