Xamarin iOS Objective-C library binding - Build errors when creating a fat binary using "make" command - objective-c

I'm trying to create a Xamarin iOS binding for this Objective C library SPSlideTabController.
I have created a static library and am now in the process of creating a fat binary. I have the Makefile set up correctly and saved in the same folder as my static library. Not inside the static library folder though. Then I run the make command in the terminal.
Each time I have tried, only one file is generated libSPSlideTabController-i386.a then I get 4 build errors:
** BUILD FAILED **
The following build commands failed:
CompileC build/SPSlideTabBarController.build/Release-iphoneos/SPSlideTabBarController.build/Objects-normal/armv7/SPAppearance.o SPSlideTabBarController/Appearance/SPAppearance.m normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler
CompileC build/SPSlideTabBarController.build/Release-iphoneos/SPSlideTabBarController.build/Objects-normal/armv7/SPSlideTabBarItem.o SPSlideTabBarController/SPSlideTabBar/SPSlideTabBarItem.m normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler
CompileC build/SPSlideTabBarController.build/Release-iphoneos/SPSlideTabBarController.build/Objects-normal/armv7/SPSlideTabBar.o SPSlideTabBarController/SPSlideTabBar/SPSlideTabBar.m normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler
CompileC build/SPSlideTabBarController.build/Release-iphoneos/SPSlideTabBarController.build/Objects-normal/armv7/SPSlideTabBarController.o SPSlideTabBarController/SPSlideTabBarController.m normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler
(4 failures)
make: *** [libSPSlideTabBarController-armv7.a] Error 65
The ---armv7.a and the ---SDK.a files are not generated.
What am I doing wrong?
Here's my Makefile
XBUILD=/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild
PROJECT_ROOT=./SPSlideTabBarController
PROJECT=$(PROJECT_ROOT)/SPSlideTabBarController.xcodeproj
TARGET=SPSlideTabBarController
all: lib$(TARGET).a
lib$(TARGET)-i386.a:
$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphonesimulator
-configuration Release clean build
-mv $(PROJECT_ROOT)/build/Release-iphonesimulator/lib$(TARGET).a $#
lib$(TARGET)-armv7.a:
$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch
armv7 -configuration Release clean build
-mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $#
lib$(TARGET)-arm64.a:
$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch
arm64 -configuration Release clean build
-mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $#
lib$(TARGET).a: lib$(TARGET)-i386.a lib$(TARGET)-armv7.a
lib$(TARGET)-
arm64.a
xcrun -sdk iphoneos lipo -create -output $# $^
clean:
-rm -f *.a *.dll

It's better that you share your MAKE file.
I normally open the code in XCode then add a runscript using my GIST here
You could follow this guide for more details.

Related

iOS 14, lipo error while creating library for both device and simulator

We have been using lipo command to create a framework which works on both device and simulator when integrated in other project.
following are the build commands used to generate device and simulator builds
xcodebuild -target SampleSDK ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" OBJROOT="${OBJROOT}/DependentBuilds"
xcodebuild -target SampleSDK ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" OBJROOT="${OBJROOT}/DependentBuilds"
after this we are copying swift modules from iphonesimulator(if it exists) to the copied framework dir
cp -R "$BUILD_DIR/${CONFIGURATION}-iphonesimulator/${PRODUCT_NAME}/Modules/SampleSDK.swiftmodule/" "${UNIVERSAL_OUTPUTFOLDER}/${PRODUCT_NAME}/Modules/${PROJECT_NAME}.swiftmodule/"
and then lipo command
lipo -create "$BUILD_DIR/${CONFIGURATION}-iphonesimulator/${PRODUCT_NAME}/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PRODUCT_NAME}/${PROJECT_NAME}" -output "${UNIVERSAL_OUTPUTFOLDER}/${PRODUCT_NAME}/${PROJECT_NAME}"
the above command is failing with following error
fatal error: lipo: /path/to/Library/Developer/Xcode/DerivedData/Sample-bhfmlauxsdympmdjkjyvujaljevg/Build/Products/Debug-iphonesimulator/SampleSDK.framework/SampleSDK and /Users/rramshettysiddaraju/Library/Developer/Xcode/DerivedData/Sample-bhfmlauxsdympmdjkjyvujaljevg/Build/Products/Debug-iphoneos/SampleSDK.framework/SampleSDK have the same architectures (arm64) and can't be in the same fat output file
I tried one of the answers in stackoverflow, about adding user-defined setting VALID_ARCHS and then removing it. but that didnt work
The reason for the error is that Xcode 12 includes a slice for the "arm64" architecture when building for the simulator (in addition to the usual "i386" and "x86_64" architectures for Xcode <12). This is probably for supporting the simulator on (future) Macs using Apple Silicon processors. As your device build also includes the "arm64" architecture, lipo does not know which of the two "arm64" slices you want and refuses to create a combined fat binary framework.
As a workaround, you can either exclude the "arm64" architecture from the simulator build by appending the EXCLUDED_ARCHS build variable:
xcodebuild -target SampleSDK ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" OBJROOT="${OBJROOT}/DependentBuilds" EXCLUDED_ARCHS="arm64"
Alternatively, use lipo -remove to remove the "arm64" architecture from the simulator build before combining the simulator and device frameworks into one:
lipo -remove arm64 "$BUILD_DIR/${CONFIGURATION}-iphonesimulator/${PRODUCT_NAME}/${PROJECT_NAME}" -output "$BUILD_DIR/${CONFIGURATION}-iphonesimulator/${PRODUCT_NAME}/${PROJECT_NAME}"
In the long run, you might be better off building an XCFramework, which should support devices and simulators without the need for using lipo. But I haven’t tested this yet.
styv is right.
You can also set Excluded Architectures in the Xcode Build Settings
#xtyv's suggestion is spot on: using an XCFramework is the way to go.
Here is a Makefile to generate an XCFramework (apply substitutions and add other architectures accordingly to your scenario):
ARCHS = aarch64-apple-ios aarch64-apple-ios-sim
LIB = lib<library_name>.a
XCFRAMEWORK = <framework_name>-iOS.xcframework
all: $(XCFRAMEWORK)
.PHONY: $(ARCHS)
$(ARCHS): %:
cargo build --target $#
$(XCFRAMEWORK): $(ARCHS)
xcodebuild -create-xcframework $(addprefix -library , $(foreach arch, $(ARCHS),$(wildcard target/$(arch)/debug/$(LIB)))) -headers <header_file> -output $#

Xcodebuild calling test but never running

I'm trying to run tests with the xcodebuild command line in this way ("Ink" is my project):
xcodebuild test -target "Ink" -sdk iphonesimulator TEST_AFTER_BUILD=YES "VALID_ARCHS=armv6 armv7 i386" -arch i386
but the command prompt give me the result:
unsupported build action 'test' - ** TEST FAILED **
What command is missing?
I guess that the command You try to run is badly ordered (the action You want to execute should always be at the end), try:
xcodebuild -target "Ink" -sdk iphonesimulator TEST_AFTER_BUILD=YES "VALID_ARCHS=armv6 armv7 i386" -arch i386 clean test
I also suppose it may be simplified to:
xcodebuild -target "Ink" -sdk iphonesimulator clean test
Which version of xcodebuild You use? Prior to 5.0 it was impossible to execute test action from command line.

Objective C Library and Search Path

I created a static library in Objective C (for OSX) for performing some calculations. I then compiled it and included it in another project. Later on I'm not able to use it in my codes.
1> When I wrote
import "Auth.h"
it was giving me a File Not Found error. Why is it so?
2> Then I had to set the search path to the source of the libraries and it got compiled and executed correctly. Does that mean I can't reuse the compiled library with other projects without distributing the source code along with it?
3> I thought if Search path is being specified then the compiled library won't need to be needed. So I deleted the library. But that didn't work. It means source + the library both are required.
What is actually happenning. I just want to distribute libAuth.a with other teams for the project without giving out the source. How can I do that.
You just need to provide the library file (.a) and the header files; the source files can remain private and undistributed.
Be sure to compile the library for all architectures (x86_64 and i386 on OSX) that can possibly use the library, using lipo to create a fat binary .a file.
For example:
xcrun --sdk macosx10.8 clang -arch x86_64 -o file1.o file1.m
xcrun --sdk macosx10.8 clang -arch x86_64 -o file2.o file2.m
xcrun --sdk macosx10.8 libtool -static -arch_only x86_64 -o libmystuff_x86_64.a file1.o file2.o
xcrun --sdk macosx10.8 clang -arch i386 -o file1.o file1.m
xcrun --sdk macosx10.8 clang -arch i386 -o file2.o file2.m
xcrun --sdk macosx10.8 libtool -static -arch_only i386 -o libmystuff_i386.a file1.o file2.o
xcrun --sdk macosx10.8 lipo -arch x86_64 libmystuff_x86_64.a -arch i386 libmystuff_i386.a -create -output libmystuff.a
Try adding the followings in your main project target settings;
”-ObjC” and ”-all_load” to Build Settings > Linking > Other Linker Flags,
”$(TARGET_BUILD_DIR)/usr/local/lib/include” and ”$(OBJROOT)/UninstalledProducts/include” to Build Settings > Search Paths > Header Search Paths,
"$(BUILT_PRODUCTS_DIR)" to Build Settings > User Header Search Paths.

Compile Mach-o arm object file

Im trying to compile a mach-o arm object file to mach-o arm executable using the command line. I have used various commands like these
clang -arch armv7 helloapp.o -o helloapp
clang helloapp.o -o helloapp
gcc helloapp.o -o helloapp
They all return different errors saying compiling for wrong architecture or missing neccessary files. What is the command I need to compile this properly??
The default compilers (the ones in your $PATH) reference the ones that can compile for your local machine. You need a cross-compiler that knows how to create ARM binaries. If you've got Xcode with iOS SDK installed you can use for example:
PATH_TO_Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc
or
PATH_TO_Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
For example, on my machine:
ARM_GCC=~/Documents/Xcode4.6.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc
IOS_SDK=~/Documents/Xcode4.6.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk
# Compile
$ARM_GCC -arch armv7 -c test.c -o test.o
# Link
$ARM_GCC -arch armv7 -isysroot "$IOS_SDK" test.o -o test
If I then run file test I get:
test: Mach-O executable arm

How do I extract object files from an iOS library (on a Mac)?

I have a third party iOS library that links and runs fine in my app and in the simulator. I am trying to extract the object files from it in order to integrate it with another piece of third party software that repackages the object files with their own code. However, I am unable to extract the object files via ar; I consistently get the error, "Inappropriate file type or format".
The library in question is a fat library with armv7, armv7s, and i386 included. Stock lipo doesn't know about armv7s on my machine, but Xcode's does:
$ lipo -info library.a
Architectures in the fat file: library.a are: armv7 (cputype (12) cpusubtype (11)) i386
$ xcrun -sdk iphoneos lipo -info library.a
Architectures in the fat file: library.a are: armv7 armv7s i386
I can successfully thin it out with lipo:
$ xcrun -sdk iphoneos lipo library.a -thin armv7 -output library-armv7.a
$ xcrun -sdk iphoneos lipo -info library-armv7.a
Non-fat file: library-armv7.a is architecture: armv7
However, even after thinning it out, I can't manipulate it with ar:
$ xcrun -sdk iphoneos ar -tv library-armv7.a
ar: library-armv7.a: Inappropriate file type or format
$ xcrun -sdk iphoneos ar -xv library-armv7.a
ar: library-armv7.a: Inappropriate file type or format
I'm on OS X 10.8.2, Xcode 4.6 with development tools installed.
Is there any additional step I can take for this troublesome library?
Update in response to Martin's comment
file shows the following:
$ file library.a
library.a: Mach-O universal binary with 3 architectures
library.a (for architecture armv7): Mach-O object arm
library.a (for architecture cputype (12) cpusubtype (11)): Mach-O object arm
library.a (for architecture i386): Mach-O object i386
$ file library-armv7.a
library-armv7.a: Mach-O object arm
Looks like it's not a library at all!
The "library" is not actually a library, but is an object file itself. There is nothing further to extract.
This script works well. Try it.
https://code.google.com/p/ompt-intel-openmp/source/browse/itt/libomp_oss/tools/extract-objects.pl