зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1231764 - part 6 - build rust code via cargo; r=chmanchester
This patch is really two separate changes. The first change is that rust crates are large, standalone entities that may contain multitudes of source files. It therefore doesn't make sense to keep them in SOURCES, as we have been doing. Moving to use cargo will require a higher-level approach, which suggests that we need a different, higher-level representation for Rust sources in the build system. The representation here is to have the build system refer to things defined in Cargo.toml files as the entities dealt with in the build system, and let Cargo deal with the details of actually building things. This approach means that adding a new crate to an existing library just requires editing Rust and Cargo.toml files, rather than dealing with moz.build, which seems more natural to Rust programmers. By having the source files for libraries (and binaries in subsequent iterations of this support) checked in to the tree, we can also take advantage of Cargo.lock files. The second is that we switch the core build system over to building via cargo, rather than invoking rustc directly. We also clean up a number of leftover things from the Old Way of doing things. A number of tests are added to confirm that we'll only permit crates to be built that have dependencies in-tree.
This commit is contained in:
Родитель
dec8ad67e8
Коммит
f7fb6722a6
|
@ -29,6 +29,20 @@ def rustc_info(rustc):
|
|||
commit=info.get('commit-hash', 'unknown'),
|
||||
)
|
||||
|
||||
@depends_if(cargo)
|
||||
@checking('cargo support for --frozen')
|
||||
@imports('subprocess')
|
||||
def cargo_supports_frozen(cargo):
|
||||
try:
|
||||
lines = subprocess.check_output(
|
||||
[cargo, 'help', 'build']
|
||||
).splitlines()
|
||||
return any(' --frozen' in l for l in lines)
|
||||
except subprocess.CalledProcessError as e:
|
||||
die('Failed to call cargo: %s', e.message)
|
||||
|
||||
set_config('MOZ_CARGO_SUPPORTS_FROZEN', cargo_supports_frozen)
|
||||
|
||||
@depends('--enable-rust', rustc, rustc_info)
|
||||
@imports(_from='textwrap', _import='dedent')
|
||||
def rust_compiler(value, rustc, rustc_info):
|
||||
|
@ -105,10 +119,7 @@ def rust_target(rust_compiler, rustc, target, cross_compiling):
|
|||
}.get((target.cpu, os_or_kernel), None)
|
||||
|
||||
if rustc_target is None:
|
||||
if cross_compiling:
|
||||
die("Don't know how to translate {} for rustc".format(target.alias))
|
||||
# Fall back to implicit (native) target when not cross-compiling
|
||||
return None
|
||||
die("Don't know how to translate {} for rustc".format(target.alias))
|
||||
|
||||
# Check to see whether our rustc has a reasonably functional stdlib
|
||||
# for our chosen target.
|
||||
|
@ -141,7 +152,7 @@ def rust_target(rust_compiler, rustc, target, cross_compiling):
|
|||
os.remove(in_path)
|
||||
os.remove(out_path)
|
||||
# This target is usable.
|
||||
return target_arg
|
||||
return rustc_target
|
||||
|
||||
set_config('RUST_TARGET', rust_target)
|
||||
|
||||
|
|
|
@ -63,6 +63,14 @@ def Library(name):
|
|||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
@template
|
||||
def SharedLibrary(name):
|
||||
'''Template for shared libraries.'''
|
||||
|
|
|
@ -240,10 +240,9 @@ CMOBJS = $(notdir $(CMSRCS:.m=.$(OBJ_SUFFIX)))
|
|||
CMMOBJS = $(notdir $(CMMSRCS:.mm=.$(OBJ_SUFFIX)))
|
||||
# ASFILES can have different extensions (.s, .asm)
|
||||
ASOBJS = $(notdir $(addsuffix .$(OBJ_SUFFIX),$(basename $(ASFILES))))
|
||||
RSOBJS = $(addprefix lib,$(notdir $(RSSRCS:.rs=.rlib)))
|
||||
RS_STATICLIB_CRATE_OBJ = $(addprefix lib,$(notdir $(RS_STATICLIB_CRATE_SRC:.rs=.$(LIB_SUFFIX))))
|
||||
ifndef OBJS
|
||||
_OBJS = $(COBJS) $(SOBJS) $(CPPOBJS) $(CMOBJS) $(CMMOBJS) $(ASOBJS) $(RSOBJS)
|
||||
_OBJS = $(COBJS) $(SOBJS) $(CPPOBJS) $(CMOBJS) $(CMMOBJS) $(ASOBJS)
|
||||
OBJS = $(strip $(_OBJS))
|
||||
endif
|
||||
|
||||
|
@ -566,7 +565,7 @@ compile:: host target
|
|||
|
||||
host:: $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS)
|
||||
|
||||
target:: $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS)
|
||||
target:: $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(RUST_LIBRARY_FILE)
|
||||
|
||||
include $(MOZILLA_DIR)/config/makefiles/target_binaries.mk
|
||||
endif
|
||||
|
@ -915,16 +914,33 @@ $(ASOBJS):
|
|||
endif
|
||||
|
||||
ifdef MOZ_RUST
|
||||
# Assume any system libraries rustc links against are already
|
||||
# in the target's LIBS.
|
||||
$(RSOBJS):
|
||||
$(REPORT_BUILD)
|
||||
$(RUSTC) $(RUST_TARGET) $(RUSTFLAGS) --crate-type rlib --emit dep-info=$(MDDEPDIR)/$(call mk_libname,$<).pp,link=$(call mk_libname,$<) $(_VPATH_SRCS)
|
||||
ifdef CARGO_FILE
|
||||
|
||||
$(RS_STATICLIB_CRATE_OBJ):
|
||||
$(REPORT_BUILD)
|
||||
$(RUSTC) $(RUST_TARGET) $(RUSTFLAGS) --crate-type staticlib $(RLIB_EXTERN_CRATE_OPTIONS) --emit dep-info=$(MDDEPDIR)/$(call mk_global_crate_libname,$(RS_STATICLIB_CRATE_SRC)).pp,link=$@ $(RS_STATICLIB_CRATE_SRC)
|
||||
ifdef MOZ_DEBUG
|
||||
cargo_build_flags =
|
||||
else
|
||||
cargo_build_flags = --release
|
||||
endif
|
||||
ifdef MOZ_CARGO_SUPPORTS_FROZEN
|
||||
cargo_build_flags += --frozen
|
||||
endif
|
||||
|
||||
cargo_build_flags += --manifest-path $(CARGO_FILE)
|
||||
cargo_build_flags += --target=$(RUST_TARGET)
|
||||
cargo_build_flags += --verbose
|
||||
|
||||
# Assume any system libraries rustc links against are already in the target's LIBS.
|
||||
#
|
||||
# We need to run cargo unconditionally, because cargo is the only thing that
|
||||
# has full visibility into how changes in Rust sources might affect the final
|
||||
# build.
|
||||
force-cargo-build:
|
||||
$(REPORT_BUILD)
|
||||
env CARGO_TARGET_DIR=. RUSTC=$(RUSTC) $(CARGO) build $(cargo_build_flags) --
|
||||
|
||||
$(RUST_LIBRARY_FILE): force-cargo-build
|
||||
endif # CARGO_FILE
|
||||
endif # MOZ_RUST
|
||||
|
||||
$(SOBJS):
|
||||
$(REPORT_BUILD)
|
||||
|
|
|
@ -37,7 +37,6 @@ if CONFIG['MOZ_WEBM_ENCODER']:
|
|||
]
|
||||
|
||||
if CONFIG['MOZ_RUST']:
|
||||
SOURCES += ['hello.rs',]
|
||||
UNIFIED_SOURCES += ['TestRust.cpp',]
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
--- a/media/libstagefright/binding/mp4parse/Cargo.toml
|
||||
+++ b/media/libstagefright/binding/mp4parse/Cargo.toml
|
||||
@@ -17,23 +17,6 @@ exclude = [
|
||||
"*.mp4",
|
||||
]
|
||||
|
||||
-build = "build.rs"
|
||||
-
|
||||
-[dependencies]
|
||||
-byteorder = "0.5.0"
|
||||
-afl = { version = "0.1.1", optional = true }
|
||||
-afl-plugin = { version = "0.1.1", optional = true }
|
||||
-abort_on_panic = { version = "1.0.0", optional = true }
|
||||
-
|
||||
-[dev-dependencies]
|
||||
-test-assembler = "0.1.2"
|
||||
-
|
||||
-[build-dependencies]
|
||||
-rusty-cheddar = "0.3.2"
|
||||
-
|
||||
-[features]
|
||||
-fuzz = ["afl", "afl-plugin", "abort_on_panic"]
|
||||
-
|
||||
# Somewhat heavy-handed, but we want at least -Z force-overflow-checks=on.
|
||||
[profile.release]
|
||||
debug-assertions = true
|
|
@ -17,23 +17,6 @@ exclude = [
|
|||
"*.mp4",
|
||||
]
|
||||
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
byteorder = "0.5.0"
|
||||
afl = { version = "0.1.1", optional = true }
|
||||
afl-plugin = { version = "0.1.1", optional = true }
|
||||
abort_on_panic = { version = "1.0.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
test-assembler = "0.1.2"
|
||||
|
||||
[build-dependencies]
|
||||
rusty-cheddar = "0.3.2"
|
||||
|
||||
[features]
|
||||
fuzz = ["afl", "afl-plugin", "abort_on_panic"]
|
||||
|
||||
# Somewhat heavy-handed, but we want at least -Z force-overflow-checks=on.
|
||||
[profile.release]
|
||||
debug-assertions = true
|
||||
|
|
|
@ -38,6 +38,7 @@ cp _upstream/byteorder/src/new.rs mp4parse/src/byteorder/new.rs
|
|||
echo "Applying patches..."
|
||||
patch -p4 < byteorder-mod.patch
|
||||
patch -p4 < mp4parse-mod.patch
|
||||
patch -p4 < mp4parse-cargo.patch
|
||||
|
||||
echo "Cleaning up..."
|
||||
rm -rf _upstream
|
||||
|
|
|
@ -80,9 +80,6 @@ SOURCES += [
|
|||
]
|
||||
|
||||
if CONFIG['MOZ_RUST']:
|
||||
SOURCES += [
|
||||
'binding/mp4parse/src/lib.rs',
|
||||
]
|
||||
EXPORTS += [
|
||||
'binding/include/mp4parse.h',
|
||||
]
|
||||
|
|
|
@ -30,7 +30,6 @@ from mozbuild.frontend.data import (
|
|||
GeneratedWebIDLFile,
|
||||
PreprocessedTestWebIDLFile,
|
||||
PreprocessedWebIDLFile,
|
||||
RustCrate,
|
||||
SharedLibrary,
|
||||
TestManifest,
|
||||
TestWebIDLFile,
|
||||
|
|
|
@ -59,7 +59,7 @@ from ..frontend.data import (
|
|||
ObjdirPreprocessedFiles,
|
||||
PerSourceFlag,
|
||||
Program,
|
||||
RustCrate,
|
||||
RustLibrary,
|
||||
SharedLibrary,
|
||||
SimpleProgram,
|
||||
Sources,
|
||||
|
@ -577,9 +577,11 @@ class RecursiveMakeBackend(CommonBackend):
|
|||
else:
|
||||
return False
|
||||
|
||||
elif isinstance(obj, RustCrate):
|
||||
# Nothing to do because |Sources| has done the work for us.
|
||||
pass
|
||||
elif isinstance(obj, RustLibrary):
|
||||
self.backend_input_files.add(obj.cargo_file)
|
||||
self._process_rust_library(obj, backend_file)
|
||||
# No need to call _process_linked_libraries, because Rust
|
||||
# libraries are self-contained objects at this point.
|
||||
|
||||
elif isinstance(obj, SharedLibrary):
|
||||
self._process_shared_library(obj, backend_file)
|
||||
|
@ -1162,17 +1164,6 @@ class RecursiveMakeBackend(CommonBackend):
|
|||
if libdef.symbols_file:
|
||||
backend_file.write('SYMBOLS_FILE := %s\n' % libdef.symbols_file)
|
||||
|
||||
rust_rlibs = [o for o in libdef.linked_libraries if isinstance(o, RustCrate)]
|
||||
if rust_rlibs:
|
||||
# write out Rust file with extern crate declarations.
|
||||
extern_crate_file = mozpath.join(libdef.objdir, 'rul.rs')
|
||||
with self._write_file(extern_crate_file) as f:
|
||||
f.write('// AUTOMATICALLY GENERATED. DO NOT EDIT.\n\n')
|
||||
for rlib in rust_rlibs:
|
||||
f.write('extern crate %s;\n' % rlib.crate_name)
|
||||
|
||||
backend_file.write('RS_STATICLIB_CRATE_SRC := %s\n' % extern_crate_file)
|
||||
|
||||
def _process_static_library(self, libdef, backend_file):
|
||||
backend_file.write_once('LIBRARY_NAME := %s\n' % libdef.basename)
|
||||
backend_file.write('FORCE_STATIC_LIB := 1\n')
|
||||
|
@ -1182,6 +1173,10 @@ class RecursiveMakeBackend(CommonBackend):
|
|||
if libdef.no_expand_lib:
|
||||
backend_file.write('NO_EXPAND_LIBS := 1\n')
|
||||
|
||||
def _process_rust_library(self, libdef, backend_file):
|
||||
backend_file.write_once('RUST_LIBRARY_FILE := %s\n' % libdef.import_name)
|
||||
backend_file.write('CARGO_FILE := $(srcdir)/Cargo.toml')
|
||||
|
||||
def _process_host_library(self, libdef, backend_file):
|
||||
backend_file.write('HOST_LIBRARY_NAME = %s\n' % libdef.basename)
|
||||
|
||||
|
@ -1192,7 +1187,7 @@ class RecursiveMakeBackend(CommonBackend):
|
|||
def _process_linked_libraries(self, obj, backend_file):
|
||||
def write_shared_and_system_libs(lib):
|
||||
for l in lib.linked_libraries:
|
||||
if isinstance(l, StaticLibrary):
|
||||
if isinstance(l, (StaticLibrary, RustLibrary)):
|
||||
write_shared_and_system_libs(l)
|
||||
else:
|
||||
backend_file.write_once('SHARED_LIBS += %s/%s\n'
|
||||
|
@ -1214,14 +1209,15 @@ class RecursiveMakeBackend(CommonBackend):
|
|||
self._build_target_for_obj(lib))
|
||||
relpath = pretty_relpath(lib)
|
||||
if isinstance(obj, Library):
|
||||
if isinstance(lib, StaticLibrary):
|
||||
if isinstance(lib, RustLibrary):
|
||||
# We don't need to do anything here; we will handle
|
||||
# linkage for any RustLibrary elsewhere.
|
||||
continue
|
||||
elif isinstance(lib, StaticLibrary):
|
||||
backend_file.write_once('STATIC_LIBS += %s/%s\n'
|
||||
% (relpath, lib.import_name))
|
||||
if isinstance(obj, SharedLibrary):
|
||||
write_shared_and_system_libs(lib)
|
||||
elif isinstance(lib, RustCrate):
|
||||
backend_file.write_once('RLIB_EXTERN_CRATE_OPTIONS += --extern %s=%s/%s\n'
|
||||
% (lib.crate_name, relpath, lib.rlib_filename))
|
||||
elif isinstance(obj, SharedLibrary):
|
||||
assert lib.variant != lib.COMPONENT
|
||||
backend_file.write_once('SHARED_LIBS += %s/%s\n'
|
||||
|
@ -1240,13 +1236,28 @@ class RecursiveMakeBackend(CommonBackend):
|
|||
backend_file.write_once('HOST_LIBS += %s/%s\n'
|
||||
% (relpath, lib.import_name))
|
||||
|
||||
# We have to link the Rust super-crate after all intermediate static
|
||||
# libraries have been listed to ensure that the Rust objects are
|
||||
# We have to link any Rust libraries after all intermediate static
|
||||
# libraries have been listed to ensure that the Rust libraries are
|
||||
# searched after the C/C++ objects that might reference Rust symbols.
|
||||
# Building the Rust super-crate will take care of Rust->Rust linkage.
|
||||
if isinstance(obj, SharedLibrary) and any(isinstance(o, RustCrate)
|
||||
# Building Rust crates normally takes care of Rust->Rust linkage, but
|
||||
# we have to be careful: a savvy user might have specified that there
|
||||
# is a staticlib (that contains the Rust runtime) and several other
|
||||
# rlibs (which are plain archive files) to be linked into a given
|
||||
# library. We need to ensure that the staticlib comes after the
|
||||
# rlibs to ensure symbols are found correctly.
|
||||
if isinstance(obj, SharedLibrary) and any(isinstance(o, RustLibrary)
|
||||
for o in obj.linked_libraries):
|
||||
backend_file.write('STATIC_LIBS += $(RS_STATICLIB_CRATE_OBJ)\n')
|
||||
libs = [l for l in obj.linked_libraries if isinstance(l, RustLibrary)]
|
||||
def name_cmp(l1, l2):
|
||||
if l1.crate_type == 'staticlib':
|
||||
return 1
|
||||
if l2.crate_type == 'staticlib':
|
||||
return -1
|
||||
return cmp(l1.basename, l2.basename)
|
||||
libs.sort(cmp=name_cmp)
|
||||
for l in libs:
|
||||
relpath = pretty_relpath(l)
|
||||
backend_file.write('STATIC_LIBS += %s/%s\n' % (relpath, l.import_name))
|
||||
|
||||
for lib in obj.linked_system_libs:
|
||||
if obj.KIND == 'target':
|
||||
|
@ -1439,7 +1450,6 @@ class RecursiveMakeBackend(CommonBackend):
|
|||
backend_file = self._get_backend_file_for(obj)
|
||||
|
||||
backend_file.write('RS_STATICLIB_CRATE_SRC := %s\n' % extern_crate_file)
|
||||
backend_file.write('STATIC_LIBS += librul.$(LIB_SUFFIX)\n')
|
||||
|
||||
def _handle_ipdl_sources(self, ipdl_dir, sorted_ipdl_sources,
|
||||
unified_ipdl_cppsrcs_mapping):
|
||||
|
|
|
@ -945,6 +945,13 @@ VARIABLES = {
|
|||
|
||||
"""),
|
||||
|
||||
'IS_RUST_LIBRARY': (bool, bool,
|
||||
"""Whether the current library defined by this moz.build is built by Rust.
|
||||
|
||||
The library defined by this moz.build should have a build definition in
|
||||
a Cargo.toml file that exists in this moz.build's directory.
|
||||
"""),
|
||||
|
||||
'UNIFIED_SOURCES': (ContextDerivedTypedList(SourcePath, StrictOrderingOnAppendList), list,
|
||||
"""Source code files that can be compiled together.
|
||||
|
||||
|
|
|
@ -445,17 +445,6 @@ class Library(BaseLibrary):
|
|||
self.is_sdk = is_sdk
|
||||
|
||||
|
||||
class RustCrate(Library):
|
||||
"""Context derived container object for a Rust rlib"""
|
||||
|
||||
def __init__(self, context, basename, crate_name, srcdir, rlib_filename, link_into):
|
||||
Library.__init__(self, context, basename)
|
||||
self.crate_name = crate_name
|
||||
self.srcdir = srcdir
|
||||
self.rlib_filename = rlib_filename
|
||||
self.link_into = link_into
|
||||
|
||||
|
||||
class StaticLibrary(Library):
|
||||
"""Context derived container object for a static library"""
|
||||
__slots__ = (
|
||||
|
@ -470,6 +459,40 @@ class StaticLibrary(Library):
|
|||
self.no_expand_lib = no_expand_lib
|
||||
|
||||
|
||||
class RustLibrary(StaticLibrary):
|
||||
"""Context derived container object for a static library"""
|
||||
__slots__ = (
|
||||
'cargo_file',
|
||||
'crate_type',
|
||||
)
|
||||
|
||||
def __init__(self, context, basename, cargo_file, crate_type, **args):
|
||||
StaticLibrary.__init__(self, context, basename, **args)
|
||||
self.cargo_file = cargo_file
|
||||
self.crate_type = crate_type
|
||||
# We need to adjust our naming here because cargo replaces '-' in
|
||||
# package names defined in Cargo.toml with underscores in actual
|
||||
# filenames. But we need to keep the basename consistent because
|
||||
# many other things in the build system depend on that.
|
||||
assert self.crate_type == 'staticlib'
|
||||
self.lib_name = '%s%s%s' % (
|
||||
context.config.lib_prefix,
|
||||
basename.replace('-', '_'),
|
||||
context.config.lib_suffix
|
||||
)
|
||||
# cargo creates several directories and places its build artifacts
|
||||
# in those directories. The directory structure depends not only
|
||||
# on the target, but also what sort of build we are doing.
|
||||
rust_build_kind = 'release'
|
||||
if context.config.substs.get('MOZ_DEBUG'):
|
||||
rust_build_kind = 'debug'
|
||||
self.import_name = '%s/%s/%s' % (
|
||||
context.config.substs['RUST_TARGET'],
|
||||
rust_build_kind,
|
||||
self.lib_name,
|
||||
)
|
||||
|
||||
|
||||
class SharedLibrary(Library):
|
||||
"""Context derived container object for a shared library"""
|
||||
__slots__ = (
|
||||
|
|
|
@ -20,6 +20,7 @@ from mozbuild.util import (
|
|||
|
||||
import mozpack.path as mozpath
|
||||
import mozinfo
|
||||
import pytoml
|
||||
|
||||
from .data import (
|
||||
AndroidAssetsDirs,
|
||||
|
@ -60,7 +61,7 @@ from .data import (
|
|||
PreprocessedTestWebIDLFile,
|
||||
PreprocessedWebIDLFile,
|
||||
Program,
|
||||
RustCrate,
|
||||
RustLibrary,
|
||||
SdkFiles,
|
||||
SharedLibrary,
|
||||
SimpleProgram,
|
||||
|
@ -128,6 +129,8 @@ class TreeMetadataEmitter(LoggingMixin):
|
|||
self._binaries = OrderedDict()
|
||||
self._linkage = []
|
||||
self._static_linking_shared = set()
|
||||
self._crate_verified_local = set()
|
||||
self._crate_directories = dict()
|
||||
|
||||
# Keep track of external paths (third party build systems), starting
|
||||
# from what we run a subconfigure in. We'll eliminate some directories
|
||||
|
@ -195,7 +198,7 @@ class TreeMetadataEmitter(LoggingMixin):
|
|||
def _emit_libs_derived(self, contexts):
|
||||
# First do FINAL_LIBRARY linkage.
|
||||
for lib in (l for libs in self._libs.values() for l in libs):
|
||||
if not isinstance(lib, (StaticLibrary, RustCrate)) or not lib.link_into:
|
||||
if not isinstance(lib, (StaticLibrary, RustLibrary)) or not lib.link_into:
|
||||
continue
|
||||
if lib.link_into not in self._libs:
|
||||
raise SandboxValidationError(
|
||||
|
@ -373,6 +376,124 @@ class TreeMetadataEmitter(LoggingMixin):
|
|||
else:
|
||||
return ExternalSharedLibrary(context, name)
|
||||
|
||||
def _parse_cargo_file(self, toml_file):
|
||||
"""Parse toml_file and return a Python object representation of it."""
|
||||
with open(toml_file, 'r') as f:
|
||||
return pytoml.load(f)
|
||||
|
||||
def _verify_deps(self, context, crate_dir, crate_name, dependencies, description='Dependency'):
|
||||
"""Verify that a crate's dependencies all specify local paths."""
|
||||
for dep_crate_name, values in dependencies.iteritems():
|
||||
# A simple version number.
|
||||
if isinstance(values, (str, unicode)):
|
||||
raise SandboxValidationError(
|
||||
'%s %s of crate %s does not list a path' % (description, dep_crate_name, crate_name),
|
||||
context)
|
||||
|
||||
dep_path = values.get('path', None)
|
||||
if not dep_path:
|
||||
raise SandboxValidationError(
|
||||
'%s %s of crate %s does not list a path' % (description, dep_crate_name, crate_name),
|
||||
context)
|
||||
|
||||
# Try to catch the case where somebody listed a
|
||||
# local path for development.
|
||||
if os.path.isabs(dep_path):
|
||||
raise SandboxValidationError(
|
||||
'%s %s of crate %s has a non-relative path' % (description, dep_crate_name, crate_name),
|
||||
context)
|
||||
|
||||
if not os.path.exists(mozpath.join(context.config.topsrcdir, crate_dir, dep_path)):
|
||||
raise SandboxValidationError(
|
||||
'%s %s of crate %s refers to a non-existent path' % (description, dep_crate_name, crate_name),
|
||||
context)
|
||||
|
||||
def _verify_local_paths(self, context, crate_dir, config):
|
||||
"""Verify that a Cargo.toml config specifies local paths for all its dependencies."""
|
||||
crate_name = config['package']['name']
|
||||
|
||||
# This is not exactly how cargo works (cargo would permit
|
||||
# identically-named packages with different versions in the same
|
||||
# library), but we want to try and avoid using multiple
|
||||
# different versions of a single package for code size reasons.
|
||||
if crate_name not in self._crate_directories:
|
||||
self._crate_directories[crate_name] = crate_dir
|
||||
else:
|
||||
previous_dir = self._crate_directories[crate_name]
|
||||
if crate_dir != previous_dir:
|
||||
raise SandboxValidationError(
|
||||
'Crate %s found at multiple paths: %s, %s' % (crate_name, crate_dir, previous_dir),
|
||||
context)
|
||||
|
||||
# This check should ideally be positioned when we're recursing through
|
||||
# dependencies, but then we would never get the chance to run the
|
||||
# duplicated names check above.
|
||||
if crate_name in self._crate_verified_local:
|
||||
return
|
||||
|
||||
crate_deps = config.get('dependencies', {})
|
||||
if crate_deps:
|
||||
self._verify_deps(context, crate_dir, crate_name, crate_deps)
|
||||
|
||||
has_custom_build = 'build' in config['package']
|
||||
build_deps = config.get('build-dependencies', {})
|
||||
if has_custom_build and build_deps:
|
||||
self._verify_deps(context, crate_dir, crate_name, build_deps,
|
||||
description='Build dependency')
|
||||
|
||||
# We have now verified that all the declared dependencies of
|
||||
# this crate have local paths. Now verify recursively.
|
||||
self._crate_verified_local.add(crate_name)
|
||||
|
||||
if crate_deps:
|
||||
for dep_crate_name, values in crate_deps.iteritems():
|
||||
rel_dep_dir = mozpath.normpath(mozpath.join(crate_dir, values['path']))
|
||||
dep_toml = mozpath.join(context.config.topsrcdir, rel_dep_dir, 'Cargo.toml')
|
||||
self._verify_local_paths(context, rel_dep_dir, self._parse_cargo_file(dep_toml))
|
||||
|
||||
if has_custom_build and build_deps:
|
||||
for dep_crate_name, values in build_deps.iteritems():
|
||||
rel_dep_dir = mozpath.normpath(mozpath.join(crate_dir, values['path']))
|
||||
dep_toml = mozpath.join(context.config.topsrcdir, rel_dep_dir, 'Cargo.toml')
|
||||
self._verify_local_paths(context, rel_dep_dir, self._parse_cargo_file(dep_toml))
|
||||
|
||||
def _rust_library(self, context, libname, static_args):
|
||||
# We need to note any Rust library for linking purposes.
|
||||
cargo_file = mozpath.join(context.srcdir, 'Cargo.toml')
|
||||
if not os.path.exists(cargo_file):
|
||||
raise SandboxValidationError(
|
||||
'No Cargo.toml file found in %s' % cargo_file, context)
|
||||
|
||||
config = self._parse_cargo_file(cargo_file)
|
||||
crate_name = config['package']['name']
|
||||
|
||||
if crate_name != libname:
|
||||
raise SandboxValidationError(
|
||||
'library %s does not match Cargo.toml-defined package %s' % (libname, crate_name),
|
||||
context)
|
||||
|
||||
lib_section = config.get('lib', None)
|
||||
if not lib_section:
|
||||
raise SandboxValidationError(
|
||||
'Cargo.toml for %s has no [lib] section' % libname,
|
||||
context)
|
||||
|
||||
crate_type = lib_section.get('crate-type', None)
|
||||
if not crate_type:
|
||||
raise SandboxValidationError(
|
||||
'Can\'t determine a crate-type for %s from Cargo.toml' % libname,
|
||||
context)
|
||||
|
||||
crate_type = crate_type[0]
|
||||
if crate_type != 'staticlib':
|
||||
raise SandboxValidationError(
|
||||
'crate-type %s is not permitted for %s' % (crate_type, libname),
|
||||
context)
|
||||
|
||||
self._verify_local_paths(context, context.relsrcdir, config)
|
||||
|
||||
return RustLibrary(context, libname, cargo_file, crate_type, **static_args)
|
||||
|
||||
def _handle_linkables(self, context, passthru, generated_files):
|
||||
has_linkables = False
|
||||
|
||||
|
@ -580,9 +701,25 @@ class TreeMetadataEmitter(LoggingMixin):
|
|||
'generate_symbols_file', lib.symbols_file,
|
||||
[symbols_file], defines)
|
||||
if static_lib:
|
||||
lib = StaticLibrary(context, libname, **static_args)
|
||||
is_rust_library = context.get('IS_RUST_LIBRARY')
|
||||
if is_rust_library:
|
||||
lib = self._rust_library(context, libname, static_args)
|
||||
else:
|
||||
lib = StaticLibrary(context, libname, **static_args)
|
||||
self._libs[libname].append(lib)
|
||||
self._linkage.append((context, lib, 'USE_LIBS'))
|
||||
|
||||
# Multiple staticlibs for a library means multiple copies
|
||||
# of the Rust runtime, which will result in linking errors
|
||||
# later on.
|
||||
if is_rust_library:
|
||||
staticlibs = [l for l in self._libs[libname]
|
||||
if isinstance(l, RustLibrary) and l.crate_type == 'staticlib']
|
||||
if len(staticlibs) > 1:
|
||||
raise SandboxValidationError(
|
||||
'Cannot have multiple Rust staticlibs in %s: %s' % (libname, ', '.join(l.basename for l in staticlibs)),
|
||||
context)
|
||||
|
||||
has_linkables = True
|
||||
|
||||
if lib_defines:
|
||||
|
@ -597,7 +734,6 @@ class TreeMetadataEmitter(LoggingMixin):
|
|||
if not has_linkables:
|
||||
return
|
||||
|
||||
rust_sources = []
|
||||
sources = defaultdict(list)
|
||||
gen_sources = defaultdict(list)
|
||||
all_flags = {}
|
||||
|
@ -649,7 +785,6 @@ class TreeMetadataEmitter(LoggingMixin):
|
|||
'.m': set(),
|
||||
'.mm': set(),
|
||||
'.cpp': set(['.cc', '.cxx']),
|
||||
'.rs': set(),
|
||||
'.S': set(),
|
||||
}
|
||||
|
||||
|
@ -694,42 +829,8 @@ class TreeMetadataEmitter(LoggingMixin):
|
|||
'FILES_PER_UNIFIED_FILE' in context):
|
||||
arglist.append(context['FILES_PER_UNIFIED_FILE'])
|
||||
obj = cls(*arglist)
|
||||
|
||||
# Rust is special. Each Rust file that we compile
|
||||
# is a separate crate and gets compiled into its own
|
||||
# rlib file (Rust's equivalent of a .a file). When
|
||||
# we go to link Rust sources into a library or
|
||||
# executable, we have a separate, single crate that
|
||||
# gets compiled as a staticlib (like a rlib, but
|
||||
# includes the actual Rust runtime).
|
||||
if canonical_suffix == '.rs':
|
||||
if not final_lib:
|
||||
raise SandboxValidationError(
|
||||
'Rust sources must be destined for a FINAL_LIBRARY')
|
||||
# If we're building a shared library, we're going to
|
||||
# auto-generate a module that includes all of the rlib
|
||||
# files. This means we can't permit Rust files as
|
||||
# immediate inputs of the shared library.
|
||||
if libname and shared_lib:
|
||||
raise SandboxValidationError(
|
||||
'No Rust sources permitted as an immediate input of %s: %s' % (shlib, files))
|
||||
rust_sources.append(obj)
|
||||
yield obj
|
||||
|
||||
# Rust sources get translated into rlibs, which are essentially static
|
||||
# libraries. We need to note all of them for linking, too.
|
||||
if libname and static_lib:
|
||||
for s in rust_sources:
|
||||
for f in s.files:
|
||||
(base, _) = mozpath.splitext(mozpath.basename(f))
|
||||
crate_name = context.relsrcdir.replace('/', '_') + '_' + base
|
||||
rlib_filename = 'lib' + base + '.rlib'
|
||||
lib = RustCrate(context, libname, crate_name,
|
||||
mozpath.join(context.srcdir, mozpath.dirname(f)),
|
||||
rlib_filename, final_lib)
|
||||
self._libs[libname].append(lib)
|
||||
self._linkage.append((context, lib, 'USE_LIBS'))
|
||||
|
||||
for f, flags in all_flags.iteritems():
|
||||
if flags.flags:
|
||||
ext = mozpath.splitext(f)[1]
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
build = "build.rs"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[build-dependencies]
|
||||
bogus = { version = "0.1.0", path = "/path/to/somewhere" }
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
build = "build.rs"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[build-dependencies]
|
||||
bogus = { version = "0.1.0", path = "../bogus" }
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
ok = { version = "0.1.0", path = "ok" }
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "ok"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
build = "build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
bogus = { version = "0.1.0" }
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
build = "build.rs"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[build-dependencies]
|
||||
bogus = "0.1.0"
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
build = "build.rs"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[build-dependencies]
|
||||
bogus = { version = "0.1.0" }
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
bogus = { version = "0.1.0", path = "/path/to/somewhere" }
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
bogus = { version = "0.1.0", path = "../bogus" }
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
deep-crate = { version = "0.1.0", path = "the/depths" }
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "shallow-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "deep-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
shallow-crate = { path = "../../shallow" }
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
ok = { version = "0.1.0", path = "ok" }
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "ok"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
bogus = { version = "0.1.0" }
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
bogus = "0.1.0"
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
bogus = { version = "0.1.0" }
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
crate-one = { path = "crate-one" }
|
||||
crate-two = { path = "crate-two" }
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "crate-one"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
duplicate = { path = "duplicate" }
|
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "duplicate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "crate-two"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
duplicate = { path = "duplicate" }
|
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "duplicate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
||||
|
||||
[lib]
|
||||
crate-type = ["dylib"]
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "deterministic-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "random-crate"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Nobody <nobody@mozilla.org>",
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@template
|
||||
def Library(name):
|
||||
'''Template for libraries.'''
|
||||
LIBRARY_NAME = name
|
||||
|
||||
|
||||
@template
|
||||
def RustLibrary(name):
|
||||
'''Template for Rust libraries.'''
|
||||
Library(name)
|
||||
|
||||
IS_RUST_LIBRARY = True
|
||||
|
||||
|
||||
RustLibrary('random-crate')
|
|
@ -30,6 +30,7 @@ from mozbuild.frontend.data import (
|
|||
JARManifest,
|
||||
LocalInclude,
|
||||
Program,
|
||||
RustLibrary,
|
||||
SdkFiles,
|
||||
SharedLibrary,
|
||||
SimpleProgram,
|
||||
|
@ -992,6 +993,131 @@ class TestEmitterBasic(unittest.TestCase):
|
|||
'Only source directory paths allowed in FINAL_TARGET_PP_FILES:'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_crate_dependency_version_only(self):
|
||||
'''Test that including a crate with a version-only dependency fails.'''
|
||||
reader = self.reader('crate-dependency-version-only')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'Dependency.*of crate.*does not list a path'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_crate_dependency_with_dict(self):
|
||||
'''Test that including a crate with a dict-using version-only dependency fails.'''
|
||||
reader = self.reader('crate-dependency-with-dict')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'Dependency.*of crate.*does not list a path'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_crate_dependency_absolute_path(self):
|
||||
'''Test that including a crate with an absolute-path dependency fails.'''
|
||||
reader = self.reader('crate-dependency-absolute-path')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'Dependency.*of crate.*has a non-relative path'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_crate_dependency_nonexistent_path(self):
|
||||
'''Test that including a crate with a non-existent dependency fails.'''
|
||||
reader = self.reader('crate-dependency-nonexistent-path')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'Dependency.*of crate.*refers to a non-existent path'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_crate_build_dependency_version_only(self):
|
||||
'''Test that including a crate with a version-only dependency fails.'''
|
||||
reader = self.reader('crate-build-dependency-version-only')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'Build dependency.*of crate.*does not list a path'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_crate_build_dependency_with_dict(self):
|
||||
'''Test that including a crate with a dict-using version-only dependency fails.'''
|
||||
reader = self.reader('crate-build-dependency-with-dict')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'Build dependency.*of crate.*does not list a path'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_crate_build_dependency_absolute_path(self):
|
||||
'''Test that including a crate with an absolute-path dependency fails.'''
|
||||
reader = self.reader('crate-build-dependency-absolute-path')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'Build dependency.*of crate.*has a non-relative path'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_crate_build_dependency_nonexistent_path(self):
|
||||
'''Test that including a crate with a non-existent dependency fails.'''
|
||||
reader = self.reader('crate-build-dependency-nonexistent-path')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'Build dependency.*of crate.*refers to a non-existent path'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_crate_dependency_recursive(self):
|
||||
reader = self.reader('crate-dependency-recursive')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'Dependency.*of crate.*does not list a path'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_crate_build_dependency_recursive(self):
|
||||
reader = self.reader('crate-build-dependency-recursive')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'Build dependency.*of crate.*does not list a path'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_rust_library_no_cargo_toml(self):
|
||||
'''Test that defining a RustLibrary without a Cargo.toml fails.'''
|
||||
reader = self.reader('rust-library-no-cargo-toml')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'No Cargo.toml file found'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_rust_library_name_mismatch(self):
|
||||
'''Test that defining a RustLibrary that doesn't match Cargo.toml fails.'''
|
||||
reader = self.reader('rust-library-name-mismatch')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'library.*does not match Cargo.toml-defined package'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_rust_library_no_lib_section(self):
|
||||
'''Test that a RustLibrary Cargo.toml with no [lib] section fails.'''
|
||||
reader = self.reader('rust-library-no-lib-section')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'Cargo.toml for.* has no \\[lib\\] section'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_rust_library_invalid_crate_type(self):
|
||||
'''Test that a RustLibrary Cargo.toml has a permitted crate-type.'''
|
||||
reader = self.reader('rust-library-invalid-crate-type')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'crate-type.* is not permitted'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_rust_library_dash_folding(self):
|
||||
'''Test that on-disk names of RustLibrary objects convert dashes to underscores.'''
|
||||
reader = self.reader('rust-library-dash-folding',
|
||||
extra_substs=dict(RUST_TARGET='i686-pc-windows-msvc'))
|
||||
objs = self.read_topsrcdir(reader)
|
||||
|
||||
self.assertEqual(len(objs), 1)
|
||||
lib = objs[0]
|
||||
self.assertIsInstance(lib, RustLibrary)
|
||||
self.assertRegexpMatches(lib.lib_name, "random_crate")
|
||||
self.assertRegexpMatches(lib.import_name, "random_crate")
|
||||
self.assertRegexpMatches(lib.basename, "random-crate")
|
||||
|
||||
def test_crate_dependency_path_resolution(self):
|
||||
'''Test recursive dependencies resolve with the correct paths.'''
|
||||
reader = self.reader('crate-dependency-path-resolution',
|
||||
extra_substs=dict(RUST_TARGET='i686-pc-windows-msvc'))
|
||||
objs = self.read_topsrcdir(reader)
|
||||
|
||||
self.assertEqual(len(objs), 1)
|
||||
self.assertIsInstance(objs[0], RustLibrary)
|
||||
|
||||
def test_duplicate_crate_names(self):
|
||||
'''Test that crates are not duplicated in the tree.'''
|
||||
reader = self.reader('duplicated-crate-names')
|
||||
with self.assertRaisesRegexp(SandboxValidationError,
|
||||
'Crate.*found at multiple paths'):
|
||||
self.read_topsrcdir(reader)
|
||||
|
||||
def test_android_res_dirs(self):
|
||||
"""Test that ANDROID_RES_DIRS works properly."""
|
||||
reader = self.reader('android-res-dirs')
|
||||
|
|
|
@ -11,3 +11,8 @@ FINAL_TARGET = 'dist/bin/gtest'
|
|||
USE_LIBS += [
|
||||
'static:xul',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_RUST']:
|
||||
USE_LIBS += [
|
||||
'gkrust-gtest',
|
||||
]
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
[root]
|
||||
name = "gkrust-gtest"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"mp4parse-gtest 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mp4parse-gtest"
|
||||
version = "0.1.0"
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
[package]
|
||||
name = "gkrust-gtest"
|
||||
version = "0.1.0"
|
||||
authors = ["nobody@mozilla.org"]
|
||||
license = "MPL-2.0"
|
||||
description = "Testing code for libgkrust"
|
||||
|
||||
[dependencies]
|
||||
mp4parse-gtest = { path = "../../../../dom/media/gtest" }
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
crate-type = ["staticlib"]
|
||||
test = false
|
||||
doctest = false
|
||||
bench = false
|
||||
doc = false
|
||||
plugin = false
|
||||
harness = false
|
||||
|
||||
# Explicitly specify what our profiles use.
|
||||
[profile.dev]
|
||||
opt-level = 1
|
||||
debug = true
|
||||
rpath = false
|
||||
lto = false
|
||||
debug-assertions = true
|
||||
codegen-units = 1
|
||||
|
||||
[profile.release]
|
||||
opt-level = 2
|
||||
debug = true
|
||||
rpath = false
|
||||
lto = false
|
||||
debug-assertions = false
|
||||
codegen-units = 1
|
|
@ -0,0 +1,5 @@
|
|||
// 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/.
|
||||
|
||||
extern crate mp4parse_gtest;
|
|
@ -0,0 +1,7 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=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/.
|
||||
|
||||
RustLibrary('gkrust-gtest')
|
|
@ -384,5 +384,11 @@ if CONFIG['COMPILE_ENVIRONMENT']:
|
|||
]
|
||||
FINAL_TARGET_FILES += ['!dependentlibs.list']
|
||||
|
||||
# This needs to be last
|
||||
# This library needs to be last to make XPCOM module registration work.
|
||||
USE_LIBS += ['StaticXULComponentsEnd']
|
||||
|
||||
# The above library needs to be last for C++ purposes. This library,
|
||||
# however, is entirely composed of Rust code, and needs to come after
|
||||
# all the C++ code so any possible C++ -> Rust calls can be resolved.
|
||||
if CONFIG['MOZ_RUST']:
|
||||
USE_LIBS += ['gkrust']
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
[root]
|
||||
name = "gkrust"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"mp4parse 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mp4parse"
|
||||
version = "0.4.0"
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
[package]
|
||||
name = "gkrust"
|
||||
version = "0.1.0"
|
||||
authors = ["nobody@mozilla.org"]
|
||||
license = "MPL-2.0"
|
||||
description = "Rust code for libxul"
|
||||
|
||||
[dependencies]
|
||||
mp4parse = { path = "../../../media/libstagefright/binding/mp4parse" }
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
crate-type = ["staticlib"]
|
||||
test = false
|
||||
doctest = false
|
||||
bench = false
|
||||
doc = false
|
||||
plugin = false
|
||||
harness = false
|
||||
|
||||
# Explicitly specify what our profiles use.
|
||||
[profile.dev]
|
||||
opt-level = 1
|
||||
debug = true
|
||||
rpath = false
|
||||
lto = false
|
||||
debug-assertions = true
|
||||
codegen-units = 1
|
||||
|
||||
[profile.release]
|
||||
opt-level = 2
|
||||
debug = true
|
||||
rpath = false
|
||||
lto = false
|
||||
debug-assertions = false
|
||||
codegen-units = 1
|
|
@ -0,0 +1,5 @@
|
|||
// 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/.
|
||||
|
||||
extern crate mp4parse;
|
|
@ -0,0 +1,7 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=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/.
|
||||
|
||||
RustLibrary('gkrust')
|
|
@ -1,3 +1,4 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=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
|
||||
|
@ -142,6 +143,12 @@ DIRS += [
|
|||
if CONFIG['MOZ_GIO_COMPONENT']:
|
||||
DIRS += ['/extensions/gio']
|
||||
|
||||
if CONFIG['MOZ_RUST']:
|
||||
DIRS += [
|
||||
'/toolkit/library/gtest/rust',
|
||||
'/toolkit/library/rust',
|
||||
]
|
||||
|
||||
DIRS += [
|
||||
'/toolkit/library/StaticXULComponentsEnd',
|
||||
'/toolkit/library',
|
||||
|
|
Загрузка…
Ссылка в новой задаче