I built FFTW on my Apple m1 computer. When I run lipo -info libfftw3.a (which is located in .libs/libfftw3.a). It says it is of architecture ARM64.
In my Xcode I set the build target to 10.11, for backward compatibility.
Now when I add the FFTW library into my Xcode project, it complains:
The linked library 'libfftw3.a' is missing one or more architectures
required by this target: x86_64.
How can I solve this? Do I need to build the library in an Intel device and create a universal library with these two libraries together (using lipo) or what's the right way to solve this?
You can configure it also with this line and it will build x86_64 & arm64 binary.
./configure CFLAGS="-arch arm64 -arch x86_64 -mmacosx-version-min=11.0"
In order to build a static library for both Intel and Apple silicon archictures, I need to build FFTW for both arch individually and then make an universal library. Here is how I do it.
Go to FFTW root folder
Build for Intel arch
./configure --prefix=/path/to/build/folder/lib-intel CFLAGS="-arch x86_64 -mmacosx-version-min=10.11”
make
make install
Build for arm64
./configure --prefix=/path/to/build/folder/lib-arm64 CFLAGS="-mmacosx-version-min=10.11”
make
make install
Make an universal build
lipo -create path/to/build/folder/lib-intel/libfftw3.a path/to/build/folder/lib-intel/libfftw3.a -output libfftw3_universal.a
Include libfftw3_universal.a in the Xcode project
Related
I'm trying to build a universal binary of ffmpeg on MacOS, by compiling it twice (for arm64 and x86_64) and then using the lipo tool to combine the resulting binaries. I'm on an M1 Mac, so uname -m returns arm64 on my machine.
When running the configure script like so:
./configure --arch=x86_64
It outputs:
install prefix /usr/local
source path .
C compiler gcc
C library
ARCH c (generic)
...
And after running make, inspecting the built binaries with lipo -archs reveals that it's building them for arm64.
The result is the same if I add --enable-crosscompile to the configure call.
Based on this post, I also tried --arch=x86, but that had the exact same result, configure script displayed arch as c (generic) and inspecting artefacts with lipo shows they are built for arm64 architecture.
Does anyone have any ideas? Why is the configure script just refusing to build for x86_64?
You can speify -cc to make clang compile x86_64 binary.
Try:
./configure --enable-cross-compile --prefix=./install_x86_64 --arch=x86_64 --cc='clang -arch x86_64'
Note: don't forget to clear the outdated files by
make distclean
By the way, I have successfully built universal binrary of FFmpeg, you can refer to my build scripts. make_compile.py compile both x86_64 and arm64 binraries, and make_universal.py use lipo to generate universal binrary.
Reference
https://ffmpeg.org/platform.html
https://github.com/FFmpeg/gas-preprocessor
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!
I would like to assemble Aarch64 armv8 Assembly on my mac and eventually run it with qemu and maybe on a real device like a raspberry pi 2 or 4 later on. I don't know how to assemble the code I'm going to write, gcc, llvm-gcc and clang don't seem to support the -arch=armv8 flag or anything similar. So I can't build for the targeted architecture, how could I achieve this?
I'm running mac os 10.14.5. I wouldn't mind finding a solution that works on a recent ubuntu version either since I have a VM for linux development.
The clang version that ships with Xcode supports -arch arm64. (Or armv7 for 32bit.)
Note that if you want to use any libraries though, they'll have to be arm64 as well. If you want, you can invoke the iOS toolchain with xcrun -sdk iphoneos clang -arch arm64 [...], but then you'll also have to pull the libraries you want off of some IPSW and stuff them into qemu.
Also note that the above will give you a Mach-O binary. For your Raspberry Pi, you'll probably want an ELF, and you'll probably want gcc rather than clang. You should be able to build both gcc and GNU binutils from source with --target as either aarch64-linux-gnu or aarch64-none-elf, depending on your goals. Yet another note: since macOS silently aliases gcc to clang and many tools depend on that, you'll probably also want to build this toolchain with something like --program-prefix=aarch64-.
Please help me with issue I break my neck with..
I work with Xcode 4.5.* and I try to build a library with Build Settings:
Architectures: 32-bit Intel
Valid Architectures: *i386 & x86_64*
But after checking the library details with lipo command I see that the actual library is built only for i386
Now I know this works in Xcode <=4.3 - the library is built for both architectures
Thanks
Roman
This may be a very silly question, but I'm new to developing on Macs and am having a hard time with the universal binaries.
I've got an application that I'm compiling in QT Creator, which according to lipo is producing i386 architecture outputs. As I understand it, that means it is producing Mac OS X 32 bit outputs.
The application depends on two external libraries. One of these libraries I'm compiling by calling ./config first, and then make. ./config states that it is "Configured for darwin-i386-cc". However, after running make, and calling lipo on the result, the architecture is reported as x86_64.
Similarly, I have another external library. That one has no configure script, and I compile it simply by calling make. The output from this one too is x86_64.
How can I compile these two external libraries so that they produce something compatible with my application's i386 output? Better yet, how can I compile these two external libraries to produce universal libraries so I can produce a universal binary from my application that works on both 32 and 64 bit?
Also, based on the current state of the Mac world, are there any other platforms that I should be expected to target to create a proper, user-friendly Mac OS X universal binary?
Finally got it working.
In order to control the architecture of the target, I manually went in and edited the Makefiles.
For one of them, I added to the end of the line that starts with CFLAGS: -arch i386 -arch x86_64 -arch ppc
This produced a universal binary.
For the other, when I did the same thing, the compile would error out. I had to cycle through and only put one arch at a time, and then after I produced all three, I called lipo on them with the -create flag to create a universal binary.
for ./configure, you can use this:
./configure CFLAGS="-arch i386 -arch x86_64" CXXFLAGS="-arch i386 -arch x86_64" LDFLAGS="-arch i386 -arch x86_64" --disable-dependency-tracking
--disable-dependency-tracking is important or gcc/g++ will refuse to compile code.
I can't answer the main part of your question, because I always use Xcode rather than make. But as for that last part, if you support OS versions earlier than 10.6, you may need to compile for PowerPC (arch. code "ppc") as well.