Compile C lib for iPhone - iphone

I'm trying to compile ZeroMQ C binding in order to be able to use it on iPhone, here is my configure options:
./configure --host=arm-apple-darwin --enable-static=yes --enable-shared=no CC=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/arm-apple-darwin10-gcc-4.2.1 CFLAGS="-pipe -std=c99 -Wno-trigraphs -fpascal-strings -O0 -Wreturn-type -Wunused-variable -fmessage-length=0 -fvisibility=hidden -miphoneos-version-min=3.1.2 -gdwarf-2 -mthumb -I/Library/iPhone/include -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.0.sdk -mdynamic-no-pic" CPP=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/cpp AR=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ar AS=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/as LIBTOOL=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/libtool STRIP=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/strip RANLIB=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ranlib
It actually configures and compiles fine, but when I add it to Xcode Frameworks section, I get warning: ld: warning: in /path/to/app/libzmq.a, file was built for unsupported file format which is not the architecture being linked (armv7) and a lot of symbol not found errors.
If I change current active architecture from armv6 to armv7, warning message will change it to armv6.
What am I doing wrong ?
Thanks,
Dan

It sounds like you're building a universal armv6/armv7 binary for the iPhone (this is the default, so that makes sense). That means that you need to build a universal library to link against. Build both libraries, and then use lipo to combine the two.
For example, build the armv6 one and place it at armv6/libfoo.a, and the armv7 one at armv7/libfoo.a. Then run
lipo -arch armv6 armv6/libfoo.a -arch armv7 armv7/libfoo.a -output libfoo.a -create
to create the universal library libfoo.a.

Given the warning message from ld, my guess is you're not compiling the library for the correct platform. And given you're using configure, my guess is you're trying to compile the library outside of Xcode and then bring it into Xcode later to link it in.
Perhaps you could try running configure to set up your headers, but do the actual compilation step inside Xcode?
There are lots of related questions here on SO about compiling third-party (external) C or C++ libraries for use in iPhone projects.
Creating static library for iPhone
TiMidity: need help compiling this library for the iPhone

Related

.swiftinterface 'No such module' in XCFramework

I've been trying to build an XCFramework from my program that wraps C code into Swift and I need it to support both x86_64 and arm64 archs for MacOS. I have succeeded in creating a .framework that combines the two binaries from both architectures into a single universal fat file (as you can see below) using lipo -create -output and once I implement this .framework into any Xcode project, it works right out of the box and I'm able to import it and use it without major issue.
sebasmontero#Sebastians-MBP faspio % lipo -info _builds/apple-universal/FaspIO.framework/FaspIO
Architectures in the fat file: _builds/apple-universal/FaspIO.framework/FaspIO are: x86_64 arm64
The trouble begins when I try to generate an XCFramework using this exact same universal .framework. I'm running xcodebuild -create-xcframework -framework /myFramework.framework -output myXCFramework.xcframework as you do normally and the XCFramework is generated successfully, but. when I try including it in an Xcode Project, I get a 'No such module' on the .swiftinterface file, specifically in the imported module that wraps my C code and maps it into Swift.
.../FaspIO.framework/Modules/FaspIO.swiftmodule/arm64-apple-macos.swiftinterface:4:8: No such module 'CFaspIO'
I appreciate any help or pointers!

iPhone: how to make a fat library containing armv7s support?

I have external libraries for armv6, armv7, i386 and armv7s. When I try to put all together using lipo, I got an error message like so, saying armv7s isn't supported:
lipo: known architecture flags are: any little big ppc64 x86_64 ppc970-64 ppc i386 m68k hppa sparc m88k i860 veo arm ppc601 ppc603 ppc603e ppc603ev ppc604 ppc604e ppc750 ppc7400 ppc7450 ppc970 i486 i486SX pentium i586 pentpro i686 pentIIm3 pentIIm5 pentium4 m68030 m68040 hppa7100LC veo1 veo2 veo3 veo4 armv4t armv5 xscale armv6 armv7 armv7f armv7k
How to solve this problem?
You are possibly trying to use an older version of lipo that does not support armv7s. You should try that with the lipo version bundled with Xcode 4.5.
You would need the sources and compile it with armv7s support. Also, armv7 should work just fine on the armv7s devices too.

iOS simulator on mac is running i386 architecture, not armv7?

I've got some static libraries I've built for use on armv7 architectures. When I try to use them in a iOS project which I testrun on the iphone 5.0 simulator, I get errors telling me about undefined symbols for architecture i386 in my static libraries.
So I guess this means the iphone simulator wants libraries compiled for i386? What is the point of the simulator then - why dosn't it emulate armv7 architecture as well?
So the only way I can test my static libraries is to connect a physical iOS device and run it?
Or did I get it wrong?
So I guess this means the iphone simulator wants libraries compiled
for i386? What is the point of the simulator then - why dosn't it
emulate armv7 architecture as well?
You've answered your own question. It's a simulator, not an emulator. Therefore it is a Mac OSX program, running on i386 architecture. If you compile your static libraries for i386 as well you will be able to use them on the simulator.
I am not very sure but i386 is for Simulator and armv7 is for Devices that you have connected to your Machine.
You can actually compile the app through Xcode command line tool using i386 architecture (there is also a way to run it in Xcode UI by modifying the build settings).
xcodebuild -sdk iphonesimulator6.1 -arch i386 VALID_ARCHS="i386 armv7 armv7s" clean install
Run this command in the directory that you have the projectName.xcodeproj file.
Here's a break down of the script:
-sdk iphonesimulator6.1 // Build the app on iPhone simulator 6.1
-arch i386 // Build your app using i386 architecture
VALID_ARCHS="i386 armv7 armv7s" // Specify these architectures are valid
clean install // Clean all the builds then re-build and install
If you want to try simulators with i386 just go for =< iPhone 5.

Link Issue with C library in XCode - file was build for unsupported file format which is not the architecture being linked

So I am trying to use a C library in a Objective-C, iPhone project. I am getting this linker error when I try to compile:
file was built for unsupported file
format which is not the architecture
being linked (i386)
I build this library using the standard
./configure
make
Which architecture should I build this with to work with iPhone project? Thanks!
Update
I updated the Makefile and added -arch i386 to the CFLAGS line. When I run make I now this get this error:
Compiling spammer.c
gcc -o spammer spammer.o ../src/libircclient.a -lpthread
ld: warning: in ../src/libircclient.a, file was built for unsupported file format which is not the architecture being linked (x86_64)
Does this mean I need to edit another makefile somewhere??
It likely was built for x86_64 which is the default. You need to modify the library so that it's compiled for i386 and will match your application.
Typically you do that by setting the CFLAGS environment variable to -arch i386 before running configure. Make sure to do a "make dist clean" first though. If that doesn't work, you can also hand-edit the Makefile after configure creates it and add -arch i386 to the CFLAGS= line.
This error:
Compiling spammer.c gcc -o spammer spammer.o ../src/libircclient.a -lpthread ld: warning: in ../src/libircclient.a, file was built for unsupported file format which is not the architecture being linked (x86_64)
Comes when building the examples and that's not really what you want right?
Do a make in the SRC folder and building with -arch i386 or -arch arvm7 will work.

How do i compile a static library (fat) for armv6, armv7 and i386

I know this question has been posed several times, but my goal is slightly different with regard to what I have found searching the web. Specifically, I am already able to build a static library for iPhone, but the final fat file I am able to build only contains arm and i386 architectures (and I am not sure to what arm refers: is v6 or v7?). I am not able to compile specifically for armv6 and armv7 and them merge both architectures using lipo. The lipo tool complains that the same architecture (arm, not armv6 or armv7) is present in both the armv6 and armv7 libraries.
Can someone explain exactly how to build for armv6 and armv7, and them merge these libraries into a fat file using lipo?
EDIT: I need to build not using Xcode but compiling directly a traditional unix library.
Here is a good solution I found: Static Libs With Support to iOS 5 and Arm64
Edited:
The solution is to build different architectures separated then bind them using lipo, by using command line (or Rakefile).
First build the binary with arm using xcodebuild:
xcodebuild -project 'StaticLibDemo.xcodeproj' -configuration 'Release' -sdk 'iphoneos7.0' clean build ARCHS='armv7 armv7s' IPHONEOS_DEPLOYMENT_TARGET='5.0' TARGET_BUILD_DIR='./build-arm' BUILT_PRODUCTS_DIR='./build-arm'
Note that you must set IPHONEOS_DEPLOYMENT_TARGET='5.0' and ARCHS='armv7 armv7s', it’s recommended to set build and product dirs to make the things more clear, take a look at Build Setting Reference for more details what this flags means.
Next build for arm64:
xcodebuild -project 'StaticLibDemo.xcodeproj' -configuration 'Release' -sdk 'iphoneos7.0' clean build ARCHS='arm64' IPHONEOS_DEPLOYMENT_TARGET='7.0' TARGET_BUILD_DIR='./build-arm64' BUILT_PRODUCTS_DIR='./build-arm64'
Note the difference on ARCHS and IPHONEOS_DEPLOYMENT_TARGET. We also need to build for simulator, in this case we have to change the sdk to iphonesimulator7.0 and build in two steps first for i386:
xcodebuild -project 'StaticLibDemo.xcodeproj' -configuration 'Release' -sdk 'iphonesimulator7.0' clean build ARCHS='i386' IPHONEOS_DEPLOYMENT_TARGET='5.0' TARGET_BUILD_DIR='./build-i386' BUILT_PRODUCTS_DIR='./build-i386'
Now the tricky part! If you just change the ARCHS to x86_86 depending on your Xcode setting you will got an error like: “x86_64 is not a valid arch”. To avoid this just add VALID_ARCHS='x86_64':
xcodebuild -project 'StaticLibDemo.xcodeproj' -configuration 'Release' -sdk 'iphonesimulator7.0' clean build ARCHS='x86_64' VALID_ARCHS='x86_64' IPHONEOS_DEPLOYMENT_TARGET='7.0' TARGET_BUILD_DIR='./build-x86_64' BUILT_PRODUCTS_DIR='./build-x86_64'
Finally we just have to create a fat binary with all the 5 architectures:
lipo -create './build-arm/libStaticLibDemo.a' './build-arm64/libStaticLibDemo.a' './build-i386/libStaticLibDemo.a' './build-x86_64/libStaticLibDemo.a' -output 'libStaticLibDemo.a'
The author created a working example of this, you can get it: https://github.com/diogot/StaticLibDemo
Here is the Link to the post: Static Libs With Support to iOS 5 and Arm64
All credits go to Diogo Tridapalli.
Just use libtool to link the two arm6 and arm7 versions together - its what XCode does. However you will have problems if you try to combine these static libraries into a new super-library. If you need to do that then read this.
If you are doing this already, that would be why lipo is complaining that your "armv6" library contains both armv6 and armv7. My post has a fix that will probably be easier for you since you don't use XCode, but basically you use lipo -extract to make sure you have a thin armv6 library and a thin armv7 library before you go any further.
There doesn't seem to be a need to extract from the fat library before rejoining any more (as described in jamie's answer). I'm using the final 4.0 SDK from apple, which appear to create the fat armv6/armv7 libraries by default.
I was previously specifying the architecture for the input lib like so:
$DEVROOT/usr/bin/lipo -arch arm $PROJECT_DIR/buildlib/Release-iphoneos/lib.a -arch i386 $PROJECT_DIR/buildlib/Release-iphonesimulator/lib.a -create -output $PROJECT_DIR/buildlib/lib.a
This fails on the later SDKs, but removing the architecture from the (now fat) arm lib works fine:
$DEVROOT/usr/bin/lipo $PROJECT_DIR/buildlib/Release-iphoneos/lib.a -arch i386 $PROJECT_DIR/buildlib/Release-iphonesimulator/lib.a -create -output $PROJECT_DIR/buildlib/lib.a
Lipo must now be able to detect the architectures in the fat libraries.
Make sure to have your build settings set to Valid Architectures: armv6 armv7 and Architectures: Optimized (armv6 armv7). This should result in a binary optimized for both v6 & v7. If you're not sure it worked out, just set the Architectures: Standard (armv6) and compare the file sizes. Optimized should produce double the size (when I remember rightly).
You also always can use lipo -info on your binary to see all the included architecures.
Running it on a distribution build of my app gives me:
ullrich ~/Code/.../build/Distribution-iphoneos/My.app (streaming)$ lipo -info My
Architectures in the fat file: My are: armv6 armv7