Skip to content

Commit 65a7cc4

Browse files
authored
Merge pull request #6 from Karrq/fix/nightly
feat(anchor-cli): cargo shim with set nightly rust
2 parents 87bea8c + bf0afe2 commit 65a7cc4

File tree

4 files changed

+57
-91
lines changed

4 files changed

+57
-91
lines changed

anchor-cli.nix

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,37 @@
1010
rust-bin,
1111
udev,
1212
crane,
13-
runCommand,
13+
writeShellScriptBin,
1414
version ? "0.31.1",
1515
}:
1616
let
1717
pname = "anchor-cli";
1818

19+
# Anchor IDL generation makes use of rust-nightly
20+
# therefore we want to expose it to the environment to be used
21+
# Due to https://github.com/solana-foundation/anchor/pull/3663
22+
# latest nightly is always preferred when possible, since breakage may occur
23+
# due to differing dependency versions as well
1924
versionsDeps = {
2025
"0.31.1" = {
2126
hash = "sha256-c+UybdZCFL40TNvxn0PHR1ch7VPhhJFDSIScetRpS3o=";
22-
# Unfortunately dependency on nightly compiler seems to be common
23-
# in rust projects
24-
rust-nightly = rust-bin.nightly."2025-04-21".minimal;
2527
rust = rust-bin.stable."1.85.0".default;
28+
rust-nightly = rust-bin.nightly.latest.default;
2629
platform-tools = solana-platform-tools.override { version = "1.45"; };
2730
patches = [ ./patches/anchor-cli/0.31.1.patch ];
2831
};
2932
"0.31.0" = {
3033
hash = "sha256-CaBVdp7RPVmzzEiVazjpDLJxEkIgy1BHCwdH2mYLbGM=";
3134
rust = rust-bin.stable."1.85.0".default;
35+
rust-nightly = rust-bin.nightly.latest.default;
3236
platform-tools = solana-platform-tools.override { version = "1.45"; };
3337
patches = [ ./patches/anchor-cli/0.31.0.patch ];
3438
};
3539
"0.30.1" = {
3640
hash = "sha256-3fLYTJDVCJdi6o0Zd+hb9jcPDKm4M4NzpZ8EUVW/GVw=";
3741
rust = rust-bin.stable."1.78.0".default;
42+
# anchor-syn v0.30.1 still uses the old API
43+
rust-nightly = rust-bin.nightly."2025-04-15".default;
3844
platform-tools = solana-platform-tools.override { version = "1.43"; };
3945
patches = [ ./patches/anchor-cli/0.30.1.patch ];
4046
};
@@ -89,36 +95,38 @@ let
8995
};
9096

9197
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
98+
99+
# We create a small cargo shim to dispatch to a compatible nightly version when necessary
100+
cargoShim = writeShellScriptBin "cargo" ''
101+
# Check that required env variables are set
102+
if [[ -z "$_NIX_SUPPORT_STABLE_TOOLCHAIN" || -z "$_NIX_SUPPORT_NIGHTLY_TOOLCHAIN" ]]; then
103+
echo "Error: Both _NIX_SUPPORT_STABLE_TOOLCHAIN and _NIX_SUPPORT_NIGHTLY_TOOLCHAIN environment variables must be set." >&2
104+
exit 1
105+
fi
106+
107+
if [[ "$1" == "+nightly" ]]; then
108+
# Shift off +nightly and pass through all remaining args
109+
shift
110+
export PATH="$_NIX_SUPPORT_NIGHTLY_TOOLCHAIN":$PATH
111+
exec cargo "$@"
112+
else
113+
export PATH="$_NIX_SUPPORT_STABLE_TOOLCHAIN":$PATH
114+
exec cargo "$@"
115+
fi
116+
'';
92117
in
93118
craneLib.buildPackage (
94119
commonArgs
95120
// {
96121
inherit cargoArtifacts;
97122

98-
# Ensure anchor has access to Solana's cargo and rust binaries
99-
postInstall = let
100-
# Due to th way anchor is calling cargo if its not wrapped
101-
# with its own toolchain, it'll access solana rust compiler instead
102-
# hence the nightly entry points must be wrapped with the nightly bins
103-
# to guarantee correct usage
104-
# In this case we've limited the nightly bin access to `cargo`
105-
cargo-nightly = runCommand "cargo-nightly" {
106-
nativeBuildInputs = [ makeWrapper ];
107-
} ''
108-
mkdir -p $out/bin
109-
110-
ln -s ${versionDeps.rust-nightly}/bin/cargo $out/bin/cargo
111-
112-
# Wrap cargo nightly so it uses the nightly toolchain only
113-
wrapProgram $out/bin/cargo \
114-
--prefix PATH : "${versionDeps.rust-nightly}/bin"
115-
''
116-
;
117-
in
118-
''
123+
# Ensure anchor has access to Solana's rust binaries and our cargo shim with nightly
124+
postInstall = ''
119125
rust=${versionDeps.platform-tools}/bin/platform-tools-sdk/sbf/dependencies/platform-tools/rust/bin
120126
wrapProgram $out/bin/anchor \
121-
--prefix PATH : "$rust" ${if versionDeps ? rust-nightly then "--set RUST_NIGHTLY_BIN \"${cargo-nightly}/bin\"" else ""}
127+
--prefix PATH : "${cargoShim}/bin" \
128+
--set _NIX_SUPPORT_STABLE_TOOLCHAIN "$rust" \
129+
--set _NIX_SUPPORT_NIGHTLY_TOOLCHAIN "${versionDeps.rust-nightly}/bin"
122130
'';
123131

124132
cargoExtraArgs = "-p ${pname}";
@@ -130,6 +138,7 @@ craneLib.buildPackage (
130138

131139
passthru = {
132140
otherVersions = builtins.attrNames versionsDeps;
141+
rustNightly = versionDeps.rust-nightly._version;
133142
};
134143
}
135144
)

patches/anchor-cli/0.30.1.patch

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -114,31 +114,18 @@ index 9befe845..7a9ae066 100644
114114
}
115115
}
116116
diff --git a/idl/src/build.rs b/idl/src/build.rs
117-
index 96dc3db2..d28a34b5 100644
117+
index 96dc3db2..02d754c9 100644
118118
--- a/idl/src/build.rs
119119
+++ b/idl/src/build.rs
120-
@@ -60,16 +60,14 @@ pub fn build_idl(
121-
122-
/// Build IDL.
123-
fn build(program_path: &Path, resolution: bool, skip_lint: bool, no_docs: bool) -> Result<Idl> {
124-
- // `nightly` toolchain is currently required for building the IDL.
125-
- let toolchain = std::env::var("RUSTUP_TOOLCHAIN")
126-
- .map(|toolchain| format!("+{}", toolchain))
127-
- .unwrap_or_else(|_| "+nightly".to_string());
128-
+ let mut command = Command::new("cargo");
120+
@@ -65,8 +65,6 @@ fn build(program_path: &Path, resolution: bool, skip_lint: bool, no_docs: bool)
121+
.map(|toolchain| format!("+{}", toolchain))
122+
.unwrap_or_else(|_| "+nightly".to_string());
129123

130124
- install_toolchain_if_needed(&toolchain)?;
131-
+ if let Ok(toolchain) = std::env::var("RUSTUP_TOOLCHAIN") {
132-
+ command.arg(&format!("+{}", toolchain));
133-
+ }
134-
135-
- let output = Command::new("cargo")
136-
+ let output = command
125+
-
126+
let output = Command::new("cargo")
137127
.args([
138-
- &toolchain,
139-
"test",
140-
"__anchor_private_print_idl",
141-
"--features",
128+
&toolchain,
142129
@@ -202,23 +200,6 @@ fn build(program_path: &Path, resolution: bool, skip_lint: bool, no_docs: bool)
143130
idl.ok_or_else(|| anyhow!("IDL doesn't exist"))
144131
}

patches/anchor-cli/0.31.0.patch

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -152,31 +152,18 @@ index 3404b032..34b08dac 100644
152152
}
153153
}
154154
diff --git a/idl/src/build.rs b/idl/src/build.rs
155-
index ccd89745..a4edf8a5 100644
155+
index ccd89745..83028bf4 100644
156156
--- a/idl/src/build.rs
157157
+++ b/idl/src/build.rs
158-
@@ -138,15 +138,12 @@ fn build(
159-
no_docs: bool,
160-
cargo_args: &[String],
161-
) -> Result<Idl> {
162-
- // `nightly` toolchain is currently required for building the IDL.
163-
- let toolchain = std::env::var("RUSTUP_TOOLCHAIN")
164-
- .map(|toolchain| format!("+{}", toolchain))
165-
- .unwrap_or_else(|_| "+nightly".to_string());
166-
-
158+
@@ -143,7 +143,6 @@ fn build(
159+
.map(|toolchain| format!("+{}", toolchain))
160+
.unwrap_or_else(|_| "+nightly".to_string());
161+
167162
- install_toolchain_if_needed(&toolchain)?;
168-
- let output = Command::new("cargo")
169-
+ let mut command = Command::new("cargo");
170-
+ if let Ok(toolchain) = std::env::var("RUSTUP_TOOLCHAIN") {
171-
+ command.arg(&format!("+{}", toolchain));
172-
+ }
173-
+ let output = command
163+
let output = Command::new("cargo")
174164
.args([
175-
- &toolchain,
176-
"test",
177-
"__anchor_private_print_idl",
178-
"--features",
179-
@@ -283,23 +280,6 @@ fn build(
165+
&toolchain,
166+
@@ -283,23 +282,6 @@ fn build(
180167
idl.ok_or_else(|| anyhow!("IDL doesn't exist"))
181168
}
182169

patches/anchor-cli/0.31.1.patch

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -152,35 +152,18 @@ index 3404b032..34b08dac 100644
152152
}
153153
}
154154
diff --git a/idl/src/build.rs b/idl/src/build.rs
155-
index ccd89745..3c958377 100644
155+
index ccd89745..83028bf4 100644
156156
--- a/idl/src/build.rs
157157
+++ b/idl/src/build.rs
158-
@@ -139,14 +139,18 @@ fn build(
159-
cargo_args: &[String],
160-
) -> Result<Idl> {
161-
// `nightly` toolchain is currently required for building the IDL.
162-
- let toolchain = std::env::var("RUSTUP_TOOLCHAIN")
163-
- .map(|toolchain| format!("+{}", toolchain))
164-
- .unwrap_or_else(|_| "+nightly".to_string());
165-
+ let cargo_path = std::env::var("RUST_NIGHTLY_BIN")
166-
+ .map(|bin| format!("{}/cargo", bin))
167-
+ .unwrap_or_else(|_| "cargo".to_string());
158+
@@ -143,7 +143,6 @@ fn build(
159+
.map(|toolchain| format!("+{}", toolchain))
160+
.unwrap_or_else(|_| "+nightly".to_string());
168161

169162
- install_toolchain_if_needed(&toolchain)?;
170-
- let output = Command::new("cargo")
171-
+ eprintln!("Cargo at {}", cargo_path);
172-
+
173-
+ let mut command = Command::new(cargo_path);
174-
+ if let Ok(toolchain) = std::env::var("RUSTUP_TOOLCHAIN") {
175-
+ command.arg(&format!("+{}", toolchain));
176-
+ }
177-
+ let output = command
163+
let output = Command::new("cargo")
178164
.args([
179-
- &toolchain,
180-
"test",
181-
"__anchor_private_print_idl",
182-
"--features",
183-
@@ -283,23 +287,6 @@ fn build(
165+
&toolchain,
166+
@@ -283,23 +282,6 @@ fn build(
184167
idl.ok_or_else(|| anyhow!("IDL doesn't exist"))
185168
}
186169

0 commit comments

Comments
 (0)