如何在Linux下使用osxcross交叉编译Mac程序


如何在Linux下使用osxcross交叉编译Mac程序

osxcross在新窗口打开是一款为Linux提供的针对MacOS的交叉工具链,支持x86、x86_64、arm、arm64等多种输出架构,非常方便。

安装osxcross

安装基础工具

sudo apt-get update
sudo apt-get install clang llvm libxml2-dev uuid-dev libssl-dev bash patch make tar xz-utils bzip2 gzip sed cpio unzip rsync git libbz2-dev

clone osxcross代码

git clone https://github.com/tpoechtrager/osxcross.git
cd osxcross

下载MacOS SDK

我们需要一个合适的MacOS SDK,这两个仓库都有下载:

我下载的是MacOSX12.0.sdk.tar.xz,把这个文件扔到tarballs目录下。

编译osxcross

在代码目录下运行./build.sh即可,需要等待一会:

./build.sh

如果编译没有问题的话,会在target目录下生成相应的工具链等:

target/
├── bin
├── include
├── lib
├── libexec
├── SDK
├── share
└── toolchain.cmake

另外,可以类似设置一下环境变量:

export PATH=/opt/cross-tools/osxcross/target/bin:$PATH

测试

可以随便写一个hello world,然后使用 target/bin 目录中的 o64-clango64-clang++来编译一下试试。

和vcpkg如何结合使用

因为我的代码都是使用vcpkg在新窗口打开来安装第三方包的,目前vcpkg没有针对osxcross的triplet,因此我们可以添加一下。

vcpkg/triplets/目录下,分别添加arm64-osx-osxcross.cmakex64-osx-osxcross.cmake两个文件,内容分别是:

# arm64-osx-osxcross.cmake
set(VCPKG_TARGET_ARCHITECTURE arm64)
set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)

set(ENV{OSXCROSS_HOST} "arm64-apple-darwin21.1")
set(ENV{OSXCROSS_SDK} "MacOSX12.0.sdk")
set(ENV{OSXCROSS_TARGET} "darwin21.1")

# 寻找编译器的完整路径
find_program(ARM64_APPLE_DARWIN_CC arm64-apple-darwin21.1-cc)

if(NOT ARM64_APPLE_DARWIN_CC)
  message(FATAL_ERROR "无法找到 arm64-apple-darwin21.1-cc 编译器")
endif()

# 从找到的编译器路径中提取目录
get_filename_component(OSXCROSS_TARGET_BIN_DIR "${ARM64_APPLE_DARWIN_CC}" DIRECTORY)
# 设置 OSXCROSS_TARGET_DIR
# 假设 toolchain.cmake 在编译器目录的上一级目录中
set(OSXCROSS_TARGET_DIR "${OSXCROSS_TARGET_BIN_DIR}/..")

# 环境变量设置
set(ENV{OSXCROSS_TARGET_DIR} "${OSXCROSS_TARGET_DIR}")

# 设置 VCPKG_CHAINLOAD_TOOLCHAIN_FILE
set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "${OSXCROSS_TARGET_DIR}/toolchain.cmake")
# x64-osx-osxcross.cmake
# 寻找编译器的完整路径
find_program(X86_64_APPLE_DARWIN_CC x86_64-apple-darwin21.1-cc)

if(NOT X86_64_APPLE_DARWIN_CC)
  message(FATAL_ERROR "无法找到 x86_64-apple-darwin21.1-cc 编译器")
endif()

# 从找到的编译器路径中提取目录
get_filename_component(OSXCROSS_TARGET_BIN_DIR "${X86_64_APPLE_DARWIN_CC}" DIRECTORY)

# 基于编译器路径设置 OSXCROSS_TARGET_DIR
set(OSXCROSS_TARGET_DIR "${OSXCROSS_TARGET_BIN_DIR}/..")

# 设置架构和系统信息
set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
set(VCPKG_OSX_ARCHITECTURES x86_64)

# 设置工具链文件路径
set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "${OSXCROSS_TARGET_DIR}/toolchain.cmake")

# 环境变量设置
set(ENV{OSXCROSS_HOST} "x86_64-apple-darwin21.1")
set(ENV{OSXCROSS_SDK} "MacOSX12.0.sdk")
set(ENV{OSXCROSS_TARGET} "darwin21.1")
set(ENV{OSXCROSS_TARGET_DIR} "${OSXCROSS_TARGET_DIR}")

然后就可以使用类似vcpkg install pystring:arm64-osx-osxcross这样来安装依赖包了。

如何和cmake结合

类似如此,指定编译器等参数:

cmake \
	-DVCPKG_TARGET_TRIPLET=x64-osx-osxcross \
	-DCMAKE_SYSTEM_NAME=Darwin \
	-DCMAKE_OSX_ARCHITECTURES=x86_64 \
	-DCMAKE_C_COMPILER=x86_64-apple-darwin21.1-cc \
	-DCMAKE_CXX_COMPILER=x86_64-apple-darwin21.1-c++ \
	-G "Unix Makefiles" \
	-S $(pwd) \
	-B $(pwd)/build