Skip to content

Commit d7451ed

Browse files
authored
Merge pull request #4 from tindzk/feat/macos
Support building on macOS
2 parents e2b098d + c032fa7 commit d7451ed

File tree

8 files changed

+66
-14
lines changed

8 files changed

+66
-14
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ The generated Docker image allows you to compile your Rust project for any of th
3131

3232
## Requirements
3333
- Docker
34-
- [Bubblewrap](https://github.com/containers/bubblewrap) (optional)
34+
- [Bubblewrap](https://github.com/containers/bubblewrap) (optional, Linux only)
3535
- A minimum of 15 GB free disk space is recommended
3636

3737
## Installation
@@ -62,7 +62,7 @@ mkdir sample-project && cd sample-project
6262
cp $RUSTX_PATH/config.nuon.sample rustx.nuon
6363
```
6464

65-
Edit `rustx.nuon` to match your requirements.
65+
Edit `rustx.nuon` to match your requirements. Please note that Linux targets currently support only the `musl` variant.
6666

6767
Build all toolchains and generate the `Dockerfile`:
6868

config.nuon.sample

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
{
66
rust_version: "1.87.0"
77
alpine_version: "3.21"
8+
9+
# Note: Linux targets currently only support the musl variant.
810
targets: [
911
"x86_64-unknown-linux-musl"
1012
"aarch64-unknown-linux-musl"
@@ -30,7 +32,12 @@
3032

3133
# Isolation mechanism used for building toolchains
3234
#
35+
# When building on macOS, set this to `docker` as `bubblewrap` is not available.
36+
#
3337
# Possible values: bubblewrap (default), docker
3438
#
39+
# The Docker isolation creates a volume named alpine-rustx-build. It is reused
40+
# across cache runs and can be removed.
41+
#
3542
#isolation: "docker"
3643
}

rustx

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,48 @@
22

33
NU_VERSION=$(cat $(dirname $0)/.nu_version)
44

5-
if [ ! -f build/nu-$NU_VERSION ]; then
6-
name=nu-$NU_VERSION-$(uname -m)-unknown-linux-musl
5+
os=$(uname -s)
6+
arch=$(uname -m)
7+
8+
case "$os" in
9+
"Darwin")
10+
[ "$arch" = "arm64" ] && arch="aarch64"
11+
native_nu="nu-${NU_VERSION}-${arch}-apple-darwin"
12+
;;
13+
"Linux")
14+
native_nu="nu-${NU_VERSION}-${arch}-unknown-linux-musl"
15+
;;
16+
*)
17+
echo "Unsupported operating system: $os" >&2
18+
exit 1
19+
;;
20+
esac
21+
22+
linux_nu="nu-${NU_VERSION}-${arch}-unknown-linux-musl"
23+
24+
fetch_nu() {
25+
name="$1"
726

827
mkdir -p build/
928
cd build/
1029

1130
wget "https://github.com/nushell/nushell/releases/download/$NU_VERSION/$name.tar.gz"
31+
1232
tar -zxvf ${name}.tar.gz $name/nu
1333
rm ${name}.tar.gz
14-
mv $name/nu nu-$NU_VERSION
15-
rmdir $name
1634

1735
cd -
36+
}
37+
38+
if [ ! -f build/$native_nu/nu ]; then
39+
fetch_nu "$native_nu"
40+
fi
41+
42+
if [ ! -f build/$linux_nu/nu ]; then
43+
fetch_nu "$linux_nu"
1844
fi
1945

2046
script="$(dirname "$0")/src/commands/$1.nu"
2147
shift
2248

23-
exec build/nu-$NU_VERSION $script "$@"
49+
exec build/$native_nu/nu $script "$@"

src/commands/build.nu

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,33 @@ use ../config.nu
55

66
def main [config_path: string] {
77
let root_path = ($env.FILE_PWD | path join "../../")
8+
9+
mut host_arch = (uname | get machine)
10+
if $host_arch == "arm64" {
11+
# Needed if host system is macOS
12+
$host_arch = "aarch64"
13+
}
14+
815
let nu_version = (open ($root_path | path join ".nu_version") | str trim)
916
let cfg = config normalise (open $config_path)
1017

1118
mkdir build
1219
mkdir toolchains
1320

14-
let spec = {
21+
mut spec = {
1522
rw_bind: {
16-
$"(pwd)/build": "/build",
1723
$"(pwd)/toolchains": "/toolchains"
1824
}
1925
ro_bind: {
20-
$"(pwd)/build/nu-($nu_version)": "/bin/nu",
26+
$"(pwd)/build/nu-($nu_version)-($host_arch)-unknown-linux-musl/nu": "/bin/nu",
2127
($config_path | path expand): "/build/config.nuon",
2228
($root_path | path join "src"): "/src"
2329
}
2430
command: "/src/build.nu"
2531
}
2632

2733
if $cfg.isolation == "bubblewrap" {
34+
$spec.rw_bind = $spec.rw_bind | insert $"(pwd)/build" "/build"
2835
bubblewrap run $spec
2936
} else if $cfg.isolation == "docker" {
3037
docker run $spec

src/dockerfile.nu

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@ export def generate [config: record] {
4545
}
4646

4747
let macos_commands = if ($all_targets.macos | is-not-empty) {
48-
let host_arch = (uname | get machine)
48+
mut host_arch = (uname | get machine)
49+
if $host_arch == "arm64" {
50+
# Needed if host system is macOS
51+
$host_arch = "aarch64"
52+
}
53+
4954
let rust_objcopy = $"/usr/local/rustup/toolchains/($config.rust_version)-($host_arch)-unknown-linux-musl/lib/rustlib/($host_arch)-unknown-linux-musl/bin/rust-objcopy"
5055

5156
$apk_deps = [...$apk_deps, "clang", "llvm"]

src/isolation/bubblewrap.nu

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ export def run [spec: record] {
44
if not ("rootfs" | path exists) {
55
mkdir rootfs
66

7+
let major_alpine_version = ($ALPINE_VERSION | split row '.' | take 2 | str join ".")
8+
79
let host_arch = (uname | get machine)
8-
wget -O - $"https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/($host_arch)/alpine-minirootfs-($ALPINE_VERSION)-($host_arch).tar.gz" | tar -xz -C rootfs
10+
wget -O - $"https://dl-cdn.alpinelinux.org/alpine/v($major_alpine_version)/releases/($host_arch)/alpine-minirootfs-($ALPINE_VERSION)-($host_arch).tar.gz" | tar -xz -C rootfs
911
}
1012

1113
let rw_bind = $spec.rw_bind | transpose name value | each {|it| ["--bind", $it.name, $it.value]} | flatten

src/isolation/common.nu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export const ALPINE_VERSION = "3.21.3"
1+
export const ALPINE_VERSION = "3.22.0"

src/isolation/docker.nu

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,10 @@ export def run [spec: record] {
44
let rw_bind = $spec.rw_bind | transpose name value | each {|it| ["--mount", $"type=bind,src=($it.name),dst=($it.value)"]} | flatten
55
let ro_bind = $spec.ro_bind | transpose name value | each {|it| ["--mount", $"type=bind,src=($it.name),dst=($it.value),ro"]} | flatten
66

7-
(docker run --rm -t -i ...$rw_bind ...$ro_bind $"alpine:($ALPINE_VERSION)" $spec.command)
7+
# For macOS compatibility, create a separate volume for the build cache.
8+
# Otherwise, some files appear to be missing when linking the toolchain.
9+
# Using a volume should also speed up builds on macOS.
10+
(docker volume create alpine-rustx-build)
11+
12+
(docker run --rm -t -i -v alpine-rustx-build:/build ...$rw_bind ...$ro_bind $"alpine:($ALPINE_VERSION)" $spec.command)
813
}

0 commit comments

Comments
 (0)