Skip to content
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
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ roxygen = "1.0.4"
tempfile = "3.0"
itertools = "0.14.0"
if_rust_version = "1.0"
konst = "0.3.0"
konst = "0.3.0" # old one for for rust 1.75
toml = "0.9.5"

[patch]

Expand Down
1 change: 1 addition & 0 deletions prebindgen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ roxygen = { workspace = true }
if_rust_version = { workspace = true }
konst = { workspace = true, features = ["cmp"] }
itertools = { workspace = true }
toml = { workspace = true }

[features]
debug = []
Expand Down
80 changes: 65 additions & 15 deletions prebindgen/src/api/buildrs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::BTreeSet, env, fs};
use std::{collections::BTreeSet, env, fs, path::Path};

use crate::{CRATE_NAME_FILE, FEATURES_FILE};

Expand Down Expand Up @@ -62,7 +62,7 @@ pub fn init_prebindgen_out_dir() {
);
});

let features = get_features();
let features = get_enabled_features();

// Save features list to features.txt (one per line)
let features_path = prebindgen_dir.join(FEATURES_FILE);
Expand Down Expand Up @@ -92,22 +92,72 @@ pub fn init_prebindgen_out_dir() {
);
}

/// Collect enabled Cargo features from environment and store them
/// Cargo exposes enabled features to build.rs as env vars CARGO_FEATURE_<NAME>
/// where <NAME> is uppercased.
/// TODO: there is ambiguity in feature names with '-' and '_'
/// Currently this is ignored, the projects with features with hyphens will
/// not work correctly with this implementation.
pub fn get_features() -> BTreeSet<String> {
/// Read all feature names declared in the current crate's `Cargo.toml`.
///
/// Notes:
/// - Excludes the special `default` feature from the returned set.
/// - Panics if called outside of build.rs (requires OUT_DIR and CARGO_MANIFEST_DIR).
pub fn get_all_features() -> BTreeSet<String> {
// Ensure we are in build.rs context
env::var("OUT_DIR").expect(
"OUT_DIR environment variable not set. This function should be called from build.rs.",
);
let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect(
"CARGO_MANIFEST_DIR environment variable not set. This function should be called from build.rs.",
);
let manifest_path = Path::new(&manifest_dir).join("Cargo.toml");

let manifest_content = fs::read_to_string(&manifest_path).unwrap_or_else(|e| {
panic!(
"Failed to read Cargo.toml at {}: {}",
manifest_path.display(),
e
)
});

let doc: toml::Value = toml::from_str(&manifest_content).unwrap_or_else(|e| {
panic!(
"Failed to parse Cargo.toml at {} as TOML: {}",
manifest_path.display(),
e
)
});

let mut set = BTreeSet::new();
if let Some(features_tbl) = doc.get("features").and_then(|v| v.as_table()) {
for key in features_tbl.keys() {
if key != "default" {
set.insert(key.to_string());
}
}
}
set
}

/// Check whether a feature is enabled by looking at the corresponding
/// `CARGO_FEATURE_<NAME>` environment variable provided to build scripts by Cargo.
/// Hyphens in feature names are converted to underscores to match Cargo's env var format.
pub fn is_feature_enabled(feature: &str) -> bool {
// Ensure we are in build.rs context
env::var("OUT_DIR").expect(
"OUT_DIR environment variable not set. This function should be called from build.rs.",
);
std::env::vars()
.filter_map(|(k, _)| {
k.strip_prefix("CARGO_FEATURE_")
.map(|name| name.to_string())
})
.map(|name| name.to_lowercase())
let env_key = format!(
"CARGO_FEATURE_{}",
feature
.to_ascii_uppercase()
.chars()
.map(|c| if c == '-' { '_' } else { c })
.collect::<String>()
);
env::var_os(env_key).is_some()
}

/// Filter the full features list to only those that are currently enabled.
pub fn get_enabled_features() -> BTreeSet<String> {
get_all_features()
.into_iter()
.filter(|f| is_feature_enabled(f))
.collect()
}

Expand Down
4 changes: 3 additions & 1 deletion prebindgen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,11 @@ pub(crate) mod api;
pub(crate) mod codegen;
pub(crate) mod utils;

pub use crate::api::buildrs::get_all_features;
pub use crate::api::buildrs::get_enabled_features;
pub use crate::api::buildrs::get_prebindgen_out_dir;
pub use crate::api::buildrs::init_prebindgen_out_dir;
pub use crate::api::buildrs::get_features;
pub use crate::api::buildrs::is_feature_enabled;

pub use crate::api::record::SourceLocation;
pub use crate::api::source::Source;
Expand Down