I noticed on mac that some of my shared objects (dylib) are binaries with two architectures. I believe this can be achieved by separately compiling for i386 and x86_64, then using the lipo utility to create the universal executable
$ file /usr/lib/libpoll.dylib
/usr/lib/libpoll.dylib: Mach-O universal binary with 2 architectures
/usr/lib/libpoll.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
/usr/lib/libpoll.dylib (for architecture i386): Mach-O dynamically linked shared library i386
However as far as I have spot checked .dll files on my windows system, they are all of one architecture. Here are some ways to check the architecture a .dll was compiled for
Is there a way I can compile a single .dll file for two different architectures (ex. both x86_64 and i386)?
In Mac OS you can compile what is know as a fat binary or a multi architecture binary. That is not available in Windows. Unmanaged PE executable files are either 32 bit or 64 bit, but never both.
On the other hand, .net assemblies can be compiled for AnyCPU and will adapt to the bitness of their host.
But for unmanaged modules, it is one or the other.
Related
Is it possible to compile to x86 using gcc on an ARM machine? I can't find any -march option which would allow this to be done.. if it can't be done, no big deal, but I'm still interested to know if it's possible.
Yes, but you don't want a -march machine. You want to build or install a cross compiler with arm as the host architecture and x86 as the target architecture.
Typically (assuming a linux os) you might get binaries like x86_64-linux-gnu-gcc for the compiler and x86_64-linux-gnu-g++ for the C++ compiler.
Building Gcc cross compilers is a bit of an art, but the gcc documentation is reasonably good.
No. Its because cross compiler(including clang) can generate binaries from host gcc for a target. There is no compiler which can generate x86 instructions from arm.
I have compiled armv7 static libraries (lib*.a) and i'm going to compile iPad Air app (arm64).
I'm getting linker warning and then linker error:
$ lipo -info /Users/user/Documents/dev/src/iOS_Projects/iProject/libMyLib.a
input file /Users/user/Documents/dev/src/iOS_Projects/iProject/libMyLib.a is not a fat file
Non-fat file: /Users/user/Documents/dev/src/iOS_Projects/iProject/libMyLib.a is architecture: armv7
Ld: warning: ignoring file /Users/user/Documents/dev/src/iOS_Projects/iProject/libMyLib.a, file was built for archive which is not the architecture being linked (arm64): /Users/user/Documents/dev/src/iOS_Projects/iProject/libMyLib.a ignoring file
It's undesirable (and can be impossible) to recompile static libs for arm64. How can i use them?
With difficulty.
You can only switch between AArch32 state and AArch64 state at an exception boundary, so whilst e.g. 64-bit kernel/32-bit userspace is possible, it's impossible to use both in a single process. Since it's an entirely different instruction set/register layout/exception model/etc. there's no 32/64-bit interworking in the style of ARM/Thumb (which are essentially just different encodings of the same instructions).
In general (I'm not familiar with iOS specifics, but I assume it supports "legacy" AArch32 processes as Linux does):
If the libraries are completely integral to your code, your best bet is to simply give in and compile your app as 32-bit.
If you have super-crucial-absolutely-must-be-64-bit code but the library calls are not in the fast path, you could compile them into a 32-bit helper program that you spawn as an additional process and call via some form of IPC.
Otherwise you're looking at the ridiculously impractical prospect of some form of binary translation.
I gather that iOS offers no support for IPC, which rather rules out the second option in this particular case.
I made a cross compiling toolchain for arm-gcc, configuring binutils, newlib, gcc and gdb for the arm-elf target. The problem I am having is, when I compile a program with arm-elf-gcc on my Mac, it generates a 32 bit executable with cannot be executed in the 64 bit environment.
What is the easiest way to circumvent this? I could place the 32 bit executables to an arm environment, but I am interested to know if I could execute the file in my Mac in any way?
--Added--
I should have done this before, but let me inform that the target of my program is a Beagleboard, and I was expecting that I would compile and generate the objects using arm-gcc on my Mac OS X and transfer the *.o to the Beagleboard to view output. Alas, it gives the same error on the Beagleboard as well when I do a ./hello.o.
Thanks,
Sayan
There are several issues preventing you from running your executable on a Mac.
1) Architecture. Your Mac is probably an x86/x86_64 machine (or PowerPC) but your binary is compiled for ARM architecture (which is the whole point of using a cross-compiler). These instruction sets are not compatible.
2) Your binary is linked as an ELF object file, whereas Macs use the Mach-O object file format. Your OS cannot load this executable format.
3) Your executable is linked against newlib (for some target which is probably not Mac OS) instead of the Mac OS libc. Your system calls are not correct for this platform.
If your program is a standard unix executable, you may be able to simply compile it with the standard system gcc and it will run. Otherwise, you can run it in an ARM emulator, though this may be pretty complicated to set up.
The fact that it's 32-bit is irrelevant - you can't execute ARM code on a Mac (unless you can find some kind of ARM emulator).
What are the differences between compiling a Mac app in Xcode with the Active Architecture set to i386 vs x86_64 (chosen in the drop down at the top left of the main window)? In the Build settings for the project, the Architecture options are Standard (32/64-bit Universal), 32-bit Universal, and 64-bit Intel. Practically, what do these mean and how does one decide?
Assume one is targeting OS X 10.5 and above. I see in the Activity Monitor that compiling for x86_64 results in an app that uses more memory than one compiled for i386. What is the advantage? I know 64-bit is "the future", but given the higher memory usage, would it make sense to choose 32-bit ever?
32/64-bit Universal -- i386, x86_64, ppc
32-bit Universal -- i386, ppc
64-bit Intel -- 64 bit Intel only
ppc64 is no longer supported.
x86_64 binaries are faster for a number of reasons; faster ABI, more registers, on many (most & all new machines) machines the kernel is 64 bit & kernel calls are faster, etc.etc.etc...
While 64 bit has a bit of memory overhead directly related, generally, to how pointer heavy your app's data structures are, keep in mind that 32 bit applications drag in the 32 bit versions of all frameworks. If yours is the only 32 bit app on the system, it is going to incur a massive amount of overhead compare to the 64 bit version.
64 bit apps also enjoy the latest and greatest Objective-C ABI; synthesized ivars, non-fragile ivars, unified C++/ObjC exceptions, zero-cost #try blocks etc... and there are a number of optimizations that are only possible in 64 bit, too.
iOS apps need to run on many different architectures:
arm7: Used in the oldest iOS 7-supporting devices[32 bit]
arm7s: As used in iPhone 5 and 5C[32 bit]
arm64: For the 64-bit ARM processor in iPhone 5S[64 bit]
i386: For the 32-bit simulator
x86_64: Used in 64-bit simulator
Xcode basically emulates the environment of 32 bit or 64 bit based on what is set in the Valid Architecture - i386 or x86_64 respectively
Every architecture requires a different binary, and when you build an app Xcode will build the correct architecture for whatever you’re currently working with. For instance, if you’ve asked it to run in the simulator, then it’ll only build the i386 version (or x86_64 for 64-bit).
Unless you have a reason to compile for x86_64, I recommend just compiling for i386 (and PPC if you support that). Read Apple's stance on the matter:
Although 64-bit executables make it
easier for you to manage large data
sets (compared to memory mapping of
large files in a 32-bit application),
the use of 64-bit executables may
raise other issues. Therefore you
should transition your software to a
64-bit executable format only when the
64-bit environment offers a compelling
advantage for your specific purposes.
I have a Fortran program, which I can compile using f77, f95 or ifort on all the three operating systems that I have (they are i386, ia64 and x86_64 systems). However, I want to be able to compile only two types of executables, so that I can share the program and not the code. When I compile on one of the computers and try running the compiled binary on another I get the error message cannot execute binary file. Does anyone have any idea what can I do about this?
If you want the machines to run them natively, you can't do this. You've got three different architectures, so you need three different binaries.
However, x86_64 (more commonly called amd64) does have the ability to run i386 code, with a slight performance penalty. So if you're willing to give up 64-bit-ness, you could theoretically give up the amd64 binary and just use the i386 one on that machine. You will need to install the i386 emulation environment on the machine to make this work.
It's possible that ia64 supports something similar; I don't know ia64.