Max
Max

Reputation: 15955

Compile binary on arm64 macos for x86_64 linux

I'm trying to compiled a C library using C make. I have three toolchain files:

  1. MacOS arm64
  2. MacOS x86_64
  3. Linux x86_64

The files look like this:

# darwin.arm64.toolchain.cmake
set(CMAKE_SYSTEM_NAME               Darwin)
set(CMAKE_SYSTEM_PROCESSOR          arm64)
set(CMAKE_SYSTEM_VERSION "${CMAKE_HOST_SYSTEM_VERSION}")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER)
# darwin.x86_64.toolchain.cmake
set(CMAKE_SYSTEM_NAME               Darwin)
set(CMAKE_SYSTEM_PROCESSOR          x86_64)
set(CMAKE_SYSTEM_VERSION "${CMAKE_HOST_SYSTEM_VERSION}")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER)
# linux.x86_64.toolchain.cmake
set(CMAKE_SYSTEM_NAME               Linux)
set(CMAKE_SYSTEM_PROCESSOR          x86_64)
set(CMAKE_SYSTEM_VERSION "${CMAKE_HOST_SYSTEM_VERSION}")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER)

My cmake invocation looks something like this: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=${ROOT_DIR}/toolchains/linux.x86_64.toolchain.cmake .

The issue I'm having is that both the MacOS builds work correctly. The linux build, however fails with:

-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - broken
CMake Error at /opt/homebrew/Cellar/cmake/3.25.0/share/cmake/Modules/CMakeTestCCompiler.cmake:70 (message):
  The C compiler

    "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: /Users/maxgale/X/CMakeFiles/CMakeScratch/TryCompile-xBXBOz
    
    Run Build Command(s):/usr/bin/make -f Makefile cmTC_8e560/fast && /Applications/Xcode.app/Contents/Developer/usr/bin/make  -f CMakeFiles/cmTC_8e560.dir/build.make CMakeFiles/cmTC_8e560.dir/build
    Building C object CMakeFiles/cmTC_8e560.dir/testCCompiler.c.o
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc    -MD -MT CMakeFiles/cmTC_8e560.dir/testCCompiler.c.o -MF CMakeFiles/cmTC_8e560.dir/testCCompiler.c.o.d -o CMakeFiles/cmTC_8e560.dir/testCCompiler.c.o -c /Users/maxgale/X/CMakeFiles/CMakeScratch/TryCompile-xBXBOz/testCCompiler.c
    Linking C executable cmTC_8e560
    /opt/homebrew/Cellar/cmake/3.25.0/bin/cmake -E cmake_link_script CMakeFiles/cmTC_8e560.dir/link.txt --verbose=1
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc CMakeFiles/cmTC_8e560.dir/testCCompiler.c.o -o cmTC_8e560 
    ld: library not found for -lSystem
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    make[1]: *** [cmTC_8e560] Error 1
    make: *** [cmTC_8e560/fast] Error 2
    
    

  

  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:3 (project)

What am I missing to get this cross-compile to working?

Upvotes: 1

Views: 727

Answers (1)

Milan Š.
Milan Š.

Reputation: 1628

To me it seems you expect to build a MacOSX binary and expect it to run on a Linux distro. Let's start by a simple distinction between MacOSX and Linux-based operating systems:

MacOSX is Unix-based. For binaries it uses the "Mach-O" format.

Linux is Unix-like. For binaries it uses the ELF format.


Expecting to build a binary for linux without the proper toolchain is probably not going to work out well. I'm judging this by the fact that you are technically only setting "aesthetic" options in CMake. i.e.

set(CMAKE_SYSTEM_NAME               Linux)
set(CMAKE_SYSTEM_PROCESSOR          x86_64)
set(CMAKE_SYSTEM_VERSION "${CMAKE_HOST_SYSTEM_VERSION}")

These don't really do much. For example you need to configure the correct compiler, via e.g.:

set(CMAKE_C_COMPILER ... ) #This should point to a cross-compiler not your standard compiler

You also need to actually point to the correct libraries that the cross compiler should use. None of which you are doing.

As a side note: There is no -lSystem on linux. Most libraries (if not all) are lower-case.


So how do you fix this? Well the easiest way is to get a VM running with the linux kernel. Docker for desktop (on Mac) does this to provide you with docker containers. So if you already have that, you just need a docker container and build in it.

The last option you have is to check out something I found via a quick google search: osxcross on github. And even better (a docker image that handles everything for you): crossbuild on github

Upvotes: 0

Related Questions