How can I combine two different dylib into a simple one for my Mac application? - xcframework

I am trying to build ffmpeg for Intel and M1 platform for my application.
I got some problem, because when I put arm64 dylibs I got error that no x86_64 dylibs available. And I got arm64 dylibs not available when I put x86_64 dylibs.
Can I combine these two set of dylibs into a single one then I don't need to change the dylibs on different platform?
XCFramework or ??
Thank you.
Eric

You can create so called "fat" library. It is dylib which combine several architectures for one platform (MacOS in your case).
lipo -create libx86_64.dylib libarm64.dylib -output libcombined.dylib
Resulted dylib you can include in your project and it will compile fine for both archs.
If you want it more comfortable you can build framework from combined library and header folder
xcodebuild -create-xcframework -library libcombined.dylib -headers path/to/headers/directory -output output.xcframework
In this case you'll need to include only framework in your project

Related

Swift fat framework w/Objective-C Cocoapod

I've built a framework in Swift. The framework uses Cocoapods, one of the pods is written in Objective C.
I also use a custom script to make the framework a fat framework so it supports 32/64 bit systems. (This runs in a separate target on the project and I'm wondering if that has something to do with it?)
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
if [ "true" == ${ALREADYINVOKED:-false} ]
then
echo "RECURSION: Detected, stopping"
else
export ALREADYINVOKED="true"
// Step 1. Build Device and Simulator versions
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
//Step 2. Copy the framework structure (from iphoneos build) to the universal folder
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
// Step 3. Copy Swift modules (from iphonesimulator build) to the copied framework directory
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/." "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"
// Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
// Step 5. Convenience step to copy the framework to the project's directory
cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"
// Step 6. Convenience step to open the project's directory in Finder
open "${PROJECT_DIR}"
fi
When I create this fat framework and put it into a project I'd like to use it on the compiler always fails b/c the project can't see the objective C cocoa pod module.
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ld: framework not found Pusher for architecture x86_64
It is not found for any architecture when I change the build platform.
Any solution where I can produce a framework that I can use in a separate Xcode project (for all iOS or OS X) would be awesome.
You can't run xcodebuild with -target when using CocoaPods. When you use -target, Xcode will only consider the active project and fail to pull in the Pod dependencies, similar to if you just opened the project file in Xcode and tried building.
You should be running xcodebuild -workspace "${PROJECT_NAME}.xcworkspace" -scheme "${PROJECT_NAME}" ..., assuming that CocoaPods generated the workspace and Xcode generated a scheme using the target name. You will also need to make sure your scheme is marked as shared if running this on another device.
Once your framework is built you will need to include it and the frameworks it depends on in apps that will be using it. For your framework, that means including it in General > Embedded Binaries and General > Linked Frameworks and Libraries. For frameworks you depend on, (e.g. AlamoFire), you could instruct users to include it in their Podfile, you could package it and ship it along with your framework, or you could do both and let the user do what works for them.
Apparently you are missing the 64bit architecture for Simulator.
When you build a target from Xcode, depending on what kind of simulator you have selected - the produced library will contains i386 or x86_64 respectively for selected 32bit or 64bit version of the simulator.
I guess that the cli build is producing only i386 version.
You can try to set the architectures in the script:
xcodebuild -target "${PROJECT_NAME}" ARCHS="i386 x86_64" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
As an alternative You can try to build by hand using 64bit simulator (iPhone 5S +), then extract the missing architecture and then put it into the final library using lipo command.

Cross-compiling C to armv7 using arm-apple-darwin10-llvm-gcc-4.2

This might seem like a very specific question but central idea is quite broad.
I have a simple hello world console application in C. I've compiled it on Mac OS X using following command:
$ export PLATFORM=/Developer/Platforms/iPhoneOS.platform
$ $PLATFORM/Developer/usr/bin/arm-apple-darwin10-llvm-gcc-4.2 -o hello hello.c -isysroot $PLATFORM/Developer/SDKs/iPhoneOS5.0.sdk/
It compiles successfully but gives this warning:
ld: warning: -force_cpusubtype_ALL will become unsupported for ARM architectures
Now, when I run lipo -info hello I get Non-fat file: hello is architecture: arm
Which specific arm is it and how to compile it to armv7 specifically?
A) "Lipo" is only for fat binaries (that is , multi-architecture). You're running it on a Mach-O file, single architecture. If you tried "file hello" it would tell you "mach-o Executable arm".
B) "arm" is , if memory serves, armv6. You can compile to armv6 by specifying "-arch armv7". You also specify "armv7s" (for Apple A6 devices), and now also arm64 (technically armv8) for 5S/iPad Air/Mini 2. Though technically, all ARM architectures are also v6 compatible, and the v7/v7s only makes a difference for NEON/SIMD instructions.
C) You can compile multiple times for different architectures (even x86_64) with different -arch specifiers, then use lipo -create to fuse all the binaries together to one big binary (hence the name "fat" binary), which would work on all devices.

OpenCV.Framework does not compile for the armv7s architecture

I am working on an iphone application using openCV framework.
Everything was working fine. however lately with the release of iOS 6 and XCode 4.5 I was migrating my project to XCode 4.5
When building I encountered this error:
ld: file is universal (2 slices) but does not contain a(n) armv7s
slice:
/Users/jobs/iPhone_Client/workspace/MyProject/third-party/OpenCV.framework/OpenCV
for architecture armv7s clang: error: linker command failed with exit
code 1 (use -v to see invocation)
** BUILD FAILED **
The following build commands failed:
Ld build/MyProject.build/Debug-iphoneos/MyProject.build/Objects-normal/armv7s/MyProject
normal armv7s (1 failure)
As I understood this is due to the new armv7s architecture.
OpenCV is apparently it is not compiling with armv7s.
How can I fix this issue?
Where can I find a new release of the framework that is compatible with the armv7s architecture?
And if there is no compatible framework available, is there a way to get the source code and create my own library compiled against the new architecture? Maybe some quick steps on how to do it?
Note: Just to note that I need the build for armv7s not armv7.
Thank you
This answer builds upon the one given by n9986. As he suggested, I cloned the repository found at
https://github.com/jonmarimba/OpenCV-iOS
When I downloaded it several references inside the project to different libraries were broken which was strange but they were easy to fix. After they were fixed it behaved exactly as n9986 described, outputting libraries compiled for both armv7 and armv7s. For my purposes however I required that they be bundled into a .framework so that they could be a drop in replacement for the old .framework I have been using.
Previously I had downloaded the latest version of Opencv for ios here and spent quite a bit of time trying to modify their cmake files to compile with support for armv7s. jonmarimba has already restructured the xcode project file to strip away its cmake dependencies which makes changing the target architecture much more intuitive. Unfortunately he does not build as many libraries as come with the standard openCV build. I added a new target to jonmarimba's project for opencv_world which is the target used in the standard openCV release for converting into a framework. Once that was built I used it as a drop in replacement for the static library in the framework file structure generated by the standard openCV release.
The framework I created can be downloaded here. It works perfectly for me as a drop in replacement for my previous opencv2.framework. I did notice however that jonmarimba has not converted the targets for opencv_videostab, opencv_stitching, or opencv_nonfree. It is possible that if you use one of those libraries my framework will not work for you. If that is the case let me know and I can try to set those up as targets in the xcode project for you.
Update
To compile for other architectures, change the target architecture in the included xcode project to whatever you like for the opencv_world library. After you build it, go find the library you just built. Rename the opencv_world library to opencv2 and replace the library file found in the .framework with opencv_world.
Update2
OpenCV 2.4.3 now compiles with armv7s support by default so these solutions are outdated.
Clone the Xcode project for opencv and update the opencv git submodule as per the README:
https://github.com/jonmarimba/OpenCV-iOS
Check the build settings, make sure iOS6 and armv7s are present. Click build. You should now have the armv7s compatible .a files. I just tried this:
$ file libopencv_core.a
libopencv_core.a: Mach-O universal binary with 2 architectures
libopencv_core.a (for architecture armv7): current ar archive random library
libopencv_core.a (for architecture cputype (12) cpusubtype (11)): current ar archive random library
The last entry is for armv7s as per my research so far.
Edit: The last entry is indeed armv7s. I ran the Xcode's own lipo info command:
$ xcrun -sdk iphoneos lipo -info libopencv_core.a
Architectures in the fat file: libopencv_core.a are: armv7 armv7s
You can always just not target armv7s, and only target armv7. Your application will still run fine on the iPhone 5, it just won't be fully optimized for the new instruction set.
Simply, I cloned source from here and build with this tutorial.
Then I got opencv2.framewok that works with armv7, armv7s and simulator.
Stating the obvious, you will need to recompile and rebuild the library openCV.framework and target it for armv7s.
Adjust the library "project settings" and "target settings" before rebuild. good luck!
Probably its possible to build it with CMake. I had one year ago a problem with a medical library I wanted to build for iOS. I could handle that with CMake.
Perhaps this link can be a starter.
http://computer-vision-talks.com/2010/12/building-opencv-for-ios/
Good luck!
Pass -DCMAKE_OSX_ARCHITECTURES="armv6;armv7;armv7s;i386" to cmake when compiling OpenCV library/framework for iOS.

Cross-compiling ZeroMQ to ARM for use in a MonoTouch iPhone app configure settings

I'm attempting to use the ZeroMQ library in an iPhone app developed in C# using MonoTouch. I've solved almost all of the problems, but have fallen at the last hurdle. I'm using ZeroMQ 2.1.10, and the C# CLR binding/wrapper, and developing in Mac OS X 10.6.8. Here's the story so far:
I first attempted to use ZeroMq in a simple Mono C# Console app. I built ZeroMQ with ./configure, then make and sudo make install, which installs shared library /usr/local/lib/libzmq.dylib. The ZeroMq C# binding clrzmq.dll is a wrapper that uses the 'core' ZeroMq functionality via C Api [DllImport] calls.
The test app didn't work, which I figured out to be that the standard ZeroMQ ./configure produces a 64-bit output, and Mono is only 32 bit. I then rebuilt ZeroMQ with
./configure CFLAGS="-O -arch i386" CXXFLAGS="-O -arch i386" LDFLAGS="-arch i386" --disable-dependency-tracking
My simple C# ZeroMq app then worked correctly.
Moving on, I then tried to use ZeroMq from inside an iPhone app in the iPhone simulator. I discovered that the iPhone only allows statically linked libraries (no dynamic libraries allowed). This is achieved by changing all the C# wrapper calls to
[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
and including libzmq.a directly in the MonoTouch project, and setting extra mtouch arguments
-cxx -gcc_flags "-L${ProjectDir} -lzmq -force_load ${ProjectDir}/libzmq.a"
to ensure the ZeroMQ library is included in the iPhone app.
When running the app in the iPhone simulator, it crashed out, which I traced to a call made from a zmq_init() to socketpair. I finally traced this to the ZeroMQ library having been built against my build machine's MacOS headers and libraries, instead of against the iPhone SDK. This was fixed by
./configure CFLAGS="-O -arch i386 -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk" CXXFLAGS="-O -arch i386 -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk" LDFLAGS="-arch i386" --disable-dependency-tracking
Success in the iPhone Simulator! The simulator requires i386 static libraries built to the iPhone simulator SDK. I now can use ZeroMQ functionality within an iPhone app in the Simulator ONLY. It does not work however on a real iPhone.
This is because a real iPhone requires a library that has been built for the ARM architecture, and against the real iPhoneOS SDK.
(There is a side-issue of building 3 separate libraries - i386, ARM6, and ARM7, and combining all 3 into 'fat' library that can be used in any environment. I need to be able to build for ARM before I get to this problem).
** Finally, my question!! **
The last step is to cross-compile build the ZeroMQ library to ARM. I have been trying all day long to come up with the correct switches for this, and studied all the examples on the internet that I can find, but none seem to have a solution that works.
The closest I have got to working is:
./configure CXX=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/arm-apple-darwin10-llvm-g++-4.2
CC=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/arm-apple-darwin10-llvm-gcc-4.2
LD=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ld CFLAGS="-O -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk"
CXXFLAGS="-O -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk"
--disable-dependency-tracking --host=arm-apple-darwin10
LDFLAGS="-isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk"
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
This produces a config which make compiles the ZeroMq code, but fails with lots of link errors, e.g.:
ar: libzmq_la-clock.o: No such file or directory
I've tried many other configurations, but they don't even pass ./configure correctly.
Can anyone help me with a suitable ./configure parameter list to produce an ARM architecture static library? This is all I need to get ZeroMQ working on a real iPhone.
And and all help much appreciated!
Just thought I'd share that I found the answer in the end - the trick was to add CPP="cpp" CXXCPP="cpp" to the ./configure statement, giving:
./configure CPP="cpp" CXXCPP="cpp" CXX=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/arm-apple-darwin10-llvm-g++-4.2 CC=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/arm-apple-darwin10-llvm-gcc-4.2 LD=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ld CFLAGS="-O -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk" CXXFLAGS="-O -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk" --disable-dependency-tracking --host=arm-apple-darwin10 LDFLAGS="-isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk" 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
I used this configuration to successfully build ZeroMQ for ARM, as used in my new iPhone app I Buzzed First (available at http://itunes.apple.com/gb/app/i-buzzed-first!/id490622820?mt=8 )
That question is not really related to MonoTouch but on how to compile 0MQ on the iOS (ARM). Have a look at: Compile C lib for iPhone
Hopefully it will help you and also cover the next question: fat universal binaries using lipo. The good news is that, if this works on the simulator, then you likely already covered any MonoTouch related issue :-)

iPhone static library distribution and release build errors (but not for debug)

Update
Daniel was close, it just wasn't the search path. The Prefix Header under GCC 4.2 was set to:
$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h
I missed that when I was combing through the first 2 times.
I removed it and now all is well.
Original Question
I have been using/building products with a static libraries for about a week now with no issues.
For the first time, I tried to make a distribution build (for ad hoc testing) and I am getting errors all over the place.
The errors, strangely say that it can't find Appkit headers. Which is odd because it is an iPhone app and shouldn't be linking to Appkit headers
Additionally, the library name, "libFJSCodeDebug.a" turns red while when I switch from debug to distribution/release. I figure this must be a big clue.
To test, I duplicated the debug configuration and renamed it release. This built fine. So it seems the problem is somewhere in the configuration. Below is a snippet of what I get in Xcode when I build. (Note: I named my target FJSCodeDebug even though it will be used for both debug and release builds)
Building target “FJSCodeDebug” of project “FJSCode” with configuration “Release” — (169 errors)
Checking Dependencies
cd /[redacted]/FJSCode
setenv PATH "/DeveloperBeta/Platforms/iPhoneOS.platform/Developer/usr/bin:/DeveloperBeta/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/DeveloperBeta/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -x objective-c-header -arch armv6 -fmessage-length=0 -pipe -std=c99 -Wno-trigraphs -fpascal-strings -fasm-blocks -Os -Wreturn-type -Wunused-variable -isysroot /DeveloperBeta/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk -gdwarf-2 -mthumb -miphoneos-version-min=3.0 -iquote /[redacted]/build/FJSCode.build/Release-iphoneos/FJSCodeDebug.build/FJSCodeDebug-generated-files.hmap -I/[redacted]/build/FJSCode.build/Release-iphoneos/FJSCodeDebug.build/FJSCodeDebug-own-target-headers.hmap -I/[redacted]/build/FJSCode.build/Release-iphoneos/FJSCodeDebug.build/FJSCodeDebug-all-target-headers.hmap -iquote /U[redacted]/build/FJSCode.build/Release-iphoneos/FJSCodeDebug.build/FJSCodeDebug-project-headers.hmap -F/[redacted]/build/Release-iphoneos -I/[redacted]/build/Release-iphoneos/include -I/Users/coreyfloyd/Xcode/ProductionProjects/build/FJSCode.build/Release-iphoneos/FJSCodeDebug.build/DerivedSources/armv6 -I/[redacted]/build/FJSCode.build/Release-iphoneos/FJSCodeDebug.build/DerivedSources -c /System/Library/Frameworks/AppKit.framework/Headers/AppKit.h -o /var/folders/R+/R+ofDLtuH1GOYQ1ZQ2C5mk+++TI/-Caches-/com.apple.Xcode.501/SharedPrecompiledHeaders/AppKit-gihvhjsfuggoevbehiszhgrzcska/AppKit.h.gch
/System/Library/Frameworks/AppKit.framework/Headers/AppKit.h:11:33: error: AppKit/AppKitDefines.h: No such file or directory
/System/Library/Frameworks/AppKit.framework/Headers/AppKit.h:12:32: error: AppKit/AppKitErrors.h: No such file or directory
/System/Library/Frameworks/AppKit.framework/Headers/AppKit.h:13:37: error: AppKit/NSGraphicsContext.h: No such file or directory
/System/Library/Frameworks/AppKit.framework/Headers/AppKit.h:14:35: error: AppKit/NSAccessibility.h: No such file or directory
/System/Library/Frameworks/AppKit.framework/Headers/AppKit.h:15:32: error: AppKit/NSActionCell.h: No such file or directory
...... (continues for everything in AppKit)......
Build failed (169 errors)
I'm looking for 1 of 2 solutions:
Obviously, fix the release build to not get these errors
OR
Tweak the debug configuration to have all the important settings that a release configuration requires.
Any ideas??
This
-c /System/Library/Frameworks/AppKit.framework/Headers/AppKit.h
leads me to believe your build target is trying to compile AppKit.h for some reason (while I don't think it should be doing that at all), and/or it's looking for it in the wrong place (i.e. in the root /System instead of in the SDK /Developer/Platforms/...).
You should double check your build settings library/frameworks search paths, and that AppKit.h isn't in the compile phase.
Does your project include Mac OS products? Are you sure you haven't accidently included a Mac library/framework in your frameworks group?
In SDK2.2.1, I don't know why, but the thing that always gets me is when "Active SDK" and "Active Executable" become out of sync (in the build configuration dropdown). This leads to weird linker errors where the iPhone tries to dynamically link against its libraries. This setting seems to occasionally go out of sync whenever I switch from debug/release or device/simulator.
Perhaps its a similar case, its hard to tell without seeing the actual project settings.