Skip to content

Commit

Permalink
add rust to main image
Browse files Browse the repository at this point in the history
  • Loading branch information
shepherdjerred committed Feb 17, 2024
1 parent b124a8a commit ecfb4e4
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 190 deletions.
118 changes: 92 additions & 26 deletions Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ FROM ubuntu:jammy
WORKDIR /workspace

ci:
BUILD +test --download_sdk=true
BUILD +image --download_sdk=true
BUILD +image
BUILD +test

deps:
RUN apt update -y
Expand Down Expand Up @@ -205,15 +205,23 @@ image:
ARG sdk_version=13.0
ARG kernel_version=22
ARG target_sdk_version=11
ARG download_sdk=false
FROM ubuntu:jammy
ARG download_sdk=true
COPY (+sdk/ --version=$sdk_version --download_sdk=$download_sdk) /osxcross/SDK/MacOSX$sdk_version.sdk/
RUN ln -s /osxcross/SDK/MacOSX$sdk_version.sdk/ /sdk
RUN apt update
# this is the clang we'll actually be using to compile stuff with!
RUN apt install -y clang
# for inspecting the binaries
RUN apt install -y file
# for gcc
RUN apt install -y libmpc-dev libmpfr-dev

# for rust
COPY ./zig+zig/zig /usr/local/bin
RUN apt install -y curl
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH=$PATH:/root/.cargo/bin

FOR architecture IN $architectures
ENV triple=$architecture-apple-darwin$kernel_version
COPY (+cctools/ --architecture=$architecture --sdk_version=$sdk_version --kernel_version=$kernel_version --target_sdk_version=$target_sdk_version) /cctools
Expand All @@ -224,12 +232,15 @@ image:
COPY (+gcc/include --architecture=$architecture --sdk_version=$sdk_version --kernel_version=$kernel_version --target_sdk_version=$target_sdk_version --download_sdk=$download_sdk) /usr/local/include
COPY (+gcc/$triple/lib --architecture=$architecture --sdk_version=$sdk_version --kernel_version=$kernel_version --target_sdk_version=$target_sdk_version --download_sdk=$download_sdk) /usr/local/lib
COPY (+gcc/$triple/include --architecture=$architecture --sdk_version=$sdk_version --kernel_version=$kernel_version --target_sdk_version=$target_sdk_version --download_sdk=$download_sdk) /usr/local/include
COPY ./zig/zig-cc-$architecture-macos /usr/local/bin/
RUN rustup target add $architecture-apple-darwin
END

COPY (+xar/lib --target_sdk_version=$target_sdk_version) /usr/local/lib
COPY (+libtapi/lib --target_sdk_version=$target_sdk_version) /usr/local/lib
RUN ldconfig

ENV PATH=$PATH:/usr/local/bin
ENV PATH=$PATH:/gcc/bin
ENV PATH=$PATH:/cctools/bin
ENV PATH=$PATH:/osxcross/bin
Expand All @@ -242,33 +253,88 @@ test:
ARG sdk_version=13.0
ARG kernel_version=22
ARG target_sdk_version=11
ARG download_sdk=false
ARG download_sdk=true
FROM +image --architectures=$architectures --sdk_version=$sdk_version --kernel_version=$kernel_version --target_sdk_version=$target_sdk_version --download_sdk=$download_sdk
RUN apt install -y file
COPY +samples/ samples/
COPY ./samples/ samples/
FOR architecture IN $architectures
ENV triple=$architecture-apple-darwin$kernel_version
RUN $triple-clang --target=$triple samples/hello.c -o hello-clang
RUN $triple-clang++ --target=$triple samples/hello.cpp -o hello-clang++
RUN $triple-gcc samples/hello.c -o hello-gcc
RUN $triple-g++ samples/hello.cpp -o hello-g++
RUN $triple-gfortran samples/hello.f90 -o hello-gfortran

RUN mkdir -p out/

# compile the samples
RUN $triple-clang --target=$triple samples/hello.c -o out/hello-clang
RUN $triple-clang++ --target=$triple samples/hello.cpp -o out/hello-clang++
RUN $triple-gcc samples/hello.c -o out/hello-gcc
RUN $triple-g++ samples/hello.cpp -o out/hello-g++
RUN $triple-gfortran samples/hello.f90 -o out/hello-gfortran
RUN zig cc \
-target $architecture-macos \
--sysroot=/sdk \
-I/sdk/usr/include \
-L/sdk/usr/lib \
-F/sdk/System/Library/Frameworks \
-framework CoreFoundation \
-o out/hello-zig-c samples/hello.c
RUN zig c++ \
-target $architecture-macos \
--sysroot=/sdk -I/sdk/usr/include \
-I/sdk/usr/include/c++/v1/ \
-L/sdk/usr/lib \
-lc++ \
-F/sdk/System/Library/Frameworks \
-framework CoreFoundation \
-o out/hello-zig-c++ samples/hello.cpp
ENV CC="zig-cc-$architecture-macos"
RUN cd samples/rust && cargo build --target $architecture-apple-darwin && mv target/$architecture-apple-darwin/debug/hello ../../out/hello-rust

# verify that the cross-compiler targeted the correct architecture
IF [ "$architecture" = "aarch64" ]
RUN file hello-clang | grep -q "arm64 executable"
RUN file hello-clang++ | grep -q "arm64 executable"
RUN file hello-gcc | grep -q "arm64 executable"
RUN file hello-g++ | grep -q "arm64 executable"
RUN file hello-gfortran | grep -q "arm64 executable"
RUN file out/hello-clang | grep -q "Mach-O 64-bit arm64 executable"
RUN file out/hello-clang++ | grep -q "Mach-O 64-bit arm64 executable"
RUN file out/hello-gcc | grep -q "Mach-O 64-bit arm64 executable"
RUN file out/hello-g++ | grep -q "Mach-O 64-bit arm64 executable"
RUN file out/hello-gfortran | grep -q "Mach-O 64-bit arm64 executable"
RUN file out/hello-zig-c | grep -q "Mach-O 64-bit arm64 executable"
RUN file out/hello-zig-c++ | grep -q "Mach-O 64-bit arm64 executable"
RUN file out/hello-rust | grep -q "Mach-O 64-bit arm64 executable"
ELSE
RUN file hello-clang | grep -q "$architecture executable"
RUN file hello-clang++ | grep -q "$architecture executable"
RUN file hello-gcc | grep -q "$architecture executable"
RUN file hello-g++ | grep -q "$architecture executable"
RUN file hello-gfortran | grep -q "$architecture executable"
RUN file out/hello-clang | grep -q "Mach-O 64-bit $architecture executable"
RUN file out/hello-clang++ | grep -q "Mach-O 64-bit $architecture executable"
RUN file out/hello-gcc | grep -q "Mach-O 64-bit $architecture executable"
RUN file out/hello-g++ | grep -q "Mach-O 64-bit $architecture executable"
RUN file out/hello-gfortran | grep -q "Mach-O 64-bit $architecture executable"
RUN file out/hello-zig-c | grep -q "Mach-O 64-bit $architecture executable"
RUN file out/hello-zig-c++ | grep -q "Mach-O 64-bit $architecture executable"
RUN file out/hello-rust | grep -q "Mach-O 64-bit $architecture executable"
END

SAVE ARTIFACT out/* AS LOCAL out/$architecture/
END

# Can only be run on macOS
validate:
LOCALLY

ARG USERARCH
LET arch = $USERARCH
# convert arm64 -> aarch64
IF [ $arch = "arm64" ]
SET arch=aarch64
END
# convert x86_64 -> amd64
IF [ $arch = "x86_64" ]
SET arch=amd64
END

WAIT
BUILD +test --architectures=$arch --download_sdk=true
END

samples:
FROM ubuntu:jammy
COPY samples/ samples
SAVE ARTIFACT samples/*
RUN ./out/$arch/hello-clang
RUN ./out/$arch/hello-clang++
RUN ./out/$arch/hello-g++
RUN ./out/$arch/hello-gcc
# RUN ./out/$arch/hello-gfortran
RUN ./out/$arch/hello-zig-c
RUN ./out/$arch/hello-zig-c++
RUN ./out/$arch/hello-rust
68 changes: 48 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,78 @@

This project allows you to compile C, C++, Fortran, and Rust code on Linux that will be executed on macOS. This project is focused on supporting newer versions of macOS and C, C++, Fortran, and Rust. Older versions are not well tested.

Rust is supported through the [Zig subproject](zig/).

## Quick Start

Install the requirements below, then follow the instructions in the usage section.

### Requirements

* [Docker](https://docs.docker.com/engine/install/)
* [Earthly](https://earthly.dev/get-earthly)
* Earthly is a combination of Docker and [GNU Make](https://www.gnu.org/software/make/). It builds everything in Docker containers, which makes it easy to automatically cache and parallelize builds.
* Be sure to increase your cache size, otherwise you will see _terrible_ performance building this project. Run the commands below:
* `earthly config global.cache_size_mb 1000000`
* `earthly config global.cache_size_pct 70`
* Optional: A copy of the macOS SDK in `/sdks`. See [the osxcross documentation about this](https://github.com/tpoechtrager/osxcross#packaging-the-sdk).
* Docker

### Usage

```bash
# Start a Docker container using the image we built earlier
# Replace this with the path to the source you want to compile
docker run -v $PWD/samples:/workspace \
# Start a Docker container using the Docker image.
# Replace `$PWD/samples` with the path to the source you want to compile.
docker run \
-v $PWD/samples:/workspace \
--rm \
-it \
ghcr.io/shepherdjerred/macos-cross-compiler \
/bin/bash

# Inside of the Docker container
# Compile something using gcc
## for arm64
# Now that you're inside of the Docker container, you can run the compilers.

# Compile using gcc
## targeting darwin arm64
aarch64-apple-darwin22-gcc hello.c -o hello
aarch64-apple-darwin22-g++ hello.cpp -o hello
## for x86_64
## targeting darwin x86_64
x86_64-apple-darwin22-gcc hello.c -o hello
x86_64-apple-darwin22-g++ hello.cpp -o hello

# Compile using clang
## for arm64
## for darwin arm64
aarch64-apple-darwin22-clang --target=aarch64-apple-darwin22 hello.c -o hello
aarch64-apple-darwin22-clang --target=aarch64-apple-darwin22 hello.cpp -o hello
## for x86_64
## for darwin x86_64
x86_64-apple-darwin22-clang --target==x86_64-apple-darwin22 hello.c -o hello
x86_64-apple-darwin22-clang --target==x86_64-apple-darwin22 hello.cpp -o hello

# Compile using gfortran
## for arm64
## for darwin arm64
aarch64-apple-darwin22-gfortran hello.f90 -o hello
## for x86_64
## for darwin x86_64
x86_64-apple-darwin22-gfortran hello.f90 -o hello

# Using Zig

# C targeting darwin arm64 (change aarch64 -> x86_64 to target amd64)
zig cc \
-target aarch64-macos \
--sysroot=/sdk \
-I/sdk/usr/include \
-L/sdk/usr/lib \
-F/sdk/System/Library/Frameworks \
-framework CoreFoundation \
-o hello hello.c

# C++ targeting darwin arm64(change aarch64 -> x86_64 to target amd64)
zig c++ \
-target aarch64-macos \
--sysroot=/sdk -I/sdk/usr/include \
-I/sdk/usr/include/c++/v1/ \
-L/sdk/usr/lib \
-lc++ \
-F/sdk/System/Library/Frameworks \
-framework CoreFoundation \
-o hello hello.cpp

# Rust targeting darwin arm64 (change aarch64 -> x86_64 to target amd64)
# Note: Rust requires a little more configuration. Take note of the `/samples/rust` directory.
# You'll need a `Cargo.toml` and `.cargo/config.toml` properly configured.
export CC=zig-cc-aarch64-macos
cargo build --target aarch64-apple-darwin
```

### Compiler Executables
Expand Down Expand Up @@ -152,6 +175,11 @@ These resources were helpful when working on this project:
* <http://clarkkromenaker.com/post/library-dynamic-loading-mac/>
* <https://github.com/qyang-nj/llios>

The Zig and Rust portion were informed by these resources:

* <https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html>
* <https://actually.fyi/posts/zig-makes-rust-cross-compilation-just-work/>

## Development

```bash
Expand Down
Binary file added samples/hello
Binary file not shown.
97 changes: 11 additions & 86 deletions zig/Earthfile
Original file line number Diff line number Diff line change
@@ -1,94 +1,19 @@
VERSION 0.7
VERSION 0.8

ubuntu:
zig:
ARG TARGETARCH
FROM ubuntu:jammy
RUN apt update
WORKDIR /workspace

zig:
FROM +ubuntu
RUN apt install -y wget xz-utils
RUN wget -O zig.tar.xz https://ziglang.org/download/0.10.1/zig-linux-aarch64-0.10.1.tar.xz
IF [ $TARGETARCH = "aarch64" ] || [ $TARGETARCH = "arm64" ]
RUN wget -O zig.tar.xz https://ziglang.org/download/0.10.1/zig-linux-aarch64-0.10.1.tar.xz
ELSE IF [ $TARGETARCH = "x86_64" ] || [ $TARGETARCH = "amd64" ]
RUN wget -O zig.tar.xz https://ziglang.org/download/0.10.1/zig-linux-x86_64-0.10.1.tar.xz
ELSE
RUN echo "Unsupported architecture: $TARGETARCH"
RUN exit 1
END
RUN tar -xf zig.tar.xz
RUN rm zig.tar.xz
RUN mv zig* zig
SAVE ARTIFACT zig

image:
ARG --required sdk_version
ARG --required architecture
FROM +ubuntu
COPY (../+sdk/ --version=$sdk_version) /sdk
COPY +zig/zig /usr/local/bin
COPY zig-cc-$architecture-macos /usr/local/bin/
SAVE IMAGE macos-cross-compiler:zig

image.rust:
ARG --required sdk_version
ARG --required architecture
FROM +image --sdk_version=$sdk_version --architecture=$architecture
RUN apt install -y curl
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH=$PATH:/root/.cargo/bin
SAVE IMAGE macos-cross-compiler:zig-rust

test.c:
ARG --required sdk_version
ARG --required architecture
FROM +image --sdk_version=$sdk_version --architecture=$architecture
COPY ../+samples/hello.c hello.c
RUN zig cc \
-target $architecture-macos \
--sysroot=/sdk \
-I/sdk/usr/include \
-L/sdk/usr/lib \
-F/sdk/System/Library/Frameworks \
-framework CoreFoundation \
-o hello hello.c
SAVE ARTIFACT hello AS LOCAL out/$architecture/c/

test.cpp:
ARG --required sdk_version
ARG --required architecture
FROM +image --sdk_version=$sdk_version --architecture=$architecture
COPY ../+samples/hello.cpp hello.cpp
RUN zig c++ \
-target $architecture-macos \
--sysroot=/sdk -I/sdk/usr/include \
-I/sdk/usr/include/c++/v1/ \
-L/sdk/usr/lib \
-lc++ \
-F/sdk/System/Library/Frameworks \
-framework CoreFoundation \
-o hello hello.cpp
SAVE ARTIFACT hello AS LOCAL out/$architecture/cpp/

test.rust:
ARG --required sdk_version
ARG --required architecture
FROM +image.rust --sdk_version=$sdk_version --architecture=$architecture
RUN rustup target add $architecture-apple-darwin
COPY ../+samples/rust .
ENV CC="zig-cc-$architecture-macos"
RUN cargo build --target $architecture-apple-darwin
SAVE ARTIFACT target/$architecture-apple-darwin/debug/hello AS LOCAL out/$architecture/rust/

test:
ARG sdk_version=13.0
ARG architectures=aarch64 x86_64
FROM +ubuntu
FOR architecture IN $architectures
BUILD +test.c --sdk_version=$sdk_version --architecture=$architecture
BUILD +test.cpp --sdk_version=$sdk_version --architecture=$architecture
BUILD +test.rust --sdk_version=$sdk_version --architecture=$architecture
END

validate:
ARG architecture=aarch64
LOCALLY
WAIT
BUILD +test --architectures=$architecture
END
RUN ./out/aarch64/c/hello
RUN ./out/aarch64/cpp/hello
RUN ./out/aarch64/rust/hello
Loading

0 comments on commit ecfb4e4

Please sign in to comment.