diff --git a/build/rust/rustc_artifact.gni b/build/rust/rustc_artifact.gni
index 302d7f4c24f8ea40ce47b6107e63e2596ff8c391..ec9cb51737641f38095bc601489fe35e922a157f 100644
--- a/build/rust/rustc_artifact.gni
+++ b/build/rust/rustc_artifact.gni
@@ -324,6 +324,8 @@ template("rustc_artifact") {
   extra_inputs = [ zircon_lib_dirs_file ]
   generated_file("${build_target_name}_zircon_libs") {
     forward_variables_from(invoker, [ "testonly" ])
+    # Clear possibly inherited visibility before setting our own.
+    visibility = []
     visibility = [ ":$build_target_name" ]
     deps = [
       third_party_build,
diff --git a/src/sys/component_manager/BUILD.gn b/src/sys/component_manager/BUILD.gn
index 46af162c365638149f5afab8bba8b12f32338b1e..c82352bf90b8f74f99737099a0526452eb15713c 100644
--- a/src/sys/component_manager/BUILD.gn
+++ b/src/sys/component_manager/BUILD.gn
@@ -4,14 +4,18 @@
 
 import("//build/package.gni")
 import("//build/rust/rustc_binary.gni")
+import("//build/rust/rustc_library.gni")
 import("//build/test/test_package.gni")
 import("//build/testing/environments.gni")
 
-rustc_binary("bin") {
-  name = "component_manager"
+rustc_library("lib") {
+  name = "component_manager_lib"
   with_unit_tests = true
   edition = "2018"
 
+  # Only for internal use.
+  visibility = [ "//src/sys/component_manager/*" ]
+
   deps = [
     "//garnet/examples/fidl/services:echo-rustc",
     "//garnet/lib/rust/cm_fidl_translator",
@@ -45,6 +49,23 @@ rustc_binary("bin") {
   ]
 }
 
+rustc_binary("bin") {
+  name = "component_manager"
+  with_unit_tests = true
+  edition = "2018"
+
+  deps = [
+    ":lib",
+    "//garnet/public/lib/fidl/rust/fidl",
+    "//garnet/public/rust/fuchsia-async",
+    "//garnet/public/rust/fuchsia-component",
+    "//sdk/fidl/fuchsia.pkg:fuchsia.pkg-rustc",
+    "//third_party/rust_crates:failure",
+    "//third_party/rust_crates:futures-preview",
+    "//third_party/rust_crates:log",
+  ]
+}
+
 # This manifest is consumed by the ZBI rule in //build/images to add component_manager to bootfs.
 generate_manifest("component_manager.bootfs") {
   deps = [
diff --git a/src/sys/component_manager/src/elf_runner/library_loader.rs b/src/sys/component_manager/src/elf_runner/library_loader.rs
index 3aa90e00d04e6d5ed2cd5ac372853377d7b24af8..69cec6be7a656d5e159004b5694ba74e1d8e7f8d 100644
--- a/src/sys/component_manager/src/elf_runner/library_loader.rs
+++ b/src/sys/component_manager/src/elf_runner/library_loader.rs
@@ -10,7 +10,6 @@ use {
     fidl_fuchsia_ldsvc::{LoaderRequest, LoaderRequestStream},
     fuchsia_async as fasync, fuchsia_zircon as zx,
     futures::{TryFutureExt, TryStreamExt},
-    io_util,
     log::*,
     std::collections::HashMap,
     std::path::PathBuf,
diff --git a/src/sys/component_manager/src/fuchsia_boot_resolver.rs b/src/sys/component_manager/src/fuchsia_boot_resolver.rs
index 6609ffb050e22d5f71600cea3a90c64ee813675e..0891669c4fecd5e10eee4c29708d3bc319a4cfa2 100644
--- a/src/sys/component_manager/src/fuchsia_boot_resolver.rs
+++ b/src/sys/component_manager/src/fuchsia_boot_resolver.rs
@@ -9,7 +9,6 @@ use {
     fidl_fuchsia_sys2 as fsys,
     fuchsia_uri::boot_uri::BootUri,
     futures::future::FutureObj,
-    io_util,
     std::path::PathBuf,
 };
 
diff --git a/src/sys/component_manager/src/fuchsia_pkg_resolver.rs b/src/sys/component_manager/src/fuchsia_pkg_resolver.rs
index 6a0c887145ffd637bc426161d65f6b8992ecf1c0..6fa3022b1a7816bcebbdcbfd9a4b540a2a0d2484 100644
--- a/src/sys/component_manager/src/fuchsia_pkg_resolver.rs
+++ b/src/sys/component_manager/src/fuchsia_pkg_resolver.rs
@@ -13,7 +13,6 @@ use {
     fuchsia_uri::pkg_uri::PkgUri,
     fuchsia_zircon as zx,
     futures::future::FutureObj,
-    io_util,
     std::path::PathBuf,
 };
 
diff --git a/src/sys/component_manager/src/lib.rs b/src/sys/component_manager/src/lib.rs
new file mode 100644
index 0000000000000000000000000000000000000000..4ff203cbabd15da4780241a45cf4a38d37bae9dd
--- /dev/null
+++ b/src/sys/component_manager/src/lib.rs
@@ -0,0 +1,16 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#![feature(async_await, await_macro)]
+// This is needed for the pseudo_directory nesting in crate::model::tests
+#![recursion_limit = "128"]
+
+pub mod elf_runner;
+pub mod fuchsia_boot_resolver;
+pub mod fuchsia_pkg_resolver;
+pub mod klog;
+pub mod model;
+
+mod directory_broker;
+mod ns_util;
diff --git a/src/sys/component_manager/src/main.rs b/src/sys/component_manager/src/main.rs
index 89ed8a9a11875a12ddea38e50f3e215a2a40f1f6..0b5db3c18c31dde524a334c2d750639f3e0ff523 100644
--- a/src/sys/component_manager/src/main.rs
+++ b/src/sys/component_manager/src/main.rs
@@ -3,33 +3,21 @@
 // found in the LICENSE file.
 
 #![feature(async_await, await_macro)]
-#![deny(warnings)]
-// Temporarily allow dead code during early development since not all
-// features are fully exercised.
-#![allow(dead_code)]
-// This is needed for the pseudo_directory nesting in crate::model::tests
-#![recursion_limit = "128"]
-
-mod directory_broker;
-mod elf_runner;
-mod fuchsia_boot_resolver;
-mod fuchsia_pkg_resolver;
-mod klog;
-mod model;
-mod ns_util;
 
 use {
-    elf_runner::ElfRunner,
+    component_manager_lib::{
+        elf_runner::ElfRunner,
+        fuchsia_boot_resolver::{self, FuchsiaBootResolver},
+        fuchsia_pkg_resolver::{self, FuchsiaPkgResolver},
+        klog,
+        model::{AbsoluteMoniker, Model, ModelParams, ResolverRegistry},
+    },
     failure::{self, Error, ResultExt},
     fidl_fuchsia_pkg::PackageResolverMarker,
     fuchsia_async as fasync,
-    fuchsia_boot_resolver::FuchsiaBootResolver,
     fuchsia_component::client::connect_to_service,
-    fuchsia_pkg_resolver::FuchsiaPkgResolver,
     futures::prelude::*,
-    io_util,
     log::*,
-    model::{AbsoluteMoniker, Model, ModelParams, ResolverRegistry},
     std::env,
     std::process,
     std::sync::Arc,
diff --git a/src/sys/component_manager/src/model/model.rs b/src/sys/component_manager/src/model/model.rs
index 1c868ce289cba38c64b0697508291c23480fc7ed..6eb1e855ee2ca18ef99e85f8379d1ad4e0016358 100644
--- a/src/sys/component_manager/src/model/model.rs
+++ b/src/sys/component_manager/src/model/model.rs
@@ -14,7 +14,6 @@ use {
         future::{join_all, FutureObj},
         lock::Mutex,
     },
-    io_util,
     std::sync::Arc,
 };
 
diff --git a/src/sys/component_manager/src/model/namespace.rs b/src/sys/component_manager/src/model/namespace.rs
index bfc0fd825a4537f82349b3a859202e49ecf59a9c..d4b156c63f845df5e2d155afa55cb9b53039e9bb 100644
--- a/src/sys/component_manager/src/model/namespace.rs
+++ b/src/sys/component_manager/src/model/namespace.rs
@@ -5,7 +5,7 @@
 use {
     crate::model::*,
     crate::ns_util::PKG_PATH,
-    crate::{directory_broker, io_util},
+    crate::directory_broker,
     cm_rust::{self, ComponentDecl, UseDirectoryDecl, UseServiceDecl},
     fidl::endpoints::{create_endpoints, ClientEnd, ServerEnd},
     fidl_fuchsia_io::{DirectoryProxy, NodeMarker, MODE_TYPE_DIRECTORY, OPEN_RIGHT_READABLE},
diff --git a/src/sys/component_manager/src/model/routing.rs b/src/sys/component_manager/src/model/routing.rs
index 9acecc5f7b9182cd071eba63dbfc2f97e394a434..88cedb0f1667857886adf6efe713cdd9010a0574 100644
--- a/src/sys/component_manager/src/model/routing.rs
+++ b/src/sys/component_manager/src/model/routing.rs
@@ -7,7 +7,7 @@ use {
     cm_rust::{self, Capability, ExposeDecl, ExposeSource, OfferDecl, OfferSource},
     failure::format_err,
     fidl_fuchsia_io::{MODE_TYPE_DIRECTORY, MODE_TYPE_SERVICE, OPEN_RIGHT_READABLE},
-    fuchsia_zircon as zx, io_util,
+    fuchsia_zircon as zx,
     std::sync::Arc,
 };
 
diff --git a/src/sys/component_manager/src/model/tests/routing_test_helpers.rs b/src/sys/component_manager/src/model/tests/routing_test_helpers.rs
index e8ee6da16a5e540f3de1222c5931d7f3c4a0a2a3..84aa3426dae21ca1f18592d7b02a5443e584a5a4 100644
--- a/src/sys/component_manager/src/model/tests/routing_test_helpers.rs
+++ b/src/sys/component_manager/src/model/tests/routing_test_helpers.rs
@@ -23,7 +23,6 @@ use {
     fuchsia_zircon::HandleBased,
     futures::lock::Mutex,
     futures::TryStreamExt,
-    io_util,
     std::{
         collections::{HashMap, HashSet},
         convert::TryFrom,
diff --git a/src/sys/component_manager/src/ns_util.rs b/src/sys/component_manager/src/ns_util.rs
index e1f1a8d1acfd4cde84270c0aaf700c4f315eb6b8..49d39db578621dd13aeff221c0fe3cf75acbc9a4 100644
--- a/src/sys/component_manager/src/ns_util.rs
+++ b/src/sys/component_manager/src/ns_util.rs
@@ -6,7 +6,7 @@ use {
     failure::{err_msg, Error},
     fidl::endpoints::ClientEnd,
     fidl_fuchsia_io::DirectoryProxy,
-    fidl_fuchsia_sys2 as fsys, io_util,
+    fidl_fuchsia_sys2 as fsys,
     lazy_static::lazy_static,
     std::collections::HashMap,
     std::path::PathBuf,