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
This commit is contained in:
Xidorn Quan 2016-12-09 13:55:49 -10:00
parent 6dd4b4822f
commit 1cefd1bef0
8 changed files with 739 additions and 835 deletions

View file

@ -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"

View file

@ -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())

View file

@ -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();
}

View file

@ -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();
}

View file

@ -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;