aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXidorn Quan <me@upsuper.org>2016-12-09 13:55:49 -1000
committerXidorn Quan <me@upsuper.org>2016-12-10 00:33:41 -1000
commit1cefd1bef037c361a785345e619508312883389e (patch)
treeadf34e40e9c45c54f9eddcb79506f8869e80aff5
parent6dd4b4822fa788694153ee61a04dd9a5dfb748ec (diff)
downloadservo-1cefd1bef037c361a785345e619508312883389e.tar.gz
servo-1cefd1bef037c361a785345e619508312883389e.zip
Do build-time bindgen
Majority of build_gecko.rs is just the straightforward conversion from regen.py. There are two differences that: 1. Side in whitelist is changed to mozilla::Side 2. std::atomic__My_base is added to opaque types for Windows
-rw-r--r--Cargo.lock74
-rw-r--r--components/style/Cargo.toml4
-rwxr-xr-xcomponents/style/binding_tools/regen.py820
-rw-r--r--components/style/build.rs23
-rw-r--r--components/style/build_gecko.rs617
-rw-r--r--components/style/gecko_bindings/mod.rs19
-rw-r--r--ports/geckolib/Cargo.toml3
-rw-r--r--python/servo/build_commands.py14
8 files changed, 739 insertions, 835 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8a79b8eda44..0f5db66439d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -69,6 +69,14 @@ dependencies = [
]
[[package]]
+name = "aster"
+version = "0.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "audio-video-metadata"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -282,6 +290,14 @@ dependencies = [
]
[[package]]
+name = "cexpr"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "cfg-if"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -296,6 +312,16 @@ dependencies = [
]
[[package]]
+name = "clang-sys"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "clippy_lints"
version = "0.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1380,6 +1406,26 @@ dependencies = [
]
[[package]]
+name = "libbindgen"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aster 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clang-sys 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quasi 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quasi_codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.1.76 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "libc"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2068,6 +2114,26 @@ dependencies = [
]
[[package]]
+name = "quasi"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quasi_codegen"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aster 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "quickersort"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2601,6 +2667,7 @@ dependencies = [
"html5ever-atoms 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libbindgen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"nsstring_vendor 0.1.0",
@@ -2616,6 +2683,7 @@ dependencies = [
"quickersort 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.1.76 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.18 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3212,6 +3280,7 @@ dependencies = [
"checksum angle 0.1.2 (git+https://github.com/servo/angle?branch=servo)" = "<none>"
"checksum app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "636ee56f12e31dbc11dc0a1ac6004f08b04e6e6595963716fc8130e90d4e04cf"
"checksum arrayvec 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "80a137392e2e92ce7387c063d98a11f0d47115426c5f8759657af3c7b385c860"
+"checksum aster 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88bb8ecdf6a7eaddb7bfd872ebf5e085d343ca42ce98c582dba8046e3450b524"
"checksum audio-video-metadata 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "03da2550cb89fe3faf218c179261c26cf7891c4234707c15f5d09ebb32ae2400"
"checksum azure 0.9.1 (git+https://github.com/servo/rust-azure)" = "<none>"
"checksum backtrace 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "346d7644f0b5f9bc73082d3b2236b69a05fd35cce0cfa3724e184e6a5c9e2a2f"
@@ -3230,8 +3299,10 @@ dependencies = [
"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
"checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27"
"checksum caseless 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6893f86ac0c9275b5cbba9212ccd71020b447d4c3e2eebad70e1bc47fdd6dfb"
+"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
"checksum cgl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8bdd78cca65a739cb5475dbf6b6bbb49373e327f4a6f2b499c0f98632df38c10"
+"checksum clang-sys 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19911f7964ce61a02d382adee8400f919d0fedd53c5441e3d6a9858ba73e249e"
"checksum clippy_lints 0.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "4329699b62341fd3ce3ebe13ade6c87d35b8778091e0c2f6da51399e081b9671"
"checksum cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dfcf5bcece56ef953b8ea042509e9dcbdfe97820b7e20d86beb53df30ed94978"
"checksum cocoa 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d24ed9a15e9c0892cdb20c7acc3e50441501b990ee6dc318c176981829a7941"
@@ -3313,6 +3384,7 @@ dependencies = [
"checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f"
"checksum leak 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd100e01f1154f2908dfa7d02219aeab25d0b9c7fa955164192e3245255a0c73"
"checksum leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40a8225d44241fd324a8af2806ba635fc7c8a7e9a7de4d5cf3ef54e71f5926fc"
+"checksum libbindgen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6a46e95efa501b2940e9c81dbb727e557b39b41f77f1170aba6eed5a546e9964"
"checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8"
"checksum libloading 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "eceb2637ee9a27c7f19764048a9f377e40e3a70a322722f348e6bc7704d565f2"
"checksum libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "cbc058951ab6a3ef35ca16462d7642c4867e6403520811f28537a4e2f2db3e71"
@@ -3367,6 +3439,8 @@ dependencies = [
"checksum pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8cee804ecc7eaf201a4a207241472cc870e825206f6c031e3ee2a72fa425f2fa"
"checksum pnacl-build-helper 1.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "61c9231d31aea845007443d62fcbb58bb6949ab9c18081ee1e09920e0cf1118b"
"checksum png 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "06208e2ee243e3118a55dda9318f821f206d8563fb8d4df258767f8e62bb0997"
+"checksum quasi 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ab7992920bf5bc5f1ed6fdc49090bf665cd00b3aa4b78c16ac3465286257db1"
+"checksum quasi_codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d52e5e2c92ffdad67a9b86ad27ad999bf1a652723f1d4cc93b7cf6c272b5f8e0"
"checksum quickersort 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e952ea7699262481636004bc4ab8afaccf2bc13f91b79d1aee6617bd8fc39651"
"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
"checksum quote 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1e0c9bc6bfb0a60d539aab6e338207c1a5456e62f5bd5375132cee119aa4b3"
diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml
index 95778b61c88..cb386d1ac7e 100644
--- a/components/style/Cargo.toml
+++ b/components/style/Cargo.toml
@@ -14,6 +14,7 @@ doctest = false
[features]
gecko = ["nsstring_vendor", "num_cpus", "rayon/unstable"]
+bindgen = ["libbindgen", "regex"]
servo = ["serde/unstable", "serde", "serde_derive", "heapsize_derive",
"style_traits/servo", "app_units/plugins", "servo_atoms", "html5ever-atoms",
"cssparser/heap_size", "cssparser/serde-serialization",
@@ -65,5 +66,8 @@ version = "1.0"
kernel32-sys = "0.2"
[build-dependencies]
+lazy_static = "0.2"
+libbindgen = {version = "0.1.1", optional = true}
phf_codegen = "0.7.20"
+regex = {version = "0.1", optional = true}
walkdir = "0.1"
diff --git a/components/style/binding_tools/regen.py b/components/style/binding_tools/regen.py
deleted file mode 100755
index 248d50ea9ea..00000000000
--- a/components/style/binding_tools/regen.py
+++ /dev/null
@@ -1,820 +0,0 @@
-#!/usr/bin/env python
-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-from __future__ import print_function
-
-import re
-import os
-import sys
-import argparse
-import platform
-import copy
-import subprocess
-import fileinput
-
-import regen_atoms
-
-DESCRIPTION = 'Regenerate the rust version of the structs or the bindings file.'
-TOOLS_DIR = os.path.dirname(os.path.abspath(__file__))
-COMMON_BUILD_KEY = "__common__"
-
-COMPILATION_TARGETS = {
- # Flags common for all the targets.
- COMMON_BUILD_KEY: {
- "flags": [
- "--no-unstable-rust",
- ],
- "clang_flags": [
- "-x", "c++", "-std=c++14",
- "-DTRACING=1", "-DIMPL_LIBXUL", "-DMOZ_STYLO_BINDINGS=1",
- "-DMOZILLA_INTERNAL_API", "-DRUST_BINDGEN", "-DMOZ_STYLO"
- ],
- "search_dirs": [
- "{}/dist/include",
- "{}/dist/include/nspr",
- "{}/../nsprpub/pr/include"
- ],
- "includes": [
- "{}/mozilla-config.h",
- ],
- },
- # Generation of style structs.
- "structs": {
- "target_dir": "../gecko_bindings",
- "flags": [
- "--enable-cxx-namespaces",
- # FIXME(emilio): Incrementally remove these. 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::*;",
- "--generate", "types,vars",
- ],
- "includes": [
- "{}/dist/include/gfxFontConstants.h",
- "{}/dist/include/nsThemeConstants.h",
- "{}/dist/include/mozilla/dom/AnimationEffectReadOnlyBinding.h",
- "{}/dist/include/mozilla/ServoElementSnapshot.h",
- "{}/dist/include/mozilla/dom/Element.h",
- "{}/dist/include/mozilla/ServoBindings.h",
- ],
- "files": [
- "{}/dist/include/nsStyleStruct.h",
- ],
- "build_kinds": {
- "debug": {
- "clang_flags": [
- "-DDEBUG=1",
- "-DJS_DEBUG=1",
- ]
- },
- "release": {
- }
- },
- "raw_lines": [
- "use atomic_refcell::AtomicRefCell;",
- "use data::ElementData;",
- ],
- "blacklist_types": [
- "nsString",
- ],
- "whitelist_vars": [
- "NS_THEME_.*",
- "NODE_.*",
- "NS_FONT_.*",
- "NS_STYLE_.*",
- "NS_CORNER_.*",
- "NS_RADIUS_.*",
- "BORDER_COLOR_.*",
- "BORDER_STYLE_.*"
- ],
- "whitelist": [
- "RawGecko.*",
- "mozilla::ServoElementSnapshot.*",
- "mozilla::ConsumeStyleBehavior",
- "mozilla::LazyComputeBehavior",
- "mozilla::css::SheetParsingMode",
- "mozilla::SkipRootBehavior",
- "mozilla::DisplayItemClip", # Needed because bindgen generates
- # specialization tests for this even
- # though it shouldn't.
- ".*ThreadSafe.*Holder",
- "AnonymousContent",
- "AudioContext",
- "CapturingContentInfo",
- "ConsumeStyleBehavior",
- "DefaultDelete",
- "DOMIntersectionObserverEntry",
- "Element",
- "FontFamilyList",
- "FontFamilyListRefCnt",
- "FontFamilyName",
- "FontFamilyType",
- "FragmentOrURL",
- "FrameRequestCallback",
- "gfxAlternateValue",
- "gfxFontFeature",
- "gfxFontVariation",
- "GridNamedArea",
- "Image",
- "ImageURL",
- "LazyComputeBehavior",
- "nsAttrName",
- "nsAttrValue",
- "nsBorderColors",
- "nscolor",
- "nsChangeHint",
- "nsCSSKeyword",
- "nsCSSPropertyID",
- "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",
- "nsRect",
- "nsRestyleHint",
- "nsresult",
- "nsSize",
- "nsStyleBackground",
- "nsStyleBorder",
- "nsStyleColor",
- "nsStyleColumn",
- "nsStyleContent",
- "nsStyleContentData",
- "nsStyleContext",
- "nsStyleCoord",
- "nsStyleCounterData",
- "nsStyleDisplay",
- "nsStyleEffects",
- "nsStyleFilter",
- "nsStyleFont",
- "nsStyleGradient",
- "nsStyleGradientStop",
- "nsStyleImage",
- "nsStyleImageLayers",
- "nsStyleList",
- "nsStyleMargin",
- "nsStyleOutline",
- "nsStylePadding",
- "nsStylePosition",
- "nsStyleSVG",
- "nsStyleSVGReset",
- "nsStyleTable",
- "nsStyleTableBorder",
- "nsStyleText",
- "nsStyleTextReset",
- "nsStyleUIReset",
- "nsStyleUnion",
- "nsStyleUnit",
- "nsStyleUserInterface",
- "nsStyleVariables",
- "nsStyleVisibility",
- "nsStyleXUL",
- "nsTArray",
- "nsTArrayHeader",
- "pair",
- "Position",
- "Runnable",
- "ServoAttrSnapshot",
- "ServoElementSnapshot",
- "SheetParsingMode",
- "Side",
- "StaticRefPtr",
- "StyleAnimation",
- "StyleBasicShape",
- "StyleBasicShapeType",
- "StyleClipPath",
- "StyleClipPathGeometryBox",
- "StyleTransition",
- "mozilla::UniquePtr",
- "mozilla::DefaultDelete",
- ],
- "bitfield_enum_types": ["nsChangeHint", "nsRestyleHint"],
- "opaque_types": [
- "atomic___base",
- "nsAString_internal_char_traits",
- "nsAString_internal_incompatible_char_type",
- "nsACString_internal_char_traits",
- "nsACString_internal_incompatible_char_type",
- "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.
- ],
- "manual_fixups": [
- ["root::nsString", "::nsstring::nsStringRepr"]
- ],
- "servo_mapped_generic_types": [
- {
- "generic": True,
- "gecko": "mozilla::ServoUnsafeCell",
- "servo": "::std::cell::UnsafeCell"
- }, {
- "generic": True,
- "gecko": "mozilla::ServoCell",
- "servo": "::std::cell::Cell"
- }, {
- "generic": False,
- "gecko": "ServoNodeData",
- "servo": "AtomicRefCell<ElementData>",
- }
- ],
- },
- # Generation of the ffi bindings.
- "bindings": {
- "target_dir": "../gecko_bindings",
- "raw_lines": [
- "pub use nsstring::{nsACString, nsAString};",
- "type nsACString_internal = nsACString;",
- "type nsAString_internal = nsAString;"
- ],
- "flags": [
- "--generate", "functions",
- "--disable-name-namespacing",
- ],
- "match_headers": [
- "ServoBindingList.h",
- "ServoBindings.h",
- "ServoTypes.h",
- "nsStyleStructList.h",
- ],
- "files": [
- "{}/dist/include/mozilla/ServoBindings.h",
- ],
- # Types to just use from the `structs` target.
- "structs_types": [
- "RawGeckoDocument",
- "RawGeckoElement",
- "RawGeckoNode",
- "ThreadSafeURIHolder",
- "ThreadSafePrincipalHolder",
- "ConsumeStyleBehavior",
- "LazyComputeBehavior",
- "SkipRootBehavior",
- "FontFamilyList",
- "FontFamilyType",
- "ServoElementSnapshot",
- "SheetParsingMode",
- "StyleBasicShape",
- "StyleBasicShapeType",
- "StyleClipPath",
- "nsCSSKeyword",
- "nsCSSShadowArray",
- "nsCSSValue",
- "nsCSSValueSharedList",
- "nsChangeHint",
- "nsCursorImage",
- "nsFont",
- "nsIAtom",
- "nsRestyleHint",
- "nsStyleBackground",
- "nsStyleBorder",
- "nsStyleColor",
- "nsStyleColumn",
- "nsStyleContent",
- "nsStyleContext",
- "nsStyleCoord",
- "nsStyleCoord_Calc",
- "nsStyleCoord_CalcValue",
- "nsStyleDisplay",
- "nsStyleEffects",
- "nsStyleFont",
- "nsStyleGradient",
- "nsStyleGradientStop",
- "nsStyleImage",
- "nsStyleImageLayers",
- "nsStyleImageLayers_Layer",
- "nsStyleImageLayers_LayerType",
- "nsStyleImageRequest",
- "nsStyleList",
- "nsStyleMargin",
- "nsStyleOutline",
- "nsStylePadding",
- "nsStylePosition",
- "nsStyleQuoteValues",
- "nsStyleSVG",
- "nsStyleSVGReset",
- "nsStyleTable",
- "nsStyleTableBorder",
- "nsStyleText",
- "nsStyleTextReset",
- "nsStyleUIReset",
- "nsStyleUnion",
- "nsStyleUnit",
- "nsStyleUserInterface",
- "nsStyleVariables",
- "nsStyleVisibility",
- "nsStyleXUL",
- "nscoord",
- "nsresult",
- ],
- "array_types": {
- "uintptr_t": "usize",
- },
- "servo_nullable_arc_types": [
- "ServoComputedValues",
- "ServoCssRules",
- "RawServoStyleSheet",
- "RawServoDeclarationBlock",
- "RawServoStyleRule",
- ],
- "servo_owned_types": [
- {
- "name": "RawServoStyleSet",
- "opaque": True,
- }, {
- "name": "StyleChildrenIterator",
- "opaque": True,
- }, {
- "name": "ServoElementSnapshot",
- "opaque": False,
- },
- ],
- "servo_immutable_borrow_types": [
- "RawGeckoNode",
- "RawGeckoElement",
- "RawGeckoDocument",
- "RawServoDeclarationBlockStrong",
- ],
- "servo_borrow_types": [
- "nsCSSValue",
- ],
- "whitelist_functions": [
- "Servo_.*",
- "Gecko_.*"
- ]
- },
-
- "atoms": {
- "custom_build": regen_atoms.build,
- }
-}
-
-
-def platform_dependent_defines():
- ret = []
-
- if os.name == "posix":
- ret.append("-DOS_POSIX=1")
-
- system = platform.system()
- if system == "Linux":
- ret.append("-DOS_LINUX=1")
- elif system == "Darwin":
- ret.append("-DOS_MACOSX=1")
- elif system == "Windows":
- ret.append("-DOS_WIN=1")
- ret.append("-DWIN32=1")
- msvc_platform = os.environ["PLATFORM"]
- if msvc_platform == "X86":
- ret.append("--target=i686-pc-win32")
- elif msvc_platform == "X64":
- ret.append("--target=x86_64-pc-win32")
- else:
- raise Exception("Only MSVC builds are supported on Windows")
- # For compatibility with MSVC 2015
- ret.append("-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().
- ret.append("-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.
- ret.append("-DHAVE_VISIBILITY_HIDDEN_ATTRIBUTE=1")
- else:
- raise Exception("Unknown platform")
-
- return ret
-
-
-def extend_object(obj, other):
- if not obj or not other:
- return obj
-
- if isinstance(obj, list) and isinstance(other, list):
- obj.extend(other)
- return
-
- assert isinstance(obj, dict) and isinstance(other, dict)
-
- for key in other.keys():
- if key in obj:
- extend_object(obj[key], other[key])
- else:
- obj[key] = copy.deepcopy(other[key])
-
-
-def build(objdir, target_name, debug, debugger, kind_name=None,
- output_filename=None, bindgen=None, skip_test=False,
- verbose=False):
- assert target_name in COMPILATION_TARGETS
-
- current_target = COMPILATION_TARGETS[target_name]
- if COMMON_BUILD_KEY in COMPILATION_TARGETS:
- current_target = copy.deepcopy(COMPILATION_TARGETS[COMMON_BUILD_KEY])
- extend_object(current_target, COMPILATION_TARGETS[target_name])
-
- assert ((kind_name is None and "build_kinds" not in current_target) or
- (kind_name in current_target["build_kinds"]))
-
- if "custom_build" in current_target:
- print("[CUSTOM] {}::{} in \"{}\"... ".format(target_name, kind_name, objdir), end='')
- sys.stdout.flush()
- ret = current_target["custom_build"](objdir, verbose=True)
- if ret != 0:
- print("FAIL")
- else:
- print("OK")
-
- return ret
-
- if bindgen is None:
- bindgen = os.path.join(TOOLS_DIR, "rust-bindgen")
-
- if os.path.isdir(bindgen):
- bindgen = ["cargo", "run", "--manifest-path",
- os.path.join(bindgen, "Cargo.toml"), "--features", "llvm_stable", "--release", "--"]
- else:
- bindgen = [bindgen]
-
- if kind_name is not None:
- current_target = copy.deepcopy(current_target)
- extend_object(current_target, current_target["build_kinds"][kind_name])
-
- target_dir = None
- if output_filename is None and "target_dir" in current_target:
- target_dir = current_target["target_dir"]
-
- if output_filename is None:
- output_filename = "{}.rs".format(target_name)
-
- if kind_name is not None:
- output_filename = "{}_{}.rs".format(target_name, kind_name)
-
- if target_dir:
- output_filename = "{}/{}".format(target_dir, output_filename)
-
- print("[BINDGEN] {}::{} in \"{}\"... ".format(target_name, kind_name, objdir), end='')
- sys.stdout.flush()
-
- flags = []
-
- # Types we have to fixup since we insert them manually.
- #
- # Bindgen only allows us to add stuff outside of the root module. This
- # wasn't intended to add new types, but we do so, so we postprocess the
- # bindgen output to fixup the path to these types.
- fixups = []
-
- if "manual_fixups" in current_target:
- fixups = current_target["manual_fixups"]
-
- # This makes an FFI-safe void type that can't be matched on
- # &VoidType is UB to have, because you can match on it
- # to produce a reachable unreachable. If it's wrapped in
- # a struct as a private field it becomes okay again
- #
- # 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
- def zero_size_type(ty, flags):
- flags.append("--blacklist-type")
- flags.append(ty)
- flags.append("--raw-line")
- flags.append("enum {0}Void{{ }}".format(ty))
- flags.append("--raw-line")
- flags.append("pub struct {0}({0}Void);".format(ty))
-
- if "flags" in current_target:
- flags.extend(current_target["flags"])
-
- clang_flags = []
-
- if "clang_flags" in current_target:
- clang_flags.extend(current_target["clang_flags"])
-
- clang_flags.extend(platform_dependent_defines())
-
- if platform.system() == "Windows":
- flags.append("--use-msvc-mangling")
-
- if "raw_lines" in current_target:
- for raw_line in current_target["raw_lines"]:
- flags.append("--raw-line")
- flags.append(raw_line)
-
- if "search_dirs" in current_target:
- for dir_name in current_target["search_dirs"]:
- clang_flags.append("-I")
- clang_flags.append(dir_name.format(objdir))
-
- if "includes" in current_target:
- for file_name in current_target["includes"]:
- clang_flags.append("-include")
- clang_flags.append(file_name.format(objdir))
-
- if "whitelist" in current_target:
- for header in current_target["whitelist"]:
- flags.append("--whitelist-type")
- flags.append(header)
-
- if "whitelist_functions" in current_target:
- for header in current_target["whitelist_functions"]:
- flags.append("--whitelist-function")
- flags.append(header)
-
- if "whitelist_vars" in current_target:
- for header in current_target["whitelist_vars"]:
- flags.append("--whitelist-var")
- flags.append(header)
-
- if "bitfield_enum_types" in current_target:
- for ty in current_target["bitfield_enum_types"]:
- flags.append("--bitfield-enum")
- flags.append(ty)
-
- if "opaque_types" in current_target:
- for ty in current_target["opaque_types"]:
- flags.append("--opaque-type")
- flags.append(ty)
-
- if "array_types" in current_target:
- for cpp_type, rust_type in current_target["array_types"].items():
- flags.append("--blacklist-type")
- flags.append("nsTArrayBorrowed_{}".format(cpp_type))
- flags.append("--raw-line")
- flags.append("pub type nsTArrayBorrowed_{0}<'a> = &'a mut ::gecko_bindings::structs::nsTArray<{1}>;"
- .format(cpp_type, rust_type))
-
- if "blacklist_types" in current_target:
- for ty in current_target["blacklist_types"]:
- flags.append("--blacklist-type")
- flags.append(ty)
-
- if "servo_nullable_arc_types" in current_target:
- for ty in current_target["servo_nullable_arc_types"]:
- flags.append("--blacklist-type")
- flags.append("{}Strong".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}Strong = ::gecko_bindings::sugar::ownership::Strong<{0}>;"
- .format(ty))
- flags.append("--blacklist-type")
- flags.append("{}BorrowedOrNull".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}BorrowedOrNull<'a> = \
-Option<&'a {0}>;".format(ty))
- flags.append("--blacklist-type")
- flags.append("{}Borrowed".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}Borrowed<'a> = &'a {0};".format(ty))
- zero_size_type(ty, flags)
-
- if "servo_immutable_borrow_types" in current_target:
- for ty in current_target.get("servo_immutable_borrow_types", []) + current_target.get("servo_borrow_types", []):
- flags.append("--blacklist-type")
- flags.append("{}Borrowed".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}Borrowed<'a> = &'a {0};".format(ty))
- flags.append("--blacklist-type")
- flags.append("{}BorrowedOrNull".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}BorrowedOrNull<'a> = Option<&'a {0}>;".format(ty))
- if "servo_borrow_types" in current_target:
- for ty in current_target["servo_borrow_types"]:
- flags.append("--blacklist-type")
- flags.append("{}BorrowedMut".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}BorrowedMut<'a> = &'a mut {0};".format(ty))
- flags.append("--blacklist-type")
- flags.append("{}BorrowedMutOrNull".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}BorrowedMutOrNull<'a> = \
-Option<&'a mut {0}>;".format(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.
-
- if "servo_mapped_generic_types" in current_target:
- for ty in current_target["servo_mapped_generic_types"]:
- flags.append("--blacklist-type")
- flags.append(ty["gecko"])
-
- gecko_name = ty["gecko"].split("::")[-1]
- flags.append("--raw-line")
- flags.append("pub type {0}{2} = {1}{2};".format(gecko_name, ty["servo"], "<T>" if ty["generic"] else ""))
- fixups.append(["root::{}".format(ty["gecko"]), "::gecko_bindings::structs::{}".format(gecko_name)])
-
- if "servo_owned_types" in current_target:
- for entry in current_target["servo_owned_types"]:
- ty = entry["name"]
- flags.append("--blacklist-type")
- flags.append("{}Borrowed".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}Borrowed<'a> = &'a {0};".format(ty))
- flags.append("--blacklist-type")
- flags.append("{}BorrowedMut".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}BorrowedMut<'a> = &'a mut {0};".format(ty))
- flags.append("--blacklist-type")
- flags.append("{}Owned".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}Owned = ::gecko_bindings::sugar::ownership::Owned<{0}>;".format(ty))
- flags.append("--blacklist-type")
- flags.append("{}BorrowedOrNull".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}BorrowedOrNull<'a> = Option<&'a {0}>;"
- .format(ty))
- flags.append("--blacklist-type")
- flags.append("{}BorrowedMutOrNull".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}BorrowedMutOrNull<'a> = Option<&'a mut {0}>;"
- .format(ty))
- flags.append("--blacklist-type")
- flags.append("{}OwnedOrNull".format(ty))
- flags.append("--raw-line")
- flags.append("pub type {0}OwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull<{0}>;".format(ty))
- if entry["opaque"]:
- zero_size_type(ty, flags)
-
- if "structs_types" in current_target:
- for ty in current_target["structs_types"]:
- flags.append("--blacklist-type")
- flags.append(ty)
- flags.append("--raw-line")
- flags.append("use gecko_bindings::structs::{};".format(ty))
-
- # TODO: this is hacky, figure out a better way to do it without
- # hardcoding everything...
- if ty.startswith("nsStyle"):
- flags.extend([
- "--raw-line",
- "unsafe impl Send for {} {{}}".format(ty),
- "--raw-line",
- "unsafe impl Sync for {} {{}}".format(ty),
- ])
-
- flags.append("-o")
- flags.append(output_filename)
-
- assert len(current_target["files"]) == 1
- flags.append(current_target["files"][0].format(objdir))
-
- flags = bindgen + flags + ["--"] + clang_flags
-
- if verbose:
- print(flags)
-
- output = ""
- try:
- if debug:
- flags = [debugger, "--args"] + flags
- subprocess.check_call(flags)
- else:
- output = subprocess.check_output(flags, stderr=subprocess.STDOUT,
- universal_newlines=True)
- except subprocess.CalledProcessError as e:
- print("FAIL\n", e.output)
- return 1
-
- generated = fileinput.input(output_filename, inplace=True)
- for line in generated:
- for fixup in fixups:
- line = re.sub("\\b{}\\b".format(fixup[0]), fixup[1], line)
- print(line, end='')
- generated.close()
-
- print("OK")
- print("(please test with ./mach test-stylo)")
-
- if verbose:
- print(output)
-
- return 0
-
-
-def builds_for(target_name, kind):
- if target_name == "all":
- for target in COMPILATION_TARGETS.keys():
- if target == COMMON_BUILD_KEY:
- continue
-
- if "build_kinds" in COMPILATION_TARGETS[target]:
- for kind in COMPILATION_TARGETS[target]["build_kinds"].keys():
- yield (target, kind)
- else:
- yield (target, None)
- return
-
- target = COMPILATION_TARGETS[target_name]
- if "build_kinds" in target:
- if kind is None:
- for kind in target["build_kinds"].keys():
- yield(target_name, kind)
- else:
- yield (target_name, kind)
- return
-
- yield (target_name, None)
-
-
-def main():
- parser = argparse.ArgumentParser(description=DESCRIPTION)
- parser.add_argument('--target', default='all',
- help='The target to build, either "structs" or "bindings"')
- parser.add_argument('--kind',
- help='Kind of build')
- parser.add_argument('--bindgen',
- help='Override bindgen binary')
- parser.add_argument('--output', '-o',
- help='Output of the script')
- parser.add_argument('--skip-test',
- action='store_true',
- help='Skip automatic tests, useful for debugging')
- parser.add_argument('--verbose', '-v',
- action='store_true',
- help='Be... verbose')
- parser.add_argument('--debug',
- action='store_true',
- help='Try to use a debugger to debug bindgen commands (default: gdb)')
- parser.add_argument('--debugger', default='gdb',
- help='Debugger to use. Only used if --debug is passed.')
- parser.add_argument('objdir')
-
- args = parser.parse_args()
-
- if not os.path.isdir(args.objdir):
- print("\"{}\" doesn't seem to be a directory".format(args.objdir))
- return 1
-
- if (args.target != "all" and args.target not in COMPILATION_TARGETS) or args.target == COMMON_BUILD_KEY:
- print("{} is not a valid compilation target.".format(args.target))
- print("Valid compilation targets are:")
- for target in COMPILATION_TARGETS.keys():
- if target != COMMON_BUILD_KEY:
- print("\t * {}".format(target))
- return 1
-
- current_target = COMPILATION_TARGETS.get(args.target, {})
- if args.kind and "build_kinds" in current_target and args.kind not in current_target["build_kinds"]:
- print("{} is not a valid build kind.".format(args.kind))
- print("Valid build kinds are:")
- for kind in current_target["build_kinds"].keys():
- print("\t * {}".format(kind))
- return 1
-
- for target, kind in builds_for(args.target, args.kind):
- ret = build(args.objdir, target, kind_name=kind,
- debug=args.debug, debugger=args.debugger,
- bindgen=args.bindgen, skip_test=args.skip_test,
- output_filename=args.output,
- verbose=args.verbose)
- if ret != 0:
- print("{}::{} failed".format(target, kind))
- return ret
-
- return 0
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/components/style/build.rs b/components/style/build.rs
index 8d68fe45ce6..fb8d4a5e5f9 100644
--- a/components/style/build.rs
+++ b/components/style/build.rs
@@ -2,6 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#[macro_use]
+extern crate lazy_static;
+#[cfg(feature = "bindgen")]
+extern crate libbindgen;
+#[cfg(feature = "bindgen")]
+extern crate regex;
extern crate walkdir;
extern crate phf_codegen;
@@ -12,6 +18,14 @@ use std::path::Path;
use std::process::{Command, exit};
use walkdir::WalkDir;
+#[cfg(feature = "gecko")]
+mod build_gecko;
+
+#[cfg(not(feature = "gecko"))]
+mod build_gecko {
+ pub fn generate() {}
+}
+
#[cfg(windows)]
fn find_python() -> String {
if Command::new("python2.7.exe").arg("--version").output().is_ok() {
@@ -39,8 +53,7 @@ fn find_python() -> String {
}.to_owned()
}
-fn main() {
- println!("cargo:rerun-if-changed=build.rs");
+fn generate_properties() {
for entry in WalkDir::new("properties") {
let entry = entry.unwrap();
match entry.path().extension().and_then(|e| e.to_str()) {
@@ -82,3 +95,9 @@ fn main() {
map.build(&mut file).unwrap();
write!(&mut file, ";\n").unwrap();
}
+
+fn main() {
+ println!("cargo:rerun-if-changed=build.rs");
+ generate_properties();
+ build_gecko::generate();
+}
diff --git a/components/style/build_gecko.rs b/components/style/build_gecko.rs
new file mode 100644
index 00000000000..a96a92e9871
--- /dev/null
+++ b/components/style/build_gecko.rs
@@ -0,0 +1,617 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+mod common {
+ use std::env;
+ use std::path::PathBuf;
+
+ lazy_static! {
+ pub static ref OUTDIR_PATH: PathBuf = PathBuf::from(env::var("OUT_DIR").unwrap()).join("gecko");
+ }
+
+ pub const STRUCTS_DEBUG_FILE: &'static str = "structs_debug.rs";
+ pub const STRUCTS_RELEASE_FILE: &'static str = "structs_release.rs";
+ pub const BINDINGS_FILE: &'static str = "bindings.rs";
+
+ #[derive(Clone, Copy, PartialEq)]
+ pub enum BuildType {
+ Debug,
+ Release,
+ }
+
+ pub fn structs_file(build_type: BuildType) -> &'static str {
+ match build_type {
+ BuildType::Debug => STRUCTS_DEBUG_FILE,
+ BuildType::Release => STRUCTS_RELEASE_FILE
+ }
+ }
+}
+
+#[cfg(feature = "bindgen")]
+mod bindings {
+ use libbindgen::{Builder, CodegenConfig};
+ use regex::Regex;
+ use std::collections::HashSet;
+ use std::env;
+ use std::fs::File;
+ use std::io::{BufWriter, Read, Write};
+ use std::path::PathBuf;
+ use std::sync::Mutex;
+ use super::common::*;
+
+ lazy_static! {
+ static ref INCLUDE_RE: Regex = Regex::new(r#"#include\s*"(.+?)""#).unwrap();
+ static ref DISTDIR_PATH: PathBuf = PathBuf::from(env::var("MOZ_DIST").unwrap());
+ static ref SEARCH_PATHS: Vec<PathBuf> = vec![
+ DISTDIR_PATH.join("include"),
+ DISTDIR_PATH.join("include/nspr"),
+ ];
+ static ref ADDED_PATHS: Mutex<HashSet<PathBuf>> = Mutex::new(HashSet::new());
+ }
+
+ fn search_include(name: &str) -> Option<PathBuf> {
+ for path in SEARCH_PATHS.iter() {
+ let file = path.join(name);
+ if file.is_file() {
+ return Some(file);
+ }
+ }
+ None
+ }
+
+ fn add_headers_recursively(path: PathBuf, added_paths: &mut HashSet<PathBuf>) {
+ if added_paths.contains(&path) {
+ return;
+ }
+ let mut file = File::open(&path).unwrap();
+ let mut content = String::new();
+ file.read_to_string(&mut content).unwrap();
+ println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
+ added_paths.insert(path);
+ // Find all includes and add them recursively
+ for cap in INCLUDE_RE.captures_iter(&content) {
+ if let Some(path) = search_include(cap.at(1).unwrap()) {
+ add_headers_recursively(path, added_paths);
+ }
+ }
+ }
+
+ fn add_include(name: &str) -> String {
+ let mut added_paths = ADDED_PATHS.lock().unwrap();
+ let file = search_include(name).unwrap();
+ let result = String::from(file.to_str().unwrap());
+ add_headers_recursively(file, &mut *added_paths);
+ result
+ }
+
+ 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) -> Builder;
+ fn borrowed_type(self, ty: &str) -> Builder;
+ fn mutable_borrowed_type(self, ty: &str) -> 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());
+ }
+ builder = builder.include(add_include("mozilla-config.h"));
+
+ if build_type == BuildType::Debug {
+ builder = builder.clang_arg("-DDEBUG=1").clang_arg("-DJS_DEBUG=1");
+ }
+ if cfg!(target_family = "unix") {
+ builder = builder.clang_arg("-DOS_POSIX=1");
+ }
+ if cfg!(target_os = "linux") {
+ builder = builder.clang_arg("-DOS_LINUX=1");
+ } else if cfg!(target_os = "macos") {
+ builder = builder.clang_arg("-DOS_MACOSX=1");
+ } else if cfg!(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 cfg!(target_pointer_width = "32") {
+ builder = builder.clang_arg("--target=i686-pc-win32");
+ } else {
+ builder = builder.clang_arg("--target=x86_64-pc-win32");
+ }
+ } else {
+ panic!("Unknown platform");
+ }
+ builder
+ }
+ fn include<T: Into<String>>(self, file: T) -> Builder {
+ self.clang_arg("-include").clang_arg(file)
+ }
+ // This makes an FFI-safe void type that can't be matched on
+ // &VoidType is UB to have, because you can match on it
+ // to produce a reachable unreachable. If it's wrapped in
+ // a struct as a private field it becomes okay again
+ //
+ // 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) -> Builder {
+ self.hide_type(ty)
+ .raw_line(format!("enum {}Void {{ }}", ty))
+ .raw_line(format!("pub struct {0}({0}Void);", ty))
+ }
+ fn borrowed_type(self, ty: &str) -> Builder {
+ self.hide_type(format!("{}Borrowed", ty))
+ .raw_line(format!("pub type {0}Borrowed<'a> = &'a {0};", ty))
+ .hide_type(format!("{}BorrowedOrNull", ty))
+ .raw_line(format!("pub type {0}BorrowedOrNull<'a> = Option<&'a {0}>;", ty))
+ }
+ fn mutable_borrowed_type(self, ty: &str) -> Builder {
+ self.borrowed_type(ty)
+ .hide_type(format!("{}BorrowedMut", ty))
+ .raw_line(format!("pub type {0}BorrowedMut<'a> = &'a mut {0};", ty))
+ .hide_type(format!("{}BorrowedMutOrNull", ty))
+ .raw_line(format!("pub type {0}BorrowedMutOrNull<'a> = Option<&'a mut {0}>;", ty))
+ }
+ }
+
+ fn write_binding_file(builder: Builder, file: &str) {
+ let bindings = builder.generate().expect("Unable to generate bindings");
+ let binding_file = File::create(&OUTDIR_PATH.join(file)).unwrap();
+ bindings.write(Box::new(BufWriter::new(binding_file))).expect("Unable to write output");
+ }
+
+ pub fn generate_structs(build_type: BuildType) {
+ let mut builder = Builder::get_initial_builder(build_type)
+ .enable_cxx_namespaces()
+ .with_codegen_config(CodegenConfig {
+ types: true,
+ vars: true,
+ ..CodegenConfig::nothing()
+ })
+ .header(add_include("nsStyleStruct.h"))
+ .include(add_include("gfxFontConstants.h"))
+ .include(add_include("nsThemeConstants.h"))
+ .include(add_include("mozilla/dom/AnimationEffectReadOnlyBinding.h"))
+ .include(add_include("mozilla/ServoElementSnapshot.h"))
+ .include(add_include("mozilla/dom/Element.h"))
+ .include(add_include("mozilla/ServoBindings.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");
+ let whitelist_vars = [
+ "NS_THEME_.*",
+ "NODE_.*",
+ "NS_FONT_.*",
+ "NS_STYLE_.*",
+ "NS_CORNER_.*",
+ "NS_RADIUS_.*",
+ "BORDER_COLOR_.*",
+ "BORDER_STYLE_.*"
+ ];
+ let whitelist = [
+ "RawGecko.*",
+ "mozilla::ServoElementSnapshot.*",
+ "mozilla::ConsumeStyleBehavior",
+ "mozilla::LazyComputeBehavior",
+ "mozilla::css::SheetParsingMode",
+ "mozilla::SkipRootBehavior",
+ "mozilla::DisplayItemClip", // Needed because bindgen generates
+ // specialization tests for this even
+ // though it shouldn't.
+ ".*ThreadSafe.*Holder",
+ "AnonymousContent",
+ "AudioContext",
+ "CapturingContentInfo",
+ "ConsumeStyleBehavior",
+ "DefaultDelete",
+ "DOMIntersectionObserverEntry",
+ "Element",
+ "FontFamilyList",
+ "FontFamilyListRefCnt",
+ "FontFamilyName",
+ "FontFamilyType",
+ "FragmentOrURL",
+ "FrameRequestCallback",
+ "gfxAlternateValue",
+ "gfxFontFeature",
+ "gfxFontVariation",
+ "GridNamedArea",
+ "Image",
+ "ImageURL",
+ "LazyComputeBehavior",
+ "nsAttrName",
+ "nsAttrValue",
+ "nsBorderColors",
+ "nscolor",
+ "nsChangeHint",
+ "nsCSSKeyword",
+ "nsCSSPropertyID",
+ "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",
+ "nsRect",
+ "nsRestyleHint",
+ "nsresult",
+ "nsSize",
+ "nsStyleBackground",
+ "nsStyleBorder",
+ "nsStyleColor",
+ "nsStyleColumn",
+ "nsStyleContent",
+ "nsStyleContentData",
+ "nsStyleContext",
+ "nsStyleCoord",
+ "nsStyleCounterData",
+ "nsStyleDisplay",
+ "nsStyleEffects",
+ "nsStyleFilter",
+ "nsStyleFont",
+ "nsStyleGradient",
+ "nsStyleGradientStop",
+ "nsStyleImage",
+ "nsStyleImageLayers",
+ "nsStyleList",
+ "nsStyleMargin",
+ "nsStyleOutline",
+ "nsStylePadding",
+ "nsStylePosition",
+ "nsStyleSVG",
+ "nsStyleSVGReset",
+ "nsStyleTable",
+ "nsStyleTableBorder",
+ "nsStyleText",
+ "nsStyleTextReset",
+ "nsStyleUIReset",
+ "nsStyleUnion",
+ "nsStyleUnit",
+ "nsStyleUserInterface",
+ "nsStyleVariables",
+ "nsStyleVisibility",
+ "nsStyleXUL",
+ "nsTArray",
+ "nsTArrayHeader",
+ "pair",
+ "Position",
+ "Runnable",
+ "ServoAttrSnapshot",
+ "ServoElementSnapshot",
+ "SheetParsingMode",
+ "mozilla::Side",
+ "StaticRefPtr",
+ "StyleAnimation",
+ "StyleBasicShape",
+ "StyleBasicShapeType",
+ "StyleClipPath",
+ "StyleClipPathGeometryBox",
+ "StyleTransition",
+ "mozilla::UniquePtr",
+ "mozilla::DefaultDelete",
+ ];
+ let opaque_types = [
+ "atomic___base", "std::atomic__My_base",
+ "nsAString_internal_char_traits",
+ "nsAString_internal_incompatible_char_type",
+ "nsACString_internal_char_traits",
+ "nsACString_internal_incompatible_char_type",
+ "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.
+ ];
+ 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>",
+ }
+ ];
+ struct Fixup {
+ pat: String,
+ rep: String
+ }
+ 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 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 result = builder.generate().expect("Unable to generate bindings").to_string();
+ for fixup in fixups.iter() {
+ result = Regex::new(&format!(r"\b{}\b", fixup.pat)).unwrap().replace_all(&result, fixup.rep.as_str());
+ }
+ File::create(&OUTDIR_PATH.join(structs_file(build_type))).unwrap()
+ .write_all(&result.into_bytes()).unwrap();
+ }
+
+ pub fn generate_bindings() {
+ let mut builder = Builder::get_initial_builder(BuildType::Release)
+ .disable_name_namespacing()
+ .with_codegen_config(CodegenConfig {
+ functions: true,
+ ..CodegenConfig::nothing()
+ })
+ .header(add_include("mozilla/ServoBindings.h"))
+ .hide_type("nsACString_internal")
+ .hide_type("nsAString_internal")
+ .raw_line("pub use nsstring::{nsACString, nsAString};")
+ .raw_line("type nsACString_internal = nsACString;")
+ .raw_line("type nsAString_internal = nsAString;")
+ .whitelisted_function("Servo_.*")
+ .whitelisted_function("Gecko_.*");
+ let structs_types = [
+ "RawGeckoDocument",
+ "RawGeckoElement",
+ "RawGeckoNode",
+ "ThreadSafeURIHolder",
+ "ThreadSafePrincipalHolder",
+ "ConsumeStyleBehavior",
+ "LazyComputeBehavior",
+ "SkipRootBehavior",
+ "FontFamilyList",
+ "FontFamilyType",
+ "ServoElementSnapshot",
+ "SheetParsingMode",
+ "StyleBasicShape",
+ "StyleBasicShapeType",
+ "StyleClipPath",
+ "nsCSSKeyword",
+ "nsCSSShadowArray",
+ "nsCSSValue",
+ "nsCSSValueSharedList",
+ "nsChangeHint",
+ "nsCursorImage",
+ "nsFont",
+ "nsIAtom",
+ "nsRestyleHint",
+ "nsStyleBackground",
+ "nsStyleBorder",
+ "nsStyleColor",
+ "nsStyleColumn",
+ "nsStyleContent",
+ "nsStyleContext",
+ "nsStyleCoord",
+ "nsStyleCoord_Calc",
+ "nsStyleCoord_CalcValue",
+ "nsStyleDisplay",
+ "nsStyleEffects",
+ "nsStyleFont",
+ "nsStyleGradient",
+ "nsStyleGradientStop",
+ "nsStyleImage",
+ "nsStyleImageLayers",
+ "nsStyleImageLayers_Layer",
+ "nsStyleImageLayers_LayerType",
+ "nsStyleImageRequest",
+ "nsStyleList",
+ "nsStyleMargin",
+ "nsStyleOutline",
+ "nsStylePadding",
+ "nsStylePosition",
+ "nsStyleQuoteValues",
+ "nsStyleSVG",
+ "nsStyleSVGReset",
+ "nsStyleTable",
+ "nsStyleTableBorder",
+ "nsStyleText",
+ "nsStyleTextReset",
+ "nsStyleUIReset",
+ "nsStyleUnion",
+ "nsStyleUnit",
+ "nsStyleUserInterface",
+ "nsStyleVariables",
+ "nsStyleVisibility",
+ "nsStyleXUL",
+ "nscoord",
+ "nsresult",
+ ];
+ struct ArrayType {
+ cpp_type: &'static str,
+ rust_type: &'static str
+ }
+ let array_types = [
+ ArrayType { cpp_type: "uintptr_t", rust_type: "usize" },
+ ];
+ let servo_nullable_arc_types = [
+ "ServoComputedValues",
+ "ServoCssRules",
+ "RawServoStyleSheet",
+ "RawServoDeclarationBlock",
+ "RawServoStyleRule",
+ ];
+ 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 },
+ ];
+ let servo_immutable_borrow_types = [
+ "RawGeckoNode",
+ "RawGeckoElement",
+ "RawGeckoDocument",
+ "RawServoDeclarationBlockStrong",
+ ];
+ let servo_borrow_types = [
+ "nsCSSValue",
+ ];
+ 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))
+ }
+ for &ty in servo_nullable_arc_types.iter() {
+ builder = builder
+ .hide_type(format!("{}Strong", ty))
+ .raw_line(format!("pub type {0}Strong = ::gecko_bindings::sugar::ownership::Strong<{0}>;", ty))
+ .borrowed_type(ty)
+ .zero_size_type(ty);
+ }
+ 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);
+ }
+ }
+ 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.
+ }
+ write_binding_file(builder, BINDINGS_FILE);
+ }
+}
+
+#[cfg(not(feature = "bindgen"))]
+mod bindings {
+ use std::fs;
+ use std::path::{Path, PathBuf};
+ use super::common::*;
+
+ lazy_static! {
+ static ref BINDINGS_PATH: PathBuf = Path::new(file!()).parent().unwrap().join("gecko_bindings");
+ }
+
+ pub fn generate_structs(build_type: BuildType) {
+ let file = structs_file(build_type);
+ let source = BINDINGS_PATH.join(file);
+ println!("cargo:rerun-if-changed={}", source.display());
+ fs::copy(source, OUTDIR_PATH.join(file)).unwrap();
+ }
+
+ pub fn generate_bindings() {
+ let source = BINDINGS_PATH.join(BINDINGS_FILE);
+ println!("cargo:rerun-if-changed={}", source.display());
+ fs::copy(source, OUTDIR_PATH.join(BINDINGS_FILE)).unwrap();
+ }
+}
+
+pub fn generate() {
+ use self::common::*;
+ use std::fs;
+ fs::create_dir_all(&*OUTDIR_PATH).unwrap();
+ bindings::generate_structs(BuildType::Debug);
+ bindings::generate_structs(BuildType::Release);
+ bindings::generate_bindings();
+}
diff --git a/components/style/gecko_bindings/mod.rs b/components/style/gecko_bindings/mod.rs
index 7201bdb2668..d86bfb60484 100644
--- a/components/style/gecko_bindings/mod.rs
+++ b/components/style/gecko_bindings/mod.rs
@@ -3,22 +3,23 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#[allow(dead_code, improper_ctypes, non_camel_case_types)]
-pub mod bindings;
+pub mod bindings {
+ include!(concat!(env!("OUT_DIR"), "/gecko/bindings.rs"));
+}
// FIXME: We allow `improper_ctypes` (for now), because the lint doesn't allow
// foreign structs to have `PhantomData`. We should remove this once the lint
// ignores this case.
-#[cfg(debug_assertions)]
-#[allow(dead_code, improper_ctypes, non_camel_case_types, non_snake_case, non_upper_case_globals)]
-pub mod structs {
- include!("structs_debug.rs");
-}
-
-#[cfg(not(debug_assertions))]
#[allow(dead_code, improper_ctypes, non_camel_case_types, non_snake_case, non_upper_case_globals)]
pub mod structs {
- include!("structs_release.rs");
+ cfg_if! {
+ if #[cfg(debug_assertions)] {
+ include!(concat!(env!("OUT_DIR"), "/gecko/structs_debug.rs"));
+ } else {
+ include!(concat!(env!("OUT_DIR"), "/gecko/structs_release.rs"));
+ }
+ }
}
pub mod sugar;
diff --git a/ports/geckolib/Cargo.toml b/ports/geckolib/Cargo.toml
index 0df70bc465b..23e9db63a13 100644
--- a/ports/geckolib/Cargo.toml
+++ b/ports/geckolib/Cargo.toml
@@ -9,6 +9,9 @@ name = "geckoservo"
path = "lib.rs"
crate-type = ["staticlib", "rlib"]
+[features]
+bindgen = ["style/bindgen"]
+
[dependencies]
app_units = "0.3"
cssparser = {version = "0.7"}
diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py
index 514a8f87e69..a54d667f5f4 100644
--- a/python/servo/build_commands.py
+++ b/python/servo/build_commands.py
@@ -384,6 +384,9 @@ class MachCommands(CommandBase):
@Command('build-geckolib',
description='Build a static library of components used by Gecko',
category='build')
+ @CommandArgument('--with-gecko',
+ default=None,
+ help='Build with Gecko dist directory')
@CommandArgument('--jobs', '-j',
default=None,
help='Number of jobs to run in parallel')
@@ -393,12 +396,18 @@ class MachCommands(CommandBase):
@CommandArgument('--release', '-r',
action='store_true',
help='Build in release mode')
- def build_geckolib(self, jobs=None, verbose=False, release=False):
+ def build_geckolib(self, with_gecko=None, jobs=None, verbose=False, release=False):
self.set_use_stable_rust()
self.ensure_bootstrapped()
+ env = self.build_env(is_build=True)
+ env["CARGO_TARGET_DIR"] = path.join(self.context.topdir, "target", "geckolib").encode("UTF-8")
+
ret = None
opts = []
+ if with_gecko is not None:
+ opts += ["--features", "bindgen"]
+ env["MOZ_DIST"] = path.abspath(with_gecko)
if jobs is not None:
opts += ["-j", jobs]
if verbose:
@@ -406,9 +415,6 @@ class MachCommands(CommandBase):
if release:
opts += ["--release"]
- env = self.build_env(is_build=True)
- env["CARGO_TARGET_DIR"] = path.join(self.context.topdir, "target", "geckolib").encode("UTF-8")
-
build_start = time()
with cd(path.join("ports", "geckolib")):
ret = call(["cargo", "build"] + opts, env=env, verbose=verbose)