how to link a static library for iOS - ios

I have create a bunch of .o files (via gcc -c $file.c $someotherops -o $file.o). Now I want to link them into a static library.
I'm not exactly sure wether I am supposed to use ld or gcc for this. In the ld manual, it is said that I'm not supposed to use it directly. However, I cannot figure out the gcc parameters to create a static library.
I tried ld *.o -static -o libfoo.a but it complains about a lot of missing symbols (I think all from libc). I don't understand why it complains because it is supposed to be a static library. I thought it would check for the symbols once I link that static library to some other thing.
Another thing: I use /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ld here (my target is iOS). It complains with the warning ld: warning: using ld_classic. What is this about?
Then I thought, maybe it needs to have the dynamic libraries specified. So I added -lc to link against libc. But it complains with can't locate file for: -lc. I added -L/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/lib and there is a libc.dylib.
Any ideas?
About the -lc error: It got away after I specified -arch armv6. Then it complained about a wrong libcache.dylib (which must be linked from libc.dylib I guess because it didn't specified it). Adding -L.../usr/lib/system helped.
Now, for each single .o file, I get the warning ld: warning: CPU_SUBTYPE_ARM_ALL subtype is deprecated. What is this about?
And I still have a bunch of missing symbols, esp:
Undefined symbols for architecture armv6:
"start", referenced from:
-u command line option
(maybe you meant: _PyThread_start_new_thread)
"___udivsi3", referenced from:
_get_len_of_range in bltinmodule.o
_quorem in dtoa.o
_array_resize in arraymodule.o
_newarrayobject in arraymodule.o
_array_fromfile in arraymodule.o
_get_len_of_range in rangeobject.o
_inplace_divrem1 in longobject.o
...
"___unorddf2", referenced from:
_builtin_round in bltinmodule.o
...
I checked some of those symbols, e.g. ___udivsi3 in get_len_of_range. This function uses C arithmetic only, no external call. So this seems to be translated to use some external functions like ___udivsi3. But what libraries is this in?
-lgcc_s.1 fixed most of the ___udivsi3 and related missing symbols. The start symbol is still missing. What does -u command line option mean?
From here, I got the feeling that maybe ld isn't the right tool after all. There, a simple call to aris used. And this seem to make more sense. I will check if that does work and transform this into an answer then.
While playing more around, ar throw some warnings at me when building a fat static library. It gave me the hint to use libtool instead. That is what I'm doing now, i.e. libtool -static -o libfoo.a *.o. Also I switched the compiler to /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clangbut not sure if that matters.
Now, at compiling some test application which links to this static library, I get these warnings:
ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in __PyBuiltin_Init from /Users/az/Programmierung/python-embedded/libpython.a(bltinmodule.o). To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie
ld: warning: 32-bit absolute address out of range (0x1001B70C4 max is 4GB): from _usedpools + 0x00000004 (0x001B70CC) to 0x1001B70C4
ld: warning: 32-bit absolute address out of range (0x1001B70C4 max is 4GB): from _usedpools + 0x00000000 (0x001B70CC) to 0x1001B70C4
What are they about? I don't use -mdynamic-no-pic. I also don't really see in _PyBuiltin_Init how I use absolute addressing there.
Also, what are these absolute addresses out of range about? Edit: These were some really huge allocations. I just removed this code for now (this was WITH_PYMALLOC, if anyone is interested in these specific Python internals).
When I start it on my iPhone, I get the abort:
dyld: vm_protect(0x00001000, 0x00173000, false, 0x07) failed, result=2 for segment __TEXT in /var/mobile/Applications/C15D9525-E7DC-4463-B05B-D39C9CA24319/...
When I use -no_pie for linking, it doesn't even link. It fails with:
Illegal text-relocation to ___stderrp in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/libSystem.dylib from _read_object in /Users/az/Programmierung/python-embedded/libpython.a(marshal.o) for architecture armv7
I solved the PIE disabled, Absolute addressing error. I had a -static in my command line Clang. Once I removed that, the warning got away, as well as the dyld/vm_protect error. It was the first time it actually run some code.
Until I hit another strange error about integer comparison. Whereby this looks more like a bug in their Clang build.

It all works now. Basically, the answer is:
Just compile every *.c file as usual to *.o files. The only real difference is the different GCC/Clang, the -arch armv7, the different SDK / include dirs.
Use libtool -static -o libfoo.a *.o to build the static library.
That's it. The other problems in my question were just wrongly headed tries.

If anyone gets here by searching for the dyld: vm_protect(...) runtime error but you are using XCode, the -static flag mentioned in the OP is likely the issue.
Get rid of it by switching "Enable linking with shared libraries" to "Yes" (the default) in the LLVM compiler language settings. (This removes GCC_LINK_WITH_DYNAMIC_LIBRARIES = NO from the project file).

Related

Clang Error "duplicate symbols for architecture x86_64"

This error is listed a lot over stack and the common fixes don't seem to work for me. I am getting the error: "duplicate symbols for architecture x86_64" when compiling an Obj-C MacOS Xcode App. Xcode 11.5 and MacOS Catalina 10.15.5. It is saying there are 15 duplicate symbols, with one of the 15 errors looking like:
duplicate symbol '_visual10Window' in:
/Users/tempuser/Library/Developer/Xcode/DerivedData/test-cdicjztmkktfomehwaphnzhbozgh/Build/Intermediates.noindex/test.build/Debug/test.build/Objects-normal/x86_64/Test.o
/Users/tempuser/Library/Developer/Xcode/DerivedData/test-cdicjztmkktfomehwaphnzhbozgh/Build/Intermediates.noindex/test.build/Debug/test.build/Objects-normal/x86_64/MainView.o
My MainView.h and MainView.mm do not contain any definition for visual10Window.
My Test.h has (removing this give a use of undeclared identifier error).
#class Visual10;
Visual10 *visual10Window;
and Test.mm includes
#import "Visual10.h"
and I'm calling a xib from a menu item in Test.mm
- (void)Visual10Menu:(id)sender {
if (!visual10Window) {
visual10Window = [[Visual10 alloc] initWithWindowNibName:#"Visual10"]; }
[visual10Window showWindow:self]; }
I have tried the common suggestions including:
Install and reinstall pods (this project doesn't use pods)
Checked for wrong imports like import ".m" instead of ".h"
Remove -all_load from Other Linker Flags
Build Settings / No Common Blocks set to NO
Checked for duplicate files Build Phases / Compile Sources (None)
Tried adding and removing -ObjC from Other linker flag
Tried Build Settings / Enable Testability set to NO
Tried clearing derived data
None of these work and still get duplicate symbol errors.

.c File via Bridging Header Not Working After Xcode 8 Update

The app I've been working on uses an external library, pdlib, which has it's own externals (.c files) which I've been importing via the bridging header #import "Uzi.c" and calling in my main Swift file via Uzi.c's setup function Uzi_setup() in my ViewController class. I've had no problem with this until after updating to new public Xcode 8 a few days ago (I had no problem with Xcode 8 Beta 1 over the Summer).
Here are the 7 errors I get, listed under a single "Mach-O Linker Error" umbrella:
Undefined symbols for architecture x86_64:
"_Uzi_bang", referenced from:
_Uzi_setup in ViewController.o
"_Uzi_class", referenced from:
_Uzi_setup in ViewController.o
"_Uzi_float", referenced from:
_Uzi_setup in ViewController.o
"_Uzi_new", referenced from:
_Uzi_setup in ViewController.o
"_Uzi_pause", referenced from:
_Uzi_setup in ViewController.o
"_Uzi_resume", referenced from:
_Uzi_setup in ViewController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Those undefined symbols are 6 functions and a class declare from Uzi.c. Here's a link to the whole c file: https://github.com/electrickery/pd-miXedSon/blob/master/hammer/Uzi.c
I've tried every solution I've found online for dealing with similar problems, with no solution yet... I tried changing the "Architecture" and "Valid Architecture" settings to only armv7 and armv7s (no arm64) and changed "Build Active Architecture Only" to "No". These step seem to help others in similar situations, but they didn't work for me (and taking away arm64 causes additional errors to appear).
XCode 8 is pretty recent (the public version was released Sept. 13), so there are virtually no other questions about this upgrade causing a similar problem.
Any help would be greatly appreciated!
Solved by #danomatika on GitHub: https://github.com/libpd/libpd/issues/149
"You generally shouldn't include/import an implementation file aka .c, .cpp, .m, etc. This is what is causing the duplicate symbol issue.
This is what the "forward function declaration" in the header file is for: to tell the compiler that a function exists and what data it takes/returns. The compiler then assumes the actual implementation of the function exists in an implementation file. If it can't be found, then you get an "undefined symbol error." If you somehow end up declaring the function twice, aka include both a header with the forward declaration and the implemetaton of the function itself in the .c file, then you get a "duplicate symbol error."
This is all lower-level stuff that is only really an issue since Pd externals are designed around being dynamic libraries, so are not built or provided with headers which include the function declarations. This is why you have to do a little extra work and do it yourself.
Their are two easy fixes for this, both of which involve declaring the required function you want to call from the .c file in a header file.
Simply declare the function in the bridging header:
void uzi_setup();
Create a header, say Externals.h, and declare all of the externals stuff there:
// forward declare setup functions only found in .c implementations
void uzi_setup();
// convenience wrapper function
void externals_setup() {
uzi_setup();
}
Then import the file in your bridging header:
#import "Externals.h"
And in swift, you can now do:
externals_setup()

iOS - Circular Imports - fixing blocks and typedef enums

I am getting an error that this block, which I defined in a header file, has 78 duplicate symbols. I have tried putting it in the precompiled header file but I still get the same results.
This is the error: ld: 34 duplicate symbols for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
It's possible that there are some circular imports, but I can't really change a lot unless anyone has a way to forward define a typedef enum (which I have used all throguhout the project) - something like #class but for typedef.
Can anyone please help?

Xcode - Linker command failed with exit code

Got a strange issue from Xcode, there aren't code issues and I haven't any idea how to handle with this problem. I also used Google and saw similar questions but the answers weren't useful for me.
duplicate symbol _OBJC_IVAR_$_Level._name in:
..../Library/Developer/Xcode/DerivedData/MobileMaps-bfaaljugbcgusoazfkvdbpbdyiqf/Build /Intermediates/MobileMaps.build/Debug-iphonesimulator/MobileMaps.build/Objects-normal/i386/Level-C98F33E28EFA5297.o
/Library/Developer/Xcode/DerivedData/MobileMaps-bfaaljugbcgusoazfkvdbpbdyiqf/Build/Intermediates/MobileMaps.build/Debug-iphonesimulator/MobileMaps.build/Objects-normal/i386/Level-C635B4AD47A32079.o
duplicate symbol _OBJC_IVAR_$_Level._type in:
...../Library/Developer/Xcode/DerivedData/MobileMaps-bfaaljugbcgusoazfkvdbpbdyiqf/Build/Intermediates/MobileMaps.build/Debug-iphonesimulator/MobileMaps.build/Objects-normal/i386/Level-C98F33E28EFA5297.o
...../Library/Developer/Xcode/DerivedData/MobileMaps-bfaaljugbcgusoazfkvdbpbdyiqf/Build/Intermediates/MobileMaps.build/Debug-iphonesimulator/MobileMaps.build/Objects-normal/i386/Level-C635B4AD47A32079.o
duplicate symbol _OBJC_IVAR_$_Level._binaryImage in:
...../Library/Developer/Xcode/DerivedData/MobileMaps-bfaaljugbcgusoazfkvdbpbdyiqf/Build/Intermediates/MobileMaps.build/Debug-iphonesimulator/MobileMaps.build/Objects-normal/i386/Level-C98F33E28EFA5297.o
..../Library/Developer/Xcode/DerivedData/MobileMaps-bfaaljugbcgusoazfkvdbpbdyiqf/Build/Intermediates/MobileMaps.build/Debug-iphonesimulator/MobileMaps.build/Objects-normal/i386/Level-C635B4AD47A32079.o
duplicate symbol _OBJC_CLASS_$_Level in:
..../Library/Developer/Xcode/DerivedData/MobileMaps-bfaaljugbcgusoazfkvdbpbdyiqf/Build/Intermediates/MobileMaps.build/Debug-iphonesimulator/MobileMaps.build/Objects-normal/i386/Level-C98F33E28EFA5297.o
... ../Library/Developer/Xcode/DerivedData/MobileMaps-bfaaljugbcgusoazfkvdbpbdyiqf/Build/Intermediates/MobileMaps.build/Debug-iphonesimulator/MobileMaps.build/Objects-normal/i386/Level-C635B4AD47A32079.o
duplicate symbol _OBJC_METACLASS_$_Level in:
...Library/Developer/Xcode/DerivedData/MobileMaps-bfaaljugbcgusoazfkvdbpbdyiqf/Build/Intermediates/MobileMaps.build/Debug-iphonesimulator/MobileMaps.build/Objects-normal/i386/Level-C98F33E28EFA5297.o
......Library/Developer/Xcode/DerivedData/MobileMaps-bfaaljugbcgusoazfkvdbpbdyiqf/Build/Intermediates/MobileMaps.build/Debug-iphonesimulator/MobileMaps.build/Objects-normal/i386/Level-C635B4AD47A32079.o
ld: 5 duplicate symbols for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
From what I've read there are many different reasons for this problem and therefore many different solutions but maybe someone will have done the same stupid thing as me and this will help them. I am fairly certain this is not the problem the OP experienced though as my duplicate symbols were in differently named .o files.
Basically be very careful with autocorrect when typing your #import statements. I accidentally imported the .m file instead of the proper .h file and ended up with output similar to what the OP has posted.
Hope this helps somebody!

Using SQLCipher with MonoTouch

I've compiled a static library and linked both SQLCipher and OpenSSL. The full project, makefile, and compiled library can be found here:
https://github.com/anujb/SQLCipherNet
When I link the resulting library in a normal Objective-C Xcode project, the call to sqlite3_key works fine.
I've linked the same library into a MonoTouch project using:
-gcc_flags "-L${ProjectDir} -lsqlciphernet -force_load ${ProjectDir}/libsqlciphernet.a"
Then I've modified SQLite-NET to call the the key function, after every SQLite3.Open(...) function:
[DllImport("__Internal", EntryPoint = "sqlite3_key")]
public static extern Result Key(IntPtr db, string key, int keyLength);
But I get a EntryPointNotFoundException when the Key method is called. Here's the stack trace:
System.EntryPointNotFoundException has been thrown at:
at (wrapper managed-to-native) SQLite.SQLite3:Decrypt (intptr,string,int)
at SQLite.SQLiteConnection..ctor (System.String databasePath) [0x00031] in
../SQLite.cs:108
Obviously the stacktrace isn't particularly helpful, but I'm at a loss as to where to begin to debug this issue. Halp?
I get the same error when building your solution for "Debug|iPhoneSimulator". However your project options, for this configuration, do not include the gcc_flags you mentioned - so the exception is totally normal.
Trying to build the "Debug|iPhone" configuration (where the options are specified) fails because of path issues... but I'm pretty sure it would work if I fixed them ;-)
UPDATE
Moving the library to it's right location gives me:
Undefined symbols for architecture armv6: "___udivmodsi4",
referenced from:
_sqlite3BitvecSet in libsqlciphernet.a(sqlite3.o)
_sqlite3BitvecClear in libsqlciphernet.a(sqlite3.o)
_sqlite3BitvecTest in libsqlciphernet.a(sqlite3.o) ld: symbol(s) not found for architecture armv6
I believe it's missing because of libopenssl ?

Resources