Skip to content

Commit

Permalink
feat: use git-version instead of git2 (#173)
Browse files Browse the repository at this point in the history
An alternative approach for #172. This replaces the `git2` dependency
with `git-version` which uses the `git` binary directly at compile time.
This means that:

For dev builds, needs `git` binary:
- There is a submodule checked out: version file is written to the `gen`
folder.
- There is no submodule checked out: the build fails with a hint to
clone the submodule.

For packaged builds (substrait is not included as a git submodule, see
`Cargo.toml` includes), don't need a `git` binary:
- The version file is in the `gen` folder: the build script skips the
version generation part
- The version file is missing: the build fails - the package is broken
  • Loading branch information
mbrobbel authored Apr 8, 2024
1 parent f19ebc2 commit 22d6df7
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 57 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
Cargo.lock

# Generated by build.rs (substrait submodule version information)
src/version.in
gen/

.idea

package.json
package-lock.json
node_modules/
.vscode/
.vscode/
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ build = "build.rs"
include = [
"LICENSE",
"build.rs",
"gen/",
"src/**/*.rs",
"src/version.in",
"substrait/LICENSE",
"substrait/README.md",
"substrait/extensions/**/*.yaml",
Expand Down Expand Up @@ -44,7 +44,7 @@ serde_json = "1.0.114"
thiserror = { version = "1.0.57", optional = true }

[build-dependencies]
git2 = { version = "0.18.2", default-features = false }
git-version = "0.3.9"
heck = "0.5.0"
pbjson-build = { version = "0.6.2", optional = true }
prettyplease = "0.2.4"
Expand Down
99 changes: 47 additions & 52 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,57 +10,56 @@ use std::{
};
use walkdir::{DirEntry, WalkDir};

const SUBMODULE_ROOT: &str = "substrait";
const PROTO_ROOT: &str = "substrait/proto";
const TEXT_ROOT: &str = "substrait/text";
const GEN_ROOT: &str = "gen";

/// Add Substrait version information to the build
fn substrait_version() -> Result<(), Box<dyn Error>> {
use git2::{DescribeFormatOptions, DescribeOptions, Repository};
let gen_dir = Path::new(GEN_ROOT);
fs::create_dir_all(gen_dir)?;

let substrait_version_file =
PathBuf::from(env::var("CARGO_MANIFEST_DIR")?).join("src/version.in");
let version_in_file = gen_dir.join("version.in");

// Rerun if the Substrait submodule changed (to allow setting `dirty`)
println!(
"cargo:rerun-if-changed={}",
Path::new("substrait").display()
);

// Get the version from the submodule
match Repository::open("substrait") {
Ok(repo) => {
// Rerun if the Substrait submodule HEAD changed (when there is a submodule)
println!(
"cargo:rerun-if-changed={}",
Path::new(".git/modules/substrait/HEAD").display()
);

// Get describe output
let mut describe_options = DescribeOptions::default();
describe_options.describe_tags();
let mut describe_format_options = DescribeFormatOptions::default();
describe_format_options.always_use_long_format(true);
describe_format_options.dirty_suffix("-dirty");
let git_describe = repo
.describe(&describe_options)?
.format(Some(&describe_format_options))?;

let mut split = git_describe.split('-');
let git_version = split.next().unwrap_or_default();
let git_depth = split.next().unwrap_or_default();
let git_dirty = git_describe.ends_with("dirty");
let git_hash = repo.head()?.peel_to_commit()?.id().to_string();
let semver::Version {
major,
minor,
patch,
..
} = semver::Version::parse(git_version.trim_start_matches('v'))?;

fs::write(
substrait_version_file,
format!(
r#"// SPDX-License-Identifier: Apache-2.0
// Check if there is a submodule. This file is not included in the packaged crate.
if Path::new(SUBMODULE_ROOT).join(".git").exists() {
// Rerun if the Substrait submodule HEAD changed (when there is a submodule)
println!(
"cargo:rerun-if-changed={}",
Path::new(".git/modules/substrait/HEAD").display()
);

// Get the version of the submodule. The fallback is needed for the package build.
const VERSION: &str = git_version::git_submodule_versions!(
args = ["--tags", "--long", "--dirty=-dirty", "--abbrev=40"],
fallback = ""
)[0]
.1;
let mut split = VERSION.split('-');
let git_version = split.next().unwrap_or_default();
let git_depth = split.next().unwrap_or_default();
let git_hash = split.next().unwrap_or_default();
let git_dirty = VERSION.ends_with("dirty");
let version = semver::Version::parse(git_version.trim_start_matches('v'))?;

let &semver::Version {
major,
minor,
patch,
..
} = &version;

fs::write(
version_in_file,
format!(
r#"// SPDX-License-Identifier: Apache-2.0
// Note that this file is auto-generated and auto-synced using `build.rs`. It is
// included in `version.rs`.
Expand All @@ -79,27 +78,23 @@ pub const SUBSTRAIT_GIT_SHA: &str = "{git_hash}";
/// The `git describe` output of the Substrait submodule used to build this
/// crate
pub const SUBSTRAIT_GIT_DESCRIBE: &str = "{git_describe}";
pub const SUBSTRAIT_GIT_DESCRIBE: &str = "{VERSION}";
/// The amount of commits between the latest tag and this version of the
/// Substrait module used to build this crate
/// The amount of commits between the latest tag and the version of the
/// Substrait submodule used to build this crate
pub const SUBSTRAIT_GIT_DEPTH: u32 = {git_depth};
/// The dirty state of the Substrait submodule used to build this crate
pub const SUBSTRAIT_GIT_DIRTY: bool = {git_dirty};
"#
),
)?;
),
)?;
} else {
// If we don't have a version file yet we fail the build.
if !version_in_file.exists() {
panic!("Couldn't find the substrait submodule. Please clone the submodule: `git submodule update --init`.")
}
Err(e) => {
// If this is a package build the `substrait_version_file` should
// exist. If it does not, it means this is probably a Git build that
// did not clone the substrait submodule.
if !substrait_version_file.exists() {
panic!("Couldn't open the substrait submodule: {e}")
}
}
};
}

Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

use crate::proto::Version;

include!("version.in");
include!("../gen/version.in");

/// Returns the version of Substrait used to build this crate.
///
Expand Down

0 comments on commit 22d6df7

Please sign in to comment.