Unk*_*own 68 c c++ macos cross-compiling
我想将我的C/C++应用程序移植到OS X.
我没有Mac,但我有Linux和Windows.这有什么工具吗?
Vik*_*pov 48
对于Linux,有一个预构建的GCC交叉编译器(来自公开提供的Apple修改后的GCC源代码).
https://launchpad.net/~flosoft/+archive/cross-apple
2015年更新
http://channel9.msdn.com/Events/Visual-Studio/Connect-event-2014/311
对于所有这些选项,您仍然需要一个真正的mac/i设备来测试应用程序.
Tho*_*mas 28
我创建了一个名为OSXCross的项目,旨在从Linux中定位OS X(10.4-10.9).
它目前支持clang3.2到3.8(主干)(你可以使用你的dist clang).
此外,您还可以构建最新的香草GCC(4.6+).  
LTO也适用于两者clang和GCC.
目前使用cctools-870和ld64-242.
https://github.com/tpoechtrager/osxcross
Bri*_*ell 22
似乎已经编写了一些脚本来帮助您为Mac设置交叉编译; 我不能说它们有多好,或者对你的项目有多适用.在文档中,他们参考了10.4的交叉编译这些指令,以及这些指令用于交叉编译10.5; 这些说明可能比脚本更有用,具体取决于脚本符合您的需求的程度.
如果您的程序是免费或开源软件,那么您可能希望创建一个MacPorts端口文件(此处的文档),并允许您的用户使用MacPorts构建您的程序; 这通常是在Mac OS X上安装便携式免费或开源软件的首选方式.过去已知MacPorts可以在Linux上运行,所以有可能在Linux上开发和测试你的Portfile(虽然它显然需要在Mac上测试).
当您尝试在多个平台上运行时,您必须在目标平台上编译/运行/集成/测试.你不能只在一个平台上编译/运行然后说"哦,它应该在另一个平台上工作相同".
即使使用像Java这样非常好的跨平台语言,您也会遇到问题,而在其他平台上它将无法完全相同.
我发现尊重我的时间/生产力/能力以在多个平台上快速迭代的唯一方法是使用其他平台的VM.
还有其他解决方案,如双启动和我没有提到的解决方案,但我发现它们不尊重我的生产力/时间.
以双启动为例:
BAM有30分钟的时间,我没有做任何有成效的事情.
对于这个项目,我们将从编译 LibreSSL 开始。之所以选择它,是因为它提供了 CMake 构建选项,并且应该从 C 源代码生成一个静态和共享的库,该库通常是跨平台的,这将作为可以完成的演示。
Xcode 是Apple 的工具链和IDE。然而,我们只需要从捆绑包中获取 SDK。假设您可以使用 Xcode 访问 Mac,您可以快速获取 SDK。
要确定您使用 xcrun 的 SDK 版本,例如 iphoneos、iphonesimulator 或 macosx。
% xcrun --sdk macosx --show-sdk-version
13.3
Xcode 安装在哪里?
% xcode-select --print-path
/Applications/Xcode.app/Contents/Developer
有哪些平台可用?
% ls -1 $(xcode-select --print-path)/Platforms
AppleTVOS.platform
AppleTVSimulator.platform
DriverKit.platform
MacOSX.platform
WatchOS.platform
WatchSimulator.platform
iPhoneOS.platform
iPhoneSimulator.platform
然后假设 iphoneos 的 SDK 就在
% ls -1 $(xcode-select --print-path)/Platforms/MacOSX.platform/Developer/SDKs
MacOSX.sdk
MacOSX13.3.sdk
MacOSX13.sdk
MacOSX13.3.sdk(到 的符号链接)的内容MacOSX.sdk将被称为 Sysroot。在此文件夹中,您将找到您编译和链接的头文件和 TBD(基于文本的定义,它们是基于 YAML 的存根库)。这些 TBD 节省了大量空间,因为替代方案可能是传送所有不同版本的二进制文件。为了方便起见,我创建了一个工具来从已安装的 Xcode 版本中获取这些 SDK,并创建一个 gzip 压缩包。
SDK打包器可以从GitHub下载
以您认为合适的任何方式将 tarball 移至您的 Linux 计算机。
在 Linux 上编译 Clang 和 LLVM 相当简单。检查项目并切换到分支后,llvmorg-15.0.7我创建了一个build.sh在源目录的根目录中调用的脚本。
#!/bin/bash
set -ex
function join_by { local IFS="$1"; shift; echo "$*"; }
PROJECTS=( clang lld clang-tools-extra ) 
RUNTIMES=( libcxx libcxxabi )
TARGETS=( X86 ARM AArch64 ) 
SOURCE_DIR=$( pwd )
BUILD_DIR=${SOURCE_DIR}/builddir
DIST_DIR=${SOURCE_DIR}/dist
rm -rf ${BUILD_DIR} ${DIST_DIR}
mkdir -p ${BUILD_DIR}
pushd ${BUILD_DIR}
cmake \
    -G Ninja \
    -D CMAKE_BUILD_TYPE=Release \
    -D CMAKE_INSTALL_PREFIX=${DIST_DIR} \
    -D CMAKE_VERBOSE_MAKEFILE=on \
    -D LLVM_TARGETS_TO_BUILD=$(join_by ";" "${TARGETS[@]}") \
    -D LLVM_ENABLE_PROJECTS=$(join_by ";" "${PROJECTS[@]}") \
    -D LLVM_ENABLE_RUNTIMES=$(join_by ";" "${RUNTIMES[@]}") \
    ${SOURCE_DIR}/llvm
cmake --build .
cmake --build . --target install
popd
Apple 有一些“特殊”工具,用于操作与 Clang/LLVM 附带的二进制文件不同的二进制文件。幸运的是,这些工具都是开源的,并且已经完成了必要的移植工作。它们可以在
构建libtapi并libxar首先构建 cctools。
#!/bin/bash
set -ex
./configure \
    --prefix=${HOME}/cctools \
    --with-libtapi=${HOME}/cctools \
    --with-libxar=${HOME}/cctools \
    --with-llvm-config=${HOME}/Development/llvm-project/dist/bin/llvm-config
make -j8
make install
我们需要的工具是ar、、、、、和。我怀疑不再部分或全部需要这个额外的步骤,但对于本版本的教程,我们将坚持使用它们。install_name_toollibtoolliporanlibld
将安装的 bin 目录添加到您的搜索路径。
PATH=${HOME}/cctools/bin:${PATH}
我们将从为 x86 和 arm 构建 LibreSSL macOS 开始,这样我们就可以运行 LibreSSL 附带的“应用程序”,从而证明它是有效的。
从 git 查看 LibreSSL 是不切实际的,因为该项目本身并不是发行版的形式,而是依赖于 OpenBSD。因此,压缩包。
下载https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.7.2.tar.gz
以下是有关如何编译 LibreSSL 的 bash 脚本示例。接下来是两个附加文件,即工具链和启动器脚本。
#!/bin/bash
 APPLE_SDK_SYSROOT="${HOME}/Development/apple_sdks/MacOSX13.3.sdk"
LLVM_DIST="${HOME}/Development/llvm-project/dist"
CCTOOLS_DIST="${HOME}/cctools"
SOURCE_DIR=$( pwd )
BUILD_DIR=${SOURCE_DIR}/builddir
INSTALL_DIR=${SOURCE_DIR}/dist
CMAKE_DIR=${SOURCE_DIR}/cmake
rm -rf ${BUILD_DIR} ${DIST_DIR}
mkdir -p ${BUILD_DIR}
pushd ${BUILD_DIR}
    cmake \
        -G Ninja \
        -D CMAKE_VERBOSE_MAKEFILE=on \
        -D CMAKE_TOOLCHAIN_FILE=${CMAKE_DIR}/macosx.toolchain.cmake \
        -D LINKER_LAUNCHER=${SOURCE_DIR}/launcher.sh \
        -D LLVM_DIST=${LLVM_DIST} \
        -D CCTOOLS_DIST=${CCTOOLS_DIST} \
        -D APPLE_SDK_SYSROOT=${APPLE_SDK_SYSROOT} \
        -D CMAKE_INSTALL_PREFIX=${INSTALL_DIR} \
        -D BUILD_SHARED_LIBS=OFF \
        -D LIBRESSL_APPS=YES \
        -D LIBRESSL_TESTS=NO \
        ${SOURCE_DIR}
    cmake --build .
    cmake --build . --target install
popd
Clang/LLVM 和 CMake 真正伟大的事情之一是您可以轻松生成交叉编译的构建。交叉编译构建中的关键组件是 CMake 工具链文件。大多数开发人员习惯于安装像 Xcode 这样的编译器/IDE 环境,并 100% 依赖 IDE 来了解编译和链接是如何发生的。但是,在没有此环境的情况下进行编译也是可能的。
如果您决定启用,BUILD_SHARED_LIBS则需要对二进制文件和 dylib 进行协同设计才能运行。
codesign -f -s - bin/openssl
for LIB in lib/*.dylib; do
    codesign -f -s - $LIB
done
在构建dylib库的版本时,您通常会遵守一些关于动态链接器将在何处查找它们的约定。在这种情况下,我们需要了解dyld它们的位置,因为我们不想将实验安装到/usr/local/lib或中/usr/lib。在 Mac 上我们使用该DYLD_LIBRARY_PATH变量。
DYLD_LIBRARY_PATH=$(pwd)/lib; export DYLD_LIBRARY_PATH
我们使用一个小型 shell 脚本将路径附加到链接器
#!/bin/bash
set -ex
# -fuse-ld=/path/to/ld if pre-clang 12
"$@" --ld-path=${HOME}/cctools/bin/ld
在本例中,编译器标志-arch x86_64 -arch arm64说服 clang 创建具有 x86_64 和 arm64 架构的 FAT Mach-O 二进制文件。然后,将通过两次 clang 调用(在幕后)生成三元组,然后调用 lipo 来组合对象。
cmake_minimum_required(VERSION 3.16)
# APPLE_SDK_SYSROOT, LLVM_DIST, CCTOOLS_DIST, LINKER_LAUNCHER
set(SDK_NAME macosx)
list(APPEND ARCHS x86_64 arm64)
set(DEPLOYMENT_TARGET "10.13")
# If you want clang to output universal binaries you must use
# multiple -arch flags. Doing so results in clang calling 
# itself multiple times with different target triples. Finally,    
# it will call lipo to combine the two object files into one.  
# Clang also complains if you don't use -isysroot on these
# Apple SDK builds. This leaves -m<sdk>-version-min=x.xx. 
# You can cover it in the triple or pass them through 
# CMAKE_OSX_DEPLOYMENT_TARGET to generate the version min 
# string. The target triple is necessary if you want to build
# Mac Catalyst and you'll need to add -macabi to the end of the
# triple and it will look like <arch>-apple-ios<version>-macabi
set(CMAKE_SYSTEM_NAME Darwin) # iOS if you're iOS or Simulator
set(CMAKE_OSX_SYSROOT "${APPLE_SDK_SYSROOT}" CACHE PATH "")
set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET})
set(CMAKE_OSX_ARCHITECTURES ${ARCHS})
list(JOIN ARCHS "-" ARCHS_DASH)
set(APPLE_TARGET_TRIPLE ${ARCHS_DASH}-apple-${SDK_NAME}${DEPLOYMENT_TARGET})
set(CMAKE_C_COMPILER_TARGET ${APPLE_TARGET_TRIPLE})
set(CMAKE_ASM_COMPILER_TARGET ${APPLE_TARGET_TRIPLE})
set(CMAKE_C_COMPILER ${LLVM_DIST}/bin/clang CACHE FILEPATH "")
set(CMAKE_C_LINKER_LAUNCHER ${LINKER_LAUNCHER} CACHE FILEPATH "")
set(CMAKE_AR ${CCTOOLS_DIST}/bin/ar CACHE FILEPATH "" FORCE)
set(CMAKE_RANLIB ${CCTOOLS_DIST}/bin/ranlib CACHE FILEPATH "" FORCE)
set(CMAKE_STRIP ${CCTOOLS_DIST}/bin/strip CACHE FILEPATH "" FORCE)
set(BUILD_LIBTOOL ${CCTOOLS_DIST}/bin/libtool CACHE FILEPATH "")
set(CMAKE_INSTALL_NAME_TOOL ${CCTOOLS_DIST}/bin/install_name_tool CACHE FILEPATH "")
set(CMAKE_C_CREATE_STATIC_LIBRARY "${BUILD_LIBTOOL} -static -o <TARGET> <LINK_FLAGS> <OBJECTS> " CACHE INTERNAL "")
压缩并将安装目录复制到 Mac,然后您可以测试二进制文件以查看它们是否有效。
最简单的做法是输出 .app 文件-help,但为了进行更有趣的测试,我们可以从现有的 .app 包中转储 DER,然后漂亮地打印它们。
codesign -d --extract-certificates MyApp.app
/path/to/openssl x509 -inform der -in codesign0 -text
| 归档时间: | 
 | 
| 查看次数: | 69521 次 | 
| 最近记录: |