aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXidorn Quan <me@upsuper.org>2017-05-19 10:35:36 +1000
committerXidorn Quan <me@upsuper.org>2017-05-19 11:08:35 +1000
commitf123b26e6c47b1f317ff3ec213a25f6d7b71dfe5 (patch)
tree96a7653225ba817088500be4a93e136a232fdd54
parent0b3fd8de767c6ad6ea2fd983c396f5c0a20becfc (diff)
downloadservo-f123b26e6c47b1f317ff3ec213a25f6d7b71dfe5.tar.gz
servo-f123b26e6c47b1f317ff3ec213a25f6d7b71dfe5.zip
Move config info from build_gecko.rs to a toml file in gecko.
-rw-r--r--Cargo.lock1
-rw-r--r--components/style/Cargo.toml3
-rw-r--r--components/style/build.rs2
-rw-r--r--components/style/build_gecko.rs822
4 files changed, 248 insertions, 580 deletions
diff --git a/Cargo.lock b/Cargo.lock
index b21ff19f356..ba083e6e890 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2852,6 +2852,7 @@ dependencies = [
"smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"style_traits 0.0.1",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml
index 708488861e8..f9b93b7500d 100644
--- a/components/style/Cargo.toml
+++ b/components/style/Cargo.toml
@@ -14,7 +14,7 @@ doctest = false
[features]
gecko = ["nsstring_vendor", "rayon/unstable", "num_cpus", "style_traits/gecko"]
-use_bindgen = ["bindgen", "regex"]
+use_bindgen = ["bindgen", "regex", "toml"]
servo = ["serde", "serde_derive", "heapsize", "heapsize_derive",
"style_traits/servo", "servo_atoms", "servo_config", "html5ever",
"cssparser/heapsize", "cssparser/serde", "encoding", "smallvec/heapsizeof",
@@ -69,3 +69,4 @@ log = "0.3"
bindgen = { version = "0.25", optional = true }
regex = {version = "0.2", optional = true}
walkdir = "1.0"
+toml = {version = "0.2.1", optional = true, default-features = false}
diff --git a/components/style/build.rs b/components/style/build.rs
index 8d40ccb9969..e5d3b40c204 100644
--- a/components/style/build.rs
+++ b/components/style/build.rs
@@ -10,6 +10,8 @@ extern crate bindgen;
extern crate log;
#[cfg(feature = "bindgen")]
extern crate regex;
+#[cfg(feature = "bindgen")]
+extern crate toml;
extern crate walkdir;
use std::env;
diff --git a/components/style/build_gecko.rs b/components/style/build_gecko.rs
index 0812e902707..a6ecb8ac732 100644
--- a/components/style/build_gecko.rs
+++ b/components/style/build_gecko.rs
@@ -29,18 +29,20 @@ mod common {
mod bindings {
use bindgen::{Builder, CodegenConfig};
use bindgen::callbacks::{EnumVariantCustomBehavior, EnumVariantValue, ParseCallbacks};
- use regex::Regex;
+ use regex::{Regex, RegexSet};
use std::cmp;
- use std::collections::HashSet;
+ use std::collections::{HashSet, HashMap};
use std::env;
use std::fs::{self, File};
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use std::process::{Command, exit};
+ use std::slice;
use std::sync::Mutex;
use std::time::SystemTime;
use super::common::*;
use super::super::PYTHON;
+ use toml;
const STRUCTS_DEBUG_FILE: &'static str = "structs_debug.rs";
const STRUCTS_RELEASE_FILE: &'static str = "structs_release.rs";
@@ -60,6 +62,41 @@ mod bindings {
}
lazy_static! {
+ static ref CONFIG: toml::Table = {
+ let path = PathBuf::from(env::var("MOZ_SRC").unwrap())
+ .join("layout/style/ServoBindings.toml");
+ println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
+ update_last_modified(&path);
+
+ let mut contents = String::new();
+ File::open(path).expect("Failed to open config file")
+ .read_to_string(&mut contents).expect("Failed to read config file");
+ let mut parser = toml::Parser::new(&contents);
+ if let Some(result) = parser.parse() {
+ result
+ } else {
+ use std::fmt::Write;
+ let mut reason = String::from("Failed to parse config file:");
+ for err in parser.errors.iter() {
+ let parsed = &contents[..err.lo];
+ write!(&mut reason, "\n* line {} column {}: {}",
+ parsed.lines().count(),
+ parsed.lines().last().map_or(0, |l| l.len()),
+ err).unwrap();
+ }
+ panic!(reason)
+ }
+ };
+ static ref TARGET_INFO: HashMap<String, String> = {
+ const TARGET_PREFIX: &'static str = "CARGO_CFG_TARGET_";
+ let mut result = HashMap::new();
+ for (k, v) in env::vars() {
+ if k.starts_with(TARGET_PREFIX) {
+ result.insert(k[TARGET_PREFIX.len()..].to_lowercase(), v);
+ }
+ }
+ result
+ };
static ref INCLUDE_RE: Regex = Regex::new(r#"#include\s*"(.+?)""#).unwrap();
static ref DISTDIR_PATH: PathBuf = {
let path = PathBuf::from(env::var("MOZ_DIST").unwrap());
@@ -73,7 +110,7 @@ mod bindings {
DISTDIR_PATH.join("include/nspr"),
];
static ref ADDED_PATHS: Mutex<HashSet<PathBuf>> = Mutex::new(HashSet::new());
- pub static ref LAST_MODIFIED: Mutex<SystemTime> =
+ static ref LAST_MODIFIED: Mutex<SystemTime> =
Mutex::new(get_modified_time(&env::current_exe().unwrap())
.expect("Failed to get modified time of executable"));
}
@@ -82,16 +119,19 @@ mod bindings {
file.metadata().and_then(|m| m.modified()).ok()
}
+ fn update_last_modified(file: &Path) {
+ let modified = get_modified_time(file).unwrap();
+ let mut last_modified = LAST_MODIFIED.lock().unwrap();
+ *last_modified = cmp::max(modified, *last_modified);
+ }
+
fn search_include(name: &str) -> Option<PathBuf> {
for path in SEARCH_PATHS.iter() {
let file = path.join(name);
- if !file.is_file() {
- continue;
+ if file.is_file() {
+ update_last_modified(&file);
+ return Some(file);
}
- let modified = get_modified_time(&file).unwrap();
- let mut last_modified = LAST_MODIFIED.lock().unwrap();
- *last_modified = cmp::max(modified, *last_modified);
- return Some(file);
}
None
}
@@ -124,22 +164,43 @@ mod bindings {
trait BuilderExt {
fn get_initial_builder(build_type: BuildType) -> Builder;
fn include<T: Into<String>>(self, file: T) -> Builder;
- fn zero_size_type(self, ty: &str, structs_list: &[&str]) -> Builder;
+ fn zero_size_type(self, ty: &str, structs_list: &HashSet<&str>) -> Builder;
fn borrowed_type(self, ty: &str) -> Builder;
fn mutable_borrowed_type(self, ty: &str) -> Builder;
}
+ fn add_clang_args(mut builder: Builder, config: &toml::Table, matched_os: &mut bool) -> Builder {
+ fn add_args(mut builder: Builder, values: &[toml::Value]) -> Builder {
+ for item in values.iter() {
+ builder = builder.clang_arg(item.as_str().expect("Expect string in list"));
+ }
+ builder
+ }
+ for (k, v) in config.iter() {
+ if k == "args" {
+ builder = add_args(builder, v.as_slice().unwrap());
+ continue;
+ }
+ let equal_idx = k.find('=').expect(&format!("Invalid key: {}", k));
+ let (target_type, target_value) = k.split_at(equal_idx);
+ if TARGET_INFO[target_type] != target_value[1..] {
+ continue;
+ }
+ if target_type == "os" {
+ *matched_os = true;
+ }
+ builder = match *v {
+ toml::Value::Table(ref table) => add_clang_args(builder, table, matched_os),
+ toml::Value::Array(ref array) => add_args(builder, array),
+ _ => panic!("Unknown type"),
+ };
+ }
+ builder
+ }
+
impl BuilderExt for Builder {
fn get_initial_builder(build_type: BuildType) -> Builder {
let mut builder = Builder::default().no_unstable_rust();
- let args = [
- "-x", "c++", "-std=c++14",
- "-DTRACING=1", "-DIMPL_LIBXUL", "-DMOZ_STYLO_BINDINGS=1",
- "-DMOZILLA_INTERNAL_API", "-DRUST_BINDGEN", "-DMOZ_STYLO"
- ];
- for &arg in args.iter() {
- builder = builder.clang_arg(arg);
- }
for dir in SEARCH_PATHS.iter() {
builder = builder.clang_arg("-I").clang_arg(dir.to_str().unwrap());
}
@@ -148,63 +209,11 @@ mod bindings {
if build_type == BuildType::Debug {
builder = builder.clang_arg("-DDEBUG=1").clang_arg("-DJS_DEBUG=1");
}
- // cfg!(...) will check the attributes of the Rust target this file
- // is being compiled for. We want the attributes of the target that
- // the clang we're going to invoke is being compiled for, which isn't
- // necessarily the same thing. Cargo provides the (yet-to-be-documented)
- // CARGO_CFG_* environment variables for this purpose. Those variables
- // should be used in preference to cfg! checks below.
- let target_family = env::var("CARGO_CFG_TARGET_FAMILY").unwrap();
- let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
- let target_pointer_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap();
- let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
- let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
-
- if target_family == "unix" {
- builder = builder.clang_arg("-DOS_POSIX=1");
- }
- if target_os == "linux" {
- builder = builder.clang_arg("-DOS_LINUX=1");
- if target_arch == "x86" {
- builder = builder.clang_arg("-m32");
- } else if target_arch == "x86_64" {
- builder = builder.clang_arg("-m64");
- }
- } else if target_os == "solaris" {
- builder = builder.clang_arg("-DOS_SOLARIS=1");
- } else if target_os == "dragonfly" {
- builder = builder.clang_arg("-DOS_BSD=1").clang_arg("-DOS_DRAGONFLY=1");
- } else if target_os == "freebsd" {
- builder = builder.clang_arg("-DOS_BSD=1").clang_arg("-DOS_FREEBSD=1");
- } else if target_os == "netbsd" {
- builder = builder.clang_arg("-DOS_BSD=1").clang_arg("-DOS_NETBSD=1");
- } else if target_os == "openbsd" {
- builder = builder.clang_arg("-DOS_BSD=1").clang_arg("-DOS_OPENBSD=1");
- } else if target_os == "macos" {
- builder = builder.clang_arg("-DOS_MACOSX=1")
- .clang_arg("-stdlib=libc++")
- // To disable the fixup bindgen applies which adds search
- // paths from clang command line in order to avoid potential
- // conflict with -stdlib=libc++.
- .clang_arg("--target=x86_64-apple-darwin");
- } else if target_env == "msvc" {
- builder = builder.clang_arg("-DOS_WIN=1").clang_arg("-DWIN32=1")
- // For compatibility with MSVC 2015
- .clang_arg("-fms-compatibility-version=19")
- // To enable the builtin __builtin_offsetof so that CRT wouldn't
- // use reinterpret_cast in offsetof() which is not allowed inside
- // static_assert().
- .clang_arg("-D_CRT_USE_BUILTIN_OFFSETOF")
- // Enable hidden attribute (which is not supported by MSVC and
- // thus not enabled by default with a MSVC-compatibile build)
- // to exclude hidden symbols from the generated file.
- .clang_arg("-DHAVE_VISIBILITY_HIDDEN_ATTRIBUTE=1");
- if target_pointer_width == "32" {
- builder = builder.clang_arg("--target=i686-pc-win32");
- } else {
- builder = builder.clang_arg("--target=x86_64-pc-win32");
- }
- } else {
+
+ let mut matched_os = false;
+ let build_config = CONFIG["build"].as_table().expect("Malformed config file");
+ builder = add_clang_args(builder, build_config, &mut matched_os);
+ if !matched_os {
panic!("Unknown platform");
}
builder
@@ -220,8 +229,8 @@ mod bindings {
// Not 100% sure of how safe this is, but it's what we're using
// in the XPCOM ffi too
// https://github.com/nikomatsakis/rust-memory-model/issues/2
- fn zero_size_type(self, ty: &str, structs_list: &[&str]) -> Builder {
- if !structs_list.contains(&ty) {
+ fn zero_size_type(self, ty: &str, structs_list: &HashSet<&str>) -> Builder {
+ if !structs_list.contains(ty) {
self.hide_type(ty)
.raw_line(format!("enum {}Void {{ }}", ty))
.raw_line(format!("pub struct {0}({0}Void);", ty))
@@ -292,318 +301,123 @@ mod bindings {
.collect()
}
- #[derive(Debug)]
- struct Callbacks;
- impl ParseCallbacks for Callbacks {
- fn enum_variant_behavior(&self,
- enum_name: Option<&str>,
- variant_name: &str,
- _variant_value: EnumVariantValue)
- -> Option<EnumVariantCustomBehavior> {
- if enum_name.map_or(false, |n| n == "nsCSSPropertyID") &&
- variant_name.starts_with("eCSSProperty_COUNT") {
- Some(EnumVariantCustomBehavior::Constify)
- } else {
- None
+ struct BuilderWithConfig<'a> {
+ builder: Builder,
+ config: &'a toml::Table,
+ used_keys: HashSet<&'static str>,
+ }
+ impl<'a> BuilderWithConfig<'a> {
+ fn new(builder: Builder, config: &'a toml::Table) -> Self {
+ BuilderWithConfig {
+ builder, config,
+ used_keys: HashSet::new(),
+ }
+ }
+
+ fn handle_list<F>(self, key: &'static str, func: F) -> BuilderWithConfig<'a>
+ where F: FnOnce(Builder, slice::Iter<'a, toml::Value>) -> Builder {
+ let mut builder = self.builder;
+ let config = self.config;
+ let mut used_keys = self.used_keys;
+ if let Some(list) = config.get(key) {
+ used_keys.insert(key);
+ builder = func(builder, list.as_slice().unwrap().iter());
}
+ BuilderWithConfig { builder, config, used_keys }
+ }
+ fn handle_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
+ where F: FnMut(Builder, &'a toml::Value) -> Builder {
+ self.handle_list(key, |b, iter| iter.fold(b, |b, item| func(b, item)))
+ }
+ fn handle_str_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
+ where F: FnMut(Builder, &'a str) -> Builder {
+ self.handle_items(key, |b, item| func(b, item.as_str().unwrap()))
+ }
+ fn handle_table_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
+ where F: FnMut(Builder, &'a toml::Table) -> Builder {
+ self.handle_items(key, |b, item| func(b, item.as_table().unwrap()))
+ }
+ fn handle_common(self, fixups: &mut Vec<Fixup>) -> BuilderWithConfig<'a> {
+ self.handle_str_items("headers", |b, item| b.header(add_include(item)))
+ .handle_str_items("raw-lines", |b, item| b.raw_line(item))
+ .handle_str_items("hide-types", |b, item| b.hide_type(item))
+ .handle_table_items("fixups", |builder, item| {
+ fixups.push(Fixup {
+ pat: item["pat"].as_str().unwrap().into(),
+ rep: item["rep"].as_str().unwrap().into(),
+ });
+ builder
+ })
+ }
+
+ fn get_builder(self) -> Builder {
+ for key in self.config.keys() {
+ if !self.used_keys.contains(key.as_str()) {
+ panic!(format!("Unknown key: {}", key));
+ }
+ }
+ self.builder
}
}
fn generate_structs(build_type: BuildType) {
- let mut builder = Builder::get_initial_builder(build_type)
+ #[derive(Debug)]
+ struct Callbacks(HashMap<String, RegexSet>);
+ impl ParseCallbacks for Callbacks {
+ fn enum_variant_behavior(&self,
+ enum_name: Option<&str>,
+ variant_name: &str,
+ _variant_value: EnumVariantValue)
+ -> Option<EnumVariantCustomBehavior> {
+ enum_name.and_then(|enum_name| self.0.get(enum_name))
+ .and_then(|regex| if regex.is_match(variant_name) {
+ Some(EnumVariantCustomBehavior::Constify)
+ } else {
+ None
+ })
+ }
+ }
+
+ let builder = Builder::get_initial_builder(build_type)
.enable_cxx_namespaces()
.with_codegen_config(CodegenConfig {
types: true,
vars: true,
..CodegenConfig::nothing()
- })
- .header(add_include("nsCSSPseudoClasses.h")) // servo/rust-bindgen#599
- .include(add_include("nsStyleStruct.h"))
- .include(add_include("mozilla/ServoPropPrefList.h"))
- .include(add_include("mozilla/StyleAnimationValue.h"))
- .include(add_include("gfxFontConstants.h"))
- .include(add_include("nsThemeConstants.h"))
- .include(add_include("mozilla/dom/AnimationEffectReadOnlyBinding.h"))
- .include(add_include("mozilla/AnimationPropertySegment.h"))
- .include(add_include("mozilla/ComputedTiming.h"))
- .include(add_include("mozilla/ComputedTimingFunction.h"))
- .include(add_include("mozilla/Keyframe.h"))
- .include(add_include("mozilla/ServoElementSnapshot.h"))
- .include(add_include("mozilla/ServoElementSnapshotTable.h"))
- .include(add_include("mozilla/dom/Element.h"))
- .include(add_include("mozilla/dom/NameSpaceConstants.h"))
- .include(add_include("mozilla/LookAndFeel.h"))
- .include(add_include("mozilla/ServoBindings.h"))
- .include(add_include("nsCSSCounterStyleRule.h"))
- .include(add_include("nsCSSFontFaceRule.h"))
- .include(add_include("nsMediaFeatures.h"))
- .include(add_include("nsMediaList.h"))
- // FIXME(emilio): Incrementally remove these "pub use"s. Probably
- // mozilla::css and mozilla::dom are easier.
- .raw_line("pub use self::root::*;")
- .raw_line("pub use self::root::mozilla::*;")
- .raw_line("pub use self::root::mozilla::css::*;")
- .raw_line("pub use self::root::mozilla::dom::*;")
- .raw_line("use atomic_refcell::AtomicRefCell;")
- .raw_line("use data::ElementData;")
- .hide_type("nsString")
- .bitfield_enum("nsChangeHint")
- .bitfield_enum("nsRestyleHint")
- .constified_enum("UpdateAnimationsTasks")
- .constified_enum("ParsingMode")
- .parse_callbacks(Box::new(Callbacks));
- let whitelist_vars = [
- "NS_AUTHOR_SPECIFIED_.*",
- "NS_THEME_.*",
- "NODE_.*",
- "ELEMENT_.*",
- "NS_FONT_.*",
- "NS_STYLE_.*",
- "NS_MATHML_.*",
- "NS_RADIUS_.*",
- "BORDER_COLOR_.*",
- "BORDER_STYLE_.*",
- "mozilla::SERVO_PREF_.*",
- "CSS_PSEUDO_ELEMENT_.*",
- "SERVO_CSS_PSEUDO_ELEMENT_FLAGS_.*",
- "kNameSpaceID_.*",
- "kGenericFont_.*",
- "kPresContext_.*",
- ];
- let whitelist = [
- "RawGecko.*",
- "mozilla::AnimationPropertySegment",
- "mozilla::ComputedTiming",
- "mozilla::ComputedTimingFunction",
- "mozilla::ComputedTimingFunction::BeforeFlag",
- "mozilla::ServoStyleSheet",
- "mozilla::ServoElementSnapshot.*",
- "mozilla::CSSPseudoClassType",
- "mozilla::css::SheetParsingMode",
- "mozilla::css::URLMatchingFunction",
- "mozilla::HalfCorner",
- "mozilla::PropertyStyleAnimationValuePair",
- "mozilla::TraversalRestyleBehavior",
- "mozilla::TraversalRootBehavior",
- "mozilla::StyleShapeRadius",
- "mozilla::StyleGrid.*",
- "mozilla::UpdateAnimationsTasks",
- "mozilla::LookAndFeel",
- ".*ThreadSafe.*Holder",
- "AnonymousContent",
- "AudioContext",
- "CapturingContentInfo",
- "DefaultDelete",
- "DOMIntersectionObserverEntry",
- "Element",
- "FontFamilyList",
- "FontFamilyListRefCnt",
- "FontFamilyName",
- "FontFamilyType",
- "FontSizePrefs",
- "FragmentOrURL",
- "FrameRequestCallback",
- "GeckoParserExtraData",
- "GeckoFontMetrics",
- "gfxAlternateValue",
- "gfxFontFeature",
- "gfxFontVariation",
- "GridNamedArea",
- "HalfCorner",
- "Image",
- "ImageURL",
- "Keyframe",
- "nsAttrName",
- "nsAttrValue",
- "nsBorderColors",
- "nscolor",
- "nsChangeHint",
- "nsCSSCounterStyleRule",
- "nsCSSFontFaceRule",
- "nsCSSKeyword",
- "nsCSSPropertyID",
- "nsCSSProps",
- "nsCSSRect",
- "nsCSSRect_heap",
- "nsCSSShadowArray",
- "nsCSSValue",
- "nsCSSValueFloatColor",
- "nsCSSValueGradient",
- "nsCSSValueGradientStop",
- "nsCSSValueList",
- "nsCSSValueList_heap",
- "nsCSSValuePair_heap",
- "nsCSSValuePairList",
- "nsCSSValuePairList_heap",
- "nsCSSValueTokenStream",
- "nsCSSValueTriplet_heap",
- "nsCursorImage",
- "nsFont",
- "nsIAtom",
- "nsMainThreadPtrHandle",
- "nsMainThreadPtrHolder",
- "nsMargin",
- "nsMediaExpression",
- "nsMediaFeature",
- "nsMediaFeatures",
- "nsMediaList",
- "nsRect",
- "nsRestyleHint",
- "nsresult",
- "nsSize",
- "nsStyleBackground",
- "nsStyleBorder",
- "nsStyleColor",
- "nsStyleColumn",
- "nsStyleContent",
- "nsStyleContentData",
- "nsStyleContext",
- "nsStyleCoord",
- "nsStyleCounterData",
- "nsStyleDisplay",
- "nsStyleEffects",
- "nsStyleFilter",
- "nsStyleFont",
- "nsStyleGradient",
- "nsStyleGradientStop",
- "nsStyleGridTemplate",
- "nsStyleImage",
- "nsStyleImageLayers",
- "nsStyleList",
- "nsStyleMargin",
- "nsStyleOutline",
- "nsStylePadding",
- "nsStylePosition",
- "nsStyleSVG",
- "nsStyleSVGPaint",
- "nsStyleSVGReset",
- "nsStyleTable",
- "nsStyleTableBorder",
- "nsStyleText",
- "nsStyleTextReset",
- "nsStyleUIReset",
- "nsStyleUnion",
- "nsStyleUnit",
- "nsStyleUserInterface",
- "nsStyleVariables",
- "nsStyleVisibility",
- "nsStyleXUL",
- "nsTArray",
- "nsTArrayHeader",
- "Position",
- "PropertyValuePair",
- "Runnable",
- "ServoAttrSnapshot",
- "ServoBundledURI",
- "ServoElementSnapshot",
- "SheetParsingMode",
- "StaticRefPtr",
- "StyleAnimation",
- "StyleBasicShape",
- "StyleBasicShapeType",
- "StyleGeometryBox",
- "StyleShapeSource",
- "StyleTransition",
- "mozilla::UniquePtr",
- "mozilla::DefaultDelete",
- "mozilla::Side",
- "mozilla::binding_danger::AssertAndSuppressCleanupPolicy",
- "mozilla::ParsingMode",
- "mozilla::InheritTarget",
- ];
- let opaque_types = [
- "std::pair__PCCP",
- "std::namespace::atomic___base", "std::atomic__My_base",
- "std::atomic",
- "std::atomic___base",
- "mozilla::gfx::.*",
- "FallibleTArray",
- "mozilla::dom::Sequence",
- "mozilla::dom::Optional",
- "mozilla::dom::Nullable",
- "RefPtr_Proxy",
- "RefPtr_Proxy_member_function",
- "nsAutoPtr_Proxy",
- "nsAutoPtr_Proxy_member_function",
- "mozilla::detail::PointerType",
- "mozilla::Pair_Base",
- "mozilla::SupportsWeakPtr",
- "SupportsWeakPtr",
- "mozilla::detail::WeakReference",
- "mozilla::WeakPtr",
- "nsWritingIterator_reference", "nsReadingIterator_reference",
- "nsTObserverArray", // <- Inherits from nsAutoTObserverArray<T, 0>
- "nsTHashtable", // <- Inheriting from inner typedefs that clang
- // doesn't expose properly.
- "nsRefPtrHashtable", "nsDataHashtable", "nsClassHashtable", // <- Ditto
- "nsIDocument_SelectorCache", // <- Inherits from nsExpirationTracker<.., 4>
- "nsIPresShell_ScrollAxis", // <- For some reason the alignment of this is 4
- // for clang.
- "nsPIDOMWindow", // <- Takes the vtable from a template parameter, and we can't
- // generate it conditionally.
- "JS::Rooted",
- "mozilla::Maybe",
- "gfxSize", // <- union { struct { T width; T height; }; T components[2] };
- "gfxSize_Super", // Ditto.
- "mozilla::ErrorResult", // Causes JSWhyMagic to be included & handled incorrectly.
- "mozilla::StyleAnimationValue",
- "StyleAnimationValue", // pulls in a whole bunch of stuff we don't need in the bindings
- ];
- let blacklist = [
- ".*char_traits",
- ".*incompatible_char_type",
- ];
-
- struct MappedGenericType {
- generic: bool,
- gecko: &'static str,
- servo: &'static str,
- }
- let servo_mapped_generic_types = [
- MappedGenericType {
- generic: true,
- gecko: "mozilla::ServoUnsafeCell",
- servo: "::std::cell::UnsafeCell"
- },
- MappedGenericType {
- generic: true,
- gecko: "mozilla::ServoCell",
- servo: "::std::cell::Cell"
- },
- MappedGenericType {
- generic: false,
- gecko: "ServoNodeData",
- servo: "AtomicRefCell<ElementData>",
- }
- ];
- let mut fixups = vec![
- Fixup {
- pat: "root::nsString".into(),
- rep: "::nsstring::nsStringRepr".into()
- },
- ];
- for &var in whitelist_vars.iter() {
- builder = builder.whitelisted_var(var);
- }
- for &ty in whitelist.iter() {
- builder = builder.whitelisted_type(ty);
- }
- for &ty in opaque_types.iter() {
- builder = builder.opaque_type(ty);
- }
- for &ty in blacklist.iter() {
- builder = builder.hide_type(ty);
- }
- for ty in servo_mapped_generic_types.iter() {
- let gecko_name = ty.gecko.rsplit("::").next().unwrap();
- builder = builder.hide_type(ty.gecko)
- .raw_line(format!("pub type {0}{2} = {1}{2};", gecko_name, ty.servo,
- if ty.generic { "<T>" } else { "" }));
- fixups.push(Fixup {
- pat: format!("root::{}", ty.gecko),
- rep: format!("::gecko_bindings::structs::{}", gecko_name)
});
- }
+ let mut fixups = vec![];
+ let builder = BuilderWithConfig::new(builder, CONFIG["structs"].as_table().unwrap())
+ .handle_common(&mut fixups)
+ .handle_str_items("bitfield-enums", |b, item| b.bitfield_enum(item))
+ .handle_str_items("constified-enums", |b, item| b.constified_enum(item))
+ .handle_str_items("whitelist-vars", |b, item| b.whitelisted_var(item))
+ .handle_str_items("whitelist-types", |b, item| b.whitelisted_type(item))
+ .handle_str_items("opaque-types", |b, item| b.opaque_type(item))
+ .handle_list("constified-enum-variants", |builder, iter| {
+ let mut map = HashMap::new();
+ for item in iter {
+ let item = item.as_table().unwrap();
+ let name = item["enum"].as_str().unwrap();
+ let variants = item["variants"].as_slice().unwrap().iter()
+ .map(|item| item.as_str().unwrap());
+ map.insert(name.into(), RegexSet::new(variants).unwrap());
+ }
+ builder.parse_callbacks(Box::new(Callbacks(map)))
+ })
+ .handle_table_items("mapped-generic-types", |builder, item| {
+ let generic = item["generic"].as_bool().unwrap();
+ let gecko = item["gecko"].as_str().unwrap();
+ let servo = item["servo"].as_str().unwrap();
+ let gecko_name = gecko.rsplit("::").next().unwrap();
+ fixups.push(Fixup {
+ pat: format!("root::{}", gecko),
+ rep: format!("::gecko_bindings::structs::{}", gecko_name)
+ });
+ builder.hide_type(gecko)
+ .raw_line(format!("pub type {0}{2} = {1}{2};", gecko_name, servo,
+ if generic { "<T>" } else { "" }))
+ })
+ .get_builder();
write_binding_file(builder, structs_file(build_type), &fixups);
}
@@ -653,184 +467,62 @@ mod bindings {
}
fn generate_bindings() {
- let mut builder = Builder::get_initial_builder(BuildType::Release)
+ let builder = Builder::get_initial_builder(BuildType::Release)
.disable_name_namespacing()
.with_codegen_config(CodegenConfig {
functions: true,
..CodegenConfig::nothing()
+ });
+ let config = CONFIG["bindings"].as_table().unwrap();
+ let mut structs_types = HashSet::new();
+ let mut fixups = vec![];
+ let mut builder = BuilderWithConfig::new(builder, config)
+ .handle_common(&mut fixups)
+ .handle_str_items("whitelist-functions", |b, item| b.whitelisted_function(item))
+ .handle_str_items("structs-types", |mut builder, ty| {
+ builder = builder.hide_type(ty)
+ .raw_line(format!("use gecko_bindings::structs::{};", ty));
+ structs_types.insert(ty);
+ // TODO this is hacky, figure out a better way to do it without
+ // hardcoding everything...
+ if ty.starts_with("nsStyle") {
+ builder = builder
+ .raw_line(format!("unsafe impl Send for {} {{}}", ty))
+ .raw_line(format!("unsafe impl Sync for {} {{}}", ty));
+ }
+ builder
})
- .header(add_include("mozilla/ServoBindings.h"))
- .hide_type("nsACString_internal")
- .hide_type("nsAString_internal")
- .raw_line("pub use nsstring::{nsACString, nsAString, nsString, nsStringRepr};")
- .raw_line("use gecko_bindings::structs::nsTArray;")
- .raw_line("type nsACString_internal = nsACString;")
- .raw_line("type nsAString_internal = nsAString;")
- .whitelisted_function("Servo_.*")
- .whitelisted_function("Gecko_.*");
- let structs_types = [
- "mozilla::css::GridTemplateAreasValue",
- "mozilla::css::ImageValue",
- "mozilla::css::URLValue",
- "mozilla::Side",
- "RawGeckoAnimationPropertySegment",
- "RawGeckoComputedTiming",
- "RawGeckoDocument",
- "RawGeckoElement",
- "RawGeckoKeyframeList",
- "RawGeckoComputedKeyframeValuesList",
- "RawGeckoFontFaceRuleList",
- "RawGeckoNode",
- "RawGeckoAnimationValueList",
- "RawServoAnimationValue",
- "RawServoDeclarationBlock",
- "RawServoStyleRule",
- "RawGeckoPresContext",
- "RawGeckoPresContextOwned",
- "RawGeckoStyleAnimationList",
- "RawGeckoServoStyleRuleList",
- "RawGeckoURLExtraData",
- "RefPtr",
- "CSSPseudoClassType",
- "CSSPseudoElementType",
- "TraversalRestyleBehavior",
- "TraversalRootBehavior",
- "ComputedTimingFunction_BeforeFlag",
- "FontFamilyList",
- "FontFamilyType",
- "FontSizePrefs",
- "GeckoFontMetrics",
- "Keyframe",
- "ServoBundledURI",
- "ServoElementSnapshot",
- "ServoElementSnapshotTable",
- "SheetParsingMode",
- "StyleBasicShape",
- "StyleBasicShapeType",
- "StyleShapeSource",
- "StyleTransition",
- "nsCSSCounterStyleRule",
- "nsCSSFontFaceRule",
- "nsCSSKeyword",
- "nsCSSPropertyID",
- "nsCSSShadowArray",
- "nsCSSUnit",
- "nsCSSValue",
- "nsCSSValueSharedList",
- "nsChangeHint",
- "nsCursorImage",
- "nsFont",
- "nsIAtom",
- "nsCompatibility",
- "nsMediaFeature",
- "nsRestyleHint",
- "nsStyleBackground",
- "nsStyleBorder",
- "nsStyleColor",
- "nsStyleColumn",
- "nsStyleContent",
- "nsStyleContentData",
- "nsStyleContentType",
- "nsStyleContext",
- "nsStyleCoord",
- "nsStyleCoord_Calc",
- "nsStyleCoord_CalcValue",
- "nsStyleDisplay",
- "nsStyleEffects",
- "nsStyleFilter",
- "nsStyleFont",
- "nsStyleGradient",
- "nsStyleGradientStop",
- "nsStyleGridTemplate",
- "nsStyleImage",
- "nsStyleImageLayers",
- "nsStyleImageLayers_Layer",
- "nsStyleImageLayers_LayerType",
- "nsStyleImageRequest",
- "nsStyleList",
- "nsStyleMargin",
- "nsStyleOutline",
- "nsStylePadding",
- "nsStylePosition",
- "nsStyleQuoteValues",
- "nsStyleSVG",
- "nsStyleSVGPaint",
- "nsStyleSVGReset",
- "nsStyleTable",
- "nsStyleTableBorder",
- "nsStyleText",
- "nsStyleTextReset",
- "nsStyleUIReset",
- "nsStyleUnion",
- "nsStyleUnit",
- "nsStyleUserInterface",
- "nsStyleVariables",
- "nsStyleVisibility",
- "nsStyleXUL",
- "nsTimingFunction",
- "nscolor",
- "nscoord",
- "nsresult",
- "Loader",
- "ServoStyleSheet",
- "EffectCompositor_CascadeLevel",
- "UpdateAnimationsTasks",
- "ParsingMode",
- "InheritTarget",
- "URLMatchingFunction",
- ];
- struct ArrayType {
- cpp_type: &'static str,
- rust_type: &'static str
- }
- let array_types = [
- ArrayType { cpp_type: "uintptr_t", rust_type: "usize" },
- ];
- struct ServoOwnedType {
- name: &'static str,
- opaque: bool,
- }
- let servo_owned_types = [
- ServoOwnedType { name: "RawServoStyleSet", opaque: true },
- ServoOwnedType { name: "StyleChildrenIterator", opaque: true },
- ServoOwnedType { name: "ServoElementSnapshot", opaque: false },
- ServoOwnedType { name: "RawServoAnimationValueMap", opaque: true },
- ];
- let servo_immutable_borrow_types = [
- "RawGeckoNode",
- "RawGeckoElement",
- "RawGeckoDocument",
- "RawServoDeclarationBlockStrong",
- "RawGeckoPresContext",
- "RawGeckoStyleAnimationList",
- ];
- let servo_borrow_types = [
- "nsCSSValue",
- "nsTimingFunction",
- "RawGeckoAnimationPropertySegment",
- "RawGeckoAnimationValueList",
- "RawGeckoComputedTiming",
- "RawGeckoKeyframeList",
- "RawGeckoComputedKeyframeValuesList",
- "RawGeckoFontFaceRuleList",
- "RawGeckoServoStyleRuleList",
- ];
- for &ty in structs_types.iter() {
- builder = builder.hide_type(ty)
- .raw_line(format!("use gecko_bindings::structs::{};", ty));
- // TODO this is hacky, figure out a better way to do it without
- // hardcoding everything...
- if ty.starts_with("nsStyle") {
- builder = builder
- .raw_line(format!("unsafe impl Send for {} {{}}", ty))
- .raw_line(format!("unsafe impl Sync for {} {{}}", ty));
- }
- }
- for &ArrayType { cpp_type, rust_type } in array_types.iter() {
- builder = builder.hide_type(format!("nsTArrayBorrowed_{}", cpp_type))
- .raw_line(format!("pub type nsTArrayBorrowed_{}<'a> = &'a mut ::gecko_bindings::structs::nsTArray<{}>;",
- cpp_type, rust_type))
- }
+ // TODO This was added due to servo/rust-bindgen#75, but
+ // that has been fixed in clang 4.0+. When we switch people
+ // to libclang 4.0, we can remove this.
+ .handle_table_items("array-types", |builder, item| {
+ let cpp_type = item["cpp-type"].as_str().unwrap();
+ let rust_type = item["rust-type"].as_str().unwrap();
+ builder.hide_type(format!("nsTArrayBorrowed_{}", cpp_type))
+ .raw_line(format!(concat!("pub type nsTArrayBorrowed_{}<'a> = ",
+ "&'a mut ::gecko_bindings::structs::nsTArray<{}>;"),
+ cpp_type, rust_type))
+ })
+ .handle_table_items("servo-owned-types", |mut builder, item| {
+ let name = item["name"].as_str().unwrap();
+ builder = builder.hide_type(format!("{}Owned", name))
+ .raw_line(format!("pub type {0}Owned = ::gecko_bindings::sugar::ownership::Owned<{0}>;", name))
+ .hide_type(format!("{}OwnedOrNull", name))
+ .raw_line(format!(concat!("pub type {0}OwnedOrNull = ",
+ "::gecko_bindings::sugar::ownership::OwnedOrNull<{0}>;"), name))
+ .mutable_borrowed_type(name);
+ if item["opaque"].as_bool().unwrap() {
+ builder = builder.zero_size_type(name, &structs_types);
+ }
+ builder
+ })
+ .handle_str_items("servo-immutable-borrow-types", |b, ty| b.borrowed_type(ty))
+ // Right now the only immutable borrow types are ones which we import
+ // from the |structs| module. As such, we don't need to create an opaque
+ // type with zero_size_type. If we ever introduce immutable borrow types
+ // which _do_ need to be opaque, we'll need a separate mode.
+ .handle_str_items("servo-borrow-types", |b, ty| b.mutable_borrowed_type(ty))
+ .get_builder();
for ty in get_arc_types().iter() {
builder = builder
.hide_type(format!("{}Strong", ty))
@@ -838,34 +530,6 @@ mod bindings {
.borrowed_type(ty)
.zero_size_type(ty, &structs_types);
}
- for &ServoOwnedType { name, opaque } in servo_owned_types.iter() {
- builder = builder
- .hide_type(format!("{}Owned", name))
- .raw_line(format!("pub type {0}Owned = ::gecko_bindings::sugar::ownership::Owned<{0}>;", name))
- .hide_type(format!("{}OwnedOrNull", name))
- .raw_line(format!("pub type {0}OwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull<{0}>;",
- name))
- .mutable_borrowed_type(name);
- if opaque {
- builder = builder.zero_size_type(name, &structs_types);
- }
- }
- for &ty in servo_immutable_borrow_types.iter() {
- builder = builder.borrowed_type(ty);
- }
- for &ty in servo_borrow_types.iter() {
- builder = builder.mutable_borrowed_type(ty);
- // Right now the only immutable borrow types are ones which we import
- // from the |structs| module. As such, we don't need to create an opaque
- // type with zero_size_type. If we ever introduce immutable borrow types
- // which _do_ need to be opaque, we'll need a separate mode.
- }
- let fixups = vec![
- Fixup { // hack for gecko-owned string
- pat: "<nsString".into(),
- rep: "<nsStringRepr".into()
- },
- ];
write_binding_file(builder, BINDINGS_FILE, &fixups);
}