Installer: stop requiring a developer toolchain on the consumer path (#7547)
* Installer: stop requiring a developer toolchain on the consumer path A brand new Mac cannot install Studio at all. install.sh gates on `xcode-select -p` and exits 1 with 'Xcode Command Line Tools are required', and Linux exits 1 on any non-apt distro over cmake/gcc/git/libcurl headers. Nothing under either gate needs a toolchain. uv is a prebuilt binary, CPython comes from uv's managed python-build-standalone, llama.cpp and whisper.cpp are prebuilt downloads, Node is a pinned nodejs.org archive, and triton is skipped on macOS. unslothai/llama.cpp b10107-mix-1911198 publishes macos-arm64, macos-x64, linux-x64 and linux-arm64 builds covering cpu, cuda12, cuda13, rocm and vulkan. PR #6617 already dropped the Homebrew/cmake stop on macOS for this reason and just left the CLT stop behind. macOS: warn and continue when the CLT are absent. Linux: only a download transport (curl or wget) is fatal; build tooling warns. Both keep a hard git requirement for --local, which installs unsloth-zoo from a git+https URL. Both gates move into functions so tests/sh can extract them. The old inline form could not be reached by the tests/sh convention, which is why this shipped broken and stayed broken. test_macos_clt_gate.sh (19 assertions) and test_linux_deps_gate.sh (25) cover the clean machine, the CLT-stub shape where /usr/bin/git exists but fails, the non-apt distro, and the --local paths. Writing the Linux test caught a latent bug: the gate trimmed its list with $(echo ... | sed ...), so on a minimal image without sed the substitution yields empty and it reports 'all system dependencies found' on a machine with none of them. Replaced with parameter expansion. Also caps av<16 in the single-env constraints. av 16+ ships no cp313 macOS arm64 wheel, and it is a C extension over FFmpeg, so uv would silently fall back to a source build needing both a compiler and FFmpeg headers. Verified on GitHub-hosted macOS runners with /var/db/xcode_select_link, /Library/Developer/CommandLineTools, /Applications/Xcode*.app and Homebrew moved aside. macos-14, macos-15 and macos-26 fail on main and install cleanly with this; the recorded tool-invocation trace for the whole install is a single `xcode-select -p`, so nothing compiled and nothing installed a toolchain. * Linux: auto-install git rather than dropping it, and skip triton kernels without it Making git optional on Linux was too broad. studio/backend/requirements/ triton-kernels.txt line 2 is a git+https URL, so step 6/14 died with 'Cannot find command git' and failed the whole setup on ubuntu2404-root, ubuntu2404-arm-root and fedora41, all of which had been passing. The claim that nothing on the consumer path needs git holds on macOS, where triton is skipped, but not here. install.sh now auto-installs git through apt with the other optional tooling, so Debian and Ubuntu are unchanged. The triton kernels step skips with a message when git is absent instead of failing: they are a training speedup, not a boot requirement, and a GGUF chat install has no use for them. Six more assertions pin both halves. * macOS Intel: skip the one package with no x86_64 wheel The Intel clean-machine leg installed with the toolchain masked, then died in studio setup: subprocess.CalledProcessError: Command '['cmake', ...]' returned non-zero ERROR: Failed building wheel for pytorch_tokenizers pytorch_tokenizers publishes wheels for macOS arm64, linux x86_64, linux aarch64 and windows, but none for macOS x86_64 at any Python version, so uv falls back to an sdist that shells out to cmake. Nothing passes --only-binary, so the compiler-free property was an assumption rather than a contract, and Intel is where it broke. Marked so it installs everywhere except Intel macOS. Apple Silicon is unaffected. * Stop the optional dep gate from aborting the install _smart_apt_install exits rather than returns, and `|| true` does not catch an exit, so a box missing cmake or git aborted at the gate added to let it continue. Verified in sh, dash and bash. Run it in a subshell and re-raise only code 2, the NEED_SUDO handshake install.rs answers with an elevation prompt. install.sh treats a present-but-broken git as missing, but the Python side tested only shutil.which, so it promised to skip the git+https triton requirement and then fetched it anyway. Same check on both sides now. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Never elevate for optional build tools Re-raising code 2 turned the optional set into a NEED_SUDO handshake, so a box missing cmake or gcc got the desktop's mandatory permission dialog, whose Cancel drops back to not-installed. That re-imposes through a prompt the build-tool requirement this gate removes, and none of those tools are needed to run. Suppress the handshake for optional callers; a required package still elevates. Verified in sh, dash and bash. Also advance the progress bar on the no-git triton skip, which otherwise ends at 14/15. * Tighten the comments on the dependency gate * Correct why the PyAV cap is needed 16.0.0 does ship cp313-cp313-macosx_14_0_arm64; the comment claimed no cp313 wheel exists. The actual reason is the deployment target: 15.1.0 is macosx_13_0 and 16+ is macosx_14_0, so the cap is what keeps macOS 13 off a source build. * Tighten the installer gate comments * Cap cryptography on x86_64 macOS so the consumer install needs no Rust cryptography 49.0.0 (2026-06-12) dropped the macosx_10_9_universal2 wheel and now ships macosx_11_0_arm64 only, so x86_64 macOS has no wheel and uv falls back to the sdist. That build calls maturin, which pulls Rust and then fails at 'linking with cc failed' on a clean Mac without the Xcode Command Line Tools. It surfaced in the clean-machine leg mac macos-15-intel / mask / file, several minutes into the studio dependency step, which is exactly the up-front toolchain requirement this branch removes. 48.0.1 is the newest release carrying a universal2 wheel, and its cp39-abi3 / cp311-abi3 tags cover the 3.12 and 3.13 interpreters the installer creates. The cap is marker-scoped to darwin + x86_64, so arm64 macOS and every other platform still resolve to the latest. Lift it when cryptography ships an x86_64-capable macOS wheel again. Resolution of studio/backend/requirements/studio.txt under this constraints file gives 48.0.1 on x86_64-apple-darwin and 49.0.0 on aarch64-apple-darwin and x86_64-unknown-linux-gnu, on both 3.12 and 3.13. * Correct the av note now that cryptography also compiles on macOS * Never escalate for optional apt packages outside Tauri mode The optional bypass sat inside the TAURI_MODE branch, so a plain curl | sh install on a non-root Debian or Ubuntu box still fell through to the escalation branch and showed the default-yes permission prompt for cmake, GCC and the libcurl headers. That is exactly the toolchain this change set declared unnecessary on the consumer path, so the prompt asked for a password to install packages nothing here uses, and a headless run failed the same way instead of falling through to prebuilt llama.cpp. Move the check above the mode split so optional callers return 2 in both modes. Required packages such as curl still escalate unchanged. --------- Co-authored-by: danielhanchen <unslothai@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
9e2fc49851
commit
df63522369
6 changed files with 573 additions and 66 deletions
|
|
@ -15,7 +15,9 @@ trl==0.23.1
|
|||
torch-c-dlpack-ext
|
||||
sentence_transformers==5.2.0
|
||||
transformers==4.57.6
|
||||
pytorch_tokenizers
|
||||
# No macOS x86_64 wheel at any version, so uv falls back to an sdist that shells out to
|
||||
# cmake. Skipping it on Intel Macs keeps that install compiler-free.
|
||||
pytorch_tokenizers; sys_platform != "darwin" or platform_machine == "arm64"
|
||||
kernels==0.12.1
|
||||
# kernels<3.11 imports tomli as its tomllib fallback; --no-deps skips its own
|
||||
# marker dep, so list it here (no-op on the 3.12/3.13 default installs).
|
||||
|
|
|
|||
|
|
@ -21,3 +21,20 @@ websockets>=15.0.1
|
|||
anyio<4.14.0
|
||||
|
||||
pandas==2.3.3
|
||||
|
||||
# av (PyAV) 16+ builds its macOS arm64 wheels against macosx_14_0, so on macOS 13 none
|
||||
# are installable and the resolver falls back to a source build, which needs FFmpeg
|
||||
# headers the Xcode CLT do not supply and so fails however that Mac is equipped.
|
||||
# 15.1.0 is the newest release with a macosx_13_0 arm64 wheel; 17+ moves to cp311-abi3
|
||||
# at macosx_14_0 too.
|
||||
#
|
||||
# The remaining sdist-only macOS defaults are pure Python, hence allowlisted in
|
||||
# .github/scripts/clean-machine-assert.sh instead; cryptography below is the one
|
||||
# other package that would compile.
|
||||
av<16
|
||||
|
||||
# cryptography 49.0.0 dropped the macosx_10_9_universal2 wheel for arm64-only, so
|
||||
# x86_64 macOS has no wheel and builds the sdist, needing Rust plus a working
|
||||
# linker. 48.0.1 is the newest release with a universal2 wheel. Lift when
|
||||
# cryptography ships an x86_64-capable macOS wheel again.
|
||||
cryptography<49; sys_platform == "darwin" and platform_machine == "x86_64"
|
||||
|
|
|
|||
|
|
@ -2892,6 +2892,30 @@ def patch_package_file(package_name: str, relative_path: str, url: str) -> None:
|
|||
# -- Main install sequence ---------------------------------------------
|
||||
|
||||
|
||||
def _has_working_git() -> bool:
|
||||
"""Match install.sh's _has_working_git: on PATH *and* actually runnable.
|
||||
|
||||
A present-but-broken git (a bare xcrun shim) counts as missing there too. Testing
|
||||
only shutil.which disagreed, so the installer promised to skip the git+https triton
|
||||
requirement and then tried to fetch it anyway.
|
||||
"""
|
||||
exe = shutil.which("git")
|
||||
if exe is None:
|
||||
return False
|
||||
try:
|
||||
return (
|
||||
subprocess.run(
|
||||
[exe, "--version"],
|
||||
stdout = subprocess.DEVNULL,
|
||||
stderr = subprocess.DEVNULL,
|
||||
timeout = 30,
|
||||
).returncode
|
||||
== 0
|
||||
)
|
||||
except (OSError, subprocess.SubprocessError):
|
||||
return False
|
||||
|
||||
|
||||
def install_python_stack() -> int:
|
||||
global USE_UV, _STEP, _TOTAL
|
||||
_STEP = 0
|
||||
|
|
@ -3197,17 +3221,22 @@ def install_python_stack() -> int:
|
|||
_torchao_spec,
|
||||
)
|
||||
|
||||
# 5. Triton kernels (no-deps, from source). Skip on Windows and macOS
|
||||
# (no support).
|
||||
# 5. Triton kernels (no-deps, from source). Skipped on Windows/macOS (no support)
|
||||
# and without git (the requirement is a git+https URL); a training speedup
|
||||
# only, so warn rather than fail the install.
|
||||
if not IS_WINDOWS and not IS_MACOS:
|
||||
_progress("triton kernels")
|
||||
pip_install(
|
||||
"Installing triton kernels",
|
||||
"--no-deps",
|
||||
"--no-cache-dir",
|
||||
req = REQ_ROOT / "triton-kernels.txt",
|
||||
constrain = False,
|
||||
)
|
||||
if not _has_working_git():
|
||||
_progress("triton kernels (skipped, no git)")
|
||||
_safe_print(" no working git -- skipping triton kernels (training speedup only)")
|
||||
else:
|
||||
_progress("triton kernels")
|
||||
pip_install(
|
||||
"Installing triton kernels",
|
||||
"--no-deps",
|
||||
"--no-cache-dir",
|
||||
req = REQ_ROOT / "triton-kernels.txt",
|
||||
constrain = False,
|
||||
)
|
||||
|
||||
if not IS_WINDOWS and not IS_MACOS and not NO_TORCH:
|
||||
_progress("flash-attn")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue