Bug 1312916 - Add support for host rust libraries in moz.build. r=froydnj draft
authorChris Manchester <cmanchester@mozilla.com>
Thu, 19 Jan 2017 14:58:10 -0800
changeset 465741 bc4dabb18ff51c45ac8df5a409881d0d4a7279fa
parent 464990 5a4412474c63e1d9e66036d603ac42e9cb2b9150
child 543239 b96a41f4948e9d24a06f52ee1a2fb6a77af930fa
push id42697
push usercmanchester@mozilla.com
push dateTue, 24 Jan 2017 19:37:12 +0000
reviewersfroydnj
bugs1312916
milestone54.0a1
Bug 1312916 - Add support for host rust libraries in moz.build. r=froydnj MozReview-Commit-ID: It8VH5Obnx5
build/templates.mozbuild
config/rules.mk
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/frontend/context.py
python/mozbuild/mozbuild/frontend/data.py
python/mozbuild/mozbuild/frontend/emitter.py
python/mozbuild/mozbuild/test/backend/common.py
python/mozbuild/mozbuild/test/backend/data/host-rust-library-features/Cargo.toml
python/mozbuild/mozbuild/test/backend/data/host-rust-library-features/moz.build
python/mozbuild/mozbuild/test/backend/data/host-rust-library/Cargo.toml
python/mozbuild/mozbuild/test/backend/data/host-rust-library/moz.build
python/mozbuild/mozbuild/test/backend/test_recursivemake.py
python/mozbuild/mozbuild/test/frontend/data/host-rust-libraries/Cargo.toml
python/mozbuild/mozbuild/test/frontend/data/host-rust-libraries/moz.build
python/mozbuild/mozbuild/test/frontend/test_emitter.py
--- a/build/templates.mozbuild
+++ b/build/templates.mozbuild
@@ -124,11 +124,21 @@ def HostSimplePrograms(names, ext='.cpp'
     HostStdCppCompat()
 
 
 @template
 def HostLibrary(name):
     '''Template for build tools libraries.'''
     HOST_LIBRARY_NAME = name
 
+@template
+def HostRustLibrary(name, features=None):
+    '''Template for host Rust libraries.'''
+    HostLibrary(name)
+
+    IS_RUST_LIBRARY = True
+
+    if features:
+        HOST_RUST_LIBRARY_FEATURES = features
+
 
 include('gecko_templates.mozbuild')
 include('test_templates.mozbuild')
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -542,17 +542,17 @@ STATIC_LIBS_DEPS := $(foreach l,$(STATIC
 GLOBAL_DEPS += Makefile $(addprefix $(DEPTH)/config/,$(INCLUDED_AUTOCONF_MK)) $(MOZILLA_DIR)/config/config.mk
 
 ##############################################
 ifdef COMPILE_ENVIRONMENT
 OBJ_TARGETS = $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)
 
 compile:: host target
 
-host:: $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(HOST_RUST_PROGRAMS)
+host:: $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(HOST_RUST_PROGRAMS) $(HOST_RUST_LIBRARY_FILE)
 
 target:: $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(RUST_LIBRARY_FILE) $(RUST_PROGRAMS)
 
 include $(MOZILLA_DIR)/config/makefiles/target_binaries.mk
 endif
 
 ##############################################
 ifneq (1,$(NO_PROFILE_GUIDED_OPTIMIZE))
@@ -963,16 +963,29 @@ endif
 # build.
 force-cargo-library-build:
 	$(REPORT_BUILD)
 	$(CARGO_BUILD) --lib $(cargo_target_flag) $(rust_features_flag)
 
 $(RUST_LIBRARY_FILE): force-cargo-library-build
 endif # RUST_LIBRARY_FILE
 
+ifdef HOST_RUST_LIBRARY_FILE
+
+ifdef HOST_RUST_LIBRARY_FEATURES
+host_rust_features_flag := --features "$(HOST_RUST_LIBRARY_FEATURES)"
+endif
+
+force-cargo-host-library-build:
+	$(REPORT_BUILD)
+	$(CARGO_BUILD) --lib $(cargo_host_flag) $(host_rust_features_flag)
+
+$(HOST_RUST_LIBRARY_FILE): force-cargo-host-library-build
+endif # HOST_RUST_LIBRARY_FILE
+
 ifdef RUST_PROGRAMS
 force-cargo-program-build:
 	$(REPORT_BUILD)
 	$(CARGO_BUILD) $(addprefix --bin ,$(RUST_CARGO_PROGRAMS)) $(cargo_target_flag)
 
 $(RUST_PROGRAMS): force-cargo-program-build
 endif # RUST_PROGRAMS
 ifdef HOST_RUST_PROGRAMS
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -56,16 +56,17 @@ from ..frontend.data import (
     JavaJarData,
     Library,
     LocalInclude,
     ObjdirFiles,
     ObjdirPreprocessedFiles,
     PerSourceFlag,
     Program,
     RustLibrary,
+    HostRustLibrary,
     RustProgram,
     SharedLibrary,
     SimpleProgram,
     Sources,
     StaticLibrary,
     TestManifest,
     VariablePassthru,
     XPIDLFile,
@@ -1200,20 +1201,25 @@ class RecursiveMakeBackend(CommonBackend
         backend_file.write('FORCE_STATIC_LIB := 1\n')
         backend_file.write('REAL_LIBRARY := %s\n' % libdef.lib_name)
         if libdef.is_sdk:
             backend_file.write('SDK_LIBRARY := %s\n' % libdef.import_name)
         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)
+        lib_var = 'RUST_LIBRARY_FILE'
+        feature_var = 'RUST_LIBRARY_FEATURES'
+        if isinstance(libdef, HostRustLibrary):
+            lib_var = 'HOST_RUST_LIBRARY_FILE'
+            feature_var = 'HOST_RUST_LIBRARY_FEATURES'
+        backend_file.write_once('%s := %s\n' % (libdef.LIB_FILE_VAR, libdef.import_name))
         backend_file.write('CARGO_FILE := $(srcdir)/Cargo.toml\n')
         if libdef.features:
-            backend_file.write('RUST_LIBRARY_FEATURES := %s\n' % ' '.join(libdef.features))
+            backend_file.write('%s := %s\n' % (libdef.FEATURES_VAR, ' '.join(libdef.features)))
 
     def _process_host_library(self, libdef, backend_file):
         backend_file.write('HOST_LIBRARY_NAME = %s\n' % libdef.basename)
 
     def _build_target_for_obj(self, obj):
         return '%s/%s' % (mozpath.relpath(obj.objdir,
             self.environment.topobjdir), obj.KIND)
 
@@ -1260,17 +1266,17 @@ class RecursiveMakeBackend(CommonBackend
                     backend_file.write_once('STATIC_LIBS += %s/%s\n'
                                         % (relpath, lib.import_name))
                     write_shared_and_system_libs(lib)
                 else:
                     assert lib.variant != lib.COMPONENT
                     backend_file.write_once('SHARED_LIBS += %s/%s\n'
                                         % (relpath, lib.import_name))
             elif isinstance(obj, (HostLibrary, HostProgram, HostSimpleProgram)):
-                assert isinstance(lib, HostLibrary)
+                assert isinstance(lib, (HostLibrary, HostRustLibrary))
                 backend_file.write_once('HOST_LIBS += %s/%s\n'
                                    % (relpath, lib.import_name))
 
         # 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.
         if isinstance(obj, SharedLibrary):
             self._process_rust_libraries(obj, backend_file, pretty_relpath)
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -954,16 +954,23 @@ VARIABLES = {
 
     'RUST_LIBRARY_FEATURES': (List, list,
         """Cargo features to activate for this library.
 
         This variable should not be used directly; you should be using the
         RustLibrary template instead.
         """),
 
+    'HOST_RUST_LIBRARY_FEATURES': (List, list,
+        """Cargo features to activate for this host library.
+
+        This variable should not be used directly; you should be using the
+        HostRustLibrary template instead.
+        """),
+
     'UNIFIED_SOURCES': (ContextDerivedTypedList(SourcePath, StrictOrderingOnAppendList), list,
         """Source code files that can be compiled together.
 
         This variable contains a list of source code files to compile,
         that can be concatenated all together and built as a single source
         file. This can help make the build faster and reduce the debug info
         size.
         """),
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -415,17 +415,17 @@ class SimpleProgram(BaseProgram):
 
 class HostSimpleProgram(HostMixin, BaseProgram):
     """Context derived container object for each program in
     HOST_SIMPLE_PROGRAMS"""
     SUFFIX_VAR = 'HOST_BIN_SUFFIX'
     KIND = 'host'
 
 
-def cargo_target_directory(context, target_var='RUST_TARGET'):
+def cargo_target_directory(context, target_var):
     # 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'
     return mozpath.join(context.config.substs[target_var], rust_build_kind)
 
@@ -521,32 +521,35 @@ class RustLibrary(StaticLibrary):
     """Context derived container object for a static library"""
     __slots__ = (
         'cargo_file',
         'crate_type',
         'dependencies',
         'deps_path',
         'features',
     )
+    TARGET_SUBST_VAR = 'RUST_TARGET'
+    FEATURES_VAR = 'RUST_LIBRARY_FEATURES'
+    LIB_FILE_VAR = 'RUST_LIBRARY_FILE'
 
     def __init__(self, context, basename, cargo_file, crate_type, dependencies,
                  features, **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)
         self.dependencies = dependencies
-        build_dir = cargo_target_directory(context)
+        build_dir = cargo_target_directory(context, self.TARGET_SUBST_VAR)
         self.import_name = mozpath.join(build_dir, self.lib_name)
         self.deps_path = mozpath.join(build_dir, 'deps')
         self.features = features
 
 
 class SharedLibrary(Library):
     """Context derived container object for a shared library"""
     __slots__ = (
@@ -627,16 +630,24 @@ class ExternalSharedLibrary(SharedLibrar
     build system."""
 
 
 class HostLibrary(HostMixin, BaseLibrary):
     """Context derived container object for a host library"""
     KIND = 'host'
 
 
+class HostRustLibrary(HostMixin, RustLibrary):
+    """Context derived container object for a host rust library"""
+    KIND = 'host'
+    TARGET_SUBST_VAR = 'RUST_HOST_TARGET'
+    FEATURES_VAR = 'HOST_RUST_LIBRARY_FEATURES'
+    LIB_FILE_VAR = 'HOST_RUST_LIBRARY_FILE'
+
+
 class TestManifest(ContextDerived):
     """Represents a manifest file containing information about tests."""
 
     __slots__ = (
         # The type of test manifest this is.
         'flavor',
 
         # Maps source filename to destination filename. The destination
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -58,16 +58,17 @@ from .data import (
     LocalInclude,
     ObjdirFiles,
     ObjdirPreprocessedFiles,
     PerSourceFlag,
     PreprocessedTestWebIDLFile,
     PreprocessedWebIDLFile,
     Program,
     RustLibrary,
+    HostRustLibrary,
     RustProgram,
     SdkFiles,
     SharedLibrary,
     SimpleProgram,
     Sources,
     StaticLibrary,
     TestHarnessFiles,
     TestWebIDLFile,
@@ -409,17 +410,17 @@ class TreeMetadataEmitter(LoggingMixin):
                     '%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 _rust_library(self, context, libname, static_args):
+    def _rust_library(self, context, libname, static_args, cls=RustLibrary):
         # We need to note any Rust library for linking purposes.
         config, cargo_file = self._parse_cargo_file(context)
         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)
@@ -461,25 +462,26 @@ class TreeMetadataEmitter(LoggingMixin):
             if panic != 'abort':
                 raise SandboxValidationError(
                     ('Cargo.toml for %s does not specify `panic = "abort"`'
                      ' in [profile.%s] section') % (libname, profile_name),
                     context)
 
         dependencies = set(config.get('dependencies', {}).iterkeys())
 
-        features = context.get('RUST_LIBRARY_FEATURES', [])
+        features = context.get(cls.FEATURES_VAR, [])
         unique_features = set(features)
         if len(features) != len(unique_features):
             raise SandboxValidationError(
                 'features for %s should not contain duplicates: %s' % (libname, features),
                 context)
 
-        return RustLibrary(context, libname, cargo_file, crate_type,
-                           dependencies, features, **static_args)
+        return cls(context, libname, cargo_file, crate_type, dependencies,
+                   features, **static_args)
+
 
     def _handle_linkables(self, context, passthru, generated_files):
         linkables = []
         host_linkables = []
         def add_program(prog, var):
             if var.startswith('HOST_'):
                 host_linkables.append(prog)
             else:
@@ -549,17 +551,22 @@ class TreeMetadataEmitter(LoggingMixin):
 
         host_libname = context.get('HOST_LIBRARY_NAME')
         libname = context.get('LIBRARY_NAME')
 
         if host_libname:
             if host_libname == libname:
                 raise SandboxValidationError('LIBRARY_NAME and '
                     'HOST_LIBRARY_NAME must have a different value', context)
-            lib = HostLibrary(context, host_libname)
+
+            is_rust_library = context.get('IS_RUST_LIBRARY')
+            if is_rust_library:
+                lib = self._rust_library(context, host_libname, {}, cls=HostRustLibrary)
+            else:
+                lib = HostLibrary(context, host_libname)
             self._libs[host_libname].append(lib)
             self._linkage.append((context, lib, 'HOST_USE_LIBS'))
             host_linkables.append(lib)
 
         final_lib = context.get('FINAL_LIBRARY')
         if not libname and final_lib:
             # If no LIBRARY_NAME is given, create one.
             libname = context.relsrcdir.replace('/', '_')
--- a/python/mozbuild/mozbuild/test/backend/common.py
+++ b/python/mozbuild/mozbuild/test/backend/common.py
@@ -57,16 +57,38 @@ CONFIGS = defaultdict(lambda: {
         'non_global_defines': [],
         'substs': {
             'COMPILE_ENVIRONMENT': '1',
             'RUST_TARGET': 'x86_64-unknown-linux-gnu',
             'LIB_PREFIX': 'lib',
             'LIB_SUFFIX': 'a',
         },
     },
+    'host-rust-library': {
+        'defines': {},
+        'non_global_defines': [],
+        'substs': {
+            'COMPILE_ENVIRONMENT': '1',
+            'RUST_HOST_TARGET': 'x86_64-unknown-linux-gnu',
+            'RUST_TARGET': 'armv7-linux-androideabi',
+            'LIB_PREFIX': 'lib',
+            'LIB_SUFFIX': 'a',
+        },
+    },
+    'host-rust-library-features': {
+        'defines': {},
+        'non_global_defines': [],
+        'substs': {
+            'COMPILE_ENVIRONMENT': '1',
+            'RUST_HOST_TARGET': 'x86_64-unknown-linux-gnu',
+            'RUST_TARGET': 'armv7-linux-androideabi',
+            'LIB_PREFIX': 'lib',
+            'LIB_SUFFIX': 'a',
+        },
+    },
     'rust-library-features': {
         'defines': {},
         'non_global_defines': [],
         'substs': {
             'COMPILE_ENVIRONMENT': '1',
             'RUST_TARGET': 'x86_64-unknown-linux-gnu',
             'LIB_PREFIX': 'lib',
             'LIB_SUFFIX': 'a',
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/backend/data/host-rust-library-features/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "hostrusttool"
+version = "0.1.0"
+authors = [
+  "Nobody <nobody@mozilla.org>",
+]
+
+[lib]
+crate-type = ["staticlib"]
+
+[profile.dev]
+panic = "abort"
+
+[profile.release]
+panic = "abort"
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/backend/data/host-rust-library-features/moz.build
@@ -0,0 +1,19 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+@template
+def HostLibrary(name):
+    '''Template for libraries.'''
+    HOST_LIBRARY_NAME = name
+
+@template
+def HostRustLibrary(name, features=None):
+    '''Template for Rust libraries.'''
+    HostLibrary(name)
+
+    IS_RUST_LIBRARY = True
+
+    if features:
+        HOST_RUST_LIBRARY_FEATURES = features
+
+HostRustLibrary('hostrusttool', ['musthave', 'cantlivewithout'])
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/backend/data/host-rust-library/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "hostrusttool"
+version = "0.1.0"
+authors = [
+  "Nobody <nobody@mozilla.org>",
+]
+
+[lib]
+crate-type = ["staticlib"]
+
+[profile.dev]
+panic = "abort"
+
+[profile.release]
+panic = "abort"
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/backend/data/host-rust-library/moz.build
@@ -0,0 +1,19 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+@template
+def HostLibrary(name):
+    '''Template for libraries.'''
+    HOST_LIBRARY_NAME = name
+
+@template
+def HostRustLibrary(name, features=None):
+    '''Template for Rust libraries.'''
+    HostLibrary(name)
+
+    IS_RUST_LIBRARY = True
+
+    if features:
+        HOST_RUST_LIBRARY_FEATURES = features
+
+HostRustLibrary('hostrusttool')
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -744,16 +744,45 @@ class TestRecursiveMakeBackend(BackendTe
 
         expected = [
             'RUST_LIBRARY_FILE := x86_64-unknown-linux-gnu/release/libgkrust.a',
             'CARGO_FILE := $(srcdir)/Cargo.toml',
         ]
 
         self.assertEqual(lines, expected)
 
+    def test_host_rust_library(self):
+        """Test that a Rust library is written to backend.mk correctly."""
+        env = self._consume('host-rust-library', RecursiveMakeBackend)
+
+        backend_path = mozpath.join(env.topobjdir, 'backend.mk')
+        lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
+
+        expected = [
+            'HOST_RUST_LIBRARY_FILE := x86_64-unknown-linux-gnu/release/libhostrusttool.a',
+            'CARGO_FILE := $(srcdir)/Cargo.toml',
+        ]
+
+        self.assertEqual(lines, expected)
+
+    def test_host_rust_library_with_features(self):
+        """Test that a host Rust library with features is written to backend.mk correctly."""
+        env = self._consume('host-rust-library-features', RecursiveMakeBackend)
+
+        backend_path = mozpath.join(env.topobjdir, 'backend.mk')
+        lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
+
+        expected = [
+            'HOST_RUST_LIBRARY_FILE := x86_64-unknown-linux-gnu/release/libhostrusttool.a',
+            'CARGO_FILE := $(srcdir)/Cargo.toml',
+            'HOST_RUST_LIBRARY_FEATURES := musthave cantlivewithout',
+        ]
+
+        self.assertEqual(lines, expected)
+
     def test_rust_library_with_features(self):
         """Test that a Rust library with features is written to backend.mk correctly."""
         env = self._consume('rust-library-features', RecursiveMakeBackend)
 
         backend_path = mozpath.join(env.topobjdir, 'backend.mk')
         lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
 
         expected = [
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/frontend/data/host-rust-libraries/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "host-lib"
+version = "0.1.0"
+authors = [
+  "Nobody <nobody@mozilla.org>",
+]
+
+[lib]
+crate-type = ["staticlib"]
+
+[profile.dev]
+panic = "abort"
+
+[profile.release]
+panic = "abort"
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/frontend/data/host-rust-libraries/moz.build
@@ -0,0 +1,19 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+@template
+def HostLibrary(name):
+    '''Template for libraries.'''
+    HOST_LIBRARY_NAME = name
+
+@template
+def HostRustLibrary(name, features=None):
+    '''Template for Rust libraries.'''
+    HostLibrary(name)
+
+    IS_RUST_LIBRARY = True
+
+    if features:
+        RUST_LIBRARY_FEATURES = features
+
+HostRustLibrary('host-lib')
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
@@ -20,16 +20,17 @@ from mozbuild.frontend.data import (
     ConfigFileSubstitution,
     Defines,
     DirectoryTraversal,
     Exports,
     FinalTargetPreprocessedFiles,
     GeneratedFile,
     GeneratedSources,
     HostDefines,
+    HostRustLibrary,
     HostRustProgram,
     HostSources,
     IPDLFile,
     JARManifest,
     LinkageMultipleRustLibrariesError,
     LocalInclude,
     Program,
     RustLibrary,
@@ -1143,16 +1144,27 @@ class TestEmitterBasic(unittest.TestCase
                              extra_substs=dict(RUST_HOST_TARGET='i686-pc-windows-msvc',
                                                HOST_BIN_SUFFIX='.exe'))
         objs = self.read_topsrcdir(reader)
 
         self.assertEqual(len(objs), 1)
         self.assertIsInstance(objs[0], HostRustProgram)
         self.assertEqual(objs[0].name, 'some')
 
+    def test_host_rust_libraries(self):
+        '''Test HOST_RUST_LIBRARIES emission.'''
+        reader = self.reader('host-rust-libraries',
+                             extra_substs=dict(RUST_HOST_TARGET='i686-pc-windows-msvc',
+                                               HOST_BIN_SUFFIX='.exe'))
+        objs = self.read_topsrcdir(reader)
+        self.assertEqual(len(objs), 1)
+        self.assertIsInstance(objs[0], HostRustLibrary)
+        self.assertRegexpMatches(objs[0].lib_name, 'host_lib')
+        self.assertRegexpMatches(objs[0].import_name, 'host_lib')
+
     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)