Programmatically getting the architecture info `file` produces on macOS? - macos

On macOS, is there any way to programmatically get (from C or Swift) the same architecture info that file produces when run on an executable? E.g.:
$ file /Library/Audio/Plug-Ins/HAL/ACE.driver/Contents/MacOS/ACE
/Library/Audio/Plug-Ins/HAL/ACE.driver/Contents/MacOS/ACE: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit bundle x86_64] [arm64:Mach-O 64-bit bundle arm64]
/Library/Audio/Plug-Ins/HAL/ACE.driver/Contents/MacOS/ACE (for architecture x86_64): Mach-O 64-bit bundle x86_64
/Library/Audio/Plug-Ins/HAL/ACE.driver/Contents/MacOS/ACE (for architecture arm64): Mach-O 64-bit bundle arm64
$ file `which plutil`
/usr/bin/plutil: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
/usr/bin/plutil (for architecture x86_64): Mach-O 64-bit executable x86_64
/usr/bin/plutil (for architecture arm64e): Mach-O 64-bit executable arm64e
I know I can invoke file from my code, but I’m looking for a library call I can make.

Related

Linking against XCode dylibs with Python ctypes

I am installing Pyglet as a dependency for VisPy but am seeing the following error after installation
File "/Library/Python/2.7/site-packages/pyglet/lib.py", line 160, in load_library
raise ImportError('Library "%s" not found.' % names[0])
ImportError: Library "c" not found.
Digging through the source code, I realized that Pyglet is attempting to load the standard C library using the ctypes framework.
Further digging reveals the actual (un-swallowed) error:
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 365, in __init__
self._handle = _dlopen(self._name, mode)
OSError: dlopen(/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib/libc.dylib, 6): no suitable image found. Did find:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib/libc.dylib: mach-o, but wrong filetype
The issue, I think, is similar to this question where there is an architecture mismatch. The Python C binding framework 'ctypes' is attempting to load a .dylib with the wrong architecture.
Since I have set $LD_LIBRARY_PATH to
/Applications.../MacOSX10.10.sdk/usr/lib/
the loader is favoring this directory. However, if I try to load 'libc.dylib' from the standard location /usr/lib everything works perfectly.
The obvious potential problem is that the XCode version of 'libc' is for the 32-bit architecture but the /usr/lib is for the 64-bit architecture.
Not true!
Here is the output of file for both libraries:
XCode version
libc.dylib: Mach-O universal binary with 2 architectures
libc.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library stub x86_64
libc.dylib (for architecture i386): Mach-O dynamically linked shared library stub i386
and the standard in /usr/lib
/usr/lib/libc.dylib: Mach-O universal binary with 2 architectures
/usr/lib/libc.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
/usr/lib/libc.dylib (for architecture i386): Mach-O dynamically linked shared library i386
The only difference is that the XCode version is a "stub". Despite some googling, the difference is not entirely clear, though it appears that the difference between a "stub" dylib and a "non-stub" is what is causing the problem.
A bit more information about my setup:
/usr/bin/python : Python 2.7.10 and appears to be running as a 64-bit app
uname -a: Darwin x-10-104-106-204.uofm-secure.wireless.umn.edu 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64
My question is thus how does one properly link against the dylibs installed by XCode?
Thanks in advance for all ideas and suggestions.

How to build fat gcc46 libstdc++ on OS X?

I have successfully built and installed gcc 4.6.1 on my OS X box, but I can't seem to get it to create a fat/universal libstdc++ library for me. How do I make it do that?
The default /usr/lib/libstdc++.6.dylib supports the following architectures:
[host:~] nsteiner% file /usr/lib/libstdc++.6.dylib
/usr/lib/libstdc++.6.dylib: Mach-O universal binary with 3 architectures
/usr/lib/libstdc++.6.dylib (for architecture i386): Mach-O dynamically linked shared library i386
/usr/lib/libstdc++.6.dylib (for architecture ppc7400): Mach-O dynamically linked shared library ppc
/usr/lib/libstdc++.6.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
I would like for gcc to give me a /usr/local/lib/libstdc++.6.dylib for those same architectures, but my attempts to configure with --enable-multilib or --with-multilib-list=i386,ppc,x86_64 or --enable-targets=all were clearly misguided. Neither configure nor make generate errors, but all that gets generated is this:
[host:~] nsteiner% file /usr/local/lib/libstdc++.6.dylib
/usr/local/lib/libstdc++.6.dylib: Mach-O 64-bit dynamically linked shared library x86_64
Only Apple's GCC 4.2.1 still supports fat binaries. You'll have to take additional manual steps (or provide damn good wrapper scripts) to compile all sources twice, and run lipo on the resulting binaries.

libiconv.2.dylib Mac OS X Problem

I have a problem with the important file libiconv.2.dylib. When I want to start some applications (like macvim, etc.) i get this error:
dyld: Library not loaded: /usr/lib/libiconv.2.dylib
Referenced from: /Applications/MacVim.app/Contents/MacOS/Vim
Reason: no suitable image found. Did find:
/usr/lib/libiconv.2.dylib: mach-o, but wrong architecture
/usr/lib/libiconv.2.dylib: mach-o, but wrong architecture
Trace/BPT trap
Is there any way to restore (no time machine available) or recompile this library for Mac (10.6)?
You appear to have a mismatch between architectures. The system library libiconv should be a universal file that contains all necessary archs; on OS X 10.6, Apple ships it with three.
$ file /usr/lib/libiconv.2.dylib
/usr/lib/libiconv.2.dylib: Mach-O universal binary with 3 architectures
/usr/lib/libiconv.2.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
/usr/lib/libiconv.2.dylib (for architecture i386): Mach-O dynamically linked shared library i386
/usr/lib/libiconv.2.dylib (for architecture ppc7400): Mach-O dynamically linked shared library ppc
Try something similar for the MacVim.app executable:
$ file /Applications/MacVim.app/Contents/MacOS/Vim
There needs to be at least one common architecture and the app needs to be running in one of those common archs. Make sure you have a current version of the app. If the libiconv does not have all of those architectures, your system installation of OS X 10.6 is faulty. Perhaps you tried to install something into /usr/lib? Don't do that. If so, you may need to carefully reinstall OS X 10.6.

On OS X, how do I find out what architecture a shared lib is compiled for?

I need to know whether I compiled libjpeg for 32 or 64 bits architecture, but don't know how to find out, is there a command that will let me check?
just type file libjpeg.dylib and you'll get output like the following
libpoll.dylib: Mach-O universal binary with 3 architectures
libpoll.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
libpoll.dylib (for architecture i386): Mach-O dynamically linked shared library i386
libpoll.dylib (for architecture ppc7400): Mach-O dynamically linked shared library ppc
The file command will work just fine. Alternatively, you can use
otool to print the fat headers.
$ otool -vf /usr/lib/libSystem.B.dylib
Fat headers
fat_magic FAT_MAGIC
nfat_arch 2
architecture ppc
cputype CPU_TYPE_POWERPC
cpusubtype CPU_SUBTYPE_POWERPC_ALL
offset 4096
size 2221800
align 2^12 (4096)
architecture ppc64
cputype CPU_TYPE_POWERPC64
cpusubtype CPU_SUBTYPE_POWERPC64_ALL
offset 2228224
size 2169980
align 2^12 (4096)
Use the file command:
[mqudsi#iqudsi:Xcode/FSLogger]$ file ./original (07-31 02:53)
./original: Mach-O executable i386

How to build mach-0 for different architectures?

I have some dylibs to load from python with ctypes. I can load libbass.dylib without problem, but I can't load the self-compiled libmp3lame.dylib. Here is the error I get.
OSError: dlopen(libmp3lame.dylib, 6):
no suitable image found. Did find:
libmp3lame.dylib: mach-o, but wrong
architecture
Then, I inspect the file type of those libs. Here is the result of libbass.dylib:
libbass.dylib: Mach-O universal binary with 2 architectures
libbass.dylib (for architecture i386): Mach-O dynamically linked shared library i386
libbass.dylib (for architecture ppc): Mach-O dynamically linked shared library ppc
And here is the self-compiled one:
libmp3lame.dylib: Mach-O 64-bit dynamically linked shared library x86_64
I did compile the lame library with the install instructions:
./configure
make
make install
I'm new to mac system, here comes the problem: how to build the libmp3lame.dylib so that it supports different architecture I want?
Thanks.
Just run:
CFLAGS="-arch i386 -arch x86_64 -arch pcc" ./configure
For further information, see http://developer.apple.com/library/mac/#technotes/tn2005/tn2137.html

Resources