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!
Related
So I have an iPhone static library that I am trying to build. I've got the script that was used in this question (http://stackoverflow.com/questions/3520977/build-fat-static-library-device-simulator-using-xcode-and-sdk-4), but the issue I've hit is that I'm seemingly still unable to successfully build the static library for the simulator. When I build in the static library project, I get the follow warnings:
warning: no rule to process file '$(PROJECT_DIR)/GDInAppStore/GDInAppStore.m' of type sourcecode.c.objc for architecture i386
warning: no rule to process file '$(PROJECT_DIR)/GDInAppStore/SKProduct+priceAsString.m' of type sourcecode.c.objc for architecture i386
warning: no rule to process file '$(PROJECT_DIR)/GDInAppStore/VerificationControllerPBK.m' of type sourcecode.c.objc for architecture i386
I believe this issue is causing the problem that is leading to the universal library I get from the build script causing this error in my other project
ld: warning: ignoring file /Users/abotkin/Projects/Static Libraries/GDInAppStore/libGDInAppStore.a, missing required architecture i386 in file
"_OBJC_CLASS_$_GDInAppStore", referenced from:
objc-class-ref in SubscribeNowInAppController.o
ld: symbol(s) not found for architecture i386
I'm using Xcode 4.3.2 and have set the flags in the static library Xcode project so that i386 is included in the Architecture and Valid Architectures. Any tips?
Make sure you are building for the simulator if you are compiling for i386. Basically, your arch parameter has to match your sdk parameter. i.e.
xcodebuild -project proj.xcodeproj -arch armv64 -sdk iphoneos8.1 build
and
xcodebuild -project proj.xcodeproj -arch i386 -sdk iphonesimulator8.1 build
I was able to do a workaround this issue by using Karl's iOS Universal Framework that he mentioned in the other topic here https://stackoverflow.com/a/5721978/497718
That said, if anyone could point me into what I may have been doing wrong in using the script in that same topic, I'd love to learn how to do it the right way.
With Xcode 6, Apple has added iOS framework support to their build tools.
Using Apple's framework target for all new projects, as it is less hacky and is supported by Apple themselves.
I was trying to make a sample code run download by the link
http://www.magtek.com/support/software/downloads/sw/99510108.zip
This is a card reader api ,here is a sample code.When I run this code I got the error:
ld: warning: ignoring file /Users/gaurav.garg/Downloads/99510108/SampleCode/Lib/libMTSCRA.a, missing required architecture i386 in file
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_MTSCRA", referenced from:
objc-class-ref in MagTekDemoAppDelegate.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The class MTSCRA is only a header file,And the solution that I have cheked That we have to add the .m file in compiled source path of build build phase of target...but unfortunately I don't have the MTSCRA.m file.MTscra.h have the AudioToolBox and externalAccesory framework.
Actually the problem is that MagTek provides you two separate .a files.
If you look at the one in the Release-iphoneos and run the following command:
> lipo -info libMTSCRA.a
Architectures in the fat file: libMTSCRA.a are: armv7 (cputype (12) cpusubtype (11))
Likewise if you look at the one in Release-iphonesimulator...
> lipo -info libMTSCRA.a
input file libMTSCRA.a is not a fat file
Non-fat file: libMTSCRA.a is architecture: i386
So the real answer is to create a new libMTSCRA.a for DEBUG that is n-way FAT by combining the two using lib tool and then creating separate DEBUG and RELEASE library search paths.
To start you would go to the directory above where MagTek keeps the two different versions of libMTSCRA.a When you are there, you will run the following command:
libtool -static -o libMTSCRA_FAT.a Release-iphoneos/libMTSCRA.a Release-iphonesimulator/libMTSCRA.a
When you examine the output file, you should see:
>lipo -info libMTSCRA_FAT.a
Architectures in the fat file: libMTSCRA.a are: armv7 (cputype (12) cpusubtype (11)) i386
Then in your project, create two folders (aka groups) "debug" & "release" and then restructure the DEBUG and RELEASE Library Search Paths to use these respective directories.
Lastly, rename libMTSCRA_FAT.a to libMTSCRA.a and place it in the debug search path keeping the iOS (armv7 (cputype (12) cpusubtype (11))) in release. The reason we do this is because while it might be ok to use this newly created .a file in debug mode it is considered bad taste to push this into production because we have no way to confirm that the merged lib is 100% what we intended ( the merge of the archs ).
Et voilà !
Undefined symbols for architecture i386:
It means that the library you are linking against does not have symbols for i386. Which means you can not use the simulator. You will need to run the sample on the device or get the version of the library created for the simulator.
You need to make sure you are including all of the Frameworks that are required by that library.
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.
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
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