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

Feature 832 custom rust target #859

Merged
merged 1 commit into from
Aug 4, 2017
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
18 changes: 9 additions & 9 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ impl CodeGenerator for Module {
}

if item.id() == ctx.root_module() {
if result.saw_union && !ctx.options().unstable_rust {
if result.saw_union && !ctx.options().rust_features().untagged_union() {
utils::prepend_union_types(ctx, &mut *result);
}
if result.saw_incomplete_array {
Expand Down Expand Up @@ -911,8 +911,8 @@ impl<'a> FieldCodegen<'a> for FieldData {
let field_ty = ctx.resolve_type(self.ty());
let ty = self.ty().to_rust_ty_or_opaque(ctx, &());

// NB: In unstable rust we use proper `union` types.
let ty = if parent.is_union() && !ctx.options().unstable_rust {
// NB: If supported, we use proper `union` types.
let ty = if parent.is_union() && !ctx.options().rust_features().untagged_union() {
if ctx.options().enable_cxx_namespaces {
quote_ty!(ctx.ext_cx(), root::__BindgenUnionField<$ty>)
} else {
Expand Down Expand Up @@ -1052,8 +1052,8 @@ impl BitfieldUnit {
-> P<ast::Item> {
let ctor_name = self.ctor_name(ctx);

// If we're generating unstable Rust, add the const.
let fn_prefix = if ctx.options().unstable_rust {
// If supported, add the const.
let fn_prefix = if ctx.options().rust_features().const_fn() {
quote_tokens!(ctx.ext_cx(), pub const fn)
} else {
quote_tokens!(ctx.ext_cx(), pub fn)
Expand Down Expand Up @@ -1115,8 +1115,8 @@ impl Bitfield {
let offset = self.offset_into_unit();
let mask = self.mask();

// If we're generating unstable Rust, add the const.
let fn_prefix = if ctx.options().unstable_rust {
// If supported, add the const.
let fn_prefix = if ctx.options().rust_features().const_fn() {
quote_tokens!(ctx.ext_cx(), pub const fn)
} else {
quote_tokens!(ctx.ext_cx(), pub fn)
Expand Down Expand Up @@ -1445,7 +1445,7 @@ impl CodeGenerator for CompInfo {
}

let canonical_name = item.canonical_name(ctx);
let builder = if is_union && ctx.options().unstable_rust {
let builder = if is_union && ctx.options().rust_features().untagged_union() {
aster::AstBuilder::new()
.item()
.pub_()
Expand Down Expand Up @@ -1552,7 +1552,7 @@ impl CodeGenerator for CompInfo {
());
}

if is_union && !ctx.options().unstable_rust {
if is_union && !ctx.options().rust_features().untagged_union() {
let layout = layout.expect("Unable to get layout information?");
let ty = BlobTyBuilder::new(layout).build();
let field = StructFieldBuilder::named("bindgen_union_field")
Expand Down
187 changes: 187 additions & 0 deletions src/features.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
//! Contains code for selecting features

#![deny(missing_docs)]
#![deny(warnings)]
#![deny(unused_extern_crates)]

use std::io;
use std::str::FromStr;

/// Define RustTarget struct definition, Default impl, and conversions
/// between RustTarget and String.
macro_rules! rust_target_def {
( $( $( #[$attr:meta] )* => $release:ident => $value:expr; )* ) => {
/// Represents the version of the Rust language to target.
///
/// To support a beta release, use the corresponding stable release.
///
/// This enum will have more variants added as necessary.
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Hash)]
#[allow(non_camel_case_types)]
pub enum RustTarget {
$(
$(
#[$attr]
)*
$release,
)*
}

impl Default for RustTarget {
/// Gives the latest stable Rust version
fn default() -> RustTarget {
LATEST_STABLE_RUST
}
}

impl FromStr for RustTarget {
type Err = io::Error;

#[allow(dead_code)]
/// Create a `RustTarget` from a string.
///
/// * The stable/beta versions of Rust are of the form "1.0",
/// "1.19", etc.
/// * The nightly version should be specified with "nightly".
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.as_ref() {
$(
stringify!($value) => Ok(RustTarget::$release),
)*
_ => Err(
io::Error::new(
io::ErrorKind::InvalidInput,
concat!(
"Got an invalid rust target. Accepted values ",
"are of the form ",
"\"1.0\" or \"nightly\"."))),
}
}
}

impl From<RustTarget> for String {
fn from(target: RustTarget) -> Self {
match target {
$(
RustTarget::$release => stringify!($value),
)*
}.into()
}
}
}
}

/// Defines an array slice with all RustTarget values
macro_rules! rust_target_values_def {
( $( $( #[$attr:meta] )* => $release:ident => $value:expr; )* ) => {
/// Strings of allowed `RustTarget` values
#[allow(dead_code)]
pub static RUST_TARGET_STRINGS: &'static [&str] = &[
$(
stringify!($value),
)*
];
}
}

/// Defines macro which takes a macro
macro_rules! rust_target_base {
( $x_macro:ident ) => {
$x_macro!(
/// Rust stable 1.0
=> Stable_1_0 => 1.0;
/// Rust stable 1.19
=> Stable_1_19 => 1.19;
/// Nightly rust
=> Nightly => nightly;
);
}
}

rust_target_base!(rust_target_def);
rust_target_base!(rust_target_values_def);

/// Latest stable release of Rust
pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_19;

/// Create RustFeatures struct definition, new(), and a getter for each field
macro_rules! rust_feature_def {
( $( $( #[$attr:meta] )* => $feature:ident; )* ) => {
/// Features supported by a rust target
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct RustFeatures {
$(
$feature: bool,
)*
}

impl RustFeatures {
/// Gives a RustFeatures struct with all features disabled
fn new() -> Self {
RustFeatures {
$(
$feature: false,
)*
}
}

$(
$(
#[$attr]
)*
pub fn $feature(&self) -> bool {
self.$feature
}
)*
}
}
}

rust_feature_def!(
/// Untagged unions ([RFC 1444](https://github.com/rust-lang/rfcs/blob/master/text/1444-union.md))
=> untagged_union;
/// Constant function ([RFC 911](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md))
=> const_fn;
);

impl From<RustTarget> for RustFeatures {
fn from(rust_target: RustTarget) -> Self {
let mut features = RustFeatures::new();

if rust_target >= RustTarget::Stable_1_19 {
features.untagged_union = true;
}

if rust_target >= RustTarget::Nightly {
features.const_fn = true;
}

features
}
}

impl Default for RustFeatures {
fn default() -> Self {
let default_rust_target: RustTarget = Default::default();
Self::from(default_rust_target)
}
}

#[cfg(test)]
mod test {
#![allow(unused_imports)]
use super::*;

fn test_target(target_str: &str, target: RustTarget) {
let target_string: String = target.into();
assert_eq!(target_str, target_string);
assert_eq!(target, RustTarget::from_str(target_str).unwrap());
}

#[test]
fn str_to_target() {
test_target("1.0", RustTarget::Stable_1_0);
test_target("1.19", RustTarget::Stable_1_19);
test_target("nightly", RustTarget::Nightly);
}
}
2 changes: 1 addition & 1 deletion src/ir/analysis/derive_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> {
}

if info.kind() == CompKind::Union {
if !self.ctx.options().unstable_rust {
if !self.ctx.options().rust_features().untagged_union() {
// NOTE: If there's no template parameters we can derive copy
// unconditionally, since arrays are magical for rustc, and
// __BindgenUnionField always implements copy.
Expand Down
2 changes: 1 addition & 1 deletion src/ir/analysis/derive_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
);

if info.kind() == CompKind::Union {
if self.ctx.options().unstable_rust {
if self.ctx.options().rust_features().untagged_union() {
trace!(" cannot derive Debug for Rust unions");
return self.insert(id);
}
Expand Down
2 changes: 1 addition & 1 deletion src/ir/analysis/derive_default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> {
);

if info.kind() == CompKind::Union {
if self.ctx.options().unstable_rust {
if self.ctx.options().rust_features().untagged_union() {
trace!(" cannot derive Default for Rust unions");
return self.insert(id);
}
Expand Down
Loading