ffmpeg refuses to compile for x86_64 arch on M1 mac - ffmpeg

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

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!

Build FFTW for Apple M1 and the older intel devices

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

qmake on OS X: disable x86/i386 arch (build only x86_64)

I'm trying to get qmake to produce a makefile which does not include -arch i386 in CFLAGS/LFLAGS and so far I'm not succeeding. I tried the following:
CONFIG-=x86
QMAKE_CFLAGS-="-arch i386"
and a couple of other variations. The only one that does work is removing x86.prf from mkspecs/features/mac but I don't think it's a proper solution.
The current commandline looks approximately like this:
qmake -makefile -nocache CONFIG-=release CONFIG+=Debug CONFIG+=mac
CONFIG+=CMDMAKE CONFIG-=x86 CONFIG+=x64
QMAKE_MAKEFILE=makefile_mac_Debugx64 QMAKE_LFLAGS="<...>"
QMAKE_CXXFLAGS="<..>" QMAKE_CFLAGS="<...>" QTVER=4.8.4 project.pro
I believe that qmake uses the compiler available in the PATH. If you want to use x86_64 compiler, alter PATH (and possibly INCLUDE, LIB and LIBPATH) environment variables for x86_64 compiler to be available, and then run qmake.
Tentative solution (need to verify a few things to confirm it, but seems to work):
1) make a separate build of Qt for x64 only, i.e.:
./configure -platform macx-g++42 -arch x64 -debug-and-release <...>
2) use qmake from that build to generate x64 makefiles.
It apparently still needs CONFIG-=x86 but that looks to be enough to prevent stray -arch i386 in the generated makefiles.

How to compile universal libraries on Mac OS X?

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.

Building crti.o for i386

I am trying to build a cross-compiler with x86_64 being the host and i386 being the target. I'm getting the (all to common) crti.o: No such file error. Instead of grabbing an already built crti.o and crtn.o from a distro... how might I go about building these files explicitly from glibc (or possibly gcc) sources?
FYI, I am well aware of the -m32 option for x86_64 compilers. I'd prefer to just have a 32bit-only compiler environment. Also, the reason I don't want to use any of the gazillion already build i386 compilers is because I plan on mixing and matching glibc/binutils/gcc versions depending on my testing needs.
Thanks,
Chenz
Here's one possibility (from here)
You need to install your distro's 32
bit libc-dev package, or you need to
--disable-multilib which will result in a compiler that doesn't support 32
bit mode.
Are you sure you're using configuring the cross-compile correctly? It should be
CBUILD = CHOST = x86_64-pc-linux-gnu
CTARGET = i386-pc-linux-gnu
as you're running a build on an x86_64, for a compiler to run on an x86_64, which generates code for an i386.
If you used CHOST = i386-pc-linux-gnu, you'll be trying to generate 32-bit binaries, which will need to link with a 32-bit libc. Which is fine, if you already have a 32-bit libc, but it sounds like you don't.
i.e.
$ tar xvjf gcc-*.tar.bz2
$ cd gcc-*/
$ mkdir build
$ cd build
$ ../configure --build=x86_64-pc-linux-gnu --host=x86_64-pc-linux-gnu --target=i386-pc-linux-gnu

Resources