distributable OSX binary

distributable OSX binary

Izaak Beekman的头像

Hi,

I found the following article on compiling universal binaries on Mac OS X with the intel compilers:

http://software.intel.com/sites/products/documentation/doclib/stdxe/2013...

However, when I try to run my executable on another apple machine (which is actually 64 bit, as is the machine on which the binary is built) I am getting an "unknown instruction: 4" error. My sources are in Fortran and C but linked with ifort, since Fortran provides the main program. Here is the script I am currently using to build the binaries:

!/bin/bash
# 32 bit
icc -W -trace -g -static-intel -static-libgcc -m32 -c a.c
ifort -warn -trace -g -static-intel -static-libgcc -m32 - wrap_a.f90
ifort -warn -trace -g -static-intel -static-libgcc -m32 -c b.f90
ifort -warn -trace -g -static-intel -static-libgcc -m32 -c main.f90
ifort -warn -trace -g -static-intel -static-libgcc -m32 -o main_32 main.o b.o wrap_a.o a.o
# 64 bit
icc -W -trace -g -static-intel -static-libgcc -m64 -c a.c
ifort -warn -trace -g -static-intel -static-libgcc -m64 -c wrap_a.f90
ifort -warn -trace -g -static-intel -static-libgcc -m64 -c b.f90
ifort -warn -trace -g -static-intel -static-libgcc -m64 -c main.f90
ifort -warn -trace -g -static-intel -static-libgcc -m64 -o main_64 main.o b.o wrap_a.o a.o
# Universal binary
lipo -create -arch i386 main_32 -arch x86_64 main_64 -output main

As I said, the program compiles and runs fine on the machine on which it is built.

  1. Are there any additional flags I need to add? CMake tries to add -arch i386 and -arch x86_64 but at compile time it says that it cannot build with -arch i386.
  2. Do I need to `source compilervars.sh intel32` before I build the 32 bit binary? Right now I am only `source compilervars.sh intel64` for building both executables (32 and 64 bit)
  3. XCode and Intel compilers are not installed on the "target" machine, are there any other libraries that I need to statically link against? (Does -static-intel take care of all the Fortran run-time library(ies) stuff?)
  4. Do I need a specific license/product to achieve this? (This is a hobby project, non-commercial, non-research and I am using the student license for mac os-x as I am a student.)
-Zaak
13 帖子 / 0 new
最新文章
如需更全面地了解编译器优化,请参阅优化注意事项
Casey的头像

Quote:

Izaak Beekman wrote:XCode and Intel compilers are not installed on the "target" machine, are there any other libraries that I need to statically link against? (Does -static-intel take care of all the Fortran run-time library(ies) stuff?)

The program "ldd" will display your dynamic link dependancies and if you goal is an entirely static binary, those are the libraries you'd need to statically link against.  

Izaak Beekman的头像

Ah yes, good idea. No ldd on apple, but otool -L will acheive the same thing. The results are:

/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1669.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

From what little I know about OS X, I think that libSystem.B will always have to be dynamically linked, but it's strange that libgcc is dynamically linked since I passed -static-libgcc in my build script....

-Zaak
Izaak Beekman的头像

Does anyone else have any suggestions? Please see the original post. I would love to have a binary that I could use on other people's computers. I can't seem to get it to link statically against libgcc. I have no idea if this is causing the error or not. Is it possible to compile a binary on mac with ifort and then send it to a different intel mac? (It's a password recall tool for my personal usage, of my own design.)

-Zaak
Steve Lionel (Intel)的头像

I am not at all familiar with the Mac environment, but I don't see how a shared library dependency would turn into an invalid instruction trap. What compile (not link) options did you use on both the Fortran and C code, and what model Mac is the program being executed on? Could it be that the other Mac, while it is 64-bit capable, is running a 32-bit version of OS X?

Steve
Izaak Beekman的头像

Steve,

I'll check the OS when I get home... Even if that were the case though, I *think* I built a 32 bit and 64 bit binary and combined them into a "universal binary" (for Intel Macs) with the lipo tool.

I wish Apple didn't make life so hard with its fancy llvm compilers and dynamic libraries. From their perspective, there is one--and only one--correct way to program for Macs: using the XCode IDE with the Apple supplied compilers.

-Zaak
Steve Lionel (Intel)的头像

Ah, had forgotten about lipo. In any event, I would focus on the invalid instruction aspect of it, which suggests 64-bit code running on a 32-bit system. Can you build a straight 32-bit version? - it should work everywhere.

Steve
Izaak Beekman的头像

Steve,

Since this is my first forray into cross compiling, forgive me for being dense, but I have a few questions:

  1. When I set up my environment for 32 bit compilation do I still `source compilervars.sh intel64` or should it be ia32 (or whatever) isntead of 'intel64'
  2. Other than making sure to statically link as much as possible, could there be any issues with the licensing (student license for this pet project) or additional command line switches that I need to add?
-Zaak
Steve Lionel (Intel)的头像

You should use "ia32" as the argument to the command.

As for licensing - there is no run-time license enforcement and the product is identical to that issued under a commercial license.

Steve
Izaak Beekman的头像

Thanks for the info Steve. I suspect this might have been the issue with the "universal binary". While I built two executables, 'main_64' and 'main_32' specifying the target architecture with -m64 and -m32 respectively, I was compiling from the intel64 environment, not switching it when I was compiling for 32 bit hosts. Hopefully this fixes it. I'll report back later.

As an aside, if I only build the 32 bit version from the 32 bit environment this should work in the Intel 64 bit environment too, right? The advantage of 64 bit, is that the code will be faster, but if run-time is trivial, then there's no need to optimize against the 64 bit hosts, right?

-Zaak
Steve Lionel (Intel)的头像

Re your aside: yes, exactly.

Steve
Izaak Beekman的头像

Problem Solved

For some reason Apple has changed the error messages printed since this article was written, but the contents are still salient. The culprit was -macosx_version_min=10.x needed to be passed to the linker. I guess 'unknown instruction: 4' is a load instruction error. Adding -Wl,-macosx_version_min,10.6 to the (ifort) link line fixed the issue.

Another fun complication is that CMake/cmake-gui has a different search path from the parent shell, so if you set FC=ifort after initializing the intel compilers via the compilervars.sh script, CMake will use /usr/bin/ifort if it exists rather than /opt/intel/Composer_xe... etc. (Use `export FC=$(which ifort)` instead.)

Also, there are two relevant CMake variables that are supposed to help cross compiling on Mac: CMAKE_OSX_ARCHITECTURES and CMAKE_OSX_DEPLOYMENT_TARGET. In theory setting CMAKE_OSX_DEPLOYMENT_TARGET to 10.6 *should* have added -Wl,-macosx_version_min,10.6 to the ifort link line, but CMake's compatibility with Intel compilers + makefile builds seems to be lacking. (It adds the appropriate flags to clang and other native compilers etc.) Also, CMAKE_OSX_ARCHITECTURES does not fully work with ifort. It looks like ifort recognizes the -arch i386 option as a gcc/gfortran compatibility option, but if this variable is set to i386;x86_64 it will try to make ifort build a binary for both in one go, passing -arch i386 *and* -arch x86_64 on the same invocation rather than using the two pass build approach recommended here: http://software.intel.com/sites/products/documentation/doclib/stdxe/2013...

I hope, in the future, someone finds this post helpful and doesn't have to go through the same process I did.

Thanks for everyones help and advice,

-Zaak
Steve Lionel (Intel)的头像

Thanks for the update!

Steve

登陆并发表评论。