Skip to content

Rustup can be invoked by this module as the wrong architecture on MacOS #80

Closed
@zbentley

Description

@zbentley

Context/Setup

  • MacOS 14
  • An ARM/M1/2 MacOS environment.
  • Rosetta installed.
  • Puppet-bolt installed via brew install --cask puppetlabs/puppet/puppet-bolt, the suggested install method.
    • An important note: for whatever reason, puppet labs does not provide a bolt installer for arm64, and only provides an x86_64 installer: https://downloads.puppet.com/mac/puppet-tools/12/x86_64/puppet-bolt-3.27.4-1.osx12.dmg at the time of this writing. This means that bolt will run via Rosetta in x86 emulation mode.
  • A puppet-bolt project which ncludes this module in its dependencies.
  • A puppet manifest which invokes this module to install any toolchain/target.
  • No pre-existing rustup/rust/cargo installation or materials anywhere on the system (rustup self uninstall followed by rm -rf ~/.rustup ~/.cargo should reset things to this state, albeit somewhat destructively).

To reproduce

  • Using bolt, apply a manifest that uses this module. For example (given your user name as $USER):
> bolt apply --target localhost --run-as root --execute 'rustup { "$USER": toolchains => ["nightly-aarch64-apple-darwin"], targets => ["aarch64-apple-darwin"] }'
  • Check the file type of cargo with file $(which cargo).

Expected behavior:

cargo and rustc report file types matching the host architecture. For an ARM mac that would look like

> file $(which cargo)
/Users/$USER/.cargo/bin/cargo: Mach-O 64-bit executable arm64

> file $(which rustc)
/Users/$USER/.cargo/bin/rustc: Mach-O 64-bit executable arm64

Observed behavior

> file $(which cargo)
file $(which cargo)
/Users/$USER/.cargo/bin/cargo: Mach-O 64-bit executable x86_64

> file $(which rustc)
/Users/$USER/.cargo/bin/rustc: Mach-O 64-bit executable x86_64

Why this matters

So what happens if cargo is a non-native architecture?

  • That does not affect cargo's build behavior. It and rustc will still compile/cross-compile Rust code normally according to the targets configured in rustup and will produce binaries of the selected architecture.
  • Medium severity: cargo and rustc will run unusually slowly on MacOS due to the presence of binary emulation translating the x86_64 binaries into arm64 code.
  • High severity: programs launched by cargo and their subprograms will prefer to launch x86 programs on MacOS. In other words, if cargo run or some Cargo plugin runs a universal binary on the system (like, say sudo), that subprogram will run in x86 mode. Even if spawned subprograms do not support x86 execution (in which case cargo will spawn them as arm64), those programs' spawned subprocesses will still run preferring x86 execution.

That last one can cause problems. I encountered one such issue where the cargo flamegraph plugin supplied by flamegraph-rs runs its inner dtrace process as x86, causing dtrace to fail when it traced arm64 processes. The bug report for that issue is here, and I blogged about the discovery process of this issue here.

Given that rustup/cargo installations can persist untouched for long periods of time, and given that the main compiler suite still works, I think it's likely that incorrect-architecture installations of cargo/rustc by this module persist without users' knowledge in many cases, silently causing slowdowns and occasionally causing louder issues like the above.

Suggested resolution

When this module bootstraps cargo with the rustup resource, or when it installs a per-toolchain cargo via the rustup::toolchain resource, it should allow user specification of the architecture to those resources.

The new architecture => or toolchain_architecture => parameter that users can specify should, if unspecified, default to the invoking machine's native architecture via the "architecture" fact.

When this module invokes subprograms internally, they should be wrapped in the arch command to force the architecture as requested by the user.

This behavior need only be present on MacOS, as other platforms do not do multiarch/binfmt translation in the same way (and the issue is much more common on MacOS than on free operating systems due to the frequently limited availability of source builds, as is the case with puppet-bolt in this case: only an x86_64 binary installable is provided, and build steps for creating a correct executable are not readily available).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions