How to check a static library is built contain bitcode? - bitcode

I have a static library that is built by other company. I want to know if it's a static library containing bitcode, which command can detect it in terminal?

As it was alread written in other answers,
otool -l yourlib.a | grep __LLVM
is the way to go.
An Apple engineer says using
otool -l yourlib.a | grep bitcode
is not reliable.
Searching for a "bitcode" section is not a reliable way to detect if your files contain embedded bitcode. If you want to do that, search for the "__LLVM" segment. You should be aware that a normal build with the -fembed-bitcode-marker option will produce minimal size embedded bitcode sections without any real content. This is done as a way of testing the bitcode-related aspects of your build without slowing down the build process. The actual bitcode content is included when you do an Archive build.
See also the comments by xCocoa.
It seems, that otool does not report the bitcode if code for the iPhone Simulator's architecture is included (x86_64 or i386).
You can list the lib's architectures with:
lipo -info yourlib.a
Then you can check for bitcode for each architecture separately, e.g:
otool -arch armv7 -l yourlib.a | grep bitcode
otool -arch arm64 -l yourlib.a | grep bitcode

It is recommended to test against LLVM symbols:
otool -l yourlib.a | grep LLVM
You should get some lines with "__LLVM"

Disclaimer: I'm the author of LibEBC.
You can use ebcutil to see whether bitcode is present in a Mach-O binary or library. You can even use it to extract the embedded bitcode from it.
https://github.com/JDevlieghere/LibEBC

And if you want to check if a specific file (yourFile.o) in the static library is bitcode enabled, you can extract the 'staticLibrary.a' and use the same otool command. However macOS doesn't allow to extract your staticLibrary.a at times with the default extract utility and most 3rd party tools doesn't work either.
You can follow these steps to check specific .o files
Get the info of the architecture
lipo -info yourStaticLibrary.a
eg output: armv7 arm64
Extract yourStaticLibrary.a for any or both of the above architecture
lipo yourStaticLibrary.a -thin armv7 -output yourStaticLibraryarmv7.a
(specify the output path you want to extract to)
You get the 'yourStaticLibraryarmv7.a' which then can be easily extracted with the default mac unarchiver
On extracting, you then get a folder 'yourStaticLibraryarmv7' containing all the .o files
otool -l yourFile.o | grep bitcode
or with the specific architecture
otool -arch armv7 -l yourFile.o | grep bitcode
If the file is bitcode enabled , you get 'sectname __bitcode' in the commandline

lipo -info lib.a // Your static library
Check architectures, select your architecture
lipo lib.a -thin arm64 -output lib_arm64.a // Extract your architecture
ar -tv lib_arm64.a // List the files
ar -xv lib_arm64.a yourfile.o // File extracted
otool -arch armm64 -l yourfile.o | grep bitcode
If the file is bitcode enabled, you get 'sectname __bitcode'

You can try:
otool -l (.o or .a file)
and look for "__bitcode" section
It was answered here:
How do I xcodebuild a static library with Bitcode enabled?

Related

How to build openssl for M1 and for Intel?

I have a project which needs to use Libcrypto - and I have two versions of Libcrypto (libcrypto.a (from OpenSSL 1.1.1) built for ARM64) and (lcrypto.a (from OpenSSL 1.0.2) for Intel). Leaving aside the issues of whether it's good practice or not to have two different versions, I can say that if I include libcrypto.a then I can build and run on M1 and it works fine on M1. If I include lcrypto.a then I can build and run on Intel and it works fine on Intel. What I can't do is include them both (linker error - The linked library 'lcrypto.a' is missing one or more architectures required by this target: arm64.) - and if I can't include them both then I can't build a fat binary, and my app is less than entirely useful!
My question is How can I include both in my project - or where can I get (and how can I include) a fat version of Libcrypto? I've looked at this https://github.com/balthisar/openssl-xcframeworks/releases and this https://developer.apple.com/forums/thread/670631 but I'm none the wiser. I think I built a Fat Binary - but the Fat Binary I thought that I built doesn't work for either architecture!
Use command lipo to combine binaries
Compile Intel and ARM versions separately (arm version requires Xcode 12).
export MACOSX_DEPLOYMENT_TARGET=10.9
cp -r openssl-1.1.1t openssl-1.1.1t-arm64
cp -r openssl-1.1.1t openssl-1.1.1t-x86_x64
Build the Intel half
cd openssl-1.1.1t-x86_x64
./Configure darwin64-x86_64-cc shared
make
NOTE: For openssl-1.1.1q use -Wno-error=implicit-function-declaration as a configure parameter
Build the Arm half
export MACOSX_DEPLOYMENT_TARGET=10.15 /* arm64 only with Big Sur -> minimum might be 10.16 or 11.0 */)
cd ../openssl-1.1.1t-arm64
./Configure enable-rc5 zlib darwin64-arm64-cc no-asm
make
NOTE: For openssl-1.1.1q use -Wno-error=implicit-function-declaration as a configure parameter
To create universal binary use command lipo:
cd ..
mkdir openssl-mac
lipo -create openssl-1.1.1t-arm64/libcrypto.a openssl-1.1.1t-x86_x64/libcrypto.a -output openssl-mac/libcrypto.a
lipo -create openssl-1.1.1t-arm64/libssl.a openssl-1.1.1t-x86_x64/libssl.a -output openssl-mac/libssl.a
Verify that resulting binary contains both architectures:
file libcrypto.a libssl.a
libcrypto.a: Mach-O universal binary with 2 architectures: [x86_64:current ar archive random library] [arm64]
libcrypto.a (for architecture x86_64): current ar archive random library
libcrypto.a (for architecture arm64): current ar archive random library
libssl.a: Mach-O universal binary with 2 architectures: [x86_64:current ar archive random library] [arm64]
libssl.a (for architecture x86_64): current ar archive random library
libssl.a (for architecture arm64): current ar archive random library
PS: If you plan to use dynamic library combine dylib files using lipo and run instal_name_tool
cd openssl-mac
install_name_tool -id '#rpath/libcrypto.1.1.1.dylib' libcrypto.1.1.1.dylib
install_name_tool -id '#rpath/libssl.1.1.dylib' libssl.1.1.dylib
otool -D libssl.1.1.dylib /* to verify */
Result:
libssl.1.1.dylib:
#rpath/libssl.1.1.dylib
Even though this question already has an accepted answer, I'd like to mention that I found an easier way to do this that doesn't require using lipo, just in case it helps make someone else's life easier.
The trick is to force it to compile for both architectures simultaneously.
Before calling Configure in the openssl source directory, create a file somewhere convenient (for the purposes of explaining I'll just have it in the home folder) named cc, and have it contain the following text:
#!/bin/bash
if [[ $* == *-arch\ x86_64* ]] && ! [[ $* == *-arch\ arm64* ]]; then
echo Forcing compilation with arm64
cc -arch arm64 $#
else
cc $#
fi
That script will automatically add -arch arm64 to any compilation command that only includes -arch x86_64, and leave all other compilation commands unmodified.
Give it execute permissions:
chmod a+x ~/cc
Then execute the following in your shell to force compilation with this shell script:
export CC=/Users/yourname/cc
Then proceed with configuring and building as though for arm64, but tell it to compile as x86_64:
./Configure enable-rc5 zlib no-asm darwin64-x86_64-cc
make
make install
The resulting static libs and dylibs will already be x86_64 / arm64 universal!

ldd -r equivalent on macOS

I am trying to make my software available on macOS and in my toolchain I use ldd -r MyModel.so to verify is everything went well but I can't really find anything conclusive on macOS that would have the same behaviour.
otool or nm seems the two directions to go but I am not sure how to be sure what options would behave the same. Or is there another tool ?
ldd uses ld to load executable files, and recursively loads
dynamically-linked libraries. So using ldd requires being on the target system
(e.g., Linux). Thus, ldd cannot be used for ELF files on macOS.
Assuming that the question is about analyzing Mach-O files on macOS, I do not know of any tool that works for Mach-O files as ldd does for ELF files.
Both otool and nm perform a static analysis.
A possibility is:
otool -L /usr/bin/true
Relevant:
MacOSX: which dynamic libraries linked by binary?
Inspect and get binary from ELF file on MAC

How to use otool to check if bitcode is enabled

I am playing around with otool now for hour, but I didn't figure out how to get infos, if a binary is bitcode enabled.
It tried the following:
First I build a simple iOS app and run:
otool -arch arm64 -l testApp1 | grep bitcode
After that I downloaded a binary framework from kontakt.io. I am sure that there bitcode is enabled. So I tried:
otool -arch arm64 -l KontaktSDK | grep bitcode
I also got no infos back. Do I something wrong? Is this a bug with the new Xcode8?
The reason why I play around with this is, that I have build a binary framework and I don't know why sometimes the framework is fully bitcode enabled and sometimes it isn't.
According to this answer there's two possible things to check, bitcode and __LLVM.
When I download the KontaktSDK, I can do this:
[.../KontaktSDK.framework]:;otool -arch arm64 -l KontaktSDK | grep __LLVM
segname __LLVM
segname __LLVM

How can I check if a compiled binary is 32-bit or 64-bit?

I have a Mac running Lion and I just downloaded latest version of apache.
I did the usual things:
$./configure --prefix=/Users/daniels/Sandbox
$ make
$ make install
For what architecture is the httpd binary compiled? x86 or x64? Is there a way to find this?
What I am looking for is that I want to make a MAMP-like application and I want to compile Apache, PHP, and MySQL in such way that I can put them in a DMG file and then give it to other people and they can run it.
Check out the file command.
$ file /usr/bin/grep
/usr/bin/grep: Mach-O universal binary with 2 architectures
/usr/bin/grep (for architecture x86_64): Mach-O 64-bit executable x86_64
/usr/bin/grep (for architecture i386): Mach-O executable i386
The lipo binary also does this.
lipo -archs
$ lipo -archs 'Adobe Photoshop Lightroom 5'
x86_64
lipo -info
$ lipo -info 'Adobe Photoshop Lightroom 5'
Non-fat file: Adobe Photoshop Lightroom 5 is architecture: x86_64
An easy way to determine if the Apache is 32-bit or 64-bit is to execute the following in the global zone by using dtrace:
sudo dtrace -qn 'syscall::: /execname == "httpd"/ { ab = (curpsinfo->pr_dmodel == PR_MODEL_ILP32) ? "32-bit" : "64-bit" ; exit(0); } END { printf("Apache: %s",ab); }'

How do i remove the ppc section in growl framework?

Now i add growl notification support into my app ,when i submitted it to mac app store with organizer,it says that
"
Unsupported Architecture - Application executables may support either or both of the Intel architectures:
i386 (32-bit)
x86_64 (64-bit)
"
Finally i find that its issue by growl library, so i need to remove the ppc section in growl,so,how to?
Please help..
Use the lipo command line utility, which strips architectures off fat binaries (what an appropriate name). First, check which architectures there are in your Growl framework:
$ lipo -info path/to/Growl.framework/Growl
Architectures in the fat file: Growl are: x86_64 i386 ppc
In this case, we simply have ppc, but there are about 10 variants (of which I've met 3). To avoid any surprise, you should run this command any time you want to strip architectures from a file instead of just jumping to the removal part. (If you're curious, man 3 arch has the exhaustive list of possible architectures for fat binaries on Mac OS.)
Then, remove the ppc achitecture:
$ lipo -remove ppc path/to/Growl.framework/Growl -output GrowlIntel
Find the real Growl binary (should be under Versions somewhere) and replace it with GrowlIntel.
You can also use "ditto". I submitted my last Mac app with frameworks included that are stripped off ppc support using the two below commands. No rejections from Apple.
$ ditto -rsrc --arch i386 --arch x86_64 Growl-WithInstaller Growl-WithInstaller_noppc
$ lipo -info Growl-WithInstaller_noppc

Resources