Bug 1300208 - Allow specifying multiple rust crates to mozbuild within the same FINAL_LIBRARY, r=froydnj

MozReview-Commit-ID: IIjV4Kg7wOv
This commit is contained in:
Michael Layzell 2016-09-02 18:05:09 -04:00
parent eea6b5c9c8
commit 05bd5a1076
9 changed files with 84 additions and 46 deletions

View File

@ -21,6 +21,11 @@ def generate(args):
else:
raise Exception("File not found: %s" % arg)
elif os.path.splitext(arg)[1] == conf.LIB_SUFFIX:
# We want to skip static libraries with the name foo-rs-prelink
# as they are individually linked for every final library, and
# thus should not be included in the descriptor file
if '-rs-prelink' in os.path.basename(arg):
continue
if os.path.exists(arg) or os.path.exists(arg + conf.LIBS_DESC_SUFFIX):
desc['LIBS'].append(os.path.abspath(arg))
else:

View File

@ -940,6 +940,30 @@ force-cargo-build:
$(RUST_LIBRARY_FILE): force-cargo-build
endif # CARGO_FILE
ifdef RUST_PRELINK
# Make target for building a prelinked rust library. This merges rust .rlibs
# together into a single .a file which is used within the FINAL_LIBRARY.
#
# RUST_PRELINK_FLAGS, RUST_PRELINK_SRC, and RUST_PRELINK_DEPS are set in
# recursivemake.py, and together tell rustc how to find the libraries to link
# together, but we compute the optimization flags below
RUST_PRELINK_FLAGS += -g
RUST_PRELINK_FLAGS += -C panic=abort
ifdef MOZ_DEBUG
RUST_PRELINK_FLAGS += -C opt-level=1
RUST_PRELINK_FLAGS += -C debug-assertions
else
RUST_PRELINK_FLAGS += -C opt-level=2
RUST_PRELINK_FLAGS += -C lto
endif
$(RUST_PRELINK): $(RUST_PRELINK_DEPS) $(RUST_PRELINK_SRC)
$(REPORT_BUILD)
$(RUSTC) -o $@ --crate-type staticlib --target $(RUST_TARGET) $(RUST_PRELINK_FLAGS) $(RUST_PRELINK_SRC)
endif # RUST_PRELINK
endif # MOZ_RUST
$(SOBJS):

View File

@ -1236,25 +1236,49 @@ class RecursiveMakeBackend(CommonBackend):
# 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 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):
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))
def find_rlibs(obj):
if isinstance(obj, RustLibrary):
yield obj
elif isinstance(obj, StaticLibrary) and not obj.no_expand_lib:
for l in obj.linked_libraries:
for rlib in find_rlibs(l):
yield rlib
# Check if we have any rust libraries to prelink and include in our
# final library. If we do, write out the RUST_PRELINK information
rlibs = []
if isinstance(obj, (SharedLibrary, StaticLibrary)):
for l in obj.linked_libraries:
rlibs += find_rlibs(l)
if rlibs:
prelink_libname = '%s/%s%s-rs-prelink%s' \
% (relpath,
obj.config.lib_prefix,
obj.basename,
obj.config.lib_suffix)
backend_file.write('RUST_PRELINK := %s\n' % prelink_libname)
backend_file.write_once('STATIC_LIBS += %s\n' % prelink_libname)
extern_crate_file = mozpath.join(
obj.objdir, '%s-rs-prelink.rs' % obj.basename)
with self._write_file(extern_crate_file) as f:
f.write('// AUTOMATICALLY GENERATED. DO NOT EDIT.\n\n')
for rlib in rlibs:
f.write('extern crate %s;\n'
% rlib.basename.replace('-', '_'))
backend_file.write('RUST_PRELINK_SRC := %s\n' % extern_crate_file)
backend_file.write('RUST_PRELINK_FLAGS :=\n')
backend_file.write('RUST_PRELINK_DEPS :=\n')
for rlib in rlibs:
rlib_relpath = pretty_relpath(rlib)
backend_file.write('RUST_PRELINK_FLAGS += --extern %s=%s/%s\n'
% (rlib.basename, rlib_relpath, rlib.import_name))
backend_file.write('RUST_PRELINK_FLAGS += -L %s/%s\n'
% (rlib_relpath, rlib.deps_path))
backend_file.write('RUST_PRELINK_DEPS += %s/%s\n'
% (rlib_relpath, rlib.import_name))
for lib in obj.linked_system_libs:
if obj.KIND == 'target':

View File

@ -464,6 +464,7 @@ class RustLibrary(StaticLibrary):
__slots__ = (
'cargo_file',
'crate_type',
'deps_path',
)
def __init__(self, context, basename, cargo_file, crate_type, **args):
@ -474,23 +475,18 @@ class RustLibrary(StaticLibrary):
# 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
)
assert self.crate_type == 'rlib'
self.lib_name = 'lib%s.rlib' % basename.replace('-', '_')
# 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,
)
build_dir = mozpath.join(context.config.substs['RUST_TARGET'],
rust_build_kind)
self.import_name = mozpath.join(build_dir, self.lib_name)
self.deps_path = mozpath.join(build_dir, 'deps')
class SharedLibrary(Library):

View File

@ -436,7 +436,7 @@ class TreeMetadataEmitter(LoggingMixin):
context)
crate_type = crate_type[0]
if crate_type != 'staticlib':
if crate_type != 'rlib':
raise SandboxValidationError(
'crate-type %s is not permitted for %s' % (crate_type, libname),
context)
@ -659,17 +659,6 @@ class TreeMetadataEmitter(LoggingMixin):
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:

View File

@ -6,7 +6,7 @@ authors = [
]
[lib]
crate-type = ["staticlib"]
crate-type = ["rlib"]
[dependencies]
deep-crate = { version = "0.1.0", path = "the/depths" }

View File

@ -6,4 +6,4 @@ authors = [
]
[lib]
crate-type = ["staticlib"]
crate-type = ["rlib"]

View File

@ -10,7 +10,7 @@ mp4parse-gtest = { path = "../../../../dom/media/gtest" }
[lib]
path = "lib.rs"
crate-type = ["staticlib"]
crate-type = ["rlib"]
test = false
doctest = false
bench = false

View File

@ -10,7 +10,7 @@ mp4parse_capi = { path = "../../../media/libstagefright/binding/mp4parse_capi" }
[lib]
path = "lib.rs"
crate-type = ["staticlib"]
crate-type = ["rlib"]
test = false
doctest = false
bench = false