Files
nushell/scripts/build.rs
T
Darren Schroeder d88d4fe0e1 Faster startup: chained fixups on Apple silicon, a cheaper banner, and async prompt pushes that survive (#19236)
## Description

Three independent changes make the REPL ready to type into sooner. With
the default config, launching `nu` until the first prompt is drawn drops
from 15.7 ms to 13.1 ms (−17%). `$nu.startup-time` is measured the same
way as before.

Measurements:
| default config, from `~` | main | this PR |
| --- | --- | --- |
| launch to first prompt | 15.70 ms | 13.10 ms |
| `$nu.startup-time` | 8.03 ms | 7.36 ms |
| instructions retired by the first prompt | 149.3M | 119.8M |


1. Change the linker on Apple silicon to
`"cargo:rustc-link-arg-bins=-Wl,-fixup_chains"`
2. Make `banner` cheaper (all architectures)
3. Keep prompt pushes that land before the prompt is rebuilt (all
architectures)

## User-facing changes (Release notes)

- Improved startup time. On Apple silicon Macs, `nu` is now linked with
chained fixups, so less work happens before Nushell's own code starts
and each `nu` process uses about 3 MiB less memory. The startup banner
no longer computes the welcome message when it only prints the startup
time.
- `date to-timezone` (all architectures) now accepts IANA time zone
names in any letter case, for example `date now | date to-timezone
america/new_york`. Before, some lowercase names were rejected as
invalid.
- Background jobs that update the prompt with `commandline set-prompt`
(all architectures), started from a `pre_prompt` or `env_change` hook or
from a prompt closure such as `$env.PROMPT_COMMAND`, no longer lose that
update when they finish before the prompt is drawn. A `commandline
set-prompt` called directly inside one of those hooks or prompt closures
now also shows on that prompt, in place of the value the prompt
variables give that segment. Before, the prompt evaluation that follows
the hooks always replaced it.


## Additional notes
<!--
Optional.

Examples:
- fixes #123
- closes #456
- related #789

Anything else reviewers should know.
Remove this section if not needed.
-->
2026-10-14 16:15:25 -05:00

37 lines
2.0 KiB
Rust

fn main() {
let target_os = std::env::var("CARGO_CFG_TARGET_OS").expect("set by cargo");
let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").expect("set by cargo");
println!("cargo:rerun-if-changed=scripts/build.rs");
println!(
"cargo:rustc-env=NU_FEATURES={}",
std::env::var("CARGO_CFG_FEATURE").expect("set by cargo")
);
if target_os == "windows" {
println!("cargo:rerun-if-changed=assets/nu_logo.ico");
let mut res = winresource::WindowsResource::new();
res.set_icon("assets/nu_logo.ico");
res.compile()
.expect("Failed to run the Windows resource compiler (rc.exe)");
} else {
if target_os == "macos"
&& target_arch == "aarch64"
&& std::env::var_os("RUSTC_LINKER").is_none()
{
// Link with chained fixups. At Rust's default deployment target (macOS 11) the linker
// writes classic rebase opcodes instead, and dyld rewrites every pointer in the
// binary's constant data before `main` runs. Since macOS 13 the kernel applies chained
// fixups page by page as pages are first touched, so startup only pays for the pages
// it uses. macOS 11 is the first release that loads them. That is why this is limited
// to aarch64: every arm64 Mac runs macOS 11 or later, but x86_64's default deployment
// target (10.12) predates them, and the binary would fail to load on 10.12-10.15.
// Cargo sets `RUSTC_LINKER` only when the build configures its own linker, and some,
// such as `zig cc` (cargo-zigbuild), reject the flag, so only Apple's default gets it.
println!("cargo:rustc-link-arg-bins=-Wl,-fixup_chains");
}
// Tango uses dynamic linking, to allow us to dynamically change between two bench suit at runtime.
// This is currently not supported on non nightly rust, on windows.
println!("cargo:rustc-link-arg-benches=-rdynamic");
}
}