Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dont check in the grammar, but generate it at release time #2145

Merged
merged 9 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions core/build.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,36 @@
use std::path::{Path, PathBuf};

fn main() {
lalrpop::Configuration::new()
.use_cargo_dir_conventions()
.process_file("src/parser/grammar.lalrpop")
.unwrap();
let checked_in_grammar_path = Path::new(&concat!(
env!("CARGO_MANIFEST_DIR"),
"/src/parser/grammar.rs"
));

let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").expect("missing OUT_DIR variable"));
let out_parser_dir = out_dir.join("parser");
std::fs::create_dir_all(&out_parser_dir).expect("failed to create $OUT_DIR/parser");
// Running lalrpop can be expensive. When building from git, we generate the parser
// in this build script, but when publishing the crate we add the generated
// parser to the published crate at `src/parser/grammar.rs`.
//
// In order to have this build script work for both the published crate and the git
// version, we try to copy `src/parser/grammar.rs` into the same location in $OUT_DIR
// that lalrpop would generate the grammar. If that copy fails because `src/parser/grammar.rs`
// doesn't exist, we're probably building from git and so we generate the grammar.
match std::fs::copy(checked_in_grammar_path, out_parser_dir.join("grammar.rs")) {
Ok(_) => {
eprintln!("Found a pre-generated LALRPOP grammar, copying it over");
}
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
eprintln!("Generating a fresh LALRPOP grammar");
lalrpop::Configuration::new()
.use_cargo_dir_conventions()
.process_file("src/parser/grammar.lalrpop")
.unwrap();
}
Err(e) => panic!("{e}"),
}
println!("cargo:rerun-if-changed=src/parser/grammar.lalrpop");

#[cfg(feature = "nix-experimental")]
{
Expand Down
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@
pkgs.nodejs
pkgs.yarn
pkgs.yarn2nix
pkgs.yq
pkgs.nodePackages.markdownlint-cli
pkgs.python3
];
Expand Down
14 changes: 14 additions & 0 deletions scripts/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,20 @@ for crate in "${crates_to_publish[@]}"; do
cleanup_actions+=('git reset -- '"$crate/Cargo.toml")
done

# Generate the nickel grammar so that users of the published crate don't
# have to deal with lalrpop being slow.
#
# cargo check is the cheapest supported way to run just the build script
# https://github.com/rust-lang/cargo/issues/7178
# The output path is hard to predict (it contains a hash), so we find it
# using a clean output directory and some globbing
report_progress "Pre-generating the Nickel parser from the LALRPOP grammar"
temp_target_dir=$(mktemp -d)
cargo check -p nickel-lang-core --target-dir=$temp_target_dir
cp $temp_target_dir/debug/build/nickel-lang-core-*/out/parser/grammar.rs core/src/parser/grammar.rs
rm -rf $temp_target_dir || true
git add core/src/parser/grammar.rs

# Cargo requires to commit changes, but the last changes are temporary
# work-arounds for the crates.io release that aren't supposed to stay. we'll
# reset them later.
Expand Down
Loading