Skip to content

Commit 24df4de

Browse files
committed
target-triple by value
1 parent cf39c12 commit 24df4de

File tree

5 files changed

+91
-84
lines changed

5 files changed

+91
-84
lines changed

prebindgen/src/api/source.rs

Lines changed: 42 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ pub struct Source {
7070
items: HashMap<String, Vec<(syn::Item, SourceLocation)>>,
7171
// Configuration needed to build a CfgFilter at iteration time
7272
features_constant: Option<String>,
73-
target_triple_env_var: Option<String>,
73+
target_triple: Option<String>,
7474
features_list: Vec<String>, // normalized list from features.txt
7575
}
7676

@@ -95,7 +95,7 @@ impl Source {
9595
fn build_internal(
9696
input_dir: &Path,
9797
features_constant: Option<String>,
98-
target_triple_env_var: Option<String>,
98+
target_triple: Option<String>,
9999
) -> Self {
100100
if let Some(source) = DOCTEST_SOURCE.with(|source| (*source.borrow()).clone()) {
101101
return source;
@@ -130,7 +130,7 @@ impl Source {
130130
items,
131131
features_constant,
132132
features_list,
133-
target_triple_env_var,
133+
target_triple,
134134
}
135135
}
136136

@@ -164,7 +164,7 @@ impl Source {
164164
),
165165
]),
166166
features_constant: None,
167-
target_triple_env_var: None,
167+
target_triple: None,
168168
features_list: Vec::new(),
169169
};
170170
DOCTEST_SOURCE.with(|cell| {
@@ -282,20 +282,9 @@ impl Source {
282282
.join(" ");
283283
builder = builder.predefined_features(qualified_const, features_list);
284284
}
285-
if let Some(env_var) = &self.target_triple_env_var {
286-
let target = std::env::var(env_var).unwrap_or_else(|_| {
287-
panic!(
288-
"Environment variable {} is not set. \
289-
Ensure that the build script sets it to the target triple.",
290-
env_var
291-
)
292-
});
293-
let target_triple = TargetTriple::parse(&target).unwrap_or_else(|e| {
294-
panic!(
295-
"Failed to parse target triple '{}' from environment variable {}: {}",
296-
target, env_var, e
297-
)
298-
});
285+
if let Some(target) = &self.target_triple {
286+
let target_triple = TargetTriple::parse(target)
287+
.unwrap_or_else(|e| panic!("Failed to parse target triple '{}': {}", target, e));
299288
builder = builder
300289
.enable_target_arch(target_triple.arch())
301290
.enable_target_os(target_triple.os())
@@ -400,15 +389,16 @@ fn read_features_from_out_dir(input_dir: &Path) -> Vec<String> {
400389
pub struct Builder {
401390
input_dir: PathBuf,
402391
features_constant: Option<String>,
403-
target_triple_env_var: Option<String>,
392+
target_triple: Option<String>,
404393
}
405394

406395
impl Builder {
407396
fn new<P: AsRef<Path>>(input_dir: P) -> Self {
397+
let target_triple = std::env::var("TARGET").or(std::env::var("HOST")).ok();
408398
Self {
409399
input_dir: input_dir.as_ref().to_path_buf(),
410400
features_constant: Some("FEATURES".to_string()),
411-
target_triple_env_var: Some("TARGET".to_string()),
401+
target_triple,
412402
}
413403
}
414404

@@ -448,54 +438,58 @@ impl Builder {
448438
self
449439
}
450440

451-
/// Enables filtering source code by target-triple which is usually
452-
/// passed to `build.rs` in `TARGET` environment variable.
453-
/// Accepts the name of the environment variable as an optional string.
454-
/// Default value is `TARGET`.
441+
/// Enables filtering source code by target-triple. This is
442+
/// useful if some binding generators or custom tools over them
443+
/// encounter problems with build conditions in the source code.
444+
///
445+
/// Accepts the target triple string.
446+
///
447+
/// Default value is the value of the environment variable
448+
/// `TARGET` or `HOST` if `TARGET` is not set.
455449
///
456450
/// Pass `None` to disable target filtering.
457451
///
458452
/// When enabled, the code will be filtered by the target triple specified
459-
/// (architecture, vendor, os, env). By default filtering is performed
460-
/// by the value from the `TARGET` environment variable which contains
461-
/// the target triple for the library.
453+
/// (architecture, vendor, os, env).
462454
///
463455
/// It's useful to mention that it's hard to imagine a scenario
464-
/// when it's necessary to change the environment variable name.
456+
/// when it's necessary to change the target triple.
465457
/// The `Source` object is used in the final crate, the one which builds the
466-
/// no-mangle library and the language bindings (e.g. C headers). On this
467-
/// stage the `TARGET` environment variable contains real target triple
468-
/// even in cross-compilation scenarios. Passing the real target in the
469-
/// other variable's name, e.g:
458+
/// no-mangle library. On this stage the `TARGET` environment variable contains
459+
/// real target triple for cross-compilation scenarios.
460+
///
461+
/// There is the case when build.rs is not aware of the cross-compilation
462+
/// target: the build.rs for library in [build-dependencies] section.
463+
/// This is the situation which the "ffi" crate found itself in. So sometimes
464+
/// for correct code generation it's necessary to inform the underlying "ffi"
465+
/// crate about the real target in a way like this:
466+
///
470467
/// ```ignore
471468
/// CROSS_TARGET=x86_64-pc-windows-gnu cargo build --target x86_64-pc-windows-gnu
472469
/// ```
473-
/// sometimes is necessary to inform the underlying "ffi" crate about the
474-
/// real target triple, because it's compiled as a `build.rs` dependency on
475-
/// the host platform and therefore it's target is the host.
476-
/// But the `Source` is not called on this stage, so normally the access to
477-
/// this `CROSS_TARGET` variable is not needed.
478-
/// But for the sake of completeness the ability to use any environment variable
479-
/// is provided.
480-
/// It's also possible to just create standalone `CfgFilter` object
470+
///
471+
/// But in typical situation this doesn't affect the `Source` object which
472+
/// reads the data prepared by "ffi" crate on the following stage.
473+
///
474+
/// So this `Some(<target-triple>)` is added mostly for API completeness,
475+
/// typical usage if this function will be with `None` argument to disable
476+
/// filtering by target triple if it's necessary to see the original
477+
/// collected code.
478+
///
479+
/// Notice also that it's possible to just create standalone `CfgFilter` object
481480
/// with necessary configuration and insert into the iterator chain.
482481
#[roxygen]
483482
pub fn enable_target_filtering(
484483
mut self,
485-
/// Full name of the environment variable which contains the target triple
486-
/// to which the code is generated
484+
/// The target triple to filter collected sources
487485
name: Option<impl Into<String>>,
488486
) -> Self {
489-
self.target_triple_env_var = name.map(|n| n.into());
487+
self.target_triple = name.map(|n| n.into());
490488
self
491489
}
492490

493491
/// Build the `Source` instance
494492
pub fn build(self) -> Source {
495-
Source::build_internal(
496-
&self.input_dir,
497-
self.features_constant,
498-
self.target_triple_env_var,
499-
)
493+
Source::build_internal(&self.input_dir, self.features_constant, self.target_triple)
500494
}
501495
}

prebindgen/src/codegen/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ pub struct CfgExprRules {
2626
impl CfgExprRules {
2727
// Return true if any rule is exists
2828
pub fn is_active(&self) -> bool {
29-
!self.enabled_features.is_empty() ||
30-
!self.disabled_features.is_empty() ||
31-
!self.feature_mappings.is_empty() ||
32-
self.disable_unknown_features ||
33-
self.enabled_target_arch.is_some() ||
34-
self.enabled_target_vendor.is_some() ||
35-
self.enabled_target_os.is_some() ||
36-
self.enabled_target_env.is_some()
29+
!self.enabled_features.is_empty()
30+
|| !self.disabled_features.is_empty()
31+
|| !self.feature_mappings.is_empty()
32+
|| self.disable_unknown_features
33+
|| self.enabled_target_arch.is_some()
34+
|| self.enabled_target_vendor.is_some()
35+
|| self.enabled_target_os.is_some()
36+
|| self.enabled_target_env.is_some()
3737
}
3838
}
3939

prebindgen/src/codegen/process_features.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,7 @@ fn process_enum_variants(
104104
for variant_pair in variants.pairs() {
105105
let mut variant = variant_pair.into_value().clone();
106106
// Process variant attributes
107-
let keep_variant = process_attributes(
108-
&mut variant.attrs,
109-
rules,
110-
source_location,
111-
);
107+
let keep_variant = process_attributes(&mut variant.attrs, rules, source_location);
112108

113109
if keep_variant {
114110
// Process variant fields if it's kept
@@ -129,11 +125,7 @@ fn process_union_fields(
129125
let mut new_fields = syn::punctuated::Punctuated::new();
130126
for field_pair in fields.named.pairs() {
131127
let mut field = field_pair.into_value().clone();
132-
if process_attributes(
133-
&mut field.attrs,
134-
rules,
135-
source_location,
136-
) {
128+
if process_attributes(&mut field.attrs, rules, source_location) {
137129
new_fields.push(field);
138130
}
139131
}
@@ -158,10 +150,7 @@ fn process_attributes(
158150
match CfgExpr::parse_from_tokens(&meta_list.tokens) {
159151
Ok(cfg_expr) => {
160152
// Apply strict feature processing
161-
match cfg_expr.apply_rules(
162-
rules,
163-
source_location,
164-
) {
153+
match cfg_expr.apply_rules(rules, source_location) {
165154
Some(processed_expr) => {
166155
// Check if the processed expression is CfgExpr::False
167156
if matches!(processed_expr, CfgExpr::False) {

prebindgen/src/codegen/tests/cfg_expr.rs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ fn test_target_filters_processing() {
3030

3131
// With no selection, keep predicates as-is
3232
let expr = CfgExpr::TargetOs("macos".into());
33-
assert_eq!(expr.apply_rules(&CfgExprRules::default(), &src), Some(CfgExpr::TargetOs("macos".into())));
33+
assert_eq!(
34+
expr.apply_rules(&CfgExprRules::default(), &src),
35+
Some(CfgExpr::TargetOs("macos".into()))
36+
);
3437

3538
// No selection for arch/vendor/env should also keep predicates as-is
3639
assert_eq!(
@@ -49,7 +52,10 @@ fn test_target_filters_processing() {
4952
// Select OS = macos: becomes true (None)
5053
assert_eq!(
5154
CfgExpr::TargetOs("macos".into()).apply_rules(
52-
&CfgExprRules { enabled_target_os: Some("macos".into()), ..Default::default() },
55+
&CfgExprRules {
56+
enabled_target_os: Some("macos".into()),
57+
..Default::default()
58+
},
5359
&src,
5460
),
5561
None
@@ -58,7 +64,10 @@ fn test_target_filters_processing() {
5864
// Non-matching becomes False
5965
assert_eq!(
6066
CfgExpr::TargetOs("linux".into()).apply_rules(
61-
&CfgExprRules { enabled_target_os: Some("macos".into()), ..Default::default() },
67+
&CfgExprRules {
68+
enabled_target_os: Some("macos".into()),
69+
..Default::default()
70+
},
6271
&src,
6372
),
6473
Some(CfgExpr::False)
@@ -67,14 +76,20 @@ fn test_target_filters_processing() {
6776
// Arch selection
6877
assert_eq!(
6978
CfgExpr::TargetArch("x86_64".into()).apply_rules(
70-
&CfgExprRules { enabled_target_arch: Some("x86_64".into()), ..Default::default() },
79+
&CfgExprRules {
80+
enabled_target_arch: Some("x86_64".into()),
81+
..Default::default()
82+
},
7183
&src,
7284
),
7385
None
7486
);
7587
assert_eq!(
7688
CfgExpr::TargetArch("aarch64".into()).apply_rules(
77-
&CfgExprRules { enabled_target_arch: Some("x86_64".into()), ..Default::default() },
89+
&CfgExprRules {
90+
enabled_target_arch: Some("x86_64".into()),
91+
..Default::default()
92+
},
7893
&src,
7994
),
8095
Some(CfgExpr::False)
@@ -83,30 +98,42 @@ fn test_target_filters_processing() {
8398
// Vendor and Env selection
8499
assert_eq!(
85100
CfgExpr::TargetVendor("apple".into()).apply_rules(
86-
&CfgExprRules { enabled_target_vendor: Some("apple".into()), ..Default::default() },
101+
&CfgExprRules {
102+
enabled_target_vendor: Some("apple".into()),
103+
..Default::default()
104+
},
87105
&src,
88106
),
89107
None
90108
);
91109
// Non-matching vendor becomes False
92110
assert_eq!(
93111
CfgExpr::TargetVendor("unknown".into()).apply_rules(
94-
&CfgExprRules { enabled_target_vendor: Some("apple".into()), ..Default::default() },
112+
&CfgExprRules {
113+
enabled_target_vendor: Some("apple".into()),
114+
..Default::default()
115+
},
95116
&src,
96117
),
97118
Some(CfgExpr::False)
98119
);
99120
assert_eq!(
100121
CfgExpr::TargetEnv("gnu".into()).apply_rules(
101-
&CfgExprRules { enabled_target_env: Some("gnu".into()), ..Default::default() },
122+
&CfgExprRules {
123+
enabled_target_env: Some("gnu".into()),
124+
..Default::default()
125+
},
102126
&src,
103127
),
104128
None
105129
);
106130
// Non-matching env becomes False
107131
assert_eq!(
108132
CfgExpr::TargetEnv("msvc".into()).apply_rules(
109-
&CfgExprRules { enabled_target_env: Some("gnu".into()), ..Default::default() },
133+
&CfgExprRules {
134+
enabled_target_env: Some("gnu".into()),
135+
..Default::default()
136+
},
110137
&src,
111138
),
112139
Some(CfgExpr::False)
@@ -259,10 +286,7 @@ fn test_strict_feature_processing() {
259286
fn test_strict_feature_processing_unmapped_panic() {
260287
// Test unmapped feature - should panic
261288
let expr = CfgExpr::Feature("unknown".to_string());
262-
expr.apply_rules(
263-
&CfgExprRules::default(),
264-
&SourceLocation::default(),
265-
);
289+
expr.apply_rules(&CfgExprRules::default(), &SourceLocation::default());
266290
}
267291

268292
#[test]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
mod cfg_expr;
1+
mod cfg_expr;

0 commit comments

Comments
 (0)